Implement Skylark aspects originating from Skylark rules.
--
MOS_MIGRATED_REVID=108777120
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
index f445eb66..58b9386 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
@@ -14,6 +14,8 @@
package com.google.devtools.build.lib.rules;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.Attribute;
@@ -21,6 +23,7 @@
import com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition;
import com.google.devtools.build.lib.packages.Attribute.SkylarkLateBound;
import com.google.devtools.build.lib.packages.BuildType;
+import com.google.devtools.build.lib.rules.SkylarkRuleClassFunctions.SkylarkAspect;
import com.google.devtools.build.lib.syntax.BuiltinFunction;
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.EvalException;
@@ -68,6 +71,10 @@
"which rule targets (name of the classes) are allowed. This is deprecated (kept only for "
+ "compatiblity), use providers instead.";
+ private static final String ASPECTS_ARG = "aspects";
+ private static final String ASPECT_ARG_DOC =
+ "aspects that should be applied to dependencies specified by this attribute";
+
private static final String CONFIGURATION_ARG = "cfg";
private static final String CONFIGURATION_DOC =
"configuration of the attribute. " + "For example, use DATA_CFG or HOST_CFG.";
@@ -184,7 +191,7 @@
return builder;
}
- private static Descriptor createAttribute(
+ private static Descriptor createAttrDescriptor(
Map<String, Object> kwargs, Type<?> type, FuncallExpression ast, Environment env)
throws EvalException {
try {
@@ -230,7 +237,7 @@
throws EvalException {
// TODO(bazel-team): Replace literal strings with constants.
env.checkLoadingPhase("attr.int", ast.getLocation());
- return createAttribute(
+ return createAttrDescriptor(
EvalUtils.optionMap(
DEFAULT_ARG, defaultInt, MANDATORY_ARG, mandatory, VALUES_ARG, values),
Type.INTEGER,
@@ -274,7 +281,7 @@
Environment env)
throws EvalException {
env.checkLoadingPhase("attr.string", ast.getLocation());
- return createAttribute(
+ return createAttrDescriptor(
EvalUtils.optionMap(
DEFAULT_ARG, defaultString, MANDATORY_ARG, mandatory, VALUES_ARG, values),
Type.STRING,
@@ -362,7 +369,7 @@
Environment env)
throws EvalException {
env.checkLoadingPhase("attr.label", ast.getLocation());
- return createAttribute(
+ return createAttrDescriptor(
EvalUtils.optionMap(
DEFAULT_ARG,
defaultO,
@@ -417,7 +424,7 @@
Environment env)
throws EvalException {
env.checkLoadingPhase("attr.string_list", ast.getLocation());
- return createAttribute(
+ return createAttrDescriptor(
EvalUtils.optionMap(
DEFAULT_ARG, defaultList, MANDATORY_ARG, mandatory, NON_EMPTY_ARG, nonEmpty),
Type.STRING_LIST,
@@ -457,7 +464,7 @@
Environment env)
throws EvalException {
env.checkLoadingPhase("attr.int_list", ast.getLocation());
- return createAttribute(
+ return createAttrDescriptor(
EvalUtils.optionMap(
DEFAULT_ARG, defaultList, MANDATORY_ARG, mandatory, NON_EMPTY_ARG, nonEmpty),
Type.INTEGER_LIST,
@@ -522,6 +529,13 @@
noneable = true,
defaultValue = "None",
doc = CONFIGURATION_DOC
+ ),
+ @Param(
+ name = ASPECTS_ARG,
+ type = SkylarkList.class,
+ generic1 = SkylarkAspect.class,
+ defaultValue = "[]",
+ doc = ASPECT_ARG_DOC
)
},
useAst = true,
@@ -538,31 +552,48 @@
Boolean mandatory,
Boolean nonEmpty,
Object cfg,
+ SkylarkList aspects,
FuncallExpression ast,
Environment env)
throws EvalException {
env.checkLoadingPhase("attr.label_list", ast.getLocation());
- return createAttribute(
- EvalUtils.optionMap(
- DEFAULT_ARG,
- defaultList,
- ALLOW_FILES_ARG,
- allowFiles,
- ALLOW_RULES_ARG,
- allowRules,
- PROVIDERS_ARG,
- providers,
- FLAGS_ARG,
- flags,
- MANDATORY_ARG,
- mandatory,
- NON_EMPTY_ARG,
- nonEmpty,
- CONFIGURATION_ARG,
- cfg),
- BuildType.LABEL_LIST,
- ast,
- env);
+ ImmutableMap<String, Object> kwargs = EvalUtils.optionMap(
+ DEFAULT_ARG, defaultList,
+ ALLOW_FILES_ARG,
+ allowFiles,
+ ALLOW_RULES_ARG,
+ allowRules,
+ PROVIDERS_ARG,
+ providers,
+ FLAGS_ARG,
+ flags,
+ MANDATORY_ARG,
+ mandatory,
+ NON_EMPTY_ARG,
+ nonEmpty,
+ CONFIGURATION_ARG,
+ cfg);
+ try {
+ Attribute.Builder<?> attribute = createAttribute(
+ BuildType.LABEL_LIST, kwargs, ast, env);
+
+ ImmutableList<SkylarkAspect> skylarkAspects = getSkylarkAspects(aspects);
+ return new Descriptor(attribute, skylarkAspects);
+ } catch (ConversionException e) {
+ throw new EvalException(ast.getLocation(), e.getMessage());
+ }
+ }
+
+ protected ImmutableList<SkylarkAspect> getSkylarkAspects(SkylarkList aspects)
+ throws ConversionException {
+ ImmutableList.Builder<SkylarkAspect> aspectBuilder = ImmutableList.builder();
+ for (Object aspect : aspects) {
+ if (!(aspect instanceof SkylarkAspect)) {
+ throw new ConversionException("Expected a list of aspects for 'aspects'");
+ }
+ aspectBuilder.add((SkylarkAspect) aspect);
+ }
+ return aspectBuilder.build();
}
};
@@ -585,7 +616,7 @@
Boolean defaultO, Boolean mandatory, FuncallExpression ast, Environment env)
throws EvalException {
env.checkLoadingPhase("attr.bool", ast.getLocation());
- return createAttribute(
+ return createAttrDescriptor(
EvalUtils.optionMap(DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
Type.BOOLEAN,
ast,
@@ -621,7 +652,7 @@
Object defaultO, Boolean mandatory, FuncallExpression ast, Environment env)
throws EvalException {
env.checkLoadingPhase("attr.output", ast.getLocation());
- return createAttribute(
+ return createAttrDescriptor(
EvalUtils.optionMap(DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
BuildType.OUTPUT,
ast,
@@ -662,7 +693,7 @@
Environment env)
throws EvalException {
env.checkLoadingPhase("attr.output_list", ast.getLocation());
- return createAttribute(
+ return createAttrDescriptor(
EvalUtils.optionMap(
DEFAULT_ARG, defaultList, MANDATORY_ARG, mandatory, NON_EMPTY_ARG, nonEmpty),
BuildType.OUTPUT_LIST,
@@ -698,7 +729,7 @@
Environment env)
throws EvalException {
env.checkLoadingPhase("attr.string_dict", ast.getLocation());
- return createAttribute(
+ return createAttrDescriptor(
EvalUtils.optionMap(
DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory, NON_EMPTY_ARG, nonEmpty),
Type.STRING_DICT,
@@ -734,7 +765,7 @@
Environment env)
throws EvalException {
env.checkLoadingPhase("attr.string_list_dict", ast.getLocation());
- return createAttribute(
+ return createAttrDescriptor(
EvalUtils.optionMap(
DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory, NON_EMPTY_ARG, nonEmpty),
Type.STRING_LIST_DICT,
@@ -764,7 +795,7 @@
Object defaultO, Boolean mandatory, FuncallExpression ast, Environment env)
throws EvalException {
env.checkLoadingPhase("attr.license", ast.getLocation());
- return createAttribute(
+ return createAttrDescriptor(
EvalUtils.optionMap(DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
BuildType.LICENSE,
ast,
@@ -777,14 +808,24 @@
*/
public static final class Descriptor {
private final Attribute.Builder<?> attributeBuilder;
+ private final ImmutableList<SkylarkAspect> aspects;
public Descriptor(Attribute.Builder<?> attributeBuilder) {
+ this(attributeBuilder, ImmutableList.<SkylarkAspect>of());
+ }
+
+ public Descriptor(Attribute.Builder<?> attributeBuilder, ImmutableList<SkylarkAspect> aspects) {
this.attributeBuilder = attributeBuilder;
+ this.aspects = aspects;
}
public Attribute.Builder<?> getAttributeBuilder() {
return attributeBuilder;
}
+
+ public ImmutableList<SkylarkAspect> getAspects() {
+ return aspects;
+ }
}
static {