Correctly handle exports in AndroidStudioInfoAspect.

* Propagate aspects via exports property
* Treat exports as direct dependencies

--
MOS_MIGRATED_REVID=104350818
diff --git a/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java b/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java
index b6badb5..dfab195 100644
--- a/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java
@@ -22,6 +22,7 @@
 import com.google.devtools.build.lib.actions.ActionOwner;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.analysis.AnalysisUtils;
 import com.google.devtools.build.lib.analysis.Aspect;
 import com.google.devtools.build.lib.analysis.Aspect.Builder;
 import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
@@ -87,6 +88,7 @@
   public AspectDefinition getDefinition() {
     return new AspectDefinition.Builder(NAME)
         .attributeAspect("deps", AndroidStudioInfoAspect.class)
+        .attributeAspect("exports", AndroidStudioInfoAspect.class)
         .build();
   }
 
@@ -97,33 +99,31 @@
 
     AndroidStudioInfoFilesProvider.Builder providerBuilder =
         new AndroidStudioInfoFilesProvider.Builder();
-    // Collect ide build files and calculate dependencies.
     NestedSetBuilder<Label> dependenciesBuilder = NestedSetBuilder.stableOrder();
 
-    // todo(dslomov,tomlu): following current build info logic, this code enumerates dependencies
-    // directly by iterating over deps attribute. The more robust way to do this might be
-    // to iterate classpath as provided to build action.
+    ImmutableList.Builder<TransitiveInfoCollection> prerequisitesBuilder = ImmutableList.builder();
     if (ruleContext.attributes().has("deps", BuildType.LABEL_LIST)) {
-      Iterable<AndroidStudioInfoFilesProvider> androidStudioInfoFilesProviders =
-          ruleContext.getPrerequisites("deps", Mode.TARGET, AndroidStudioInfoFilesProvider.class);
-      for (AndroidStudioInfoFilesProvider depProvider : androidStudioInfoFilesProviders) {
-        providerBuilder.ideBuildFilesBuilder().addTransitive(depProvider.getIdeBuildFiles());
-        providerBuilder.transitiveDependenciesBuilder().addTransitive(
-            depProvider.getTransitiveDependencies());
-        providerBuilder.transitiveResourcesBuilder().addTransitive(
-            depProvider.getTransitiveResources());
-      }
-      List<? extends TransitiveInfoCollection> deps =
-          ruleContext.getPrerequisites("deps", Mode.TARGET);
-      for (TransitiveInfoCollection dep : deps) {
-        dependenciesBuilder.add(dep.getLabel());
-      }
+      prerequisitesBuilder.addAll(ruleContext.getPrerequisites("deps", Mode.TARGET));
+    }
+    if (ruleContext.attributes().has("exports", BuildType.LABEL_LIST)) {
+      prerequisitesBuilder.addAll(ruleContext.getPrerequisites("exports", Mode.TARGET));
+    }
+    List<TransitiveInfoCollection> prerequisites = prerequisitesBuilder.build();
 
-      Iterable<JavaExportsProvider> javaExportsProviders = ruleContext
-          .getPrerequisites("deps", Mode.TARGET, JavaExportsProvider.class);
-      for (JavaExportsProvider javaExportsProvider : javaExportsProviders) {
-        dependenciesBuilder.addTransitive(javaExportsProvider.getTransitiveExports());
-      }
+    for (AndroidStudioInfoFilesProvider depProvider :
+        AnalysisUtils.getProviders(prerequisites, AndroidStudioInfoFilesProvider.class)) {
+      providerBuilder.ideBuildFilesBuilder().addTransitive(depProvider.getIdeBuildFiles());
+      providerBuilder.transitiveDependenciesBuilder().addTransitive(
+          depProvider.getTransitiveDependencies());
+      providerBuilder.transitiveResourcesBuilder().addTransitive(
+          depProvider.getTransitiveResources());
+    }
+    for (TransitiveInfoCollection dep : prerequisites) {
+      dependenciesBuilder.add(dep.getLabel());
+    }
+    for (JavaExportsProvider javaExportsProvider :
+        AnalysisUtils.getProviders(prerequisites, JavaExportsProvider.class)) {
+      dependenciesBuilder.addTransitive(javaExportsProvider.getTransitiveExports());
     }
 
     NestedSet<Label> directDependencies = dependenciesBuilder.build();
diff --git a/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTest.java b/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTest.java
index 8f68ead..0e44047 100644
--- a/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTest.java
+++ b/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTest.java
@@ -246,7 +246,6 @@
         "java_library(",
         "    name = 'complex',",
         "    srcs = ['complex/Complex.java'],",
-        "    deps = [':simple'],",
         "    exports = [':simple'],",
         ")",
         "java_library(",
@@ -261,13 +260,17 @@
     getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos);
     getRuleInfoAndVerifyLabel("//com/google/example:complex", ruleIdeInfos);
 
+    RuleIdeInfo complexRuleIdeInfo = getRuleInfoAndVerifyLabel("//com/google/example:complex",
+        ruleIdeInfos);
     RuleIdeInfo extraComplexRuleIdeInfo = getRuleInfoAndVerifyLabel(target, ruleIdeInfos);
 
-    assertThat(relativePathsForSourcesOf(extraComplexRuleIdeInfo))
-        .containsExactly("com/google/example/extracomplex/ExtraComplex.java");
+    assertThat(complexRuleIdeInfo.getDependenciesList())
+        .containsExactly("//com/google/example:simple");
+    assertThat(complexRuleIdeInfo.getTransitiveDependenciesList())
+        .containsExactly("//com/google/example:simple");
+
     assertThat(extraComplexRuleIdeInfo.getDependenciesList())
         .containsExactly("//com/google/example:complex", "//com/google/example:simple");
-
     assertThat(extraComplexRuleIdeInfo.getTransitiveDependenciesList())
         .containsExactly(
             "//com/google/example:complex",
@@ -284,13 +287,11 @@
         "java_library(",
         "    name = 'complex',",
         "    srcs = ['complex/Complex.java'],",
-        "    deps = [':simple'],",
         "    exports = [':simple'],",
         ")",
         "java_library(",
         "    name = 'extracomplex',",
         "    srcs = ['extracomplex/ExtraComplex.java'],",
-        "    deps = [':complex'],",
         "    exports = [':complex'],",
         ")",
         "java_library(",
@@ -374,12 +375,30 @@
     Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:lib");
     RuleIdeInfo libInfo = getRuleInfoAndVerifyLabel("//com/google/example:lib", ruleIdeInfos);
     RuleIdeInfo impInfo = getRuleInfoAndVerifyLabel("//com/google/example:imp", ruleIdeInfos);
+
     assertThat(impInfo.getKind()).isEqualTo(Kind.JAVA_IMPORT);
     assertThat(impInfo.getDependenciesList()).containsExactly("//com/google/example:foobar");
     assertThat(libInfo.getDependenciesList())
         .containsExactly("//com/google/example:imp", "//com/google/example:foobar");
   }
 
+  public void testAspectIsPropagatedAcrossExports() throws Exception {
+    scratch.file(
+        "com/google/example/BUILD",
+        "java_library(",
+        "   name = 'foobar',",
+        "   srcs = ['FooBar.java'],",
+        ")",
+        "java_library(",
+        "   name = 'lib',",
+        "   srcs = ['Lib.java'],",
+        "   exports = [':foobar'],",
+        ")");
+
+    Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:lib");
+    getRuleInfoAndVerifyLabel("//com/google/example:foobar", ruleIdeInfos);
+  }
+
   public void testJavaTest() throws Exception {
     scratch.file(
         "java/com/google/example/BUILD",
@@ -495,7 +514,7 @@
     assertThat(relativePathsForSourcesOf(ruleInfo)).containsExactly("com/google/example/Main.java");
     assertThat(transform(ruleInfo.getJavaRuleIdeInfo().getJarsList(), LIBRARY_ARTIFACT_TO_STRING))
         .containsExactly(jarString("com/google/example",
-                "libb.jar", "libb-ijar.jar", "libb-src.jar"));
+            "libb.jar", "libb-ijar.jar", "libb-src.jar"));
     assertThat(
             transform(
                 ruleInfo.getAndroidRuleIdeInfo().getResourcesList(), ARTIFACT_TO_RELATIVE_PATH))