You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2020/06/23 00:57:10 UTC
[groovy] 01/01: GROOVY-9598: account for static modifier when
checking for outer members
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY-9598
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 38d11b0e4733e49828a52e34ee017d777e860760
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
---
.../groovy/classgen/VariableScopeVisitor.java | 28 +++++--------
.../stc/FieldsAndPropertiesSTCTest.groovy | 47 ++++++++++++++++++++++
2 files changed, 58 insertions(+), 17 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
index 12edb39..5228987 100644
--- a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
@@ -56,6 +56,7 @@ import java.util.LinkedList;
import java.util.function.BiConsumer;
import static java.lang.reflect.Modifier.isFinal;
+import static java.lang.reflect.Modifier.isStatic;
import static org.apache.groovy.ast.tools.MethodNodeUtils.getPropertyName;
/**
@@ -191,10 +192,7 @@ 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);
+ return findClassMember(cn.getSuperClass(), name);
}
private Variable findVariableDeclaration(final String name) {
@@ -225,9 +223,13 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
break;
}
- ClassNode classScope = scope.getClassScope();
- if (classScope != null) {
- Variable member = findClassMember(classScope, name);
+ 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 || inSpecialConstructorCall), staticMember = member.isInStaticContext();
// prevent a static context (e.g. a static method) from accessing a non-static variable (e.g. a non-static field)
@@ -236,12 +238,12 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
}
}
// GROOVY-5961
- if (!isAnonymous(classScope)) break;
+ if (!isAnonymous(scope.getClassScope())) break;
}
scope = scope.getParent();
}
if (variable == null) {
- variable = new DynamicVariable(name, crossingStaticContext);
+ variable = new DynamicVariable(name, currentScope.isInStaticContext() || inSpecialConstructorCall);
}
boolean isClassVariable = (scope.isClassScope() && !scope.isReferencedLocalVariable(name))
@@ -460,14 +462,6 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
popState();
}
- /**
- * Sets the current class node context.
- */
- public void prepareVisit(ClassNode node) {
- currentClass = node;
- currentScope.setClassScope(node);
- }
-
@Override
public void visitConstructorCallExpression(final ConstructorCallExpression expression) {
boolean oldInSpecialCtorFlag = inSpecialConstructorCall;
diff --git a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
index 545cde5..5104ce9 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()
+ ''', 'The variable [p] is undeclared'
+ }
+
+ 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 {