Refactor JavaInfo.

Convert implementation from populating an immutable map to a set of
SkylarkCallables. That saves memory and allows specifying documentation.

Also properly implements equals() and hashCode().

RELNOTES: None.
PiperOrigin-RevId: 166364059
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfo.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfo.java
index 46c45c6..f50fae3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfo.java
@@ -15,7 +15,6 @@
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.analysis.Runfiles;
@@ -26,6 +25,9 @@
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.packages.NativeInfo;
 import com.google.devtools.build.lib.packages.NativeProvider;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
 import java.util.ArrayList;
 import java.util.LinkedList;
@@ -33,6 +35,11 @@
 import javax.annotation.Nullable;
 
 /** A Skylark declared provider that encapsulates all providers that are needed by Java rules. */
+@SkylarkModule(
+    name = "java_common.provider",
+    doc = "Encapsulates all information provided by Java rules",
+    category = SkylarkModuleCategory.PROVIDER
+)
 @Immutable
 public final class JavaInfo extends NativeInfo {
 
@@ -175,23 +182,64 @@
   }
 
   private JavaInfo(TransitiveInfoProviderMap providers) {
-    super(PROVIDER, ImmutableMap.<String, Object>of(
-        "transitive_runtime_jars", SkylarkNestedSet.of(
-            Artifact.class,
-            providers.getProvider(JavaCompilationArgsProvider.class)
-                .getRecursiveJavaCompilationArgs().getRuntimeJars()),
-        "transitive_compile_time_jars", SkylarkNestedSet.of(
-            Artifact.class,
-            providers.getProvider(JavaCompilationArgsProvider.class)
-                .getRecursiveJavaCompilationArgs().getCompileTimeJars()),
-        "compile_jars", SkylarkNestedSet.of(
-            Artifact.class,
-            providers.getProvider(JavaCompilationArgsProvider.class)
-                .getJavaCompilationArgs().getCompileTimeJars())
-    ));
+    super(PROVIDER);
     this.providers = providers;
   }
 
+  @SkylarkCallable(
+      name = "transitive_runtime_jars",
+      doc = "Depset of runtime jars required by this target",
+      structField = true
+  )
+  public SkylarkNestedSet getTransitiveRuntimeJars() {
+    return SkylarkNestedSet.of(
+        Artifact.class,
+        providers.getProvider(JavaCompilationArgsProvider.class)
+            .getRecursiveJavaCompilationArgs().getRuntimeJars());
+  }
+
+  @SkylarkCallable(
+      name = "transitive_compile_time_jars",
+      doc = "Depset of compile time jars recusrively required by this target",
+      structField = true
+  )
+  public SkylarkNestedSet getTransitiveCompileTimeJars() {
+    return SkylarkNestedSet.of(
+        Artifact.class,
+        providers.getProvider(JavaCompilationArgsProvider.class)
+            .getRecursiveJavaCompilationArgs().getCompileTimeJars());
+  }
+
+  @SkylarkCallable(
+      name = "compile_jars",
+      doc = "Depset of compile time jars required by this target directly",
+      structField = true
+  )
+  public SkylarkNestedSet getCompileTimeJars() {
+    return SkylarkNestedSet.of(
+        Artifact.class,
+        providers.getProvider(JavaCompilationArgsProvider.class)
+            .getJavaCompilationArgs().getCompileTimeJars());
+  }
+
+  @Override
+  public boolean equals(Object otherObject) {
+    if (this == otherObject) {
+      return true;
+    }
+    if (!(otherObject instanceof JavaInfo)) {
+      return false;
+    }
+
+    JavaInfo other = (JavaInfo) otherObject;
+    return providers.equals(other.providers);
+  }
+
+  @Override
+  public int hashCode() {
+    return providers.hashCode();
+  }
+
   /**
    * A Builder for {@link JavaInfo}.
    */
diff --git a/src/test/java/com/google/devtools/build/lib/rules/java/JavaSkylarkApiTest.java b/src/test/java/com/google/devtools/build/lib/rules/java/JavaSkylarkApiTest.java
index e21ef2c..0e5d1d1 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/java/JavaSkylarkApiTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/java/JavaSkylarkApiTest.java
@@ -295,18 +295,16 @@
         "    transitive_runtime_jars = ['libd.jar'],",
         ")");
     ConfiguredTarget target = getConfiguredTarget("//foo:myrule");
-    Info info = target.get(JavaInfo.PROVIDER);
+    JavaInfo info = target.get(JavaInfo.PROVIDER);
 
-    SkylarkNestedSet compileJars = (SkylarkNestedSet) info.getValue("compile_jars");
+    SkylarkNestedSet compileJars = info.getCompileTimeJars();
     assertThat(prettyJarNames(compileJars.getSet(Artifact.class))).containsExactly("foo/liba.jar");
 
-    SkylarkNestedSet transitiveCompileTimeJars =
-        (SkylarkNestedSet) info.getValue("transitive_compile_time_jars");
+    SkylarkNestedSet transitiveCompileTimeJars = info.getTransitiveCompileTimeJars();
     assertThat(prettyJarNames(
         transitiveCompileTimeJars.getSet(Artifact.class))).containsExactly("foo/libc.jar");
 
-    SkylarkNestedSet transitiveRuntimeJars =
-        (SkylarkNestedSet) info.getValue("transitive_runtime_jars");
+    SkylarkNestedSet transitiveRuntimeJars = info.getTransitiveRuntimeJars();
     assertThat(prettyJarNames(
         transitiveRuntimeJars.getSet(Artifact.class))).containsExactly("foo/libd.jar");
   }
@@ -335,17 +333,15 @@
         "    transitive_runtime_jars = ['libd.jar'],",
         ")");
     ConfiguredTarget target = getConfiguredTarget("//foo:myrule");
-    Info info = target.get(JavaInfo.PROVIDER);
+    JavaInfo info = target.get(JavaInfo.PROVIDER);
 
-    SkylarkNestedSet compileJars = (SkylarkNestedSet) info.getValue("compile_jars");
+    SkylarkNestedSet compileJars = info.getCompileTimeJars();
     assertThat(prettyJarNames(compileJars.getSet(Artifact.class))).containsExactly("foo/liba.jar");
 
-    SkylarkNestedSet transitiveCompileTimeJars =
-        (SkylarkNestedSet) info.getValue("transitive_compile_time_jars");
+    SkylarkNestedSet transitiveCompileTimeJars = info.getTransitiveCompileTimeJars();
     assertThat(prettyJarNames(transitiveCompileTimeJars.getSet(Artifact.class))).isEmpty();
 
-    SkylarkNestedSet transitiveRuntimeJars =
-        (SkylarkNestedSet) info.getValue("transitive_runtime_jars");
+    SkylarkNestedSet transitiveRuntimeJars = info.getTransitiveRuntimeJars();
     assertThat(prettyJarNames(
         transitiveRuntimeJars.getSet(Artifact.class))).containsExactly("foo/libd.jar");
   }