blob: 18eaf8f2f366141adf8c6a0d2f0ddc1a2cb61bbf [file] [log] [blame]
// Copyright 2015 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.analysis.util;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.packages.Type.STRING;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableCollection;
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.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.Runfiles;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
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.AspectParameters;
import com.google.devtools.build.lib.packages.Attribute.LabelListLateBoundDefault;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.NativeAspectClass;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.rules.java.JavaConfiguration;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.util.FileTypeSet;
import java.util.List;
/**
* 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 used as sentinel. Created by aspects.
*/
@Immutable
public static final class FooProvider implements TransitiveInfoProvider {
}
/**
* A transitive info provider used as sentinel. Created by aspects.
*/
@Immutable
public static final class BarProvider implements TransitiveInfoProvider {
}
/**
* 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 {
}
/**
* 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);
Iterable<String> attributeNames = ruleContext.attributes().getAttributeNames();
for (String attributeName : attributeNames) {
Type<?> attributeType = ruleContext.attributes().getAttributeType(attributeName);
if (!LABEL.equals(attributeType) && !LABEL_LIST.equals(attributeType)) {
continue;
}
Iterable<AspectInfo> prerequisites = ruleContext
.getPrerequisites(attributeName, Mode.DONT_CHECK, AspectInfo.class);
for (AspectInfo prerequisite : prerequisites) {
result.addTransitive(prerequisite.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, RuleErrorException, ActionConflictException {
RuleConfiguredTargetBuilder builder =
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));
if (ruleContext.getRule().getRuleClassObject().getName().equals("honest")) {
builder.addProvider(new RequiredProvider());
}
return builder.build();
}
}
/**
* 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, RuleErrorException, ActionConflictException {
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 simple rule configured target factory that expects different providers added through
* different aspects.
*/
public static class MultiAspectRuleFactory implements RuleConfiguredTargetFactory {
@Override
public ConfiguredTarget create(RuleContext ruleContext)
throws InterruptedException, RuleErrorException, ActionConflictException {
TransitiveInfoCollection fooAttribute = ruleContext.getPrerequisite("foo", Mode.DONT_CHECK);
TransitiveInfoCollection barAttribute = ruleContext.getPrerequisite("bar", Mode.DONT_CHECK);
NestedSetBuilder<String> infoBuilder = NestedSetBuilder.<String>stableOrder();
if (fooAttribute.getProvider(FooProvider.class) != null) {
infoBuilder.add("foo");
}
if (barAttribute.getProvider(BarProvider.class) != null) {
infoBuilder.add("bar");
}
RuleConfiguredTargetBuilder builder =
new RuleConfiguredTargetBuilder(ruleContext)
.addProvider(
new RuleInfo(infoBuilder.build()))
.setFilesToBuild(NestedSetBuilder.<Artifact>create(Order.STABLE_ORDER))
.setRunfilesSupport(null, null)
.add(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY));
return builder.build();
}
}
/**
* A base class for mock aspects to reduce boilerplate.
*/
public abstract static class BaseAspect extends NativeAspectClass
implements ConfiguredAspectFactory {
@Override
public ConfiguredAspect create(
ConfiguredTargetAndData ctadBase,
RuleContext ruleContext,
AspectParameters parameters,
String toolsRepository)
throws ActionConflictException {
String information = parameters.isEmpty()
? ""
: " data " + Iterables.getFirst(parameters.getAttribute("baz"), null);
return new ConfiguredAspect.Builder(this, parameters, ruleContext)
.addProvider(
new AspectInfo(
collectAspectData("aspect " + ruleContext.getLabel() + information, ruleContext)))
.build();
}
}
public static final SimpleAspect SIMPLE_ASPECT = new SimpleAspect();
public static final FooProviderAspect FOO_PROVIDER_ASPECT = new FooProviderAspect();
public static final BarProviderAspect BAR_PROVIDER_ASPECT = new BarProviderAspect();
private static final AspectDefinition SIMPLE_ASPECT_DEFINITION =
new AspectDefinition.Builder(SIMPLE_ASPECT).build();
private static final AspectDefinition FOO_PROVIDER_ASPECT_DEFINITION =
new AspectDefinition.Builder(FOO_PROVIDER_ASPECT).build();
private static final AspectDefinition BAR_PROVIDER_ASPECT_DEFINITION =
new AspectDefinition.Builder(BAR_PROVIDER_ASPECT).build();
/**
* A very simple aspect.
*/
public static class SimpleAspect extends BaseAspect {
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
return SIMPLE_ASPECT_DEFINITION;
}
}
/**
* A simple aspect that propagates a FooProvider provider.
*/
public static class FooProviderAspect extends NativeAspectClass
implements ConfiguredAspectFactory {
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
return FOO_PROVIDER_ASPECT_DEFINITION;
}
@Override
public ConfiguredAspect create(
ConfiguredTargetAndData ctadBase,
RuleContext ruleContext,
AspectParameters parameters,
String toolsRepository)
throws ActionConflictException {
return new ConfiguredAspect.Builder(this, parameters, ruleContext)
.addProvider(new FooProvider())
.build();
}
}
/**
* A simple aspect that propagates a BarProvider provider.
*/
public static class BarProviderAspect extends NativeAspectClass
implements ConfiguredAspectFactory{
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
return BAR_PROVIDER_ASPECT_DEFINITION;
}
@Override
public ConfiguredAspect create(
ConfiguredTargetAndData ctadBase,
RuleContext ruleContext,
AspectParameters parameters,
String toolsRepository)
throws ActionConflictException {
return new ConfiguredAspect.Builder(this, parameters, ruleContext)
.addProvider(new BarProvider())
.build();
}
}
public static final ExtraAttributeAspect EXTRA_ATTRIBUTE_ASPECT = new ExtraAttributeAspect();
private static final AspectDefinition EXTRA_ATTRIBUTE_ASPECT_DEFINITION =
new AspectDefinition.Builder(EXTRA_ATTRIBUTE_ASPECT)
.add(attr("$dep", LABEL).value(Label.parseAbsoluteUnchecked("//extra:extra")))
.build();
private static final ExtraAttributeAspectRequiringProvider
EXTRA_ATTRIBUTE_ASPECT_REQUIRING_PROVIDER = new ExtraAttributeAspectRequiringProvider();
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")))
.requireProviders(RequiredProvider.class)
.build();
/**
* An aspect that defines its own implicit attribute.
*/
public static class ExtraAttributeAspect extends BaseAspect {
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
return EXTRA_ATTRIBUTE_ASPECT_DEFINITION;
}
}
public static final AttributeAspect ATTRIBUTE_ASPECT = new AttributeAspect();
private static final AspectDefinition ATTRIBUTE_ASPECT_DEFINITION =
new AspectDefinition.Builder(ATTRIBUTE_ASPECT)
.propagateAlongAttribute("foo")
.build();
/**
* An aspect that propagates along all attributes.
*/
public static class AllAttributesAspect extends BaseAspect {
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
return ALL_ATTRIBUTES_ASPECT_DEFINITION;
}
}
public static final NativeAspectClass ALL_ATTRIBUTES_ASPECT = new AllAttributesAspect();
private static final AspectDefinition ALL_ATTRIBUTES_ASPECT_DEFINITION =
new AspectDefinition.Builder(ALL_ATTRIBUTES_ASPECT)
.propagateAlongAllAttributes()
.build();
/** An aspect that propagates along all attributes and has a tool dependency. */
public static class AllAttributesWithToolAspect extends BaseAspect {
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
return ALL_ATTRIBUTES_WITH_TOOL_ASPECT_DEFINITION;
}
}
public static final NativeAspectClass ALL_ATTRIBUTES_WITH_TOOL_ASPECT =
new AllAttributesWithToolAspect();
private static final AspectDefinition ALL_ATTRIBUTES_WITH_TOOL_ASPECT_DEFINITION =
new AspectDefinition.Builder(ALL_ATTRIBUTES_WITH_TOOL_ASPECT)
.propagateAlongAllAttributes()
.add(
attr("$tool", BuildType.LABEL)
.allowedFileTypes(FileTypeSet.ANY_FILE)
.value(Label.parseAbsoluteUnchecked("//a:tool")))
.build();
/**
* An aspect that requires aspects on the attributes of rules it attaches to.
*/
public static class AttributeAspect extends BaseAspect {
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
return ATTRIBUTE_ASPECT_DEFINITION;
}
}
/**
* An aspect that defines its own implicit attribute and requires provider.
*/
public static class ExtraAttributeAspectRequiringProvider extends BaseAspect {
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
return EXTRA_ATTRIBUTE_ASPECT_REQUIRING_PROVIDER_DEFINITION;
}
}
public static class AspectRequiringProvider extends BaseAspect {
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
return ASPECT_REQUIRING_PROVIDER_DEFINITION;
}
}
/**
* 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
implements ConfiguredAspectFactory {
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
AspectDefinition.Builder builder =
new AspectDefinition.Builder(PARAMETRIZED_DEFINITION_ASPECT)
.propagateAlongAttribute("foo");
ImmutableCollection<String> baz = aspectParameters.getAttribute("baz");
if (baz != null) {
try {
builder.add(
attr("$dep", LABEL)
.value(Label.parseAbsolute(baz.iterator().next(), ImmutableMap.of())));
} catch (LabelSyntaxException e) {
throw new IllegalStateException(e);
}
}
return builder.build();
}
@Override
public ConfiguredAspect create(
ConfiguredTargetAndData ctadBase,
RuleContext ruleContext,
AspectParameters parameters,
String toolsRepository)
throws ActionConflictException {
StringBuilder information = new StringBuilder("aspect " + ruleContext.getLabel());
if (!parameters.isEmpty()) {
information.append(" data " + Iterables.getFirst(parameters.getAttribute("baz"), null));
information.append(" ");
}
List<? extends TransitiveInfoCollection> deps =
ruleContext.getPrerequisites("$dep", Mode.TARGET);
information.append("$dep:[");
for (TransitiveInfoCollection dep : deps) {
information.append(" ");
information.append(dep.getLabel());
}
information.append("]");
return new ConfiguredAspect.Builder(this, parameters, ruleContext)
.addProvider(new AspectInfo(collectAspectData(information.toString(), ruleContext)))
.build();
}
}
static final ParametrizedDefinitionAspect PARAMETRIZED_DEFINITION_ASPECT =
new ParametrizedDefinitionAspect();
static final AspectRequiringProvider ASPECT_REQUIRING_PROVIDER = new AspectRequiringProvider();
static final AspectRequiringProviderSets ASPECT_REQUIRING_PROVIDER_SETS =
new AspectRequiringProviderSets();
private static final AspectDefinition ASPECT_REQUIRING_PROVIDER_DEFINITION =
new AspectDefinition.Builder(ASPECT_REQUIRING_PROVIDER)
.requireProviders(RequiredProvider.class)
.propagateAlongAttribute("foo")
.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();
/**
* An aspect that prints a warning.
*/
public static class WarningAspect extends NativeAspectClass
implements ConfiguredAspectFactory {
@Override
public ConfiguredAspect create(
ConfiguredTargetAndData ctadBase,
RuleContext ruleContext,
AspectParameters parameters,
String toolsRepository)
throws ActionConflictException {
ruleContext.ruleWarning("Aspect warning on " + ctadBase.getTarget().getLabel());
return new ConfiguredAspect.Builder(this, parameters, ruleContext).build();
}
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
return WARNING_ASPECT_DEFINITION;
}
}
public static final WarningAspect WARNING_ASPECT = new WarningAspect();
private static final AspectDefinition WARNING_ASPECT_DEFINITION =
new AspectDefinition.Builder(WARNING_ASPECT)
.propagateAlongAttribute("bar")
.build();
/**
* An aspect that raises an error.
*/
public static class ErrorAspect extends NativeAspectClass
implements ConfiguredAspectFactory {
@Override
public ConfiguredAspect create(
ConfiguredTargetAndData ctadBase,
RuleContext ruleContext,
AspectParameters parameters,
String toolsRepository) {
ruleContext.ruleError("Aspect error");
return null;
}
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
return ERROR_ASPECT_DEFINITION;
}
}
public static final ErrorAspect ERROR_ASPECT = new ErrorAspect();
private static final AspectDefinition ERROR_ASPECT_DEFINITION =
new AspectDefinition.Builder(ERROR_ASPECT)
.propagateAlongAttribute("bar")
.build();
/**
* An aspect that advertises but fails to provide providers.
*/
public static class FalseAdvertisementAspect extends NativeAspectClass
implements ConfiguredAspectFactory {
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
return FALSE_ADVERTISEMENT_DEFINITION;
}
@Override
public ConfiguredAspect create(
ConfiguredTargetAndData ctadBase,
RuleContext context,
AspectParameters parameters,
String toolsRepository)
throws InterruptedException, ActionConflictException {
return new ConfiguredAspect.Builder(this, parameters, context).build();
}
}
public static final FalseAdvertisementAspect FALSE_ADVERTISEMENT_ASPECT
= new FalseAdvertisementAspect();
private static final AspectDefinition FALSE_ADVERTISEMENT_DEFINITION =
new AspectDefinition.Builder(FALSE_ADVERTISEMENT_ASPECT)
.advertiseProvider(RequiredProvider.class)
.advertiseProvider(
ImmutableList.of(SkylarkProviderIdentifier.forLegacy("advertised_provider")))
.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 final MockRule BASE_RULE = () ->
MockRule.factory(DummyRuleFactory.class).define("base");
/**
* A rule that defines an aspect on one of its attributes.
*/
public static final MockRule ASPECT_REQUIRING_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"aspect",
attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
.aspect(SIMPLE_ASPECT),
attr("bar", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
.aspect(SIMPLE_ASPECT));
/**
* A rule that defines different aspects on different attributes.
*/
public static final MockRule MULTI_ASPECT_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(MultiAspectRuleFactory.class).define(
"multi_aspect",
attr("foo", LABEL).allowedFileTypes(FileTypeSet.ANY_FILE)
.mandatory()
.aspect(FOO_PROVIDER_ASPECT),
attr("bar", LABEL).allowedFileTypes(FileTypeSet.ANY_FILE)
.mandatory()
.aspect(BAR_PROVIDER_ASPECT));
private static final Function<Rule, AspectParameters> TEST_ASPECT_PARAMETERS_EXTRACTOR =
(rule) -> {
if (rule.isAttrDefined("baz", STRING)) {
String value = rule.getAttributeContainer().getAttr("baz").toString();
if (!value.equals("")) {
return new AspectParameters.Builder().addAttribute("baz", value).build();
}
}
return AspectParameters.EMPTY;
};
/**
* A rule that defines an {@link AspectRequiringProvider} on one of its attributes.
*/
public static final MockRule ASPECT_REQUIRING_PROVIDER_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"aspect_requiring_provider",
(builder, env) ->
builder
.add(
attr("foo", LABEL_LIST)
.allowedFileTypes(FileTypeSet.ANY_FILE)
.aspect(ASPECT_REQUIRING_PROVIDER, TEST_ASPECT_PARAMETERS_EXTRACTOR))
.add(attr("baz", STRING)));
/**
* A rule that defines an {@link AspectRequiringProviderSets} on one of its attributes.
*/
public static final MockRule ASPECT_REQUIRING_PROVIDER_SETS_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"aspect_requiring_provider_sets",
attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
.aspect(ASPECT_REQUIRING_PROVIDER_SETS),
attr("baz", STRING));
/**
* A rule that defines an {@link ExtraAttributeAspect} on one of its attributes.
*/
public static final MockRule EXTRA_ATTRIBUTE_ASPECT_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"rule_with_extra_deps_aspect",
attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
.aspect(EXTRA_ATTRIBUTE_ASPECT));
/**
* A rule that defines an {@link ParametrizedDefinitionAspect} on one of its attributes.
*/
public static final MockRule PARAMETERIZED_DEFINITION_ASPECT_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"parametrized_definition_aspect",
(builder, env) ->
builder
.add(
attr("foo", LABEL_LIST)
.allowedFileTypes(FileTypeSet.ANY_FILE)
.aspect(PARAMETRIZED_DEFINITION_ASPECT, TEST_ASPECT_PARAMETERS_EXTRACTOR))
.add(attr("baz", STRING)));
/**
* A rule that defines an {@link ExtraAttributeAspectRequiringProvider} on one of its attributes.
*/
public static final MockRule EXTRA_ATTRIBUTE_ASPECT_REQUIRING_PROVIDER_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"extra_attribute_aspect_requiring_provider",
attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
.aspect(EXTRA_ATTRIBUTE_ASPECT_REQUIRING_PROVIDER));
/**
* A rule that defines an {@link AllAttributesAspect} on one of its attributes.
*/
public static final MockRule ALL_ATTRIBUTES_ASPECT_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"all_attributes_aspect",
attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
.aspect(ALL_ATTRIBUTES_ASPECT));
/** A rule that defines an {@link AllAttributesWithToolAspect} on one of its attributes. */
public static final MockRule ALL_ATTRIBUTES_WITH_TOOL_ASPECT_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"all_attributes_with_tool_aspect",
attr("foo", LABEL_LIST)
.allowedFileTypes(FileTypeSet.ANY_FILE)
.aspect(ALL_ATTRIBUTES_WITH_TOOL_ASPECT));
/**
* A rule that defines a {@link WarningAspect} on one of its attributes.
*/
public static final MockRule WARNING_ASPECT_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"warning_aspect",
attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
.aspect(WARNING_ASPECT),
attr("bar", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE));
/**
* A rule that defines an {@link ErrorAspect} on one of its attributes.
*/
public static final MockRule ERROR_ASPECT_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"error_aspect",
attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
.aspect(ERROR_ASPECT),
attr("bar", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE));
/**
* A simple rule that has an attribute.
*/
public static final MockRule SIMPLE_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"simple",
attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE),
attr("foo1", LABEL).allowedFileTypes(FileTypeSet.ANY_FILE),
attr("txt", STRING));
/**
* A rule that advertises a provider but doesn't implement it.
*/
public static final MockRule LIAR_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"liar",
(builder, env) ->
builder
.add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE))
.advertiseProvider(RequiredProvider.class));
/**
* A rule that advertises a provider and implements it.
*/
public static final MockRule HONEST_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"honest",
(builder, env) ->
builder
.add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE))
.advertiseProvider(RequiredProvider.class));
/**
* A rule that advertises another, different provider and implements it.
*/
public static final MockRule HONEST_RULE_2 = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory2.class).define(
"honest2",
(builder, env) ->
builder
.add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE))
.advertiseProvider(RequiredProvider2.class));
/**
* Rule with an implcit dependency.
*/
public static final MockRule IMPLICIT_DEP_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"implicit_dep",
attr("$dep", LABEL).value(Label.parseAbsoluteUnchecked("//extra:extra")));
// TODO(b/65746853): provide a way to do this without passing the entire configuration
private static final LabelListLateBoundDefault<?> PLUGINS_LABEL_LIST =
LabelListLateBoundDefault.fromTargetConfiguration(
JavaConfiguration.class, (rule, attributes, javaConfig) -> javaConfig.getPlugins());
public static final MockRule LATE_BOUND_DEP_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"late_bound_dep",
attr(":plugins", LABEL_LIST).value(PLUGINS_LABEL_LIST));
/**
* Rule with {@link FalseAdvertisementAspect}
*/
public static final MockRule FALSE_ADVERTISEMENT_ASPECT_RULE = () ->
MockRule.ancestor(BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
"false_advertisement_aspect",
attr("deps", LABEL_LIST).allowedFileTypes().aspect(FALSE_ADVERTISEMENT_ASPECT));
/** Aspect that propagates over rule outputs. */
public static class AspectApplyingToFiles extends NativeAspectClass
implements ConfiguredAspectFactory {
/** Simple provider for testing */
@Immutable
public static final class Provider implements TransitiveInfoProvider {
private final Label label;
private Provider(Label label) {
this.label = label;
}
public Label getLabel() {
return label;
}
}
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
return AspectDefinition.builder(this).applyToFiles(true).build();
}
@Override
public ConfiguredAspect create(
ConfiguredTargetAndData ctadBase,
RuleContext context,
AspectParameters parameters,
String toolsRepository)
throws InterruptedException, ActionConflictException {
return ConfiguredAspect.builder(this, parameters, context)
.addProvider(Provider.class, new Provider(ctadBase.getConfiguredTarget().getLabel()))
.build();
}
}
}