diff options
author | Vladimir Moskva <vladmos@google.com> | 2016-12-23 16:35:37 +0000 |
---|---|---|
committer | Damien Martin-Guillerez <dmarting@google.com> | 2016-12-27 10:03:42 +0000 |
commit | d200dafb29ba901ca8afb88d31b973fed9d5f725 (patch) | |
tree | 50122e4488b7682ab53147893a643a138baaa4e0 /src/main | |
parent | b5fb12f8b45d3b277f5a310549258f9dcbdf3c7c (diff) |
Add `depset` as an alias to `set` in Skylark
Renamed all occurrences of `set` to `depset`, added a `set` object constructor for (temporary) backward compatibility. `type(depset())` still temporarily returns "set", that will be changed in the future.
RELNOTES: The `set` constructor is deprecated in favor of `depset`
--
PiperOrigin-RevId: 142851587
MOS_MIGRATED_REVID=142851587
Diffstat (limited to 'src/main')
4 files changed, 176 insertions, 124 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BazelLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/BazelLibrary.java index 8c9d47659c..9db64d2cbf 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/BazelLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/BazelLibrary.java @@ -48,37 +48,76 @@ public class BazelLibrary { new BuiltinFunction("type") { public String invoke(Object object) { // There is no 'type' type in Skylark, so we return a string with the type name. - return EvalUtils.getDataTypeName(object, false); + String name = EvalUtils.getDataTypeName(object, false); + // TODO(bazel-team): Temporary change to avoid breaking existing code. + if (name.equals("depset")) { + return "set"; + } + return name; } }; @SkylarkSignature( - name = "set", + name = "depset", returnType = SkylarkNestedSet.class, doc = - "Creates a <a href=\"set.html\">set</a> from the <code>items</code>. " - + "The set supports nesting other sets of the same element type in it. " - + "A desired <a href=\"set.html\">iteration order</a> can also be specified.<br>" - + "Examples:<br><pre class=\"language-python\">set([\"a\", \"b\"])\n" - + "set([1, 2, 3], order=\"compile\")</pre>", + "Creates a <a href=\"depset.html\">depset</a> from the <code>items</code>. " + + "The depset supports nesting other depsets of the same element type in it. " + + "A desired <a href=\"depset.html\">iteration order</a> can also be specified.<br>" + + "Examples:<br><pre class=\"language-python\">depset([\"a\", \"b\"])\n" + + "depset([1, 2, 3], order=\"compile\")</pre>", parameters = { @Param( name = "items", type = Object.class, defaultValue = "[]", doc = - "The items to initialize the set with. May contain both standalone items " - + "and other sets." + "The items to initialize the depset with. May contain both standalone items " + + "and other depsets." ), @Param( name = "order", type = String.class, defaultValue = "\"stable\"", doc = - "The ordering strategy for the set if it's nested, " + "The ordering strategy for the depset if it's nested, " + "possible values are: <code>stable</code> (default), <code>compile</code>, " + "<code>link</code> or <code>naive_link</code>. An explanation of the " - + "values can be found <a href=\"set.html\">here</a>." + + "values can be found <a href=\"depset.html\">here</a>." + ) + }, + useLocation = true + ) + private static final BuiltinFunction depset = + new BuiltinFunction("depset") { + public SkylarkNestedSet invoke(Object items, String order, Location loc) + throws EvalException { + try { + return new SkylarkNestedSet(Order.parse(order), items, loc); + } catch (IllegalArgumentException ex) { + throw new EvalException(loc, ex); + } + } + }; + + @SkylarkSignature( + name = "set", + returnType = SkylarkNestedSet.class, + doc = + "A temporary alias for <a href=\"#depset\">depset</a>. " + + "Deprecated in favor of <code>depset</code>.", + parameters = { + @Param( + name = "items", + type = Object.class, + defaultValue = "[]", + doc = "Same as for <a href=\"#depset\">depset</a>." + ), + @Param( + name = "order", + type = String.class, + defaultValue = "\"stable\"", + doc = "Same as for <a href=\"#depset\">depset</a>." ) }, useLocation = true @@ -100,10 +139,10 @@ public class BazelLibrary { objectType = SkylarkNestedSet.class, returnType = SkylarkNestedSet.class, doc = - "Creates a new <a href=\"set.html\">set</a> that contains both " - + "the input set as well as all additional elements.", + "Creates a new <a href=\"depset.html\">depset</a> that contains both " + + "the input depset as well as all additional elements.", parameters = { - @Param(name = "input", type = SkylarkNestedSet.class, doc = "The input set"), + @Param(name = "input", type = SkylarkNestedSet.class, doc = "The input depset"), @Param(name = "new_elements", type = Iterable.class, doc = "The elements to be added") }, useLocation = true @@ -143,7 +182,8 @@ public class BazelLibrary { }; private static Environment.Frame createGlobals() { - List<BaseFunction> bazelGlobalFunctions = ImmutableList.<BaseFunction>of(select, set, type); + List<BaseFunction> bazelGlobalFunctions = + ImmutableList.<BaseFunction>of(select, depset, set, type); try (Mutability mutability = Mutability.create("BUILD")) { Environment env = Environment.builder(mutability).build(); diff --git a/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java b/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java index c95df57c89..370692336b 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java @@ -53,43 +53,45 @@ public final class EvalUtils { /** * Compare two Skylark objects. * - * <p> It may throw an unchecked exception ComparisonException that should be wrapped in - * an EvalException. + * <p>It may throw an unchecked exception ComparisonException that should be wrapped in an + * EvalException. */ - public static final Ordering<Object> SKYLARK_COMPARATOR = new Ordering<Object>() { - private int compareLists(SkylarkList o1, SkylarkList o2) { - for (int i = 0; i < Math.min(o1.size(), o2.size()); i++) { - int cmp = compare(o1.get(i), o2.get(i)); - if (cmp != 0) { - return cmp; + public static final Ordering<Object> SKYLARK_COMPARATOR = + new Ordering<Object>() { + private int compareLists(SkylarkList o1, SkylarkList o2) { + for (int i = 0; i < Math.min(o1.size(), o2.size()); i++) { + int cmp = compare(o1.get(i), o2.get(i)); + if (cmp != 0) { + return cmp; + } + } + return Integer.compare(o1.size(), o2.size()); } - } - return Integer.compare(o1.size(), o2.size()); - } - - @Override - @SuppressWarnings("unchecked") - public int compare(Object o1, Object o2) { - o1 = SkylarkType.convertToSkylark(o1, /*env=*/ null); - o2 = SkylarkType.convertToSkylark(o2, /*env=*/ null); - if (o1 instanceof ClassObject && o2 instanceof ClassObject) { - throw new ComparisonException("Cannot compare structs"); - } - if (o1 instanceof SkylarkNestedSet && o2 instanceof SkylarkNestedSet) { - throw new ComparisonException("Cannot compare sets"); - } - if (o1 instanceof SkylarkList && o2 instanceof SkylarkList - && ((SkylarkList) o1).isTuple() == ((SkylarkList) o2).isTuple()) { - return compareLists((SkylarkList) o1, (SkylarkList) o2); - } - try { - return ((Comparable<Object>) o1).compareTo(o2); - } catch (ClassCastException e) { - return compareByClass(o1, o2); - } - } - }; + @Override + @SuppressWarnings("unchecked") + public int compare(Object o1, Object o2) { + o1 = SkylarkType.convertToSkylark(o1, /*env=*/ null); + o2 = SkylarkType.convertToSkylark(o2, /*env=*/ null); + + if (o1 instanceof ClassObject && o2 instanceof ClassObject) { + throw new ComparisonException("Cannot compare structs"); + } + if (o1 instanceof SkylarkNestedSet && o2 instanceof SkylarkNestedSet) { + throw new ComparisonException("Cannot compare depsets"); + } + if (o1 instanceof SkylarkList + && o2 instanceof SkylarkList + && ((SkylarkList) o1).isTuple() == ((SkylarkList) o2).isTuple()) { + return compareLists((SkylarkList) o1, (SkylarkList) o2); + } + try { + return ((Comparable<Object>) o1).compareTo(o2); + } catch (ClassCastException e) { + return compareByClass(o1, o2); + } + } + }; public static final int compareByClass(Object o1, Object o2) { try { @@ -211,7 +213,7 @@ public final class EvalUtils { if (fullDetails) { if (object instanceof SkylarkNestedSet) { SkylarkNestedSet set = (SkylarkNestedSet) object; - return "set of " + set.getContentType() + "s"; + return "depset of " + set.getContentType() + "s"; } if (object instanceof SelectorList) { SelectorList list = (SelectorList) object; @@ -254,7 +256,7 @@ public final class EvalUtils { return "function"; } else if (c.equals(SelectorValue.class)) { return "select"; - } else if (NestedSet.class.isAssignableFrom(c) || SkylarkNestedSet.class.isAssignableFrom(c)) { + } else if (NestedSet.class.isAssignableFrom(c)) { // TODO(bazel-team): no one should be seeing naked NestedSet at all. return "set"; } else { diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java index 7c20ea4963..b4e2a21301 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java @@ -1106,7 +1106,8 @@ public class MethodLibrary { throw new EvalException( loc, "Argument to reversed() must be a sequence, not a dictionary."); } else if (sequence instanceof NestedSet || sequence instanceof SkylarkNestedSet) { - throw new EvalException(loc, "Argument to reversed() must be a sequence, not a set."); + throw new EvalException( + loc, "Argument to reversed() must be a sequence, not a depset."); } LinkedList<Object> tmpList = new LinkedList<>(); for (Object element : EvalUtils.toIterable(sequence, loc)) { @@ -1524,9 +1525,9 @@ public class MethodLibrary { name = "tuple", returnType = Tuple.class, doc = - "Converts a collection (e.g. set or dictionary) to a tuple." + "Converts a collection (e.g. list, tuple or dictionary) to a tuple." + "<pre class=\"language-python\">tuple([1, 2]) == (1, 2)\n" - + "tuple(set([2, 3, 2])) == (2, 3)\n" + + "tuple((2, 3, 2)) == (2, 3, 2)\n" + "tuple({5: \"a\", 2: \"b\", 4: \"c\"}) == (5, 2, 4)</pre>", parameters = {@Param(name = "x", doc = "The object to convert.")}, useLocation = true @@ -1542,9 +1543,9 @@ public class MethodLibrary { name = "list", returnType = MutableList.class, doc = - "Converts a collection (e.g. set or dictionary) to a list." + "Converts a collection (e.g. list, tuple or dictionary) to a list." + "<pre class=\"language-python\">list([1, 2]) == [1, 2]\n" - + "list(set([2, 3, 2])) == [2, 3]\n" + + "list((2, 3, 2)) == [2, 3, 2]\n" + "list({5: \"a\", 2: \"b\", 4: \"c\"}) == [5, 2, 4]</pre>", parameters = {@Param(name = "x", doc = "The object to convert.")}, useLocation = true, @@ -1560,7 +1561,7 @@ public class MethodLibrary { @SkylarkSignature( name = "len", returnType = Integer.class, - doc = "Returns the length of a string, list, tuple, set, or dictionary.", + doc = "Returns the length of a string, list, tuple, depset, or dictionary.", parameters = {@Param(name = "x", doc = "The object to check length of.")}, useLocation = true ) @@ -1698,8 +1699,9 @@ public class MethodLibrary { returnType = SkylarkDict.class, doc = "Creates a <a href=\"#modules.dict\">dictionary</a> from an optional positional " - + "argument and an optional set of keyword arguments. Values from the keyword argument " - + "will overwrite values from the positional argument if a key appears multiple times.", + + "argument and an optional set of keyword arguments. Values from the keyword " + + "argument will overwrite values from the positional argument if a key appears " + + "multiple times.", parameters = { @Param( name = "args", @@ -1711,21 +1713,23 @@ public class MethodLibrary { ), }, extraKeywords = @Param(name = "kwargs", doc = "Dictionary of additional entries."), - useLocation = true, useEnvironment = true + useLocation = true, + useEnvironment = true ) private static final BuiltinFunction dict = new BuiltinFunction("dict") { - public SkylarkDict invoke(Object args, SkylarkDict<String, Object> kwargs, - Location loc, Environment env) + public SkylarkDict invoke( + Object args, SkylarkDict<String, Object> kwargs, Location loc, Environment env) throws EvalException { - SkylarkDict<Object, Object> argsDict = (args instanceof SkylarkDict) - ? (SkylarkDict<Object, Object>) args : getDictFromArgs(args, loc, env); + SkylarkDict<Object, Object> argsDict = + (args instanceof SkylarkDict) + ? (SkylarkDict<Object, Object>) args + : getDictFromArgs(args, loc, env); return SkylarkDict.plus(argsDict, kwargs, env); } private SkylarkDict<Object, Object> getDictFromArgs( - Object args, Location loc, Environment env) - throws EvalException { + Object args, Location loc, Environment env) throws EvalException { SkylarkDict<Object, Object> result = SkylarkDict.of(env); int pos = 0; for (Object element : Type.OBJECT_LIST.convert(args, "parameter args in dict()")) { @@ -1746,8 +1750,7 @@ public class MethodLibrary { location, String.format( "Sequence #%d has length %d, but exactly two elements are required", - pos, - numElements)); + pos, numElements)); } return tuple; } catch (ConversionException e) { diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java index 28ce63896d..6fc5c8bf13 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java @@ -33,57 +33,62 @@ import javax.annotation.Nullable; /** A generic type safe NestedSet wrapper for Skylark. */ @SkylarkModule( - name = "set", - category = SkylarkModuleCategory.BUILTIN, - doc = - "A language built-in type that supports sets. " - + "Sets can be created using the <a href=\"globals.html#set\">set</a> function, and " - + "they support the <code>|</code> operator to extend the set with more elements or " - + "to nest other sets inside of it. Examples:<br>" - + "<pre class=language-python>s = set([1, 2])\n" - + "s = s | [3] # s == {1, 2, 3}\n" - + "s = s | set([4, 5]) # s == {1, 2, 3, {4, 5}}\n" - + "other = set([\"a\", \"b\", \"c\"], order=\"compile\")</pre>" - + "Note that in these examples <code>{..}</code> is not a valid literal to create sets. " - + "Sets have a fixed generic type, so <code>set([1]) + [\"a\"]</code> or " - + "<code>set([1]) + set([\"a\"])</code> results in an error.<br>" - + "Elements in a set can neither be mutable or be of type <code>list</code>, " - + "<code>struct</code> or <code>dict</code>.<br>" - + "When aggregating data from providers, sets can take significantly less memory than " - + "other types as they support nesting, that is, their subsets are shared in memory.<br>" - + "Every set has an <code>order</code> parameter which determines the iteration order. " - + "There are four possible values:" - + "<ul><li><code>compile</code>: Defines a left-to-right post-ordering where child " - + "elements come after those of nested sets (parent-last). For example, " - + "<code>{1, 2, 3, {4, 5}}</code> leads to <code>4 5 1 2 3</code>. Left-to-right order " - + "is preserved for both the child elements and the references to nested sets.</li>" - + "<li><code>stable</code>: Same behavior as <code>compile</code>.</li>" - + "<li><code>link</code>: Defines a variation of left-to-right pre-ordering, i.e. " - + "<code>{1, 2, 3, {4, 5}}</code> leads to <code>1 2 3 4 5</code>. " - + "This ordering enforces that elements of the set always come before elements of " - + "nested sets (parent-first), which may lead to situations where left-to-right " - + "order cannot be preserved (<a href=\"https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/collect/nestedset/LinkOrderExpander.java#L56\">Example</a>)." - + "</li>" - + "<li><code>naive_link</code>: Defines \"naive\" left-to-right pre-ordering " - + "(parent-first), i.e. <code>{1, 2, 3, {4, 5}}</code> leads to <code>1 2 3 4 5</code>. " - + "Unlike <code>link</code> ordering, it will sacrifice the parent-first property in " - + "order to uphold left-to-right order in cases where both properties cannot be " - + "guaranteed (<a href=\"https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/collect/nestedset/NaiveLinkOrderExpander.java#L26\">Example</a>)." - + "</li></ul>" - + "Except for <code>stable</code>, the above values are incompatible with each other. " - + "Consequently, two sets can only be merged via the <code>|</code> operator or via " - + "<code>union()</code> if either both sets have the same <code>order</code> or one of " - + "the sets has <code>stable</code> order. In the latter case the iteration order will be " - + "determined by the outer set, thus ignoring the <code>order</code> parameter of " - + "nested sets." + name = "depset", + category = SkylarkModuleCategory.BUILTIN, + doc = + "A language built-in type that supports efficiently accumulating data from transitive " + + "dependencies. Note that depsets are not hash sets: they don't support fast membership " + + "tests, but on the contrary they support fast union. Depsets are designed to be used as " + + "a collection of items (such as file names) generated by Bazel targets. " + + "Depsets can be created using the <a href=\"globals.html#depset\">depset</a> function, " + + "and they support the <code>|</code> operator to extend the depset with more elements or " + + "to nest other depsets inside of it. Examples:<br>" + + "<pre class=language-python>s = depset([1, 2])\n" + + "s = s | [3] # s == {1, 2, 3}\n" + + "s = s | depset([4, 5]) # s == {1, 2, 3, {4, 5}}\n" + + "other = depset([\"a\", \"b\", \"c\"], order=\"compile\")</pre>" + + "Note that in these examples <code>{..}</code> is not a valid literal to create depsets. " + + "Sets have a fixed generic type, so <code>set([1]) + [\"a\"]</code> or " + + "<code>set([1]) + depset([\"a\"])</code> results in an error.<br>" + + "Elements in a depset can neither be mutable or be of type <code>list</code>, " + + "<code>struct</code> or <code>dict</code>.<br>" + + "When aggregating data from providers, depsets can take significantly less memory than " + + "other types as they support nesting, that is, their subsets are shared in memory.<br>" + + "Every depset has an <code>order</code> parameter which determines the iteration order. " + + "There are four possible values:" + + "<ul><li><code>compile</code>: Defines a left-to-right post-ordering where child " + + "elements come after those of nested depsets (parent-last). For example, " + + "<code>{1, 2, 3, {4, 5}}</code> leads to <code>4 5 1 2 3</code>. Left-to-right order " + + "is preserved for both the child elements and the references to nested depsets.</li>" + + "<li><code>stable</code>: Same behavior as <code>compile</code>.</li>" + + "<li><code>link</code>: Defines a variation of left-to-right pre-ordering, i.e. " + + "<code>{1, 2, 3, {4, 5}}</code> leads to <code>1 2 3 4 5</code>. " + + "This ordering enforces that elements of the depset always come before elements of " + + "nested depsets (parent-first), which may lead to situations where left-to-right " + + "order cannot be preserved (<a href=\"https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/collect/nestedset/LinkOrderExpander.java#L56\">Example</a>)." + + "</li>" + + "<li><code>naive_link</code>: Defines \"naive\" left-to-right pre-ordering " + + "(parent-first), i.e. <code>{1, 2, 3, {4, 5}}</code> leads to <code>1 2 3 4 5</code>. " + + "Unlike <code>link</code> ordering, it will sacrifice the parent-first property in " + + "order to uphold left-to-right order in cases where both properties cannot be " + + "guaranteed (<a href=\"https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/collect/nestedset/NaiveLinkOrderExpander.java#L26\">Example</a>)." + + "</li></ul>" + + "Except for <code>stable</code>, the above values are incompatible with each other. " + + "Consequently, two depsets can only be merged via the <code>|</code> operator or via " + + "<code>union()</code> if either both depsets have the same <code>order</code> or one of " + + "the depsets has <code>stable</code> order. In the latter case the iteration order will " + + "be determined by the outer depset, thus ignoring the <code>order</code> parameter of " + + "nested depsets." ) @Immutable public final class SkylarkNestedSet implements Iterable<Object>, SkylarkValue, SkylarkQueryable { private final SkylarkType contentType; private final NestedSet<?> set; - @Nullable private final List<Object> items; - @Nullable private final List<NestedSet> transitiveItems; + @Nullable + private final List<Object> items; + @Nullable + private final List<NestedSet> transitiveItems; public SkylarkNestedSet(Order order, Object item, Location loc) throws EvalException { this(order, SkylarkType.TOP, item, loc, null); @@ -96,7 +101,7 @@ public final class SkylarkNestedSet implements Iterable<Object>, SkylarkValue, S // This is safe because of the type checking @SuppressWarnings("unchecked") private SkylarkNestedSet(Order order, SkylarkType contentType, Object item, Location loc, - @Nullable SkylarkNestedSet left) throws EvalException { + @Nullable SkylarkNestedSet left) throws EvalException { ArrayList<Object> items = new ArrayList<>(); ArrayList<NestedSet> transitiveItems = new ArrayList<>(); @@ -125,7 +130,8 @@ public final class SkylarkNestedSet implements Iterable<Object>, SkylarkValue, S } else { throw new EvalException( loc, - String.format("cannot add value of type '%s' to a set", EvalUtils.getDataTypeName(item))); + String.format( + "cannot add value of type '%s' to a depset", EvalUtils.getDataTypeName(item))); } this.contentType = Preconditions.checkNotNull(contentType, "type cannot be null"); @@ -184,21 +190,21 @@ public final class SkylarkNestedSet implements Iterable<Object>, SkylarkValue, S SkylarkType.Union.of(SkylarkType.DICT, SkylarkType.LIST), itemType) != SkylarkType.BOTTOM) { throw new EvalException( - loc, String.format("sets cannot contain items of type '%s'", itemType)); + loc, String.format("depsets cannot contain items of type '%s'", itemType)); } SkylarkType newType = SkylarkType.intersection(builderType, itemType); if (newType == SkylarkType.BOTTOM) { throw new EvalException( loc, - String.format("cannot add an item of type '%s' to a set of '%s'", itemType, builderType)); + String.format( + "cannot add an item of type '%s' to a depset of '%s'", itemType, builderType)); } return newType; } private static void checkImmutable(Object o, Location loc) throws EvalException { if (!EvalUtils.isImmutable(o)) { - throw new EvalException( - loc, "sets cannot contain mutable items"); + throw new EvalException(loc, "depsets cannot contain mutable items"); } } @@ -212,10 +218,11 @@ public final class SkylarkNestedSet implements Iterable<Object>, SkylarkValue, S if (set.isEmpty()) { return (NestedSet<T>) set; } - Preconditions.checkArgument(contentType.canBeCastTo(type), - String.format("Expected a set of '%s' but got a set of '%s'", - EvalUtils.getDataTypeNameFromClass(type), - contentType)); + Preconditions.checkArgument( + contentType.canBeCastTo(type), + String.format( + "Expected a depset of '%s' but got a depset of '%s'", + EvalUtils.getDataTypeNameFromClass(type), contentType)); return (NestedSet<T>) set; } @@ -260,7 +267,7 @@ public final class SkylarkNestedSet implements Iterable<Object>, SkylarkValue, S @Override public void write(Appendable buffer, char quotationMark) { - Printer.append(buffer, "set("); + Printer.append(buffer, "depset("); Printer.printList(buffer, this, "[", ", ", "]", null, quotationMark); Order order = getOrder(); if (order != Order.STABLE_ORDER) { |