diff options
3 files changed, 55 insertions, 1 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 dc3f50b72e..2a64a0e02b 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 @@ -1183,7 +1183,7 @@ public class MethodLibrary { "Returns the index in the list of the first item whose value is x. " + "It is an error if there is no such item.", mandatoryPositionals = { - @Param(name = "self", type = MutableList.class, doc = "This string, a separator."), + @Param(name = "self", type = MutableList.class, doc = "This list."), @Param(name = "x", type = Object.class, doc = "The object to search.") }, useLocation = true @@ -1202,6 +1202,34 @@ public class MethodLibrary { } }; + @SkylarkSignature( + name = "remove", + objectType = MutableList.class, + returnType = Runtime.NoneType.class, + doc = + "Removes the first item from the list whose value is x. " + + "It is an error if there is no such item.", + mandatoryPositionals = { + @Param(name = "self", type = MutableList.class, doc = "This list."), + @Param(name = "x", type = Object.class, doc = "The object to remove.") + }, + useLocation = true, + useEnvironment = true + ) + private static BuiltinFunction listRemove = + new BuiltinFunction("remove") { + public Runtime.NoneType invoke(MutableList self, Object x, Location loc, Environment env) + throws EvalException { + for (int i = 0; i < self.size(); i++) { + if (self.get(i).equals(x)) { + self.remove(i, loc, env); + return Runtime.NONE; + } + } + throw new EvalException(loc, Printer.format("Item %r not found in list", x)); + } + }; + // dictionary access operator @SkylarkSignature(name = "$index", documented = false, objectType = Map.class, doc = "Looks up a value in a dictionary.", diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkList.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkList.java index 547fd3e5b7..74031d3dfe 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkList.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkList.java @@ -318,6 +318,11 @@ public abstract class SkylarkList implements Iterable<Object>, SkylarkValue { add(element); } + public void remove(int index, Location loc, Environment env) throws EvalException { + checkMutable(loc, env); + contents.remove(index); + } + /** * Adds all the elements at the end of the MutableList. * @param elements the elements to add diff --git a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java index f649ce2ab1..772d875850 100644 --- a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java +++ b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java @@ -1306,6 +1306,27 @@ public class MethodLibraryTest extends EvaluationTestCase { } @Test + public void testListRemove() throws Exception { + new BothModesTest() + .setUp("foo = ['a', 'b', 'c', 'b']", "foo.remove('b')") + .testLookup("foo", MutableList.of(env, "a", "c", "b")) + .setUp("foo.remove('c')") + .testLookup("foo", MutableList.of(env, "a", "b")) + .setUp("foo.remove('a')") + .testLookup("foo", MutableList.of(env, "b")) + .setUp("foo.remove('b')") + .testLookup("foo", MutableList.of(env)) + .testIfErrorContains("Item 3 not found in list", "[1, 2].remove(3)"); + + new BuildTest() + .testIfErrorContains( + "function remove is not defined on object of type 'tuple'", "(1, 2).remove(3)"); + + new SkylarkTest() + .testIfErrorContains("Type tuple has no function remove(int)", "(1, 2).remove(3)"); + } + + @Test public void testReassignmentOfPrimitivesNotForbiddenByCoreLanguage() throws Exception { new BuildTest() .setUp("cc_binary = (['hello.cc'])") |