aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/syntax
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/syntax')
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java175
1 files changed, 173 insertions, 2 deletions
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 856c262e49..cbf8ce4e17 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
@@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skylarkinterface.Param;
@@ -861,6 +862,176 @@ public class MethodLibrary {
};
@SkylarkSignature(
+ name = "type",
+ returnType = String.class,
+ doc =
+ "Returns the type name of its argument. This is useful for debugging and "
+ + "type-checking. Examples:"
+ + "<pre class=\"language-python\">"
+ + "type(2) == \"int\"\n"
+ + "type([1]) == \"list\"\n"
+ + "type(struct(a = 2)) == \"struct\""
+ + "</pre>"
+ + "This function might change in the future. To write Python-compatible code and "
+ + "be future-proof, use it only to compare return values: "
+ + "<pre class=\"language-python\">"
+ + "if type(x) == type([]): # if x is a list"
+ + "</pre>",
+ parameters = {@Param(name = "x", doc = "The object to check type of.")})
+ private static final BuiltinFunction type =
+ 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);
+ }
+ };
+
+ @SkylarkSignature(
+ name = "depset",
+ returnType = SkylarkNestedSet.class,
+ doc =
+ "Creates a <a href=\"depset.html\">depset</a>. The <code>direct</code> parameter is a list "
+ + "of direct elements of the depset, and <code>transitive</code> parameter is "
+ + "a list of depsets whose elements become indirect elements of the created depset. "
+ + "The order in which elements are returned when the depset is converted to a list "
+ + "is specified by the <code>order</code> parameter. "
+ + "See the <a href=\"../depsets.md\">Depsets overview</a> for more information. "
+ + "<p> All elements (direct and indirect) of a depset must be of the same type. "
+ + "<p> The order of the created depset should be <i>compatible</i> with the order of "
+ + "its <code>transitive</code> depsets. <code>\"default\"</code> order is compatible "
+ + "with any other order, all other orders are only compatible with themselves."
+ + "<p> Note on backward/forward compatibility. This function currently accepts a "
+ + "positional <code>items</code> parameter. It is deprecated and will be removed "
+ + "in the future, and after its removal <code>direct</code> will become a sole "
+ + "positional parameter of the <code>depset</code> function. Thus, both of the "
+ + "following calls are equivalent and future-proof:<br>"
+ + "<pre class=language-python>"
+ + "depset(['a', 'b'], transitive = [...])\n"
+ + "depset(direct = ['a', 'b'], transitive = [...])\n"
+ + "</pre>",
+ parameters = {
+ @Param(
+ name = "items",
+ type = Object.class,
+ defaultValue = "[]",
+ doc =
+ "Deprecated: Either an iterable whose items become the direct elements of "
+ + "the new depset, in left-to-right order, or else a depset that becomes "
+ + "a transitive element of the new depset. In the latter case, "
+ + "<code>transitive</code> cannot be specified."),
+ @Param(
+ name = "order",
+ type = String.class,
+ defaultValue = "\"default\"",
+ doc =
+ "The traversal strategy for the new depset. See <a href=\"depset.html\">here</a> for "
+ + "the possible values."),
+ @Param(
+ name = "direct",
+ type = SkylarkList.class,
+ defaultValue = "None",
+ positional = false,
+ named = true,
+ noneable = true,
+ doc = "A list of <i>direct</i> elements of a depset."),
+ @Param(
+ name = "transitive",
+ named = true,
+ positional = false,
+ type = SkylarkList.class,
+ generic1 = SkylarkNestedSet.class,
+ noneable = true,
+ doc = "A list of depsets whose elements will become indirect elements of the depset.",
+ defaultValue = "None")
+ },
+ useLocation = true)
+ private static final BuiltinFunction depset =
+ new BuiltinFunction("depset") {
+ public SkylarkNestedSet invoke(
+ Object items, String orderString, Object direct, Object transitive, Location loc)
+ throws EvalException {
+ Order order;
+ try {
+ order = Order.parse(orderString);
+ } catch (IllegalArgumentException ex) {
+ throw new EvalException(loc, ex);
+ }
+
+ if (transitive == Runtime.NONE && direct == Runtime.NONE) {
+ // Legacy behavior.
+ return SkylarkNestedSet.of(order, items, loc);
+ }
+
+ if (direct != Runtime.NONE && !isEmptySkylarkList(items)) {
+ throw new EvalException(
+ loc, "Do not pass both 'direct' and 'items' argument to depset constructor.");
+ }
+
+ // Non-legacy behavior: either 'transitive' or 'direct' were specified.
+ Iterable<Object> directElements;
+ if (direct != Runtime.NONE) {
+ directElements = ((SkylarkList<?>) direct).getContents(Object.class, "direct");
+ } else {
+ SkylarkType.checkType(items, SkylarkList.class, "items");
+ directElements = ((SkylarkList<?>) items).getContents(Object.class, "items");
+ }
+
+ Iterable<SkylarkNestedSet> transitiveList;
+ if (transitive != Runtime.NONE) {
+ SkylarkType.checkType(transitive, SkylarkList.class, "transitive");
+ transitiveList =
+ ((SkylarkList<?>) transitive).getContents(SkylarkNestedSet.class, "transitive");
+ } else {
+ transitiveList = ImmutableList.of();
+ }
+ SkylarkNestedSet.Builder builder = SkylarkNestedSet.builder(order, loc);
+ for (Object directElement : directElements) {
+ builder.addDirect(directElement);
+ }
+ for (SkylarkNestedSet transitiveSet : transitiveList) {
+ builder.addTransitive(transitiveSet);
+ }
+ return builder.build();
+ }
+ };
+
+ private static boolean isEmptySkylarkList(Object o) {
+ return o instanceof SkylarkList && ((SkylarkList) o).isEmpty();
+ }
+
+ /**
+ * Returns a function-value implementing "select" (i.e. configurable attributes) in the specified
+ * package context.
+ */
+ @SkylarkSignature(
+ name = "select",
+ doc = "<code>select()</code> is the helper function that makes a rule attribute "
+ + "<a href=\"$BE_ROOT/common-definitions.html#configurable-attributes\">configurable</a>. "
+ + "See <a href=\"$BE_ROOT/functions.html#select\">build encyclopedia</a> for details.",
+ parameters = {
+ @Param(name = "x", type = SkylarkDict.class, doc = "The parameter to convert."),
+ @Param(
+ name = "no_match_error",
+ type = String.class,
+ defaultValue = "''",
+ doc = "Optional custom error to report if no condition matches.")
+ },
+ useLocation = true)
+ private static final BuiltinFunction select =
+ new BuiltinFunction("select") {
+ public Object invoke(SkylarkDict<?, ?> dict, String noMatchError, Location loc)
+ throws EvalException {
+ for (Object key : dict.keySet()) {
+ if (!(key instanceof String)) {
+ throw new EvalException(
+ loc, String.format("Invalid key: %s. select keys must be label references", key));
+ }
+ }
+ return SelectorList.of(new SelectorValue(dict, noMatchError));
+ }
+ };
+
+ @SkylarkSignature(
name = "zip",
doc =
"Returns a <code>list</code> of <code>tuple</code>s, where the i-th tuple contains "
@@ -947,8 +1118,8 @@ public class MethodLibrary {
private static final ImmutableList<BaseFunction> allFunctions =
ImmutableList.of(
- all, any, bool, dict, dir, fail, getattr, hasattr, hash, enumerate, int_, len, list, max,
- min, print, range, repr, reversed, sorted, str, tuple, zip);
+ all, any, bool, depset, dict, dir, fail, getattr, hasattr, hash, enumerate, int_, len,
+ list, max, min, print, range, repr, reversed, select, sorted, str, tuple, type, zip);
static {
SkylarkSignatureProcessor.configureSkylarkFunctions(MethodLibrary.class);