Add java_toolchain to IDE aspect output.

--
MOS_MIGRATED_REVID=123858617
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 9429249..1b95ca3 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
@@ -51,6 +51,7 @@
 import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.CRuleIdeInfo;
 import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.CToolchainIdeInfo;
 import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.JavaRuleIdeInfo;
+import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.JavaToolchainIdeInfo;
 import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.LibraryArtifact;
 import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.RuleIdeInfo;
 import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.RuleIdeInfo.Kind;
@@ -74,6 +75,7 @@
 import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider;
 import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider.OutputJar;
 import com.google.devtools.build.lib.rules.java.JavaSourceInfoProvider;
+import com.google.devtools.build.lib.rules.java.JavaToolchainProvider;
 import com.google.devtools.build.lib.syntax.Type;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.protobuf.MessageLite;
@@ -134,6 +136,8 @@
     builder.add(new PrerequisiteAttr("exports", BuildType.LABEL_LIST));
     // From android_test
     builder.add(new PrerequisiteAttr("binary_under_test", BuildType.LABEL));
+    // from java_* rules
+    builder.add(new PrerequisiteAttr(":java_toolchain", BuildType.LABEL));
     // from cc_* rules
     builder.add(new PrerequisiteAttr(":cc_toolchain", BuildType.LABEL));
 
@@ -384,6 +388,14 @@
       outputBuilder.setTestInfo(builder);
     }
 
+    // Java toolchain rule
+    JavaToolchainProvider javaToolchainProvider = base.getProvider(JavaToolchainProvider.class);
+    if (javaToolchainProvider != null) {
+      outputBuilder.setJavaToolchainIdeInfo(JavaToolchainIdeInfo.newBuilder()
+          .setSourceVersion(javaToolchainProvider.getSourceVersion())
+          .setTargetVersion(javaToolchainProvider.getTargetVersion()));
+    }
+
     androidStudioInfoSemantics.augmentRuleInfo(
         outputBuilder, base, ruleContext, ideResolveArtifacts);
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchain.java
index 39eedaa..2b13983 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchain.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchain.java
@@ -78,6 +78,8 @@
             genClass,
             ijar);
     RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext)
+        .addSkylarkTransitiveInfo(JavaToolchainSkylarkApiProvider.NAME,
+            new JavaToolchainSkylarkApiProvider())
         .add(JavaToolchainProvider.class, provider)
         .setFilesToBuild(new NestedSetBuilder<Artifact>(Order.STABLE_ORDER).build())
         .add(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY));
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainSkylarkApiProvider.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainSkylarkApiProvider.java
new file mode 100644
index 0000000..9d4435b
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainSkylarkApiProvider.java
@@ -0,0 +1,57 @@
+// Copyright 2015 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.devtools.build.lib.rules.java;
+
+import com.google.devtools.build.lib.rules.SkylarkApiProvider;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+
+/**
+ * A class that exposes the java_toolchain providers to Skylark. It is intended to provide a
+ * simple and stable interface for Skylark users.
+ */
+@SkylarkModule(
+    name = "JavaToolchainSkylarkApiProvider",
+    doc = "Provides access to information about the Java toolchain rule. "
+    + "Accessible as a 'java_toolchain' field on a Target struct.")
+public final class JavaToolchainSkylarkApiProvider extends SkylarkApiProvider {
+  /** The name of the field in Skylark used to access this class. */
+  public static final String NAME = "java_toolchain";
+
+  /** @return the input Java language level */
+  @SkylarkCallable(
+      name = "source_version",
+      doc = "The java source version.",
+      structField = true
+  )
+  public String getSourceVersion() {
+    JavaToolchainProvider javaToolchainProvider =
+        getInfo().getProvider(JavaToolchainProvider.class);
+    return javaToolchainProvider.getSourceVersion();
+  }
+
+  /** @return the target Java language level */
+  @SkylarkCallable(
+      name = "target_version",
+      doc = "The java target version.",
+      structField = true
+  )
+  public String getTargetVersion() {
+    JavaToolchainProvider javaToolchainProvider =
+        getInfo().getProvider(JavaToolchainProvider.class);
+    return javaToolchainProvider.getTargetVersion();
+  }
+
+}
diff --git a/src/main/protobuf/android_studio_ide_info.proto b/src/main/protobuf/android_studio_ide_info.proto
index 04b073e..8c48e19 100644
--- a/src/main/protobuf/android_studio_ide_info.proto
+++ b/src/main/protobuf/android_studio_ide_info.proto
@@ -102,6 +102,11 @@
   string size = 1;
 }
 
+message JavaToolchainIdeInfo {
+  string source_version = 1;
+  string target_version = 2;
+}
+
 message RuleIdeInfo {
   enum Kind {
     ANDROID_BINARY = 0;
@@ -147,4 +152,5 @@
   TestInfo test_info = 15;
 
   ProtoLibraryLegacyJavaIdeInfo proto_library_legacy_java_ide_info = 16;
+  JavaToolchainIdeInfo java_toolchain_ide_info = 17;
 }
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 a8bdeb1..f099c9e 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
@@ -18,6 +18,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
+import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.ArtifactLocation;
 import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.CRuleIdeInfo;
 import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.CToolchainIdeInfo;
@@ -33,6 +34,7 @@
 import org.junit.runners.JUnit4;
 
 import java.nio.file.Paths;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -52,7 +54,6 @@
             "    srcs = ['simple/Simple.java']",
             ")");
     Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple");
-    assertThat(ruleIdeInfos.size()).isEqualTo(1);
     RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel(
         "//com/google/example:simple", ruleIdeInfos);
     ArtifactLocation location = ruleIdeInfo.getBuildFileArtifactLocation();
@@ -65,7 +66,6 @@
     }
     assertThat(ruleIdeInfo.getKind()).isEqualTo(Kind.JAVA_LIBRARY);
     assertThat(ruleIdeInfo.getKindString()).isEqualTo("java_library");
-    assertThat(ruleIdeInfo.getDependenciesCount()).isEqualTo(0);
     assertThat(relativePathsForJavaSourcesOf(ruleIdeInfo))
         .containsExactly("com/google/example/simple/Simple.java");
     assertThat(
@@ -76,8 +76,7 @@
     assertThat(getIdeResolveFiles()).containsExactly(
         "com/google/example/libsimple.jar",
         "com/google/example/libsimple-ijar.jar",
-        "com/google/example/libsimple-src.jar"
-    );
+        "com/google/example/libsimple-src.jar");
     assertThat(ruleIdeInfo.getJavaRuleIdeInfo().getJdeps().getRelativePath())
         .isEqualTo("com/google/example/libsimple.jdeps");
   }
@@ -95,7 +94,6 @@
         "    srcs = ['simple/Simple.java']",
         ")");
     Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple");
-    assertThat(ruleIdeInfos.size()).isEqualTo(1);
     RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel(
         "//com/google/example:simple", ruleIdeInfos);
     
@@ -122,7 +120,6 @@
         "    srcs = [':gen_sources']",
         ")");
     Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple");
-    assertThat(ruleIdeInfos.size()).isEqualTo(1);
     RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel(
         "//com/google/example:simple", ruleIdeInfos);
     assertThat(ruleIdeInfo.getJavaRuleIdeInfo().hasPackageManifest()).isFalse();
@@ -143,7 +140,6 @@
         ")");
 
     Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:complex");
-    assertThat(ruleIdeInfos.size()).isEqualTo(2);
 
     getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos);
     RuleIdeInfo complexRuleIdeInfo = getRuleInfoAndVerifyLabel(
@@ -152,7 +148,7 @@
     assertThat(relativePathsForJavaSourcesOf(complexRuleIdeInfo))
         .containsExactly("com/google/example/complex/Complex.java");
     assertThat(complexRuleIdeInfo.getDependenciesList())
-        .containsExactly("//com/google/example:simple");
+        .contains("//com/google/example:simple");
   }
   
   @Test
@@ -174,7 +170,6 @@
         "    deps = [':complex']",
         ")");
     Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:extracomplex");
-    assertThat(ruleIdeInfos.size()).isEqualTo(3);
 
     getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos);
     getRuleInfoAndVerifyLabel("//com/google/example:complex", ruleIdeInfos);
@@ -185,7 +180,7 @@
     assertThat(relativePathsForJavaSourcesOf(extraComplexRuleIdeInfo))
         .containsExactly("com/google/example/extracomplex/ExtraComplex.java");
     assertThat(extraComplexRuleIdeInfo.getDependenciesList())
-        .containsExactly("//com/google/example:complex");
+        .contains("//com/google/example:complex");
 
     assertThat(getIdeResolveFiles()).containsExactly(
         "com/google/example/libextracomplex.jar",
@@ -196,8 +191,7 @@
         "com/google/example/libcomplex-src.jar",
         "com/google/example/libsimple.jar",
         "com/google/example/libsimple-ijar.jar",
-        "com/google/example/libsimple-src.jar"
-    );
+        "com/google/example/libsimple-src.jar");
   }
 
   @Test
@@ -224,7 +218,6 @@
         "    deps = [':complex', ':complex1']",
         ")");
     Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:extracomplex");
-    assertThat(ruleIdeInfos.size()).isEqualTo(4);
 
     getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos);
     getRuleInfoAndVerifyLabel("//com/google/example:complex", ruleIdeInfos);
@@ -235,8 +228,9 @@
 
     assertThat(relativePathsForJavaSourcesOf(extraComplexRuleIdeInfo))
         .containsExactly("com/google/example/extracomplex/ExtraComplex.java");
-    assertThat(extraComplexRuleIdeInfo.getDependenciesList())
-        .containsExactly("//com/google/example:complex", "//com/google/example:complex1");
+    assertThat(extraComplexRuleIdeInfo.getDependenciesList()).containsAllOf(
+        "//com/google/example:complex",
+        "//com/google/example:complex1");
   }
 
   @Test
@@ -258,7 +252,6 @@
         "    deps = [':complex']",
         ")");
     Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:extracomplex");
-    assertThat(ruleIdeInfos.size()).isEqualTo(3);
 
     getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos);
     getRuleInfoAndVerifyLabel("//com/google/example:complex", ruleIdeInfos);
@@ -269,11 +262,11 @@
         "//com/google/example:extracomplex", ruleIdeInfos);
 
     assertThat(complexRuleIdeInfo.getDependenciesList())
-        .containsExactly("//com/google/example:simple");
+        .contains("//com/google/example:simple");
 
-    assertThat(extraComplexRuleIdeInfo.getDependenciesList())
-        .containsExactly("//com/google/example:simple", "//com/google/example:complex")
-        .inOrder();
+    assertThat(extraComplexRuleIdeInfo.getDependenciesList()).containsAllOf(
+        "//com/google/example:simple",
+        "//com/google/example:complex");
     assertThat(getIdeResolveFiles()).containsExactly(
         "com/google/example/libextracomplex.jar",
         "com/google/example/libextracomplex-ijar.jar",
@@ -283,8 +276,7 @@
         "com/google/example/libcomplex-src.jar",
         "com/google/example/libsimple.jar",
         "com/google/example/libsimple-ijar.jar",
-        "com/google/example/libsimple-src.jar"
-    );
+        "com/google/example/libsimple-src.jar");
   }
 
   @Test
@@ -312,7 +304,6 @@
         ")"
     );
     Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:megacomplex");
-    assertThat(ruleIdeInfos.size()).isEqualTo(4);
 
     getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos);
     getRuleInfoAndVerifyLabel("//com/google/example:complex", ruleIdeInfos);
@@ -323,12 +314,10 @@
 
     assertThat(relativePathsForJavaSourcesOf(megaComplexRuleIdeInfo))
         .containsExactly("com/google/example/megacomplex/MegaComplex.java");
-    assertThat(megaComplexRuleIdeInfo.getDependenciesList())
-        .containsExactly(
-            "//com/google/example:simple",
-            "//com/google/example:complex",
-            "//com/google/example:extracomplex")
-        .inOrder();
+    assertThat(megaComplexRuleIdeInfo.getDependenciesList()).containsAllOf(
+        "//com/google/example:simple",
+        "//com/google/example:complex",
+        "//com/google/example:extracomplex");
   }
 
   @Test
@@ -349,9 +338,10 @@
     Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:lib");
     final 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.getKindString()).isEqualTo("java_import");
-    assertThat(libInfo.getDependenciesList()).containsExactly("//com/google/example:imp");
+    assertThat(libInfo.getDependenciesList()).contains("//com/google/example:imp");
 
     JavaRuleIdeInfo javaRuleIdeInfo = impInfo.getJavaRuleIdeInfo();
     assertThat(javaRuleIdeInfo).isNotNull();
@@ -368,8 +358,7 @@
         "com/google/example/_ijar/imp/com/google/example/b-ijar.jar",
         "com/google/example/liblib.jar",
         "com/google/example/liblib-ijar.jar",
-        "com/google/example/liblib-src.jar"
-    );
+        "com/google/example/liblib-src.jar");
   }
 
   @Test
@@ -398,10 +387,10 @@
 
     assertThat(impInfo.getKind()).isEqualTo(Kind.JAVA_IMPORT);
     assertThat(impInfo.getKindString()).isEqualTo("java_import");
-    assertThat(impInfo.getDependenciesList()).containsExactly("//com/google/example:foobar");
-    assertThat(libInfo.getDependenciesList())
-        .containsExactly("//com/google/example:foobar", "//com/google/example:imp")
-        .inOrder();
+    assertThat(impInfo.getDependenciesList()).contains("//com/google/example:foobar");
+    assertThat(libInfo.getDependenciesList()).containsAllOf(
+        "//com/google/example:foobar",
+        "//com/google/example:imp");
   }
 
   @Test
@@ -459,8 +448,7 @@
     assertThat(getIdeResolveFiles()).containsExactly(
         "com/google/example/_ijar/imp/com/google/example/gen_jar-ijar.jar",
         "com/google/example/gen_jar.jar",
-        "com/google/example/gen_srcjar.jar"
-    );
+        "com/google/example/gen_srcjar.jar");
   }
 
   @Test
@@ -504,7 +492,6 @@
     assertThat(relativePathsForJavaSourcesOf(testInfo))
         .containsExactly("java/com/google/example/FooBarTest.java");
     assertThat(testInfo.getDependenciesList()).contains("//java/com/google/example:foobar");
-    assertThat(testInfo.getDependenciesList()).hasSize(2);
     assertThat(transform(testInfo.getJavaRuleIdeInfo().getJarsList(), LIBRARY_ARTIFACT_TO_STRING))
         .containsExactly(jarString("java/com/google/example",
             "FooBarTest.jar", null, "FooBarTest-src.jar"));
@@ -514,8 +501,7 @@
         "java/com/google/example/libfoobar-ijar.jar",
         "java/com/google/example/libfoobar-src.jar",
         "java/com/google/example/FooBarTest.jar",
-        "java/com/google/example/FooBarTest-src.jar"
-    );
+        "java/com/google/example/FooBarTest-src.jar");
     assertThat(testInfo.getJavaRuleIdeInfo().getJdeps().getRelativePath())
         .isEqualTo("java/com/google/example/FooBarTest.jdeps");
 
@@ -539,12 +525,13 @@
     Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:foobar-exe");
     RuleIdeInfo binaryInfo = getRuleInfoAndVerifyLabel(
         "//com/google/example:foobar-exe", ruleIdeInfos);
+
     assertThat(binaryInfo.getKind()).isEqualTo(Kind.JAVA_BINARY);
     assertThat(binaryInfo.getKindString()).isEqualTo("java_binary");
     assertThat(relativePathsForJavaSourcesOf(binaryInfo))
         .containsExactly("com/google/example/FooBarMain.java");
     assertThat(binaryInfo.getDependenciesList()).contains("//com/google/example:foobar");
-    assertThat(binaryInfo.getDependenciesList()).hasSize(2);
+
     assertThat(transform(binaryInfo.getJavaRuleIdeInfo().getJarsList(), LIBRARY_ARTIFACT_TO_STRING))
         .containsExactly(jarString("com/google/example",
             "foobar-exe.jar", null, "foobar-exe-src.jar"));
@@ -554,13 +541,56 @@
         "com/google/example/libfoobar-ijar.jar",
         "com/google/example/libfoobar-src.jar",
         "com/google/example/foobar-exe.jar",
-        "com/google/example/foobar-exe-src.jar"
-    );
+        "com/google/example/foobar-exe-src.jar");
     assertThat(binaryInfo.getJavaRuleIdeInfo().getJdeps().getRelativePath())
         .isEqualTo("com/google/example/foobar-exe.jdeps");
   }
 
   @Test
+  public void testJavaToolchain() throws Exception {
+    scratch.file(
+        "com/google/example/BUILD",
+        "java_library(",
+        "    name = 'a',",
+        "    srcs = ['A.java'],",
+        "    deps = [':b'],",
+        ")",
+        "java_library(",
+        "    name = 'b',",
+        "    srcs = ['B.java'],",
+        ")");
+
+    Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:a");
+
+    List<RuleIdeInfo> javaToolChainInfos = findJavaToolchain(ruleIdeInfos);
+    assertThat(javaToolChainInfos).hasSize(1); // Ensure we don't get one instance per java_library
+    RuleIdeInfo toolChainInfo = Iterables.getOnlyElement(javaToolChainInfos);
+    assertThat(toolChainInfo.getJavaToolchainIdeInfo().getSourceVersion()).isNotEmpty();
+    assertThat(toolChainInfo.getJavaToolchainIdeInfo().getTargetVersion()).isNotEmpty();
+
+    RuleIdeInfo a = ruleIdeInfos.get("//com/google/example:a");
+    assertThat(a.getDependenciesList()).containsAllOf(
+        "//com/google/example:b",
+        toolChainInfo.getLabel());
+  }
+
+  @Test
+  public void testJavaToolchainForAndroid() throws Exception {
+    scratch.file(
+        "com/google/example/BUILD",
+        "android_library(",
+        "    name = 'a',",
+        "    srcs = ['A.java'],",
+        ")");
+
+    Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:a");
+    assertThat(ruleIdeInfos).hasSize(2);
+
+    List<RuleIdeInfo> javaToolChainInfos = findJavaToolchain(ruleIdeInfos);
+    assertThat(javaToolChainInfos).hasSize(1);
+  }
+
+  @Test
   public void testAndroidLibrary() throws Exception {
     scratch.file(
         "com/google/example/BUILD",
@@ -597,7 +627,7 @@
         .isEqualTo("com/google/example/AndroidManifest.xml");
     assertThat(ruleInfo.getAndroidRuleIdeInfo().getJavaPackage()).isEqualTo("com.google.example");
 
-    assertThat(ruleInfo.getDependenciesList()).containsExactly("//com/google/example:l1");
+    assertThat(ruleInfo.getDependenciesList()).contains("//com/google/example:l1");
     assertThat(getIdeResolveFiles()).containsExactly(
         "com/google/example/libl.jar",
         "com/google/example/libl-ijar.jar",
@@ -609,8 +639,7 @@
         "com/google/example/libl1-src.jar",
         "com/google/example/l1_resources.jar",
         "com/google/example/l1_resources-ijar.jar",
-        "com/google/example/l1_resources-src.jar"
-    );
+        "com/google/example/l1_resources-src.jar");
     assertThat(ruleInfo.getJavaRuleIdeInfo().getJdeps().getRelativePath())
         .isEqualTo("com/google/example/libl.jdeps");
   }
@@ -635,6 +664,7 @@
         ")");
     Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:b");
     RuleIdeInfo ruleInfo = getRuleInfoAndVerifyLabel("//com/google/example:b", ruleIdeInfos);
+
     assertThat(ruleInfo.getKind()).isEqualTo(Kind.ANDROID_BINARY);
     assertThat(ruleInfo.getKindString()).isEqualTo("android_binary");
     assertThat(relativePathsForJavaSourcesOf(ruleInfo)).containsExactly("com/google/example/Main.java");
@@ -657,7 +687,6 @@
 
 
     assertThat(ruleInfo.getDependenciesList()).contains("//com/google/example:l1");
-    assertThat(ruleInfo.getDependenciesList()).hasSize(2);
 
     assertThat(getIdeResolveFiles()).containsExactly(
         "com/google/example/libb.jar",
@@ -670,8 +699,7 @@
         "com/google/example/libl1-src.jar",
         "com/google/example/l1_resources.jar",
         "com/google/example/l1_resources-ijar.jar",
-        "com/google/example/l1_resources-src.jar"
-    );
+        "com/google/example/l1_resources-src.jar");
     assertThat(ruleInfo.getJavaRuleIdeInfo().getJdeps().getRelativePath())
         .isEqualTo("com/google/example/libb.jdeps");
   }
@@ -738,8 +766,7 @@
         "java/com/google/example/libhas_idl-ijar.jar",
         "java/com/google/example/libhas_idl-src.jar",
         "java/com/google/example/libhas_idl-idl.jar",
-        "java/com/google/example/libhas_idl-idl.srcjar"
-    );
+        "java/com/google/example/libhas_idl-idl.srcjar");
   }
 
   @Test
@@ -763,8 +790,7 @@
         "com/google/example/lib_resources.jar",
         "com/google/example/lib_resources-ijar.jar",
         "com/google/example/lib_resources-src.jar",
-        "com/google/example/AndroidManifest.xml"
-    );
+        "com/google/example/AndroidManifest.xml");
   }
 
   @Test
@@ -817,8 +843,7 @@
         "java/com/google/example/libtest-ijar.jar",
         "java/com/google/example/libtest-src.jar",
         "java/com/google/example/libtest-gen.jar",
-        "java/com/google/example/libtest-gensrc.jar"
-    );
+        "java/com/google/example/libtest-gensrc.jar");
   }
 
   @Test
@@ -856,7 +881,7 @@
     RuleIdeInfo ruleInfo = getRuleInfoAndVerifyLabel(
         "//java/com/google/example:super", ruleIdeInfos);
 
-    assertThat(ruleInfo.getDependenciesList()).containsExactly(
+    assertThat(ruleInfo.getDependenciesList()).containsAllOf(
         "//java/com/google/example:forward",
         "//java/com/google/example:lib");
   }
@@ -911,8 +936,7 @@
     // Fails if aspect was not propagated
     getRuleInfoAndVerifyLabel("//com/google/example:foobar", ruleIdeInfos);
 
-    RuleIdeInfo libInfo = getRuleInfoAndVerifyLabel("//com/google/example:foobar", ruleIdeInfos);
-    assertThat(libInfo.getDependenciesList()).isEmpty();
+    getRuleInfoAndVerifyLabel("//com/google/example:foobar", ruleIdeInfos);
   }
 
   @Test
@@ -1312,11 +1336,10 @@
         "    hdrs = ['simple/simple.h'],",
         ")");
     Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:androidlib");
-    assertThat(ruleIdeInfos.size()).isEqualTo(3);
     RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel(
         "//com/google/example:androidlib", ruleIdeInfos);
 
-    assertThat(ruleIdeInfo.getDependenciesList()).containsExactly("//com/google/example:simple");
+    assertThat(ruleIdeInfo.getDependenciesList()).contains("//com/google/example:simple");
   }
 
   @Test
diff --git a/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTestBase.java b/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTestBase.java
index dfff8a8..41f3e96 100644
--- a/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTestBase.java
+++ b/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTestBase.java
@@ -21,7 +21,6 @@
 
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import com.google.common.eventbus.EventBus;
 import com.google.devtools.build.lib.actions.Action;
@@ -196,18 +195,18 @@
       AndroidStudioInfoFilesProvider provider =
           configuredAspect.getProvider(AndroidStudioInfoFilesProvider.class);
       Iterable<Artifact> artifacts = provider.getIdeInfoFiles();
-      ImmutableMap.Builder<String, RuleIdeInfo> builder = ImmutableMap.builder();
+      Map<String, RuleIdeInfo> ruleIdeInfos = new HashMap<>();
       for (Artifact artifact : artifacts) {
         Action generatingAction = getGeneratingAction(artifact);
         if (generatingAction instanceof BinaryFileWriteAction) {
           BinaryFileWriteAction writeAction = (BinaryFileWriteAction) generatingAction;
           RuleIdeInfo ruleIdeInfo = RuleIdeInfo.parseFrom(writeAction.getSource().openStream());
-          builder.put(ruleIdeInfo.getLabel(), ruleIdeInfo);
+          ruleIdeInfos.put(ruleIdeInfo.getLabel(), ruleIdeInfo);
         } else {
           verifyPackageManifestSpawnAction(generatingAction);
         }
       }
-      return builder.build();
+      return ruleIdeInfos;
     } else {
       BuildView.AnalysisResult analysisResult = update(
           ImmutableList.of(target),
@@ -267,5 +266,15 @@
     return getOutputGroupResult(AndroidStudioInfoAspect.IDE_RESOLVE);
   }
 
+  protected static List<RuleIdeInfo> findJavaToolchain(Map<String, RuleIdeInfo> ruleIdeInfos) {
+    List<RuleIdeInfo> result = Lists.newArrayList();
+    for (RuleIdeInfo ruleIdeInfo : ruleIdeInfos.values()) {
+      if (ruleIdeInfo.getKindString().equals("java_toolchain")) {
+        result.add(ruleIdeInfo);
+      }
+    }
+    return result;
+  }
+
   protected abstract boolean isNativeTest();
 }
diff --git a/src/test/java/com/google/devtools/build/lib/ideinfo/intellij_info.bzl b/src/test/java/com/google/devtools/build/lib/ideinfo/intellij_info.bzl
index 7eca57a..c73e7f8 100644
--- a/src/test/java/com/google/devtools/build/lib/ideinfo/intellij_info.bzl
+++ b/src/test/java/com/google/devtools/build/lib/ideinfo/intellij_info.bzl
@@ -17,86 +17,83 @@
 # A map to convert rule names to a RuleIdeInfo.Kind
 # Deprecated - only here for backwards compatibility with the tests
 _kind_to_kind_id = {
-  "android_binary"  : 0,
-  "android_library" : 1,
-  "android_test" :    2,
-  "android_robolectric_test" : 3,
-  "java_library" : 4,
-  "java_test" : 5,
-  "java_import" : 6,
-  "java_binary" : 7,
-  "proto_library" : 8,
-  "android_sdk" : 9,
-  "java_plugin" : 10,
-  "android_resources" : 11,
-  "cc_library" : 12,
-  "cc_binary" : 13,
-  "cc_test" : 14,
-  "cc_inc_library" : 15,
-  "cc_toolchain": 16,
-  "java_wrap_cc": 17,
+    "android_binary": 0,
+    "android_library": 1,
+    "android_test": 2,
+    "android_robolectric_test": 3,
+    "java_library": 4,
+    "java_test": 5,
+    "java_import": 6,
+    "java_binary": 7,
+    "proto_library": 8,
+    "android_sdk": 9,
+    "java_plugin": 10,
+    "android_resources": 11,
+    "cc_library": 12,
+    "cc_binary": 13,
+    "cc_test": 14,
+    "cc_inc_library": 15,
+    "cc_toolchain": 16,
+    "java_wrap_cc": 17,
 }
 
 # A map to convert JavaApiFlavor to ProtoLibraryLegacyJavaIdeInfo.ApiFlavor
 _api_flavor_to_id = {
-  "FLAVOR_NONE": 0,
-  "FLAVOR_IMMUTABLE": 1,
-  "FLAVOR_MUTABLE": 2,
-  "FLAVOR_BOTH": 3,
+    "FLAVOR_NONE": 0,
+    "FLAVOR_IMMUTABLE": 1,
+    "FLAVOR_MUTABLE": 2,
+    "FLAVOR_BOTH": 3,
 }
 
-_unrecognized_rule = -1;
+_unrecognized_rule = -1
 
 def get_kind_legacy(target, ctx):
   """ Gets kind of a rule given a target and rule context.
   """
   return _kind_to_kind_id.get(ctx.rule.kind, _unrecognized_rule)
 
-
 # Compile-time dependency attributes, grouped by type.
 DEPS = struct(
     label = [
-      "binary_under_test", #  From android_test
-      "java_lib",# From proto_library
-      "_proto1_java_lib", # From proto_library
-      "_junit", # From android_robolectric_test
-      "_cc_toolchain", # From C rules
-      "module_target",
+        "binary_under_test",  #  From android_test
+        "java_lib",  # From proto_library
+        "_proto1_java_lib",  # From proto_library
+        "_junit",  # From android_robolectric_test
+        "_cc_toolchain",  # From C rules
+        "module_target",
+        "_java_toolchain",  # From java rules
     ],
     label_list = [
-      "deps",
-      "exports",
-      "_robolectric", # From android_robolectric_test
+        "deps",
+        "exports",
+        "_robolectric",  # From android_robolectric_test
     ],
 )
 
-
 # Run-time dependency attributes, grouped by type.
 RUNTIME_DEPS = struct(
     label = [
-      # todo(dslomov,tomlu): resources are tricky since they are sometimes labels and sometimes label_lists.
-      # "resources"
+        # todo(dslomov,tomlu): resources are tricky since they are sometimes labels and sometimes label_lists.
+        # "resources"
     ],
     label_list = [
-      "runtime_deps",
-    ]
+        "runtime_deps",
+    ],
 )
 
 # All dependency attributes along which the aspect propagates, grouped by type.
 ALL_DEPS = struct(
-  label = DEPS.label + RUNTIME_DEPS.label,
-  label_list = DEPS.label_list + RUNTIME_DEPS.label_list,
+    label = DEPS.label + RUNTIME_DEPS.label,
+    label_list = DEPS.label_list + RUNTIME_DEPS.label_list,
 )
 
 def struct_omit_none(**kwargs):
-    """ A replacement for standard `struct` function that omits the fields with None value.
-    """
+    """A replacement for standard `struct` function that omits the fields with None value."""
     d = {name: kwargs[name] for name in kwargs if kwargs[name] != None}
     return struct(**d)
 
 def artifact_location(file):
-  """ Creates an ArtifactLocation proto from a File.
-  """
+  """Creates an ArtifactLocation proto from a File."""
   if file == None:
     return None
   return struct_omit_none(
@@ -106,8 +103,7 @@
   )
 
 def source_directory_tuple(resource_file):
-  """ Creates a tuple of (source directory, is_source, root execution path) from an android resource file.
-  """
+  """Creates a tuple of (source directory, is_source, root execution path)."""
   return (
       str(android_common.resource_source_directory(resource_file)),
       resource_file.is_source,
@@ -115,7 +111,9 @@
   )
 
 def all_unique_source_directories(resources):
-  """ Builds a list of ArtifactLocation protos for all source directories for a list of Android resources.
+  """Builds a list of ArtifactLocation protos.
+
+  This is done for all source directories for a list of Android resources.
   """
   # Sets can contain tuples, but cannot contain structs.
   # Use set of tuples to unquify source directories.
@@ -126,16 +124,14 @@
           for (relative_path, is_source, root_execution_path_fragment) in source_directory_tuples]
 
 def build_file_artifact_location(build_file_path):
-  """ Creates an ArtifactLocation proto representing a location of a given BUILD file.
-  """
+  """Creates an ArtifactLocation proto representing a location of a given BUILD file."""
   return struct(
       relative_path = build_file_path,
       is_source = True,
   )
 
 def library_artifact(java_output):
-  """ Creates a LibraryArtifact representing a given java_output.
-  """
+  """Creates a LibraryArtifact representing a given java_output."""
   if java_output == None or java_output.class_jar == None:
     return None
   return struct_omit_none(
@@ -145,24 +141,22 @@
   )
 
 def annotation_processing_jars(annotation_processing):
-  """ Creates a LibraryArtifact representing Java annotation processing jars.
-  """
+  """Creates a LibraryArtifact representing Java annotation processing jars."""
   return struct_omit_none(
         jar = artifact_location(annotation_processing.class_jar),
         source_jar = artifact_location(annotation_processing.source_jar),
   )
 
 def jars_from_output(output):
-  """ Collect jars for ide-resolve-files from Java output.
-  """
+  """Collect jars for ide-resolve-files from Java output."""
   if output == None:
     return []
   return [jar
           for jar in [output.class_jar, output.ijar, output.source_jar]
           if jar != None and not jar.is_source]
 
-def c_rule_ide_info(target, ctx):
-  """ Build CRuleIdeInfo.
+def build_c_rule_ide_info(target, ctx):
+  """Build CRuleIdeInfo.
 
   Returns a pair of (CRuleIdeInfo proto, a set of ide-resolve-files).
   (or (None, empty set) if the rule is not a C rule).
@@ -198,8 +192,8 @@
          ),
          ide_resolve_files)
 
-def c_toolchain_ide_info(target, ctx):
-  """ Build CToolchainIdeInfo.
+def build_c_toolchain_ide_info(target, ctx):
+  """Build CToolchainIdeInfo.
 
   Returns a pair of (CToolchainIdeInfo proto, a set of ide-resolve-files).
   (or (None, empty set) if the rule is not a cc_toolchain rule).
@@ -244,8 +238,9 @@
             for file in src.files]
   return []
 
-def java_rule_ide_info(target, ctx):
-  """ Build JavaRuleIdeInfo.
+def build_java_rule_ide_info(target, ctx):
+  """
+  Build JavaRuleIdeInfo.
 
   Returns a pair of (JavaRuleIdeInfo proto, a set of ide-resolve-files).
   (or (None, empty set) if the rule is not Java rule).
@@ -278,13 +273,14 @@
           ),
           ide_resolve_files)
 
-def android_rule_ide_info(target, ctx):
-  """ Build AndroidRuleIdeInfo.
+def build_android_rule_ide_info(target, ctx):
+  """
+  Build AndroidRuleIdeInfo.
 
   Returns a pair of (AndroidRuleIdeInfo proto, a set of ide-resolve-files).
   (or (None, empty set) if the rule is not Android rule).
   """
-  if not hasattr(target, 'android'):
+  if not hasattr(target, "android"):
     return (None, set())
   ide_resolve_files = set(jars_from_output(target.android.idl.output))
   return (struct_omit_none(
@@ -299,8 +295,8 @@
         ),
         ide_resolve_files)
 
-def test_info(target, ctx):
-  """ Build TestInfo """
+def build_test_info(target, ctx):
+  """Build TestInfo"""
   if not is_test_rule(ctx):
     return None
   return struct_omit_none(
@@ -311,9 +307,9 @@
   kind_string = ctx.rule.kind
   return kind_string.endswith("_test")
 
-def proto_library_legacy_java_ide_info(target, ctx):
-  """ Build ProtoLibraryLegacyJavaIdeInfo."""
-  if not hasattr(target, 'proto_legacy_java'):
+def build_proto_library_legacy_java_ide_info(target, ctx):
+  """Build ProtoLibraryLegacyJavaIdeInfo."""
+  if not hasattr(target, "proto_legacy_java"):
     return None
   proto_info = target.proto_legacy_java.legacy_info
   return struct_omit_none(
@@ -324,8 +320,19 @@
     jars_immutable = [library_artifact(output) for output in proto_info.jars_immutable],
   )
 
+def build_java_toolchain_ide_info(target):
+  """Build JavaToolchainIdeInfo."""
+  if not hasattr(target, "java_toolchain"):
+    return None
+  toolchain_info = target.java_toolchain
+  return struct_omit_none(
+      source_version = toolchain_info.source_version,
+      target_version = toolchain_info.target_version,
+  )
+
 def collect_labels(rule_attrs, attrs):
-  """ Collect labels from attribute values.
+  """
+  Collect labels from attribute values.
 
   Assuming that values of attributes from attr_list in rule_atrs
   are label lists, collect a set of string representation of those labels.
@@ -339,8 +346,7 @@
       if hasattr(rule_attrs, attr_name)])
 
 def collect_export_deps(rule_attrs):
-  """ Build a union of all export dependencies.
-  """
+  """Build a union of all export dependencies."""
   result = set()
   for attr_name in DEPS.label_list:
     if hasattr(rule_attrs, attr_name):
@@ -354,8 +360,7 @@
   return result
 
 def _aspect_impl(target, ctx):
-  """ Aspect implementation function
-  """
+  """Aspect implementation function."""
   kind_legacy = get_kind_legacy(target, ctx)
   kind_string = ctx.rule.kind
   rule_attrs = ctx.rule.attr
@@ -383,24 +388,26 @@
 
 
   # Collect C-specific information
-  (c_rule_ide_info, c_ide_resolve_files) = c_rule_ide_info(target, ctx)
+  (c_rule_ide_info, c_ide_resolve_files) = build_c_rule_ide_info(target, ctx)
   ide_resolve_files = ide_resolve_files | c_ide_resolve_files
 
-  (c_toolchain_ide_info, c_toolchain_ide_resolve_files) = c_toolchain_ide_info(target, ctx)
+  (c_toolchain_ide_info, c_toolchain_ide_resolve_files) = build_c_toolchain_ide_info(target, ctx)
   ide_resolve_files = ide_resolve_files | c_toolchain_ide_resolve_files
 
   # Collect Java-specific information
-  (java_rule_ide_info, java_ide_resolve_files) = java_rule_ide_info(target, ctx)
+  (java_rule_ide_info, java_ide_resolve_files) = build_java_rule_ide_info(target, ctx)
   ide_resolve_files = ide_resolve_files | java_ide_resolve_files
 
   # Collect Android-specific information
-  (android_rule_ide_info, android_ide_resolve_files) = android_rule_ide_info(target, ctx)
+  (android_rule_ide_info, android_ide_resolve_files) = build_android_rule_ide_info(target, ctx)
   ide_resolve_files = ide_resolve_files | android_ide_resolve_files
 
-  proto_library_legacy_java_ide_info = proto_library_legacy_java_ide_info(target, ctx)
+  proto_library_legacy_java_ide_info = build_proto_library_legacy_java_ide_info(target, ctx)
+
+  java_toolchain_ide_info = build_java_toolchain_ide_info(target)
 
   # Collect test info
-  test_info = test_info(target, ctx)
+  test_info = build_test_info(target, ctx)
 
   # Collect information about exports.
   export_deps = set()
@@ -426,6 +433,7 @@
       tags = ctx.rule.attr.tags,
       test_info = test_info,
       proto_library_legacy_java_ide_info = proto_library_legacy_java_ide_info,
+      java_toolchain_ide_info = java_toolchain_ide_info,
   )
 
   # Output the ide information file.
@@ -449,7 +457,7 @@
     )
 
 intellij_info_aspect = aspect(
-    implementation = _aspect_impl,
     attr_aspects = ALL_DEPS.label + ALL_DEPS.label_list,
     fragments = ["cpp"],
+    implementation = _aspect_impl,
 )