Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeigo Imai2013-05-16 07:53:54 +0000
committerJayaprakash Arthanareeswaran2013-05-16 10:59:10 +0000
commita4f4cf398b9c048885f33786fe40b8704243b93a (patch)
tree76d2f4445ce36cd85b34db8954759c821b819087
parentf9a29367ea8f3c4c9489072b937e0b301d28ae36 (diff)
downloadeclipse.jdt.core-a4f4cf398b9c048885f33786fe40b8704243b93a.tar.gz
eclipse.jdt.core-a4f4cf398b9c048885f33786fe40b8704243b93a.tar.xz
eclipse.jdt.core-a4f4cf398b9c048885f33786fe40b8704243b93a.zip
[388903] Cannot extend inner class as an anonymous class when it extends
the outer class Thanks, Keigo!
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerEmulationTest.java49
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java10
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java38
4 files changed, 88 insertions, 12 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerEmulationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerEmulationTest.java
index bbb9c35a56..b177c9c467 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerEmulationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerEmulationTest.java
@@ -13,6 +13,8 @@
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contribution for
* Bug 388800 - [1.8] adjust tests to 1.8 JRE
+ * Keigo Imai - Contribution for bug 388903 - Cannot extend inner class as an anonymous class when it extends the outer class
+>>>>>>> 11dd8a9 [388903] Cannot extend inner class as an anonymous class when it extends the outer class
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -6899,6 +6901,53 @@ public void test174() throws Exception {
},
"SUCCESS");
}
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=388903
+public void test175() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",//=======================
+ "public class X {\n" +
+ " class Inner extends X {\n" +
+ " }\n" +
+ " public static void main(String[] args) {\n" +
+ " new X().new Inner(){};\n" +
+ " System.out.println(\"SUCCESS\");\n" +
+ " }\n" +
+ "}",
+ },
+ "SUCCESS");
+ this.runConformTest(
+ new String[] {
+ "X.java",//=======================
+ "public class X {\n" +
+ " String which;\n" +
+ " X(String s) {\n" +
+ " this.which = s;\n" +
+ " }\n" +
+ " class Inner extends X {\n" +
+ " Inner() {\n" +
+ " super(\"Inner\");\n" +
+ " System.out.print( X.this.which + \",\" ); // will output 'Enclosing,'\n" +
+ " }\n" +
+ " }\n" +
+ " void check() {\n" +
+ " new X(\"Enclosing\").new Inner() {\n" +
+ " {\n" +
+ " System.out.print( X.this.which + \",\" ); // will output 'Context,'\n" +
+ " }\n" +
+ " void f() {\n" +
+ " System.out.println( X.this.which ); // will output 'Context'\n" +
+ " }\n" +
+ " }.f();\n" +
+ " }\n" +
+ " public static void main(String[] args) {\n" +
+ " new X(\"Context\").check();\n" +
+ " }\n" +
+ "}",
+ },
+ "Enclosing,Context,Context");
+}
+
public static Class testClass() {
return InnerEmulationTest.class;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
index 34ae4bfce5..b1aa52695e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
@@ -14,6 +14,7 @@
* Stephan Herrmann - Contributions for
* Bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
* Bug 388630 - @NonNull diagnostics at line 0
+ * Keigo Imai - Contribution for bug 388903 - Cannot extend inner class as an anonymous class when it extends the outer class
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -796,7 +797,7 @@ public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, Fl
if (enclosing.isNestedType()) {
NestedTypeBinding nestedEnclosing = (NestedTypeBinding)enclosing;
// if (nestedEnclosing.findSuperTypeErasingTo(nestedEnclosing.enclosingType()) == null) { // only if not inheriting
- SyntheticArgumentBinding syntheticEnclosingInstanceArgument = nestedEnclosing.getSyntheticArgument(nestedEnclosing.enclosingType(), true);
+ SyntheticArgumentBinding syntheticEnclosingInstanceArgument = nestedEnclosing.getSyntheticArgument(nestedEnclosing.enclosingType(), true, false);
if (syntheticEnclosingInstanceArgument != null) {
nestedType.addSyntheticArgumentAndField(syntheticEnclosingInstanceArgument);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
index e80e2533c9..83bed12349 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
@@ -23,6 +23,7 @@
* bug 404649 - [1.8][compiler] detect illegal reference to indirect or redundant super
* Jesper S Moller <jesper@selskabet.org> - Contributions for
* bug 378674 - "The method can be declared as static" is wrong
+ * Keigo Imai - Contribution for bug 388903 - Cannot extend inner class as an anonymous class when it extends the outer class
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -809,10 +810,13 @@ public Object[] getEmulationPath(ReferenceBinding targetEnclosingType, boolean o
// use synthetic constructor arguments if possible
if (insideConstructor) {
SyntheticArgumentBinding syntheticArg;
- if ((syntheticArg = ((NestedTypeBinding) sourceType).getSyntheticArgument(targetEnclosingType, onlyExactMatch)) != null) {
+ if ((syntheticArg = ((NestedTypeBinding) sourceType).getSyntheticArgument(targetEnclosingType, onlyExactMatch, currentMethodScope.isConstructorCall)) != null) {
+ boolean isAnonymousAndHasEnclosing = sourceType.isAnonymousType()
+ && sourceType.scope.referenceContext.allocation.enclosingInstance != null;
// reject allocation and super constructor call
if (denyEnclosingArgInConstructorCall
&& currentMethodScope.isConstructorCall
+ && !isAnonymousAndHasEnclosing
&& (sourceType == targetEnclosingType || (!onlyExactMatch && sourceType.findSuperTypeOriginatingFrom(targetEnclosingType) != null))) {
return BlockScope.NoEnclosingInstanceInConstructorCall;
}
@@ -828,7 +832,7 @@ public Object[] getEmulationPath(ReferenceBinding targetEnclosingType, boolean o
ReferenceBinding enclosingType = sourceType.enclosingType();
if (enclosingType.isNestedType()) {
NestedTypeBinding nestedEnclosingType = (NestedTypeBinding) enclosingType;
- SyntheticArgumentBinding enclosingArgument = nestedEnclosingType.getSyntheticArgument(nestedEnclosingType.enclosingType(), onlyExactMatch);
+ SyntheticArgumentBinding enclosingArgument = nestedEnclosingType.getSyntheticArgument(nestedEnclosingType.enclosingType(), onlyExactMatch, currentMethodScope.isConstructorCall);
if (enclosingArgument != null) {
FieldBinding syntheticField = sourceType.getSyntheticField(enclosingArgument);
if (syntheticField != null) {
@@ -850,7 +854,7 @@ public Object[] getEmulationPath(ReferenceBinding targetEnclosingType, boolean o
Object[] path = new Object[2]; // probably at least 2 of them
ReferenceBinding currentType = sourceType.enclosingType();
if (insideConstructor) {
- path[0] = ((NestedTypeBinding) sourceType).getSyntheticArgument(currentType, onlyExactMatch);
+ path[0] = ((NestedTypeBinding) sourceType).getSyntheticArgument(currentType, onlyExactMatch, currentMethodScope.isConstructorCall);
} else {
if (currentMethodScope.isConstructorCall){
return BlockScope.NoEnclosingInstanceInConstructorCall;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
index af25174cfa..d101e138a5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contribution for bug 365662 - [compiler][null] warn on contradictory and redundant null annotations
+ * Keigo Imai - Contribution for bug 388903 - Cannot extend inner class as an anonymous class when it extends the outer class
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -70,12 +71,13 @@ public SyntheticArgumentBinding addSyntheticArgument(ReferenceBinding targetEncl
} else {
int size = this.enclosingInstances.length;
int newArgIndex = size;
- for (int i = size; --i >= 0;) {
- if (this.enclosingInstances[i].type == targetEnclosingType)
- return this.enclosingInstances[i]; // already exists
- if (enclosingType() == targetEnclosingType)
- newArgIndex = 0;
- }
+ if (enclosingType() == targetEnclosingType)
+ newArgIndex = 0;
+ // do not cache things! there can be two instances of same type!
+ // for (int i = size; --i >= 0;) {
+ //if (this.enclosingInstances[i].type == targetEnclosingType)
+ // return this.enclosingInstances[i]; // already exists
+ // }
SyntheticArgumentBinding[] newInstances = new SyntheticArgumentBinding[size + 1];
System.arraycopy(this.enclosingInstances, 0, newInstances, newArgIndex == 0 ? 1 : 0, size);
newInstances[newArgIndex] = synthLocal = new SyntheticArgumentBinding(targetEnclosingType);
@@ -170,9 +172,29 @@ public SyntheticArgumentBinding getSyntheticArgument(LocalVariableBinding actual
/* Answer the synthetic argument for <targetEnclosingType> or null if one does not exist.
*/
-public SyntheticArgumentBinding getSyntheticArgument(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
+/* Answer the synthetic argument for <targetEnclosingType> or null if one does not exist.
+*/
+public SyntheticArgumentBinding getSyntheticArgument(ReferenceBinding targetEnclosingType, boolean onlyExactMatch, boolean scopeIsConstructorCall) {
if (this.enclosingInstances == null) return null; // is null if no enclosing instances are known
+
// exact match
+
+ // firstly, during allocation, check and use the leftmost one (if possible)
+ // to handle cases involving two instances of same type, such as
+ // class X {
+ // class Inner extends X {}
+ // void f(){
+ // new X().new Inner(){}
+ // // here the result of (new X()) is passed as the first (synthetic) arg for ctor of new Inner(){}
+ // // (and (this) as the second, of course)
+ // }
+ // }
+ if (scopeIsConstructorCall && this.enclosingInstances.length > 0)
+ if (this.enclosingInstances[0].type == targetEnclosingType)
+ if (this.enclosingInstances[0].actualOuterLocalVariable == null)
+ return this.enclosingInstances[0];
+
+ // then check other possibility
for (int i = this.enclosingInstances.length; --i >= 0;)
if (this.enclosingInstances[i].type == targetEnclosingType)
if (this.enclosingInstances[i].actualOuterLocalVariable == null)

Back to the top