Implement list.remove function

--
MOS_MIGRATED_REVID=110356439
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 dc3f50b..2a64a0e 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 @@
         "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 @@
         }
       };
 
+  @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 547fd3e..74031d3 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 @@
       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 f649ce2..772d875 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 @@
   }
 
   @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'])")