Skylark: 'in' works on sets. -- MOS_MIGRATED_REVID=89977206
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java index 39f220e..7b8c2df 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java
@@ -36,9 +36,7 @@ private final Operator operator; - public BinaryOperatorExpression(Operator operator, - Expression lhs, - Expression rhs) { + public BinaryOperatorExpression(Operator operator, Expression lhs, Expression rhs) { this.lhs = lhs; this.rhs = rhs; this.operator = operator; @@ -250,6 +248,8 @@ return ((Collection<?>) rval).contains(lval); } else if (rval instanceof Map<?, ?>) { return ((Map<?, ?>) rval).containsKey(lval); + } else if (rval instanceof SkylarkNestedSet) { + return ((SkylarkNestedSet) rval).expandedSet().contains(lval); } else if (rval instanceof String) { if (lval instanceof String) { return ((String) rval).contains((String) lval); @@ -259,7 +259,7 @@ } } else { throw new EvalException(getLocation(), - "in operator only works on lists, tuples, dictionaries and strings"); + "in operator only works on lists, tuples, sets, dicts and strings"); } }
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 233cfdd..39441b0 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
@@ -26,6 +26,7 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Set; import javax.annotation.Nullable; @@ -183,6 +184,10 @@ return (NestedSet<T>) set; } + public Set<?> expandedSet() { + return set.toSet(); + } + // For some reason this cast is unsafe in Java @SuppressWarnings("unchecked") @Override
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java b/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java index 1637525..cb52cc4 100644 --- a/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java +++ b/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java
@@ -471,60 +471,24 @@ } @Test - public void testInOnListContains() throws Exception { + public void testInOperator() throws Exception { assertEquals(Boolean.TRUE, eval("'b' in ['a', 'b']")); - } - - @Test - public void testInOnListDoesNotContain() throws Exception { assertEquals(Boolean.FALSE, eval("'c' in ['a', 'b']")); - } - - @Test - public void testInOnTupleContains() throws Exception { assertEquals(Boolean.TRUE, eval("'b' in ('a', 'b')")); - } - - @Test - public void testInOnTupleDoesNotContain() throws Exception { assertEquals(Boolean.FALSE, eval("'c' in ('a', 'b')")); - } - - @Test - public void testInOnDictContains() throws Exception { assertEquals(Boolean.TRUE, eval("'b' in {'a' : 1, 'b' : 2}")); - } - - @Test - public void testInOnDictDoesNotContainKey() throws Exception { assertEquals(Boolean.FALSE, eval("'c' in {'a' : 1, 'b' : 2}")); - } - - @Test - public void testInOnDictDoesNotContainVal() throws Exception { assertEquals(Boolean.FALSE, eval("1 in {'a' : 1, 'b' : 2}")); - } - - @Test - public void testInOnStringContains() throws Exception { assertEquals(Boolean.TRUE, eval("'b' in 'abc'")); - } - - @Test - public void testInOnStringDoesNotContain() throws Exception { assertEquals(Boolean.FALSE, eval("'d' in 'abc'")); } @Test - public void testInOnStringLeftNotString() throws Exception { + public void testInFail() throws Exception { checkEvalError("1 in '123'", "in operator only works on strings if the left operand is also a string"); - } - - @Test - public void testInFailsOnNonIterable() throws Exception { checkEvalError("'a' in 1", - "in operator only works on lists, tuples, dictionaries and strings"); + "in operator only works on lists, tuples, sets, dicts and strings"); } @Test
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java index da38aa0..b55f428 100644 --- a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java +++ b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
@@ -534,6 +534,13 @@ } @Test + public void testInSet() throws Exception { + assertEquals(Boolean.TRUE, eval("'b' in set(['a', 'b'])")); + assertEquals(Boolean.FALSE, eval("'c' in set(['a', 'b'])")); + assertEquals(Boolean.FALSE, eval("1 in set(['a', 'b'])")); + } + + @Test public void testClassObjectCannotAccessNestedSet() throws Exception { env.update("mock", new MockClassObject()); checkEvalError(parseFileForSkylark("v = mock.nset", MOCK_TYPES), env,