Allow aspects to specify multiple sets of required providers to match against rules. Aspects can attach to a rule if at least one set of required providers are present on the rule.
--
MOS_MIGRATED_REVID=140605023
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
index 635b39a..9fadc28 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
@@ -537,11 +537,22 @@
extractAspectCandidates(aspects, attributeAndOwner.attribute, originalRule);
RuleClass ruleClass = ((Rule) target).getRuleClassObject();
ImmutableSet.Builder<AspectDescriptor> result = ImmutableSet.builder();
+
for (Aspect aspectCandidate : aspectCandidates) {
- if (ruleClass.canHaveAnyProvider() || Sets.difference(
- aspectCandidate.getDefinition().getRequiredProviders(),
- ruleClass.getAdvertisedProviders())
- .isEmpty()) {
+ boolean requireAspect = ruleClass.canHaveAnyProvider();
+
+ if (!requireAspect) {
+ ImmutableList<ImmutableSet<Class<?>>> providersList =
+ aspectCandidate.getDefinition().getRequiredProviders();
+ for (ImmutableSet<Class<?>> providers : providersList) {
+ if (Sets.difference(providers, ruleClass.getAdvertisedProviders()).isEmpty()) {
+ requireAspect = true;
+ break;
+ }
+ }
+ }
+
+ if (requireAspect) {
result.add(
new AspectDescriptor(
aspectCandidate.getAspectClass(),
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 f3186d7..bda14e9 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
@@ -29,7 +29,6 @@
import com.google.devtools.build.lib.util.Preconditions;
import java.util.Collection;
import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -56,8 +55,8 @@
public final class AspectDefinition {
private final AspectClass aspectClass;
- private final ImmutableSet<Class<?>> requiredProviders;
- private final ImmutableSet<String> requiredProviderNames;
+ private final ImmutableList<ImmutableSet<Class<?>>> requiredProviderSets;
+ private final ImmutableList<ImmutableSet<String>> requiredProviderNameSets;
private final ImmutableMap<String, Attribute> attributes;
private final PropagationFunction attributeAspects;
@Nullable private final ConfigurationFragmentPolicy configurationFragmentPolicy;
@@ -68,16 +67,22 @@
private AspectDefinition(
AspectClass aspectClass,
- ImmutableSet<Class<?>> requiredProviders,
+ ImmutableList<ImmutableSet<Class<?>>> requiredProviderSets,
ImmutableMap<String, Attribute> attributes,
PropagationFunction attributeAspects,
@Nullable ConfigurationFragmentPolicy configurationFragmentPolicy) {
this.aspectClass = aspectClass;
- this.requiredProviders = requiredProviders;
- this.requiredProviderNames = toStringSet(requiredProviders);
+ this.requiredProviderSets = requiredProviderSets;
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() {
@@ -98,8 +103,9 @@
}
/**
- * Returns the set of {@link com.google.devtools.build.lib.analysis.TransitiveInfoProvider}
- * instances that must be present on a configured target so that this aspect can be applied to it.
+ * 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.
*
* <p>We cannot refer to that class here due to our dependency structure, so this returns a set
* of unconstrained class objects.
@@ -107,14 +113,15 @@
* <p>If a configured target does not have a required provider, the aspect is silently not created
* for it.
*/
- public ImmutableSet<Class<?>> getRequiredProviders() {
- return requiredProviders;
+ public ImmutableList<ImmutableSet<Class<?>>> getRequiredProviders() {
+ return requiredProviderSets;
}
/**
- * Returns the set of class names of
- * {@link com.google.devtools.build.lib.analysis.TransitiveInfoProvider} instances that must be
- * present on a configured target so that this aspect can be applied to it.
+ * 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.
@@ -122,8 +129,8 @@
* <p>If a configured target does not have a required provider, the aspect is silently not created
* for it.
*/
- public ImmutableSet<String> getRequiredProviderNames() {
- return requiredProviderNames;
+ public ImmutableList<ImmutableSet<String>> getRequiredProviderNames() {
+ return requiredProviderNameSets;
}
/**
@@ -166,11 +173,19 @@
for (Aspect candidateClass : attribute.getAspects(from)) {
// Check if target satisfies condition for this aspect (has to provide all required
// TransitiveInfoProviders)
- if (!canHaveAnyProvider && !advertisedProviders.containsAll(
- candidateClass.getDefinition().getRequiredProviderNames())) {
- continue;
+ if (!canHaveAnyProvider) {
+ ImmutableList<ImmutableSet<String>> providerNamesList =
+ candidateClass.getDefinition().getRequiredProviderNames();
+
+ for (ImmutableSet<String> providerNames : providerNamesList) {
+ if (advertisedProviders.containsAll(providerNames)) {
+ addAllAttributesOfAspect(from, result, candidateClass, dependencyFilter);
+ break;
+ }
+ }
+ } else {
+ addAllAttributesOfAspect(from, result, candidateClass, dependencyFilter);
}
- addAllAttributesOfAspect(from, result, candidateClass, dependencyFilter);
}
return ImmutableMultimap.copyOf(result);
}
@@ -228,7 +243,7 @@
public static final class Builder {
private final AspectClass aspectClass;
private final Map<String, Attribute> attributes = new LinkedHashMap<>();
- private final Set<Class<?>> requiredProviders = new LinkedHashSet<>();
+ private ImmutableList<ImmutableSet<Class<?>>> requiredProviderSets = ImmutableList.of();
private final Multimap<String, AspectClass> attributeAspects = LinkedHashMultimap.create();
private ImmutableCollection<AspectClass> allAttributesAspects = null;
private final ConfigurationFragmentPolicy.Builder configurationFragmentPolicy =
@@ -239,10 +254,25 @@
}
/**
- * Asserts that this aspect can only be evaluated for rules that supply the specified provider.
+ * Asserts that this aspect can only be evaluated for rules that supply all of the providers
+ * from at least one set of required providers.
*/
- public Builder requireProvider(Class<?> requiredProvider) {
- this.requiredProviders.add(requiredProvider);
+ 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));
+ }
+ requiredProviderSets = requiredProviderSetsBuilder.build();
+ return this;
+ }
+
+ /**
+ * 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)));
return this;
}
@@ -412,7 +442,15 @@
* <p>The builder object is reusable afterwards.
*/
public AspectDefinition build() {
- return new AspectDefinition(aspectClass, ImmutableSet.copyOf(requiredProviders),
+ // 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),
ImmutableMap.copyOf(attributes),
allAttributesAspects != null
? new AllAttributesPropagationFunction(allAttributesAspects)
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java
index e743a92..b7c6c59 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java
@@ -83,7 +83,7 @@
}
return builder
- .requireProvider(JavaCompilationArgsProvider.class)
+ .requireProviders(JavaCompilationArgsProvider.class)
.requiresConfigurationFragments()
.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java b/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java
index eec142c..a4d8960 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java
@@ -112,7 +112,7 @@
public AspectDefinition getDefinition(AspectParameters params) {
AspectDefinition.Builder result = new AspectDefinition.Builder(this)
// Actually we care about JavaRuntimeJarProvider, but rules don't advertise that provider.
- .requireProvider(JavaCompilationArgsProvider.class)
+ .requireProviders(JavaCompilationArgsProvider.class)
// Parse labels since we don't have RuleDefinitionEnvironment.getLabel like in a rule
.add(attr(ASPECT_DESUGAR_PREREQ, LABEL).cfg(HOST).exec()
.value(Label.parseAbsoluteUnchecked(toolsRepository + "//tools/android:desugar_java8")))
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/JackAspect.java b/src/main/java/com/google/devtools/build/lib/rules/android/JackAspect.java
index 4df83e7..c6a25ee 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/JackAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/JackAspect.java
@@ -61,7 +61,7 @@
}
return new AspectDefinition.Builder(this)
- .requireProvider(JavaSourceInfoProvider.class)
+ .requireProviders(JavaSourceInfoProvider.class)
.add(attr(":android_sdk", LABEL)
.allowedRuleClasses("android_sdk")
.value(new AndroidSdkLabel(androidSdk)))
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaLiteProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaLiteProtoAspect.java
index e8fa346..43d8256 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaLiteProtoAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaLiteProtoAspect.java
@@ -113,7 +113,7 @@
new AspectDefinition.Builder(this)
.attributeAspect("deps", this)
.requiresConfigurationFragments(JavaConfiguration.class, ProtoConfiguration.class)
- .requireProvider(ProtoSourcesProvider.class)
+ .requireProviders(ProtoSourcesProvider.class)
.add(
attr(PROTO_TOOLCHAIN_ATTR, LABEL)
.mandatoryNativeProviders(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoAspect.java
index 5c0b292..d2e194e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoAspect.java
@@ -161,7 +161,7 @@
new AspectDefinition.Builder(this)
.attributeAspect("deps", this)
.requiresConfigurationFragments(JavaConfiguration.class, ProtoConfiguration.class)
- .requireProvider(ProtoSourcesProvider.class)
+ .requireProviders(ProtoSourcesProvider.class)
.add(
attr(SPEED_PROTO_RUNTIME_ATTR, LABEL)
.legacyAllowAnyFileType()
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AbstractJ2ObjcProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AbstractJ2ObjcProtoAspect.java
index a6a8a1e..3dcfb6f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/AbstractJ2ObjcProtoAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AbstractJ2ObjcProtoAspect.java
@@ -83,7 +83,7 @@
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
AspectDefinition.Builder builder = new AspectDefinition.Builder(this)
- .requireProvider(ProtoSourcesProvider.class)
+ .requireProviders(ProtoSourcesProvider.class)
.requiresConfigurationFragments(
AppleConfiguration.class,
J2ObjcConfiguration.class,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
index 8679970..0f1bc80 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
@@ -110,8 +110,7 @@
.attributeAspect("deps", this, j2ObjcProtoAspect)
.attributeAspect("exports", this, j2ObjcProtoAspect)
.attributeAspect("runtime_deps", this, j2ObjcProtoAspect)
- .requireProvider(JavaSourceInfoProvider.class)
- .requireProvider(JavaCompilationArgsProvider.class)
+ .requireProviders(JavaSourceInfoProvider.class, JavaCompilationArgsProvider.class)
.requiresConfigurationFragments(
AppleConfiguration.class, J2ObjcConfiguration.class, ObjcConfiguration.class)
.requiresHostConfigurationFragments(Jvm.class)
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
index 38db025..df1b7c9 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
@@ -20,6 +20,7 @@
import com.google.common.base.VerifyException;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.LinkedListMultimap;
@@ -844,12 +845,22 @@
private static boolean aspectMatchesConfiguredTarget(ConfiguredTarget dep, Aspect aspect) {
AspectDefinition aspectDefinition = aspect.getDefinition();
- for (Class<?> provider : aspectDefinition.getRequiredProviders()) {
- if (dep.getProvider(provider.asSubclass(TransitiveInfoProvider.class)) == null) {
- return false;
+ ImmutableList<ImmutableSet<Class<?>>> providersList = aspectDefinition.getRequiredProviders();
+
+ for (ImmutableSet<Class<?>> providers : providersList) {
+ boolean matched = true;
+ for (Class<?> provider : providers) {
+ if (dep.getProvider(provider.asSubclass(TransitiveInfoProvider.class)) == null) {
+ matched = false;
+ break;
+ }
+ }
+
+ if (matched) {
+ return true;
}
}
- return true;
+ return false;
}
/**
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/AspectDefinitionTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AspectDefinitionTest.java
index eb6b8f8..6edae5e 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/AspectDefinitionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AspectDefinitionTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.fail;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.AspectDefinition;
import com.google.devtools.build.lib.packages.AspectParameters;
@@ -150,15 +151,36 @@
@Test
public void testRequireProvider_AddsToSetOfRequiredProvidersAndNames() throws Exception {
AspectDefinition requiresProviders = new AspectDefinition.Builder(TEST_ASPECT_CLASS)
- .requireProvider(String.class)
- .requireProvider(Integer.class)
+ .requireProviders(String.class, Integer.class)
.build();
- assertThat(requiresProviders.getRequiredProviders())
+ assertThat(requiresProviders.getRequiredProviders()).hasSize(1);
+ assertThat(requiresProviders.getRequiredProviders().get(0))
.containsExactly(String.class, Integer.class);
- assertThat(requiresProviders.getRequiredProviderNames())
+ assertThat(requiresProviders.getRequiredProviderNames()).hasSize(1);
+ assertThat(requiresProviders.getRequiredProviderNames().get(0))
.containsExactly("java.lang.String", "java.lang.Integer");
}
+ @Test
+ public void testRequireProvider_AddsTwoSetsOfRequiredProvidersAndNames() throws Exception {
+ AspectDefinition requiresProviders = new AspectDefinition.Builder(TEST_ASPECT_CLASS)
+ .requireProviderSets(
+ ImmutableList.of(
+ ImmutableSet.<Class<?>>of(String.class, Integer.class),
+ ImmutableSet.<Class<?>>of(Boolean.class)))
+ .build();
+ assertThat(requiresProviders.getRequiredProviders()).hasSize(2);
+ assertThat(requiresProviders.getRequiredProviders().get(0))
+ .containsExactly(String.class, Integer.class);
+ assertThat(requiresProviders.getRequiredProviders().get(1))
+ .containsExactly(Boolean.class);
+ assertThat(requiresProviders.getRequiredProviderNames()).hasSize(2);
+ assertThat(requiresProviders.getRequiredProviderNames().get(0))
+ .containsExactly("java.lang.String", "java.lang.Integer");
+ assertThat(requiresProviders.getRequiredProviderNames().get(1))
+ .containsExactly("java.lang.Boolean");
+ }
+
@Test
public void testNoConfigurationFragmentPolicySetup_HasNonNullPolicy() throws Exception {
AspectDefinition noPolicy = new AspectDefinition.Builder(TEST_ASPECT_CLASS)
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
index 37abaaf..ae4f533 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
@@ -163,6 +163,21 @@
}
@Test
+ public void aspectCreatedIfAtLeastOneSetOfAdvertisedProvidersArePresent() throws Exception {
+ setRulesAvailableInTests(new TestAspects.BaseRule(), new TestAspects.HonestRule(),
+ new TestAspects.HonestRule2(), new TestAspects.AspectRequiringProviderSetsRule());
+
+ pkg("a",
+ "aspect_requiring_provider_sets(name='a', foo=[':b', ':c'])",
+ "honest(name='b', foo=[])",
+ "honest2(name='c', foo=[])");
+
+ ConfiguredTarget a = getConfiguredTarget("//a:a");
+ assertThat(a.getProvider(RuleInfo.class).getData())
+ .containsExactly("rule //a:a", "aspect //a:b", "aspect //a:c");
+ }
+
+ @Test
public void aspectWithParametrizedDefinition() throws Exception {
setRulesAvailableInTests(
new TestAspects.BaseRule(),
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java b/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
index 55b0fe8..22a9412 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
@@ -24,6 +24,8 @@
import com.google.common.base.Function;
import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
@@ -117,6 +119,14 @@
public static final class RequiredProvider implements TransitiveInfoProvider {
}
+ /**
+ * Another very simple provider used in tests that check whether the logic that attaches aspects
+ * depending on whether a configured target has a provider works or not.
+ */
+ @Immutable
+ public static final class RequiredProvider2 implements TransitiveInfoProvider {
+ }
+
private static NestedSet<String> collectAspectData(String me, RuleContext ruleContext) {
NestedSetBuilder<String> result = new NestedSetBuilder<>(Order.STABLE_ORDER);
result.add(me);
@@ -160,6 +170,24 @@
}
/**
+ * A simple rule configured target factory that exports provider {@link RequiredProvider2}.
+ */
+ public static class DummyRuleFactory2 implements RuleConfiguredTargetFactory {
+ @Override
+ public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException {
+ return new RuleConfiguredTargetBuilder(ruleContext)
+ .addProvider(
+ new RuleInfo(collectAspectData("rule " + ruleContext.getLabel(), ruleContext)))
+ .setFilesToBuild(NestedSetBuilder.<Artifact>create(Order.STABLE_ORDER))
+ .setRunfilesSupport(null, null)
+ .add(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY))
+ .addProvider(new RequiredProvider())
+ .addProvider(new RequiredProvider2())
+ .build();
+ }
+ }
+
+ /**
* A base class for mock aspects to reduce boilerplate.
*/
public abstract static class BaseAspect extends NativeAspectClass
@@ -203,7 +231,7 @@
private static final AspectDefinition EXTRA_ATTRIBUTE_ASPECT_REQUIRING_PROVIDER_DEFINITION =
new AspectDefinition.Builder(EXTRA_ATTRIBUTE_ASPECT_REQUIRING_PROVIDER)
.add(attr("$dep", LABEL).value(Label.parseAbsoluteUnchecked("//extra:extra")))
- .requireProvider(RequiredProvider.class)
+ .requireProviders(RequiredProvider.class)
.build();
/**
@@ -286,6 +314,17 @@
}
/**
+ * An aspect that requires provider sets {{@link RequiredProvider}} and
+ * {{@link RequiredProvider2}}.
+ */
+ public static class AspectRequiringProviderSets extends BaseAspect {
+ @Override
+ public AspectDefinition getDefinition(AspectParameters aspectParameters) {
+ return ASPECT_REQUIRING_PROVIDER_SETS_DEFINITION;
+ }
+ }
+
+ /**
* An aspect that has a definition depending on parameters provided by originating rule.
*/
public static class ParametrizedDefinitionAspect extends NativeAspectClass
@@ -334,9 +373,18 @@
private static final AspectRequiringProvider ASPECT_REQUIRING_PROVIDER =
new AspectRequiringProvider();
+ private static final AspectRequiringProviderSets ASPECT_REQUIRING_PROVIDER_SETS =
+ new AspectRequiringProviderSets();
private static final AspectDefinition ASPECT_REQUIRING_PROVIDER_DEFINITION =
new AspectDefinition.Builder(ASPECT_REQUIRING_PROVIDER)
- .requireProvider(RequiredProvider.class)
+ .requireProviders(RequiredProvider.class)
+ .build();
+ private static final AspectDefinition ASPECT_REQUIRING_PROVIDER_SETS_DEFINITION =
+ new AspectDefinition.Builder(ASPECT_REQUIRING_PROVIDER_SETS)
+ .requireProviderSets(
+ ImmutableList.of(
+ ImmutableSet.<Class<?>>of(RequiredProvider.class),
+ ImmutableSet.<Class<?>>of(RequiredProvider2.class)))
.build();
/**
@@ -486,6 +534,30 @@
}
/**
+ * A rule that defines an {@link AspectRequiringProviderSets} on one of its attributes.
+ */
+ public static class AspectRequiringProviderSetsRule implements RuleDefinition {
+
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
+ return builder
+ .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
+ .aspect(ASPECT_REQUIRING_PROVIDER_SETS))
+ .add(attr("baz", STRING))
+ .build();
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("aspect_requiring_provider_sets")
+ .factoryClass(DummyRuleFactory.class)
+ .ancestors(BaseRule.class)
+ .build();
+ }
+ }
+
+ /**
* A rule that defines an {@link ExtraAttributeAspect} on one of its attributes.
*/
public static class ExtraAttributeAspectRule implements RuleDefinition {
@@ -731,6 +803,29 @@
}
/**
+ * A rule that advertises another, different provider and implements it.
+ */
+ public static class HonestRule2 implements RuleDefinition {
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
+ return builder
+ .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE))
+ .advertiseProvider(RequiredProvider2.class)
+ .build();
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("honest2")
+ .factoryClass(DummyRuleFactory2.class)
+ .ancestors(BaseRule.class)
+ .build();
+ }
+ }
+
+
+ /**
* Rule with an implcit dependency.
*/
public static class ImplicitDepRule implements RuleDefinition {