diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/basic/InnerClassTests.java b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/basic/InnerClassTests.java index d29c178baa..7e3d474130 100644 --- a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/basic/InnerClassTests.java +++ b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/basic/InnerClassTests.java @@ -2318,6 +2318,31 @@ public void testAccessOuterClassMemberFromInnerClassConstructor3() { runConformTest(sources, "ok"); } + @Test // GROOVY-11352 + public void testAccessOuterClassMemberFromInnerClassConstructor4() { + //@formatter:off + String[] sources = { + "Script.groovy", + "class Super {\n" + + " protected final String s\n" + + " Super(String s) { this.s = s }\n" + + "}\n" + + "class Outer {\n" + + " static String initValue() { 'ok' }\n" + + " static class Inner extends Super {\n" + + " Inner() {\n" + + " super(initValue())\n" + // here + " }\n" + + " }\n" + + " String test() { new Inner().s }\n" + + "}\n" + + "print new Outer().test()\n", + }; + //@formatter:on + + runConformTest(sources, "ok"); + } + @Test // GROOVY-9501 public void testAccessOuterClassMemberFromInnerClassMethod1() { //@formatter:off diff --git a/base/org.codehaus.groovy30/src/org/codehaus/groovy/classgen/Verifier.java b/base/org.codehaus.groovy30/src/org/codehaus/groovy/classgen/Verifier.java index 27f7b32ba2..2be982eb99 100644 --- a/base/org.codehaus.groovy30/src/org/codehaus/groovy/classgen/Verifier.java +++ b/base/org.codehaus.groovy30/src/org/codehaus/groovy/classgen/Verifier.java @@ -749,12 +749,17 @@ public void visitMapEntryExpression(MapEntryExpression mee) { @Override public void visitMethodCallExpression(MethodCallExpression mce) { if (inSpecialConstructorCall() && isThisObjectExpression(mce)) { - MethodNode methodTarget = mce.getMethodTarget(); - if (methodTarget == null || !(methodTarget.isStatic() || classNode.getOuterClasses().contains(methodTarget.getDeclaringClass()))) { - if (!mce.isImplicitThis()) { - throw newVariableError(mce.getObjectExpression().getText(), mce.getObjectExpression()); - } else { + boolean outerOrStaticMember = false; + if (mce.getMethodTarget() != null) { + outerOrStaticMember = mce.getMethodTarget().isStatic() || classNode.getOuterClasses().contains(mce.getMethodTarget().getDeclaringClass()); + } else if (mce.isImplicitThis()) { // GROOVY-11352 + outerOrStaticMember = classNode.getOuterClasses().stream().anyMatch(oc -> oc.hasPossibleStaticMethod(mce.getMethodAsString(), mce.getArguments())); + } + if (!outerOrStaticMember) { + if (mce.isImplicitThis()) { throw newVariableError(mce.getMethodAsString(), mce.getMethod()); + } else { + throw newVariableError(mce.getObjectExpression().getText(), mce.getObjectExpression()); } } nodes.push(mce); diff --git a/base/org.codehaus.groovy40/src/org/codehaus/groovy/classgen/Verifier.java b/base/org.codehaus.groovy40/src/org/codehaus/groovy/classgen/Verifier.java index b164e1d7e8..3acdc0cbc3 100644 --- a/base/org.codehaus.groovy40/src/org/codehaus/groovy/classgen/Verifier.java +++ b/base/org.codehaus.groovy40/src/org/codehaus/groovy/classgen/Verifier.java @@ -828,12 +828,17 @@ public void visitMapEntryExpression(MapEntryExpression mee) { @Override public void visitMethodCallExpression(MethodCallExpression mce) { if (inSpecialConstructorCall() && isThisObjectExpression(mce)) { - MethodNode methodTarget = mce.getMethodTarget(); - if (methodTarget == null || !(methodTarget.isStatic() || classNode.getOuterClasses().contains(methodTarget.getDeclaringClass()))) { - if (!mce.isImplicitThis()) { - throw newVariableError(mce.getObjectExpression().getText(), mce.getObjectExpression()); - } else { + boolean outerOrStaticMember = false; + if (mce.getMethodTarget() != null) { + outerOrStaticMember = mce.getMethodTarget().isStatic() || classNode.getOuterClasses().contains(mce.getMethodTarget().getDeclaringClass()); + } else if (mce.isImplicitThis()) { // GROOVY-11352 + outerOrStaticMember = classNode.getOuterClasses().stream().anyMatch(oc -> oc.hasPossibleStaticMethod(mce.getMethodAsString(), mce.getArguments())); + } + if (!outerOrStaticMember) { + if (mce.isImplicitThis()) { throw newVariableError(mce.getMethodAsString(), mce.getMethod()); + } else { + throw newVariableError(mce.getObjectExpression().getText(), mce.getObjectExpression()); } } nodes.push(mce); diff --git a/base/org.codehaus.groovy50/src/org/codehaus/groovy/classgen/Verifier.java b/base/org.codehaus.groovy50/src/org/codehaus/groovy/classgen/Verifier.java index 73f31bede7..c3fc8be0f1 100644 --- a/base/org.codehaus.groovy50/src/org/codehaus/groovy/classgen/Verifier.java +++ b/base/org.codehaus.groovy50/src/org/codehaus/groovy/classgen/Verifier.java @@ -805,12 +805,17 @@ public void visitMapEntryExpression(MapEntryExpression mee) { @Override public void visitMethodCallExpression(MethodCallExpression mce) { if (inSpecialConstructorCall() && isThisObjectExpression(mce)) { - MethodNode methodTarget = mce.getMethodTarget(); - if (methodTarget == null || !(methodTarget.isStatic() || classNode.getOuterClasses().contains(methodTarget.getDeclaringClass()))) { - if (!mce.isImplicitThis()) { - throw newVariableError(mce.getObjectExpression().getText(), mce.getObjectExpression()); - } else { + boolean outerOrStaticMember = false; + if (mce.getMethodTarget() != null) { + outerOrStaticMember = mce.getMethodTarget().isStatic() || classNode.getOuterClasses().contains(mce.getMethodTarget().getDeclaringClass()); + } else if (mce.isImplicitThis()) { // GROOVY-11352 + outerOrStaticMember = classNode.getOuterClasses().stream().anyMatch(oc -> oc.hasPossibleStaticMethod(mce.getMethodAsString(), mce.getArguments())); + } + if (!outerOrStaticMember) { + if (mce.isImplicitThis()) { throw newVariableError(mce.getMethodAsString(), mce.getMethod()); + } else { + throw newVariableError(mce.getObjectExpression().getText(), mce.getObjectExpression()); } } nodes.push(mce);