You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2020/07/09 23:32:43 UTC
[groovy] 01/02: GROOVY-9598: account for static modifier when
checking for outer members (port to 2_5_X)
This is an automated email from the ASF dual-hosted git repository.
paulk pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 65f16095ba6ceb08220cbbba4f3aeffcbbc0c33d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Jun 22 19:56:48 2020 -0500
GROOVY-9598: account for static modifier when checking for outer members (port to 2_5_X)
(cherry picked from commit a960547e9a560d5d7216912c5fe2e1ea7116d20e)
---
.../groovy/classgen/VariableScopeVisitor.java | 24 ++++++-----
src/test/gls/innerClass/InnerClassTest.groovy | 38 +++++++++++++++++
.../stc/FieldsAndPropertiesSTCTest.groovy | 47 ++++++++++++++++++++++
3 files changed, 100 insertions(+), 9 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
index a504b69..7c1b889 100644
--- a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
@@ -58,6 +58,7 @@ import java.util.List;
import java.util.Map;
import static java.lang.reflect.Modifier.isFinal;
+import static java.lang.reflect.Modifier.isStatic;
import static org.apache.groovy.ast.tools.MethodNodeUtils.getPropertyName;
/**
@@ -202,10 +203,12 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
if (pn.getName().equals(name)) return pn;
}
- Variable ret = findClassMember(cn.getSuperClass(), name);
- if (ret != null) return ret;
- if (isAnonymous(cn)) return null;
- return findClassMember(cn.getOuterClass(), name);
+ for (ClassNode face : cn.getInterfaces()) {
+ FieldNode fn = face.getDeclaredField(name);
+ if (fn != null) return fn;
+ }
+
+ return findClassMember(cn.getSuperClass(), name);
}
private static boolean isAnonymous(ClassNode node) {
@@ -245,9 +248,13 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
break;
}
- ClassNode classScope = scope.getClassScope();
- if (classScope != null) {
- Variable member = findClassMember(classScope, var.getName());
+ ClassNode node = scope.getClassScope();
+ if (node != null) {
+ Variable member = findClassMember(node, name);
+ while (member == null && node.getOuterClass() != null && !isAnonymous(node)) {
+ crossingStaticContext = (crossingStaticContext || isStatic(node.getModifiers()));
+ member = findClassMember((node = node.getOuterClass()), name);
+ }
if (member != null) {
boolean staticScope = crossingStaticContext || isSpecialConstructorCall;
boolean staticMember = member.isInStaticContext();
@@ -257,8 +264,7 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
var = member;
}
// GROOVY-5961
- if (!isAnonymous(classScope))
- break;
+ if (!isAnonymous(scope.getClassScope())) break;
}
scope = scope.getParent();
}
diff --git a/src/test/gls/innerClass/InnerClassTest.groovy b/src/test/gls/innerClass/InnerClassTest.groovy
index b6b5e8e..b09556f 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -558,6 +558,26 @@ final class InnerClassTest {
}
@Test
+ void testUsageOfOuterField12() {
+ def err = shouldFail '''
+ class C {
+ int count
+ static def m() {
+ new LinkedList() {
+ def get(int i) {
+ count += 1
+ super.get(i)
+ }
+ }
+ }
+ }
+ C.m()
+ '''
+
+ assert err =~ /Apparent variable 'count' was found in a static scope but doesn't refer to a local variable, static field or class./
+ }
+
+ @Test
void testUsageOfOuterSuperField() {
assertScript '''
class InnerBase {
@@ -593,6 +613,24 @@ final class InnerClassTest {
}
@Test
+ void testUsageOfOuterSuperField2() {
+ assertScript '''
+ interface I {
+ String CONST = 'value'
+ }
+ class A implements I {
+ static class B {
+ def test() {
+ CONST
+ }
+ }
+ }
+ def x = new A.B().test()
+ assert x == 'value'
+ '''
+ }
+
+ @Test
void testUsageOfOuterField_WrongCallToSuper() {
shouldFail '''
class Outer {
diff --git a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
index 2cf90b3..de9647e 100644
--- a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
+++ b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
@@ -387,6 +387,53 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
'''
}
+ void testOuterPropertyAccess1() {
+ assertScript '''
+ class Outer {
+ class Inner {
+ def m() {
+ p
+ }
+ }
+ def p = 1
+ }
+ def i = new Outer.Inner(new Outer())
+ def x = i.m()
+ assert x == 1
+ '''
+ }
+
+ // GROOVY-9598
+ void testOuterPropertyAccess2() {
+ shouldFailWithMessages '''
+ class Outer {
+ static class Inner {
+ def m() {
+ p
+ }
+ }
+ def p = 1
+ }
+ def i = new Outer.Inner()
+ def x = i.m()
+ ''', "Apparent variable 'p' was found in a static scope but doesn't refer to a local variable, static field or class."
+ }
+
+ void testOuterPropertyAccess3() {
+ shouldFailWithMessages '''
+ class Outer {
+ static class Inner {
+ def m() {
+ this.p
+ }
+ }
+ def p = 1
+ }
+ def i = new Outer.Inner()
+ def x = i.m()
+ ''', 'No such property: p for class: Outer$Inner'
+ }
+
void testPrivateFieldAccessInClosure() {
assertScript '''
class A {