Open source the aspects-related tests.
--
MOS_MIGRATED_REVID=91907246
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
new file mode 100644
index 0000000..b4b055a
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AspectDefinitionTest.java
@@ -0,0 +1,79 @@
+// Copyright 2015 Google Inc. 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.analysis;
+
+import static com.google.devtools.build.lib.packages.Attribute.attr;
+import static org.junit.Assert.fail;
+
+import com.google.devtools.build.lib.packages.AspectDefinition;
+import com.google.devtools.build.lib.packages.Type;
+import com.google.devtools.build.lib.syntax.Label;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for aspect definitions.
+ */
+@RunWith(JUnit4.class)
+public class AspectDefinitionTest {
+ /**
+ * A dummy aspect factory. Is there to demonstrate how to define aspects and so that we can test
+ * {@code attributeAspect}.
+ */
+ public static final class TestAspectFactory implements ConfiguredAspectFactory {
+ private final AspectDefinition definition;
+
+ /**
+ * Normal aspects will have an argumentless constructor and their definition will be hard-wired
+ * as a static member. This one is different so that we can create the definition in a test
+ * method.
+ */
+ private TestAspectFactory(AspectDefinition definition) {
+ this.definition = definition;
+ }
+
+ @Override
+ public Aspect create(ConfiguredTarget base, RuleContext context) {
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public AspectDefinition getDefinition() {
+ return definition;
+ }
+ }
+
+ @Test
+ public void testSimpleAspect() throws Exception {
+ new AspectDefinition.Builder("simple")
+ .add(attr("$runtime", Type.LABEL).value(Label.parseAbsoluteUnchecked("//run:time")))
+ .attributeAspect("deps", TestAspectFactory.class)
+ .build();
+ }
+
+ @Test
+ public void testAspectWithUserVisibleAttribute() throws Exception {
+ try {
+ new AspectDefinition.Builder("user_visible_attribute")
+ .add(attr("invalid", Type.LABEL).value(Label.parseAbsoluteUnchecked("//run:time")))
+ .attributeAspect("deps", TestAspectFactory.class)
+ .build();
+ fail(); // expected IllegalStateException
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+}
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
new file mode 100644
index 0000000..c8fcf96
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
@@ -0,0 +1,127 @@
+// Copyright 2015 Google Inc. 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.analysis;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
+import com.google.devtools.build.lib.analysis.util.TestAspects;
+import com.google.devtools.build.lib.analysis.util.TestAspects.AspectRequiringRule;
+import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for aspect creation and merging with configured targets.
+ *
+ * <p>Uses the complete analysis machinery and depends on custom rules so that behaviors related to
+ * aspects can be tested even if they aren't used by regular rules.
+ */
+@RunWith(JUnit4.class)
+public class AspectTest extends AnalysisTestCase {
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @SafeVarargs
+ private final void setRules(RuleDefinition... rules) throws Exception {
+ ConfiguredRuleClassProvider.Builder builder =
+ new ConfiguredRuleClassProvider.Builder();
+ TestRuleClassProvider.addStandardRules(builder);
+ for (RuleDefinition rule : rules) {
+ builder.addRuleDefinition(rule);
+ }
+
+ useRuleClassProvider(builder.build());
+ update();
+ }
+
+ private void pkg(String name, String... contents) throws Exception {
+ scratchFile("" + name + "/BUILD", contents);
+ }
+
+ @Test
+ public void providersOfAspectAreMergedIntoDependency() throws Exception {
+ setRules(new TestAspects.BaseRule(), new AspectRequiringRule());
+ pkg("a",
+ "aspect(name='a', foo=[':b'])",
+ "aspect(name='b', foo=[])");
+
+ ConfiguredTarget a = getConfiguredTarget("//a:a");
+ assertThat(a.getProvider(TestAspects.RuleInfo.class).getData())
+ .containsExactly("aspect //a:b", "rule //a:a");
+ }
+
+ @Test
+ public void aspectIsNotCreatedIfAdvertisedProviderIsNotPresent() throws Exception {
+ setRules(new TestAspects.BaseRule(), new TestAspects.LiarRule(),
+ new TestAspects.AspectRequiringProviderRule());
+
+ pkg("a",
+ "aspect_requiring_provider(name='a', foo=[':b'])",
+ "liar(name='b', foo=[])");
+
+ ConfiguredTarget a = getConfiguredTarget("//a:a");
+ assertThat(a.getProvider(TestAspects.RuleInfo.class).getData())
+ .containsExactly("rule //a:a");
+ }
+
+ @Test
+ public void aspectCreatedIfAdvertisedProviderIsPresent() throws Exception {
+ setRules(new TestAspects.BaseRule(), new TestAspects.HonestRule(),
+ new TestAspects.AspectRequiringProviderRule());
+
+ pkg("a",
+ "aspect_requiring_provider(name='a', foo=[':b'])",
+ "honest(name='b', foo=[])");
+
+ ConfiguredTarget a = getConfiguredTarget("//a:a");
+ assertThat(a.getProvider(TestAspects.RuleInfo.class).getData())
+ .containsExactly("rule //a:a", "aspect //a:b");
+ }
+
+ @Test
+ public void aspectInError() throws Exception {
+ setRules(new TestAspects.BaseRule(), new TestAspects.ErrorAspectRule(),
+ new TestAspects.SimpleRule());
+
+ pkg("a",
+ "simple(name='a', foo=[':b'])",
+ "error_aspect(name='b', foo=[':c'])",
+ "simple(name='c')");
+
+ reporter.removeHandler(failFastHandler);
+ // getConfiguredTarget() uses a separate code path that does not hit
+ // SkyframeBuildView#configureTargets
+ try {
+ update("//a:a");
+ fail();
+ } catch (ViewCreationFailedException e) {
+ // expected
+ }
+ assertContainsEvent("Aspect error");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/AspectValueTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AspectValueTest.java
new file mode 100644
index 0000000..5365728
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AspectValueTest.java
@@ -0,0 +1,69 @@
+// Copyright 2015 Google Inc. 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.analysis;
+
+import com.google.common.testing.EqualsTester;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
+import com.google.devtools.build.lib.analysis.util.TestAspects;
+import com.google.devtools.build.lib.skyframe.AspectValue;
+import com.google.devtools.build.lib.syntax.Label;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link com.google.devtools.build.lib.skyframe.AspectValue}.
+ */
+@RunWith(JUnit4.class)
+public class AspectValueTest extends AnalysisTestCase {
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Test
+ public void equality() throws Exception {
+ update();
+ BuildConfiguration c1 = getTargetConfiguration();
+ BuildConfiguration c2 = getHostConfiguration();
+ Label l1 = Label.parseAbsolute("//a:l1");
+ Label l1b = Label.parseAbsolute("//a:l1");
+ Label l2 = Label.parseAbsolute("//a:l2");
+ Class<? extends ConfiguredAspectFactory> a1 = TestAspects.AttributeAspect.class;
+ Class<? extends ConfiguredAspectFactory> a2 = TestAspects.ExtraAttributeAspect.class;
+
+ new EqualsTester()
+ .addEqualityGroup(AspectValue.key(l1, c1, a1), AspectValue.key(l1b, c1, a1))
+ .addEqualityGroup(AspectValue.key(l2, c1, a1))
+ .addEqualityGroup(AspectValue.key(l1, c2, a1))
+ .addEqualityGroup(AspectValue.key(l2, c2, a1))
+ .addEqualityGroup(AspectValue.key(l1, c1, a2))
+ .addEqualityGroup(AspectValue.key(l2, c1, a2))
+ .addEqualityGroup(AspectValue.key(l1, c2, a2))
+ .addEqualityGroup(AspectValue.key(l2, c2, a2))
+ .addEqualityGroup(l1) // A random object
+ .testEquals();
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisTestCase.java b/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisTestCase.java
index 4ebd024..54f2593 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisTestCase.java
@@ -139,6 +139,7 @@
mockToolsConfig = new MockToolsConfig(rootDirectory);
mock.setupMockClient(mockToolsConfig);
+ mock.setupMockWorkspaceFiles(directories.getEmbeddedBinariesRoot());
configurationFactory = mock.createConfigurationFactory();
useRuleClassProvider(TestRuleClassProvider.getRuleClassProvider());
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
new file mode 100644
index 0000000..4d0fa69
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
@@ -0,0 +1,418 @@
+// Copyright 2015 Google Inc. 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.analysis.util;
+
+import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST;
+import static com.google.devtools.build.lib.packages.Attribute.attr;
+import static com.google.devtools.build.lib.packages.Type.BOOLEAN;
+import static com.google.devtools.build.lib.packages.Type.LABEL;
+import static com.google.devtools.build.lib.packages.Type.LABEL_LIST;
+import static com.google.devtools.build.lib.packages.Type.NODEP_LABEL_LIST;
+import static com.google.devtools.build.lib.packages.Type.STRING;
+import static com.google.devtools.build.lib.packages.Type.STRING_LIST;
+
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.Aspect;
+import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.RuleDefinition;
+import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
+import com.google.devtools.build.lib.analysis.Runfiles;
+import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+import com.google.devtools.build.lib.packages.AspectDefinition;
+import com.google.devtools.build.lib.packages.RuleClass;
+import com.google.devtools.build.lib.packages.RuleClass.Builder;
+import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
+import com.google.devtools.build.lib.syntax.Label;
+import com.google.devtools.build.lib.util.FileTypeSet;
+
+/**
+ * Various rule and aspect classes that aid in testing the aspect machinery.
+ *
+ * <p>These are mostly used in {@link com.google.devtools.build.lib.analysis.DependencyResolverTest}
+ * and {@link com.google.devtools.build.lib.analysis.AspectTest}.
+ */
+public class TestAspects {
+ /**
+ * A transitive info provider for collecting aspects in the transitive closure. Created by
+ * aspects.
+ */
+ @Immutable
+ public static final class AspectInfo implements TransitiveInfoProvider {
+ private final NestedSet<String> data;
+
+ public AspectInfo(NestedSet<String> data) {
+ this.data = data;
+ }
+
+ public NestedSet<String> getData() {
+ return data;
+ }
+ }
+
+ /**
+ * A transitive info provider for collecting aspects in the transitive closure. Created by
+ * rules.
+ */
+ @Immutable
+ public static final class RuleInfo implements TransitiveInfoProvider {
+ private final NestedSet<String> data;
+
+ public RuleInfo(NestedSet<String> data) {
+ this.data = data;
+ }
+
+ public NestedSet<String> getData() {
+ return data;
+ }
+ }
+
+ /**
+ * A 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 RequiredProvider implements TransitiveInfoProvider {
+ }
+
+ private static NestedSet<String> collectAspectData(String me, RuleContext ruleContext) {
+ NestedSetBuilder<String> result = new NestedSetBuilder<>(Order.STABLE_ORDER);
+ result.add(me);
+ for (AspectInfo dep : ruleContext.getPrerequisites("foo", Mode.TARGET, AspectInfo.class)) {
+ result.addTransitive(dep.getData());
+ }
+
+ return result.build();
+ }
+
+ /**
+ * A simple rule configured target factory that is used in all the mock rules in this class.
+ */
+ public static class DummyRuleFactory implements RuleConfiguredTargetFactory {
+ @Override
+ public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException {
+
+ RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext)
+ .addProvider(RuleInfo.class,
+ new RuleInfo(collectAspectData("rule " + ruleContext.getLabel(), ruleContext)))
+ .setFilesToBuild(NestedSetBuilder.<Artifact>create(Order.STABLE_ORDER))
+ .setRunfilesSupport(null, null)
+ .add(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY));
+
+ if (ruleContext.getRule().getRuleClassObject().getName().equals("honest")) {
+ builder.addProvider(RequiredProvider.class, new RequiredProvider());
+ }
+
+ return builder.build();
+ }
+ }
+
+ /**
+ * A base class for mock aspects to reduce boilerplate.
+ */
+ public abstract static class BaseAspect implements ConfiguredAspectFactory {
+ @Override
+ public Aspect create(ConfiguredTarget base, RuleContext ruleContext) {
+ return new Aspect.Builder()
+ .addProvider(AspectInfo.class,
+ new AspectInfo(collectAspectData("aspect " + ruleContext.getLabel(), ruleContext)))
+ .build();
+ }
+ }
+
+ private static final AspectDefinition SIMPLE_ASPECT =
+ new AspectDefinition.Builder("simple").build();
+
+ /**
+ * A very simple aspect.
+ */
+ public static class SimpleAspect extends BaseAspect {
+ @Override
+ public AspectDefinition getDefinition() {
+ return SIMPLE_ASPECT;
+ }
+ }
+
+ private static final AspectDefinition EXTRA_ATTRIBUTE_ASPECT =
+ new AspectDefinition.Builder("extra_attribute")
+ .add(attr("$dep", LABEL).value(Label.parseAbsoluteUnchecked("//extra:extra")))
+ .build();
+
+ private static final AspectDefinition EXTRA_ATTRIBUTE_ASPECT_REQUIRING_PROVIDER =
+ new AspectDefinition.Builder("extra_attribute_with_provider")
+ .add(attr("$dep", LABEL).value(Label.parseAbsoluteUnchecked("//extra:extra")))
+ .requireProvider(RequiredProvider.class)
+ .build();
+
+ /**
+ * An aspect that defines its own implicit attribute.
+ */
+ public static class ExtraAttributeAspect extends BaseAspect {
+ @Override
+ public AspectDefinition getDefinition() {
+ return EXTRA_ATTRIBUTE_ASPECT;
+ }
+ }
+
+ private static final AspectDefinition ATTRIBUTE_ASPECT = new AspectDefinition.Builder("attribute")
+ .attributeAspect("foo", AttributeAspect.class)
+ .build();
+
+ /**
+ * An aspect that requires aspects on the attributes of rules it attaches to.
+ */
+ public static class AttributeAspect extends BaseAspect {
+ @Override
+ public AspectDefinition getDefinition() {
+ return ATTRIBUTE_ASPECT;
+ }
+ }
+
+ /**
+ * An aspect that defines its own implicit attribute and requires provider.
+ */
+ public static class ExtraAttributeAspectRequiringProvider extends BaseAspect {
+ @Override
+ public AspectDefinition getDefinition() {
+ return EXTRA_ATTRIBUTE_ASPECT_REQUIRING_PROVIDER;
+ }
+ }
+
+ public static class AspectRequiringProvider extends BaseAspect {
+ @Override
+ public AspectDefinition getDefinition() {
+ return ASPECT_REQUIRING_PROVIDER;
+ }
+ }
+
+ private static final AspectDefinition ASPECT_REQUIRING_PROVIDER =
+ new AspectDefinition.Builder("requiring_provider")
+ .requireProvider(RequiredProvider.class)
+ .build();
+
+ /**
+ * An aspect that raises an error.
+ */
+ public static class ErrorAspect implements ConfiguredAspectFactory {
+ @Override
+ public Aspect create(ConfiguredTarget base, RuleContext ruleContext) {
+ ruleContext.ruleError("Aspect error");
+ return null;
+ }
+
+ @Override
+ public AspectDefinition getDefinition() {
+ return ERROR_ASPECT;
+ }
+ }
+
+ private static final AspectDefinition ERROR_ASPECT = new AspectDefinition.Builder("error")
+ .build();
+
+ /**
+ * A common base rule for mock rules in this class to reduce boilerplate.
+ *
+ * <p>It has a few common attributes because internal Blaze machinery assumes the presence of
+ * these.
+ */
+ public static class BaseRule implements RuleDefinition {
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
+ return builder
+ .add(attr("testonly", BOOLEAN).nonconfigurable("test").value(false))
+ .add(attr("deprecation", STRING).nonconfigurable("test"))
+ .add(attr("tags", STRING_LIST))
+ .add(attr("visibility", NODEP_LABEL_LIST).orderIndependent().cfg(HOST)
+ .nonconfigurable("test"))
+ .add(attr(RuleClass.COMPATIBLE_ENVIRONMENT_ATTR, LABEL_LIST)
+ .allowedFileTypes(FileTypeSet.NO_FILE))
+ .add(attr(RuleClass.RESTRICTED_ENVIRONMENT_ATTR, LABEL_LIST)
+ .allowedFileTypes(FileTypeSet.NO_FILE))
+ .build();
+
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("base")
+ .factoryClass(DummyRuleFactory.class)
+ .build();
+ }
+ }
+
+ /**
+ * A rule that defines an aspect on one of its attributes.
+ */
+ public static class AspectRequiringRule implements RuleDefinition {
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
+ return builder
+ .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
+ .aspect(SimpleAspect.class))
+ .build();
+
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("aspect")
+ .factoryClass(DummyRuleFactory.class)
+ .ancestors(BaseRule.class)
+ .build();
+ }
+ }
+
+ /**
+ * A rule that defines an {@link AspectRequiringProvider} on one of its attributes.
+ */
+ public static class AspectRequiringProviderRule implements RuleDefinition {
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
+ return builder
+ .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
+ .aspect(AspectRequiringProvider.class))
+ .build();
+
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("aspect_requiring_provider")
+ .factoryClass(DummyRuleFactory.class)
+ .ancestors(BaseRule.class)
+ .build();
+ }
+ }
+
+ /**
+ * A rule that defines an {@link ExtraAttributeAspectRequiringProvider} on one of its attributes.
+ */
+ public static class ExtraAttributeAspectRequiringProviderRule implements RuleDefinition {
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
+ return builder
+ .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
+ .aspect(ExtraAttributeAspectRequiringProvider.class))
+ .build();
+
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("extra_attribute_aspect_requiring_provider")
+ .factoryClass(DummyRuleFactory.class)
+ .ancestors(BaseRule.class)
+ .build();
+ }
+ }
+
+ /**
+ * A rule that defines an {@link AspectRequiringProvider} on one of its attributes.
+ */
+ public static class ErrorAspectRule implements RuleDefinition {
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
+ return builder
+ .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
+ .aspect(ErrorAspect.class))
+ .build();
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("error_aspect")
+ .factoryClass(DummyRuleFactory.class)
+ .ancestors(BaseRule.class)
+ .build();
+ }
+ }
+
+ /**
+ * A simple rule that has an attribute.
+ */
+ public static class SimpleRule implements RuleDefinition {
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
+ return builder
+ .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE))
+ .build();
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("simple")
+ .factoryClass(DummyRuleFactory.class)
+ .ancestors(BaseRule.class)
+ .build();
+ }
+ }
+
+ /**
+ * A rule that advertises a provider but doesn't implement it.
+ */
+ public static class LiarRule implements RuleDefinition {
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
+ return builder
+ .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE))
+ .advertiseProvider(RequiredProvider.class)
+ .build();
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("liar")
+ .factoryClass(DummyRuleFactory.class)
+ .ancestors(BaseRule.class)
+ .build();
+ }
+ }
+
+ /**
+ * A rule that advertises a provider and implements it.
+ */
+ public static class HonestRule implements RuleDefinition {
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
+ return builder
+ .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE))
+ .advertiseProvider(RequiredProvider.class)
+ .build();
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("honest")
+ .factoryClass(DummyRuleFactory.class)
+ .ancestors(BaseRule.class)
+ .build();
+ }
+ }
+}