From ba14bbbc6821c0d75003b6d6a0edf04119df6a74 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Tue, 19 Oct 2021 13:54:28 -0700 Subject: [PATCH 01/47] Internal change. PiperOrigin-RevId: 404358622 --- java/BUILD | 1 - 1 file changed, 1 deletion(-) diff --git a/java/BUILD b/java/BUILD index 28f67eedbc3..b60808d086c 100644 --- a/java/BUILD +++ b/java/BUILD @@ -64,7 +64,6 @@ java_library( name = "fast_build_javac", srcs = _FAST_BUILD_JAVAC_SRCS + _FAST_BUILD_JAVAC_IMPL_SRCS, visibility = FAST_BUILD_JAVAC_VISIBILITY, - deps = ["//third_party/java/jdk:langtools"], ) # This is provided by the IDE at runtime From 618408e6a7186cd4d9dfccad2e16e541ee073717 Mon Sep 17 00:00:00 2001 From: Googler Date: Wed, 20 Oct 2021 03:20:53 -0700 Subject: [PATCH 02/47] Remove obsolete WebExperimentLoader PiperOrigin-RevId: 404483857 --- base/src/META-INF/blaze-base.xml | 1 - .../experiments/WebExperimentLoader.java | 45 ----- .../experiments/WebExperimentSyncer.java | 174 ------------------ 3 files changed, 220 deletions(-) delete mode 100644 common/experiments/src/com/google/idea/common/experiments/WebExperimentLoader.java delete mode 100644 common/experiments/src/com/google/idea/common/experiments/WebExperimentSyncer.java diff --git a/base/src/META-INF/blaze-base.xml b/base/src/META-INF/blaze-base.xml index 41c0de3a52b..b202e575639 100644 --- a/base/src/META-INF/blaze-base.xml +++ b/base/src/META-INF/blaze-base.xml @@ -553,7 +553,6 @@ - diff --git a/common/experiments/src/com/google/idea/common/experiments/WebExperimentLoader.java b/common/experiments/src/com/google/idea/common/experiments/WebExperimentLoader.java deleted file mode 100644 index 9111f61de82..00000000000 --- a/common/experiments/src/com/google/idea/common/experiments/WebExperimentLoader.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2016 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.common.experiments; - -import java.util.Map; - -@Deprecated -final class WebExperimentLoader implements ExperimentLoader { - - private static final String DEFAULT_PLUGIN_NAME = "ijwb"; - - private final WebExperimentSyncer syncer; - - WebExperimentLoader() { - this(DEFAULT_PLUGIN_NAME); - } - - WebExperimentLoader(String pluginName) { - syncer = new WebExperimentSyncer(pluginName); - } - - @Override - public Map getExperiments() { - return syncer.getExperimentValues(); - } - - @Override - public void initialize() { - - syncer.initialize(); - } -} diff --git a/common/experiments/src/com/google/idea/common/experiments/WebExperimentSyncer.java b/common/experiments/src/com/google/idea/common/experiments/WebExperimentSyncer.java deleted file mode 100644 index 4a05b0251c5..00000000000 --- a/common/experiments/src/com/google/idea/common/experiments/WebExperimentSyncer.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2016 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.common.experiments; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListenableScheduledFuture; -import com.google.common.util.concurrent.ListeningScheduledExecutorService; -import com.google.common.util.concurrent.MoreExecutors; -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.util.concurrency.AppExecutorUtil; -import com.intellij.util.io.HttpRequests; -import java.io.File; -import java.io.IOException; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import org.jetbrains.io.JsonReaderEx; - -/** - * A singleton class that retrieves the experiments from the experiments service. - * - *

The first time {@link #getExperimentValues()} is called, fresh data will be retrieved in the - * current thread. Thereafter, data will be retrieved every 5 minutes in a background thread. If - * there is a failure retrieving data, new attempts will be made every minute. - */ -final class WebExperimentSyncer { - - private static final Logger logger = Logger.getInstance(WebExperimentSyncer.class); - - private static final String DEFAULT_EXPERIMENT_URL = - "https://intellij-experiments.appspot.com/api/experiments/"; - private static final String EXPERIMENTS_URL_PROPERTY = "intellij.experiments.url"; - - private static final int SUCESSFUL_DOWNLOAD_DELAY_MINUTES = 5; - private static final int DOWNLOAD_FAILURE_DELAY_MINUTES = 1; - - private final File cacheFile; - private final String pluginName; - - // null indicates no fetch attempt has been made. After the first attempt, this will always be a - // (possibly empty) map. - private Map experimentValues = null; - - private final ListeningScheduledExecutorService executor = - MoreExecutors.listeningDecorator(AppExecutorUtil.getAppScheduledExecutorService()); - - WebExperimentSyncer(String pluginName) { - this.pluginName = pluginName; - cacheFile = - Paths.get(PathManager.getSystemPath(), "blaze", pluginName + ".experiments.cache.dat") - .toFile(); - } - - /** - * Get the last-retrieved set of experiment values. - * - *

The first time this method is called, an attempt to retrieve the values will take place. - * Thereafter, the values will be retrieved every five minutes on a background thread and this - * method will return the most recent successfully retrieved values. - */ - synchronized Map getExperimentValues() { - if (experimentValues == null) { - initialize(); - } - - return experimentValues; - } - - private synchronized void setExperimentValues(HashMap experimentValues) { - this.experimentValues = experimentValues; - saveCache(experimentValues); - } - - /** Fetch and process the experiments on the current thread. */ - void initialize() { - experimentValues = loadCache(); - ListenableFuture response = executor.submit(new WebExperimentsDownloader()); - response.addListener( - new WebExperimentsResultProcessor(response), MoreExecutors.directExecutor()); - } - - private void scheduleNextRefresh(boolean refreshWasSuccessful) { - int delayInMinutes = - refreshWasSuccessful ? SUCESSFUL_DOWNLOAD_DELAY_MINUTES : DOWNLOAD_FAILURE_DELAY_MINUTES; - ListenableScheduledFuture refreshResults = - executor.schedule(new WebExperimentsDownloader(), delayInMinutes, TimeUnit.MINUTES); - refreshResults.addListener( - new WebExperimentsResultProcessor(refreshResults), MoreExecutors.directExecutor()); - } - - private class WebExperimentsDownloader implements Callable { - - @Override - public String call() throws Exception { - logger.debug("About to fetch experiments."); - return HttpRequests.request( - System.getProperty(EXPERIMENTS_URL_PROPERTY, DEFAULT_EXPERIMENT_URL) + pluginName) - .readString(/* progress indicator */ null); - } - } - - private class WebExperimentsResultProcessor implements Runnable { - - private final Future resultFuture; - - private WebExperimentsResultProcessor(Future resultFuture) { - this.resultFuture = resultFuture; - } - - @Override - public void run() { - logger.debug("Experiments fetched. Processing results."); - try { - HashMap mapBuilder = Maps.newHashMap(); - String result = resultFuture.get(); - try (JsonReaderEx reader = new JsonReaderEx(result)) { - reader.beginObject(); - while (reader.hasNext()) { - String experimentName = reader.nextName(); - String experimentValue = reader.nextString(); - mapBuilder.put(experimentName, experimentValue); - } - } - setExperimentValues(mapBuilder); - - logger.debug("Successfully fetched experiments: " + getExperimentValues()); - scheduleNextRefresh(/* refreshWasSuccessful= */ true); - } catch (InterruptedException | ExecutionException | RuntimeException e) { - logger.debug("Error fetching experiments", e); - scheduleNextRefresh(/* refreshWasSuccessful= */ false); - } - } - } - - private void saveCache(HashMap experiments) { - try { - SerializationUtil.saveToDisk(cacheFile, experiments); - } catch (IOException e) { - logger.warn("Could not save experiments cache to disk: " + cacheFile); - } - } - - @SuppressWarnings("unchecked") - private Map loadCache() { - try { - Map loaded = (Map) SerializationUtil.loadFromDisk(cacheFile); - return loaded != null ? loaded : ImmutableMap.of(); - } catch (IOException e) { - // This is normal, we might be offline and have never loaded the cache. - logger.info("Could not load experiments file: " + cacheFile); - } - return ImmutableMap.of(); - } -} From ec19efeb21699dad9cdc79c9ee7f9aa7571e56cb Mon Sep 17 00:00:00 2001 From: Mai Hussien Date: Wed, 20 Oct 2021 08:48:59 -0700 Subject: [PATCH 03/47] Use relative resources paths This CL reorganizes the base package of Bazel plugin to allow using relative paths to refer to resources in code. This is done by moving base/resources folder to base/src/resources. Manually tested that with the new structure, icons, buildifier binary and color schemes can be retrieved successfully for both Blaze and Bazel plugins. This CL applies the modification requested in unknown commit which was reverted by mistake. PiperOrigin-RevId: 404552911 --- base/BUILD | 2 +- base/src/META-INF/blaze-base.xml | 2 +- .../BazelBuildifierBinaryProvider.java | 4 +--- base/src/icons/BlazeIcons.java | 2 +- base/{ => src}/resources/binaries/README | 0 base/{ => src}/resources/binaries/bazel-buildifier | Bin .../resources/colorSchemes/BuildDefault.xml | 0 base/{ => src}/resources/icons/bazel/failed.png | Bin base/{ => src}/resources/icons/bazel/failed@2x.png | Bin base/{ => src}/resources/icons/bazel/logo.png | Bin base/{ => src}/resources/icons/bazel/logo@2x.png | Bin .../{ => src}/resources/icons/bazel/tool_window.png | Bin .../resources/icons/bazel/tool_window@2x.png | Bin base/{ => src}/resources/icons/blaze/failed.png | Bin base/{ => src}/resources/icons/blaze/logo.png | Bin .../{ => src}/resources/icons/blaze/tool_window.png | Bin base/{ => src}/resources/icons/blazeRerun.png | Bin base/{ => src}/resources/icons/blazeRerun@2x.png | Bin .../resources/icons/blazeRerun@2x_dark.png | Bin base/{ => src}/resources/icons/blazeRerun_dark.png | Bin base/{ => src}/resources/icons/blaze_slow.png | Bin base/{ => src}/resources/icons/build_editor.png | Bin base/{ => src}/resources/icons/build_file.png | Bin base/{ => src}/resources/icons/build_rule.png | Bin base/{ => src}/resources/icons/lightningOverlay.png | Bin .../resources/icons/lightningOverlay@2x.png | Bin 26 files changed, 4 insertions(+), 6 deletions(-) rename base/{ => src}/resources/binaries/README (100%) rename base/{ => src}/resources/binaries/bazel-buildifier (100%) rename base/{ => src}/resources/colorSchemes/BuildDefault.xml (100%) rename base/{ => src}/resources/icons/bazel/failed.png (100%) rename base/{ => src}/resources/icons/bazel/failed@2x.png (100%) rename base/{ => src}/resources/icons/bazel/logo.png (100%) rename base/{ => src}/resources/icons/bazel/logo@2x.png (100%) rename base/{ => src}/resources/icons/bazel/tool_window.png (100%) rename base/{ => src}/resources/icons/bazel/tool_window@2x.png (100%) rename base/{ => src}/resources/icons/blaze/failed.png (100%) rename base/{ => src}/resources/icons/blaze/logo.png (100%) rename base/{ => src}/resources/icons/blaze/tool_window.png (100%) rename base/{ => src}/resources/icons/blazeRerun.png (100%) rename base/{ => src}/resources/icons/blazeRerun@2x.png (100%) rename base/{ => src}/resources/icons/blazeRerun@2x_dark.png (100%) rename base/{ => src}/resources/icons/blazeRerun_dark.png (100%) rename base/{ => src}/resources/icons/blaze_slow.png (100%) rename base/{ => src}/resources/icons/build_editor.png (100%) rename base/{ => src}/resources/icons/build_file.png (100%) rename base/{ => src}/resources/icons/build_rule.png (100%) rename base/{ => src}/resources/icons/lightningOverlay.png (100%) rename base/{ => src}/resources/icons/lightningOverlay@2x.png (100%) diff --git a/base/BUILD b/base/BUILD index 22e4f0dc6f1..3bbd9d60a42 100644 --- a/base/BUILD +++ b/base/BUILD @@ -22,7 +22,7 @@ java_library( name = "base", srcs = glob(["src/**/*.java"]), javacopts = ["-Xep:FutureReturnValueIgnored:OFF"], - resources = glob(["resources/**/*"]), + resources = glob(["src/resources/**/*"]), visibility = PLUGIN_PACKAGES_VISIBILITY, deps = [ "//common/actions", diff --git a/base/src/META-INF/blaze-base.xml b/base/src/META-INF/blaze-base.xml index b202e575639..5322425f574 100644 --- a/base/src/META-INF/blaze-base.xml +++ b/base/src/META-INF/blaze-base.xml @@ -278,7 +278,7 @@ - + diff --git a/base/src/com/google/idea/blaze/base/buildmodifier/BazelBuildifierBinaryProvider.java b/base/src/com/google/idea/blaze/base/buildmodifier/BazelBuildifierBinaryProvider.java index 20a2b8224ad..6c48207b9d9 100644 --- a/base/src/com/google/idea/blaze/base/buildmodifier/BazelBuildifierBinaryProvider.java +++ b/base/src/com/google/idea/blaze/base/buildmodifier/BazelBuildifierBinaryProvider.java @@ -22,9 +22,7 @@ /** Provides the bazel buildifier binary. */ public class BazelBuildifierBinaryProvider implements BuildifierBinaryProvider { - private static final String BASE = "/"; - private static final String BUILDIFIER_BINARY_PATH = - BASE + "base/resources/binaries/bazel-buildifier"; + private static final String BUILDIFIER_BINARY_PATH = "/resources/binaries/bazel-buildifier"; @Nullable @Override diff --git a/base/src/icons/BlazeIcons.java b/base/src/icons/BlazeIcons.java index 8b225ed12df..232ab521376 100644 --- a/base/src/icons/BlazeIcons.java +++ b/base/src/icons/BlazeIcons.java @@ -25,7 +25,7 @@ /** Class to manage icons used by the Blaze plugin. */ public class BlazeIcons { - private static final String BASE = "/base/resources/icons/"; + private static final String BASE = "resources/icons/"; public static final Icon Logo = loadForBuildSystem("logo.png"); // 16x16 public static final Icon BazelLogo = load("bazel/logo.png"); // 16x16 diff --git a/base/resources/binaries/README b/base/src/resources/binaries/README similarity index 100% rename from base/resources/binaries/README rename to base/src/resources/binaries/README diff --git a/base/resources/binaries/bazel-buildifier b/base/src/resources/binaries/bazel-buildifier similarity index 100% rename from base/resources/binaries/bazel-buildifier rename to base/src/resources/binaries/bazel-buildifier diff --git a/base/resources/colorSchemes/BuildDefault.xml b/base/src/resources/colorSchemes/BuildDefault.xml similarity index 100% rename from base/resources/colorSchemes/BuildDefault.xml rename to base/src/resources/colorSchemes/BuildDefault.xml diff --git a/base/resources/icons/bazel/failed.png b/base/src/resources/icons/bazel/failed.png similarity index 100% rename from base/resources/icons/bazel/failed.png rename to base/src/resources/icons/bazel/failed.png diff --git a/base/resources/icons/bazel/failed@2x.png b/base/src/resources/icons/bazel/failed@2x.png similarity index 100% rename from base/resources/icons/bazel/failed@2x.png rename to base/src/resources/icons/bazel/failed@2x.png diff --git a/base/resources/icons/bazel/logo.png b/base/src/resources/icons/bazel/logo.png similarity index 100% rename from base/resources/icons/bazel/logo.png rename to base/src/resources/icons/bazel/logo.png diff --git a/base/resources/icons/bazel/logo@2x.png b/base/src/resources/icons/bazel/logo@2x.png similarity index 100% rename from base/resources/icons/bazel/logo@2x.png rename to base/src/resources/icons/bazel/logo@2x.png diff --git a/base/resources/icons/bazel/tool_window.png b/base/src/resources/icons/bazel/tool_window.png similarity index 100% rename from base/resources/icons/bazel/tool_window.png rename to base/src/resources/icons/bazel/tool_window.png diff --git a/base/resources/icons/bazel/tool_window@2x.png b/base/src/resources/icons/bazel/tool_window@2x.png similarity index 100% rename from base/resources/icons/bazel/tool_window@2x.png rename to base/src/resources/icons/bazel/tool_window@2x.png diff --git a/base/resources/icons/blaze/failed.png b/base/src/resources/icons/blaze/failed.png similarity index 100% rename from base/resources/icons/blaze/failed.png rename to base/src/resources/icons/blaze/failed.png diff --git a/base/resources/icons/blaze/logo.png b/base/src/resources/icons/blaze/logo.png similarity index 100% rename from base/resources/icons/blaze/logo.png rename to base/src/resources/icons/blaze/logo.png diff --git a/base/resources/icons/blaze/tool_window.png b/base/src/resources/icons/blaze/tool_window.png similarity index 100% rename from base/resources/icons/blaze/tool_window.png rename to base/src/resources/icons/blaze/tool_window.png diff --git a/base/resources/icons/blazeRerun.png b/base/src/resources/icons/blazeRerun.png similarity index 100% rename from base/resources/icons/blazeRerun.png rename to base/src/resources/icons/blazeRerun.png diff --git a/base/resources/icons/blazeRerun@2x.png b/base/src/resources/icons/blazeRerun@2x.png similarity index 100% rename from base/resources/icons/blazeRerun@2x.png rename to base/src/resources/icons/blazeRerun@2x.png diff --git a/base/resources/icons/blazeRerun@2x_dark.png b/base/src/resources/icons/blazeRerun@2x_dark.png similarity index 100% rename from base/resources/icons/blazeRerun@2x_dark.png rename to base/src/resources/icons/blazeRerun@2x_dark.png diff --git a/base/resources/icons/blazeRerun_dark.png b/base/src/resources/icons/blazeRerun_dark.png similarity index 100% rename from base/resources/icons/blazeRerun_dark.png rename to base/src/resources/icons/blazeRerun_dark.png diff --git a/base/resources/icons/blaze_slow.png b/base/src/resources/icons/blaze_slow.png similarity index 100% rename from base/resources/icons/blaze_slow.png rename to base/src/resources/icons/blaze_slow.png diff --git a/base/resources/icons/build_editor.png b/base/src/resources/icons/build_editor.png similarity index 100% rename from base/resources/icons/build_editor.png rename to base/src/resources/icons/build_editor.png diff --git a/base/resources/icons/build_file.png b/base/src/resources/icons/build_file.png similarity index 100% rename from base/resources/icons/build_file.png rename to base/src/resources/icons/build_file.png diff --git a/base/resources/icons/build_rule.png b/base/src/resources/icons/build_rule.png similarity index 100% rename from base/resources/icons/build_rule.png rename to base/src/resources/icons/build_rule.png diff --git a/base/resources/icons/lightningOverlay.png b/base/src/resources/icons/lightningOverlay.png similarity index 100% rename from base/resources/icons/lightningOverlay.png rename to base/src/resources/icons/lightningOverlay.png diff --git a/base/resources/icons/lightningOverlay@2x.png b/base/src/resources/icons/lightningOverlay@2x.png similarity index 100% rename from base/resources/icons/lightningOverlay@2x.png rename to base/src/resources/icons/lightningOverlay@2x.png From adbd4bc8e62727587a055f5e4eb3682eb44a958a Mon Sep 17 00:00:00 2001 From: Googler Date: Wed, 20 Oct 2021 15:02:52 -0700 Subject: [PATCH 04/47] extract lint.jar in aars to local cache PiperOrigin-RevId: 404647099 --- .../blaze/android/libraries/UnpackedAars.java | 7 ++- .../android/libraries/UnpackedAarsTest.java | 55 +++++++++++++++++++ .../libraries/AarLibraryFileBuilder.java | 12 ++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java b/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java index 150887eddcc..f213b8fac58 100644 --- a/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java +++ b/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java @@ -15,6 +15,7 @@ */ package com.google.idea.blaze.android.libraries; +import static com.android.SdkConstants.FN_LINT_JAR; import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableMap.toImmutableMap; import static com.google.common.collect.ImmutableSet.toImmutableSet; @@ -423,8 +424,10 @@ private void copyLocally(FileOperationProvider ops, AarLibraryContents aarAndJar ZipUtil.extract( toCopy, aarDir, - // Skip jars. The merged jar will be synchronized by JarTraits. - (dir, name) -> !name.endsWith(".jar")); + // Skip jars except lint.jar. We will copy jar in AarLibraryContents instead. + // That could give us freedom in the future to use an ijar or header jar instead, + // which is more lightweight. But it's not applied to lint.jar + (dir, name) -> name.equals(FN_LINT_JAR) || !name.endsWith(".jar")); createStampFile(ops, aarDir, aarAndJar.aar()); diff --git a/aswb/tests/unittests/com/google/idea/blaze/android/libraries/UnpackedAarsTest.java b/aswb/tests/unittests/com/google/idea/blaze/android/libraries/UnpackedAarsTest.java index 890189d05aa..fe4c4a67d70 100644 --- a/aswb/tests/unittests/com/google/idea/blaze/android/libraries/UnpackedAarsTest.java +++ b/aswb/tests/unittests/com/google/idea/blaze/android/libraries/UnpackedAarsTest.java @@ -15,6 +15,7 @@ */ package com.google.idea.blaze.android.libraries; +import static com.android.SdkConstants.FN_LINT_JAR; import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.UTF_8; @@ -188,6 +189,60 @@ public void testRefresh_fileNotExist_success() throws IOException { assertThat(messages).contains("Removed 1 AARs"); } + @Test + public void testRefresh_includeLintJar() throws IOException { + UnpackedAars unpackedAars = UnpackedAars.getInstance(project); + File aarCacheDir = unpackedAars.getCacheDir(); + String lintAar = "lint.aar"; + File lintJar = workspaceRoot.fileForPath(new WorkspacePath(FN_LINT_JAR)); + try (ZipOutputStream zo = new ZipOutputStream(new FileOutputStream(lintJar))) { + zo.putNextEntry(new ZipEntry("com/google/foo/sampleDetector.java")); + zo.write("package com.google.foo; class sampleDetector {}".getBytes(UTF_8)); + zo.closeEntry(); + } + byte[] expectedJarContent = Files.readAllBytes(lintJar.toPath()); + AarLibraryFileBuilder.aar(workspaceRoot, lintAar).setLintJar(expectedJarContent).build(); + ArtifactLocation lintAarArtifactLocation = generateArtifactLocation(lintAar); + AarLibrary lintAarLibrary = new AarLibrary(lintAarArtifactLocation, null); + + BlazeAndroidImportResult importResult = + new BlazeAndroidImportResult( + ImmutableList.of(), + ImmutableMap.of( + LibraryKey.libraryNameFromArtifactLocation(lintAarArtifactLocation), + lintAarLibrary), + ImmutableList.of(), + ImmutableList.of()); + BlazeAndroidSyncData syncData = + new BlazeAndroidSyncData(importResult, new AndroidSdkPlatform("stable", 15)); + BlazeProjectData blazeProjectData = + MockBlazeProjectDataBuilder.builder(workspaceRoot) + .setWorkspaceLanguageSettings( + new WorkspaceLanguageSettings(WorkspaceType.ANDROID, ImmutableSet.of())) + .setSyncState(new SyncState.Builder().put(syncData).build()) + .setArtifactLocationDecoder(artifactLocationDecoder) + .build(); + FileCache.EP_NAME + .extensions() + .forEach( + ep -> + ep.onSync( + getProject(), + context, + ProjectViewSet.builder().add(ProjectView.builder().build()).build(), + blazeProjectData, + null, + SyncMode.INCREMENTAL)); + + assertThat(aarCacheDir.list()).hasLength(1); + File lintJarAarDir = unpackedAars.getAarDir(artifactLocationDecoder, lintAarLibrary); + + assertThat(aarCacheDir.listFiles()).asList().containsExactly(lintJarAarDir); + assertThat(lintJarAarDir.list()).asList().contains(FN_LINT_JAR); + byte[] actualJarContent = Files.readAllBytes(new File(lintJarAarDir, FN_LINT_JAR).toPath()); + assertThat(actualJarContent).isEqualTo(expectedJarContent); + } + @Test public void testRefresh_success() throws IOException { // aars cached last time but not included in current build output. It should be removed after diff --git a/aswb/tests/utils/unit/com/google/idea/blaze/android/libraries/AarLibraryFileBuilder.java b/aswb/tests/utils/unit/com/google/idea/blaze/android/libraries/AarLibraryFileBuilder.java index 3ffd76ef286..601e4e13d55 100644 --- a/aswb/tests/utils/unit/com/google/idea/blaze/android/libraries/AarLibraryFileBuilder.java +++ b/aswb/tests/utils/unit/com/google/idea/blaze/android/libraries/AarLibraryFileBuilder.java @@ -15,6 +15,7 @@ */ package com.google.idea.blaze.android.libraries; +import static com.android.SdkConstants.FN_LINT_JAR; import static java.nio.charset.StandardCharsets.UTF_8; import com.android.annotations.NonNull; @@ -35,6 +36,7 @@ public class AarLibraryFileBuilder { private static final Logger LOG = Logger.getInstance(AarLibraryFileBuilder.class); private final File aarFile; private final Map resourceNameToContent; + private byte[] lintJar = new byte[0]; public static AarLibraryFileBuilder aar( @NonNull WorkspaceRoot workspaceRoot, @NonNull String aarFilePath) { @@ -56,6 +58,11 @@ public AarLibraryFileBuilder src(String relativePath, byte[] content) { return this; } + public AarLibraryFileBuilder setLintJar(byte[] lintJar) { + this.lintJar = lintJar; + return this; + } + public File build() { try { // create aarFilePath if it does not exist @@ -67,6 +74,11 @@ public File build() { out.write(entry.getValue(), 0, entry.getValue().length); out.closeEntry(); } + if (lintJar.length > 0) { + out.putNextEntry(new ZipEntry(FN_LINT_JAR)); + out.write(lintJar, 0, lintJar.length); + out.closeEntry(); + } } } catch (Exception e) { LOG.error(e); From df49751378b37d59694c7e539b6e0a8b805e0fe2 Mon Sep 17 00:00:00 2001 From: Sophie Bi Date: Thu, 21 Oct 2021 00:58:19 -0700 Subject: [PATCH 05/47] Support import by code search feature for Kotlin files. PiperOrigin-RevId: 404733284 --- intellij_platform_sdk/BUILD | 2 ++ 1 file changed, 2 insertions(+) diff --git a/intellij_platform_sdk/BUILD b/intellij_platform_sdk/BUILD index ff57629b7b2..6214b907dcd 100644 --- a/intellij_platform_sdk/BUILD +++ b/intellij_platform_sdk/BUILD @@ -423,6 +423,7 @@ java_library( ":sdk", ":cidr_plugins", ":java", + ":kotlin", ":android", ":test_recorder", ":platform_images", @@ -434,6 +435,7 @@ java_library( intellij = [ ":sdk", ":java", + ":kotlin", ":platform_images", ], ), From 0c3c1943553918c6aa198ac54610b92152e31ad6 Mon Sep 17 00:00:00 2001 From: Googler Date: Thu, 21 Oct 2021 10:03:54 -0700 Subject: [PATCH 06/47] New WorkerMetrics on blaze.invocations table Added new worker metrics based on workerKey(worker_id, mnemonic, is_sandboxed, is_multiplex) and on process (used_memory_in_kb). PiperOrigin-RevId: 404819898 --- .../proto/build_event_stream.proto | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/third_party/bazel/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto b/third_party/bazel/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto index 924b8ec1990..bde66b38c7d 100644 --- a/third_party/bazel/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto +++ b/third_party/bazel/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto @@ -1006,6 +1006,35 @@ message BuildMetrics { } BuildGraphMetrics build_graph_metrics = 8; + + // Information about all workers that were alive during the invocation. + message WorkerMetrics { + // Unique id of worker. + int32 worker_id = 1; + // Worker process id. If there is no process for worker, equals to zero. + uint32 process_id = 2; + // Mnemonic of running worker. + string mnemonic = 3; + // Multiplex or singleplex worker. + bool is_multiplex = 4; + // Using worker sandbox file system or not. + bool is_sandbox = 5; + // Shows is worker stats measured at the end of invocation. + bool is_measurable = 6; + + // Information collected from worker at some point. + message WorkerStats { + // Epoch unix time of collection of metrics. + int64 collect_time_in_ms = 1; + // RSS size of worker process. + int32 worker_memory_in_kb = 2; + } + + // Combined workers statistics. + repeated WorkerStats worker_stats = 7; + } + + repeated WorkerMetrics worker_metrics = 9; } // Event providing additional statistics/logs after completion of the build. From 0dc5010be71e3f0c9657c3466a29df6a11e2a36c Mon Sep 17 00:00:00 2001 From: Googler Date: Fri, 22 Oct 2021 01:36:59 -0700 Subject: [PATCH 07/47] Update the plugin API for IntelliJ CE, UE and CLion to 2021.2.3 PiperOrigin-RevId: 404969758 --- WORKSPACE | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 408d5963707..c5ef6a222ae 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -29,8 +29,8 @@ http_archive( http_archive( name = "intellij_ce_2021_2", build_file = "@//intellij_platform_sdk:BUILD.idea212", - sha256 = "562cc3a7600f266f5a7029a8fef4ca499667ad3f4cda4adaa90b8b7d10e9f618", - url = "https://www.jetbrains.com/intellij-repository/releases/com/jetbrains/intellij/idea/ideaIC/2021.2.1/ideaIC-2021.2.1.zip", + sha256 = "8f55f3bbe6ae78160301820b0ed52e226139754958247b6a3d8924c8f778d2b8", + url = "https://www.jetbrains.com/intellij-repository/releases/com/jetbrains/intellij/idea/ideaIC/2021.2.3/ideaIC-2021.2.3.zip", ) # The plugin api for intellij_ce_2021_3. This is required to build IJwB and run integration tests. @@ -64,8 +64,8 @@ http_archive( http_archive( name = "intellij_ue_2021_2", build_file = "@//intellij_platform_sdk:BUILD.ue212", - sha256 = "3b19b029edfe229ca5f7fe9d84f7d25fde1436953b2a0f491b25fc3859e9a0f2", - url = "https://www.jetbrains.com/intellij-repository/releases/com/jetbrains/intellij/idea/ideaIU/2021.2.1/ideaIU-2021.2.1.zip", + sha256 = "89ad86c940ab1cc7dc13882cd705919830ccfb02814789c0f9389fff26af1ad1", + url = "https://www.jetbrains.com/intellij-repository/releases/com/jetbrains/intellij/idea/ideaIU/2021.2.3/ideaIU-2021.2.3.zip", ) # The plugin api for intellij_ue_2021_3. This is required to run UE-specific integration tests. @@ -97,8 +97,8 @@ http_archive( http_archive( name = "clion_2021_2", build_file = "@//intellij_platform_sdk:BUILD.clion212", - sha256 = "2db99f8a755ad35b87b276dcbdfbb95be4fe35d0a741e7dfb340b2121403d44e", - url = "https://download.jetbrains.com/cpp/CLion-2021.2.1.tar.gz", + sha256 = "25c3968c72976b2de5e3e8f39b242702c4ec25b32268022cd16590e9fbfc0b27", + url = "https://download.jetbrains.com/cpp/CLion-2021.2.3.tar.gz", ) _PYTHON_CE_BUILD_FILE = """ From 02b6047a9b0c1d3d69e9cb44ec3dc53bad7c446f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexey=20Gy=C3=B6ri?= Date: Fri, 22 Oct 2021 05:12:46 -0700 Subject: [PATCH 08/47] Internal change. PiperOrigin-RevId: 404993609 --- .../BlazeTypeScriptConfigServiceImpl.java | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/javascript/src/com/google/idea/blaze/typescript/BlazeTypeScriptConfigServiceImpl.java b/javascript/src/com/google/idea/blaze/typescript/BlazeTypeScriptConfigServiceImpl.java index 2551b7dd671..692eb1fd111 100644 --- a/javascript/src/com/google/idea/blaze/typescript/BlazeTypeScriptConfigServiceImpl.java +++ b/javascript/src/com/google/idea/blaze/typescript/BlazeTypeScriptConfigServiceImpl.java @@ -16,7 +16,6 @@ package com.google.idea.blaze.typescript; import com.google.common.base.Functions; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.idea.blaze.base.model.primitives.Label; @@ -197,18 +196,7 @@ public List getTypeScriptConfigs() { @Override public List getConfigFiles() { - List configs = this.configs.keySet().asList(); - StackTraceElement caller = Thread.currentThread().getStackTrace()[3]; - if (configs.size() == 1 && Objects.equals(caller.getMethodName(), "getDefaultConfigPath")) { - // If we have a single tsconfig file, IntelliJ will send a defaultConfig to the language - // service, which will override the isUseSingleInferredProject that we set and cause crashes - // in the language service when it tries to watch certain directories. - // We'll return an empty list here to fool IntelliJ into not sending the defaultConfig. - // This is extremely hacky. The proper fix should likely be somewhere in the tsconfig.json - // or in the typescript service. - return ImmutableList.of(); - } - return configs; + return this.configs.keySet().asList(); } @Override From ce7073a23065fdbe34407cfcd79ec27e3ac5a1c6 Mon Sep 17 00:00:00 2001 From: Alice Kober-Sotzek Date: Mon, 25 Oct 2021 00:47:40 -0700 Subject: [PATCH 09/47] Automated rollback of commit df4830088619d158a790514970de239824033503. *** Reason for rollback *** The default JDK is now set to Java 11 and we don't encounter the hybrid JDK 8/11 setup anymore. *** Original change description *** Avoid an issue with a hybrid JDK 8/11 setup when using fast run/debug From JDK 9 on, string concatenation is handled by StringConcatFactory. This causes issues for the fast run feature when the plugin runs javac with a JDK 8 as bootclasspath combined with "-source 8 target 11". The problematic behavior can be turned off at compile time by passing "-XDstringConcat=inline" (see also [this stackoverflow post](https://stackoverflow.com/a/58681713)). PiperOrigin-RevId: 405334857 --- .../blaze/java/fastbuild/FastBuildCompilerFactoryImpl.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/java/src/com/google/idea/blaze/java/fastbuild/FastBuildCompilerFactoryImpl.java b/java/src/com/google/idea/blaze/java/fastbuild/FastBuildCompilerFactoryImpl.java index c8c1a4f7d79..2cdbb4a2a83 100644 --- a/java/src/com/google/idea/blaze/java/fastbuild/FastBuildCompilerFactoryImpl.java +++ b/java/src/com/google/idea/blaze/java/fastbuild/FastBuildCompilerFactoryImpl.java @@ -242,12 +242,6 @@ public void compile(BlazeContext context, CompileInstructions instructions) .add("-cp") .add(instructions.classpath().stream().map(File::getPath).collect(joining(":"))) .add("-g"); - if ("8".equals(sourceVersion) && "11".equals(targetVersion)) { - // Disable StringConcatFactory (not available in JDK 8) to avoid issues when using - // "-source 8 -target 11" and a JDK 8 bootclasspath. Remove when only full JDK 11 is - // supported. - argsBuilder.add("-XDstringConcat=inline"); - } if (!bootClassPathJars.isEmpty()) { argsBuilder .add("-bootclasspath") From 62d98e798894f725bf1623a851a464ccf8163944 Mon Sep 17 00:00:00 2001 From: Googler Date: Mon, 25 Oct 2021 02:36:16 -0700 Subject: [PATCH 10/47] Upgrade language plugins for Go and Scala to version 2021.2.3 PiperOrigin-RevId: 405352648 --- WORKSPACE | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index c5ef6a222ae..727209723d8 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -169,8 +169,8 @@ http_archive( http_archive( name = "go_2021_2", build_file_content = _GO_BUILD_FILE, - sha256 = "99cb14fe215f92e7a2f257cf01490edf534ef39a85f99b60a7a41e367e567ab3", - url = "https://plugins.jetbrains.com/files/9568/133958/go-212.5080.55.zip", + sha256 = "c60cdbce31a4aa66648db6e69de4c6eeb590a030a80ad54b1e3ab6225a59c957", + url = "https://plugins.jetbrains.com/files/9568/139071/go-212.5457.20.zip", ) # Go plugin for IntelliJ UE. Required at compile-time for Bazel integration. @@ -209,8 +209,8 @@ http_archive( http_archive( name = "scala_2021_2", build_file_content = _SCALA_BUILD_FILE, - sha256 = "e6df682445a34acbe7bd60b84204e0ecb3ffacbfb7064ebfd394b8226c4e493f", - url = "https://plugins.jetbrains.com/files/1347/133149/scala-intellij-bin-2021.2.17.zip", + sha256 = "ed070fd47e5f349e6948b39ae521b14710b175fcd9668e58c0e762e3937b0e08", + url = "https://plugins.jetbrains.com/files/1347/139883/scala-intellij-bin-2021.2.23.zip", ) # Scala plugin for IntelliJ CE. Required at compile-time for scala-specific features. From ac40c20bdfd96e530001e98cfaceda01018d3d17 Mon Sep 17 00:00:00 2001 From: Alice Kober-Sotzek Date: Mon, 25 Oct 2021 02:42:02 -0700 Subject: [PATCH 11/47] FastBuild: Remove now unnecessary reflection code All current IDE versions the plugin is compatible with run on Java 11. As there's no need anymore to keep this code compatible with Java 8, remove the reflection code with a direct call. PiperOrigin-RevId: 405353599 --- .../java/fastbuild/FastBuildCompilerFactoryImpl.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/java/src/com/google/idea/blaze/java/fastbuild/FastBuildCompilerFactoryImpl.java b/java/src/com/google/idea/blaze/java/fastbuild/FastBuildCompilerFactoryImpl.java index 2cdbb4a2a83..1311706f142 100644 --- a/java/src/com/google/idea/blaze/java/fastbuild/FastBuildCompilerFactoryImpl.java +++ b/java/src/com/google/idea/blaze/java/fastbuild/FastBuildCompilerFactoryImpl.java @@ -200,19 +200,10 @@ private Class loadJavacClass(String javaCompilerClass, List jars) for (int i = 0; i < jars.size(); ++i) { urls[i] = jars.get(i).toURI().toURL(); } - URLClassLoader urlClassLoader = new URLClassLoader(urls, platformClassLoader()); + URLClassLoader urlClassLoader = new URLClassLoader(urls, ClassLoader.getPlatformClassLoader()); return urlClassLoader.loadClass(javaCompilerClass); } - private static ClassLoader platformClassLoader() { - try { - return (ClassLoader) ClassLoader.class.getMethod("getPlatformClassLoader").invoke(null); - } catch (ReflectiveOperationException e) { - // Java 8 - return null; - } - } - private static class JavacRunner implements FastBuildCompiler { private final Javac javac; From 52d9b32dd69eaae71239276c0e77bad32d5d8d78 Mon Sep 17 00:00:00 2001 From: Googler Date: Mon, 25 Oct 2021 06:29:59 -0700 Subject: [PATCH 12/47] Upgrade language plugins for Python-CE to version 2021.2.3 PiperOrigin-RevId: 405384211 --- WORKSPACE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 727209723d8..dbe067fb388 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -129,8 +129,8 @@ http_archive( http_archive( name = "python_2021_2", build_file_content = _PYTHON_CE_BUILD_FILE, - sha256 = "4025477d62a6eda6602fefea2abcfc0078ee387d5cc95dc303ee3583bc3604ce", - url = "https://plugins.jetbrains.com/files/7322/134206/python-ce-212.5080.64.zip", + sha256 = "e094cce16a4ca6062f0aa9974217299aa3d4fcec8130581e2d83c76bea10841a", + url = "https://plugins.jetbrains.com/files/7322/142192/python-ce-212.5457.59.zip", ) # Python plugin for IntelliJ CE. Required at compile-time for python-specific features. From 9352a986f8dfc94aa88ba6407a78fe099922c67f Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Mon, 25 Oct 2021 11:02:32 -0700 Subject: [PATCH 13/47] Internal change. PiperOrigin-RevId: 405443461 --- java/BUILD | 8 -------- .../FastBuildCompilerFactoryImplTest.java | 14 +++----------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/java/BUILD b/java/BUILD index b60808d086c..842f8d2b220 100644 --- a/java/BUILD +++ b/java/BUILD @@ -121,7 +121,6 @@ intellij_unit_test_suite( ":auto_value_plugin_lib_deploy.jar", ":fast_build_javac", ":guava_lib_deploy.jar", - ":jdk_tools_lib_deploy.jar", ":truth_lib_deploy.jar", ], jvm_flags = [ @@ -129,7 +128,6 @@ intellij_unit_test_suite( "-Dauto_value_plugin.jar=$(location :auto_value_plugin_lib_deploy.jar)", "-Dfast_build_javac.jar=$(location :fast_build_javac)", "-Dguava.jar=$(location :guava_lib_deploy.jar)", - "-Djdk_tools.jar=$(location :jdk_tools_lib_deploy.jar)", "-Dtruth.jar=$(location :truth_lib_deploy.jar)", ], test_package_root = "com.google.idea.blaze.java", @@ -168,12 +166,6 @@ java_binary( runtime_deps = ["//intellij_platform_sdk:guava"], ) -java_binary( - name = "jdk_tools_lib", - main_class = "None", - runtime_deps = ["//third_party/java/jdk:langtools"], -) - java_binary( name = "truth_lib", testonly = 1, diff --git a/java/tests/unittests/com/google/idea/blaze/java/fastbuild/FastBuildCompilerFactoryImplTest.java b/java/tests/unittests/com/google/idea/blaze/java/fastbuild/FastBuildCompilerFactoryImplTest.java index 5113aafa8e1..2cb71af510c 100644 --- a/java/tests/unittests/com/google/idea/blaze/java/fastbuild/FastBuildCompilerFactoryImplTest.java +++ b/java/tests/unittests/com/google/idea/blaze/java/fastbuild/FastBuildCompilerFactoryImplTest.java @@ -21,7 +21,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; -import com.google.idea.blaze.base.ideinfo.ArtifactLocation; import com.google.idea.blaze.base.model.BlazeProjectData; import com.google.idea.blaze.base.model.MockBlazeProjectDataBuilder; import com.google.idea.blaze.base.model.MockBlazeProjectDataManager; @@ -61,18 +60,12 @@ public final class FastBuildCompilerFactoryImplTest { private static final File FAST_BUILD_JAVAC_JAR = new File(System.getProperty("fast_build_javac.jar")); private static final File GUAVA_JAR = new File(System.getProperty("guava.jar")); - private static final File JDK_TOOLS_JAR = new File(System.getProperty("jdk_tools.jar")); private static final File TRUTH_JAR = new File(System.getProperty("truth.jar")); private static final String WORKSPACE_NAME = "io_bazel"; - private static ImmutableList getJavacJars() { - return ImmutableList.of( - ArtifactLocation.builder().setRelativePath(JDK_TOOLS_JAR.getPath()).build()); - } - private static final JavaToolchainInfo JAVA_TOOLCHAIN = JavaToolchainInfo.create( - getJavacJars(), + /* javacJars= */ ImmutableList.of(), /* bootJars= */ ImmutableList.of(), /* sourceVersion= */ "8", /* targetVersion= */ "8"); @@ -86,7 +79,6 @@ public static void verifyJars() { checkState(AUTO_VALUE_PLUGIN_JAR.exists()); checkState(GUAVA_JAR.exists()); checkState(FAST_BUILD_JAVAC_JAR.exists()); - checkState(JDK_TOOLS_JAR.exists()); checkState(TRUTH_JAR.exists()); } @@ -157,7 +149,7 @@ public void testMultipleDifferentJavaToolchains() { .setJavaInfo(JAVA_LIBRARY_WITHOUT_SOURCES) .setJavaToolchainInfo( JavaToolchainInfo.create( - getJavacJars(), + /* javacJars= */ ImmutableList.of(), /* bootJars= */ ImmutableList.of(), /* sourceVersion= */ "12345", /* targetVersion= */ "9876")) @@ -291,7 +283,7 @@ public void errorOnTooNewSource() throws IOException, FastBuildException { try { getCompiler( JavaToolchainInfo.create( - getJavacJars(), + /* javacJars= */ ImmutableList.of(), /* bootJars= */ ImmutableList.of(), /* sourceVersion= */ "7", /* targetVersion= */ "8")) From 6d6f94804dfb1be89db2380da87ad0b2a61f017a Mon Sep 17 00:00:00 2001 From: Googler Date: Mon, 25 Oct 2021 23:59:31 -0700 Subject: [PATCH 14/47] Fix incorrect reference to deleted class in extension order PiperOrigin-RevId: 405577078 --- base/src/META-INF/blaze-base.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/src/META-INF/blaze-base.xml b/base/src/META-INF/blaze-base.xml index 5322425f574..f3ed5e20856 100644 --- a/base/src/META-INF/blaze-base.xml +++ b/base/src/META-INF/blaze-base.xml @@ -552,7 +552,7 @@ - + From 731ce24d5052c76557c794b9ec1d20aaa2c4d625 Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 26 Oct 2021 18:18:08 -0700 Subject: [PATCH 15/47] Output template content and substitutions of TemplateExpansionAction actions in aquery result. PiperOrigin-RevId: 405780883 --- third_party/bazel/src/main/protobuf/analysis_v2.proto | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/third_party/bazel/src/main/protobuf/analysis_v2.proto b/third_party/bazel/src/main/protobuf/analysis_v2.proto index f3833f9a33a..8f25c471799 100644 --- a/third_party/bazel/src/main/protobuf/analysis_v2.proto +++ b/third_party/bazel/src/main/protobuf/analysis_v2.proto @@ -104,6 +104,14 @@ message Action { // The execution platform for this action. Empty if the action has no // execution platform. string execution_platform = 14; + + // The template content of the action, if it is TemplateExpand action. + string template_content = 15; + + // The list of substitution should be performed on the template. The key is + // the string to be substituted and the value is the string to be substituted + // to. + repeated KeyValuePair substitutions = 16; } // Represents a single target (without configuration information) that is From 30257b6bb314217a6224a0ffe3636545910804fa Mon Sep 17 00:00:00 2001 From: Googler Date: Wed, 27 Oct 2021 10:39:52 -0700 Subject: [PATCH 16/47] Switch invocation policy enforcer to use behavior enum instead of the old boolean flags. We have recently added a new enum to express the intended behavior for `SetValue` invocation policy entries. This enum replaces the `overridable` and `append` boolean flags and offers significant advantages over those -- does not have a usable default value, thus must be explicitly set, and does not allow combination of `overridable && append` which is semantically contradictory (`overridable` only applies to non-repetable flags and `append` to repeatable flags). Deprecate the boolean flags which are superseded by the new enum and use the enum instead of the boolean flags in invocation policy enforcer. PiperOrigin-RevId: 405924139 --- .../src/main/protobuf/invocation_policy.proto | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/third_party/bazel/src/main/protobuf/invocation_policy.proto b/third_party/bazel/src/main/protobuf/invocation_policy.proto index 38869e7d114..0d687f81ccd 100644 --- a/third_party/bazel/src/main/protobuf/invocation_policy.proto +++ b/third_party/bazel/src/main/protobuf/invocation_policy.proto @@ -100,18 +100,8 @@ message SetValue { // may fail to parse or result in an unexpected value. repeated string flag_value = 1; - // Whether to allow this policy to be overridden by user-specified values. - // When set, if the user specified a value for this flag, use the value - // from the user, otherwise use the value specified in this policy. - // This value is redundant to behavior -- please keep it in sync with it. - optional bool overridable = 2; - - // If true, and if the flag named in the policy is a repeatable flag, then - // the values listed in flag_value do not replace all the user-set or default - // values of the flag, but instead append to them. If the flag is not - // repeatable, then this has no effect. - // This value is redundant to behavior -- please keep it in sync with it. - optional bool append = 3; + // Obsolete overridable and append fields. + reserved 2, 3; enum Behavior { UNDEFINED = 0; @@ -134,8 +124,6 @@ message SetValue { // For the time being, it coexists with overridable and append with duplicate // semantics.Please fill both of the values as we migrate to use behavior // only. - // TODO(b/186167747): Deprecate and remove append and overridable flag in - // favor of this one. optional Behavior behavior = 4; } From dcc3293ba560eb824fd1dc1652604f651a00fe24 Mon Sep 17 00:00:00 2001 From: Tim Peut Date: Wed, 27 Oct 2021 15:04:07 -0700 Subject: [PATCH 17/47] Add additional fields to android deploy info to support mobile-install usage. PiperOrigin-RevId: 405990157 --- .../bazel/src/main/protobuf/android_deploy_info.proto | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/third_party/bazel/src/main/protobuf/android_deploy_info.proto b/third_party/bazel/src/main/protobuf/android_deploy_info.proto index 46a1197a350..d491e5623ac 100644 --- a/third_party/bazel/src/main/protobuf/android_deploy_info.proto +++ b/third_party/bazel/src/main/protobuf/android_deploy_info.proto @@ -13,6 +13,7 @@ // limitations under the License. syntax = "proto3"; + package blaze; // option java_api_version = 2; @@ -21,6 +22,10 @@ option java_package = "com.google.devtools.build.lib.rules.android.deployinfo"; message Artifact { // This path is relative to "bazel info execution_root" string exec_root_path = 1; + + // Points to a globally valid URI whenever possible. + // See BuildEventStreamOptions.java + string canonical_uri = 2; } // Information about how to deploy and launch the result of an android build @@ -37,4 +42,7 @@ message AndroidDeployInfo { // Unused repeated Artifact data_to_deploy = 4; + + // Used by mobile-install + string manifest_package_name = 5; } From 44e6ed9f51d3678065a17c267a592c89e5265abc Mon Sep 17 00:00:00 2001 From: Mai Hussien Date: Fri, 29 Oct 2021 01:27:52 -0700 Subject: [PATCH 18/47] Import CLion 2021.3 EAP plugin api as oss-under-dev PiperOrigin-RevId: 406309745 --- WORKSPACE | 8 ++ intellij_platform_sdk/BUILD | 17 +++++ intellij_platform_sdk/BUILD.clion213 | 106 +++++++++++++++++++++++++++ intellij_platform_sdk/build_defs.bzl | 10 ++- sdkcompat/BUILD | 1 + testing/BUILD | 1 + third_party/javascript/BUILD | 4 + third_party/python/BUILD | 1 + 8 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 intellij_platform_sdk/BUILD.clion213 diff --git a/WORKSPACE b/WORKSPACE index dbe067fb388..403aebef971 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -101,6 +101,14 @@ http_archive( url = "https://download.jetbrains.com/cpp/CLion-2021.2.3.tar.gz", ) +# The plugin api for clion_2021_3. This is required to build CLwB, and run integration tests. +http_archive( + name = "clion_2021_3", + build_file = "@//intellij_platform_sdk:BUILD.clion213", + sha256 = "fa74a1e1433fdcd662d7cfae50b914f0b2eb3275b21a9e1caa50efac0f913a81", + url = "https://download.jetbrains.com/cpp/CLion-213.4928.11.tar.gz", +) + _PYTHON_CE_BUILD_FILE = """ java_import( name = "python", diff --git a/intellij_platform_sdk/BUILD b/intellij_platform_sdk/BUILD index 6214b907dcd..ccc9ecc5457 100644 --- a/intellij_platform_sdk/BUILD +++ b/intellij_platform_sdk/BUILD @@ -412,6 +412,21 @@ config_setting( }, ) +config_setting( + name = "clion-2021.3", + values = { + "define": "ij_product=clion-2021.3", + }, +) + +config_setting( + name = "clion-2021.3-mac", + values = { + "cpu": "darwin_x86_64", + "define": "ij_product=clion-2021.3", + }, +) + # The purpose of this rule is to hide the versioning # complexity from users of this api. # There will be additional versions added in the future @@ -506,6 +521,7 @@ java_library( "clion-2020.3": [":bundled_jsr305"], "clion-2021.1": [":bundled_jsr305"], "clion-2021.2": [":bundled_jsr305"], + "clion-2021.3": [":bundled_jsr305"], "intellij-2020.3": [":bundled_jsr305"], "intellij-2021.1": [":bundled_jsr305"], "intellij-2021.2": ["@jsr305_annotations//jar"], @@ -664,6 +680,7 @@ filegroup( "intellij-2021.3": [":application_info_json"], "intellij-ue-2021.3": [":application_info_json"], "clion-2021.2": [":application_info_json"], + "clion-2021.3": [":application_info_json"], "default": [":application_info_jar"], }), ) diff --git a/intellij_platform_sdk/BUILD.clion213 b/intellij_platform_sdk/BUILD.clion213 new file mode 100644 index 00000000000..5a29d03361c --- /dev/null +++ b/intellij_platform_sdk/BUILD.clion213 @@ -0,0 +1,106 @@ +# Description: +# +# Plugin source jars for CLion, accessed remotely. + +load("@//intellij_platform_sdk:build_defs.bzl", "no_mockito_extensions") + +package(default_visibility = ["//visibility:public"]) + +java_import( + name = "sdk", + jars = glob( + ["clion-*/lib/*.jar"], + exclude = glob([ + # mockito-extensions needs to be removed from this jar. + "clion-*/lib/testFramework.jar", + ]), + ), + tags = ["intellij-provided-by-sdk"], + exports = [":jars_without_mockito_extensions"], + deps = ["@error_prone_annotations//jar"], +) + +no_mockito_extensions( + name = "jars_without_mockito_extensions", + jars = glob(["clion-*/lib/testFramework.jar"]), +) + +java_import( + name = "guava", + jars = glob([ + "clion-*/lib/3rd-party.jar", + ]), +) + +java_import( + name = "jsr305", + jars = glob(["clion-*/lib/3rd-party.jar"]), +) + +java_import( + name = "clion_plugins", + jars = glob([ + "clion-*/plugins/c-plugin/lib/*.jar", + "clion-*/plugins/cidr-base-plugin/lib/*.jar", + "clion-*/plugins/cidr-debugger-plugin/lib/*.jar", + "clion-*/plugins/clion/lib/*.jar", + "clion-*/plugins/clion-test-google/lib/*.jar", + "clion-*/plugins/clion-test-catch/lib/*.jar", + "clion-*/plugins/clion-test-boost/lib/*.jar", + ]), +) + +java_import( + name = "hg4idea", + jars = glob(["clion-*/plugins/hg4idea/lib/hg4idea.jar"]), +) + +java_import( + name = "javascript", + jars = glob(["clion-*/plugins/JavaScriptLanguage/lib/*.jar"]), +) + +java_import( + name = "css", + jars = glob(["clion-*/plugins/CSS/lib/*.jar"]), +) + +java_import( + name = "tslint", + jars = glob(["clion-*/plugins/tslint/lib/*.jar"]), +) + +java_import( + name = "tasks", + jars = glob([ + "clion-*/plugins/tasks/lib/tasks-api.jar", + "clion-*/plugins/tasks/lib/tasks-core.jar", + ]), +) + +java_import( + name = "terminal", + jars = glob(["clion-*/plugins/terminal/lib/terminal.jar"]), +) + +java_import( + name = "python", + jars = glob(["clion-*/plugins/python-ce/lib/*.jar"]), +) + +# The plugins required by CLwB. Presumably there will be some, when we write +# some integration tests. +java_import( + name = "bundled_plugins", + jars = [], + tags = ["intellij-provided-by-sdk"], +) + +filegroup( + name = "application_info_json", + srcs = glob(["clion-*/product-info.json"]), +) + +filegroup( + name = "application_info_jar", +) diff --git a/intellij_platform_sdk/build_defs.bzl b/intellij_platform_sdk/build_defs.bzl index 40140475e29..e29514ddb68 100644 --- a/intellij_platform_sdk/build_defs.bzl +++ b/intellij_platform_sdk/build_defs.bzl @@ -31,7 +31,7 @@ INDIRECT_IJ_PRODUCTS = { "android-studio-oss-under-dev": "android-studio-2021.1", "clion-oss-stable": "clion-2021.2", "clion-oss-beta": "clion-2021.2", - "clion-oss-under-dev": "clion-2021.2", + "clion-oss-under-dev": "clion-2021.3", } DIRECT_IJ_PRODUCTS = { @@ -135,6 +135,14 @@ DIRECT_IJ_PRODUCTS = { ide = "clion", directory = "clion_2021_2", ), + "clion-2021.3": struct( + ide = "clion", + directory = "clion_2021_3", + ), + "clion-2021.3-mac": struct( + ide = "clion", + directory = "clion_2021_3", + ), } def select_for_plugin_api(params): diff --git a/sdkcompat/BUILD b/sdkcompat/BUILD index 9347df45202..6fae501538b 100644 --- a/sdkcompat/BUILD +++ b/sdkcompat/BUILD @@ -28,5 +28,6 @@ java_library( "clion-2020.3": ["//sdkcompat/v203"], "clion-2021.1": ["//sdkcompat/v211"], "clion-2021.2": ["//sdkcompat/v212"], + "clion-2021.3": ["//sdkcompat/v212"], }), ) diff --git a/testing/BUILD b/testing/BUILD index 9156a5938d6..3e69adcd024 100644 --- a/testing/BUILD +++ b/testing/BUILD @@ -36,6 +36,7 @@ java_library( "clion-2020.3": glob(["testcompat/v203/com/google/idea/sdkcompat/**/*.java"]), "clion-2021.1": glob(["testcompat/v211/com/google/idea/sdkcompat/**/*.java"]), "clion-2021.2": glob(["testcompat/v212/com/google/idea/sdkcompat/**/*.java"]), + "clion-2021.3": glob(["testcompat/v212/com/google/idea/sdkcompat/**/*.java"]), "intellij-2020.3": glob(["testcompat/v203/com/google/idea/sdkcompat/**/*.java"]), "intellij-ue-2020.3": glob(["testcompat/v203/com/google/idea/sdkcompat/**/*.java"]), "intellij-2021.1": glob(["testcompat/v211/com/google/idea/sdkcompat/**/*.java"]), diff --git a/third_party/javascript/BUILD b/third_party/javascript/BUILD index adddf462ed4..89804f420ee 100644 --- a/third_party/javascript/BUILD +++ b/third_party/javascript/BUILD @@ -16,6 +16,7 @@ java_library( "clion-2020.3": ["@clion_2020_3//:javascript"], "clion-2021.1": ["@clion_2021_1//:javascript"], "clion-2021.2": ["@clion_2021_2//:javascript"], + "clion-2021.3": ["@clion_2021_3//:javascript"], "default": [], }), ) @@ -32,6 +33,7 @@ java_library( "clion-2020.3": ["@clion_2020_3//:css"], "clion-2021.1": ["@clion_2021_1//:css"], "clion-2021.2": ["@clion_2021_2//:css"], + "clion-2021.3": ["@clion_2021_3//:css"], "default": [], }), ) @@ -48,6 +50,7 @@ java_library( "clion-2020.3": ["@clion_2020_3//:tslint"], "clion-2021.1": ["@clion_2021_1//:tslint"], "clion-2021.2": ["@clion_2021_2//:tslint"], + "clion-2021.3": ["@clion_2021_3//:tslint"], "default": [], }), ) @@ -64,6 +67,7 @@ java_library( "clion-2020.3": ["@intellij_ue_2020_3//:angular"], "clion-2021.1": ["@intellij_ue_2021_1//:angular"], "clion-2021.2": ["@intellij_ue_2021_2//:angular"], + "clion-2021.3": ["@intellij_ue_2021_3//:angular"], "default": [], }), ) diff --git a/third_party/python/BUILD b/third_party/python/BUILD index e662f2ddcfe..6e5f9345529 100644 --- a/third_party/python/BUILD +++ b/third_party/python/BUILD @@ -19,6 +19,7 @@ java_library( "clion-2020.3": ["@clion_2020_3//:python"], "clion-2021.1": ["@clion_2021_1//:python"], "clion-2021.2": ["@clion_2021_2//:python"], + "clion-2021.3": ["@clion_2021_3//:python"], "android-studio-2020.3": ["@python_2020_3//:python"], "android-studio-2021.1": ["@python_2021_1//:python"], }), From b24d9355a93e1f2ed8e5c30c16e0fca1c4bfe6cc Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 2 Nov 2021 12:32:29 -0700 Subject: [PATCH 19/47] Update changelogs for 2021.11.02 release PiperOrigin-RevId: 407150809 --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index a91466aea9f..87d12b5c20e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -v2021.10.19 +v2021.11.02 =========== * Bug fixes and internal cleanup. From 8a81d085694511d5e1f202e1a396e3fd498c222b Mon Sep 17 00:00:00 2001 From: Googler Date: Wed, 3 Nov 2021 17:21:36 -0700 Subject: [PATCH 20/47] Branch as211 sdkcompat to as212 PiperOrigin-RevId: 407463790 --- .../idea/run/tasks/DeployTasksCompat.java | 74 +++++++ .../projectsystem/BlazeModuleSystem.java | 159 ++++++++++++++ .../ExternalLibraryInterner.java | 35 +++ .../blaze/android/resources/BlazeRClass.java | 82 +++++++ .../run/BlazeAndroidDeploymentService.java | 49 +++++ ...azeAndroidBinaryNormalBuildRunContext.java | 56 +++++ ...eAndroidBinaryMobileInstallRunContext.java | 57 +++++ .../BlazeAndroidLaunchTasksProvider.java | 206 ++++++++++++++++++ .../run/runner/BlazeAndroidRunContext.java | 75 +++++++ .../run/test/BlazeAndroidTestRunContext.java | 91 ++++++++ .../test/ConnectBlazeTestDebuggerTask.java | 138 ++++++++++++ .../sync/model/idea/BlazeAndroidModel.java | 53 +++++ 12 files changed, 1075 insertions(+) create mode 100644 aswb/sdkcompat/as212/com/android/tools/idea/run/tasks/DeployTasksCompat.java create mode 100644 aswb/sdkcompat/as212/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java create mode 100644 aswb/sdkcompat/as212/com/google/idea/blaze/android/projectsystem/ExternalLibraryInterner.java create mode 100644 aswb/sdkcompat/as212/com/google/idea/blaze/android/resources/BlazeRClass.java create mode 100644 aswb/sdkcompat/as212/com/google/idea/blaze/android/run/BlazeAndroidDeploymentService.java create mode 100644 aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java create mode 100644 aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java create mode 100644 aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java create mode 100644 aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java create mode 100644 aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java create mode 100644 aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/ConnectBlazeTestDebuggerTask.java create mode 100644 aswb/sdkcompat/as212/com/google/idea/blaze/android/sync/model/idea/BlazeAndroidModel.java diff --git a/aswb/sdkcompat/as212/com/android/tools/idea/run/tasks/DeployTasksCompat.java b/aswb/sdkcompat/as212/com/android/tools/idea/run/tasks/DeployTasksCompat.java new file mode 100644 index 00000000000..3365e2bc5e0 --- /dev/null +++ b/aswb/sdkcompat/as212/com/android/tools/idea/run/tasks/DeployTasksCompat.java @@ -0,0 +1,74 @@ +/* + * Copyright 2020 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.android.tools.idea.run.tasks; + +import com.android.tools.idea.deploy.DeploymentConfiguration; +import com.android.tools.idea.run.ApkInfo; +import com.android.tools.idea.run.LaunchOptions; +import com.android.tools.idea.run.util.SwapInfo; +import com.android.tools.idea.run.util.SwapInfo.SwapType; +import com.google.idea.blaze.android.run.BlazeAndroidDeploymentService; +import com.google.idea.common.experiments.BoolExperiment; +import com.intellij.execution.runners.ExecutionEnvironment; +import com.intellij.openapi.project.Project; +import java.util.Collection; + +/** Compat class for {@link DeployTask} */ +public class DeployTasksCompat { + private static final BoolExperiment updateCodeViaJvmti = + new BoolExperiment("android.apply.changes", false); + + private DeployTasksCompat() {} + + public static LaunchTask createDeployTask( + Project project, Collection packages, LaunchOptions launchOptions) { + // We don't have a device information, fallback to the most conservative + // install option. + return new DeployTask( + project, + packages, + launchOptions.getPmInstallOptions(/*device=*/ null), + launchOptions.getInstallOnAllUsers(), + launchOptions.getAlwaysInstallWithPm()); + } + + public static LaunchTask getDeployTask( + Project project, + ExecutionEnvironment env, + LaunchOptions launchOptions, + Collection packages) { + if (updateCodeViaJvmti.getValue()) { + // Set the appropriate action based on which deployment we're doing. + SwapInfo swapInfo = env.getUserData(SwapInfo.SWAP_INFO_KEY); + SwapInfo.SwapType swapType = swapInfo == null ? null : swapInfo.getType(); + if (swapType == SwapType.APPLY_CHANGES) { + return new ApplyChangesTask( + project, + packages, + DeploymentConfiguration.getInstance().APPLY_CHANGES_FALLBACK_TO_RUN, + false); + } else if (swapType == SwapType.APPLY_CODE_CHANGES) { + return new ApplyCodeChangesTask( + project, + packages, + DeploymentConfiguration.getInstance().APPLY_CODE_CHANGES_FALLBACK_TO_RUN, + false); + } + } + return BlazeAndroidDeploymentService.getInstance(project) + .getDeployTask(packages, launchOptions); + } +} diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java new file mode 100644 index 00000000000..2703983d02f --- /dev/null +++ b/aswb/sdkcompat/as212/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java @@ -0,0 +1,159 @@ +/* + * Copyright 2020 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.android.projectsystem; + +import com.android.ide.common.util.PathString; +import com.android.projectmodel.ExternalAndroidLibrary; +import com.android.projectmodel.ExternalLibraryImpl; +import com.android.projectmodel.SelectiveResourceFolder; +import com.android.tools.idea.projectsystem.AndroidModuleSystem; +import com.android.tools.idea.projectsystem.DependencyScopeType; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.idea.blaze.android.libraries.UnpackedAars; +import com.google.idea.blaze.android.sync.model.AarLibrary; +import com.google.idea.blaze.android.sync.model.AndroidResourceModuleRegistry; +import com.google.idea.blaze.android.sync.model.BlazeAndroidSyncData; +import com.google.idea.blaze.base.ideinfo.TargetIdeInfo; +import com.google.idea.blaze.base.model.BlazeLibrary; +import com.google.idea.blaze.base.model.BlazeProjectData; +import com.google.idea.blaze.base.projectview.ProjectViewManager; +import com.google.idea.blaze.base.sync.SyncCache; +import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager; +import com.google.idea.blaze.base.sync.libraries.BlazeLibraryCollector; +import com.google.idea.blaze.base.sync.workspace.ArtifactLocationDecoder; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import java.io.File; +import java.util.Collection; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** Blaze implementation of {@link AndroidModuleSystem}. */ +public class BlazeModuleSystem extends BlazeModuleSystemBase { + BlazeModuleSystem(Module module) { + super(module); + } + + public Collection getDependentLibraries() { + BlazeProjectData blazeProjectData = + BlazeProjectDataManager.getInstance(project).getBlazeProjectData(); + + if (blazeProjectData == null) { + return ImmutableList.of(); + } + + if (isWorkspaceModule) { + return SyncCache.getInstance(project) + .get(BlazeModuleSystem.class, BlazeModuleSystem::getLibrariesForWorkspaceModule); + } + + AndroidResourceModuleRegistry registry = AndroidResourceModuleRegistry.getInstance(project); + TargetIdeInfo target = blazeProjectData.getTargetMap().get(registry.getTargetKey(module)); + if (target == null) { + // this can happen if the module points to the , + // does not contain any resource + // contains all external resources as module's local resources, so there's + // no dependent libraries + return ImmutableList.of(); + } + + BlazeAndroidSyncData androidSyncData = + blazeProjectData.getSyncState().get(BlazeAndroidSyncData.class); + if (androidSyncData == null) { + return ImmutableList.of(); + } + + ImmutableList.Builder libraries = ImmutableList.builder(); + ArtifactLocationDecoder decoder = blazeProjectData.getArtifactLocationDecoder(); + ExternalLibraryInterner externalLibraryInterner = ExternalLibraryInterner.getInstance(project); + for (String libraryKey : registry.get(module).resourceLibraryKeys) { + ImmutableMap aarLibraries = androidSyncData.importResult.aarLibraries; + ExternalAndroidLibrary externalLibrary = + toExternalLibrary(project, aarLibraries.get(libraryKey), decoder); + if (externalLibrary != null) { + libraries.add(externalLibraryInterner.intern(externalLibrary)); + } + } + return libraries.build(); + } + + private static ImmutableList getLibrariesForWorkspaceModule( + Project project, BlazeProjectData blazeProjectData) { + ArtifactLocationDecoder decoder = blazeProjectData.getArtifactLocationDecoder(); + ExternalLibraryInterner externalLibraryInterner = ExternalLibraryInterner.getInstance(project); + ImmutableList.Builder libraries = ImmutableList.builder(); + for (BlazeLibrary library : + BlazeLibraryCollector.getLibraries( + ProjectViewManager.getInstance(project).getProjectViewSet(), blazeProjectData)) { + if (library instanceof AarLibrary) { + ExternalAndroidLibrary externalLibrary = + toExternalLibrary(project, (AarLibrary) library, decoder); + if (externalLibrary != null) { + libraries.add(externalLibraryInterner.intern(externalLibrary)); + } + } + } + return libraries.build(); + } + + @Nullable + static ExternalAndroidLibrary toExternalLibrary( + Project project, @Nullable AarLibrary library, ArtifactLocationDecoder decoder) { + if (library == null) { + return null; + } + UnpackedAars unpackedAars = UnpackedAars.getInstance(project); + File aarFile = unpackedAars.getAarDir(decoder, library); + if (aarFile == null) { + logger.warn( + String.format( + "Fail to locate AAR file %s. Re-sync the project may solve the problem", + library.aarArtifact)); + return null; + } + File resFolder = unpackedAars.getResourceDirectory(decoder, library); + PathString resFolderPathString = resFolder == null ? null : new PathString(resFolder); + return new ExternalLibraryImpl(library.key.toString()) + .withLocation(new PathString(aarFile)) + .withManifestFile( + resFolderPathString == null + ? null + : resFolderPathString.getParentOrRoot().resolve("AndroidManifest.xml")) + .withResFolder( + resFolderPathString == null + ? null + : new SelectiveResourceFolder(resFolderPathString, null)) + .withSymbolFile( + resFolderPathString == null + ? null + : resFolderPathString.getParentOrRoot().resolve("R.txt")) + .withPackageName(library.resourcePackage); + } + + @NotNull + @Override + public Collection getAndroidLibraryDependencies() { + return getDependentLibraries(); + } + + @NotNull + @Override + public Collection getAndroidLibraryDependencies( + @NotNull DependencyScopeType dependencyScopeType) { + return getDependentLibraries(); + } +} diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/projectsystem/ExternalLibraryInterner.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/projectsystem/ExternalLibraryInterner.java new file mode 100644 index 00000000000..428579821e8 --- /dev/null +++ b/aswb/sdkcompat/as212/com/google/idea/blaze/android/projectsystem/ExternalLibraryInterner.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * 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.android.projectsystem; + +import com.android.projectmodel.ExternalAndroidLibrary; +import com.google.common.collect.Interner; +import com.google.common.collect.Interners; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; + +/** Project Level service to dedup instances of {@link ExternalAndroidLibrary}. */ +public class ExternalLibraryInterner { + private Interner externalLibraryInterner = Interners.newWeakInterner(); + + public static ExternalLibraryInterner getInstance(Project project) { + return ServiceManager.getService(project, ExternalLibraryInterner.class); + } + + public ExternalAndroidLibrary intern(ExternalAndroidLibrary externalLibrary) { + return externalLibraryInterner.intern(externalLibrary); + } +} diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/resources/BlazeRClass.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/resources/BlazeRClass.java new file mode 100644 index 00000000000..2c123e0a66f --- /dev/null +++ b/aswb/sdkcompat/as212/com/google/idea/blaze/android/resources/BlazeRClass.java @@ -0,0 +1,82 @@ +/* + * Copyright 2018 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.android.resources; + +import static org.jetbrains.android.AndroidResolveScopeEnlarger.LIGHT_CLASS_KEY; +import static org.jetbrains.android.AndroidResolveScopeEnlarger.MODULE_POINTER_KEY; + +import com.android.ide.common.rendering.api.ResourceNamespace; +import com.android.tools.idea.res.LocalResourceRepository; +import com.android.tools.idea.res.ResourceRepositoryManager; +import com.android.tools.idea.res.ResourceRepositoryRClass; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModulePointerManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiManager; +import org.jetbrains.android.augment.AndroidLightField; +import org.jetbrains.android.facet.AndroidFacet; + +/** Blaze implementation of an R class based on resource repositories. */ +public class BlazeRClass extends ResourceRepositoryRClass { + + private final AndroidFacet androidFacet; + + public BlazeRClass(PsiManager psiManager, AndroidFacet androidFacet, String packageName) { + super( + psiManager, + new ResourcesSource() { + @Override + public String getPackageName() { + return packageName; + } + + // @Override #api4.1 + public Transitivity getTransitivity() { + return Transitivity.TRANSITIVE; + } + + @Override + public ResourceRepositoryManager getResourceRepositoryManager() { + return ResourceRepositoryManager.getInstance(androidFacet); + } + + @Override + public LocalResourceRepository getResourceRepository() { + return ResourceRepositoryManager.getAppResources(androidFacet); + } + + @Override + public ResourceNamespace getResourceNamespace() { + return ResourceNamespace.RES_AUTO; + } + + @Override + public AndroidLightField.FieldModifier getFieldModifier() { + return AndroidLightField.FieldModifier.NON_FINAL; + } + }); + this.androidFacet = androidFacet; + setModuleInfo(getModule(), false); + VirtualFile virtualFile = myFile.getViewProvider().getVirtualFile(); + virtualFile.putUserData( + MODULE_POINTER_KEY, ModulePointerManager.getInstance(getProject()).create(getModule())); + virtualFile.putUserData(LIGHT_CLASS_KEY, ResourceRepositoryRClass.class); + } + + public Module getModule() { + return androidFacet.getModule(); + } +} diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/BlazeAndroidDeploymentService.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/BlazeAndroidDeploymentService.java new file mode 100644 index 00000000000..032ec26e8bb --- /dev/null +++ b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/BlazeAndroidDeploymentService.java @@ -0,0 +1,49 @@ +/* + * Copyright 2020 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.android.run; + +import com.android.tools.idea.run.ApkInfo; +import com.android.tools.idea.run.LaunchOptions; +import com.android.tools.idea.run.tasks.DeployTask; +import com.android.tools.idea.run.tasks.DeployTasksCompat; +import com.android.tools.idea.run.tasks.LaunchTask; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import java.util.Collection; + +/** A service that provides {@link DeployTask}. */ +public interface BlazeAndroidDeploymentService { + static BlazeAndroidDeploymentService getInstance(Project project) { + return ServiceManager.getService(project, BlazeAndroidDeploymentService.class); + } + + /** Returns a {@link DeployTask} to deploy the given files and launch options. */ + LaunchTask getDeployTask(Collection packages, LaunchOptions launchOptions); + + /** A default implementation that uses {@link DeployTasksCompat#createDeployTask}. */ + class DefaultDeploymentService implements BlazeAndroidDeploymentService { + private final Project project; + + public DefaultDeploymentService(Project project) { + this.project = project; + } + + @Override + public LaunchTask getDeployTask(Collection packages, LaunchOptions launchOptions) { + return DeployTasksCompat.createDeployTask(project, packages, launchOptions); + } + } +} diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java new file mode 100644 index 00000000000..b44fb8c8eee --- /dev/null +++ b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019 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.android.run.binary; + +import com.android.tools.idea.run.editor.AndroidDebugger; +import com.android.tools.idea.run.editor.AndroidDebuggerState; +import com.android.tools.idea.run.tasks.ConnectDebuggerTask; +import com.google.idea.blaze.android.run.runner.BlazeApkBuildStep; +import com.intellij.execution.ExecutionException; +import com.intellij.execution.configurations.RunConfiguration; +import com.intellij.execution.runners.ExecutionEnvironment; +import com.intellij.openapi.project.Project; +import javax.annotation.Nullable; +import org.jetbrains.android.facet.AndroidFacet; + +/** Compat for #api203 */ +public class BlazeAndroidBinaryNormalBuildRunContext + extends BlazeAndroidBinaryNormalBuildRunContextBase { + BlazeAndroidBinaryNormalBuildRunContext( + Project project, + AndroidFacet facet, + RunConfiguration runConfiguration, + ExecutionEnvironment env, + BlazeAndroidBinaryRunConfigurationState configState, + BlazeApkBuildStep buildStep) { + super(project, facet, runConfiguration, env, configState, buildStep); + } + + @Nullable + @Override + @SuppressWarnings("unchecked") + public ConnectDebuggerTask getDebuggerTask( + AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState) + throws ExecutionException { + return androidDebugger.getConnectDebuggerTask( + env, + null, + applicationIdProvider, + facet, + androidDebuggerState, + runConfiguration.getType().getId()); + } +} diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java new file mode 100644 index 00000000000..d387698e763 --- /dev/null +++ b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java @@ -0,0 +1,57 @@ +/* + * Copyright 2016 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.android.run.binary.mobileinstall; + +import com.android.tools.idea.run.editor.AndroidDebugger; +import com.android.tools.idea.run.editor.AndroidDebuggerState; +import com.android.tools.idea.run.tasks.ConnectDebuggerTask; +import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryRunConfigurationState; +import com.google.idea.blaze.android.run.runner.BlazeApkBuildStep; +import com.intellij.execution.ExecutionException; +import com.intellij.execution.configurations.RunConfiguration; +import com.intellij.execution.runners.ExecutionEnvironment; +import com.intellij.openapi.project.Project; +import javax.annotation.Nullable; +import org.jetbrains.android.facet.AndroidFacet; + +/** Run Context for mobile install launches, #api4.0 compat. */ +public class BlazeAndroidBinaryMobileInstallRunContext + extends BlazeAndroidBinaryMobileInstallRunContextBase { + public BlazeAndroidBinaryMobileInstallRunContext( + Project project, + AndroidFacet facet, + RunConfiguration runConfiguration, + ExecutionEnvironment env, + BlazeAndroidBinaryRunConfigurationState configState, + BlazeApkBuildStep buildStep) { + super(project, facet, runConfiguration, env, configState, buildStep); + } + + @Nullable + @Override + @SuppressWarnings("unchecked") + public ConnectDebuggerTask getDebuggerTask( + AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState) + throws ExecutionException { + return androidDebugger.getConnectDebuggerTask( + env, + null, + applicationIdProvider, + facet, + androidDebuggerState, + runConfiguration.getType().getId()); + } +} diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java new file mode 100644 index 00000000000..72bf4c15c0d --- /dev/null +++ b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java @@ -0,0 +1,206 @@ +/* + * Copyright 2018 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.android.run.runner; + +import static com.android.tools.idea.profilers.AndroidProfilerLaunchTaskContributor.isProfilerLaunch; + +import com.android.ddmlib.IDevice; +import com.android.sdklib.AndroidVersion; +import com.android.tools.deployer.ApkVerifierTracker; +import com.android.tools.idea.profilers.AndroidProfilerLaunchTaskContributor; +import com.android.tools.idea.run.ApkProvisionException; +import com.android.tools.idea.run.ApplicationIdProvider; +import com.android.tools.idea.run.ConsolePrinter; +import com.android.tools.idea.run.LaunchOptions; +import com.android.tools.idea.run.editor.AndroidDebugger; +import com.android.tools.idea.run.editor.AndroidDebuggerState; +import com.android.tools.idea.run.tasks.ClearLogcatTask; +import com.android.tools.idea.run.tasks.ConnectDebuggerTask; +import com.android.tools.idea.run.tasks.DismissKeyguardTask; +import com.android.tools.idea.run.tasks.LaunchTask; +import com.android.tools.idea.run.tasks.LaunchTasksProvider; +import com.android.tools.idea.run.tasks.ShowLogcatTask; +import com.android.tools.idea.run.util.LaunchStatus; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.idea.blaze.android.run.binary.UserIdHelper; +import com.intellij.execution.ExecutionException; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import java.util.List; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** Normal launch tasks provider. #api4.1 */ +public class BlazeAndroidLaunchTasksProvider implements LaunchTasksProvider { + public static final String NATIVE_DEBUGGING_ENABLED = "NATIVE_DEBUGGING_ENABLED"; + private static final Logger LOG = Logger.getInstance(BlazeAndroidLaunchTasksProvider.class); + + private final Project project; + private final BlazeAndroidRunContext runContext; + private final ApplicationIdProvider applicationIdProvider; + private final LaunchOptions.Builder launchOptionsBuilder; + + public BlazeAndroidLaunchTasksProvider( + Project project, + BlazeAndroidRunContext runContext, + ApplicationIdProvider applicationIdProvider, + LaunchOptions.Builder launchOptionsBuilder) { + this.project = project; + this.runContext = runContext; + this.applicationIdProvider = applicationIdProvider; + this.launchOptionsBuilder = launchOptionsBuilder; + } + + @NotNull + @Override + public List getTasks( + @NotNull IDevice device, + @NotNull LaunchStatus launchStatus, + @NotNull ConsolePrinter consolePrinter) + throws ExecutionException { + final List launchTasks = Lists.newArrayList(); + + String packageName; + try { + packageName = applicationIdProvider.getPackageName(); + } catch (ApkProvisionException e) { + LOG.error(e); + launchStatus.terminateLaunch("Unable to determine application id: " + e, true); + return ImmutableList.of(); + } + + Integer userId = runContext.getUserId(device, consolePrinter); + String userIdFlags = UserIdHelper.getFlagsFromUserId(userId); + String skipVerification = + ApkVerifierTracker.getSkipVerificationInstallationFlag(device, packageName); + String pmInstallOption; + if (skipVerification != null) { + pmInstallOption = userIdFlags + " " + skipVerification; + } else { + pmInstallOption = userIdFlags; + } + launchOptionsBuilder.setPmInstallOptions(d -> pmInstallOption); + + LaunchOptions launchOptions = launchOptionsBuilder.build(); + + // NOTE: Task for opening the profiler tool-window should come before deployment + // to ensure the tool-window opens correctly. This is required because starting + // the profiler session requires the tool-window to be open. + if (isProfilerLaunch(launchOptions)) { + launchTasks.add(new BlazeAndroidOpenProfilerWindowTask(project)); + } + + if (launchOptions.isClearLogcatBeforeStart()) { + launchTasks.add(new ClearLogcatTask(project)); + } + + launchTasks.add(new DismissKeyguardTask()); + + if (launchOptions.isDeploy()) { + ImmutableList deployTasks = runContext.getDeployTasks(device, launchOptions); + launchTasks.addAll(deployTasks); + } + if (launchStatus.isLaunchTerminated()) { + return ImmutableList.copyOf(launchTasks); + } + + try { + if (launchOptions.isDebug()) { + launchTasks.add(new CheckApkDebuggableTask(runContext.getBuildStep().getDeployInfo())); + } + + ImmutableList.Builder amStartOptions = ImmutableList.builder(); + amStartOptions.add(runContext.getAmStartOptions()); + if (isProfilerLaunch(launchOptions)) { + amStartOptions.add( + AndroidProfilerLaunchTaskContributor.getAmStartOptions( + project, packageName, launchOptions, device)); + launchTasks.add( + new AndroidProfilerLaunchTaskContributor.AndroidProfilerToolWindowLaunchTask( + project, launchOptions, packageName)); + } + + // Do not get debugger state directly from the debugger itself. + // See BlazeAndroidDebuggerService#getDebuggerState for an explanation. + BlazeAndroidDebuggerService debuggerService = + BlazeAndroidDebuggerService.getInstance(project); + AndroidDebugger debugger = + debuggerService.getDebugger(isNativeDebuggingEnabled(launchOptions)); + AndroidDebuggerState debuggerState = debuggerService.getDebuggerState(debugger); + LaunchTask appLaunchTask = + runContext.getApplicationLaunchTask( + launchOptions, + userId, + String.join(" ", amStartOptions.build()), + debugger, + debuggerState, + launchStatus); + if (appLaunchTask != null) { + launchTasks.add(appLaunchTask); + } + } catch (ApkProvisionException e) { + LOG.error(e); + launchStatus.terminateLaunch("Unable to determine application id: " + e, true); + return ImmutableList.of(); + } catch (ExecutionException e) { + launchStatus.terminateLaunch(e.getMessage(), true); + return ImmutableList.of(); + } + + if (!launchOptions.isDebug() && launchOptions.isOpenLogcatAutomatically()) { + launchTasks.add(new ShowLogcatTask(project, packageName)); + } + + return ImmutableList.copyOf(launchTasks); + } + + @Nullable + @Override + public ConnectDebuggerTask getConnectDebuggerTask( + @NotNull LaunchStatus launchStatus, @Nullable AndroidVersion version) { + LaunchOptions launchOptions = launchOptionsBuilder.build(); + if (!launchOptions.isDebug()) { + return null; + } + + // Do not get debugger state directly from the debugger itself. + // See BlazeAndroidDebuggerService#getDebuggerState for an explanation. + BlazeAndroidDebuggerService debuggerService = BlazeAndroidDebuggerService.getInstance(project); + AndroidDebugger debugger = debuggerService.getDebugger(isNativeDebuggingEnabled(launchOptions)); + AndroidDebuggerState debuggerState = debuggerService.getDebuggerState(debugger); + if (debugger == null || debuggerState == null) { + return null; + } + + try { + return runContext.getDebuggerTask(debugger, debuggerState); + } catch (ExecutionException e) { + launchStatus.terminateLaunch(e.getMessage(), true); + return null; + } + } + + @Override + public String getLaunchTypeDisplayName() { + return "Launch"; + } + + private boolean isNativeDebuggingEnabled(LaunchOptions launchOptions) { + Object flag = launchOptions.getExtraOption(NATIVE_DEBUGGING_ENABLED); + return flag instanceof Boolean && (Boolean) flag; + } +} diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java new file mode 100644 index 00000000000..b1396a80d24 --- /dev/null +++ b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java @@ -0,0 +1,75 @@ +/* + * Copyright 2016 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.android.run.runner; + +import com.android.ddmlib.IDevice; +import com.android.tools.idea.run.ApplicationIdProvider; +import com.android.tools.idea.run.ConsolePrinter; +import com.android.tools.idea.run.ConsoleProvider; +import com.android.tools.idea.run.LaunchOptions; +import com.android.tools.idea.run.editor.AndroidDebugger; +import com.android.tools.idea.run.editor.AndroidDebuggerState; +import com.android.tools.idea.run.tasks.ConnectDebuggerTask; +import com.android.tools.idea.run.tasks.LaunchTask; +import com.android.tools.idea.run.tasks.LaunchTasksProvider; +import com.android.tools.idea.run.util.LaunchStatus; +import com.google.common.collect.ImmutableList; +import com.intellij.execution.ExecutionException; +import javax.annotation.Nullable; +import org.jetbrains.annotations.NotNull; + +/** Instantiated when the configuration wants to run. */ +public interface BlazeAndroidRunContext { + + BlazeAndroidDeviceSelector getDeviceSelector(); + + void augmentLaunchOptions(LaunchOptions.Builder options); + + ConsoleProvider getConsoleProvider(); + + BlazeApkBuildStep getBuildStep(); + + ApplicationIdProvider getApplicationIdProvider() throws ExecutionException; + + LaunchTasksProvider getLaunchTasksProvider(LaunchOptions.Builder launchOptionsBuilder) + throws ExecutionException; + + /** Returns the tasks to deploy the application. */ + ImmutableList getDeployTasks(IDevice device, LaunchOptions launchOptions) + throws ExecutionException; + + /** Returns the task to launch the application. */ + @Nullable + LaunchTask getApplicationLaunchTask( + LaunchOptions launchOptions, + @Nullable Integer userId, + @NotNull String contributorsAmStartOptions, + AndroidDebugger androidDebugger, + AndroidDebuggerState androidDebuggerState, + LaunchStatus launchStatus) + throws ExecutionException; + + /** Returns the task to connect the debugger. */ + @Nullable + ConnectDebuggerTask getDebuggerTask( + AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState) + throws ExecutionException; + + @Nullable + Integer getUserId(IDevice device, ConsolePrinter consolePrinter) throws ExecutionException; + + String getAmStartOptions(); +} diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java new file mode 100644 index 00000000000..a2794e91b3e --- /dev/null +++ b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java @@ -0,0 +1,91 @@ +/* + * Copyright 2021 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.android.run.test; + +import static com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryNormalBuildRunContext.getApkInfoToInstall; + +import com.android.ddmlib.IDevice; +import com.android.tools.idea.run.LaunchOptions; +import com.android.tools.idea.run.editor.AndroidDebugger; +import com.android.tools.idea.run.editor.AndroidDebuggerState; +import com.android.tools.idea.run.tasks.ConnectDebuggerTask; +import com.android.tools.idea.run.tasks.LaunchTask; +import com.google.common.collect.ImmutableList; +import com.google.idea.blaze.android.run.BlazeAndroidDeploymentService; +import com.google.idea.blaze.base.model.primitives.Label; +import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration; +import com.intellij.execution.ExecutionException; +import com.intellij.execution.runners.ExecutionEnvironment; +import com.intellij.openapi.project.Project; +import org.jetbrains.android.facet.AndroidFacet; + +/** + * Run context for android_test. + * + *

#api42 + */ +public class BlazeAndroidTestRunContext extends BlazeAndroidTestRunContextBase { + BlazeAndroidTestRunContext( + Project project, + AndroidFacet facet, + BlazeCommandRunConfiguration runConfiguration, + ExecutionEnvironment env, + BlazeAndroidTestRunConfigurationState configState, + Label label, + ImmutableList blazeFlags, + ImmutableList exeFlags) { + super(project, facet, runConfiguration, env, configState, label, blazeFlags, exeFlags); + } + + @Override + public ImmutableList getDeployTasks(IDevice device, LaunchOptions launchOptions) + throws ExecutionException { + switch (configState.getLaunchMethod()) { + case NON_BLAZE: + // fall through + case BLAZE_TEST: + return ImmutableList.of( + BlazeAndroidDeploymentService.getInstance(project) + .getDeployTask( + getApkInfoToInstall(device, launchOptions, apkProvider), launchOptions)); + case MOBILE_INSTALL: + return ImmutableList.of(); + } + throw new AssertionError(); + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) // Raw type from upstream. + public ConnectDebuggerTask getDebuggerTask( + AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState) + throws ExecutionException { + switch (configState.getLaunchMethod()) { + case BLAZE_TEST: + return new ConnectBlazeTestDebuggerTask( + env.getProject(), androidDebugger, null, applicationIdProvider, this); + case NON_BLAZE: + case MOBILE_INSTALL: + return androidDebugger.getConnectDebuggerTask( + env, + null, + applicationIdProvider, + facet, + androidDebuggerState, + runConfiguration.getType().getId()); + } + throw new AssertionError(); + } +} diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/ConnectBlazeTestDebuggerTask.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/ConnectBlazeTestDebuggerTask.java new file mode 100644 index 00000000000..437cdd425f6 --- /dev/null +++ b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/ConnectBlazeTestDebuggerTask.java @@ -0,0 +1,138 @@ +/* + * Copyright 2016 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.android.run.test; + +import com.android.ddmlib.AndroidDebugBridge; +import com.android.ddmlib.Client; +import com.android.ddmlib.ClientData; +import com.android.ddmlib.IDevice; +import com.android.tools.idea.run.ApkProvisionException; +import com.android.tools.idea.run.ApplicationIdProvider; +import com.android.tools.idea.run.LaunchInfo; +import com.android.tools.idea.run.ProcessHandlerConsolePrinter; +import com.android.tools.idea.run.editor.AndroidDebugger; +import com.android.tools.idea.run.tasks.ConnectDebuggerTaskBase; +import com.android.tools.idea.run.tasks.ConnectJavaDebuggerTask; +import com.android.tools.idea.run.util.ProcessHandlerLaunchStatus; +import com.intellij.execution.process.ProcessHandler; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import java.util.Set; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** Connects the blaze debugger during execution. */ +class ConnectBlazeTestDebuggerTask extends ConnectDebuggerTaskBase { + private static final Logger LOG = Logger.getInstance(ConnectBlazeTestDebuggerTask.class); + + private final Project project; + private final ApplicationIdProvider applicationIdProvider; + private final BlazeAndroidTestRunContext runContext; + + public ConnectBlazeTestDebuggerTask( + Project project, + AndroidDebugger debugger, + @Nullable Set applicationIds, // parameter present only for #api42 compat + ApplicationIdProvider applicationIdProvider, + BlazeAndroidTestRunContext runContext) { + super(applicationIdProvider, debugger, project, true); + this.project = project; + this.applicationIdProvider = applicationIdProvider; + this.runContext = runContext; + } + + @Nullable + @Override + public ProcessHandler perform( + @NotNull LaunchInfo launchInfo, + @NotNull IDevice device, + @NotNull ProcessHandlerLaunchStatus state, + @NotNull ProcessHandlerConsolePrinter printer) { + try { + String packageName = applicationIdProvider.getPackageName(); + setUpForReattachingDebugger(packageName, launchInfo, state, printer); + } catch (ApkProvisionException e) { + LOG.error(e); + } + + // The return value for this task is not used + return null; + } + + /** + * Wires up listeners to automatically reconnect the debugger for each test method. When you + * `blaze test` an android_test in debug mode, it kills the instrumentation process between each + * test method, disconnecting the debugger. We listen for the start of a new method waiting for a + * debugger, and reconnect. TODO: Support stopping Blaze from the UI. This is hard because we have + * no way to distinguish process handler termination/debug session ending initiated by the user. + */ + private void setUpForReattachingDebugger( + String targetPackage, + LaunchInfo launchInfo, + ProcessHandlerLaunchStatus launchStatus, + ProcessHandlerConsolePrinter printer) { + final AndroidDebugBridge.IClientChangeListener reattachingListener = + new AndroidDebugBridge.IClientChangeListener() { + // The target application can either + // 1. Match our target name, and become available for debugging. + // 2. Be available for debugging, and suddenly have its name changed to match. + static final int CHANGE_MASK = Client.CHANGE_DEBUGGER_STATUS | Client.CHANGE_NAME; + + @Override + public void clientChanged(@NotNull Client client, int changeMask) { + ClientData data = client.getClientData(); + String clientDescription = data.getClientDescription(); + if (clientDescription != null + && clientDescription.equals(targetPackage) + && (changeMask & CHANGE_MASK) != 0 + && data.getDebuggerConnectionStatus().equals(ClientData.DebuggerStatus.WAITING)) { + reattachDebugger(launchInfo, client, launchStatus, printer); + } + } + }; + + AndroidDebugBridge.addClientChangeListener(reattachingListener); + runContext.addLaunchTaskCompleteListener( + () -> { + AndroidDebugBridge.removeClientChangeListener(reattachingListener); + launchStatus.terminateLaunch("Test run completed.\n", true); + }); + } + + private void reattachDebugger( + LaunchInfo launchInfo, + final Client client, + ProcessHandlerLaunchStatus launchStatus, + ProcessHandlerConsolePrinter printer) { + ApplicationManager.getApplication() + .invokeLater(() -> launchDebugger(launchInfo, client, launchStatus, printer)); + } + + /** + * Nearly a clone of {@link ConnectJavaDebuggerTask#launchDebugger}. There are a few changes to + * account for null variables that could occur in our implementation. + */ + @Override + public ProcessHandler launchDebugger( + @NotNull LaunchInfo currentLaunchInfo, + @NotNull Client client, + @NotNull ProcessHandlerLaunchStatus launchStatus, + @NotNull ProcessHandlerConsolePrinter printer) { + return ConnectBlazeTestDebuggerTaskHelper.launchDebugger( + project, currentLaunchInfo, client, launchStatus, printer); + } +} diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/sync/model/idea/BlazeAndroidModel.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/sync/model/idea/BlazeAndroidModel.java new file mode 100644 index 00000000000..00a9e4a94c9 --- /dev/null +++ b/aswb/sdkcompat/as212/com/google/idea/blaze/android/sync/model/idea/BlazeAndroidModel.java @@ -0,0 +1,53 @@ +/* + * Copyright 2020 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.android.sync.model.idea; + +import com.android.tools.idea.model.AndroidModel; +import com.android.tools.idea.model.Namespacing; +import com.android.tools.idea.projectsystem.NamedIdeaSourceProvider; +import com.google.common.util.concurrent.ListenableFuture; +import com.intellij.openapi.project.Project; +import java.io.File; + +/** Blaze model for an android project. #api42. */ +public class BlazeAndroidModel extends BlazeAndroidModelBase { + private final NamedIdeaSourceProvider sourceProvider; + + public BlazeAndroidModel( + Project project, + File rootDirPath, + NamedIdeaSourceProvider sourceProvider, + ListenableFuture applicationId, + int minSdkVersion, + boolean desugarJava8Libs) { + super(project, rootDirPath, applicationId, minSdkVersion, desugarJava8Libs); + this.sourceProvider = sourceProvider; + } + + public NamedIdeaSourceProvider getDefaultSourceProvider() { + return sourceProvider; + } + + @Override + public Namespacing getNamespacing() { + return Namespacing.DISABLED; + } + + @Override + protected String uninitializedApplicationId() { + return AndroidModel.UNINITIALIZED_APPLICATION_ID; + } +} From ee4277acf370d4454eca571062aa6726eb0c302f Mon Sep 17 00:00:00 2001 From: Googler Date: Thu, 4 Nov 2021 01:53:36 -0700 Subject: [PATCH 21/47] Make 2021.2 latest for CLion and IntelliJ PiperOrigin-RevId: 407527215 --- intellij_platform_sdk/build_defs.bzl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/intellij_platform_sdk/build_defs.bzl b/intellij_platform_sdk/build_defs.bzl index e29514ddb68..ac3fb1aa988 100644 --- a/intellij_platform_sdk/build_defs.bzl +++ b/intellij_platform_sdk/build_defs.bzl @@ -3,20 +3,20 @@ # The current indirect ij_product mapping (eg. "intellij-latest") INDIRECT_IJ_PRODUCTS = { # Indirect ij_product mapping for internal Blaze Plugin - "intellij-latest": "intellij-2021.1", - "intellij-latest-mac": "intellij-2021.1-mac", + "intellij-latest": "intellij-2021.2", + "intellij-latest-mac": "intellij-2021.2-mac", "intellij-beta": "intellij-2021.2", "intellij-under-dev": "intellij-2021.2", - "intellij-ue-latest": "intellij-ue-2021.1", - "intellij-ue-latest-mac": "intellij-ue-2021.1-mac", + "intellij-ue-latest": "intellij-ue-2021.2", + "intellij-ue-latest-mac": "intellij-ue-2021.2-mac", "intellij-ue-beta": "intellij-ue-2021.2", "intellij-ue-under-dev": "intellij-ue-2021.2", "android-studio-latest": "android-studio-2020.3", "android-studio-beta": "android-studio-2020.3", "android-studio-beta-mac": "android-studio-2020.3-mac", "android-studio-canary": "android-studio-2021.1", - "clion-latest": "clion-2021.1", - "clion-latest-mac": "clion-2021.1-mac", + "clion-latest": "clion-2021.2", + "clion-latest-mac": "clion-2021.2-mac", "clion-beta": "clion-2021.2", "clion-under-dev": "clion-2021.2", # Indirect ij_product mapping for Bazel Plugin OSS From a711d3b6d5592f5254cc499046531ba811a99f83 Mon Sep 17 00:00:00 2001 From: Mai Hussien Date: Thu, 4 Nov 2021 03:21:52 -0700 Subject: [PATCH 22/47] Add Kotlin example project This CL adds examples directory to the plugin code and adds a simple example for Kotling project. The examples directory is excluded from the project views of the plugin code. This CL also updates the rules_kotlin version in workspace.oss to the latest 1.3. It also adds dependency `diffutils` because without it failing tests that use Google truth crash with java.lang.NoClassDefFoundError: `difflib/DiffUtils` instead of reporting the textual difference. PiperOrigin-RevId: 407541490 --- WORKSPACE | 23 ++++++++++--- aswb/aswb.bazelproject | 1 + clwb/clwb.bazelproject | 1 + examples/kotlin/simple_project/BUILD | 34 +++++++++++++++++++ .../simple_project/main/ProjectRunner.kt | 19 +++++++++++ .../simple_project/main/lib/Greeting.kt | 13 +++++++ .../simple_project.bazelproject | 8 +++++ .../simple_project/test/lib/GreetingTest.kt | 28 +++++++++++++++ ijwb/ijwb.bazelproject | 1 + 9 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 examples/kotlin/simple_project/BUILD create mode 100644 examples/kotlin/simple_project/main/ProjectRunner.kt create mode 100644 examples/kotlin/simple_project/main/lib/Greeting.kt create mode 100644 examples/kotlin/simple_project/simple_project.bazelproject create mode 100644 examples/kotlin/simple_project/test/lib/GreetingTest.kt diff --git a/WORKSPACE b/WORKSPACE index 403aebef971..a151065e282 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -448,14 +448,29 @@ load("@io_bazel_rules_scala//scala:toolchains.bzl", "scala_register_toolchains") scala_register_toolchains() # LICENSE: The Apache Software License, Version 2.0 +rules_kotlin_version = "legacy-1.3.0" +rules_kotlin_sha = "4fd769fb0db5d3c6240df8a9500515775101964eebdf85a3f9f0511130885fde" http_archive( name = "io_bazel_rules_kotlin", - sha256 = "f1293902a15397a10957e866f133dcd027a0a6d21eae8c4fb7557f010add8a09", - strip_prefix = "rules_kotlin-cab5eaffc2012dfe46260c03d6419c0d2fa10be0", + urls = ["https://github.com/bazelbuild/rules_kotlin/archive/%s.zip" % rules_kotlin_version], type = "zip", - url = "https://github.com/bazelbuild/rules_kotlin/archive/cab5eaffc2012dfe46260c03d6419c0d2fa10be0.zip", + strip_prefix = "rules_kotlin-%s" % rules_kotlin_version, + sha256 = rules_kotlin_sha, ) -load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kotlin_repositories") +load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", + "kotlin_repositories", + "kt_register_toolchains") kotlin_repositories() +kt_register_toolchains() + +# Without this dependency, when a test that uses Google truth fails, instead of +# the textual difference we get java.lang.NoClassDefFoundError: difflib/DiffUtils +jvm_maven_import_external( + name = "diffutils", + artifact = "com.googlecode.java-diff-utils:diffutils:1.2.1", + artifact_sha256 = "c98697c3b8dd745353cd0a83b109c1c999fec43b4a5cedb2f579452d8da2c171", + licenses = ["notice"], # Apache 2.0 + server_urls = ["https://repo1.maven.org/maven2"], +) diff --git a/aswb/aswb.bazelproject b/aswb/aswb.bazelproject index 5ef78c947e2..96d6a6a7271 100644 --- a/aswb/aswb.bazelproject +++ b/aswb/aswb.bazelproject @@ -3,6 +3,7 @@ directories: -ijwb -plugin_dev -clwb + -examples targets: //aswb:aswb_bazel_dev diff --git a/clwb/clwb.bazelproject b/clwb/clwb.bazelproject index 56b26b14f8a..bf46c0d13ba 100644 --- a/clwb/clwb.bazelproject +++ b/clwb/clwb.bazelproject @@ -3,6 +3,7 @@ directories: -ijwb -aswb -plugin_dev + -examples targets: //clwb:clwb_bazel_dev diff --git a/examples/kotlin/simple_project/BUILD b/examples/kotlin/simple_project/BUILD new file mode 100644 index 00000000000..25c43386cc3 --- /dev/null +++ b/examples/kotlin/simple_project/BUILD @@ -0,0 +1,34 @@ +load( + "@io_bazel_rules_kotlin//kotlin:kotlin.bzl", + "kt_jvm_binary", + "kt_jvm_library", + "kt_jvm_test", +) + +package(default_visibility = ["//visibility:private"]) + +licenses(["notice"]) + +kt_jvm_library( + name = "greeting_lib", + srcs = ["main/lib/Greeting.kt"], +) + +kt_jvm_binary( + name = "run_project", + srcs = ["main/ProjectRunner.kt"], + main_class = "main.ProjectRunner", + deps = [":greeting_lib"], +) + +kt_jvm_test( + name = "test_greeting", + srcs = ["test/lib/GreetingTest.kt"], + test_class = "test.lib.GreetingTest", + deps = [ + ":greeting_lib", + "@diffutils//jar", + "@junit//jar", + "@truth//jar", + ], +) diff --git a/examples/kotlin/simple_project/main/ProjectRunner.kt b/examples/kotlin/simple_project/main/ProjectRunner.kt new file mode 100644 index 00000000000..3b3157380ab --- /dev/null +++ b/examples/kotlin/simple_project/main/ProjectRunner.kt @@ -0,0 +1,19 @@ +package main + +import main.lib.Greeting + +class ProjectRunner { + companion object { + @JvmStatic + fun main(args: Array) { + var names: Array = arrayOf("World") + + if (args.size > 0) { + names = args + } + + val greeting = Greeting.getGreetings(names) + println(greeting.contentToString()) + } + } +} diff --git a/examples/kotlin/simple_project/main/lib/Greeting.kt b/examples/kotlin/simple_project/main/lib/Greeting.kt new file mode 100644 index 00000000000..5b1c7d37227 --- /dev/null +++ b/examples/kotlin/simple_project/main/lib/Greeting.kt @@ -0,0 +1,13 @@ +package main.lib + +class Greeting { + companion object { + private fun getGreeting(name: String): String { + return "Hello $name!" + } + + fun getGreetings(names: Array): Array { + return Array(names.size) { i -> getGreeting(names.get(i)) } + } + } +} diff --git a/examples/kotlin/simple_project/simple_project.bazelproject b/examples/kotlin/simple_project/simple_project.bazelproject new file mode 100644 index 00000000000..a5851c44792 --- /dev/null +++ b/examples/kotlin/simple_project/simple_project.bazelproject @@ -0,0 +1,8 @@ +directories: + examples/kotlin/simple_project + +targets: + //examples/kotlin/simple_project/... + +additional_languages: + kotlin diff --git a/examples/kotlin/simple_project/test/lib/GreetingTest.kt b/examples/kotlin/simple_project/test/lib/GreetingTest.kt new file mode 100644 index 00000000000..f8a010df0af --- /dev/null +++ b/examples/kotlin/simple_project/test/lib/GreetingTest.kt @@ -0,0 +1,28 @@ +package test.lib + +import main.lib.Greeting + +import com.google.common.truth.Truth.assertThat +import org.junit.Test + +internal class GreetingTest { + + @Test + fun testGetNoGreetings() { + val actual = Greeting.getGreetings(arrayOf()) + assertThat(actual).isEmpty() + } + + @Test + fun testGetSingleGreeting() { + val actual = Greeting.getGreetings(arrayOf("User")) + assertThat(actual).asList().containsExactly("Hello User!") + } + + @Test + fun testGetMultipleGreetings() { + val actual = Greeting.getGreetings(arrayOf("User 1", "User 2", "User 3")) + val expected = arrayOf("Hello User 1!", "Hello User 2!", "Hello User 3!") + assertThat(actual).asList().containsExactlyElementsIn(expected) + } +} diff --git a/ijwb/ijwb.bazelproject b/ijwb/ijwb.bazelproject index 9faba5ff6a7..8271963f016 100644 --- a/ijwb/ijwb.bazelproject +++ b/ijwb/ijwb.bazelproject @@ -3,6 +3,7 @@ directories: -aswb -clwb -cpp + -examples targets: //ijwb:ijwb_bazel_dev From 2ccabd9dd38ab3587577cfd17f1c08e191314e7e Mon Sep 17 00:00:00 2001 From: Mai Hussien Date: Thu, 4 Nov 2021 09:45:30 -0700 Subject: [PATCH 23/47] Add kotlin coroutines example This CL adds an example project of using Kotlin coroutines. To enable this, we add `kotlinx-coroutines-core` dependency of version 1.3.8 or later so that coroutine debugging can be supported: (https://kotlinlang.org/docs/debug-coroutines-with-idea.html). Also `rules_kotlin` had to be updated to be compatible with the `kotlinx-coroutines-core` version. PiperOrigin-RevId: 407602146 --- WORKSPACE | 23 +++++++----- .../kotlin/simple_coroutines_project/BUILD | 12 +++++++ .../simple_coroutines_project/main/Main.kt | 36 +++++++++++++++++++ .../simple_coroutines_project.bazelproject | 8 +++++ 4 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 examples/kotlin/simple_coroutines_project/BUILD create mode 100644 examples/kotlin/simple_coroutines_project/main/Main.kt create mode 100644 examples/kotlin/simple_coroutines_project/simple_coroutines_project.bazelproject diff --git a/WORKSPACE b/WORKSPACE index a151065e282..2087b5730ec 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -448,20 +448,16 @@ load("@io_bazel_rules_scala//scala:toolchains.bzl", "scala_register_toolchains") scala_register_toolchains() # LICENSE: The Apache Software License, Version 2.0 -rules_kotlin_version = "legacy-1.3.0" -rules_kotlin_sha = "4fd769fb0db5d3c6240df8a9500515775101964eebdf85a3f9f0511130885fde" +rules_kotlin_version = "v1.5.0-beta-3" +rules_kotlin_sha = "58edd86f0f3c5b959c54e656b8e7eb0b0becabd412465c37a2078693c2571f7f" http_archive( name = "io_bazel_rules_kotlin", - urls = ["https://github.com/bazelbuild/rules_kotlin/archive/%s.zip" % rules_kotlin_version], - type = "zip", - strip_prefix = "rules_kotlin-%s" % rules_kotlin_version, + urls = ["https://github.com/bazelbuild/rules_kotlin/releases/download/%s/rules_kotlin_release.tgz" % rules_kotlin_version], sha256 = rules_kotlin_sha, ) -load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", - "kotlin_repositories", - "kt_register_toolchains") - +load("@io_bazel_rules_kotlin//kotlin:repositories.bzl", "kotlin_repositories", ) +load("@io_bazel_rules_kotlin//kotlin:core.bzl", "kt_register_toolchains") kotlin_repositories() kt_register_toolchains() @@ -474,3 +470,12 @@ jvm_maven_import_external( licenses = ["notice"], # Apache 2.0 server_urls = ["https://repo1.maven.org/maven2"], ) + +# Dependency needed for kotlin coroutines library +jvm_maven_import_external( + name = "kotlinx_coroutines", + artifact = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2", + artifact_sha256 = "4cd24a06b2a253110d8afd250e9eec6c6faafea6463d740824743d637e761f12", + licenses = ["notice"], # Apache 2.0 + server_urls = ["https://repo1.maven.org/maven2"], +) diff --git a/examples/kotlin/simple_coroutines_project/BUILD b/examples/kotlin/simple_coroutines_project/BUILD new file mode 100644 index 00000000000..a715e4014ad --- /dev/null +++ b/examples/kotlin/simple_coroutines_project/BUILD @@ -0,0 +1,12 @@ +load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_binary") + +package(default_visibility = ["//visibility:private"]) + +licenses(["notice"]) + +kt_jvm_binary( + name = "run_project", + srcs = ["main/Main.kt"], + main_class = "main.Main", + deps = ["@kotlinx_coroutines//jar"], +) diff --git a/examples/kotlin/simple_coroutines_project/main/Main.kt b/examples/kotlin/simple_coroutines_project/main/Main.kt new file mode 100644 index 00000000000..c5d58180774 --- /dev/null +++ b/examples/kotlin/simple_coroutines_project/main/Main.kt @@ -0,0 +1,36 @@ +package main + +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.launch +import kotlinx.coroutines.delay + +class Main { + companion object { + /** + * Create a list of coroutines (based on the user input). Each coroutine is delayed for + * a number of minutes relative to its order in the list, i.e. coroutine {@code i} is delayed + * for {@code i} seconds. After the delay, the coroutine prints a greeting message indicating + * its number. + * */ + @JvmStatic + fun main(args: Array) = runBlocking { + val num: Int + + if (args.size > 0) { + num = args[0].toInt() + } else { + num = 1 + } + + for (i in 0 until num) { + launch { + delay(1000L * (i + 1)) + println("Hello from Coroutine $i") + } + } + + // this should be printed before any of the coroutines output their messages + println("Hello from Main coroutine") + } + } +} diff --git a/examples/kotlin/simple_coroutines_project/simple_coroutines_project.bazelproject b/examples/kotlin/simple_coroutines_project/simple_coroutines_project.bazelproject new file mode 100644 index 00000000000..e45e7649288 --- /dev/null +++ b/examples/kotlin/simple_coroutines_project/simple_coroutines_project.bazelproject @@ -0,0 +1,8 @@ +directories: + examples/kotlin/simple_coroutines_project + +targets: + //examples/kotlin/simple_coroutines_project/... + +additional_languages: + kotlin From c8d1585c6b9c850f6890a0912599342c36718fc2 Mon Sep 17 00:00:00 2001 From: Googler Date: Thu, 4 Nov 2021 10:58:10 -0700 Subject: [PATCH 24/47] Move cache state to AarCache Create AarCache to store cache state specifically. PiperOrigin-RevId: 407621185 --- .../blaze/android/libraries/AarCache.java | 176 ++++++++++++++++++ .../blaze/android/libraries/UnpackedAars.java | 158 ++++------------ 2 files changed, 217 insertions(+), 117 deletions(-) create mode 100644 aswb/src/com/google/idea/blaze/android/libraries/AarCache.java diff --git a/aswb/src/com/google/idea/blaze/android/libraries/AarCache.java b/aswb/src/com/google/idea/blaze/android/libraries/AarCache.java new file mode 100644 index 00000000000..3f45e4a2b98 --- /dev/null +++ b/aswb/src/com/google/idea/blaze/android/libraries/AarCache.java @@ -0,0 +1,176 @@ +/* + * Copyright 2021 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.android.libraries; + +import static com.google.common.collect.ImmutableList.toImmutableList; +import static com.google.common.collect.ImmutableMap.toImmutableMap; +import static com.google.common.collect.ImmutableSet.toImmutableSet; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.idea.blaze.base.io.FileOperationProvider; +import com.google.idea.blaze.base.prefetch.FetchExecutor; +import com.intellij.openapi.diagnostic.Logger; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import javax.annotation.Nullable; + +/** Local cache of the aars referenced by the project. */ +public class AarCache { + private static final Logger logger = Logger.getInstance(AarCache.class); + /** + * The state of the cache as of the last call to {@link #readFileState}. It will cleared by {@link + * #clearCache} + */ + private volatile ImmutableMap cacheState = ImmutableMap.of(); + + private static final String STAMP_FILE_NAME = "aar.timestamp"; + + private final File cacheDir; + + public AarCache(File cacheDir) { + this.cacheDir = cacheDir; + } + + /** + * Get the dir path to aar cache. Create one if it does exists. + * + * @return path to cache directory. Null will be return if the directory does not exist and fails + * to create one. + */ + @Nullable + public File getOrCreateCacheDir() throws IOException { + FileOperationProvider fileOpProvider = FileOperationProvider.getInstance(); + // Ensure the cache dir exists + if (!fileOpProvider.exists(cacheDir) && !fileOpProvider.mkdirs(cacheDir)) { + throw new IOException("Fail to create cache dir " + cacheDir); + } + return cacheDir; + } + + /* Get path to aar directory for the given key. The file is not guaranteed to be existed. */ + public File aarDirForKey(String key) { + return new File(cacheDir, key); + } + + /** + * Create a clean aar directory for the given key. The directory will be removed and recreate if + * the directory has already existed. + */ + public File recreateAarDir(FileOperationProvider ops, String key) throws IOException { + File aarDir = aarDirForKey(key); + if (ops.exists(aarDir)) { + ops.deleteRecursively(aarDir, true); + } + ops.mkdirs(aarDir); + return aarDir; + } + + /** + * Create timestamp file for the given key. The stamp file is used to identify if we need to + * update. + */ + public File createTimeStampFile(String key) throws IOException { + File stampFile = new File(aarDirForKey(key), STAMP_FILE_NAME); + stampFile.createNewFile(); + return stampFile; + } + + /** + * Returns a map of cache keys for the currently-cached files, along with a representative file + * used for timestamp-based diffing. + * + *

We use a stamp file instead of the directory itself to stash the timestamp. Directory + * timestamps are bit more brittle and can change whenever an operation is done to a child of the + * directory. + * + *

Also sets the in-memory @link #cacheState}. + */ + public ImmutableMap readFileState() { + FileOperationProvider ops = FileOperationProvider.getInstance(); + // Go through all of the aar directories, and get the stamp file. + File[] unpackedAarDirectories = ops.listFiles(cacheDir); + if (unpackedAarDirectories == null) { + return ImmutableMap.of(); + } + ImmutableMap cachedFiles = + Arrays.stream(unpackedAarDirectories) + .collect(toImmutableMap(File::getName, dir -> new File(dir, STAMP_FILE_NAME))); + cacheState = cachedFiles; + return cachedFiles; + } + + /* Remove all files that not list in retainedFiles. */ + public Collection> retainOnly(ImmutableSet retainedFiles) { + ImmutableSet cacheKeys = cacheState.keySet(); + ImmutableSet removedKeys = + cacheKeys.stream() + .filter(fileName -> !retainedFiles.contains(fileName)) + .collect(toImmutableSet()); + + FileOperationProvider ops = FileOperationProvider.getInstance(); + + return removedKeys.stream() + .map( + subDir -> + FetchExecutor.EXECUTOR.submit( + () -> { + try { + ops.deleteRecursively(new File(cacheDir, subDir), true); + } catch (IOException e) { + logger.warn(e); + } + })) + .collect(toImmutableList()); + } + + /* Clean up whole cache directory and reset cache state. */ + public void clearCache() { + FileOperationProvider fileOperationProvider = FileOperationProvider.getInstance(); + if (fileOperationProvider.exists(cacheDir)) { + try { + fileOperationProvider.deleteDirectoryContents(cacheDir, true); + } catch (IOException e) { + logger.warn("Failed to clear unpacked AAR directory: " + cacheDir, e); + } + } + cacheState = ImmutableMap.of(); + } + + /* Get the path to specific aar library. */ + @Nullable + public File getCachedAarDir(String aarDirName) { + ImmutableMap cacheState = this.cacheState; + if (cacheState.containsKey(aarDirName)) { + return new File(cacheDir, aarDirName); + } + return null; + } + + /* Whether the cache state is empty. */ + public boolean isEmpty() { + return cacheState.isEmpty(); + } + + /* Get all cached aar directories. */ + public ImmutableSet getCachedKeys() { + return cacheState.keySet(); + } +} diff --git a/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java b/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java index f213b8fac58..e6c62e75912 100644 --- a/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java +++ b/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java @@ -16,7 +16,6 @@ package com.google.idea.blaze.android.libraries; import static com.android.SdkConstants.FN_LINT_JAR; -import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableMap.toImmutableMap; import static com.google.common.collect.ImmutableSet.toImmutableSet; @@ -63,7 +62,6 @@ import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -97,10 +95,7 @@ public class UnpackedAars { private static final Logger logger = Logger.getInstance(UnpackedAars.class); private final Project project; - private final File cacheDir; - - /** The state of the cache as of the last call to {@link #readFileState}. */ - private volatile ImmutableMap cacheState = ImmutableMap.of(); + private final AarCache aarCache; public static UnpackedAars getInstance(Project project) { return ServiceManager.getService(project, UnpackedAars.class); @@ -110,12 +105,19 @@ public UnpackedAars(Project project) { BlazeImportSettings importSettings = BlazeImportSettingsManager.getInstance(project).getImportSettings(); this.project = project; - this.cacheDir = getCacheDir(importSettings); + aarCache = new AarCache(getCacheDir(importSettings)); } + /* Provide path to aar cache directory. This is for test only. */ @VisibleForTesting + @Nullable public File getCacheDir() { - return this.cacheDir; + try { + return aarCache.getOrCreateCacheDir(); + } catch (IOException e) { + logger.warn("Fail to get cache directory. ", e); + return null; + } } private static File getCacheDir(BlazeImportSettings importSettings) { @@ -130,7 +132,7 @@ void onSync( SyncMode syncMode) { boolean fullRefresh = syncMode == SyncMode.FULL; if (fullRefresh) { - clearCache(); + aarCache.clearCache(); } // TODO(brendandouglas): add a mechanism for removing missing files for partial syncs @@ -149,17 +151,14 @@ private void refresh( BlazeProjectData projectData, RemoteOutputArtifacts previousOutputs, boolean removeMissingFiles) { - FileOperationProvider fileOpProvider = FileOperationProvider.getInstance(); - - // Ensure the cache dir exists - if (!fileOpProvider.exists(cacheDir)) { - if (!fileOpProvider.mkdirs(cacheDir)) { - logger.warn("Could not create unpacked AAR directory: " + cacheDir); - return; - } + try { + aarCache.getOrCreateCacheDir(); + } catch (IOException e) { + logger.warn("Could not create unpacked AAR directory", e); + return; } - ImmutableMap cacheFiles = readFileState(); + ImmutableMap cacheFiles = aarCache.readFileState(); ImmutableMap projectState = getArtifactsToCache(viewSet, projectData); ImmutableMap aarOutputs = @@ -204,7 +203,7 @@ private void refresh( // update cache files, and remove files if required List> futures = new ArrayList<>(copyLocally(projectState, updatedKeys)); if (removeMissingFiles) { - futures.addAll(deleteCacheEntries(removedKeys)); + futures.addAll(aarCache.retainOnly(/* retainedFiles= */ projectState.keySet())); } Futures.allAsList(futures).get(); @@ -222,7 +221,7 @@ private void refresh( logger.warn("Unpacked AAR synchronization didn't complete", e); } finally { // update the in-memory record of which files are cached - readFileState(); + aarCache.readFileState(); } } @@ -232,9 +231,8 @@ public File getClassJar(ArtifactLocationDecoder decoder, AarLibrary library) { if (library.libraryArtifact == null) { return null; } - ImmutableMap cacheState = this.cacheState; BlazeArtifact jar = decoder.resolveOutput(library.libraryArtifact.jarForIntellijLibrary()); - if (cacheState.isEmpty()) { + if (aarCache.isEmpty()) { logger.warn("Cache state is empty"); return getFallbackFile(jar); } @@ -251,7 +249,7 @@ public File getClassJar(ArtifactLocationDecoder decoder, AarLibrary library) { String.format( "Fail to look up %s from cache state for library [aarArtifact = %s, jar = %s]", aarDir, aar, jar)); - logger.debug("Cache state contains the following keys: " + cacheState.keySet()); + logger.debug("Cache state contains the following keys: " + aarCache.getCachedKeys()); } return getFallbackFile(jar); } @@ -265,24 +263,11 @@ public File getResourceDirectory(ArtifactLocationDecoder decoder, AarLibrary lib return aarDir == null ? aarDir : UnpackedAarUtils.getResDir(aarDir); } - @Nullable - public File getAarDir(String cacheKey) { - ImmutableMap cacheState = this.cacheState; - if (!cacheState.containsKey(cacheKey)) { - return null; - } - return aarDirForKey(cacheKey); - } - @Nullable public File getAarDir(ArtifactLocationDecoder decoder, AarLibrary library) { BlazeArtifact artifact = decoder.resolveOutput(library.aarArtifact); String aarDirName = UnpackedAarUtils.getAarDirName(artifact); - return getAarDir(aarDirName); - } - - private File aarDirForKey(String key) { - return new File(cacheDir, key); + return aarCache.getCachedAarDir(aarDirName); } /** The file to return if there's no locally cached version. */ @@ -294,18 +279,6 @@ private static File getFallbackFile(BlazeArtifact output) { return ((LocalFileArtifact) output).getFile(); } - private void clearCache() { - FileOperationProvider fileOperationProvider = FileOperationProvider.getInstance(); - if (fileOperationProvider.exists(cacheDir)) { - try { - fileOperationProvider.deleteRecursively(cacheDir, true); - } catch (IOException e) { - logger.warn("Failed to clear unpacked AAR directory: " + cacheDir, e); - } - } - cacheState = ImmutableMap.of(); - } - static class FileCacheAdapter implements FileCache { @Override public String getName() { @@ -344,7 +317,7 @@ public void refreshFiles( @Override public void initialize(Project project) { - getInstance(project).readFileState(); + getInstance(project).aarCache.readFileState(); } } @@ -375,32 +348,6 @@ private static ImmutableMap getArtifactsToCache( return ImmutableMap.copyOf(outputs); } - private static final String STAMP_FILE_NAME = "aar.timestamp"; - - /** - * Returns a map of cache keys for the currently-cached files, along with a representative file - * used for timestamp-based diffing. - * - *

We use a stamp file instead of the directory itself to stash the timestamp. Directory - * timestamps are bit more brittle and can change whenever an operation is done to a child of the - * directory. - * - *

Also sets the in-memory @link #cacheState}. - */ - private ImmutableMap readFileState() { - FileOperationProvider ops = FileOperationProvider.getInstance(); - // Go through all of the aar directories, and get the stamp file. - File[] unpackedAarDirectories = ops.listFiles(cacheDir); - if (unpackedAarDirectories == null) { - return ImmutableMap.of(); - } - ImmutableMap cachedFiles = - Arrays.stream(unpackedAarDirectories) - .collect(toImmutableMap(File::getName, dir -> new File(dir, STAMP_FILE_NAME))); - cacheState = cachedFiles; - return cachedFiles; - } - private Collection> copyLocally( ImmutableMap toCache, Set updatedKeys) { FileOperationProvider ops = FileOperationProvider.getInstance(); @@ -413,12 +360,8 @@ private Collection> copyLocally( private void copyLocally(FileOperationProvider ops, AarLibraryContents aarAndJar) { String cacheKey = UnpackedAarUtils.getAarDirName(aarAndJar.aar()); - File aarDir = aarDirForKey(cacheKey); try { - if (ops.exists(aarDir)) { - ops.deleteRecursively(aarDir, true); - } - ops.mkdirs(aarDir); + File aarDir = aarCache.recreateAarDir(ops, cacheKey); // TODO(brendandouglas): decompress via ZipInputStream so we don't require a local file File toCopy = getOrCreateLocalFile(aarAndJar.aar()); ZipUtil.extract( @@ -429,7 +372,19 @@ private void copyLocally(FileOperationProvider ops, AarLibraryContents aarAndJar // which is more lightweight. But it's not applied to lint.jar (dir, name) -> name.equals(FN_LINT_JAR) || !name.endsWith(".jar")); - createStampFile(ops, aarDir, aarAndJar.aar()); + try { + File stampFile = aarCache.createTimeStampFile(cacheKey); + if (!(aarAndJar.aar() instanceof LocalFileArtifact)) { + // no need to set the timestamp for remote artifacts + return; + } + long sourceTime = ops.getFileModifiedTime(((LocalFileArtifact) aarAndJar.aar()).getFile()); + if (!ops.setFileModifiedTime(stampFile, sourceTime)) { + logger.warn("Failed to set AAR cache timestamp for " + aarAndJar.aar()); + } + } catch (IOException e) { + logger.warn("Failed to set AAR cache timestamp for " + aarAndJar.aar(), e); + } // copy merged jar if (aarAndJar.jar() != null) { @@ -441,44 +396,13 @@ private void copyLocally(FileOperationProvider ops, AarLibraryContents aarAndJar } } catch (IOException e) { - logger.warn(String.format("Failed to extract AAR %s to %s", aarAndJar.aar(), aarDir), e); - } - } - - private static void createStampFile( - FileOperationProvider fileOps, File aarDir, BlazeArtifact aar) { - File stampFile = new File(aarDir, STAMP_FILE_NAME); - try { - stampFile.createNewFile(); - if (!(aar instanceof LocalFileArtifact)) { - // no need to set the timestamp for remote artifacts - return; - } - long sourceTime = fileOps.getFileModifiedTime(((LocalFileArtifact) aar).getFile()); - if (!fileOps.setFileModifiedTime(stampFile, sourceTime)) { - logger.warn("Failed to set AAR cache timestamp for " + aar); - } - } catch (IOException e) { - logger.warn("Failed to set AAR cache timestamp for " + aar, e); + logger.warn( + String.format( + "Failed to extract AAR %s to %s", aarAndJar.aar(), aarCache.aarDirForKey(cacheKey)), + e); } } - private Collection> deleteCacheEntries(Collection cacheKeys) { - FileOperationProvider ops = FileOperationProvider.getInstance(); - return cacheKeys.stream() - .map( - key -> - FetchExecutor.EXECUTOR.submit( - () -> { - try { - ops.deleteRecursively(aarDirForKey(key), true); - } catch (IOException e) { - logger.warn(e); - } - })) - .collect(toImmutableList()); - } - /** Returns a locally-accessible file mirroring the contents of this {@link BlazeArtifact}. */ private static File getOrCreateLocalFile(BlazeArtifact artifact) throws IOException { if (artifact instanceof LocalFileArtifact) { From ca0ead47eafc31918c285b3ab19b6568274a28dd Mon Sep 17 00:00:00 2001 From: Alice Kober-Sotzek Date: Fri, 5 Nov 2021 07:24:00 -0700 Subject: [PATCH 25/47] Clean up left-over StubOCCompilerSettings from testcompat PiperOrigin-RevId: 407817223 --- .../testing/cidr/StubOCCompilerSettings.java | 0 .../testing/cidr/StubOCCompilerSettings.java | 124 ------------------ .../testing/cidr/StubOCCompilerSettings.java | 124 ------------------ 3 files changed, 248 deletions(-) rename testing/{testcompat/v203 => cidr}/com/google/idea/testing/cidr/StubOCCompilerSettings.java (100%) delete mode 100644 testing/testcompat/v211/com/google/idea/testing/cidr/StubOCCompilerSettings.java delete mode 100644 testing/testcompat/v212/com/google/idea/testing/cidr/StubOCCompilerSettings.java diff --git a/testing/testcompat/v203/com/google/idea/testing/cidr/StubOCCompilerSettings.java b/testing/cidr/com/google/idea/testing/cidr/StubOCCompilerSettings.java similarity index 100% rename from testing/testcompat/v203/com/google/idea/testing/cidr/StubOCCompilerSettings.java rename to testing/cidr/com/google/idea/testing/cidr/StubOCCompilerSettings.java diff --git a/testing/testcompat/v211/com/google/idea/testing/cidr/StubOCCompilerSettings.java b/testing/testcompat/v211/com/google/idea/testing/cidr/StubOCCompilerSettings.java deleted file mode 100644 index 02ec541a76e..00000000000 --- a/testing/testcompat/v211/com/google/idea/testing/cidr/StubOCCompilerSettings.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2017 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.testing.cidr; - -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VfsUtilCore; -import com.intellij.openapi.vfs.VirtualFile; -import com.jetbrains.cidr.lang.toolchains.CidrCompilerSwitches; -import com.jetbrains.cidr.lang.toolchains.CidrSwitchBuilder; -import com.jetbrains.cidr.lang.workspace.OCCompilerSettings; -import com.jetbrains.cidr.lang.workspace.compiler.CompilerSettingsKey; -import com.jetbrains.cidr.lang.workspace.compiler.OCCompilerFeatures; -import com.jetbrains.cidr.lang.workspace.compiler.OCCompilerKind; -import com.jetbrains.cidr.lang.workspace.headerRoots.HeadersSearchPath; -import com.jetbrains.cidr.lang.workspace.headerRoots.HeadersSearchRoot; -import com.jetbrains.cidr.lang.workspace.headerRoots.HeadersSearchRoots; -import java.io.File; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.annotation.Nullable; - -/** Stub {@link OCCompilerSettings} for testing. */ -class StubOCCompilerSettings implements OCCompilerSettings { - private final Project project; - private HeadersSearchRoots roots; - - StubOCCompilerSettings(Project project) { - this.project = project; - } - - @Override - @Nullable - public OCCompilerKind getCompilerKind() { - return OCCompilerKind.CLANG; - } - - @Override - @Nullable - public File getCompilerExecutable() { - return null; - } - - @Override - public File getCompilerWorkingDir() { - return VfsUtilCore.virtualToIoFile(project.getBaseDir()); - } - - @Override - @Nullable - public CidrCompilerSwitches getCompilerSwitches() { - return new CidrSwitchBuilder().build(); - } - - @Override - public HeadersSearchRoots getHeadersSearchRoots() { - return roots; - } - - @Override - public List getHeadersSearchPaths() { - return Collections.emptyList(); - } - - @Override - public List getImplicitIncludes() { - return Collections.emptyList(); - } - - @Override - public List getImplicitIncludeUrls() { - return Collections.emptyList(); - } - - @Nullable - @Override - public VirtualFile getMappedInclude(String include) { - return null; - } - - @Override - public String getMappedIncludeUrl(String include) { - return ""; - } - - @Override - public List getPreprocessorDefines() { - return Collections.emptyList(); - } - - @Override - public Map, ?> getCompilerFeatures() { - return new HashMap<>(); - } - - @Nullable - @Override - public CompilerSettingsKey getCachingKey() { - return null; - } - - @Override - public Object getIndexingCluster() { - return null; - } - - public void setLibraryIncludeRoots(List roots) { - this.roots = HeadersSearchRoots.create(roots); - } -} diff --git a/testing/testcompat/v212/com/google/idea/testing/cidr/StubOCCompilerSettings.java b/testing/testcompat/v212/com/google/idea/testing/cidr/StubOCCompilerSettings.java deleted file mode 100644 index 02ec541a76e..00000000000 --- a/testing/testcompat/v212/com/google/idea/testing/cidr/StubOCCompilerSettings.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2017 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.testing.cidr; - -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VfsUtilCore; -import com.intellij.openapi.vfs.VirtualFile; -import com.jetbrains.cidr.lang.toolchains.CidrCompilerSwitches; -import com.jetbrains.cidr.lang.toolchains.CidrSwitchBuilder; -import com.jetbrains.cidr.lang.workspace.OCCompilerSettings; -import com.jetbrains.cidr.lang.workspace.compiler.CompilerSettingsKey; -import com.jetbrains.cidr.lang.workspace.compiler.OCCompilerFeatures; -import com.jetbrains.cidr.lang.workspace.compiler.OCCompilerKind; -import com.jetbrains.cidr.lang.workspace.headerRoots.HeadersSearchPath; -import com.jetbrains.cidr.lang.workspace.headerRoots.HeadersSearchRoot; -import com.jetbrains.cidr.lang.workspace.headerRoots.HeadersSearchRoots; -import java.io.File; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.annotation.Nullable; - -/** Stub {@link OCCompilerSettings} for testing. */ -class StubOCCompilerSettings implements OCCompilerSettings { - private final Project project; - private HeadersSearchRoots roots; - - StubOCCompilerSettings(Project project) { - this.project = project; - } - - @Override - @Nullable - public OCCompilerKind getCompilerKind() { - return OCCompilerKind.CLANG; - } - - @Override - @Nullable - public File getCompilerExecutable() { - return null; - } - - @Override - public File getCompilerWorkingDir() { - return VfsUtilCore.virtualToIoFile(project.getBaseDir()); - } - - @Override - @Nullable - public CidrCompilerSwitches getCompilerSwitches() { - return new CidrSwitchBuilder().build(); - } - - @Override - public HeadersSearchRoots getHeadersSearchRoots() { - return roots; - } - - @Override - public List getHeadersSearchPaths() { - return Collections.emptyList(); - } - - @Override - public List getImplicitIncludes() { - return Collections.emptyList(); - } - - @Override - public List getImplicitIncludeUrls() { - return Collections.emptyList(); - } - - @Nullable - @Override - public VirtualFile getMappedInclude(String include) { - return null; - } - - @Override - public String getMappedIncludeUrl(String include) { - return ""; - } - - @Override - public List getPreprocessorDefines() { - return Collections.emptyList(); - } - - @Override - public Map, ?> getCompilerFeatures() { - return new HashMap<>(); - } - - @Nullable - @Override - public CompilerSettingsKey getCachingKey() { - return null; - } - - @Override - public Object getIndexingCluster() { - return null; - } - - public void setLibraryIncludeRoots(List roots) { - this.roots = HeadersSearchRoots.create(roots); - } -} From 9d0cecdd42623754512af8fafd907f85a8dc4333 Mon Sep 17 00:00:00 2001 From: Googler Date: Fri, 5 Nov 2021 07:35:46 -0700 Subject: [PATCH 26/47] Create sdk compat for version 2021.3 PiperOrigin-RevId: 407819082 --- sdkcompat/BUILD | 6 +- sdkcompat/v213/BUILD | 39 +++++++ .../OCNewFileProjectModelHandlerWrapper.java | 100 ++++++++++++++++++ .../idea/sdkcompat/general/BaseSdkCompat.java | 95 +++++++++++++++++ .../idea/sdkcompat/golang/GoLangCompat.java | 28 +++++ .../typescript/TypeScriptSDKCompat.java | 61 +++++++++++ .../sdkcompat/vcs/DvcsBranchPopupCompat.java | 39 +++++++ .../vcs/VcsManagedFilesHolderCompat.java | 13 +++ testing/BUILD | 6 +- .../idea/sdkcompat/BaseSdkTestCompat.java | 56 ++++++++++ .../testing/cidr/BaseClionSdkTestCompat.java | 32 ++++++ 11 files changed, 469 insertions(+), 6 deletions(-) create mode 100644 sdkcompat/v213/BUILD create mode 100644 sdkcompat/v213/com/google/idea/sdkcompat/clion/OCNewFileProjectModelHandlerWrapper.java create mode 100644 sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java create mode 100644 sdkcompat/v213/com/google/idea/sdkcompat/golang/GoLangCompat.java create mode 100644 sdkcompat/v213/com/google/idea/sdkcompat/typescript/TypeScriptSDKCompat.java create mode 100644 sdkcompat/v213/com/google/idea/sdkcompat/vcs/DvcsBranchPopupCompat.java create mode 100644 sdkcompat/v213/com/google/idea/sdkcompat/vcs/VcsManagedFilesHolderCompat.java create mode 100644 testing/testcompat/v213/com/google/idea/sdkcompat/BaseSdkTestCompat.java create mode 100644 testing/testcompat/v213/com/google/idea/testing/cidr/BaseClionSdkTestCompat.java diff --git a/sdkcompat/BUILD b/sdkcompat/BUILD index 6fae501538b..5c46dfc9b74 100644 --- a/sdkcompat/BUILD +++ b/sdkcompat/BUILD @@ -23,11 +23,11 @@ java_library( "intellij-ue-2021.1": ["//sdkcompat/v211"], "intellij-2021.2": ["//sdkcompat/v212"], "intellij-ue-2021.2": ["//sdkcompat/v212"], - "intellij-2021.3": ["//sdkcompat/v212"], - "intellij-ue-2021.3": ["//sdkcompat/v212"], + "intellij-2021.3": ["//sdkcompat/v213"], + "intellij-ue-2021.3": ["//sdkcompat/v213"], "clion-2020.3": ["//sdkcompat/v203"], "clion-2021.1": ["//sdkcompat/v211"], "clion-2021.2": ["//sdkcompat/v212"], - "clion-2021.3": ["//sdkcompat/v212"], + "clion-2021.3": ["//sdkcompat/v213"], }), ) diff --git a/sdkcompat/v213/BUILD b/sdkcompat/v213/BUILD new file mode 100644 index 00000000000..f650a017e89 --- /dev/null +++ b/sdkcompat/v213/BUILD @@ -0,0 +1,39 @@ +# Description: Indirections for SDK changes to the underlying platform library. + +load("//intellij_platform_sdk:build_defs.bzl", "select_for_ide") + +licenses(["notice"]) + +java_library( + name = "v213", + srcs = glob([ + "com/google/idea/sdkcompat/general/**", + "com/google/idea/sdkcompat/platform/**", + "com/google/idea/sdkcompat/python/**", + "com/google/idea/sdkcompat/vcs/**", + ]) + select_for_ide( + android_studio = glob([ + "com/google/idea/sdkcompat/java/**", + ]), + clion = glob([ + "com/google/idea/sdkcompat/clion/**", + "com/google/idea/sdkcompat/typescript/**", + ]), + intellij = glob([ + "com/google/idea/sdkcompat/java/**", + ]), + intellij_ue = glob([ + "com/google/idea/sdkcompat/golang/**", + "com/google/idea/sdkcompat/java/**", + "com/google/idea/sdkcompat/typescript/**", + ]), + ), + visibility = ["//sdkcompat:__pkg__"], + deps = [ + "//intellij_platform_sdk:jsr305", + "//intellij_platform_sdk:plugin_api", + "//third_party/go", + "//third_party/javascript", + "//third_party/python", + ], +) diff --git a/sdkcompat/v213/com/google/idea/sdkcompat/clion/OCNewFileProjectModelHandlerWrapper.java b/sdkcompat/v213/com/google/idea/sdkcompat/clion/OCNewFileProjectModelHandlerWrapper.java new file mode 100644 index 00000000000..02f990ad529 --- /dev/null +++ b/sdkcompat/v213/com/google/idea/sdkcompat/clion/OCNewFileProjectModelHandlerWrapper.java @@ -0,0 +1,100 @@ +package com.google.idea.sdkcompat.clion; + +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.extensions.ExtensionPoint; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiFile; +import com.jetbrains.cidr.cpp.cmake.actions.newFile.CPPNewFileProjectModelHandlerProvider; +import com.jetbrains.cidr.lang.actions.newFile.OCNewFileActionBase; +import com.jetbrains.cidr.lang.actions.newFile.OCNewFileProjectModelHandler; +import com.jetbrains.cidr.lang.actions.newFile.OCNewFileProjectModelHandlerProvider; +import org.jetbrains.annotations.Nullable; + +/** + * Compatibility wrapper for {@link OCNewFileProjectModelHandler}. + * + *

#api203: OCNewFileHelper was renamed to OCNewFileProjectModelHandler with API change. + */ +public class OCNewFileProjectModelHandlerWrapper implements OCNewFileProjectModelHandler { + + // Method extracted to compat class because of different types used for ExtensionPoint generic. + public static void replaceExtension(OCNewFileProjectModelHandlerProvider newProvider) { + // TODO (b/192065413): Get rid of deprecated API. + ExtensionPoint ep = + Extensions.getRootArea() + .getExtensionPoint(ExtensionPointName.create("cidr.lang.newFileModelHandlerProvider")); + for (OCNewFileProjectModelHandlerProvider filehelperProvider : ep.getExtensions()) { + ep.unregisterExtension(filehelperProvider); + } + ep.registerExtension(newProvider); + } + + // Class uses delegation instead of extension to use super.createHandler() in {@link CPPProvider} + @Nullable private final OCNewFileProjectModelHandler delegate; + + @Override + public boolean initFromDataContext(DataContext var1) { + return delegate.initFromDataContext(var1); + } + + @Override + public boolean initFromFile(PsiFile var1) { + return delegate.initFromFile(var1); + } + + @Override + public String getDefaultClassPrefix() { + return delegate.getDefaultClassPrefix(); + } + + @Override + public boolean canChangeDir() { + return delegate.canChangeDir(); + } + + @Override + public DialogWrapper createDialog( + OCNewFileActionBase.CreateFileDialogBase var1, + @Nullable PsiDirectory var2, + @Nullable DataContext var3) { + return delegate.createDialog(var1, var2, var3); + } + + @Override + public void doCreateFiles( + Project var1, + PsiDirectory var2, + String[] var3, + PsiFile[] var4, + @Nullable DialogWrapper var5, + @Nullable PsiFile var6) { + delegate.doCreateFiles(var1, var2, var3, var4, var5, var6); + } + + public boolean isAvailable(DataContext dataContext) { + return true; + } + + OCNewFileProjectModelHandlerWrapper(OCNewFileProjectModelHandler delegate) { + this.delegate = delegate; + } + + public OCNewFileProjectModelHandlerWrapper() { + this.delegate = null; + } + + /** + * Compat for {@link CPPNewFileProjectModelHandlerProvider}. + * + *

#api203. CPPNewFileHelperProvider was renamed to CPPNewFileProjectModelHandlerProvider. + */ + public static class CPPProvider extends CPPNewFileProjectModelHandlerProvider { + public OCNewFileProjectModelHandlerWrapper createHandler() { + return new OCNewFileProjectModelHandlerWrapper(super.createHandler()); + } + } +} diff --git a/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java new file mode 100644 index 00000000000..e3b4fd3d701 --- /dev/null +++ b/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -0,0 +1,95 @@ +package com.google.idea.sdkcompat.general; + +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider; +import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProviderImpl; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.DependencyScope; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.changes.ui.ChangesListView; +import com.intellij.ui.CoreIconManager; +import com.intellij.ui.IconManager; +import com.intellij.usageView.UsageTreeColors; +import com.intellij.usages.TextChunk; +import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory.IndexingTimes; +import java.nio.file.Path; +import java.time.Duration; +import java.util.List; +import javax.annotation.Nullable; + +/** Provides SDK compatibility shims for base plugin API classes, available to all IDEs. */ +public final class BaseSdkCompat { + private BaseSdkCompat() {} + + /** #api203: refactor this function back into CodesearchResultData and make it private. */ + public static void addLineNumber(int lineNumber, List chunks) { + chunks.add( + new TextChunk( + UsageTreeColors.NUMBER_OF_USAGES_ATTRIBUTES.toTextAttributes(), + String.valueOf(lineNumber))); + } + + /** #api203: refactor back into MoveChangesToChangeListAction#getUnversionedFileStreamFromEvent */ + @Nullable + public static Iterable getFilePaths(AnActionEvent e) { + return e.getData(ChangesListView.UNVERSIONED_FILE_PATHS_DATA_KEY); + } + + /** + * See {@link PathManager#getIndexRoot()}. + * + *

#api203: Method return type changed in 2021.1 from File to Path. + */ + public static Path getIndexRoot() { + return PathManager.getIndexRoot(); + } + + /** #api211 Activating IconManager requires an IconManager parameter in 2021.2 */ + public static void activateIconManager() throws Throwable { + IconManager.activate(new CoreIconManager()); + } + + /** #api203: inline this method into IndexingLogger */ + public static Duration getTotalUpdatingTime(IndexingTimes times) { + return Duration.ofNanos(times.getTotalUpdatingTime()); + } + + /** #api203: inline this method into IndexingLogger */ + public static Duration getScanFilesDuration(IndexingTimes times) { + return times.getScanFilesDuration(); + } + + /** #api203: inline this method into IndexingLogger */ + public static Duration getTotalIndexingTime(IndexingTimes times) { + return times.getIndexingDuration(); + } + + /** + * See {@link ModifiableRootModel#addLibraryEntries(List, DependencyScope, boolean)}. + * + *

#api211: New method addLibraryEntries() is only available from 2021.2.1 on (or from 2021.1.4 + * if that bugfix release will ever be published). + */ + public static void addLibraryEntriesToModel( + ModifiableRootModel modifiableRootModel, List libraries) { + for (Library library : libraries) { + modifiableRootModel.addLibraryEntry(library); + } + } + + /** + * Creates an {@link IdeModifiableModelsProvider} for performant updates of the project model even + * when many modifications are involved. {@link IdeModifiableModelsProvider#commit()} must be + * called for any changes to take effect but call that method only after completing all changes. + * + *

#api212: New method createModifiableModelsProvider() is only available from 2021.3 on. + */ + public static IdeModifiableModelsProvider createModifiableModelsProvider(Project project) { + // Switch to ProjectDataManager#createModifiableModelsProvider in 2021.3 for a public, stable + // API to create an IdeModifiableModelsProvider. + return new IdeModifiableModelsProviderImpl(project); + } +} diff --git a/sdkcompat/v213/com/google/idea/sdkcompat/golang/GoLangCompat.java b/sdkcompat/v213/com/google/idea/sdkcompat/golang/GoLangCompat.java new file mode 100644 index 00000000000..975f21e1a53 --- /dev/null +++ b/sdkcompat/v213/com/google/idea/sdkcompat/golang/GoLangCompat.java @@ -0,0 +1,28 @@ +package com.google.idea.sdkcompat.golang; + +import com.goide.execution.GoBuildingRunConfiguration.Kind; + +/** Provides SDK compatibility shims for Go lang classes, available to IntelliJ UE. */ +public class GoLangCompat { + private GoLangCompat() {} + + /** + * #api203: Kind enum moved from GoApplicationConfiguration to GoBuildingRunConfiguration in + * 2021.1 + */ + public enum KindWrapper { + DIRECTORY(Kind.DIRECTORY), + PACKAGE(Kind.PACKAGE), + FILE(Kind.FILE); + + private final Kind kind; + + private KindWrapper(Kind kind) { + this.kind = kind; + } + + public Kind getKind() { + return this.kind; + } + } +} diff --git a/sdkcompat/v213/com/google/idea/sdkcompat/typescript/TypeScriptSDKCompat.java b/sdkcompat/v213/com/google/idea/sdkcompat/typescript/TypeScriptSDKCompat.java new file mode 100644 index 00000000000..90a1a78f742 --- /dev/null +++ b/sdkcompat/v213/com/google/idea/sdkcompat/typescript/TypeScriptSDKCompat.java @@ -0,0 +1,61 @@ +package com.google.idea.sdkcompat.typescript; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.google.common.collect.ImmutableMap; +import com.intellij.lang.typescript.tsconfig.TypeScriptConfig; +import com.intellij.lang.typescript.tsconfig.TypeScriptConfigService; +import com.intellij.lang.typescript.tsconfig.TypeScriptConfigServiceImpl; +import com.intellij.openapi.vfs.VirtualFile; +import java.util.Collection; +import java.util.List; +import javax.annotation.Nullable; + +/** Provides SDK compatibility shims for Typescript classes, available to IntelliJ UE and CLion. */ +public class TypeScriptSDKCompat { + private TypeScriptSDKCompat() {} + + /** + * #api203: TypeScriptConfigUtil.getNearestParentConfigFiles was removed and + * TypeScriptConfigServiceImpl.getNearestParentTsConfigs was added in 2021.1 + */ + public static Collection getNearestParentTsConfigs( + @Nullable VirtualFile scopeFile, ImmutableMap configs) { + return TypeScriptConfigServiceImpl.getNearestParentTsConfigs(scopeFile, false).stream() + .filter(configs::containsKey) + .collect(toImmutableList()); + } + + /** #api203: TypeScriptConfigService#getPreferableOrParentConfig was added in 2021.1. */ + public static TypeScriptConfig getPreferableOrParentConfig( + TypeScriptConfigService impl, VirtualFile virtualFile) { + return impl.getPreferableOrParentConfig(virtualFile); + } + + /** #api203: TypeScriptConfigService#getDirectIncludePreferableConfig was added in 2021.1. */ + public static TypeScriptConfig getDirectIncludePreferableConfig( + TypeScriptConfigService impl, VirtualFile virtualFile) { + return impl.getDirectIncludePreferableConfig(virtualFile); + } + + /** #api203: TypeScriptConfigService#getRootConfigFiles was added in 2021.1. */ + public static List getRootConfigFiles(TypeScriptConfigService impl) { + return impl.getRootConfigFiles(); + } + + /** + * #api203: TypeScriptConfigService#getConfigs was removed in 2021.1, so we do nothing in this + * compat. + */ + public static List getConfigs(TypeScriptConfigService impl) { + return null; + } + + /** + * #api203: TypeScriptConfigService#hasConfigs was removed in 2021.1, so we do nothing in this + * compat. + */ + public static boolean hasConfigs(TypeScriptConfigService impl) { + return false; + } +} diff --git a/sdkcompat/v213/com/google/idea/sdkcompat/vcs/DvcsBranchPopupCompat.java b/sdkcompat/v213/com/google/idea/sdkcompat/vcs/DvcsBranchPopupCompat.java new file mode 100644 index 00000000000..3e7314d6f33 --- /dev/null +++ b/sdkcompat/v213/com/google/idea/sdkcompat/vcs/DvcsBranchPopupCompat.java @@ -0,0 +1,39 @@ +package com.google.idea.sdkcompat.vcs; + +import com.intellij.dvcs.branch.DvcsBranchPopup; +import com.intellij.dvcs.branch.DvcsMultiRootBranchConfig; +import com.intellij.dvcs.branch.DvcsSyncSettings; +import com.intellij.dvcs.repo.AbstractRepositoryManager; +import com.intellij.dvcs.repo.Repository; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.util.Condition; + +/** + * Compat for {@link DvcsBranchPopup}. DvcsBranchPopup changed the number of parameters in + * constructor starting with 2021.2. + * + *

To cleanup delete the class and use DvcsBranchPopup directly. + * + *

#api211 + */ +public abstract class DvcsBranchPopupCompat extends DvcsBranchPopup { + + protected DvcsBranchPopupCompat( + R currentRepository, + AbstractRepositoryManager repositoryManager, + DvcsMultiRootBranchConfig multiRootBranchConfig, + DvcsSyncSettings vcsSettings, + Condition preselectActionCondition, + String dimensionKey, + DataContext dataContext) { + super( + currentRepository, + repositoryManager, + multiRootBranchConfig, + vcsSettings, + preselectActionCondition, + dimensionKey, + dataContext); + } +} diff --git a/sdkcompat/v213/com/google/idea/sdkcompat/vcs/VcsManagedFilesHolderCompat.java b/sdkcompat/v213/com/google/idea/sdkcompat/vcs/VcsManagedFilesHolderCompat.java new file mode 100644 index 00000000000..bb18c247899 --- /dev/null +++ b/sdkcompat/v213/com/google/idea/sdkcompat/vcs/VcsManagedFilesHolderCompat.java @@ -0,0 +1,13 @@ +package com.google.idea.sdkcompat.vcs; + +import com.intellij.openapi.vcs.changes.VcsManagedFilesHolder; + +/** + * Compat for {@link VcsManagedFilesHolder}. VcsIgnoredFilesHolder was renamed to + * VcsManagedFilesHolder starting with 2021.2. + * + *

To cleanup delete interface and use VcsManagedFilesHolder directly. + * + *

#api211 + */ +public interface VcsManagedFilesHolderCompat extends VcsManagedFilesHolder {} diff --git a/testing/BUILD b/testing/BUILD index 3e69adcd024..611a98f460d 100644 --- a/testing/BUILD +++ b/testing/BUILD @@ -36,15 +36,15 @@ java_library( "clion-2020.3": glob(["testcompat/v203/com/google/idea/sdkcompat/**/*.java"]), "clion-2021.1": glob(["testcompat/v211/com/google/idea/sdkcompat/**/*.java"]), "clion-2021.2": glob(["testcompat/v212/com/google/idea/sdkcompat/**/*.java"]), - "clion-2021.3": glob(["testcompat/v212/com/google/idea/sdkcompat/**/*.java"]), + "clion-2021.3": glob(["testcompat/v213/com/google/idea/sdkcompat/**/*.java"]), "intellij-2020.3": glob(["testcompat/v203/com/google/idea/sdkcompat/**/*.java"]), "intellij-ue-2020.3": glob(["testcompat/v203/com/google/idea/sdkcompat/**/*.java"]), "intellij-2021.1": glob(["testcompat/v211/com/google/idea/sdkcompat/**/*.java"]), "intellij-ue-2021.1": glob(["testcompat/v211/com/google/idea/sdkcompat/**/*.java"]), "intellij-2021.2": glob(["testcompat/v212/com/google/idea/sdkcompat/**/*.java"]), "intellij-ue-2021.2": glob(["testcompat/v212/com/google/idea/sdkcompat/**/*.java"]), - "intellij-2021.3": glob(["testcompat/v212/com/google/idea/sdkcompat/**/*.java"]), - "intellij-ue-2021.3": glob(["testcompat/v212/com/google/idea/sdkcompat/**/*.java"]), + "intellij-2021.3": glob(["testcompat/v213/com/google/idea/sdkcompat/**/*.java"]), + "intellij-ue-2021.3": glob(["testcompat/v213/com/google/idea/sdkcompat/**/*.java"]), "default": glob(["testcompat/v203/com/google/idea/sdkcompat/**/*.java"]), }), deps = [ diff --git a/testing/testcompat/v213/com/google/idea/sdkcompat/BaseSdkTestCompat.java b/testing/testcompat/v213/com/google/idea/sdkcompat/BaseSdkTestCompat.java new file mode 100644 index 00000000000..6950cedadb4 --- /dev/null +++ b/testing/testcompat/v213/com/google/idea/sdkcompat/BaseSdkTestCompat.java @@ -0,0 +1,56 @@ +/* + * Copyright 2021 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.sdkcompat; + +import com.intellij.openapi.project.Project; +import com.intellij.util.indexing.diagnostic.IndexingJobStatistics; +import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory; +import java.time.Duration; + +/** + * Provides SDK compatibility shims for base plugin API classes, available to all IDEs during + * test-time. + */ +public final class BaseSdkTestCompat { + private BaseSdkTestCompat() {} + + /** + * #api203: Doing duration calculations is not necessary anymore. Inline into IndexingLoggerTest. + */ + @SuppressWarnings("UnstableApiUsage") + public static void setIndexingTimes( + ProjectIndexingHistory.IndexingTimes projectIndexingHistory, + Duration expectedIndexingDuration, + Duration expectedUpdatingDuration, + Duration expectedScanFilesDuration) { + projectIndexingHistory.setIndexingDuration(expectedIndexingDuration); + projectIndexingHistory.setTotalUpdatingTime(expectedUpdatingDuration.toNanos()); + projectIndexingHistory.setScanFilesDuration(expectedScanFilesDuration); + } + + /** #api203: inline into IndexingLoggerTest */ + @SuppressWarnings("UnstableApiUsage") + public static void setIndexingVisibleTime( + IndexingJobStatistics indexingStatistic, Duration expectedIndexingVisibleTime) { + indexingStatistic.setIndexingVisibleTime(expectedIndexingVisibleTime.toNanos()); + } + + /** #api211 inline into IndexingLoggerTest */ + @SuppressWarnings("UnstableApiUsage") + public static ProjectIndexingHistory initializeProjectIndexingHistory(Project project) { + return new ProjectIndexingHistory(project, /* indexingReason= */ ""); + } +} diff --git a/testing/testcompat/v213/com/google/idea/testing/cidr/BaseClionSdkTestCompat.java b/testing/testcompat/v213/com/google/idea/testing/cidr/BaseClionSdkTestCompat.java new file mode 100644 index 00000000000..7fd1d278832 --- /dev/null +++ b/testing/testcompat/v213/com/google/idea/testing/cidr/BaseClionSdkTestCompat.java @@ -0,0 +1,32 @@ +/* + * Copyright 2021 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.sdkcompat; + +import com.intellij.openapi.project.Project; +import com.jetbrains.cidr.lang.symbols.symtable.building.OCSymbolTablesBuildingActivity; + +/** + * Provides SDK compatibility shims for base plugin API classes, available to all IDEs during + * test-time. + */ +public final class BaseClionSdkTestCompat { + private BaseClionSdkTestCompat() {} + + /** #api211 inline into test cases */ + public static void rebuildSymbols(Project project) { + OCSymbolTablesBuildingActivity.getInstance(project).rebuildSymbols(); + } +} From 244064d9306bec7d62cfb4cfdd0e502f984d17b6 Mon Sep 17 00:00:00 2001 From: Googler Date: Mon, 8 Nov 2021 03:49:34 -0800 Subject: [PATCH 27/47] Move IntelliJ dev version to 2021.3 SDK PiperOrigin-RevId: 408300870 --- intellij_platform_sdk/build_defs.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intellij_platform_sdk/build_defs.bzl b/intellij_platform_sdk/build_defs.bzl index ac3fb1aa988..1b6f41a6f21 100644 --- a/intellij_platform_sdk/build_defs.bzl +++ b/intellij_platform_sdk/build_defs.bzl @@ -6,11 +6,11 @@ INDIRECT_IJ_PRODUCTS = { "intellij-latest": "intellij-2021.2", "intellij-latest-mac": "intellij-2021.2-mac", "intellij-beta": "intellij-2021.2", - "intellij-under-dev": "intellij-2021.2", + "intellij-under-dev": "intellij-2021.3", "intellij-ue-latest": "intellij-ue-2021.2", "intellij-ue-latest-mac": "intellij-ue-2021.2-mac", "intellij-ue-beta": "intellij-ue-2021.2", - "intellij-ue-under-dev": "intellij-ue-2021.2", + "intellij-ue-under-dev": "intellij-ue-2021.3", "android-studio-latest": "android-studio-2020.3", "android-studio-beta": "android-studio-2020.3", "android-studio-beta-mac": "android-studio-2020.3-mac", From e39fec7a6517bce893b7c86bee8d1068462ec312 Mon Sep 17 00:00:00 2001 From: Googler Date: Mon, 8 Nov 2021 13:34:41 -0800 Subject: [PATCH 28/47] Use Studio's deploy logic PiperOrigin-RevId: 408428795 --- ...roidBinaryMobileInstallRunContextBase.java | 39 +++++++++++- .../BlazeApkBuildStepMobileInstall.java | 60 +++++++++++++------ .../StudioDeployerExperiment.java | 40 +++++++++++++ .../common/experiments/experiment.properties | 4 ++ 4 files changed, 122 insertions(+), 21 deletions(-) create mode 100644 aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/StudioDeployerExperiment.java diff --git a/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java b/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java index 1724dbfe5e9..eff99693c0f 100644 --- a/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java +++ b/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java @@ -16,6 +16,8 @@ package com.google.idea.blaze.android.run.binary.mobileinstall; import com.android.ddmlib.IDevice; +import com.android.tools.idea.run.ApkFileUnit; +import com.android.tools.idea.run.ApkInfo; import com.android.tools.idea.run.ApkProvisionException; import com.android.tools.idea.run.ApplicationIdProvider; import com.android.tools.idea.run.ConsolePrinter; @@ -31,6 +33,7 @@ import com.android.tools.idea.run.util.LaunchStatus; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.idea.blaze.android.run.BlazeAndroidDeploymentService; import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryApplicationIdProvider; import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryApplicationLaunchTaskProvider; import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryConsoleProvider; @@ -41,16 +44,18 @@ import com.google.idea.blaze.android.run.runner.BlazeAndroidLaunchTasksProvider; import com.google.idea.blaze.android.run.runner.BlazeAndroidRunContext; import com.google.idea.blaze.android.run.runner.BlazeApkBuildStep; +import com.google.idea.blaze.base.sync.data.BlazeDataStorage; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.RunConfiguration; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.openapi.project.Project; +import java.util.Collections; +import java.util.stream.Collectors; import javax.annotation.Nullable; import org.jetbrains.android.facet.AndroidFacet; /** Run context for android_binary. */ abstract class BlazeAndroidBinaryMobileInstallRunContextBase implements BlazeAndroidRunContext { - protected final Project project; protected final AndroidFacet facet; protected final RunConfiguration runConfiguration; @@ -84,7 +89,9 @@ public BlazeAndroidDeviceSelector getDeviceSelector() { @Override public void augmentLaunchOptions(LaunchOptions.Builder options) { - options.setDeploy(false).setOpenLogcatAutomatically(configState.showLogcatAutomatically()); + options + .setDeploy(StudioDeployerExperiment.isEnabled()) + .setOpenLogcatAutomatically(configState.showLogcatAutomatically()); options.addExtraOptions( ImmutableMap.of(ProfilerState.ANDROID_PROFILER_STATE_ID, configState.getProfilerState())); } @@ -107,7 +114,33 @@ public BlazeApkBuildStep getBuildStep() { @Override public ImmutableList getDeployTasks(IDevice device, LaunchOptions launchOptions) throws ExecutionException { - return ImmutableList.of(); + if (!StudioDeployerExperiment.isEnabled()) { + return ImmutableList.of(); + } + + BlazeAndroidDeployInfo deployInfo; + try { + deployInfo = buildStep.getDeployInfo(); + } catch (ApkProvisionException e) { + throw new ExecutionException(e); + } + + String packageName = deployInfo.getMergedManifest().packageName; + if (packageName == null) { + throw new ExecutionException("Could not determine package name from deploy info"); + } + + ApkInfo info = + new ApkInfo( + deployInfo.getApksToDeploy().stream() + .map(file -> new ApkFileUnit(BlazeDataStorage.WORKSPACE_MODULE_NAME, file)) + .collect(Collectors.toList()), + packageName); + + LaunchTask deployTask = + BlazeAndroidDeploymentService.getInstance(project) + .getDeployTask(Collections.singletonList(info), launchOptions); + return ImmutableList.of(deployTask); } @Nullable diff --git a/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeApkBuildStepMobileInstall.java b/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeApkBuildStepMobileInstall.java index 78e8d70d86d..08cf033ad01 100644 --- a/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeApkBuildStepMobileInstall.java +++ b/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeApkBuildStepMobileInstall.java @@ -56,6 +56,7 @@ import com.google.idea.blaze.base.sync.aspects.BuildResult; import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager; import com.google.idea.blaze.base.util.SaveUtil; +import com.google.idea.common.experiments.BoolExperiment; import com.intellij.execution.ExecutionException; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -67,6 +68,9 @@ /** Builds and installs the APK using mobile-install. */ public class BlazeApkBuildStepMobileInstall implements BlazeApkBuildStep { + private static final BoolExperiment passAdbArgWithSerialToMi = + new BoolExperiment("aswb.mi.adb.arg.device.serial", false); + private static final Logger log = Logger.getInstance(BlazeApkBuildStepMobileInstall.class); private final Project project; private final Label label; @@ -133,12 +137,17 @@ public void build(BlazeContext context, BlazeAndroidDeviceSelector.DeviceSession Blaze.getBuildSystemProvider(project).getBinaryPath(project), BlazeCommandName.MOBILE_INSTALL); - // Redundant, but we need this to get around bug in bazel. - // https://github.com/bazelbuild/bazel/issues/4922 - command.addBlazeFlags( - BlazeFlags.ADB_ARG + "-s ", BlazeFlags.ADB_ARG + device.getSerialNumber()); - MobileInstallAdbLocationProvider.getAdbLocationForMobileInstall(project) - .ifPresent((location) -> command.addBlazeFlags(BlazeFlags.ADB, location)); + if (passAdbArgWithSerialToMi.getValue()) { + // Redundant, but we need this to get around bug in bazel. + // https://github.com/bazelbuild/bazel/issues/4922 + command.addBlazeFlags( + BlazeFlags.ADB_ARG + "-s ", BlazeFlags.ADB_ARG + device.getSerialNumber()); + } + + if (!StudioDeployerExperiment.isEnabled()) { + MobileInstallAdbLocationProvider.getAdbLocationForMobileInstall(project) + .ifPresent((location) -> command.addBlazeFlags(BlazeFlags.ADB, location)); + } WorkspaceRoot workspaceRoot = WorkspaceRoot.fromProject(project); final String deployInfoSuffix = getDeployInfoSuffix(Blaze.getBuildSystem(project)); @@ -147,21 +156,24 @@ public void build(BlazeContext context, BlazeAndroidDeviceSelector.DeviceSession BuildResultHelperProvider.createForLocalBuild(project); AdbTunnelConfigurator tunnelConfig = getTunnelConfigurator(context)) { tunnelConfig.setupConnection(context); - String deviceFlag = device.getSerialNumber(); - if (tunnelConfig.isActive()) { - deviceFlag += ":tcp:" + tunnelConfig.getAdbServerPort(); - } else { - InetSocketAddress adbAddr = AndroidDebugBridge.getSocketAddress(); - if (adbAddr == null) { - IssueOutput.warn( - "Can't get ADB server port, please ensure ADB server is running. Will fallback to" - + " the default adb server.") - .submit(context); + + if (!StudioDeployerExperiment.isEnabled()) { + String deviceFlag = device.getSerialNumber(); + if (tunnelConfig.isActive()) { + deviceFlag += ":tcp:" + tunnelConfig.getAdbServerPort(); } else { - deviceFlag += ":tcp:" + adbAddr.getPort(); + InetSocketAddress adbAddr = AndroidDebugBridge.getSocketAddress(); + if (adbAddr == null) { + IssueOutput.warn( + "Can't get ADB server port, please ensure ADB server is running. Will fallback" + + " to the default adb server.") + .submit(context); + } else { + deviceFlag += ":tcp:" + adbAddr.getPort(); + } } + command.addBlazeFlags(BlazeFlags.DEVICE, deviceFlag); } - command.addBlazeFlags(BlazeFlags.DEVICE, deviceFlag); command .addTargets(label) @@ -171,6 +183,10 @@ public void build(BlazeContext context, BlazeAndroidDeviceSelector.DeviceSession // MI launches apps by default. Defer app launch to BlazeAndroidLaunchTasksProvider. .addExeFlags("--nolaunch_app"); + if (StudioDeployerExperiment.isEnabled()) { + command.addExeFlags("--nodeploy"); + } + SaveUtil.saveAllFiles(); context.output(new StatusOutput("Invoking mobile-install...")); int retVal = @@ -206,6 +222,14 @@ public void build(BlazeContext context, BlazeAndroidDeviceSelector.DeviceSession deployInfo = deployInfoHelper.extractDeployInfoAndInvalidateManifests( project, new File(executionRoot), deployInfoProto); + + String msg; + if (StudioDeployerExperiment.isEnabled()) { + msg = "mobile-install build completed, deploying split apks..."; + } else { + msg = "Done."; + } + context.output(new StatusOutput(msg)); } catch (GetArtifactsException e) { IssueOutput.error("Could not read BEP output: " + e.getMessage()).submit(context); } catch (GetDeployInfoException e) { diff --git a/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/StudioDeployerExperiment.java b/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/StudioDeployerExperiment.java new file mode 100644 index 00000000000..893b7b15881 --- /dev/null +++ b/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/StudioDeployerExperiment.java @@ -0,0 +1,40 @@ +/* + * Copyright 2020 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.android.run.binary.mobileinstall; + +import com.google.idea.common.experiments.FeatureRolloutExperiment; +import com.intellij.openapi.util.SystemInfo; + +/** + * A utility class that manages the experiment to use studio's built in deployer for deploying apks + * instead of using the one present in mobile-install. + */ +public class StudioDeployerExperiment { + /** Indicates if we should deploy via Studio or via MI. */ + private static final FeatureRolloutExperiment useStudioDeployer = + new FeatureRolloutExperiment("aswb.use.studio.deployer"); + + /** Returns whether mobile install deployments should happen via the studio deployer. */ + public static boolean isEnabled() { + if (!SystemInfo.isLinux) { + // TODO(b/197761450): Enable this for Macs after mdproxy related issues are sorted out. + return false; + } + return useStudioDeployer.isEnabled(); + } + + private StudioDeployerExperiment() {} +} diff --git a/common/experiments/src/com/google/idea/common/experiments/experiment.properties b/common/experiments/src/com/google/idea/common/experiments/experiment.properties index 47e90d45c83..90a01dea954 100644 --- a/common/experiments/src/com/google/idea/common/experiments/experiment.properties +++ b/common/experiments/src/com/google/idea/common/experiments/experiment.properties @@ -2,3 +2,7 @@ # Each line of the file except comment lines marked by # or ! symbols # contains one flag. For each flag, the format `flag_name=value` is used. + +# Flags used by ASwB +# Use Studio's deployer: b/197761450 +aswb.use.studio.deployer=25 \ No newline at end of file From f4cf883c6b1b12dc7124efecaf7ca56f2a29f583 Mon Sep 17 00:00:00 2001 From: Googler Date: Mon, 8 Nov 2021 14:06:34 -0800 Subject: [PATCH 29/47] Log metrics for build + deploy timings PiperOrigin-RevId: 408437219 --- ...azeAndroidBinaryNormalBuildRunContext.java | 5 +- ...eAndroidBinaryMobileInstallRunContext.java | 5 +- .../run/test/BlazeAndroidTestRunContext.java | 8 +- ...azeAndroidBinaryNormalBuildRunContext.java | 5 +- ...eAndroidBinaryMobileInstallRunContext.java | 5 +- .../run/test/BlazeAndroidTestRunContext.java | 8 +- ...azeAndroidBinaryNormalBuildRunContext.java | 5 +- ...eAndroidBinaryMobileInstallRunContext.java | 5 +- .../run/test/BlazeAndroidTestRunContext.java | 8 +- .../android/run/BlazeApkBuildService.java | 8 +- .../idea/blaze/android/run/LaunchMetrics.java | 133 ++++++++++++++++++ ...ndroidBinaryNormalBuildRunContextBase.java | 10 +- ...eAndroidBinaryRunConfigurationHandler.java | 32 ++--- .../binary/DeploymentTimingReporterTask.java | 80 +++++++++++ ...roidBinaryMobileInstallRunContextBase.java | 8 +- .../BlazeApkBuildStepMobileInstall.java | 46 ++++-- ...azeAndroidTestRunConfigurationHandler.java | 31 ++-- .../test/BlazeAndroidTestRunContextBase.java | 6 +- 18 files changed, 330 insertions(+), 78 deletions(-) create mode 100644 aswb/src/com/google/idea/blaze/android/run/LaunchMetrics.java create mode 100644 aswb/src/com/google/idea/blaze/android/run/binary/DeploymentTimingReporterTask.java diff --git a/aswb/sdkcompat/as203/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java b/aswb/sdkcompat/as203/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java index 5eb4bfb21e7..e7044fdbd55 100644 --- a/aswb/sdkcompat/as203/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java +++ b/aswb/sdkcompat/as203/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java @@ -35,8 +35,9 @@ public class BlazeAndroidBinaryNormalBuildRunContext RunConfiguration runConfiguration, ExecutionEnvironment env, BlazeAndroidBinaryRunConfigurationState configState, - BlazeApkBuildStep buildStep) { - super(project, facet, runConfiguration, env, configState, buildStep); + BlazeApkBuildStep buildStep, + String launchId) { + super(project, facet, runConfiguration, env, configState, buildStep, launchId); } @Nullable diff --git a/aswb/sdkcompat/as203/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java b/aswb/sdkcompat/as203/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java index b77216240a8..8dca6051ea7 100644 --- a/aswb/sdkcompat/as203/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java +++ b/aswb/sdkcompat/as203/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java @@ -36,8 +36,9 @@ public BlazeAndroidBinaryMobileInstallRunContext( RunConfiguration runConfiguration, ExecutionEnvironment env, BlazeAndroidBinaryRunConfigurationState configState, - BlazeApkBuildStep buildStep) { - super(project, facet, runConfiguration, env, configState, buildStep); + BlazeApkBuildStep buildStep, + String launchId) { + super(project, facet, runConfiguration, env, configState, buildStep, launchId); } @Nullable diff --git a/aswb/sdkcompat/as203/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java b/aswb/sdkcompat/as203/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java index 7f3c8b7798e..41854928531 100644 --- a/aswb/sdkcompat/as203/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java +++ b/aswb/sdkcompat/as203/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java @@ -35,7 +35,7 @@ /** * Run context for android_test. * - *

#api42 + *

#api203 */ public class BlazeAndroidTestRunContext extends BlazeAndroidTestRunContextBase { BlazeAndroidTestRunContext( @@ -46,8 +46,10 @@ public class BlazeAndroidTestRunContext extends BlazeAndroidTestRunContextBase { BlazeAndroidTestRunConfigurationState configState, Label label, ImmutableList blazeFlags, - ImmutableList exeFlags) { - super(project, facet, runConfiguration, env, configState, label, blazeFlags, exeFlags); + ImmutableList exeFlags, + String launchId) { + super( + project, facet, runConfiguration, env, configState, label, blazeFlags, exeFlags, launchId); } @Override diff --git a/aswb/sdkcompat/as211/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java b/aswb/sdkcompat/as211/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java index b44fb8c8eee..db8dee4ae61 100644 --- a/aswb/sdkcompat/as211/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java +++ b/aswb/sdkcompat/as211/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java @@ -35,8 +35,9 @@ public class BlazeAndroidBinaryNormalBuildRunContext RunConfiguration runConfiguration, ExecutionEnvironment env, BlazeAndroidBinaryRunConfigurationState configState, - BlazeApkBuildStep buildStep) { - super(project, facet, runConfiguration, env, configState, buildStep); + BlazeApkBuildStep buildStep, + String launchId) { + super(project, facet, runConfiguration, env, configState, buildStep, launchId); } @Nullable diff --git a/aswb/sdkcompat/as211/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java b/aswb/sdkcompat/as211/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java index d387698e763..184e67cafe2 100644 --- a/aswb/sdkcompat/as211/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java +++ b/aswb/sdkcompat/as211/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java @@ -36,8 +36,9 @@ public BlazeAndroidBinaryMobileInstallRunContext( RunConfiguration runConfiguration, ExecutionEnvironment env, BlazeAndroidBinaryRunConfigurationState configState, - BlazeApkBuildStep buildStep) { - super(project, facet, runConfiguration, env, configState, buildStep); + BlazeApkBuildStep buildStep, + String launchId) { + super(project, facet, runConfiguration, env, configState, buildStep, launchId); } @Nullable diff --git a/aswb/sdkcompat/as211/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java b/aswb/sdkcompat/as211/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java index a2794e91b3e..7c708659e24 100644 --- a/aswb/sdkcompat/as211/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java +++ b/aswb/sdkcompat/as211/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java @@ -35,7 +35,7 @@ /** * Run context for android_test. * - *

#api42 + *

#api203 */ public class BlazeAndroidTestRunContext extends BlazeAndroidTestRunContextBase { BlazeAndroidTestRunContext( @@ -46,8 +46,10 @@ public class BlazeAndroidTestRunContext extends BlazeAndroidTestRunContextBase { BlazeAndroidTestRunConfigurationState configState, Label label, ImmutableList blazeFlags, - ImmutableList exeFlags) { - super(project, facet, runConfiguration, env, configState, label, blazeFlags, exeFlags); + ImmutableList exeFlags, + String launchId) { + super( + project, facet, runConfiguration, env, configState, label, blazeFlags, exeFlags, launchId); } @Override diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java index b44fb8c8eee..db8dee4ae61 100644 --- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java +++ b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java @@ -35,8 +35,9 @@ public class BlazeAndroidBinaryNormalBuildRunContext RunConfiguration runConfiguration, ExecutionEnvironment env, BlazeAndroidBinaryRunConfigurationState configState, - BlazeApkBuildStep buildStep) { - super(project, facet, runConfiguration, env, configState, buildStep); + BlazeApkBuildStep buildStep, + String launchId) { + super(project, facet, runConfiguration, env, configState, buildStep, launchId); } @Nullable diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java index d387698e763..184e67cafe2 100644 --- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java +++ b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java @@ -36,8 +36,9 @@ public BlazeAndroidBinaryMobileInstallRunContext( RunConfiguration runConfiguration, ExecutionEnvironment env, BlazeAndroidBinaryRunConfigurationState configState, - BlazeApkBuildStep buildStep) { - super(project, facet, runConfiguration, env, configState, buildStep); + BlazeApkBuildStep buildStep, + String launchId) { + super(project, facet, runConfiguration, env, configState, buildStep, launchId); } @Nullable diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java index a2794e91b3e..7c708659e24 100644 --- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java +++ b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java @@ -35,7 +35,7 @@ /** * Run context for android_test. * - *

#api42 + *

#api203 */ public class BlazeAndroidTestRunContext extends BlazeAndroidTestRunContextBase { BlazeAndroidTestRunContext( @@ -46,8 +46,10 @@ public class BlazeAndroidTestRunContext extends BlazeAndroidTestRunContextBase { BlazeAndroidTestRunConfigurationState configState, Label label, ImmutableList blazeFlags, - ImmutableList exeFlags) { - super(project, facet, runConfiguration, env, configState, label, blazeFlags, exeFlags); + ImmutableList exeFlags, + String launchId) { + super( + project, facet, runConfiguration, env, configState, label, blazeFlags, exeFlags, launchId); } @Override diff --git a/aswb/src/com/google/idea/blaze/android/run/BlazeApkBuildService.java b/aswb/src/com/google/idea/blaze/android/run/BlazeApkBuildService.java index e33ff75b3e1..b8ad1208e5a 100644 --- a/aswb/src/com/google/idea/blaze/android/run/BlazeApkBuildService.java +++ b/aswb/src/com/google/idea/blaze/android/run/BlazeApkBuildService.java @@ -34,7 +34,8 @@ BlazeApkBuildStep getBuildStep( boolean useMobileInstall, Label label, ImmutableList blazeFlags, - ImmutableList exeFlags); + ImmutableList exeFlags, + String launchId); /** * A default implementation that uses {@link BlazeApkBuildStepNormalBuild} and {@link @@ -52,9 +53,10 @@ public BlazeApkBuildStep getBuildStep( boolean useMobileInstall, Label label, ImmutableList blazeFlags, - ImmutableList exeFlags) { + ImmutableList exeFlags, + String launchId) { if (useMobileInstall) { - return new BlazeApkBuildStepMobileInstall(project, label, blazeFlags, exeFlags); + return new BlazeApkBuildStepMobileInstall(project, label, blazeFlags, exeFlags, launchId); } else { return new BlazeApkBuildStepNormalBuild(project, label, blazeFlags); } diff --git a/aswb/src/com/google/idea/blaze/android/run/LaunchMetrics.java b/aswb/src/com/google/idea/blaze/android/run/LaunchMetrics.java new file mode 100644 index 00000000000..a739ecbf57f --- /dev/null +++ b/aswb/src/com/google/idea/blaze/android/run/LaunchMetrics.java @@ -0,0 +1,133 @@ +/* + * Copyright 2021 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.android.run; + +import com.android.tools.idea.run.tasks.LaunchResult; +import com.google.common.base.StandardSystemProperty; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableMap; +import com.google.idea.blaze.base.logging.EventLoggingService; +import com.google.idea.common.experiments.BoolExperiment; +import java.time.Duration; +import java.time.Instant; + +/** Metrics collected during launch events. */ +public class LaunchMetrics { + private static final BoolExperiment launchMetricsEnabled = + new BoolExperiment("aswb.launch.metrics", true); + + private static final String SANITIZED_USER_NAME = + Strings.nullToEmpty(StandardSystemProperty.USER_NAME.value()); + + // Launch metrics are currently logged using an untyped map of key values. + // The following constants represent the keys currently in use. + private static final String KEY_LAUNCH_ID = "launchId"; + private static final String KEY_LAUNCH_METHOD = "launchMethod"; + private static final String KEY_EXECUTOR_ID = "executorId"; + private static final String KEY_TARGET_LABEL = "targetLabel"; + private static final String KEY_NATIVE_DEBUGGING_ENABLED = "nativeDebuggingEnabled"; + private static final String KEY_USES_STUDIO_DEPLOYER = "studioDeployerEnabled"; + private static final String KEY_BUILD_DURATION_MILLIS = "buildDurationMillis"; + private static final String KEY_BLAZE_EXIT_CODE = "blazeExitCode"; + private static final String KEY_DEPLOY_DURATION_MILLIS = "deployDurationMillis"; + private static final String KEY_DEPLOY_STATUS = "deployStatus"; + + /** + * Returns a string suitable for use as a unique launch id. + * + *

An id is generated just based on the user name and the current time since epoch, where we + * are basically assuming that the same user hasn't performed two launches from the IDE at the + * same instant in time. + */ + public static String newLaunchId() { + return String.format("%1$s:%2$d", SANITIZED_USER_NAME, Instant.now().toEpochMilli()); + } + + public static void logBuildTime( + String launchId, boolean usesStudioDeployer, Duration buildDuration, int blazeExitCode) { + if (!launchMetricsEnabled.getValue()) { + return; + } + + ImmutableMap metrics = + ImmutableMap.of( + KEY_LAUNCH_ID, + launchId, + KEY_USES_STUDIO_DEPLOYER, + Boolean.toString(usesStudioDeployer), + KEY_BUILD_DURATION_MILLIS, + Long.toString(buildDuration.toMillis()), + KEY_BLAZE_EXIT_CODE, + Integer.toString(blazeExitCode)); + EventLoggingService.getInstance().logEvent(LaunchMetrics.class, "BuildTiming", metrics); + } + + public static void logDeploymentTime( + String launchId, Duration duration, LaunchResult launchResult) { + if (!launchMetricsEnabled.getValue()) { + return; + } + + ImmutableMap metrics = + ImmutableMap.of( + KEY_LAUNCH_ID, + launchId, + KEY_DEPLOY_DURATION_MILLIS, + Long.toString(duration.toMillis()), + KEY_DEPLOY_STATUS, + Boolean.toString(launchResult.getSuccess())); + EventLoggingService.getInstance().logEvent(LaunchMetrics.class, "DeployTiming", metrics); + } + + public static void logBinaryLaunch( + String launchId, + String launchMethod, + String executorId, + String target, + boolean nativeDebuggingEnabled) { + if (!launchMetricsEnabled.getValue()) { + return; + } + + ImmutableMap metrics = + ImmutableMap.of( + KEY_LAUNCH_ID, + launchId, + KEY_LAUNCH_METHOD, + launchMethod, + KEY_EXECUTOR_ID, + executorId, + KEY_TARGET_LABEL, + target, + KEY_NATIVE_DEBUGGING_ENABLED, + Boolean.toString(nativeDebuggingEnabled)); + EventLoggingService.getInstance() + .logEvent(LaunchMetrics.class, "BlazeAndroidBinaryRun", metrics); + } + + public static void logTestLaunch(String launchId, String launchMethod, String executorId) { + if (!launchMetricsEnabled.getValue()) { + return; + } + + ImmutableMap metrics = + ImmutableMap.of( + KEY_LAUNCH_ID, launchId, KEY_LAUNCH_METHOD, launchMethod, KEY_EXECUTOR_ID, executorId); + EventLoggingService.getInstance().logEvent(LaunchMetrics.class, "BlazeAndroidTestRun", metrics); + } + + private LaunchMetrics() {} +} diff --git a/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java b/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java index 91e0bf4ae15..fd30bf4bcba 100644 --- a/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java +++ b/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java @@ -67,6 +67,7 @@ public abstract class BlazeAndroidBinaryNormalBuildRunContextBase protected final BlazeApkBuildStep buildStep; protected final ApkProvider apkProvider; protected final ApplicationIdProvider applicationIdProvider; + private final String launchId; BlazeAndroidBinaryNormalBuildRunContextBase( Project project, @@ -74,7 +75,8 @@ public abstract class BlazeAndroidBinaryNormalBuildRunContextBase RunConfiguration runConfiguration, ExecutionEnvironment env, BlazeAndroidBinaryRunConfigurationState configState, - BlazeApkBuildStep buildStep) { + BlazeApkBuildStep buildStep, + String launchId) { this.project = project; this.facet = facet; this.runConfiguration = runConfiguration; @@ -84,6 +86,7 @@ public abstract class BlazeAndroidBinaryNormalBuildRunContextBase this.buildStep = buildStep; this.apkProvider = BlazeApkProviderService.getInstance().getApkProvider(project, buildStep); this.applicationIdProvider = new BlazeAndroidBinaryApplicationIdProvider(buildStep); + this.launchId = launchId; } @Override @@ -173,9 +176,10 @@ public String getAmStartOptions() { @Override public ImmutableList getDeployTasks(IDevice device, LaunchOptions launchOptions) throws ExecutionException { - return ImmutableList.of( + LaunchTask deployTask = DeployTasksCompat.getDeployTask( - project, env, launchOptions, getApkInfoToInstall(device, launchOptions, apkProvider))); + project, env, launchOptions, getApkInfoToInstall(device, launchOptions, apkProvider)); + return ImmutableList.of(new DeploymentTimingReporterTask(launchId, deployTask)); } /** Returns a list of APKs excluding any APKs for features that are disabled. */ diff --git a/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationHandler.java b/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationHandler.java index 324965c432b..11f850a8a51 100644 --- a/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationHandler.java +++ b/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationHandler.java @@ -16,6 +16,7 @@ package com.google.idea.blaze.android.run.binary; import static com.android.tools.idea.run.deployment.DeviceAndSnapshotComboBoxAction.DEPLOYS_TO_LOCAL_DEVICE; +import static com.google.idea.blaze.android.run.LaunchMetrics.logBinaryLaunch; import com.android.tools.idea.run.ValidationError; import com.google.common.annotations.VisibleForTesting; @@ -25,6 +26,7 @@ import com.google.idea.blaze.android.run.BlazeAndroidRunConfigurationHandler; import com.google.idea.blaze.android.run.BlazeAndroidRunConfigurationValidationUtil; import com.google.idea.blaze.android.run.BlazeApkBuildService; +import com.google.idea.blaze.android.run.LaunchMetrics; import com.google.idea.blaze.android.run.binary.AndroidBinaryLaunchMethodsUtils.AndroidBinaryLaunchMethod; import com.google.idea.blaze.android.run.binary.mobileinstall.BlazeAndroidBinaryMobileInstallRunContext; import com.google.idea.blaze.android.run.runner.BlazeAndroidRunConfigurationRunner; @@ -117,6 +119,10 @@ public BlazeCommandRunConfigurationRunner createRunner( maybeShowMobileInstallOptIn(project, configuration); } + // We collect metrics from a few different locations. In order to tie them all + // together, we create a unique launch id. + String launchId = LaunchMetrics.newLaunchId(); + // Create build step for matching launch method. ImmutableList blazeFlags = configState @@ -136,7 +142,8 @@ public BlazeCommandRunConfigurationRunner createRunner( AndroidBinaryLaunchMethodsUtils.useMobileInstall(configState.getLaunchMethod()), Label.create(configuration.getSingleTarget().toString()), blazeFlags, - exeFlags); + exeFlags, + launchId); // Create run context for matching launch method. BlazeAndroidRunContext runContext = null; @@ -144,7 +151,7 @@ public BlazeCommandRunConfigurationRunner createRunner( case NON_BLAZE: runContext = new BlazeAndroidBinaryNormalBuildRunContext( - project, facet, configuration, env, configState, buildStep); + project, facet, configuration, env, configState, buildStep, launchId); break; case MOBILE_INSTALL_V2: // Standardize on a single mobile-install launch method @@ -153,25 +160,18 @@ public BlazeCommandRunConfigurationRunner createRunner( case MOBILE_INSTALL: runContext = new BlazeAndroidBinaryMobileInstallRunContext( - project, facet, configuration, env, configState, buildStep); + project, facet, configuration, env, configState, buildStep, launchId); break; default: throw new ExecutionException("No compatible launch methods."); } - EventLoggingService.getInstance() - .logEvent( - BlazeAndroidBinaryRunConfigurationHandler.class, - "BlazeAndroidBinaryRun", - ImmutableMap.of( - "launchMethod", - configState.getLaunchMethod().name(), - "executorId", - env.getExecutor().getId(), - "targetLabel", - configuration.getSingleTarget().toString(), - "nativeDebuggingEnabled", - Boolean.toString(configState.getCommonState().isNativeDebuggingEnabled()))); + logBinaryLaunch( + launchId, + configState.getLaunchMethod().name(), + env.getExecutor().getId(), + configuration.getSingleTarget().toString(), + configState.getCommonState().isNativeDebuggingEnabled()); return new BlazeAndroidRunConfigurationRunner(module, runContext, configuration); } diff --git a/aswb/src/com/google/idea/blaze/android/run/binary/DeploymentTimingReporterTask.java b/aswb/src/com/google/idea/blaze/android/run/binary/DeploymentTimingReporterTask.java new file mode 100644 index 00000000000..74f2cb14835 --- /dev/null +++ b/aswb/src/com/google/idea/blaze/android/run/binary/DeploymentTimingReporterTask.java @@ -0,0 +1,80 @@ +/* + * Copyright 2021 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.android.run.binary; + +import com.android.tools.idea.run.ApkInfo; +import com.android.tools.idea.run.tasks.LaunchContext; +import com.android.tools.idea.run.tasks.LaunchResult; +import com.android.tools.idea.run.tasks.LaunchTask; +import com.google.common.base.Stopwatch; +import com.google.idea.blaze.android.run.LaunchMetrics; +import com.google.wireless.android.sdk.stats.LaunchTaskDetail; +import java.util.Collection; +import org.jetbrains.annotations.TestOnly; + +/** A wrapper launch task that wraps the given deployment task and logs the deployment latency. */ +public class DeploymentTimingReporterTask implements LaunchTask { + private final LaunchTask deployTask; + private final String launchId; + + public DeploymentTimingReporterTask(String launchId, LaunchTask deployTask) { + this.launchId = launchId; + this.deployTask = deployTask; + } + + @Override + public String getDescription() { + return deployTask.getDescription(); + } + + @Override + public int getDuration() { + return deployTask.getDuration(); + } + + @Override + public boolean shouldRun(LaunchContext launchContext) { + return deployTask.shouldRun(launchContext); + } + + @Override + public LaunchResult run(LaunchContext launchContext) { + Stopwatch s = Stopwatch.createStarted(); + LaunchResult launchResult = deployTask.run(launchContext); + LaunchMetrics.logDeploymentTime(launchId, s.elapsed(), launchResult); + return launchResult; + } + + @Override + public String getId() { + return deployTask.getId(); + } + + @Override + public Collection getApkInfos() { + return deployTask.getApkInfos(); + } + + @Override + public Collection getSubTaskDetails() { + return deployTask.getSubTaskDetails(); + } + + @TestOnly + public LaunchTask getWrappedTask() { + return deployTask; + } +} diff --git a/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java b/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java index eff99693c0f..82c54938899 100644 --- a/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java +++ b/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java @@ -38,6 +38,7 @@ import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryApplicationLaunchTaskProvider; import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryConsoleProvider; import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryRunConfigurationState; +import com.google.idea.blaze.android.run.binary.DeploymentTimingReporterTask; import com.google.idea.blaze.android.run.binary.UserIdHelper; import com.google.idea.blaze.android.run.deployinfo.BlazeAndroidDeployInfo; import com.google.idea.blaze.android.run.runner.BlazeAndroidDeviceSelector; @@ -64,6 +65,7 @@ abstract class BlazeAndroidBinaryMobileInstallRunContextBase implements BlazeAnd protected final ConsoleProvider consoleProvider; protected final ApplicationIdProvider applicationIdProvider; protected final BlazeApkBuildStep buildStep; + private final String launchId; public BlazeAndroidBinaryMobileInstallRunContextBase( Project project, @@ -71,7 +73,8 @@ public BlazeAndroidBinaryMobileInstallRunContextBase( RunConfiguration runConfiguration, ExecutionEnvironment env, BlazeAndroidBinaryRunConfigurationState configState, - BlazeApkBuildStep buildStep) { + BlazeApkBuildStep buildStep, + String launchId) { this.project = project; this.facet = facet; this.runConfiguration = runConfiguration; @@ -80,6 +83,7 @@ public BlazeAndroidBinaryMobileInstallRunContextBase( this.consoleProvider = new BlazeAndroidBinaryConsoleProvider(project); this.buildStep = buildStep; this.applicationIdProvider = new BlazeAndroidBinaryApplicationIdProvider(buildStep); + this.launchId = launchId; } @Override @@ -140,7 +144,7 @@ public ImmutableList getDeployTasks(IDevice device, LaunchOptions la LaunchTask deployTask = BlazeAndroidDeploymentService.getInstance(project) .getDeployTask(Collections.singletonList(info), launchOptions); - return ImmutableList.of(deployTask); + return ImmutableList.of(new DeploymentTimingReporterTask(launchId, deployTask)); } @Nullable diff --git a/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeApkBuildStepMobileInstall.java b/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeApkBuildStepMobileInstall.java index 08cf033ad01..029c415fde0 100644 --- a/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeApkBuildStepMobileInstall.java +++ b/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeApkBuildStepMobileInstall.java @@ -15,11 +15,13 @@ */ package com.google.idea.blaze.android.run.binary.mobileinstall; +import static com.google.idea.blaze.android.run.LaunchMetrics.logBuildTime; + import com.android.ddmlib.AndroidDebugBridge; import com.android.ddmlib.IDevice; import com.android.tools.idea.run.ApkProvisionException; import com.android.tools.idea.run.DeviceFutures; -import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Stopwatch; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.util.concurrent.Futures; @@ -65,6 +67,7 @@ import java.util.NoSuchElementException; import java.util.concurrent.CancellationException; import javax.annotation.Nullable; +import org.jetbrains.annotations.TestOnly; /** Builds and installs the APK using mobile-install. */ public class BlazeApkBuildStepMobileInstall implements BlazeApkBuildStep { @@ -77,6 +80,7 @@ public class BlazeApkBuildStepMobileInstall implements BlazeApkBuildStep { private final ImmutableList blazeFlags; private final ImmutableList exeFlags; private final BlazeApkDeployInfoProtoHelper deployInfoHelper; + private final String launchId; private BlazeAndroidDeployInfo deployInfo = null; /** @@ -88,26 +92,38 @@ public static String getDeployInfoSuffix(BuildSystem buildSystem) { return buildSystem == BuildSystem.Bazel ? "_incremental.deployinfo.pb" : "_mi.deployinfo.pb"; } - @VisibleForTesting - public BlazeApkBuildStepMobileInstall( + private BlazeApkBuildStepMobileInstall( Project project, Label label, ImmutableList blazeFlags, ImmutableList exeFlags, - BlazeApkDeployInfoProtoHelper deployInfoHelper) { + BlazeApkDeployInfoProtoHelper deployInfoHelper, + String launchId) { this.project = project; this.label = label; this.blazeFlags = blazeFlags; this.exeFlags = exeFlags; this.deployInfoHelper = deployInfoHelper; + this.launchId = launchId; + } + + public BlazeApkBuildStepMobileInstall( + Project project, + Label label, + ImmutableList blazeFlags, + ImmutableList exeFlags, + String launchId) { + this(project, label, blazeFlags, exeFlags, new BlazeApkDeployInfoProtoHelper(), launchId); } + @TestOnly public BlazeApkBuildStepMobileInstall( Project project, Label label, ImmutableList blazeFlags, - ImmutableList exeFlags) { - this(project, label, blazeFlags, exeFlags, new BlazeApkDeployInfoProtoHelper()); + ImmutableList exeFlags, + BlazeApkDeployInfoProtoHelper deployInfoHelper) { + this(project, label, blazeFlags, exeFlags, deployInfoHelper, ""); } @Override @@ -189,7 +205,7 @@ public void build(BlazeContext context, BlazeAndroidDeviceSelector.DeviceSession SaveUtil.saveAllFiles(); context.output(new StatusOutput("Invoking mobile-install...")); - int retVal = + ExternalTask task = ExternalTask.builder(workspaceRoot) .addBlazeCommand(command.build()) .context(context) @@ -197,17 +213,21 @@ public void build(BlazeContext context, BlazeAndroidDeviceSelector.DeviceSession .stderr( LineProcessingOutputStream.of( BlazeConsoleLineProcessorProvider.getAllStderrLineProcessors(context))) - .build() - .run(); - ListenableFuture unusedFuture = - FileCaches.refresh( - project, context, BlazeBuildOutputs.noOutputs(BuildResult.fromExitCode(retVal))); + .build(); - if (retVal != 0) { + Stopwatch s = Stopwatch.createStarted(); + int exitCode = task.run(); + logBuildTime(launchId, StudioDeployerExperiment.isEnabled(), s.elapsed(), exitCode); + + if (exitCode != 0) { IssueOutput.error("Blaze build failed. See Blaze Console for details.").submit(context); return; } + ListenableFuture unusedFuture = + FileCaches.refresh( + project, context, BlazeBuildOutputs.noOutputs(BuildResult.fromExitCode(exitCode))); + context.output(new StatusOutput("Reading deployment information...")); String executionRoot = ExecRootUtil.getExecutionRoot(buildResultHelper, project, blazeFlags, context); diff --git a/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunConfigurationHandler.java b/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunConfigurationHandler.java index 72d3f744b28..755eedeb5ab 100644 --- a/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunConfigurationHandler.java +++ b/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunConfigurationHandler.java @@ -19,17 +19,16 @@ import com.android.tools.idea.run.ValidationError; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.idea.blaze.android.run.BlazeAndroidRunConfigurationCommonState; import com.google.idea.blaze.android.run.BlazeAndroidRunConfigurationHandler; import com.google.idea.blaze.android.run.BlazeAndroidRunConfigurationValidationUtil; +import com.google.idea.blaze.android.run.LaunchMetrics; import com.google.idea.blaze.android.run.runner.BlazeAndroidRunConfigurationRunner; import com.google.idea.blaze.android.run.runner.BlazeAndroidRunContext; import com.google.idea.blaze.android.run.test.BlazeAndroidTestLaunchMethodsProvider.AndroidTestLaunchMethod; import com.google.idea.blaze.base.command.BlazeCommandName; import com.google.idea.blaze.base.command.BlazeInvocationContext; -import com.google.idea.blaze.base.logging.EventLoggingService; import com.google.idea.blaze.base.model.primitives.Label; import com.google.idea.blaze.base.model.primitives.TargetExpression; import com.google.idea.blaze.base.projectview.ProjectViewManager; @@ -105,6 +104,11 @@ public BlazeCommandRunConfigurationRunner createRunner( ImmutableList exeFlags = ImmutableList.copyOf( configState.getCommonState().getExeFlagsState().getFlagsForExternalProcesses()); + + // We collect metrics from a few different locations. In order to tie them all + // together, we create a unique launch id. + String launchId = LaunchMetrics.newLaunchId(); + BlazeAndroidRunContext runContext = new BlazeAndroidTestRunContext( project, @@ -114,22 +118,13 @@ public BlazeCommandRunConfigurationRunner createRunner( configState, Label.create(configuration.getSingleTarget().toString()), blazeFlags, - exeFlags); - - EventLoggingService.getInstance() - .logEvent( - BlazeAndroidTestRunConfigurationHandler.class, - "BlazeAndroidTestRun", - ImmutableMap.of( - "launchMethod", - configState.getLaunchMethod().name(), - "executorId", - env.getExecutor().getId())); - - return new BlazeAndroidRunConfigurationRunner( - module, - runContext, - configuration); + exeFlags, + launchId); + + LaunchMetrics.logTestLaunch( + launchId, configState.getLaunchMethod().name(), env.getExecutor().getId()); + + return new BlazeAndroidRunConfigurationRunner(module, runContext, configuration); } @Override diff --git a/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContextBase.java b/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContextBase.java index ad29ceafcce..54a27c50807 100644 --- a/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContextBase.java +++ b/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContextBase.java @@ -76,7 +76,8 @@ abstract class BlazeAndroidTestRunContextBase implements BlazeAndroidRunContext BlazeAndroidTestRunConfigurationState configState, Label label, ImmutableList blazeFlags, - ImmutableList exeFlags) { + ImmutableList exeFlags, + String launchId) { this.project = project; this.facet = facet; this.runConfiguration = runConfiguration; @@ -85,7 +86,8 @@ abstract class BlazeAndroidTestRunContextBase implements BlazeAndroidRunContext this.configState = configState; if (configState.getLaunchMethod().equals(AndroidTestLaunchMethod.MOBILE_INSTALL)) { - this.buildStep = new BlazeApkBuildStepMobileInstall(project, label, blazeFlags, exeFlags); + this.buildStep = + new BlazeApkBuildStepMobileInstall(project, label, blazeFlags, exeFlags, launchId); } else if (runConfiguration.getTargetKind() == AndroidBlazeRules.RuleTypes.ANDROID_INSTRUMENTATION_TEST.getKind()) { // android_instrumentation_test builds both test and app target APKs. From 2808f6387e5098444aee46c234af35f4eb811967 Mon Sep 17 00:00:00 2001 From: Googler Date: Mon, 8 Nov 2021 19:22:30 -0800 Subject: [PATCH 30/47] Workaround exceptions thrown during retrieving artifacts from cache PiperOrigin-RevId: 408499179 --- .../android/filecache/LocalArtifactCache.java | 17 ++++++++++++++++- .../projectsystem/RenderJarClassFileFinder.java | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/aswb/src/com/google/idea/blaze/android/filecache/LocalArtifactCache.java b/aswb/src/com/google/idea/blaze/android/filecache/LocalArtifactCache.java index c0f1ea50c01..65e36fd66ff 100644 --- a/aswb/src/com/google/idea/blaze/android/filecache/LocalArtifactCache.java +++ b/aswb/src/com/google/idea/blaze/android/filecache/LocalArtifactCache.java @@ -246,9 +246,24 @@ public synchronized void putAll( @Override @Nullable public synchronized Path get(OutputArtifact artifact) { + try { + return unsafeGet(artifact); + } catch (RuntimeException e) { + // b/201702401: Under certain conditions, LocalFileOutputArtifact.toArtifactState throws + // an IllegalArgumentException when it can't locate the artifact on objfsd. It is unclear what + // leads to this as we haven't been able to reproduce it. However, the #get method is not + // supposed to ever crash, so we just log a warning if we ever run into an exception. + String msg = + "Unexpected exception retrieving cached path for artifact: " + artifact.getRelativePath(); + Logger.getInstance(LocalArtifactCache.class).warn(msg, e); + return null; + } + } + + @Nullable + private Path unsafeGet(OutputArtifact artifact) { CacheEntry queriedEntry = CacheEntry.forArtifact(artifact); String cacheKey = queriedEntry.getCacheKey(); - CacheEntry cacheEntry = cacheState.get(cacheKey); if (cacheEntry == null) { return null; diff --git a/aswb/src/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java b/aswb/src/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java index 01349317681..f24ca661c71 100644 --- a/aswb/src/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java +++ b/aswb/src/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java @@ -65,7 +65,7 @@ public class RenderJarClassFileFinder implements ClassFileFinder { /** Experiment to control whether class file finding from render jars should be enabled. */ private static final BoolExperiment enabled = - new BoolExperiment("aswb.renderjar.cff.enabled.1", true); + new BoolExperiment("aswb.renderjar.cff.enabled.2", true); /** * Experiment to toggle whether resource resolution is allowed from Render JARs. Render JARs From ec1cd2e286ab96e8f423d2c1f9c8a58bcd6aa21e Mon Sep 17 00:00:00 2001 From: Janak Ramakrishnan Date: Tue, 9 Nov 2021 03:13:56 -0500 Subject: [PATCH 31/47] Two nit-picks in README.md (#2943) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1fa18bcc5d3..d25e834679c 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ We welcome contributions to support new IDE versions. However, to make the review process faster and easier, we recommend the following: * We can only accept small pull requests. Smaller pull requests tend to have - less review comments and hence can get submitted much faster. They also tend + fewer review comments and hence can get submitted much faster. They also tend to conflict less with our internal code base, simplifying the integration for us. For example, you should have separate pull requests each focusing on a certain incompatible change rather than having a large pull request fixing multiple ones. @@ -140,7 +140,7 @@ We may also be able to accept contributions to fix general issues or adding new * Improvements for old not supported IDE versions will not be accepted. Your changes should target the currently supported IDE versions. You can find a list of these versions [here](./intellij_platform_sdk/build_defs.bzl#L31). - * We can't accept sylistic, refactoring, or "cleanup" changes. + * We can't accept stylistic, refactoring, or "cleanup" changes. * We have very limited bandwidth, and applying patches upstream is a time-consuming process. Large patches generally can't be accepted unless there's clear value for all our users. From 5adbf0d382989f3d0db0c5ce5b6c6b6a895667ae Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 9 Nov 2021 02:33:52 -0800 Subject: [PATCH 32/47] Update changelogs for 2021.11.09 release PiperOrigin-RevId: 408559342 --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 87d12b5c20e..f9548982c37 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -v2021.11.02 +v2021.11.09 =========== * Bug fixes and internal cleanup. From 96aefc06dc4ae12611d9f82485aa6bf84ea7ca38 Mon Sep 17 00:00:00 2001 From: Ivo List Date: Tue, 9 Nov 2021 07:42:15 -0800 Subject: [PATCH 33/47] Upgrade scala version to support latest Bazel [Imports https://github.com/bazelbuild/intellij/pull/3052] Fixes Downstream builds: https://buildkite.com/bazel/bazel-at-head-plus-downstream/builds/2241#708a7870-2e5a-4e59-bdf7-da99206e3fde Closes #3052 COPYBARA_INTEGRATE_REVIEW=https://github.com/bazelbuild/intellij/pull/3052 from comius:upgrade-scala ada398be2ed301f1a45a65a98f55c270d33e397e PiperOrigin-RevId: 408607439 --- WORKSPACE | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 2087b5730ec..90ed53276d2 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -433,12 +433,15 @@ rules_proto_toolchains() # LICENSE: The Apache Software License, Version 2.0 http_archive( name = "io_bazel_rules_scala", - sha256 = "b8b18d0fe3f6c3401b4f83f78f536b24c7fb8b92c593c1dcbcd01cc2b3e85c9a", - strip_prefix = "rules_scala-a676633dc14d8239569affb2acafbef255df3480", - type = "zip", - url = "https://github.com/bazelbuild/rules_scala/archive/a676633dc14d8239569affb2acafbef255df3480.zip", + sha256 = "ccf19e8f966022eaaca64da559c6140b23409829cb315f2eff5dc3e757fb6ad8", + strip_prefix = "rules_scala-e4560ac332e9da731c1e50a76af2579c55836a5c", + urls = ["https://github.com/bazelbuild/rules_scala/archive/e4560ac332e9da731c1e50a76af2579c55836a5c.zip"], ) +load("@io_bazel_rules_scala//:scala_config.bzl", "scala_config") + +scala_config() + load("@io_bazel_rules_scala//scala:scala.bzl", "scala_repositories") scala_repositories() @@ -447,6 +450,11 @@ load("@io_bazel_rules_scala//scala:toolchains.bzl", "scala_register_toolchains") scala_register_toolchains() +load("@io_bazel_rules_scala//testing:scalatest.bzl", "scalatest_repositories", "scalatest_toolchain") + +scalatest_repositories() +scalatest_toolchain() + # LICENSE: The Apache Software License, Version 2.0 rules_kotlin_version = "v1.5.0-beta-3" rules_kotlin_sha = "58edd86f0f3c5b959c54e656b8e7eb0b0becabd412465c37a2078693c2571f7f" From c101e9786fe30ea2eb787ce3ed848fe06fc187d4 Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 9 Nov 2021 08:32:06 -0800 Subject: [PATCH 34/47] Internal change. PiperOrigin-RevId: 408617712 --- sdkcompat/v203/BUILD | 1 + .../idea/sdkcompat/general/BaseSdkCompat.java | 24 ------- .../indexing/IndexingTimesWrapper.java | 38 +++++++++++ ...ProjectIndexingHistoryListenerAdapter.java | 6 ++ sdkcompat/v211/BUILD | 1 + .../idea/sdkcompat/general/BaseSdkCompat.java | 17 ----- .../indexing/IndexingTimesWrapper.java | 33 +++++++++ ...ProjectIndexingHistoryListenerAdapter.java | 6 ++ sdkcompat/v212/BUILD | 1 + .../idea/sdkcompat/general/BaseSdkCompat.java | 17 ----- .../indexing/IndexingTimesWrapper.java | 33 +++++++++ ...ProjectIndexingHistoryListenerAdapter.java | 6 ++ sdkcompat/v213/BUILD | 1 + .../idea/sdkcompat/general/BaseSdkCompat.java | 17 ----- .../indexing/IndexingTimesWrapper.java | 33 +++++++++ ...ProjectIndexingHistoryListenerAdapter.java | 6 ++ .../idea/sdkcompat/BaseSdkTestCompat.java | 42 ------------ .../ProjectIndexingHistoryWrapper.java | 67 +++++++++++++++++++ .../idea/sdkcompat/BaseSdkTestCompat.java | 32 --------- .../ProjectIndexingHistoryWrapper.java | 58 ++++++++++++++++ .../idea/sdkcompat/BaseSdkTestCompat.java | 32 --------- .../ProjectIndexingHistoryWrapper.java | 59 ++++++++++++++++ .../idea/sdkcompat/BaseSdkTestCompat.java | 32 --------- .../ProjectIndexingHistoryWrapper.java | 58 ++++++++++++++++ 24 files changed, 407 insertions(+), 213 deletions(-) create mode 100644 sdkcompat/v203/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java create mode 100644 sdkcompat/v203/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java create mode 100644 sdkcompat/v211/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java create mode 100644 sdkcompat/v211/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java create mode 100644 sdkcompat/v212/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java create mode 100644 sdkcompat/v212/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java create mode 100644 sdkcompat/v213/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java create mode 100644 sdkcompat/v213/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java create mode 100644 testing/testcompat/v203/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java create mode 100644 testing/testcompat/v211/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java create mode 100644 testing/testcompat/v212/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java create mode 100644 testing/testcompat/v213/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java diff --git a/sdkcompat/v203/BUILD b/sdkcompat/v203/BUILD index 5494db8c681..283eedef4c0 100644 --- a/sdkcompat/v203/BUILD +++ b/sdkcompat/v203/BUILD @@ -8,6 +8,7 @@ java_library( name = "v203", srcs = glob([ "com/google/idea/sdkcompat/general/**", + "com/google/idea/sdkcompat/indexing/**", "com/google/idea/sdkcompat/platform/**", "com/google/idea/sdkcompat/python/**", "com/google/idea/sdkcompat/vcs/**", diff --git a/sdkcompat/v203/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v203/com/google/idea/sdkcompat/general/BaseSdkCompat.java index 7aa16996c55..f6a641bb6a6 100644 --- a/sdkcompat/v203/com/google/idea/sdkcompat/general/BaseSdkCompat.java +++ b/sdkcompat/v203/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -14,9 +14,7 @@ import com.intellij.usageView.UsageTreeColors; import com.intellij.usageView.UsageTreeColorsScheme; import com.intellij.usages.TextChunk; -import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory.IndexingTimes; import java.nio.file.Path; -import java.time.Duration; import java.util.List; import java.util.stream.Stream; import javax.annotation.Nullable; @@ -56,28 +54,6 @@ public static void activateIconManager() { IconManager.activate(); } - /** #api203: inline this method into IndexingLogger */ - public static Duration getTotalUpdatingTime(IndexingTimes times) { - if (times.getTotalEnd() == null || times.getTotalStart() == null) { - return Duration.ZERO; - } - return Duration.between(times.getTotalStart(), times.getTotalEnd()); - } - /** #api203: inline this method into IndexingLogger */ - public static Duration getScanFilesDuration(IndexingTimes times) { - if (times.getScanFilesEnd() == null || times.getScanFilesStart() == null) { - return Duration.ZERO; - } - return Duration.between(times.getScanFilesStart(), times.getScanFilesEnd()); - } - /** #api203: inline this method into IndexingLogger */ - public static Duration getTotalIndexingTime(IndexingTimes times) { - if (times.getIndexingDuration() == null) { - return Duration.ZERO; - } - return times.getIndexingDuration(); - } - /** * See {@link ModifiableRootModel#addLibraryEntry(Library)}. * diff --git a/sdkcompat/v203/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java b/sdkcompat/v203/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java new file mode 100644 index 00000000000..d1eeef34737 --- /dev/null +++ b/sdkcompat/v203/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java @@ -0,0 +1,38 @@ +package com.google.idea.sdkcompat.indexing; + +import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory.IndexingTimes; +import java.time.Duration; + +/** #api212: inline into IndexingLogger */ +public class IndexingTimesWrapper { + + private final IndexingTimes indexingTimes; + + public IndexingTimesWrapper(IndexingTimes indexingTimes) { + this.indexingTimes = indexingTimes; + } + + /** #api203: inline this method into IndexingLogger */ + public Duration getTotalUpdatingTime() { + if (indexingTimes.getTotalEnd() == null || indexingTimes.getTotalStart() == null) { + return Duration.ZERO; + } + return Duration.between(indexingTimes.getTotalStart(), indexingTimes.getTotalEnd()); + } + + /** #api203: inline this method into IndexingLogger */ + public Duration getScanFilesDuration() { + if (indexingTimes.getScanFilesEnd() == null || indexingTimes.getScanFilesStart() == null) { + return Duration.ZERO; + } + return Duration.between(indexingTimes.getScanFilesStart(), indexingTimes.getScanFilesEnd()); + } + + /** #api203: inline this method into IndexingLogger */ + public Duration getTotalIndexingTime() { + if (indexingTimes.getIndexingDuration() == null) { + return Duration.ZERO; + } + return indexingTimes.getIndexingDuration(); + } +} diff --git a/sdkcompat/v203/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java b/sdkcompat/v203/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java new file mode 100644 index 00000000000..11af781296d --- /dev/null +++ b/sdkcompat/v203/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java @@ -0,0 +1,6 @@ +package com.google.idea.sdkcompat.indexing; + +import com.intellij.util.indexing.diagnostic.IndexDiagnosticDumper.ProjectIndexingHistoryListener; + +/** #api212: inline into IndexingLogger */ +public interface ProjectIndexingHistoryListenerAdapter extends ProjectIndexingHistoryListener {} diff --git a/sdkcompat/v211/BUILD b/sdkcompat/v211/BUILD index 9baf6951ba4..0a49f8482f2 100644 --- a/sdkcompat/v211/BUILD +++ b/sdkcompat/v211/BUILD @@ -8,6 +8,7 @@ java_library( name = "v211", srcs = glob([ "com/google/idea/sdkcompat/general/**", + "com/google/idea/sdkcompat/indexing/**", "com/google/idea/sdkcompat/platform/**", "com/google/idea/sdkcompat/python/**", "com/google/idea/sdkcompat/vcs/**", diff --git a/sdkcompat/v211/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v211/com/google/idea/sdkcompat/general/BaseSdkCompat.java index 100fb0fc7e6..944e56f47be 100644 --- a/sdkcompat/v211/com/google/idea/sdkcompat/general/BaseSdkCompat.java +++ b/sdkcompat/v211/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -12,9 +12,7 @@ import com.intellij.ui.IconManager; import com.intellij.usageView.UsageTreeColors; import com.intellij.usages.TextChunk; -import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory.IndexingTimes; import java.nio.file.Path; -import java.time.Duration; import java.util.List; import javax.annotation.Nullable; @@ -50,21 +48,6 @@ public static void activateIconManager() { IconManager.activate(); } - /** #api203: inline this method into IndexingLogger */ - public static Duration getTotalUpdatingTime(IndexingTimes times) { - return Duration.ofNanos(times.getTotalUpdatingTime()); - } - - /** #api203: inline this method into IndexingLogger */ - public static Duration getScanFilesDuration(IndexingTimes times) { - return times.getScanFilesDuration(); - } - - /** #api203: inline this method into IndexingLogger */ - public static Duration getTotalIndexingTime(IndexingTimes times) { - return times.getIndexingDuration(); - } - /** * See {@link ModifiableRootModel#addLibraryEntry(Library)}. * diff --git a/sdkcompat/v211/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java b/sdkcompat/v211/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java new file mode 100644 index 00000000000..8fe26e937ab --- /dev/null +++ b/sdkcompat/v211/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java @@ -0,0 +1,33 @@ +package com.google.idea.sdkcompat.indexing; + +import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory.IndexingTimes; +import java.time.Duration; + +/** #api212: inline into IndexingLogger */ +public class IndexingTimesWrapper { + + private final IndexingTimes indexingTimes; + + public IndexingTimesWrapper(IndexingTimes indexingTimes) { + this.indexingTimes = indexingTimes; + } + + public IndexingTimes getTimes() { + return indexingTimes; + } + + /** #api203: inline this method into IndexingLogger */ + public Duration getTotalUpdatingTime() { + return Duration.ofNanos(getTimes().getTotalUpdatingTime()); + } + + /** #api203: inline this method into IndexingLogger */ + public Duration getScanFilesDuration() { + return getTimes().getScanFilesDuration(); + } + + /** #api203: inline this method into IndexingLogger */ + public Duration getTotalIndexingTime() { + return getTimes().getIndexingDuration(); + } +} diff --git a/sdkcompat/v211/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java b/sdkcompat/v211/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java new file mode 100644 index 00000000000..11af781296d --- /dev/null +++ b/sdkcompat/v211/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java @@ -0,0 +1,6 @@ +package com.google.idea.sdkcompat.indexing; + +import com.intellij.util.indexing.diagnostic.IndexDiagnosticDumper.ProjectIndexingHistoryListener; + +/** #api212: inline into IndexingLogger */ +public interface ProjectIndexingHistoryListenerAdapter extends ProjectIndexingHistoryListener {} diff --git a/sdkcompat/v212/BUILD b/sdkcompat/v212/BUILD index 0998aaa7ddc..fb829ae4700 100644 --- a/sdkcompat/v212/BUILD +++ b/sdkcompat/v212/BUILD @@ -8,6 +8,7 @@ java_library( name = "v212", srcs = glob([ "com/google/idea/sdkcompat/general/**", + "com/google/idea/sdkcompat/indexing/**", "com/google/idea/sdkcompat/platform/**", "com/google/idea/sdkcompat/python/**", "com/google/idea/sdkcompat/vcs/**", diff --git a/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java index e3b4fd3d701..3e987db53fd 100644 --- a/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java +++ b/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -14,9 +14,7 @@ import com.intellij.ui.IconManager; import com.intellij.usageView.UsageTreeColors; import com.intellij.usages.TextChunk; -import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory.IndexingTimes; import java.nio.file.Path; -import java.time.Duration; import java.util.List; import javax.annotation.Nullable; @@ -52,21 +50,6 @@ public static void activateIconManager() throws Throwable { IconManager.activate(new CoreIconManager()); } - /** #api203: inline this method into IndexingLogger */ - public static Duration getTotalUpdatingTime(IndexingTimes times) { - return Duration.ofNanos(times.getTotalUpdatingTime()); - } - - /** #api203: inline this method into IndexingLogger */ - public static Duration getScanFilesDuration(IndexingTimes times) { - return times.getScanFilesDuration(); - } - - /** #api203: inline this method into IndexingLogger */ - public static Duration getTotalIndexingTime(IndexingTimes times) { - return times.getIndexingDuration(); - } - /** * See {@link ModifiableRootModel#addLibraryEntries(List, DependencyScope, boolean)}. * diff --git a/sdkcompat/v212/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java b/sdkcompat/v212/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java new file mode 100644 index 00000000000..8fe26e937ab --- /dev/null +++ b/sdkcompat/v212/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java @@ -0,0 +1,33 @@ +package com.google.idea.sdkcompat.indexing; + +import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory.IndexingTimes; +import java.time.Duration; + +/** #api212: inline into IndexingLogger */ +public class IndexingTimesWrapper { + + private final IndexingTimes indexingTimes; + + public IndexingTimesWrapper(IndexingTimes indexingTimes) { + this.indexingTimes = indexingTimes; + } + + public IndexingTimes getTimes() { + return indexingTimes; + } + + /** #api203: inline this method into IndexingLogger */ + public Duration getTotalUpdatingTime() { + return Duration.ofNanos(getTimes().getTotalUpdatingTime()); + } + + /** #api203: inline this method into IndexingLogger */ + public Duration getScanFilesDuration() { + return getTimes().getScanFilesDuration(); + } + + /** #api203: inline this method into IndexingLogger */ + public Duration getTotalIndexingTime() { + return getTimes().getIndexingDuration(); + } +} diff --git a/sdkcompat/v212/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java b/sdkcompat/v212/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java new file mode 100644 index 00000000000..11af781296d --- /dev/null +++ b/sdkcompat/v212/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java @@ -0,0 +1,6 @@ +package com.google.idea.sdkcompat.indexing; + +import com.intellij.util.indexing.diagnostic.IndexDiagnosticDumper.ProjectIndexingHistoryListener; + +/** #api212: inline into IndexingLogger */ +public interface ProjectIndexingHistoryListenerAdapter extends ProjectIndexingHistoryListener {} diff --git a/sdkcompat/v213/BUILD b/sdkcompat/v213/BUILD index f650a017e89..b2ab5bb1270 100644 --- a/sdkcompat/v213/BUILD +++ b/sdkcompat/v213/BUILD @@ -8,6 +8,7 @@ java_library( name = "v213", srcs = glob([ "com/google/idea/sdkcompat/general/**", + "com/google/idea/sdkcompat/indexing/**", "com/google/idea/sdkcompat/platform/**", "com/google/idea/sdkcompat/python/**", "com/google/idea/sdkcompat/vcs/**", diff --git a/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java index e3b4fd3d701..3e987db53fd 100644 --- a/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java +++ b/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -14,9 +14,7 @@ import com.intellij.ui.IconManager; import com.intellij.usageView.UsageTreeColors; import com.intellij.usages.TextChunk; -import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory.IndexingTimes; import java.nio.file.Path; -import java.time.Duration; import java.util.List; import javax.annotation.Nullable; @@ -52,21 +50,6 @@ public static void activateIconManager() throws Throwable { IconManager.activate(new CoreIconManager()); } - /** #api203: inline this method into IndexingLogger */ - public static Duration getTotalUpdatingTime(IndexingTimes times) { - return Duration.ofNanos(times.getTotalUpdatingTime()); - } - - /** #api203: inline this method into IndexingLogger */ - public static Duration getScanFilesDuration(IndexingTimes times) { - return times.getScanFilesDuration(); - } - - /** #api203: inline this method into IndexingLogger */ - public static Duration getTotalIndexingTime(IndexingTimes times) { - return times.getIndexingDuration(); - } - /** * See {@link ModifiableRootModel#addLibraryEntries(List, DependencyScope, boolean)}. * diff --git a/sdkcompat/v213/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java b/sdkcompat/v213/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java new file mode 100644 index 00000000000..98c6b5655ef --- /dev/null +++ b/sdkcompat/v213/com/google/idea/sdkcompat/indexing/IndexingTimesWrapper.java @@ -0,0 +1,33 @@ +package com.google.idea.sdkcompat.indexing; + +import com.intellij.util.indexing.diagnostic.IndexingTimes; +import java.time.Duration; + +/** #api212: inline into IndexingLogger */ +public class IndexingTimesWrapper { + + private final IndexingTimes indexingTimes; + + public IndexingTimesWrapper(IndexingTimes indexingTimes) { + this.indexingTimes = indexingTimes; + } + + public IndexingTimes getTimes() { + return indexingTimes; + } + + /** #api203: inline this method into IndexingLogger */ + public Duration getTotalUpdatingTime() { + return Duration.ofNanos(getTimes().getTotalUpdatingTime()); + } + + /** #api203: inline this method into IndexingLogger */ + public Duration getScanFilesDuration() { + return getTimes().getScanFilesDuration(); + } + + /** #api203: inline this method into IndexingLogger */ + public Duration getTotalIndexingTime() { + return getTimes().getIndexingDuration(); + } +} diff --git a/sdkcompat/v213/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java b/sdkcompat/v213/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java new file mode 100644 index 00000000000..4bff7bf257d --- /dev/null +++ b/sdkcompat/v213/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryListenerAdapter.java @@ -0,0 +1,6 @@ +package com.google.idea.sdkcompat.indexing; + +import com.intellij.util.indexing.diagnostic.ProjectIndexingHistoryListener; + +/** #api212: inline into IndexingLogger */ +public interface ProjectIndexingHistoryListenerAdapter extends ProjectIndexingHistoryListener {} diff --git a/testing/testcompat/v203/com/google/idea/sdkcompat/BaseSdkTestCompat.java b/testing/testcompat/v203/com/google/idea/sdkcompat/BaseSdkTestCompat.java index 64c334d5232..ef8fd093dcb 100644 --- a/testing/testcompat/v203/com/google/idea/sdkcompat/BaseSdkTestCompat.java +++ b/testing/testcompat/v203/com/google/idea/sdkcompat/BaseSdkTestCompat.java @@ -15,52 +15,10 @@ */ package com.google.idea.sdkcompat; -import com.intellij.openapi.project.Project; -import com.intellij.util.indexing.diagnostic.IndexingJobStatistics; -import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory; -import java.time.Duration; -import java.time.Instant; - /** * Provides SDK compatibility shims for base plugin API classes, available to all IDEs during * test-time. */ public final class BaseSdkTestCompat { private BaseSdkTestCompat() {} - - /** - * #api203: Doing duration calculations is not necessary anymore. Inline into IndexingLoggerTest. - */ - @SuppressWarnings("UnstableApiUsage") - public static void setIndexingTimes( - ProjectIndexingHistory.IndexingTimes projectIndexingHistory, - Duration expectedIndexingDuration, - Duration expectedUpdatingDuration, - Duration expectedScanFilesDuration) { - - Instant indexingStart = Instant.ofEpochMilli(1627913529); - projectIndexingHistory.setIndexingEnd(indexingStart.plus(expectedIndexingDuration)); - projectIndexingHistory.setIndexingStart(indexingStart); - - Instant totalStart = Instant.ofEpochMilli(1627913533); - projectIndexingHistory.setTotalEnd(totalStart.plus(expectedUpdatingDuration)); - projectIndexingHistory.setTotalStart(totalStart); - - Instant scanFilesEnd = Instant.ofEpochMilli(1327913533); - projectIndexingHistory.setScanFilesEnd(scanFilesEnd.plus(expectedScanFilesDuration)); - projectIndexingHistory.setScanFilesStart(scanFilesEnd); - } - - /** #api203: inline into IndexingLoggerTest */ - @SuppressWarnings("UnstableApiUsage") - public static void setIndexingVisibleTime( - IndexingJobStatistics indexingStatistic, Duration expectedIndexingVisibleTime) { - indexingStatistic.setTotalIndexingTime(expectedIndexingVisibleTime.toNanos()); - } - - /** #api211 inline into IndexingLoggerTest */ - @SuppressWarnings("UnstableApiUsage") - public static ProjectIndexingHistory initializeProjectIndexingHistory(Project project) { - return new ProjectIndexingHistory(project); - } } diff --git a/testing/testcompat/v203/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java b/testing/testcompat/v203/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java new file mode 100644 index 00000000000..3aba893929e --- /dev/null +++ b/testing/testcompat/v203/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java @@ -0,0 +1,67 @@ +/* + * Copyright 2021 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.sdkcompat.indexing; + +import com.intellij.openapi.project.Project; +import com.intellij.util.indexing.diagnostic.IndexingJobStatistics; +import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory; +import java.time.Duration; +import java.time.Instant; + +/** #api212: inline into IndexingLoggerTest */ +public class ProjectIndexingHistoryWrapper { + private final ProjectIndexingHistory projectIndexingHistory; + + private ProjectIndexingHistoryWrapper(ProjectIndexingHistory projectIndexingHistory) { + this.projectIndexingHistory = projectIndexingHistory; + } + + public static ProjectIndexingHistoryWrapper create(Project project) { + return new ProjectIndexingHistoryWrapper(new ProjectIndexingHistory(project)); + } + + public ProjectIndexingHistory getProjectIndexingHistory() { + return projectIndexingHistory; + } + + /** #api203: inline into IndexingLoggerTest */ + @SuppressWarnings("UnstableApiUsage") + public static void setIndexingVisibleTime( + IndexingJobStatistics indexingStatistic, Duration expectedIndexingVisibleTime) { + indexingStatistic.setTotalIndexingTime(expectedIndexingVisibleTime.toNanos()); + } + + public void addProviderStatistics(IndexingJobStatistics statistics) { + projectIndexingHistory.addProviderStatistics(statistics); + } + + public void setIndexingTimes( + Duration expectedIndexingDuration, + Duration expectedUpdatingDuration, + Duration expectedScanFilesDuration) { + Instant indexingStart = Instant.ofEpochMilli(1627913529); + projectIndexingHistory.getTimes().setIndexingEnd(indexingStart.plus(expectedIndexingDuration)); + projectIndexingHistory.getTimes().setIndexingStart(indexingStart); + + Instant totalStart = Instant.ofEpochMilli(1627913533); + projectIndexingHistory.getTimes().setTotalEnd(totalStart.plus(expectedUpdatingDuration)); + projectIndexingHistory.getTimes().setTotalStart(totalStart); + + Instant scanFilesEnd = Instant.ofEpochMilli(1327913533); + projectIndexingHistory.getTimes().setScanFilesEnd(scanFilesEnd.plus(expectedScanFilesDuration)); + projectIndexingHistory.getTimes().setScanFilesStart(scanFilesEnd); + } +} diff --git a/testing/testcompat/v211/com/google/idea/sdkcompat/BaseSdkTestCompat.java b/testing/testcompat/v211/com/google/idea/sdkcompat/BaseSdkTestCompat.java index 8375d0e7614..ef8fd093dcb 100644 --- a/testing/testcompat/v211/com/google/idea/sdkcompat/BaseSdkTestCompat.java +++ b/testing/testcompat/v211/com/google/idea/sdkcompat/BaseSdkTestCompat.java @@ -15,42 +15,10 @@ */ package com.google.idea.sdkcompat; -import com.intellij.openapi.project.Project; -import com.intellij.util.indexing.diagnostic.IndexingJobStatistics; -import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory; -import java.time.Duration; - /** * Provides SDK compatibility shims for base plugin API classes, available to all IDEs during * test-time. */ public final class BaseSdkTestCompat { private BaseSdkTestCompat() {} - - /** - * #api203: Doing duration calculations is not necessary anymore. Inline into IndexingLoggerTest. - */ - @SuppressWarnings("UnstableApiUsage") - public static void setIndexingTimes( - ProjectIndexingHistory.IndexingTimes projectIndexingHistory, - Duration expectedIndexingDuration, - Duration expectedUpdatingDuration, - Duration expectedScanFilesDuration) { - projectIndexingHistory.setIndexingDuration(expectedIndexingDuration); - projectIndexingHistory.setTotalUpdatingTime(expectedUpdatingDuration.toNanos()); - projectIndexingHistory.setScanFilesDuration(expectedScanFilesDuration); - } - - /** #api203: inline into IndexingLoggerTest */ - @SuppressWarnings("UnstableApiUsage") - public static void setIndexingVisibleTime( - IndexingJobStatistics indexingStatistic, Duration expectedIndexingVisibleTime) { - indexingStatistic.setIndexingVisibleTime(expectedIndexingVisibleTime.toNanos()); - } - - /** #api211 inline into IndexingLoggerTest */ - @SuppressWarnings("UnstableApiUsage") - public static ProjectIndexingHistory initializeProjectIndexingHistory(Project project) { - return new ProjectIndexingHistory(project); - } } diff --git a/testing/testcompat/v211/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java b/testing/testcompat/v211/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java new file mode 100644 index 00000000000..aa3d1b5e60e --- /dev/null +++ b/testing/testcompat/v211/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java @@ -0,0 +1,58 @@ +/* + * Copyright 2021 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.sdkcompat.indexing; + +import com.intellij.openapi.project.Project; +import com.intellij.util.indexing.diagnostic.IndexingJobStatistics; +import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory; +import java.time.Duration; + +/** #api212: inline into IndexingLoggerTest */ +public class ProjectIndexingHistoryWrapper { + private final ProjectIndexingHistory projectIndexingHistory; + + private ProjectIndexingHistoryWrapper(ProjectIndexingHistory projectIndexingHistory) { + this.projectIndexingHistory = projectIndexingHistory; + } + + public static ProjectIndexingHistoryWrapper create(Project project) { + return new ProjectIndexingHistoryWrapper(new ProjectIndexingHistory(project)); + } + + /** #api203: inline into IndexingLoggerTest */ + @SuppressWarnings("UnstableApiUsage") + public static void setIndexingVisibleTime( + IndexingJobStatistics indexingStatistic, Duration expectedIndexingVisibleTime) { + indexingStatistic.setIndexingVisibleTime(expectedIndexingVisibleTime.toNanos()); + } + + public ProjectIndexingHistory getProjectIndexingHistory() { + return projectIndexingHistory; + } + + public void addProviderStatistics(IndexingJobStatistics statistics) { + projectIndexingHistory.addProviderStatistics(statistics); + } + + public void setIndexingTimes( + Duration expectedIndexingDuration, + Duration expectedUpdatingDuration, + Duration expectedScanFilesDuration) { + projectIndexingHistory.getTimes().setIndexingDuration(expectedIndexingDuration); + projectIndexingHistory.getTimes().setTotalUpdatingTime(expectedUpdatingDuration.toNanos()); + projectIndexingHistory.getTimes().setScanFilesDuration(expectedScanFilesDuration); + } +} diff --git a/testing/testcompat/v212/com/google/idea/sdkcompat/BaseSdkTestCompat.java b/testing/testcompat/v212/com/google/idea/sdkcompat/BaseSdkTestCompat.java index 6950cedadb4..ef8fd093dcb 100644 --- a/testing/testcompat/v212/com/google/idea/sdkcompat/BaseSdkTestCompat.java +++ b/testing/testcompat/v212/com/google/idea/sdkcompat/BaseSdkTestCompat.java @@ -15,42 +15,10 @@ */ package com.google.idea.sdkcompat; -import com.intellij.openapi.project.Project; -import com.intellij.util.indexing.diagnostic.IndexingJobStatistics; -import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory; -import java.time.Duration; - /** * Provides SDK compatibility shims for base plugin API classes, available to all IDEs during * test-time. */ public final class BaseSdkTestCompat { private BaseSdkTestCompat() {} - - /** - * #api203: Doing duration calculations is not necessary anymore. Inline into IndexingLoggerTest. - */ - @SuppressWarnings("UnstableApiUsage") - public static void setIndexingTimes( - ProjectIndexingHistory.IndexingTimes projectIndexingHistory, - Duration expectedIndexingDuration, - Duration expectedUpdatingDuration, - Duration expectedScanFilesDuration) { - projectIndexingHistory.setIndexingDuration(expectedIndexingDuration); - projectIndexingHistory.setTotalUpdatingTime(expectedUpdatingDuration.toNanos()); - projectIndexingHistory.setScanFilesDuration(expectedScanFilesDuration); - } - - /** #api203: inline into IndexingLoggerTest */ - @SuppressWarnings("UnstableApiUsage") - public static void setIndexingVisibleTime( - IndexingJobStatistics indexingStatistic, Duration expectedIndexingVisibleTime) { - indexingStatistic.setIndexingVisibleTime(expectedIndexingVisibleTime.toNanos()); - } - - /** #api211 inline into IndexingLoggerTest */ - @SuppressWarnings("UnstableApiUsage") - public static ProjectIndexingHistory initializeProjectIndexingHistory(Project project) { - return new ProjectIndexingHistory(project, /* indexingReason= */ ""); - } } diff --git a/testing/testcompat/v212/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java b/testing/testcompat/v212/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java new file mode 100644 index 00000000000..d5b746e42f6 --- /dev/null +++ b/testing/testcompat/v212/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java @@ -0,0 +1,59 @@ +/* + * Copyright 2021 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.sdkcompat.indexing; + +import com.intellij.openapi.project.Project; +import com.intellij.util.indexing.diagnostic.IndexingJobStatistics; +import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory; +import java.time.Duration; + +/** #api212: inline into IndexingLoggerTest */ +public class ProjectIndexingHistoryWrapper { + private final ProjectIndexingHistory projectIndexingHistory; + + private ProjectIndexingHistoryWrapper(ProjectIndexingHistory projectIndexingHistory) { + this.projectIndexingHistory = projectIndexingHistory; + } + + public static ProjectIndexingHistoryWrapper create(Project project) { + return new ProjectIndexingHistoryWrapper( + new ProjectIndexingHistory(project, /* indexingReason= */ "")); + } + + /** #api203: inline into IndexingLoggerTest */ + @SuppressWarnings("UnstableApiUsage") + public static void setIndexingVisibleTime( + IndexingJobStatistics indexingStatistic, Duration expectedIndexingVisibleTime) { + indexingStatistic.setIndexingVisibleTime(expectedIndexingVisibleTime.toNanos()); + } + + public ProjectIndexingHistory getProjectIndexingHistory() { + return projectIndexingHistory; + } + + public void addProviderStatistics(IndexingJobStatistics statistics) { + projectIndexingHistory.addProviderStatistics(statistics); + } + + public void setIndexingTimes( + Duration expectedIndexingDuration, + Duration expectedUpdatingDuration, + Duration expectedScanFilesDuration) { + projectIndexingHistory.getTimes().setIndexingDuration(expectedIndexingDuration); + projectIndexingHistory.getTimes().setTotalUpdatingTime(expectedUpdatingDuration.toNanos()); + projectIndexingHistory.getTimes().setScanFilesDuration(expectedScanFilesDuration); + } +} diff --git a/testing/testcompat/v213/com/google/idea/sdkcompat/BaseSdkTestCompat.java b/testing/testcompat/v213/com/google/idea/sdkcompat/BaseSdkTestCompat.java index 6950cedadb4..ef8fd093dcb 100644 --- a/testing/testcompat/v213/com/google/idea/sdkcompat/BaseSdkTestCompat.java +++ b/testing/testcompat/v213/com/google/idea/sdkcompat/BaseSdkTestCompat.java @@ -15,42 +15,10 @@ */ package com.google.idea.sdkcompat; -import com.intellij.openapi.project.Project; -import com.intellij.util.indexing.diagnostic.IndexingJobStatistics; -import com.intellij.util.indexing.diagnostic.ProjectIndexingHistory; -import java.time.Duration; - /** * Provides SDK compatibility shims for base plugin API classes, available to all IDEs during * test-time. */ public final class BaseSdkTestCompat { private BaseSdkTestCompat() {} - - /** - * #api203: Doing duration calculations is not necessary anymore. Inline into IndexingLoggerTest. - */ - @SuppressWarnings("UnstableApiUsage") - public static void setIndexingTimes( - ProjectIndexingHistory.IndexingTimes projectIndexingHistory, - Duration expectedIndexingDuration, - Duration expectedUpdatingDuration, - Duration expectedScanFilesDuration) { - projectIndexingHistory.setIndexingDuration(expectedIndexingDuration); - projectIndexingHistory.setTotalUpdatingTime(expectedUpdatingDuration.toNanos()); - projectIndexingHistory.setScanFilesDuration(expectedScanFilesDuration); - } - - /** #api203: inline into IndexingLoggerTest */ - @SuppressWarnings("UnstableApiUsage") - public static void setIndexingVisibleTime( - IndexingJobStatistics indexingStatistic, Duration expectedIndexingVisibleTime) { - indexingStatistic.setIndexingVisibleTime(expectedIndexingVisibleTime.toNanos()); - } - - /** #api211 inline into IndexingLoggerTest */ - @SuppressWarnings("UnstableApiUsage") - public static ProjectIndexingHistory initializeProjectIndexingHistory(Project project) { - return new ProjectIndexingHistory(project, /* indexingReason= */ ""); - } } diff --git a/testing/testcompat/v213/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java b/testing/testcompat/v213/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java new file mode 100644 index 00000000000..3f3d22690d2 --- /dev/null +++ b/testing/testcompat/v213/com/google/idea/sdkcompat/indexing/ProjectIndexingHistoryWrapper.java @@ -0,0 +1,58 @@ +/* + * Copyright 2021 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.sdkcompat.indexing; + +import com.intellij.openapi.project.Project; +import com.intellij.util.indexing.diagnostic.IndexingJobStatistics; +import com.intellij.util.indexing.diagnostic.ProjectIndexingHistoryImpl; +import java.time.Duration; + +/** #api212: inline into IndexingLoggerTest */ +public class ProjectIndexingHistoryWrapper { + private final ProjectIndexingHistoryImpl projectIndexingHistoryImpl; + + private ProjectIndexingHistoryWrapper(ProjectIndexingHistoryImpl projectIndexingHistoryImpl) { + this.projectIndexingHistoryImpl = projectIndexingHistoryImpl; + } + + public static ProjectIndexingHistoryWrapper create(Project project) { + return new ProjectIndexingHistoryWrapper( + new ProjectIndexingHistoryImpl(project, /* indexingReason= */ "")); + } + + /** #api203: inline into IndexingLoggerTest */ + public static void setIndexingVisibleTime( + IndexingJobStatistics indexingStatistic, Duration expectedIndexingVisibleTime) { + indexingStatistic.setIndexingVisibleTime(expectedIndexingVisibleTime.toNanos()); + } + + public ProjectIndexingHistoryImpl getProjectIndexingHistory() { + return projectIndexingHistoryImpl; + } + + public void addProviderStatistics(IndexingJobStatistics statistics) { + projectIndexingHistoryImpl.addProviderStatistics(statistics); + } + + public void setIndexingTimes( + Duration expectedIndexingDuration, + Duration expectedUpdatingDuration, + Duration expectedScanFilesDuration) { + projectIndexingHistoryImpl.getTimes().setIndexingDuration(expectedIndexingDuration); + projectIndexingHistoryImpl.getTimes().setTotalUpdatingTime(expectedUpdatingDuration.toNanos()); + projectIndexingHistoryImpl.getTimes().setScanFilesDuration(expectedScanFilesDuration); + } +} From c74c7d7ad708884adde09866e6a23be0ac55edc7 Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 9 Nov 2021 08:46:43 -0800 Subject: [PATCH 35/47] [2021.3 compat] Add wrapper for TEXT_FIELD_WITH_STORED_HISTORY_WHOLE_TEXT PiperOrigin-RevId: 408620363 --- .../idea/blaze/base/ui/FileSelectorWithStoredHistory.java | 4 ++-- .../com/google/idea/sdkcompat/general/BaseSdkCompat.java | 7 +++++++ .../com/google/idea/sdkcompat/general/BaseSdkCompat.java | 7 +++++++ .../com/google/idea/sdkcompat/general/BaseSdkCompat.java | 7 +++++++ .../com/google/idea/sdkcompat/general/BaseSdkCompat.java | 8 ++++++++ 5 files changed, 31 insertions(+), 2 deletions(-) diff --git a/base/src/com/google/idea/blaze/base/ui/FileSelectorWithStoredHistory.java b/base/src/com/google/idea/blaze/base/ui/FileSelectorWithStoredHistory.java index 8636726d7e9..b073dd1f52d 100644 --- a/base/src/com/google/idea/blaze/base/ui/FileSelectorWithStoredHistory.java +++ b/base/src/com/google/idea/blaze/base/ui/FileSelectorWithStoredHistory.java @@ -15,9 +15,9 @@ */ package com.google.idea.blaze.base.ui; +import com.google.idea.sdkcompat.general.BaseSdkCompat; import com.intellij.ide.util.BrowseFilesListener; import com.intellij.openapi.ui.ComponentWithBrowseButton; -import com.intellij.openapi.ui.TextComponentAccessor; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.TextFieldWithStoredHistory; import javax.annotation.Nullable; @@ -39,7 +39,7 @@ private FileSelectorWithStoredHistory(TextFieldWithStoredHistory textField, Stri "", null, BrowseFilesListener.SINGLE_FILE_DESCRIPTOR, - TextComponentAccessor.TEXT_FIELD_WITH_STORED_HISTORY_WHOLE_TEXT); + BaseSdkCompat.TEXT_FIELD_WITH_STORED_HISTORY_WHOLE_TEXT); } /** Set the text without altering the history. */ diff --git a/sdkcompat/v203/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v203/com/google/idea/sdkcompat/general/BaseSdkCompat.java index f6a641bb6a6..5c44e4563d2 100644 --- a/sdkcompat/v203/com/google/idea/sdkcompat/general/BaseSdkCompat.java +++ b/sdkcompat/v203/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -8,9 +8,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.ui.TextComponentAccessor; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.changes.ui.ChangesListView; import com.intellij.ui.IconManager; +import com.intellij.ui.TextFieldWithStoredHistory; import com.intellij.usageView.UsageTreeColors; import com.intellij.usageView.UsageTreeColorsScheme; import com.intellij.usages.TextChunk; @@ -23,6 +25,11 @@ public final class BaseSdkCompat { private BaseSdkCompat() {} + /** #api212: inline into FileSelectorWithStoredHistory */ + public static final TextComponentAccessor + TEXT_FIELD_WITH_STORED_HISTORY_WHOLE_TEXT = + TextComponentAccessor.TEXT_FIELD_WITH_STORED_HISTORY_WHOLE_TEXT; + /** #api203: refactor this function back into CodesearchResultData and make it private. */ public static void addLineNumber(int lineNumber, List chunks) { EditorColorsScheme colorsScheme = UsageTreeColorsScheme.getInstance().getScheme(); diff --git a/sdkcompat/v211/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v211/com/google/idea/sdkcompat/general/BaseSdkCompat.java index 944e56f47be..8438ac57e72 100644 --- a/sdkcompat/v211/com/google/idea/sdkcompat/general/BaseSdkCompat.java +++ b/sdkcompat/v211/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -7,9 +7,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.ui.TextComponentAccessor; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.changes.ui.ChangesListView; import com.intellij.ui.IconManager; +import com.intellij.ui.TextFieldWithStoredHistory; import com.intellij.usageView.UsageTreeColors; import com.intellij.usages.TextChunk; import java.nio.file.Path; @@ -20,6 +22,11 @@ public final class BaseSdkCompat { private BaseSdkCompat() {} + /** #api212: inline into FileSelectorWithStoredHistory */ + public static final TextComponentAccessor + TEXT_FIELD_WITH_STORED_HISTORY_WHOLE_TEXT = + TextComponentAccessor.TEXT_FIELD_WITH_STORED_HISTORY_WHOLE_TEXT; + /** #api203: refactor this function back into CodesearchResultData and make it private. */ public static void addLineNumber(int lineNumber, List chunks) { chunks.add( diff --git a/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java index 3e987db53fd..6f6f7ddbd9d 100644 --- a/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java +++ b/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -8,10 +8,12 @@ import com.intellij.openapi.roots.DependencyScope; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.ui.TextComponentAccessor; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.changes.ui.ChangesListView; import com.intellij.ui.CoreIconManager; import com.intellij.ui.IconManager; +import com.intellij.ui.TextFieldWithStoredHistory; import com.intellij.usageView.UsageTreeColors; import com.intellij.usages.TextChunk; import java.nio.file.Path; @@ -22,6 +24,11 @@ public final class BaseSdkCompat { private BaseSdkCompat() {} + /** #api212: inline into FileSelectorWithStoredHistory */ + public static final TextComponentAccessor + TEXT_FIELD_WITH_STORED_HISTORY_WHOLE_TEXT = + TextComponentAccessor.TEXT_FIELD_WITH_STORED_HISTORY_WHOLE_TEXT; + /** #api203: refactor this function back into CodesearchResultData and make it private. */ public static void addLineNumber(int lineNumber, List chunks) { chunks.add( diff --git a/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java index 3e987db53fd..edd4838b0a6 100644 --- a/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java +++ b/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -8,10 +8,13 @@ import com.intellij.openapi.roots.DependencyScope; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.ui.TextComponentAccessor; +import com.intellij.openapi.ui.TextComponentAccessors; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.changes.ui.ChangesListView; import com.intellij.ui.CoreIconManager; import com.intellij.ui.IconManager; +import com.intellij.ui.TextFieldWithStoredHistory; import com.intellij.usageView.UsageTreeColors; import com.intellij.usages.TextChunk; import java.nio.file.Path; @@ -22,6 +25,11 @@ public final class BaseSdkCompat { private BaseSdkCompat() {} + /** #api212: inline into FileSelectorWithStoredHistory */ + public static final TextComponentAccessor + TEXT_FIELD_WITH_STORED_HISTORY_WHOLE_TEXT = + TextComponentAccessors.TEXT_FIELD_WITH_STORED_HISTORY_WHOLE_TEXT; + /** #api203: refactor this function back into CodesearchResultData and make it private. */ public static void addLineNumber(int lineNumber, List chunks) { chunks.add( From dcd5960ef7f64ceabb9adb0e16de6a4df40ef9b8 Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 9 Nov 2021 09:13:26 -0800 Subject: [PATCH 36/47] [2021.3 compat] Add wrapper for WizardContext.setWizard PiperOrigin-RevId: 408626151 --- .../idea/blaze/base/wizard2/BlazeNewProjectWizard.java | 3 ++- .../com/google/idea/sdkcompat/general/BaseSdkCompat.java | 7 +++++++ .../com/google/idea/sdkcompat/general/BaseSdkCompat.java | 7 +++++++ .../com/google/idea/sdkcompat/general/BaseSdkCompat.java | 7 +++++++ .../com/google/idea/sdkcompat/general/BaseSdkCompat.java | 7 +++++++ 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/base/src/com/google/idea/blaze/base/wizard2/BlazeNewProjectWizard.java b/base/src/com/google/idea/blaze/base/wizard2/BlazeNewProjectWizard.java index 5e2366a188e..7df8f32181f 100644 --- a/base/src/com/google/idea/blaze/base/wizard2/BlazeNewProjectWizard.java +++ b/base/src/com/google/idea/blaze/base/wizard2/BlazeNewProjectWizard.java @@ -17,6 +17,7 @@ import com.google.idea.blaze.base.help.BlazeHelpHandler; import com.google.idea.blaze.base.settings.Blaze; +import com.google.idea.sdkcompat.general.BaseSdkCompat; import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.ide.wizard.AbstractWizard; import com.intellij.ide.wizard.CommitStepException; @@ -41,7 +42,7 @@ public BlazeNewProjectWizard() { builder = new BlazeProjectImportBuilder(); context = new WizardContext(null, getDisposable()); - context.setWizard(this); + BaseSdkCompat.setContextWizard(context, this); context.setProjectBuilder(builder); for (ProjectImportWizardStep step : getSteps(context)) { addStep(step); diff --git a/sdkcompat/v203/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v203/com/google/idea/sdkcompat/general/BaseSdkCompat.java index 5c44e4563d2..04c7bc2e223 100644 --- a/sdkcompat/v203/com/google/idea/sdkcompat/general/BaseSdkCompat.java +++ b/sdkcompat/v203/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -1,5 +1,7 @@ package com.google.idea.sdkcompat.general; +import com.intellij.ide.util.projectWizard.WizardContext; +import com.intellij.ide.wizard.AbstractWizard; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; @@ -84,4 +86,9 @@ public static void addLibraryEntriesToModel( public static IdeModifiableModelsProvider createModifiableModelsProvider(Project project) { return new IdeModifiableModelsProviderImpl(project); } + + /** #api212: inline into BlazeNewProjectWizard */ + public static void setContextWizard(WizardContext context, AbstractWizard wizard) { + context.setWizard(wizard); + } } diff --git a/sdkcompat/v211/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v211/com/google/idea/sdkcompat/general/BaseSdkCompat.java index 8438ac57e72..afa55bb7e6c 100644 --- a/sdkcompat/v211/com/google/idea/sdkcompat/general/BaseSdkCompat.java +++ b/sdkcompat/v211/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -1,5 +1,7 @@ package com.google.idea.sdkcompat.general; +import com.intellij.ide.util.projectWizard.WizardContext; +import com.intellij.ide.wizard.AbstractWizard; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider; @@ -79,4 +81,9 @@ public static void addLibraryEntriesToModel( public static IdeModifiableModelsProvider createModifiableModelsProvider(Project project) { return new IdeModifiableModelsProviderImpl(project); } + + /** #api212: inline into BlazeNewProjectWizard */ + public static void setContextWizard(WizardContext context, AbstractWizard wizard) { + context.setWizard(wizard); + } } diff --git a/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java index 6f6f7ddbd9d..396216e67fc 100644 --- a/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java +++ b/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -1,5 +1,7 @@ package com.google.idea.sdkcompat.general; +import com.intellij.ide.util.projectWizard.WizardContext; +import com.intellij.ide.wizard.AbstractWizard; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider; @@ -82,4 +84,9 @@ public static IdeModifiableModelsProvider createModifiableModelsProvider(Project // API to create an IdeModifiableModelsProvider. return new IdeModifiableModelsProviderImpl(project); } + + /** #api212: inline into BlazeNewProjectWizard */ + public static void setContextWizard(WizardContext context, AbstractWizard wizard) { + context.setWizard(wizard); + } } diff --git a/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java index edd4838b0a6..d16b371e0e2 100644 --- a/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java +++ b/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -1,5 +1,7 @@ package com.google.idea.sdkcompat.general; +import com.intellij.ide.util.projectWizard.WizardContext; +import com.intellij.ide.wizard.AbstractWizard; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider; @@ -83,4 +85,9 @@ public static IdeModifiableModelsProvider createModifiableModelsProvider(Project // API to create an IdeModifiableModelsProvider. return new IdeModifiableModelsProviderImpl(project); } + + /** #api212: inline into BlazeNewProjectWizard */ + public static void setContextWizard(WizardContext context, AbstractWizard wizard) { + context.putUserData(AbstractWizard.KEY, wizard); + } } From 048ab16e2853852994d11b498521e938f3d956d2 Mon Sep 17 00:00:00 2001 From: Alice Kober-Sotzek Date: Wed, 10 Nov 2021 02:07:41 -0800 Subject: [PATCH 37/47] [Bazel plugin] Performance: Use batch addition of libraries in IntelliJ 2021.2.1+ The API to add the libraries in a batch to the new project model exists only in 2021.2.1+ but avoids performance issues. By configuring the plugin to be compatible only with 2021.2.1+, we can switch to this more performant API. In 2021.3, we can use the API without restrictions. PiperOrigin-RevId: 408820946 --- aswb/BUILD | 2 ++ clwb/BUILD | 2 ++ ijwb/BUILD | 2 ++ .../com/google/idea/sdkcompat/general/BaseSdkCompat.java | 8 +++++--- .../com/google/idea/sdkcompat/general/BaseSdkCompat.java | 8 +++++--- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/aswb/BUILD b/aswb/BUILD index 5df26aa53c4..33beeb08420 100644 --- a/aswb/BUILD +++ b/aswb/BUILD @@ -56,6 +56,8 @@ stamped_plugin_xml( description_file = "src/META-INF/description.html", plugin_id = "com.google.idea.bazel.aswb", plugin_name = "Bazel", + # #api212: We depend on an API which is only contained in 2021.2.1+. + since_build_numbers = {"212": "212.5080.55"}, stamp_since_build = True, stamp_until_build = True, version = VERSION, diff --git a/clwb/BUILD b/clwb/BUILD index 706fe12083c..2765b34d7ca 100644 --- a/clwb/BUILD +++ b/clwb/BUILD @@ -40,6 +40,8 @@ stamped_plugin_xml( description_file = "src/META-INF/description.html", plugin_id = "com.google.idea.bazel.clwb", plugin_name = "Bazel", + # #api212: We depend on an API which is only contained in 2021.2.1+. + since_build_numbers = {"212": "212.5080.55"}, stamp_since_build = True, stamp_until_build = True, version = VERSION, diff --git a/ijwb/BUILD b/ijwb/BUILD index b5c64c7b45e..467875241bd 100644 --- a/ijwb/BUILD +++ b/ijwb/BUILD @@ -50,6 +50,8 @@ stamped_plugin_xml( description_file = "src/META-INF/description.html", plugin_id = "com.google.idea.bazel.ijwb", plugin_name = "Bazel", + # #api212: We depend on an API which is only contained in 2021.2.1+. + since_build_numbers = {"212": "212.5080.55"}, stamp_since_build = True, stamp_until_build = True, version = VERSION, diff --git a/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java index 396216e67fc..4b5c188c096 100644 --- a/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java +++ b/sdkcompat/v212/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -67,9 +67,11 @@ public static void activateIconManager() throws Throwable { */ public static void addLibraryEntriesToModel( ModifiableRootModel modifiableRootModel, List libraries) { - for (Library library : libraries) { - modifiableRootModel.addLibraryEntry(library); - } + // Use the batch addition of libraries as adding them one after the other is not performant. + // The other parameters (scope + exported flag) are derived from their default values in + // ModifiableRootModel#addLibraryEntry. + modifiableRootModel.addLibraryEntries( + libraries, DependencyScope.COMPILE, /* exported= */ false); } /** diff --git a/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java b/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java index d16b371e0e2..685bf987550 100644 --- a/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java +++ b/sdkcompat/v213/com/google/idea/sdkcompat/general/BaseSdkCompat.java @@ -68,9 +68,11 @@ public static void activateIconManager() throws Throwable { */ public static void addLibraryEntriesToModel( ModifiableRootModel modifiableRootModel, List libraries) { - for (Library library : libraries) { - modifiableRootModel.addLibraryEntry(library); - } + // Use the batch addition of libraries as adding them one after the other is not performant. + // The other parameters (scope + exported flag) are derived from their default values in + // ModifiableRootModel#addLibraryEntry. + modifiableRootModel.addLibraryEntries( + libraries, DependencyScope.COMPILE, /* exported= */ false); } /** From f31232949a3a95d997fe86f69a6138b5ef1cafb8 Mon Sep 17 00:00:00 2001 From: Kurt Alfred Kluever Date: Wed, 10 Nov 2021 03:15:05 -0800 Subject: [PATCH 38/47] Automatic code cleanup. PiperOrigin-RevId: 408832759 --- .../com/google/idea/blaze/java/fastbuild/FastBuildState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/src/com/google/idea/blaze/java/fastbuild/FastBuildState.java b/java/src/com/google/idea/blaze/java/fastbuild/FastBuildState.java index 31eabde64a3..1e3e4460b37 100644 --- a/java/src/com/google/idea/blaze/java/fastbuild/FastBuildState.java +++ b/java/src/com/google/idea/blaze/java/fastbuild/FastBuildState.java @@ -17,12 +17,12 @@ import com.google.auto.value.AutoValue; import com.google.common.util.concurrent.ListenableFuture; +import com.google.errorprone.annotations.CheckReturnValue; import com.google.idea.blaze.base.command.info.BlazeInfo; import com.google.idea.blaze.base.model.primitives.Label; import java.io.File; import java.util.Map; import java.util.Optional; -import javax.annotation.CheckReturnValue; /** Internal state about an existing build. */ @AutoValue From c2f856025f022138f5ad3947207566b3cbb01627 Mon Sep 17 00:00:00 2001 From: Googler Date: Wed, 10 Nov 2021 23:15:20 -0800 Subject: [PATCH 39/47] [2021.3 compat] Add adapter for VcsLogActionPlaces constants PiperOrigin-RevId: 409067324 --- .../sdkcompat/vcs/VcsLogActionPlacesCompat.java | 17 +++++++++++++++++ .../sdkcompat/vcs/VcsLogActionPlacesCompat.java | 17 +++++++++++++++++ .../sdkcompat/vcs/VcsLogActionPlacesCompat.java | 17 +++++++++++++++++ .../sdkcompat/vcs/VcsLogActionPlacesCompat.java | 15 +++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 sdkcompat/v203/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java create mode 100644 sdkcompat/v211/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java create mode 100644 sdkcompat/v212/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java create mode 100644 sdkcompat/v213/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java diff --git a/sdkcompat/v203/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java b/sdkcompat/v203/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java new file mode 100644 index 00000000000..02628367fad --- /dev/null +++ b/sdkcompat/v203/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java @@ -0,0 +1,17 @@ +package com.google.idea.sdkcompat.vcs; + +import com.intellij.vcs.log.ui.VcsLogActionPlaces; + +/** #api212. Inline values into PiperChangeListProvider */ +public final class VcsLogActionPlacesCompat { + + private VcsLogActionPlacesCompat() {} + + public static final String VCS_LOG_TOOLBAR_PLACE = VcsLogActionPlaces.VCS_LOG_TOOLBAR_PLACE; + public static final String VCS_LOG_TOOLBAR_POPUP_PLACE = + VcsLogActionPlaces.VCS_LOG_TOOLBAR_POPUP_PLACE; + public static final String VCS_LOG_TABLE_PLACE = VcsLogActionPlaces.VCS_LOG_TABLE_PLACE; + public static final String VCS_HISTORY_TOOLBAR_PLACE = + VcsLogActionPlaces.VCS_HISTORY_TOOLBAR_PLACE; + public static final String VCS_HISTORY_PLACE = VcsLogActionPlaces.VCS_HISTORY_PLACE; +} diff --git a/sdkcompat/v211/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java b/sdkcompat/v211/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java new file mode 100644 index 00000000000..02628367fad --- /dev/null +++ b/sdkcompat/v211/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java @@ -0,0 +1,17 @@ +package com.google.idea.sdkcompat.vcs; + +import com.intellij.vcs.log.ui.VcsLogActionPlaces; + +/** #api212. Inline values into PiperChangeListProvider */ +public final class VcsLogActionPlacesCompat { + + private VcsLogActionPlacesCompat() {} + + public static final String VCS_LOG_TOOLBAR_PLACE = VcsLogActionPlaces.VCS_LOG_TOOLBAR_PLACE; + public static final String VCS_LOG_TOOLBAR_POPUP_PLACE = + VcsLogActionPlaces.VCS_LOG_TOOLBAR_POPUP_PLACE; + public static final String VCS_LOG_TABLE_PLACE = VcsLogActionPlaces.VCS_LOG_TABLE_PLACE; + public static final String VCS_HISTORY_TOOLBAR_PLACE = + VcsLogActionPlaces.VCS_HISTORY_TOOLBAR_PLACE; + public static final String VCS_HISTORY_PLACE = VcsLogActionPlaces.VCS_HISTORY_PLACE; +} diff --git a/sdkcompat/v212/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java b/sdkcompat/v212/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java new file mode 100644 index 00000000000..02628367fad --- /dev/null +++ b/sdkcompat/v212/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java @@ -0,0 +1,17 @@ +package com.google.idea.sdkcompat.vcs; + +import com.intellij.vcs.log.ui.VcsLogActionPlaces; + +/** #api212. Inline values into PiperChangeListProvider */ +public final class VcsLogActionPlacesCompat { + + private VcsLogActionPlacesCompat() {} + + public static final String VCS_LOG_TOOLBAR_PLACE = VcsLogActionPlaces.VCS_LOG_TOOLBAR_PLACE; + public static final String VCS_LOG_TOOLBAR_POPUP_PLACE = + VcsLogActionPlaces.VCS_LOG_TOOLBAR_POPUP_PLACE; + public static final String VCS_LOG_TABLE_PLACE = VcsLogActionPlaces.VCS_LOG_TABLE_PLACE; + public static final String VCS_HISTORY_TOOLBAR_PLACE = + VcsLogActionPlaces.VCS_HISTORY_TOOLBAR_PLACE; + public static final String VCS_HISTORY_PLACE = VcsLogActionPlaces.VCS_HISTORY_PLACE; +} diff --git a/sdkcompat/v213/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java b/sdkcompat/v213/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java new file mode 100644 index 00000000000..fbe3f0054fa --- /dev/null +++ b/sdkcompat/v213/com/google/idea/sdkcompat/vcs/VcsLogActionPlacesCompat.java @@ -0,0 +1,15 @@ +package com.google.idea.sdkcompat.vcs; + +import com.intellij.openapi.actionSystem.ActionPlaces; + +/** #api212. Inline values into PiperChangeListProvider */ +public final class VcsLogActionPlacesCompat { + + private VcsLogActionPlacesCompat() {} + + public static final String VCS_LOG_TOOLBAR_PLACE = ActionPlaces.VCS_LOG_TOOLBAR_PLACE; + public static final String VCS_LOG_TOOLBAR_POPUP_PLACE = ActionPlaces.VCS_LOG_TOOLBAR_POPUP_PLACE; + public static final String VCS_LOG_TABLE_PLACE = ActionPlaces.VCS_LOG_TABLE_PLACE; + public static final String VCS_HISTORY_TOOLBAR_PLACE = ActionPlaces.VCS_HISTORY_TOOLBAR_PLACE; + public static final String VCS_HISTORY_PLACE = ActionPlaces.VCS_HISTORY_PLACE; +} From 6aebd24db73bd7a0931bc9bb9b6b6e5edede7847 Mon Sep 17 00:00:00 2001 From: Alice Kober-Sotzek Date: Thu, 11 Nov 2021 06:03:01 -0800 Subject: [PATCH 40/47] Internal change. PiperOrigin-RevId: 409128604 --- .../blaze/clwb/run/BlazeGDBDriverConfiguration.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/clwb/src/com/google/idea/blaze/clwb/run/BlazeGDBDriverConfiguration.java b/clwb/src/com/google/idea/blaze/clwb/run/BlazeGDBDriverConfiguration.java index 758d10461c8..049d496b510 100644 --- a/clwb/src/com/google/idea/blaze/clwb/run/BlazeGDBDriverConfiguration.java +++ b/clwb/src/com/google/idea/blaze/clwb/run/BlazeGDBDriverConfiguration.java @@ -63,20 +63,20 @@ private void modifyCommandLine(GeneralCommandLine commandLine) { } commandLine.setWorkDirectory(workspaceRoot.directory()); } - + @Override public String convertToLocalPath(@Nullable String absolutePath) { if (absolutePath != null) { final File file = new File(absolutePath); final File workspaceDirectory = workspaceRoot.directory(); final String relativePath = gdbPathToWorkspaceRelativePath(workspaceDirectory, file); - File git5SafeFile = null; + File gdbFile = null; BlazeProjectData blazeProjectData = BlazeProjectDataManager.getInstance(project).getBlazeProjectData(); if (blazeProjectData != null) { - git5SafeFile = blazeProjectData.getWorkspacePathResolver().resolveToFile(relativePath); + gdbFile = blazeProjectData.getWorkspacePathResolver().resolveToFile(relativePath); } - absolutePath = git5SafeFile == null ? null : git5SafeFile.getPath(); + absolutePath = gdbFile == null ? null : gdbFile.getPath(); } return super.convertToLocalPath(absolutePath); } @@ -84,14 +84,14 @@ public String convertToLocalPath(@Nullable String absolutePath) { /** * Heuristic to try to handle the case where the file returned by gdb uses the canonical path but * the user imported their project using a non-canonical path. For example, this handles the case - * where the user keeps their git5 repos on a different mount and accesses them via a symlink from + * where the user keeps their repos on a different mount and accesses them via a symlink from * their home directory. * * @param workspaceDirectory workspace root, as it was imported into CLion * @param file file returned by GDB * @return The relative path for {@param file} as it was imported into CLion */ - private String gdbPathToWorkspaceRelativePath(File workspaceDirectory, File file) { + private static String gdbPathToWorkspaceRelativePath(File workspaceDirectory, File file) { try { File canonicalWorkspaceDirectory = workspaceDirectory.getCanonicalFile(); File canonicalFile = file.getCanonicalFile(); From c3188ed82bc97374975199c2622df3b281392bf5 Mon Sep 17 00:00:00 2001 From: Googler Date: Thu, 11 Nov 2021 10:22:43 -0800 Subject: [PATCH 41/47] Add artifact digest and length to BEP. Various BEP consumers would like to know whether a given artifact has changed from one invocation to the next. Since we produce BEP after an action has completed, we know the digest of all inputs/outputs and can report them with the file URI. RELNOTES: The Build Event Protocol now contains file digests and sizes along with the file name and URI. PiperOrigin-RevId: 409181875 --- .../lib/buildeventstream/proto/build_event_stream.proto | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/third_party/bazel/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto b/third_party/bazel/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto index bde66b38c7d..ad6d35e78a6 100644 --- a/third_party/bazel/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto +++ b/third_party/bazel/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto @@ -479,6 +479,13 @@ message File { // The contents of the file, if they are guaranteed to be short. bytes contents = 3; } + + // Digest of the file, using the build tool's configured digest algorithm, + // hex-encoded. + string digest = 5; + + // Length of the file in bytes. + int64 length = 6; } // Payload of a message to describe a set of files, usually build artifacts, to From 09badf515c0bf5933d77ba4ca1a8a84c242914d6 Mon Sep 17 00:00:00 2001 From: Googler Date: Fri, 12 Nov 2021 14:28:23 -0800 Subject: [PATCH 42/47] RELNOTES: Refactor system suspend event handling. We are looking to add more build anomaly reporting, so refactor the current system suspend handling to match the new model where we have a module and an event that we can record. Note this deprecates the AnomalyRecord out of BES for the time being. PiperOrigin-RevId: 409502784 --- .../build/lib/buildeventstream/proto/build_event_stream.proto | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/third_party/bazel/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto b/third_party/bazel/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto index ad6d35e78a6..8d2a80c2985 100644 --- a/third_party/bazel/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto +++ b/third_party/bazel/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto @@ -799,6 +799,7 @@ message BuildFinished { // Examples of suspensions are SIGSTOP, or the hardware being put to sleep. // If was_suspended is true, then most of the timings for this build are // suspect. + // NOTE: This is no longer set and is deprecated. bool was_suspended = 1; } @@ -819,7 +820,7 @@ message BuildFinished { // End of the build. google.protobuf.Timestamp finish_time = 5; - AnomalyReport anomaly_report = 4; + AnomalyReport anomaly_report = 4 [deprecated = true]; } message BuildMetrics { From cfa604a92a6ce0b51cd80dfcd8b610c87b49d7ef Mon Sep 17 00:00:00 2001 From: Googler Date: Mon, 15 Nov 2021 12:38:49 -0800 Subject: [PATCH 43/47] Move unpack aars methods to Unpacker PiperOrigin-RevId: 410053535 --- .../blaze/android/libraries/UnpackedAars.java | 109 ++----------- .../blaze/android/libraries/Unpacker.java | 153 ++++++++++++++++++ 2 files changed, 164 insertions(+), 98 deletions(-) create mode 100644 aswb/src/com/google/idea/blaze/android/libraries/Unpacker.java diff --git a/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java b/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java index e6c62e75912..c8a6094a9cb 100644 --- a/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java +++ b/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java @@ -15,9 +15,7 @@ */ package com.google.idea.blaze.android.libraries; -import static com.android.SdkConstants.FN_LINT_JAR; import static com.google.common.collect.ImmutableMap.toImmutableMap; -import static com.google.common.collect.ImmutableSet.toImmutableSet; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; @@ -30,11 +28,9 @@ import com.google.idea.blaze.base.command.buildresult.RemoteOutputArtifact; import com.google.idea.blaze.base.filecache.FileCache; import com.google.idea.blaze.base.filecache.FileCacheDiffer; -import com.google.idea.blaze.base.io.FileOperationProvider; import com.google.idea.blaze.base.model.BlazeLibrary; import com.google.idea.blaze.base.model.BlazeProjectData; import com.google.idea.blaze.base.model.RemoteOutputArtifacts; -import com.google.idea.blaze.base.prefetch.FetchExecutor; import com.google.idea.blaze.base.prefetch.RemoteArtifactPrefetcher; import com.google.idea.blaze.base.projectview.ProjectViewManager; import com.google.idea.blaze.base.projectview.ProjectViewSet; @@ -52,16 +48,8 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.util.io.ZipUtil; import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -180,14 +168,6 @@ private void refresh( } } - Set removedKeys = new HashSet<>(); - if (removeMissingFiles) { - removedKeys = - cacheFiles.keySet().stream() - .filter(file -> !projectState.containsKey(file)) - .collect(toImmutableSet()); - } - // Prefetch all libraries to local before reading and copying content ListenableFuture downloadArtifactsFuture = RemoteArtifactPrefetcher.getInstance() @@ -200,19 +180,23 @@ private void refresh( .withProgressMessage("Fetching aar files...") .run(); - // update cache files, and remove files if required - List> futures = new ArrayList<>(copyLocally(projectState, updatedKeys)); + // remove files if required. Remove file before updating cache files to avoid removing any + // manually created directory. if (removeMissingFiles) { - futures.addAll(aarCache.retainOnly(/* retainedFiles= */ projectState.keySet())); + Collection> removedFiles = + aarCache.retainOnly(/* retainedFiles= */ projectState.keySet()); + Futures.allAsList(removedFiles).get(); + if (!removedFiles.isEmpty()) { + context.output(PrintOutput.log(String.format("Removed %d AARs", removedFiles.size()))); + } } - Futures.allAsList(futures).get(); + // update cache files, and remove files if required + Unpacker.unpack(projectState, updatedKeys, aarCache); + if (!updatedKeys.isEmpty()) { context.output(PrintOutput.log(String.format("Copied %d AARs", updatedKeys.size()))); } - if (!removedKeys.isEmpty()) { - context.output(PrintOutput.log(String.format("Removed %d AARs", removedKeys.size()))); - } } catch (InterruptedException e) { context.setCancelled(); @@ -347,75 +331,4 @@ private static ImmutableMap getArtifactsToCache( } return ImmutableMap.copyOf(outputs); } - - private Collection> copyLocally( - ImmutableMap toCache, Set updatedKeys) { - FileOperationProvider ops = FileOperationProvider.getInstance(); - List> futures = new ArrayList<>(); - updatedKeys.forEach( - key -> - futures.add(FetchExecutor.EXECUTOR.submit(() -> copyLocally(ops, toCache.get(key))))); - return futures; - } - - private void copyLocally(FileOperationProvider ops, AarLibraryContents aarAndJar) { - String cacheKey = UnpackedAarUtils.getAarDirName(aarAndJar.aar()); - try { - File aarDir = aarCache.recreateAarDir(ops, cacheKey); - // TODO(brendandouglas): decompress via ZipInputStream so we don't require a local file - File toCopy = getOrCreateLocalFile(aarAndJar.aar()); - ZipUtil.extract( - toCopy, - aarDir, - // Skip jars except lint.jar. We will copy jar in AarLibraryContents instead. - // That could give us freedom in the future to use an ijar or header jar instead, - // which is more lightweight. But it's not applied to lint.jar - (dir, name) -> name.equals(FN_LINT_JAR) || !name.endsWith(".jar")); - - try { - File stampFile = aarCache.createTimeStampFile(cacheKey); - if (!(aarAndJar.aar() instanceof LocalFileArtifact)) { - // no need to set the timestamp for remote artifacts - return; - } - long sourceTime = ops.getFileModifiedTime(((LocalFileArtifact) aarAndJar.aar()).getFile()); - if (!ops.setFileModifiedTime(stampFile, sourceTime)) { - logger.warn("Failed to set AAR cache timestamp for " + aarAndJar.aar()); - } - } catch (IOException e) { - logger.warn("Failed to set AAR cache timestamp for " + aarAndJar.aar(), e); - } - - // copy merged jar - if (aarAndJar.jar() != null) { - try (InputStream stream = aarAndJar.jar().getInputStream()) { - Path destination = Paths.get(UnpackedAarUtils.getJarFile(aarDir).getPath()); - ops.mkdirs(destination.getParent().toFile()); - Files.copy(stream, destination, StandardCopyOption.REPLACE_EXISTING); - } - } - - } catch (IOException e) { - logger.warn( - String.format( - "Failed to extract AAR %s to %s", aarAndJar.aar(), aarCache.aarDirForKey(cacheKey)), - e); - } - } - - /** Returns a locally-accessible file mirroring the contents of this {@link BlazeArtifact}. */ - private static File getOrCreateLocalFile(BlazeArtifact artifact) throws IOException { - if (artifact instanceof LocalFileArtifact) { - return ((LocalFileArtifact) artifact).getFile(); - } - File tmpFile = - FileUtil.createTempFile( - "local-aar-file", - Integer.toHexString(UnpackedAarUtils.getArtifactKey(artifact).hashCode()), - /* deleteOnExit= */ true); - try (InputStream stream = artifact.getInputStream()) { - Files.copy(stream, Paths.get(tmpFile.getPath()), StandardCopyOption.REPLACE_EXISTING); - return tmpFile; - } - } } diff --git a/aswb/src/com/google/idea/blaze/android/libraries/Unpacker.java b/aswb/src/com/google/idea/blaze/android/libraries/Unpacker.java new file mode 100644 index 00000000000..13ce12902d3 --- /dev/null +++ b/aswb/src/com/google/idea/blaze/android/libraries/Unpacker.java @@ -0,0 +1,153 @@ +/* + * Copyright 2021 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.android.libraries; + +import static com.android.SdkConstants.FN_LINT_JAR; + +import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.idea.blaze.base.command.buildresult.BlazeArtifact; +import com.google.idea.blaze.base.command.buildresult.BlazeArtifact.LocalFileArtifact; +import com.google.idea.blaze.base.io.FileOperationProvider; +import com.google.idea.blaze.base.prefetch.FetchExecutor; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.io.ZipUtil; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutionException; + +/** + * Unzip prefetched aars to local cache directories. AARs are directories with many files. {@see + * https://developer.android.com/studio/projects/android-library.html#aar-contents}, for a subset of + * the contents (documentation may be outdated). + * + *

The IDE wants at least the following: + * + *

    + *
  • the res/ folder + *
  • the R.txt file adjacent to the res/ folder + *
  • See {@link com.android.tools.idea.resources.aar.AarSourceResourceRepository} for the + * dependency on R.txt. + *
  • jars: we use the merged output jar from Bazel instead of taking jars from the AAR. It gives + * us freedom in the future to use an ijar or header jar instead, which is more lightweight. + * It should be placed in a jars/ folder adjacent to the res/ folder. See {@link + * org.jetbrains.android.uipreview.ModuleClassLoader}, for that possible assumption. + *
  • The IDE may want the AndroidManifest.xml as well. + *
+ */ +public final class Unpacker { + private static final Logger logger = Logger.getInstance(Unpacker.class); + + /** Updated prefetched aars to aar directory. */ + public static void unpack( + ImmutableMap toCache, Set updatedKeys, AarCache aarCache) + throws ExecutionException, InterruptedException { + unpackAarsToDir(toCache, updatedKeys, aarCache); + } + + private static void unpackAarsToDir( + ImmutableMap toCache, Set updatedKeys, AarCache aarCache) + throws ExecutionException, InterruptedException { + FileOperationProvider ops = FileOperationProvider.getInstance(); + List> futures = new ArrayList<>(); + updatedKeys.forEach( + key -> + futures.add( + FetchExecutor.EXECUTOR.submit( + () -> unpackAarToDir(ops, toCache.get(key), aarCache)))); + Futures.allAsList(futures).get(); + } + + /** + * Each .aar file will be unpacked as .aar directories in cache + * directory. A timestamp file will be created to decide if updated is needed when a new .aar file + * with same name is found next time. + */ + private static void unpackAarToDir( + FileOperationProvider ops, AarLibraryContents aarAndJar, AarCache aarCache) { + String cacheKey = UnpackedAarUtils.getAarDirName(aarAndJar.aar()); + try { + File aarDir = aarCache.recreateAarDir(ops, cacheKey); + // TODO(brendandouglas): decompress via ZipInputStream so we don't require a local file + File toCopy = getOrCreateLocalFile(aarAndJar.aar()); + ZipUtil.extract( + toCopy, + aarDir, + // Skip jars except lint.jar. We will copy jar in AarLibraryContents instead. + // That could give us freedom in the future to use an ijar or header jar instead, + // which is more lightweight. But it's not applied to lint.jar + (dir, name) -> name.equals(FN_LINT_JAR) || !name.endsWith(".jar")); + + try { + File stampFile = aarCache.createTimeStampFile(cacheKey); + if (!(aarAndJar.aar() instanceof LocalFileArtifact)) { + // no need to set the timestamp for remote artifacts + return; + } + long sourceTime = ops.getFileModifiedTime(((LocalFileArtifact) aarAndJar.aar()).getFile()); + if (!ops.setFileModifiedTime(stampFile, sourceTime)) { + logger.warn("Failed to set AAR cache timestamp for " + aarAndJar.aar()); + } + } catch (IOException e) { + logger.warn("Failed to set AAR cache timestamp for " + aarAndJar.aar(), e); + } + + // copy merged jar + if (aarAndJar.jar() != null) { + try (InputStream stream = aarAndJar.jar().getInputStream()) { + Path destination = Paths.get(UnpackedAarUtils.getJarFile(aarDir).getPath()); + ops.mkdirs(destination.getParent().toFile()); + Files.copy(stream, destination, StandardCopyOption.REPLACE_EXISTING); + } + } + + } catch (IOException e) { + logger.warn( + String.format( + "Failed to extract AAR %s to %s", aarAndJar.aar(), aarCache.aarDirForKey(cacheKey)), + e); + } + } + + /** Returns a locally-accessible file mirroring the contents of this {@link BlazeArtifact}. */ + private static File getOrCreateLocalFile(BlazeArtifact artifact) throws IOException { + if (artifact instanceof LocalFileArtifact) { + return ((LocalFileArtifact) artifact).getFile(); + } + File tmpFile = + FileUtil.createTempFile( + "local-aar-file", + Integer.toHexString(UnpackedAarUtils.getArtifactKey(artifact).hashCode()), + /* deleteOnExit= */ true); + try (InputStream stream = artifact.getInputStream()) { + Files.copy(stream, Paths.get(tmpFile.getPath()), StandardCopyOption.REPLACE_EXISTING); + return tmpFile; + } + } + + private Unpacker() {} +} From 93af4bd17c1d7102177418cb6fd57f314cc934b6 Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 16 Nov 2021 06:20:13 -0800 Subject: [PATCH 44/47] Update IntelliJ UE 2021.3 EAP plugin api. PiperOrigin-RevId: 410235396 --- WORKSPACE | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 90ed53276d2..d454873f02c 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -72,8 +72,8 @@ http_archive( http_archive( name = "intellij_ue_2021_3", build_file = "@//intellij_platform_sdk:BUILD.ue213", - sha256 = "f36fd4f655ab8500be0ca8d6e031307dba379b0f97dfff8fcdd9b84ac806d936", - url = "https://www.jetbrains.com/intellij-repository/snapshots/com/jetbrains/intellij/idea/ideaIU/213.4631.20-EAP-SNAPSHOT/ideaIU-213.4631.20-EAP-SNAPSHOT.zip", + sha256 = "c0d4252d96931d8d1146cd3bf358bdc9c4e6d9b7ff54b90b0616d5dcd77637d2", + url = "https://www.jetbrains.com/intellij-repository/snapshots/com/jetbrains/intellij/idea/ideaIU/213.5744.18-EAP-SNAPSHOT/ideaIU-213.5744.18-EAP-SNAPSHOT.zip", ) # The plugin api for CLion 2020.3. This is required to build CLwB, @@ -453,20 +453,25 @@ scala_register_toolchains() load("@io_bazel_rules_scala//testing:scalatest.bzl", "scalatest_repositories", "scalatest_toolchain") scalatest_repositories() + scalatest_toolchain() # LICENSE: The Apache Software License, Version 2.0 rules_kotlin_version = "v1.5.0-beta-3" + rules_kotlin_sha = "58edd86f0f3c5b959c54e656b8e7eb0b0becabd412465c37a2078693c2571f7f" + http_archive( name = "io_bazel_rules_kotlin", - urls = ["https://github.com/bazelbuild/rules_kotlin/releases/download/%s/rules_kotlin_release.tgz" % rules_kotlin_version], sha256 = rules_kotlin_sha, + urls = ["https://github.com/bazelbuild/rules_kotlin/releases/download/%s/rules_kotlin_release.tgz" % rules_kotlin_version], ) -load("@io_bazel_rules_kotlin//kotlin:repositories.bzl", "kotlin_repositories", ) +load("@io_bazel_rules_kotlin//kotlin:repositories.bzl", "kotlin_repositories") load("@io_bazel_rules_kotlin//kotlin:core.bzl", "kt_register_toolchains") + kotlin_repositories() + kt_register_toolchains() # Without this dependency, when a test that uses Google truth fails, instead of From d37adb0365adfaca4e1935b685cc2b72603df60d Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 16 Nov 2021 13:29:12 -0800 Subject: [PATCH 45/47] Add OptionMetadataTag.EXPLICIT_IN_OUTPUT_PATH See OptionMetadataTag.java for documentation on what the tag does. Also audited the transitive calls of OutputDirectories.buildMnemonic and annotated options that seemingly can safely have the tag. (Note that some, like AppleConfiguration, have a getOutputDirectory that is too intricate for me to comfortably add the tag to any of the associated options.) Related to https://github.com/bazelbuild/bazel/issues/14023. PiperOrigin-RevId: 410335434 --- third_party/bazel/src/main/protobuf/option_filters.proto | 2 ++ 1 file changed, 2 insertions(+) diff --git a/third_party/bazel/src/main/protobuf/option_filters.proto b/third_party/bazel/src/main/protobuf/option_filters.proto index 424e3af2072..d931083c405 100644 --- a/third_party/bazel/src/main/protobuf/option_filters.proto +++ b/third_party/bazel/src/main/protobuf/option_filters.proto @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. syntax = "proto3"; + package options; // option java_api_version = 2; @@ -54,4 +55,5 @@ enum OptionMetadataTag { INTERNAL = 4; reserved "TRIGGERED_BY_ALL_INCOMPATIBLE_CHANGES"; reserved 5; + EXPLICIT_IN_OUTPUT_PATH = 6; } From 152a958dba2c5767acf8a10398f3a322127a2a51 Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 16 Nov 2021 17:25:17 -0800 Subject: [PATCH 46/47] Automated rollback of commit cfa604a92a6ce0b51cd80dfcd8b610c87b49d7ef. *** Reason for rollback *** b/206641735 *** Original change description *** Move unpack aars methods to Unpacker PiperOrigin-RevId: 410390279 --- .../blaze/android/libraries/UnpackedAars.java | 109 +++++++++++-- .../blaze/android/libraries/Unpacker.java | 153 ------------------ 2 files changed, 98 insertions(+), 164 deletions(-) delete mode 100644 aswb/src/com/google/idea/blaze/android/libraries/Unpacker.java diff --git a/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java b/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java index c8a6094a9cb..e6c62e75912 100644 --- a/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java +++ b/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java @@ -15,7 +15,9 @@ */ package com.google.idea.blaze.android.libraries; +import static com.android.SdkConstants.FN_LINT_JAR; import static com.google.common.collect.ImmutableMap.toImmutableMap; +import static com.google.common.collect.ImmutableSet.toImmutableSet; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; @@ -28,9 +30,11 @@ import com.google.idea.blaze.base.command.buildresult.RemoteOutputArtifact; import com.google.idea.blaze.base.filecache.FileCache; import com.google.idea.blaze.base.filecache.FileCacheDiffer; +import com.google.idea.blaze.base.io.FileOperationProvider; import com.google.idea.blaze.base.model.BlazeLibrary; import com.google.idea.blaze.base.model.BlazeProjectData; import com.google.idea.blaze.base.model.RemoteOutputArtifacts; +import com.google.idea.blaze.base.prefetch.FetchExecutor; import com.google.idea.blaze.base.prefetch.RemoteArtifactPrefetcher; import com.google.idea.blaze.base.projectview.ProjectViewManager; import com.google.idea.blaze.base.projectview.ProjectViewSet; @@ -48,8 +52,16 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.io.ZipUtil; import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -168,6 +180,14 @@ private void refresh( } } + Set removedKeys = new HashSet<>(); + if (removeMissingFiles) { + removedKeys = + cacheFiles.keySet().stream() + .filter(file -> !projectState.containsKey(file)) + .collect(toImmutableSet()); + } + // Prefetch all libraries to local before reading and copying content ListenableFuture downloadArtifactsFuture = RemoteArtifactPrefetcher.getInstance() @@ -180,23 +200,19 @@ private void refresh( .withProgressMessage("Fetching aar files...") .run(); - // remove files if required. Remove file before updating cache files to avoid removing any - // manually created directory. + // update cache files, and remove files if required + List> futures = new ArrayList<>(copyLocally(projectState, updatedKeys)); if (removeMissingFiles) { - Collection> removedFiles = - aarCache.retainOnly(/* retainedFiles= */ projectState.keySet()); - Futures.allAsList(removedFiles).get(); - if (!removedFiles.isEmpty()) { - context.output(PrintOutput.log(String.format("Removed %d AARs", removedFiles.size()))); - } + futures.addAll(aarCache.retainOnly(/* retainedFiles= */ projectState.keySet())); } - // update cache files, and remove files if required - Unpacker.unpack(projectState, updatedKeys, aarCache); - + Futures.allAsList(futures).get(); if (!updatedKeys.isEmpty()) { context.output(PrintOutput.log(String.format("Copied %d AARs", updatedKeys.size()))); } + if (!removedKeys.isEmpty()) { + context.output(PrintOutput.log(String.format("Removed %d AARs", removedKeys.size()))); + } } catch (InterruptedException e) { context.setCancelled(); @@ -331,4 +347,75 @@ private static ImmutableMap getArtifactsToCache( } return ImmutableMap.copyOf(outputs); } + + private Collection> copyLocally( + ImmutableMap toCache, Set updatedKeys) { + FileOperationProvider ops = FileOperationProvider.getInstance(); + List> futures = new ArrayList<>(); + updatedKeys.forEach( + key -> + futures.add(FetchExecutor.EXECUTOR.submit(() -> copyLocally(ops, toCache.get(key))))); + return futures; + } + + private void copyLocally(FileOperationProvider ops, AarLibraryContents aarAndJar) { + String cacheKey = UnpackedAarUtils.getAarDirName(aarAndJar.aar()); + try { + File aarDir = aarCache.recreateAarDir(ops, cacheKey); + // TODO(brendandouglas): decompress via ZipInputStream so we don't require a local file + File toCopy = getOrCreateLocalFile(aarAndJar.aar()); + ZipUtil.extract( + toCopy, + aarDir, + // Skip jars except lint.jar. We will copy jar in AarLibraryContents instead. + // That could give us freedom in the future to use an ijar or header jar instead, + // which is more lightweight. But it's not applied to lint.jar + (dir, name) -> name.equals(FN_LINT_JAR) || !name.endsWith(".jar")); + + try { + File stampFile = aarCache.createTimeStampFile(cacheKey); + if (!(aarAndJar.aar() instanceof LocalFileArtifact)) { + // no need to set the timestamp for remote artifacts + return; + } + long sourceTime = ops.getFileModifiedTime(((LocalFileArtifact) aarAndJar.aar()).getFile()); + if (!ops.setFileModifiedTime(stampFile, sourceTime)) { + logger.warn("Failed to set AAR cache timestamp for " + aarAndJar.aar()); + } + } catch (IOException e) { + logger.warn("Failed to set AAR cache timestamp for " + aarAndJar.aar(), e); + } + + // copy merged jar + if (aarAndJar.jar() != null) { + try (InputStream stream = aarAndJar.jar().getInputStream()) { + Path destination = Paths.get(UnpackedAarUtils.getJarFile(aarDir).getPath()); + ops.mkdirs(destination.getParent().toFile()); + Files.copy(stream, destination, StandardCopyOption.REPLACE_EXISTING); + } + } + + } catch (IOException e) { + logger.warn( + String.format( + "Failed to extract AAR %s to %s", aarAndJar.aar(), aarCache.aarDirForKey(cacheKey)), + e); + } + } + + /** Returns a locally-accessible file mirroring the contents of this {@link BlazeArtifact}. */ + private static File getOrCreateLocalFile(BlazeArtifact artifact) throws IOException { + if (artifact instanceof LocalFileArtifact) { + return ((LocalFileArtifact) artifact).getFile(); + } + File tmpFile = + FileUtil.createTempFile( + "local-aar-file", + Integer.toHexString(UnpackedAarUtils.getArtifactKey(artifact).hashCode()), + /* deleteOnExit= */ true); + try (InputStream stream = artifact.getInputStream()) { + Files.copy(stream, Paths.get(tmpFile.getPath()), StandardCopyOption.REPLACE_EXISTING); + return tmpFile; + } + } } diff --git a/aswb/src/com/google/idea/blaze/android/libraries/Unpacker.java b/aswb/src/com/google/idea/blaze/android/libraries/Unpacker.java deleted file mode 100644 index 13ce12902d3..00000000000 --- a/aswb/src/com/google/idea/blaze/android/libraries/Unpacker.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2021 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.android.libraries; - -import static com.android.SdkConstants.FN_LINT_JAR; - -import com.google.common.collect.ImmutableMap; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.idea.blaze.base.command.buildresult.BlazeArtifact; -import com.google.idea.blaze.base.command.buildresult.BlazeArtifact.LocalFileArtifact; -import com.google.idea.blaze.base.io.FileOperationProvider; -import com.google.idea.blaze.base.prefetch.FetchExecutor; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.util.io.ZipUtil; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ExecutionException; - -/** - * Unzip prefetched aars to local cache directories. AARs are directories with many files. {@see - * https://developer.android.com/studio/projects/android-library.html#aar-contents}, for a subset of - * the contents (documentation may be outdated). - * - *

The IDE wants at least the following: - * - *

    - *
  • the res/ folder - *
  • the R.txt file adjacent to the res/ folder - *
  • See {@link com.android.tools.idea.resources.aar.AarSourceResourceRepository} for the - * dependency on R.txt. - *
  • jars: we use the merged output jar from Bazel instead of taking jars from the AAR. It gives - * us freedom in the future to use an ijar or header jar instead, which is more lightweight. - * It should be placed in a jars/ folder adjacent to the res/ folder. See {@link - * org.jetbrains.android.uipreview.ModuleClassLoader}, for that possible assumption. - *
  • The IDE may want the AndroidManifest.xml as well. - *
- */ -public final class Unpacker { - private static final Logger logger = Logger.getInstance(Unpacker.class); - - /** Updated prefetched aars to aar directory. */ - public static void unpack( - ImmutableMap toCache, Set updatedKeys, AarCache aarCache) - throws ExecutionException, InterruptedException { - unpackAarsToDir(toCache, updatedKeys, aarCache); - } - - private static void unpackAarsToDir( - ImmutableMap toCache, Set updatedKeys, AarCache aarCache) - throws ExecutionException, InterruptedException { - FileOperationProvider ops = FileOperationProvider.getInstance(); - List> futures = new ArrayList<>(); - updatedKeys.forEach( - key -> - futures.add( - FetchExecutor.EXECUTOR.submit( - () -> unpackAarToDir(ops, toCache.get(key), aarCache)))); - Futures.allAsList(futures).get(); - } - - /** - * Each .aar file will be unpacked as .aar directories in cache - * directory. A timestamp file will be created to decide if updated is needed when a new .aar file - * with same name is found next time. - */ - private static void unpackAarToDir( - FileOperationProvider ops, AarLibraryContents aarAndJar, AarCache aarCache) { - String cacheKey = UnpackedAarUtils.getAarDirName(aarAndJar.aar()); - try { - File aarDir = aarCache.recreateAarDir(ops, cacheKey); - // TODO(brendandouglas): decompress via ZipInputStream so we don't require a local file - File toCopy = getOrCreateLocalFile(aarAndJar.aar()); - ZipUtil.extract( - toCopy, - aarDir, - // Skip jars except lint.jar. We will copy jar in AarLibraryContents instead. - // That could give us freedom in the future to use an ijar or header jar instead, - // which is more lightweight. But it's not applied to lint.jar - (dir, name) -> name.equals(FN_LINT_JAR) || !name.endsWith(".jar")); - - try { - File stampFile = aarCache.createTimeStampFile(cacheKey); - if (!(aarAndJar.aar() instanceof LocalFileArtifact)) { - // no need to set the timestamp for remote artifacts - return; - } - long sourceTime = ops.getFileModifiedTime(((LocalFileArtifact) aarAndJar.aar()).getFile()); - if (!ops.setFileModifiedTime(stampFile, sourceTime)) { - logger.warn("Failed to set AAR cache timestamp for " + aarAndJar.aar()); - } - } catch (IOException e) { - logger.warn("Failed to set AAR cache timestamp for " + aarAndJar.aar(), e); - } - - // copy merged jar - if (aarAndJar.jar() != null) { - try (InputStream stream = aarAndJar.jar().getInputStream()) { - Path destination = Paths.get(UnpackedAarUtils.getJarFile(aarDir).getPath()); - ops.mkdirs(destination.getParent().toFile()); - Files.copy(stream, destination, StandardCopyOption.REPLACE_EXISTING); - } - } - - } catch (IOException e) { - logger.warn( - String.format( - "Failed to extract AAR %s to %s", aarAndJar.aar(), aarCache.aarDirForKey(cacheKey)), - e); - } - } - - /** Returns a locally-accessible file mirroring the contents of this {@link BlazeArtifact}. */ - private static File getOrCreateLocalFile(BlazeArtifact artifact) throws IOException { - if (artifact instanceof LocalFileArtifact) { - return ((LocalFileArtifact) artifact).getFile(); - } - File tmpFile = - FileUtil.createTempFile( - "local-aar-file", - Integer.toHexString(UnpackedAarUtils.getArtifactKey(artifact).hashCode()), - /* deleteOnExit= */ true); - try (InputStream stream = artifact.getInputStream()) { - Files.copy(stream, Paths.get(tmpFile.getPath()), StandardCopyOption.REPLACE_EXISTING); - return tmpFile; - } - } - - private Unpacker() {} -} From 722f901878f8a5e862a429f069cf749e9d25f8ad Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 16 Nov 2021 17:33:22 -0800 Subject: [PATCH 47/47] Automated rollback of commit c8d1585c6b9c850f6890a0912599342c36718fc2. *** Reason for rollback *** b/206641735 *** Original change description *** Move cache state to AarCache Create AarCache to store cache state specifically. PiperOrigin-RevId: 410391746 --- .../blaze/android/libraries/AarCache.java | 176 ------------------ .../blaze/android/libraries/UnpackedAars.java | 158 ++++++++++++---- 2 files changed, 117 insertions(+), 217 deletions(-) delete mode 100644 aswb/src/com/google/idea/blaze/android/libraries/AarCache.java diff --git a/aswb/src/com/google/idea/blaze/android/libraries/AarCache.java b/aswb/src/com/google/idea/blaze/android/libraries/AarCache.java deleted file mode 100644 index 3f45e4a2b98..00000000000 --- a/aswb/src/com/google/idea/blaze/android/libraries/AarCache.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2021 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.android.libraries; - -import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.common.collect.ImmutableMap.toImmutableMap; -import static com.google.common.collect.ImmutableSet.toImmutableSet; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.idea.blaze.base.io.FileOperationProvider; -import com.google.idea.blaze.base.prefetch.FetchExecutor; -import com.intellij.openapi.diagnostic.Logger; -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; -import javax.annotation.Nullable; - -/** Local cache of the aars referenced by the project. */ -public class AarCache { - private static final Logger logger = Logger.getInstance(AarCache.class); - /** - * The state of the cache as of the last call to {@link #readFileState}. It will cleared by {@link - * #clearCache} - */ - private volatile ImmutableMap cacheState = ImmutableMap.of(); - - private static final String STAMP_FILE_NAME = "aar.timestamp"; - - private final File cacheDir; - - public AarCache(File cacheDir) { - this.cacheDir = cacheDir; - } - - /** - * Get the dir path to aar cache. Create one if it does exists. - * - * @return path to cache directory. Null will be return if the directory does not exist and fails - * to create one. - */ - @Nullable - public File getOrCreateCacheDir() throws IOException { - FileOperationProvider fileOpProvider = FileOperationProvider.getInstance(); - // Ensure the cache dir exists - if (!fileOpProvider.exists(cacheDir) && !fileOpProvider.mkdirs(cacheDir)) { - throw new IOException("Fail to create cache dir " + cacheDir); - } - return cacheDir; - } - - /* Get path to aar directory for the given key. The file is not guaranteed to be existed. */ - public File aarDirForKey(String key) { - return new File(cacheDir, key); - } - - /** - * Create a clean aar directory for the given key. The directory will be removed and recreate if - * the directory has already existed. - */ - public File recreateAarDir(FileOperationProvider ops, String key) throws IOException { - File aarDir = aarDirForKey(key); - if (ops.exists(aarDir)) { - ops.deleteRecursively(aarDir, true); - } - ops.mkdirs(aarDir); - return aarDir; - } - - /** - * Create timestamp file for the given key. The stamp file is used to identify if we need to - * update. - */ - public File createTimeStampFile(String key) throws IOException { - File stampFile = new File(aarDirForKey(key), STAMP_FILE_NAME); - stampFile.createNewFile(); - return stampFile; - } - - /** - * Returns a map of cache keys for the currently-cached files, along with a representative file - * used for timestamp-based diffing. - * - *

We use a stamp file instead of the directory itself to stash the timestamp. Directory - * timestamps are bit more brittle and can change whenever an operation is done to a child of the - * directory. - * - *

Also sets the in-memory @link #cacheState}. - */ - public ImmutableMap readFileState() { - FileOperationProvider ops = FileOperationProvider.getInstance(); - // Go through all of the aar directories, and get the stamp file. - File[] unpackedAarDirectories = ops.listFiles(cacheDir); - if (unpackedAarDirectories == null) { - return ImmutableMap.of(); - } - ImmutableMap cachedFiles = - Arrays.stream(unpackedAarDirectories) - .collect(toImmutableMap(File::getName, dir -> new File(dir, STAMP_FILE_NAME))); - cacheState = cachedFiles; - return cachedFiles; - } - - /* Remove all files that not list in retainedFiles. */ - public Collection> retainOnly(ImmutableSet retainedFiles) { - ImmutableSet cacheKeys = cacheState.keySet(); - ImmutableSet removedKeys = - cacheKeys.stream() - .filter(fileName -> !retainedFiles.contains(fileName)) - .collect(toImmutableSet()); - - FileOperationProvider ops = FileOperationProvider.getInstance(); - - return removedKeys.stream() - .map( - subDir -> - FetchExecutor.EXECUTOR.submit( - () -> { - try { - ops.deleteRecursively(new File(cacheDir, subDir), true); - } catch (IOException e) { - logger.warn(e); - } - })) - .collect(toImmutableList()); - } - - /* Clean up whole cache directory and reset cache state. */ - public void clearCache() { - FileOperationProvider fileOperationProvider = FileOperationProvider.getInstance(); - if (fileOperationProvider.exists(cacheDir)) { - try { - fileOperationProvider.deleteDirectoryContents(cacheDir, true); - } catch (IOException e) { - logger.warn("Failed to clear unpacked AAR directory: " + cacheDir, e); - } - } - cacheState = ImmutableMap.of(); - } - - /* Get the path to specific aar library. */ - @Nullable - public File getCachedAarDir(String aarDirName) { - ImmutableMap cacheState = this.cacheState; - if (cacheState.containsKey(aarDirName)) { - return new File(cacheDir, aarDirName); - } - return null; - } - - /* Whether the cache state is empty. */ - public boolean isEmpty() { - return cacheState.isEmpty(); - } - - /* Get all cached aar directories. */ - public ImmutableSet getCachedKeys() { - return cacheState.keySet(); - } -} diff --git a/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java b/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java index e6c62e75912..f213b8fac58 100644 --- a/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java +++ b/aswb/src/com/google/idea/blaze/android/libraries/UnpackedAars.java @@ -16,6 +16,7 @@ package com.google.idea.blaze.android.libraries; import static com.android.SdkConstants.FN_LINT_JAR; +import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableMap.toImmutableMap; import static com.google.common.collect.ImmutableSet.toImmutableSet; @@ -62,6 +63,7 @@ import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -95,7 +97,10 @@ public class UnpackedAars { private static final Logger logger = Logger.getInstance(UnpackedAars.class); private final Project project; - private final AarCache aarCache; + private final File cacheDir; + + /** The state of the cache as of the last call to {@link #readFileState}. */ + private volatile ImmutableMap cacheState = ImmutableMap.of(); public static UnpackedAars getInstance(Project project) { return ServiceManager.getService(project, UnpackedAars.class); @@ -105,19 +110,12 @@ public UnpackedAars(Project project) { BlazeImportSettings importSettings = BlazeImportSettingsManager.getInstance(project).getImportSettings(); this.project = project; - aarCache = new AarCache(getCacheDir(importSettings)); + this.cacheDir = getCacheDir(importSettings); } - /* Provide path to aar cache directory. This is for test only. */ @VisibleForTesting - @Nullable public File getCacheDir() { - try { - return aarCache.getOrCreateCacheDir(); - } catch (IOException e) { - logger.warn("Fail to get cache directory. ", e); - return null; - } + return this.cacheDir; } private static File getCacheDir(BlazeImportSettings importSettings) { @@ -132,7 +130,7 @@ void onSync( SyncMode syncMode) { boolean fullRefresh = syncMode == SyncMode.FULL; if (fullRefresh) { - aarCache.clearCache(); + clearCache(); } // TODO(brendandouglas): add a mechanism for removing missing files for partial syncs @@ -151,14 +149,17 @@ private void refresh( BlazeProjectData projectData, RemoteOutputArtifacts previousOutputs, boolean removeMissingFiles) { - try { - aarCache.getOrCreateCacheDir(); - } catch (IOException e) { - logger.warn("Could not create unpacked AAR directory", e); - return; + FileOperationProvider fileOpProvider = FileOperationProvider.getInstance(); + + // Ensure the cache dir exists + if (!fileOpProvider.exists(cacheDir)) { + if (!fileOpProvider.mkdirs(cacheDir)) { + logger.warn("Could not create unpacked AAR directory: " + cacheDir); + return; + } } - ImmutableMap cacheFiles = aarCache.readFileState(); + ImmutableMap cacheFiles = readFileState(); ImmutableMap projectState = getArtifactsToCache(viewSet, projectData); ImmutableMap aarOutputs = @@ -203,7 +204,7 @@ private void refresh( // update cache files, and remove files if required List> futures = new ArrayList<>(copyLocally(projectState, updatedKeys)); if (removeMissingFiles) { - futures.addAll(aarCache.retainOnly(/* retainedFiles= */ projectState.keySet())); + futures.addAll(deleteCacheEntries(removedKeys)); } Futures.allAsList(futures).get(); @@ -221,7 +222,7 @@ private void refresh( logger.warn("Unpacked AAR synchronization didn't complete", e); } finally { // update the in-memory record of which files are cached - aarCache.readFileState(); + readFileState(); } } @@ -231,8 +232,9 @@ public File getClassJar(ArtifactLocationDecoder decoder, AarLibrary library) { if (library.libraryArtifact == null) { return null; } + ImmutableMap cacheState = this.cacheState; BlazeArtifact jar = decoder.resolveOutput(library.libraryArtifact.jarForIntellijLibrary()); - if (aarCache.isEmpty()) { + if (cacheState.isEmpty()) { logger.warn("Cache state is empty"); return getFallbackFile(jar); } @@ -249,7 +251,7 @@ public File getClassJar(ArtifactLocationDecoder decoder, AarLibrary library) { String.format( "Fail to look up %s from cache state for library [aarArtifact = %s, jar = %s]", aarDir, aar, jar)); - logger.debug("Cache state contains the following keys: " + aarCache.getCachedKeys()); + logger.debug("Cache state contains the following keys: " + cacheState.keySet()); } return getFallbackFile(jar); } @@ -263,11 +265,24 @@ public File getResourceDirectory(ArtifactLocationDecoder decoder, AarLibrary lib return aarDir == null ? aarDir : UnpackedAarUtils.getResDir(aarDir); } + @Nullable + public File getAarDir(String cacheKey) { + ImmutableMap cacheState = this.cacheState; + if (!cacheState.containsKey(cacheKey)) { + return null; + } + return aarDirForKey(cacheKey); + } + @Nullable public File getAarDir(ArtifactLocationDecoder decoder, AarLibrary library) { BlazeArtifact artifact = decoder.resolveOutput(library.aarArtifact); String aarDirName = UnpackedAarUtils.getAarDirName(artifact); - return aarCache.getCachedAarDir(aarDirName); + return getAarDir(aarDirName); + } + + private File aarDirForKey(String key) { + return new File(cacheDir, key); } /** The file to return if there's no locally cached version. */ @@ -279,6 +294,18 @@ private static File getFallbackFile(BlazeArtifact output) { return ((LocalFileArtifact) output).getFile(); } + private void clearCache() { + FileOperationProvider fileOperationProvider = FileOperationProvider.getInstance(); + if (fileOperationProvider.exists(cacheDir)) { + try { + fileOperationProvider.deleteRecursively(cacheDir, true); + } catch (IOException e) { + logger.warn("Failed to clear unpacked AAR directory: " + cacheDir, e); + } + } + cacheState = ImmutableMap.of(); + } + static class FileCacheAdapter implements FileCache { @Override public String getName() { @@ -317,7 +344,7 @@ public void refreshFiles( @Override public void initialize(Project project) { - getInstance(project).aarCache.readFileState(); + getInstance(project).readFileState(); } } @@ -348,6 +375,32 @@ private static ImmutableMap getArtifactsToCache( return ImmutableMap.copyOf(outputs); } + private static final String STAMP_FILE_NAME = "aar.timestamp"; + + /** + * Returns a map of cache keys for the currently-cached files, along with a representative file + * used for timestamp-based diffing. + * + *

We use a stamp file instead of the directory itself to stash the timestamp. Directory + * timestamps are bit more brittle and can change whenever an operation is done to a child of the + * directory. + * + *

Also sets the in-memory @link #cacheState}. + */ + private ImmutableMap readFileState() { + FileOperationProvider ops = FileOperationProvider.getInstance(); + // Go through all of the aar directories, and get the stamp file. + File[] unpackedAarDirectories = ops.listFiles(cacheDir); + if (unpackedAarDirectories == null) { + return ImmutableMap.of(); + } + ImmutableMap cachedFiles = + Arrays.stream(unpackedAarDirectories) + .collect(toImmutableMap(File::getName, dir -> new File(dir, STAMP_FILE_NAME))); + cacheState = cachedFiles; + return cachedFiles; + } + private Collection> copyLocally( ImmutableMap toCache, Set updatedKeys) { FileOperationProvider ops = FileOperationProvider.getInstance(); @@ -360,8 +413,12 @@ private Collection> copyLocally( private void copyLocally(FileOperationProvider ops, AarLibraryContents aarAndJar) { String cacheKey = UnpackedAarUtils.getAarDirName(aarAndJar.aar()); + File aarDir = aarDirForKey(cacheKey); try { - File aarDir = aarCache.recreateAarDir(ops, cacheKey); + if (ops.exists(aarDir)) { + ops.deleteRecursively(aarDir, true); + } + ops.mkdirs(aarDir); // TODO(brendandouglas): decompress via ZipInputStream so we don't require a local file File toCopy = getOrCreateLocalFile(aarAndJar.aar()); ZipUtil.extract( @@ -372,19 +429,7 @@ private void copyLocally(FileOperationProvider ops, AarLibraryContents aarAndJar // which is more lightweight. But it's not applied to lint.jar (dir, name) -> name.equals(FN_LINT_JAR) || !name.endsWith(".jar")); - try { - File stampFile = aarCache.createTimeStampFile(cacheKey); - if (!(aarAndJar.aar() instanceof LocalFileArtifact)) { - // no need to set the timestamp for remote artifacts - return; - } - long sourceTime = ops.getFileModifiedTime(((LocalFileArtifact) aarAndJar.aar()).getFile()); - if (!ops.setFileModifiedTime(stampFile, sourceTime)) { - logger.warn("Failed to set AAR cache timestamp for " + aarAndJar.aar()); - } - } catch (IOException e) { - logger.warn("Failed to set AAR cache timestamp for " + aarAndJar.aar(), e); - } + createStampFile(ops, aarDir, aarAndJar.aar()); // copy merged jar if (aarAndJar.jar() != null) { @@ -396,13 +441,44 @@ private void copyLocally(FileOperationProvider ops, AarLibraryContents aarAndJar } } catch (IOException e) { - logger.warn( - String.format( - "Failed to extract AAR %s to %s", aarAndJar.aar(), aarCache.aarDirForKey(cacheKey)), - e); + logger.warn(String.format("Failed to extract AAR %s to %s", aarAndJar.aar(), aarDir), e); + } + } + + private static void createStampFile( + FileOperationProvider fileOps, File aarDir, BlazeArtifact aar) { + File stampFile = new File(aarDir, STAMP_FILE_NAME); + try { + stampFile.createNewFile(); + if (!(aar instanceof LocalFileArtifact)) { + // no need to set the timestamp for remote artifacts + return; + } + long sourceTime = fileOps.getFileModifiedTime(((LocalFileArtifact) aar).getFile()); + if (!fileOps.setFileModifiedTime(stampFile, sourceTime)) { + logger.warn("Failed to set AAR cache timestamp for " + aar); + } + } catch (IOException e) { + logger.warn("Failed to set AAR cache timestamp for " + aar, e); } } + private Collection> deleteCacheEntries(Collection cacheKeys) { + FileOperationProvider ops = FileOperationProvider.getInstance(); + return cacheKeys.stream() + .map( + key -> + FetchExecutor.EXECUTOR.submit( + () -> { + try { + ops.deleteRecursively(aarDirForKey(key), true); + } catch (IOException e) { + logger.warn(e); + } + })) + .collect(toImmutableList()); + } + /** Returns a locally-accessible file mirroring the contents of this {@link BlazeArtifact}. */ private static File getOrCreateLocalFile(BlazeArtifact artifact) throws IOException { if (artifact instanceof LocalFileArtifact) {