Skip to content

Commit

Permalink
Unify Skylark and BUILD lists
Browse files Browse the repository at this point in the history
Use SkylarkList everywhere rather than either List or GlobList.
Keep a GlobList underneath a MutableList, where applicable.

--
MOS_MIGRATED_REVID=105864035
  • Loading branch information
fare authored and philwo committed Oct 20, 2015
1 parent 67f14b8 commit 93ed7f1
Show file tree
Hide file tree
Showing 25 changed files with 345 additions and 467 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@
import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.Runtime.NoneType;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkList.MutableList;
import com.google.devtools.build.lib.syntax.SkylarkList.Tuple;
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.HackHackEitherList;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
Expand Down Expand Up @@ -55,12 +54,12 @@ protected String getTypeAnchor(Class<?> type) {
return "<a class=\"anchor\" href=\"string.html\">string</a>";
} else if (Map.class.isAssignableFrom(type)) {
return "<a class=\"anchor\" href=\"dict.html\">dict</a>";
} else if (Tuple.class.isAssignableFrom(type)) {
} else if (type.equals(Tuple.class)) {
return "<a class=\"anchor\" href=\"list.html\">tuple</a>";
} else if (List.class.isAssignableFrom(type) || SkylarkList.class.isAssignableFrom(type)
|| type == HackHackEitherList.class) {
// Annotated Java methods can return simple java.util.Lists (which get auto-converted).
} else if (type.equals(MutableList.class)) {
return "<a class=\"anchor\" href=\"list.html\">list</a>";
} else if (type.equals(SkylarkList.class)) {
return "<a class=\"anchor\" href=\"list.html\">sequence</a>";
} else if (type.equals(Void.TYPE) || type.equals(NoneType.class)) {
return "<a class=\"anchor\" href=\"" + TOP_LEVEL_ID + ".html#None\">None</a>";
} else if (type.isAnnotationPresent(SkylarkModule.class)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,11 @@
import com.google.devtools.build.lib.syntax.Mutability;
import com.google.devtools.build.lib.syntax.ParserInputSource;
import com.google.devtools.build.lib.syntax.Runtime;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkList.MutableList;
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.SkylarkSignatureProcessor.HackHackEitherList;
import com.google.devtools.build.lib.syntax.Statement;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.syntax.Type.ConversionException;
Expand Down Expand Up @@ -475,13 +476,13 @@ private ImmutableMap<String, PackageArgument<?>> createPackageArguments() {
* @param async if true, start globs in the background but don't block on their completion.
* Only use this for heuristic preloading.
*/
@SkylarkSignature(name = "glob", objectType = Object.class, returnType = GlobList.class,
@SkylarkSignature(name = "glob", objectType = Object.class, returnType = SkylarkList.class,
doc = "Returns a list of files that match glob search pattern",
mandatoryPositionals = {
@Param(name = "include", type = HackHackEitherList.class, generic1 = String.class,
@Param(name = "include", type = SkylarkList.class, generic1 = String.class,
doc = "a list of strings specifying patterns of files to include.")},
optionalPositionals = {
@Param(name = "exclude", type = HackHackEitherList.class, generic1 = String.class,
@Param(name = "exclude", type = SkylarkList.class, generic1 = String.class,
defaultValue = "[]",
doc = "a list of strings specifying patterns of files to exclude."),
// TODO(bazel-team): migrate all existing code to use boolean instead?
Expand All @@ -492,8 +493,8 @@ private ImmutableMap<String, PackageArgument<?>> createPackageArguments() {
new BuiltinFunction.Factory("glob") {
public BuiltinFunction create(final PackageContext originalContext, final boolean async) {
return new BuiltinFunction("glob", this) {
public GlobList<String> invoke(
Object include, Object exclude, Integer excludeDirectories,
public SkylarkList invoke(
SkylarkList include, SkylarkList exclude, Integer excludeDirectories,
FuncallExpression ast, Environment env)
throws EvalException, ConversionException, InterruptedException {
return callGlob(
Expand All @@ -503,7 +504,7 @@ public GlobList<String> invoke(
}
};

static GlobList<String> callGlob(@Nullable PackageContext originalContext,
static SkylarkList callGlob(@Nullable PackageContext originalContext,
boolean async, Object include, Object exclude, boolean excludeDirs,
FuncallExpression ast, Environment env)
throws EvalException, ConversionException, InterruptedException {
Expand All @@ -520,16 +521,18 @@ static GlobList<String> callGlob(@Nullable PackageContext originalContext,
List<String> includes = Type.STRING_LIST.convert(include, "'glob' argument");
List<String> excludes = Type.STRING_LIST.convert(exclude, "'glob' argument");

GlobList<String> globList;
if (async) {
try {
context.globber.runAsync(includes, excludes, excludeDirs);
} catch (GlobCache.BadGlobException e) {
// Ignore: errors will appear during the actual evaluation of the package.
}
return GlobList.captureResults(includes, excludes, ImmutableList.<String>of());
globList = GlobList.captureResults(includes, excludes, ImmutableList.<String>of());
} else {
return handleGlob(includes, excludes, excludeDirs, context, ast);
globList = handleGlob(includes, excludes, excludeDirs, context, ast);
}
return new MutableList(globList, env);
}

/**
Expand Down Expand Up @@ -621,20 +624,21 @@ public Runtime.NoneType invoke(Object labelO, String pathString,
@Param(name = "name", type = String.class,
doc = "The name of the rule."),
// Both parameter below are lists of label designators
@Param(name = "environments", type = HackHackEitherList.class, generic1 = Object.class,
@Param(name = "environments", type = SkylarkList.class, generic1 = Object.class,
doc = "A list of Labels for the environments to be grouped, from the same package."),
@Param(name = "defaults", type = HackHackEitherList.class, generic1 = Object.class,
@Param(name = "defaults", type = SkylarkList.class, generic1 = Object.class,
doc = "A list of Labels.")}, // TODO(bazel-team): document what that is
documented = false, useLocation = true)
private static final BuiltinFunction.Factory newEnvironmentGroupFunction =
new BuiltinFunction.Factory("environment_group") {
public BuiltinFunction create(final PackageContext context) {
return new BuiltinFunction("environment_group", this) {
public Runtime.NoneType invoke(String name, Object environmentsO, Object defaultsO,
public Runtime.NoneType invoke(
String name, SkylarkList environmentsList, SkylarkList defaultsList,
Location loc) throws EvalException, ConversionException {
List<Label> environments = BuildType.LABEL_LIST.convert(environmentsO,
List<Label> environments = BuildType.LABEL_LIST.convert(environmentsList,
"'environment_group argument'", context.pkgBuilder.getBuildFileLabel());
List<Label> defaults = BuildType.LABEL_LIST.convert(defaultsO,
List<Label> defaults = BuildType.LABEL_LIST.convert(defaultsList,
"'environment_group argument'", context.pkgBuilder.getBuildFileLabel());

try {
Expand All @@ -659,24 +663,25 @@ public Runtime.NoneType invoke(String name, Object environmentsO, Object default
@SkylarkSignature(name = "exports_files", returnType = Runtime.NoneType.class,
doc = "Declare a set of files as exported",
mandatoryPositionals = {
@Param(name = "srcs", type = HackHackEitherList.class, generic1 = String.class,
@Param(name = "srcs", type = SkylarkList.class, generic1 = String.class,
doc = "A list of strings, the names of the files to export.")},
optionalPositionals = {
// TODO(blaze-team): make it possible to express a list of label designators,
// i.e. a java List or Skylark list of Label or String.
@Param(name = "visibility", type = HackHackEitherList.class, noneable = true,
@Param(name = "visibility", type = SkylarkList.class, noneable = true,
defaultValue = "None",
doc = "A list of Labels specifying the visibility of the exported files "
+ "(defaults to public)"),
@Param(name = "licenses", type = HackHackEitherList.class, generic1 = String.class,
@Param(name = "licenses", type = SkylarkList.class, generic1 = String.class,
noneable = true, defaultValue = "None",
doc = "A list of strings specifying the licenses used in the exported code.")},
documented = false, useAst = true, useEnvironment = true)
private static final BuiltinFunction.Factory newExportsFilesFunction =
new BuiltinFunction.Factory("exports_files") {
public BuiltinFunction create () {
return new BuiltinFunction("exports_files", this) {
public Runtime.NoneType invoke(Object srcs, Object visibility, Object licenses,
public Runtime.NoneType invoke(
SkylarkList srcs, Object visibility, Object licenses,
FuncallExpression ast, Environment env)
throws EvalException, ConversionException {
return callExportsFiles(srcs, visibility, licenses, ast, env);
Expand Down Expand Up @@ -741,16 +746,16 @@ static Runtime.NoneType callExportsFiles(Object srcs, Object visibilityO, Object
@SkylarkSignature(name = "licenses", returnType = Runtime.NoneType.class,
doc = "Declare the license(s) for the code in the current package.",
mandatoryPositionals = {
@Param(name = "license_strings", type = HackHackEitherList.class, generic1 = String.class,
@Param(name = "license_strings", type = SkylarkList.class, generic1 = String.class,
doc = "A list of strings, the names of the licenses used.")},
documented = false, useLocation = true)
private static final BuiltinFunction.Factory newLicensesFunction =
new BuiltinFunction.Factory("licenses") {
public BuiltinFunction create(final PackageContext context) {
return new BuiltinFunction("licenses", this) {
public Runtime.NoneType invoke(Object licensesO, Location loc) {
public Runtime.NoneType invoke(SkylarkList licensesList, Location loc) {
try {
License license = BuildType.LICENSE.convert(licensesO, "'licenses' operand");
License license = BuildType.LICENSE.convert(licensesList, "'licenses' operand");
context.pkgBuilder.setDefaultLicense(license);
} catch (ConversionException e) {
context.eventHandler.handle(Event.error(loc, e.getMessage()));
Expand Down Expand Up @@ -801,19 +806,19 @@ public Runtime.NoneType invoke(Object object, Location loc) {
@Param(name = "name", type = String.class,
doc = "The name of the rule.")},
optionalNamedOnly = {
@Param(name = "packages", type = HackHackEitherList.class, generic1 = String.class,
@Param(name = "packages", type = SkylarkList.class, generic1 = String.class,
defaultValue = "[]",
doc = "A list of Strings specifying the packages grouped."),
// java list or list of label designators: Label or String
@Param(name = "includes", type = HackHackEitherList.class, generic1 = Object.class,
@Param(name = "includes", type = SkylarkList.class, generic1 = Object.class,
defaultValue = "[]",
doc = "A list of Label specifiers for the files to include.")},
documented = false, useAst = true, useEnvironment = true)
private static final BuiltinFunction.Factory newPackageGroupFunction =
new BuiltinFunction.Factory("package_group") {
public BuiltinFunction create() {
return new BuiltinFunction("package_group", this) {
public Runtime.NoneType invoke(String name, Object packages, Object includes,
public Runtime.NoneType invoke(String name, SkylarkList packages, SkylarkList includes,
FuncallExpression ast, Environment env) throws EvalException, ConversionException {
return callPackageFunction(name, packages, includes, ast, env);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.GlobList;
import com.google.devtools.build.lib.syntax.Runtime;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.util.StringUtil;
import com.google.devtools.build.lib.vfs.PathFragment;
Expand Down Expand Up @@ -1350,13 +1351,22 @@ private static void populateConfigDependenciesAttribute(Rule rule) {

private void checkAttrValNonEmpty(
Rule rule, EventHandler eventHandler, Object attributeValue, Integer attrIndex) {
if (attributeValue instanceof List<?>) {
Attribute attr = getAttribute(attrIndex);
if (attr.isNonEmpty() && ((List<?>) attributeValue).isEmpty()) {
rule.reportError(rule.getLabel() + ": non empty " + "attribute '" + attr.getName()
+ "' in '" + name + "' rule '" + rule.getLabel() + "' has to have at least one value",
eventHandler);
}
List<?> list;

if (attributeValue instanceof SkylarkList) {
list = ((SkylarkList) attributeValue).getList();
} else if (attributeValue instanceof List<?>) {
list = (List<?>) attributeValue;
} else {
// TODO(bazel-team): Test maps, not just lists, as being non-empty.
return;
}

Attribute attr = getAttribute(attrIndex);
if (attr.isNonEmpty() && list.isEmpty()) {
rule.reportError(rule.getLabel() + ": non empty " + "attribute '" + attr.getName()
+ "' in '" + name + "' rule '" + rule.getLabel() + "' has to have at least one value",
eventHandler);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
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.Runtime;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkModule;
Expand All @@ -39,7 +38,7 @@ public class SkylarkNativeModule {

// TODO(bazel-team): shouldn't we return a SkylarkList instead?
@SkylarkSignature(name = "glob", objectType = SkylarkNativeModule.class,
returnType = GlobList.class,
returnType = SkylarkList.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> "
Expand All @@ -57,7 +56,7 @@ public class SkylarkNativeModule {
doc = "A flag whether to exclude directories or not.")},
useAst = true, useEnvironment = true)
private static final BuiltinFunction glob = new BuiltinFunction("glob") {
public GlobList<String> invoke(
public SkylarkList invoke(
SkylarkList include, SkylarkList exclude,
Integer excludeDirectories, FuncallExpression ast, Environment env)
throws EvalException, ConversionException, InterruptedException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@

package com.google.devtools.build.lib.rules;

import static com.google.devtools.build.lib.syntax.SkylarkType.castList;

import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.Attribute;
Expand All @@ -40,6 +38,7 @@
import com.google.devtools.build.lib.syntax.UserDefinedFunction;
import com.google.devtools.build.lib.util.FileTypeSet;

import java.util.List;
import java.util.Map;

/**
Expand Down Expand Up @@ -123,7 +122,8 @@ private static Attribute.Builder<?> createAttribute(
}
}

for (String flag : castList(arguments.get(FLAGS_ARG), String.class)) {
for (String flag : SkylarkList.castSkylarkListOrNoneToList(
arguments.get(FLAGS_ARG), String.class, FLAGS_ARG)) {
builder.setPropertyFlag(flag);
}

Expand Down Expand Up @@ -163,16 +163,19 @@ private static Attribute.Builder<?> createAttribute(
Object ruleClassesObj = arguments.get(ALLOW_RULES_ARG);
if (ruleClassesObj != null && ruleClassesObj != Runtime.NONE) {
builder.allowedRuleClasses(
castList(ruleClassesObj, String.class, "allowed rule classes for attribute definition"));
SkylarkList.castSkylarkListOrNoneToList(
ruleClassesObj, String.class, "allowed rule classes for attribute definition"));
}

Iterable<Object> values = castList(arguments.get(VALUES_ARG), Object.class);
List<Object> values = SkylarkList.castSkylarkListOrNoneToList(
arguments.get(VALUES_ARG), Object.class, VALUES_ARG);
if (!Iterables.isEmpty(values)) {
builder.allowedValues(new AllowedValueSet(values));
}

if (containsNonNoneKey(arguments, PROVIDERS_ARG)) {
builder.mandatoryProviders(castList(arguments.get(PROVIDERS_ARG), String.class));
builder.mandatoryProviders(SkylarkList.castSkylarkListOrNoneToList(
arguments.get(PROVIDERS_ARG), String.class, PROVIDERS_ARG));
}

if (containsNonNoneKey(arguments, CONFIGURATION_ARG)) {
Expand Down
Loading

0 comments on commit 93ed7f1

Please sign in to comment.