Migrate OutputGroupInfo to skylarkbuildapi

RELNOTES: None.
PiperOrigin-RevId: 197949354
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupInfo.java b/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupInfo.java
index 3a2d65a..2f09dbb 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupInfo.java
@@ -29,12 +29,13 @@
 import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.BuiltinProvider;
 import com.google.devtools.build.lib.packages.NativeInfo;
-import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
-import com.google.devtools.build.lib.syntax.Environment;
+import com.google.devtools.build.lib.skylarkbuildapi.OutputGroupInfoApi;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalUtils;
+import com.google.devtools.build.lib.syntax.SkylarkDict;
 import com.google.devtools.build.lib.syntax.SkylarkIndexable;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
 import java.util.HashSet;
@@ -60,10 +61,10 @@
 @Immutable
 @AutoCodec
 public final class OutputGroupInfo extends NativeInfo
-    implements SkylarkIndexable, Iterable<String> {
+    implements SkylarkIndexable, Iterable<String>, OutputGroupInfoApi {
   public static final String SKYLARK_NAME = "output_groups";
 
-  public static NativeProvider<OutputGroupInfo> SKYLARK_CONSTRUCTOR = new Constructor();
+  public static final OutputGroupInfoProvider SKYLARK_CONSTRUCTOR = new OutputGroupInfoProvider();
 
   /**
    * Prefix for output groups that are not reported to the user on the terminal output of Blaze when
@@ -258,22 +259,22 @@
     return outputGroups.keySet();
   }
 
-  /** A constructor callable from Skylark for OutputGroupInfo. */
-  private static class Constructor extends NativeProvider<OutputGroupInfo> {
-
-    private Constructor() {
-      super(OutputGroupInfo.class, "OutputGroupInfo");
+  /**
+   * Provider implementation for {@link OutputGroupInfoApi.OutputGroupInfoApiProvider}.
+   */
+  public static class OutputGroupInfoProvider extends BuiltinProvider<OutputGroupInfo>
+      implements OutputGroupInfoApi.OutputGroupInfoApiProvider {
+    private OutputGroupInfoProvider() {
+      super("OutputGroupInfo", OutputGroupInfo.class);
     }
 
     @Override
-    protected OutputGroupInfo createInstanceFromSkylark(
-        Object[] args, Environment env, Location loc) throws EvalException {
-
-      @SuppressWarnings("unchecked")
-      Map<String, Object> kwargs = (Map<String, Object>) args[0];
+    public OutputGroupInfoApi constructor(SkylarkDict<?, ?> kwargs, Location loc)
+        throws EvalException {
+      Map<String, Object> kwargsMap = kwargs.getContents(String.class, Object.class, "kwargs");
 
       ImmutableMap.Builder<String, NestedSet<Artifact>> builder = ImmutableMap.builder();
-      for (Map.Entry<String, Object> entry : kwargs.entrySet()) {
+      for (Map.Entry<String, Object> entry : kwargsMap.entrySet()) {
         builder.put(
             entry.getKey(),
             SkylarkRuleConfiguredTargetUtil.convertToOutputGroupValue(
@@ -281,10 +282,5 @@
       }
       return new OutputGroupInfo(builder.build());
     }
-
-    @Override
-    public String getErrorMessageFormatForUnknownField() {
-      return "Output group '%s' not present";
-    }
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index 49bd743..93387fa 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -69,6 +69,7 @@
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.AttributeMap;
 import com.google.devtools.build.lib.packages.BuildType;
+import com.google.devtools.build.lib.packages.BuiltinProvider;
 import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy;
 import com.google.devtools.build.lib.packages.ConfiguredAttributeMapper;
 import com.google.devtools.build.lib.packages.FileTarget;
@@ -932,6 +933,15 @@
   }
 
   /**
+   * Returns all the declared providers (native and Skylark) for the specified constructor under the
+   * specified attribute of this target in the BUILD file.
+   */
+  public <T extends Info> Iterable<T> getPrerequisites(
+      String attributeName, Mode mode, final BuiltinProvider<T> skylarkKey) {
+    return AnalysisUtils.getProviders(getPrerequisites(attributeName, mode), skylarkKey);
+  }
+
+  /**
    * Returns the declared provider (native and Skylark) for the specified constructor under the
    * specified attribute of this target in the BUILD file. May return null if there is no
    * TransitiveInfoCollection under the specified attribute.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java
index 3450283..4ea908d 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java
@@ -15,6 +15,7 @@
 package com.google.devtools.build.lib.analysis.skylark;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.analysis.OutputGroupInfo;
 import com.google.devtools.build.lib.packages.BazelLibrary;
 import com.google.devtools.build.lib.packages.SkylarkNativeModule;
 import com.google.devtools.build.lib.packages.StructProvider;
@@ -35,7 +36,8 @@
           SkylarkCommandLine.class,
           SkylarkNativeModule.class,
           SkylarkRuleClassFunctions.class,
-          StructProvider.STRUCT);
+          StructProvider.STRUCT,
+          OutputGroupInfo.SKYLARK_CONSTRUCTOR);
 
   /**
    * Adds bindings for skylark built-ins and non-rules-specific globals of the build API to
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
index b995abf..b8c7471 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
@@ -36,7 +36,6 @@
 import com.google.devtools.build.lib.analysis.ActionsProvider;
 import com.google.devtools.build.lib.analysis.BaseRuleClasses;
 import com.google.devtools.build.lib.analysis.DefaultInfo;
-import com.google.devtools.build.lib.analysis.OutputGroupInfo;
 import com.google.devtools.build.lib.analysis.config.ConfigAwareRuleClassBuilder;
 import com.google.devtools.build.lib.analysis.config.HostTransition;
 import com.google.devtools.build.lib.analysis.config.transitions.PatchTransition;
@@ -243,19 +242,6 @@
   )
   private static final NativeProvider<?> defaultInfo = DefaultInfo.PROVIDER;
 
-  @SkylarkSignature(
-    name = "OutputGroupInfo",
-    returnType = Provider.class,
-    doc =
-        "A provider that indicates what output groups a rule has.<br>"
-            + "Instantiate this provider with <br>"
-            + "<pre class=language-python>"
-            + "OutputGroupInfo(group1 = &lt;files&gt;, group2 = &lt;files&gt;...)</pre>"
-            + "See <a href=\"../rules.$DOC_EXT#requesting-output-files\">Requesting output files"
-            + "</a> for more information."
-  )
-  private static final NativeProvider<?> outputGroupInfo = OutputGroupInfo.SKYLARK_CONSTRUCTOR;
-
   // TODO(bazel-team): Move to a "testing" namespace module. Normally we'd pass an objectType
   // to @SkylarkSignature to do this, but that doesn't work here because we're exposing an already-
   // configured BaseFunction, rather than defining a new BuiltinFunction. This should wait for
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
index 1ebd4ab..56d4cb7 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
@@ -38,6 +38,7 @@
 import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.packages.AttributeMap;
 import com.google.devtools.build.lib.packages.BuildType;
+import com.google.devtools.build.lib.packages.BuiltinProvider;
 import com.google.devtools.build.lib.packages.Info;
 import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.packages.Rule;
@@ -112,6 +113,18 @@
     return builder.build();
   }
 
+  public static final <T extends Info> Iterable<T> getTransitivePrerequisites(
+      RuleContext ruleContext, Mode mode, BuiltinProvider<T> key) {
+    IterablesChain.Builder<T> builder = IterablesChain.builder();
+    AttributeMap attributes = ruleContext.attributes();
+    for (String attr : TRANSITIVE_ATTRIBUTES) {
+      if (attributes.has(attr, BuildType.LABEL_LIST)) {
+        builder.add(ruleContext.getPrerequisites(attr, mode, key));
+      }
+    }
+    return builder.build();
+  }
+
   private final RuleContext ruleContext;
   private final JavaCommon javaCommon;
   private final boolean asNeverLink;
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/OutputGroupInfoApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/OutputGroupInfoApi.java
new file mode 100644
index 0000000..13c1f26
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/OutputGroupInfoApi.java
@@ -0,0 +1,65 @@
+// 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.devtools.build.lib.skylarkbuildapi;
+
+import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.skylarkinterface.Param;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkConstructor;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.SkylarkDict;
+
+/**
+ * Interface for an info object that indicates what output groups a rule has.
+ */
+@SkylarkModule(
+    name = "OutputGroupInfo",
+    category = SkylarkModuleCategory.PROVIDER,
+    doc = "A provider that indicates what output groups a rule has.<br>"
+        + "See <a href=\"../rules.$DOC_EXT#requesting-output-files\">Requesting output files"
+        + "</a> for more information."
+)
+public interface OutputGroupInfoApi extends StructApi {
+
+  /**
+   * Provider for {@link OutputGroupInfoApi}.
+   */
+  @SkylarkModule(name = "Provider", documented = false, doc = "")
+  public static interface OutputGroupInfoApiProvider extends ProviderApi {
+
+    @SkylarkCallable(
+        name = "OutputGroupInfo",
+        doc =
+            "Instantiate this provider with <br>"
+                + "<pre class=language-python>"
+                + "OutputGroupInfo(group1 = &lt;files&gt;, group2 = &lt;files&gt;...)</pre>"
+                + "See <a href=\"../rules.$DOC_EXT#requesting-output-files\">Requesting output "
+                + "files </a> for more information.",
+        extraKeywords =
+            @Param(
+                name = "kwargs",
+                type = SkylarkDict.class,
+                defaultValue = "{}",
+                doc = "Dictionary of arguments."),
+        useLocation = true,
+        selfCall = true)
+    @SkylarkConstructor(objectType = OutputGroupInfoApi.class,
+        receiverNameForDoc = "OutputGroupInfo")
+    public OutputGroupInfoApi constructor(
+        SkylarkDict<?, ?> kwargs, Location loc) throws EvalException;
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java
index 881b5fc..b64d50c 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java
@@ -15,6 +15,7 @@
 package com.google.devtools.build.lib.skylarkbuildapi;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.skylarkbuildapi.OutputGroupInfoApi.OutputGroupInfoApiProvider;
 import com.google.devtools.build.lib.syntax.Runtime;
 
 /**
@@ -27,6 +28,7 @@
   private final Class<? extends SkylarkNativeModuleApi> skylarkNativeModuleApi;
   private final Class<? extends SkylarkRuleFunctionsApi<?>> skylarkRuleFunctionsApi;
   private final StructApi.StructProviderApi structProvider;
+  private final OutputGroupInfoApiProvider outputGroupInfoProvider;
 
   public TopLevelBootstrap(
       Class<? extends SkylarkBuildApiGlobals> skylarkBuildApiGlobals,
@@ -34,13 +36,15 @@
       Class<? extends SkylarkCommandLineApi> skylarkCommandLineApi,
       Class<? extends SkylarkNativeModuleApi> skylarkNativeModuleApi,
       Class<? extends SkylarkRuleFunctionsApi<?>> skylarkRuleFunctionsApi,
-      StructApi.StructProviderApi structProvider) {
+      StructApi.StructProviderApi structProvider,
+      OutputGroupInfoApiProvider outputGroupInfoProvider) {
     this.skylarkAttrApi = skylarkAttrApi;
     this.skylarkBuildApiGlobals = skylarkBuildApiGlobals;
     this.skylarkCommandLineApi = skylarkCommandLineApi;
     this.skylarkNativeModuleApi = skylarkNativeModuleApi;
     this.skylarkRuleFunctionsApi = skylarkRuleFunctionsApi;
     this.structProvider = structProvider;
+    this.outputGroupInfoProvider = outputGroupInfoProvider;
   }
 
   @Override
@@ -51,5 +55,6 @@
     Runtime.setupModuleGlobals(builder, skylarkNativeModuleApi);
     Runtime.setupModuleGlobals(builder, skylarkRuleFunctionsApi);
     builder.put("struct", structProvider);
+    builder.put("OutputGroupInfo", outputGroupInfoProvider);
   }
 }