diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules')
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); + } } |