Rewrite of ArrayList.java
- Optimized ArrayList for the same operations the JRE version is optimized for
- Made the code simpler; removed as much JSNI as possible
- Some consistency stuff in AbstractList
- Added common functions to create a JS object/array on JavaScriptObject; using those from HashMap.java
- Also privitized HashMap & ArrayLists's clear implementation

Review by: knorton


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1212 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/core/client/JavaScriptObject.java b/user/src/com/google/gwt/core/client/JavaScriptObject.java
index abbb960..bd55e8d 100644
--- a/user/src/com/google/gwt/core/client/JavaScriptObject.java
+++ b/user/src/com/google/gwt/core/client/JavaScriptObject.java
@@ -29,6 +29,20 @@
  */
 public class JavaScriptObject {
 
+  /**
+   * Returns a new array.
+   */
+  public static native JavaScriptObject createArray() /*-{
+    return [];
+  }-*/;
+  
+  /**
+   * Returns a new object.
+   */
+  public static native JavaScriptObject createObject() /*-{
+    return {};
+  }-*/;
+
   private static native boolean equalsImpl(JavaScriptObject o,
       JavaScriptObject other) /*-{
     return o === other;
diff --git a/user/super/com/google/gwt/emul/java/util/AbstractList.java b/user/super/com/google/gwt/emul/java/util/AbstractList.java
index cf3b05a..b810725 100644
--- a/user/super/com/google/gwt/emul/java/util/AbstractList.java
+++ b/user/super/com/google/gwt/emul/java/util/AbstractList.java
@@ -30,14 +30,14 @@
     int i = 0, last = -1;
 
     public boolean hasNext() {
-      return i < size();
+      return i < AbstractList.this.size();
     }
 
     public Object next() {
       if (!hasNext()) {
         throw new NoSuchElementException();
       }
-      return get(last = i++);
+      return AbstractList.this.get(last = i++);
     }
 
     public void remove() {
@@ -68,8 +68,7 @@
     private ListIteratorImpl(int start) {
       int size = AbstractList.this.size();
       if (start < 0 || start > size) {
-        throw new IndexOutOfBoundsException("Size: " + AbstractList.this.size()
-            + " Index: " + i);
+        AbstractList.this.indexOutOfBounds(start);
       }
       i = start;
     }
@@ -91,7 +90,7 @@
       if (!hasPrevious()) {
         throw new NoSuchElementException();
       }
-      return get(last = --i);
+      return AbstractList.this.get(last = --i);
     }
 
     public int previousIndex() {
@@ -208,6 +207,14 @@
     throw new UnsupportedOperationException("set");
   }
 
+  /**
+   * Throws an <code>indexOutOfBoundsException</code>.
+   */
+  protected void indexOutOfBounds(int i) {
+    throw new IndexOutOfBoundsException("Index: " + i + ", Size: "
+        + this.size());
+  }
+
   protected void removeRange(int fromIndex, int endIndex) {
     ListIterator iter = listIterator(fromIndex);
     for (int i = fromIndex; i < endIndex; ++i) {
diff --git a/user/super/com/google/gwt/emul/java/util/ArrayList.java b/user/super/com/google/gwt/emul/java/util/ArrayList.java
index 0d11e3c..a01dc07 100644
--- a/user/super/com/google/gwt/emul/java/util/ArrayList.java
+++ b/user/super/com/google/gwt/emul/java/util/ArrayList.java
@@ -18,110 +18,103 @@
 import com.google.gwt.core.client.JavaScriptObject;
 
 /**
- * See Sun's JDK 1.4 documentation for documentation.   
+ * See Sun's JDK 1.4 documentation for documentation.
  * 
- * Differences between this implementation and JDK 1.4 <code>ArrayList</code>
- * include capacity management and range checking.
- * <p>
- * <b>Capacity</b> There is no speed advantage to pre-allocating array sizes in
- * JavaScript, so this implementation does not include any of the capacity and
- * "growth increment" concepts in the standard ArrayList class. Although
- * <code>ArrayList(int)</code> accepts a value for the intitial capacity of
- * the array, this constructor simply delegates to <code>ArrayList()</code>.
- * It is only present for compatibility with JDK 1.4's API.
- * </p>
- * <p>
- * <b>Dual endedness</b> For increased performance, this implementation supports
- * constant time insertion and deletion from either end.
+ * This implementation differs from JDK 1.4 <code>ArrayList</code> in terms of
+ * capacity management. There is no speed advantage to pre-allocating array
+ * sizes in JavaScript, so this implementation does not include any of the
+ * capacity and "growth increment" concepts in the standard ArrayList class.
+ * Although <code>ArrayList(int)</code> accepts a value for the intitial
+ * capacity of the array, this constructor simply delegates to
+ * <code>ArrayList()</code>. It is only present for compatibility with JDK
+ * 1.4's API.
  * </p>
  */
 public class ArrayList extends AbstractList implements List, Cloneable,
     RandomAccess {
-  /*
-   * Implementation notes:  
-   *   Currently if one uses an ArrayList as a ring buffer, adding from one end,
-   *   and deleting from the other, the indexes will increase (or decrease) 
-   *   without ever being normalized.  Back of the envelope calculations 
-   *   indicate that at 30 indexes per second, it will take a year of solid run
-   *   time to chew through the billion indexes needed to get into trouble.
-   *   Given that it seemed better not to rebalance than to charge everyone the
-   *   extra code size the rebalancing code would represent. 
-   */
 
-  protected static boolean equals(Object a, Object b) {
-    return (a == null ? b == null : a.equals(b));
-  } 
-  /** 
-   * This field holds the javascript array, and is not private to avoid Eclipse
-   * warnings. 
+  private static native void addImpl(JavaScriptObject array, int index, Object o) /*-{
+    array.splice(index, 0, o);
+  }-*/;
+
+  private static boolean equals(Object a, Object b) {
+    return a == b || (a != null && a.equals(b));
+  }
+
+  private static native Object getImpl(JavaScriptObject array, int index) /*-{
+    return array[index];
+  }-*/;
+
+  private static native void removeRangeImpl(JavaScriptObject array, int index,
+      int count) /*-{
+    array.splice(index, count);
+  }-*/;
+
+  private static native void setImpl(JavaScriptObject array, int index, Object o) /*-{
+    array[index] = o;
+  }-*/;
+
+  private static native void setSizeImpl(JavaScriptObject array, int newSize) /*-{
+    array.length = newSize;
+  }-*/;
+
+  /**
+   * This field holds a JavaScript array.
    */
-  transient JavaScriptObject array;
-  /** 
-   * This field holds the last populated index of the array and is not private
-   * to avoid Eclipse warnings.
+  private transient JavaScriptObject array;
+
+  /**
+   * The size of the array.
    */
-  int endIndex;
-  /** 
-   * This field holds the first populated index of the array and is not private
-   * to avoid Eclipse warnings.
-   */
-  int startIndex;
+  private int size;
+
+  {
+    clearImpl();
+  }
 
   public ArrayList() {
-    initArray();
   }
 
   public ArrayList(Collection c) {
-    initArray();
     addAll(c);
   }
 
   /**
-   * There is no speed advantage to pre-allocating array sizes in JavaScript,
-   * so the <code>intialCapacity</code> parameter is ignored. This constructor is
+   * There is no speed advantage to pre-allocating array sizes in JavaScript, so
+   * the <code>intialCapacity</code> parameter is ignored. This constructor is
    * only present for compatibility with JDK 1.4's API.
    */
   public ArrayList(int initialCapacity) {
     // initialCapacity is ignored in JS implementation; this constructor is
     // present for JDK 1.4 compatibility
-    this();
   }
 
-  public native void add(int index, Object o) /*-{
-    var array  = this.@java.util.ArrayList::array;
-    var endIndex = this.@java.util.ArrayList::endIndex;
-    var startIndex = this.@java.util.ArrayList::startIndex;
-    // This if is not an else if to call attention to the early return.
-    if (index + startIndex == endIndex) {
-      // If we are at the end simply set the next element to hold the value.
-      array[endIndex] = o;
-      this.@java.util.ArrayList::endIndex++;
-      return;
+  public void add(int index, Object o) {
+    if (index < 0 || index > size) {
+      indexOutOfBounds(index);
     }
-    if (index == 0) {
-      // If we are adding at the beginning, simply set the new element, and 
-      // move the beginning back.
-      array[--this.@java.util.ArrayList::startIndex] = o;
-      return;
-    }
-    
-    // Somewhere in the middle, so do range checking and the splice.
-    // Range checking, must be more permissive since one can add off the end.
-    this.@java.util.ArrayList::verifyIndexOneExtra(I)(index);
-    array.splice(index + startIndex, 0, o);
-    // The end of the array moved forward if we got here so record that.
-    this.@java.util.ArrayList::endIndex++;
-  }-*/;
+    addImpl(array, index, o);
+    ++size;
+  }
 
   public boolean add(Object o) {
-    add(size(),o);
+    setImpl(array, size++, o);
     return true;
   }
- 
-  public void clear() {
-    setSize(0);
+
+  public boolean addAll(Collection c) {
+    Iterator iter = c.iterator();
+    boolean changed = iter.hasNext();
+    while (iter.hasNext()) {
+      setImpl(array, size++, iter.next());
+    }
+    return changed;
   }
-  
+
+  public void clear() {
+    clearImpl();
+  }
+
   public Object clone() {
     return new ArrayList(this);
   }
@@ -129,30 +122,32 @@
   public boolean contains(Object o) {
     return (indexOf(o) != -1);
   }
- 
-  public native Object get(int index) /*-{
-    this.@java.util.ArrayList::verifyIndex(I)(index);
-    var startIndex = this.@java.util.ArrayList::startIndex;
-    return this.@java.util.ArrayList::array[index + startIndex];
-  }-*/;
-  
+
+  public Object get(int index) {
+    if (index < 0 || index >= size) {
+      indexOutOfBounds(index);
+    }
+    return getImpl(array, index);
+  }
+
   public int indexOf(Object o) {
     return indexOf(o, 0);
   }
 
-  public native boolean isEmpty() /*-{
-    return (this.@java.util.ArrayList::endIndex == this.@java.util.ArrayList::startIndex);
-  }-*/;
+  public boolean isEmpty() {
+    return size == 0;
+  }
 
   public int lastIndexOf(Object o) {
-     return lastIndexOf(o, size() - 1);
+    return lastIndexOf(o, size() - 1);
   }
 
   public Object remove(int index) {
-    Object old = get(index);
-    removeRange(index,index + 1);
-    return old;
-  } 
+    Object previous = get(index);
+    removeRangeImpl(array, index, 1);
+    --size;
+    return previous;
+  }
 
   public boolean remove(Object o) {
     int i = indexOf(o);
@@ -163,127 +158,70 @@
     return true;
   }
 
-  public native Object set(int index, Object o) /*-{
-    this.@java.util.ArrayList::verifyIndex(I)(index);
-    var array = this.@java.util.ArrayList::array;
-    var startIndex = this.@java.util.ArrayList::startIndex;
-    var old = array[index + startIndex];
-    array[index + startIndex] = o;
-    return old;
-  }-*/;
-
-  public native int size() /*-{
-    return this.@java.util.ArrayList::endIndex - this.@java.util.ArrayList::startIndex; 
-  }-*/;
-  
-  protected native void removeRange(int fromIndex, int toIndex) /*-{
-    this.@java.util.ArrayList::verifyIndexOneExtra(I)(fromIndex);
-    this.@java.util.ArrayList::verifyIndexOneExtra(I)(toIndex);
-    var array = this.@java.util.ArrayList::array;
-    var startIndex = this.@java.util.ArrayList::startIndex;
-    var endIndex = this.@java.util.ArrayList::endIndex;
-    if (fromIndex == 0) {
-      // Chop off the beginning.
-      for (var i = startIndex; i < (toIndex + startIndex); i++) {
-        delete array[i];
-      }
-      this.@java.util.ArrayList::startIndex += (toIndex - fromIndex);
-    } else if (toIndex + startIndex == endIndex) {
-      // Chop off the end.
-      for (var i = (fromIndex + startIndex); i < endIndex; i++) {
-        delete array[i];
-      }
-      this.@java.util.ArrayList::endIndex = (fromIndex + startIndex);
-    } else {
-      // Splice from the middle.
-      var numToRemove = toIndex - fromIndex;
-      array.splice(fromIndex + startIndex, numToRemove);
-      this.@java.util.ArrayList::endIndex -= numToRemove;
-    }
-  }-*/;
-  
-  native int indexOf(Object o, int index) /*-{
-    var array = this.@java.util.ArrayList::array;
-    var startIndex = this.@java.util.ArrayList::startIndex;
-    var i = index + startIndex;
-    var endIndex = this.@java.util.ArrayList::endIndex;            
-    while (i < endIndex) {
-      if (@java.util.ArrayList::equals(Ljava/lang/Object;Ljava/lang/Object;)(array[i],o)) {
-        return i - startIndex;
-      }
-      ++i;
-    }
-    return -1;
-  }-*/;
-  
-  /**
-   * Throws an <code>indexOutOfBoundsException</code>, and is not 
-   * private to avoid eclipse warnings.
-   */
-  void indexOutOfBounds(int i) {
-    throw new IndexOutOfBoundsException("Size: " + this.size() + " Index: " + i);
+  public Object set(int index, Object o) {
+    Object previous = get(index);
+    setImpl(array, index, o);
+    return previous;
   }
-  
-  /**
-   * Computes the last index of an element given an offset, and is
-   * not private to avoid eclipse warnings.
-   */
-  native int lastIndexOf(Object o, int index) /*-{
-    var array = this.@java.util.ArrayList::array;
-    var startIndex = this.@java.util.ArrayList::startIndex;
-    var i = index + startIndex;
-    while (i >= startIndex) {
-      if (@java.util.ArrayList::equals(Ljava/lang/Object;Ljava/lang/Object;)(array[i],o)) {
-        return i - startIndex;
+
+  public int size() {
+    return size;
+  }
+
+  protected int indexOf(Object o, int index) {
+    if (index < 0) {
+      indexOutOfBounds(index);
+    }
+    for (; index < size; ++index) {
+      if (equals(o, getImpl(array, index))) {
+        return index;
       }
-      --i;
     }
     return -1;
-  }-*/;
+  }
+
+  protected int lastIndexOf(Object o, int index) {
+    if (index >= size) {
+      indexOutOfBounds(index);
+    }
+    for (; index >= 0; --index) {
+      if (equals(o, getImpl(array, index))) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  protected void removeRange(int fromIndex, int endIndex) {
+    if (fromIndex < 0 || fromIndex >= size) {
+      indexOutOfBounds(fromIndex);
+    }
+    if (endIndex < fromIndex || endIndex > size) {
+      indexOutOfBounds(endIndex);
+    }
+    int count = endIndex - fromIndex;
+    removeRangeImpl(array, fromIndex, count);
+    size -= count;
+  }
 
   /**
-   * This function sets the size of the array, and is used in Vector.
+   * This function sets the size of the array, and is used by Vector.
    */
-  native void setSize(int newSize) /*-{
-    // Make sure to null fill any newly created slots (otherwise,
-    // get() can return 'undefined').
-    var endIndex = this.@java.util.ArrayList::endIndex;
-    var startIndex = this.@java.util.ArrayList::startIndex;
-    var array = this.@java.util.ArrayList::array;
-    var newEnd = newSize + startIndex;
-    for (var i = endIndex; i < newEnd; ++i) {
-      array[i] = null;
+  protected void setSize(int newSize) {
+    if (newSize < 0) {
+      indexOutOfBounds(newSize);
     }
+    setSizeImpl(array, newSize);
+    // null fill any new slots if size < newSize
+    for (; size < newSize; ++size) {
+      setImpl(array, size, null);
+    }
+    // assignment necessary when size > newSize
+    size = newSize;
+  }
 
-    // Also make sure to clean up orphaned slots (or we'll end up
-    // leaving garbage uncollected).
-    for (var i = endIndex - 1; i >= newEnd; --i) {
-      delete array[i];
-    }
-    this.@java.util.ArrayList::endIndex = newEnd;
-  }-*/;
-  
-  native void verifyIndex(int index) /*-{
-    var endIndex = this.@java.util.ArrayList::endIndex;
-    var startIndex = this.@java.util.ArrayList::startIndex;
-    if (index < 0 || index + startIndex >= endIndex) {
-      this.@java.util.ArrayList::indexOutOfBounds(I)(index);
-    }
-  }-*/;
-  
-  native void verifyIndexOneExtra(int index) /*-{
-    var endIndex = this.@java.util.ArrayList::endIndex;
-    var startIndex = this.@java.util.ArrayList::startIndex;
-    if (index < 0 || index + startIndex > endIndex) {
-      this.@java.util.ArrayList::indexOutOfBounds(I)(index);
-    }
-  }-*/;
- 
-  private native void initArray() /*-{
-    this.@java.util.ArrayList::array = new Array();
-    var HALFWAY_INDEX = 1000000000; // Halfway through the address space
-    // Javascript arrays are sparse, so this wastes no space
-    this.@java.util.ArrayList::startIndex = HALFWAY_INDEX;
-    this.@java.util.ArrayList::endIndex = HALFWAY_INDEX;
-  }-*/;
+  private void clearImpl() {
+    array = JavaScriptObject.createArray();
+    size = 0;
+  }
 }
diff --git a/user/super/com/google/gwt/emul/java/util/HashMap.java b/user/super/com/google/gwt/emul/java/util/HashMap.java
index 13ab2ad..d79bbc9 100644
--- a/user/super/com/google/gwt/emul/java/util/HashMap.java
+++ b/user/super/com/google/gwt/emul/java/util/HashMap.java
@@ -250,24 +250,6 @@
   }-*/;
 
   /**
-   * Returns a new array.
-   * 
-   * TODO: move this to JavaScriptObject?
-   */
-  private static native JavaScriptObject createArray() /*-{
-    return [];
-  }-*/;
-
-  /**
-   * Returns a new object.
-   * 
-   * TODO: move this to JavaScriptObject?
-   */
-  private static native JavaScriptObject createObject() /*-{
-    return {};
-  }-*/;
-
-  /**
    * Returns <code>undefined</code>. This is technically a violation of the
    * JSNI contract, so we have to be very careful how we use the result.
    */
@@ -417,7 +399,7 @@
   private transient JavaScriptObject stringMap;
 
   {
-    clear();
+    clearImpl();
   }
 
   public HashMap() {
@@ -441,10 +423,7 @@
   }
 
   public void clear() {
-    hashCodeMap = createArray();
-    stringMap = createObject();
-    nullSlot = UNDEFINED;
-    size = 0;
+    clearImpl();
   }
 
   public Object clone() {
@@ -540,4 +519,11 @@
     return size;
   }
 
+  private void clearImpl() {
+    hashCodeMap = JavaScriptObject.createArray();
+    stringMap = JavaScriptObject.createObject();
+    nullSlot = UNDEFINED;
+    size = 0;
+  }
+
 }
diff --git a/user/super/com/google/gwt/emul/java/util/Vector.java b/user/super/com/google/gwt/emul/java/util/Vector.java
index 65234e6..d4015b5 100644
--- a/user/super/com/google/gwt/emul/java/util/Vector.java
+++ b/user/super/com/google/gwt/emul/java/util/Vector.java
@@ -18,7 +18,6 @@
 /**
  * To keep performance characteristics in line with Java community expectations, 
  * <code>Vector</code> is a wrapper around <code>ArrayList</code>.  
- *
  */
 public class Vector extends AbstractList implements List, RandomAccess,
     Cloneable {
diff --git a/user/test/com/google/gwt/emultest/java/util/ArrayListTest.java b/user/test/com/google/gwt/emultest/java/util/ArrayListTest.java
index 8672a86..524a143 100644
--- a/user/test/com/google/gwt/emultest/java/util/ArrayListTest.java
+++ b/user/test/com/google/gwt/emultest/java/util/ArrayListTest.java
@@ -16,17 +16,24 @@
 
 package com.google.gwt.emultest.java.util;
 
-import com.google.gwt.core.client.GWT;
-
 import org.apache.commons.collections.TestArrayList;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.ListIterator;
 
-/** Tests ArrayList, and, by extension AbstractList.  Uses inheritance to 
- * inherit all of Apache's TestList and TestCollection. */
+/**
+ * Tests ArrayList, and, by extension AbstractList. Uses inheritance to inherit
+ * all of Apache's TestList and TestCollection.
+ */
 public class ArrayListTest extends TestArrayList {
+
+  private static final class ArrayListWithRemoveRange extends ArrayList {
+    public void removeRange(int fromIndex, int toIndex) {
+      super.removeRange(fromIndex, toIndex);
+    }
+  }
+
   public ArrayListTest() {
   }
 
@@ -61,45 +68,45 @@
   public void testListIteratorCreateInvalid() {
     ArrayList l = new ArrayList();
     l.add(new Integer(1));
-    ListIterator i = l.listIterator(0);
+    l.listIterator(0);
     try {
-      i = l.listIterator(1);
+      l.listIterator(1);
     } catch (IndexOutOfBoundsException e) {
       // expected
     }
     try {
-      i = l.listIterator(-1);
+      l.listIterator(-1);
     } catch (IndexOutOfBoundsException e) {
       // expected
-    }    
+    }
   }
-  
+
   public void testListIteratorHasNextHasPreviousAndIndexes() {
     List l = new ArrayList();
     ListIterator i = l.listIterator();
     assertFalse(i.hasNext());
     assertFalse(i.hasPrevious());
     i.add(new Integer(1));
-    assertEquals(1,i.nextIndex());
+    assertEquals(1, i.nextIndex());
     assertEquals(0, i.previousIndex());
     i = l.listIterator();
-    assertEquals(0,i.nextIndex());
+    assertEquals(0, i.nextIndex());
     assertEquals(-1, i.previousIndex());
     assertTrue(i.hasNext());
     assertFalse(i.hasPrevious());
     i.next();
-    assertEquals(1,i.nextIndex());
+    assertEquals(1, i.nextIndex());
     assertEquals(0, i.previousIndex());
     assertFalse(i.hasNext());
-    assertTrue(i.hasPrevious());    
+    assertTrue(i.hasPrevious());
   }
-  
+
   public void testListIteratorSetInSeveralPositions() {
     ArrayList l = new ArrayList();
     for (int n = 0; n < 5; n += 2) {
       l.add(new Integer(n));
     }
-    ListIterator i = l.listIterator();
+    l.listIterator();
     for (int n = 0; n < 3; n++) {
       l.set(n, new Integer(n));
     }
@@ -107,44 +114,43 @@
       assertEquals(new Integer(n), l.get(n));
     }
   }
-  
+
   public void testRemoveRange() {
-    if (GWT.isScript()) {
-      ArrayList l = new ArrayList();
-      for (int i = 0; i < 10; i++) {
-        l.add(new Integer(i));
-      }
-      verifyRemoveRangeWorks(l);
+    ArrayListWithRemoveRange l = new ArrayListWithRemoveRange();
+    for (int i = 0; i < 10; i++) {
+      l.add(new Integer(i));
+    }
+    try {
+      l.removeRange(-1, 1);
+      fail();
+    } catch (IndexOutOfBoundsException expected) {
+    }
+    
+    try {
+      l.removeRange(2, 1);
+      fail();
+    } catch (IndexOutOfBoundsException expected) {
+    }
+
+    try {
+      l.removeRange(2, 11);
+      fail();
+    } catch (IndexOutOfBoundsException expected) {
+    }
+
+    l.removeRange(3, 5);
+    assertEquals(8, l.size());
+    for (int i = 0; i < 3; i++) {
+      Integer elem = (Integer) l.get(i);
+      assertEquals(i, elem.intValue());
+    }
+    for (int i = 3; i < 8; i++) {
+      Integer elem = (Integer) l.get(i);
+      assertEquals(i + 2, elem.intValue());
     }
   }
-  
+
   protected List makeEmptyList() {
     return new ArrayList();
   }
-
-  private native void verifyRemoveRangeWorks(ArrayList l) /*-{
-    var startIndex = l.@java.util.ArrayList::startIndex;
-    var endIndex = l.@java.util.ArrayList::endIndex;
-    var array = l.@java.util.ArrayList::array;
-    l.@java.util.ArrayList::removeRange(II)(0,2);
-    if (array[startIndex] !== undefined) {
-      @junit.framework.Assert::fail(Ljava/lang/String;)("startIndex should be empty");
-    }
-    if (array[startIndex + 1] !== undefined) {
-      @junit.framework.Assert::fail(Ljava/lang/String;)("startIndex + 1 should be empty");
-    }
-    if (array[startIndex + 2] === undefined) {
-      @junit.framework.Assert::fail(Ljava/lang/String;)("startIndex + 2 should not be empty");
-    }
-    l.@java.util.ArrayList::removeRange(II)(6,8);
-    if (array[endIndex - 3] === undefined) {
-      @junit.framework.Assert::fail(Ljava/lang/String;)("endIndex - 3 should not be empty");
-    }
-    if (array[endIndex - 2] !== undefined) {
-      @junit.framework.Assert::fail(Ljava/lang/String;)("endIndex - 2 should be empty");
-    }
-    if (array[endIndex - 1] !== undefined) {
-      @junit.framework.Assert::fail(Ljava/lang/String;)("endIndex - 1 should be empty");
-    }
-  }-*/;
 }