Skip to content

Commit

Permalink
ECJ writes incorrect enclosing method for doubly-nested anonymous cla…
Browse files Browse the repository at this point in the history
…ss (#1906)

* Do not traverse past enclosing type declaration to compute enclosing
method

* Fixes #1905
  • Loading branch information
srikanth-sankaran authored Jan 25, 2024
1 parent a2da032 commit 856cefa
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1735,6 +1735,24 @@ public TypeDeclaration referenceType() {
return this.referenceContext;
}

public final MethodBinding enclosingMethod() {
Scope scope = this;
while ((scope = scope.parent) != null) {
if (scope instanceof MethodScope) {
MethodScope methodScope = (MethodScope) scope;
/* 4.7.7 The EnclosingMethod Attribute: ... In particular, method_index must be zero if the current class
* was immediately enclosed in source code by an instance initializer, static initializer, instance variable initializer, or
* class variable initializer....
*/
if (methodScope.referenceContext instanceof TypeDeclaration)
return null;
if (methodScope.referenceContext instanceof AbstractMethodDeclaration)
return ((MethodScope) scope).referenceMethodBinding();
}
}
return null; // may answer null if no method around
}

@Override
public boolean hasDefaultNullnessFor(int location, int sourceStart) {
int nonNullByDefaultValue = localNonNullByDefaultValue(sourceStart);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ public LocalTypeBinding(ClassScope scope, SourceTypeBinding enclosingType, CaseS
}
this.enclosingCase = switchCase;
this.sourceStart = typeDeclaration.sourceStart;
MethodScope methodScope = scope.lexicallyEnclosingMethodScope();
MethodBinding methodBinding = methodScope != null ? methodScope.referenceMethodBinding() : null;
MethodBinding methodBinding = scope.enclosingMethod();
if (methodBinding != null) {
this.enclosingMethod = methodBinding;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1160,18 +1160,6 @@ public final MethodScope enclosingMethodScope() {
return null; // may answer null if no method around
}

public final MethodScope lexicallyEnclosingMethodScope() {
Scope scope = this;
while ((scope = scope.parent) != null) {
if (scope instanceof MethodScope) {
MethodScope methodScope = (MethodScope) scope;
if (methodScope.referenceContext instanceof AbstractMethodDeclaration)
return (MethodScope) scope;
}
}
return null; // may answer null if no method around
}

public final MethodScope enclosingLambdaScope() {
Scope scope = this;
while ((scope = scope.parent) != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
Expand Down Expand Up @@ -257,4 +258,34 @@ public void test004() throws Exception {
ReferenceBinding binaryType = batchCompiler.lookupEnvironment.askForType(new char[][] {new char[0], "X$1".toCharArray()}, batchCompiler.lookupEnvironment.UnNamedModule);
assertNotNull("Should not be null", binaryType);
}

// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/1905
// ECJ writes incorrect enclosing method for doubly-nested anonymous class
public void testGH1905() throws Exception {
if (this.complianceLevel < ClassFileConstants.JDK10)
return;

this.runConformTest(
new String[] {
"X.java",
"""
public class X {
static Object o = new Object () {};
public static void main(String[] args) {
var outer = new Object() {
Object inner = new Object() {
//
};
};
System.out.println(o.getClass().getEnclosingMethod());
System.out.println(outer.getClass().getEnclosingMethod());
System.out.println(outer.inner.getClass().getEnclosingMethod());
}
}
"""
},
"null\n" +
"public static void X.main(java.lang.String[])\n" +
"null");
}
}

0 comments on commit 856cefa

Please sign in to comment.