aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
diff options
context:
space:
mode:
authorGravatar Dmitry Lomov <dslomov@google.com>2017-03-04 00:58:14 +0000
committerGravatar Yue Gan <yueg@google.com>2017-03-06 09:47:03 +0000
commit8ff5a87323240625ea5d9efe95f4033d29b6a8f9 (patch)
treebb413ef618501783ca48fce72906ab83e195e221 /src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
parent04c71be192739eae9197e0fe3b054e4278fe16d1 (diff)
Allow declared providers in attribute and aspect defintions.
-- PiperOrigin-RevId: 149169656 MOS_MIGRATED_REVID=149169656
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java76
1 files changed, 53 insertions, 23 deletions
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 4c18384f4d..3f2b066575 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
@@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.Attribute.AllowedValueSet;
import com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition;
@@ -26,6 +27,7 @@ import com.google.devtools.build.lib.packages.Attribute.SkylarkComputedDefaultTe
import com.google.devtools.build.lib.packages.Attribute.SplitTransition;
import com.google.devtools.build.lib.packages.AttributeValueSource;
import com.google.devtools.build.lib.packages.BuildType;
+import com.google.devtools.build.lib.packages.ClassObjectConstructor;
import com.google.devtools.build.lib.packages.SkylarkAspect;
import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
import com.google.devtools.build.lib.skylarkinterface.Param;
@@ -256,7 +258,7 @@ public final class SkylarkAttr {
Object obj = arguments.get(PROVIDERS_ARG);
SkylarkType.checkType(obj, SkylarkList.class, PROVIDERS_ARG);
ImmutableList<ImmutableSet<SkylarkProviderIdentifier>> providersList = buildProviderPredicate(
- (SkylarkList<?>) obj);
+ (SkylarkList<?>) obj, PROVIDERS_ARG, ast.getLocation());
builder.mandatoryProvidersList(providersList);
}
@@ -288,56 +290,84 @@ public final class SkylarkAttr {
return builder;
}
- public static ImmutableList<ImmutableSet<SkylarkProviderIdentifier>> buildProviderPredicate(
- SkylarkList<?> obj) throws EvalException {
+ /**
+ * Builds a list of sets of accepted providers from Skylark list {@code obj}.
+ * The list can either be a list of providers (in that case the result is a list with one
+ * set) or a list of lists of providers (then the result is the list of sets).
+ * @param argumentName used in error messages.
+ * @param location location for error messages.
+ */
+ static ImmutableList<ImmutableSet<SkylarkProviderIdentifier>> buildProviderPredicate(
+ SkylarkList<?> obj, String argumentName, Location location) throws EvalException {
if (obj.isEmpty()) {
return ImmutableList.of();
}
- boolean isSingleListOfStr = true;
- for (Object o : (SkylarkList) obj) {
- isSingleListOfStr = o instanceof String;
- if (!isSingleListOfStr) {
+ boolean isListOfProviders = true;
+ for (Object o : obj) {
+ if (!isProvider(o)) {
+ isListOfProviders = false;
break;
}
}
- if (isSingleListOfStr) {
- return ImmutableList.of(getSkylarkProviderIdentifiers(obj));
+ if (isListOfProviders) {
+ return ImmutableList.of(getSkylarkProviderIdentifiers(obj, location));
} else {
- return getProvidersList((SkylarkList) obj);
+ return getProvidersList(obj, argumentName, location);
}
}
- private static ImmutableSet<SkylarkProviderIdentifier> getSkylarkProviderIdentifiers(
- SkylarkList<?> obj) throws EvalException {
+ /**
+ * Returns true if {@code o} is a Skylark provider (either a declared provider or
+ * a legacy provider name.
+ */
+ static boolean isProvider(Object o) {
+ return o instanceof String || o instanceof ClassObjectConstructor;
+ }
+
+ /**
+ * Converts Skylark identifiers of providers (either a string or a provider value)
+ * to their internal representations.
+ */
+ static ImmutableSet<SkylarkProviderIdentifier> getSkylarkProviderIdentifiers(
+ SkylarkList<?> list, Location location) throws EvalException {
ImmutableList.Builder<SkylarkProviderIdentifier> result = ImmutableList.builder();
- List<String> contents = obj.getContents(String.class, PROVIDERS_ARG);
- for (String legacyId : contents) {
- result.add(SkylarkProviderIdentifier.forLegacy(legacyId));
+ for (Object obj : list) {
+ if (obj instanceof String) {
+ result.add(SkylarkProviderIdentifier.forLegacy((String) obj));
+ } else if (obj instanceof ClassObjectConstructor) {
+ ClassObjectConstructor constructor = (ClassObjectConstructor) obj;
+ if (!constructor.isExported()) {
+ throw new EvalException(location,
+ "Providers should be assigned to top-level values in modules");
+ }
+ result.add(SkylarkProviderIdentifier.forKey(constructor.getKey()));
+ }
}
return ImmutableSet.copyOf(result.build());
}
private static ImmutableList<ImmutableSet<SkylarkProviderIdentifier>> getProvidersList(
- SkylarkList<?> skylarkList) throws EvalException {
+ SkylarkList<?> skylarkList, String argumentName, Location location) throws EvalException {
ImmutableList.Builder<ImmutableSet<SkylarkProviderIdentifier>> providersList =
ImmutableList.builder();
String errorMsg = "Illegal argument: element in '%s' is of unexpected type. "
- + "Should be list of string, but got %s. "
- + "Notice: one single list of string as 'providers' is still supported.";
+ + "Either all elements should be providers, "
+ + "or all elements should be lists of providers, but got %s.";
+
for (Object o : skylarkList) {
if (!(o instanceof SkylarkList)) {
- throw new EvalException(null, String.format(errorMsg, PROVIDERS_ARG,
- EvalUtils.getDataTypeName(o, true)));
+ throw new EvalException(location, String.format(errorMsg, PROVIDERS_ARG,
+ "an element of type " + EvalUtils.getDataTypeName(o, true)));
}
for (Object value : (SkylarkList) o) {
- if (!(value instanceof String)) {
- throw new EvalException(null, String.format(errorMsg, PROVIDERS_ARG,
+ if (!isProvider(value)) {
+ throw new EvalException(location, String.format(errorMsg, argumentName,
"list with an element of type "
+ EvalUtils.getDataTypeNameFromClass(value.getClass())));
}
}
- providersList.add(getSkylarkProviderIdentifiers((SkylarkList<?>) o));
+ providersList.add(getSkylarkProviderIdentifiers((SkylarkList<?>) o, location));
}
return providersList.build();
}