runBlazeInfo() {
BlazeCommandName.INFO,
blazeContext,
BlazeInvocationContext.SYNC_CONTEXT);
+ if (BlazeInfoProvider.isEnabled()) {
+ return BlazeInfoProvider.getInstance(project)
+ .getBlazeInfo(blazeContext, syncFlags);
+ }
return BlazeInfoRunner.getInstance()
- .runBlazeInfo(project, this, blazeContext, buildSystem.getName(), syncFlags);
+ .runBlazeInfo(project,
+ this,
+ blazeContext,
+ buildSystem.getName(),
+ syncFlags);
}
}
diff --git a/base/src/com/google/idea/blaze/base/command/info/BlazeInfoProvider.java b/base/src/com/google/idea/blaze/base/command/info/BlazeInfoProvider.java
new file mode 100644
index 00000000000..ab8ca6c6787
--- /dev/null
+++ b/base/src/com/google/idea/blaze/base/command/info/BlazeInfoProvider.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.idea.blaze.base.command.info;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.idea.blaze.base.async.executor.BlazeExecutor;
+import com.google.idea.blaze.base.bazel.BuildSystem;
+import com.google.idea.blaze.base.scope.BlazeContext;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.settings.BlazeImportSettings;
+import com.google.idea.blaze.base.settings.BlazeImportSettingsManager;
+import com.google.idea.blaze.base.sync.SyncListener;
+import com.google.idea.blaze.base.sync.SyncMode;
+import com.google.idea.blaze.base.sync.SyncResult;
+import com.google.idea.common.experiments.BoolExperiment;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Providing a {@link com.google.idea.blaze.base.command.info.BlazeInfo}, the result will be cached and invalidated on any sync failure.
+ *
+ * @see BlazeInfoRunner
+ */
+public class BlazeInfoProvider {
+ private static final Logger logger = Logger.getInstance(BlazeInfoProvider.class);
+ private static final BoolExperiment enabled =
+ new BoolExperiment("blaze.info.provider.enabled", false);
+
+ private final Project project;
+ private volatile BlazeInfo blazeInfo;
+
+ public BlazeInfoProvider(Project project) {
+ this.project = project;
+ }
+
+ public static BlazeInfoProvider getInstance(Project project) {
+ return project.getService(BlazeInfoProvider.class);
+ }
+
+ public static Boolean isEnabled() {
+ return enabled.getValue();
+ }
+
+ public ListenableFuture getBlazeInfo(
+ BlazeContext context,
+ List blazeFlags) {
+ return BlazeExecutor.getInstance().submit(() -> {
+ BlazeInfo info = getCachedBlazeInfo(context,
+ blazeFlags);
+ if (info == null) {
+ throw new BlazeInfoException("Unable to get blaze info");
+ }
+ return info;
+ });
+ }
+
+ private @Nullable BlazeInfo getCachedBlazeInfo(
+ BlazeContext context,
+ List blazeFlags) {
+ if (blazeInfo != null) {
+ logger.debug("Returning cached BlazeInfo");
+ return blazeInfo;
+ }
+ try {
+ BlazeImportSettings importSettings = BlazeImportSettingsManager.getInstance(project).getImportSettings();
+ if (importSettings == null) {
+ return null;
+ }
+ BuildSystem.BuildInvoker buildInvoker = Blaze.getBuildSystemProvider(project)
+ .getBuildSystem()
+ .getDefaultInvoker(project, context);
+ logger.debug("Running bazel info");
+ blazeInfo = BlazeInfoRunner.getInstance().runBlazeInfo(
+ project,
+ buildInvoker,
+ BlazeContext.create(),
+ importSettings.getBuildSystem(),
+ blazeFlags
+ ).get();
+ return blazeInfo;
+ } catch (InterruptedException | ExecutionException e) {
+ logger.warn("Unable to run blaze info", e);
+ return null;
+ }
+ }
+
+ public void invalidate() {
+ logger.debug("invalidating");
+ blazeInfo = null;
+ }
+
+ public static final class Invalidator implements SyncListener {
+ @Override
+ public void afterSync(
+ Project project,
+ BlazeContext context,
+ SyncMode syncMode,
+ SyncResult syncResult,
+ ImmutableSet buildIds) {
+ if(!isEnabled()) {
+ return;
+ }
+ BlazeInfoProvider provider = BlazeInfoProvider.getInstance(project);
+ if(provider != null) {
+ provider.invalidate();
+ }
+ }
+ }
+}
diff --git a/base/src/com/google/idea/blaze/base/sync/ProjectStateSyncTask.java b/base/src/com/google/idea/blaze/base/sync/ProjectStateSyncTask.java
index 011e8cdebe6..14dbb8ddab6 100644
--- a/base/src/com/google/idea/blaze/base/sync/ProjectStateSyncTask.java
+++ b/base/src/com/google/idea/blaze/base/sync/ProjectStateSyncTask.java
@@ -26,6 +26,7 @@
import com.google.idea.blaze.base.command.BlazeFlags;
import com.google.idea.blaze.base.command.BlazeInvocationContext;
import com.google.idea.blaze.base.command.info.BlazeInfo;
+import com.google.idea.blaze.base.command.info.BlazeInfoProvider;
import com.google.idea.blaze.base.command.info.BlazeInfoRunner;
import com.google.idea.blaze.base.io.FileOperationProvider;
import com.google.idea.blaze.base.model.BlazeVersionData;
@@ -115,15 +116,7 @@ private SyncProjectState getProjectState(BlazeContext context, BlazeSyncParams p
BlazeInvocationContext.SYNC_CONTEXT);
ListenableFuture blazeInfoFuture =
- BlazeInfoRunner.getInstance()
- .runBlazeInfo(
- project,
- Blaze.getBuildSystemProvider(project)
- .getBuildSystem()
- .getDefaultInvoker(project, context),
- context,
- importSettings.getBuildSystem(),
- syncFlags);
+ createBazelInfoFuture(context, syncFlags, params.syncMode());
ListenableFuture workingSetFuture;
if(params.addWorkingSet() || params.syncMode() == SyncMode.FULL) {
@@ -189,6 +182,29 @@ private SyncProjectState getProjectState(BlazeContext context, BlazeSyncParams p
.build();
}
+ private ListenableFuture createBazelInfoFuture(
+ BlazeContext context,
+ List syncFlags,
+ SyncMode syncMode) {
+ boolean useBazelInfoRunner = !BlazeInfoProvider.isEnabled() || syncMode == SyncMode.FULL;
+ if (useBazelInfoRunner) {
+ return BlazeInfoRunner.getInstance()
+ .runBlazeInfo(
+ project,
+ Blaze.getBuildSystemProvider(project)
+ .getBuildSystem()
+ .getDefaultInvoker(project,
+ context),
+ context,
+ importSettings.getBuildSystem(),
+ syncFlags);
+ }
+ return BlazeInfoProvider.getInstance(project)
+ .getBlazeInfo(
+ context,
+ syncFlags);
+ }
+
private static class WorkspacePathResolverAndProjectView {
final WorkspacePathResolver workspacePathResolver;
final ProjectViewSet projectViewSet;