Implement OutputGroupInfo provider.

Work towards #2894.

RELNOTES: None.
PiperOrigin-RevId: 154829065
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupProvider.java
index 7ba2eff..397d7fd 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupProvider.java
@@ -16,6 +16,7 @@
 
 import static com.google.devtools.build.lib.syntax.EvalUtils.SKYLARK_COMPARATOR;
 
+import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSortedSet;
@@ -27,6 +28,9 @@
 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.NativeClassObjectConstructor;
+import com.google.devtools.build.lib.packages.SkylarkClassObject;
+import com.google.devtools.build.lib.rules.SkylarkRuleConfiguredTargetBuilder;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalUtils;
 import com.google.devtools.build.lib.syntax.SkylarkIndexable;
@@ -34,6 +38,8 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 import javax.annotation.Nullable;
 
@@ -51,10 +57,12 @@
  * not mentioned on the output.
  */
 @Immutable
-public final class OutputGroupProvider implements
-    TransitiveInfoProvider, SkylarkIndexable, Iterable<String> {
+public final class OutputGroupProvider extends SkylarkClassObject
+    implements SkylarkIndexable, Iterable<String> {
   public static final String SKYLARK_NAME = "output_groups";
 
+  public static NativeClassObjectConstructor SKYLARK_CONSTRUCTOR = new Constructor();
+
   /**
    * Prefix for output groups that are not reported to the user on the terminal output of Blaze when
    * they are built.
@@ -113,9 +121,26 @@
   private final ImmutableMap<String, NestedSet<Artifact>> outputGroups;
 
   public OutputGroupProvider(ImmutableMap<String, NestedSet<Artifact>> outputGroups) {
+    super(SKYLARK_CONSTRUCTOR, ImmutableMap.<String, Object>of());
     this.outputGroups = outputGroups;
   }
 
+  @Nullable
+  public static OutputGroupProvider get(TransitiveInfoCollection collection) {
+    return (OutputGroupProvider) collection.get(SKYLARK_CONSTRUCTOR.getKey());
+  }
+
+  @Nullable
+  public static OutputGroupProvider get(ConfiguredAspect aspect) {
+    SkylarkProviders skylarkProviders = aspect.getProvider(SkylarkProviders.class);
+
+
+    return skylarkProviders != null
+        ? (OutputGroupProvider) skylarkProviders.getDeclaredProvider(SKYLARK_CONSTRUCTOR.getKey())
+        : null;
+  }
+
+
   /** Return the artifacts in a particular output group.
    *
    * @return the artifacts in the output group with the given name. The return value is never null.
@@ -210,7 +235,6 @@
           "Output group %s not present", key
       ));
     }
-
   }
 
   @Override
@@ -222,4 +246,51 @@
   public Iterator<String> iterator() {
     return SKYLARK_COMPARATOR.sortedCopy(outputGroups.keySet()).iterator();
   }
+
+  @Override
+  public Object getValue(String name) {
+    NestedSet<Artifact> result = outputGroups.get(name);
+    if (result == null) {
+      return null;
+    }
+    return SkylarkNestedSet.of(Artifact.class, result);
+  }
+
+  @Override
+  public ImmutableCollection<String> getKeys() {
+    return outputGroups.keySet();
+  }
+
+  /**
+   * A constructor callable from Skylark for OutputGroupProvider.
+   */
+  private static class Constructor extends NativeClassObjectConstructor {
+
+    private Constructor() {
+      super("OutputGroupInfo");
+    }
+
+    @Override
+    protected SkylarkClassObject createInstanceFromSkylark(Object[] args, Location loc)
+        throws EvalException {
+
+      @SuppressWarnings("unchecked")
+      Map<String, Object> kwargs = (Map<String, Object>) args[0];
+
+      ImmutableMap.Builder<String, NestedSet<Artifact>> builder = ImmutableMap.builder();
+      for (Entry<String, Object> entry : kwargs.entrySet()) {
+        builder.put(entry.getKey(),
+            SkylarkRuleConfiguredTargetBuilder.convertToOutputGroupValue(
+                loc, entry.getKey(), entry.getValue()));
+
+
+      }
+      return new OutputGroupProvider(builder.build());
+    }
+
+    @Override
+    public String getErrorMessageFormatForInstances() {
+      return "Output group %s not present";
+    }
+  }
 }