diff --git a/.bazelci/android-studio.yml b/.bazelci/android-studio.yml
index 4cde6c593cd..a599b916a74 100644
--- a/.bazelci/android-studio.yml
+++ b/.bazelci/android-studio.yml
@@ -2,7 +2,7 @@
tasks:
Android-Studio-internal-stable:
name: Android Studio Internal Stable
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=android-studio-latest
build_targets:
@@ -14,7 +14,7 @@ tasks:
- //:aswb_tests
Android-Studio-internal-beta:
name: Android Studio Internal Beta
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=android-studio-beta
build_targets:
@@ -26,7 +26,7 @@ tasks:
- //:aswb_tests
Android-Studio-internal-canary:
name: Android Studio Internal Canary
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=android-studio-canary
build_targets:
@@ -36,35 +36,33 @@ tasks:
- --test_output=errors
test_targets:
- //:aswb_tests
- soft_fail:
- - exit_status: 1
- Android-Studio-OSS-stable:
- name: Android Studio OSS Stable
- platform: ubuntu1804
+ Android-Studio-OSS-oldest-stable:
+ name: Android Studio OSS Oldest Stable
+ platform: ubuntu2204
build_flags:
- - --define=ij_product=android-studio-oss-stable
+ - --define=ij_product=android-studio-oss-oldest-stable
build_targets:
- //aswb/...
test_flags:
- - --define=ij_product=android-studio-oss-stable
+ - --define=ij_product=android-studio-oss-oldest-stable
- --test_output=errors
test_targets:
- //:aswb_tests
- Android-Studio-OSS-beta:
- name: Android Studio OSS Beta
- platform: ubuntu1804
+ Android-Studio-OSS-latest-stable:
+ name: Android Studio OSS Latest Stable
+ platform: ubuntu2204
build_flags:
- - --define=ij_product=android-studio-oss-beta
+ - --define=ij_product=android-studio-oss-latest-stable
build_targets:
- //aswb/...
test_flags:
- - --define=ij_product=android-studio-oss-beta
+ - --define=ij_product=android-studio-oss-latest-stable
- --test_output=errors
test_targets:
- //:aswb_tests
Android-Studio-OSS-under-dev:
name: Android Studio OSS Under Development
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=android-studio-oss-under-dev
build_targets:
@@ -74,6 +72,3 @@ tasks:
- --test_output=errors
test_targets:
- //:aswb_tests
- soft_fail:
- - exit_status: 1
-
diff --git a/.bazelci/aspect.yml b/.bazelci/aspect.yml
index 41809729a15..be4fa26a482 100644
--- a/.bazelci/aspect.yml
+++ b/.bazelci/aspect.yml
@@ -2,7 +2,7 @@
tasks:
Aspect-internal-stable:
name: Aspect Tests for IJ Internal Stable
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=intellij-latest
build_targets:
@@ -13,9 +13,10 @@ tasks:
- --notrim_test_configuration
test_targets:
- //aspect/testing/...
+ skip_use_bazel_version_for_test: true
Aspect-internal-beta:
name: Aspect Tests for IJ Internal Beta
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=intellij-beta
build_targets:
@@ -26,9 +27,10 @@ tasks:
- --notrim_test_configuration
test_targets:
- //aspect/testing/...
+ skip_use_bazel_version_for_test: true
Aspect-internal-under-dev:
name: Aspect Tests for IJ Internal Under Development
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=intellij-under-dev
build_targets:
@@ -41,35 +43,38 @@ tasks:
- //aspect/testing/...
soft_fail:
- exit_status: 1
- Aspect-oss-stable:
- name: Aspect Tests for IJ OSS Stable
- platform: ubuntu1804
+ skip_use_bazel_version_for_test: true
+ Aspect-oss-oldest-stable:
+ name: Aspect Tests for IJ OSS Oldest Stable
+ platform: ubuntu2204
build_flags:
- - --define=ij_product=intellij-oss-stable
+ - --define=ij_product=intellij-oss-oldest-stable
build_targets:
- //aspect:aspect_files
test_flags:
- - --define=ij_product=intellij-oss-stable
+ - --define=ij_product=intellij-oss-oldest-stable
- --test_output=errors
- --notrim_test_configuration
test_targets:
- //aspect/testing/...
- Aspect-oss-beta:
- name: Aspect Tests for IJ OSS Beta
- platform: ubuntu1804
+ skip_use_bazel_version_for_test: true
+ Aspect-oss-latest-stable:
+ name: Aspect Tests for IJ OSS Latest Stable
+ platform: ubuntu2204
build_flags:
- - --define=ij_product=intellij-oss-beta
+ - --define=ij_product=intellij-oss-latest-stable
build_targets:
- //aspect:aspect_files
test_flags:
- - --define=ij_product=intellij-oss-beta
+ - --define=ij_product=intellij-oss-latest-stable
- --test_output=errors
- --notrim_test_configuration
test_targets:
- //aspect/testing/...
+ skip_use_bazel_version_for_test: true
Aspect-oss-under-dev:
name: Aspect Tests for IJ OSS Under Development
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=intellij-oss-under-dev
build_targets:
@@ -82,3 +87,4 @@ tasks:
- //aspect/testing/...
soft_fail:
- exit_status: 1
+ skip_use_bazel_version_for_test: true
diff --git a/.bazelci/clion.yml b/.bazelci/clion.yml
index a4534ad2ab3..0672b9c551c 100644
--- a/.bazelci/clion.yml
+++ b/.bazelci/clion.yml
@@ -2,7 +2,7 @@
tasks:
CLion-internal-stable:
name: CLion Internal Stable
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=clion-latest
build_targets:
@@ -14,7 +14,7 @@ tasks:
- //:clwb_tests
CLion-internal-beta:
name: CLion Internal Beta
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=clion-beta
build_targets:
@@ -26,7 +26,7 @@ tasks:
- //:clwb_tests
CLion-internal-under-dev:
name: CLion Internal Under Development
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=clion-under-dev
build_targets:
@@ -38,33 +38,33 @@ tasks:
- //:clwb_tests
soft_fail:
- exit_status: 1
- CLion-OSS-stable:
- name: CLion OSS Stable
- platform: ubuntu1804
+ CLion-OSS-oldest-stable:
+ name: CLion OSS Oldest Stable
+ platform: ubuntu2204
build_flags:
- - --define=ij_product=clion-oss-stable
+ - --define=ij_product=clion-oss-oldest-stable
build_targets:
- //clwb/...
test_flags:
- - --define=ij_product=clion-oss-stable
+ - --define=ij_product=clion-oss-oldest-stable
- --test_output=errors
test_targets:
- //:clwb_tests
- CLion-OSS-beta:
- name: CLion OSS Beta
- platform: ubuntu1804
+ CLion-OSS-latest-stable:
+ name: CLion OSS Latest Stable
+ platform: ubuntu2204
build_flags:
- - --define=ij_product=clion-oss-beta
+ - --define=ij_product=clion-oss-latest-stable
build_targets:
- //clwb/...
test_flags:
- - --define=ij_product=clion-oss-beta
+ - --define=ij_product=clion-oss-latest-stable
- --test_output=errors
test_targets:
- //:clwb_tests
CLion-OSS-under-dev:
name: CLion OSS Under Development
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=clion-oss-under-dev
build_targets:
diff --git a/.bazelci/intellij-ue.yml b/.bazelci/intellij-ue.yml
index 5175d667aa9..28f470caf2a 100644
--- a/.bazelci/intellij-ue.yml
+++ b/.bazelci/intellij-ue.yml
@@ -2,7 +2,7 @@
tasks:
IntelliJ-UE-internal-stable:
name: IntelliJ UE Internal Stable
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=intellij-ue-latest
build_targets:
@@ -14,7 +14,7 @@ tasks:
- //:ijwb_ue_tests
IntelliJ-UE-internal-beta:
name: IntelliJ UE Internal Beta
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=intellij-ue-beta
build_targets:
@@ -26,7 +26,7 @@ tasks:
- //:ijwb_ue_tests
IntelliJ-UE-internal-under-dev:
name: IntelliJ UE Internal Under Development
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=intellij-ue-under-dev
build_targets:
@@ -38,33 +38,33 @@ tasks:
- //:ijwb_ue_tests
soft_fail:
- exit_status: 1
- IntelliJ-UE-OSS-stable:
- name: IntelliJ UE OSS Stable
- platform: ubuntu1804
+ IntelliJ-UE-OSS-oldest-stable:
+ name: IntelliJ UE OSS Oldest Stable
+ platform: ubuntu2204
build_flags:
- - --define=ij_product=intellij-ue-oss-stable
+ - --define=ij_product=intellij-ue-oss-oldest-stable
build_targets:
- //ijwb/...
test_flags:
- - --define=ij_product=intellij-ue-oss-stable
+ - --define=ij_product=intellij-ue-oss-oldest-stable
- --test_output=errors
test_targets:
- //:ijwb_ue_tests
- IntelliJ-UE-OSS-beta:
- name: IntelliJ UE OSS Beta
- platform: ubuntu1804
+ IntelliJ-UE-OSS-latest-stable:
+ name: IntelliJ UE OSS Latest Stable
+ platform: ubuntu2204
build_flags:
- - --define=ij_product=intellij-ue-oss-beta
+ - --define=ij_product=intellij-ue-oss-latest-stable
build_targets:
- //ijwb/...
test_flags:
- - --define=ij_product=intellij-ue-oss-beta
+ - --define=ij_product=intellij-ue-oss-latest-stable
- --test_output=errors
test_targets:
- //:ijwb_ue_tests
IntelliJ-UE-OSS-under-dev:
name: IntelliJ UE OSS Under Development
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=intellij-ue-oss-under-dev
build_targets:
@@ -76,4 +76,3 @@ tasks:
- //:ijwb_ue_tests
soft_fail:
- exit_status: 1
-
diff --git a/.bazelci/intellij.yml b/.bazelci/intellij.yml
index 2ebc69aa24c..a4e70ac8adc 100644
--- a/.bazelci/intellij.yml
+++ b/.bazelci/intellij.yml
@@ -2,7 +2,7 @@
tasks:
IntelliJ-CE-internal-stable:
name: IntelliJ CE Internal Stable
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=intellij-latest
build_targets:
@@ -14,7 +14,7 @@ tasks:
- //:ijwb_ce_tests
IntelliJ-CE-internal-beta:
name: IntelliJ CE Internal Beta
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=intellij-beta
build_targets:
@@ -26,7 +26,7 @@ tasks:
- //:ijwb_ce_tests
IntelliJ-CE-internal-under-dev:
name: IntelliJ CE Internal Under Development
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=intellij-under-dev
build_targets:
@@ -38,33 +38,33 @@ tasks:
- //:ijwb_ce_tests
soft_fail:
- exit_status: 1
- IntelliJ-CE-OSS-stable:
- name: IntelliJ CE OSS Stable
- platform: ubuntu1804
+ IntelliJ-CE-OSS-oldest-stable:
+ name: IntelliJ CE OSS Oldest Stable
+ platform: ubuntu2204
build_flags:
- - --define=ij_product=intellij-oss-stable
+ - --define=ij_product=intellij-oss-oldest-stable
build_targets:
- //ijwb/...
test_flags:
- - --define=ij_product=intellij-oss-stable
+ - --define=ij_product=intellij-oss-oldest-stable
- --test_output=errors
test_targets:
- //:ijwb_ce_tests
- IntelliJ-CE-OSS-beta:
- name: IntelliJ CE OSS Beta
- platform: ubuntu1804
+ IntelliJ-CE-OSS-latest-stable:
+ name: IntelliJ CE OSS Latest Stable
+ platform: ubuntu2204
build_flags:
- - --define=ij_product=intellij-oss-beta
+ - --define=ij_product=intellij-oss-latest-stable
build_targets:
- //ijwb/...
test_flags:
- - --define=ij_product=intellij-oss-beta
+ - --define=ij_product=intellij-oss-latest-stable
- --test_output=errors
test_targets:
- //:ijwb_ce_tests
IntelliJ-CE-OSS-under-dev:
name: IntelliJ CE OSS Under Development
- platform: ubuntu1804
+ platform: ubuntu2204
build_flags:
- --define=ij_product=intellij-oss-under-dev
build_targets:
@@ -76,4 +76,3 @@ tasks:
- //:ijwb_ce_tests
soft_fail:
- exit_status: 1
-
diff --git a/.bazelrc b/.bazelrc
new file mode 100644
index 00000000000..5e811013437
--- /dev/null
+++ b/.bazelrc
@@ -0,0 +1,11 @@
+build --java_language_version=17 --java_runtime_version=17
+
+# delete testdata package needed for bazel integration tests
+build --deleted_packages=//aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata
+query --deleted_packages=//aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata
+
+# TODO: migrate all dependencies from WORKSPACE to MODULE.bazel
+common --noenable_bzlmod
+common --enable_workspace
+common --experimental_google_legacy_api
+common --noincompatible_disallow_empty_glob
\ No newline at end of file
diff --git a/BUILD b/BUILD
index ccefc718112..ea8a9006e31 100644
--- a/BUILD
+++ b/BUILD
@@ -1,9 +1,13 @@
+load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain")
+load("@rules_java//java:defs.bzl", "java_package_configuration")
+
#
# Description: Blaze plugin for various IntelliJ products.
#
load(
"//:build-visibility.bzl",
"BAZEL_PLUGIN_SUBPACKAGES",
+ "DEFAULT_TEST_VISIBILITY",
"create_plugin_packages_group",
)
@@ -18,6 +22,7 @@ filegroup(
visibility = BAZEL_PLUGIN_SUBPACKAGES,
)
+# BEGIN-EXTERNAL
# IJwB tests, run with an IntelliJ plugin SDK
test_suite(
name = "ijwb_common_tests",
@@ -62,6 +67,19 @@ test_suite(
],
)
+# CLwB tests, run with a CLion plugin SDK
+test_suite(
+ name = "clwb_tests",
+ tests = [
+ "//base:unit_tests",
+ "//clwb:unit_tests",
+ "//cpp:unit_tests",
+ "//dart:unit_tests",
+ "//python:unit_tests",
+ ],
+)
+# END-EXTERNAL
+
# ASwB tests, run with an Android Studio plugin SDK
test_suite(
name = "aswb_tests",
@@ -76,24 +94,32 @@ test_suite(
"//java:integration_tests",
"//java:unit_tests",
],
+ visibility = DEFAULT_TEST_VISIBILITY,
)
-test_suite(
- name = "aswb_python_tests",
- tests = [
- "//python:integration_tests",
- "//python:unit_tests",
+default_java_toolchain(
+ name = "custom_java_17_toolchain",
+ configuration = dict(),
+ java_runtime = "@rules_java//toolchains:remotejdk_17",
+ package_configuration = [
+ ":java_8",
],
+ source_version = "17",
+ target_version = "17",
)
-# CLwB tests, run with a CLion plugin SDK
-test_suite(
- name = "clwb_tests",
- tests = [
- "//base:unit_tests",
- "//clwb:unit_tests",
- "//cpp:unit_tests",
- "//dart:unit_tests",
- "//python:unit_tests",
+# this associates a set of javac flags with a set of packages
+java_package_configuration(
+ name = "java_8",
+ javacopts = ["-source 8 -target 8"],
+ packages = ["java_8_packages"],
+)
+
+# this is a regular package_group, which is used to specify a set of packages to apply flags to
+package_group(
+ name = "java_8_packages",
+ packages = [
+ "//proto/...",
+ "//third_party/bazel/src/main/protobuf/...",
],
)
diff --git a/CHANGELOG b/CHANGELOG
index 12668069987..6fede1ab6fd 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,220 @@
+v2024.08.27
+===========
+* Internal cleanup
+
+v2024.08.13
+===========
+* Internal cleanup
+
+v2024.07.30
+===========
+* Internal cleanup
+
+v2024.07.16
+===========
+* Internal cleanup
+
+v2024.07.02
+===========
+* Internal cleanup
+
+v2024.06.18
+===========
+* Internal cleanup
+
+v2024.06.04-RC-2
+================
+* Address CVE-2024-5899
+* Internal cleanup
+
+v2024.06.04
+===========
+* Internal cleanup
+
+v2024.05.21
+===========
+* Internal cleanup
+
+v2024.05.07
+===========
+* Internal cleanup
+
+v2024.04.23
+===========
+* Plugin aspect now depends on @rules_java. If this breaks you, please update your @rules_java version to 5.3.5 or later.
+* Internal Cleanup
+
+v2024.04.09
+===========
+* Internal cleanup
+
+v2024.03.26
+===========
+* Plugin is now compatible with Iguana RC 2 2023.2 and Jellyfish Beta 1 2023.3
+* Internal cleanup
+
+v2024.03.12
+===========
+* Internal cleanup
+
+v2024.02.27
+===========
+* Internal cleanup
+
+v2024.02.13
+===========
+* Internal cleanup
+
+v2024.01.30
+===========
+* Internal Cleanup
+
+v2024.01.16
+===========
+* Internal Cleanup
+
+v2024.01.02
+===========
+* Internal Cleanup
+
+v2023.12.19
+===========
+* Internal Cleanup
+
+v2023.12.05
+===========
+* Internal Cleanup
+
+v2023.11.21
+===========
+* Internal Cleanup
+
+v2023.11.07
+===========
+* Internal Cleanup
+
+v2023.10.24
+===========
+* Internal Cleanup
+
+v2023.10.10
+===========
+* Internal Cleanup
+
+v2023.09.26
+===========
+* Internal cleanup
+
+v2023.09.12
+===========
+* Internal Cleanup
+
+v2023.08.29
+===========
+* Support Android Studio 2023.1
+* Internal Cleanup
+
+v2023.08.15
+===========
+* Internal cleanup
+
+v2023.08.01
+===========
+* Internal cleanup
+
+v2023.07.18
+===========
+* [query-sync] "Build dependecies for open files" action
+* Internal cleanup
+
+v2023.07.04
+===========
+* [query-sync] Support the "Build dependencies" action for directories and BUILD files.
+* Internal cleanup
+
+
+v2023.06.13
+===========
+* Move oldest supported Bazel version to 4.0.0
+* Internal cleanup
+
+v2023.05.30
+===========
+* Internal cleanup
+
+v2023.05.16
+===========
+* Internal cleanup
+
+v2023.05.02
+===========
+* Internal cleanup
+* Plugin compatible with Android Studio 2022.3
+
+v2023.04.18
+===========
+* Fix mobile install step: https://github.com/bazelbuild/intellij/pull/4669
+* Fix partial query fails to read input stream: https://github.com/bazelbuild/intellij/pull/4739
+* Internal cleanup
+
+v2023.04.04
+===========
+Internal cleanup.
+
+v2023.03.21
+===========
+* Internal cleanup.
+* Plugin compatible with Android Studio 2022.2.
+
+v2023.03.07
+===========
+* Internal cleanup.
+* Fix (Failed Android apk target build: https://github.com/bazelbuild/intellij/issues/4462)
+* Support leading `@` in instrumentation test targets labels (https://github.com/bazelbuild/intellij/pull/4530)
+
+v2023.02.22
+===========
+* Internal cleanup.
+
+v2023.02.07
+===========
+* Internal cleanup.
+
+v2023.01.24
+===========
+* Internal cleanup.
+* Plugin compatible with Android Studio 2022.1
+
+v2023.01.10
+===========
+* `BlazeAndroidSyncBuildFlagsProvider` is removed in (https://github.com/bazelbuild/intellij/commit/583537c63866eac13169ce128bb53aa0017bc6e0) (addresses issues: #3787 and #3703)
+* Internal cleanup.
+
+v2022.12.13
+===========
+* Internal cleanup.
+
+v2022.11.29
+===========
+* Bug fixes and internal cleanup.
+
+v2022.11.15
+===========
+* Invoke Live Edit from ASwB (56913bc).
+* Internal cleanup.
+
+v2022.11.01
+===========
+* Internal cleanup.
+
+v2022.07.26
+===========
+* Fix Blaze target highlighting in the integrated terminal.
+
+v2022.07.12
+===========
+* Bug fixes and internal cleanup.
+
v2022.06.14
===========
* Kotlin: Fix the detection of which test target to run for a newly created
diff --git a/WORKSPACE b/WORKSPACE
index 3a7cdab66a8..164279e483e 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -35,8 +35,16 @@ http_archive(
http_archive(
name = "intellij_ce_2022_2",
build_file = "@//intellij_platform_sdk:BUILD.idea222",
- sha256 = "a935cd7832613d223c711cf2c509bbc8399f29d2b36c2da10bf5fdfb0dbd2788",
- url = "https://www.jetbrains.com/intellij-repository/snapshots/com/jetbrains/intellij/idea/ideaIC/222.2964.55-EAP-SNAPSHOT/ideaIC-222.2964.55-EAP-SNAPSHOT.zip",
+ sha256 = "19cf087718400dbc5a90c6423aa71ebfbfe1c504e8fc399034b864cb6d2e7275",
+ url = "https://www.jetbrains.com/intellij-repository/releases/com/jetbrains/intellij/idea/ideaIC/2022.2.5/ideaIC-2022.2.5.zip",
+)
+
+# The plugin api for intellij_ce_2022_3 idea. This is required to build IJwB and run integration tests.
+http_archive(
+ name = "intellij_ce_2022_3",
+ build_file = "@//intellij_platform_sdk:BUILD.idea223",
+ sha256 = "5fe178e7a52ed3efa72f0761f17cbf065ebfc7e6c91c4366cd2e87d1bb032794",
+ url = "https://www.jetbrains.com/intellij-repository/releases/com/jetbrains/intellij/idea/ideaIC/2022.3.3/ideaIC-2022.3.3.zip",
)
# The plugin api for IntelliJ UE 2021.2. This is required to run UE-specific
@@ -68,8 +76,16 @@ http_archive(
http_archive(
name = "intellij_ue_2022_2",
build_file = "@//intellij_platform_sdk:BUILD.ue222",
- sha256 = "eb085ef7b95e86f2525c268252dcdb4edeb03584fa6aa0284584fe4faf2401bc",
- url = "https://www.jetbrains.com/intellij-repository/snapshots/com/jetbrains/intellij/idea/ideaIU/222.2964.55-EAP-SNAPSHOT/ideaIU-222.2964.55-EAP-SNAPSHOT.zip",
+ sha256 = "557eb6ddab79894ea3b96f072b7ab797b7733329c0ae03b3701fb098e0ebb63a",
+ url = "https://www.jetbrains.com/intellij-repository/releases/com/jetbrains/intellij/idea/ideaIU/2022.2.5/ideaIU-2022.2.5.zip",
+)
+
+# The plugin api for intellij_ue_2022_3 ue. This is required to run UE-specific integration tests.
+http_archive(
+ name = "intellij_ue_2022_3",
+ build_file = "@//intellij_platform_sdk:BUILD.ue223",
+ sha256 = "c4711503aed650d12c2d3014721384d7c223d23591400bae7e94286e511d3220",
+ url = "https://www.jetbrains.com/intellij-repository/releases/com/jetbrains/intellij/idea/ideaIU/2022.3.3/ideaIU-2022.3.3.zip",
)
# The plugin api for clion_2021_2. This is required to build CLwB, and run integration tests.
@@ -100,8 +116,16 @@ http_archive(
http_archive(
name = "clion_2022_2",
build_file = "@//intellij_platform_sdk:BUILD.clion222",
- sha256 = "12edae92d2fdb2a6234963f329fb65241a0aba12ec96a8302571affa0e3edd26",
- url = "https://download.jetbrains.com/cpp/CLion-222.2964.48.tar.gz",
+ sha256 = "94ffbdf82606f2f90618c1fdb89432d627e7f24ae158b36a591da2c303047436",
+ url = "https://download.jetbrains.com/cpp/CLion-2022.2.tar.gz",
+)
+
+# The plugin api for clion_2022_3 clion. This is required to build CLwB\, and run integration tests.
+http_archive(
+ name = "clion_2022_3",
+ build_file = "@//intellij_platform_sdk:BUILD.clion223",
+ sha256 = "1b46ff0791bcb38ecb39c5f4a99941f99ed73d4f6d924a2042fdb55afc5fc03d",
+ url = "https://download.jetbrains.com/cpp/CLion-2022.3.3.tar.gz",
)
_PYTHON_CE_BUILD_FILE = """
@@ -153,14 +177,42 @@ http_archive(
http_archive(
name = "python_2022_2",
build_file_content = _PYTHON_CE_BUILD_FILE,
- sha256 = "19f54957e89be0e9c2e4af67aeefa357ec4d2801b353cf912df65ce9a8fc6732",
- url = "https://plugins.jetbrains.com/files/7322/183142/python-ce-222.2964.16.zip",
+ sha256 = "aaae5ea44b5ad18793f8de63c00dce0371d91c14f7381260d19c4adaf4f9c9bf",
+ url = "https://plugins.jetbrains.com/files/7322/305491/python-ce-222.4554.5.zip",
+)
+
+http_archive(
+ name = "python_2022_3",
+ build_file_content = _PYTHON_CE_BUILD_FILE,
+ sha256 = "bfbde44928f446b2706df875bfa56cc64ee490875341c79aebba32ff7bb0f9d4",
+ url = "https://plugins.jetbrains.com/files/7322/300704/python-ce-223.8836.26.zip",
+)
+
+http_archive(
+ name = "python_2023_1",
+ build_file_content = _PYTHON_CE_BUILD_FILE,
+ sha256 = "825c30d2cbcce405fd18fddf356eb1f425607e9c780f8eff95d21ac23f8d90fd",
+ url = "https://plugins.jetbrains.com/maven/com/jetbrains/plugins/PythonCore/231.8770.65/PythonCore-231.8770.65.zip",
+)
+
+http_archive(
+ name = "python_2023_2",
+ build_file_content = _PYTHON_CE_BUILD_FILE,
+ sha256 = "e744349f353568c18a9e11ec5e3a205f62bbdc1b65c9abc96783c479fe2aa51b",
+ url = "https://plugins.jetbrains.com/maven/com/jetbrains/plugins/PythonCore/232.9921.47/PythonCore-232.9921.47.zip",
+)
+
+http_archive(
+ name = "python_2023_3",
+ build_file_content = _PYTHON_CE_BUILD_FILE,
+ sha256 = "48ef31f29e40ab3824027299b6bd7a0267aaad8175ebb1a5f10841122f5e9513",
+ url = "https://plugins.jetbrains.com/maven/com/jetbrains/plugins/PythonCore/233.13135.65/PythonCore-233.13135.65.zip",
)
_GO_BUILD_FILE = """
java_import(
name = "go",
- jars = glob(["go/lib/*.jar"]),
+ jars = glob(["go*/lib/*.jar"]),
visibility = ["//visibility:public"],
)
"""
@@ -185,15 +237,22 @@ http_archive(
http_archive(
name = "go_2022_1",
build_file_content = _GO_BUILD_FILE,
- sha256 = "50b96a18d3bf95b2742fb01d8d8ae9d7faef7113b882011afea4a912699ac0f9",
- url = "https://plugins.jetbrains.com/files/9568/167522/go-221.5080.210.zip",
+ sha256 = "4219a3b76c985ad1066d4ff99f516422bcbbfda2feba6a950e8bb6c5e544e3ea",
+ url = "https://plugins.jetbrains.com/files/9568/185980/go-221.5921.16.zip",
)
http_archive(
name = "go_2022_2",
build_file_content = _GO_BUILD_FILE,
- sha256 = "eaab17db1de510ab28df8c65c07c9c35252a67a89253fa99660c703c88c1ec68",
- url = "https://plugins.jetbrains.com/files/9568/183564/go-222.2964.55.zip",
+ sha256 = "cc19cc418b512420643c8c94eaf2cf1775de3183b1a8d0c2703959fcc4275afd",
+ url = "https://plugins.jetbrains.com/files/9568/256314/go-222.4459.24.zip",
+)
+
+http_archive(
+ name = "go_2022_3",
+ build_file_content = _GO_BUILD_FILE,
+ sha256 = "c762d2ff0253b8a996b8225344b345ae30b518dd20b3fd23bc1f417a90756c79",
+ url = "https://plugins.jetbrains.com/files/9568/293630/go-plugin-223.8836.7.zip",
)
_SCALA_BUILD_FILE = """
@@ -231,28 +290,107 @@ http_archive(
http_archive(
name = "scala_2022_2",
build_file_content = _SCALA_BUILD_FILE,
- sha256 = "7fb67d1baa3dea7ffcf5ea3c6e06796aa00144062e6895b2422fa0cdac32a876",
- url = "https://plugins.jetbrains.com/files/1347/183692/scala-intellij-bin-2022.2.4.zip",
+ sha256 = "9f668afa80e5cff90667fca7e7737d47a9ec73f39ff59b3488881371349afcff",
+ url = "https://plugins.jetbrains.com/files/1347/258933/scala-intellij-bin-2022.2.19.zip",
)
-# The plugin api for android_studio_2021_2. This is required to build ASwB,
-# and run integration tests.
http_archive(
- name = "android_studio_2021_2",
- build_file = "@//intellij_platform_sdk:BUILD.android_studio212",
- sha256 = "0018e0dfc0dd2921700516f7a2c443377c557788da7fb0a45243ecb4300745be",
- url = "https://dl.google.com/dl/android/studio/ide-zips/2021.2.1.15/android-studio-2021.2.1.15-linux.tar.gz",
+ name = "scala_2022_3",
+ build_file_content = _SCALA_BUILD_FILE,
+ sha256 = "e3b49e40153f441a3e0f8bf28aa09fccf7b5bf92b58f53c72aa546d74bfeefbb",
+ url = "https://plugins.jetbrains.com/files/1347/301506/scala-intellij-bin-2022.3.20.zip",
)
-# The plugin api for android_studio_2021_3. This is required to build ASwB,
-# and run integration tests.
+# The plugin api for android_studio_2022_2 android_studio. This is required to build ASwB and run integration tests
+http_archive(
+ name = "android_studio_2022_2",
+ build_file = "@//intellij_platform_sdk:BUILD.android_studio222",
+ sha256 = "cdd852c4499b5f7402df44dfc69e8ca418ffc9a684caab34047476fd2cb24efc",
+ url = "https://dl.google.com/dl/android/studio/ide-zips/2022.2.1.18/android-studio-2022.2.1.18-linux.tar.gz",
+)
+
+# The plugin api for android_studio_dev android_studio. This is required to build ASwB and run integration tests
+http_archive(
+ name = "android_studio_dev",
+ build_file = "@//intellij_platform_sdk:BUILD.android_studiodev",
+ sha256 = "cb3f0494220f92dd85399adfb8655a1a2bd81b238d26e63a8bbd8bde95a0fccf",
+ url = "https://android-build",
+)
+
+# The plugin api for android_studio_2023_3 android_studio. This is required to build ASwB and run integration tests
http_archive(
- name = "android_studio_2021_3",
- build_file = "@//intellij_platform_sdk:BUILD.android_studio213",
- sha256 = "fdfa6acc089934d747d3af56a4fb83534384e0e2869b09c221c30856efbb5fb2",
- url = "https://dl.google.com/dl/android/studio/ide-zips/2021.3.1.13/android-studio-2021.3.1.13-linux.tar.gz",
+ name = "android_studio_2023_3",
+ build_file = "@//intellij_platform_sdk:BUILD.android_studio233",
+ sha256 = "3e786a48a831b345d0e5c9bf3c1d753a6b36a7568089b5ca7b9d900bef255fc7",
+ url = "https://dl.google.com/dl/android/studio/ide-zips/2023.3.1.7/android-studio-2023.3.1.7-linux.tar.gz",
)
+# The plugin api for android_studio_2023_2 android_studio. This is required to build ASwB and run integration tests
+http_archive(
+ name = "android_studio_2023_2",
+ build_file = "@//intellij_platform_sdk:BUILD.android_studio232",
+ sha256 = "0026427572849c9cbb0c94d6f9718ea08bc345dccfe3b372b54100a95fff99b5",
+ url = "https://dl.google.com/dl/android/studio/ide-zips/2023.2.1.24/android-studio-2023.2.1.24-linux.tar.gz",
+)
+
+# The plugin api for android_studio_2023_1 android_studio. This is required to build ASwB and run integration tests
+http_archive(
+ name = "android_studio_2023_1",
+ build_file = "@//intellij_platform_sdk:BUILD.android_studio231",
+ sha256 = "139d0dbb4909353b68fbf55c09b6d31a34512044a9d4f02ce0f1a9accca128f9",
+ url = "https://dl.google.com/dl/android/studio/ide-zips/2023.1.1.28/android-studio-2023.1.1.28-linux.tar.gz",
+)
+
+# The plugin api for android_studio_2022_3 android_studio. This is required to build ASwB and run integration tests
+http_archive(
+ name = "android_studio_2022_3",
+ build_file = "@//intellij_platform_sdk:BUILD.android_studio223",
+ sha256 = "250625dcab183e0c68ebf12ef8a522af7369527d76f1efc704f93c05b02ffa9e",
+ url = "https://dl.google.com/dl/android/studio/ide-zips/2022.3.1.19/android-studio-2022.3.1.19-linux.tar.gz",
+)
+
+http_archive(
+ name = "rules_java",
+ urls = [
+ "https://github.com/bazelbuild/rules_java/releases/download/8.6.2/rules_java-8.6.2.tar.gz",
+ ],
+ sha256 = "a64ab04616e76a448c2c2d8165d836f0d2fb0906200d0b7c7376f46dd62e59cc",
+)
+
+_protobuf_version = "29.0"
+
+_protobuf_sha256 = "10a0d58f39a1a909e95e00e8ba0b5b1dc64d02997f741151953a2b3659f6e78c"
+
+http_archive(
+ name = "com_google_protobuf",
+ sha256 = _protobuf_sha256,
+ strip_prefix = "protobuf-%s" % _protobuf_version,
+ urls = ["https://github.com/protocolbuffers/protobuf/archive/v%s.tar.gz" % _protobuf_version],
+)
+
+http_archive(
+ name = "rules_python",
+ sha256 = "690e0141724abb568267e003c7b6d9a54925df40c275a870a4d934161dc9dd53",
+ strip_prefix = "rules_python-0.40.0",
+ url = "https://github.com/bazelbuild/rules_python/releases/download/0.40.0/rules_python-0.40.0.tar.gz",
+)
+
+http_archive(
+ name = "rules_proto",
+ sha256 = "0e5c64a2599a6e26c6a03d6162242d231ecc0de219534c38cb4402171def21e8",
+ strip_prefix = "rules_proto-7.0.2",
+ url = "https://github.com/bazelbuild/rules_proto/releases/download/7.0.2/rules_proto-7.0.2.tar.gz",
+)
+
+load("@rules_java//java:rules_java_deps.bzl", "rules_java_dependencies")
+rules_java_dependencies()
+
+load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
+protobuf_deps()
+
+load("@rules_java//java:repositories.bzl", "rules_java_toolchains")
+rules_java_toolchains()
+
# LICENSE: Common Public License 1.0
jvm_maven_import_external(
name = "junit",
@@ -334,6 +472,72 @@ jvm_maven_import_external(
server_urls = ["https://repo1.maven.org/maven2"],
)
+jvm_maven_import_external(
+ name = "com_google_guava_guava",
+ artifact = "com.google.guava:guava:31.1-jre",
+ artifact_sha256 = "a42edc9cab792e39fe39bb94f3fca655ed157ff87a8af78e1d6ba5b07c4a00ab",
+ server_urls = [
+ "https://repo1.maven.org/maven2",
+ ],
+)
+
+jvm_maven_import_external(
+ name = "com_google_guava_failureaccess",
+ artifact = "com.google.guava:failureaccess:1.0.2",
+ artifact_sha256 = "8a8f81cf9b359e3f6dfa691a1e776985c061ef2f223c9b2c80753e1b458e8064",
+ server_urls = [
+ "https://repo1.maven.org/maven2",
+ ],
+)
+
+jvm_maven_import_external(
+ name = "gson",
+ artifact = "com.google.code.gson:gson:2.9.1",
+ artifact_sha256 = "378534e339e6e6d50b1736fb3abb76f1c15d1be3f4c13cec6d536412e23da603",
+ server_urls = [
+ "https://repo1.maven.org/maven2",
+ ],
+)
+
+jvm_maven_import_external(
+ name = "flogger",
+ artifact = "com.google.flogger:flogger:0.7.4",
+ artifact_sha256 = "77aac11b3c26e1e184dcfe79c55ac6e27967a6dfe1c04146125176940bc64a55",
+ server_urls = [
+ "https://repo1.maven.org/maven2",
+ ],
+)
+
+jvm_maven_import_external(
+ name = "flogger_system_backend",
+ artifact = "com.google.flogger:flogger-system-backend:0.7.4",
+ artifact_sha256 = "fd66f2615a9d8fe1b2274f1b5005a5555a0cd63cdfdab2ca9500e6eb81dc5f63",
+ server_urls = [
+ "https://repo1.maven.org/maven2",
+ ],
+)
+
+http_archive(
+ name = "rules_android",
+ sha256 = "af84b69ab3d16dd1a41056286e6511f147a94ccea995603e13e934c915c1631c",
+ strip_prefix = "rules_android-0.6.0",
+ urls = ["https://github.com/bazelbuild/rules_android/releases/download/v0.6.0/rules_android-v0.6.0.tar.gz"],
+)
+load("@rules_android//:prereqs.bzl", "rules_android_prereqs")
+rules_android_prereqs()
+load("@rules_android//:defs.bzl", "rules_android_workspace")
+rules_android_workspace()
+
+load("@rules_android//rules:rules.bzl", "android_sdk_repository")
+android_sdk_repository(
+ name = "androidsdk",
+)
+
+register_toolchains(
+ "@rules_android//toolchains/android:android_default_toolchain",
+ "@rules_android//toolchains/android_sdk:android_sdk_tools",
+)
+
_JARJAR_BUILD_FILE = """
java_binary(
name = "jarjar_bin",
@@ -373,10 +577,17 @@ new_git_repository(
shallow_since = "1518210648 -0800",
)
+load("@rules_python//python:repositories.bzl", "py_repositories")
+
+py_repositories()
+
http_archive(
name = "bazel_skylib",
- sha256 = "2ef429f5d7ce7111263289644d233707dba35e39696377ebab8b0bc701f7818e",
- url = "https://github.com/bazelbuild/bazel-skylib/releases/download/0.8.0/bazel-skylib.0.8.0.tar.gz",
+ sha256 = "74d544d96f4a5bb630d465ca8bbcfe231e3594e5aae57e1edbf17a6eb3ca2506",
+ urls = [
+ "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
+ "https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
+ ],
)
# specify a minimum version for bazel otherwise users on old versions may see
@@ -385,63 +596,39 @@ load("@bazel_skylib//lib:versions.bzl", "versions")
versions.check(minimum_bazel_version = "5.2.0")
-http_archive(
- name = "build_bazel_integration_testing",
- sha256 = "e055ff971787a27d6942a83ffd182953988c88dfa82e89138ccc83bf410a65d6",
- strip_prefix = "bazel-integration-testing-2a4f6c244312c036e0f3a125ee6086637ee7723b",
- url = "https://github.com/bazelbuild/bazel-integration-testing/archive/2a4f6c244312c036e0f3a125ee6086637ee7723b.zip",
-)
-
-load("@build_bazel_integration_testing//tools:bazel_java_integration_test.bzl", "bazel_java_integration_test_deps")
-
-bazel_java_integration_test_deps(versions = [
- "0.28.1",
- "0.27.2",
-])
-
-load("@build_bazel_integration_testing//tools:import.bzl", "bazel_external_dependency_archive")
+load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
-bazel_external_dependency_archive(
- name = "integration_test_deps",
- srcs = {
- # Bazel 0.28.1, 0.27.2
- "cc470e529fafb6165b5be3929ff2d99b38429b386ac100878687416603a67889": [
- "https://mirror.bazel.build/bazel_coverage_output_generator/releases/coverage_output_generator-v1.0.zip",
- ],
- # Bazel 0.28.1
- "96e223094a12c842a66db0bb7bb6866e88e26e678f045842911f9bd6b47161f5": [
- "https://mirror.bazel.build/bazel_java_tools/releases/javac11/v4.0/java_tools_javac11_linux-v4.0.zip",
- ],
- # Bazel 0.27.2
- "074d624fb34441df369afdfd454e75dba821d5d54932fcfee5ba598d17dc1b99": [
- "https://mirror.bazel.build/bazel_java_tools/releases/javac11/v2.0/java_tools_javac11_linux-v2.0.zip",
- ],
- },
-)
+bazel_skylib_workspace()
-# LICENSE: The Apache Software License, Version 2.0
http_archive(
- name = "rules_proto",
- sha256 = "aa1ee19226f707d44bee44c720915199c20c84a23318bb0597ed4e5c873ccbd5",
- strip_prefix = "rules_proto-40298556293ae502c66579620a7ce867d5f57311",
+ name = "contrib_rules_bazel_integration_test",
+ sha256 = "20d670bb614d311a2a0fc8af53760439214731c3d5be2d9b0a197dccc19583f5",
+ strip_prefix = "rules_bazel_integration_test-0.9.0",
urls = [
- "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/40298556293ae502c66579620a7ce867d5f57311.tar.gz",
- "https://github.com/bazelbuild/rules_proto/archive/40298556293ae502c66579620a7ce867d5f57311.tar.gz",
+ "http://github.com/bazel-contrib/rules_bazel_integration_test/archive/v0.9.0.tar.gz",
],
)
-load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
+load("@contrib_rules_bazel_integration_test//bazel_integration_test:deps.bzl", "bazel_integration_test_rules_dependencies")
-rules_proto_dependencies()
+bazel_integration_test_rules_dependencies()
-rules_proto_toolchains()
+load("@contrib_rules_bazel_integration_test//bazel_integration_test:defs.bzl", "bazel_binaries")
+
+bazel_binaries(versions = [
+ "4.0.0",
+ "6.0.0",
+])
# LICENSE: The Apache Software License, Version 2.0
+rules_scala_version = "8f255cd1fecfe4d43934b161b3edda58bdb2e8f4"
+
http_archive(
name = "io_bazel_rules_scala",
- sha256 = "ccf19e8f966022eaaca64da559c6140b23409829cb315f2eff5dc3e757fb6ad8",
- strip_prefix = "rules_scala-e4560ac332e9da731c1e50a76af2579c55836a5c",
- urls = ["https://github.com/bazelbuild/rules_scala/archive/e4560ac332e9da731c1e50a76af2579c55836a5c.zip"],
+ sha256 = "14797e907c5614387452c42412d755ad7e343ea12540a53da1430be3301c8b4b",
+ strip_prefix = "rules_scala-%s" % rules_scala_version,
+ type = "zip",
+ url = "https://github.com/bazelbuild/rules_scala/archive/%s.zip" % rules_scala_version,
)
load("@io_bazel_rules_scala//:scala_config.bzl", "scala_config")
@@ -463,9 +650,9 @@ scalatest_repositories()
scalatest_toolchain()
# LICENSE: The Apache Software License, Version 2.0
-rules_kotlin_version = "1.6.0"
+rules_kotlin_version = "1.7.0-RC-1"
-rules_kotlin_sha = "a57591404423a52bd6b18ebba7979e8cd2243534736c5c94d35c89718ea38f94"
+rules_kotlin_sha = "68b910730026921814d3a504ccbe9adaac9938983d940e626523e6e4ecfb0355"
http_archive(
name = "io_bazel_rules_kotlin",
@@ -508,3 +695,65 @@ jvm_maven_import_external(
licenses = ["notice"], # Apache 2.0
server_urls = ["https://repo1.maven.org/maven2"],
)
+
+http_archive(
+ name = "io_bazel_rules_go",
+ sha256 = "6b65cb7917b4d1709f9410ffe00ecf3e160edf674b78c54a894471320862184f",
+ urls = [
+ "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.39.0/rules_go-v0.39.0.zip",
+ "https://github.com/bazelbuild/rules_go/releases/download/v0.39.0/rules_go-v0.39.0.zip",
+ ],
+)
+
+# needed for cpp tests
+http_archive(
+ name = "com_google_absl",
+ sha256 = "987ce98f02eefbaf930d6e38ab16aa05737234d7afbab2d5c4ea7adbe50c28ed",
+ strip_prefix = "abseil-cpp-20230802.1",
+ urls = [
+ "https://github.com/abseil/abseil-cpp/archive/refs/tags/20230802.1.tar.gz",
+ ],
+)
+
+jvm_maven_import_external(
+ name = "io_netty_netty_common",
+ artifact = "io.netty:netty-common:4.1.96.Final",
+ artifact_sha256 = "da104e80db830922eaf860eb1c5e957cd1d124068253d02e9c7a7843bc66427a",
+ licenses = ["notice"], # Apache 2.0
+ server_urls = ["https://repo1.maven.org/maven2"],
+)
+
+jvm_maven_import_external(
+ name = "io_netty_netty_transport",
+ artifact = "io.netty:netty-transport:4.1.96.Final",
+ artifact_sha256 = "8fe3afbe8b094a7b9f1eb27becf1cf017e5572343c1744d2b6040d5f331e84e3",
+ licenses = ["notice"], # Apache 2.0
+ server_urls = ["https://repo1.maven.org/maven2"],
+)
+
+jvm_maven_import_external(
+ name = "io_netty_netty_transport_native_epoll",
+ artifact = "io.netty:netty-transport-classes-epoll:4.1.96.Final",
+ artifact_sha256 = "1591b3ea061932677dc2bab6cb7d82e8f1837a52b3c781f4daa99984ec87a9cd",
+ licenses = ["notice"], # Apache 2.0
+ server_urls = ["https://repo1.maven.org/maven2"],
+)
+
+jvm_maven_import_external(
+ name = "io_netty_netty_transport_native_unix_common",
+ artifact = "io.netty:netty-transport-native-unix-common:4.1.96.Final",
+ artifact_sha256 = "4f96297a06a544a4cdb6fe6af8b868640f100fa96969e2196be216bd41adef13",
+ licenses = ["notice"], # Apache 2.0
+ server_urls = ["https://repo1.maven.org/maven2"],
+)
+
+jvm_maven_import_external(
+ name = "io_netty_netty_transport_classes_kqueue",
+ artifact = "io.netty:netty-transport-classes-kqueue:4.1.96.Final",
+ artifact_sha256 = "f2f1fab3b297aee20a3922c79b548c8b4b72bb10b635375434c108ee05f29430",
+ licenses = ["notice"], # Apache 2.0
+ server_urls = ["https://repo1.maven.org/maven2"],
+)
+
+# Register custom java 17 toolchain
+register_toolchains("//:custom_java_17_toolchain_definition")
diff --git a/aspect/BUILD b/aspect/BUILD
index bfc18c42d0a..7b857a764ae 100644
--- a/aspect/BUILD
+++ b/aspect/BUILD
@@ -7,7 +7,7 @@ load(
"define_flag_hack",
)
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
# Files needed at runtime for blaze-invoking integration tests
filegroup(
@@ -31,9 +31,11 @@ filegroup(
srcs = [
"WORKSPACE",
"artifacts.bzl",
- "fast_build_info.bzl",
+ "build_dependencies.bzl",
+ "fast_build_info_bundled.bzl",
+ "intellij_info.bzl",
"intellij_info_bundled.bzl",
- "intellij_info_impl.bzl",
+ "intellij_info_impl_bundled.bzl",
"java_classpath.bzl",
"make_variables.bzl",
":BUILD.bazel",
@@ -61,13 +63,35 @@ _dev_aspect_path = package_name()
# Changes:
# //.../aspect/tools:tool_name -> //:tool_name_bin
# //.../aspect:flag_hack -> //:flag_hack
+# :intellij_info_impl.bzl -> :intellij_info_impl_bundled.bzl
genrule(
name = "modify_tools_path",
srcs = ["intellij_info.bzl"],
outs = ["intellij_info_bundled.bzl"],
cmd = "cat $(SRCS) >$@ && " +
"sed -i -e 's,//%s/tools:\" + tool_name,//:\" + tool_name + \"_bin\",g' $@ && " % _dev_aspect_path +
- "sed -i -e 's,//%s:flag_hack,//:flag_hack,g' $@" % _dev_aspect_path,
+ "sed -i -e 's,//%s:flag_hack,//:flag_hack,g' $@ && " % _dev_aspect_path +
+ "sed -i -e 's,:intellij_info_impl.bzl,:intellij_info_impl_bundled.bzl,g' $@",
+)
+
+# Removes internal only content from bundled aspect files as they cannot access
+# by bazel no matter it's build from git repo or internal repo.
+genrule(
+ name = "create_intellij_info_impl_bundle",
+ srcs = ["intellij_info_impl.bzl"],
+ outs = ["intellij_info_impl_bundled.bzl"],
+ cmd = "cat $(SRCS) >$@ && " +
+ "sed -i -e '/BUNDLED-IGNORE-BEGIN/,/BUNDLED-IGNORE-END/d' $@ && " +
+ "sed -i -e 's,load(\".*/rules_java/,load(\"@rules_java//', $@",
+)
+
+# Makes bundled fast_build_info.bzl use bundled intellij_info_impl.bzl
+genrule(
+ name = "create_fast_build_info_bundle",
+ srcs = ["fast_build_info.bzl"],
+ outs = ["fast_build_info_bundled.bzl"],
+ cmd = "cat $(SRCS) >$@ && " +
+ "sed -i -e 's,:intellij_info_impl.bzl,:intellij_info_impl_bundled.bzl,g' $@",
)
define_flag_hack()
diff --git a/aspect/BUILD.aspect b/aspect/BUILD.aspect
index cbcadb0c6ea..8369d08edf1 100644
--- a/aspect/BUILD.aspect
+++ b/aspect/BUILD.aspect
@@ -3,16 +3,19 @@
# The final form of the BUILD file accessed at runtime as an external WORKSPACE.
#
-licenses(["notice"]) # Apache 2.0
+load("@rules_java//java:defs.bzl", "java_binary", "java_import")
+load(
+ ":intellij_info_impl_bundled.bzl",
+ "define_flag_hack",
+)
-load(":intellij_info_impl.bzl",
- "define_flag_hack")
+licenses(["notice"]) # Apache 2.0
java_binary(
name = "JarFilter_bin",
main_class = "com.google.idea.blaze.aspect.JarFilter",
- runtime_deps = [":jar_filter_lib"],
visibility = ["//visibility:public"],
+ runtime_deps = [":jar_filter_lib"],
)
java_import(
@@ -23,8 +26,8 @@ java_import(
java_binary(
name = "PackageParser_bin",
main_class = "com.google.idea.blaze.aspect.PackageParser",
- runtime_deps = [":package_parser_lib"],
visibility = ["//visibility:public"],
+ runtime_deps = [":package_parser_lib"],
)
java_import(
@@ -35,11 +38,10 @@ java_import(
java_binary(
name = "CreateAar_bin",
main_class = "com.google.idea.blaze.aspect.CreateAar",
- runtime_deps = [":jar_filter_lib"],
visibility = ["//visibility:public"],
+ runtime_deps = [":jar_filter_lib"],
)
-
java_import(
name = "create_aar_lib",
jars = ["tools/CreateAar_deploy.jar"],
diff --git a/aspect/build_dependencies.bzl b/aspect/build_dependencies.bzl
new file mode 100644
index 00000000000..778d91c775f
--- /dev/null
+++ b/aspect/build_dependencies.bzl
@@ -0,0 +1,810 @@
+"""Aspects to build and collect project dependencies."""
+
+load(
+ "@bazel_tools//tools/build_defs/cc:action_names.bzl",
+ "CPP_COMPILE_ACTION_NAME",
+ "C_COMPILE_ACTION_NAME",
+)
+load("@rules_java//java:defs.bzl", "JavaInfo")
+
+ALWAYS_BUILD_RULES = "java_proto_library,java_lite_proto_library,java_mutable_proto_library,kt_proto_library_helper,_java_grpc_library,_java_lite_grpc_library,kt_grpc_library_helper,java_stubby_library,kt_stubby_library_helper,aar_import,java_import"
+
+PROTO_RULE_KINDS = [
+ "java_proto_library",
+ "java_lite_proto_library",
+ "java_mutable_proto_library",
+ "kt_proto_library_helper",
+]
+
+def _package_dependencies_impl(target, ctx):
+ java_info_file = _write_java_target_info(target, ctx)
+ cc_info_file = _write_cc_target_info(target, ctx)
+
+ return [OutputGroupInfo(
+ qsync_jars = target[DependenciesInfo].compile_time_jars.to_list(),
+ artifact_info_file = java_info_file,
+ qsync_aars = target[DependenciesInfo].aars.to_list(),
+ qsync_gensrcs = target[DependenciesInfo].gensrcs.to_list(),
+ cc_headers = target[DependenciesInfo].cc_headers.to_list(),
+ cc_info_file = cc_info_file + [target[DependenciesInfo].cc_toolchain_info.file] if target[DependenciesInfo].cc_toolchain_info else [],
+ )]
+
+def _write_java_target_info(target, ctx):
+ if not target[DependenciesInfo].target_to_artifacts:
+ return []
+ file_name = target.label.name + ".java-info.txt"
+ artifact_info_file = ctx.actions.declare_file(file_name)
+ ctx.actions.write(
+ artifact_info_file,
+ _encode_target_info_proto(target[DependenciesInfo].target_to_artifacts),
+ )
+ return [artifact_info_file]
+
+def _write_cc_target_info(target, ctx):
+ if not target[DependenciesInfo].cc_info:
+ return []
+ cc_info_file_name = target.label.name + ".cc-info.txt"
+ cc_info_file = ctx.actions.declare_file(cc_info_file_name)
+ ctx.actions.write(
+ cc_info_file,
+ _encode_cc_info_proto(target.label, target[DependenciesInfo].cc_info),
+ )
+ return [cc_info_file]
+
+DependenciesInfo = provider(
+ "The out-of-project dependencies",
+ fields = {
+ "compile_time_jars": "a list of jars generated by targets",
+ "target_to_artifacts": "a map between a target and all its artifacts",
+ "aars": "a list of aars with resource files",
+ "gensrcs": "a list of sources generated by project targets",
+ "expand_sources": "boolean, true if the sources for this target should be expanded when it appears inside another rules srcs list",
+ "cc_info": "a structure containing info required to compile cc sources",
+ "cc_headers": "a depset of generated headers required to compile cc sources",
+ "cc_toolchain_info": "struct containing cc toolchain info, with keys file (the output file) and id (unique ID for the toolchain info, referred to from elsewhere)",
+ "test_mode_own_files": "a structure describing Java artifacts required when the target is requested within the project scope",
+ "test_mode_cc_src_deps": "a list of sources (e.g. headers) required to compile cc sources in integratrion tests",
+ },
+)
+
+def create_dependencies_info(
+ compile_time_jars = depset(),
+ target_to_artifacts = {},
+ aars = depset(),
+ gensrcs = depset(),
+ expand_sources = False,
+ cc_info = None,
+ cc_headers = depset(),
+ cc_toolchain_info = None,
+ test_mode_own_files = None,
+ test_mode_cc_src_deps = depset()):
+ """A helper function to create a DependenciesInfo provider instance."""
+ return DependenciesInfo(
+ compile_time_jars = compile_time_jars,
+ target_to_artifacts = target_to_artifacts,
+ aars = aars,
+ gensrcs = gensrcs,
+ expand_sources = expand_sources,
+ cc_info = cc_info,
+ cc_headers = cc_headers,
+ cc_toolchain_info = cc_toolchain_info,
+ test_mode_own_files = test_mode_own_files,
+ test_mode_cc_src_deps = test_mode_cc_src_deps,
+ )
+
+def _encode_target_info_proto(target_to_artifacts):
+ contents = []
+ for label, target_info in target_to_artifacts.items():
+ contents.append(
+ struct(
+ target = label,
+ jars = target_info["jars"],
+ ide_aars = target_info["ide_aars"],
+ gen_srcs = target_info["gen_srcs"],
+ srcs = target_info["srcs"],
+ srcjars = target_info["srcjars"],
+ android_resources_package = target_info["android_resources_package"],
+ ),
+ )
+ return proto.encode_text(struct(artifacts = contents))
+
+def _encode_cc_info_proto(label, cc_info):
+ return proto.encode_text(
+ struct(targets = [
+ struct(
+ label = str(label),
+ defines = cc_info.transitive_defines,
+ include_directories = cc_info.transitive_include_directory,
+ quote_include_directories = cc_info.transitive_quote_include_directory,
+ system_include_directories = cc_info.transitive_system_include_directory,
+ framework_include_directories = cc_info.framework_include_directory,
+ gen_hdrs = cc_info.gen_headers,
+ toolchain_id = cc_info.toolchain_id,
+ ),
+ ]),
+ )
+
+package_dependencies = aspect(
+ implementation = _package_dependencies_impl,
+ required_aspect_providers = [[DependenciesInfo]],
+)
+
+def declares_android_resources(target, ctx):
+ """
+ Returns true if the target has resource files and an android provider.
+
+ The IDE needs aars from targets that declare resources. AndroidIdeInfo
+ has a defined_android_resources flag, but this returns true for additional
+ cases (aidl files, etc), so we check if the target has resource files.
+
+ Args:
+ target: the target.
+ ctx: the context.
+ Returns:
+ True if the target has resource files and an android provider.
+ """
+ if _get_android_provider(target) == None:
+ return False
+ return hasattr(ctx.rule.attr, "resource_files") and len(ctx.rule.attr.resource_files) > 0
+
+def _get_android_provider(target):
+ if hasattr(android_common, "AndroidIdeInfo"):
+ if android_common.AndroidIdeInfo in target:
+ return target[android_common.AndroidIdeInfo]
+ else:
+ return None
+ elif hasattr(target, "android"):
+ # Backwards compatibility: supports android struct provider
+ legacy_android = getattr(target, "android")
+
+ # Transform into AndroidIdeInfo form
+ return struct(
+ aar = legacy_android.aar,
+ java_package = legacy_android.java_package,
+ manifest = legacy_android.manifest,
+ idl_source_jar = getattr(legacy_android.idl.output, "source_jar", None),
+ idl_class_jar = getattr(legacy_android.idl.output, "class_jar", None),
+ defines_android_resources = legacy_android.defines_resources,
+ idl_import_root = getattr(legacy_android.idl, "import_root", None),
+ idl_generated_java_files = getattr(legacy_android.idl, "generated_java_files", []),
+ resource_jar = legacy_android.resource_jar,
+ signed_apk = legacy_android.apk,
+ apks_under_test = legacy_android.apks_under_test,
+ )
+ return None
+
+def declares_aar_import(ctx):
+ """
+ Returns true if the target has aar and is aar_import rule.
+
+ Args:
+ ctx: the context.
+ Returns:
+ True if the target has aar and is aar_import rule.
+ """
+ return ctx.rule.kind == "aar_import" and hasattr(ctx.rule.attr, "aar")
+
+def _collect_dependencies_impl(target, ctx):
+ return _collect_dependencies_core_impl(
+ target,
+ ctx,
+ ctx.attr.include,
+ ctx.attr.exclude,
+ ctx.attr.always_build_rules,
+ ctx.attr.generate_aidl_classes,
+ ctx.attr.use_generated_srcjars,
+ test_mode = False,
+ )
+
+def _collect_all_dependencies_for_tests_impl(target, ctx):
+ return _collect_dependencies_core_impl(
+ target,
+ ctx,
+ include = None,
+ exclude = None,
+ always_build_rules = ALWAYS_BUILD_RULES,
+ generate_aidl_classes = None,
+ use_generated_srcjars = False,
+ test_mode = True,
+ )
+
+def _target_within_project_scope(label, include, exclude):
+ result = False
+ if include:
+ for inc in include.split(","):
+ if label.startswith(inc):
+ if label[len(inc)] in [":", "/"]:
+ result = True
+ break
+ if result and len(exclude) > 0:
+ for exc in exclude.split(","):
+ if label.startswith(exc):
+ if label[len(exc)] in [":", "/"]:
+ result = False
+ break
+ return result
+
+def _get_followed_kotlin_toolchain_dependency_info(rule):
+ return []
+
+def _get_followed_java_dependency_infos(rule):
+ deps = []
+ for (attr, kinds) in FOLLOW_JAVA_ATTRIBUTES_BY_RULE_KIND:
+ if hasattr(rule.attr, attr) and (not kinds or rule.kind in kinds):
+ to_add = getattr(rule.attr, attr)
+ if type(to_add) == "list":
+ deps += [t for t in to_add if type(t) == "Target"]
+ elif type(to_add) == "Target":
+ deps.append(to_add)
+
+ deps.extend(_get_followed_kotlin_toolchain_dependency_info(rule))
+
+ return {
+ str(dep.label): dep[DependenciesInfo]
+ for dep in deps
+ if DependenciesInfo in dep and dep[DependenciesInfo].target_to_artifacts
+ }
+
+def _collect_own_java_artifacts(
+ target,
+ ctx,
+ dependency_infos,
+ always_build_rules,
+ generate_aidl_classes,
+ use_generated_srcjars,
+ target_is_within_project_scope):
+ rule = ctx.rule
+
+ # Toolchains are collected for proto targets via aspect traversal, but jars
+ # produced for proto deps of the underlying proto_library are not
+ can_follow_dependencies = bool(dependency_infos) and not ctx.rule.kind in PROTO_RULE_KINDS
+
+ must_build_main_artifacts = (
+ not target_is_within_project_scope or rule.kind in always_build_rules.split(",")
+ )
+
+ own_jar_files = []
+ own_jar_depsets = []
+ own_ide_aar_files = []
+ own_gensrc_files = []
+ own_src_files = []
+ own_srcjar_files = []
+ resource_package = ""
+
+ if must_build_main_artifacts:
+ # For rules that we do not follow dependencies of (either because they don't
+ # have further dependencies with JavaInfo or do so in attributes we don't care)
+ # we gather all their transitive dependencies. If they have dependencies, we
+ # only gather their own compile jars and continue down the tree.
+ # This is done primarily for rules like proto, whose toolchain classes
+ # are collected via attribute traversal, but still requires jars for any
+ # proto deps of the underlying proto_library.
+ if JavaInfo in target:
+ if can_follow_dependencies:
+ own_jar_depsets.append(target[JavaInfo].compile_jars)
+ else:
+ own_jar_depsets.append(target[JavaInfo].transitive_compile_time_jars)
+
+ if declares_android_resources(target, ctx):
+ ide_aar = _get_ide_aar_file(target, ctx)
+ if ide_aar:
+ own_ide_aar_files.append(ide_aar)
+ elif declares_aar_import(ctx):
+ own_ide_aar_files.append(rule.attr.aar.files.to_list()[0])
+
+ else:
+ android = _get_android_provider(target)
+ if android != None:
+ resource_package = android.java_package
+
+ if generate_aidl_classes:
+ add_base_idl_jar = False
+ idl_jar = android.idl_class_jar
+ if idl_jar != None:
+ own_jar_files.append(idl_jar)
+ add_base_idl_jar = True
+
+ generated_java_files = android.idl_generated_java_files
+ if generated_java_files:
+ own_gensrc_files += generated_java_files
+ add_base_idl_jar = True
+
+ # An AIDL base jar needed for resolving base classes for aidl generated stubs.
+ if add_base_idl_jar:
+ if hasattr(rule.attr, "_aidl_lib"):
+ own_jar_depsets.append(rule.attr._aidl_lib.files)
+ elif hasattr(rule.attr, "_android_sdk") and hasattr(android_common, "AndroidSdkInfo"):
+ android_sdk_info = getattr(rule.attr, "_android_sdk")[android_common.AndroidSdkInfo]
+ own_jar_depsets.append(android_sdk_info.aidl_lib.files)
+
+ # Add generated java_outputs (e.g. from annotation processing)
+ generated_class_jars = []
+ if JavaInfo in target:
+ for java_output in target[JavaInfo].java_outputs:
+ # Prefer source jars if they exist:
+ if use_generated_srcjars and java_output.generated_source_jar:
+ own_gensrc_files.append(java_output.generated_source_jar)
+ elif java_output.generated_class_jar:
+ generated_class_jars.append(java_output.generated_class_jar)
+
+ if generated_class_jars:
+ own_jar_files += generated_class_jars
+
+ # Add generated sources for included targets
+ if hasattr(rule.attr, "srcs"):
+ for src in rule.attr.srcs:
+ for file in src.files.to_list():
+ if not file.is_source:
+ expand_sources = False
+ if str(file.owner) in dependency_infos:
+ src_depinfo = dependency_infos[str(file.owner)]
+ expand_sources = src_depinfo.expand_sources
+
+ # If the target that generates this source specifies that
+ # the sources should be expanded, we ignore the generated
+ # sources - the IDE will substitute the target sources
+ # themselves instead.
+ if not expand_sources:
+ own_gensrc_files.append(file)
+
+ if not target_is_within_project_scope:
+ if hasattr(rule.attr, "srcs"):
+ for src in rule.attr.srcs:
+ for file in src.files.to_list():
+ if file.is_source:
+ own_src_files.append(file.path)
+ else:
+ own_gensrc_files.append(file)
+ if hasattr(rule.attr, "srcjar"):
+ if rule.attr.srcjar and type(rule.attr.srcjar) == "Target":
+ for file in rule.attr.srcjar.files.to_list():
+ if file.is_source:
+ own_srcjar_files.append(file.path)
+ else:
+ own_gensrc_files.append(file)
+
+ return struct(
+ jars = own_jar_files,
+ jar_depsets = own_jar_depsets,
+ ide_aars = own_ide_aar_files,
+ gensrcs = own_gensrc_files,
+ srcs = own_src_files,
+ srcjars = own_srcjar_files,
+ android_resources_package = resource_package,
+ )
+
+def _collect_own_and_dependency_java_artifacts(
+ target,
+ ctx,
+ dependency_infos,
+ always_build_rules,
+ generate_aidl_classes,
+ use_generated_srcjars,
+ target_is_within_project_scope):
+ own_files = _collect_own_java_artifacts(
+ target,
+ ctx,
+ dependency_infos,
+ always_build_rules,
+ generate_aidl_classes,
+ use_generated_srcjars,
+ target_is_within_project_scope,
+ )
+
+ has_own_artifacts = (
+ len(own_files.jars) +
+ len(own_files.jar_depsets) +
+ len(own_files.ide_aars) +
+ len(own_files.gensrcs) +
+ len(own_files.srcs) +
+ len(own_files.srcjars) +
+ (1 if own_files.android_resources_package else 0)
+ ) > 0
+
+ target_to_artifacts = {}
+ if has_own_artifacts:
+ jars = depset(own_files.jars, transitive = own_files.jar_depsets).to_list()
+
+ # Pass the following lists through depset() too to remove any duplicates.
+ ide_aars = depset(own_files.ide_aars).to_list()
+ gen_srcs = depset(own_files.gensrcs).to_list()
+ target_to_artifacts[str(target.label)] = {
+ "jars": [_output_relative_path(file.path) for file in jars],
+ "ide_aars": [_output_relative_path(file.path) for file in ide_aars],
+ "gen_srcs": [_output_relative_path(file.path) for file in gen_srcs],
+ "srcs": own_files.srcs,
+ "srcjars": own_files.srcjars,
+ "android_resources_package": own_files.android_resources_package,
+ }
+
+ own_and_transitive_jar_depsets = list(own_files.jar_depsets) # Copy to prevent changes to own_jar_depsets.
+ own_and_transitive_ide_aar_depsets = []
+ own_and_transitive_gensrc_depsets = []
+
+ for info in dependency_infos.values():
+ target_to_artifacts.update(info.target_to_artifacts)
+ own_and_transitive_jar_depsets.append(info.compile_time_jars)
+ own_and_transitive_ide_aar_depsets.append(info.aars)
+ own_and_transitive_gensrc_depsets.append(info.gensrcs)
+
+ return (
+ target_to_artifacts,
+ depset(own_files.jars, transitive = own_and_transitive_jar_depsets),
+ depset(own_files.ide_aars, transitive = own_and_transitive_ide_aar_depsets),
+ depset(own_files.gensrcs, transitive = own_and_transitive_gensrc_depsets),
+ )
+
+def _get_followed_cc_toolchain_dependency_info(rule):
+ return None
+
+def _get_followed_cc_dependency_info(rule):
+ if hasattr(rule.attr, "_cc_toolchain"):
+ cc_toolchain_target = getattr(rule.attr, "_cc_toolchain")
+ if DependenciesInfo in cc_toolchain_target:
+ return cc_toolchain_target[DependenciesInfo]
+ return _get_followed_cc_toolchain_dependency_info(rule)
+
+def _collect_own_and_dependency_cc_info(target, dependency_info, test_mode):
+ compilation_context = target[CcInfo].compilation_context
+ cc_toolchain_info = None
+ test_mode_cc_src_deps = depset()
+ if dependency_info:
+ cc_toolchain_info = dependency_info.cc_toolchain_info
+ if test_mode:
+ test_mode_cc_src_deps = dependency_info.test_mode_cc_src_deps
+
+ gen_headers = depset()
+ compilation_info = None
+ if compilation_context:
+ gen_headers = depset([f for f in compilation_context.headers.to_list() if not f.is_source])
+
+ if test_mode:
+ test_mode_cc_src_deps = depset(
+ [f for f in compilation_context.headers.to_list() if f.is_source],
+ transitive = [test_mode_cc_src_deps],
+ )
+
+ compilation_info = struct(
+ transitive_defines = compilation_context.defines.to_list(),
+ transitive_include_directory = compilation_context.includes.to_list(),
+ transitive_quote_include_directory = compilation_context.quote_includes.to_list(),
+ transitive_system_include_directory = compilation_context.system_includes.to_list() + compilation_context.external_includes.to_list(),
+ framework_include_directory = compilation_context.framework_includes.to_list(),
+ gen_headers = [f.path for f in gen_headers.to_list()],
+ toolchain_id = cc_toolchain_info.id if cc_toolchain_info else None,
+ )
+ return struct(
+ compilation_info = compilation_info,
+ gen_headers = gen_headers,
+ test_mode_cc_src_deps = test_mode_cc_src_deps,
+ cc_toolchain_info = cc_toolchain_info,
+ )
+
+def _collect_dependencies_core_impl(
+ target,
+ ctx,
+ include,
+ exclude,
+ always_build_rules,
+ generate_aidl_classes,
+ use_generated_srcjars,
+ test_mode):
+ dep_infos = _collect_java_dependencies_core_impl(
+ target,
+ ctx,
+ include,
+ exclude,
+ always_build_rules,
+ generate_aidl_classes,
+ use_generated_srcjars,
+ test_mode,
+ )
+ if CcInfo in target:
+ dep_infos.append(_collect_cc_dependencies_core_impl(target, ctx, test_mode))
+ if cc_common.CcToolchainInfo in target:
+ dep_infos.append(_collect_cc_toolchain_info(target, ctx))
+ return dep_infos
+
+def _collect_java_dependencies_core_impl(
+ target,
+ ctx,
+ include,
+ exclude,
+ always_build_rules,
+ generate_aidl_classes,
+ use_generated_srcjars,
+ test_mode):
+ target_is_within_project_scope = _target_within_project_scope(str(target.label), include, exclude) and not test_mode
+ dependency_infos = _get_followed_java_dependency_infos(ctx.rule)
+
+ target_to_artifacts, compile_jars, aars, gensrcs = _collect_own_and_dependency_java_artifacts(
+ target,
+ ctx,
+ dependency_infos,
+ always_build_rules,
+ generate_aidl_classes,
+ use_generated_srcjars,
+ target_is_within_project_scope,
+ )
+
+ test_mode_own_files = None
+ if test_mode:
+ within_scope_own_files = _collect_own_java_artifacts(
+ target,
+ ctx,
+ dependency_infos,
+ always_build_rules,
+ generate_aidl_classes,
+ use_generated_srcjars,
+ target_is_within_project_scope = True,
+ )
+ test_mode_own_files = struct(
+ test_mode_within_scope_own_jar_files = depset(within_scope_own_files.jars, transitive = within_scope_own_files.jar_depsets).to_list(),
+ test_mode_within_scope_own_ide_aar_files = within_scope_own_files.ide_aars,
+ test_mode_within_scope_own_gensrc_files = within_scope_own_files.gensrcs,
+ )
+
+ expand_sources = False
+ if hasattr(ctx.rule.attr, "tags"):
+ if "ij-ignore-source-transform" in ctx.rule.attr.tags:
+ expand_sources = True
+
+ return [
+ create_dependencies_info(
+ target_to_artifacts = target_to_artifacts,
+ compile_time_jars = compile_jars,
+ aars = aars,
+ gensrcs = gensrcs,
+ expand_sources = expand_sources,
+ test_mode_own_files = test_mode_own_files,
+ ),
+ ]
+
+def _collect_cc_dependencies_core_impl(target, ctx, test_mode):
+ dependency_info = _get_followed_cc_dependency_info(ctx.rule)
+
+ cc_info = _collect_own_and_dependency_cc_info(target, dependency_info, test_mode)
+
+ return create_dependencies_info(
+ cc_info = cc_info.compilation_info,
+ cc_headers = cc_info.gen_headers,
+ cc_toolchain_info = cc_info.cc_toolchain_info,
+ test_mode_cc_src_deps = cc_info.test_mode_cc_src_deps,
+ )
+
+def _collect_cc_toolchain_info(target, ctx):
+ toolchain_info = target[cc_common.CcToolchainInfo]
+
+ cpp_fragment = ctx.fragments.cpp
+
+ # TODO(b/301235884): This logic is not quite right. `ctx` here is the context for the
+ # cc_toolchain target itself, so the `features` and `disabled_features` were using here are
+ # for the cc_toolchain, not the individual targets that this information will ultimately be
+ # used for. Instead, we should attach `toolchain_info` itself to the `DependenciesInfo`
+ # provider, and execute this logic once per top level cc target that we're building, to ensure
+ # that the right features are used.
+ feature_config = cc_common.configure_features(
+ ctx = ctx,
+ cc_toolchain = toolchain_info,
+ requested_features = ctx.features,
+ unsupported_features = ctx.disabled_features + [
+ # Note: module_maps appears to be necessary here to ensure the API works
+ # in all cases, and to avoid the error:
+ # Invalid toolchain configuration: Cannot find variable named 'module_name'
+ # yaqs/3227912151964319744
+ "module_maps",
+ ],
+ )
+ c_variables = cc_common.create_compile_variables(
+ feature_configuration = feature_config,
+ cc_toolchain = toolchain_info,
+ user_compile_flags = cpp_fragment.copts + cpp_fragment.conlyopts,
+ )
+ cpp_variables = cc_common.create_compile_variables(
+ feature_configuration = feature_config,
+ cc_toolchain = toolchain_info,
+ user_compile_flags = cpp_fragment.copts + cpp_fragment.cxxopts,
+ )
+ c_options = cc_common.get_memory_inefficient_command_line(
+ feature_configuration = feature_config,
+ action_name = C_COMPILE_ACTION_NAME,
+ variables = c_variables,
+ )
+ cpp_options = cc_common.get_memory_inefficient_command_line(
+ feature_configuration = feature_config,
+ action_name = CPP_COMPILE_ACTION_NAME,
+ variables = cpp_variables,
+ )
+ toolchain_id = str(target.label) + "%" + toolchain_info.target_gnu_system_name
+
+ cc_toolchain_info = struct(
+ id = toolchain_id,
+ compiler_executable = toolchain_info.compiler_executable,
+ cpu = toolchain_info.cpu,
+ compiler = toolchain_info.compiler,
+ target_name = toolchain_info.target_gnu_system_name,
+ built_in_include_directories = toolchain_info.built_in_include_directories,
+ c_options = c_options,
+ cpp_options = cpp_options,
+ )
+
+ cc_toolchain_file_name = target.label.name + "." + cc_toolchain_info.target_name + ".txt"
+ cc_toolchain_file = ctx.actions.declare_file(cc_toolchain_file_name)
+ ctx.actions.write(
+ cc_toolchain_file,
+ proto.encode_text(
+ struct(toolchains = cc_toolchain_info),
+ ),
+ )
+
+ return create_dependencies_info(
+ cc_toolchain_info = struct(file = cc_toolchain_file, id = toolchain_id),
+ test_mode_cc_src_deps = depset([f for f in toolchain_info.all_files.to_list() if f.is_source]),
+ )
+
+def _get_ide_aar_file(target, ctx):
+ """
+ Builds a resource only .aar file for the ide.
+
+ The IDE requires just resource files and the manifest from the IDE.
+ Moreover, there are cases when the existing rules fail to build a full .aar
+ file from a library, on which other targets can still depend.
+
+ The function builds a minimalistic .aar file that contains resources and the
+ manifest only.
+ """
+ android = _get_android_provider(target)
+ full_aar = android.aar
+ if full_aar:
+ resource_files = _collect_resource_files(ctx)
+ resource_map = _build_ide_aar_file_map(android.manifest, resource_files)
+ aar = ctx.actions.declare_file(full_aar.short_path.removesuffix(".aar") + "_ide/" + full_aar.basename)
+ _package_ide_aar(ctx, aar, resource_map)
+ return aar
+ else:
+ return None
+
+def _collect_resource_files(ctx):
+ """
+ Collects the list of resource files from the target rule attributes.
+ """
+
+ # Unfortunately, there are no suitable bazel providers that describe
+ # resource files used a target.
+ # However, AndroidIdeInfo returns a reference to a so-called resource APK
+ # file, which contains everything the IDE needs to load resources from a
+ # given library. However, this format is currently supported by Android
+ # Studio in the namespaced resource mode. We should consider conditionally
+ # enabling support in Android Studio and use them in ASwB, instead of
+ # building special .aar files for the IDE.
+ resource_files = []
+ for t in ctx.rule.attr.resource_files:
+ for f in t.files.to_list():
+ resource_files.append(f)
+ return resource_files
+
+def _build_ide_aar_file_map(manifest_file, resource_files):
+ """
+ Build the list of files and their paths as they have to appear in .aar.
+ """
+ file_map = {}
+ file_map["AndroidManifest.xml"] = manifest_file
+ for f in resource_files:
+ res_dir_path = f.short_path \
+ .removeprefix(android_common.resource_source_directory(f)) \
+ .removeprefix("/")
+ if res_dir_path:
+ res_dir_path = "res/" + res_dir_path
+ file_map[res_dir_path] = f
+ return file_map
+
+def _package_ide_aar(ctx, aar, file_map):
+ """
+ Declares a file and defines actions to build .aar according to file_map.
+ """
+ files_map_args = []
+ files = []
+ for aar_dir_path, f in file_map.items():
+ files.append(f)
+ files_map_args.append("%s=%s" % (aar_dir_path, f.path))
+
+ ctx.actions.run(
+ mnemonic = "GenerateIdeAar",
+ executable = ctx.executable._build_zip,
+ inputs = files,
+ outputs = [aar],
+ arguments = ["c", aar.path] + files_map_args,
+ )
+
+def _output_relative_path(path):
+ """Get file path relative to the output path.
+
+ Args:
+ path: path of artifact path = (../repo_name)? + (root_fragment)? + relative_path
+
+ Returns:
+ path relative to the output path
+ """
+ if (path.startswith("blaze-out/")) or (path.startswith("bazel-out/")):
+ # len("blaze-out/") or len("bazel-out/")
+ path = path[10:]
+ return path
+
+# List of tuples containing:
+# 1. An attribute for the aspect to traverse
+# 2. A list of rule kinds to specify which rules for which the attribute labels
+# need to be added as dependencies. If empty, the attribute is followed for
+# all rules.
+FOLLOW_JAVA_ATTRIBUTES_BY_RULE_KIND = [
+ ("deps", []),
+ ("exports", []),
+ ("srcs", []),
+ ("_junit", []),
+ ("_aspect_proto_toolchain_for_javalite", []),
+ ("_aspect_java_proto_toolchain", []),
+ ("runtime", ["proto_lang_toolchain", "java_rpc_toolchain"]),
+ ("_toolchain", ["_java_grpc_library", "_java_lite_grpc_library", "kt_jvm_library_helper", "android_library", "kt_android_library"]),
+ ("kotlin_libs", ["kt_jvm_toolchain"]),
+]
+
+FOLLOW_CC_ATTRIBUTES = ["_cc_toolchain"]
+
+FOLLOW_ATTRIBUTES = [attr for (attr, _) in FOLLOW_JAVA_ATTRIBUTES_BY_RULE_KIND] + FOLLOW_CC_ATTRIBUTES
+
+collect_dependencies = aspect(
+ implementation = _collect_dependencies_impl,
+ provides = [DependenciesInfo],
+ attr_aspects = FOLLOW_ATTRIBUTES,
+ attrs = {
+ "include": attr.string(
+ doc = "Comma separated list of workspace paths included in the project as source. Any targets inside here will not be built.",
+ mandatory = True,
+ ),
+ "exclude": attr.string(
+ doc = "Comma separated list of exclusions to 'include'.",
+ default = "",
+ ),
+ "always_build_rules": attr.string(
+ doc = "Comma separated list of rules. Any targets belonging to these rules will be built, regardless of location",
+ default = "",
+ ),
+ "generate_aidl_classes": attr.bool(
+ doc = "If True, generates classes for aidl files included as source for the project targets",
+ default = False,
+ ),
+ "use_generated_srcjars": attr.bool(
+ doc = "If True, collects generated source jars for a target instead of compiled jar",
+ default = False,
+ ),
+ "_build_zip": attr.label(
+ allow_files = True,
+ cfg = "exec",
+ executable = True,
+ default = "@@bazel_tools//tools/zip:zipper",
+ ),
+ },
+ fragments = ["cpp"],
+)
+
+collect_all_dependencies_for_tests = aspect(
+ doc = """
+ A variant of collect_dependencies aspect used by query sync integration
+ tests.
+
+ The difference is that collect_all_dependencies does not apply
+ include/exclude directory filtering, which is applied in the test framework
+ instead. See: test_project.bzl for more details.
+ """,
+ implementation = _collect_all_dependencies_for_tests_impl,
+ provides = [DependenciesInfo],
+ attr_aspects = FOLLOW_ATTRIBUTES,
+ attrs = {
+ "_build_zip": attr.label(
+ allow_files = True,
+ cfg = "exec",
+ executable = True,
+ default = "@@bazel_tools//tools/zip:zipper",
+ ),
+ },
+ fragments = ["cpp"],
+)
diff --git a/aspect/fast_build_info.bzl b/aspect/fast_build_info.bzl
index 054954b8c65..c764d67e5e1 100644
--- a/aspect/fast_build_info.bzl
+++ b/aspect/fast_build_info.bzl
@@ -1,14 +1,26 @@
"""An aspect to gather info needed by the FastBuildService."""
+load("@rules_java//java:defs.bzl", "JavaInfo", "java_common")
load(
":artifacts.bzl",
"artifact_location",
"sources_from_target",
"struct_omit_none",
)
+load(
+ ":intellij_info_impl.bzl",
+ "stringify_label",
+)
_DEP_ATTRS = ["deps", "exports", "runtime_deps", "_java_toolchain"]
+def _get_android_ide_info(target):
+ if hasattr(android_common, "AndroidIdeInfo") and android_common.AndroidIdeInfo in target:
+ return target[android_common.AndroidIdeInfo]
+ if hasattr(target, "android"):
+ return target.android
+ return None
+
def _fast_build_info_impl(target, ctx):
dep_targets = _get_all_dep_targets(target, ctx)
dep_outputs = _get_all_dep_outputs(dep_targets)
@@ -17,8 +29,8 @@ def _fast_build_info_impl(target, ctx):
info = {
"workspace_name": ctx.workspace_name,
- "label": str(target.label),
- "dependencies": [str(t.label) for t in dep_targets],
+ "label": stringify_label(target.label),
+ "dependencies": [stringify_label(t.label) for t in dep_targets],
}
write_output = False
@@ -28,7 +40,7 @@ def _fast_build_info_impl(target, ctx):
write_output = True
info["data"] = [
struct(
- label = str(datadep.label),
+ label = stringify_label(datadep.label),
artifacts = [artifact_location(file) for file in datadep.files.to_list()],
)
for datadep in ctx.rule.attr.data
@@ -60,10 +72,13 @@ def _fast_build_info_impl(target, ctx):
launcher = None
if hasattr(ctx.rule.attr, "use_launcher") and not ctx.rule.attr.use_launcher:
launcher = None
+ elif hasattr(ctx.rule.attr, "launcher") and ctx.rule.attr.launcher:
+ launcher = stringify_label(ctx.rule.attr.launcher.label)
elif hasattr(ctx.rule.attr, "_java_launcher") and ctx.rule.attr._java_launcher:
- launcher = str(ctx.rule.attr._java_launcher.label)
+ # TODO: b/295221112 - remove _java_launcher when it's removed from Java rules
+ launcher = stringify_label(ctx.rule.attr._java_launcher.label)
elif hasattr(ctx.rule.attr, "_javabase") and ctx.rule.attr._javabase:
- launcher = str(ctx.rule.attr._javabase.label)
+ launcher = stringify_label(ctx.rule.attr._javabase.label)
java_info = {
"sources": sources_from_target(ctx),
"test_class": getattr(ctx.rule.attr, "test_class", None),
@@ -80,17 +95,22 @@ def _fast_build_info_impl(target, ctx):
for t in annotation_processing.processor_classpath.to_list()
]
info["java_info"] = struct_omit_none(**java_info)
- if hasattr(target, "android"):
+
+ android_ide_info = _get_android_ide_info(target)
+ if android_ide_info:
write_output = True
android_info = struct_omit_none(
- aar = artifact_location(target.android.aar),
- merged_manifest = artifact_location(target.android.merged_manifest),
+ aar = artifact_location(android_ide_info.aar),
+ merged_manifest = artifact_location(
+ getattr(android_ide_info, "generated_manifest", None) or
+ getattr(android_ide_info, "merged_manifest", None),
+ ),
)
info["android_info"] = android_info
if write_output:
output_file = ctx.actions.declare_file(target.label.name + ".ide-fast-build-info.txt")
- ctx.actions.write(output_file, struct_omit_none(**info).to_proto())
+ ctx.actions.write(output_file, proto.encode_text(struct_omit_none(**info)))
output_files += [output_file]
output_groups = depset(output_files, transitive = dep_outputs)
diff --git a/aspect/intellij_info.bzl b/aspect/intellij_info.bzl
index f0852547713..652b83c95a4 100644
--- a/aspect/intellij_info.bzl
+++ b/aspect/intellij_info.bzl
@@ -8,6 +8,8 @@ load(
EXTRA_DEPS = [
"embed", # From go rules (bazel only)
+ "_cc_toolchain", # From rules_cc (bazel only)
+ "_kt_toolchain", # From rules_kotlin (bazel only)
]
def tool_label(tool_name):
@@ -31,6 +33,13 @@ def get_go_import_path(ctx):
import_path += "/" + ctx.label.name
return import_path
+def is_go_proto_library(target, _ctx):
+ return hasattr(target[OutputGroupInfo], "go_generated_srcs")
+
+def get_go_proto_library_generated_srcs(target):
+ files = target[OutputGroupInfo].go_generated_srcs.to_list()
+ return [f for f in files if f.basename.endswith(".go")]
+
def get_py_launcher(target, ctx):
"""Returns the python launcher for a given rule."""
@@ -44,8 +53,11 @@ def get_py_launcher(target, ctx):
semantics = struct(
tool_label = tool_label,
extra_deps = EXTRA_DEPS,
+ extra_required_aspect_providers = [],
go = struct(
get_import_path = get_go_import_path,
+ is_proto_library = is_go_proto_library,
+ get_proto_library_generated_srcs = get_go_proto_library_generated_srcs,
),
py = struct(
get_launcher = get_py_launcher,
diff --git a/aspect/intellij_info_impl.bzl b/aspect/intellij_info_impl.bzl
index 2192d7fd4e2..536bc00bc90 100644
--- a/aspect/intellij_info_impl.bzl
+++ b/aspect/intellij_info_impl.bzl
@@ -1,5 +1,6 @@
"""Implementation of IntelliJ-specific information collecting aspect."""
+load("@rules_java//java:defs.bzl", "JavaInfo", "java_common")
load(
":artifacts.bzl",
"artifact_location",
@@ -14,6 +15,16 @@ load(
"expand_make_variables",
)
+IntelliJInfo = provider(
+ doc = "Collected information about the targets visited by the aspect.",
+ fields = [
+ "export_deps",
+ "kind",
+ "output_groups",
+ "target_key",
+ ],
+)
+
# Defensive list of features that can appear in the C++ toolchain, but which we
# definitely don't want to enable (when enabled, they'd contribute command line
# flags that don't make sense in the context of intellij info).
@@ -27,7 +38,6 @@ UNSUPPORTED_FEATURES = [
# Compile-time dependency attributes, grouped by type.
DEPS = [
- "_cc_toolchain", # From cc rules
"_stl", # From cc rules
"malloc", # From cc_binary rules
"_java_toolchain", # From java rules
@@ -36,7 +46,7 @@ DEPS = [
"exports",
"java_lib", # From old proto_library rules
"_android_sdk", # from android rules
- "aidl_lib", # from android_sdk
+ "_aidl_lib", # from android_library
"_scala_toolchain", # From scala rules
"test_app", # android_instrumentation_test
"instruments", # android_instrumentation_test
@@ -136,15 +146,21 @@ def get_res_artifacts(resources):
def build_file_artifact_location(ctx):
"""Creates an ArtifactLocation proto representing a location of a given BUILD file."""
return to_artifact_location(
- ctx.build_file_path,
- ctx.build_file_path,
+ ctx.label.package + "/BUILD",
+ ctx.label.package + "/BUILD",
True,
is_external_artifact(ctx.label),
)
+# https://github.com/bazelbuild/bazel/issues/18966
+def _list_or_depset_to_list(list_or_depset):
+ if hasattr(list_or_depset, "to_list"):
+ return list_or_depset.to_list()
+ return list_or_depset
+
def get_source_jars(output):
if hasattr(output, "source_jars"):
- return output.source_jars
+ return _list_or_depset_to_list(output.source_jars)
if hasattr(output, "source_jar"):
return [output.source_jar]
return []
@@ -208,20 +224,18 @@ def list_omit_none(value):
def is_valid_aspect_target(target):
"""Returns whether the target has had the aspect run on it."""
- return hasattr(target, "intellij_info")
+ return IntelliJInfo in target
-def get_aspect_ids(ctx, target):
+def get_aspect_ids(ctx):
"""Returns the all aspect ids, filtering out self."""
aspect_ids = None
if hasattr(ctx, "aspect_ids"):
aspect_ids = ctx.aspect_ids
- elif hasattr(target, "aspect_ids"):
- aspect_ids = target.aspect_ids
else:
return None
return [aspect_id for aspect_id in aspect_ids if "intellij_info_aspect" not in aspect_id]
-def _is_language_specific_proto_library(ctx, target):
+def _is_language_specific_proto_library(ctx, target, semantics):
"""Returns True if the target is a proto library with attached language-specific aspect."""
if ctx.rule.kind != "proto_library":
return False
@@ -229,22 +243,30 @@ def _is_language_specific_proto_library(ctx, target):
return True
if CcInfo in target:
return True
- if hasattr(target, "aspect_proto_go_api_info"):
+ if semantics.go.is_proto_library(target, ctx):
return True
return False
+def stringify_label(label):
+ """Stringifies a label, making sure any leading '@'s are stripped from main repo labels."""
+ s = str(label)
+
+ # If the label is in the main repo, make sure any leading '@'s are stripped so that tests are
+ # okay with the fixture setups.
+ return s.lstrip("@") if s.startswith("@@//") or s.startswith("@//") else s
+
def make_target_key(label, aspect_ids):
"""Returns a TargetKey proto struct from a target."""
return struct_omit_none(
aspect_ids = tuple(aspect_ids) if aspect_ids else None,
- label = str(label),
+ label = stringify_label(label),
)
def make_dep(dep, dependency_type):
"""Returns a Dependency proto struct."""
return struct(
dependency_type = dependency_type,
- target = dep.intellij_info.target_key,
+ target = dep[IntelliJInfo].target_key,
)
def make_deps(deps, dependency_type):
@@ -255,7 +277,7 @@ def make_dep_from_label(label, dependency_type):
"""Returns a Dependency proto struct from a label."""
return struct(
dependency_type = dependency_type,
- target = struct(label = str(label)),
+ target = struct(label = stringify_label(label)),
)
def update_sync_output_groups(groups_dict, key, new_set):
@@ -279,7 +301,7 @@ def update_set_in_dict(input_dict, key, other_set):
def _get_output_mnemonic(ctx):
"""Gives the output directory mnemonic for some target context."""
- return ctx.configuration.bin_dir.path.split("/")[1]
+ return ctx.bin_dir.path.split("/")[1]
def _get_python_version(ctx):
if ctx.attr._flag_hack[FlagHackInfo].incompatible_py2_outputs_are_suffixed:
@@ -316,7 +338,7 @@ def _do_starlark_string_expansion(ctx, name, strings, extra_targets = []):
def collect_py_info(target, ctx, semantics, ide_info, ide_info_file, output_groups):
"""Updates Python-specific output groups, returns false if not a Python target."""
- if not PyInfo in target or _is_language_specific_proto_library(ctx, target):
+ if not PyInfo in target or _is_language_specific_proto_library(ctx, target, semantics):
return False
py_semantics = getattr(semantics, "py", None)
@@ -326,6 +348,7 @@ def collect_py_info(target, ctx, semantics, ide_info, ide_info_file, output_grou
py_launcher = None
sources = sources_from_target(ctx)
+
to_build = target[PyInfo].transitive_sources
args = getattr(ctx.rule.attr, "args", [])
data_deps = getattr(ctx.rule.attr, "data", [])
@@ -344,15 +367,10 @@ def collect_py_info(target, ctx, semantics, ide_info, ide_info_file, output_grou
update_sync_output_groups(output_groups, "intellij-resolve-py", to_build)
return True
-def _collect_generated_go_sources(target):
+def _collect_generated_go_sources(target, ctx, semantics):
"""Returns a depset of go source files generated by this target."""
- if hasattr(target, "aspect_proto_go_api_info"):
- go_proto_info = target.aspect_proto_go_api_info
- files = getattr(go_proto_info, "files_to_build", depset()).to_list()
- return [f for f in files if f.basename.endswith(".pb.go")]
- elif hasattr(target[OutputGroupInfo], "go_generated_srcs"):
- files = target[OutputGroupInfo].go_generated_srcs.to_list()
- return [f for f in files if f.basename.endswith(".go")]
+ if semantics.go.is_proto_library(target, ctx):
+ return semantics.go.get_proto_library_generated_srcs(target)
else:
return None
@@ -382,7 +400,7 @@ def collect_go_info(target, ctx, semantics, ide_info, ide_info_file, output_grou
# if the .go file isn't in 'files', build the .a and .x files instead
generated = genfiles
else:
- generated_sources = _collect_generated_go_sources(target)
+ generated_sources = _collect_generated_go_sources(target, ctx, semantics)
if not generated_sources:
return False
sources = generated_sources
@@ -508,7 +526,6 @@ def collect_c_toolchain_info(target, ctx, semantics, ide_info, ide_info_file, ou
cpp_variables = cc_common.create_compile_variables(
feature_configuration = feature_configuration,
cc_toolchain = cpp_toolchain,
- add_legacy_cxx_options = True,
user_compile_flags = copts + cxxopts,
)
c_options = cc_common.get_memory_inefficient_command_line(
@@ -543,11 +560,9 @@ def collect_c_toolchain_info(target, ctx, semantics, ide_info, ide_info_file, ou
def get_java_provider(target):
"""Find a provider exposing java compilation/outputs data."""
- # Check for scala and kt providers before JavaInfo. e.g. scala targets have
- # JavaInfo, but their data lives in the "scala" provider and not JavaInfo.
+ # Check for kt providers before JavaInfo. e.g. kt targets have
+ # JavaInfo, but their data lives in the "kt" provider and not JavaInfo.
# See https://github.com/bazelbuild/intellij/pull/1202
- if hasattr(target, "scala"):
- return target.scala
if hasattr(target, "kt") and hasattr(target.kt, "outputs"):
return target.kt
if JavaInfo in target:
@@ -629,7 +644,7 @@ def collect_java_info(target, ctx, semantics, ide_info, ide_info_file, output_gr
package_manifest = None
if java_sources:
package_manifest = build_java_package_manifest(ctx, target, java_sources, ".java-manifest")
- ide_info_files += [package_manifest]
+ ide_info_files.append(package_manifest)
filtered_gen_jar = None
if java_sources and (gen_java_sources or srcjars):
@@ -645,7 +660,11 @@ def collect_java_info(target, ctx, semantics, ide_info, ide_info_file, output_gr
# Custom lint checks are incorporated as java plugins. We collect them here and register them with the IDE so that the IDE can also run the same checks.
plugin_processor_jar_files = []
if hasattr(ctx.rule.attr, "_android_lint_plugins"):
- plugin_processor_jar_files += [jar for p in getattr(ctx.rule.attr, "_android_lint_plugins", []) for jar in p[JavaInfo].transitive_runtime_jars.to_list()]
+ plugin_processor_jar_files += [
+ jar
+ for p in getattr(ctx.rule.attr, "_android_lint_plugins", [])
+ for jar in _android_lint_plugin_jars(p)
+ ]
if hasattr(java, "annotation_processing") and java.annotation_processing and hasattr(java.annotation_processing, "processor_classpath"):
plugin_processor_jar_files += java.annotation_processing.processor_classpath.to_list()
@@ -665,7 +684,7 @@ def collect_java_info(target, ctx, semantics, ide_info, ide_info_file, output_gr
)
ide_info["java_ide_info"] = java_info
- ide_info_files += [ide_info_file]
+ ide_info_files.append(ide_info_file)
update_sync_output_groups(output_groups, "intellij-info-java", depset(ide_info_files))
update_sync_output_groups(output_groups, "intellij-compile-java", depset(compile_files))
update_sync_output_groups(output_groups, "intellij-resolve-java", depset(resolve_files))
@@ -676,6 +695,12 @@ def collect_java_info(target, ctx, semantics, ide_info, ide_info_file, output_gr
update_set_in_dict(output_groups, "intellij-resolve-java-direct-deps", java.transitive_source_jars)
return True
+def _android_lint_plugin_jars(target):
+ if JavaInfo in target:
+ return target[JavaInfo].transitive_runtime_jars.to_list()
+ else:
+ return []
+
def _package_manifest_file_argument(f):
artifact = artifact_location(f)
is_external = "1" if is_external_artifact(f.owner) else "0"
@@ -717,7 +742,7 @@ def _build_filtered_gen_jar(ctx, target, java_outputs, gen_java_sources, srcjars
elif jar.class_jar:
jar_artifacts.append(jar.class_jar)
if hasattr(jar, "source_jars") and jar.source_jars:
- source_jar_artifacts.extend(jar.source_jars)
+ source_jar_artifacts.extend(_list_or_depset_to_list(jar.source_jars))
elif hasattr(jar, "source_jar") and jar.source_jar:
source_jar_artifacts.append(jar.source_jar)
@@ -785,18 +810,53 @@ def collect_android_info(target, ctx, semantics, ide_info, ide_info_file, output
update_sync_output_groups(output_groups, "intellij-info-android", depset([ide_info_file]))
return handled
+def _get_android_ide_info(target):
+ """Returns the AndroidIdeInfo provider for the given target."""
+
+ if hasattr(android_common, "AndroidIdeInfo"):
+ return target[android_common.AndroidIdeInfo]
+
+ # Backwards compatibility: supports android struct provider
+ legacy_android = getattr(target, "android")
+
+ # Transform into AndroidIdeInfo form
+ return struct(
+ java_package = legacy_android.java_package,
+ manifest = legacy_android.manifest,
+ idl_source_jar = getattr(legacy_android.idl.output, "source_jar", None),
+ idl_class_jar = getattr(legacy_android.idl.output, "class_jar", None),
+ defines_android_resources = legacy_android.defines_resources,
+ idl_import_root = getattr(legacy_android.idl, "import_root", None),
+ resource_jar = legacy_android.resource_jar,
+ signed_apk = legacy_android.apk,
+ apks_under_test = legacy_android.apks_under_test,
+ )
+
def _collect_android_ide_info(target, ctx, semantics, ide_info, ide_info_file, output_groups):
- """Updates ide_info proto with android_ide_info, and intellij_resolve_android with android resolve files. Returns false if target doesn't contain android attribute."""
- if not hasattr(target, "android"):
+ """Populates ide_info proto and intellij_resolve_android output group
+
+ Updates ide_info proto with android_ide_info, and intellij_resolve_android with android
+ resolve files. It returns false on android_library and android_binary targets, as this preserves
+ consistent functionality with the previous condition of the presence of the .android legacy
+ provider.
+ """
+ if ctx.rule.kind not in ["android_library", "android_binary", "kt_android_library"]:
return False
android_semantics = semantics.android if hasattr(semantics, "android") else None
extra_ide_info = android_semantics.extra_ide_info(target, ctx) if android_semantics else {}
- android = target.android
+ android = _get_android_ide_info(target)
+
+ output_jar = struct(
+ class_jar = android.idl_class_jar,
+ ijar = None,
+ source_jar = android.idl_source_jar,
+ ) if android.idl_class_jar else None
+
resources = []
res_folders = []
- resolve_files = jars_from_output(android.idl.output)
+ resolve_files = jars_from_output(output_jar)
if hasattr(ctx.rule.attr, "resource_files"):
for artifact_path_fragments, res_files in get_res_artifacts(ctx.rule.attr.resource_files).items():
# Generate unique ArtifactLocation for resource directories.
@@ -835,7 +895,7 @@ def _collect_android_ide_info(target, ctx, semantics, ide_info, ide_info_file, o
instruments = None
if hasattr(ctx.rule.attr, "instruments") and ctx.rule.attr.instruments:
- instruments = str(ctx.rule.attr.instruments.label)
+ instruments = stringify_label(ctx.rule.attr.instruments.label)
render_resolve_jar = None
if android_semantics and hasattr(android_semantics, "build_render_resolve_jar"):
@@ -846,14 +906,14 @@ def _collect_android_ide_info(target, ctx, semantics, ide_info, ide_info_file, o
android_info = struct_omit_none(
java_package = android.java_package,
- idl_import_root = android.idl.import_root if hasattr(android.idl, "import_root") else None,
+ idl_import_root = getattr(android, "idl_import_root", None),
manifest = artifact_location(android.manifest),
manifest_values = [struct_omit_none(key = key, value = value) for key, value in ctx.rule.attr.manifest_values.items()] if hasattr(ctx.rule.attr, "manifest_values") else None,
- apk = artifact_location(android.apk),
+ apk = artifact_location(android.signed_apk),
dependency_apk = [artifact_location(apk) for apk in android.apks_under_test],
- has_idl_sources = android.idl.output != None,
- idl_jar = library_artifact(android.idl.output),
- generate_resource_class = android.defines_resources,
+ has_idl_sources = android.idl_class_jar != None,
+ idl_jar = library_artifact(output_jar),
+ generate_resource_class = android.defines_android_resources,
resources = resources,
res_folders = res_folders,
resource_jar = library_artifact(android.resource_jar),
@@ -863,7 +923,7 @@ def _collect_android_ide_info(target, ctx, semantics, ide_info, ide_info_file, o
)
if android.manifest and not android.manifest.is_source:
- resolve_files += [android.manifest]
+ resolve_files.append(android.manifest)
# b/176209293: expose resource jar to make sure empty library
# knows they are remote output artifact
@@ -880,7 +940,7 @@ def _collect_android_instrumentation_info(target, ctx, semantics, ide_info, ide_
return False
android_instrumentation_info = struct_omit_none(
- test_app = str(ctx.rule.attr.test_app.label),
+ test_app = stringify_label(ctx.rule.attr.test_app.label),
target_device = str(ctx.rule.attr.target_device.label),
)
ide_info["android_instrumentation_info"] = android_instrumentation_info
@@ -949,13 +1009,15 @@ def collect_java_toolchain_info(target, ide_info, ide_info_file, output_groups):
def artifact_to_path(artifact):
return artifact.root_execution_path_fragment + "/" + artifact.relative_path
-def collect_kotlin_toolchain_info(target, ide_info, ide_info_file, output_groups):
+def collect_kotlin_toolchain_info(target, ctx, ide_info, ide_info_file, output_groups):
"""Updates kotlin_toolchain-relevant output groups, returns false if not a kotlin_toolchain target."""
- if not hasattr(target, "kt"):
- return False
- kt = target.kt
- if not hasattr(kt, "language_version"):
+ if ctx.rule.kind == "_kt_toolchain" and platform_common.ToolchainInfo in target:
+ kt = target[platform_common.ToolchainInfo]
+ elif hasattr(target, "kt") and hasattr(target.kt, "language_version"):
+ kt = target.kt # Legacy struct provider mechanism
+ else:
return False
+
ide_info["kt_toolchain_ide_info"] = struct(
language_version = kt.language_version,
)
@@ -969,7 +1031,7 @@ def _is_proto_library_wrapper(target, ctx):
# treat any *proto_library rule with a single proto_library dep as a shim
deps = collect_targets_from_attrs(ctx.rule.attr, ["deps"])
- return len(deps) == 1 and deps[0].intellij_info and deps[0].intellij_info.kind == "proto_library"
+ return len(deps) == 1 and IntelliJInfo in deps[0] and deps[0][IntelliJInfo].kind == "proto_library"
def _get_forwarded_deps(target, ctx):
"""Returns the list of deps of this target to forward.
@@ -1008,12 +1070,22 @@ def intellij_info_aspect_impl(target, ctx, semantics):
rule_attrs,
semantics_extra_deps(DEPS, semantics, "extra_deps"),
)
+
+ # Collect direct toolchain type-based dependencies
+ if hasattr(semantics, "toolchains_propagation"):
+ direct_dep_targets.extend(
+ semantics.toolchains_propagation.collect_toolchain_deps(
+ ctx,
+ semantics.toolchains_propagation.toolchain_types,
+ ),
+ )
+
direct_deps = make_deps(direct_dep_targets, COMPILE_TIME)
# Add exports from direct dependencies
exported_deps_from_deps = []
for dep in direct_dep_targets:
- exported_deps_from_deps = exported_deps_from_deps + dep.intellij_info.export_deps
+ exported_deps_from_deps = exported_deps_from_deps + dep[IntelliJInfo].export_deps
# Combine into all compile time deps
compiletime_deps = direct_deps + exported_deps_from_deps
@@ -1027,9 +1099,9 @@ def intellij_info_aspect_impl(target, ctx, semantics):
# Collect transitive exports
for export in direct_exports:
- export_deps.extend(export.intellij_info.export_deps)
+ export_deps.extend(export[IntelliJInfo].export_deps)
- if ctx.rule.kind == "android_library":
+ if ctx.rule.kind == "android_library" or ctx.rule.kind == "kt_android_library":
# Empty android libraries export all their dependencies.
if not hasattr(rule_attrs, "srcs") or not ctx.rule.attr.srcs:
export_deps.extend(compiletime_deps)
@@ -1057,7 +1129,7 @@ def intellij_info_aspect_impl(target, ctx, semantics):
prerequisites = direct_dep_targets + runtime_dep_targets + extra_prerequisite_targets + direct_exports
output_groups = dict()
for dep in prerequisites:
- for k, v in dep.intellij_info.output_groups.items():
+ for k, v in dep[IntelliJInfo].output_groups.items():
if dep in forwarded_deps:
# unconditionally roll up deps for these targets
output_groups[k] = output_groups[k] + [v] if k in output_groups else [v]
@@ -1087,7 +1159,7 @@ def intellij_info_aspect_impl(target, ctx, semantics):
# bazel allows target names differing only by case, so append a hash to support
# case-insensitive file systems
file_name = file_name + "-" + str(hash(file_name))
- aspect_ids = get_aspect_ids(ctx, target)
+ aspect_ids = get_aspect_ids(ctx)
if aspect_ids:
aspect_hash = hash(".".join(aspect_ids))
file_name = file_name + "-" + str(aspect_hash)
@@ -1115,7 +1187,7 @@ def intellij_info_aspect_impl(target, ctx, semantics):
handled = collect_java_info(target, ctx, semantics, ide_info, ide_info_file, output_groups) or handled
handled = collect_java_toolchain_info(target, ide_info, ide_info_file, output_groups) or handled
handled = collect_android_info(target, ctx, semantics, ide_info, ide_info_file, output_groups) or handled
- handled = collect_kotlin_toolchain_info(target, ide_info, ide_info_file, output_groups) or handled
+ handled = collect_kotlin_toolchain_info(target, ctx, ide_info, ide_info_file, output_groups) or handled
# Any extra ide info
if hasattr(semantics, "extra_ide_info"):
@@ -1127,18 +1199,18 @@ def intellij_info_aspect_impl(target, ctx, semantics):
# Output the ide information file.
info = struct_omit_none(**ide_info)
- ctx.actions.write(ide_info_file, info.to_proto())
+ ctx.actions.write(ide_info_file, proto.encode_text(info))
# Return providers.
- return struct_omit_none(
- intellij_info = struct(
+ return [
+ IntelliJInfo(
export_deps = export_deps,
kind = ctx.rule.kind,
output_groups = output_groups,
target_key = target_key,
),
- output_groups = output_groups,
- )
+ OutputGroupInfo(**output_groups),
+ ]
def semantics_extra_deps(base, semantics, name):
if not hasattr(semantics, name):
@@ -1146,7 +1218,7 @@ def semantics_extra_deps(base, semantics, name):
extra_deps = getattr(semantics, name)
return base + extra_deps
-def make_intellij_info_aspect(aspect_impl, semantics):
+def make_intellij_info_aspect(aspect_impl, semantics, **kwargs):
"""Creates the aspect given the semantics."""
tool_label = semantics.tool_label
flag_hack_label = semantics.flag_hack_label
@@ -1159,13 +1231,13 @@ def make_intellij_info_aspect(aspect_impl, semantics):
attrs = {
"_package_parser": attr.label(
default = tool_label("PackageParser"),
- cfg = "host",
+ cfg = "exec",
executable = True,
allow_files = True,
),
"_jar_filter": attr.label(
default = tool_label("JarFilter"),
- cfg = "host",
+ cfg = "exec",
executable = True,
allow_files = True,
),
@@ -1174,7 +1246,7 @@ def make_intellij_info_aspect(aspect_impl, semantics):
),
"_create_aar": attr.label(
default = tool_label("CreateAar"),
- cfg = "host",
+ cfg = "exec",
executable = True,
allow_files = True,
),
@@ -1188,6 +1260,7 @@ def make_intellij_info_aspect(aspect_impl, semantics):
attr_aspects = attr_aspects,
attrs = attrs,
fragments = ["cpp"],
- required_aspect_providers = [[JavaInfo], [CcInfo], ["dart"], ["aspect_proto_go_api_info"]],
+ required_aspect_providers = [[JavaInfo], [CcInfo]] + semantics.extra_required_aspect_providers,
implementation = aspect_impl,
+ **kwargs
)
diff --git a/aspect/java_classpath.bzl b/aspect/java_classpath.bzl
index be3dfb648c6..1a47bd9448a 100644
--- a/aspect/java_classpath.bzl
+++ b/aspect/java_classpath.bzl
@@ -1,5 +1,7 @@
"""An aspect which extracts the runtime classpath from a java target."""
+load("@rules_java//java:defs.bzl", "JavaInfo")
+
def _runtime_classpath_impl(target, ctx):
"""The top level aspect implementation function.
diff --git a/aspect/testing/BUILD b/aspect/testing/BUILD
index 7225e2391cb..b4831afd6e1 100644
--- a/aspect/testing/BUILD
+++ b/aspect/testing/BUILD
@@ -1,6 +1,8 @@
# Integration tests for the plugin's Skylark aspect
-licenses(["notice"]) # Apache 2.0
+load("@rules_java//java:defs.bzl", "java_library")
+
+licenses(["notice"])
# To prevent versioning conflicts when developing internally, we always use the same
# guava version bundled with the IntelliJ plugin API.
diff --git a/aspect/testing/rules/BUILD b/aspect/testing/rules/BUILD
index 34df9444371..40666505324 100644
--- a/aspect/testing/rules/BUILD
+++ b/aspect/testing/rules/BUILD
@@ -1,12 +1,15 @@
# Testing infrastructure for the plugin's Skylark aspect
+load("@com_google_protobuf//bazel:java_proto_library.bzl", "java_proto_library")
+load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
+load("@rules_java//java:defs.bzl", "java_binary", "java_library")
load(
"//:build-visibility.bzl",
"ASPECT_TEST_RULES_VISIBILITY_TO_ALL",
"ASPECT_TEST_RULES_VISIBILITY_TO_TESTS",
)
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
proto_library(
name = "intellij_aspect_test_fixture_proto",
diff --git a/aspect/testing/rules/fast_build_aspect_test_fixture.bzl b/aspect/testing/rules/fast_build_aspect_test_fixture.bzl
index 9768ff687a7..6db5767419f 100644
--- a/aspect/testing/rules/fast_build_aspect_test_fixture.bzl
+++ b/aspect/testing/rules/fast_build_aspect_test_fixture.bzl
@@ -29,7 +29,7 @@ def _impl(ctx):
mnemonic = "FastBuildAspectTestFixtureBuilder",
progress_message = "Building Fast Build Aspect Test Fixture",
)
- return struct(
+ return DefaultInfo(
files = depset([output]),
runfiles = ctx.runfiles(
files = [output],
@@ -43,7 +43,7 @@ _fast_build_aspect_test_fixture = rule(
"output": attr.string(mandatory = True),
"_fast_build_aspect_test_fixture_builder": attr.label(
default = Label("//aspect/testing/rules:FastBuildAspectTestFixtureBuilder"),
- cfg = "host",
+ cfg = "exec",
executable = True,
allow_files = True,
),
diff --git a/aspect/testing/rules/intellij_aspect_test_fixture.bzl b/aspect/testing/rules/intellij_aspect_test_fixture.bzl
index 091e2c94fe7..cb0bccebb7f 100644
--- a/aspect/testing/rules/intellij_aspect_test_fixture.bzl
+++ b/aspect/testing/rules/intellij_aspect_test_fixture.bzl
@@ -6,6 +6,7 @@ load(
)
load(
"//aspect:intellij_info_impl.bzl",
+ "IntelliJInfo",
"update_set_in_dict",
)
@@ -13,9 +14,9 @@ def _impl(ctx):
"""Implementation method for _intellij_aspect_test_fixture."""
output_groups = dict()
inputs = depset()
- deps = [dep for dep in ctx.attr.deps if hasattr(dep, "intellij_info")]
+ deps = [dep for dep in ctx.attr.deps if IntelliJInfo in dep]
for dep in deps:
- for k, v in dep.intellij_info.output_groups.items():
+ for k, v in dep[IntelliJInfo].output_groups.items():
update_set_in_dict(output_groups, k, v)
inputs = depset(
[f for f in v.to_list() if f.short_path.endswith(".intellij-info.txt")],
@@ -43,7 +44,7 @@ def _impl(ctx):
mnemonic = "IntellijAspectTestFixtureBuilder",
progress_message = "Building Intellij Aspect Test Fixture",
)
- return struct(
+ return DefaultInfo(
files = depset([output]),
runfiles = ctx.runfiles(
files = [output],
@@ -57,19 +58,20 @@ _intellij_aspect_test_fixture = rule(
"output": attr.string(mandatory = True),
"_intellij_aspect_test_fixture_builder": attr.label(
default = Label("//aspect/testing/rules:IntellijAspectTestFixtureBuilder"),
- cfg = "host",
+ cfg = "exec",
executable = True,
allow_files = True,
),
},
)
-def intellij_aspect_test_fixture(name, deps):
+def intellij_aspect_test_fixture(name, deps, transitive_configs = []):
_intellij_aspect_test_fixture(
name = name,
output = name + ".intellij-aspect-test-fixture",
deps = deps,
testonly = 1,
+ transitive_configs = transitive_configs,
)
def test_sources(outs):
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/ccbinary/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/ccbinary/BUILD
index f88ab3dd232..cea04ab9275 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/ccbinary/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/ccbinary/BUILD
@@ -1,10 +1,11 @@
-licenses(["notice"]) # Apache 2.0
-
+load("@rules_java//java:defs.bzl", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
+licenses(["notice"])
+
cc_binary(
name = "simple",
srcs = ["simple/simple.cc"],
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cclibrary/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cclibrary/BUILD
index 8e63a2da997..960e4caf30e 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cclibrary/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cclibrary/BUILD
@@ -1,10 +1,11 @@
-licenses(["notice"]) # Apache 2.0
-
+load("@rules_java//java:defs.bzl", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
+licenses(["notice"])
+
cc_library(
name = "simple",
srcs = ["simple/simple.cc"],
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cctest/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cctest/BUILD
index 69e39c9dae5..45f5f4bff95 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cctest/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cctest/BUILD
@@ -1,10 +1,11 @@
-licenses(["notice"]) # Apache 2.0
-
+load("@rules_java//java:defs.bzl", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
+licenses(["notice"])
+
cc_test(
name = "simple",
srcs = ["simple/simple.cc"],
@@ -12,6 +13,7 @@ cc_test(
intellij_aspect_test_fixture(
name = "simple_fixture",
+ transitive_configs = ["//command_line_option/fragment:test"],
deps = [":simple"],
)
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cctoolchain/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cctoolchain/BUILD
index b12f695aef5..4f902b89dc1 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cctoolchain/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cctoolchain/BUILD
@@ -1,10 +1,11 @@
-licenses(["notice"]) # Apache 2.0
-
+load("@rules_java//java:defs.bzl", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
+licenses(["notice"])
+
cc_library(
name = "simple",
srcs = ["simple.cc"],
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cctoolchain/CcToolchainTest.java b/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cctoolchain/CcToolchainTest.java
index 208d6ff9783..2f4e19efe22 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cctoolchain/CcToolchainTest.java
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/cctoolchain/CcToolchainTest.java
@@ -78,10 +78,6 @@ public void testCcToolchain() throws Exception {
&& !dir.contains("clang/")
&& dir.endsWith("include")))
.isTrue();
- assertThat(
- toolchainInfo.getBuiltInIncludeDirectoryList().stream()
- .anyMatch(dir -> dir.contains("c++")))
- .isTrue();
}
}
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/coptsmakevars/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/coptsmakevars/BUILD
index aa109c070c4..ec62fa8dd2b 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/coptsmakevars/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/cpp/coptsmakevars/BUILD
@@ -1,10 +1,11 @@
-licenses(["notice"]) # Apache 2.0
-
+load("@rules_java//java:defs.bzl", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
+licenses(["notice"])
+
cc_binary(
name = "simple_prefined",
srcs = ["simple/simple.cc"],
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/alias/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/alias/BUILD
index c2261c39ff3..f53e2da963b 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/alias/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/alias/BUILD
@@ -1,10 +1,11 @@
-licenses(["notice"]) # Apache 2.0
-
+load("@rules_java//java:defs.bzl", "java_library", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
+licenses(["notice"])
+
java_library(
name = "test",
srcs = ["Foo.java"],
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/analysistest/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/analysistest/BUILD
index f10ee99e9ca..dc23f814058 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/analysistest/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/analysistest/BUILD
@@ -1,3 +1,4 @@
+load("@rules_java//java:defs.bzl", "java_library", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/artifacts/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/artifacts/BUILD
index 5be27ce8fc5..8d9de8be671 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/artifacts/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/artifacts/BUILD
@@ -1,9 +1,10 @@
+load("@rules_java//java:defs.bzl", "java_library", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
genrule(
name = "gen_source",
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/build/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/build/BUILD
index 5d164c1fb7c..d2c38a9a14d 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/build/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/build/BUILD
@@ -1,10 +1,11 @@
-licenses(["notice"]) # Apache 2.0
-
+load("@rules_java//java:defs.bzl", "java_library", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
+licenses(["notice"])
+
java_library(
name = "simple",
srcs = ["Foo.java"],
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/noide/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/noide/BUILD
index 860743ba1d1..7ac0636cea0 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/noide/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/noide/BUILD
@@ -1,10 +1,11 @@
-licenses(["notice"]) # Apache 2.0
-
+load("@rules_java//java:defs.bzl", "java_library", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
+licenses(["notice"])
+
java_library(
name = "foo",
srcs = ["Foo.java"],
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/tags/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/tags/BUILD
index 7158a5ddd78..5125523cc07 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/tags/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/general/tags/BUILD
@@ -1,10 +1,11 @@
-licenses(["notice"]) # Apache 2.0
-
+load("@rules_java//java:defs.bzl", "java_library", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
+licenses(["notice"])
+
java_library(
name = "foo",
srcs = ["Foo.java"],
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/BUILD
index 88b6136bb7a..8504bc8cd1d 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/BUILD
@@ -1,24 +1,30 @@
-load("@build_bazel_integration_testing//tools:bazel_java_integration_test.bzl", "bazel_java_integration_test")
+load(
+ "@contrib_rules_bazel_integration_test//bazel_integration_test:defs.bzl",
+ "bazel_integration_tests",
+)
-bazel_java_integration_test(
- name = "BazelInvokingIntegrationTest",
- srcs = [
- "BazelInvokingIntegrationTest.java",
- ],
+java_binary(
+ name = "BazelInvokingIntegrationTestRunner",
+ testonly = True,
+ srcs = ["BazelInvokingIntegrationTestRunner.java"],
data = [
"//aspect:aspect_files",
],
- external_deps = [
- "@integration_test_deps",
- ],
- tags = ["block-network"],
- versions = [
- "0.28.1",
- "0.27.2",
- ],
+ main_class = "com.google.idea.blaze.aspect.integration.BazelInvokingIntegrationTestRunner",
deps = [
"//aspect/testing:guava",
"//base",
- "//base:integration_test_utils",
],
)
+
+bazel_integration_tests(
+ name = "bazel_invocation_integration_tests",
+ bazel_versions = [
+ "6.0.0",
+ ],
+ # set tags = [] because otherwise bazel_integration_tests sets
+ # tags = ["manual"] and the target is not be detected via test //pkg/...
+ tags = [],
+ test_runner = ":BazelInvokingIntegrationTestRunner",
+ workspace_path = "testdata",
+)
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/BazelInvokingIntegrationTest.java b/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/BazelInvokingIntegrationTest.java
deleted file mode 100644
index 70c26a23fed..00000000000
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/BazelInvokingIntegrationTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.aspect.integration;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import build.bazel.tests.integration.BazelCommand;
-import build.bazel.tests.integration.WorkspaceDriver;
-import com.google.common.collect.ImmutableList;
-import com.google.idea.blaze.base.model.primitives.LanguageClass;
-import com.google.idea.blaze.base.sync.aspects.strategy.AspectStrategy;
-import com.google.idea.blaze.base.sync.aspects.strategy.AspectStrategy.OutputGroup;
-import com.google.idea.blaze.base.sync.aspects.strategy.AspectStrategyBazel;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.stream.Collectors;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/**
- * A Bazel-invoking integration test for the bundled IntelliJ aspect.
- *
- *
These tests assert the end-to-end behavior of the plugin's aspect during a sync, and ensure
- * that it generates the correct IDE info files.
- */
-public class BazelInvokingIntegrationTest {
-
- // Flags for wiring up the plugin aspect from the external @intellij_aspect repository.
- public static final ImmutableList ASPECT_FLAGS =
- ImmutableList.of(
- AspectStrategyBazel.ASPECT_FLAG,
- String.format(
- "%s=%s/%s/aspect",
- AspectStrategyBazel.OVERRIDE_REPOSITORY_FLAG,
- System.getenv("TEST_SRCDIR"),
- System.getenv("TEST_WORKSPACE")));
- private WorkspaceDriver driver = new WorkspaceDriver();
-
- @BeforeClass
- public static void setUpClass() throws IOException {
- WorkspaceDriver.setUpClass();
- }
-
- @Before
- public void setUp() throws Exception {
- driver.setUp();
- }
-
- @Test
- public void aspect_genericOutputGroup_generatesInfoTxt() throws Exception {
- driver.scratchFile("foo/BUILD", "sh_test(name = \"bar\",\n" + "srcs = [\"bar.sh\"])");
- driver.scratchExecutableFile("foo/bar.sh", "echo \"bar\"", "exit 0");
-
- ImmutableList.Builder args = ImmutableList.builder();
- args.add("build");
- args.add("//foo:bar");
- args.add("--define=ij_product=intellij-latest");
- args.addAll(ASPECT_FLAGS);
- args.add(
- getOutputGroupsFlag(
- ImmutableList.of(OutputGroup.INFO), ImmutableList.of(LanguageClass.GENERIC)));
-
- BazelCommand cmd = driver.bazel(args.build()).runVerbose();
-
- assertEquals("return code is 0", 0, cmd.exitCode());
-
- // Bazel's output goes into stderr by default, even on success.
- assertTrue(
- "stderr contains up-to-date message",
- cmd.errorLines().stream().anyMatch(line -> line.endsWith("//foo:bar up-to-date:")));
- assertTrue(
- "stderr contains intellij-info.txt filename",
- cmd.errorLines().stream()
- .anyMatch(line -> line.endsWith(getIntelliJInfoTxtFilename("bar"))));
- }
-
- private String getIntelliJInfoTxtFilename(String targetName) {
- // e.g. bar-97299.intellij-info.txt
- // The hashCode() call here is the implementation function underlying the Starlark hash()
- // function in used in intellij-info-impl.bzl.
- return String.format("%s-%s.intellij-info.txt", targetName, targetName.hashCode());
- }
-
- private String getOutputGroupsFlag(
- Collection outputGroups, Collection languageClassList) {
- // e.g. --output_groups=intellij-info-generic,intellij-resolve-java,intellij-compile-java
- Set languageClasses = new HashSet<>(languageClassList);
- AspectStrategy strategy = new AspectStrategyBazel();
- String outputGroupNames =
- outputGroups.stream()
- .flatMap(
- g ->
- strategy
- .getBaseOutputGroups(g, languageClasses, /* directDepsOnly= */ false)
- .stream())
- .collect(Collectors.joining(","));
- return "--output_groups=" + outputGroupNames;
- }
-}
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/BazelInvokingIntegrationTestRunner.java b/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/BazelInvokingIntegrationTestRunner.java
new file mode 100644
index 00000000000..8cce1825556
--- /dev/null
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/BazelInvokingIntegrationTestRunner.java
@@ -0,0 +1,152 @@
+/*
+ * 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.aspect.integration;
+
+import com.google.common.collect.ImmutableList;
+import com.google.idea.blaze.base.bazel.BazelVersion;
+import com.google.idea.blaze.base.model.BlazeVersionData;
+import com.google.idea.blaze.base.model.primitives.LanguageClass;
+import com.google.idea.blaze.base.sync.aspects.strategy.AspectStrategy;
+import com.google.idea.blaze.base.sync.aspects.strategy.AspectStrategy.OutputGroup;
+import com.google.idea.blaze.base.sync.aspects.strategy.AspectStrategyBazel;
+import java.io.File;
+import java.nio.file.Paths;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * A Bazel-invoking integration test for the bundled IntelliJ aspect.
+ *
+ * These tests assert the end-to-end behavior of the plugin's aspect during a sync, and ensure
+ * that it generates the correct IDE info files.
+ */
+public class BazelInvokingIntegrationTestRunner {
+
+ public static void main(String[] a) throws Exception {
+ BazelVersion bazelVersion = getBazelVersion();
+ if (bazelVersion == null) {
+ exitWithError(
+ String.format(
+ "Failed to get Bazel version from Bazel path (%s)",
+ System.getenv("BIT_BAZEL_BINARY")));
+ }
+ AspectStrategyBazel aspectStrategyBazel =
+ new AspectStrategyBazel(BlazeVersionData.builder().setBazelVersion(bazelVersion).build());
+
+ // Flags for wiring up the plugin aspect from the external @intellij_aspect repository.
+ ImmutableList aspectFlags =
+ ImmutableList.of(
+ aspectStrategyBazel.getAspectFlag(),
+ String.format(
+ "%s=%s/%s/aspect",
+ AspectStrategyBazel.OVERRIDE_REPOSITORY_FLAG,
+ System.getenv("TEST_SRCDIR"),
+ System.getenv("TEST_WORKSPACE")));
+
+ if (bazelVersion.isAtLeast(6, 0, 0)
+ && !aspectFlags.contains(
+ "--aspects=@@intellij_aspect//:intellij_info_bundled.bzl%intellij_info_aspect")) {
+ exitWithError(
+ String.format("Incorrect/Missing aspects flag in command args (%s)", aspectFlags));
+ }
+
+ ImmutableList.Builder args = ImmutableList.builder();
+ args.add(System.getenv("BIT_BAZEL_BINARY"));
+ args.add("build");
+ args.add("//:foo");
+ args.add("--define=ij_product=intellij-latest");
+ args.addAll(aspectFlags);
+ args.add(
+ getOutputGroupsFlag(
+ ImmutableList.of(OutputGroup.INFO),
+ ImmutableList.of(LanguageClass.GENERIC),
+ aspectStrategyBazel));
+
+ ProcessBuilder processBuilder =
+ new ProcessBuilder()
+ .command(args.build())
+ .directory(Paths.get(System.getenv("BIT_WORKSPACE_DIR")).toFile());
+ Process bazelInvocation = processBuilder.start();
+ int exitCode = bazelInvocation.waitFor();
+ String invocationOutput = new String(bazelInvocation.getErrorStream().readAllBytes());
+
+ if (exitCode != 0) {
+ exitWithError(
+ String.format(
+ "Bazel invocation failed: exit code (%d), invocation result (%s).",
+ exitCode, invocationOutput));
+ }
+
+ // Bazel's output goes into stderr by default, even on success.
+ if (!invocationOutput.contains("//:foo up-to-date:")
+ || !invocationOutput.contains(getIntelliJInfoTxtFilename("foo"))) {
+ exitWithError(String.format("Missing output in invocation result (%s)", invocationOutput));
+ }
+ }
+
+ private static void exitWithError(String message) {
+ System.err.println(message);
+ System.exit(1);
+ }
+
+ private static String getIntelliJInfoTxtFilename(String targetName) {
+ // e.g. foo-97299.intellij-info.txt
+ // The hashCode() call here is the implementation function underlying the Starlark hash()
+ // function in used in intellij-info-impl.bzl.
+ return String.format("%s-%s.intellij-info.txt", targetName, targetName.hashCode());
+ }
+
+ private static String getOutputGroupsFlag(
+ Collection outputGroups,
+ Collection languageClassList,
+ AspectStrategy strategy) {
+ // e.g. --output_groups=intellij-info-generic,intellij-resolve-java,intellij-compile-java
+ Set languageClasses = new HashSet<>(languageClassList);
+ String outputGroupNames =
+ outputGroups.stream()
+ .flatMap(
+ g ->
+ strategy
+ .getBaseOutputGroups(g, languageClasses, /* directDepsOnly= */ false)
+ .stream())
+ .collect(Collectors.joining(","));
+ return "--output_groups=" + outputGroupNames;
+ }
+
+ private static BazelVersion getBazelVersion() {
+ // The name of the directory containing the bazel binary is formatted as
+ // build_bazel_bazel_{major}_{minor}_{bugfix}[-pre] for a bazel binary of version
+ // {major}.{minor}.{bugfix}
+ String bazelBinaryPath = System.getenv("BIT_BAZEL_BINARY");
+ if (bazelBinaryPath == null) {
+ return null;
+ }
+ String bazelDir = new File(bazelBinaryPath).getParentFile().getName();
+ String[] parts = bazelDir.split("_|-");
+ if (parts.length < 6) {
+ return null;
+ }
+ try {
+ return new BazelVersion(
+ Integer.parseInt(parts[3]), Integer.parseInt(parts[4]), Integer.parseInt(parts[5]));
+ } catch (NumberFormatException e) {
+ // invalid version
+ return null;
+ }
+ }
+}
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata/BUILD
new file mode 100644
index 00000000000..b1403111b10
--- /dev/null
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata/BUILD
@@ -0,0 +1,4 @@
+sh_binary(
+ name = "foo",
+ srcs = ["foo.sh"],
+)
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata/WORKSPACE b/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata/WORKSPACE
new file mode 100644
index 00000000000..eae2adb1da5
--- /dev/null
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata/WORKSPACE
@@ -0,0 +1,8 @@
+workspace(name = "testdata")
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+http_archive(
+ name = "rules_java",
+ url = "https://github.com/bazelbuild/rules_java/releases/download/5.3.5/rules_java-5.3.5.tar.gz",
+ sha256 = "c73336802d0b4882e40770666ad055212df4ea62cfa6edf9cb0f9d29828a0934",
+)
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata/foo.sh b/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata/foo.sh
new file mode 100644
index 00000000000..ff4c040a250
--- /dev/null
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata/foo.sh
@@ -0,0 +1,2 @@
+echo "foo"
+exit 0
\ No newline at end of file
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/dependencies/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/dependencies/BUILD
index 2774be8df6b..05e81e9cd5b 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/dependencies/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/dependencies/BUILD
@@ -1,10 +1,11 @@
-licenses(["notice"]) # Apache 2.0
-
+load("@rules_java//java:defs.bzl", "java_library", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
+licenses(["notice"])
+
java_library(
name = "foo",
srcs = ["testsrc/Foo.java"],
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/filteredgenjar/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/filteredgenjar/BUILD
index cc0584b40ae..4a2b4ccbcb1 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/filteredgenjar/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/filteredgenjar/BUILD
@@ -1,9 +1,10 @@
+load("@rules_java//java:defs.bzl", "java_library", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
java_library(
name = "source_only",
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/genjars/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/genjars/BUILD
index 393ab0a00e5..1dbfe3092b1 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/genjars/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/genjars/BUILD
@@ -1,10 +1,11 @@
-licenses(["notice"]) # Apache 2.0
-
+load("@rules_java//java:defs.bzl", "java_library", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
+licenses(["notice"])
+
java_library(
name = "no_plugin",
srcs = ["Foo.java"],
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javabinary/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javabinary/BUILD
index b98d1e97f2f..32b42bc3753 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javabinary/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javabinary/BUILD
@@ -1,10 +1,11 @@
-licenses(["notice"]) # Apache 2.0
-
+load("@rules_java//java:defs.bzl", "java_binary", "java_library", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
+licenses(["notice"])
+
java_library(
name = "foolib",
srcs = ["Foo.java"],
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javalibrary/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javalibrary/BUILD
index 4499022271a..42b17066639 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javalibrary/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javalibrary/BUILD
@@ -1,9 +1,10 @@
+load("@rules_java//java:defs.bzl", "java_library", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
java_library(
name = "foo",
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javaplugin/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javaplugin/BUILD
index a3e3fe1eae2..314545e433c 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javaplugin/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javaplugin/BUILD
@@ -1,10 +1,11 @@
-licenses(["notice"]) # Apache 2.0
-
+load("@rules_java//java:defs.bzl", "java_plugin", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
+licenses(["notice"])
+
java_plugin(
name = "plugin",
srcs = ["Plugin.java"],
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javatest/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javatest/BUILD
index ee376821396..9cb128c2d31 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javatest/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javatest/BUILD
@@ -1,13 +1,14 @@
-licenses(["notice"]) # Apache 2.0
-
-load(
- "//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
- "intellij_aspect_test_fixture",
-)
+load("@rules_java//java:defs.bzl", "java_test")
load(
"//aspect/testing/rules:fast_build_aspect_test_fixture.bzl",
"fast_build_aspect_test_fixture",
)
+load(
+ "//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
+ "intellij_aspect_test_fixture",
+)
+
+licenses(["notice"])
java_test(
name = "FooTest",
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javatest/JavaTestFastBuildAspectTest.java b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javatest/JavaTestFastBuildAspectTest.java
index 7a5c361d751..68763a08bfb 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javatest/JavaTestFastBuildAspectTest.java
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/java/javatest/JavaTestFastBuildAspectTest.java
@@ -31,6 +31,7 @@
public final class JavaTestFastBuildAspectTest {
private static final String NO_LAUNCHER_TARGET = "";
+ private static final String LAUNCHER_ALIAS = "@bazel_tools//tools/jdk:launcher_flag_alias";
@Rule
public FastBuildAspectRule aspectLoader =
@@ -45,7 +46,8 @@ public void testNoJavaLauncherSpecified() throws Exception {
aspectLoader.loadTestFixture(":footest_no_launcher_fast_build_fixture");
FastBuildBlazeData data =
getDataForTarget(aspectLoader.testRelative(":FooTestNoLauncher"), fixture);
- assertThat(data.getJavaInfo().getLauncher()).isEqualTo(NO_LAUNCHER_TARGET);
+ // TODO: b/295221112 - remove LAUNCHER_ALIAS once label_flag is used
+ assertThat(data.getJavaInfo().getLauncher()).isAnyOf(NO_LAUNCHER_TARGET, LAUNCHER_ALIAS);
}
@Test
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/proto/jpl/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/proto/jpl/BUILD
index afd5d449475..6dade648605 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/proto/jpl/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/proto/jpl/BUILD
@@ -1,10 +1,13 @@
-licenses(["notice"]) # Apache 2.0
-
+load("@com_google_protobuf//bazel:java_proto_library.bzl", "java_proto_library")
+load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
+load("@rules_java//java:defs.bzl", "java_library", "java_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
+licenses(["notice"])
+
proto_library(
name = "foo_proto",
srcs = ["foo.proto"],
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/python/pybinary/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/python/pybinary/BUILD
index bf2b8ee67ea..9062e117250 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/python/pybinary/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/python/pybinary/BUILD
@@ -1,9 +1,11 @@
+load("@rules_java//java:defs.bzl", "java_test")
+load("@rules_python//python:defs.bzl", "py_binary")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
py_binary(
name = "simple",
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/python/pylibrary/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/python/pylibrary/BUILD
index a7c591eb5b3..9a050e016b1 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/python/pylibrary/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/python/pylibrary/BUILD
@@ -1,3 +1,5 @@
+load("@rules_java//java:defs.bzl", "java_test")
+load("@rules_python//python:defs.bzl", "py_library")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/python/pytest/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/python/pytest/BUILD
index 6b1ef473f3c..27b929db763 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/python/pytest/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/python/pytest/BUILD
@@ -1,9 +1,11 @@
+load("@rules_java//java:defs.bzl", "java_test")
+load("@rules_python//python:defs.bzl", "py_test")
load(
"//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
"intellij_aspect_test_fixture",
)
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
py_test(
name = "simple",
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalabinary/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalabinary/BUILD
index 485aacdd2b2..9f41d205f77 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalabinary/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalabinary/BUILD
@@ -1,12 +1,12 @@
-load(
- "//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
- "intellij_aspect_test_fixture",
-)
load(
"@io_bazel_rules_scala//scala:scala.bzl",
"scala_binary",
"scala_library",
)
+load(
+ "//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
+ "intellij_aspect_test_fixture",
+)
licenses(["notice"]) # Apache 2.0
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalalibrary/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalalibrary/BUILD
index 19b71b77b12..44fee56d8a0 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalalibrary/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalalibrary/BUILD
@@ -1,11 +1,11 @@
-load(
- "//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
- "intellij_aspect_test_fixture",
-)
load(
"@io_bazel_rules_scala//scala:scala.bzl",
"scala_library",
)
+load(
+ "//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
+ "intellij_aspect_test_fixture",
+)
licenses(["notice"]) # Apache 2.0
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalamacrolibrary/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalamacrolibrary/BUILD
index 3e77908a74c..ab6254b0475 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalamacrolibrary/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalamacrolibrary/BUILD
@@ -1,11 +1,11 @@
-load(
- "//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
- "intellij_aspect_test_fixture",
-)
load(
"@io_bazel_rules_scala//scala:scala.bzl",
"scala_macro_library",
)
+load(
+ "//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
+ "intellij_aspect_test_fixture",
+)
licenses(["notice"]) # Apache 2.0
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalatest/BUILD b/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalatest/BUILD
index 058fbdde30d..b15cce19aee 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalatest/BUILD
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalatest/BUILD
@@ -1,11 +1,11 @@
-load(
- "//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
- "intellij_aspect_test_fixture",
-)
load(
"@io_bazel_rules_scala//scala:scala.bzl",
"scala_test",
)
+load(
+ "//aspect/testing/rules:intellij_aspect_test_fixture.bzl",
+ "intellij_aspect_test_fixture",
+)
licenses(["notice"]) # Apache 2.0
diff --git a/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalatest/FooTest.scala b/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalatest/FooTest.scala
index 68857b805a4..8b621808404 100644
--- a/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalatest/FooTest.scala
+++ b/aspect/testing/tests/src/com/google/idea/blaze/aspect/scala/scalatest/FooTest.scala
@@ -1,8 +1,8 @@
package com.google.idea.blaze.aspect.scala.scalatest;
-import org.scalatest.FlatSpec
+import org.scalatest.flatspec.AnyFlatSpec
/** Dummy test class. */
-class FooTest extends FlatSpec {
+class FooTest extends AnyFlatSpec {
"test" should "pass" in {}
}
diff --git a/aspect/tools/BUILD b/aspect/tools/BUILD
index ef9eb8068da..cfefd3a5579 100644
--- a/aspect/tools/BUILD
+++ b/aspect/tools/BUILD
@@ -3,9 +3,11 @@
# Tools needed by the bazel plugin's aspect.
#
+load("@rules_java//java:defs.bzl", "java_binary", "java_library", "java_test")
+
package(default_visibility = ["//aspect:__pkg__"])
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
# To prevent versioning conflicts when developing internally, we always use the same
# guava version bundled with the IntelliJ plugin API.
@@ -18,10 +20,11 @@ java_library(
java_library(
name = "lib",
srcs = glob(["src/**/*.java"]),
+ javacopts = ["-source 8 -target 8"],
deps = [
":guava",
- "//intellij_platform_sdk:jsr305",
"//proto:proto_deps",
+ "@jsr305_annotations//jar",
],
)
@@ -79,7 +82,10 @@ java_test(
size = "small",
srcs = ["tests/unittests/com/google/idea/blaze/aspect/PackageParserTest.java"],
test_class = "com.google.idea.blaze.aspect.PackageParserTest",
- deps = [":test_lib"],
+ deps = [
+ ":test_lib",
+ "@error_prone_annotations//jar",
+ ],
)
java_test(
diff --git a/aspect/tools/src/com/google/idea/blaze/aspect/PackageParserIoProvider.java b/aspect/tools/src/com/google/idea/blaze/aspect/PackageParserIoProvider.java
index 5106b28e700..26be71aaf31 100644
--- a/aspect/tools/src/com/google/idea/blaze/aspect/PackageParserIoProvider.java
+++ b/aspect/tools/src/com/google/idea/blaze/aspect/PackageParserIoProvider.java
@@ -16,7 +16,7 @@
package com.google.idea.blaze.aspect;
import com.google.common.annotations.VisibleForTesting;
-import com.google.repackaged.bazel.protobuf.MessageLite;
+import com.google.protobuf.MessageLite;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStream;
diff --git a/aspect/tools/tests/unittests/com/google/idea/blaze/aspect/ArtifactLocationParserTest.java b/aspect/tools/tests/unittests/com/google/idea/blaze/aspect/ArtifactLocationParserTest.java
index 3f0e338e90d..f7178b2b06e 100644
--- a/aspect/tools/tests/unittests/com/google/idea/blaze/aspect/ArtifactLocationParserTest.java
+++ b/aspect/tools/tests/unittests/com/google/idea/blaze/aspect/ArtifactLocationParserTest.java
@@ -116,7 +116,7 @@ private void assertFails(String input, String expectedError) {
ArtifactLocationParser.parse(input);
fail();
} catch (IllegalArgumentException e) {
- assertThat(e).hasMessage(expectedError);
+ assertThat(e).hasMessageThat().isEqualTo(expectedError);
}
}
}
diff --git a/aspect/tools/tests/unittests/com/google/idea/blaze/aspect/OptionParserTest.java b/aspect/tools/tests/unittests/com/google/idea/blaze/aspect/OptionParserTest.java
index 37f18c49c8d..e91ccd08055 100644
--- a/aspect/tools/tests/unittests/com/google/idea/blaze/aspect/OptionParserTest.java
+++ b/aspect/tools/tests/unittests/com/google/idea/blaze/aspect/OptionParserTest.java
@@ -49,7 +49,7 @@ public void testParseSingleOption() throws Exception {
OptionParser.parseSingleOption(new String[] {"--foo", "1", "--bar"}, "bar", String::toString);
fail("Expected failure");
} catch (IllegalArgumentException e) {
- assertThat(e).hasMessage("Expected value after --bar");
+ assertThat(e).hasMessageThat().isEqualTo("Expected value after --bar");
}
// Test that a single-value flag should not appear multiple times.
try {
@@ -57,7 +57,7 @@ public void testParseSingleOption() throws Exception {
new String[] {"--foo", "1", "--foo", "2"}, "foo", String::toString);
fail("Expected failure");
} catch (IllegalArgumentException e) {
- assertThat(e).hasMessage("Expected --foo to appear at most once");
+ assertThat(e).hasMessageThat().isEqualTo("Expected --foo to appear at most once");
}
}
@@ -89,7 +89,7 @@ public void testParseMultiOption() throws Exception {
new String[] {"--foo", "1", "--bar", "2", "--foo"}, "foo", String::toString);
fail("Expected failure");
} catch (IllegalArgumentException e) {
- assertThat(e).hasMessage("Expected value after --foo");
+ assertThat(e).hasMessageThat().isEqualTo("Expected value after --foo");
}
}
}
diff --git a/aspect/tools/tests/unittests/com/google/idea/blaze/aspect/PackageParserTest.java b/aspect/tools/tests/unittests/com/google/idea/blaze/aspect/PackageParserTest.java
index 9c89d8f2579..18a6b0ee88e 100644
--- a/aspect/tools/tests/unittests/com/google/idea/blaze/aspect/PackageParserTest.java
+++ b/aspect/tools/tests/unittests/com/google/idea/blaze/aspect/PackageParserTest.java
@@ -23,7 +23,8 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.devtools.intellij.aspect.Common.ArtifactLocation;
-import com.google.repackaged.bazel.protobuf.MessageLite;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import com.google.protobuf.MessageLite;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -51,6 +52,7 @@ private static class MockPackageParserIoProvider extends PackageParserIoProvider
private final List sourceLocations = Lists.newArrayList();
private StringWriter writer = new StringWriter();
+ @CanIgnoreReturnValue
public MockPackageParserIoProvider addSource(ArtifactLocation source, String javaSrc) {
try {
Path path = Paths.get(source.getRootExecutionPathFragment(), source.getRelativePath());
diff --git a/aswb/BUILD b/aswb/BUILD
index 74609ee2260..7b6f74c5332 100644
--- a/aswb/BUILD
+++ b/aswb/BUILD
@@ -2,6 +2,16 @@
# Description: Builds ASwB for blaze and bazel
#
+load("@rules_java//java:defs.bzl", "java_library")
+load(
+ "//:build-visibility.bzl",
+ "ASWB_PACKAGES_VISIBILITY",
+ "ASWB_PLUGIN_PACKAGES_VISIBILITY",
+ "ASWB_SUBPACKAGES_VISIBILITY",
+ "DEFAULT_TEST_VISIBILITY",
+ "TEST_ASWB_SUBPACKAGES_VISIBILITY",
+)
+load("//:version.bzl", "VERSION")
load(
"//build_defs:build_defs.bzl",
"intellij_plugin",
@@ -15,7 +25,6 @@ load(
"//build_defs:intellij_plugin_debug_target.bzl",
"intellij_plugin_debug_target",
)
-load("//:version.bzl", "VERSION")
load(
"//intellij_platform_sdk:build_defs.bzl",
"combine_visibilities",
@@ -26,15 +35,6 @@ load(
"intellij_integration_test_suite",
"intellij_unit_test_suite",
)
-load(
- "//:build-visibility.bzl",
- "ASWB_PACKAGES_VISIBILITY",
- "ASWB_PLUGIN_PACKAGES_VISIBILITY",
- "ASWB_SUBPACKAGES_VISIBILITY",
- "TEST_ASWB_SUBPACKAGES_VISIBILITY",
-)
-
-licenses(["notice"]) # Apache 2.0
optional_plugin_xml(
name = "optional_ndk_xml",
@@ -45,7 +45,17 @@ optional_plugin_xml(
intellij_plugin_library(
name = "plugin_library",
optional_plugin_xmls = [":optional_ndk_xml"],
- plugin_xmls = ["src/META-INF/aswb.xml"],
+ plugin_xmls = [
+ "src/META-INF/aswb.xml",
+ ] + select_for_plugin_api({
+ "android-studio-2023.2": [
+ "sdkcompat/as232/com/META-INF/aswb.xml",
+ ],
+ "android-studio-2023.3": [
+ "sdkcompat/as233/com/META-INF/aswb.xml",
+ ],
+ "default": [],
+ }),
visibility = ASWB_PLUGIN_PACKAGES_VISIBILITY,
deps = [":aswb_lib"],
)
@@ -55,7 +65,7 @@ stamped_plugin_xml(
changelog_file = "//:changelog",
description_file = "src/META-INF/description.html",
plugin_id = "com.google.idea.bazel.aswb",
- plugin_name = "Bazel",
+ plugin_name = "Bazel for Android Studio",
# #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,
@@ -66,13 +76,27 @@ stamped_plugin_xml(
java_library(
name = "unit_test_utils",
testonly = 1,
- srcs = glob(["tests/utils/unit/**/*.java"]),
- visibility = TEST_ASWB_SUBPACKAGES_VISIBILITY,
+ srcs = glob(["tests/utils/unit/**/*.java"]) + select_for_plugin_api({
+ "android-studio-2022.3": [
+ "tests/utils/sdkcompat/as223/com/android/ide/common/repository/GoogleMavenArtifactIdCompat.java",
+ ],
+ "android-studio-2023.1": [
+ "tests/utils/sdkcompat/as231/com/android/ide/common/repository/GoogleMavenArtifactIdCompat.java",
+ ],
+ "android-studio-2023.2": [
+ "tests/utils/sdkcompat/as232/com/android/ide/common/repository/GoogleMavenArtifactIdCompat.java",
+ ],
+ "android-studio-2023.3": [
+ "tests/utils/sdkcompat/as233/com/android/ide/common/repository/GoogleMavenArtifactIdCompat.java",
+ ],
+ }),
+ visibility = combine_visibilities(TEST_ASWB_SUBPACKAGES_VISIBILITY, DEFAULT_TEST_VISIBILITY),
deps = [
":aswb_lib",
"//base",
"//intellij_platform_sdk:plugin_api_for_tests",
"//intellij_platform_sdk:test_libs",
+ "@com_google_guava_guava//jar",
],
)
@@ -80,12 +104,33 @@ java_library(
name = "integration_test_utils",
testonly = 1,
srcs = glob(["tests/utils/integration/**/*.java"]) + select_for_plugin_api({
- "android-studio-2021.2": glob([
- "tests/utils/sdkcompat/as212/com/google/idea/blaze/android/functional/*.java",
- ]),
- "android-studio-2021.3": glob([
- "tests/utils/sdkcompat/as213/com/google/idea/blaze/android/functional/*.java",
- ]),
+ "android-studio-2022.3": [
+ "sdkcompat/as223/com/android/tools/rendering/RenderResultCompat.java",
+ "tests/utils/sdkcompat/as223/com/android/tools/idea/sdk/IdeSdksCompat.java",
+ "tests/utils/sdkcompat/as223/com/google/idea/blaze/android/functional/AndroidDeviceCompat.java",
+ "tests/utils/sdkcompat/as223/com/google/idea/blaze/android/tools/idea/run/editor/AndroidDebuggerCompat.java",
+ ],
+ "android-studio-2023.1": [
+ "sdkcompat/as231/com/android/tools/rendering/RenderResultCompat.java",
+ "tests/utils/sdkcompat/as231/com/android/tools/idea/sdk/IdeSdksCompat.java",
+ "tests/utils/sdkcompat/as231/com/google/idea/blaze/android/MobileInstallBuildStepTestCase.java",
+ "tests/utils/sdkcompat/as231/com/google/idea/blaze/android/functional/AndroidDeviceCompat.java",
+ "tests/utils/sdkcompat/as231/com/google/idea/blaze/android/tools/idea/run/editor/AndroidDebuggerCompat.java",
+ ],
+ "android-studio-2023.2": [
+ "sdkcompat/as232/com/android/tools/rendering/RenderResultCompat.java",
+ "tests/utils/sdkcompat/as232/com/android/tools/idea/sdk/IdeSdksCompat.java",
+ "tests/utils/sdkcompat/as232/com/google/idea/blaze/android/MobileInstallBuildStepTestCase.java",
+ "tests/utils/sdkcompat/as232/com/google/idea/blaze/android/functional/AndroidDeviceCompat.java",
+ "tests/utils/sdkcompat/as232/com/google/idea/blaze/android/tools/idea/run/editor/AndroidDebuggerCompat.java",
+ ],
+ "android-studio-2023.3": [
+ "sdkcompat/as233/com/android/tools/rendering/RenderResultCompat.java",
+ "tests/utils/sdkcompat/as233/com/android/tools/idea/sdk/IdeSdksCompat.java",
+ "tests/utils/sdkcompat/as233/com/google/idea/blaze/android/MobileInstallBuildStepTestCase.java",
+ "tests/utils/sdkcompat/as233/com/google/idea/blaze/android/functional/AndroidDeviceCompat.java",
+ "tests/utils/sdkcompat/as233/com/google/idea/blaze/android/tools/idea/run/editor/AndroidDebuggerCompat.java",
+ ],
}),
visibility = TEST_ASWB_SUBPACKAGES_VISIBILITY,
deps = [
@@ -95,19 +140,34 @@ java_library(
"//base:unit_test_utils",
"//cpp",
"//intellij_platform_sdk:jsr305",
- "//intellij_platform_sdk:plugin_api_for_tests",
+ "//intellij_platform_sdk:plugin_api_for_tests", # unuseddeps: keep
"//intellij_platform_sdk:test_libs",
"//java",
+ "//shared:artifact",
"//testing:lib",
+ "@com_google_guava_guava//jar",
+ "@error_prone_annotations//jar",
"@junit//jar",
],
)
java_library(
name = "aswb_lib",
- srcs = glob(["src/**/*.java"]) + select_for_plugin_api({
- "android-studio-2021.2": glob(["sdkcompat/as212/**/*.java"]),
- "android-studio-2021.3": glob(["sdkcompat/as213/**/*.java"]),
+ srcs = glob(
+ ["src/**/*.java"],
+ # These source files below should be omitted for versions < 2023.1.1.11
+ exclude = ["src/com/google/idea/blaze/android/run/binary/tasks/*.java"],
+ ) + select_for_plugin_api({
+ "android-studio-2022.3": glob(["sdkcompat/as223/**/*.java"]),
+ "android-studio-2023.1": glob(["sdkcompat/as231/**/*.java"] + [
+ "src/com/google/idea/blaze/android/run/binary/tasks/*.java",
+ ]),
+ "android-studio-2023.2": glob(["sdkcompat/as232/**/*.java"] + [
+ "src/com/google/idea/blaze/android/run/binary/tasks/*.java",
+ ]),
+ "android-studio-2023.3": glob(["sdkcompat/as233/**/*.java"] + [
+ "src/com/google/idea/blaze/android/run/binary/tasks/*.java",
+ ]),
}),
resources = glob(["resources/**/*"]),
visibility = combine_visibilities(
@@ -117,12 +177,17 @@ java_library(
deps = [
"//base",
"//common/experiments",
- "//intellij_platform_sdk:jsr305",
+ "//cpp",
+ "//intellij_platform_sdk:jsr305", # unuseddeps: keep
"//intellij_platform_sdk:kotlin",
"//intellij_platform_sdk:plugin_api",
"//java",
"//proto:proto_deps",
+ "//querysync",
+ "//shared",
+ "//shared:artifact",
"//third_party/auto_value",
+ "@gson//jar",
],
)
@@ -130,9 +195,17 @@ intellij_unit_test_suite(
name = "unit_tests",
srcs = glob(
["tests/unittests/**/*.java"],
- exclude = ["tests/unittests/com/google/idea/blaze/android/sync/model/idea/BlazeClassJarProviderTest.java"], # b/145809318
- ),
+ exclude = [
+ "tests/unittests/com/google/idea/blaze/android/sync/model/idea/BlazeClassJarProviderTest.java", # b/145809318
+ ] + glob(["tests/unittests/sdkcompat/**"]),
+ ) + select_for_plugin_api({
+ "android-studio-2022.3": glob(["tests/unittests/sdkcompat/as223/**/*.java"]),
+ "android-studio-2023.1": glob(["tests/unittests/sdkcompat/as231/**/*.java"]),
+ "android-studio-2023.2": glob(["tests/unittests/sdkcompat/as232/**/*.java"]),
+ "android-studio-2023.3": glob(["tests/unittests/sdkcompat/as232/**/*.java"]),
+ }),
test_package_root = "com.google.idea.blaze.android",
+ visibility = DEFAULT_TEST_VISIBILITY,
deps = [
":aswb_lib",
":unit_test_utils",
@@ -145,7 +218,10 @@ intellij_unit_test_suite(
"//intellij_platform_sdk:test_libs",
"//java",
"//proto:proto_deps",
+ "//shared",
+ "//shared:artifact",
"//testing:lib",
+ "@com_google_guava_guava//jar",
"@junit//jar",
],
)
@@ -156,25 +232,38 @@ test_suite(
#b/139825934 ":NdkDependenciesTest",
":normal_integration_tests",
],
+ visibility = DEFAULT_TEST_VISIBILITY,
)
intellij_integration_test_suite(
name = "normal_integration_tests",
srcs = glob(
[
- "tests/integrationtests/**/*.java",
+ "tests/integrationtests/com/google/idea/blaze/android/**/*.java",
],
exclude = [
"tests/integrationtests/com/google/idea/blaze/android/plugin/NdkDependenciesTest.java", # Extracted to separate target
- "tests/integrationtests/com/google/idea/blaze/android/functional/AswbRenderTaskTest.java", # b/177371104
"tests/integrationtests/com/google/idea/blaze/android/functional/AswbMergedManifestTest.java", #b/222322106
- ],
- ),
+ ] + glob(["tests/integrationtests/sdkcompat/**"]),
+ ) + select_for_plugin_api({
+ "android-studio-2022.3": glob(["tests/integrationtests/sdkcompat/as223/**/*.java"]),
+ "android-studio-2023.1": glob(["tests/integrationtests/sdkcompat/as231/**/*.java"]),
+ "android-studio-2023.2": glob(["tests/integrationtests/sdkcompat/as232/**/*.java"]),
+ "default": [],
+ }),
+ additional_class_rules = select_for_plugin_api({
+ "android-studio-2022.2": ["com.google.idea.blaze.android.NormalIntegrationTestSetupRule"],
+ "android-studio-2022.3": ["com.google.idea.blaze.android.NormalIntegrationTestSetupRule"],
+ "android-studio-2023.1": ["com.google.idea.blaze.android.NormalIntegrationTestSetupRule"],
+ "android-studio-2023.2": ["com.google.idea.blaze.android.NormalIntegrationTestSetupRule"],
+ "default": [],
+ }),
data = [
"testdata/golden.png",
"testdata/ic_banner.png",
+ "tools/adt/idea/android/annotations/empty_file",
],
- required_plugins = "com.google.idea.bazel.aswb",
+ required_plugins = "com.google.idea.bazel.aswb,com.android.tools.ndk",
test_package_root = "com.google.idea.blaze.android",
runtime_deps = [
":aswb_bazel",
@@ -191,11 +280,14 @@ intellij_integration_test_suite(
"//common/experiments",
"//common/experiments:unit_test_utils",
"//cpp",
+ "//intellij_platform_sdk:jsr305",
"//intellij_platform_sdk:plugin_api_for_tests",
"//intellij_platform_sdk:test_libs",
"//java",
"//proto:proto_deps",
- "@error_prone_annotations//jar",
+ "//shared:artifact",
+ "@com_google_guava_guava//jar",
+ "@gson//jar",
"@junit//jar",
],
)
@@ -225,6 +317,9 @@ intellij_integration_test_suite(
intellij_plugin(
name = "aswb_bazel",
plugin_xml = ":stamped_plugin_xml",
+ tags = [
+ "incomplete-deps", # remove this suppression and add any missing deps, see go/java-import-deps-checking-lsc
+ ],
deps = [
":plugin_library",
"//base:plugin_library",
@@ -232,7 +327,10 @@ intellij_plugin(
"//dart:plugin_library",
"//java:plugin_library",
"//kotlin:plugin_library",
+ "//plugin_dev:plugin_library",
+ # BEGIN-EXTERNAL
"//python:plugin_library",
+ # END-EXTERNAL
"//skylark:plugin_library",
"//terminal:plugin_library",
],
@@ -278,3 +376,9 @@ plugin_deploy_zip(
visibility = ["//visibility:public"],
zip_filename = "aswb_bazel.zip",
)
+
+genrule(
+ name = "create_empty_annotations_folder",
+ outs = ["tools/adt/idea/android/annotations/empty_file"],
+ cmd = "echo \"No contents\" > $@",
+)
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
deleted file mode 100644
index 3365e2bc5e0..00000000000
--- a/aswb/sdkcompat/as212/com/android/tools/idea/run/tasks/DeployTasksCompat.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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/cppimpl/debug/BlazeNativeAndroidDebugger.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebugger.java
deleted file mode 100644
index 32472baf85e..00000000000
--- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebugger.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.cppimpl.debug;
-
-import com.android.ddmlib.Client;
-import com.android.tools.idea.run.editor.AndroidDebuggerState;
-import com.android.tools.ndk.run.attach.AndroidNativeAttachConfiguration;
-import com.android.tools.ndk.run.editor.NativeAndroidDebuggerState;
-import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
-import com.google.idea.blaze.base.settings.Blaze;
-import com.intellij.execution.RunManager;
-import com.intellij.execution.RunnerAndConfigurationSettings;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * API compat of {@link BlazeNativeAndroidDebuggerBase} with the following additions:
- *
- *
- * - Creates a run-config setting using {@link BlazeAndroidNativeAttachConfiguration} instead of
- * {@link AndroidNativeAttachConfiguration} to override counterproductive validations.
- *
- *
- * #api4.0
- */
-public class BlazeNativeAndroidDebugger extends BlazeNativeAndroidDebuggerBase {
- @NotNull
- @Override
- protected RunnerAndConfigurationSettings createRunnerAndConfigurationSettings(
- @NotNull Project project,
- @NotNull Module module,
- @NotNull Client client,
- @Nullable AndroidDebuggerState inputState) {
- String runConfigurationName =
- String.format(
- "%s %s Debugger (%d)",
- Blaze.getBuildSystemName(project).getName(),
- getDisplayName(),
- client.getClientData().getPid());
- RunnerAndConfigurationSettings runSettings =
- RunManager.getInstance(project)
- .createConfiguration(
- runConfigurationName, new BlazeAndroidNativeAttachConfigurationType.Factory());
- BlazeAndroidNativeAttachConfiguration configuration =
- (BlazeAndroidNativeAttachConfiguration) runSettings.getConfiguration();
- configuration.setClient(client);
- configuration.getAndroidDebuggerContext().setDebuggerType(getId());
- configuration.getConfigurationModule().setModule(module);
- configuration.setConsoleProvider(getConsoleProvider());
-
- // TODO(b/145707569): Copy debugger settings from inputState to state. See
- // NativeAndroidDebugger.
- AndroidDebuggerState state =
- configuration.getAndroidDebuggerContext().getAndroidDebuggerState();
- if (state instanceof NativeAndroidDebuggerState) {
- NativeAndroidDebuggerState nativeState = (NativeAndroidDebuggerState) state;
- nativeState.setWorkingDir(WorkspaceRoot.fromProject(project).directory().getPath());
- }
- return runSettings;
- }
-}
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
deleted file mode 100644
index 2703983d02f..00000000000
--- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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/ManifestValueProcessor.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/projectsystem/ManifestValueProcessor.java
deleted file mode 100644
index c87829ed348..00000000000
--- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/projectsystem/ManifestValueProcessor.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2022 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.manifmerger.ManifestSystemProperty;
-import com.google.common.collect.ImmutableMap;
-import java.util.Map;
-
-class ManifestValueProcessor {
- /**
- * Puts the key-value pair from a target's manifest_values map into either {@code directOverrides}
- * if the key corresponds to a manifest attribute that Blaze allows you to override directly, or
- * {@code placeholders} otherwise.
- *
- * @see manifest_values
- */
- static void processManifestValue(
- String key,
- String value,
- ImmutableMap.Builder directOverrides,
- ImmutableMap.Builder placeholders) {
- switch (key) {
- case "applicationId":
- directOverrides.put(ManifestSystemProperty.PACKAGE, value);
- break;
- case "versionCode":
- directOverrides.put(ManifestSystemProperty.VERSION_CODE, value);
- break;
- case "versionName":
- directOverrides.put(ManifestSystemProperty.VERSION_NAME, value);
- break;
- case "minSdkVersion":
- directOverrides.put(ManifestSystemProperty.MIN_SDK_VERSION, value);
- break;
- case "targetSdkVersion":
- directOverrides.put(ManifestSystemProperty.TARGET_SDK_VERSION, value);
- break;
- case "maxSdkVersion":
- directOverrides.put(ManifestSystemProperty.MAX_SDK_VERSION, value);
- break;
- case "packageName":
- // From the doc: "packageName will be ignored and will be set from either applicationId if
- // specified or the package in manifest"
- break;
- default:
- placeholders.put(key, value);
- }
- }
-
- static String getPackageOverride(Map overrides) {
- return overrides.get(ManifestSystemProperty.PACKAGE);
- }
-
- private ManifestValueProcessor() {}
-}
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
deleted file mode 100644
index 032ec26e8bb..00000000000
--- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/BlazeAndroidDeploymentService.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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/runner/BlazeAndroidLaunchTasksProvider.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java
deleted file mode 100644
index aaf5a9897b6..00000000000
--- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * 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(runContext.getExecutor())) {
- 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(runContext.getExecutor())) {
- amStartOptions.add(
- AndroidProfilerLaunchTaskContributor.getAmStartOptions(
- project,
- packageName,
- runContext.getProfileState(),
- device,
- runContext.getExecutor()));
- launchTasks.add(
- new AndroidProfilerLaunchTaskContributor.AndroidProfilerToolWindowLaunchTask(
- project, 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/test/BlazeAndroidTestRunContext.java b/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java
deleted file mode 100644
index 8f536daf68a..00000000000
--- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java
+++ /dev/null
@@ -1,99 +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.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.Executor;
-import com.intellij.execution.runners.ExecutionEnvironment;
-import com.intellij.openapi.project.Project;
-import org.jetbrains.android.facet.AndroidFacet;
-
-/**
- * Run context for android_test.
- *
- * #api203
- */
-public class BlazeAndroidTestRunContext extends BlazeAndroidTestRunContextBase {
- BlazeAndroidTestRunContext(
- Project project,
- AndroidFacet facet,
- BlazeCommandRunConfiguration runConfiguration,
- ExecutionEnvironment env,
- BlazeAndroidTestRunConfigurationState configState,
- Label label,
- ImmutableList blazeFlags,
- ImmutableList exeFlags,
- String launchId) {
- super(
- project, facet, runConfiguration, env, configState, label, blazeFlags, exeFlags, launchId);
- }
-
- @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();
- }
-
- @Override
- public Executor getExecutor() {
- return env.getExecutor();
- }
-}
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
deleted file mode 100644
index 437cdd425f6..00000000000
--- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/test/ConnectBlazeTestDebuggerTask.java
+++ /dev/null
@@ -1,138 +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.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/as213/com/android/tools/idea/run/tasks/DeployTasksCompat.java b/aswb/sdkcompat/as213/com/android/tools/idea/run/tasks/DeployTasksCompat.java
deleted file mode 100644
index 3365e2bc5e0..00000000000
--- a/aswb/sdkcompat/as213/com/android/tools/idea/run/tasks/DeployTasksCompat.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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/as213/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebugger.java b/aswb/sdkcompat/as213/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebugger.java
deleted file mode 100644
index 096b2e327d7..00000000000
--- a/aswb/sdkcompat/as213/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebugger.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.cppimpl.debug;
-
-import com.android.ddmlib.Client;
-import com.android.tools.ndk.run.attach.AndroidNativeAttachConfiguration;
-import com.android.tools.ndk.run.editor.NativeAndroidDebuggerState;
-import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
-import com.google.idea.blaze.base.settings.Blaze;
-import com.intellij.execution.RunManager;
-import com.intellij.execution.RunnerAndConfigurationSettings;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * API compat of {@link BlazeNativeAndroidDebuggerBase} with the following additions:
- *
- *
- * - Creates a run-config setting using {@link BlazeAndroidNativeAttachConfiguration} instead of
- * {@link AndroidNativeAttachConfiguration} to override counterproductive validations.
- *
- *
- * #api4.0
- */
-public class BlazeNativeAndroidDebugger extends BlazeNativeAndroidDebuggerBase {
- @NotNull
- @Override
- protected RunnerAndConfigurationSettings createRunnerAndConfigurationSettings(
- @NotNull Project project,
- @NotNull Module module,
- @NotNull Client client,
- @Nullable NativeAndroidDebuggerState state) {
- String runConfigurationName =
- String.format(
- "%s %s Debugger (%d)",
- Blaze.getBuildSystemName(project).getName(),
- getDisplayName(),
- client.getClientData().getPid());
- RunnerAndConfigurationSettings runSettings =
- RunManager.getInstance(project)
- .createConfiguration(
- runConfigurationName, new BlazeAndroidNativeAttachConfigurationType.Factory());
- BlazeAndroidNativeAttachConfiguration configuration =
- (BlazeAndroidNativeAttachConfiguration) runSettings.getConfiguration();
- configuration.setClient(client);
- configuration.getAndroidDebuggerContext().setDebuggerType(getId());
- configuration.getConfigurationModule().setModule(module);
- configuration.setConsoleProvider(getConsoleProvider());
-
- // TODO(b/145707569): Copy debugger settings from inputState to state. See
- // NativeAndroidDebugger.
- NativeAndroidDebuggerState targetState =
- configuration.getAndroidDebuggerContext().getAndroidDebuggerState();
- if (state != null) {
- // Copy the settings of the state provided as the input onto the targetState.
- assert targetState != null;
- targetState.setSymbolDirs(state.getSymbolDirs());
- targetState.setUserStartupCommands(state.getUserStartupCommands());
- targetState.setUserPostAttachCommands(state.getUserPostAttachCommands());
- targetState.setWorkingDir(WorkspaceRoot.fromProject(project).directory().getPath());
- }
- return runSettings;
- }
-}
diff --git a/aswb/sdkcompat/as213/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java b/aswb/sdkcompat/as213/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java
deleted file mode 100644
index 8a6efabe9e1..00000000000
--- a/aswb/sdkcompat/as213/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * 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 java.util.Collections;
-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);
- }
-
- @Override
- public Collection getAndroidLibraryDependencies(
- DependencyScopeType dependencyScopeType) {
- if (dependencyScopeType == DependencyScopeType.MAIN) {
- return getDependentLibraries();
- } else {
- return Collections.emptyList();
- }
- }
-}
diff --git a/aswb/sdkcompat/as213/com/google/idea/blaze/android/projectsystem/ExternalLibraryInterner.java b/aswb/sdkcompat/as213/com/google/idea/blaze/android/projectsystem/ExternalLibraryInterner.java
deleted file mode 100644
index 428579821e8..00000000000
--- a/aswb/sdkcompat/as213/com/google/idea/blaze/android/projectsystem/ExternalLibraryInterner.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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/as213/com/google/idea/blaze/android/run/BlazeAndroidDeploymentService.java b/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/BlazeAndroidDeploymentService.java
deleted file mode 100644
index 032ec26e8bb..00000000000
--- a/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/BlazeAndroidDeploymentService.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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/as213/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java b/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java
deleted file mode 100644
index 01c6a1a7885..00000000000
--- a/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java
+++ /dev/null
@@ -1,93 +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.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.Executor;
-import com.intellij.execution.runners.ExecutionEnvironment;
-import com.intellij.openapi.project.Project;
-import org.jetbrains.android.facet.AndroidFacet;
-
-/**
- * Run context for android_test.
- *
- * #api203
- */
-public class BlazeAndroidTestRunContext extends BlazeAndroidTestRunContextBase {
- BlazeAndroidTestRunContext(
- Project project,
- AndroidFacet facet,
- BlazeCommandRunConfiguration runConfiguration,
- ExecutionEnvironment env,
- BlazeAndroidTestRunConfigurationState configState,
- Label label,
- ImmutableList blazeFlags,
- ImmutableList exeFlags,
- String launchId) {
- super(
- project, facet, runConfiguration, env, configState, label, blazeFlags, exeFlags, launchId);
- }
-
- @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(), applicationIdProvider, this);
- case NON_BLAZE:
- case MOBILE_INSTALL:
- return androidDebugger.getConnectDebuggerTask(
- env, applicationIdProvider, facet, androidDebuggerState);
- }
- throw new AssertionError();
- }
-
- @Override
- public Executor getExecutor() {
- return env.getExecutor();
- }
-}
diff --git a/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/test/ConnectBlazeTestDebuggerTask.java b/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/test/ConnectBlazeTestDebuggerTask.java
deleted file mode 100644
index c164398f30a..00000000000
--- a/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/test/ConnectBlazeTestDebuggerTask.java
+++ /dev/null
@@ -1,134 +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.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.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 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,
- ApplicationIdProvider applicationIdProvider,
- BlazeAndroidTestRunContext runContext) {
- super(applicationIdProvider, 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/as223/com/android/tools/configurations/ConfigurationCompat.java b/aswb/sdkcompat/as223/com/android/tools/configurations/ConfigurationCompat.java
new file mode 100644
index 00000000000..f4c78781600
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/android/tools/configurations/ConfigurationCompat.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.configurations;
+
+import com.android.sdklib.devices.Device;
+import com.android.tools.idea.configurations.Configuration;
+
+/** Compat class for Configuration. */
+public class ConfigurationCompat {
+
+ private Configuration configuration;
+
+ public ConfigurationCompat(Configuration configuration) {
+ this.configuration = configuration;
+ }
+
+ public void setDevice(Device device, boolean preserveState) {
+ configuration.setDevice(device, preserveState);
+ }
+}
diff --git a/aswb/sdkcompat/as212/com/android/tools/idea/model/AndroidManifestIndexCompat.java b/aswb/sdkcompat/as223/com/android/tools/idea/model/AndroidManifestIndexCompat.java
similarity index 100%
rename from aswb/sdkcompat/as212/com/android/tools/idea/model/AndroidManifestIndexCompat.java
rename to aswb/sdkcompat/as223/com/android/tools/idea/model/AndroidManifestIndexCompat.java
diff --git a/aswb/sdkcompat/as212/com/android/tools/idea/progress/StudioLoggerProgressIndicatorCompat.java b/aswb/sdkcompat/as223/com/android/tools/idea/progress/StudioLoggerProgressIndicatorCompat.java
similarity index 100%
rename from aswb/sdkcompat/as212/com/android/tools/idea/progress/StudioLoggerProgressIndicatorCompat.java
rename to aswb/sdkcompat/as223/com/android/tools/idea/progress/StudioLoggerProgressIndicatorCompat.java
diff --git a/aswb/sdkcompat/as223/com/android/tools/idea/rendering/RenderErrorContributorCompat.java b/aswb/sdkcompat/as223/com/android/tools/idea/rendering/RenderErrorContributorCompat.java
new file mode 100644
index 00000000000..cb3193e1072
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/android/tools/idea/rendering/RenderErrorContributorCompat.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.idea.rendering;
+
+import com.android.tools.idea.ui.designer.EditorDesignSurface;
+import com.android.tools.rendering.RenderResultCompat;
+import com.intellij.openapi.actionSystem.DataContext;
+import org.jetbrains.annotations.Nullable;
+
+/** Contribute blaze specific render errors. */
+public class RenderErrorContributorCompat extends RenderErrorContributor {
+ public RenderErrorContributorCompat(
+ EditorDesignSurface surface, RenderResultCompat result, @Nullable DataContext dataContext) {
+ super(surface, result.get(), dataContext);
+ }
+}
diff --git a/aswb/sdkcompat/as223/com/android/tools/idea/run/tasks/DeployTasksCompat.java b/aswb/sdkcompat/as223/com/android/tools/idea/run/tasks/DeployTasksCompat.java
new file mode 100644
index 00000000000..500a6786340
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/android/tools/idea/run/tasks/DeployTasksCompat.java
@@ -0,0 +1,46 @@
+/*
+ * 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.run.ApkInfo;
+import com.android.tools.idea.run.LaunchOptions;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.blaze.BlazeLaunchTaskWrapper;
+import com.google.idea.common.experiments.BoolExperiment;
+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 BlazeLaunchTask createDeployTask(
+ Project project, Collection packages, LaunchOptions launchOptions) {
+ // We don't have a device information, fallback to the most conservative
+ // install option.
+ return new BlazeLaunchTaskWrapper(
+ new DeployTask(
+ project,
+ packages,
+ launchOptions.getPmInstallOptions(/* device= */ null),
+ launchOptions.getInstallOnAllUsers(),
+ launchOptions.getAlwaysInstallWithPm()));
+ }
+}
+
diff --git a/aswb/sdkcompat/as223/com/android/tools/rendering/HtmlLinkManagerCompat.java b/aswb/sdkcompat/as223/com/android/tools/rendering/HtmlLinkManagerCompat.java
new file mode 100644
index 00000000000..594132f69af
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/android/tools/rendering/HtmlLinkManagerCompat.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.rendering;
+
+import com.android.tools.idea.rendering.HtmlLinkManager;
+import java.io.File;
+import org.jetbrains.annotations.NotNull;
+
+/** Compat class for {@link HtmlLinkManager} */
+public final class HtmlLinkManagerCompat {
+ public static String createFilePositionUrl(@NotNull File file, int line, int column) {
+ return HtmlLinkManager.createFilePositionUrl(file, line, column);
+ }
+
+ private HtmlLinkManagerCompat() {}
+}
diff --git a/aswb/sdkcompat/as223/com/android/tools/rendering/RenderLoggerCompat.java b/aswb/sdkcompat/as223/com/android/tools/rendering/RenderLoggerCompat.java
new file mode 100644
index 00000000000..e1a83953327
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/android/tools/rendering/RenderLoggerCompat.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.rendering;
+
+import com.android.tools.idea.rendering.RenderLogger;
+import java.util.Map;
+import java.util.Set;
+
+/** Compat class for RenderLogger. */
+public class RenderLoggerCompat {
+ private final RenderLogger renderLogger;
+
+ public RenderLoggerCompat(RenderResultCompat result) {
+ renderLogger = result.getLogger();
+ }
+
+ public boolean hasErrors() {
+ return renderLogger.hasErrors();
+ }
+
+ public Map getBrokenClasses() {
+ return renderLogger.getBrokenClasses();
+ }
+
+ public Set getMissingClasses() {
+ return renderLogger.getMissingClasses();
+ }
+
+ public static void resetFidelityErrorsFilters() {
+ RenderLogger.resetFidelityErrorsFilters();
+ }
+}
diff --git a/aswb/sdkcompat/as223/com/android/tools/rendering/RenderResultCompat.java b/aswb/sdkcompat/as223/com/android/tools/rendering/RenderResultCompat.java
new file mode 100644
index 00000000000..8892c2fe813
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/android/tools/rendering/RenderResultCompat.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.rendering;
+
+import com.android.tools.idea.rendering.RenderErrorContributor;
+import com.android.tools.idea.rendering.RenderErrorModelFactory;
+import com.android.tools.idea.rendering.RenderLogger;
+import com.android.tools.idea.rendering.RenderResult;
+import com.android.tools.idea.rendering.RenderResults;
+import com.android.tools.idea.rendering.errors.ui.RenderErrorModel;
+import com.android.tools.idea.ui.designer.EditorDesignSurface;
+import com.google.idea.blaze.android.rendering.BlazeRenderErrorContributor;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.Nullable;
+
+/** Compat class for {@link RenderResult} */
+public final class RenderResultCompat {
+ private RenderResult result;
+
+ public static RenderResultCompat createBlank(PsiFile file) {
+ return new RenderResultCompat(RenderResults.createBlank(file));
+ }
+
+ public RenderErrorModel createErrorModel() {
+ return RenderErrorModelFactory.createErrorModel(null, result, null);
+ }
+
+ public RenderResult get() {
+ return result;
+ }
+
+ public RenderLogger getLogger() {
+ return result.getLogger();
+ }
+
+ public Module getModule() {
+ return result.getModule();
+ }
+
+ public RenderResultCompat(RenderResult result) {
+ this.result = result;
+ }
+
+ private RenderResultCompat() {}
+
+ /** Extension to provide {@link BlazeRenderErrorContributor}. */
+ public static class BlazeProvider extends RenderErrorContributor.Provider {
+ @Override
+ public boolean isApplicable(Project project) {
+ return Blaze.isBlazeProject(project);
+ }
+
+ @Override
+ public RenderErrorContributor getContributor(
+ @Nullable EditorDesignSurface surface,
+ RenderResult result,
+ @Nullable DataContext dataContext) {
+ return new BlazeRenderErrorContributor(surface, new RenderResultCompat(result), dataContext);
+ }
+ }
+}
diff --git a/aswb/sdkcompat/as223/com/android/tools/rendering/RenderServiceCompat.java b/aswb/sdkcompat/as223/com/android/tools/rendering/RenderServiceCompat.java
new file mode 100644
index 00000000000..4802d5ebf45
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/android/tools/rendering/RenderServiceCompat.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.rendering;
+
+import com.android.tools.idea.rendering.RenderService;
+
+/** Compat class for {@link RenderService} */
+public final class RenderServiceCompat {
+ public static void shutdownRenderExecutor(long l) {
+ RenderService.shutdownRenderExecutor(l);
+ }
+
+ public static void initializeRenderExecutor() {
+ RenderService.initializeRenderExecutor();
+ }
+
+ private RenderServiceCompat() {}
+}
diff --git a/aswb/sdkcompat/as213/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java
similarity index 66%
rename from aswb/sdkcompat/as213/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java
index 9aa08f911e9..7aa210d0595 100644
--- a/aswb/sdkcompat/as213/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java
@@ -17,17 +17,26 @@
import com.android.ddmlib.Client;
import com.android.tools.ndk.run.editor.AutoAndroidDebuggerState;
+import com.intellij.execution.ExecutionException;
+import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XDebugSession;
/** Shim for #api212 compat. */
public class BlazeAutoAndroidDebugger extends BlazeAutoAndroidDebuggerBase {
@Override
- public void attachToClient(Project project, Client client, AutoAndroidDebuggerState state) {
+ public XDebugSession attachToClient(
+ Project project, Client client, AutoAndroidDebuggerState state) throws ExecutionException {
if (isNativeProject(project)) {
log.info("Project has native development enabled. Attaching native debugger.");
- nativeDebugger.attachToClient(project, client, state);
+ return nativeDebugger.attachToClient(project, client, state);
} else {
- super.attachToClient(project, client, state);
+ return super.attachToClient(project, client, state);
}
}
+
+ @Override
+ protected boolean isNativeDeployment(Project project, Module debuggeeModule) {
+ return isNativeProject(project);
+ }
}
diff --git a/aswb/sdkcompat/as223/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebugger.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebugger.java
new file mode 100644
index 00000000000..e92afddc27c
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebugger.java
@@ -0,0 +1,28 @@
+/*
+ * 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.cppimpl.debug;
+
+/**
+ * API compat of {@link BlazeNativeAndroidDebuggerBase} with the following additions:
+ *
+ *
+ * - Creates a run-config setting using {@link BlazeAndroidNativeAttachConfiguration} instead of
+ * {@link AndroidNativeAttachConfiguration} to override counterproductive validations.
+ *
+ *
+ * #api4.0
+ */
+public class BlazeNativeAndroidDebugger extends BlazeNativeAndroidDebuggerBase {}
diff --git a/aswb/sdkcompat/as223/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebuggerBase.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebuggerBase.java
new file mode 100644
index 00000000000..911d90b7711
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebuggerBase.java
@@ -0,0 +1,59 @@
+/*
+ * 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.cppimpl.debug;
+
+import com.android.tools.ndk.run.editor.NativeAndroidDebugger;
+import com.google.idea.blaze.base.model.BlazeProjectData;
+import com.google.idea.blaze.base.model.primitives.LanguageClass;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
+import com.intellij.openapi.project.Project;
+
+/**
+ * Extension of {@link NativeAndroidDebugger} with the following key differences compared to {@link
+ * NativeAndroidDebugger}.
+ *
+ *
+ * - Overrides {@link #supportsProject} so native debugger is only enabled for native support is
+ * enabled.
+ *
+ */
+public class BlazeNativeAndroidDebuggerBase extends NativeAndroidDebugger {
+ /**
+ * This ID needs to be lexicographically larger than "Java" so it come after the "Java" debugger
+ * when sorted lexicographically in the "Attach Debugger to Android Process" dialog. See {@link
+ * org.jetbrains.android.actions.AndroidProcessChooserDialog#populateDebuggerTypeCombo}.
+ */
+ public static final String ID = "Native" + Blaze.defaultBuildSystemName();
+
+ @Override
+ public String getId() {
+ return ID;
+ }
+
+ @Override
+ public String getDisplayName() {
+ return "Native Only";
+ }
+
+ @Override
+ public boolean supportsProject(Project project) {
+ BlazeProjectData blazeProjectData =
+ BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
+ return blazeProjectData != null
+ && blazeProjectData.getWorkspaceLanguageSettings().isLanguageActive(LanguageClass.C);
+ }
+}
diff --git a/aswb/sdkcompat/as223/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java
new file mode 100644
index 00000000000..162fd8f1793
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java
@@ -0,0 +1,27 @@
+/*
+ * 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.tools.idea.projectsystem.AndroidModuleSystem;
+import com.intellij.openapi.module.Module;
+
+/** Blaze implementation of {@link AndroidModuleSystem}. */
+public class BlazeModuleSystem extends BlazeModuleSystemBase {
+
+ BlazeModuleSystem(Module module) {
+ super(module);
+ }
+}
diff --git a/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeProjectSystem.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/projectsystem/BlazeProjectSystem.java
similarity index 75%
rename from aswb/src/com/google/idea/blaze/android/projectsystem/BlazeProjectSystem.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/projectsystem/BlazeProjectSystem.java
index 036bdc41e3a..4aa6e3b854d 100755
--- a/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeProjectSystem.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/projectsystem/BlazeProjectSystem.java
@@ -15,6 +15,7 @@
*/
package com.google.idea.blaze.android.projectsystem;
+import static com.android.tools.idea.projectsystem.SourceProvidersKt.emptySourceProvider;
import static org.jetbrains.android.facet.SourceProviderUtil.createSourceProvidersForLegacyModule;
import com.android.tools.apk.analyzer.AaptInvoker;
@@ -26,8 +27,11 @@
import com.android.tools.idea.projectsystem.NamedIdeaSourceProvider;
import com.android.tools.idea.projectsystem.ProjectSystemBuildManager;
import com.android.tools.idea.projectsystem.ProjectSystemSyncManager;
+import com.android.tools.idea.projectsystem.ScopeType;
+import com.android.tools.idea.projectsystem.SourceProviderManager;
import com.android.tools.idea.projectsystem.SourceProviders;
import com.android.tools.idea.projectsystem.SourceProvidersFactory;
+import com.android.tools.idea.projectsystem.SourceProvidersImpl;
import com.android.tools.idea.res.AndroidInnerClassFinder;
import com.android.tools.idea.res.AndroidResourceClassPsiElementFinder;
import com.android.tools.idea.sdk.AndroidSdks;
@@ -35,7 +39,8 @@
import com.google.idea.blaze.android.resources.BlazeLightResourceClassService;
import com.google.idea.blaze.android.sync.model.idea.BlazeAndroidModel;
import com.google.idea.blaze.android.sync.model.idea.BlazeClassJarProvider;
-import com.google.idea.blaze.base.build.BlazeBuildService;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.settings.BlazeImportSettings.ProjectType;
import com.intellij.facet.ProjectFacetManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
@@ -49,8 +54,7 @@
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.jetbrains.android.facet.AndroidFacet;
-import org.jetbrains.android.facet.SourceProviderManager;
-import org.jetbrains.android.facet.SourceProvidersImpl;
+import org.jetbrains.annotations.NotNull;
/**
* Base class to implement common methods in {@link AndroidProjectSystem} for blaze with different
@@ -73,6 +77,10 @@ public BlazeProjectSystem(Project project) {
new AndroidResourceClassPsiElementFinder(getLightResourceClassService()));
}
+ public Project getProject() {
+ return project;
+ }
+
@Override
public boolean allowsFileCreation() {
return true;
@@ -91,12 +99,7 @@ public Path getPathToAapt() {
new LogWrapper(BlazeProjectSystem.class));
}
- // @Override #api42
- public void buildProject() {
- BlazeBuildService.getInstance(project).buildProject();
- }
-
- // @Override #api42
+ @Override
public ProjectSystemBuildManager getBuildManager() {
return buildManager;
}
@@ -136,18 +139,38 @@ public SourceProviders createSourceProvidersFor(AndroidFacet facet) {
private SourceProviders createForModel(BlazeAndroidModel model) {
NamedIdeaSourceProvider mainSourceProvider = model.getDefaultSourceProvider();
- return new SourceProvidersImpl(
- mainSourceProvider,
- ImmutableList.of(mainSourceProvider),
- ImmutableList.of(mainSourceProvider),
- ImmutableList.of(mainSourceProvider),
- ImmutableList.of(mainSourceProvider),
- ImmutableList.of(mainSourceProvider));
+ if (Blaze.getProjectType(project).equals(ProjectType.QUERY_SYNC)) {
+ return new SourceProvidersImpl(
+ mainSourceProvider,
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(),
+ ImmutableList.of(),
+ ImmutableList.of(),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ emptySourceProvider(ScopeType.MAIN),
+ emptySourceProvider(ScopeType.UNIT_TEST),
+ emptySourceProvider(ScopeType.ANDROID_TEST),
+ emptySourceProvider(ScopeType.TEST_FIXTURES));
+ } else {
+ return new SourceProvidersImpl(
+ mainSourceProvider,
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ emptySourceProvider(ScopeType.MAIN),
+ emptySourceProvider(ScopeType.UNIT_TEST),
+ emptySourceProvider(ScopeType.ANDROID_TEST),
+ emptySourceProvider(ScopeType.TEST_FIXTURES));
+ }
}
};
}
- // @Override #api212
+ @Override
public ClassJarProvider getClassJarProvider() {
return new BlazeClassJarProvider(project);
}
@@ -159,8 +182,7 @@ public Collection getAndroidFacetsWithPackageName(
project, packageName, GlobalSearchScope.projectScope(project));
}
- // @Override #api203
- public Collection getAndroidFacetsWithPackageName(
+ private Collection getAndroidFacetsWithPackageName(
Project project, String packageName, GlobalSearchScope scope) {
List facets = ProjectFacetManager.getInstance(project).getFacets(AndroidFacet.ID);
return facets.stream()
@@ -182,6 +204,12 @@ public Collection getSubmodules() {
return ImmutableList.of();
}
+ @Override
+ public Collection getBootClasspath(@NotNull Module module) {
+ // TODO: b/266586669
+ return ImmutableList.of();
+ }
+
private static boolean hasPackageName(AndroidFacet facet, String packageName) {
String nameFromFacet = PackageNameUtils.getPackageName(facet.getModule());
if (nameFromFacet == null) {
diff --git a/aswb/src/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java
similarity index 88%
rename from aswb/src/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java
index 8c1a383a496..81504173f22 100644
--- a/aswb/src/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java
@@ -30,6 +30,11 @@
import com.google.idea.blaze.base.ideinfo.TargetKey;
import com.google.idea.blaze.base.io.VirtualFileSystemProvider;
import com.google.idea.blaze.base.model.BlazeProjectData;
+import com.google.idea.blaze.base.qsync.QuerySync;
+import com.google.idea.blaze.base.qsync.QuerySyncManager;
+import com.google.idea.blaze.base.qsync.RenderJarArtifactTracker;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.settings.BlazeImportSettings.ProjectType;
import com.google.idea.blaze.base.sync.BlazeSyncModificationTracker;
import com.google.idea.blaze.base.sync.data.BlazeDataStorage;
import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
@@ -136,6 +141,28 @@ public VirtualFile findClass(String fqcn) {
return null;
}
+ if (Blaze.getProjectType(project).equals(ProjectType.QUERY_SYNC)) {
+ if (QuerySync.isComposeEnabled(project)) {
+ RenderJarArtifactTracker renderJarArtifactTracker =
+ QuerySyncManager.getInstance(project).getRenderJarArtifactTracker();
+ // TODO(b/283280194): Setup fqcn -> target and target -> Render jar mappings to avoid
+ // iterating over all render jars when trying to locate class for fqcn.
+ // TODO(b/284002836): Collect metrics on time taken to iterate over the jars
+ for (File renderJar : renderJarArtifactTracker.getRenderJars()) {
+ VirtualFile renderResolveJarVf =
+ VirtualFileSystemProvider.getInstance().getSystem().findFileByIoFile(renderJar);
+ if (renderResolveJarVf != null) {
+ return findClassInJar(renderResolveJarVf, fqcn);
+ }
+ log.warn(String.format("Could not find class `%1$s` with Query Sync", fqcn));
+ return null;
+ }
+ } else {
+ // Disable this class for Query Sync if Compose is not enabled
+ return null;
+ }
+ }
+
BlazeProjectData projectData =
BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
if (projectData == null) {
diff --git a/aswb/src/com/google/idea/blaze/android/rendering/BlazeRenderErrorContributor.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/rendering/BlazeRenderErrorContributor.java
similarity index 91%
rename from aswb/src/com/google/idea/blaze/android/rendering/BlazeRenderErrorContributor.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/rendering/BlazeRenderErrorContributor.java
index e45d473a4f2..827e5975a35 100644
--- a/aswb/src/com/google/idea/blaze/android/rendering/BlazeRenderErrorContributor.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/rendering/BlazeRenderErrorContributor.java
@@ -16,19 +16,21 @@
package com.google.idea.blaze.android.rendering;
import static com.android.SdkConstants.ANDROID_MANIFEST_XML;
+import static com.google.common.collect.ImmutableMap.toImmutableMap;
-import com.android.tools.idea.rendering.HtmlLinkManager;
-import com.android.tools.idea.rendering.RenderErrorContributor;
-import com.android.tools.idea.rendering.RenderLogger;
-import com.android.tools.idea.rendering.RenderResult;
+import com.android.tools.idea.rendering.RenderErrorContributorCompat;
import com.android.tools.idea.rendering.errors.ui.RenderErrorModel;
import com.android.tools.idea.ui.designer.EditorDesignSurface;
+import com.android.tools.rendering.HtmlLinkManagerCompat;
+import com.android.tools.rendering.RenderLoggerCompat;
+import com.android.tools.rendering.RenderResultCompat;
import com.android.utils.HtmlBuilder;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.Maps;
import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.idea.blaze.android.sync.model.AndroidResourceModule;
import com.google.idea.blaze.android.sync.model.AndroidResourceModuleRegistry;
import com.google.idea.blaze.base.command.buildresult.OutputArtifactResolver;
@@ -40,6 +42,7 @@
import com.google.idea.blaze.base.lang.buildfile.references.BuildReferenceManager;
import com.google.idea.blaze.base.model.BlazeProjectData;
import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.settings.BlazeImportSettings.ProjectType;
import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
import com.google.idea.blaze.base.sync.workspace.ArtifactLocationDecoder;
import com.google.idea.blaze.base.targetmaps.SourceToTargetMap;
@@ -62,21 +65,21 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
+import java.util.Set;
import java.util.SortedMap;
import java.util.function.Function;
-import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;
/** Contribute blaze specific render errors. */
-public class BlazeRenderErrorContributor extends RenderErrorContributor {
- private RenderLogger logger;
- private Module module;
- private Project project;
+public class BlazeRenderErrorContributor extends RenderErrorContributorCompat {
+ private final RenderLoggerCompat logger;
+ private final Module module;
+ private final Project project;
public BlazeRenderErrorContributor(
- EditorDesignSurface surface, RenderResult result, @Nullable DataContext dataContext) {
+ EditorDesignSurface surface, RenderResultCompat result, @Nullable DataContext dataContext) {
super(surface, result, dataContext);
- logger = result.getLogger();
+ logger = new RenderLoggerCompat(result);
module = result.getModule();
project = module.getProject();
}
@@ -90,6 +93,11 @@ public Collection reportIssues() {
return getIssues();
}
+ if (Blaze.getProjectType(project).equals(ProjectType.QUERY_SYNC)) {
+ // TODO(b/284002829): Setup resource-module specific issue reporting
+ return getIssues();
+ }
+
TargetMap targetMap = blazeProjectData.getTargetMap();
ArtifactLocationDecoder decoder = blazeProjectData.getArtifactLocationDecoder();
AndroidResourceModule resourceModule =
@@ -162,7 +170,7 @@ private static SortedMap getGeneratedResources(
target.getAndroidIdeInfo().getResources().stream()
.map(AndroidResFolder::getRoot)
.filter(ArtifactLocation::isGenerated)
- .collect(Collectors.toMap(Function.identity(), resource -> target)));
+ .collect(toImmutableMap(Function.identity(), resource -> target)));
return generatedResources;
}
@@ -195,7 +203,7 @@ private void reportNonStandardAndroidManifestName(
HtmlBuilder builder = new HtmlBuilder();
addTargetLink(builder, target, decoder)
.add(" uses a non-standard name for the Android manifest: ");
- String linkToManifest = HtmlLinkManager.createFilePositionUrl(manifest, -1, 0);
+ String linkToManifest = HtmlLinkManagerCompat.createFilePositionUrl(manifest, -1, 0);
if (linkToManifest != null) {
builder.addLink(manifest.getName(), linkToManifest);
} else {
@@ -220,9 +228,10 @@ private void reportNonStandardAndroidManifestName(
* android_binary, so we could end up with resources that ultimately build correctly, but fail to
* find their class dependencies during rendering in the layout editor.
*/
+ @SuppressWarnings("rawtypes")
private void reportResourceTargetShouldDependOnClassTarget(
TargetIdeInfo target, TargetMap targetMap, ArtifactLocationDecoder decoder) {
- Collection missingClasses = logger.getMissingClasses();
+ Set missingClasses = logger.getMissingClasses();
if (missingClasses == null || missingClasses.isEmpty()) {
return;
}
@@ -307,6 +316,7 @@ private File getSourceFileForClass(String className) {
});
}
+ @CanIgnoreReturnValue
private HtmlBuilder addTargetLink(
HtmlBuilder builder, TargetIdeInfo target, ArtifactLocationDecoder decoder) {
File buildFile =
@@ -332,26 +342,10 @@ private HtmlBuilder addTargetLink(
return StringUtil.offsetToLineNumber(
psiFile.getText(), buildTargetPsi.getTextOffset());
});
- String url = HtmlLinkManager.createFilePositionUrl(buildFile, line, 0);
+ String url = HtmlLinkManagerCompat.createFilePositionUrl(buildFile, line, 0);
if (url != null) {
return builder.addLink(target.toString(), url);
}
return builder.add(target.toString());
}
-
- /** Extension to provide {@link BlazeRenderErrorContributor}. */
- public static class BlazeProvider extends Provider {
- @Override
- public boolean isApplicable(Project project) {
- return Blaze.isBlazeProject(project);
- }
-
- @Override
- public RenderErrorContributor getContributor(
- @Nullable EditorDesignSurface surface,
- RenderResult result,
- @Nullable DataContext dataContext) {
- return new BlazeRenderErrorContributor(surface, result, dataContext);
- }
- }
}
diff --git a/aswb/src/com/google/idea/blaze/android/rendering/BlazeRenderSecurityManagerOverrides.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/rendering/BlazeRenderSecurityManagerOverrides.java
similarity index 100%
rename from aswb/src/com/google/idea/blaze/android/rendering/BlazeRenderSecurityManagerOverrides.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/rendering/BlazeRenderSecurityManagerOverrides.java
diff --git a/aswb/sdkcompat/as223/com/google/idea/blaze/android/resources/BlazeLightResourceClassServiceBase.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/resources/BlazeLightResourceClassServiceBase.java
new file mode 100644
index 00000000000..21516076cc2
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/resources/BlazeLightResourceClassServiceBase.java
@@ -0,0 +1,66 @@
+/*
+ * 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.resources;
+
+import com.android.tools.idea.projectsystem.LightResourceClassService;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.idea.blaze.base.sync.data.BlazeDataStorage;
+import com.google.idea.common.experiments.FeatureRolloutExperiment;
+import com.intellij.openapi.module.Module;
+import com.intellij.psi.PsiClass;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/** Implementation of {@link LightResourceClassService} set up at Blaze sync time. */
+public abstract class BlazeLightResourceClassServiceBase implements LightResourceClassService {
+
+ @VisibleForTesting
+ public static final FeatureRolloutExperiment workspaceResourcesFeature =
+ new FeatureRolloutExperiment("aswb.workspace.light.class.enabled");
+
+ Map rClasses = Maps.newHashMap();
+ Map rClassesByModule = Maps.newHashMap();
+ final Set allRClasses = Sets.newHashSet();
+
+ @Override
+ public Collection extends PsiClass> getLightRClassesAccessibleFromModule(
+ Module module, boolean includeTest) {
+ if (workspaceResourcesFeature.isEnabled()
+ && module.getName().equals(BlazeDataStorage.WORKSPACE_MODULE_NAME)) {
+ // Returns all the packages in resource modules, and all the workspace packages that
+ // have previously been asked for. All `res/` directories in our project should belong to a
+ // resource module. For java sources, IntelliJ will ask for explicit resource package by
+ // calling `getLightRClasses` at which point we can create the package. This is not completely
+ // correct and the autocomplete will be slightly off when initial `R` is typed in the editor,
+ // but this workaround is being used to mitigate issues (b/136685602) while resources
+ // are re-worked.
+ return allRClasses;
+ } else {
+ return rClasses.values();
+ }
+ }
+
+ @Override
+ public Collection extends PsiClass> getLightRClassesDefinedByModule(
+ Module module, boolean includeTestClasses) {
+ BlazeRClass rClass = rClassesByModule.get(module);
+ return rClass == null ? ImmutableSet.of() : ImmutableSet.of(rClass);
+ }
+}
diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/resources/BlazeRClass.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/resources/BlazeRClass.java
similarity index 89%
rename from aswb/sdkcompat/as212/com/google/idea/blaze/android/resources/BlazeRClass.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/resources/BlazeRClass.java
index 2c123e0a66f..5a8cbf8e450 100644
--- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/resources/BlazeRClass.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/resources/BlazeRClass.java
@@ -20,8 +20,8 @@
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.android.tools.idea.res.StudioResourceRepositoryManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModulePointerManager;
import com.intellij.openapi.vfs.VirtualFile;
@@ -43,19 +43,19 @@ public String getPackageName() {
return packageName;
}
- // @Override #api4.1
+ @Override
public Transitivity getTransitivity() {
return Transitivity.TRANSITIVE;
}
@Override
- public ResourceRepositoryManager getResourceRepositoryManager() {
- return ResourceRepositoryManager.getInstance(androidFacet);
+ public StudioResourceRepositoryManager getResourceRepositoryManager() {
+ return StudioResourceRepositoryManager.getInstance(androidFacet);
}
@Override
public LocalResourceRepository getResourceRepository() {
- return ResourceRepositoryManager.getAppResources(androidFacet);
+ return StudioResourceRepositoryManager.getAppResources(androidFacet);
}
@Override
diff --git a/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryApplicationLaunchTaskProvider.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryApplicationLaunchTaskProvider.java
similarity index 78%
rename from aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryApplicationLaunchTaskProvider.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryApplicationLaunchTaskProvider.java
index abfe50ccd8d..8a74f3d458f 100644
--- a/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryApplicationLaunchTaskProvider.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryApplicationLaunchTaskProvider.java
@@ -18,12 +18,13 @@
import com.android.tools.idea.run.ApkProvisionException;
import com.android.tools.idea.run.ApplicationIdProvider;
import com.android.tools.idea.run.activity.StartActivityFlagsProvider;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.blaze.BlazeLaunchTaskWrapper;
import com.android.tools.idea.run.tasks.AndroidDeepLinkLaunchTask;
import com.android.tools.idea.run.tasks.DefaultActivityLaunchTask;
-import com.android.tools.idea.run.tasks.LaunchTask;
import com.android.tools.idea.run.tasks.SpecificActivityLaunchTask;
-import com.android.tools.idea.run.util.LaunchStatus;
import com.google.idea.blaze.android.manifest.ManifestParser;
+import com.intellij.execution.ExecutionException;
import com.intellij.openapi.diagnostic.Logger;
/** Provides the launch task for android_binary */
@@ -31,44 +32,35 @@ public class BlazeAndroidBinaryApplicationLaunchTaskProvider {
private static final Logger LOG =
Logger.getInstance(BlazeAndroidBinaryApplicationLaunchTaskProvider.class);
- public static LaunchTask getApplicationLaunchTask(
+ public static BlazeLaunchTask getApplicationLaunchTask(
ApplicationIdProvider applicationIdProvider,
ManifestParser.ParsedManifest mergedManifestParsedManifest,
BlazeAndroidBinaryRunConfigurationState configState,
- StartActivityFlagsProvider startActivityFlagsProvider,
- LaunchStatus launchStatus) {
+ StartActivityFlagsProvider startActivityFlagsProvider)
+ throws ExecutionException {
try {
String applicationId = applicationIdProvider.getPackageName();
- final LaunchTask launchTask;
-
switch (configState.getMode()) {
case BlazeAndroidBinaryRunConfigurationState.LAUNCH_DEFAULT_ACTIVITY:
BlazeDefaultActivityLocator activityLocator =
new BlazeDefaultActivityLocator(mergedManifestParsedManifest);
- launchTask =
+ return new BlazeLaunchTaskWrapper(
new DefaultActivityLaunchTask(
- applicationId, activityLocator, startActivityFlagsProvider);
- break;
+ applicationId, activityLocator, startActivityFlagsProvider));
case BlazeAndroidBinaryRunConfigurationState.LAUNCH_SPECIFIC_ACTIVITY:
- launchTask =
+ return new BlazeLaunchTaskWrapper(
new SpecificActivityLaunchTask(
- applicationId, configState.getActivityClass(), startActivityFlagsProvider);
- break;
+ applicationId, configState.getActivityClass(), startActivityFlagsProvider));
case BlazeAndroidBinaryRunConfigurationState.LAUNCH_DEEP_LINK:
- launchTask =
- new AndroidDeepLinkLaunchTask(configState.getDeepLink(), startActivityFlagsProvider);
- break;
+ return new BlazeLaunchTaskWrapper(
+ new AndroidDeepLinkLaunchTask(configState.getDeepLink(), startActivityFlagsProvider));
case BlazeAndroidBinaryRunConfigurationState.DO_NOTHING:
default:
- launchTask = null;
- break;
+ return null;
}
- return launchTask;
} catch (ApkProvisionException e) {
- LOG.error(e);
- launchStatus.terminateLaunch("Unable to identify application id", true);
- return null;
+ throw new ExecutionException("Unable to identify application id");
}
}
}
diff --git a/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java
similarity index 80%
rename from aswb/sdkcompat/as213/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java
index 9bda7c9d0de..6b2d10e2dac 100644
--- a/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java
@@ -15,15 +15,16 @@
*/
package com.google.idea.blaze.android.run.binary;
+import static com.android.tools.idea.run.tasks.DefaultConnectDebuggerTaskKt.getBaseDebuggerTask;
+
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
import com.android.tools.idea.run.ApkProvisionException;
import com.android.tools.idea.run.LaunchOptions;
import com.android.tools.idea.run.activity.DefaultStartActivityFlagsProvider;
import com.android.tools.idea.run.activity.StartActivityFlagsProvider;
-import com.android.tools.idea.run.editor.AndroidDebugger;
-import com.android.tools.idea.run.editor.AndroidDebuggerState;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
import com.android.tools.idea.run.tasks.ConnectDebuggerTask;
-import com.android.tools.idea.run.tasks.LaunchTask;
-import com.android.tools.idea.run.util.LaunchStatus;
import com.google.idea.blaze.android.run.deployinfo.BlazeAndroidDeployInfo;
import com.google.idea.blaze.android.run.runner.ApkBuildStep;
import com.intellij.execution.ExecutionException;
@@ -49,11 +50,8 @@ public class BlazeAndroidBinaryNormalBuildRunContext
}
@Override
- public LaunchTask getApplicationLaunchTask(
- LaunchOptions launchOptions,
- @Nullable Integer userId,
- String contributorsAmStartOptions,
- LaunchStatus launchStatus)
+ public BlazeLaunchTask getApplicationLaunchTask(
+ LaunchOptions launchOptions, @Nullable Integer userId, String contributorsAmStartOptions)
throws ExecutionException {
String extraFlags = UserIdHelper.getFlagsFromUserId(userId);
if (!contributorsAmStartOptions.isEmpty()) {
@@ -61,7 +59,7 @@ public LaunchTask getApplicationLaunchTask(
}
final StartActivityFlagsProvider startActivityFlagsProvider =
- new DefaultStartActivityFlagsProvider(launchOptions.isDebug(), extraFlags);
+ new DefaultStartActivityFlagsProvider(project, launchOptions.isDebug(), extraFlags);
BlazeAndroidDeployInfo deployInfo;
try {
@@ -74,18 +72,15 @@ public LaunchTask getApplicationLaunchTask(
applicationIdProvider,
deployInfo.getMergedManifest(),
configState,
- startActivityFlagsProvider,
- launchStatus);
+ startActivityFlagsProvider);
}
@Nullable
@Override
@SuppressWarnings("unchecked")
public ConnectDebuggerTask getDebuggerTask(
- AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState)
- throws ExecutionException {
- return androidDebugger.getConnectDebuggerTask(
- env, applicationIdProvider, facet, androidDebuggerState);
+ AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState) {
+ return getBaseDebuggerTask(androidDebugger, androidDebuggerState, env, facet);
}
@Override
diff --git a/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java
similarity index 87%
rename from aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java
index f78be5f1929..0dac5606ada 100644
--- a/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java
@@ -24,13 +24,12 @@
import com.android.tools.idea.run.ApkProvider;
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.ConsoleProvider;
import com.android.tools.idea.run.LaunchOptions;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.blaze.BlazeLaunchTasksProvider;
import com.android.tools.idea.run.editor.ProfilerState;
import com.android.tools.idea.run.tasks.DeployTasksCompat;
-import com.android.tools.idea.run.tasks.LaunchTask;
-import com.android.tools.idea.run.tasks.LaunchTasksProvider;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.idea.blaze.android.run.deployinfo.BlazeApkProviderService;
@@ -105,7 +104,7 @@ public ConsoleProvider getConsoleProvider() {
}
@Override
- public ApplicationIdProvider getApplicationIdProvider() throws ExecutionException {
+ public ApplicationIdProvider getApplicationIdProvider() {
return applicationIdProvider;
}
@@ -116,13 +115,12 @@ public ApkBuildStep getBuildStep() {
@Nullable
@Override
- public Integer getUserId(IDevice device, ConsolePrinter consolePrinter)
- throws ExecutionException {
- return UserIdHelper.getUserIdFromConfigurationState(device, consolePrinter, configState);
+ public Integer getUserId(IDevice device) throws ExecutionException {
+ return UserIdHelper.getUserIdFromConfigurationState(project, device, configState);
}
@Override
- public LaunchTasksProvider getLaunchTasksProvider(LaunchOptions.Builder launchOptionsBuilder)
+ public BlazeLaunchTasksProvider getLaunchTasksProvider(LaunchOptions.Builder launchOptionsBuilder)
throws ExecutionException {
return new BlazeAndroidLaunchTasksProvider(
project, this, applicationIdProvider, launchOptionsBuilder);
@@ -133,18 +131,18 @@ public String getAmStartOptions() {
return configState.getAmStartOptions();
}
- // @Override #api211
+ @Override
public ProfilerState getProfileState() {
return configState.getProfilerState();
}
@Nullable
@Override
- public ImmutableList getDeployTasks(IDevice device, LaunchOptions launchOptions)
+ public ImmutableList getDeployTasks(IDevice device, LaunchOptions launchOptions)
throws ExecutionException {
- LaunchTask deployTask =
- DeployTasksCompat.getDeployTask(
- project, env, launchOptions, getApkInfoToInstall(device, launchOptions, apkProvider));
+ BlazeLaunchTask deployTask =
+ DeployTasksCompat.createDeployTask(
+ project, getApkInfoToInstall(device, launchOptions, apkProvider), launchOptions);
return ImmutableList.of(new DeploymentTimingReporterTask(launchId, deployTask));
}
diff --git a/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextCompat.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextCompat.java
new file mode 100644
index 00000000000..d54c472c84b
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextCompat.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2022 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 static com.android.tools.idea.run.tasks.DefaultConnectDebuggerTaskKt.getBaseDebuggerTask;
+
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
+import com.android.tools.idea.run.tasks.ConnectDebuggerTask;
+import com.google.idea.blaze.android.run.runner.ApkBuildStep;
+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 class for {@link BlazeAndroidBinaryNormalBuildRunContext}. */
+public class BlazeAndroidBinaryNormalBuildRunContextCompat
+ extends BlazeAndroidBinaryNormalBuildRunContext {
+
+ BlazeAndroidBinaryNormalBuildRunContextCompat(
+ Project project,
+ AndroidFacet facet,
+ RunConfiguration runConfiguration,
+ ExecutionEnvironment env,
+ BlazeAndroidBinaryRunConfigurationState configState,
+ ApkBuildStep buildStep,
+ String launchId) {
+ super(project, facet, runConfiguration, env, configState, buildStep, launchId);
+ }
+
+ @Nullable
+ @Override
+ @SuppressWarnings("unchecked")
+ public ConnectDebuggerTask getDebuggerTask(
+ AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState) {
+ return getBaseDebuggerTask(androidDebugger, androidDebuggerState, env, facet);
+ }
+}
diff --git a/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryProgramRunner.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryProgramRunner.java
new file mode 100644
index 00000000000..50f42d4b2dd
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryProgramRunner.java
@@ -0,0 +1,114 @@
+/*
+ * 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;
+
+import static com.intellij.openapi.application.ModalityState.NON_MODAL;
+
+import com.android.tools.idea.profilers.ProfileRunExecutor;
+import com.android.tools.idea.run.configuration.execution.AndroidConfigurationExecutor;
+import com.google.idea.blaze.android.run.BlazeAndroidRunConfigurationHandler;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.ExecutionResult;
+import com.intellij.execution.Executor;
+import com.intellij.execution.configurations.RunProfile;
+import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.configurations.RunnerSettings;
+import com.intellij.execution.executors.DefaultDebugExecutor;
+import com.intellij.execution.executors.DefaultRunExecutor;
+import com.intellij.execution.runners.AsyncProgramRunner;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.RunContentBuilder;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.openapi.application.ActionsKt;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
+import org.jetbrains.concurrency.AsyncPromise;
+import org.jetbrains.concurrency.Promise;
+
+/** Program runner for configurations from {@link BlazeAndroidBinaryRunConfigurationHandler}. */
+public class BlazeAndroidBinaryProgramRunner extends AsyncProgramRunner {
+ @Override
+ public boolean canRun(String executorId, RunProfile profile) {
+ BlazeAndroidRunConfigurationHandler handler =
+ BlazeAndroidRunConfigurationHandler.getHandlerFrom(profile);
+ if (!(handler instanceof BlazeAndroidBinaryRunConfigurationHandler)) {
+ return false;
+ }
+ return (DefaultDebugExecutor.EXECUTOR_ID.equals(executorId)
+ || DefaultRunExecutor.EXECUTOR_ID.equals(executorId)
+ || ProfileRunExecutor.EXECUTOR_ID.equals(executorId));
+ }
+
+ @Override
+ protected Promise execute(
+ ExecutionEnvironment environment, RunProfileState state) {
+ FileDocumentManager.getInstance().saveAllDocuments();
+
+ AsyncPromise promise = new AsyncPromise<>();
+
+ ProgressManager.getInstance()
+ .run(
+ new Task.Backgroundable(environment.getProject(), "Launching ${runProfile.name}") {
+ @Override
+ public void run(ProgressIndicator indicator) {
+ try {
+ RunContentDescriptor descriptor;
+ if (state instanceof AndroidConfigurationExecutor) {
+ AndroidConfigurationExecutor configurationExecutor =
+ (AndroidConfigurationExecutor) state;
+ Executor executor = environment.getExecutor();
+ if (executor.getId().equals(DefaultDebugExecutor.EXECUTOR_ID)) {
+ descriptor = configurationExecutor.debug(indicator);
+ } else if (executor.getId().equals(DefaultRunExecutor.EXECUTOR_ID)
+ || executor.getId().equals(ProfileRunExecutor.EXECUTOR_ID)) {
+ descriptor = configurationExecutor.run(indicator);
+ } else {
+ throw new ExecutionException("Unsupported executor");
+ }
+ } else {
+ descriptor = doExecute(state, environment);
+ }
+ promise.setResult(descriptor);
+ } catch (ExecutionException e) {
+ boolean unused = promise.setError(e);
+ }
+ }
+
+ @Override
+ public void onCancel() {
+ super.onCancel();
+ promise.setResult(null);
+ }
+ });
+
+ return promise;
+ }
+
+ private RunContentDescriptor doExecute(
+ final RunProfileState state, final ExecutionEnvironment env) throws ExecutionException {
+ ExecutionResult result = state.execute(env.getExecutor(), this);
+ return ActionsKt.invokeAndWaitIfNeeded(
+ NON_MODAL,
+ () -> new RunContentBuilder(result, env).showRunContent(env.getContentToReuse()));
+ }
+
+ @Override
+ public String getRunnerId() {
+ return "AndroidBinaryProgramRunner";
+ }
+}
diff --git a/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationHandlerCompat.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationHandlerCompat.java
new file mode 100644
index 00000000000..296c3ea57af
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationHandlerCompat.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2022 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 static com.android.tools.idea.run.deployment.DeviceAndSnapshotComboBoxAction.DEPLOYS_TO_LOCAL_DEVICE;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.intellij.openapi.project.Project;
+
+/** Compat class for {@link BlazeAndroidBinaryRunConfigurationHandlerCompat}. */
+public class BlazeAndroidBinaryRunConfigurationHandlerCompat {
+ protected final Project project;
+ protected final BlazeAndroidBinaryRunConfigurationState configState;
+
+ @VisibleForTesting
+ protected BlazeAndroidBinaryRunConfigurationHandlerCompat(
+ BlazeCommandRunConfiguration configuration) {
+ project = configuration.getProject();
+ configState =
+ new BlazeAndroidBinaryRunConfigurationState(
+ Blaze.buildSystemName(configuration.getProject()));
+ configuration.putUserData(DEPLOYS_TO_LOCAL_DEVICE, true);
+ }
+}
diff --git a/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/DeploymentTimingReporterTask.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/DeploymentTimingReporterTask.java
new file mode 100644
index 00000000000..81696ad5b1e
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/DeploymentTimingReporterTask.java
@@ -0,0 +1,45 @@
+/*
+ * 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.blaze.BlazeLaunchContext;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.google.common.base.Stopwatch;
+import com.google.idea.blaze.android.run.LaunchMetrics;
+import com.intellij.execution.ExecutionException;
+
+/** A wrapper launch task that wraps the given deployment task and logs the deployment latency. */
+public class DeploymentTimingReporterTask implements BlazeLaunchTask {
+ private final BlazeLaunchTask deployTask;
+ private final String launchId;
+
+ public DeploymentTimingReporterTask(String launchId, BlazeLaunchTask deployTask) {
+ this.launchId = launchId;
+ this.deployTask = deployTask;
+ }
+
+ @Override
+ public void run(BlazeLaunchContext launchContext) throws ExecutionException {
+ Stopwatch s = Stopwatch.createStarted();
+ try {
+ deployTask.run(launchContext);
+ LaunchMetrics.logDeploymentTime(launchId, s.elapsed(), true);
+ } catch (ExecutionException e) {
+ LaunchMetrics.logDeploymentTime(launchId, s.elapsed(), false);
+ throw e;
+ }
+ }
+}
diff --git a/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java
similarity index 81%
rename from aswb/sdkcompat/as213/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java
index 00aa0e82561..c49082cfdaa 100644
--- a/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java
@@ -15,15 +15,16 @@
*/
package com.google.idea.blaze.android.run.binary.mobileinstall;
+import static com.android.tools.idea.run.tasks.DefaultConnectDebuggerTaskKt.getBaseDebuggerTask;
+
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
import com.android.tools.idea.run.ApkProvisionException;
import com.android.tools.idea.run.LaunchOptions;
import com.android.tools.idea.run.activity.DefaultStartActivityFlagsProvider;
import com.android.tools.idea.run.activity.StartActivityFlagsProvider;
-import com.android.tools.idea.run.editor.AndroidDebugger;
-import com.android.tools.idea.run.editor.AndroidDebuggerState;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
import com.android.tools.idea.run.tasks.ConnectDebuggerTask;
-import com.android.tools.idea.run.tasks.LaunchTask;
-import com.android.tools.idea.run.util.LaunchStatus;
import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryApplicationLaunchTaskProvider;
import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryRunConfigurationState;
import com.google.idea.blaze.android.run.binary.UserIdHelper;
@@ -51,12 +52,10 @@ public BlazeAndroidBinaryMobileInstallRunContext(
super(project, facet, runConfiguration, env, configState, buildStep, launchId);
}
+ @SuppressWarnings("unchecked") // upstream API
@Override
- public LaunchTask getApplicationLaunchTask(
- LaunchOptions launchOptions,
- @Nullable Integer userId,
- String contributorsAmStartOptions,
- LaunchStatus launchStatus)
+ public BlazeLaunchTask getApplicationLaunchTask(
+ LaunchOptions launchOptions, @Nullable Integer userId, String contributorsAmStartOptions)
throws ExecutionException {
String extraFlags = UserIdHelper.getFlagsFromUserId(userId);
@@ -65,7 +64,7 @@ public LaunchTask getApplicationLaunchTask(
}
final StartActivityFlagsProvider startActivityFlagsProvider =
- new DefaultStartActivityFlagsProvider(launchOptions.isDebug(), extraFlags);
+ new DefaultStartActivityFlagsProvider(project, launchOptions.isDebug(), extraFlags);
BlazeAndroidDeployInfo deployInfo;
try {
deployInfo = buildStep.getDeployInfo();
@@ -77,18 +76,15 @@ public LaunchTask getApplicationLaunchTask(
applicationIdProvider,
deployInfo.getMergedManifest(),
configState,
- startActivityFlagsProvider,
- launchStatus);
+ startActivityFlagsProvider);
}
@Nullable
@Override
@SuppressWarnings("unchecked")
public ConnectDebuggerTask getDebuggerTask(
- AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState)
- throws ExecutionException {
- return androidDebugger.getConnectDebuggerTask(
- env, applicationIdProvider, facet, androidDebuggerState);
+ AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState) {
+ return getBaseDebuggerTask(androidDebugger, androidDebuggerState, env, facet);
}
@Override
diff --git a/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java
similarity index 84%
rename from aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java
index 3469d8cbaf5..b18f117f80f 100644
--- a/aswb/src/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java
@@ -20,15 +20,14 @@
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;
import com.android.tools.idea.run.ConsoleProvider;
import com.android.tools.idea.run.LaunchOptions;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.blaze.BlazeLaunchTasksProvider;
import com.android.tools.idea.run.editor.ProfilerState;
-import com.android.tools.idea.run.tasks.LaunchTask;
-import com.android.tools.idea.run.tasks.LaunchTasksProvider;
+import com.android.tools.idea.run.tasks.DeployTasksCompat;
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.BlazeAndroidBinaryConsoleProvider;
import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryRunConfigurationState;
@@ -88,7 +87,7 @@ public BlazeAndroidDeviceSelector getDeviceSelector() {
@Override
public void augmentLaunchOptions(LaunchOptions.Builder options) {
options
- .setDeploy(StudioDeployerExperiment.isEnabled())
+ .setDeploy(buildStep.needsIdeDeploy())
.setOpenLogcatAutomatically(configState.showLogcatAutomatically());
// This is needed for compatibility with #api211
options.addExtraOptions(
@@ -101,7 +100,7 @@ public ConsoleProvider getConsoleProvider() {
}
@Override
- public ApplicationIdProvider getApplicationIdProvider() throws ExecutionException {
+ public ApplicationIdProvider getApplicationIdProvider() {
return applicationIdProvider;
}
@@ -110,15 +109,15 @@ public ApkBuildStep getBuildStep() {
return buildStep;
}
- // @Override #api211
+ @Override
public ProfilerState getProfileState() {
return configState.getProfilerState();
}
@Override
- public ImmutableList getDeployTasks(IDevice device, LaunchOptions launchOptions)
+ public ImmutableList getDeployTasks(IDevice device, LaunchOptions launchOptions)
throws ExecutionException {
- if (!StudioDeployerExperiment.isEnabled()) {
+ if (!buildStep.needsIdeDeploy()) {
return ImmutableList.of();
}
@@ -141,21 +140,19 @@ public ImmutableList getDeployTasks(IDevice device, LaunchOptions la
.collect(Collectors.toList()),
packageName);
- LaunchTask deployTask =
- BlazeAndroidDeploymentService.getInstance(project)
- .getDeployTask(Collections.singletonList(info), launchOptions);
+ BlazeLaunchTask deployTask =
+ DeployTasksCompat.createDeployTask(project, Collections.singletonList(info), launchOptions);
return ImmutableList.of(new DeploymentTimingReporterTask(launchId, deployTask));
}
@Nullable
@Override
- public Integer getUserId(IDevice device, ConsolePrinter consolePrinter)
- throws ExecutionException {
- return UserIdHelper.getUserIdFromConfigurationState(device, consolePrinter, configState);
+ public Integer getUserId(IDevice device) throws ExecutionException {
+ return UserIdHelper.getUserIdFromConfigurationState(project, device, configState);
}
@Override
- public LaunchTasksProvider getLaunchTasksProvider(LaunchOptions.Builder launchOptionsBuilder)
+ public BlazeLaunchTasksProvider getLaunchTasksProvider(LaunchOptions.Builder launchOptionsBuilder)
throws ExecutionException {
return new BlazeAndroidLaunchTasksProvider(
project, this, applicationIdProvider, launchOptionsBuilder);
diff --git a/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextCompat.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextCompat.java
new file mode 100644
index 00000000000..29411ebad5a
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextCompat.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2022 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 static com.android.tools.idea.run.tasks.DefaultConnectDebuggerTaskKt.getBaseDebuggerTask;
+
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.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.ApkBuildStep;
+import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.openapi.project.Project;
+import javax.annotation.Nullable;
+import org.jetbrains.android.facet.AndroidFacet;
+
+/** Compatct class for {@link BlazeAndroidBinaryMobileInstallRunContext}. */
+public class BlazeAndroidBinaryMobileInstallRunContextCompat
+ extends BlazeAndroidBinaryMobileInstallRunContext {
+
+ public BlazeAndroidBinaryMobileInstallRunContextCompat(
+ Project project,
+ AndroidFacet facet,
+ BlazeCommandRunConfiguration configuration,
+ ExecutionEnvironment env,
+ BlazeAndroidBinaryRunConfigurationState configState,
+ ApkBuildStep buildStep,
+ String launchId) {
+ super(project, facet, configuration, env, configState, buildStep, launchId);
+ }
+
+ @Nullable
+ @Override
+ @SuppressWarnings("unchecked")
+ public ConnectDebuggerTask getDebuggerTask(
+ AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState) {
+ return getBaseDebuggerTask(androidDebugger, androidDebuggerState, env, facet);
+ }
+}
diff --git a/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeAndroidDebuggerService.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeAndroidDebuggerService.java
new file mode 100644
index 00000000000..c8658223baa
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeAndroidDebuggerService.java
@@ -0,0 +1,111 @@
+/*
+ * 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.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
+import com.android.tools.idea.execution.common.debug.impl.java.AndroidJavaDebugger;
+import com.android.tools.ndk.run.editor.AutoAndroidDebuggerState;
+import com.google.common.collect.ImmutableList;
+import com.google.idea.blaze.android.cppimpl.debug.BlazeAutoAndroidDebugger;
+import com.google.idea.blaze.android.run.deployinfo.BlazeAndroidDeployInfo;
+import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
+import com.intellij.ide.plugins.PluginManagerCore;
+import com.intellij.openapi.project.Project;
+import javax.annotation.Nullable;
+
+/** Provides android debuggers and debugger states for blaze projects. */
+public interface BlazeAndroidDebuggerService {
+
+ static BlazeAndroidDebuggerService getInstance(Project project) {
+ return project.getService(BlazeAndroidDebuggerService.class);
+ }
+
+ /** Returns the standard debugger for non-native (Java) debugging. */
+ AndroidDebugger getDebugger();
+
+ /** Returns the standard debugger for native (C++) debugging. */
+ AndroidDebugger getNativeDebugger();
+
+ /**
+ * Performs additional necessary setup for native debugging, incorporating info from {@link
+ * BlazeAndroidDeployInfo}.
+ */
+ void configureNativeDebugger(
+ AndroidDebuggerState state, @Nullable BlazeAndroidDeployInfo deployInfo);
+
+ /** Default debugger service. */
+ class DefaultDebuggerService implements BlazeAndroidDebuggerService {
+ private final Project project;
+
+ public DefaultDebuggerService(Project project) {
+ this.project = project;
+ }
+
+ @Override
+ public AndroidDebugger getDebugger() {
+ return new AndroidJavaDebugger();
+ }
+
+ @Override
+ public AndroidDebugger getNativeDebugger() {
+ return new BlazeAutoAndroidDebugger();
+ }
+
+ @Override
+ public void configureNativeDebugger(
+ AndroidDebuggerState rawState, @Nullable BlazeAndroidDeployInfo deployInfo) {
+ if (!isNdkPluginLoaded() && !(rawState instanceof AutoAndroidDebuggerState)) {
+ return;
+ }
+ AutoAndroidDebuggerState state = (AutoAndroidDebuggerState) rawState;
+
+ // Source code is always relative to the workspace root in a blaze project.
+ String workingDirPath = WorkspaceRoot.fromProject(project).directory().getPath();
+ state.setWorkingDir(workingDirPath);
+
+ // Remote built binaries may use /proc/self/cwd to represent the working directory,
+ // so we manually map /proc/self/cwd to the workspace root. We used to use
+ // `plugin.symbol-file.dwarf.comp-dir-symlink-paths = "/proc/self/cwd"`
+ // to automatically resolve this, but it's no longer supported in newer versions of
+ // LLDB.
+ String sourceMapToWorkspaceRootCommand =
+ "settings append target.source-map /proc/self/cwd/ " + workingDirPath;
+
+ ImmutableList startupCommands =
+ ImmutableList.builder()
+ .addAll(state.getUserStartupCommands())
+ .add(sourceMapToWorkspaceRootCommand)
+ .build();
+ state.setUserStartupCommands(startupCommands);
+
+ // NDK plugin will pass symbol directories to LLDB as `settings append
+ // target.exec-search-paths`.
+ if (deployInfo != null) {
+ state.setSymbolDirs(
+ deployInfo.getSymbolFiles().stream()
+ .map(symbol -> symbol.getParentFile().getAbsolutePath())
+ .collect(ImmutableList.toImmutableList()));
+ }
+ }
+ }
+
+ static boolean isNdkPluginLoaded() {
+ return PluginManagerCore.getLoadedPlugins().stream()
+ .anyMatch(
+ d -> d.isEnabled() && d.getPluginId().getIdString().equals("com.android.tools.ndk"));
+ }
+}
diff --git a/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java
similarity index 59%
rename from aswb/sdkcompat/as213/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java
index a694833e05d..9ede8d06e50 100644
--- a/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
+ * Copyright 2022 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.
@@ -18,25 +18,25 @@
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.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
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.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.blaze.BlazeLaunchTaskWrapper;
+import com.android.tools.idea.run.blaze.BlazeLaunchTasksProvider;
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.android.tools.ndk.run.editor.AutoAndroidDebuggerState;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.idea.blaze.android.run.binary.UserIdHelper;
+import com.google.idea.blaze.android.run.deployinfo.BlazeAndroidDeployInfo;
import com.intellij.execution.ExecutionException;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -45,7 +45,7 @@
import org.jetbrains.annotations.Nullable;
/** Normal launch tasks provider. #api4.1 */
-public class BlazeAndroidLaunchTasksProvider implements LaunchTasksProvider {
+public class BlazeAndroidLaunchTasksProvider implements BlazeLaunchTasksProvider {
public static final String NATIVE_DEBUGGING_ENABLED = "NATIVE_DEBUGGING_ENABLED";
private static final Logger LOG = Logger.getInstance(BlazeAndroidLaunchTasksProvider.class);
@@ -67,23 +67,17 @@ public BlazeAndroidLaunchTasksProvider(
@NotNull
@Override
- public List getTasks(
- @NotNull IDevice device,
- @NotNull LaunchStatus launchStatus,
- @NotNull ConsolePrinter consolePrinter)
- throws ExecutionException {
- final List launchTasks = Lists.newArrayList();
+ public List getTasks(@NotNull IDevice device) 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();
+ throw new ExecutionException("Unable to determine application id: " + e);
}
- Integer userId = runContext.getUserId(device, consolePrinter);
+ Integer userId = runContext.getUserId(device);
String userIdFlags = UserIdHelper.getFlagsFromUserId(userId);
String skipVerification =
ApkVerifierTracker.getSkipVerificationInstallationFlag(device, packageName);
@@ -104,23 +98,23 @@ public List getTasks(
launchTasks.add(new BlazeAndroidOpenProfilerWindowTask(project));
}
+ // TODO(kovalp): Check if there's any drawback to add these tasks with BlazeLaunchTaskWrapper
+ // since it's different with ag/21610897
if (launchOptions.isClearLogcatBeforeStart()) {
- launchTasks.add(new ClearLogcatTask(project));
+ launchTasks.add(new BlazeLaunchTaskWrapper(new ClearLogcatTask(project)));
}
- launchTasks.add(new DismissKeyguardTask());
+ launchTasks.add(new BlazeLaunchTaskWrapper(new DismissKeyguardTask()));
if (launchOptions.isDeploy()) {
- ImmutableList deployTasks = runContext.getDeployTasks(device, launchOptions);
+ 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()));
+ launchTasks.add(
+ new CheckApkDebuggableTask(project, runContext.getBuildStep().getDeployInfo()));
}
ImmutableList.Builder amStartOptions = ImmutableList.builder();
@@ -134,71 +128,55 @@ public List getTasks(
device,
runContext.getExecutor()));
launchTasks.add(
- new AndroidProfilerLaunchTaskContributor.AndroidProfilerToolWindowLaunchTask(
- project, packageName));
+ new BlazeLaunchTaskWrapper(
+ new AndroidProfilerLaunchTaskContributor.AndroidProfilerToolWindowLaunchTask(
+ project, 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 =
+ BlazeLaunchTask appLaunchTask =
runContext.getApplicationLaunchTask(
- launchOptions,
- userId,
- String.join(" ", amStartOptions.build()),
- launchStatus);
+ launchOptions, userId, String.join(" ", amStartOptions.build()));
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();
+ throw new ExecutionException("Unable to determine application id: " + e);
}
- if (!launchOptions.isDebug() && launchOptions.isOpenLogcatAutomatically()) {
- launchTasks.add(new ShowLogcatTask(project, packageName));
+ if (launchOptions.isOpenLogcatAutomatically()) {
+ launchTasks.add(new BlazeLaunchTaskWrapper(new ShowLogcatTask(project, packageName)));
}
return ImmutableList.copyOf(launchTasks);
}
- @Nullable
@Override
- public ConnectDebuggerTask getConnectDebuggerTask(
- @NotNull LaunchStatus launchStatus, @Nullable AndroidVersion version) {
+ @Nullable
+ public ConnectDebuggerTask getConnectDebuggerTask() {
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;
- }
-
+ BlazeAndroidDeployInfo deployInfo;
try {
- return runContext.getDebuggerTask(debugger, debuggerState);
- } catch (ExecutionException e) {
- launchStatus.terminateLaunch(e.getMessage(), true);
- return null;
+ deployInfo = runContext.getBuildStep().getDeployInfo();
+ } catch (ApkProvisionException e) {
+ LOG.error(e);
+ deployInfo = null;
}
- }
- @Override
- public String getLaunchTypeDisplayName() {
- return "Launch";
+ BlazeAndroidDebuggerService debuggerService = BlazeAndroidDebuggerService.getInstance(project);
+ if (isNativeDebuggingEnabled(launchOptions)) {
+ AndroidDebugger debugger = debuggerService.getNativeDebugger();
+ // The below state type should be AutoAndroidDebuggerState, but referencing it will crash the
+ // task if the NDK plugin is not loaded.
+ AndroidDebuggerState state = debugger.createState();
+ debuggerService.configureNativeDebugger(state, deployInfo);
+ return runContext.getDebuggerTask(debugger, state);
+ } else {
+ AndroidDebugger debugger = debuggerService.getDebugger();
+ return runContext.getDebuggerTask(debugger, debugger.createState());
+ }
}
private boolean isNativeDebuggingEnabled(LaunchOptions launchOptions) {
diff --git a/aswb/src/com/google/idea/blaze/android/run/runner/BlazeAndroidRunConfigurationRunner.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeAndroidRunConfigurationRunner.java
similarity index 63%
rename from aswb/src/com/google/idea/blaze/android/run/runner/BlazeAndroidRunConfigurationRunner.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeAndroidRunConfigurationRunner.java
index 71a297a1f4b..78728d9c46f 100644
--- a/aswb/src/com/google/idea/blaze/android/run/runner/BlazeAndroidRunConfigurationRunner.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeAndroidRunConfigurationRunner.java
@@ -17,21 +17,34 @@
package com.google.idea.blaze.android.run.runner;
import com.android.ddmlib.IDevice;
-import com.android.tools.idea.run.AndroidSessionInfo;
+import com.android.tools.idea.execution.common.AppRunSettings;
+import com.android.tools.idea.execution.common.ApplicationDeployer;
+import com.android.tools.idea.execution.common.ComponentLaunchOptions;
+import com.android.tools.idea.execution.common.DeployOptions;
+import com.android.tools.idea.run.ApkProvider;
+import com.android.tools.idea.run.ApplicationIdProvider;
import com.android.tools.idea.run.DeviceFutures;
import com.android.tools.idea.run.LaunchOptions;
+import com.android.tools.idea.run.blaze.BlazeAndroidConfigurationExecutor;
+import com.android.tools.idea.run.configuration.execution.AndroidComplicationConfigurationExecutor;
+import com.android.tools.idea.run.configuration.execution.AndroidConfigurationExecutor;
+import com.android.tools.idea.run.configuration.execution.AndroidConfigurationExecutorRunProfileState;
+import com.android.tools.idea.run.configuration.execution.AndroidTileConfigurationExecutor;
+import com.android.tools.idea.run.configuration.execution.AndroidWatchFaceConfigurationExecutor;
+import com.android.tools.idea.run.configuration.execution.ComplicationLaunchOptions;
+import com.android.tools.idea.run.configuration.execution.TileLaunchOptions;
+import com.android.tools.idea.run.configuration.execution.WatchFaceLaunchOptions;
import com.android.tools.idea.run.editor.DeployTarget;
import com.android.tools.idea.run.editor.DeployTargetState;
import com.android.tools.idea.run.util.LaunchUtils;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import com.google.idea.blaze.android.run.BlazeAndroidRunState;
+import com.google.idea.blaze.android.run.binary.mobileinstall.MobileInstallBuildStep;
+import com.google.idea.blaze.android.run.deployinfo.BlazeApkProviderService;
import com.google.idea.blaze.base.async.executor.ProgressiveTaskWithProgressIndicator;
-import com.google.idea.blaze.base.command.BlazeInvocationContext;
import com.google.idea.blaze.base.command.BlazeInvocationContext.ContextType;
import com.google.idea.blaze.base.experiments.ExperimentScope;
import com.google.idea.blaze.base.issueparser.BlazeIssueParser;
-import com.google.idea.blaze.base.issueparser.IssueOutputFilter;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration;
import com.google.idea.blaze.base.run.confighandler.BlazeCommandRunConfigurationRunner;
@@ -39,7 +52,6 @@
import com.google.idea.blaze.base.scope.Scope;
import com.google.idea.blaze.base.scope.ScopedTask;
import com.google.idea.blaze.base.scope.output.IssueOutput;
-import com.google.idea.blaze.base.scope.scopes.BlazeConsoleScope;
import com.google.idea.blaze.base.scope.scopes.IdeaLogScope;
import com.google.idea.blaze.base.scope.scopes.ProblemsViewScope;
import com.google.idea.blaze.base.scope.scopes.ToolWindowScope;
@@ -51,14 +63,17 @@
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.ui.ConsoleView;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
+import java.util.Collections;
import java.util.concurrent.CancellationException;
import javax.annotation.Nullable;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.util.AndroidBundle;
+import org.jetbrains.annotations.NotNull;
/**
* Supports the execution. Used by both android_binary and android_test.
@@ -99,13 +114,11 @@ public final RunProfileState getRunProfileState(final Executor executor, Executi
final Project project = env.getProject();
boolean isDebug = executor instanceof DefaultDebugExecutor;
- AndroidSessionInfo info =
- AndroidSessionInfo.findOldSession(project, null, runConfig, env.getExecutionTarget());
BlazeAndroidDeviceSelector deviceSelector = runContext.getDeviceSelector();
BlazeAndroidDeviceSelector.DeviceSession deviceSession =
- deviceSelector.getDevice(
- project, facet, executor, env, info, isDebug, runConfig.getUniqueID());
+ deviceSelector.getDevice(project, executor, env, isDebug, runConfig.getUniqueID());
+
if (deviceSession == null) {
return null;
}
@@ -140,9 +153,99 @@ public final RunProfileState getRunProfileState(final Executor executor, Executi
env.putCopyableUserData(RUN_CONTEXT_KEY, runContext);
env.putCopyableUserData(DEVICE_SESSION_KEY, deviceSession);
- return new BlazeAndroidRunState(env, launchOptionsBuilder, deviceSession, runContext);
+ BlazeAndroidConfigurationExecutor runner =
+ new BlazeAndroidConfigurationExecutor(
+ runContext.getConsoleProvider(),
+ runContext.getApplicationIdProvider(),
+ env,
+ deviceFutures,
+ runContext.getLaunchTasksProvider(launchOptionsBuilder),
+ LaunchOptions.builder().build());
+ return new AndroidConfigurationExecutorRunProfileState(runner);
+ }
+
+ private RunProfileState getWearExecutor(
+ ComponentLaunchOptions launchOptions, ExecutionEnvironment env, DeployTarget deployTarget)
+ throws ExecutionException {
+
+ AppRunSettings settings =
+ new AppRunSettings() {
+ @NotNull
+ @Override
+ public DeployOptions getDeployOptions() {
+ return new DeployOptions(Collections.emptyList(), "", true, true);
+ }
+
+ @NotNull
+ @Override
+ public ComponentLaunchOptions getComponentLaunchOptions() {
+ return launchOptions;
+ }
+
+ @Override
+ public Module getModule() {
+ return runConfig.getModules()[0];
+ }
+ };
+
+ AndroidConfigurationExecutor configurationExecutor;
+ ApplicationIdProvider appIdProvider = runContext.getApplicationIdProvider();
+ ApkProvider apkProvider =
+ BlazeApkProviderService.getInstance()
+ .getApkProvider(env.getProject(), runContext.getBuildStep());
+ DeviceFutures deviceFutures = deployTarget.getDevices(env.getProject());
+
+ if (launchOptions instanceof TileLaunchOptions) {
+ configurationExecutor =
+ new AndroidTileConfigurationExecutor(
+ env, deviceFutures, settings, appIdProvider, apkProvider) {
+ @NotNull
+ @Override
+ public ApplicationDeployer getApplicationDeployer(@NotNull ConsoleView console)
+ throws ExecutionException {
+ if (runContext.getBuildStep() instanceof MobileInstallBuildStep) {
+ return new MobileInstallApplicationDeployer(console);
+ }
+ return super.getApplicationDeployer(console);
+ }
+ };
+ } else if (launchOptions instanceof WatchFaceLaunchOptions) {
+ configurationExecutor =
+ new AndroidWatchFaceConfigurationExecutor(
+ env, deviceFutures, settings, appIdProvider, apkProvider) {
+ @NotNull
+ @Override
+ public ApplicationDeployer getApplicationDeployer(@NotNull ConsoleView console)
+ throws ExecutionException {
+ if (runContext.getBuildStep() instanceof MobileInstallBuildStep) {
+ return new MobileInstallApplicationDeployer(console);
+ }
+ return super.getApplicationDeployer(console);
+ }
+ };
+ } else if (launchOptions instanceof ComplicationLaunchOptions) {
+ configurationExecutor =
+ new AndroidComplicationConfigurationExecutor(
+ env, deviceFutures, settings, appIdProvider, apkProvider) {
+ @NotNull
+ @Override
+ public ApplicationDeployer getApplicationDeployer(@NotNull ConsoleView console)
+ throws ExecutionException {
+ if (runContext.getBuildStep() instanceof MobileInstallBuildStep) {
+ return new MobileInstallApplicationDeployer(console);
+ }
+ return super.getApplicationDeployer(console);
+ }
+ };
+ } else {
+ throw new RuntimeException("Unknown launch options " + launchOptions.getClass().getName());
+ }
+
+ return new AndroidConfigurationExecutorRunProfileState(
+ new BlazeWrapperForAndroidConfigurationExecutor(configurationExecutor));
}
+ @Nullable
private static String canDebug(
DeviceFutures deviceFutures, AndroidFacet facet, String moduleName) {
// If we are debugging on a device, then the app needs to be debuggable
@@ -173,16 +276,6 @@ public boolean executeBeforeRunTask(ExecutionEnvironment env) {
context
.push(new ProblemsViewScope(project, settings.getShowProblemsViewOnRun()))
.push(new ExperimentScope())
- .push(
- new BlazeConsoleScope.Builder(project)
- .setPopupBehavior(settings.getShowBlazeConsoleOnRun())
- .addConsoleFilters(
- new IssueOutputFilter(
- project,
- WorkspaceRoot.fromProject(project),
- BlazeInvocationContext.ContextType.BeforeRunTask,
- true))
- .build())
.push(
new ToolWindowScope.Builder(
project, new Task(project, "Build apk", Task.Type.BEFORE_LAUNCH))
diff --git a/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java
similarity index 70%
rename from aswb/sdkcompat/as213/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java
index a879851c38a..327d7f4aeae 100644
--- a/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java
@@ -16,17 +16,15 @@
package com.google.idea.blaze.android.run.runner;
import com.android.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
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.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.blaze.BlazeLaunchTasksProvider;
import com.android.tools.idea.run.editor.ProfilerState;
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 com.intellij.execution.Executor;
@@ -44,32 +42,30 @@ public interface BlazeAndroidRunContext {
ApkBuildStep getBuildStep();
- ApplicationIdProvider getApplicationIdProvider() throws ExecutionException;
+ ApplicationIdProvider getApplicationIdProvider();
- LaunchTasksProvider getLaunchTasksProvider(LaunchOptions.Builder launchOptionsBuilder)
+ BlazeLaunchTasksProvider getLaunchTasksProvider(LaunchOptions.Builder launchOptionsBuilder)
throws ExecutionException;
/** Returns the tasks to deploy the application. */
- ImmutableList getDeployTasks(IDevice device, LaunchOptions launchOptions)
+ ImmutableList getDeployTasks(IDevice device, LaunchOptions launchOptions)
throws ExecutionException;
/** Returns the task to launch the application. */
@Nullable
- LaunchTask getApplicationLaunchTask(
+ BlazeLaunchTask getApplicationLaunchTask(
LaunchOptions launchOptions,
@Nullable Integer userId,
- @NotNull String contributorsAmStartOptions,
- LaunchStatus launchStatus)
+ @NotNull String contributorsAmStartOptions)
throws ExecutionException;
/** Returns the task to connect the debugger. */
@Nullable
ConnectDebuggerTask getDebuggerTask(
- AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState)
- throws ExecutionException;
+ AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState);
@Nullable
- Integer getUserId(IDevice device, ConsolePrinter consolePrinter) throws ExecutionException;
+ Integer getUserId(IDevice device) throws ExecutionException;
String getAmStartOptions();
diff --git a/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeWrapperForAndroidConfigurationExecutor.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeWrapperForAndroidConfigurationExecutor.java
new file mode 100644
index 00000000000..be6f1f8552c
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/BlazeWrapperForAndroidConfigurationExecutor.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2022 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.run.runner;
+
+import com.android.tools.idea.run.DeviceFutures;
+import com.android.tools.idea.run.configuration.execution.AndroidConfigurationExecutor;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.openapi.progress.ProgressIndicator;
+import org.jetbrains.annotations.NotNull;
+
+/** Implementation of {@code AndroidConfigurationExecutor} specific for Blaze project. */
+public class BlazeWrapperForAndroidConfigurationExecutor implements AndroidConfigurationExecutor {
+ private final AndroidConfigurationExecutor delegateExecutor;
+
+ BlazeWrapperForAndroidConfigurationExecutor(@NotNull AndroidConfigurationExecutor executor) {
+ delegateExecutor = executor;
+ }
+
+ @NotNull
+ @Override
+ public RunConfiguration getConfiguration() {
+ return delegateExecutor.getConfiguration();
+ }
+
+ @NotNull
+ @Override
+ public DeviceFutures getDeviceFutures() {
+ return delegateExecutor.getDeviceFutures();
+ }
+
+ @NotNull
+ @Override
+ public RunContentDescriptor run(@NotNull ProgressIndicator indicator) throws ExecutionException {
+ return delegateExecutor.run(indicator);
+ }
+
+ @NotNull
+ @Override
+ public RunContentDescriptor debug(@NotNull ProgressIndicator indicator)
+ throws ExecutionException {
+ return delegateExecutor.debug(indicator);
+ }
+
+ @NotNull
+ @Override
+ public RunContentDescriptor applyChanges(@NotNull ProgressIndicator indicator) {
+ throw new RuntimeException("Apply code changes is not supported for blaze");
+ }
+
+ @NotNull
+ @Override
+ public RunContentDescriptor applyCodeChanges(@NotNull ProgressIndicator indicator) {
+ throw new RuntimeException("Apply changes is not supported for blaze");
+ }
+}
diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/LaunchOptionsCompat.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/LaunchOptionsCompat.java
similarity index 100%
rename from aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/LaunchOptionsCompat.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/LaunchOptionsCompat.java
diff --git a/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/MobileInstallApplicationDeployer.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/MobileInstallApplicationDeployer.java
new file mode 100644
index 00000000000..dad762309be
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/runner/MobileInstallApplicationDeployer.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 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.run.runner;
+
+import com.android.ddmlib.IDevice;
+import com.android.tools.deployer.ApkParser;
+import com.android.tools.deployer.Deployer;
+import com.android.tools.deployer.DeployerException;
+import com.android.tools.deployer.model.Apk;
+import com.android.tools.deployer.model.App;
+import com.android.tools.idea.execution.common.ApplicationDeployer;
+import com.android.tools.idea.execution.common.DeployOptions;
+import com.android.tools.idea.run.ApkFileUnit;
+import com.android.tools.idea.run.ApkInfo;
+import com.android.tools.idea.run.configuration.execution.AdbCommandCaptureLoggerWithConsole;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.jetbrains.annotations.NotNull;
+
+/** Deploys mobile install application. */
+public class MobileInstallApplicationDeployer implements ApplicationDeployer {
+ private static final Logger LOG = Logger.getInstance(MobileInstallApplicationDeployer.class);
+ private final ConsoleView myConsole;
+
+ public MobileInstallApplicationDeployer(ConsoleView console) {
+ myConsole = console;
+ }
+
+ @NotNull
+ @Override
+ public Deployer.Result fullDeploy(
+ @NotNull IDevice device,
+ @NotNull ApkInfo apkInfo,
+ @NotNull DeployOptions deployOptions,
+ ProgressIndicator indicator)
+ throws DeployerException {
+ final List apkPaths =
+ apkInfo.getFiles().stream()
+ .map(ApkFileUnit::getApkPath)
+ .map(Path::toString)
+ .collect(Collectors.toList());
+ final List apks = new ApkParser().parsePaths(apkPaths);
+ App app =
+ new App(
+ apkInfo.getApplicationId(),
+ apks,
+ device,
+ new AdbCommandCaptureLoggerWithConsole(LOG, myConsole));
+ return new Deployer.Result(false, false, false, app);
+ }
+
+ @NotNull
+ @Override
+ public Deployer.Result applyChangesDeploy(
+ @NotNull IDevice device,
+ @NotNull ApkInfo app,
+ @NotNull DeployOptions deployOptions,
+ ProgressIndicator indicator)
+ throws DeployerException {
+ throw new RuntimeException("Apply changes is not supported for mobile-install");
+ }
+
+ @NotNull
+ @Override
+ public Deployer.Result applyCodeChangesDeploy(
+ @NotNull IDevice device,
+ @NotNull ApkInfo app,
+ @NotNull DeployOptions deployOptions,
+ ProgressIndicator indicator)
+ throws DeployerException {
+ throw new RuntimeException("Apply code changes is not supported for mobile-install");
+ }
+}
diff --git a/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestProgramRunner.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/test/BlazeAndroidTestProgramRunner.java
similarity index 54%
rename from aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestProgramRunner.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/run/test/BlazeAndroidTestProgramRunner.java
index bf54ebf2c6c..eab7b24890f 100644
--- a/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestProgramRunner.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/test/BlazeAndroidTestProgramRunner.java
@@ -15,25 +15,25 @@
*/
package com.google.idea.blaze.android.run.test;
-import com.android.tools.idea.run.AndroidProgramRunner;
-import com.android.tools.idea.run.AndroidSessionInfo;
+import com.android.tools.idea.run.configuration.AndroidConfigurationProgramRunner;
+import com.android.tools.idea.run.configuration.execution.AndroidConfigurationExecutor;
import com.google.idea.blaze.android.run.BlazeAndroidRunConfigurationHandler;
import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration;
+import com.google.idea.blaze.base.run.BlazeCommandRunConfigurationType;
import com.intellij.execution.ExecutionException;
-import com.intellij.execution.ExecutionResult;
-import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.executors.DefaultRunExecutor;
-import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
-import com.intellij.execution.runners.RunContentBuilder;
import com.intellij.execution.ui.RunContentDescriptor;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.progress.ProgressIndicator;
+import java.util.Collections;
+import java.util.List;
+import org.jetbrains.annotations.NotNull;
/** Program runner for configurations from {@link BlazeAndroidTestRunConfigurationHandler}. */
-public class BlazeAndroidTestProgramRunner extends AndroidProgramRunner {
+public class BlazeAndroidTestProgramRunner extends AndroidConfigurationProgramRunner {
@Override
public boolean canRun(String executorId, RunProfile profile) {
BlazeAndroidRunConfigurationHandler handler =
@@ -49,37 +49,35 @@ public boolean canRun(String executorId, RunProfile profile) {
}
@Override
- protected boolean canRunWithMultipleDevices(String executorId) {
- return false;
+ public String getRunnerId() {
+ return "AndroidTestProgramRunner";
}
@Override
- protected RunContentDescriptor doExecute(
- final RunProfileState state, final ExecutionEnvironment env) throws ExecutionException {
- FileDocumentManager.getInstance().saveAllDocuments();
- ExecutionResult result = state.execute(env.getExecutor(), this);
- RunContentDescriptor descriptor =
- new RunContentBuilder(result, env).showRunContent(env.getContentToReuse());
- if (descriptor != null) {
- ProcessHandler processHandler = descriptor.getProcessHandler();
- assert processHandler != null;
- RunProfile runProfile = env.getRunProfile();
- RunConfiguration runConfiguration =
- (runProfile instanceof RunConfiguration) ? (RunConfiguration) runProfile : null;
- AndroidSessionInfo sessionInfo =
- AndroidSessionInfo.create(
- processHandler,
- descriptor,
- runConfiguration,
- env.getExecutor().getId(),
- env.getExecutor().getActionName(),
- env.getExecutionTarget());
- processHandler.putUserData(AndroidSessionInfo.KEY, sessionInfo);
- }
- return descriptor;
+ protected boolean canRunWithMultipleDevices(@NotNull String executorId) {
+ return true;
}
+
+ @NotNull
@Override
- public String getRunnerId() {
- return "AndroidTestProgramRunner";
+ protected List getSupportedConfigurationTypeIds() {
+ return Collections.singletonList(BlazeCommandRunConfigurationType.getInstance().getId());
+ }
+
+ @NotNull
+ @Override
+ protected RunContentDescriptor run(
+ @NotNull ExecutionEnvironment environment,
+ @NotNull RunProfileState state,
+ @NotNull ProgressIndicator indicator)
+ throws ExecutionException {
+ final AndroidConfigurationExecutor state1 = (AndroidConfigurationExecutor) state;
+ if (DefaultDebugExecutor.EXECUTOR_ID.equals(environment.getExecutor().getId())) {
+ return state1.debug(indicator);
+ }
+ if (DefaultRunExecutor.EXECUTOR_ID.equals(environment.getExecutor().getId())) {
+ return state1.run(indicator);
+ }
+ throw new RuntimeException("Unsupported executor");
}
}
diff --git a/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunConfigurationHandler.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunConfigurationHandler.java
similarity index 81%
rename from aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunConfigurationHandler.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunConfigurationHandler.java
index 755eedeb5ab..050ddc03fee 100644
--- a/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunConfigurationHandler.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunConfigurationHandler.java
@@ -20,12 +20,15 @@
import com.android.tools.idea.run.ValidationError;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
+import com.google.idea.blaze.android.run.ApkBuildStepProvider;
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.ApkBuildStep;
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.runner.FullApkBuildStep;
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;
@@ -40,6 +43,7 @@
import com.google.idea.blaze.base.settings.Blaze;
import com.google.idea.blaze.base.sync.data.BlazeDataStorage;
import com.google.idea.blaze.base.sync.projectstructure.ModuleFinder;
+import com.google.idea.blaze.java.AndroidBlazeRules;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.JavaExecutionUtil;
@@ -108,18 +112,15 @@ public BlazeCommandRunConfigurationRunner createRunner(
// 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();
+ Label label = Label.create(configuration.getSingleTarget().toString());
+
+ ApkBuildStep buildStep =
+ getTestBuildStep(
+ project, configState, configuration, blazeFlags, exeFlags, launchId, label);
BlazeAndroidRunContext runContext =
new BlazeAndroidTestRunContext(
- project,
- facet,
- configuration,
- env,
- configState,
- Label.create(configuration.getSingleTarget().toString()),
- blazeFlags,
- exeFlags,
- launchId);
+ project, facet, configuration, env, configState, label, blazeFlags, buildStep);
LaunchMetrics.logTestLaunch(
launchId, configState.getLaunchMethod().name(), env.getExecutor().getId());
@@ -127,6 +128,35 @@ public BlazeCommandRunConfigurationRunner createRunner(
return new BlazeAndroidRunConfigurationRunner(module, runContext, configuration);
}
+ private static ApkBuildStep getTestBuildStep(
+ Project project,
+ BlazeAndroidTestRunConfigurationState configState,
+ BlazeCommandRunConfiguration configuration,
+ ImmutableList blazeFlags,
+ ImmutableList exeFlags,
+ String launchId,
+ Label label)
+ throws ExecutionException {
+ if (configuration.getTargetKind()
+ == AndroidBlazeRules.RuleTypes.ANDROID_INSTRUMENTATION_TEST.getKind()) {
+ boolean useMobileInstall =
+ AndroidTestLaunchMethod.MOBILE_INSTALL.equals(configState.getLaunchMethod());
+ return ApkBuildStepProvider.getInstance(Blaze.getBuildSystemName(project))
+ .getAitBuildStep(
+ project,
+ useMobileInstall,
+ /* nativeDebuggingEnabled= */ false,
+ label,
+ blazeFlags,
+ exeFlags,
+ launchId);
+ } else {
+ // TODO(b/248317444): This path is only invoked for the deprecated {@code android_test}
+ // targets, and should eventually be removed.
+ return new FullApkBuildStep(project, label, blazeFlags, /* nativeDebuggingEnabled= */ false);
+ }
+ }
+
@Override
public final void checkConfiguration() throws RuntimeConfigurationException {
BlazeAndroidRunConfigurationValidationUtil.throwTopConfigurationError(validate());
diff --git a/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContextBase.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java
similarity index 59%
rename from aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContextBase.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java
index 066c9615043..3caea8d6d81 100644
--- a/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContextBase.java
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java
@@ -15,39 +15,37 @@
*/
package com.google.idea.blaze.android.run.test;
+import static com.android.tools.idea.run.tasks.DefaultConnectDebuggerTaskKt.getBaseDebuggerTask;
+import static com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryNormalBuildRunContextBase.getApkInfoToInstall;
+
import com.android.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
import com.android.tools.idea.run.ApkProvider;
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.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.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.blaze.BlazeLaunchTasksProvider;
import com.android.tools.idea.run.editor.ProfilerState;
-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.android.tools.idea.run.tasks.ConnectDebuggerTask;
+import com.android.tools.idea.run.tasks.DeployTasksCompat;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
-import com.google.idea.blaze.android.run.binary.mobileinstall.MobileInstallBuildStep;
import com.google.idea.blaze.android.run.deployinfo.BlazeAndroidDeployInfo;
import com.google.idea.blaze.android.run.deployinfo.BlazeApkProviderService;
import com.google.idea.blaze.android.run.runner.ApkBuildStep;
import com.google.idea.blaze.android.run.runner.BlazeAndroidDeviceSelector;
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.BlazeInstrumentationTestApkBuildStep;
-import com.google.idea.blaze.android.run.runner.FullApkBuildStep;
import com.google.idea.blaze.android.run.test.BlazeAndroidTestLaunchMethodsProvider.AndroidTestLaunchMethod;
import com.google.idea.blaze.base.model.primitives.Label;
import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration;
import com.google.idea.blaze.base.run.smrunner.BlazeTestUiSession;
-import com.google.idea.blaze.base.run.smrunner.TestUiSessionProvider;
-import com.google.idea.blaze.java.AndroidBlazeRules;
+import com.google.idea.blaze.base.run.testlogs.BlazeTestResultHolder;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
-import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.project.Project;
import java.util.List;
@@ -55,7 +53,7 @@
import org.jetbrains.android.facet.AndroidFacet;
/** Run context for android_test. */
-abstract class BlazeAndroidTestRunContextBase implements BlazeAndroidRunContext {
+public class BlazeAndroidTestRunContext implements BlazeAndroidRunContext {
protected final Project project;
protected final AndroidFacet facet;
protected final BlazeCommandRunConfiguration runConfiguration;
@@ -68,8 +66,9 @@ abstract class BlazeAndroidTestRunContextBase implements BlazeAndroidRunContext
protected final ApkBuildStep buildStep;
protected final ApplicationIdProvider applicationIdProvider;
protected final ApkProvider apkProvider;
+ private final BlazeTestResultHolder testResultsHolder = new BlazeTestResultHolder();
- BlazeAndroidTestRunContextBase(
+ public BlazeAndroidTestRunContext(
Project project,
AndroidFacet facet,
BlazeCommandRunConfiguration runConfiguration,
@@ -77,52 +76,31 @@ abstract class BlazeAndroidTestRunContextBase implements BlazeAndroidRunContext
BlazeAndroidTestRunConfigurationState configState,
Label label,
ImmutableList blazeFlags,
- ImmutableList exeFlags,
- String launchId) {
+ ApkBuildStep buildStep) {
this.project = project;
this.facet = facet;
this.runConfiguration = runConfiguration;
this.env = env;
this.label = label;
this.configState = configState;
-
- if (configState.getLaunchMethod().equals(AndroidTestLaunchMethod.MOBILE_INSTALL)) {
- this.buildStep = new MobileInstallBuildStep(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.
- this.buildStep = new BlazeInstrumentationTestApkBuildStep(project, label, blazeFlags);
- } else {
- this.buildStep = new FullApkBuildStep(project, label, blazeFlags);
- }
-
- this.applicationIdProvider = new BlazeAndroidTestApplicationIdProvider(buildStep);
- this.apkProvider = BlazeApkProviderService.getInstance().getApkProvider(project, buildStep);
-
- BlazeTestUiSession testUiSession =
- canUseTestUi(env.getExecutor())
- ? TestUiSessionProvider.getInstance(env.getProject())
- .getTestUiSession(ImmutableList.of(label))
- : null;
- if (testUiSession != null) {
- this.blazeFlags =
- ImmutableList.builder()
- .addAll(testUiSession.getBlazeFlags())
- .addAll(blazeFlags)
- .build();
- } else {
- this.blazeFlags = blazeFlags;
+ this.buildStep = buildStep;
+ this.blazeFlags = blazeFlags;
+ switch (configState.getLaunchMethod()) {
+ case MOBILE_INSTALL:
+ case NON_BLAZE:
+ consoleProvider = new AitIdeTestConsoleProvider(runConfiguration, configState);
+ break;
+ case BLAZE_TEST:
+ BlazeTestUiSession session =
+ BlazeTestUiSession.create(ImmutableList.of(), testResultsHolder);
+ this.consoleProvider = new AitBlazeTestConsoleProvider(project, runConfiguration, session);
+ break;
+ default:
+ throw new IllegalStateException(
+ "Unsupported launch method " + configState.getLaunchMethod());
}
- this.consoleProvider =
- new AndroidTestConsoleProvider(project, runConfiguration, configState, testUiSession);
- }
-
- private static boolean canUseTestUi(Executor executor) {
- return !isDebugging(executor);
- }
-
- private static boolean isDebugging(Executor executor) {
- return executor instanceof DefaultDebugExecutor;
+ applicationIdProvider = new BlazeAndroidTestApplicationIdProvider(buildStep);
+ apkProvider = BlazeApkProviderService.getInstance().getApkProvider(project, buildStep);
}
@Override
@@ -141,7 +119,7 @@ public ConsoleProvider getConsoleProvider() {
}
@Override
- public ApplicationIdProvider getApplicationIdProvider() throws ExecutionException {
+ public ApplicationIdProvider getApplicationIdProvider() {
return applicationIdProvider;
}
@@ -151,53 +129,50 @@ public ApkBuildStep getBuildStep() {
return buildStep;
}
- // @Override #api211
+ @Override
public ProfilerState getProfileState() {
return null;
}
@Override
- public LaunchTasksProvider getLaunchTasksProvider(LaunchOptions.Builder launchOptionsBuilder)
+ public BlazeLaunchTasksProvider getLaunchTasksProvider(LaunchOptions.Builder launchOptionsBuilder)
throws ExecutionException {
return new BlazeAndroidLaunchTasksProvider(
project, this, applicationIdProvider, launchOptionsBuilder);
}
- // @Override #api212
- @Nullable
- public LaunchTask getApplicationLaunchTask(
- LaunchOptions launchOptions,
- @Nullable Integer userId,
- String contributorsAmStartOptions,
- LaunchStatus launchStatus)
+ @Override
+ public ImmutableList getDeployTasks(IDevice device, LaunchOptions launchOptions)
throws ExecutionException {
- return getApplicationLaunchTask(
- launchOptions, userId, contributorsAmStartOptions, null, null, launchStatus);
+ if (configState.getLaunchMethod() != AndroidTestLaunchMethod.NON_BLAZE) {
+ return ImmutableList.of();
+ }
+ return ImmutableList.of(
+ DeployTasksCompat.createDeployTask(
+ project, getApkInfoToInstall(device, launchOptions, apkProvider), launchOptions));
}
- @SuppressWarnings({"rawtypes"}) // Raw type from upstream.
+ @Override
@Nullable
- public LaunchTask getApplicationLaunchTask(
- LaunchOptions launchOptions,
- @Nullable Integer userId,
- String contributorsAmStartOptions,
- AndroidDebugger androidDebugger,
- AndroidDebuggerState androidDebuggerState,
- LaunchStatus launchStatus)
+ public BlazeLaunchTask getApplicationLaunchTask(
+ LaunchOptions launchOptions, @Nullable Integer userId, String contributorsAmStartOptions)
throws ExecutionException {
switch (configState.getLaunchMethod()) {
case BLAZE_TEST:
- return new BlazeAndroidTestLaunchTask(
- project,
- label,
- blazeFlags,
+ BlazeAndroidTestFilter testFilter =
new BlazeAndroidTestFilter(
configState.getTestingType(),
configState.getClassName(),
configState.getMethodName(),
- configState.getPackageName()),
+ configState.getPackageName());
+ return new BlazeAndroidTestLaunchTask(
+ project,
+ label,
+ blazeFlags,
+ testFilter,
this,
- launchOptions.isDebug());
+ launchOptions.isDebug(),
+ testResultsHolder);
case NON_BLAZE:
case MOBILE_INSTALL:
BlazeAndroidDeployInfo deployInfo;
@@ -207,7 +182,21 @@ public LaunchTask getApplicationLaunchTask(
throw new ExecutionException(e);
}
return StockAndroidTestLaunchTask.getStockTestLaunchTask(
- configState, applicationIdProvider, launchOptions.isDebug(), deployInfo, launchStatus);
+ configState, applicationIdProvider, launchOptions.isDebug(), deployInfo, project);
+ }
+ throw new AssertionError();
+ }
+
+ @Override
+ @SuppressWarnings({"unchecked", "rawtypes"}) // Raw type from upstream.
+ public ConnectDebuggerTask getDebuggerTask(
+ AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState) {
+ switch (configState.getLaunchMethod()) {
+ case BLAZE_TEST:
+ return new ConnectBlazeTestDebuggerTask(this, androidDebugger, androidDebuggerState);
+ case NON_BLAZE:
+ case MOBILE_INSTALL:
+ return getBaseDebuggerTask(androidDebugger, androidDebuggerState, env, facet, 30);
}
throw new AssertionError();
}
@@ -222,9 +211,14 @@ void addLaunchTaskCompleteListener(Runnable runnable) {
launchTaskCompleteListeners.add(runnable);
}
+ @Override
+ public Executor getExecutor() {
+ return env.getExecutor();
+ }
+
@Nullable
@Override
- public Integer getUserId(IDevice device, ConsolePrinter consolePrinter) {
+ public Integer getUserId(IDevice device) {
return null;
}
diff --git a/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/test/ConnectBlazeTestDebuggerTask.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/test/ConnectBlazeTestDebuggerTask.java
new file mode 100644
index 00000000000..3ef2a6c9493
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/test/ConnectBlazeTestDebuggerTask.java
@@ -0,0 +1,105 @@
+/*
+ * 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.IDevice;
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
+import com.android.tools.idea.execution.common.debug.DebugSessionStarter;
+import com.android.tools.idea.run.tasks.ConnectDebuggerTask;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.xdebugger.impl.XDebugSessionImpl;
+import java.io.OutputStream;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/** Connects the blaze debugger during execution. */
+class ConnectBlazeTestDebuggerTask implements ConnectDebuggerTask {
+
+ private final BlazeAndroidTestRunContext runContext;
+ private final AndroidDebugger myAndroidDebugger;
+ private final S myAndroidDebuggerState;
+
+ public ConnectBlazeTestDebuggerTask(
+ BlazeAndroidTestRunContext runContext,
+ AndroidDebugger androidDebugger,
+ S androidDebuggerState) {
+ this.runContext = runContext;
+ myAndroidDebugger = androidDebugger;
+ myAndroidDebuggerState = androidDebuggerState;
+ }
+
+ /**
+ * 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.
+ *
+ * @return Promise with debug session or error
+ */
+ @Override
+ public @NotNull XDebugSessionImpl perform(
+ @NotNull IDevice device,
+ @NotNull String applicationId,
+ @NotNull ExecutionEnvironment environment,
+ @NotNull ProgressIndicator progressIndicator,
+ ConsoleView console) {
+ final ProcessHandler masterProcessHandler =
+ new ProcessHandler() {
+
+ @Override
+ protected void destroyProcessImpl() {
+ notifyProcessTerminated(0);
+ }
+
+ @Override
+ protected void detachProcessImpl() {
+ notifyProcessDetached();
+ }
+
+ @Override
+ public boolean detachIsDefault() {
+ return false;
+ }
+
+ @Override
+ public @Nullable OutputStream getProcessInput() {
+ return null;
+ }
+ };
+ runContext.addLaunchTaskCompleteListener(
+ () -> {
+ masterProcessHandler.notifyTextAvailable(
+ "Test run completed.\n", ProcessOutputTypes.STDOUT);
+ masterProcessHandler.detachProcess();
+ });
+ return DebugSessionStarter.INSTANCE.attachReattachingDebuggerToStartedProcess(
+ device,
+ applicationId,
+ masterProcessHandler,
+ environment,
+ myAndroidDebugger,
+ myAndroidDebuggerState,
+ progressIndicator,
+ console,
+ Long.MAX_VALUE);
+ }
+}
diff --git a/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/testrecorder/TestRecorderBlazeCommandRunConfigurationProxy.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/testrecorder/TestRecorderBlazeCommandRunConfigurationProxy.java
new file mode 100644
index 00000000000..1a7f9a4f621
--- /dev/null
+++ b/aswb/sdkcompat/as223/com/google/idea/blaze/android/run/testrecorder/TestRecorderBlazeCommandRunConfigurationProxy.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.idea.blaze.android.run.testrecorder;
+
+import com.android.annotations.Nullable;
+import com.android.ddmlib.IDevice;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidRunConfigurationRunner;
+import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import java.util.List;
+
+/** Compat class for implementing TestRecorderBlazeCommandRunConfigurationProxy. */
+public class TestRecorderBlazeCommandRunConfigurationProxy
+ extends TestRecorderBlazeCommandRunConfigurationProxyBase {
+
+ public TestRecorderBlazeCommandRunConfigurationProxy(
+ BlazeCommandRunConfiguration baseConfiguration) {
+ super(baseConfiguration);
+ }
+
+ @Override
+ @Nullable
+ public List> getDeviceFutures(ExecutionEnvironment environment) {
+ return environment
+ .getCopyableUserData(BlazeAndroidRunConfigurationRunner.DEVICE_SESSION_KEY)
+ .deviceFutures
+ .get();
+ }
+}
diff --git a/aswb/sdkcompat/as213/com/google/idea/blaze/android/sync/model/idea/BlazeAndroidModel.java b/aswb/sdkcompat/as223/com/google/idea/blaze/android/sync/model/idea/BlazeAndroidModel.java
similarity index 100%
rename from aswb/sdkcompat/as213/com/google/idea/blaze/android/sync/model/idea/BlazeAndroidModel.java
rename to aswb/sdkcompat/as223/com/google/idea/blaze/android/sync/model/idea/BlazeAndroidModel.java
diff --git a/aswb/sdkcompat/as231/com/android/tools/configurations/ConfigurationCompat.java b/aswb/sdkcompat/as231/com/android/tools/configurations/ConfigurationCompat.java
new file mode 100644
index 00000000000..3d51e831ad7
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/android/tools/configurations/ConfigurationCompat.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.configurations;
+
+import com.android.sdklib.devices.Device;
+
+/** Compat class for Configuration. */
+public class ConfigurationCompat {
+
+ private Configuration configuration;
+
+ public ConfigurationCompat(Configuration configuration) {
+ this.configuration = configuration;
+ }
+
+ public void setDevice(Device device, boolean preserveState) {
+ configuration.setDevice(device, preserveState);
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/android/tools/idea/model/AndroidManifestIndexCompat.java b/aswb/sdkcompat/as231/com/android/tools/idea/model/AndroidManifestIndexCompat.java
new file mode 100644
index 00000000000..27f94f054c6
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/android/tools/idea/model/AndroidManifestIndexCompat.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 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.android.tools.idea.model;
+
+/** Compat class for {@link com.android.tools.idea.model.AndroidManifestIndex}. */
+public class AndroidManifestIndexCompat {
+
+ private AndroidManifestIndexCompat() {}
+
+ /** {@code indexEnabled} was removed in Studio 2021.2. #api211 */
+ public static boolean indexEnabled() {
+ return true;
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/android/tools/idea/progress/StudioLoggerProgressIndicatorCompat.java b/aswb/sdkcompat/as231/com/android/tools/idea/progress/StudioLoggerProgressIndicatorCompat.java
new file mode 100644
index 00000000000..e581bd190d8
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/android/tools/idea/progress/StudioLoggerProgressIndicatorCompat.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2023 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.android.tools.idea.progress;
+
+/** Compat layer for StudioLoggerProgressIndicator which moved packages in 2021.2. #api211 */
+public class StudioLoggerProgressIndicatorCompat extends StudioLoggerProgressIndicator {
+ public StudioLoggerProgressIndicatorCompat(Class> c) {
+ super(c);
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/android/tools/idea/rendering/RenderErrorContributorCompat.java b/aswb/sdkcompat/as231/com/android/tools/idea/rendering/RenderErrorContributorCompat.java
new file mode 100644
index 00000000000..f869496110c
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/android/tools/idea/rendering/RenderErrorContributorCompat.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.idea.rendering;
+
+import com.android.tools.idea.ui.designer.EditorDesignSurface;
+import com.android.tools.rendering.RenderResultCompat;
+import com.intellij.openapi.actionSystem.DataContext;
+import groovyjarjarantlr4.v4.runtime.misc.Nullable;
+
+/** Contribute blaze specific render errors. */
+public class RenderErrorContributorCompat extends RenderErrorContributor {
+ public RenderErrorContributorCompat(
+ EditorDesignSurface surface, RenderResultCompat result, @Nullable DataContext dataContext) {
+ super(surface, result.get());
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/android/tools/idea/run/tasks/DeployTasksCompat.java b/aswb/sdkcompat/as231/com/android/tools/idea/run/tasks/DeployTasksCompat.java
new file mode 100644
index 00000000000..8c5bde9785e
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/android/tools/idea/run/tasks/DeployTasksCompat.java
@@ -0,0 +1,52 @@
+/*
+ * 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.deployer.DeployerException;
+import com.android.tools.idea.execution.common.AndroidExecutionException;
+import com.android.tools.idea.execution.common.DeployOptions;
+import com.android.tools.idea.run.ApkInfo;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.google.idea.common.experiments.BoolExperiment;
+import com.intellij.openapi.project.Project;
+import java.util.Collection;
+import java.util.List;
+
+/** Compat class for {@link DeployTask} */
+public class DeployTasksCompat {
+ private static final BoolExperiment updateCodeViaJvmti =
+ new BoolExperiment("android.apply.changes", false);
+
+ private DeployTasksCompat() {}
+
+ public static BlazeLaunchTask createDeployTask(
+ Project project, Collection packages, DeployOptions deployOptions) {
+ return launchContext -> {
+ try {
+ List unused =
+ new DeployTask(
+ project,
+ packages,
+ deployOptions.getPmInstallFlags(),
+ deployOptions.getInstallOnAllUsers(),
+ deployOptions.getAlwaysInstallWithPm())
+ .run(launchContext.getDevice(), launchContext.getProgressIndicator());
+ } catch (DeployerException e) {
+ throw new AndroidExecutionException(e.getId(), e.getMessage());
+ }
+ };
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/android/tools/rendering/HtmlLinkManagerCompat.java b/aswb/sdkcompat/as231/com/android/tools/rendering/HtmlLinkManagerCompat.java
new file mode 100644
index 00000000000..28ca9471258
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/android/tools/rendering/HtmlLinkManagerCompat.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.rendering;
+
+import java.io.File;
+import org.jetbrains.annotations.NotNull;
+
+/** Compat class for {@link HtmlLinkManager} */
+public final class HtmlLinkManagerCompat {
+ public static String createFilePositionUrl(@NotNull File file, int line, int column) {
+ return HtmlLinkManager.createFilePositionUrl(file, line, column);
+ }
+
+ private HtmlLinkManagerCompat() {}
+}
diff --git a/aswb/sdkcompat/as231/com/android/tools/rendering/RenderLoggerCompat.java b/aswb/sdkcompat/as231/com/android/tools/rendering/RenderLoggerCompat.java
new file mode 100644
index 00000000000..96af24f48d3
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/android/tools/rendering/RenderLoggerCompat.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.rendering;
+
+import java.util.Map;
+import java.util.Set;
+
+/** Compat class for RenderLogger. */
+public class RenderLoggerCompat {
+ private final RenderLogger renderLogger;
+
+ public RenderLoggerCompat(RenderResultCompat result) {
+ renderLogger = result.getLogger();
+ }
+
+ public RenderLogger get() {
+ return renderLogger;
+ }
+
+ public boolean hasErrors() {
+ return renderLogger.hasErrors();
+ }
+
+ public Map getBrokenClasses() {
+ return renderLogger.getBrokenClasses();
+ }
+
+ public Set getMissingClasses() {
+ return renderLogger.getMissingClasses();
+ }
+
+ public static void resetFidelityErrorsFilters() {
+ RenderLogger.resetFidelityErrorsFilters();
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/android/tools/rendering/RenderResultCompat.java b/aswb/sdkcompat/as231/com/android/tools/rendering/RenderResultCompat.java
new file mode 100644
index 00000000000..75fc9c912b9
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/android/tools/rendering/RenderResultCompat.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.rendering;
+
+import com.android.ide.common.rendering.api.Result;
+import com.android.tools.idea.rendering.RenderErrorContributor;
+import com.android.tools.idea.rendering.RenderErrorModelFactory;
+import com.android.tools.idea.rendering.RenderResults;
+import com.android.tools.idea.rendering.errors.ui.RenderErrorModel;
+import com.android.tools.idea.ui.designer.EditorDesignSurface;
+import com.android.tools.rendering.imagepool.ImagePool.Image;
+import com.google.idea.blaze.android.rendering.BlazeRenderErrorContributor;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.Nullable;
+
+/** Compat class for {@link RenderResult} */
+public final class RenderResultCompat {
+ private RenderResult result;
+
+ public RenderResultCompat(RenderResult result) {
+ this.result = result;
+ }
+
+ public static RenderResultCompat createBlank(PsiFile file) {
+ return new RenderResultCompat(RenderResults.createBlank(file));
+ }
+
+ public RenderErrorModel createErrorModel() {
+ return RenderErrorModelFactory.createErrorModel(null, result, null);
+ }
+
+ public RenderResult get() {
+ return result;
+ }
+
+ public RenderLogger getLogger() {
+ return result.getLogger();
+ }
+
+ public Module getModule() {
+ return result.getModule();
+ }
+
+ public Result getRenderResult() {
+ return result.getRenderResult();
+ }
+
+ public Image getRenderedImage() {
+ return result.getRenderedImage();
+ }
+
+ private RenderResultCompat() {}
+
+ /** Extension to provide {@link BlazeRenderErrorContributor}. */
+ public static class BlazeProvider extends RenderErrorContributor.Provider {
+ @Override
+ public boolean isApplicable(Project project) {
+ return Blaze.isBlazeProject(project);
+ }
+
+ @Override
+ public RenderErrorContributor getContributor(
+ @Nullable EditorDesignSurface surface, RenderResult result) {
+ return new BlazeRenderErrorContributor(surface, new RenderResultCompat(result), null);
+ }
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/android/tools/rendering/RenderServiceCompat.java b/aswb/sdkcompat/as231/com/android/tools/rendering/RenderServiceCompat.java
new file mode 100644
index 00000000000..de22b6df36d
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/android/tools/rendering/RenderServiceCompat.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.rendering;
+
+/** Compat class for {@link RenderService} */
+public class RenderServiceCompat {
+ public static void shutdownRenderExecutor(long l) {
+ RenderService.shutdownRenderExecutor(l);
+ }
+
+ public static void initializeRenderExecutor() {
+ RenderService.initializeRenderExecutor();
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java
new file mode 100644
index 00000000000..7aa210d0595
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java
@@ -0,0 +1,42 @@
+/*
+ * 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.cppimpl.debug;
+
+import com.android.ddmlib.Client;
+import com.android.tools.ndk.run.editor.AutoAndroidDebuggerState;
+import com.intellij.execution.ExecutionException;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XDebugSession;
+
+/** Shim for #api212 compat. */
+public class BlazeAutoAndroidDebugger extends BlazeAutoAndroidDebuggerBase {
+ @Override
+ public XDebugSession attachToClient(
+ Project project, Client client, AutoAndroidDebuggerState state) throws ExecutionException {
+ if (isNativeProject(project)) {
+ log.info("Project has native development enabled. Attaching native debugger.");
+ return nativeDebugger.attachToClient(project, client, state);
+ } else {
+ return super.attachToClient(project, client, state);
+ }
+ }
+
+ @Override
+ protected boolean isNativeDeployment(Project project, Module debuggeeModule) {
+ return isNativeProject(project);
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebugger.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebugger.java
new file mode 100644
index 00000000000..bfa296e12e2
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebugger.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 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.cppimpl.debug;
+
+/**
+ * API compat of {@link BlazeNativeAndroidDebuggerBase} with the following additions:
+ *
+ *
+ * - Creates a run-config setting using {@link BlazeAndroidNativeAttachConfiguration} instead of
+ * {@link AndroidNativeAttachConfiguration} to override counterproductive validations.
+ *
+ *
+ * #api4.0
+ */
+public class BlazeNativeAndroidDebugger extends BlazeNativeAndroidDebuggerBase {}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebuggerBase.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebuggerBase.java
new file mode 100644
index 00000000000..911d90b7711
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebuggerBase.java
@@ -0,0 +1,59 @@
+/*
+ * 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.cppimpl.debug;
+
+import com.android.tools.ndk.run.editor.NativeAndroidDebugger;
+import com.google.idea.blaze.base.model.BlazeProjectData;
+import com.google.idea.blaze.base.model.primitives.LanguageClass;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
+import com.intellij.openapi.project.Project;
+
+/**
+ * Extension of {@link NativeAndroidDebugger} with the following key differences compared to {@link
+ * NativeAndroidDebugger}.
+ *
+ *
+ * - Overrides {@link #supportsProject} so native debugger is only enabled for native support is
+ * enabled.
+ *
+ */
+public class BlazeNativeAndroidDebuggerBase extends NativeAndroidDebugger {
+ /**
+ * This ID needs to be lexicographically larger than "Java" so it come after the "Java" debugger
+ * when sorted lexicographically in the "Attach Debugger to Android Process" dialog. See {@link
+ * org.jetbrains.android.actions.AndroidProcessChooserDialog#populateDebuggerTypeCombo}.
+ */
+ public static final String ID = "Native" + Blaze.defaultBuildSystemName();
+
+ @Override
+ public String getId() {
+ return ID;
+ }
+
+ @Override
+ public String getDisplayName() {
+ return "Native Only";
+ }
+
+ @Override
+ public boolean supportsProject(Project project) {
+ BlazeProjectData blazeProjectData =
+ BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
+ return blazeProjectData != null
+ && blazeProjectData.getWorkspaceLanguageSettings().isLanguageActive(LanguageClass.C);
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java
new file mode 100644
index 00000000000..162fd8f1793
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java
@@ -0,0 +1,27 @@
+/*
+ * 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.tools.idea.projectsystem.AndroidModuleSystem;
+import com.intellij.openapi.module.Module;
+
+/** Blaze implementation of {@link AndroidModuleSystem}. */
+public class BlazeModuleSystem extends BlazeModuleSystemBase {
+
+ BlazeModuleSystem(Module module) {
+ super(module);
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/projectsystem/BlazeProjectSystem.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/projectsystem/BlazeProjectSystem.java
new file mode 100755
index 00000000000..df7e6246ef5
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/projectsystem/BlazeProjectSystem.java
@@ -0,0 +1,246 @@
+/*
+ * 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.blaze.android.projectsystem;
+
+import static com.android.tools.idea.projectsystem.SourceProvidersKt.emptySourceProvider;
+import static org.jetbrains.android.facet.SourceProviderUtil.createSourceProvidersForLegacyModule;
+
+import com.android.tools.apk.analyzer.AaptInvoker;
+import com.android.tools.idea.log.LogWrapper;
+import com.android.tools.idea.model.AndroidModel;
+import com.android.tools.idea.model.ClassJarProvider;
+import com.android.tools.idea.projectsystem.AndroidProjectSystem;
+import com.android.tools.idea.projectsystem.NamedIdeaSourceProvider;
+import com.android.tools.idea.projectsystem.ProjectSystemBuildManager;
+import com.android.tools.idea.projectsystem.ProjectSystemSyncManager;
+import com.android.tools.idea.projectsystem.ScopeType;
+import com.android.tools.idea.projectsystem.SourceProviderManager;
+import com.android.tools.idea.projectsystem.SourceProviders;
+import com.android.tools.idea.projectsystem.SourceProvidersFactory;
+import com.android.tools.idea.projectsystem.SourceProvidersImpl;
+import com.android.tools.idea.res.AndroidInnerClassFinder;
+import com.android.tools.idea.res.AndroidResourceClassPsiElementFinder;
+import com.android.tools.idea.sdk.AndroidSdks;
+import com.google.common.collect.ImmutableList;
+import com.google.idea.blaze.android.resources.BlazeLightResourceClassService;
+import com.google.idea.blaze.android.sync.model.idea.BlazeAndroidModel;
+import com.google.idea.blaze.android.sync.model.idea.BlazeClassJarProvider;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.settings.BlazeImportSettings.ProjectType;
+import com.intellij.facet.ProjectFacetManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElementFinder;
+import com.intellij.psi.search.GlobalSearchScope;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+import org.jetbrains.android.facet.AndroidFacet;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Base class to implement common methods in {@link AndroidProjectSystem} for blaze with different
+ * sdk
+ */
+public class BlazeProjectSystem implements AndroidProjectSystem {
+ protected final Project project;
+ protected final ProjectSystemSyncManager syncManager;
+ protected final List myFinders;
+ private final BlazeProjectSystemBuildManager buildManager;
+
+ public BlazeProjectSystem(Project project) {
+ this.project = project;
+ syncManager = new BlazeProjectSystemSyncManager(project);
+ buildManager = new BlazeProjectSystemBuildManager(project);
+
+ myFinders =
+ Arrays.asList(
+ AndroidInnerClassFinder.INSTANCE,
+ new AndroidResourceClassPsiElementFinder(getLightResourceClassService()));
+ }
+
+ public Project getProject() {
+ return project;
+ }
+
+ @Override
+ public boolean allowsFileCreation() {
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public VirtualFile getDefaultApkFile() {
+ return null;
+ }
+
+ @Override
+ public Path getPathToAapt() {
+ return AaptInvoker.getPathToAapt(
+ AndroidSdks.getInstance().tryToChooseSdkHandler(),
+ new LogWrapper(BlazeProjectSystem.class));
+ }
+
+ @Override
+ public ProjectSystemBuildManager getBuildManager() {
+ return buildManager;
+ }
+
+ @Override
+ public BlazeModuleSystem getModuleSystem(Module module) {
+ return BlazeModuleSystem.getInstance(module);
+ }
+
+ @Override
+ public ProjectSystemSyncManager getSyncManager() {
+ return syncManager;
+ }
+
+ @Override
+ public Collection getPsiElementFinders() {
+ return myFinders;
+ }
+
+ @Override
+ public BlazeLightResourceClassService getLightResourceClassService() {
+ return BlazeLightResourceClassService.getInstance(project);
+ }
+
+ @Override
+ public SourceProvidersFactory getSourceProvidersFactory() {
+ return new SourceProvidersFactory() {
+ @Override
+ public SourceProviders createSourceProvidersFor(AndroidFacet facet) {
+ BlazeAndroidModel model = ((BlazeAndroidModel) AndroidModel.get(facet));
+ if (model != null) {
+ return createForModel(model);
+ } else {
+ return createSourceProvidersForLegacyModule(facet);
+ }
+ }
+
+ private SourceProviders createForModel(BlazeAndroidModel model) {
+ NamedIdeaSourceProvider mainSourceProvider = model.getDefaultSourceProvider();
+ if (Blaze.getProjectType(project).equals(ProjectType.QUERY_SYNC)) {
+ return new SourceProvidersImpl(
+ mainSourceProvider,
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(),
+ ImmutableList.of(),
+ ImmutableList.of(),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ emptySourceProvider(ScopeType.MAIN),
+ emptySourceProvider(ScopeType.UNIT_TEST),
+ emptySourceProvider(ScopeType.ANDROID_TEST),
+ emptySourceProvider(ScopeType.TEST_FIXTURES));
+ } else {
+ return new SourceProvidersImpl(
+ mainSourceProvider,
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ emptySourceProvider(ScopeType.MAIN),
+ emptySourceProvider(ScopeType.UNIT_TEST),
+ emptySourceProvider(ScopeType.ANDROID_TEST),
+ emptySourceProvider(ScopeType.TEST_FIXTURES));
+ }
+ }
+ };
+ }
+
+ @Override
+ public ClassJarProvider getClassJarProvider() {
+ return new BlazeClassJarProvider(project);
+ }
+
+ @Override
+ public Collection getAndroidFacetsWithPackageName(
+ Project project, String packageName) {
+ return getAndroidFacetsWithPackageName(
+ project, packageName, GlobalSearchScope.projectScope(project));
+ }
+
+ private Collection getAndroidFacetsWithPackageName(
+ Project project, String packageName, GlobalSearchScope scope) {
+ List facets = ProjectFacetManager.getInstance(project).getFacets(AndroidFacet.ID);
+ return facets.stream()
+ .filter(facet -> hasPackageName(facet, packageName))
+ .filter(
+ facet -> {
+ VirtualFile file = SourceProviderManager.getInstance(facet).getMainManifestFile();
+ if (file == null) {
+ return false;
+ } else {
+ return scope.contains(file);
+ }
+ })
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public boolean isNamespaceOrParentPackage(@NotNull String packageName) {
+ List facets = ProjectFacetManager.getInstance(project).getFacets(AndroidFacet.ID);
+ GlobalSearchScope scope = GlobalSearchScope.projectScope(project);
+ for (AndroidFacet facet : facets) {
+ String moduleNamespace = PackageNameUtils.getPackageName(facet.getModule());
+ if (moduleNamespace == null) {
+ continue;
+ }
+ // Check if the moduleNamespace is exactly the package name, or is a subpackage
+ if (!moduleNamespace.startsWith(packageName)) {
+ continue;
+ }
+ // packageName=com.example should not match moduleNamespace=com.example2
+ if (moduleNamespace.length() > packageName.length()
+ && moduleNamespace.charAt(packageName.length()) != '.') {
+ continue;
+ }
+ VirtualFile file = SourceProviderManager.getInstance(facet).getMainManifestFile();
+ if (file == null || !scope.contains(file)) {
+ continue;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Collection getSubmodules() {
+ return ImmutableList.of();
+ }
+
+ @Override
+ public Collection getBootClasspath(@NotNull Module module) {
+ // TODO: b/266586669
+ return ImmutableList.of();
+ }
+
+ private static boolean hasPackageName(AndroidFacet facet, String packageName) {
+ String nameFromFacet = PackageNameUtils.getPackageName(facet.getModule());
+ if (nameFromFacet == null) {
+ return false;
+ }
+ return nameFromFacet.equals(packageName);
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java
new file mode 100644
index 00000000000..81504173f22
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java
@@ -0,0 +1,292 @@
+/*
+ * 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 static java.util.stream.Collectors.joining;
+
+import com.android.tools.idea.projectsystem.ClassFileFinder;
+import com.android.tools.idea.projectsystem.ClassFileFinderUtil;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableSet;
+import com.google.idea.blaze.android.libraries.RenderJarCache;
+import com.google.idea.blaze.android.sync.model.AndroidResourceModule;
+import com.google.idea.blaze.android.sync.model.AndroidResourceModuleRegistry;
+import com.google.idea.blaze.android.targetmaps.TargetToBinaryMap;
+import com.google.idea.blaze.base.ideinfo.TargetIdeInfo;
+import com.google.idea.blaze.base.ideinfo.TargetKey;
+import com.google.idea.blaze.base.io.VirtualFileSystemProvider;
+import com.google.idea.blaze.base.model.BlazeProjectData;
+import com.google.idea.blaze.base.qsync.QuerySync;
+import com.google.idea.blaze.base.qsync.QuerySyncManager;
+import com.google.idea.blaze.base.qsync.RenderJarArtifactTracker;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.settings.BlazeImportSettings.ProjectType;
+import com.google.idea.blaze.base.sync.BlazeSyncModificationTracker;
+import com.google.idea.blaze.base.sync.data.BlazeDataStorage;
+import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
+import com.google.idea.common.experiments.BoolExperiment;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.JarFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import java.io.File;
+import java.util.regex.Pattern;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * A {@link ClassFileFinder} that uses deploy JAR like artifacts (called render jar henceforth) for
+ * class files.
+ *
+ * The render JAR contains all runtime dependencies of a binary target.
+ *
+ *
The Blaze targets that go into creating a resource module is known. Consequently, it is
+ * possible to determine which binaries in the projectview depend on the resource declaring blaze
+ * targets that constitutes the module. This class calculates the binary targets and attempts to
+ * find classes from the render JARs.
+ *
+ *
This only works for resource modules (i.e. not the .workspace module). For .workspace module,
+ * we try to find the class in all binary targets in projectview
+ *
+ *
NOTE: Blaze targets that constitutes the resource module will be called "resource target(s)"
+ * in comments below.
+ */
+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.3", true);
+
+ /**
+ * Experiment to toggle whether resource resolution is allowed from Render JARs. Render JARs
+ * should not resolve resources by default.
+ */
+ @VisibleForTesting
+ static final BoolExperiment resolveResourceClasses =
+ new BoolExperiment("aswb.resolve.resources.render.jar", false);
+
+ private static final Logger log = Logger.getInstance(RenderJarClassFileFinder.class);
+
+ private static final String INTERNAL_PACKAGE = "_layoutlib_._internal_.";
+
+ // matches foo.bar.R or foo.bar.R$baz
+ private static final Pattern RESOURCE_CLASS_NAME = Pattern.compile(".+\\.R(\\$[^.]+)?$");
+
+ private final Module module;
+ private final Project project;
+
+ // tracks the binary targets that depend resource targets
+ // will be recalculated after every sync
+ private ImmutableSet binaryTargets = ImmutableSet.of();
+
+ // tracks the value of {@link BlazeSyncModificationTracker} when binaryTargets is calculated
+ // binaryTargets is calculated when the value of {@link BlazeSyncModificationTracker} does not
+ // equal lastSyncCount
+ long lastSyncCount = -1;
+
+ // true if the current module is the .workspace Module
+ private final boolean isWorkspaceModule;
+
+ public RenderJarClassFileFinder(Module module) {
+ this.module = module;
+ this.project = module.getProject();
+ this.isWorkspaceModule = BlazeDataStorage.WORKSPACE_MODULE_NAME.equals(module.getName());
+ }
+
+ @Nullable
+ @Override
+ public VirtualFile findClassFile(String fqcn) {
+ if (!isEnabled()) {
+ return null;
+ }
+
+ // Ever since Compose support was introduced in AS, finding class files is invoked during the
+ // normal course of opening an editor. The contract for this method requires that it shouldn't
+ // throw any exceptions, but we've had a few bugs where this method threw an exception, which
+ // resulted in users not being able to open Kotlin files at all. In order to avoid this
+ // scenario, we wrap the underlying call and ensure that no exceptions are thrown.
+ try {
+ return findClass(fqcn);
+ } catch (Error e) {
+ log.warn(
+ String.format(
+ "Unexpected error while finding the class file for `%1$s`: %2$s",
+ fqcn, Throwables.getRootCause(e).getMessage()));
+ return null;
+ }
+ }
+
+ @Nullable
+ public VirtualFile findClass(String fqcn) {
+ // Render JAR should not resolve any resources. All resources should be available to the IDE
+ // through ResourceRepository. Attempting to resolve resources from Render JAR indicates that
+ // ASwB hasn't properly set up resources for the project.
+ if (isResourceClass(fqcn) && !resolveResourceClasses.getValue()) {
+ log.warn(String.format("Attempting to load resource '%s' from RenderJAR.", fqcn));
+ return null;
+ }
+
+ if (Blaze.getProjectType(project).equals(ProjectType.QUERY_SYNC)) {
+ if (QuerySync.isComposeEnabled(project)) {
+ RenderJarArtifactTracker renderJarArtifactTracker =
+ QuerySyncManager.getInstance(project).getRenderJarArtifactTracker();
+ // TODO(b/283280194): Setup fqcn -> target and target -> Render jar mappings to avoid
+ // iterating over all render jars when trying to locate class for fqcn.
+ // TODO(b/284002836): Collect metrics on time taken to iterate over the jars
+ for (File renderJar : renderJarArtifactTracker.getRenderJars()) {
+ VirtualFile renderResolveJarVf =
+ VirtualFileSystemProvider.getInstance().getSystem().findFileByIoFile(renderJar);
+ if (renderResolveJarVf != null) {
+ return findClassInJar(renderResolveJarVf, fqcn);
+ }
+ log.warn(String.format("Could not find class `%1$s` with Query Sync", fqcn));
+ return null;
+ }
+ } else {
+ // Disable this class for Query Sync if Compose is not enabled
+ return null;
+ }
+ }
+
+ BlazeProjectData projectData =
+ BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
+ if (projectData == null) {
+ log.warn("Could not find BlazeProjectData for project " + project.getName());
+ return null;
+ }
+
+ ImmutableSet binaryTargets = getBinaryTargets();
+ if (binaryTargets.isEmpty()) {
+ log.warn(
+ String.format(
+ "No binaries for module %s. Adding a binary target to the projectview and resyncing"
+ + " might fix the issue.",
+ module.getName()));
+ return null;
+ }
+
+ // Remove internal package prefix if present
+ fqcn = StringUtil.trimStart(fqcn, INTERNAL_PACKAGE);
+
+ // Look through render resolve JARs of the binaries that depend on the given
+ // androidResourceModule. One androidResourceModule can comprise of multiple resource targets.
+ // The binaries can depend on any subset of these resource targets. Generally, we only
+ // expect one, or a small number of binaries here.
+ for (TargetKey binaryTarget : binaryTargets) {
+ VirtualFile classFile = getClassFromRenderResolveJar(projectData, fqcn, binaryTarget);
+ if (classFile != null) {
+ return classFile;
+ }
+ }
+
+ log.warn(String.format("Could not find class `%1$s` (module: `%2$s`)", fqcn, module.getName()));
+ return null;
+ }
+
+ @VisibleForTesting
+ static boolean isResourceClass(String fqcn) {
+ return RESOURCE_CLASS_NAME.matcher(fqcn).matches();
+ }
+
+ /**
+ * Returns the cached list of binary targets that depend on resource targets. The cache is
+ * recalculated if the project has been synced since last calculation
+ */
+ private ImmutableSet getBinaryTargets() {
+ long currentSyncCount =
+ BlazeSyncModificationTracker.getInstance(project).getModificationCount();
+ if (currentSyncCount == lastSyncCount) {
+ // Return the cached set if there hasn't been a sync since last calculation
+ return binaryTargets;
+ }
+ lastSyncCount = currentSyncCount;
+
+ AndroidResourceModule androidResourceModule =
+ AndroidResourceModuleRegistry.getInstance(project).get(module);
+ if (androidResourceModule != null) {
+ binaryTargets =
+ TargetToBinaryMap.getInstance(project)
+ .getBinariesDependingOn(androidResourceModule.sourceTargetKeys);
+ } else if (isWorkspaceModule) {
+ binaryTargets = TargetToBinaryMap.getInstance(project).getSourceBinaryTargets();
+ } else {
+ binaryTargets = ImmutableSet.of();
+ log.warn("Could not find AndroidResourceModule for " + module.getName());
+ }
+ log.info(
+ String.format(
+ "Binary targets for module `%1$s`: %2$s",
+ module.getName(),
+ binaryTargets.stream()
+ .limit(5)
+ .map(t -> t.getLabel().toString())
+ .collect(joining(", "))));
+ return binaryTargets;
+ }
+
+ /**
+ * Returns class file for fqcn if found in the render JAR corresponding to {@code binaryTarget}.
+ * Returns null if something goes wrong or if render JAR does not contain fqcn
+ */
+ @Nullable
+ private VirtualFile getClassFromRenderResolveJar(
+ BlazeProjectData projectData, String fqcn, TargetKey binaryTarget) {
+ TargetIdeInfo ideInfo = projectData.getTargetMap().get(binaryTarget);
+ if (ideInfo == null) {
+ return null;
+ }
+
+ File renderResolveJarFile =
+ RenderJarCache.getInstance(project)
+ .getCachedJarForBinaryTarget(projectData.getArtifactLocationDecoder(), ideInfo);
+
+ if (renderResolveJarFile == null) {
+ return null;
+ }
+
+ VirtualFile renderResolveJarVF =
+ VirtualFileSystemProvider.getInstance().getSystem().findFileByIoFile(renderResolveJarFile);
+ if (renderResolveJarVF == null) {
+ return null;
+ }
+
+ return findClassInJar(renderResolveJarVF, fqcn);
+ }
+
+ @Nullable
+ private static VirtualFile findClassInJar(final VirtualFile classJar, String fqcn) {
+ VirtualFile jarRoot = getJarRootForLocalFile(classJar);
+ if (jarRoot == null) {
+ return null;
+ }
+ return ClassFileFinderUtil.findClassFileInOutputRoot(jarRoot, fqcn);
+ }
+
+ /** Test aware method to redirect JARs to {@link VirtualFileSystemProvider} for tests */
+ private static VirtualFile getJarRootForLocalFile(VirtualFile file) {
+ return ApplicationManager.getApplication().isUnitTestMode()
+ ? VirtualFileSystemProvider.getInstance()
+ .getSystem()
+ .findFileByPath(file.getPath() + JarFileSystem.JAR_SEPARATOR)
+ : JarFileSystem.getInstance().getJarRootForLocalFile(file);
+ }
+
+ public static boolean isEnabled() {
+ return enabled.getValue();
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/rendering/BlazeRenderErrorContributor.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/rendering/BlazeRenderErrorContributor.java
new file mode 100644
index 00000000000..827e5975a35
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/rendering/BlazeRenderErrorContributor.java
@@ -0,0 +1,351 @@
+/*
+ * 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.rendering;
+
+import static com.android.SdkConstants.ANDROID_MANIFEST_XML;
+import static com.google.common.collect.ImmutableMap.toImmutableMap;
+
+import com.android.tools.idea.rendering.RenderErrorContributorCompat;
+import com.android.tools.idea.rendering.errors.ui.RenderErrorModel;
+import com.android.tools.idea.ui.designer.EditorDesignSurface;
+import com.android.tools.rendering.HtmlLinkManagerCompat;
+import com.android.tools.rendering.RenderLoggerCompat;
+import com.android.tools.rendering.RenderResultCompat;
+import com.android.utils.HtmlBuilder;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.Maps;
+import com.google.common.collect.SortedSetMultimap;
+import com.google.common.collect.TreeMultimap;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import com.google.idea.blaze.android.sync.model.AndroidResourceModule;
+import com.google.idea.blaze.android.sync.model.AndroidResourceModuleRegistry;
+import com.google.idea.blaze.base.command.buildresult.OutputArtifactResolver;
+import com.google.idea.blaze.base.ideinfo.AndroidResFolder;
+import com.google.idea.blaze.base.ideinfo.ArtifactLocation;
+import com.google.idea.blaze.base.ideinfo.TargetIdeInfo;
+import com.google.idea.blaze.base.ideinfo.TargetKey;
+import com.google.idea.blaze.base.ideinfo.TargetMap;
+import com.google.idea.blaze.base.lang.buildfile.references.BuildReferenceManager;
+import com.google.idea.blaze.base.model.BlazeProjectData;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.settings.BlazeImportSettings.ProjectType;
+import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
+import com.google.idea.blaze.base.sync.workspace.ArtifactLocationDecoder;
+import com.google.idea.blaze.base.targetmaps.SourceToTargetMap;
+import com.google.idea.blaze.base.targetmaps.TransitiveDependencyMap;
+import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.IndexNotReadyException;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.search.GlobalSearchScope;
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.function.Function;
+import org.jetbrains.annotations.Nullable;
+
+/** Contribute blaze specific render errors. */
+public class BlazeRenderErrorContributor extends RenderErrorContributorCompat {
+ private final RenderLoggerCompat logger;
+ private final Module module;
+ private final Project project;
+
+ public BlazeRenderErrorContributor(
+ EditorDesignSurface surface, RenderResultCompat result, @Nullable DataContext dataContext) {
+ super(surface, result, dataContext);
+ logger = new RenderLoggerCompat(result);
+ module = result.getModule();
+ project = module.getProject();
+ }
+
+ @Override
+ public Collection reportIssues() {
+ BlazeProjectData blazeProjectData =
+ BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
+
+ if (blazeProjectData == null || !logger.hasErrors()) {
+ return getIssues();
+ }
+
+ if (Blaze.getProjectType(project).equals(ProjectType.QUERY_SYNC)) {
+ // TODO(b/284002829): Setup resource-module specific issue reporting
+ return getIssues();
+ }
+
+ TargetMap targetMap = blazeProjectData.getTargetMap();
+ ArtifactLocationDecoder decoder = blazeProjectData.getArtifactLocationDecoder();
+ AndroidResourceModule resourceModule =
+ AndroidResourceModuleRegistry.getInstance(project).get(module);
+ if (resourceModule == null) {
+ return getIssues();
+ }
+
+ TargetIdeInfo target = targetMap.get(resourceModule.targetKey);
+ if (target == null) {
+ return getIssues();
+ }
+
+ reportGeneratedResources(resourceModule, targetMap, decoder);
+ reportNonStandardAndroidManifestName(target, decoder);
+ reportResourceTargetShouldDependOnClassTarget(target, targetMap, decoder);
+ return getIssues();
+ }
+
+ /**
+ * We can't find generated resources. If a layout uses them, the layout won't render correctly.
+ */
+ private void reportGeneratedResources(
+ AndroidResourceModule resourceModule, TargetMap targetMap, ArtifactLocationDecoder decoder) {
+ Map brokenClasses = logger.getBrokenClasses();
+ if (brokenClasses == null || brokenClasses.isEmpty()) {
+ return;
+ }
+
+ // Sorted entries for deterministic error message.
+ SortedMap generatedResources =
+ Maps.newTreeMap(getGeneratedResources(targetMap.get(resourceModule.targetKey)));
+
+ for (TargetKey dependency : resourceModule.transitiveResourceDependencies) {
+ generatedResources.putAll(getGeneratedResources(targetMap.get(dependency)));
+ }
+
+ if (generatedResources.isEmpty()) {
+ return;
+ }
+
+ HtmlBuilder builder = new HtmlBuilder();
+ builder.add("Generated resources will not be discovered by the IDE:");
+ builder.beginList();
+ for (Map.Entry entry : generatedResources.entrySet()) {
+ ArtifactLocation resource = entry.getKey();
+ TargetIdeInfo target = entry.getValue();
+ builder.listItem().add(resource.getRelativePath()).add(" from ");
+ addTargetLink(builder, target, decoder);
+ }
+ builder
+ .endList()
+ .add("Please avoid using generated resources, ")
+ .addLink("then ", "sync the project", " ", getLinkManager().createSyncProjectUrl())
+ .addLink("and ", "refresh the layout", ".", getLinkManager().createRefreshRenderUrl());
+ addIssue()
+ .setSeverity(HighlightSeverity.ERROR, HIGH_PRIORITY + 1) // Reported above broken classes
+ .setSummary("Generated resources")
+ .setHtmlContent(builder)
+ .build();
+ }
+
+ private static SortedMap getGeneratedResources(
+ TargetIdeInfo target) {
+ if (target == null || target.getAndroidIdeInfo() == null) {
+ return Collections.emptySortedMap();
+ }
+ SortedMap generatedResources = Maps.newTreeMap();
+ generatedResources.putAll(
+ target.getAndroidIdeInfo().getResources().stream()
+ .map(AndroidResFolder::getRoot)
+ .filter(ArtifactLocation::isGenerated)
+ .collect(toImmutableMap(Function.identity(), resource -> target)));
+ return generatedResources;
+ }
+
+ /**
+ * When the Android manifest isn't AndroidManifest.xml, resolving resource IDs would fail. This
+ * doesn't seem to be an issue if the manifest belongs to one of the target's dependencies.
+ */
+ private void reportNonStandardAndroidManifestName(
+ TargetIdeInfo target, ArtifactLocationDecoder decoder) {
+ if (target.getAndroidIdeInfo() == null || target.getAndroidIdeInfo().getManifest() == null) {
+ return;
+ }
+
+ Map brokenClasses = logger.getBrokenClasses();
+ if (brokenClasses == null || brokenClasses.isEmpty()) {
+ return;
+ }
+
+ ArtifactLocation maniftestArtifactLocation = target.getAndroidIdeInfo().getManifest();
+
+ File manifest =
+ Preconditions.checkNotNull(
+ OutputArtifactResolver.resolve(project, decoder, maniftestArtifactLocation),
+ "Fail to find file %s",
+ maniftestArtifactLocation.getRelativePath());
+ if (manifest.getName().equals(ANDROID_MANIFEST_XML)) {
+ return;
+ }
+
+ HtmlBuilder builder = new HtmlBuilder();
+ addTargetLink(builder, target, decoder)
+ .add(" uses a non-standard name for the Android manifest: ");
+ String linkToManifest = HtmlLinkManagerCompat.createFilePositionUrl(manifest, -1, 0);
+ if (linkToManifest != null) {
+ builder.addLink(manifest.getName(), linkToManifest);
+ } else {
+ builder.newline().add(manifest.getPath());
+ }
+ // TODO: add a link to automatically rename the file and refactor all references.
+ builder
+ .newline()
+ .add("Please rename it to ")
+ .add(ANDROID_MANIFEST_XML)
+ .addLink(", then ", "sync the project", "", getLinkManager().createSyncProjectUrl())
+ .addLink(" and ", "refresh the layout", ".", getLinkManager().createRefreshRenderUrl());
+ addIssue()
+ .setSeverity(HighlightSeverity.ERROR, HIGH_PRIORITY + 1) // Reported above broken classes.
+ .setSummary("Non-standard manifest name")
+ .setHtmlContent(builder)
+ .build();
+ }
+
+ /**
+ * Blaze doesn't resolve class dependencies from resources until building the final
+ * android_binary, so we could end up with resources that ultimately build correctly, but fail to
+ * find their class dependencies during rendering in the layout editor.
+ */
+ @SuppressWarnings("rawtypes")
+ private void reportResourceTargetShouldDependOnClassTarget(
+ TargetIdeInfo target, TargetMap targetMap, ArtifactLocationDecoder decoder) {
+ Set missingClasses = logger.getMissingClasses();
+ if (missingClasses == null || missingClasses.isEmpty()) {
+ return;
+ }
+
+ // Sorted entries for deterministic error message.
+ SortedSetMultimap missingClassToTargetMap = TreeMultimap.create();
+
+ SourceToTargetMap sourceToTargetMap = SourceToTargetMap.getInstance(project);
+ ImmutableCollection transitiveDependencies =
+ TransitiveDependencyMap.getInstance(project).getTransitiveDependencies(target.getKey());
+
+ for (String missingClass : missingClasses) {
+ File sourceFile = getSourceFileForClass(missingClass);
+ if (sourceFile == null) {
+ continue;
+ }
+ ImmutableCollection sourceTargets =
+ sourceToTargetMap.getRulesForSourceFile(sourceFile);
+ if (sourceTargets.stream()
+ .noneMatch(
+ sourceTarget ->
+ sourceTarget.equals(target.getKey())
+ || transitiveDependencies.contains(sourceTarget))) {
+ missingClassToTargetMap.putAll(missingClass, sourceTargets);
+ }
+ }
+
+ if (missingClassToTargetMap.isEmpty()) {
+ return;
+ }
+
+ HtmlBuilder builder = new HtmlBuilder();
+ addTargetLink(builder, target, decoder)
+ .add(" contains resource files that reference these classes:")
+ .beginList();
+ for (String missingClass : missingClassToTargetMap.keySet()) {
+ builder
+ .listItem()
+ .addLink(missingClass, getLinkManager().createOpenClassUrl(missingClass))
+ .add(" from ");
+ for (TargetKey targetKey : missingClassToTargetMap.get(missingClass)) {
+ addTargetLink(builder, targetMap.get(targetKey), decoder).add(" ");
+ }
+ }
+ builder.endList().add("Please fix your dependencies so that ");
+ addTargetLink(builder, target, decoder)
+ .add(" correctly depends on these classes, ")
+ .addLink("then ", "sync the project", " ", getLinkManager().createSyncProjectUrl())
+ .addLink("and ", "refresh the layout", ".", getLinkManager().createRefreshRenderUrl())
+ .newline()
+ .newline()
+ .addBold(
+ "NOTE: blaze can still build with the incorrect dependencies "
+ + "due to the way it handles resources, "
+ + "but the layout editor needs them to be correct.");
+
+ addIssue()
+ .setSeverity(HighlightSeverity.ERROR, HIGH_PRIORITY + 1) // Reported above missing classes.
+ .setSummary("Missing class dependencies")
+ .setHtmlContent(builder)
+ .build();
+ }
+
+ private File getSourceFileForClass(String className) {
+ return ApplicationManager.getApplication()
+ .runReadAction(
+ (Computable)
+ () -> {
+ try {
+ PsiClass psiClass =
+ JavaPsiFacade.getInstance(project)
+ .findClass(className, GlobalSearchScope.projectScope(project));
+ if (psiClass == null) {
+ return null;
+ }
+ return VfsUtilCore.virtualToIoFile(
+ psiClass.getContainingFile().getVirtualFile());
+ } catch (IndexNotReadyException ignored) {
+ // We're in dumb mode. Abort! Abort!
+ return null;
+ }
+ });
+ }
+
+ @CanIgnoreReturnValue
+ private HtmlBuilder addTargetLink(
+ HtmlBuilder builder, TargetIdeInfo target, ArtifactLocationDecoder decoder) {
+ File buildFile =
+ Preconditions.checkNotNull(
+ OutputArtifactResolver.resolve(project, decoder, target.getBuildFile()),
+ "Fail to find file %s",
+ target.getBuildFile().getRelativePath());
+ int line =
+ ApplicationManager.getApplication()
+ .runReadAction(
+ (Computable)
+ () -> {
+ PsiElement buildTargetPsi =
+ BuildReferenceManager.getInstance(project)
+ .resolveLabel(target.getKey().getLabel());
+ if (buildTargetPsi == null) {
+ return -1;
+ }
+ PsiFile psiFile = buildTargetPsi.getContainingFile();
+ if (psiFile == null) {
+ return -1;
+ }
+ return StringUtil.offsetToLineNumber(
+ psiFile.getText(), buildTargetPsi.getTextOffset());
+ });
+ String url = HtmlLinkManagerCompat.createFilePositionUrl(buildFile, line, 0);
+ if (url != null) {
+ return builder.addLink(target.toString(), url);
+ }
+ return builder.add(target.toString());
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/rendering/BlazeRenderSecurityManagerOverrides.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/rendering/BlazeRenderSecurityManagerOverrides.java
new file mode 100644
index 00000000000..39d3edd195f
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/rendering/BlazeRenderSecurityManagerOverrides.java
@@ -0,0 +1,27 @@
+/*
+ * 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.rendering;
+
+import com.android.tools.rendering.security.RenderSecurityManagerOverrides;
+
+/** Overrides some security restrictions used by the render sandbox. */
+public class BlazeRenderSecurityManagerOverrides implements RenderSecurityManagerOverrides {
+ @Override
+ public boolean allowsPropertiesAccess() {
+ // System properties access is needed for SystemPropertyExperimentLoader
+ return true;
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/resources/BlazeLightResourceClassServiceBase.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/resources/BlazeLightResourceClassServiceBase.java
new file mode 100644
index 00000000000..21516076cc2
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/resources/BlazeLightResourceClassServiceBase.java
@@ -0,0 +1,66 @@
+/*
+ * 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.resources;
+
+import com.android.tools.idea.projectsystem.LightResourceClassService;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.idea.blaze.base.sync.data.BlazeDataStorage;
+import com.google.idea.common.experiments.FeatureRolloutExperiment;
+import com.intellij.openapi.module.Module;
+import com.intellij.psi.PsiClass;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/** Implementation of {@link LightResourceClassService} set up at Blaze sync time. */
+public abstract class BlazeLightResourceClassServiceBase implements LightResourceClassService {
+
+ @VisibleForTesting
+ public static final FeatureRolloutExperiment workspaceResourcesFeature =
+ new FeatureRolloutExperiment("aswb.workspace.light.class.enabled");
+
+ Map rClasses = Maps.newHashMap();
+ Map rClassesByModule = Maps.newHashMap();
+ final Set allRClasses = Sets.newHashSet();
+
+ @Override
+ public Collection extends PsiClass> getLightRClassesAccessibleFromModule(
+ Module module, boolean includeTest) {
+ if (workspaceResourcesFeature.isEnabled()
+ && module.getName().equals(BlazeDataStorage.WORKSPACE_MODULE_NAME)) {
+ // Returns all the packages in resource modules, and all the workspace packages that
+ // have previously been asked for. All `res/` directories in our project should belong to a
+ // resource module. For java sources, IntelliJ will ask for explicit resource package by
+ // calling `getLightRClasses` at which point we can create the package. This is not completely
+ // correct and the autocomplete will be slightly off when initial `R` is typed in the editor,
+ // but this workaround is being used to mitigate issues (b/136685602) while resources
+ // are re-worked.
+ return allRClasses;
+ } else {
+ return rClasses.values();
+ }
+ }
+
+ @Override
+ public Collection extends PsiClass> getLightRClassesDefinedByModule(
+ Module module, boolean includeTestClasses) {
+ BlazeRClass rClass = rClassesByModule.get(module);
+ return rClass == null ? ImmutableSet.of() : ImmutableSet.of(rClass);
+ }
+}
diff --git a/aswb/sdkcompat/as213/com/google/idea/blaze/android/resources/BlazeRClass.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/resources/BlazeRClass.java
similarity index 88%
rename from aswb/sdkcompat/as213/com/google/idea/blaze/android/resources/BlazeRClass.java
rename to aswb/sdkcompat/as231/com/google/idea/blaze/android/resources/BlazeRClass.java
index 2c123e0a66f..3c64683d517 100644
--- a/aswb/sdkcompat/as213/com/google/idea/blaze/android/resources/BlazeRClass.java
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/resources/BlazeRClass.java
@@ -19,9 +19,9 @@
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.android.tools.idea.res.StudioResourceRepositoryManager;
+import com.android.tools.res.LocalResourceRepository;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModulePointerManager;
import com.intellij.openapi.vfs.VirtualFile;
@@ -49,13 +49,13 @@ public Transitivity getTransitivity() {
}
@Override
- public ResourceRepositoryManager getResourceRepositoryManager() {
- return ResourceRepositoryManager.getInstance(androidFacet);
+ public StudioResourceRepositoryManager getResourceRepositoryManager() {
+ return StudioResourceRepositoryManager.getInstance(androidFacet);
}
@Override
public LocalResourceRepository getResourceRepository() {
- return ResourceRepositoryManager.getAppResources(androidFacet);
+ return StudioResourceRepositoryManager.getAppResources(androidFacet);
}
@Override
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryApplicationLaunchTaskProvider.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryApplicationLaunchTaskProvider.java
new file mode 100644
index 00000000000..948dae75f36
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryApplicationLaunchTaskProvider.java
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+import com.android.tools.idea.run.ApkProvisionException;
+import com.android.tools.idea.run.ApplicationIdProvider;
+import com.android.tools.idea.run.activity.StartActivityFlagsProvider;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.google.idea.blaze.android.manifest.ManifestParser;
+import com.google.idea.blaze.android.run.binary.tasks.AndroidDeepLinkLaunchTask;
+import com.google.idea.blaze.android.run.binary.tasks.BlazeDefaultActivityLaunchTask;
+import com.google.idea.blaze.android.run.binary.tasks.SpecificActivityLaunchTask;
+import com.intellij.execution.ExecutionException;
+import com.intellij.openapi.diagnostic.Logger;
+
+/** Provides the launch task for android_binary */
+public class BlazeAndroidBinaryApplicationLaunchTaskProvider {
+ private static final Logger LOG =
+ Logger.getInstance(BlazeAndroidBinaryApplicationLaunchTaskProvider.class);
+
+ public static BlazeLaunchTask getApplicationLaunchTask(
+ ApplicationIdProvider applicationIdProvider,
+ ManifestParser.ParsedManifest mergedManifestParsedManifest,
+ BlazeAndroidBinaryRunConfigurationState configState,
+ StartActivityFlagsProvider startActivityFlagsProvider)
+ throws ExecutionException {
+ String applicationId;
+ try {
+ applicationId = applicationIdProvider.getPackageName();
+ } catch (ApkProvisionException e) {
+ throw new ExecutionException("Unable to identify application id");
+ }
+
+ switch (configState.getMode()) {
+ case BlazeAndroidBinaryRunConfigurationState.LAUNCH_DEFAULT_ACTIVITY:
+ BlazeDefaultActivityLocator activityLocator =
+ new BlazeDefaultActivityLocator(mergedManifestParsedManifest);
+ return new BlazeDefaultActivityLaunchTask(
+ applicationId, activityLocator, startActivityFlagsProvider);
+ case BlazeAndroidBinaryRunConfigurationState.LAUNCH_SPECIFIC_ACTIVITY:
+ return launchContext ->
+ new SpecificActivityLaunchTask(
+ applicationId, configState.getActivityClass(), startActivityFlagsProvider)
+ .run(
+ launchContext.getDevice(),
+ launchContext.getProgressIndicator(),
+ launchContext.getConsoleView());
+ case BlazeAndroidBinaryRunConfigurationState.LAUNCH_DEEP_LINK:
+ return launchContext ->
+ new AndroidDeepLinkLaunchTask(configState.getDeepLink(), startActivityFlagsProvider)
+ .run(
+ launchContext.getDevice(),
+ launchContext.getProgressIndicator(),
+ launchContext.getConsoleView());
+ default:
+ return null;
+ }
+ }
+}
diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java
similarity index 59%
rename from aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java
rename to aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java
index a15be047fbf..96c4e9e34b3 100644
--- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java
@@ -15,23 +15,29 @@
*/
package com.google.idea.blaze.android.run.binary;
+import com.android.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
+import com.android.tools.idea.execution.common.debug.DebugSessionStarter;
import com.android.tools.idea.run.ApkProvisionException;
-import com.android.tools.idea.run.LaunchOptions;
import com.android.tools.idea.run.activity.DefaultStartActivityFlagsProvider;
import com.android.tools.idea.run.activity.StartActivityFlagsProvider;
-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.util.LaunchStatus;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
import com.google.idea.blaze.android.run.deployinfo.BlazeAndroidDeployInfo;
import com.google.idea.blaze.android.run.runner.ApkBuildStep;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XDebugSession;
import javax.annotation.Nullable;
+import kotlin.Unit;
+import kotlin.coroutines.EmptyCoroutineContext;
+import kotlinx.coroutines.BuildersKt;
import org.jetbrains.android.facet.AndroidFacet;
/** Compat for #api212 */
@@ -48,24 +54,20 @@ public class BlazeAndroidBinaryNormalBuildRunContext
super(project, facet, runConfiguration, env, configState, buildStep, launchId);
}
- @SuppressWarnings("unchecked") // upstream API
@Override
- public LaunchTask getApplicationLaunchTask(
- LaunchOptions launchOptions,
- @Nullable Integer userId,
- String contributorsAmStartOptions,
- AndroidDebugger androidDebugger,
- AndroidDebuggerState androidDebuggerState,
- LaunchStatus launchStatus)
+ public BlazeLaunchTask getApplicationLaunchTask(
+ boolean isDebug, @Nullable Integer userId, String contributorsAmStartOptions)
throws ExecutionException {
String extraFlags = UserIdHelper.getFlagsFromUserId(userId);
if (!contributorsAmStartOptions.isEmpty()) {
extraFlags += (extraFlags.isEmpty() ? "" : " ") + contributorsAmStartOptions;
}
+ if (isDebug) {
+ extraFlags += (extraFlags.isEmpty() ? "" : " ") + "-D";
+ }
final StartActivityFlagsProvider startActivityFlagsProvider =
- new DefaultStartActivityFlagsProvider(
- androidDebugger, androidDebuggerState, project, launchOptions.isDebug(), extraFlags);
+ new DefaultStartActivityFlagsProvider(project, isDebug, extraFlags);
BlazeAndroidDeployInfo deployInfo;
try {
@@ -78,23 +80,40 @@ public LaunchTask getApplicationLaunchTask(
applicationIdProvider,
deployInfo.getMergedManifest(),
configState,
- startActivityFlagsProvider,
- launchStatus);
+ startActivityFlagsProvider);
}
@Nullable
@Override
- @SuppressWarnings("unchecked")
- public ConnectDebuggerTask getDebuggerTask(
- AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState)
- throws ExecutionException {
- return androidDebugger.getConnectDebuggerTask(
- env,
- null,
- applicationIdProvider,
- facet,
- androidDebuggerState,
- runConfiguration.getType().getId());
+ public XDebugSession startDebuggerSession(
+ AndroidDebugger androidDebugger,
+ AndroidDebuggerState androidDebuggerState,
+ ExecutionEnvironment env,
+ IDevice device,
+ ConsoleView consoleView,
+ ProgressIndicator indicator,
+ String packageName) {
+ try {
+ return BuildersKt.runBlocking(
+ EmptyCoroutineContext.INSTANCE,
+ (scope, continuation) ->
+ DebugSessionStarter.INSTANCE.attachDebuggerToStartedProcess(
+ device,
+ packageName,
+ env,
+ androidDebugger,
+ androidDebuggerState,
+ /*destroyRunningProcess*/ d -> {
+ d.forceStop(packageName);
+ return Unit.INSTANCE;
+ },
+ indicator,
+ consoleView,
+ /* timeout= */ 15L,
+ continuation));
+ } catch (InterruptedException e) {
+ throw new ProcessCanceledException();
+ }
}
@Override
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java
new file mode 100644
index 00000000000..96f3f8be324
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java
@@ -0,0 +1,186 @@
+/*
+ * 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;
+
+import static com.google.idea.blaze.android.run.runner.BlazeAndroidLaunchTasksProvider.NATIVE_DEBUGGING_ENABLED;
+
+import com.android.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.DeployOptions;
+import com.android.tools.idea.gradle.util.DynamicAppUtils;
+import com.android.tools.idea.run.ApkFileUnit;
+import com.android.tools.idea.run.ApkInfo;
+import com.android.tools.idea.run.ApkProvider;
+import com.android.tools.idea.run.ApkProvisionException;
+import com.android.tools.idea.run.ApplicationIdProvider;
+import com.android.tools.idea.run.ConsoleProvider;
+import com.android.tools.idea.run.LaunchOptions;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.blaze.BlazeLaunchTasksProvider;
+import com.android.tools.idea.run.editor.ProfilerState;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.idea.blaze.android.run.deployinfo.BlazeApkProviderService;
+import com.google.idea.blaze.android.run.runner.ApkBuildStep;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidDeviceSelector;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidLaunchTasksProvider;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidRunContext;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.Executor;
+import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.openapi.project.Project;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+import org.jetbrains.android.facet.AndroidFacet;
+import org.jetbrains.annotations.NotNull;
+
+/** Run context for android_binary. */
+public abstract class BlazeAndroidBinaryNormalBuildRunContextBase
+ implements BlazeAndroidRunContext {
+ protected final Project project;
+ protected final AndroidFacet facet;
+ protected final RunConfiguration runConfiguration;
+ protected final ExecutionEnvironment env;
+ protected final BlazeAndroidBinaryRunConfigurationState configState;
+ protected final ConsoleProvider consoleProvider;
+ protected final ApkBuildStep buildStep;
+ protected final ApkProvider apkProvider;
+ protected final ApplicationIdProvider applicationIdProvider;
+ private final String launchId;
+
+ BlazeAndroidBinaryNormalBuildRunContextBase(
+ Project project,
+ AndroidFacet facet,
+ RunConfiguration runConfiguration,
+ ExecutionEnvironment env,
+ BlazeAndroidBinaryRunConfigurationState configState,
+ ApkBuildStep buildStep,
+ String launchId) {
+ this.project = project;
+ this.facet = facet;
+ this.runConfiguration = runConfiguration;
+ this.env = env;
+ this.configState = configState;
+ this.consoleProvider = new BlazeAndroidBinaryConsoleProvider(project);
+ this.buildStep = buildStep;
+ this.apkProvider = BlazeApkProviderService.getInstance().getApkProvider(project, buildStep);
+ this.applicationIdProvider = new BlazeAndroidBinaryApplicationIdProvider(buildStep);
+ this.launchId = launchId;
+ }
+
+ @Override
+ public BlazeAndroidDeviceSelector getDeviceSelector() {
+ return new BlazeAndroidDeviceSelector.NormalDeviceSelector();
+ }
+
+ @Override
+ public void augmentLaunchOptions(LaunchOptions.Builder options) {
+ LaunchOptions.Builder unused =
+ options
+ .setDeploy(true)
+ .setOpenLogcatAutomatically(configState.showLogcatAutomatically())
+ .addExtraOptions(
+ ImmutableMap.of(
+ NATIVE_DEBUGGING_ENABLED,
+ configState.getCommonState().isNativeDebuggingEnabled()))
+ .setClearAppStorage(configState.getClearAppStorage());
+ }
+
+ @Override
+ public ConsoleProvider getConsoleProvider() {
+ return consoleProvider;
+ }
+
+ @Override
+ public ApplicationIdProvider getApplicationIdProvider() {
+ return applicationIdProvider;
+ }
+
+ @Override
+ public ApkBuildStep getBuildStep() {
+ return buildStep;
+ }
+
+ @Nullable
+ @Override
+ public Integer getUserId(IDevice device) throws ExecutionException {
+ return UserIdHelper.getUserIdFromConfigurationState(project, device, configState);
+ }
+
+ @Override
+ public BlazeLaunchTasksProvider getLaunchTasksProvider(LaunchOptions launchOptions)
+ throws ExecutionException {
+ return new BlazeAndroidLaunchTasksProvider(project, this, applicationIdProvider, launchOptions);
+ }
+
+ @Override
+ public String getAmStartOptions() {
+ return configState.getAmStartOptions();
+ }
+
+ @Nullable
+ @Override
+ public ImmutableList getDeployTasks(IDevice device, DeployOptions deployOptions)
+ throws ExecutionException {
+ return ImmutableList.of(
+ new DeploymentTimingReporterTask(
+ launchId,
+ project,
+ getApkInfoToInstall(device, deployOptions, apkProvider),
+ deployOptions));
+ }
+
+ /** Returns a list of APKs excluding any APKs for features that are disabled. */
+ public static List getApkInfoToInstall(
+ IDevice device, DeployOptions deployOptions, ApkProvider apkProvider)
+ throws ExecutionException {
+ Collection apks;
+ try {
+ apks = apkProvider.getApks(device);
+ } catch (ApkProvisionException e) {
+ throw new ExecutionException(e);
+ }
+ List disabledFeatures = deployOptions.getDisabledDynamicFeatures();
+ return apks.stream()
+ .map(apk -> getApkInfoToInstall(apk, disabledFeatures))
+ .collect(Collectors.toList());
+ }
+
+ @NotNull
+ private static ApkInfo getApkInfoToInstall(ApkInfo apkInfo, List disabledFeatures) {
+ if (apkInfo.getFiles().size() > 1) {
+ List filteredApks =
+ apkInfo.getFiles().stream()
+ .filter(feature -> DynamicAppUtils.isFeatureEnabled(disabledFeatures, feature))
+ .collect(Collectors.toList());
+ return new ApkInfo(filteredApks, apkInfo.getApplicationId());
+ } else {
+ return apkInfo;
+ }
+ }
+
+ @Override
+ public Executor getExecutor() {
+ return env.getExecutor();
+ }
+
+ @Override
+ public ProfilerState getProfileState() {
+ return configState.getProfilerState();
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextCompat.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextCompat.java
new file mode 100644
index 00000000000..af20febc771
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextCompat.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2022 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.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
+import com.android.tools.idea.execution.common.debug.DebugSessionStarter;
+import com.google.idea.blaze.android.run.runner.ApkBuildStep;
+import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XDebugSession;
+import javax.annotation.Nullable;
+import kotlin.Unit;
+import kotlin.coroutines.EmptyCoroutineContext;
+import kotlinx.coroutines.BuildersKt;
+import org.jetbrains.android.facet.AndroidFacet;
+
+/** Compat class for {@link BlazeAndroidBinaryNormalBuildRunContext}. */
+public class BlazeAndroidBinaryNormalBuildRunContextCompat
+ extends BlazeAndroidBinaryNormalBuildRunContext {
+
+ BlazeAndroidBinaryNormalBuildRunContextCompat(
+ Project project,
+ AndroidFacet facet,
+ RunConfiguration runConfiguration,
+ ExecutionEnvironment env,
+ BlazeAndroidBinaryRunConfigurationState configState,
+ ApkBuildStep buildStep,
+ String launchId) {
+ super(project, facet, runConfiguration, env, configState, buildStep, launchId);
+ }
+
+ @Nullable
+ @Override
+ public XDebugSession startDebuggerSession(
+ AndroidDebugger androidDebugger,
+ AndroidDebuggerState androidDebuggerState,
+ ExecutionEnvironment env,
+ IDevice device,
+ ConsoleView consoleView,
+ ProgressIndicator indicator,
+ String packageName) {
+ try {
+ return BuildersKt.runBlocking(
+ EmptyCoroutineContext.INSTANCE,
+ (scope, continuation) ->
+ DebugSessionStarter.INSTANCE.attachDebuggerToStartedProcess(
+ device,
+ packageName,
+ env,
+ androidDebugger,
+ androidDebuggerState,
+ /*destroyRunningProcess*/ d -> {
+ d.forceStop(packageName);
+ return Unit.INSTANCE;
+ },
+ indicator,
+ consoleView,
+ 15L,
+ continuation));
+ } catch (InterruptedException e) {
+ throw new ProcessCanceledException();
+ }
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryProgramRunner.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryProgramRunner.java
new file mode 100644
index 00000000000..60bd11debaf
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryProgramRunner.java
@@ -0,0 +1,114 @@
+/*
+ * 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;
+
+import static com.intellij.openapi.application.ModalityState.NON_MODAL;
+
+import com.android.tools.idea.execution.common.AndroidConfigurationExecutor;
+import com.android.tools.idea.profilers.ProfileRunExecutor;
+import com.google.idea.blaze.android.run.BlazeAndroidRunConfigurationHandler;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.ExecutionResult;
+import com.intellij.execution.Executor;
+import com.intellij.execution.configurations.RunProfile;
+import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.configurations.RunnerSettings;
+import com.intellij.execution.executors.DefaultDebugExecutor;
+import com.intellij.execution.executors.DefaultRunExecutor;
+import com.intellij.execution.runners.AsyncProgramRunner;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.RunContentBuilder;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.openapi.application.ActionsKt;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
+import org.jetbrains.concurrency.AsyncPromise;
+import org.jetbrains.concurrency.Promise;
+
+/** Program runner for configurations from {@link BlazeAndroidBinaryRunConfigurationHandler}. */
+public class BlazeAndroidBinaryProgramRunner extends AsyncProgramRunner {
+ @Override
+ public boolean canRun(String executorId, RunProfile profile) {
+ BlazeAndroidRunConfigurationHandler handler =
+ BlazeAndroidRunConfigurationHandler.getHandlerFrom(profile);
+ if (!(handler instanceof BlazeAndroidBinaryRunConfigurationHandler)) {
+ return false;
+ }
+ return (DefaultDebugExecutor.EXECUTOR_ID.equals(executorId)
+ || DefaultRunExecutor.EXECUTOR_ID.equals(executorId)
+ || ProfileRunExecutor.EXECUTOR_ID.equals(executorId));
+ }
+
+ @Override
+ protected Promise execute(
+ ExecutionEnvironment environment, RunProfileState state) {
+ FileDocumentManager.getInstance().saveAllDocuments();
+
+ AsyncPromise promise = new AsyncPromise<>();
+
+ ProgressManager.getInstance()
+ .run(
+ new Task.Backgroundable(environment.getProject(), "Launching ${runProfile.name}") {
+ @Override
+ public void run(ProgressIndicator indicator) {
+ try {
+ RunContentDescriptor descriptor;
+ if (state instanceof AndroidConfigurationExecutor) {
+ AndroidConfigurationExecutor configurationExecutor =
+ (AndroidConfigurationExecutor) state;
+ Executor executor = environment.getExecutor();
+ if (executor.getId().equals(DefaultDebugExecutor.EXECUTOR_ID)) {
+ descriptor = configurationExecutor.debug(indicator);
+ } else if (executor.getId().equals(DefaultRunExecutor.EXECUTOR_ID)
+ || executor.getId().equals(ProfileRunExecutor.EXECUTOR_ID)) {
+ descriptor = configurationExecutor.run(indicator);
+ } else {
+ throw new ExecutionException("Unsupported executor");
+ }
+ } else {
+ descriptor = doExecute(state, environment);
+ }
+ promise.setResult(descriptor);
+ } catch (ExecutionException e) {
+ boolean unused = promise.setError(e);
+ }
+ }
+
+ @Override
+ public void onCancel() {
+ super.onCancel();
+ promise.setResult(null);
+ }
+ });
+
+ return promise;
+ }
+
+ private RunContentDescriptor doExecute(
+ final RunProfileState state, final ExecutionEnvironment env) throws ExecutionException {
+ ExecutionResult result = state.execute(env.getExecutor(), this);
+ return ActionsKt.invokeAndWaitIfNeeded(
+ NON_MODAL,
+ () -> new RunContentBuilder(result, env).showRunContent(env.getContentToReuse()));
+ }
+
+ @Override
+ public String getRunnerId() {
+ return "AndroidBinaryProgramRunner";
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationHandlerCompat.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationHandlerCompat.java
new file mode 100644
index 00000000000..188f6e6b844
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationHandlerCompat.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2022 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.execution.common.DeployableToDevice;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.intellij.openapi.project.Project;
+
+/** Compat class for {@link BlazeAndroidBinaryRunConfigurationHandlerCompat}. */
+public class BlazeAndroidBinaryRunConfigurationHandlerCompat {
+ protected final Project project;
+ protected final BlazeAndroidBinaryRunConfigurationState configState;
+
+ @VisibleForTesting
+ protected BlazeAndroidBinaryRunConfigurationHandlerCompat(
+ BlazeCommandRunConfiguration configuration) {
+ project = configuration.getProject();
+ configState =
+ new BlazeAndroidBinaryRunConfigurationState(
+ Blaze.buildSystemName(configuration.getProject()));
+ configuration.putUserData(DeployableToDevice.getKEY(), true);
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/DeploymentTimingReporterTask.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/DeploymentTimingReporterTask.java
new file mode 100644
index 00000000000..bc567e3ff30
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/DeploymentTimingReporterTask.java
@@ -0,0 +1,60 @@
+/*
+ * 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.execution.common.DeployOptions;
+import com.android.tools.idea.run.ApkInfo;
+import com.android.tools.idea.run.blaze.BlazeLaunchContext;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.tasks.DeployTasksCompat;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.ImmutableList;
+import com.google.idea.blaze.android.run.LaunchMetrics;
+import com.intellij.execution.ExecutionException;
+import com.intellij.openapi.project.Project;
+import java.util.Collection;
+
+/** A wrapper launch task that wraps the given deployment task and logs the deployment latency. */
+public class DeploymentTimingReporterTask implements BlazeLaunchTask {
+ private final BlazeLaunchTask deployTask;
+ private final String launchId;
+ private final ImmutableList packages;
+
+ public DeploymentTimingReporterTask(
+ String launchId, Project project, Collection packages, DeployOptions deployOptions) {
+ this.launchId = launchId;
+ this.deployTask = DeployTasksCompat.createDeployTask(project, packages, deployOptions);
+ this.packages = ImmutableList.copyOf(packages);
+ }
+
+ @VisibleForTesting
+ public ImmutableList getPackages() {
+ return packages;
+ }
+
+ @Override
+ public void run(BlazeLaunchContext launchContext) throws ExecutionException {
+ Stopwatch s = Stopwatch.createStarted();
+ try {
+ deployTask.run(launchContext);
+ LaunchMetrics.logDeploymentTime(launchId, s.elapsed(), true);
+ } catch (ExecutionException e) {
+ LaunchMetrics.logDeploymentTime(launchId, s.elapsed(), false);
+ throw e;
+ }
+ }
+}
diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java
similarity index 62%
rename from aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java
rename to aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java
index 8382dba2bb3..b2308bb55a2 100644
--- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java
@@ -15,15 +15,14 @@
*/
package com.google.idea.blaze.android.run.binary.mobileinstall;
+import com.android.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
+import com.android.tools.idea.execution.common.debug.DebugSessionStarter;
import com.android.tools.idea.run.ApkProvisionException;
-import com.android.tools.idea.run.LaunchOptions;
import com.android.tools.idea.run.activity.DefaultStartActivityFlagsProvider;
import com.android.tools.idea.run.activity.StartActivityFlagsProvider;
-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.util.LaunchStatus;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryApplicationLaunchTaskProvider;
import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryRunConfigurationState;
import com.google.idea.blaze.android.run.binary.UserIdHelper;
@@ -33,8 +32,15 @@
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XDebugSession;
import javax.annotation.Nullable;
+import kotlin.Unit;
+import kotlin.coroutines.EmptyCoroutineContext;
+import kotlinx.coroutines.BuildersKt;
import org.jetbrains.android.facet.AndroidFacet;
/** Run Context for mobile install launches, #api4.0 compat. */
@@ -53,23 +59,20 @@ public BlazeAndroidBinaryMobileInstallRunContext(
@SuppressWarnings("unchecked") // upstream API
@Override
- public LaunchTask getApplicationLaunchTask(
- LaunchOptions launchOptions,
- @Nullable Integer userId,
- String contributorsAmStartOptions,
- AndroidDebugger androidDebugger,
- AndroidDebuggerState androidDebuggerState,
- LaunchStatus launchStatus)
+ public BlazeLaunchTask getApplicationLaunchTask(
+ boolean isDebug, @Nullable Integer userId, String contributorsAmStartOptions)
throws ExecutionException {
String extraFlags = UserIdHelper.getFlagsFromUserId(userId);
if (!contributorsAmStartOptions.isEmpty()) {
extraFlags += (extraFlags.isEmpty() ? "" : " ") + contributorsAmStartOptions;
}
+ if (isDebug) {
+ extraFlags += (extraFlags.isEmpty() ? "" : " ") + "-D";
+ }
final StartActivityFlagsProvider startActivityFlagsProvider =
- new DefaultStartActivityFlagsProvider(
- androidDebugger, androidDebuggerState, project, launchOptions.isDebug(), extraFlags);
+ new DefaultStartActivityFlagsProvider(project, isDebug, extraFlags);
BlazeAndroidDeployInfo deployInfo;
try {
deployInfo = buildStep.getDeployInfo();
@@ -81,23 +84,40 @@ public LaunchTask getApplicationLaunchTask(
applicationIdProvider,
deployInfo.getMergedManifest(),
configState,
- startActivityFlagsProvider,
- launchStatus);
+ startActivityFlagsProvider);
}
@Nullable
@Override
- @SuppressWarnings("unchecked")
- public ConnectDebuggerTask getDebuggerTask(
- AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState)
- throws ExecutionException {
- return androidDebugger.getConnectDebuggerTask(
- env,
- null,
- applicationIdProvider,
- facet,
- androidDebuggerState,
- runConfiguration.getType().getId());
+ public XDebugSession startDebuggerSession(
+ AndroidDebugger androidDebugger,
+ AndroidDebuggerState androidDebuggerState,
+ ExecutionEnvironment env,
+ IDevice device,
+ ConsoleView consoleView,
+ ProgressIndicator indicator,
+ String packageName) {
+ try {
+ return BuildersKt.runBlocking(
+ EmptyCoroutineContext.INSTANCE,
+ (scope, continuation) ->
+ DebugSessionStarter.INSTANCE.attachDebuggerToStartedProcess(
+ device,
+ packageName,
+ env,
+ androidDebugger,
+ androidDebuggerState,
+ /*destroyRunningProcess*/ d -> {
+ d.forceStop(packageName);
+ return Unit.INSTANCE;
+ },
+ indicator,
+ consoleView,
+ 15L,
+ continuation));
+ } catch (InterruptedException e) {
+ throw new ProcessCanceledException(e);
+ }
}
@Override
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java
new file mode 100644
index 00000000000..e0de1841828
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java
@@ -0,0 +1,163 @@
+/*
+ * 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.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.DeployOptions;
+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.ConsoleProvider;
+import com.android.tools.idea.run.LaunchOptions;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.blaze.BlazeLaunchTasksProvider;
+import com.android.tools.idea.run.editor.ProfilerState;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryApplicationIdProvider;
+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.ApkBuildStep;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidDeviceSelector;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidLaunchTasksProvider;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidRunContext;
+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;
+ protected final ExecutionEnvironment env;
+ protected final BlazeAndroidBinaryRunConfigurationState configState;
+ protected final ConsoleProvider consoleProvider;
+ protected final ApplicationIdProvider applicationIdProvider;
+ protected final ApkBuildStep buildStep;
+ private final String launchId;
+
+ public BlazeAndroidBinaryMobileInstallRunContextBase(
+ Project project,
+ AndroidFacet facet,
+ RunConfiguration runConfiguration,
+ ExecutionEnvironment env,
+ BlazeAndroidBinaryRunConfigurationState configState,
+ ApkBuildStep buildStep,
+ String launchId) {
+ this.project = project;
+ this.facet = facet;
+ this.runConfiguration = runConfiguration;
+ this.env = env;
+ this.configState = configState;
+ this.consoleProvider = new BlazeAndroidBinaryConsoleProvider(project);
+ this.buildStep = buildStep;
+ this.applicationIdProvider = new BlazeAndroidBinaryApplicationIdProvider(buildStep);
+ this.launchId = launchId;
+ }
+
+ @Override
+ public BlazeAndroidDeviceSelector getDeviceSelector() {
+ return new BlazeAndroidDeviceSelector.NormalDeviceSelector();
+ }
+
+ @Override
+ public void augmentLaunchOptions(LaunchOptions.Builder options) {
+ options
+ .setDeploy(buildStep.needsIdeDeploy())
+ .setOpenLogcatAutomatically(configState.showLogcatAutomatically());
+ // This is needed for compatibility with #api211
+ options.addExtraOptions(
+ ImmutableMap.of("android.profilers.state", configState.getProfilerState()));
+ }
+
+ @Override
+ public ConsoleProvider getConsoleProvider() {
+ return consoleProvider;
+ }
+
+ @Override
+ public ApplicationIdProvider getApplicationIdProvider() {
+ return applicationIdProvider;
+ }
+
+ @Override
+ public ApkBuildStep getBuildStep() {
+ return buildStep;
+ }
+
+ @Override
+ public ProfilerState getProfileState() {
+ return configState.getProfilerState();
+ }
+
+ @Override
+ public ImmutableList getDeployTasks(IDevice device, DeployOptions deployOptions)
+ throws ExecutionException {
+ if (!buildStep.needsIdeDeploy()) {
+ 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);
+ return ImmutableList.of(
+ new DeploymentTimingReporterTask(
+ launchId, project, Collections.singletonList(info), deployOptions));
+ }
+
+ @Nullable
+ @Override
+ public Integer getUserId(IDevice device) throws ExecutionException {
+ return UserIdHelper.getUserIdFromConfigurationState(project, device, configState);
+ }
+
+ @Override
+ public BlazeLaunchTasksProvider getLaunchTasksProvider(LaunchOptions launchOptions)
+ throws ExecutionException {
+ return new BlazeAndroidLaunchTasksProvider(project, this, applicationIdProvider, launchOptions);
+ }
+
+ @Override
+ public String getAmStartOptions() {
+ return configState.getAmStartOptions();
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextCompat.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextCompat.java
new file mode 100644
index 00000000000..c69146a143d
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextCompat.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2022 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.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
+import com.android.tools.idea.execution.common.debug.DebugSessionStarter;
+import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryRunConfigurationState;
+import com.google.idea.blaze.android.run.runner.ApkBuildStep;
+import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XDebugSession;
+import javax.annotation.Nullable;
+import kotlin.Unit;
+import kotlin.coroutines.EmptyCoroutineContext;
+import kotlinx.coroutines.BuildersKt;
+import org.jetbrains.android.facet.AndroidFacet;
+
+/** Compatct class for {@link BlazeAndroidBinaryMobileInstallRunContext}. */
+public class BlazeAndroidBinaryMobileInstallRunContextCompat
+ extends BlazeAndroidBinaryMobileInstallRunContext {
+
+ public BlazeAndroidBinaryMobileInstallRunContextCompat(
+ Project project,
+ AndroidFacet facet,
+ BlazeCommandRunConfiguration configuration,
+ ExecutionEnvironment env,
+ BlazeAndroidBinaryRunConfigurationState configState,
+ ApkBuildStep buildStep,
+ String launchId) {
+ super(project, facet, configuration, env, configState, buildStep, launchId);
+ }
+
+ @Nullable
+ @Override
+ public XDebugSession startDebuggerSession(
+ AndroidDebugger androidDebugger,
+ AndroidDebuggerState androidDebuggerState,
+ ExecutionEnvironment env,
+ IDevice device,
+ ConsoleView consoleView,
+ ProgressIndicator indicator,
+ String packageName) {
+ try {
+ return BuildersKt.runBlocking(
+ EmptyCoroutineContext.INSTANCE,
+ (scope, continuation) ->
+ DebugSessionStarter.INSTANCE.attachDebuggerToStartedProcess(
+ device,
+ packageName,
+ env,
+ androidDebugger,
+ androidDebuggerState,
+ /*destroyRunningProcess*/ d -> {
+ d.forceStop(packageName);
+ return Unit.INSTANCE;
+ },
+ indicator,
+ consoleView,
+ 15L,
+ continuation));
+ } catch (InterruptedException e) {
+ throw new ProcessCanceledException(e);
+ }
+ }
+}
diff --git a/aswb/src/com/google/idea/blaze/android/run/runner/BlazeAndroidDebuggerService.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/BlazeAndroidDebuggerService.java
similarity index 61%
rename from aswb/src/com/google/idea/blaze/android/run/runner/BlazeAndroidDebuggerService.java
rename to aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/BlazeAndroidDebuggerService.java
index 7bc133ab9e7..5715392a171 100644
--- a/aswb/src/com/google/idea/blaze/android/run/runner/BlazeAndroidDebuggerService.java
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/BlazeAndroidDebuggerService.java
@@ -15,16 +15,19 @@
*/
package com.google.idea.blaze.android.run.runner;
-import com.android.tools.idea.run.editor.AndroidDebugger;
-import com.android.tools.idea.run.editor.AndroidDebuggerState;
-import com.android.tools.idea.run.editor.AndroidJavaDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
+import com.android.tools.idea.execution.common.debug.impl.java.AndroidJavaDebugger;
+import com.android.tools.ndk.run.editor.AutoAndroidDebuggerState;
import com.android.tools.ndk.run.editor.NativeAndroidDebuggerState;
import com.google.common.collect.ImmutableList;
import com.google.idea.blaze.android.cppimpl.debug.BlazeAutoAndroidDebugger;
+import com.google.idea.blaze.android.run.deployinfo.BlazeAndroidDeployInfo;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
+import javax.annotation.Nullable;
/** Provides android debuggers and debugger states for blaze projects. */
public interface BlazeAndroidDebuggerService {
@@ -45,6 +48,9 @@ static BlazeAndroidDebuggerService getInstance(Project project) {
*/
AndroidDebuggerState getDebuggerState(AndroidDebugger debugger);
+ void configureNativeDebugger(
+ AndroidDebuggerState state, @Nullable BlazeAndroidDeployInfo deployInfo);
+
/** Default debugger service. */
class DefaultDebuggerService implements BlazeAndroidDebuggerService {
private final Project project;
@@ -85,10 +91,47 @@ public AndroidDebuggerState getDebuggerState(AndroidDebugger debugger) {
return debuggerState;
}
- private static boolean isNdkPluginLoaded() {
- return PluginManagerCore.getLoadedPlugins().stream()
- .anyMatch(
- d -> d.isEnabled() && d.getPluginId().getIdString().equals("com.android.tools.ndk"));
+ @Override
+ public void configureNativeDebugger(
+ AndroidDebuggerState rawState, @Nullable BlazeAndroidDeployInfo deployInfo) {
+ if (!isNdkPluginLoaded() && !(rawState instanceof AutoAndroidDebuggerState)) {
+ return;
+ }
+ AutoAndroidDebuggerState state = (AutoAndroidDebuggerState) rawState;
+
+ // Source code is always relative to the workspace root in a blaze project.
+ String workingDirPath = WorkspaceRoot.fromProject(project).directory().getPath();
+ state.setWorkingDir(workingDirPath);
+
+ // Remote built binaries may use /proc/self/cwd to represent the working directory,
+ // so we manually map /proc/self/cwd to the workspace root. We used to use
+ // `plugin.symbol-file.dwarf.comp-dir-symlink-paths = "/proc/self/cwd"`
+ // to automatically resolve this, but it's no longer supported in newer versions of
+ // LLDB.
+ String sourceMapToWorkspaceRootCommand =
+ "settings append target.source-map /proc/self/cwd/ " + workingDirPath;
+
+ ImmutableList startupCommands =
+ ImmutableList.builder()
+ .addAll(state.getUserStartupCommands())
+ .add(sourceMapToWorkspaceRootCommand)
+ .build();
+ state.setUserStartupCommands(startupCommands);
+
+ // NDK plugin will pass symbol directories to LLDB as `settings append
+ // target.exec-search-paths`.
+ if (deployInfo != null) {
+ state.setSymbolDirs(
+ deployInfo.getSymbolFiles().stream()
+ .map(symbol -> symbol.getParentFile().getAbsolutePath())
+ .collect(ImmutableList.toImmutableList()));
+ }
}
}
+
+ static boolean isNdkPluginLoaded() {
+ return PluginManagerCore.getLoadedPlugins().stream()
+ .anyMatch(
+ d -> d.isEnabled() && d.getPluginId().getIdString().equals("com.android.tools.ndk"));
+ }
}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java
new file mode 100644
index 00000000000..a1528a9c4d9
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/BlazeAndroidLaunchTasksProvider.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2022 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.tools.deployer.ApkVerifierTracker;
+import com.android.tools.idea.execution.common.DeployOptions;
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
+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.LaunchOptions;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.blaze.BlazeLaunchTasksProvider;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.idea.blaze.android.run.binary.UserIdHelper;
+import com.google.idea.blaze.android.run.deployinfo.BlazeAndroidDeployInfo;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XDebugSession;
+import java.util.Collections;
+import java.util.List;
+import org.jetbrains.annotations.NotNull;
+
+/** Normal launch tasks provider. #api4.1 */
+public class BlazeAndroidLaunchTasksProvider implements BlazeLaunchTasksProvider {
+ 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 launchOptions;
+
+ public BlazeAndroidLaunchTasksProvider(
+ Project project,
+ BlazeAndroidRunContext runContext,
+ ApplicationIdProvider applicationIdProvider,
+ LaunchOptions launchOptions) {
+ this.project = project;
+ this.runContext = runContext;
+ this.applicationIdProvider = applicationIdProvider;
+ this.launchOptions = launchOptions;
+ }
+
+ @NotNull
+ @Override
+ public List getTasks(@NotNull IDevice device, boolean isDebug)
+ throws ExecutionException {
+ final List launchTasks = Lists.newArrayList();
+
+ String packageName;
+ try {
+ packageName = applicationIdProvider.getPackageName();
+ } catch (ApkProvisionException e) {
+ throw new ExecutionException("Unable to determine application id: " + e);
+ }
+
+ Integer userId = runContext.getUserId(device);
+
+ // 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(runContext.getExecutor())) {
+ launchTasks.add(new BlazeAndroidOpenProfilerWindowTask(project));
+ }
+
+ if (launchOptions.isDeploy()) {
+ String userIdFlags = UserIdHelper.getFlagsFromUserId(userId);
+ String skipVerification =
+ ApkVerifierTracker.getSkipVerificationInstallationFlag(device, packageName);
+ String pmInstallOption;
+ if (skipVerification != null) {
+ pmInstallOption = userIdFlags + " " + skipVerification;
+ } else {
+ pmInstallOption = userIdFlags;
+ }
+ DeployOptions deployOptions =
+ new DeployOptions(Collections.emptyList(), pmInstallOption, false, false);
+ ImmutableList deployTasks = runContext.getDeployTasks(device, deployOptions);
+ launchTasks.addAll(deployTasks);
+ }
+
+ try {
+ if (isDebug) {
+ launchTasks.add(
+ new CheckApkDebuggableTask(project, runContext.getBuildStep().getDeployInfo()));
+ }
+
+ ImmutableList.Builder amStartOptions = ImmutableList.builder();
+ amStartOptions.add(runContext.getAmStartOptions());
+ if (isProfilerLaunch(runContext.getExecutor())) {
+ amStartOptions.add(
+ AndroidProfilerLaunchTaskContributor.getAmStartOptions(
+ project,
+ packageName,
+ runContext.getProfileState(),
+ device,
+ runContext.getExecutor()));
+ }
+ BlazeLaunchTask appLaunchTask =
+ runContext.getApplicationLaunchTask(
+ isDebug, userId, String.join(" ", amStartOptions.build()));
+ if (appLaunchTask != null) {
+ launchTasks.add(appLaunchTask);
+ // TODO(arvindanekal): the live edit api changed and we cannot get the apk here to create
+ // live
+ // edit; the live edit team or Arvind need to fix this
+ }
+ } catch (ApkProvisionException e) {
+ throw new ExecutionException("Unable to determine application id: " + e);
+ }
+
+ return ImmutableList.copyOf(launchTasks);
+ }
+
+ @NotNull
+ @Override
+ public XDebugSession startDebugSession(
+ @NotNull ExecutionEnvironment environment,
+ @NotNull IDevice device,
+ @NotNull ConsoleView console,
+ @NotNull ProgressIndicator indicator,
+ @NotNull String packageName)
+ throws ExecutionException {
+ // Do not get debugger state directly from the debugger itself.
+ // See BlazeAndroidDebuggerService#getDebuggerState for an explanation.
+ boolean isNativeDebuggingEnabled = isNativeDebuggingEnabled(launchOptions);
+ BlazeAndroidDebuggerService debuggerService = BlazeAndroidDebuggerService.getInstance(project);
+ AndroidDebugger debugger = debuggerService.getDebugger(isNativeDebuggingEnabled);
+ if (debugger == null) {
+ throw new ExecutionException("Can't find AndroidDebugger for launch");
+ }
+ AndroidDebuggerState debuggerState = debuggerService.getDebuggerState(debugger);
+ if (debuggerState == null) {
+ throw new ExecutionException("Can't find AndroidDebuggerState for launch");
+ }
+ if (isNativeDebuggingEnabled) {
+ BlazeAndroidDeployInfo deployInfo = null;
+ try {
+ deployInfo = runContext.getBuildStep().getDeployInfo();
+ } catch (ApkProvisionException e) {
+ LOG.error(e);
+ }
+ debuggerService.configureNativeDebugger(debuggerState, deployInfo);
+ }
+
+ return runContext.startDebuggerSession(
+ debugger, debuggerState, environment, device, console, indicator, packageName);
+ }
+
+ private boolean isNativeDebuggingEnabled(LaunchOptions launchOptions) {
+ Object flag = launchOptions.getExtraOption(NATIVE_DEBUGGING_ENABLED);
+ return flag instanceof Boolean && (Boolean) flag;
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/BlazeAndroidRunConfigurationRunner.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/BlazeAndroidRunConfigurationRunner.java
new file mode 100644
index 00000000000..e0634874fff
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/BlazeAndroidRunConfigurationRunner.java
@@ -0,0 +1,320 @@
+/*
+ * 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.editors.literals.LiveEditService;
+import com.android.tools.idea.execution.common.AndroidConfigurationExecutor;
+import com.android.tools.idea.execution.common.AndroidConfigurationExecutorRunProfileState;
+import com.android.tools.idea.execution.common.AppRunSettings;
+import com.android.tools.idea.execution.common.ApplicationDeployer;
+import com.android.tools.idea.execution.common.ComponentLaunchOptions;
+import com.android.tools.idea.execution.common.DeployOptions;
+import com.android.tools.idea.execution.common.stats.RunStats;
+import com.android.tools.idea.run.ApkProvider;
+import com.android.tools.idea.run.ApplicationIdProvider;
+import com.android.tools.idea.run.DeviceFutures;
+import com.android.tools.idea.run.LaunchOptions;
+import com.android.tools.idea.run.blaze.BlazeAndroidConfigurationExecutor;
+import com.android.tools.idea.run.configuration.execution.AndroidComplicationConfigurationExecutor;
+import com.android.tools.idea.run.configuration.execution.AndroidTileConfigurationExecutor;
+import com.android.tools.idea.run.configuration.execution.AndroidWatchFaceConfigurationExecutor;
+import com.android.tools.idea.run.configuration.execution.ApplicationDeployerImpl;
+import com.android.tools.idea.run.configuration.execution.ComplicationLaunchOptions;
+import com.android.tools.idea.run.configuration.execution.TileLaunchOptions;
+import com.android.tools.idea.run.configuration.execution.WatchFaceLaunchOptions;
+import com.android.tools.idea.run.editor.DeployTarget;
+import com.android.tools.idea.run.editor.DeployTargetState;
+import com.android.tools.idea.run.util.LaunchUtils;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryRunConfigurationState;
+import com.google.idea.blaze.android.run.binary.mobileinstall.MobileInstallBuildStep;
+import com.google.idea.blaze.android.run.deployinfo.BlazeApkProviderService;
+import com.google.idea.blaze.base.async.executor.ProgressiveTaskWithProgressIndicator;
+import com.google.idea.blaze.base.command.BlazeInvocationContext.ContextType;
+import com.google.idea.blaze.base.experiments.ExperimentScope;
+import com.google.idea.blaze.base.issueparser.BlazeIssueParser;
+import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
+import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration;
+import com.google.idea.blaze.base.run.confighandler.BlazeCommandRunConfigurationRunner;
+import com.google.idea.blaze.base.run.state.RunConfigurationState;
+import com.google.idea.blaze.base.scope.BlazeContext;
+import com.google.idea.blaze.base.scope.Scope;
+import com.google.idea.blaze.base.scope.ScopedTask;
+import com.google.idea.blaze.base.scope.output.IssueOutput;
+import com.google.idea.blaze.base.scope.scopes.IdeaLogScope;
+import com.google.idea.blaze.base.scope.scopes.ProblemsViewScope;
+import com.google.idea.blaze.base.scope.scopes.ToolWindowScope;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.settings.BlazeUserSettings;
+import com.google.idea.blaze.base.toolwindow.Task;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.Executor;
+import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.executors.DefaultDebugExecutor;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
+import java.util.Collections;
+import java.util.concurrent.CancellationException;
+import javax.annotation.Nullable;
+import org.jetbrains.android.facet.AndroidFacet;
+import org.jetbrains.android.util.AndroidBundle;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Supports the execution. Used by both android_binary and android_test.
+ *
+ * Builds the APK and installs it, launches and debug tasks, etc.
+ *
+ *
Any indirection between android_binary/android_test, mobile-install, InstantRun etc. should
+ * come via the strategy class.
+ */
+public final class BlazeAndroidRunConfigurationRunner
+ implements BlazeCommandRunConfigurationRunner {
+
+ private static final Logger LOG = Logger.getInstance(BlazeAndroidRunConfigurationRunner.class);
+
+ private static final Key RUN_CONTEXT_KEY =
+ Key.create("blaze.run.context");
+ public static final Key DEVICE_SESSION_KEY =
+ Key.create("blaze.device.session");
+
+ private final Module module;
+ private final BlazeAndroidRunContext runContext;
+ private final BlazeCommandRunConfiguration runConfig;
+
+ public BlazeAndroidRunConfigurationRunner(
+ Module module, BlazeAndroidRunContext runContext, BlazeCommandRunConfiguration runConfig) {
+ this.module = module;
+ this.runContext = runContext;
+ this.runConfig = runConfig;
+ }
+
+ @Override
+ @Nullable
+ public final RunProfileState getRunProfileState(final Executor executor, ExecutionEnvironment env)
+ throws ExecutionException {
+
+ final AndroidFacet facet = AndroidFacet.getInstance(module);
+ assert facet != null : "Enforced by fatal validation check in createRunner.";
+ final Project project = env.getProject();
+
+ boolean isDebug = executor instanceof DefaultDebugExecutor;
+
+ BlazeAndroidDeviceSelector deviceSelector = runContext.getDeviceSelector();
+ BlazeAndroidDeviceSelector.DeviceSession deviceSession =
+ deviceSelector.getDevice(project, executor, env, isDebug, runConfig.getUniqueID());
+ if (deviceSession == null) {
+ return null;
+ }
+
+ DeployTarget deployTarget = deviceSession.deployTarget;
+ if (deployTarget != null && deployTarget.hasCustomRunProfileState(executor)) {
+ return deployTarget.getRunProfileState(executor, env, DeployTargetState.DEFAULT_STATE);
+ }
+
+ DeviceFutures deviceFutures = deviceSession.deviceFutures;
+ if (deviceFutures == null) {
+ // The user deliberately canceled, or some error was encountered and exposed by the chooser.
+ // Quietly exit.
+ return null;
+ }
+
+ if (deviceFutures.get().isEmpty()) {
+ throw new ExecutionException(AndroidBundle.message("deployment.target.not.found"));
+ }
+
+ if (isDebug) {
+ String error = canDebug(deviceFutures, facet, module.getName());
+ if (error != null) {
+ throw new ExecutionException(error);
+ }
+ }
+
+ LaunchOptions.Builder launchOptionsBuilder = getDefaultLaunchOptions();
+ runContext.augmentLaunchOptions(launchOptionsBuilder);
+
+ // Store the run context on the execution environment so before-run tasks can access it.
+ env.putCopyableUserData(RUN_CONTEXT_KEY, runContext);
+ env.putCopyableUserData(DEVICE_SESSION_KEY, deviceSession);
+
+ RunConfigurationState state = runConfig.getHandler().getState();
+
+ if (state instanceof BlazeAndroidBinaryRunConfigurationState
+ && ((BlazeAndroidBinaryRunConfigurationState) state).getCurrentWearLaunchOptions()
+ != null) {
+ ComponentLaunchOptions launchOptions =
+ ((BlazeAndroidBinaryRunConfigurationState) state).getCurrentWearLaunchOptions();
+
+ return getWearExecutor(launchOptions, env, deployTarget);
+ }
+
+ ApkProvider apkProvider =
+ BlazeApkProviderService.getInstance()
+ .getApkProvider(env.getProject(), runContext.getBuildStep());
+ final LaunchOptions launchOptions = launchOptionsBuilder.build();
+ BlazeAndroidConfigurationExecutor runner =
+ new BlazeAndroidConfigurationExecutor(
+ runContext.getConsoleProvider(),
+ runContext.getApplicationIdProvider(),
+ env,
+ deviceFutures,
+ runContext.getLaunchTasksProvider(launchOptions),
+ launchOptions,
+ apkProvider,
+ LiveEditService.getInstance(env.getProject()));
+ return new AndroidConfigurationExecutorRunProfileState(runner);
+ }
+
+ private RunProfileState getWearExecutor(
+ ComponentLaunchOptions launchOptions, ExecutionEnvironment env, DeployTarget deployTarget)
+ throws ExecutionException {
+
+ AppRunSettings settings =
+ new AppRunSettings() {
+ @NotNull
+ @Override
+ public DeployOptions getDeployOptions() {
+ return new DeployOptions(Collections.emptyList(), "", true, true);
+ }
+
+ @NotNull
+ @Override
+ public ComponentLaunchOptions getComponentLaunchOptions() {
+ return launchOptions;
+ }
+
+ @Override
+ public Module getModule() {
+ return runConfig.getModules()[0];
+ }
+ };
+
+ AndroidConfigurationExecutor configurationExecutor;
+ ApplicationIdProvider appIdProvider = runContext.getApplicationIdProvider();
+ ApkProvider apkProvider =
+ BlazeApkProviderService.getInstance()
+ .getApkProvider(env.getProject(), runContext.getBuildStep());
+ DeviceFutures deviceFutures = deployTarget.getDevices(env.getProject());
+
+ ApplicationDeployer deployer =
+ runContext.getBuildStep() instanceof MobileInstallBuildStep
+ ? new MobileInstallApplicationDeployer()
+ : new ApplicationDeployerImpl(env.getProject(), RunStats.from(env));
+
+ if (launchOptions instanceof TileLaunchOptions) {
+ configurationExecutor =
+ new AndroidTileConfigurationExecutor(
+ env, deviceFutures, settings, appIdProvider, apkProvider, deployer);
+ } else if (launchOptions instanceof WatchFaceLaunchOptions) {
+ configurationExecutor =
+ new AndroidWatchFaceConfigurationExecutor(
+ env, deviceFutures, settings, appIdProvider, apkProvider, deployer);
+ } else if (launchOptions instanceof ComplicationLaunchOptions) {
+ configurationExecutor =
+ new AndroidComplicationConfigurationExecutor(
+ env, deviceFutures, settings, appIdProvider, apkProvider, deployer);
+ } else {
+ throw new RuntimeException("Unknown launch options " + launchOptions.getClass().getName());
+ }
+
+ return new AndroidConfigurationExecutorRunProfileState(configurationExecutor);
+ }
+
+ private static String canDebug(
+ DeviceFutures deviceFutures, AndroidFacet facet, String moduleName) {
+ // If we are debugging on a device, then the app needs to be debuggable
+ for (ListenableFuture future : deviceFutures.get()) {
+ if (!future.isDone()) {
+ // this is an emulator, and we assume that all emulators are debuggable
+ continue;
+ }
+ IDevice device = Futures.getUnchecked(future);
+ if (!LaunchUtils.canDebugAppOnDevice(facet, device)) {
+ return AndroidBundle.message(
+ "android.cannot.debug.noDebugPermissions", moduleName, device.getName());
+ }
+ }
+ return null;
+ }
+
+ private static LaunchOptions.Builder getDefaultLaunchOptions() {
+ return LaunchOptions.builder();
+ }
+
+ @Override
+ public boolean executeBeforeRunTask(ExecutionEnvironment env) {
+ final Project project = env.getProject();
+ BlazeUserSettings settings = BlazeUserSettings.getInstance();
+ return Scope.root(
+ context -> {
+ context
+ .push(new ProblemsViewScope(project, settings.getShowProblemsViewOnRun()))
+ .push(new ExperimentScope())
+ .push(
+ new ToolWindowScope.Builder(
+ project, new Task(project, "Build apk", Task.Type.BEFORE_LAUNCH))
+ .setPopupBehavior(settings.getShowBlazeConsoleOnRun())
+ .setIssueParsers(
+ BlazeIssueParser.defaultIssueParsers(
+ project,
+ WorkspaceRoot.fromProject(project),
+ ContextType.BeforeRunTask))
+ .build())
+ .push(new IdeaLogScope());
+
+ BlazeAndroidRunContext runContext = env.getCopyableUserData(RUN_CONTEXT_KEY);
+ if (runContext == null) {
+ IssueOutput.error("Could not find run context. Please try again").submit(context);
+ return false;
+ }
+ BlazeAndroidDeviceSelector.DeviceSession deviceSession =
+ env.getCopyableUserData(DEVICE_SESSION_KEY);
+
+ ApkBuildStep buildStep = runContext.getBuildStep();
+ ScopedTask buildTask =
+ new ScopedTask(context) {
+ @Override
+ protected Void execute(BlazeContext context) {
+ buildStep.build(context, deviceSession);
+ return null;
+ }
+ };
+
+ try {
+ ListenableFuture buildFuture =
+ ProgressiveTaskWithProgressIndicator.builder(
+ project,
+ String.format("Executing %s apk build", Blaze.buildSystemName(project)))
+ .submitTaskWithResult(buildTask);
+ Futures.getChecked(buildFuture, ExecutionException.class);
+ } catch (ExecutionException e) {
+ context.setHasError();
+ } catch (CancellationException e) {
+ context.setCancelled();
+ } catch (Exception e) {
+ LOG.error(e);
+ return false;
+ }
+ return context.shouldContinue();
+ });
+ }
+}
diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java
similarity index 58%
rename from aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java
rename to aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java
index 04546989cd5..a484e1735a3 100644
--- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/BlazeAndroidRunContext.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2016 The Bazel Authors. All rights reserved.
+ * Copyright (C) 2023 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
+ * 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,
@@ -16,20 +16,22 @@
package com.google.idea.blaze.android.run.runner;
import com.android.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.DeployOptions;
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
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.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.blaze.BlazeLaunchTasksProvider;
import com.android.tools.idea.run.editor.ProfilerState;
-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 com.intellij.execution.Executor;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.xdebugger.XDebugSession;
import javax.annotation.Nullable;
import org.jetbrains.annotations.NotNull;
@@ -44,34 +46,34 @@ public interface BlazeAndroidRunContext {
ApkBuildStep getBuildStep();
- ApplicationIdProvider getApplicationIdProvider() throws ExecutionException;
+ ApplicationIdProvider getApplicationIdProvider();
- LaunchTasksProvider getLaunchTasksProvider(LaunchOptions.Builder launchOptionsBuilder)
+ BlazeLaunchTasksProvider getLaunchTasksProvider(LaunchOptions launchOptions)
throws ExecutionException;
/** Returns the tasks to deploy the application. */
- ImmutableList getDeployTasks(IDevice device, LaunchOptions launchOptions)
+ ImmutableList getDeployTasks(IDevice device, DeployOptions deployOptions)
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)
+ BlazeLaunchTask getApplicationLaunchTask(
+ boolean isDebug, @Nullable Integer userId, @NotNull String contributorsAmStartOptions)
throws ExecutionException;
/** Returns the task to connect the debugger. */
@Nullable
- ConnectDebuggerTask getDebuggerTask(
- AndroidDebugger androidDebugger, AndroidDebuggerState androidDebuggerState)
- throws ExecutionException;
+ XDebugSession startDebuggerSession(
+ AndroidDebugger androidDebugger,
+ AndroidDebuggerState androidDebuggerState,
+ ExecutionEnvironment env,
+ IDevice device,
+ ConsoleView consoleView,
+ ProgressIndicator indicator,
+ String packageName);
@Nullable
- Integer getUserId(IDevice device, ConsolePrinter consolePrinter) throws ExecutionException;
+ Integer getUserId(IDevice device) throws ExecutionException;
String getAmStartOptions();
diff --git a/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/runner/LaunchOptionsCompat.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/LaunchOptionsCompat.java
similarity index 93%
rename from aswb/sdkcompat/as213/com/google/idea/blaze/android/run/runner/LaunchOptionsCompat.java
rename to aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/LaunchOptionsCompat.java
index 5a606a8a2ea..f31959514c5 100644
--- a/aswb/sdkcompat/as213/com/google/idea/blaze/android/run/runner/LaunchOptionsCompat.java
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/LaunchOptionsCompat.java
@@ -24,6 +24,6 @@ private LaunchOptionsCompat() {}
/** Create default launch options to maintain compatibility with #api211. */
public static LaunchOptions.Builder getDefaultLaunchOptions() {
- return LaunchOptions.builder().setClearLogcatBeforeStart(false);
+ return LaunchOptions.builder();
}
}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/MobileInstallApplicationDeployer.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/MobileInstallApplicationDeployer.java
new file mode 100644
index 00000000000..f637ec7c654
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/runner/MobileInstallApplicationDeployer.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2022 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.run.runner;
+
+import com.android.ddmlib.IDevice;
+import com.android.tools.deployer.ApkParser;
+import com.android.tools.deployer.Deployer;
+import com.android.tools.deployer.DeployerException;
+import com.android.tools.deployer.model.Apk;
+import com.android.tools.deployer.model.App;
+import com.android.tools.idea.execution.common.ApplicationDeployer;
+import com.android.tools.idea.execution.common.DeployOptions;
+import com.android.tools.idea.log.LogWrapper;
+import com.android.tools.idea.run.ApkFileUnit;
+import com.android.tools.idea.run.ApkInfo;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.jetbrains.annotations.NotNull;
+
+/** Deploys mobile install application. */
+public class MobileInstallApplicationDeployer implements ApplicationDeployer {
+ final Logger log = Logger.getInstance(this.getClass());
+
+ public MobileInstallApplicationDeployer() {}
+
+ @NotNull
+ @Override
+ public Deployer.Result fullDeploy(
+ @NotNull IDevice device,
+ @NotNull ApkInfo apkInfo,
+ @NotNull DeployOptions deployOptions,
+ ProgressIndicator indicator)
+ throws DeployerException {
+ final List apkPaths =
+ apkInfo.getFiles().stream()
+ .map(ApkFileUnit::getApkPath)
+ .map(Path::toString)
+ .collect(Collectors.toList());
+ final List apks = new ApkParser().parsePaths(apkPaths);
+ App app = new App(apkInfo.getApplicationId(), apks, device, new LogWrapper(log));
+ return new Deployer.Result(false, false, false, app);
+ }
+
+ @NotNull
+ @Override
+ public Deployer.Result applyChangesDeploy(
+ @NotNull IDevice device,
+ @NotNull ApkInfo app,
+ @NotNull DeployOptions deployOptions,
+ ProgressIndicator indicator)
+ throws DeployerException {
+ throw new RuntimeException("Apply changes is not supported for mobile-install");
+ }
+
+ @NotNull
+ @Override
+ public Deployer.Result applyCodeChangesDeploy(
+ @NotNull IDevice device,
+ @NotNull ApkInfo app,
+ @NotNull DeployOptions deployOptions,
+ ProgressIndicator indicator)
+ throws DeployerException {
+ throw new RuntimeException("Apply code changes is not supported for mobile-install");
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/test/BlazeAndroidTestProgramRunner.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/test/BlazeAndroidTestProgramRunner.java
new file mode 100644
index 00000000000..b294b565455
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/test/BlazeAndroidTestProgramRunner.java
@@ -0,0 +1,77 @@
+/*
+ * 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.test;
+
+import com.android.tools.idea.execution.common.AndroidConfigurationExecutor;
+import com.android.tools.idea.execution.common.AndroidConfigurationProgramRunner;
+import com.google.idea.blaze.android.run.BlazeAndroidRunConfigurationHandler;
+import com.google.idea.blaze.base.run.BlazeCommandRunConfigurationType;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.configurations.RunProfile;
+import com.intellij.execution.executors.DefaultDebugExecutor;
+import com.intellij.execution.executors.DefaultRunExecutor;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.openapi.progress.ProgressIndicator;
+import java.util.Collections;
+import java.util.List;
+import org.jetbrains.annotations.NotNull;
+
+/** Program runner for configurations from {@link BlazeAndroidTestRunConfigurationHandler}. */
+public class BlazeAndroidTestProgramRunner extends AndroidConfigurationProgramRunner {
+ @Override
+ public boolean canRun(String executorId, RunProfile profile) {
+ BlazeAndroidRunConfigurationHandler handler =
+ BlazeAndroidRunConfigurationHandler.getHandlerFrom(profile);
+ if (!(handler instanceof BlazeAndroidTestRunConfigurationHandler)) {
+ return false;
+ }
+ return super.canRun(executorId, profile) && DefaultRunExecutor.EXECUTOR_ID.equals(executorId)
+ || DefaultDebugExecutor.EXECUTOR_ID.equals(executorId);
+ }
+
+ @Override
+ public String getRunnerId() {
+ return "AndroidTestProgramRunner";
+ }
+
+ @Override
+ protected boolean canRunWithMultipleDevices(@NotNull String executorId) {
+ return true;
+ }
+
+ @NotNull
+ @Override
+ protected List getSupportedConfigurationTypeIds() {
+ return Collections.singletonList(BlazeCommandRunConfigurationType.getInstance().getId());
+ }
+
+ @NotNull
+ @Override
+ protected RunContentDescriptor run(
+ @NotNull ExecutionEnvironment environment,
+ @NotNull AndroidConfigurationExecutor executor,
+ @NotNull ProgressIndicator indicator)
+ throws ExecutionException {
+ if (DefaultDebugExecutor.EXECUTOR_ID.equals(environment.getExecutor().getId())) {
+ return executor.debug(indicator);
+ }
+ if (DefaultRunExecutor.EXECUTOR_ID.equals(environment.getExecutor().getId())) {
+ return executor.run(indicator);
+ }
+ throw new RuntimeException("Unsupported executor");
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunConfigurationHandler.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunConfigurationHandler.java
new file mode 100644
index 00000000000..67e2ad4dfb7
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunConfigurationHandler.java
@@ -0,0 +1,223 @@
+/*
+ * 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.tools.idea.execution.common.DeployableToDevice;
+import com.android.tools.idea.run.ValidationError;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.idea.blaze.android.run.ApkBuildStepProvider;
+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.ApkBuildStep;
+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.runner.FullApkBuildStep;
+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.model.primitives.Label;
+import com.google.idea.blaze.base.model.primitives.TargetExpression;
+import com.google.idea.blaze.base.projectview.ProjectViewManager;
+import com.google.idea.blaze.base.projectview.ProjectViewSet;
+import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration;
+import com.google.idea.blaze.base.run.BlazeConfigurationNameBuilder;
+import com.google.idea.blaze.base.run.ExecutorType;
+import com.google.idea.blaze.base.run.confighandler.BlazeCommandRunConfigurationRunner;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.sync.data.BlazeDataStorage;
+import com.google.idea.blaze.base.sync.projectstructure.ModuleFinder;
+import com.google.idea.blaze.java.AndroidBlazeRules;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.Executor;
+import com.intellij.execution.JavaExecutionUtil;
+import com.intellij.execution.configurations.RuntimeConfigurationException;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.jetbrains.android.facet.AndroidFacet;
+
+/**
+ * {@link com.google.idea.blaze.base.run.confighandler.BlazeCommandRunConfigurationHandler} for
+ * android_test targets.
+ */
+public class BlazeAndroidTestRunConfigurationHandler
+ implements BlazeAndroidRunConfigurationHandler {
+ private final Project project;
+ private final BlazeAndroidTestRunConfigurationState configState;
+
+ BlazeAndroidTestRunConfigurationHandler(BlazeCommandRunConfiguration configuration) {
+ this.project = configuration.getProject();
+ this.configState =
+ new BlazeAndroidTestRunConfigurationState(
+ Blaze.buildSystemName(configuration.getProject()));
+ configuration.putUserData(DeployableToDevice.getKEY(), true);
+ }
+
+ @Override
+ public BlazeAndroidTestRunConfigurationState getState() {
+ return configState;
+ }
+
+ @Override
+ public BlazeAndroidRunConfigurationCommonState getCommonState() {
+ return configState.getCommonState();
+ }
+
+ @Override
+ public BlazeCommandRunConfigurationRunner createRunner(
+ Executor executor, ExecutionEnvironment env) throws ExecutionException {
+ Project project = env.getProject();
+ BlazeCommandRunConfiguration configuration =
+ BlazeAndroidRunConfigurationHandler.getCommandConfig(env);
+
+ BlazeAndroidRunConfigurationValidationUtil.validate(project);
+ Module module =
+ ModuleFinder.getInstance(env.getProject())
+ .findModuleByName(BlazeDataStorage.WORKSPACE_MODULE_NAME);
+ AndroidFacet facet = module != null ? AndroidFacet.getInstance(module) : null;
+ ProjectViewSet projectViewSet = ProjectViewManager.getInstance(project).getProjectViewSet();
+
+ ImmutableList blazeFlags =
+ configState
+ .getCommonState()
+ .getExpandedBuildFlags(
+ project,
+ projectViewSet,
+ BlazeCommandName.TEST,
+ BlazeInvocationContext.runConfigContext(
+ ExecutorType.fromExecutor(env.getExecutor()), configuration.getType(), false));
+ 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();
+ Label label = Label.create(configuration.getSingleTarget().toString());
+
+ ApkBuildStep buildStep =
+ getTestBuildStep(
+ project, configState, configuration, blazeFlags, exeFlags, launchId, label);
+
+ BlazeAndroidRunContext runContext =
+ new BlazeAndroidTestRunContext(
+ project, facet, configuration, env, configState, label, blazeFlags, buildStep);
+
+ LaunchMetrics.logTestLaunch(
+ launchId, configState.getLaunchMethod().name(), env.getExecutor().getId());
+
+ return new BlazeAndroidRunConfigurationRunner(module, runContext, configuration);
+ }
+
+ private static ApkBuildStep getTestBuildStep(
+ Project project,
+ BlazeAndroidTestRunConfigurationState configState,
+ BlazeCommandRunConfiguration configuration,
+ ImmutableList blazeFlags,
+ ImmutableList exeFlags,
+ String launchId,
+ Label label)
+ throws ExecutionException {
+ if (configuration.getTargetKind()
+ == AndroidBlazeRules.RuleTypes.ANDROID_INSTRUMENTATION_TEST.getKind()) {
+ boolean useMobileInstall =
+ AndroidTestLaunchMethod.MOBILE_INSTALL.equals(configState.getLaunchMethod());
+ return ApkBuildStepProvider.getInstance(Blaze.getBuildSystemName(project))
+ .getAitBuildStep(
+ project,
+ useMobileInstall,
+ /* nativeDebuggingEnabled= */ false,
+ label,
+ blazeFlags,
+ exeFlags,
+ launchId);
+ } else {
+ // TODO(b/248317444): This path is only invoked for the deprecated {@code android_test}
+ // targets, and should eventually be removed.
+ return new FullApkBuildStep(project, label, blazeFlags, /* nativeDebuggingEnabled= */ false);
+ }
+ }
+
+ @Override
+ public final void checkConfiguration() throws RuntimeConfigurationException {
+ BlazeAndroidRunConfigurationValidationUtil.throwTopConfigurationError(validate());
+ }
+
+ /**
+ * We collect errors rather than throwing to avoid missing fatal errors by exiting early for a
+ * warning. We use a separate method for the collection so the compiler prevents us from
+ * accidentally throwing.
+ */
+ private List validate() {
+ List errors = Lists.newArrayList();
+ errors.addAll(BlazeAndroidRunConfigurationValidationUtil.validateWorkspaceModule(project));
+ errors.addAll(configState.validate(project));
+ return errors;
+ }
+
+ @Override
+ @Nullable
+ public String suggestedName(BlazeCommandRunConfiguration configuration) {
+ TargetExpression target = configuration.getSingleTarget();
+ if (target == null) {
+ return null;
+ }
+ BlazeConfigurationNameBuilder nameBuilder = new BlazeConfigurationNameBuilder(configuration);
+
+ boolean isClassTest =
+ configState.getTestingType() == BlazeAndroidTestRunConfigurationState.TEST_CLASS;
+ boolean isMethodTest =
+ configState.getTestingType() == BlazeAndroidTestRunConfigurationState.TEST_METHOD;
+ if ((isClassTest || isMethodTest) && configState.getClassName() != null) {
+ // Get the class name without the package.
+ String className = JavaExecutionUtil.getPresentableClassName(configState.getClassName());
+ if (className != null) {
+ String targetString = className;
+ if (isMethodTest) {
+ targetString += "#" + configState.getMethodName();
+ }
+
+ if (getState().getLaunchMethod().equals(AndroidTestLaunchMethod.NON_BLAZE)) {
+ return targetString;
+ } else {
+ return nameBuilder.setTargetString(targetString).build();
+ }
+ }
+ }
+ return nameBuilder.build();
+ }
+
+ @Override
+ @Nullable
+ public BlazeCommandName getCommandName() {
+ if (getState().getLaunchMethod().equals(AndroidTestLaunchMethod.BLAZE_TEST)) {
+ return BlazeCommandName.TEST;
+ } else if (getState().getLaunchMethod().equals(AndroidTestLaunchMethod.MOBILE_INSTALL)) {
+ return BlazeCommandName.MOBILE_INSTALL;
+ }
+ return null;
+ }
+
+ @Override
+ public String getHandlerName() {
+ return "Android Test Handler";
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java
new file mode 100644
index 00000000000..149af277a6b
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java
@@ -0,0 +1,285 @@
+/*
+ * 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 static com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryNormalBuildRunContextBase.getApkInfoToInstall;
+
+import com.android.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.DeployOptions;
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
+import com.android.tools.idea.execution.common.debug.DebugSessionStarter;
+import com.android.tools.idea.run.ApkProvider;
+import com.android.tools.idea.run.ApkProvisionException;
+import com.android.tools.idea.run.ApplicationIdProvider;
+import com.android.tools.idea.run.ConsoleProvider;
+import com.android.tools.idea.run.LaunchOptions;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.blaze.BlazeLaunchTasksProvider;
+import com.android.tools.idea.run.editor.ProfilerState;
+import com.android.tools.idea.run.tasks.DeployTasksCompat;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.idea.blaze.android.run.deployinfo.BlazeAndroidDeployInfo;
+import com.google.idea.blaze.android.run.deployinfo.BlazeApkProviderService;
+import com.google.idea.blaze.android.run.runner.ApkBuildStep;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidDeviceSelector;
+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.test.BlazeAndroidTestLaunchMethodsProvider.AndroidTestLaunchMethod;
+import com.google.idea.blaze.base.model.primitives.Label;
+import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration;
+import com.google.idea.blaze.base.run.smrunner.BlazeTestUiSession;
+import com.google.idea.blaze.base.run.testlogs.BlazeTestResultHolder;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.Executor;
+import com.intellij.execution.process.NopProcessHandler;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XDebugSession;
+import java.util.List;
+import javax.annotation.Nullable;
+import kotlin.Unit;
+import kotlin.coroutines.EmptyCoroutineContext;
+import kotlinx.coroutines.BuildersKt;
+import org.jetbrains.android.facet.AndroidFacet;
+
+/** Run context for android_test. */
+public class BlazeAndroidTestRunContext implements BlazeAndroidRunContext {
+ protected final Project project;
+ protected final AndroidFacet facet;
+ protected final BlazeCommandRunConfiguration runConfiguration;
+ protected final ExecutionEnvironment env;
+ protected final BlazeAndroidTestRunConfigurationState configState;
+ protected final Label label;
+ protected final ImmutableList blazeFlags;
+ protected final List launchTaskCompleteListeners = Lists.newArrayList();
+ protected final ConsoleProvider consoleProvider;
+ protected final ApkBuildStep buildStep;
+ protected final ApplicationIdProvider applicationIdProvider;
+ protected final ApkProvider apkProvider;
+ private final BlazeTestResultHolder testResultsHolder = new BlazeTestResultHolder();
+
+ public BlazeAndroidTestRunContext(
+ Project project,
+ AndroidFacet facet,
+ BlazeCommandRunConfiguration runConfiguration,
+ ExecutionEnvironment env,
+ BlazeAndroidTestRunConfigurationState configState,
+ Label label,
+ ImmutableList blazeFlags,
+ ApkBuildStep buildStep) {
+ this.project = project;
+ this.facet = facet;
+ this.runConfiguration = runConfiguration;
+ this.env = env;
+ this.label = label;
+ this.configState = configState;
+ this.buildStep = buildStep;
+ this.blazeFlags = blazeFlags;
+ switch (configState.getLaunchMethod()) {
+ case MOBILE_INSTALL:
+ case NON_BLAZE:
+ consoleProvider = new AitIdeTestConsoleProvider(runConfiguration, configState);
+ break;
+ case BLAZE_TEST:
+ BlazeTestUiSession session =
+ BlazeTestUiSession.create(ImmutableList.of(), testResultsHolder);
+ this.consoleProvider = new AitBlazeTestConsoleProvider(project, runConfiguration, session);
+ break;
+ default:
+ throw new IllegalStateException(
+ "Unsupported launch method " + configState.getLaunchMethod());
+ }
+ applicationIdProvider = new BlazeAndroidTestApplicationIdProvider(buildStep);
+ apkProvider = BlazeApkProviderService.getInstance().getApkProvider(project, buildStep);
+ }
+
+ @Override
+ public BlazeAndroidDeviceSelector getDeviceSelector() {
+ return new BlazeAndroidDeviceSelector.NormalDeviceSelector();
+ }
+
+ @Override
+ public void augmentLaunchOptions(LaunchOptions.Builder options) {
+ options.setDeploy(!configState.getLaunchMethod().equals(AndroidTestLaunchMethod.BLAZE_TEST));
+ }
+
+ @Override
+ public ConsoleProvider getConsoleProvider() {
+ return consoleProvider;
+ }
+
+ @Override
+ public ApplicationIdProvider getApplicationIdProvider() {
+ return applicationIdProvider;
+ }
+
+ @Nullable
+ @Override
+ public ApkBuildStep getBuildStep() {
+ return buildStep;
+ }
+
+ @Override
+ public ProfilerState getProfileState() {
+ return null;
+ }
+
+ @Override
+ public BlazeLaunchTasksProvider getLaunchTasksProvider(LaunchOptions launchOptions)
+ throws ExecutionException {
+ return new BlazeAndroidLaunchTasksProvider(project, this, applicationIdProvider, launchOptions);
+ }
+
+ @Override
+ public ImmutableList getDeployTasks(IDevice device, DeployOptions deployOptions)
+ throws ExecutionException {
+ if (configState.getLaunchMethod() != AndroidTestLaunchMethod.NON_BLAZE) {
+ return ImmutableList.of();
+ }
+ return ImmutableList.of(
+ DeployTasksCompat.createDeployTask(
+ project, getApkInfoToInstall(device, deployOptions, apkProvider), deployOptions));
+ }
+
+ @Override
+ @Nullable
+ public BlazeLaunchTask getApplicationLaunchTask(
+ boolean isDebug, @Nullable Integer userId, String contributorsAmStartOptions)
+ throws ExecutionException {
+ switch (configState.getLaunchMethod()) {
+ case BLAZE_TEST:
+ BlazeAndroidTestFilter testFilter =
+ new BlazeAndroidTestFilter(
+ configState.getTestingType(),
+ configState.getClassName(),
+ configState.getMethodName(),
+ configState.getPackageName());
+ return new BlazeAndroidTestLaunchTask(
+ project, label, blazeFlags, testFilter, this, isDebug, testResultsHolder);
+ case NON_BLAZE:
+ case MOBILE_INSTALL:
+ BlazeAndroidDeployInfo deployInfo;
+ try {
+ deployInfo = buildStep.getDeployInfo();
+ } catch (ApkProvisionException e) {
+ throw new ExecutionException(e);
+ }
+ return StockAndroidTestLaunchTask.getStockTestLaunchTask(
+ configState, applicationIdProvider, isDebug, deployInfo, project);
+ }
+ throw new AssertionError();
+ }
+
+ @Override
+ @SuppressWarnings({"unchecked", "rawtypes"}) // Raw type from upstream.
+ public XDebugSession startDebuggerSession(
+ AndroidDebugger androidDebugger,
+ AndroidDebuggerState androidDebuggerState,
+ ExecutionEnvironment env,
+ IDevice device,
+ ConsoleView consoleView,
+ ProgressIndicator indicator,
+ String packageName) {
+ try {
+ return BuildersKt.runBlocking(
+ EmptyCoroutineContext.INSTANCE,
+ (scope, continuation) -> {
+ switch (configState.getLaunchMethod()) {
+ case BLAZE_TEST:
+
+ /**
+ * 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.
+ */
+ final ProcessHandler masterProcessHandler = new NopProcessHandler();
+ addLaunchTaskCompleteListener(
+ () -> {
+ masterProcessHandler.notifyTextAvailable(
+ "Test run completed.\n", ProcessOutputTypes.STDOUT);
+ masterProcessHandler.detachProcess();
+ });
+ return DebugSessionStarter.INSTANCE.attachReattachingDebuggerToStartedProcess(
+ device,
+ packageName,
+ masterProcessHandler,
+ env,
+ androidDebugger,
+ androidDebuggerState,
+ indicator,
+ consoleView,
+ Long.MAX_VALUE,
+ continuation);
+ case NON_BLAZE:
+ case MOBILE_INSTALL:
+ return DebugSessionStarter.INSTANCE.attachDebuggerToStartedProcess(
+ device,
+ packageName,
+ env,
+ androidDebugger,
+ androidDebuggerState,
+ /*destroyRunningProcess*/ d -> {
+ d.forceStop(packageName);
+ return Unit.INSTANCE;
+ },
+ indicator,
+ consoleView,
+ Long.MAX_VALUE,
+ continuation);
+ }
+ throw new RuntimeException("Unknown lunch mode");
+ });
+ } catch (InterruptedException e) {
+ throw new ProcessCanceledException();
+ }
+ }
+
+ void onLaunchTaskComplete() {
+ for (Runnable runnable : launchTaskCompleteListeners) {
+ runnable.run();
+ }
+ }
+
+ void addLaunchTaskCompleteListener(Runnable runnable) {
+ launchTaskCompleteListeners.add(runnable);
+ }
+
+ @Override
+ public Executor getExecutor() {
+ return env.getExecutor();
+ }
+
+ @Nullable
+ @Override
+ public Integer getUserId(IDevice device) {
+ return null;
+ }
+
+ @Override
+ public String getAmStartOptions() {
+ return "";
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/testrecorder/TestRecorderBlazeCommandRunConfigurationProxy.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/testrecorder/TestRecorderBlazeCommandRunConfigurationProxy.java
new file mode 100644
index 00000000000..1a7f9a4f621
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/run/testrecorder/TestRecorderBlazeCommandRunConfigurationProxy.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.idea.blaze.android.run.testrecorder;
+
+import com.android.annotations.Nullable;
+import com.android.ddmlib.IDevice;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidRunConfigurationRunner;
+import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import java.util.List;
+
+/** Compat class for implementing TestRecorderBlazeCommandRunConfigurationProxy. */
+public class TestRecorderBlazeCommandRunConfigurationProxy
+ extends TestRecorderBlazeCommandRunConfigurationProxyBase {
+
+ public TestRecorderBlazeCommandRunConfigurationProxy(
+ BlazeCommandRunConfiguration baseConfiguration) {
+ super(baseConfiguration);
+ }
+
+ @Override
+ @Nullable
+ public List> getDeviceFutures(ExecutionEnvironment environment) {
+ return environment
+ .getCopyableUserData(BlazeAndroidRunConfigurationRunner.DEVICE_SESSION_KEY)
+ .deviceFutures
+ .get();
+ }
+}
diff --git a/aswb/sdkcompat/as231/com/google/idea/blaze/android/sync/model/idea/BlazeAndroidModel.java b/aswb/sdkcompat/as231/com/google/idea/blaze/android/sync/model/idea/BlazeAndroidModel.java
new file mode 100644
index 00000000000..3049cdd0eff
--- /dev/null
+++ b/aswb/sdkcompat/as231/com/google/idea/blaze/android/sync/model/idea/BlazeAndroidModel.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 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.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;
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/META-INF/aswb.xml b/aswb/sdkcompat/as232/com/META-INF/aswb.xml
new file mode 100644
index 00000000000..fa5c9754f9e
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/META-INF/aswb.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
diff --git a/aswb/sdkcompat/as232/com/android/tools/configurations/ConfigurationCompat.java b/aswb/sdkcompat/as232/com/android/tools/configurations/ConfigurationCompat.java
new file mode 100644
index 00000000000..3d51e831ad7
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/android/tools/configurations/ConfigurationCompat.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.configurations;
+
+import com.android.sdklib.devices.Device;
+
+/** Compat class for Configuration. */
+public class ConfigurationCompat {
+
+ private Configuration configuration;
+
+ public ConfigurationCompat(Configuration configuration) {
+ this.configuration = configuration;
+ }
+
+ public void setDevice(Device device, boolean preserveState) {
+ configuration.setDevice(device, preserveState);
+ }
+}
diff --git a/aswb/sdkcompat/as213/com/android/tools/idea/model/AndroidManifestIndexCompat.java b/aswb/sdkcompat/as232/com/android/tools/idea/model/AndroidManifestIndexCompat.java
similarity index 100%
rename from aswb/sdkcompat/as213/com/android/tools/idea/model/AndroidManifestIndexCompat.java
rename to aswb/sdkcompat/as232/com/android/tools/idea/model/AndroidManifestIndexCompat.java
diff --git a/aswb/sdkcompat/as213/com/android/tools/idea/progress/StudioLoggerProgressIndicatorCompat.java b/aswb/sdkcompat/as232/com/android/tools/idea/progress/StudioLoggerProgressIndicatorCompat.java
similarity index 100%
rename from aswb/sdkcompat/as213/com/android/tools/idea/progress/StudioLoggerProgressIndicatorCompat.java
rename to aswb/sdkcompat/as232/com/android/tools/idea/progress/StudioLoggerProgressIndicatorCompat.java
diff --git a/aswb/sdkcompat/as232/com/android/tools/idea/rendering/RenderErrorContributorCompat.java b/aswb/sdkcompat/as232/com/android/tools/idea/rendering/RenderErrorContributorCompat.java
new file mode 100644
index 00000000000..bd5059f8cc3
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/android/tools/idea/rendering/RenderErrorContributorCompat.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.idea.rendering;
+
+import com.android.tools.idea.ui.designer.EditorDesignSurface;
+import com.android.tools.rendering.RenderResultCompat;
+import com.intellij.openapi.actionSystem.DataContext;
+import groovyjarjarantlr4.v4.runtime.misc.Nullable;
+
+/** Contribute blaze specific render errors. */
+public class RenderErrorContributorCompat extends RenderErrorContributorImpl {
+ public RenderErrorContributorCompat(
+ EditorDesignSurface surface, RenderResultCompat result, @Nullable DataContext dataContext) {
+ super(surface, result.get());
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/android/tools/idea/run/tasks/DeployTasksCompat.java b/aswb/sdkcompat/as232/com/android/tools/idea/run/tasks/DeployTasksCompat.java
new file mode 100644
index 00000000000..ce440ca9d52
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/android/tools/idea/run/tasks/DeployTasksCompat.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.android.tools.idea.run.tasks;
+
+import com.android.tools.deployer.DeployerException;
+import com.android.tools.idea.execution.common.AndroidExecutionException;
+import com.android.tools.idea.execution.common.DeployOptions;
+import com.android.tools.idea.run.ApkInfo;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.google.idea.common.experiments.BoolExperiment;
+import com.intellij.openapi.project.Project;
+import java.util.Collection;
+import java.util.List;
+
+/** Compat class for {@link DeployTask} */
+public class DeployTasksCompat {
+ private static final BoolExperiment updateCodeViaJvmti =
+ new BoolExperiment("android.apply.changes", false);
+
+ private DeployTasksCompat() {}
+
+ public static BlazeLaunchTask createDeployTask(
+ Project project, Collection packages, DeployOptions deployOptions) {
+ return launchContext -> {
+ try {
+ List unused =
+ new DeployTask(
+ project,
+ packages,
+ deployOptions.getPmInstallFlags(),
+ deployOptions.getInstallOnAllUsers(),
+ deployOptions.getAlwaysInstallWithPm())
+ .run(launchContext.getDevice(), launchContext.getProgressIndicator());
+ } catch (DeployerException e) {
+ throw new AndroidExecutionException(e.getId(), e.getMessage());
+ }
+ };
+ }
+}
+
diff --git a/aswb/sdkcompat/as232/com/android/tools/rendering/HtmlLinkManagerCompat.java b/aswb/sdkcompat/as232/com/android/tools/rendering/HtmlLinkManagerCompat.java
new file mode 100644
index 00000000000..28ca9471258
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/android/tools/rendering/HtmlLinkManagerCompat.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.rendering;
+
+import java.io.File;
+import org.jetbrains.annotations.NotNull;
+
+/** Compat class for {@link HtmlLinkManager} */
+public final class HtmlLinkManagerCompat {
+ public static String createFilePositionUrl(@NotNull File file, int line, int column) {
+ return HtmlLinkManager.createFilePositionUrl(file, line, column);
+ }
+
+ private HtmlLinkManagerCompat() {}
+}
diff --git a/aswb/sdkcompat/as232/com/android/tools/rendering/RenderLoggerCompat.java b/aswb/sdkcompat/as232/com/android/tools/rendering/RenderLoggerCompat.java
new file mode 100644
index 00000000000..96af24f48d3
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/android/tools/rendering/RenderLoggerCompat.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.rendering;
+
+import java.util.Map;
+import java.util.Set;
+
+/** Compat class for RenderLogger. */
+public class RenderLoggerCompat {
+ private final RenderLogger renderLogger;
+
+ public RenderLoggerCompat(RenderResultCompat result) {
+ renderLogger = result.getLogger();
+ }
+
+ public RenderLogger get() {
+ return renderLogger;
+ }
+
+ public boolean hasErrors() {
+ return renderLogger.hasErrors();
+ }
+
+ public Map getBrokenClasses() {
+ return renderLogger.getBrokenClasses();
+ }
+
+ public Set getMissingClasses() {
+ return renderLogger.getMissingClasses();
+ }
+
+ public static void resetFidelityErrorsFilters() {
+ RenderLogger.resetFidelityErrorsFilters();
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/android/tools/rendering/RenderResultCompat.java b/aswb/sdkcompat/as232/com/android/tools/rendering/RenderResultCompat.java
new file mode 100644
index 00000000000..6cb43bf3def
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/android/tools/rendering/RenderResultCompat.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.rendering;
+
+import com.android.ide.common.rendering.api.Result;
+import com.android.tools.idea.rendering.RenderErrorContributor;
+import com.android.tools.idea.rendering.RenderErrorContributorImpl;
+import com.android.tools.idea.rendering.RenderErrorModelFactory;
+import com.android.tools.idea.rendering.RenderResults;
+import com.android.tools.idea.rendering.errors.ui.RenderErrorModel;
+import com.android.tools.idea.ui.designer.EditorDesignSurface;
+import com.android.tools.rendering.imagepool.ImagePool.Image;
+import com.google.idea.blaze.android.rendering.BlazeRenderErrorContributor;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.Nullable;
+
+/** Compat class for {@link RenderResult} */
+public final class RenderResultCompat {
+ private RenderResult result;
+
+ public RenderResultCompat(RenderResult result) {
+ this.result = result;
+ }
+
+ public static RenderResultCompat createBlank(PsiFile file) {
+ return new RenderResultCompat(RenderResults.createBlank(file));
+ }
+
+ public RenderErrorModel createErrorModel() {
+ return RenderErrorModelFactory.createErrorModel(null, result);
+ }
+
+ public RenderResult get() {
+ return result;
+ }
+
+ public RenderLogger getLogger() {
+ return result.getLogger();
+ }
+
+ public Module getModule() {
+ return result.getModule();
+ }
+
+ public Result getRenderResult() {
+ return result.getRenderResult();
+ }
+
+ public Image getRenderedImage() {
+ return result.getRenderedImage();
+ }
+
+ private RenderResultCompat() {}
+
+ /** Extension to provide {@link BlazeRenderErrorContributor}. */
+ public static class BlazeProvider extends RenderErrorContributorImpl.Provider {
+ @Override
+ public boolean isApplicable(Project project) {
+ return Blaze.isBlazeProject(project);
+ }
+
+ @Override
+ public RenderErrorContributor getContributor(
+ @Nullable EditorDesignSurface surface, RenderResult result) {
+ return new BlazeRenderErrorContributor(surface, result);
+ }
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/android/tools/rendering/RenderServiceCompat.java b/aswb/sdkcompat/as232/com/android/tools/rendering/RenderServiceCompat.java
new file mode 100644
index 00000000000..de22b6df36d
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/android/tools/rendering/RenderServiceCompat.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.rendering;
+
+/** Compat class for {@link RenderService} */
+public class RenderServiceCompat {
+ public static void shutdownRenderExecutor(long l) {
+ RenderService.shutdownRenderExecutor(l);
+ }
+
+ public static void initializeRenderExecutor() {
+ RenderService.initializeRenderExecutor();
+ }
+}
diff --git a/aswb/sdkcompat/as212/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java
similarity index 63%
rename from aswb/sdkcompat/as212/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java
rename to aswb/sdkcompat/as232/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java
index 64931a9101e..08f03d50d8f 100644
--- a/aswb/sdkcompat/as212/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/cppimpl/debug/BlazeAutoAndroidDebugger.java
@@ -16,18 +16,26 @@
package com.google.idea.blaze.android.cppimpl.debug;
import com.android.ddmlib.Client;
-import com.intellij.execution.configurations.RunConfiguration;
+import com.android.ddmlib.ClientData;
import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XDebugSession;
+import org.jetbrains.annotations.NotNull;
/** Shim for #api212 compat. */
public class BlazeAutoAndroidDebugger extends BlazeAutoAndroidDebuggerBase {
+
@Override
- public void attachToClient(Project project, Client client, RunConfiguration config) {
+ public XDebugSession getExistingDebugSession(@NotNull Project project, @NotNull Client client) {
if (isNativeProject(project)) {
- log.info("Project has native development enabled. Attaching native debugger.");
- nativeDebugger.attachToClient(project, client, config);
+ log.info("Project has native development enabled");
+ return nativeDebugger.getExistingDebugSession(project, client);
} else {
- super.attachToClient(project, client, config);
+ return super.getExistingDebugSession(project, client);
}
}
+
+ @Override
+ protected boolean isNativeDeployment(Project project, ClientData clientData) {
+ return isNativeProject(project);
+ }
}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebugger.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebugger.java
new file mode 100644
index 00000000000..e92afddc27c
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebugger.java
@@ -0,0 +1,28 @@
+/*
+ * 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.cppimpl.debug;
+
+/**
+ * API compat of {@link BlazeNativeAndroidDebuggerBase} with the following additions:
+ *
+ *
+ * - Creates a run-config setting using {@link BlazeAndroidNativeAttachConfiguration} instead of
+ * {@link AndroidNativeAttachConfiguration} to override counterproductive validations.
+ *
+ *
+ * #api4.0
+ */
+public class BlazeNativeAndroidDebugger extends BlazeNativeAndroidDebuggerBase {}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebuggerBase.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebuggerBase.java
new file mode 100644
index 00000000000..e9ba5c444c5
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeAndroidDebuggerBase.java
@@ -0,0 +1,78 @@
+/*
+ * 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.cppimpl.debug;
+
+import com.android.ddmlib.Client;
+import com.android.tools.idea.projectsystem.ApplicationProjectContext;
+import com.android.tools.ndk.run.editor.NativeAndroidDebugger;
+import com.android.tools.ndk.run.editor.NativeAndroidDebuggerState;
+import com.google.idea.blaze.base.model.BlazeProjectData;
+import com.google.idea.blaze.base.model.primitives.LanguageClass;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XDebugProcessStarter;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Extension of {@link NativeAndroidDebugger} with the following key differences compared to {@link
+ * NativeAndroidDebugger}.
+ *
+ *
+ * - Overrides {@link #supportsProject} so native debugger is only enabled for native support is
+ * enabled.
+ *
+ */
+public class BlazeNativeAndroidDebuggerBase extends NativeAndroidDebugger {
+ /**
+ * This ID needs to be lexicographically larger than "Java" so it come after the "Java" debugger
+ * when sorted lexicographically in the "Attach Debugger to Android Process" dialog. See {@link
+ * org.jetbrains.android.actions.AndroidProcessChooserDialog#populateDebuggerTypeCombo}.
+ */
+ public static final String ID = "Native" + Blaze.defaultBuildSystemName();
+
+ @Override
+ public String getId() {
+ return ID;
+ }
+
+ @Override
+ public String getDisplayName() {
+ return "Native Only";
+ }
+
+ @Override
+ public boolean supportsProject(Project project) {
+ BlazeProjectData blazeProjectData =
+ BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
+ return blazeProjectData != null
+ && blazeProjectData.getWorkspaceLanguageSettings().isLanguageActive(LanguageClass.C);
+ }
+
+ @Override
+ public XDebugProcessStarter getDebugProcessStarterForExistingProcess(
+ @NotNull Project project,
+ @NotNull Client client,
+ ApplicationProjectContext applicationContext,
+ @Nullable NativeAndroidDebuggerState state) {
+ if (state != null) {
+ BlazeNativeDebuggerStateSourceMapping.addSourceMapping(project, state);
+ }
+ return super.getDebugProcessStarterForExistingProcess(
+ project, client, applicationContext, state);
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeDebuggerStateSourceMapping.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeDebuggerStateSourceMapping.java
new file mode 100644
index 00000000000..640e5f82075
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/cppimpl/debug/BlazeNativeDebuggerStateSourceMapping.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 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.cppimpl.debug;
+
+import com.android.tools.ndk.run.editor.NativeAndroidDebuggerState;
+import com.google.common.collect.ImmutableList;
+import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+
+/** Maps source directory when attaching to a process */
+public class BlazeNativeDebuggerStateSourceMapping {
+ public static void addSourceMapping(
+ @NotNull Project project, @NotNull NativeAndroidDebuggerState state) {
+ // Source code is always relative to the workspace root in a blaze project.
+ String workingDirPath = WorkspaceRoot.fromProject(project).directory().getPath();
+ state.setWorkingDir(workingDirPath);
+
+ // Remote built binaries may use /proc/self/cwd to represent the working directory
+ // so we manually map /proc/self/cwd to the workspace root. We used to use
+ // `plugin.symbol-file.dwarf.comp-dir-symlink-paths = "/proc/self/cwd"`
+ // to automatically resolve this but it's no longer supported in newer versions of
+ // LLDB.
+ String sourceMapToWorkspaceRootCommand =
+ "settings append target.source-map /proc/self/cwd " + workingDirPath;
+ ImmutableList startupCommands =
+ ImmutableList.builder()
+ .addAll(state.getUserStartupCommands())
+ .add(sourceMapToWorkspaceRootCommand)
+ .build();
+ state.setUserStartupCommands(startupCommands);
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeAddDestinationMenuToken.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeAddDestinationMenuToken.java
new file mode 100644
index 00000000000..e74aa02a7d2
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeAddDestinationMenuToken.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 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 static com.android.tools.idea.util.DependencyManagementUtil.addDependenciesWithUiConfirmation;
+import static com.android.tools.idea.util.DependencyManagementUtil.dependsOn;
+
+import com.android.ide.common.repository.GoogleMavenArtifactId;
+import com.android.tools.idea.common.model.NlModel;
+import com.android.tools.idea.naveditor.editor.AddDestinationMenuToken;
+import com.intellij.openapi.module.Module;
+import java.util.List;
+import org.jetbrains.annotations.NotNull;
+
+/** Blaze implementation of project system tokens for the navigation editor: Add Destination Menu */
+public class BlazeAddDestinationMenuToken
+ implements AddDestinationMenuToken, BlazeToken {
+ @Override
+ public void modifyProject(
+ @NotNull BlazeProjectSystem projectSystem, @NotNull AddDestinationMenuToken.Data data) {
+ NlModel model = data.getSurface().getModel();
+ if (model == null) {
+ return;
+ }
+ Module module = model.getModule();
+ if (dependsOn(module, GoogleMavenArtifactId.ANDROIDX_NAVIGATION_DYNAMIC_FEATURES_FRAGMENT)) {
+ return;
+ }
+ final var unused =
+ addDependenciesWithUiConfirmation(
+ module,
+ List.of(
+ GoogleMavenArtifactId.ANDROIDX_NAVIGATION_DYNAMIC_FEATURES_FRAGMENT.getCoordinate(
+ "+")),
+ true,
+ false);
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeModuleDependencies.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeModuleDependencies.java
new file mode 100644
index 00000000000..72a158468e6
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeModuleDependencies.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2024 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 static com.google.common.collect.ImmutableList.toImmutableList;
+
+import com.android.ide.common.repository.GoogleMavenArtifactId;
+import com.android.projectmodel.ExternalAndroidLibrary;
+import com.android.tools.idea.projectsystem.DependencyScopeType;
+import com.android.tools.module.ModuleDependencies;
+import com.google.common.collect.ImmutableList;
+import com.google.idea.blaze.android.resources.BlazeLightResourceClassService;
+import com.intellij.openapi.module.Module;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiClass;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Predicate;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/** ASwB specific implementation of [ModuleDependencies]. */
+public class BlazeModuleDependencies implements ModuleDependencies {
+
+ Module module;
+
+ BlazeModuleDependencies(Module module) {
+ this.module = module;
+ }
+
+ @Override
+ public boolean dependsOn(@NotNull GoogleMavenArtifactId googleMavenArtifactId) {
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public PsiClass findPsiClassInModuleAndDependencies(@NotNull String fqcn) {
+ JavaPsiFacade facade = JavaPsiFacade.getInstance(module.getProject());
+ return facade.findClass(fqcn, module.getModuleWithDependenciesAndLibrariesScope(false));
+ }
+
+ /**
+ * Fetches the resource packages within the project and from external dependencies. Input
+ * parameter includeExternalLibraries is ignored as ASwB/Blaze uses a single workspace module to
+ * map both types of resources.
+ */
+ @NotNull
+ @Override
+ public List getResourcePackageNames(boolean includeExternalLibraries) {
+ // TODO(b/304821496): Add an integration test to test it similar to BuildDependenciesTest
+ // TODO(b/307604153): Update AndroidExternalLibraryManager to read package name from multiple
+ // locations
+ return ImmutableList.builder()
+ .addAll(
+ BlazeModuleSystem.getInstance(module)
+ .getAndroidLibraryDependencies(DependencyScopeType.MAIN)
+ .stream()
+ .map(ExternalAndroidLibrary::getPackageName)
+ .filter(Objects::nonNull)
+ .filter(Predicate.not(String::isEmpty))
+ .collect(toImmutableList()))
+ .addAll(
+ BlazeLightResourceClassService.getInstance(module.getProject())
+ .getWorkspaceResourcePackages())
+ .build();
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java
new file mode 100644
index 00000000000..2c64e2c2b32
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java
@@ -0,0 +1,78 @@
+/*
+ * 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 static com.google.common.collect.ImmutableList.toImmutableList;
+
+import com.android.tools.idea.projectsystem.AndroidModuleSystem;
+import com.android.tools.module.ModuleDependencies;
+import com.google.common.collect.ImmutableList;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.targetmaps.SourceToTargetMap;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.vfs.VirtualFile;
+import java.io.File;
+import java.nio.file.Path;
+
+/** Blaze implementation of {@link AndroidModuleSystem}. */
+public class BlazeModuleSystem extends BlazeModuleSystemBase {
+
+ BlazeModuleSystem(Module module) {
+ super(module);
+ }
+
+ @Override
+ public ModuleDependencies getModuleDependencies() {
+ return new BlazeModuleDependencies(getModule());
+ }
+
+ public String blazeTargetNameToKotlinModuleName(String blazeTargetName) {
+ // Before: //third_party/java_src/android_app/compose_samples/Rally:lib
+ // After: third_party_java_src_android_app_compose_samples_Rally_lib
+ assert blazeTargetName.substring(0, 2).equals("//");
+ return blazeTargetName.substring(2).replaceAll("['/',':']", "_");
+ }
+
+ @Override
+ public String getModuleNameForCompilation(VirtualFile virtualFile) {
+ String moduleName =
+ blazeTargetNameToKotlinModuleName(
+ SourceToTargetMap.getInstance(project)
+ .getTargetsToBuildForSourceFile(new File(virtualFile.getPath()))
+ .get(0) // use the first target
+ .toString());
+ return moduleName;
+ }
+
+ /** Check every supporting extension point if they contain desugaring library config files */
+ @Override
+ public boolean getDesugarLibraryConfigFilesKnown() {
+ return DesugaringLibraryConfigFilesLocator.forBuildSystem(
+ Blaze.getBuildSystemName(module.getProject()))
+ .stream()
+ .anyMatch(provider -> provider.getDesugarLibraryConfigFilesKnown());
+ }
+
+ /** Collect desugarig library config files from every supporting extension and return the list */
+ @Override
+ public ImmutableList getDesugarLibraryConfigFiles() {
+ return DesugaringLibraryConfigFilesLocator.forBuildSystem(
+ Blaze.getBuildSystemName(module.getProject()))
+ .stream()
+ .flatMap(provider -> provider.getDesugarLibraryConfigFiles(project).stream())
+ .collect(toImmutableList());
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeNavDesignSurfaceToken.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeNavDesignSurfaceToken.java
new file mode 100644
index 00000000000..80e8b353b01
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeNavDesignSurfaceToken.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 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 static com.android.tools.idea.util.DependencyManagementUtil.addDependenciesWithUiConfirmation;
+import static com.google.common.collect.ImmutableList.toImmutableList;
+
+import com.android.ide.common.repository.GradleCoordinate;
+import com.android.tools.idea.common.model.NlModel;
+import com.android.tools.idea.naveditor.surface.NavDesignSurface;
+import com.android.tools.idea.naveditor.surface.NavDesignSurfaceToken;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.jetbrains.annotations.NotNull;
+
+/** Blaze implementation of project system tokens for the navigation editor: Nav Design Surface */
+class BlazeNavDesignSurfaceToken implements NavDesignSurfaceToken, BlazeToken {
+ @Override
+ public boolean modifyProject(@NotNull BlazeProjectSystem projectSystem, @NotNull NlModel model) {
+ AtomicBoolean didAdd = new AtomicBoolean(false);
+ Module module = model.getModule();
+ List coordinates =
+ NavDesignSurface.getDependencies(module).stream()
+ .map((a) -> a.getCoordinate("+"))
+ .collect(toImmutableList());
+ Runnable runnable =
+ () -> {
+ try {
+ didAdd.set(
+ addDependenciesWithUiConfirmation(module, coordinates, true, false).isEmpty());
+ } catch (Throwable t) {
+ Logger.getInstance(NavDesignSurface.class).warn("Failed to add dependencies", t);
+ didAdd.set(false);
+ }
+ };
+ ApplicationManager.getApplication().invokeAndWait(runnable);
+ return didAdd.get();
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeProjectSystem.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeProjectSystem.java
new file mode 100644
index 00000000000..eec76246653
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeProjectSystem.java
@@ -0,0 +1,291 @@
+/*
+ * 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.blaze.android.projectsystem;
+
+import static com.android.tools.idea.projectsystem.SourceProvidersKt.emptySourceProvider;
+import static com.google.idea.blaze.base.sync.data.BlazeDataStorage.WORKSPACE_MODULE_NAME;
+import static org.jetbrains.android.facet.SourceProviderUtil.createSourceProvidersForLegacyModule;
+
+import com.android.tools.apk.analyzer.AaptInvoker;
+import com.android.tools.idea.log.LogWrapper;
+import com.android.tools.idea.model.AndroidModel;
+import com.android.tools.idea.model.ClassJarProvider;
+import com.android.tools.idea.projectsystem.AndroidProjectSystem;
+import com.android.tools.idea.projectsystem.NamedIdeaSourceProvider;
+import com.android.tools.idea.projectsystem.ProjectSystemBuildManager;
+import com.android.tools.idea.projectsystem.ProjectSystemSyncManager;
+import com.android.tools.idea.projectsystem.ScopeType;
+import com.android.tools.idea.projectsystem.SourceProviderManager;
+import com.android.tools.idea.projectsystem.SourceProviders;
+import com.android.tools.idea.projectsystem.SourceProvidersFactory;
+import com.android.tools.idea.projectsystem.SourceProvidersImpl;
+import com.android.tools.idea.res.AndroidInnerClassFinder;
+import com.android.tools.idea.res.AndroidResourceClassPsiElementFinder;
+import com.android.tools.idea.sdk.AndroidSdks;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.idea.blaze.android.resources.BlazeLightResourceClassService;
+import com.google.idea.blaze.android.sync.model.idea.BlazeAndroidModel;
+import com.google.idea.blaze.android.sync.model.idea.BlazeClassJarProvider;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.settings.BlazeImportSettings.ProjectType;
+import com.intellij.facet.ProjectFacetManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElementFinder;
+import com.intellij.psi.search.GlobalSearchScope;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+import org.jetbrains.android.facet.AndroidFacet;
+import org.jetbrains.android.sdk.AndroidPlatforms;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Base class to implement common methods in {@link AndroidProjectSystem} for blaze with different
+ * sdk
+ */
+public class BlazeProjectSystem implements AndroidProjectSystem {
+ protected final Project project;
+ protected final ProjectSystemSyncManager syncManager;
+ protected final List myFinders;
+ private final BlazeProjectSystemBuildManager buildManager;
+
+ public BlazeProjectSystem(Project project) {
+ this.project = project;
+ syncManager = new BlazeProjectSystemSyncManager(project);
+ buildManager = new BlazeProjectSystemBuildManager(project);
+
+ myFinders =
+ Arrays.asList(
+ AndroidInnerClassFinder.INSTANCE,
+ new AndroidResourceClassPsiElementFinder(getLightResourceClassService()));
+ }
+
+ @Override
+ public Project getProject() {
+ return project;
+ }
+
+ @Override
+ public boolean allowsFileCreation() {
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public VirtualFile getDefaultApkFile() {
+ return null;
+ }
+
+ @Override
+ public Path getPathToAapt() {
+ return AaptInvoker.getPathToAapt(
+ AndroidSdks.getInstance().tryToChooseSdkHandler(),
+ new LogWrapper(BlazeProjectSystem.class));
+ }
+
+ @Override
+ public ProjectSystemBuildManager getBuildManager() {
+ return buildManager;
+ }
+
+ @Override
+ public BlazeModuleSystem getModuleSystem(Module module) {
+ return BlazeModuleSystem.getInstance(module);
+ }
+
+ @Override
+ public ProjectSystemSyncManager getSyncManager() {
+ return syncManager;
+ }
+
+ @Override
+ public Collection getPsiElementFinders() {
+ return myFinders;
+ }
+
+ @Override
+ public BlazeLightResourceClassService getLightResourceClassService() {
+ return BlazeLightResourceClassService.getInstance(project);
+ }
+
+ @Override
+ public SourceProvidersFactory getSourceProvidersFactory() {
+ return new SourceProvidersFactory() {
+ @Override
+ public SourceProviders createSourceProvidersFor(AndroidFacet facet) {
+ BlazeAndroidModel model = ((BlazeAndroidModel) AndroidModel.get(facet));
+ if (model != null) {
+ return createForModel(model);
+ } else {
+ return createSourceProvidersForLegacyModule(facet);
+ }
+ }
+
+ private SourceProviders createForModel(BlazeAndroidModel model) {
+ NamedIdeaSourceProvider mainSourceProvider = model.getDefaultSourceProvider();
+ if (Blaze.getProjectType(project).equals(ProjectType.QUERY_SYNC)) {
+ return new SourceProvidersImpl(
+ mainSourceProvider,
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(),
+ ImmutableList.of(),
+ ImmutableList.of(),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ emptySourceProvider(ScopeType.MAIN),
+ emptySourceProvider(ScopeType.UNIT_TEST),
+ emptySourceProvider(ScopeType.ANDROID_TEST),
+ emptySourceProvider(ScopeType.TEST_FIXTURES));
+ } else {
+ return new SourceProvidersImpl(
+ mainSourceProvider,
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ ImmutableList.of(mainSourceProvider),
+ emptySourceProvider(ScopeType.MAIN),
+ emptySourceProvider(ScopeType.UNIT_TEST),
+ emptySourceProvider(ScopeType.ANDROID_TEST),
+ emptySourceProvider(ScopeType.TEST_FIXTURES));
+ }
+ }
+ };
+ }
+
+ @Override
+ public ClassJarProvider getClassJarProvider() {
+ return new BlazeClassJarProvider(project);
+ }
+
+ @Override
+ public Collection getAndroidFacetsWithPackageName(
+ Project project, String packageName) {
+ return getAndroidFacetsWithPackageName(
+ project, packageName, GlobalSearchScope.projectScope(project));
+ }
+
+ private Collection getAndroidFacetsWithPackageName(
+ Project project, String packageName, GlobalSearchScope scope) {
+ List facets = ProjectFacetManager.getInstance(project).getFacets(AndroidFacet.ID);
+ return facets.stream()
+ .filter(facet -> hasPackageName(facet, packageName))
+ .filter(
+ facet -> {
+ VirtualFile file = SourceProviderManager.getInstance(facet).getMainManifestFile();
+ if (file == null) {
+ return false;
+ } else {
+ return scope.contains(file);
+ }
+ })
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public boolean isNamespaceOrParentPackage(@NotNull String packageName) {
+ List facets = ProjectFacetManager.getInstance(project).getFacets(AndroidFacet.ID);
+ GlobalSearchScope scope = GlobalSearchScope.projectScope(project);
+ for (AndroidFacet facet : facets) {
+ String moduleNamespace = PackageNameUtils.getPackageName(facet.getModule());
+ if (moduleNamespace == null) {
+ continue;
+ }
+ // Check if the moduleNamespace is exactly the package name, or is a subpackage
+ if (!moduleNamespace.startsWith(packageName)) {
+ continue;
+ }
+ // packageName=com.example should not match moduleNamespace=com.example2
+ if (moduleNamespace.length() > packageName.length()
+ && moduleNamespace.charAt(packageName.length()) != '.') {
+ continue;
+ }
+ VirtualFile file = SourceProviderManager.getInstance(facet).getMainManifestFile();
+ if (file == null || !scope.contains(file)) {
+ continue;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @NotNull
+ @Override
+ public Set getKnownApplicationIds() {
+ List facets = ProjectFacetManager.getInstance(project).getFacets(AndroidFacet.ID);
+ Set applicationIds = new HashSet<>(facets.size());
+ for (AndroidFacet facet : facets) {
+ AndroidModel model = AndroidModel.get(facet);
+ if (model == null) {
+ continue;
+ }
+ applicationIds.addAll(model.getAllApplicationIds());
+ }
+ return Collections.unmodifiableSet(applicationIds);
+ }
+
+ @NotNull
+ @Override
+ public Collection findModulesWithApplicationId(@NotNull String applicationId) {
+ if (Blaze.getProjectType(project).equals(ProjectType.QUERY_SYNC)) {
+ Module workspaceModule =
+ ModuleManager.getInstance(project).findModuleByName(WORKSPACE_MODULE_NAME);
+ if (workspaceModule != null) {
+ return ImmutableList.of(workspaceModule);
+ } else {
+ return ImmutableList.of();
+ }
+ }
+ List facets = ProjectFacetManager.getInstance(project).getFacets(AndroidFacet.ID);
+ ImmutableSet.Builder resultBuilder = ImmutableSet.builder();
+ for (AndroidFacet facet : facets) {
+ AndroidModel model = AndroidModel.get(facet);
+ if (model != null && model.getApplicationId().equals(applicationId)) {
+ resultBuilder.add(facet.getModule());
+ }
+ }
+ return resultBuilder.build();
+ }
+
+ @Override
+ public Collection getSubmodules() {
+ return ImmutableList.of();
+ }
+
+ @Override
+ public Collection getBootClasspath(@NotNull Module module) {
+ return AndroidPlatforms.getInstance(module).getTarget().getBootClasspath();
+ }
+
+ private static boolean hasPackageName(AndroidFacet facet, String packageName) {
+ String nameFromFacet = PackageNameUtils.getPackageName(facet.getModule());
+ if (nameFromFacet == null) {
+ return false;
+ }
+ return nameFromFacet.equals(packageName);
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeToken.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeToken.java
new file mode 100644
index 00000000000..d9a4b21a732
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/BlazeToken.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.idea.blaze.android.projectsystem;
+
+import com.android.tools.idea.projectsystem.AndroidProjectSystem;
+import com.android.tools.idea.projectsystem.Token;
+
+/** A mix-in implementation of the {@link Token} interface for the Blaze project system. */
+public interface BlazeToken extends Token {
+ @Override
+ default boolean isApplicable(AndroidProjectSystem projectSystem) {
+ return projectSystem instanceof BlazeProjectSystem;
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java
new file mode 100644
index 00000000000..0967d9fc40c
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java
@@ -0,0 +1,300 @@
+/*
+ * 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 static java.util.stream.Collectors.joining;
+
+import com.android.tools.idea.projectsystem.ClassContent;
+import com.android.tools.idea.projectsystem.ClassFileFinder;
+import com.android.tools.idea.projectsystem.ClassFileFinderUtil;
+import com.android.tools.idea.rendering.classloading.loaders.JarManager;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableSet;
+import com.google.idea.blaze.android.libraries.RenderJarCache;
+import com.google.idea.blaze.android.sync.model.AndroidResourceModule;
+import com.google.idea.blaze.android.sync.model.AndroidResourceModuleRegistry;
+import com.google.idea.blaze.android.targetmaps.TargetToBinaryMap;
+import com.google.idea.blaze.base.ideinfo.TargetIdeInfo;
+import com.google.idea.blaze.base.ideinfo.TargetKey;
+import com.google.idea.blaze.base.model.BlazeProjectData;
+import com.google.idea.blaze.base.qsync.QuerySync;
+import com.google.idea.blaze.base.qsync.QuerySyncManager;
+import com.google.idea.blaze.base.qsync.RenderJarArtifactTracker;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.settings.BlazeImportSettings.ProjectType;
+import com.google.idea.blaze.base.sync.BlazeSyncModificationTracker;
+import com.google.idea.blaze.base.sync.data.BlazeDataStorage;
+import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
+import com.google.idea.common.experiments.BoolExperiment;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.regex.Pattern;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * A {@link ClassFileFinder} that uses deploy JAR like artifacts (called render jar henceforth) for
+ * class files.
+ *
+ * The render JAR contains all runtime dependencies of a binary target.
+ *
+ *
The Blaze targets that go into creating a resource module is known. Consequently, it is
+ * possible to determine which binaries in the projectview depend on the resource declaring blaze
+ * targets that constitutes the module. This class calculates the binary targets and attempts to
+ * find classes from the render JARs.
+ *
+ *
This only works for resource modules (i.e. not the .workspace module). For .workspace module,
+ * we try to find the class in all binary targets in projectview
+ *
+ *
NOTE: Blaze targets that constitutes the resource module will be called "resource target(s)"
+ * in comments below.
+ */
+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.3", true);
+
+ /**
+ * Experiment to toggle whether resource resolution is allowed from Render JARs. Render JARs
+ * should not resolve resources by default.
+ */
+ @VisibleForTesting
+ static final BoolExperiment resolveResourceClasses =
+ new BoolExperiment("aswb.resolve.resources.render.jar", false);
+
+ private static final Logger log = Logger.getInstance(RenderJarClassFileFinder.class);
+
+ private static final String INTERNAL_PACKAGE = "_layoutlib_._internal_.";
+
+ // matches foo.bar.R or foo.bar.R$baz
+ private static final Pattern RESOURCE_CLASS_NAME = Pattern.compile(".+\\.R(\\$[^.]+)?$");
+
+ private final Module module;
+ private final Project project;
+
+ // tracks the binary targets that depend resource targets
+ // will be recalculated after every sync
+ private ImmutableSet binaryTargets = ImmutableSet.of();
+
+ // tracks the value of {@link BlazeSyncModificationTracker} when binaryTargets is calculated
+ // binaryTargets is calculated when the value of {@link BlazeSyncModificationTracker} does not
+ // equal lastSyncCount
+ long lastSyncCount = -1;
+
+ // true if the current module is the .workspace Module
+ private final boolean isWorkspaceModule;
+
+ private final JarManager jarManager;
+
+ public RenderJarClassFileFinder(Module module) {
+ this.module = module;
+ this.project = module.getProject();
+ this.isWorkspaceModule = BlazeDataStorage.WORKSPACE_MODULE_NAME.equals(module.getName());
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ this.jarManager = null; // TODO(b/311649275): Mock in tests when made an interface.
+ } else {
+ this.jarManager = JarManager.getInstance(project);
+ }
+ }
+
+ @Nullable
+ @Override
+ public ClassContent findClassFile(@NotNull String fqcn) {
+ if (!isEnabled()) {
+ return null;
+ }
+
+ // Ever since Compose support was introduced in AS, finding class files is invoked during the
+ // normal course of opening an editor. The contract for this method requires that it shouldn't
+ // throw any exceptions, but we've had a few bugs where this method threw an exception, which
+ // resulted in users not being able to open Kotlin files at all. In order to avoid this
+ // scenario, we wrap the underlying call and ensure that no exceptions are thrown.
+ try {
+ return findClassContent(fqcn);
+ } catch (Error e) {
+ log.warn(
+ String.format(
+ "Unexpected error while finding the class file for `%1$s`: %2$s",
+ fqcn, Throwables.getRootCause(e).getMessage()));
+ return null;
+ }
+ }
+
+ @Nullable
+ public ClassContent findClassContent(String fqcn) {
+ // Render JAR should not resolve any resources. All resources should be available to the IDE
+ // through ResourceRepository. Attempting to resolve resources from Render JAR indicates that
+ // ASwB hasn't properly set up resources for the project.
+ if (isResourceClass(fqcn) && !resolveResourceClasses.getValue()) {
+ log.warn(String.format("Attempting to load resource '%s' from RenderJAR.", fqcn));
+ return null;
+ }
+
+ if (Blaze.getProjectType(project).equals(ProjectType.QUERY_SYNC)) {
+ return findClassQuerySync(fqcn);
+ }
+ return findClassLegacySync(fqcn);
+ }
+
+ private ClassContent findClassQuerySync(String fqcn) {
+ if (QuerySync.isComposeEnabled(project)) {
+ RenderJarArtifactTracker renderJarArtifactTracker =
+ QuerySyncManager.getInstance(project).getRenderJarArtifactTracker();
+ // TODO(b/283280194): Setup fqcn -> target and target -> Render jar mappings to avoid
+ // iterating over all render jars when trying to locate class for fqcn.
+ // TODO(b/284002836): Collect metrics on time taken to iterate over the jars
+ for (File renderJar : renderJarArtifactTracker.getRenderJars()) {
+ return findClassInJar(renderJar, fqcn);
+ }
+ return null;
+ }
+ return null;
+ }
+
+ private ClassContent findClassLegacySync(String fqcn) {
+ BlazeProjectData projectData =
+ BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
+ if (projectData == null) {
+ log.warn("Could not find BlazeProjectData for project " + project.getName());
+ return null;
+ }
+
+ ImmutableSet binaryTargets = getBinaryTargets();
+ if (binaryTargets.isEmpty()) {
+ log.warn(
+ String.format(
+ "No binaries for module %s. Adding a binary target to the projectview and resyncing"
+ + " might fix the issue.",
+ module.getName()));
+ return null;
+ }
+
+ // Remove internal package prefix if present
+ fqcn = StringUtil.trimStart(fqcn, INTERNAL_PACKAGE);
+
+ // Look through render resolve JARs of the binaries that depend on the given
+ // androidResourceModule. One androidResourceModule can comprise of multiple resource targets.
+ // The binaries can depend on any subset of these resource targets. Generally, we only
+ // expect one, or a small number of binaries here.
+ for (TargetKey binaryTarget : binaryTargets) {
+ ClassContent classContent = getClassFromRenderResolveJar(projectData, fqcn, binaryTarget);
+ if (classContent != null) {
+ return classContent;
+ }
+ }
+ log.warn(String.format("Could not find class `%1$s` (module: `%2$s`)", fqcn, module.getName()));
+ return null;
+ }
+
+ @VisibleForTesting
+ static boolean isResourceClass(String fqcn) {
+ return RESOURCE_CLASS_NAME.matcher(fqcn).matches();
+ }
+
+ /**
+ * Returns the cached list of binary targets that depend on resource targets. The cache is
+ * recalculated if the project has been synced since last calculation
+ */
+ private ImmutableSet getBinaryTargets() {
+ long currentSyncCount =
+ BlazeSyncModificationTracker.getInstance(project).getModificationCount();
+ if (currentSyncCount == lastSyncCount) {
+ // Return the cached set if there hasn't been a sync since last calculation
+ return binaryTargets;
+ }
+ lastSyncCount = currentSyncCount;
+
+ AndroidResourceModule androidResourceModule =
+ AndroidResourceModuleRegistry.getInstance(project).get(module);
+ if (androidResourceModule != null) {
+ binaryTargets =
+ TargetToBinaryMap.getInstance(project)
+ .getBinariesDependingOn(androidResourceModule.sourceTargetKeys);
+ } else if (isWorkspaceModule) {
+ binaryTargets = TargetToBinaryMap.getInstance(project).getSourceBinaryTargets();
+ } else {
+ binaryTargets = ImmutableSet.of();
+ log.warn("Could not find AndroidResourceModule for " + module.getName());
+ }
+ log.info(
+ String.format(
+ "Binary targets for module `%1$s`: %2$s",
+ module.getName(),
+ binaryTargets.stream()
+ .limit(5)
+ .map(t -> t.getLabel().toString())
+ .collect(joining(", "))));
+ return binaryTargets;
+ }
+
+ /**
+ * Returns class file for fqcn if found in the render JAR corresponding to {@code binaryTarget}.
+ * Returns null if something goes wrong or if render JAR does not contain fqcn
+ */
+ @Nullable
+ private ClassContent getClassFromRenderResolveJar(
+ BlazeProjectData projectData, String fqcn, TargetKey binaryTarget) {
+ TargetIdeInfo ideInfo = projectData.getTargetMap().get(binaryTarget);
+ if (ideInfo == null) {
+ return null;
+ }
+
+ File renderResolveJarFile =
+ RenderJarCache.getInstance(project)
+ .getCachedJarForBinaryTarget(projectData.getArtifactLocationDecoder(), ideInfo);
+
+ if (renderResolveJarFile == null) {
+ return null;
+ }
+
+ return findClassInJar(renderResolveJarFile, fqcn);
+ }
+
+ private ClassContent findClassInJar(File renderResolveJarFile, String fqcn) {
+ String relativePath = ClassFileFinderUtil.getPathFromFqcn(fqcn);
+ final byte[] bytes;
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ try {
+ Path targetPath = renderResolveJarFile.toPath().resolve("!" + relativePath);
+ bytes = Files.isRegularFile(targetPath) ? Files.readAllBytes(targetPath) : new byte[0];
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ } else {
+ bytes =
+ jarManager.loadFileFromJar(
+ renderResolveJarFile.toPath(), ClassFileFinderUtil.getPathFromFqcn(fqcn));
+ }
+ if (bytes == null) {
+ return null;
+ }
+
+ return ClassContent.fromJarEntryContent(renderResolveJarFile, bytes);
+ }
+
+ public static boolean isEnabled() {
+ return enabled.getValue();
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/rendering/BlazeRenderErrorContributor.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/rendering/BlazeRenderErrorContributor.java
new file mode 100644
index 00000000000..ce8b52ff595
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/rendering/BlazeRenderErrorContributor.java
@@ -0,0 +1,442 @@
+/*
+ * 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.rendering;
+
+import static com.android.SdkConstants.ANDROID_MANIFEST_XML;
+import static com.google.common.collect.ImmutableMap.toImmutableMap;
+
+import com.android.tools.idea.rendering.RenderErrorContributor;
+import com.android.tools.idea.rendering.RenderUtils;
+import com.android.tools.idea.rendering.errors.ui.RenderErrorModel;
+import com.android.tools.idea.ui.designer.EditorDesignSurface;
+import com.android.tools.rendering.HtmlLinkManager;
+import com.android.tools.rendering.HtmlLinkManagerCompat;
+import com.android.tools.rendering.RenderLogger;
+import com.android.tools.rendering.RenderResult;
+import com.android.utils.HtmlBuilder;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.Maps;
+import com.google.common.collect.SortedSetMultimap;
+import com.google.common.collect.TreeMultimap;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import com.google.idea.blaze.android.sync.model.AndroidResourceModule;
+import com.google.idea.blaze.android.sync.model.AndroidResourceModuleRegistry;
+import com.google.idea.blaze.base.command.buildresult.OutputArtifactResolver;
+import com.google.idea.blaze.base.ideinfo.AndroidResFolder;
+import com.google.idea.blaze.base.ideinfo.ArtifactLocation;
+import com.google.idea.blaze.base.ideinfo.TargetIdeInfo;
+import com.google.idea.blaze.base.ideinfo.TargetKey;
+import com.google.idea.blaze.base.ideinfo.TargetMap;
+import com.google.idea.blaze.base.lang.buildfile.references.BuildReferenceManager;
+import com.google.idea.blaze.base.model.BlazeProjectData;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.settings.BlazeImportSettings.ProjectType;
+import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
+import com.google.idea.blaze.base.sync.workspace.ArtifactLocationDecoder;
+import com.google.idea.blaze.base.targetmaps.SourceToTargetMap;
+import com.google.idea.blaze.base.targetmaps.TransitiveDependencyMap;
+import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.IndexNotReadyException;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.search.GlobalSearchScope;
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.function.Function;
+import javax.swing.JEditorPane;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+import javax.swing.text.html.HTMLDocument;
+import javax.swing.text.html.HTMLFrameHyperlinkEvent;
+
+/** Contribute blaze specific render errors. */
+public class BlazeRenderErrorContributor implements RenderErrorContributor {
+ private final EditorDesignSurface designSurface;
+ private final RenderLogger logger;
+ private final Module module;
+ private final PsiFile sourceFile;
+ private final Project project;
+ private final HtmlLinkManager linkManager;
+ private final HyperlinkListener linkHandler;
+ private final Set issues = new LinkedHashSet<>();
+
+ public BlazeRenderErrorContributor(EditorDesignSurface surface, RenderResult result) {
+ designSurface = surface;
+ logger = result.getLogger();
+ module = result.getModule();
+ sourceFile = result.getSourceFile();
+ project = module.getProject();
+ linkManager = logger.getLinkManager();
+ linkHandler =
+ e -> {
+ if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+ JEditorPane pane = (JEditorPane) e.getSource();
+ if (e instanceof HTMLFrameHyperlinkEvent) {
+ HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) e;
+ HTMLDocument doc = (HTMLDocument) pane.getDocument();
+ doc.processHTMLFrameHyperlinkEvent(evt);
+ return;
+ }
+
+ performClick(e.getDescription());
+ }
+ };
+ }
+
+ private HtmlLinkManager getLinkManager() {
+ return linkManager;
+ }
+
+ private Collection getIssues() {
+ return Collections.unmodifiableCollection(issues);
+ }
+
+ private RenderErrorModel.Issue.Builder addIssue() {
+ return new RenderErrorModel.Issue.Builder() {
+ @Override
+ public RenderErrorModel.Issue build() {
+ RenderErrorModel.Issue built = super.build();
+ issues.add(built);
+ return built;
+ }
+ }.setLinkHandler(linkHandler);
+ }
+
+ private void performClick(String url) {
+ linkManager.handleUrl(
+ url,
+ module,
+ sourceFile,
+ true,
+ new HtmlLinkManager.RefreshableSurface() {
+ @Override
+ public void handleRefreshRenderUrl() {
+ if (designSurface != null) {
+ // TODO(b/321801969): Remove and replace with direct call when in repo.
+ // Use reflection to getConfigurations() from designSurface. Can't call directly
+ // because it returns an incompatible version of ImmutableCollection.
+ // RenderUtils.clearCache(designSurface.getConfigurations()); would fail at runtime.
+ try {
+ Method getConfigurationsMethod =
+ EditorDesignSurface.class.getMethod("getConfigurations", null);
+ Object configurations = getConfigurationsMethod.invoke(designSurface);
+ Method clearCacheMethod =
+ RenderUtils.class.getMethod(
+ "clearCache", getConfigurationsMethod.getReturnType());
+ clearCacheMethod.invoke(null, configurations);
+ } catch (NoSuchMethodException ex) {
+ throw new RuntimeException(
+ "Error using reflection to get getConfigurations() instance method: " + ex);
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException(
+ "Error accessing getConfigurations() instance method" + ex);
+ } catch (InvocationTargetException ex) {
+ throw new RuntimeException("Error invoking target getConfigurations(): " + ex);
+ }
+ var unused = designSurface.forceUserRequestedRefresh();
+ }
+ }
+
+ @Override
+ public void requestRender() {
+ if (designSurface != null) {
+ var unused = designSurface.forceUserRequestedRefresh();
+ }
+ }
+ });
+ }
+
+ @Override
+ public Collection reportIssues() {
+ BlazeProjectData blazeProjectData =
+ BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
+
+ if (blazeProjectData == null || !logger.hasErrors()) {
+ return getIssues();
+ }
+
+ if (Blaze.getProjectType(project).equals(ProjectType.QUERY_SYNC)) {
+ // TODO(b/284002829): Setup resource-module specific issue reporting
+ return getIssues();
+ }
+
+ TargetMap targetMap = blazeProjectData.getTargetMap();
+ ArtifactLocationDecoder decoder = blazeProjectData.getArtifactLocationDecoder();
+ AndroidResourceModule resourceModule =
+ AndroidResourceModuleRegistry.getInstance(project).get(module);
+ if (resourceModule == null) {
+ return getIssues();
+ }
+
+ TargetIdeInfo target = targetMap.get(resourceModule.targetKey);
+ if (target == null) {
+ return getIssues();
+ }
+
+ reportGeneratedResources(resourceModule, targetMap, decoder);
+ reportNonStandardAndroidManifestName(target, decoder);
+ reportResourceTargetShouldDependOnClassTarget(target, targetMap, decoder);
+ return getIssues();
+ }
+
+ /**
+ * We can't find generated resources. If a layout uses them, the layout won't render correctly.
+ */
+ private void reportGeneratedResources(
+ AndroidResourceModule resourceModule, TargetMap targetMap, ArtifactLocationDecoder decoder) {
+ Map brokenClasses = logger.getBrokenClasses();
+ if (brokenClasses == null || brokenClasses.isEmpty()) {
+ return;
+ }
+
+ // Sorted entries for deterministic error message.
+ SortedMap generatedResources =
+ Maps.newTreeMap(getGeneratedResources(targetMap.get(resourceModule.targetKey)));
+
+ for (TargetKey dependency : resourceModule.transitiveResourceDependencies) {
+ generatedResources.putAll(getGeneratedResources(targetMap.get(dependency)));
+ }
+
+ if (generatedResources.isEmpty()) {
+ return;
+ }
+
+ HtmlBuilder builder = new HtmlBuilder();
+ builder.add("Generated resources will not be discovered by the IDE:");
+ builder.beginList();
+ for (Map.Entry entry : generatedResources.entrySet()) {
+ ArtifactLocation resource = entry.getKey();
+ TargetIdeInfo target = entry.getValue();
+ builder.listItem().add(resource.getRelativePath()).add(" from ");
+ addTargetLink(builder, target, decoder);
+ }
+ builder
+ .endList()
+ .add("Please avoid using generated resources, ")
+ .addLink("then ", "sync the project", " ", getLinkManager().createSyncProjectUrl())
+ .addLink("and ", "refresh the layout", ".", getLinkManager().createRefreshRenderUrl());
+ addIssue()
+ .setSeverity(HighlightSeverity.ERROR, HIGH_PRIORITY + 1) // Reported above broken classes
+ .setSummary("Generated resources")
+ .setHtmlContent(builder)
+ .build();
+ }
+
+ private static SortedMap getGeneratedResources(
+ TargetIdeInfo target) {
+ if (target == null || target.getAndroidIdeInfo() == null) {
+ return Collections.emptySortedMap();
+ }
+ SortedMap generatedResources = Maps.newTreeMap();
+ generatedResources.putAll(
+ target.getAndroidIdeInfo().getResources().stream()
+ .map(AndroidResFolder::getRoot)
+ .filter(ArtifactLocation::isGenerated)
+ .collect(toImmutableMap(Function.identity(), resource -> target)));
+ return generatedResources;
+ }
+
+ /**
+ * When the Android manifest isn't AndroidManifest.xml, resolving resource IDs would fail. This
+ * doesn't seem to be an issue if the manifest belongs to one of the target's dependencies.
+ */
+ private void reportNonStandardAndroidManifestName(
+ TargetIdeInfo target, ArtifactLocationDecoder decoder) {
+ if (target.getAndroidIdeInfo() == null || target.getAndroidIdeInfo().getManifest() == null) {
+ return;
+ }
+
+ Map brokenClasses = logger.getBrokenClasses();
+ if (brokenClasses == null || brokenClasses.isEmpty()) {
+ return;
+ }
+
+ ArtifactLocation maniftestArtifactLocation = target.getAndroidIdeInfo().getManifest();
+
+ File manifest =
+ Preconditions.checkNotNull(
+ OutputArtifactResolver.resolve(project, decoder, maniftestArtifactLocation),
+ "Fail to find file %s",
+ maniftestArtifactLocation.getRelativePath());
+ if (manifest.getName().equals(ANDROID_MANIFEST_XML)) {
+ return;
+ }
+
+ HtmlBuilder builder = new HtmlBuilder();
+ addTargetLink(builder, target, decoder)
+ .add(" uses a non-standard name for the Android manifest: ");
+ String linkToManifest = HtmlLinkManagerCompat.createFilePositionUrl(manifest, -1, 0);
+ if (linkToManifest != null) {
+ builder.addLink(manifest.getName(), linkToManifest);
+ } else {
+ builder.newline().add(manifest.getPath());
+ }
+ // TODO: add a link to automatically rename the file and refactor all references.
+ builder
+ .newline()
+ .add("Please rename it to ")
+ .add(ANDROID_MANIFEST_XML)
+ .addLink(", then ", "sync the project", "", getLinkManager().createSyncProjectUrl())
+ .addLink(" and ", "refresh the layout", ".", getLinkManager().createRefreshRenderUrl());
+ addIssue()
+ .setSeverity(HighlightSeverity.ERROR, HIGH_PRIORITY + 1) // Reported above broken classes.
+ .setSummary("Non-standard manifest name")
+ .setHtmlContent(builder)
+ .build();
+ }
+
+ /**
+ * Blaze doesn't resolve class dependencies from resources until building the final
+ * android_binary, so we could end up with resources that ultimately build correctly, but fail to
+ * find their class dependencies during rendering in the layout editor.
+ */
+ @SuppressWarnings("rawtypes")
+ private void reportResourceTargetShouldDependOnClassTarget(
+ TargetIdeInfo target, TargetMap targetMap, ArtifactLocationDecoder decoder) {
+ Set missingClasses = logger.getMissingClasses();
+ if (missingClasses == null || missingClasses.isEmpty()) {
+ return;
+ }
+
+ // Sorted entries for deterministic error message.
+ SortedSetMultimap missingClassToTargetMap = TreeMultimap.create();
+
+ SourceToTargetMap sourceToTargetMap = SourceToTargetMap.getInstance(project);
+ ImmutableCollection transitiveDependencies =
+ TransitiveDependencyMap.getInstance(project).getTransitiveDependencies(target.getKey());
+
+ for (String missingClass : missingClasses) {
+ File sourceFile = getSourceFileForClass(missingClass);
+ if (sourceFile == null) {
+ continue;
+ }
+ ImmutableCollection sourceTargets =
+ sourceToTargetMap.getRulesForSourceFile(sourceFile);
+ if (sourceTargets.stream()
+ .noneMatch(
+ sourceTarget ->
+ sourceTarget.equals(target.getKey())
+ || transitiveDependencies.contains(sourceTarget))) {
+ missingClassToTargetMap.putAll(missingClass, sourceTargets);
+ }
+ }
+
+ if (missingClassToTargetMap.isEmpty()) {
+ return;
+ }
+
+ HtmlBuilder builder = new HtmlBuilder();
+ addTargetLink(builder, target, decoder)
+ .add(" contains resource files that reference these classes:")
+ .beginList();
+ for (String missingClass : missingClassToTargetMap.keySet()) {
+ builder
+ .listItem()
+ .addLink(missingClass, getLinkManager().createOpenClassUrl(missingClass))
+ .add(" from ");
+ for (TargetKey targetKey : missingClassToTargetMap.get(missingClass)) {
+ addTargetLink(builder, targetMap.get(targetKey), decoder).add(" ");
+ }
+ }
+ builder.endList().add("Please fix your dependencies so that ");
+ addTargetLink(builder, target, decoder)
+ .add(" correctly depends on these classes, ")
+ .addLink("then ", "sync the project", " ", getLinkManager().createSyncProjectUrl())
+ .addLink("and ", "refresh the layout", ".", getLinkManager().createRefreshRenderUrl())
+ .newline()
+ .newline()
+ .addBold(
+ "NOTE: blaze can still build with the incorrect dependencies "
+ + "due to the way it handles resources, "
+ + "but the layout editor needs them to be correct.");
+
+ addIssue()
+ .setSeverity(HighlightSeverity.ERROR, HIGH_PRIORITY + 1) // Reported above missing classes.
+ .setSummary("Missing class dependencies")
+ .setHtmlContent(builder)
+ .build();
+ }
+
+ private File getSourceFileForClass(String className) {
+ return ApplicationManager.getApplication()
+ .runReadAction(
+ (Computable)
+ () -> {
+ try {
+ PsiClass psiClass =
+ JavaPsiFacade.getInstance(project)
+ .findClass(className, GlobalSearchScope.projectScope(project));
+ if (psiClass == null) {
+ return null;
+ }
+ return VfsUtilCore.virtualToIoFile(
+ psiClass.getContainingFile().getVirtualFile());
+ } catch (IndexNotReadyException ignored) {
+ // We're in dumb mode. Abort! Abort!
+ return null;
+ }
+ });
+ }
+
+ @CanIgnoreReturnValue
+ private HtmlBuilder addTargetLink(
+ HtmlBuilder builder, TargetIdeInfo target, ArtifactLocationDecoder decoder) {
+ File buildFile =
+ Preconditions.checkNotNull(
+ OutputArtifactResolver.resolve(project, decoder, target.getBuildFile()),
+ "Fail to find file %s",
+ target.getBuildFile().getRelativePath());
+ int line =
+ ApplicationManager.getApplication()
+ .runReadAction(
+ (Computable)
+ () -> {
+ PsiElement buildTargetPsi =
+ BuildReferenceManager.getInstance(project)
+ .resolveLabel(target.getKey().getLabel());
+ if (buildTargetPsi == null) {
+ return -1;
+ }
+ PsiFile psiFile = buildTargetPsi.getContainingFile();
+ if (psiFile == null) {
+ return -1;
+ }
+ return StringUtil.offsetToLineNumber(
+ psiFile.getText(), buildTargetPsi.getTextOffset());
+ });
+ String url = HtmlLinkManagerCompat.createFilePositionUrl(buildFile, line, 0);
+ if (url != null) {
+ return builder.addLink(target.toString(), url);
+ }
+ return builder.add(target.toString());
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/rendering/BlazeRenderSecurityManagerOverrides.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/rendering/BlazeRenderSecurityManagerOverrides.java
new file mode 100644
index 00000000000..39d3edd195f
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/rendering/BlazeRenderSecurityManagerOverrides.java
@@ -0,0 +1,27 @@
+/*
+ * 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.rendering;
+
+import com.android.tools.rendering.security.RenderSecurityManagerOverrides;
+
+/** Overrides some security restrictions used by the render sandbox. */
+public class BlazeRenderSecurityManagerOverrides implements RenderSecurityManagerOverrides {
+ @Override
+ public boolean allowsPropertiesAccess() {
+ // System properties access is needed for SystemPropertyExperimentLoader
+ return true;
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/rendering/RenderErrorLoggingContributorCompat.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/rendering/RenderErrorLoggingContributorCompat.java
new file mode 100644
index 00000000000..268e063c190
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/rendering/RenderErrorLoggingContributorCompat.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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.rendering;
+
+import com.android.tools.idea.rendering.RenderErrorContributor;
+import com.android.tools.idea.rendering.RenderErrorContributorImpl;
+import com.android.tools.idea.ui.designer.EditorDesignSurface;
+import com.android.tools.rendering.RenderResultCompat;
+import com.intellij.openapi.actionSystem.DataContext;
+import org.jetbrains.annotations.Nullable;
+
+/** Collects and uploads render errors by hooking into {@link RenderErrorContributor}. */
+abstract class RenderErrorLoggingContributorCompat extends RenderErrorContributorImpl {
+ public RenderErrorLoggingContributorCompat(
+ EditorDesignSurface surface, RenderResultCompat result, @Nullable DataContext dataContext) {
+ super(surface, result.get());
+ }
+
+ public RenderErrorLoggingContributorCompat(
+ EditorDesignSurface surface, RenderResultCompat result) {
+ super(surface, result.get());
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/resources/BlazeLightResourceClassServiceBase.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/resources/BlazeLightResourceClassServiceBase.java
new file mode 100644
index 00000000000..be9c3b2d882
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/resources/BlazeLightResourceClassServiceBase.java
@@ -0,0 +1,64 @@
+/*
+ * 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.resources;
+
+import com.android.tools.idea.projectsystem.LightResourceClassService;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.idea.blaze.base.sync.data.BlazeDataStorage;
+import com.google.idea.common.experiments.FeatureRolloutExperiment;
+import com.intellij.openapi.module.Module;
+import com.intellij.psi.PsiClass;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/** Implementation of {@link LightResourceClassService} set up at Blaze sync time. */
+public abstract class BlazeLightResourceClassServiceBase implements LightResourceClassService {
+
+ @VisibleForTesting
+ public static final FeatureRolloutExperiment workspaceResourcesFeature =
+ new FeatureRolloutExperiment("aswb.workspace.light.class.enabled");
+
+ Map rClasses = Maps.newHashMap();
+ Map rClassesByModule = Maps.newHashMap();
+ final Set allRClasses = Sets.newHashSet();
+
+ @Override
+ public Collection extends PsiClass> getLightRClassesAccessibleFromModule(Module module) {
+ if (workspaceResourcesFeature.isEnabled()
+ && module.getName().equals(BlazeDataStorage.WORKSPACE_MODULE_NAME)) {
+ // Returns all the packages in resource modules, and all the workspace packages that
+ // have previously been asked for. All `res/` directories in our project should belong to a
+ // resource module. For java sources, IntelliJ will ask for explicit resource package by
+ // calling `getLightRClasses` at which point we can create the package. This is not completely
+ // correct and the autocomplete will be slightly off when initial `R` is typed in the editor,
+ // but this workaround is being used to mitigate issues (b/136685602) while resources
+ // are re-worked.
+ return allRClasses;
+ } else {
+ return rClasses.values();
+ }
+ }
+
+ @Override
+ public Collection extends PsiClass> getLightRClassesDefinedByModule(Module module) {
+ BlazeRClass rClass = rClassesByModule.get(module);
+ return rClass == null ? ImmutableSet.of() : ImmutableSet.of(rClass);
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/resources/BlazeRClass.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/resources/BlazeRClass.java
new file mode 100644
index 00000000000..37895c5a1cc
--- /dev/null
+++ b/aswb/sdkcompat/as232/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.ResourceRepositoryRClass;
+import com.android.tools.idea.res.StudioResourceRepositoryManager;
+import com.android.tools.res.CacheableResourceRepository;
+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 StudioResourceRepositoryManager getResourceRepositoryManager() {
+ return StudioResourceRepositoryManager.getInstance(androidFacet);
+ }
+
+ @Override
+ public CacheableResourceRepository getResourceRepository() {
+ return StudioResourceRepositoryManager.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/as232/com/google/idea/blaze/android/run/BazelApplicationProjectContext.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/BazelApplicationProjectContext.java
new file mode 100644
index 00000000000..cbca2310836
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/BazelApplicationProjectContext.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2023 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.idea.blaze.android.run;
+
+import com.android.tools.idea.projectsystem.ApplicationProjectContext;
+import com.android.tools.idea.run.ApkProvisionException;
+import com.android.tools.idea.run.ApplicationIdProvider;
+import com.intellij.openapi.project.Project;
+import java.util.function.Supplier;
+
+/**
+ * An implementation of {@link ApplicationProjectContext} used in the Blaze project system.
+ *
+ * Note: The Blaze project system assumes all instances of the {@link
+ * ApplicationProjectContext} associated with its projects to be backed by this specific class.
+ */
+public class BazelApplicationProjectContext implements ApplicationProjectContext {
+
+ private final Project project;
+ private final Supplier applicationId;
+
+ public BazelApplicationProjectContext(Project project, String applicationId) {
+ this.project = project;
+ this.applicationId = () -> applicationId;
+ }
+
+ public BazelApplicationProjectContext(
+ Project project, ApplicationIdProvider applicationIdProvider) {
+ this.project = project;
+ this.applicationId =
+ () -> {
+ try {
+ return applicationIdProvider.getPackageName();
+ } catch (ApkProvisionException e) {
+ throw new RuntimeException(e);
+ }
+ };
+ }
+
+ public Project getProject() {
+ return project;
+ }
+
+ @Override
+ public String getApplicationId() {
+ return applicationId.get();
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/BazelApplicationProjectContextProvider.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/BazelApplicationProjectContextProvider.java
new file mode 100644
index 00000000000..bffcc3d238d
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/BazelApplicationProjectContextProvider.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2024 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.ddmlib.Client;
+import com.android.ddmlib.ClientData;
+import com.android.tools.idea.projectsystem.ApplicationProjectContext;
+import com.android.tools.idea.projectsystem.ApplicationProjectContextProvider;
+import com.google.idea.blaze.android.projectsystem.BlazeToken;
+import com.intellij.openapi.project.Project;
+import javax.annotation.Nullable;
+
+/** An implementation of {@link ApplicationProjectContextProvider} for the Blaze project system. */
+public class BazelApplicationProjectContextProvider
+ implements ApplicationProjectContextProvider, BlazeToken {
+
+ private final Project project;
+
+ public BazelApplicationProjectContextProvider(Project project) {
+ this.project = project;
+ }
+
+ @Nullable
+ @Override
+ public ApplicationProjectContext getApplicationProjectContextProvider(Client client) {
+ ClientData clientData = client.getClientData();
+ if (clientData == null) {
+ return null;
+ }
+ String androidPackageName = clientData.getPackageName();
+ if (androidPackageName == null) {
+ return null;
+ }
+ return new BazelApplicationProjectContext(project, androidPackageName);
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/BlazeNativeDebuggerAppContextProvider.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/BlazeNativeDebuggerAppContextProvider.java
new file mode 100644
index 00000000000..df4cd15d3cf
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/BlazeNativeDebuggerAppContextProvider.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2023 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.run;
+
+import com.android.sdklib.devices.Abi;
+import com.android.tools.idea.projectsystem.ApplicationProjectContext;
+import com.android.tools.ndk.run.NativeDebuggerAppContext;
+import com.android.tools.ndk.run.NativeDebuggerAppContextProvider;
+import com.android.tools.ndk.run.SymbolDir;
+import com.google.idea.blaze.android.projectsystem.BlazeToken;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/** An implementation of {@link NativeDebuggerAppContextProvider} for the Blaze project system. */
+public class BlazeNativeDebuggerAppContextProvider
+ implements NativeDebuggerAppContextProvider, BlazeToken {
+
+ @Override
+ public NativeDebuggerAppContext getNativeDebuggerAppContext(
+ ApplicationProjectContext applicationProjectContext) {
+ final var context = (BazelApplicationProjectContext) applicationProjectContext;
+ // TODO(solodkyy): Find out whether any configuration that is supposed to be part of this
+ // context is passed to the debugger in oher ways and make sure this is the
+ // only way to set up the debugger.
+ return new NativeDebuggerAppContext() {
+ @Override
+ public Project getProject() {
+ return context.getProject();
+ }
+
+ @Override
+ public String getApplicationId() {
+ return context.getApplicationId();
+ }
+
+ @Override
+ public Collection getSymDirs(List abis) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Map getSourceMap() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map getExplicitModuleSymbolMap(Abi abi) {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Collection getModulesToVerify() {
+ return Collections.emptyList();
+ }
+ };
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryApplicationLaunchTaskProvider.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryApplicationLaunchTaskProvider.java
new file mode 100644
index 00000000000..948dae75f36
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryApplicationLaunchTaskProvider.java
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+import com.android.tools.idea.run.ApkProvisionException;
+import com.android.tools.idea.run.ApplicationIdProvider;
+import com.android.tools.idea.run.activity.StartActivityFlagsProvider;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.google.idea.blaze.android.manifest.ManifestParser;
+import com.google.idea.blaze.android.run.binary.tasks.AndroidDeepLinkLaunchTask;
+import com.google.idea.blaze.android.run.binary.tasks.BlazeDefaultActivityLaunchTask;
+import com.google.idea.blaze.android.run.binary.tasks.SpecificActivityLaunchTask;
+import com.intellij.execution.ExecutionException;
+import com.intellij.openapi.diagnostic.Logger;
+
+/** Provides the launch task for android_binary */
+public class BlazeAndroidBinaryApplicationLaunchTaskProvider {
+ private static final Logger LOG =
+ Logger.getInstance(BlazeAndroidBinaryApplicationLaunchTaskProvider.class);
+
+ public static BlazeLaunchTask getApplicationLaunchTask(
+ ApplicationIdProvider applicationIdProvider,
+ ManifestParser.ParsedManifest mergedManifestParsedManifest,
+ BlazeAndroidBinaryRunConfigurationState configState,
+ StartActivityFlagsProvider startActivityFlagsProvider)
+ throws ExecutionException {
+ String applicationId;
+ try {
+ applicationId = applicationIdProvider.getPackageName();
+ } catch (ApkProvisionException e) {
+ throw new ExecutionException("Unable to identify application id");
+ }
+
+ switch (configState.getMode()) {
+ case BlazeAndroidBinaryRunConfigurationState.LAUNCH_DEFAULT_ACTIVITY:
+ BlazeDefaultActivityLocator activityLocator =
+ new BlazeDefaultActivityLocator(mergedManifestParsedManifest);
+ return new BlazeDefaultActivityLaunchTask(
+ applicationId, activityLocator, startActivityFlagsProvider);
+ case BlazeAndroidBinaryRunConfigurationState.LAUNCH_SPECIFIC_ACTIVITY:
+ return launchContext ->
+ new SpecificActivityLaunchTask(
+ applicationId, configState.getActivityClass(), startActivityFlagsProvider)
+ .run(
+ launchContext.getDevice(),
+ launchContext.getProgressIndicator(),
+ launchContext.getConsoleView());
+ case BlazeAndroidBinaryRunConfigurationState.LAUNCH_DEEP_LINK:
+ return launchContext ->
+ new AndroidDeepLinkLaunchTask(configState.getDeepLink(), startActivityFlagsProvider)
+ .run(
+ launchContext.getDevice(),
+ launchContext.getProgressIndicator(),
+ launchContext.getConsoleView());
+ default:
+ return null;
+ }
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java
new file mode 100644
index 00000000000..01af2003452
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContext.java
@@ -0,0 +1,130 @@
+/*
+ * 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.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
+import com.android.tools.idea.execution.common.debug.DebugSessionStarter;
+import com.android.tools.idea.projectsystem.ApplicationProjectContext;
+import com.android.tools.idea.run.ApkProvisionException;
+import com.android.tools.idea.run.activity.DefaultStartActivityFlagsProvider;
+import com.android.tools.idea.run.activity.StartActivityFlagsProvider;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.google.idea.blaze.android.run.BazelApplicationProjectContext;
+import com.google.idea.blaze.android.run.deployinfo.BlazeAndroidDeployInfo;
+import com.google.idea.blaze.android.run.runner.ApkBuildStep;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.Executor;
+import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XDebugSession;
+import javax.annotation.Nullable;
+import kotlin.Unit;
+import kotlin.coroutines.EmptyCoroutineContext;
+import kotlinx.coroutines.BuildersKt;
+import org.jetbrains.android.facet.AndroidFacet;
+
+/** Compat for #api212 */
+public class BlazeAndroidBinaryNormalBuildRunContext
+ extends BlazeAndroidBinaryNormalBuildRunContextBase {
+ BlazeAndroidBinaryNormalBuildRunContext(
+ Project project,
+ AndroidFacet facet,
+ RunConfiguration runConfiguration,
+ ExecutionEnvironment env,
+ BlazeAndroidBinaryRunConfigurationState configState,
+ ApkBuildStep buildStep,
+ String launchId) {
+ super(project, facet, runConfiguration, env, configState, buildStep, launchId);
+ }
+
+ @Override
+ public ApplicationProjectContext getApplicationProjectContext() {
+ return new BazelApplicationProjectContext(project, getApplicationIdProvider());
+ }
+
+ @Override
+ public BlazeLaunchTask getApplicationLaunchTask(
+ boolean isDebug, @Nullable Integer userId, String contributorsAmStartOptions)
+ throws ExecutionException {
+ String extraFlags = UserIdHelper.getFlagsFromUserId(userId);
+ if (!contributorsAmStartOptions.isEmpty()) {
+ extraFlags += (extraFlags.isEmpty() ? "" : " ") + contributorsAmStartOptions;
+ }
+ if (isDebug) {
+ extraFlags += (extraFlags.isEmpty() ? "" : " ") + "-D";
+ }
+
+ final StartActivityFlagsProvider startActivityFlagsProvider =
+ new DefaultStartActivityFlagsProvider(project, isDebug, extraFlags);
+
+ BlazeAndroidDeployInfo deployInfo;
+ try {
+ deployInfo = buildStep.getDeployInfo();
+ } catch (ApkProvisionException e) {
+ throw new ExecutionException(e);
+ }
+
+ return BlazeAndroidBinaryApplicationLaunchTaskProvider.getApplicationLaunchTask(
+ applicationIdProvider,
+ deployInfo.getMergedManifest(),
+ configState,
+ startActivityFlagsProvider);
+ }
+
+ @Nullable
+ @Override
+ public XDebugSession startDebuggerSession(
+ AndroidDebugger androidDebugger,
+ AndroidDebuggerState androidDebuggerState,
+ ExecutionEnvironment env,
+ IDevice device,
+ ConsoleView consoleView,
+ ProgressIndicator indicator,
+ String packageName) {
+ try {
+ return BuildersKt.runBlocking(
+ EmptyCoroutineContext.INSTANCE,
+ (scope, continuation) ->
+ DebugSessionStarter.INSTANCE.attachDebuggerToStartedProcess(
+ device,
+ new BazelApplicationProjectContext(project, packageName),
+ env,
+ androidDebugger,
+ androidDebuggerState,
+ /*destroyRunningProcess*/ d -> {
+ d.forceStop(packageName);
+ return Unit.INSTANCE;
+ },
+ indicator,
+ consoleView,
+ 15L,
+ continuation));
+ } catch (InterruptedException e) {
+ throw new ProcessCanceledException();
+ }
+ }
+
+ @Override
+ public Executor getExecutor() {
+ return env.getExecutor();
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java
new file mode 100644
index 00000000000..96f3f8be324
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextBase.java
@@ -0,0 +1,186 @@
+/*
+ * 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;
+
+import static com.google.idea.blaze.android.run.runner.BlazeAndroidLaunchTasksProvider.NATIVE_DEBUGGING_ENABLED;
+
+import com.android.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.DeployOptions;
+import com.android.tools.idea.gradle.util.DynamicAppUtils;
+import com.android.tools.idea.run.ApkFileUnit;
+import com.android.tools.idea.run.ApkInfo;
+import com.android.tools.idea.run.ApkProvider;
+import com.android.tools.idea.run.ApkProvisionException;
+import com.android.tools.idea.run.ApplicationIdProvider;
+import com.android.tools.idea.run.ConsoleProvider;
+import com.android.tools.idea.run.LaunchOptions;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.blaze.BlazeLaunchTasksProvider;
+import com.android.tools.idea.run.editor.ProfilerState;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.idea.blaze.android.run.deployinfo.BlazeApkProviderService;
+import com.google.idea.blaze.android.run.runner.ApkBuildStep;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidDeviceSelector;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidLaunchTasksProvider;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidRunContext;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.Executor;
+import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.openapi.project.Project;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+import org.jetbrains.android.facet.AndroidFacet;
+import org.jetbrains.annotations.NotNull;
+
+/** Run context for android_binary. */
+public abstract class BlazeAndroidBinaryNormalBuildRunContextBase
+ implements BlazeAndroidRunContext {
+ protected final Project project;
+ protected final AndroidFacet facet;
+ protected final RunConfiguration runConfiguration;
+ protected final ExecutionEnvironment env;
+ protected final BlazeAndroidBinaryRunConfigurationState configState;
+ protected final ConsoleProvider consoleProvider;
+ protected final ApkBuildStep buildStep;
+ protected final ApkProvider apkProvider;
+ protected final ApplicationIdProvider applicationIdProvider;
+ private final String launchId;
+
+ BlazeAndroidBinaryNormalBuildRunContextBase(
+ Project project,
+ AndroidFacet facet,
+ RunConfiguration runConfiguration,
+ ExecutionEnvironment env,
+ BlazeAndroidBinaryRunConfigurationState configState,
+ ApkBuildStep buildStep,
+ String launchId) {
+ this.project = project;
+ this.facet = facet;
+ this.runConfiguration = runConfiguration;
+ this.env = env;
+ this.configState = configState;
+ this.consoleProvider = new BlazeAndroidBinaryConsoleProvider(project);
+ this.buildStep = buildStep;
+ this.apkProvider = BlazeApkProviderService.getInstance().getApkProvider(project, buildStep);
+ this.applicationIdProvider = new BlazeAndroidBinaryApplicationIdProvider(buildStep);
+ this.launchId = launchId;
+ }
+
+ @Override
+ public BlazeAndroidDeviceSelector getDeviceSelector() {
+ return new BlazeAndroidDeviceSelector.NormalDeviceSelector();
+ }
+
+ @Override
+ public void augmentLaunchOptions(LaunchOptions.Builder options) {
+ LaunchOptions.Builder unused =
+ options
+ .setDeploy(true)
+ .setOpenLogcatAutomatically(configState.showLogcatAutomatically())
+ .addExtraOptions(
+ ImmutableMap.of(
+ NATIVE_DEBUGGING_ENABLED,
+ configState.getCommonState().isNativeDebuggingEnabled()))
+ .setClearAppStorage(configState.getClearAppStorage());
+ }
+
+ @Override
+ public ConsoleProvider getConsoleProvider() {
+ return consoleProvider;
+ }
+
+ @Override
+ public ApplicationIdProvider getApplicationIdProvider() {
+ return applicationIdProvider;
+ }
+
+ @Override
+ public ApkBuildStep getBuildStep() {
+ return buildStep;
+ }
+
+ @Nullable
+ @Override
+ public Integer getUserId(IDevice device) throws ExecutionException {
+ return UserIdHelper.getUserIdFromConfigurationState(project, device, configState);
+ }
+
+ @Override
+ public BlazeLaunchTasksProvider getLaunchTasksProvider(LaunchOptions launchOptions)
+ throws ExecutionException {
+ return new BlazeAndroidLaunchTasksProvider(project, this, applicationIdProvider, launchOptions);
+ }
+
+ @Override
+ public String getAmStartOptions() {
+ return configState.getAmStartOptions();
+ }
+
+ @Nullable
+ @Override
+ public ImmutableList getDeployTasks(IDevice device, DeployOptions deployOptions)
+ throws ExecutionException {
+ return ImmutableList.of(
+ new DeploymentTimingReporterTask(
+ launchId,
+ project,
+ getApkInfoToInstall(device, deployOptions, apkProvider),
+ deployOptions));
+ }
+
+ /** Returns a list of APKs excluding any APKs for features that are disabled. */
+ public static List getApkInfoToInstall(
+ IDevice device, DeployOptions deployOptions, ApkProvider apkProvider)
+ throws ExecutionException {
+ Collection apks;
+ try {
+ apks = apkProvider.getApks(device);
+ } catch (ApkProvisionException e) {
+ throw new ExecutionException(e);
+ }
+ List disabledFeatures = deployOptions.getDisabledDynamicFeatures();
+ return apks.stream()
+ .map(apk -> getApkInfoToInstall(apk, disabledFeatures))
+ .collect(Collectors.toList());
+ }
+
+ @NotNull
+ private static ApkInfo getApkInfoToInstall(ApkInfo apkInfo, List disabledFeatures) {
+ if (apkInfo.getFiles().size() > 1) {
+ List filteredApks =
+ apkInfo.getFiles().stream()
+ .filter(feature -> DynamicAppUtils.isFeatureEnabled(disabledFeatures, feature))
+ .collect(Collectors.toList());
+ return new ApkInfo(filteredApks, apkInfo.getApplicationId());
+ } else {
+ return apkInfo;
+ }
+ }
+
+ @Override
+ public Executor getExecutor() {
+ return env.getExecutor();
+ }
+
+ @Override
+ public ProfilerState getProfileState() {
+ return configState.getProfilerState();
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextCompat.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextCompat.java
new file mode 100644
index 00000000000..d3e7ab1dc65
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryNormalBuildRunContextCompat.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2022 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.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
+import com.android.tools.idea.execution.common.debug.DebugSessionStarter;
+import com.google.idea.blaze.android.run.BazelApplicationProjectContext;
+import com.google.idea.blaze.android.run.runner.ApkBuildStep;
+import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XDebugSession;
+import javax.annotation.Nullable;
+import kotlin.Unit;
+import kotlin.coroutines.EmptyCoroutineContext;
+import kotlinx.coroutines.BuildersKt;
+import org.jetbrains.android.facet.AndroidFacet;
+
+/** Compat class for {@link BlazeAndroidBinaryNormalBuildRunContext}. */
+public class BlazeAndroidBinaryNormalBuildRunContextCompat
+ extends BlazeAndroidBinaryNormalBuildRunContext {
+
+ BlazeAndroidBinaryNormalBuildRunContextCompat(
+ Project project,
+ AndroidFacet facet,
+ RunConfiguration runConfiguration,
+ ExecutionEnvironment env,
+ BlazeAndroidBinaryRunConfigurationState configState,
+ ApkBuildStep buildStep,
+ String launchId) {
+ super(project, facet, runConfiguration, env, configState, buildStep, launchId);
+ }
+
+ @Nullable
+ @Override
+ public XDebugSession startDebuggerSession(
+ AndroidDebugger androidDebugger,
+ AndroidDebuggerState androidDebuggerState,
+ ExecutionEnvironment env,
+ IDevice device,
+ ConsoleView consoleView,
+ ProgressIndicator indicator,
+ String packageName) {
+ try {
+ return BuildersKt.runBlocking(
+ EmptyCoroutineContext.INSTANCE,
+ (scope, continuation) ->
+ DebugSessionStarter.INSTANCE.attachDebuggerToStartedProcess(
+ device,
+ new BazelApplicationProjectContext(project, packageName),
+ env,
+ androidDebugger,
+ androidDebuggerState,
+ /*destroyRunningProcess*/ d -> {
+ d.forceStop(packageName);
+ return Unit.INSTANCE;
+ },
+ indicator,
+ consoleView,
+ 15L,
+ continuation));
+ } catch (InterruptedException e) {
+ throw new ProcessCanceledException();
+ }
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryProgramRunner.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryProgramRunner.java
new file mode 100644
index 00000000000..60bd11debaf
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryProgramRunner.java
@@ -0,0 +1,114 @@
+/*
+ * 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;
+
+import static com.intellij.openapi.application.ModalityState.NON_MODAL;
+
+import com.android.tools.idea.execution.common.AndroidConfigurationExecutor;
+import com.android.tools.idea.profilers.ProfileRunExecutor;
+import com.google.idea.blaze.android.run.BlazeAndroidRunConfigurationHandler;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.ExecutionResult;
+import com.intellij.execution.Executor;
+import com.intellij.execution.configurations.RunProfile;
+import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.configurations.RunnerSettings;
+import com.intellij.execution.executors.DefaultDebugExecutor;
+import com.intellij.execution.executors.DefaultRunExecutor;
+import com.intellij.execution.runners.AsyncProgramRunner;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.RunContentBuilder;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.openapi.application.ActionsKt;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
+import org.jetbrains.concurrency.AsyncPromise;
+import org.jetbrains.concurrency.Promise;
+
+/** Program runner for configurations from {@link BlazeAndroidBinaryRunConfigurationHandler}. */
+public class BlazeAndroidBinaryProgramRunner extends AsyncProgramRunner {
+ @Override
+ public boolean canRun(String executorId, RunProfile profile) {
+ BlazeAndroidRunConfigurationHandler handler =
+ BlazeAndroidRunConfigurationHandler.getHandlerFrom(profile);
+ if (!(handler instanceof BlazeAndroidBinaryRunConfigurationHandler)) {
+ return false;
+ }
+ return (DefaultDebugExecutor.EXECUTOR_ID.equals(executorId)
+ || DefaultRunExecutor.EXECUTOR_ID.equals(executorId)
+ || ProfileRunExecutor.EXECUTOR_ID.equals(executorId));
+ }
+
+ @Override
+ protected Promise execute(
+ ExecutionEnvironment environment, RunProfileState state) {
+ FileDocumentManager.getInstance().saveAllDocuments();
+
+ AsyncPromise promise = new AsyncPromise<>();
+
+ ProgressManager.getInstance()
+ .run(
+ new Task.Backgroundable(environment.getProject(), "Launching ${runProfile.name}") {
+ @Override
+ public void run(ProgressIndicator indicator) {
+ try {
+ RunContentDescriptor descriptor;
+ if (state instanceof AndroidConfigurationExecutor) {
+ AndroidConfigurationExecutor configurationExecutor =
+ (AndroidConfigurationExecutor) state;
+ Executor executor = environment.getExecutor();
+ if (executor.getId().equals(DefaultDebugExecutor.EXECUTOR_ID)) {
+ descriptor = configurationExecutor.debug(indicator);
+ } else if (executor.getId().equals(DefaultRunExecutor.EXECUTOR_ID)
+ || executor.getId().equals(ProfileRunExecutor.EXECUTOR_ID)) {
+ descriptor = configurationExecutor.run(indicator);
+ } else {
+ throw new ExecutionException("Unsupported executor");
+ }
+ } else {
+ descriptor = doExecute(state, environment);
+ }
+ promise.setResult(descriptor);
+ } catch (ExecutionException e) {
+ boolean unused = promise.setError(e);
+ }
+ }
+
+ @Override
+ public void onCancel() {
+ super.onCancel();
+ promise.setResult(null);
+ }
+ });
+
+ return promise;
+ }
+
+ private RunContentDescriptor doExecute(
+ final RunProfileState state, final ExecutionEnvironment env) throws ExecutionException {
+ ExecutionResult result = state.execute(env.getExecutor(), this);
+ return ActionsKt.invokeAndWaitIfNeeded(
+ NON_MODAL,
+ () -> new RunContentBuilder(result, env).showRunContent(env.getContentToReuse()));
+ }
+
+ @Override
+ public String getRunnerId() {
+ return "AndroidBinaryProgramRunner";
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationHandlerCompat.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationHandlerCompat.java
new file mode 100644
index 00000000000..188f6e6b844
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationHandlerCompat.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2022 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.execution.common.DeployableToDevice;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.intellij.openapi.project.Project;
+
+/** Compat class for {@link BlazeAndroidBinaryRunConfigurationHandlerCompat}. */
+public class BlazeAndroidBinaryRunConfigurationHandlerCompat {
+ protected final Project project;
+ protected final BlazeAndroidBinaryRunConfigurationState configState;
+
+ @VisibleForTesting
+ protected BlazeAndroidBinaryRunConfigurationHandlerCompat(
+ BlazeCommandRunConfiguration configuration) {
+ project = configuration.getProject();
+ configState =
+ new BlazeAndroidBinaryRunConfigurationState(
+ Blaze.buildSystemName(configuration.getProject()));
+ configuration.putUserData(DeployableToDevice.getKEY(), true);
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/DeploymentTimingReporterTask.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/DeploymentTimingReporterTask.java
new file mode 100644
index 00000000000..bc567e3ff30
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/DeploymentTimingReporterTask.java
@@ -0,0 +1,60 @@
+/*
+ * 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.execution.common.DeployOptions;
+import com.android.tools.idea.run.ApkInfo;
+import com.android.tools.idea.run.blaze.BlazeLaunchContext;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.tasks.DeployTasksCompat;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.ImmutableList;
+import com.google.idea.blaze.android.run.LaunchMetrics;
+import com.intellij.execution.ExecutionException;
+import com.intellij.openapi.project.Project;
+import java.util.Collection;
+
+/** A wrapper launch task that wraps the given deployment task and logs the deployment latency. */
+public class DeploymentTimingReporterTask implements BlazeLaunchTask {
+ private final BlazeLaunchTask deployTask;
+ private final String launchId;
+ private final ImmutableList packages;
+
+ public DeploymentTimingReporterTask(
+ String launchId, Project project, Collection packages, DeployOptions deployOptions) {
+ this.launchId = launchId;
+ this.deployTask = DeployTasksCompat.createDeployTask(project, packages, deployOptions);
+ this.packages = ImmutableList.copyOf(packages);
+ }
+
+ @VisibleForTesting
+ public ImmutableList getPackages() {
+ return packages;
+ }
+
+ @Override
+ public void run(BlazeLaunchContext launchContext) throws ExecutionException {
+ Stopwatch s = Stopwatch.createStarted();
+ try {
+ deployTask.run(launchContext);
+ LaunchMetrics.logDeploymentTime(launchId, s.elapsed(), true);
+ } catch (ExecutionException e) {
+ LaunchMetrics.logDeploymentTime(launchId, s.elapsed(), false);
+ throw e;
+ }
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java
new file mode 100644
index 00000000000..1d04c7b4e95
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContext.java
@@ -0,0 +1,134 @@
+/*
+ * 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.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.debug.AndroidDebugger;
+import com.android.tools.idea.execution.common.debug.AndroidDebuggerState;
+import com.android.tools.idea.execution.common.debug.DebugSessionStarter;
+import com.android.tools.idea.projectsystem.ApplicationProjectContext;
+import com.android.tools.idea.run.ApkProvisionException;
+import com.android.tools.idea.run.activity.DefaultStartActivityFlagsProvider;
+import com.android.tools.idea.run.activity.StartActivityFlagsProvider;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.google.idea.blaze.android.run.BazelApplicationProjectContext;
+import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryApplicationLaunchTaskProvider;
+import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryRunConfigurationState;
+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.ApkBuildStep;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.Executor;
+import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XDebugSession;
+import javax.annotation.Nullable;
+import kotlin.Unit;
+import kotlin.coroutines.EmptyCoroutineContext;
+import kotlinx.coroutines.BuildersKt;
+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,
+ ApkBuildStep buildStep,
+ String launchId) {
+ super(project, facet, runConfiguration, env, configState, buildStep, launchId);
+ }
+
+ @Override
+ public ApplicationProjectContext getApplicationProjectContext() {
+ return new BazelApplicationProjectContext(project, getApplicationIdProvider());
+ }
+
+ @SuppressWarnings("unchecked") // upstream API
+ @Override
+ public BlazeLaunchTask getApplicationLaunchTask(
+ boolean isDebug, @Nullable Integer userId, String contributorsAmStartOptions)
+ throws ExecutionException {
+
+ String extraFlags = UserIdHelper.getFlagsFromUserId(userId);
+ if (!contributorsAmStartOptions.isEmpty()) {
+ extraFlags += (extraFlags.isEmpty() ? "" : " ") + contributorsAmStartOptions;
+ }
+ if (isDebug) {
+ extraFlags += (extraFlags.isEmpty() ? "" : " ") + "-D";
+ }
+
+ final StartActivityFlagsProvider startActivityFlagsProvider =
+ new DefaultStartActivityFlagsProvider(project, isDebug, extraFlags);
+ BlazeAndroidDeployInfo deployInfo;
+ try {
+ deployInfo = buildStep.getDeployInfo();
+ } catch (ApkProvisionException e) {
+ throw new ExecutionException(e);
+ }
+
+ return BlazeAndroidBinaryApplicationLaunchTaskProvider.getApplicationLaunchTask(
+ applicationIdProvider,
+ deployInfo.getMergedManifest(),
+ configState,
+ startActivityFlagsProvider);
+ }
+
+ @Nullable
+ @Override
+ public XDebugSession startDebuggerSession(
+ AndroidDebugger androidDebugger,
+ AndroidDebuggerState androidDebuggerState,
+ ExecutionEnvironment env,
+ IDevice device,
+ ConsoleView consoleView,
+ ProgressIndicator indicator,
+ String packageName) {
+ try {
+ return BuildersKt.runBlocking(
+ EmptyCoroutineContext.INSTANCE,
+ (scope, continuation) ->
+ DebugSessionStarter.INSTANCE.attachDebuggerToStartedProcess(
+ device,
+ new BazelApplicationProjectContext(project, packageName),
+ env,
+ androidDebugger,
+ androidDebuggerState,
+ /*destroyRunningProcess*/ d -> {
+ d.forceStop(packageName);
+ return Unit.INSTANCE;
+ },
+ indicator,
+ consoleView,
+ 15L,
+ continuation));
+ } catch (InterruptedException e) {
+ throw new ProcessCanceledException(e);
+ }
+ }
+
+ @Override
+ public Executor getExecutor() {
+ return env.getExecutor();
+ }
+}
diff --git a/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java
new file mode 100644
index 00000000000..967e5926fb0
--- /dev/null
+++ b/aswb/sdkcompat/as232/com/google/idea/blaze/android/run/binary/mobileinstall/BlazeAndroidBinaryMobileInstallRunContextBase.java
@@ -0,0 +1,164 @@
+/*
+ * 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.ddmlib.IDevice;
+import com.android.tools.idea.execution.common.DeployOptions;
+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.ConsoleProvider;
+import com.android.tools.idea.run.LaunchOptions;
+import com.android.tools.idea.run.blaze.BlazeLaunchTask;
+import com.android.tools.idea.run.blaze.BlazeLaunchTasksProvider;
+import com.android.tools.idea.run.editor.ProfilerState;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.idea.blaze.android.run.binary.BlazeAndroidBinaryApplicationIdProvider;
+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.ApkBuildStep;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidDeviceSelector;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidLaunchTasksProvider;
+import com.google.idea.blaze.android.run.runner.BlazeAndroidRunContext;
+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;
+ protected final ExecutionEnvironment env;
+ protected final BlazeAndroidBinaryRunConfigurationState configState;
+ protected final ConsoleProvider consoleProvider;
+ protected final ApplicationIdProvider applicationIdProvider;
+ protected final ApkBuildStep buildStep;
+ private final String launchId;
+
+ public BlazeAndroidBinaryMobileInstallRunContextBase(
+ Project project,
+ AndroidFacet facet,
+ RunConfiguration runConfiguration,
+ ExecutionEnvironment env,
+ BlazeAndroidBinaryRunConfigurationState configState,
+ ApkBuildStep buildStep,
+ String launchId) {
+ this.project = project;
+ this.facet = facet;
+ this.runConfiguration = runConfiguration;
+ this.env = env;
+ this.configState = configState;
+ this.consoleProvider = new BlazeAndroidBinaryConsoleProvider(project);
+ this.buildStep = buildStep;
+ this.applicationIdProvider = new BlazeAndroidBinaryApplicationIdProvider(buildStep);
+ this.launchId = launchId;
+ }
+
+ @Override
+ public BlazeAndroidDeviceSelector getDeviceSelector() {
+ return new BlazeAndroidDeviceSelector.NormalDeviceSelector();
+ }
+
+ @Override
+ public void augmentLaunchOptions(LaunchOptions.Builder options) {
+ options
+ .setDeploy(buildStep.needsIdeDeploy())
+ .setOpenLogcatAutomatically(configState.showLogcatAutomatically());
+ // This is needed for compatibility with #api211
+ options.addExtraOptions(
+ ImmutableMap.of("android.profilers.state", configState.getProfilerState()));
+ }
+
+ @Override
+ public ConsoleProvider getConsoleProvider() {
+ return consoleProvider;
+ }
+
+ @Override
+ public ApplicationIdProvider getApplicationIdProvider() {
+ return applicationIdProvider;
+ }
+
+ @Override
+ public ApkBuildStep getBuildStep() {
+ return buildStep;
+ }
+
+ @Override
+ public ProfilerState getProfileState() {
+ return configState.getProfilerState();
+ }
+
+ @Override
+ public ImmutableList