diff options
author | 2017-03-04 00:58:14 +0000 | |
---|---|---|
committer | 2017-03-06 09:47:03 +0000 | |
commit | 8ff5a87323240625ea5d9efe95f4033d29b6a8f9 (patch) | |
tree | bb413ef618501783ca48fce72906ab83e195e221 /src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java | |
parent | 04c71be192739eae9197e0fe3b054e4278fe16d1 (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.java | 76 |
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(); } |