Repository: bazelbuild/bazel
Issue: Skylark operator list * int missing
Labels: type: feature request

Currently it is not supported to write `[foo] * 5`.
Message is:

```
unsupported operand type(s) for *: 'list' and 'int'.
```


Issue comments:
Isn't this fixed already?
Andreas's fix is still pending: https://github.com/bazelbuild/bazel/pull/1524
Is merged.
Thank you!

Pull request review comments:

Patch that resolved the issue:
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 ed0e55f569ac0f..973260fefb1f8f 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
@@ -144,7 +144,7 @@ Object doEval(Environment env) throws EvalException, InterruptedException {
         return minus(lval, rval, getLocation());
 
       case MULT:
-        return mult(lval, rval, getLocation());
+        return mult(lval, rval, env, getLocation());
 
       case DIVIDE:
         return divide(lval, rval, getLocation());
@@ -374,7 +374,7 @@ public static Object minus(Object lval, Object rval, Location location) throws E
    *
    * <p>Publicly accessible for reflection and compiled Skylark code.
    */
-  public static Object mult(Object lval, Object rval, Location location) throws EvalException {
+  public static Object mult(Object lval, Object rval, Environment env, Location location) throws EvalException {
     Integer number = null;
     Object otherFactor = null;
 
@@ -392,8 +392,10 @@ public static Object mult(Object lval, Object rval, Location location) throws Ev
       } else if (otherFactor instanceof String) {
         // Similar to Python, a factor < 1 leads to an empty string.
         return Strings.repeat((String) otherFactor, Math.max(0, number.intValue()));
+      } else if (otherFactor instanceof MutableList) {
+        // Similar to Python, a factor < 1 leads to an empty string.
+        return MutableList.duplicate((MutableList) otherFactor, Math.max(0, number.intValue()), env);
       }
-      // TODO(skylark-team): implement int * list
     }
     throw typeException(lval, rval, Operator.MULT, location);
   }
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 1221aa67cc8e66..b6f17e9f4e907b 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
@@ -407,6 +407,33 @@ public static <E> MutableList<E> concat(
           left.getGlobListOrContentsUnsafe(), right.getGlobListOrContentsUnsafe()), env);
     }
 
+    /**
+     * Duplicates MutableList n times
+     * @param list the list to duplicate
+     * @param times the count of times to duplicate
+     * @param env the Environment in which to create a new list
+     * @return a new MutableList
+     */
+    public static <E> MutableList<E> duplicate(
+        final MutableList<? extends E> list,
+        final int times,
+        final Environment env) {
+      final int concatCount = times - 1;
+      if (list.getGlobList() == null) {
+        Iterable<? extends E> iterable = list;
+        for (int i = concatCount; i > 0; --i) {
+          iterable = Iterables.concat(iterable, iterable);
+        }
+        return new MutableList(iterable, env);
+      }
+
+      List<?> globs = list.getGlobListOrContentsUnsafe();
+      for (int i = concatCount; i > 0; --i) {
+        globs = GlobList.concat(globs, globs);
+      }
+      return new MutableList(globs, env);
+    }
+
     /**
      * Adds one element at the end of the MutableList.
      * @param element the element to add


Test patch:
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 9bdaa150e7b39c..21a4cc2d3bb06a 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
@@ -537,6 +537,19 @@ public void testListConcatenation() throws Exception {
             "(1, 2) + [3, 4]");
   }
 
+  @Test
+  public void testListMultiply() throws Exception {
+    newTest()
+            .testStatement("[1, 2] * 2", MutableList.of(env, 1, 2, 1, 2))
+            .testStatement("[    ] * 10", MutableList.EMPTY)
+            .testStatement("[1, 2] * 0", MutableList.EMPTY)
+            .testStatement("[1, 2] * -4", MutableList.EMPTY)
+            .testStatement(" 2 * [1, 2]", MutableList.of(env, 1, 2, 1, 2))
+            .testStatement("10 * []", MutableList.EMPTY)
+            .testStatement(" 0 * [1, 2]", MutableList.EMPTY)
+            .testStatement("-4 * [1, 2]", MutableList.EMPTY);
+  }
+
   @SuppressWarnings("unchecked")
   @Test
   public void testSelectorListConcatenation() throws Exception {