Misc Skylark cleanups and small features
--
MOS_MIGRATED_REVID=88224368
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 59aadd1..c03a9ff 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
@@ -138,11 +138,14 @@
// TODO(bazel-team): move the following few type-related functions to SkylarkType
/**
- * Compute the super-class of a class that Skylark considers as the Skylark type of its instances
+ * Return the Skylark-type of {@code c}
*
- * <p>Skylark type validation isn't otherwise equipped to deal with inheritance, so we must tell
- * it which is the super-class or interface that matters for Skylark type compatibility.
- * e.g. instances of all subclasses of SkylarkList are considered as being of type SkylarkList.
+ * <p>The result will be a type that Skylark understands and is either equal to {@code c}
+ * or is a supertype of it. For example, all instances of (all subclasses of) SkylarkList
+ * are considered to be SkylarkLists.
+ *
+ * <p>Skylark's type validation isn't equipped to deal with inheritance so we must tell it which
+ * of the superclasses or interfaces of {@code c} is the one that matters for type compatibility.
*
* @param c a class
* @return a super-class of c to be used in validation-time type inference.
@@ -162,7 +165,8 @@
} else if (Set.class.isAssignableFrom(c)) {
return Set.class;
} else {
- // TODO(bazel-team): also unify all ClassObject, that we print the same?
+ // TODO(bazel-team): also unify all implementations of ClassObject,
+ // that we used to all print the same as "struct"?
//
// Check if one of the superclasses or implemented interfaces has the SkylarkModule
// annotation. If yes return that class.
@@ -271,7 +275,7 @@
private static void printValueX(Object o, Appendable buffer)
throws IOException {
if (o == null) {
- throw new NullPointerException(); // None is not a build language value.
+ throw new NullPointerException(); // Java null is not a build language value.
} else if (o instanceof String || o instanceof Integer || o instanceof Double) {
buffer.append(o.toString());
@@ -619,7 +623,7 @@
}
/**
- * Returns the size of the Skylark object or -1 in case the object doesn't have a size.
+ * @return the size of the Skylark object or -1 in case the object doesn't have a size.
*/
public static int size(Object arg) {
if (arg instanceof String) {
@@ -634,4 +638,40 @@
}
return -1;
}
+
+ /** @return true if x is Java null or Skylark None */
+ public static boolean isNullOrNone(Object x) {
+ return x == null || x == Environment.NONE;
+ }
+
+ /**
+ * Build a map of kwarg arguments from a list, removing null-s or None-s.
+ *
+ * @param init a series of key, value pairs (as consecutive arguments), and optionally
+ * a lone map at the end, as in {@code optionMap(k1, v1, k2, v2, k3, v3, map)}
+ * where each key is a String, each value is an arbitrary Objet, and the map
+ * must be a {@code Map<String, Object>}.
+ * @return a {@code Map<String, Object>} that has all the specified entries,
+ * where key, value pairs appearing earlier have precedence,
+ * i.e. {@code k1, v1} may override {@code k3, v3}.
+ *
+ * Ignore any entry the key or value of which is null or None.
+ */
+ @SuppressWarnings("unchecked")
+ public static ImmutableMap<String, Object> optionMap(Object... init) {
+ ImmutableMap.Builder<String, Object> b = new ImmutableMap.Builder<>();
+ int l = init.length;
+ if (l % 2 == 1) { // If there's an odd number of argument, the last one is a Map.
+ l--;
+ b.putAll((Map<String, Object>) init[l]);
+ }
+ for (int i = l - 2; i >= 0; i -= 2) {
+ String key = (String) init[i];
+ Object value = init[i + 1];
+ if (!(isNullOrNone(key) || isNullOrNone(value))) {
+ b.put(key, value);
+ }
+ }
+ return b.build();
+ }
}