aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main
diff options
context:
space:
mode:
authorGravatar Francois-Rene Rideau <tunes@google.com>2015-04-21 19:43:19 +0000
committerGravatar Laurent Le Brun <laurentlb@google.com>2015-04-22 12:42:31 +0000
commit534dca155e9d102a0897efb9a56bb7d5497f582e (patch)
tree19fb0e73e10c5121b29b246cd77d1cd299dffe46 /src/main
parent379f7c0ac1a155283692be1dc543cc2cc3d8938d (diff)
More Skylark function cleanups
-- MOS_MIGRATED_REVID=91713784
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/MethodLibrary.java34
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java51
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/DotExpression.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java7
7 files changed, 55 insertions, 51 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/packages/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/packages/MethodLibrary.java
index 9466c694b1..07988a9374 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/MethodLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/MethodLibrary.java
@@ -173,7 +173,7 @@ public class MethodLibrary {
@Param(name = "old", type = String.class, doc = "The string to be replaced."),
@Param(name = "new", type = String.class, doc = "The string to replace with.")},
optionalPositionals = {
- @Param(name = "maxsplit", type = Integer.class,
+ @Param(name = "maxsplit", type = Integer.class, noneable = true, defaultValue = "None",
doc = "The maximum number of replacements.")},
useLocation = true)
private static Function replace =
@@ -208,9 +208,10 @@ public class MethodLibrary {
mandatoryPositionals = {
@Param(name = "self", type = String.class, doc = "This string.")},
optionalPositionals = {
- @Param(name = "sep", type = String.class,
+ @Param(name = "sep", type = String.class, defaultValue = "' '",
doc = "The string to split on, default is space (\" \")."),
- @Param(name = "maxsplit", type = Integer.class, doc = "The maximum number of splits.")},
+ @Param(name = "maxsplit", type = Integer.class, noneable = true, defaultValue = "None",
+ doc = "The maximum number of splits.")},
useEnvironment = true)
private static Function split = new MixedModeFunction("split",
ImmutableList.of("this", "sep", "maxsplit"), 1, false) {
@@ -890,10 +891,10 @@ public class MethodLibrary {
+ "otherwise value of stop and the actual start is 0"),
},
optionalPositionals = {
- @Param(name = "stop", type = Integer.class, noneable = true,
+ @Param(name = "stop", type = Integer.class, noneable = true, defaultValue = "None",
doc = "optional index of the first item <i>not</i> to be included in the "
+ "resulting list; generation of the list stops before <code>stop</code> is reached."),
- @Param(name = "step", type = Integer.class,
+ @Param(name = "step", type = Integer.class, defaultValue = "1",
doc = "The increment (default is 1). It may be negative.")},
useLocation = true)
private static final Function range =
@@ -999,7 +1000,8 @@ public class MethodLibrary {
@Param(name = "object", doc = "The struct which's field is accessed."),
@Param(name = "name", doc = "The name of the struct field.")},
optionalPositionals = {
- @Param(name = "default", doc = "The default value to return in case the struct "
+ @Param(name = "default", defaultValue = "None",
+ doc = "The default value to return in case the struct "
+ "doesn't have a field of the given name.")},
useLocation = true)
private static final Function getattr = new MixedModeFunction(
@@ -1014,8 +1016,9 @@ public class MethodLibrary {
if (args[2] != null) {
return args[2];
} else {
- throw new EvalException(ast.getLocation(), "Object of type '"
- + EvalUtils.getDataTypeName(obj) + "' has no field '" + name + "'");
+ throw new EvalException(ast.getLocation(),
+ String.format("Object of type '%s' has no field %s",
+ EvalUtils.getDataTypeName(obj), EvalUtils.prettyPrintValue(name)));
}
}
return result;
@@ -1088,7 +1091,7 @@ public class MethodLibrary {
@SkylarkSignature(name = "print", returnType = Environment.NoneType.class,
doc = "Prints <code>msg</code> to the console.",
optionalNamedOnly = {
- @Param(name = "sep", type = String.class,
+ @Param(name = "sep", type = String.class, defaultValue = "' '",
doc = "The separator string between the objects, default is space (\" \").")},
// NB: as compared to Python3, we're missing optional named-only arguments 'end' and 'file'
extraPositionals = {@Param(name = "args", doc = "The objects to print.")},
@@ -1222,18 +1225,7 @@ public class MethodLibrary {
private static final List<Function> skylarkGlobalFunctions = ImmutableList
.<Function>builder()
.addAll(pureGlobalFunctions)
- .add(list)
- .add(struct)
- .add(hasattr)
- .add(getattr)
- .add(set)
- .add(dir)
- .add(enumerate)
- .add(range)
- .add(type)
- .add(fail)
- .add(print)
- .add(zip)
+ .add(list, struct, hasattr, getattr, set, dir, enumerate, range, type, fail, print, zip)
.build();
/**
diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
index aa9b8112d7..ac669e64de 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
@@ -447,8 +447,7 @@ public final class PackageFactory {
*/
/**
- * Returns a function-value implementing "glob" in the specified package
- * context.
+ * Returns a function-value implementing "glob" in the specified package context.
*
* @param async if true, start globs in the background but don't block on their completion.
* Only use this for heuristic preloading.
@@ -465,7 +464,7 @@ public final class PackageFactory {
};
}
- static Object callGlob(@Nullable PackageContext originalContext, boolean async,
+ static GlobList<String> callGlob(@Nullable PackageContext originalContext, boolean async,
FuncallExpression ast, Environment env, Object[] namedArguments)
throws EvalException, ConversionException, InterruptedException {
// Skylark build extensions need to get the PackageContext from the Environment;
diff --git a/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java b/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java
index cbc308e631..a5b438c3f2 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java
@@ -18,6 +18,7 @@ import com.google.devtools.build.lib.packages.Type.ConversionException;
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.FuncallExpression;
+import com.google.devtools.build.lib.syntax.GlobList;
import com.google.devtools.build.lib.syntax.SkylarkFunction;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkModule;
@@ -37,7 +38,7 @@ import java.util.Map;
public class SkylarkNativeModule {
@SkylarkSignature(name = "glob", objectType = SkylarkNativeModule.class,
- returnType = SkylarkList.class,
+ returnType = GlobList.class,
doc = "Glob returns a list of every file in the current package that:<ul>\n"
+ "<li>Matches at least one pattern in <code>include</code>.</li>\n"
+ "<li>Does not match any of the patterns in <code>exclude</code> "
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 408c4841b7..7d39e0dcfa 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
@@ -16,7 +16,6 @@ package com.google.devtools.build.lib.rules;
import static com.google.devtools.build.lib.syntax.SkylarkType.castList;
-import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition;
import com.google.devtools.build.lib.packages.Attribute.SkylarkLateBound;
@@ -24,6 +23,7 @@ import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.packages.Type.ConversionException;
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.FuncallExpression;
import com.google.devtools.build.lib.syntax.Label;
import com.google.devtools.build.lib.syntax.SkylarkCallbackFunction;
@@ -75,15 +75,18 @@ public final class SkylarkAttr {
+ "executable file, or to a rule that outputs an executable file. Access the labels with "
+ "<code>ctx.executable.&lt;attribute_name&gt;</code>.";
+ private static boolean containsNonNoneKey(Map<String, Object> arguments, String key) {
+ return arguments.containsKey(key) && arguments.get(key) != Environment.NONE;
+ }
+
private static Attribute.Builder<?> createAttribute(Type<?> type, Map<String, Object> arguments,
FuncallExpression ast, SkylarkEnvironment env) throws EvalException, ConversionException {
- final Location loc = ast.getLocation();
// We use an empty name now so that we can set it later.
// This trick makes sense only in the context of Skylark (builtin rules should not use it).
Attribute.Builder<?> builder = Attribute.attr("", type);
Object defaultValue = arguments.get("default");
- if (defaultValue != null) {
+ if (!EvalUtils.isNullOrNone(defaultValue)) {
if (defaultValue instanceof UserDefinedFunction) {
// Late bound attribute. Non label type attributes already caused a type check error.
builder.value(new SkylarkLateBound(
@@ -97,23 +100,23 @@ public final class SkylarkAttr {
builder.setPropertyFlag(flag);
}
- if (arguments.containsKey("mandatory") && (Boolean) arguments.get("mandatory")) {
+ if (containsNonNoneKey(arguments, "mandatory") && (Boolean) arguments.get("mandatory")) {
builder.setPropertyFlag("MANDATORY");
}
- if (arguments.containsKey("non_empty") && (Boolean) arguments.get("non_empty")) {
+ if (containsNonNoneKey(arguments, "non_empty") && (Boolean) arguments.get("non_empty")) {
builder.setPropertyFlag("NON_EMPTY");
}
- if (arguments.containsKey("executable") && (Boolean) arguments.get("executable")) {
+ if (containsNonNoneKey(arguments, "executable") && (Boolean) arguments.get("executable")) {
builder.setPropertyFlag("EXECUTABLE");
}
- if (arguments.containsKey("single_file") && (Boolean) arguments.get("single_file")) {
+ if (containsNonNoneKey(arguments, "single_file") && (Boolean) arguments.get("single_file")) {
builder.setPropertyFlag("SINGLE_ARTIFACT");
}
- if (arguments.containsKey("allow_files")) {
+ if (containsNonNoneKey(arguments, "allow_files")) {
Object fileTypesObj = arguments.get("allow_files");
if (fileTypesObj == Boolean.TRUE) {
builder.allowedFileTypes(FileTypeSet.ANY_FILE);
@@ -122,29 +125,30 @@ public final class SkylarkAttr {
} else if (fileTypesObj instanceof SkylarkFileType) {
builder.allowedFileTypes(((SkylarkFileType) fileTypesObj).getFileTypeSet());
} else {
- throw new EvalException(loc, "allow_files should be a boolean or a filetype object.");
+ throw new EvalException(ast.getLocation(),
+ "allow_files should be a boolean or a filetype object.");
}
} else if (type.equals(Type.LABEL) || type.equals(Type.LABEL_LIST)) {
builder.allowedFileTypes(FileTypeSet.NO_FILE);
}
Object ruleClassesObj = arguments.get("allow_rules");
- if (ruleClassesObj != null) {
+ if (ruleClassesObj != null && ruleClassesObj != Environment.NONE) {
builder.allowedRuleClasses(castList(ruleClassesObj, String.class,
"allowed rule classes for attribute definition"));
}
- if (arguments.containsKey("providers")) {
+ if (containsNonNoneKey(arguments, "providers")) {
builder.mandatoryProviders(castList(arguments.get("providers"), String.class));
}
- if (arguments.containsKey("cfg")) {
+ if (containsNonNoneKey(arguments, "cfg")) {
builder.cfg((ConfigurationTransition) arguments.get("cfg"));
}
return builder;
}
- private static Object createAttribute(Map<String, Object> kwargs, Type<?> type,
+ private static Attribute.Builder<?> createAttribute(Map<String, Object> kwargs, Type<?> type,
FuncallExpression ast, Environment env) throws EvalException {
try {
return createAttribute(type, kwargs, ast, (SkylarkEnvironment) env);
@@ -181,7 +185,7 @@ public final class SkylarkAttr {
returnType = Attribute.Builder.class,
optionalNamedOnly = {
@Param(name = "default", type = String.class,
- defaultValue = "\"\"", doc = DEFAULT_DOC + " If not specified, default is \"\"."),
+ defaultValue = "''", doc = DEFAULT_DOC + " If not specified, default is \"\"."),
@Param(name = "flags", type = SkylarkList.class, generic1 = String.class,
defaultValue = "[]", doc = FLAGS_DOC),
@Param(name = "mandatory", type = Boolean.class,
@@ -239,13 +243,18 @@ public final class SkylarkAttr {
objectType = SkylarkAttr.class,
returnType = Attribute.class,
optionalPositionals = {
- @Param(name = "default", type = SkylarkList.class, generic1 = String.class,
- doc = DEFAULT_DOC + " If not specified, default is []."),
- @Param(name = "flags", type = SkylarkList.class, generic1 = String.class, doc = FLAGS_DOC),
- @Param(name = "mandatory", type = Boolean.class, doc = MANDATORY_DOC),
- @Param(name = "non_empty", type = Boolean.class, doc = NON_EMPTY_DOC),
- @Param(name = "cfg", type = ConfigurationTransition.class,
- doc = CONFIGURATION_DOC)})
+ @Param(name = "default", type = SkylarkList.class, generic1 = String.class,
+ defaultValue = "[]",
+ doc = DEFAULT_DOC + " If not specified, default is []."),
+ @Param(name = "flags", type = SkylarkList.class, generic1 = String.class,
+ defaultValue = "[]", doc = FLAGS_DOC),
+ @Param(name = "mandatory", type = Boolean.class, defaultValue = "False",
+ doc = MANDATORY_DOC),
+ @Param(name = "non_empty", type = Boolean.class, defaultValue = "False",
+ doc = NON_EMPTY_DOC),
+ @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)
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java
index 005b528833..a5ddf3d15e 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java
@@ -117,7 +117,7 @@ public abstract class BlazeModule {
* May yield a supplier that provides factories for the Preprocessor to apply. Only one of the
* configured modules may return non-null.
*
- * The factory yielded by the supplier will be checked with
+ * <p>The factory yielded by the supplier will be checked with
* {@link Preprocessor.Factory#isStillValid} at the beginning of each incremental build. This
* allows modules to have preprocessors customizable by flags.
*
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/DotExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/DotExpression.java
index b09371ac10..9cd37e7369 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/DotExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/DotExpression.java
@@ -61,8 +61,8 @@ public final class DotExpression extends Expression {
throw new EvalException(getLocation(), customErrorMessage);
}
}
- throw new EvalException(getLocation(), "Object of type '"
- + EvalUtils.getDataTypeName(objValue) + "' has no field '" + name + "'");
+ throw new EvalException(getLocation(), String.format("Object of type '%s' has no field %s",
+ EvalUtils.getDataTypeName(objValue), EvalUtils.prettyPrintValue(name)));
}
return result;
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java
index 1d9cd818bd..42946eefb1 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java
@@ -190,9 +190,12 @@ public class SkylarkSignatureProcessor {
return new Parameter.Star<>(param.name(), officialType);
} else if (mandatory) {
return new Parameter.Mandatory<>(param.name(), officialType);
- } else {
- return new Parameter.Optional<>(param.name(), officialType, defaultValue);
+ } else if (defaultValue != null && enforcedType != null) {
+ Preconditions.checkArgument(enforcedType.contains(defaultValue),
+ "In function '%s', parameter '%s' has default value %s that isn't of enforced type %s",
+ name, param.name(), EvalUtils.prettyPrintValue(defaultValue), enforcedType);
}
+ return new Parameter.Optional<>(param.name(), officialType, defaultValue);
}
private static Object getDefaultValue(Param param, Iterator<Object> iterator) {