aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build
diff options
context:
space:
mode:
authorGravatar dslomov <dslomov@google.com>2017-08-25 09:29:50 +0200
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2017-08-25 12:54:36 +0200
commit0667b83f40e0b86b15c08513052f1e23ca9c149f (patch)
tree2dbb6ae362f692c862491fce6826c0e74d9a4c58 /src/main/java/com/google/devtools/build
parente2bfb4bb4017b9a50b6e00b84d2fc52856323592 (diff)
Implement field declarations for declared providers.
RELNOTES: Skylark providers can specify allowed fields and their documentation. PiperOrigin-RevId: 166446104
Diffstat (limited to 'src/main/java/com/google/devtools/build')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java44
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/SkylarkProvider.java50
2 files changed, 84 insertions, 10 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
index 5b4363e104..3e850d966d 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
@@ -74,6 +74,7 @@ import com.google.devtools.build.lib.packages.SkylarkProvider;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.packages.TestSize;
import com.google.devtools.build.lib.skylarkinterface.Param;
+import com.google.devtools.build.lib.skylarkinterface.ParamType;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature;
import com.google.devtools.build.lib.syntax.BaseFunction;
@@ -90,6 +91,7 @@ import com.google.devtools.build.lib.syntax.SkylarkDict;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
import com.google.devtools.build.lib.syntax.SkylarkSignatureProcessor;
+import com.google.devtools.build.lib.syntax.SkylarkType;
import com.google.devtools.build.lib.syntax.SkylarkUtils;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.syntax.Type.ConversionException;
@@ -288,15 +290,53 @@ public class SkylarkRuleClassFunctions {
defaultValue = "''",
doc =
"A description of the provider that can be extracted by documentation generating tools."
+ ),
+ @Param(
+ name = "fields",
+ doc = "If specified, restricts the set of allowed fields. <br>"
+ + "Possible values are:"
+ + "<ul>"
+ + " <li> list of fields:<br>"
+ + " <pre class=\"language-python\">provider(fields = ['a', 'b'])</pre><p>"
+ + " <li> dictionary field name -> documentation:<br>"
+ + " <pre class=\"language-python\">provider(\n"
+ + " fields = { 'a' : 'Documentation for a', 'b' : 'Documentation for b' })</pre>"
+ + "</ul>"
+ + "All fields are optional.",
+ allowedTypes = {
+ @ParamType(type = SkylarkList.class, generic1 = String.class),
+ @ParamType(type = SkylarkDict.class)
+ },
+ noneable = true,
+ named = true,
+ positional = false,
+ defaultValue = "None"
)
},
useLocation = true
)
private static final BuiltinFunction provider =
new BuiltinFunction("provider") {
- public Provider invoke(String doc, Location location) {
+ public Provider invoke(String doc, Object fields, Location location) throws EvalException {
+ Iterable<String> fieldNames = null;
+ if (fields instanceof SkylarkList<?>) {
+ @SuppressWarnings("unchecked")
+ SkylarkList<String> list = (SkylarkList<String>)
+ SkylarkType.cast(
+ fields,
+ SkylarkList.class, String.class, location,
+ "Expected list of strings or dictionary of string -> string for 'fields'");
+ fieldNames = list;
+ } else if (fields instanceof SkylarkDict) {
+ Map<String, String> dict = SkylarkType.castMap(
+ fields,
+ String.class, String.class,
+ "Expected list of strings or dictionary of string -> string for 'fields'");
+ fieldNames = dict.keySet();
+ }
return new SkylarkProvider(
"<no name>", // name is set on export.
+ fieldNames,
location);
}
};
@@ -342,7 +382,7 @@ public class SkylarkRuleClassFunctions {
+ "implicitly added and must not be specified. Attributes "
+ "<code>visibility</code>, <code>deprecation</code>, <code>tags</code>, "
+ "<code>testonly</code>, and <code>features</code> are implicitly added and "
- + "cannot be overriden."
+ + "cannot be overridden."
),
// TODO(bazel-team): need to give the types of these builtin attributes
@Param(
diff --git a/src/main/java/com/google/devtools/build/lib/packages/SkylarkProvider.java b/src/main/java/com/google/devtools/build/lib/packages/SkylarkProvider.java
index d76c006414..852c6c0f54 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/SkylarkProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/SkylarkProvider.java
@@ -14,6 +14,8 @@
package com.google.devtools.build.lib.packages;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
@@ -46,21 +48,48 @@ public class SkylarkProvider extends Provider implements SkylarkExportable {
*
* <p>Needs to be exported later.
*/
- public SkylarkProvider(String name, Location location) {
- this(name, SIGNATURE, location);
+ public SkylarkProvider(String name,
+ @Nullable Iterable<String> fields,
+ Location location) {
+ this(name, buildSignature(fields), location);
}
- public SkylarkProvider(
- String name, FunctionSignature.WithValues<Object, SkylarkType> signature, Location location) {
+ private SkylarkProvider(
+ String name,
+ FunctionSignature.WithValues<Object, SkylarkType> signature, Location location) {
super(name, signature, location);
this.errorMessageFormatForInstances = DEFAULT_ERROR_MESSAFE;
}
+ private static FunctionSignature.WithValues<Object, SkylarkType> buildSignature(
+ @Nullable Iterable<String> fields) {
+ if (fields == null) {
+ return SIGNATURE;
+ }
+ return
+ FunctionSignature.WithValues.create(
+ FunctionSignature.namedOnly(0, ImmutableList.copyOf(fields).toArray(new String[0]))
+ );
+ }
+
@Override
protected Info createInstanceFromSkylark(Object[] args, Location loc) throws EvalException {
- @SuppressWarnings("unchecked")
- Map<String, Object> kwargs = (Map<String, Object>) args[0];
- return new SkylarkInfo(this, kwargs, loc);
+ if (signature.getSignature().getShape().hasKwArg()) {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> kwargs = (Map<String, Object>) args[0];
+ return new SkylarkInfo(this, kwargs, loc);
+ } else {
+ // todo(dslomov): implement shape sharing.
+ ImmutableList<String> names = signature.getSignature().getNames();
+ Preconditions.checkState(names.size() == args.length);
+ ImmutableMap.Builder<String, Object> fields = ImmutableMap.builder();
+ for (int i = 0; i < args.length; i++) {
+ if (args[i] != null) {
+ fields.put(names.get(i), args[i]);
+ }
+ }
+ return new SkylarkInfo(this, fields.build(), loc);
+ }
}
@Override
@@ -75,8 +104,13 @@ public class SkylarkProvider extends Provider implements SkylarkExportable {
}
@Override
+ public String getName() {
+ return key != null ? key.getExportedName() : "<no name>";
+ }
+
+ @Override
public String getPrintableName() {
- return key != null ? key.getExportedName() : getName();
+ return getName();
}
@Override