Encapsulate the required provider logic in RequiredProviders class.

For now, only for aspects, but eventually expand to Attribute's
mandatory providers as well.

--
PiperOrigin-RevId: 144063369
MOS_MIGRATED_REVID=144063369
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java b/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
index 18cd2eb..92f6d0c 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
@@ -56,8 +56,7 @@
 public final class AspectDefinition {
 
   private final AspectClass aspectClass;
-  private final ImmutableList<ImmutableSet<Class<?>>> requiredProviderSets;
-  private final ImmutableList<ImmutableSet<String>> requiredProviderNameSets;
+  private final RequiredProviders requiredProviders;
   private final ImmutableMap<String, Attribute> attributes;
   private final PropagationFunction attributeAspects;
   @Nullable private final ConfigurationFragmentPolicy configurationFragmentPolicy;
@@ -68,23 +67,16 @@
 
   private AspectDefinition(
       AspectClass aspectClass,
-      ImmutableList<ImmutableSet<Class<?>>> requiredProviderSets,
+      RequiredProviders requiredProviders,
       ImmutableMap<String, Attribute> attributes,
       PropagationFunction attributeAspects,
       @Nullable ConfigurationFragmentPolicy configurationFragmentPolicy) {
     this.aspectClass = aspectClass;
-    this.requiredProviderSets = requiredProviderSets;
+    this.requiredProviders = requiredProviders;
 
     this.attributes = attributes;
     this.attributeAspects = attributeAspects;
     this.configurationFragmentPolicy = configurationFragmentPolicy;
-
-    ImmutableList.Builder<ImmutableSet<String>> requiredProviderNameSetsBuilder =
-        new ImmutableList.Builder<>();
-    for (ImmutableSet<Class<?>> requiredProviderSet : requiredProviderSets) {
-      requiredProviderNameSetsBuilder.add(toStringSet(requiredProviderSet));
-    }
-    this.requiredProviderNameSets = requiredProviderNameSetsBuilder.build();
   }
 
   public String getName() {
@@ -105,34 +97,14 @@
   }
 
   /**
-   * Returns the list of {@link com.google.devtools.build.lib.analysis.TransitiveInfoProvider}
-   * sets. All required providers from at least one set must be present on a configured target so
-   * that this aspect can be applied to it.
+   * Returns {@link RequiredProviders} that a configured target must have so that
+   * this aspect can be applied to it.
    *
-   * <p>We cannot refer to that class here due to our dependency structure, so this returns a set
-   * of unconstrained class objects.
-   *
-   * <p>If a configured target does not have a required provider, the aspect is silently not created
-   * for it.
+   * <p>If a configured target does not satisfy required providers, the aspect is
+   * silently not created for it.
    */
-  public ImmutableList<ImmutableSet<Class<?>>> getRequiredProviders() {
-    return requiredProviderSets;
-  }
-
-  /**
-   * Returns the list of class name sets of
-   * {@link com.google.devtools.build.lib.analysis.TransitiveInfoProvider}. All required providers
-   * from at least one set must be present on a configured target so that this aspect can be applied
-   * to it.
-   *
-   * <p>This set is a mirror of the set returned by {@link #getRequiredProviders}, but contains the
-   * names of the classes rather than the class objects themselves.
-   *
-   * <p>If a configured target does not have a required provider, the aspect is silently not created
-   * for it.
-   */
-  public ImmutableList<ImmutableSet<String>> getRequiredProviderNames() {
-    return requiredProviderNameSets;
+  public RequiredProviders getRequiredProviders() {
+    return requiredProviders;
   }
 
   /**
@@ -176,31 +148,15 @@
     for (Aspect candidateClass : attribute.getAspects(from)) {
       // Check if target satisfies condition for this aspect (has to provide all required
       // TransitiveInfoProviders)
-      if (!advertisedProviders.canHaveAnyProvider()) {
-        ImmutableList<ImmutableSet<Class<?>>> providerNamesList =
-            candidateClass.getDefinition().getRequiredProviders();
-
-        for (ImmutableSet<Class<?>> providerNames : providerNamesList) {
-          if (advertisedProviders.getNativeProviders().containsAll(providerNames)) {
-            addAllAttributesOfAspect(from, result, candidateClass, dependencyFilter);
-            break;
-          }
-        }
-      } else {
+      RequiredProviders requiredProviders =
+          candidateClass.getDefinition().getRequiredProviders();
+      if (requiredProviders.isSatisfiedBy(advertisedProviders)) {
         addAllAttributesOfAspect(from, result, candidateClass, dependencyFilter);
       }
     }
     return ImmutableMultimap.copyOf(result);
   }
 
-  private static ImmutableSet<String> toStringSet(ImmutableSet<Class<?>> classes) {
-    ImmutableSet.Builder<String> classStrings = new ImmutableSet.Builder<>();
-    for (Class<?> clazz : classes) {
-      classStrings.add(clazz.getName());
-    }
-    return classStrings.build();
-  }
-
   @Nullable
   private static Label maybeGetRepositoryRelativeLabel(Rule from, @Nullable Label label) {
     return label == null ? null : from.getLabel().resolveRepositoryRelative(label);
@@ -246,7 +202,7 @@
   public static final class Builder {
     private final AspectClass aspectClass;
     private final Map<String, Attribute> attributes = new LinkedHashMap<>();
-    private ImmutableList<ImmutableSet<Class<?>>> requiredProviderSets = ImmutableList.of();
+    private RequiredProviders.Builder requiredProviders = RequiredProviders.acceptAnyBuilder();
     private final Multimap<String, AspectClass> attributeAspects = LinkedHashMultimap.create();
     private ImmutableCollection<AspectClass> allAttributesAspects = null;
     private final ConfigurationFragmentPolicy.Builder configurationFragmentPolicy =
@@ -261,12 +217,9 @@
      * from at least one set of required providers.
      */
     public Builder requireProviderSets(Iterable<? extends Set<Class<?>>> providerSets) {
-      ImmutableList.Builder<ImmutableSet<Class<?>>> requiredProviderSetsBuilder =
-          ImmutableList.builder();
-      for (Iterable<Class<?>> providerSet : providerSets) {
-        requiredProviderSetsBuilder.add(ImmutableSet.copyOf(providerSet));
+      for (Set<Class<?>> providerSet : providerSets) {
+        requiredProviders.addNativeSet(ImmutableSet.copyOf(providerSet));
       }
-      requiredProviderSets = requiredProviderSetsBuilder.build();
       return this;
     }
 
@@ -274,8 +227,8 @@
      * Asserts that this aspect can only be evaluated for rules that supply all of the specified
      * providers.
      */
-    public Builder requireProviders(Class<?>... requiredProviders) {
-      requireProviderSets(ImmutableList.of(ImmutableSet.copyOf(requiredProviders)));
+    public Builder requireProviders(Class<?>... providers) {
+      requiredProviders.addNativeSet(ImmutableSet.copyOf(providers));
       return this;
     }
 
@@ -445,15 +398,7 @@
      * <p>The builder object is reusable afterwards.
      */
     public AspectDefinition build() {
-      // If there is no required provider set, we still need to at least provide one empty set of
-      // providers. We consider this case specially because aspects with no required providers
-      // should match all rules, and having an empty set faciliates the matching logic.
-      ImmutableList<ImmutableSet<Class<?>>> requiredProviders =
-          requiredProviderSets.isEmpty()
-          ? ImmutableList.of(ImmutableSet.<Class<?>>of())
-          : requiredProviderSets;
-
-      return new AspectDefinition(aspectClass, ImmutableList.copyOf(requiredProviders),
+      return new AspectDefinition(aspectClass, requiredProviders.build(),
           ImmutableMap.copyOf(attributes),
           allAttributesAspects != null
               ? new AllAttributesPropagationFunction(allAttributesAspects)