aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java162
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkCommandLine.java35
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkModules.java38
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java258
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleImplementationFunctions.java225
5 files changed, 377 insertions, 341 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 7d39e0dcfa..46d31e225d 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
@@ -21,6 +21,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.Type;
import com.google.devtools.build.lib.packages.Type.ConversionException;
+import com.google.devtools.build.lib.syntax.BuiltinFunction;
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
@@ -28,11 +29,11 @@ import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.Label;
import com.google.devtools.build.lib.syntax.SkylarkCallbackFunction;
import com.google.devtools.build.lib.syntax.SkylarkEnvironment;
-import com.google.devtools.build.lib.syntax.SkylarkFunction;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkModule;
import com.google.devtools.build.lib.syntax.SkylarkSignature;
import com.google.devtools.build.lib.syntax.SkylarkSignature.Param;
+import com.google.devtools.build.lib.syntax.SkylarkSignatureProcessor;
import com.google.devtools.build.lib.syntax.UserDefinedFunction;
import com.google.devtools.build.lib.util.FileTypeSet;
@@ -171,11 +172,14 @@ public final class SkylarkAttr {
@Param(name = "cfg", type = ConfigurationTransition.class, noneable = true,
defaultValue = "None", doc = CONFIGURATION_DOC)},
useAst = true, useEnvironment = true)
- private static SkylarkFunction integer = new SkylarkFunction("int") {
- @Override
- public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
- throws EvalException {
- return createAttribute(kwargs, Type.INTEGER, ast, env);
+ private static BuiltinFunction integer = new BuiltinFunction("int") {
+ public Attribute.Builder<?> invoke(Integer defaultInt,
+ SkylarkList flags, Boolean mandatory, Object cfg,
+ FuncallExpression ast, Environment env) throws EvalException {
+ return createAttribute(
+ EvalUtils.optionMap(
+ "default", defaultInt, "flags", flags, "mandatory", mandatory, "cfg", cfg),
+ Type.INTEGER, ast, env);
}
};
@@ -193,11 +197,14 @@ public final class SkylarkAttr {
@Param(name = "cfg", type = ConfigurationTransition.class, noneable = true,
defaultValue = "None", doc = CONFIGURATION_DOC)},
useAst = true, useEnvironment = true)
- private static SkylarkFunction string = new SkylarkFunction("string") {
- @Override
- public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
- throws EvalException {
- return createAttribute(kwargs, Type.STRING, ast, env);
+ private static BuiltinFunction string = new BuiltinFunction("string") {
+ public Attribute.Builder<?> invoke(String defaultString,
+ SkylarkList flags, Boolean mandatory, Object cfg,
+ FuncallExpression ast, Environment env) throws EvalException {
+ return createAttribute(
+ EvalUtils.optionMap(
+ "default", defaultString, "flags", flags, "mandatory", mandatory, "cfg", cfg),
+ Type.STRING, ast, env);
}
};
@@ -230,18 +237,31 @@ public final class SkylarkAttr {
@Param(name = "cfg", type = ConfigurationTransition.class, noneable = true,
defaultValue = "None", doc = CONFIGURATION_DOC)},
useAst = true, useEnvironment = true)
- private static SkylarkFunction label = new SkylarkFunction("label") {
- @Override
- public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
- throws EvalException {
- return createAttribute(kwargs, Type.LABEL, ast, env);
+ private static BuiltinFunction label = new BuiltinFunction("label") {
+ public Attribute.Builder<?> invoke(
+ Object defaultO,
+ Boolean executable,
+ SkylarkList flags,
+ Object allowFiles,
+ Boolean mandatory,
+ SkylarkList providers,
+ Object allowRules,
+ Boolean singleFile,
+ Object cfg,
+ FuncallExpression ast, Environment env) throws EvalException {
+ return createAttribute(
+ EvalUtils.optionMap(
+ "default", defaultO, "executable", executable, "flags", flags,
+ "allow_files", allowFiles, "mandatory", mandatory, "providers", providers,
+ "allow_rules", allowRules, "single_file", singleFile, "cfg", cfg),
+ Type.LABEL, ast, env);
}
};
@SkylarkSignature(name = "string_list", doc =
"Creates an attribute of type list of strings",
objectType = SkylarkAttr.class,
- returnType = Attribute.class,
+ returnType = Attribute.Builder.class,
optionalPositionals = {
@Param(name = "default", type = SkylarkList.class, generic1 = String.class,
defaultValue = "[]",
@@ -255,11 +275,19 @@ public final class SkylarkAttr {
@Param(name = "cfg", type = ConfigurationTransition.class, noneable = true,
defaultValue = "None", doc = CONFIGURATION_DOC)},
useAst = true, useEnvironment = true)
- private static SkylarkFunction stringList = new SkylarkFunction("string_list") {
- @Override
- public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
- throws EvalException {
- return createAttribute(kwargs, Type.STRING_LIST, ast, env);
+ private static BuiltinFunction stringList = new BuiltinFunction("string_list") {
+ public Attribute.Builder<?> invoke(
+ SkylarkList defaultList,
+ SkylarkList flags,
+ Boolean mandatory,
+ Boolean nonEmpty,
+ Object cfg,
+ FuncallExpression ast, Environment env) throws EvalException {
+ return createAttribute(
+ EvalUtils.optionMap(
+ "default", defaultList,
+ "flags", flags, "mandatory", mandatory, "non_empty", nonEmpty, "cfg", cfg),
+ Type.STRING_LIST, ast, env);
}
};
@@ -288,11 +316,22 @@ public final class SkylarkAttr {
@Param(name = "cfg", type = ConfigurationTransition.class, noneable = true,
defaultValue = "None", doc = CONFIGURATION_DOC)},
useAst = true, useEnvironment = true)
- private static SkylarkFunction labelList = new SkylarkFunction("label_list") {
- @Override
- public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
- throws EvalException {
- return createAttribute(kwargs, Type.LABEL_LIST, ast, env);
+ private static BuiltinFunction labelList = new BuiltinFunction("label_list") {
+ public Attribute.Builder<?> invoke(
+ Object defaultList,
+ Object allowFiles,
+ Object allowRules,
+ SkylarkList providers,
+ SkylarkList flags,
+ Boolean mandatory,
+ Boolean nonEmpty,
+ Object cfg,
+ FuncallExpression ast, Environment env) throws EvalException {
+ return createAttribute(
+ EvalUtils.optionMap("default", defaultList,
+ "allow_files", allowFiles, "allow_rules", allowRules, "providers", providers,
+ "flags", flags, "mandatory", mandatory, "non_empty", nonEmpty, "cfg", cfg),
+ Type.LABEL_LIST, ast, env);
}
};
@@ -310,11 +349,14 @@ public final class SkylarkAttr {
@Param(name = "cfg", type = ConfigurationTransition.class, noneable = true,
defaultValue = "None", doc = CONFIGURATION_DOC)},
useAst = true, useEnvironment = true)
- private static SkylarkFunction bool = new SkylarkFunction("bool") {
- @Override
- public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
- throws EvalException {
- return createAttribute(kwargs, Type.BOOLEAN, ast, env);
+ private static BuiltinFunction bool = new BuiltinFunction("bool") {
+ public Attribute.Builder<?> invoke(Boolean defaultBool,
+ SkylarkList flags, Boolean mandatory, Object cfg,
+ FuncallExpression ast, Environment env) throws EvalException {
+ return createAttribute(
+ EvalUtils.optionMap(
+ "default", defaultBool, "flags", flags, "mandatory", mandatory, "cfg", cfg),
+ Type.BOOLEAN, ast, env);
}
};
@@ -334,11 +376,14 @@ public final class SkylarkAttr {
@Param(name = "cfg", type = ConfigurationTransition.class, noneable = true,
defaultValue = "None", doc = CONFIGURATION_DOC)},
useAst = true, useEnvironment = true)
- private static SkylarkFunction output = new SkylarkFunction("output") {
- @Override
- public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
- throws EvalException {
- return createAttribute(kwargs, Type.OUTPUT, ast, env);
+ private static BuiltinFunction output = new BuiltinFunction("output") {
+ public Attribute.Builder<?> invoke(Object defaultO,
+ SkylarkList flags, Boolean mandatory, Object cfg,
+ FuncallExpression ast, Environment env) throws EvalException {
+ return createAttribute(
+ EvalUtils.optionMap(
+ "default", defaultO, "flags", flags, "mandatory", mandatory, "cfg", cfg),
+ Type.OUTPUT, ast, env);
}
};
@@ -359,11 +404,14 @@ public final class SkylarkAttr {
@Param(name = "cfg", type = ConfigurationTransition.class, noneable = true,
defaultValue = "None", doc = CONFIGURATION_DOC)},
useAst = true, useEnvironment = true)
- private static SkylarkFunction outputList = new SkylarkFunction("output_list") {
- @Override
- public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
- throws EvalException {
- return createAttribute(kwargs, Type.OUTPUT_LIST, ast, env);
+ private static BuiltinFunction outputList = new BuiltinFunction("output_list") {
+ public Attribute.Builder<?> invoke(SkylarkList defaultList,
+ SkylarkList flags, Boolean mandatory, Boolean nonEmpty, Object cfg,
+ FuncallExpression ast, Environment env) throws EvalException {
+ return createAttribute(
+ EvalUtils.optionMap("default", defaultList,
+ "flags", flags, "mandatory", mandatory, "non_empty", nonEmpty, "cfg", cfg),
+ Type.OUTPUT_LIST, ast, env);
}
};
@@ -384,11 +432,14 @@ public final class SkylarkAttr {
@Param(name = "cfg", type = ConfigurationTransition.class, noneable = true,
defaultValue = "None", doc = CONFIGURATION_DOC)},
useAst = true, useEnvironment = true)
- private static SkylarkFunction stringDict = new SkylarkFunction("string_dict") {
- @Override
- public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
- throws EvalException {
- return createAttribute(kwargs, Type.STRING_DICT, ast, env);
+ private static BuiltinFunction stringDict = new BuiltinFunction("string_dict") {
+ public Attribute.Builder<?> invoke(Map<?, ?> defaultO,
+ SkylarkList flags, Boolean mandatory, Boolean nonEmpty, Object cfg,
+ FuncallExpression ast, Environment env) throws EvalException {
+ return createAttribute(
+ EvalUtils.optionMap("default", defaultO,
+ "flags", flags, "mandatory", mandatory, "non_empty", nonEmpty, "cfg", cfg),
+ Type.STRING_DICT, ast, env);
}
};
@@ -408,11 +459,18 @@ public final class SkylarkAttr {
@Param(name = "cfg", type = ConfigurationTransition.class, noneable = true,
defaultValue = "None", doc = CONFIGURATION_DOC)},
useAst = true, useEnvironment = true)
- private static SkylarkFunction license = new SkylarkFunction("license") {
- @Override
- public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
- throws EvalException {
- return createAttribute(kwargs, Type.LICENSE, ast, env);
+ private static BuiltinFunction license = new BuiltinFunction("license") {
+ public Attribute.Builder<?> invoke(Object defaultO,
+ SkylarkList flags, Boolean mandatory, Object cfg,
+ FuncallExpression ast, Environment env) throws EvalException {
+ return createAttribute(
+ EvalUtils.optionMap(
+ "default", defaultO, "flags", flags, "mandatory", mandatory, "cfg", cfg),
+ Type.LICENSE, ast, env);
}
};
+
+ static {
+ SkylarkSignatureProcessor.configureSkylarkFunctions(SkylarkAttr.class);
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkCommandLine.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkCommandLine.java
index 260c7e4a8f..a26248656f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkCommandLine.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkCommandLine.java
@@ -18,16 +18,13 @@ import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
-import com.google.devtools.build.lib.events.Location;
-import com.google.devtools.build.lib.syntax.EvalException;
-import com.google.devtools.build.lib.syntax.SkylarkFunction.SimpleSkylarkFunction;
+import com.google.devtools.build.lib.syntax.BuiltinFunction;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkModule;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
import com.google.devtools.build.lib.syntax.SkylarkSignature;
import com.google.devtools.build.lib.syntax.SkylarkSignature.Param;
-
-import java.util.Map;
+import com.google.devtools.build.lib.syntax.SkylarkSignatureProcessor;
/**
* A Skylark module class to create memory efficient command lines.
@@ -36,23 +33,17 @@ import java.util.Map;
doc = "Module for creating memory efficient command lines.")
public class SkylarkCommandLine {
- @SkylarkSignature(name = "join_paths",
+ @SkylarkSignature(name = "join_paths", objectType = SkylarkCommandLine.class,
+ returnType = String.class,
doc = "Creates a single command line argument joining the paths of a set "
+ "of files on the separator string.",
- objectType = SkylarkCommandLine.class,
- returnType = String.class,
mandatoryPositionals = {
@Param(name = "separator", type = String.class, doc = "the separator string to join on"),
@Param(name = "files", type = SkylarkNestedSet.class, generic1 = Artifact.class,
doc = "the files to concatenate")})
- private static SimpleSkylarkFunction joinPaths =
- new SimpleSkylarkFunction("join_paths") {
- @Override
- public Object call(Map<String, Object> params, Location loc)
- throws EvalException {
- final String separator = (String) params.get("separator");
- final NestedSet<Artifact> artifacts =
- ((SkylarkNestedSet) params.get("files")).getSet(Artifact.class);
+ private static BuiltinFunction joinPaths = new BuiltinFunction("join_paths") {
+ public String invoke(String separator, SkylarkNestedSet files) {
+ NestedSet<Artifact> artifacts = files.getSet(Artifact.class);
// TODO(bazel-team): lazy evaluate
return Artifact.joinExecPaths(separator, artifacts);
}
@@ -70,12 +61,8 @@ public class SkylarkCommandLine {
doc = "The template to use for the transformation, <code>%{path}</code> and "
+ "<code>%{short_path}</code> being substituted with the corresponding fields of each"
+ " file.")})
- private static SimpleSkylarkFunction template = new SimpleSkylarkFunction("template") {
- @Override
- public Object call(Map<String, Object> params, Location loc)
- throws EvalException {
- final String template = (String) params.get("template");
- SkylarkNestedSet items = (SkylarkNestedSet) params.get("items");
+ private static BuiltinFunction template = new BuiltinFunction("template") {
+ public SkylarkList invoke(final SkylarkNestedSet items, final String template) {
return SkylarkList.lazyList(Iterables.transform(items, new Function<Object, String>() {
@Override
public String apply(Object input) {
@@ -87,4 +74,8 @@ public class SkylarkCommandLine {
}), String.class);
}
};
+
+ static {
+ SkylarkSignatureProcessor.configureSkylarkFunctions(SkylarkCommandLine.class);
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkModules.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkModules.java
index 226ceebee3..fdb69a3250 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkModules.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkModules.java
@@ -21,11 +21,10 @@ import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.packages.MethodLibrary;
import com.google.devtools.build.lib.packages.SkylarkNativeModule;
+import com.google.devtools.build.lib.syntax.BaseFunction;
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.EvaluationContext;
-import com.google.devtools.build.lib.syntax.Function;
import com.google.devtools.build.lib.syntax.SkylarkEnvironment;
-import com.google.devtools.build.lib.syntax.SkylarkFunction;
import com.google.devtools.build.lib.syntax.SkylarkModule;
import com.google.devtools.build.lib.syntax.SkylarkSignature;
import com.google.devtools.build.lib.syntax.ValidationEnvironment;
@@ -43,9 +42,11 @@ import java.util.Set;
public class SkylarkModules {
/**
- * The list of built in Skylark modules. Documentation is generated automatically for all these
- * modules. They are also registered with the {@link ValidationEnvironment} and the
- * {@link SkylarkEnvironment}. Note that only {@link SkylarkFunction}s are handled properly.
+ * The list of built in Skylark modules.
+ * Documentation is generated automatically for all these modules.
+ * They are also registered with the {@link ValidationEnvironment}
+ * and the {@link SkylarkEnvironment}.
+ * Note that only functions with a {@link SkylarkSignature} annotations are handled properly.
*/
// TODO(bazel-team): find a more general, more automated way of registering classes and building
// initial environments. And don't give syntax.Environment and packages.MethodLibrary a special
@@ -57,19 +58,20 @@ public class SkylarkModules {
SkylarkRuleClassFunctions.class,
SkylarkRuleImplementationFunctions.class);
- private static final ImmutableMap<Class<?>, ImmutableList<Function>> FUNCTION_MAP;
+ private static final ImmutableMap<Class<?>, ImmutableList<BaseFunction>> FUNCTION_MAP;
private static final ImmutableMap<String, Object> OBJECTS;
static {
try {
- ImmutableMap.Builder<Class<?>, ImmutableList<Function>> functionMap = ImmutableMap.builder();
+ ImmutableMap.Builder<Class<?>, ImmutableList<BaseFunction>> functionMap =
+ ImmutableMap.builder();
ImmutableMap.Builder<String, Object> objects = ImmutableMap.builder();
for (Class<?> moduleClass : MODULES) {
if (moduleClass.isAnnotationPresent(SkylarkModule.class)) {
objects.put(moduleClass.getAnnotation(SkylarkModule.class).name(),
moduleClass.newInstance());
}
- ImmutableList.Builder<Function> functions = ImmutableList.builder();
+ ImmutableList.Builder<BaseFunction> functions = ImmutableList.builder();
collectSkylarkFunctionsAndObjectsFromFields(moduleClass, functions, objects);
functionMap.put(moduleClass, functions.build());
}
@@ -97,8 +99,8 @@ public class SkylarkModules {
private static void setupEnvironment(Environment env) {
MethodLibrary.setupMethodEnvironment(env);
- for (Map.Entry<Class<?>, ImmutableList<Function>> entry : FUNCTION_MAP.entrySet()) {
- for (Function function : entry.getValue()) {
+ for (Map.Entry<Class<?>, ImmutableList<BaseFunction>> entry : FUNCTION_MAP.entrySet()) {
+ for (BaseFunction function : entry.getValue()) {
if (function.getObjectType() != null) {
env.registerFunction(function.getObjectType(), function.getName(), function);
} else {
@@ -143,11 +145,11 @@ public class SkylarkModules {
}
/**
- * Collects the Functions from the fields of the class of the object parameter
+ * Collects the BaseFunctions from the fields of the class of the object parameter
* and adds them into the builder.
*/
private static void collectSkylarkFunctionsAndObjectsFromFields(Class<?> type,
- ImmutableList.Builder<Function> functions, ImmutableMap.Builder<String, Object> objects) {
+ ImmutableList.Builder<BaseFunction> functions, ImmutableMap.Builder<String, Object> objects) {
try {
for (Field field : type.getDeclaredFields()) {
if (field.isAnnotationPresent(SkylarkSignature.class)) {
@@ -156,12 +158,8 @@ public class SkylarkModules {
field.setAccessible(true);
SkylarkSignature annotation = field.getAnnotation(SkylarkSignature.class);
Object value = field.get(null);
- if (SkylarkFunction.class.isAssignableFrom(field.getType())) {
- SkylarkFunction function = (SkylarkFunction) value;
- if (!function.isConfigured()) {
- function.configure(annotation);
- }
- functions.add(function);
+ if (BaseFunction.class.isAssignableFrom(field.getType())) {
+ functions.add((BaseFunction) value);
} else {
objects.put(annotation.name(), value);
}
@@ -174,14 +172,14 @@ public class SkylarkModules {
}
/**
- * Collects the Functions from the fields of the class of the object parameter
+ * Collects the BaseFunctions from the fields of the class of the object parameter
* and adds their class and their corresponding return value to the builder.
*/
private static void collectSkylarkTypesFromFields(Class<?> classObject, Set<String> builtIn) {
for (Field field : classObject.getDeclaredFields()) {
if (field.isAnnotationPresent(SkylarkSignature.class)) {
SkylarkSignature annotation = field.getAnnotation(SkylarkSignature.class);
- if (SkylarkFunction.class.isAssignableFrom(field.getType())) {
+ if (BaseFunction.class.isAssignableFrom(field.getType())) {
// Ignore non-global values.
if (annotation.objectType().equals(Object.class)) {
builtIn.add(annotation.name());
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java
index 3cb4e28f96..14bdcd7bbc 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java
@@ -54,8 +54,8 @@ import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.packages.TestSize;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.packages.Type.ConversionException;
-import com.google.devtools.build.lib.syntax.AbstractFunction;
import com.google.devtools.build.lib.syntax.BaseFunction;
+import com.google.devtools.build.lib.syntax.BuiltinFunction;
import com.google.devtools.build.lib.syntax.ClassObject;
import com.google.devtools.build.lib.syntax.ClassObject.SkylarkClassObject;
import com.google.devtools.build.lib.syntax.Environment;
@@ -64,17 +64,15 @@ import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.Function;
+import com.google.devtools.build.lib.syntax.FunctionSignature;
import com.google.devtools.build.lib.syntax.Label;
import com.google.devtools.build.lib.syntax.SkylarkCallbackFunction;
import com.google.devtools.build.lib.syntax.SkylarkEnvironment;
-import com.google.devtools.build.lib.syntax.SkylarkFunction;
-import com.google.devtools.build.lib.syntax.SkylarkFunction.SimpleSkylarkFunction;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkSignature;
import com.google.devtools.build.lib.syntax.SkylarkSignature.Param;
-import com.google.devtools.build.lib.syntax.UserDefinedFunction;
+import com.google.devtools.build.lib.syntax.SkylarkSignatureProcessor;
-import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@@ -182,7 +180,7 @@ public class SkylarkRuleClassFunctions {
"Creates a new rule. Store it in a global value, so that it can be loaded and called "
+ "from BUILD files.",
onlyLoadingPhase = true,
- returnType = BaseFunction.class,
+ returnType = Function.class,
mandatoryPositionals = {
@Param(name = "implementation", type = Function.class,
doc = "the function implementing this rule, has to have exactly one parameter: "
@@ -214,85 +212,85 @@ public class SkylarkRuleClassFunctions {
doc = "If true, the files will be generated in the genfiles directory instead of the "
+ "bin directory. This is used for compatibility with existing rules.")},
useAst = true, useEnvironment = true)
- private static final SkylarkFunction rule = new SkylarkFunction("rule") {
-
- @Override
- @SuppressWarnings({"rawtypes", "unchecked"}) // castMap produces
- // an Attribute.Builder instead of a Attribute.Builder<?> but it's OK.
- public Object call(Map<String, Object> arguments, FuncallExpression ast,
- Environment funcallEnv) throws EvalException, ConversionException {
- final Location loc = ast.getLocation();
-
- RuleClassType type = RuleClassType.NORMAL;
- if (arguments.containsKey("test") && EvalUtils.toBoolean(arguments.get("test"))) {
- type = RuleClassType.TEST;
- }
-
- // We'll set the name later, pass the empty string for now.
- final RuleClass.Builder builder = type == RuleClassType.TEST
- ? new RuleClass.Builder("", type, true, testBaseRule)
- : new RuleClass.Builder("", type, true, baseRule);
-
- for (Map.Entry<String, Attribute.Builder> attr : castMap(arguments.get("attrs"),
- String.class, Attribute.Builder.class, "attrs").entrySet()) {
- Attribute.Builder<?> attrBuilder = attr.getValue();
- String attrName = attributeToNative(attr.getKey(), loc,
+ private static final BuiltinFunction rule = new BuiltinFunction("rule") {
+ @SuppressWarnings({"rawtypes", "unchecked"}) // castMap produces
+ // an Attribute.Builder instead of a Attribute.Builder<?> but it's OK.
+ public Function invoke(Function implementation, Boolean test,
+ Object attrs, Object implicitOutputs, Boolean executable, Boolean outputToGenfiles,
+ FuncallExpression ast, Environment funcallEnv)
+ throws EvalException, ConversionException {
+
+ RuleClassType type = test ? RuleClassType.TEST : RuleClassType.NORMAL;
+
+ // We'll set the name later, pass the empty string for now.
+ RuleClass.Builder builder = test
+ ? new RuleClass.Builder("", type, true, testBaseRule)
+ : new RuleClass.Builder("", type, true, baseRule);
+
+ if (attrs != Environment.NONE) {
+ for (Map.Entry<String, Attribute.Builder> attr : castMap(
+ attrs, String.class, Attribute.Builder.class, "attrs").entrySet()) {
+ Attribute.Builder<?> attrBuilder = (Attribute.Builder<?>) attr.getValue();
+ String attrName = attributeToNative(attr.getKey(), ast.getLocation(),
attrBuilder.hasLateBoundValue());
builder.addOrOverrideAttribute(attrBuilder.build(attrName));
}
- if (arguments.containsKey("executable") && (Boolean) arguments.get("executable")) {
- builder.addOrOverrideAttribute(
- attr("$is_executable", BOOLEAN).value(true)
- .nonconfigurable("Called from RunCommand.isExecutable, which takes a Target")
- .build());
- builder.setOutputsDefaultExecutable();
- }
+ }
+ if (executable) {
+ builder.addOrOverrideAttribute(
+ attr("$is_executable", BOOLEAN).value(true)
+ .nonconfigurable("Called from RunCommand.isExecutable, which takes a Target")
+ .build());
+ builder.setOutputsDefaultExecutable();
+ }
- if (arguments.containsKey("outputs")) {
- final Object implicitOutputs = arguments.get("outputs");
- if (implicitOutputs instanceof UserDefinedFunction) {
- UserDefinedFunction func = (UserDefinedFunction) implicitOutputs;
- final SkylarkCallbackFunction callback =
- new SkylarkCallbackFunction(func, ast, (SkylarkEnvironment) funcallEnv);
- builder.setImplicitOutputsFunction(
- new SkylarkImplicitOutputsFunctionWithCallback(callback, loc));
- } else {
- builder.setImplicitOutputsFunction(new SkylarkImplicitOutputsFunctionWithMap(
- ImmutableMap.copyOf(castMap(arguments.get("outputs"), String.class, String.class,
- "implicit outputs of the rule class"))));
+ if (!(funcallEnv instanceof SkylarkEnvironment)) {
+ System.out.println("rule called from non-Skylark environment!");
+ // throw new EvaluationException("rule not accessible at the toplevel");
+ }
+
+ if (implicitOutputs != Environment.NONE) {
+ if (implicitOutputs instanceof Function) {
+ Function func = (Function) implicitOutputs;
+ final SkylarkCallbackFunction callback =
+ new SkylarkCallbackFunction(func, ast, (SkylarkEnvironment) funcallEnv);
+ builder.setImplicitOutputsFunction(
+ new SkylarkImplicitOutputsFunctionWithCallback(callback, ast.getLocation()));
+ } else {
+ builder.setImplicitOutputsFunction(new SkylarkImplicitOutputsFunctionWithMap(
+ ImmutableMap.copyOf(castMap(implicitOutputs, String.class, String.class,
+ "implicit outputs of the rule class"))));
}
- }
+ }
- if (arguments.containsKey("output_to_genfiles")
- && (Boolean) arguments.get("output_to_genfiles")) {
- builder.setOutputToGenfiles();
- }
+ if (outputToGenfiles) {
+ builder.setOutputToGenfiles();
+ }
- builder.setConfiguredTargetFunction(
- (UserDefinedFunction) arguments.get("implementation"));
- builder.setRuleDefinitionEnvironment((SkylarkEnvironment) funcallEnv);
- return new RuleFunction(builder, type);
+ builder.setConfiguredTargetFunction(implementation);
+ builder.setRuleDefinitionEnvironment((SkylarkEnvironment) funcallEnv);
+ return new RuleFunction(builder, type);
}
};
// This class is needed for testing
- static final class RuleFunction extends AbstractFunction {
+ static final class RuleFunction extends BaseFunction {
// Note that this means that we can reuse the same builder.
// This is fine since we don't modify the builder from here.
private final RuleClass.Builder builder;
private final RuleClassType type;
public RuleFunction(Builder builder, RuleClassType type) {
- super("rule");
+ super("rule", FunctionSignature.KWARGS);
this.builder = builder;
this.type = type;
}
+ @Override
@SuppressWarnings("unchecked") // the magic hidden $pkg_context variable is guaranteed
// to be a PackageContext
- @Override
- public Object call(List<Object> args, Map<String, Object> kwargs, FuncallExpression ast,
- Environment env) throws EvalException, InterruptedException {
+ public Object call(Object[] args, FuncallExpression ast, Environment env)
+ throws EvalException, InterruptedException, ConversionException {
try {
String ruleClassName = ast.getFunction().getName();
if (ruleClassName.startsWith("_")) {
@@ -305,7 +303,8 @@ public class SkylarkRuleClassFunctions {
}
RuleClass ruleClass = builder.build(ruleClassName);
PackageContext pkgContext = (PackageContext) env.lookup(PackageFactory.PKG_CONTEXT);
- return RuleFactory.createAndAddRule(pkgContext, ruleClass, kwargs, ast);
+ return RuleFactory.createAndAddRule(
+ pkgContext, ruleClass, (Map<String, Object>) args[0], ast);
} catch (InvalidRuleException | NameConflictException | NoSuchVariableException e) {
throw new EvalException(ast.getLocation(), e.getMessage());
}
@@ -324,33 +323,29 @@ public class SkylarkRuleClassFunctions {
mandatoryPositionals = {@Param(name = "label_string", type = String.class,
doc = "the label string")},
useLocation = true)
- private static final SkylarkFunction label = new SimpleSkylarkFunction("Label") {
- @Override
- public Object call(Map<String, Object> arguments, Location loc) throws EvalException,
- ConversionException {
- String labelString = (String) arguments.get("label_string");
+ private static final BuiltinFunction label = new BuiltinFunction("Label") {
+ public Label invoke(String labelString,
+ Location loc) throws EvalException, ConversionException {
try {
return labelCache.get(labelString);
} catch (ExecutionException e) {
throw new EvalException(loc, "Illegal absolute label syntax: " + labelString);
}
- }
- };
+ }
+ };
@SkylarkSignature(name = "FileType",
doc = "Creates a file filter from a list of strings. For example, to match files ending "
+ "with .cc or .cpp, use: <pre class=language-python>FileType([\".cc\", \".cpp\"])</pre>",
returnType = SkylarkFileType.class,
mandatoryPositionals = {
- @Param(name = "types", type = SkylarkList.class, generic1 = String.class,
+ @Param(name = "types", type = SkylarkList.class, generic1 = String.class, defaultValue = "[]",
doc = "a list of the accepted file extensions")})
- private static final SkylarkFunction fileType = new SimpleSkylarkFunction("FileType") {
- @Override
- public Object call(Map<String, Object> arguments, Location loc) throws EvalException,
- ConversionException {
- return SkylarkFileType.of(castList(arguments.get("types"), String.class));
- }
- };
+ private static final BuiltinFunction fileType = new BuiltinFunction("FileType") {
+ public SkylarkFileType invoke(SkylarkList types) throws ConversionException {
+ return SkylarkFileType.of(castList(types, String.class));
+ }
+ };
@SkylarkSignature(name = "to_proto",
doc = "Creates a text message from the struct parameter. This method only works if all "
@@ -373,68 +368,69 @@ public class SkylarkRuleClassFunctions {
@Param(name = "self", type = SkylarkClassObject.class,
doc = "this struct")},
useLocation = true)
- private static final SkylarkFunction toProto = new SimpleSkylarkFunction("to_proto") {
- @Override
- public Object call(Map<String, Object> arguments, Location loc) throws EvalException,
- ConversionException {
- ClassObject self = (ClassObject) arguments.get("self");
- StringBuilder sb = new StringBuilder();
- printTextMessage(self, sb, 0, loc);
- return sb.toString();
- }
-
- private void printTextMessage(ClassObject object, StringBuilder sb,
- int indent, Location loc) throws EvalException {
- for (String key : object.getKeys()) {
- printTextMessage(key, object.getValue(key), sb, indent, loc);
+ private static final BuiltinFunction toProto = new BuiltinFunction("to_proto") {
+ public String invoke(SkylarkClassObject self, Location loc) throws EvalException {
+ StringBuilder sb = new StringBuilder();
+ printTextMessage(self, sb, 0, loc);
+ return sb.toString();
}
- }
- private void printSimpleTextMessage(String key, Object value, StringBuilder sb,
- int indent, Location loc, String container) throws EvalException {
- if (value instanceof ClassObject) {
- print(sb, key + " {", indent);
- printTextMessage((ClassObject) value, sb, indent + 1, loc);
- print(sb, "}", indent);
- } else if (value instanceof String) {
- print(sb, key + ": \"" + escape((String) value) + "\"", indent);
- } else if (value instanceof Integer) {
- print(sb, key + ": " + value, indent);
- } else if (value instanceof Boolean) {
- // We're relying on the fact that Java converts Booleans to Strings in the same way
- // as the protocol buffers do.
- print(sb, key + ": " + value, indent);
- } else {
- throw new EvalException(loc,
- "Invalid text format, expected a struct, a string, a bool, or an int but got a "
- + EvalUtils.getDataTypeName(value) + " for " + container + " '" + key + "'");
+ private void printTextMessage(ClassObject object, StringBuilder sb,
+ int indent, Location loc) throws EvalException {
+ for (String key : object.getKeys()) {
+ printTextMessage(key, object.getValue(key), sb, indent, loc);
+ }
}
- }
- private void printTextMessage(String key, Object value, StringBuilder sb,
- int indent, Location loc) throws EvalException {
- if (value instanceof SkylarkList) {
- for (Object item : ((SkylarkList) value)) {
- // TODO(bazel-team): There should be some constraint on the fields of the structs
- // in the same list but we ignore that for now.
- printSimpleTextMessage(key, item, sb, indent, loc, "list element in struct field");
+ private void printSimpleTextMessage(String key, Object value, StringBuilder sb,
+ int indent, Location loc, String container) throws EvalException {
+ if (value instanceof ClassObject) {
+ print(sb, key + " {", indent);
+ printTextMessage((ClassObject) value, sb, indent + 1, loc);
+ print(sb, "}", indent);
+ } else if (value instanceof String) {
+ print(sb, key + ": \"" + escape((String) value) + "\"", indent);
+ } else if (value instanceof Integer) {
+ print(sb, key + ": " + value, indent);
+ } else if (value instanceof Boolean) {
+ // We're relying on the fact that Java converts Booleans to Strings in the same way
+ // as the protocol buffers do.
+ print(sb, key + ": " + value, indent);
+ } else {
+ throw new EvalException(loc,
+ "Invalid text format, expected a struct, a string, a bool, or an int but got a "
+ + EvalUtils.getDataTypeName(value) + " for " + container + " '" + key + "'");
}
- } else {
- printSimpleTextMessage(key, value, sb, indent, loc, "struct field");
}
- }
- private String escape(String string) {
- // TODO(bazel-team): use guava's SourceCodeEscapers when it's released.
- return string.replace("\"", "\\\"").replace("\n", "\\n");
- }
+ private void printTextMessage(String key, Object value, StringBuilder sb,
+ int indent, Location loc) throws EvalException {
+ if (value instanceof SkylarkList) {
+ for (Object item : ((SkylarkList) value)) {
+ // TODO(bazel-team): There should be some constraint on the fields of the structs
+ // in the same list but we ignore that for now.
+ printSimpleTextMessage(key, item, sb, indent, loc, "list element in struct field");
+ }
+ } else {
+ printSimpleTextMessage(key, value, sb, indent, loc, "struct field");
+ }
+ }
- private void print(StringBuilder sb, String text, int indent) {
- for (int i = 0; i < indent; i++) {
- sb.append(" ");
+ private String escape(String string) {
+ // TODO(bazel-team): use guava's SourceCodeEscapers when it's released.
+ return string.replace("\"", "\\\"").replace("\n", "\\n");
}
+
+ private void print(StringBuilder sb, String text, int indent) {
+ for (int i = 0; i < indent; i++) {
+ sb.append(" ");
+ }
sb.append(text);
sb.append("\n");
- }
- };
+ }
+ };
+
+ static {
+ SkylarkSignatureProcessor.configureSkylarkFunctions(SkylarkRuleClassFunctions.class);
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleImplementationFunctions.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleImplementationFunctions.java
index 0019fe8683..03e2bce974 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleImplementationFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleImplementationFunctions.java
@@ -32,18 +32,19 @@ import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction;
import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Substitution;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.packages.Type.ConversionException;
+import com.google.devtools.build.lib.syntax.BuiltinFunction;
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.Label;
-import com.google.devtools.build.lib.syntax.SkylarkFunction;
-import com.google.devtools.build.lib.syntax.SkylarkFunction.SimpleSkylarkFunction;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
import com.google.devtools.build.lib.syntax.SkylarkSignature;
import com.google.devtools.build.lib.syntax.SkylarkSignature.Param;
+import com.google.devtools.build.lib.syntax.SkylarkSignatureProcessor;
import com.google.devtools.build.lib.vfs.PathFragment;
+import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@@ -106,75 +107,79 @@ public class SkylarkRuleImplementationFunctions {
doc = "sets the map of input manifests files; "
+ "they are typicially generated by the command_helper")},
useLocation = true)
- private static final SkylarkFunction createSpawnAction =
- new SimpleSkylarkFunction("action") {
-
- @Override
- public Object call(Map<String, Object> params, Location loc) throws EvalException,
- ConversionException {
- SkylarkRuleContext ctx = (SkylarkRuleContext) params.get("self");
+ private static final BuiltinFunction createSpawnAction = new BuiltinFunction("action") {
+ public Environment.NoneType invoke(
+ SkylarkRuleContext ctx,
+ SkylarkList outputs,
+ SkylarkList inputs,
+ Object executableO,
+ SkylarkList arguments,
+ Object mnemonicO,
+ Object commandO,
+ Object progressMessage,
+ Boolean useDefaultShellEnv,
+ Object envO,
+ Object executionRequirementsO,
+ Object inputManifestsO,
+ Location loc) throws EvalException, ConversionException {
SpawnAction.Builder builder = new SpawnAction.Builder();
// TODO(bazel-team): builder still makes unnecessary copies of inputs, outputs and args.
- builder.addInputs(castList(params.get("inputs"), Artifact.class));
- builder.addOutputs(castList(params.get("outputs"), Artifact.class));
- builder.addArguments(castList(params.get("arguments"), String.class));
- if (params.containsKey("executable")) {
- Object exe = params.get("executable");
- if (exe instanceof Artifact) {
- Artifact executable = (Artifact) exe;
+ builder.addInputs(castList(inputs, Artifact.class));
+ builder.addOutputs(castList(outputs, Artifact.class));
+ builder.addArguments(castList(arguments, String.class));
+ if (executableO != Environment.NONE) {
+ if (executableO instanceof Artifact) {
+ Artifact executable = (Artifact) executableO;
builder.addInput(executable);
FilesToRunProvider provider = ctx.getExecutableRunfiles(executable);
if (provider == null) {
- builder.setExecutable((Artifact) exe);
+ builder.setExecutable(executable);
} else {
builder.setExecutable(provider);
}
- } else if (exe instanceof PathFragment) {
- builder.setExecutable((PathFragment) exe);
+ } else if (executableO instanceof PathFragment) {
+ builder.setExecutable((PathFragment) executableO);
} else {
throw new EvalException(loc, "expected file or PathFragment for "
- + "executable but got " + EvalUtils.getDataTypeName(exe) + " instead");
+ + "executable but got " + EvalUtils.getDataTypeName(executableO) + " instead");
}
}
- if (params.containsKey("command") == params.containsKey("executable")) {
+ if ((commandO == Environment.NONE) == (executableO == Environment.NONE)) {
throw new EvalException(loc, "You must specify either 'command' or 'executable' argument");
}
- if (params.containsKey("command")) {
- Object command = params.get("command");
- if (command instanceof String) {
- builder.setShellCommand((String) command);
- } else if (command instanceof SkylarkList) {
- SkylarkList commandList = (SkylarkList) command;
+ if (commandO != Environment.NONE) {
+ if (commandO instanceof String) {
+ builder.setShellCommand((String) commandO);
+ } else if (commandO instanceof SkylarkList) {
+ SkylarkList commandList = (SkylarkList) commandO;
if (commandList.size() < 3) {
throw new EvalException(loc, "'command' list has to be of size at least 3");
}
builder.setShellCommand(castList(commandList, String.class, "command"));
} else {
throw new EvalException(loc, "expected string or list of strings for "
- + "command instead of " + EvalUtils.getDataTypeName(command));
+ + "command instead of " + EvalUtils.getDataTypeName(commandO));
}
}
- if (params.containsKey("mnemonic")) {
- builder.setMnemonic((String) params.get("mnemonic"));
+ if (mnemonicO != Environment.NONE) {
+ builder.setMnemonic((String) mnemonicO);
}
- if (params.containsKey("env")) {
+ if (envO != Environment.NONE) {
builder.setEnvironment(ImmutableMap.copyOf(
- castMap(params.get("env"), String.class, String.class, "env")));
+ castMap(envO, String.class, String.class, "env")));
}
- if (params.containsKey("progress_message")) {
- builder.setProgressMessage((String) params.get("progress_message"));
+ if (progressMessage != Environment.NONE) {
+ builder.setProgressMessage((String) progressMessage);
}
- if (params.containsKey("use_default_shell_env")
- && EvalUtils.toBoolean(params.get("use_default_shell_env"))) {
+ if (EvalUtils.toBoolean(useDefaultShellEnv)) {
builder.useDefaultShellEnvironment();
}
- if (params.containsKey("execution_requirements")) {
+ if (executionRequirementsO != Environment.NONE) {
builder.setExecutionInfo(ImmutableMap.copyOf(castMap(
- params.get("execution_requirements"),
- String.class, String.class, "execution_requirements")));
+ executionRequirementsO, String.class, String.class, "execution_requirements")));
}
- if (params.containsKey("input_manifests")) {
- for (Map.Entry<PathFragment, Artifact> entry : castMap(params.get("input_manifests"),
+ if (inputManifestsO != Environment.NONE) {
+ for (Map.Entry<PathFragment, Artifact> entry : castMap(inputManifestsO,
PathFragment.class, Artifact.class, "input manifest file map").entrySet()) {
builder.addInputManifest(entry.getValue(), entry.getKey());
}
@@ -195,25 +200,19 @@ public class SkylarkRuleImplementationFunctions {
@Param(name = "output", type = Artifact.class, doc = "the output file"),
@Param(name = "content", type = String.class, doc = "the contents of the file")},
optionalPositionals = {
- @Param(name = "executable", type = Boolean.class,
+ @Param(name = "executable", type = Boolean.class, defaultValue = "False",
doc = "whether the output file should be executable (default is False)")})
- private static final SkylarkFunction createFileWriteAction =
- new SimpleSkylarkFunction("file_action") {
-
- @Override
- public Object call(Map<String, Object> params, Location loc) throws EvalException,
- ConversionException {
- SkylarkRuleContext ctx = (SkylarkRuleContext) params.get("self");
- boolean executable = params.containsKey("executable") && (Boolean) params.get("executable");
- FileWriteAction action = new FileWriteAction(
- ctx.getRuleContext().getActionOwner(),
- (Artifact) params.get("output"),
- (String) params.get("content"),
- executable);
- ctx.getRuleContext().registerAction(action);
- return action;
- }
- };
+ private static final BuiltinFunction createFileWriteAction =
+ new BuiltinFunction("file_action") {
+ public FileWriteAction invoke(SkylarkRuleContext ctx,
+ Artifact output, String content, Boolean executable)
+ throws EvalException, ConversionException {
+ FileWriteAction action = new FileWriteAction(
+ ctx.getRuleContext().getActionOwner(), output, content, executable);
+ ctx.getRuleContext().registerAction(action);
+ return action;
+ }
+ };
@SkylarkSignature(name = "template_action",
doc = "Creates a template expansion action.",
@@ -231,30 +230,26 @@ public class SkylarkRuleImplementationFunctions {
optionalNamedOnly = {
@Param(name = "executable", type = Boolean.class,
doc = "whether the output file should be executable (default is False)")})
- private static final SkylarkFunction createTemplateAction =
- new SimpleSkylarkFunction("template_action") {
-
- @Override
- public Object call(Map<String, Object> params, Location loc) throws EvalException,
- ConversionException {
- SkylarkRuleContext ctx = (SkylarkRuleContext) params.get("self");
- ImmutableList.Builder<Substitution> substitutions = ImmutableList.builder();
- for (Map.Entry<String, String> substitution : castMap(
- params.get("substitutions"), String.class, String.class, "substitutions").entrySet()) {
- substitutions.add(Substitution.of(substitution.getKey(), substitution.getValue()));
- }
-
- boolean executable = params.containsKey("executable") && (Boolean) params.get("executable");
- TemplateExpansionAction action = new TemplateExpansionAction(
- ctx.getRuleContext().getActionOwner(),
- (Artifact) params.get("template"),
- (Artifact) params.get("output"),
- substitutions.build(),
- executable);
- ctx.getRuleContext().registerAction(action);
- return action;
- }
- };
+ private static final BuiltinFunction createTemplateAction =
+ new BuiltinFunction("template_action", Arrays.<Object>asList(false)) {
+ public TemplateExpansionAction invoke(SkylarkRuleContext ctx,
+ Artifact template, Artifact output, Map<?, ?> substitutionsO, Boolean executable)
+ throws EvalException, ConversionException {
+ ImmutableList.Builder<Substitution> substitutions = ImmutableList.builder();
+ for (Map.Entry<String, String> substitution : castMap(
+ substitutionsO, String.class, String.class, "substitutions").entrySet()) {
+ substitutions.add(Substitution.of(substitution.getKey(), substitution.getValue()));
+ }
+ TemplateExpansionAction action = new TemplateExpansionAction(
+ ctx.getRuleContext().getActionOwner(),
+ template,
+ output,
+ substitutions.build(),
+ executable);
+ ctx.getRuleContext().registerAction(action);
+ return action;
+ }
+ };
/**
* A built in Skylark helper function to access the
@@ -267,11 +262,9 @@ public class SkylarkRuleImplementationFunctions {
doc = "the configured target which provides the provider"),
@Param(name = "type", type = String.class, doc = "the class type of the provider")},
useLocation = true)
- private static final SkylarkFunction provider = new SimpleSkylarkFunction("provider") {
- @Override
- public Object call(Map<String, Object> params, Location loc) throws EvalException {
- TransitiveInfoCollection target = (TransitiveInfoCollection) params.get("target");
- String type = (String) params.get("type");
+ private static final BuiltinFunction provider = new BuiltinFunction("provider") {
+ public Object invoke(TransitiveInfoCollection target, String type,
+ Location loc) throws EvalException {
try {
Class<?> classType = SkylarkRuleContext.classCache.get(type);
Class<? extends TransitiveInfoProvider> convertedClass =
@@ -309,24 +302,22 @@ public class SkylarkRuleImplementationFunctions {
doc = "Whether to collect the default "
+ "runfiles from the dependencies in srcs, data and deps attributes.")},
useLocation = true)
- private static final SkylarkFunction runfiles = new SimpleSkylarkFunction("runfiles") {
- @Override
- public Object call(Map<String, Object> params, Location loc) throws EvalException,
- ConversionException {
- SkylarkRuleContext ctx = (SkylarkRuleContext) params.get("self");
+ private static final BuiltinFunction runfiles = new BuiltinFunction("runfiles") {
+ public Runfiles invoke(SkylarkRuleContext ctx, SkylarkList files, Object transitiveFiles,
+ Boolean collectData, Boolean collectDefault,
+ Location loc) throws EvalException, ConversionException {
Runfiles.Builder builder = new Runfiles.Builder();
- if (params.containsKey("collect_data") && (Boolean) params.get("collect_data")) {
+ if (EvalUtils.toBoolean(collectData)) {
builder.addRunfiles(ctx.getRuleContext(), RunfilesProvider.DATA_RUNFILES);
}
- if (params.containsKey("collect_default") && (Boolean) params.get("collect_default")) {
+ if (EvalUtils.toBoolean(collectDefault)) {
builder.addRunfiles(ctx.getRuleContext(), RunfilesProvider.DEFAULT_RUNFILES);
}
- if (params.containsKey("files")) {
- builder.addArtifacts(castList(params.get("files"), Artifact.class));
+ if (!files.isEmpty()) {
+ builder.addArtifacts(castList(files, Artifact.class));
}
- if (params.containsKey("transitive_files")) {
- builder.addTransitiveArtifacts(((SkylarkNestedSet) params.get("transitive_files"))
- .getSet(Artifact.class));
+ if (transitiveFiles != Environment.NONE) {
+ builder.addTransitiveArtifacts(((SkylarkNestedSet) transitiveFiles).getSet(Artifact.class));
}
return builder.build();
}
@@ -342,20 +333,22 @@ public class SkylarkRuleImplementationFunctions {
@Param(name = "label_dict", type = Map.class, defaultValue = "{}",
doc = "dictionary of resolved labels and the corresponding list of Files "
+ "(a dict of Label : list of Files)")})
- private static final SkylarkFunction createCommandHelper =
- new SimpleSkylarkFunction("command_helper") {
- @SuppressWarnings("unchecked")
- @Override
- protected Object call(Map<String, Object> params, Location loc)
- throws ConversionException, EvalException {
- SkylarkRuleContext ctx = (SkylarkRuleContext) params.get("self");
- return new CommandHelper(ctx.getRuleContext(),
- AnalysisUtils.getProviders(
- castList(params.get("tools"), TransitiveInfoCollection.class),
- FilesToRunProvider.class),
- // TODO(bazel-team): this cast to Map is unchecked and is not safe.
- // The best way to fix this probably is to convert CommandHelper to Skylark.
- ImmutableMap.copyOf((Map<Label, Iterable<Artifact>>) params.get("label_dict")));
- }
- };
+ private static final BuiltinFunction createCommandHelper = new BuiltinFunction("command_helper") {
+ @SuppressWarnings("unchecked")
+ // TODO(bazel-team): this cast to Map is unchecked and is not safe.
+ // The best way to fix this probably is to convert CommandHelper to Skylark.
+ public CommandHelper invoke(
+ SkylarkRuleContext ctx, SkylarkList tools, Map<Label, Iterable<Artifact>> labelDict)
+ throws ConversionException, EvalException {
+ return new CommandHelper(ctx.getRuleContext(),
+ AnalysisUtils.getProviders(
+ castList(tools, TransitiveInfoCollection.class),
+ FilesToRunProvider.class),
+ ImmutableMap.copyOf(labelDict));
+ }
+ };
+
+ static {
+ SkylarkSignatureProcessor.configureSkylarkFunctions(SkylarkRuleImplementationFunctions.class);
+ }
}