Fixes compiler error for class extending an inner class.

Fixes an internal compiler error when a class extends an inner class whose enclosing class is of
generic type.

fixes ISSUE 7789

Change-Id: I0d1c5ababe332efad7b58b98b85a150b83d659f2
Review-Link: https://gwt-review.googlesource.com/#/c/1690/

Review by: mdempsky@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@11463 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
index 3ecdefb..9423eeb 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
@@ -2373,16 +2373,25 @@
       }
     }
 
+    // Only called on nested instances constructors (explicitConstructorCalls) that are of the
+    // form: outer.super(...) or super(...)
+    //
+    // Will set outer (in the first case) or the implicit enclosing object reference to
+    // be the first parameter of super(...)
     private void processSuperCallThisArgs(ReferenceBinding superClass, JMethodCall call,
         JExpression qualifier, Expression qualification) {
+      // Explicit super calls can only happend inside constructors
+      assert curMethod.scope.isInsideConstructor();
       if (superClass.syntheticEnclosingInstanceTypes() != null) {
-        for (ReferenceBinding targetType : superClass.syntheticEnclosingInstanceTypes()) {
-          if (qualification != null && superClass.enclosingType() == targetType) {
-            assert qualification.resolvedType.erasure().isCompatibleWith(targetType);
-            call.addArg(qualifier);
-          } else {
-            call.addArg(makeThisReference(call.getSourceInfo(), targetType, false, curMethod.scope));
-          }
+        // there can only be ONE immediate enclosing instance.
+        assert superClass.syntheticEnclosingInstanceTypes().length == 1;
+        ReferenceBinding targetType = superClass.syntheticEnclosingInstanceTypes()[0];
+        if (qualification != null) {
+          // Outer object is the qualifier.
+          call.addArg(qualifier);
+        } else {
+          // Get implicit outer object.
+          call.addArg(makeThisReference(call.getSourceInfo(), targetType, false, curMethod.scope));
         }
       }
     }
diff --git a/user/test/com/google/gwt/dev/jjs/test/InnerClassTest.java b/user/test/com/google/gwt/dev/jjs/test/InnerClassTest.java
index 072974a..9b8e651 100644
--- a/user/test/com/google/gwt/dev/jjs/test/InnerClassTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/InnerClassTest.java
@@ -111,12 +111,90 @@
     }
   }
 
+
+  /**
+   * Used in test {@link #testExtendsNested()}
+   */
+  private static class ESOuter {
+    class ESInner {
+      public int value;
+      public ESInner() {
+        value = 1;
+      }
+      public ESInner(int value) {
+        this.value = value;
+      }
+    }
+
+    public ESInner newESInner() {
+      return new ESInner();
+    }
+  }
+
+  private static class ESInnerSubclass extends ESOuter.ESInner {
+    ESInnerSubclass(ESOuter outer) {
+      outer.super();
+    }
+
+    ESInnerSubclass(int value, ESOuter outer) {
+      outer.super(value);
+    }
+  }
+
+  /**
+   * Used in test {@link #testExtendsNestedWithGenerics()}
+   */
+  private static class ESWGOuter<T> {
+    class ESWGInner {
+      public int value;
+      public ESWGInner() {
+        value = 1;
+      }
+      public ESWGInner(int value) {
+        this.value = value;
+      }
+    }
+
+    public ESWGInner newESWGInner() {
+      return new ESWGInner();
+    }
+  }
+
+  private static class ESWGInnerSubclass extends ESWGOuter<String>.ESWGInner {
+    ESWGInnerSubclass(ESWGOuter<String> outer) {
+      outer.super();
+    }
+
+    ESWGInnerSubclass(int value, ESWGOuter<String> outer) {
+      outer.super(value);
+    }
+  }
+
   private StringBuffer testAppend = new StringBuffer();
 
   public String getModuleName() {
     return "com.google.gwt.dev.jjs.CompilerSuite";
   }
 
+  public void testExtendsNested() {
+    ESOuter o = new ESOuter();
+    assertEquals(1, o.new ESInner().value);
+    assertEquals(2, o.new ESInner(2).value);
+    assertEquals(1, new ESInnerSubclass(o).value);
+    assertEquals(2, new ESInnerSubclass(2, o).value);
+  }
+
+  /**
+   * Test for Issue 7789
+   */
+  public void testExtendsNestedWithGenerics() {
+    ESWGOuter<String> o = new ESWGOuter<String>();
+    assertEquals(1, o.new ESWGInner().value);
+    assertEquals(2, o.new ESWGInner(2).value);
+    assertEquals(1, new ESWGInnerSubclass(o).value);
+    assertEquals(2, new ESWGInnerSubclass(2, o).value);
+  }
+
   public void testInnerClassCtors() {
     P1<?> p1 = new P1<Object>();
     assertEquals(1, p1.value);