aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/syntax
diff options
context:
space:
mode:
authorGravatar cparsons <cparsons@google.com>2018-06-15 09:04:21 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-06-15 09:05:42 -0700
commitb36470e6e0073a76012afbed7ba9cf9c32ef002c (patch)
tree26bef368c3073a6507732858222d9285f1c4ad53 /src/main/java/com/google/devtools/build/lib/syntax
parent3aea081b6f91bffbc2c9c47d6cd034778f977e39 (diff)
Move remaining BazelLibrary skylark functions to MethodLibrary
Ultimately, we'll need to make the call on whether these functions belong as part of the build API or as part of skylark builtins. For now, we keep them as skylark builtins. (In either case, we'll want to migrate to @SkylarkCallable, but that's for a later change) RELNOTES: None. PiperOrigin-RevId: 200723605
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);