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 2019/11/30 16:23:42 UTC
[groovy] branch master updated: refactor and reorganize
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new ec85fac refactor and reorganize
ec85fac is described below
commit ec85facd66b0543fe79322cc8c50e68db8136cd9
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 30 10:10:34 2019 -0600
refactor and reorganize
---
.../groovy/classgen/VariableScopeVisitor.java | 518 ++++++++++-----------
1 file changed, 242 insertions(+), 276 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
index 8d4a738..531e5f6 100644
--- a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
@@ -50,6 +50,7 @@ import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.syntax.Types;
+import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
@@ -57,49 +58,51 @@ import static java.lang.reflect.Modifier.isFinal;
import static org.apache.groovy.ast.tools.MethodNodeUtils.getPropertyName;
/**
- * Goes through an AST and initializes the scopes.
+ * Initializes the variable scopes for an AST.
*/
public class VariableScopeVisitor extends ClassCodeVisitorSupport {
- private VariableScope currentScope = null;
- private final VariableScope headScope = new VariableScope();
- private ClassNode currentClass = null;
+ private ClassNode currentClass;
+ private VariableScope currentScope;
+ private boolean inConstructor, isSpecialConstructorCall;
+
private final SourceUnit source;
- private boolean isSpecialConstructorCall = false;
- private boolean inConstructor = false;
private final boolean recurseInnerClasses;
+ private final Deque<StateStackElement> stateStack = new LinkedList<>();
- private final LinkedList stateStack = new LinkedList();
-
- private class StateStackElement {
- final VariableScope scope;
+ private static class StateStackElement {
final ClassNode clazz;
+ final VariableScope scope;
final boolean inConstructor;
- StateStackElement() {
- scope = VariableScopeVisitor.this.currentScope;
- clazz = VariableScopeVisitor.this.currentClass;
- inConstructor = VariableScopeVisitor.this.inConstructor;
+ StateStackElement(final ClassNode currentClass, final VariableScope currentScope, final boolean inConstructor) {
+ clazz = currentClass;
+ scope = currentScope;
+ this.inConstructor = inConstructor;
}
}
public VariableScopeVisitor(SourceUnit source, boolean recurseInnerClasses) {
this.source = source;
- currentScope = headScope;
+ this.currentScope = new VariableScope();
this.recurseInnerClasses = recurseInnerClasses;
}
-
public VariableScopeVisitor(SourceUnit source) {
this(source, false);
}
+ @Override
+ protected SourceUnit getSourceUnit() {
+ return source;
+ }
+
// ------------------------------
// helper methods
//------------------------------
- private void pushState(boolean isStatic) {
- stateStack.add(new StateStackElement());
+ private void pushState(final boolean isStatic) {
+ stateStack.push(new StateStackElement(currentClass, currentScope, inConstructor));
currentScope = new VariableScope(currentScope);
currentScope.setInStaticContext(isStatic);
}
@@ -109,35 +112,26 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
}
private void popState() {
- StateStackElement element = (StateStackElement) stateStack.removeLast();
- currentScope = element.scope;
- currentClass = element.clazz;
- inConstructor = element.inConstructor;
+ StateStackElement state = stateStack.pop();
+ currentClass = state.clazz;
+ currentScope = state.scope;
+ inConstructor = state.inConstructor;
}
- private void declare(Parameter[] parameters, ASTNode node) {
- for (Parameter parameter : parameters) {
- if (parameter.hasInitialExpression()) {
- parameter.getInitialExpression().visit(this);
- }
- declare(parameter, node);
- }
- }
-
- private void declare(VariableExpression vex) {
- vex.setInStaticContext(currentScope.isInStaticContext());
- declare(vex, vex);
- vex.setAccessedVariable(vex);
+ private void declare(final VariableExpression variable) {
+ variable.setInStaticContext(currentScope.isInStaticContext());
+ declare(variable, variable);
+ variable.setAccessedVariable(variable);
}
- private void declare(Variable var, ASTNode expr) {
+ private void declare(final Variable variable, final ASTNode expression) {
String scopeType = "scope";
String variableType = "variable";
- if (expr.getClass() == FieldNode.class) {
+ if (expression.getClass() == FieldNode.class) {
scopeType = "class";
variableType = "field";
- } else if (expr.getClass() == PropertyNode.class) {
+ } else if (expression.getClass() == PropertyNode.class) {
scopeType = "class";
variableType = "property";
}
@@ -145,10 +139,10 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
StringBuilder msg = new StringBuilder();
msg.append("The current ").append(scopeType);
msg.append(" already contains a ").append(variableType);
- msg.append(" of the name ").append(var.getName());
+ msg.append(" of the name ").append(variable.getName());
- if (currentScope.getDeclaredVariable(var.getName()) != null) {
- addError(msg.toString(), expr);
+ if (currentScope.getDeclaredVariable(variable.getName()) != null) {
+ addError(msg.toString(), expression);
return;
}
@@ -158,34 +152,29 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
// to declare a variable of the same name as a class member
if (scope.getClassScope() != null && !isAnonymous(scope.getClassScope())) break;
- if (scope.getDeclaredVariable(var.getName()) != null) {
+ if (scope.getDeclaredVariable(variable.getName()) != null) {
// variable already declared
- addError(msg.toString(), expr);
+ addError(msg.toString(), expression);
break;
}
}
// declare the variable even if there was an error to allow more checks
- currentScope.putDeclaredVariable(var);
+ currentScope.putDeclaredVariable(variable);
}
- @Override
- protected SourceUnit getSourceUnit() {
- return source;
- }
-
- private Variable findClassMember(ClassNode cn, String name) {
+ private Variable findClassMember(final ClassNode cn, final String name) {
if (cn == null) return null;
+
if (cn.isScript()) {
return new DynamicVariable(name, false);
}
for (FieldNode fn : cn.getFields()) {
- if (fn.getName().equals(name)) return fn;
+ if (name.equals(fn.getName())) return fn;
}
for (MethodNode mn : cn.getMethods()) {
- String pName = getPropertyName(mn);
- if (name.equals(pName)) {
+ if (name.equals(getPropertyName(mn))) {
PropertyNode property = new PropertyNode(name, mn.getModifiers(), ClassHelper.OBJECT_TYPE, cn, null, null, null);
property.getField().setHasNoRealSourcePosition(true);
property.getField().setSynthetic(true);
@@ -205,15 +194,44 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
return findClassMember(cn.getOuterClass(), name);
}
- private static boolean isAnonymous(ClassNode node) {
+ private static boolean isAnonymous(final ClassNode node) {
return (!node.isEnum() && node instanceof InnerClassNode && ((InnerClassNode) node).isAnonymous());
}
+ private void markClosureSharedVariables() {
+ for (Iterator<Variable> it = currentScope.getReferencedLocalVariablesIterator(); it.hasNext(); ) {
+ Variable variable = it.next();
+ variable.setClosureSharedVariable(true);
+ }
+ }
+
// -------------------------------
- // different Variable based checks
+ // different Variable-based checks
// -------------------------------
- private Variable checkVariableNameForDeclaration(String name, Expression expression) {
+ private void checkFinalFieldAccess(final Expression expression) {
+ if (expression instanceof TupleExpression) {
+ TupleExpression tuple = (TupleExpression) expression;
+ for (Expression tupleExpression : tuple.getExpressions()) {
+ checkForFinal(expression, (VariableExpression) tupleExpression);
+ }
+ } else if (expression instanceof VariableExpression) {
+ checkForFinal(expression, (VariableExpression) expression);
+ }
+ // currently not looking for PropertyExpression: dealt with at runtime using ReadOnlyPropertyException
+ }
+
+ private void checkForFinal(final Expression context, final VariableExpression expression) {
+ Variable variable = expression.getAccessedVariable();
+ if (variable != null) {
+ if (isFinal(variable.getModifiers()) && variable instanceof Parameter) {
+ addError("Cannot assign a value to final variable '" + variable.getName() + "'", context);
+ }
+ // TODO: handle local variables
+ }
+ }
+
+ private Variable checkVariableNameForDeclaration(final String name, final Expression expression) {
if ("super".equals(name) || "this".equals(name)) return null;
VariableScope scope = currentScope;
@@ -222,7 +240,7 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
// try to find a declaration of a variable
boolean crossingStaticContext = false;
while (true) {
- crossingStaticContext = crossingStaticContext || scope.isInStaticContext();
+ crossingStaticContext = (crossingStaticContext || scope.isInStaticContext());
Variable var1 = scope.getDeclaredVariable(var.getName());
if (var1 != null) {
@@ -246,16 +264,14 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
if (classScope != null) {
Variable member = findClassMember(classScope, var.getName());
if (member != null) {
- boolean staticScope = crossingStaticContext || isSpecialConstructorCall;
- boolean staticMember = member.isInStaticContext();
- // We don't allow a static context (e.g. a static method) to access
- // a non-static variable (e.g. a non-static field).
- if (!(staticScope && !staticMember))
+ boolean staticScope = (crossingStaticContext || isSpecialConstructorCall), staticMember = member.isInStaticContext();
+ // prevent a static context (e.g. a static method) from accessing a non-static variable (e.g. a non-static field)
+ if (!(staticScope && !staticMember)) {
var = member;
+ }
}
// GROOVY-5961
- if (!isAnonymous(classScope))
- break;
+ if (!isAnonymous(classScope)) break;
}
scope = scope.getParent();
}
@@ -264,11 +280,9 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
}
VariableScope end = scope;
-
scope = currentScope;
while (scope != end) {
- if (end.isClassScope() ||
- (end.isReferencedClassVariable(name) && end.getDeclaredVariable(name) == null)) {
+ if (end.isClassScope() || (end.isReferencedClassVariable(name) && end.getDeclaredVariable(name) == null)) {
scope.putReferencedClassVariable(var);
} else {
scope.putReferencedLocalVariable(var);
@@ -280,141 +294,143 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
}
/**
- * a property on "this", like this.x is transformed to a
- * direct field access, so we need to check the
- * static context here
- *
- * @param pe the property expression to check
+ * A property on "this", like this.x is transformed to a direct field access,
+ * so we need to check the static context here.
*/
- private void checkPropertyOnExplicitThis(PropertyExpression pe) {
+ private void checkPropertyOnExplicitThis(final PropertyExpression expression) {
if (!currentScope.isInStaticContext()) return;
- Expression object = pe.getObjectExpression();
+ Expression object = expression.getObjectExpression();
if (!(object instanceof VariableExpression)) return;
VariableExpression ve = (VariableExpression) object;
if (!ve.getName().equals("this")) return;
- String name = pe.getPropertyAsString();
+ String name = expression.getPropertyAsString();
if (name == null || name.equals("class")) return;
Variable member = findClassMember(currentClass, name);
if (member == null) return;
- checkVariableContextAccess(member, pe);
+ checkVariableContextAccess(member, expression);
}
- private void checkVariableContextAccess(Variable v, Expression expr) {
- if (v.isInStaticContext() || !currentScope.isInStaticContext()) return;
+ private void checkVariableContextAccess(final Variable variable, final Expression expression) {
+ if (variable.isInStaticContext() || !currentScope.isInStaticContext()) return;
- String msg = v.getName() +
- " is declared in a dynamic context, but you tried to" +
- " access it from a static context.";
- addError(msg, expr);
+ addError(variable.getName() + " is declared in a dynamic context, but you tried to access it from a static context.", expression);
// declare a static variable to be able to continue the check
- DynamicVariable v2 = new DynamicVariable(v.getName(), currentScope.isInStaticContext());
- currentScope.putDeclaredVariable(v2);
+ currentScope.putDeclaredVariable(new DynamicVariable(variable.getName(), currentScope.isInStaticContext()));
}
- // ------------------------------
- // code visit
- // ------------------------------
+ //--------------------------------------------------------------------------
@Override
- public void visitBlockStatement(BlockStatement block) {
+ public void visitClass(final ClassNode node) {
+ // AIC are already done, doing them here again will lead to wrong scopes
+ if (isAnonymous(node)) return;
+
pushState();
- block.setVariableScope(currentScope);
- super.visitBlockStatement(block);
+ currentClass = node;
+ currentScope.setClassScope(node);
+
+ super.visitClass(node);
+ if (recurseInnerClasses) {
+ for (Iterator<InnerClassNode> innerClasses = node.getInnerClasses(); innerClasses.hasNext(); ) {
+ visitClass(innerClasses.next());
+ }
+ }
popState();
}
@Override
- public void visitForLoop(ForStatement forLoop) {
- pushState();
- forLoop.setVariableScope(currentScope);
- Parameter p = forLoop.getVariable();
- p.setInStaticContext(currentScope.isInStaticContext());
- if (p != ForStatement.FOR_LOOP_DUMMY) declare(p, forLoop);
- super.visitForLoop(forLoop);
+ public void visitField(final FieldNode node) {
+ pushState(node.isStatic());
+ super.visitField(node);
popState();
}
@Override
- public void visitIfElse(IfStatement ifElse) {
- ifElse.getBooleanExpression().visit(this);
- pushState();
- ifElse.getIfBlock().visit(this);
- popState();
- pushState();
- ifElse.getElseBlock().visit(this);
+ public void visitProperty(final PropertyNode node) {
+ pushState(node.isStatic());
+ super.visitProperty(node);
popState();
}
@Override
- public void visitDeclarationExpression(DeclarationExpression expression) {
- visitAnnotations(expression);
- // visit right side first to avoid the usage of a
- // variable before its declaration
- expression.getRightExpression().visit(this);
+ protected void visitConstructorOrMethod(final MethodNode node, final boolean isConstructor) {
+ pushState(node.isStatic());
+ inConstructor = isConstructor;
+ node.setVariableScope(currentScope);
- if (expression.isMultipleAssignmentDeclaration()) {
- TupleExpression list = expression.getTupleExpression();
- for (Expression e : list.getExpressions()) {
- declare((VariableExpression) e);
+ visitAnnotations(node);
+ for (Parameter parameter : node.getParameters()) {
+ visitAnnotations(parameter);
+ }
+ // add parameters to scope and visit init expressions after annotations
+ // to prevent the use of parameters in annotation attributes
+ for (Parameter parameter : node.getParameters()) {
+ if (parameter.hasInitialExpression()) {
+ parameter.getInitialExpression().visit(this);
}
- } else {
- declare(expression.getVariableExpression());
+ declare(parameter, node);
}
+ visitClassCodeContainer(node.getCode());
+
+ popState();
}
- @Override
- public void visitBinaryExpression(BinaryExpression be) {
- super.visitBinaryExpression(be);
+ // statements:
- if (Types.isAssignment(be.getOperation().getType())) {
- checkFinalFieldAccess(be.getLeftExpression());
- }
+ @Override
+ public void visitBlockStatement(final BlockStatement statement) {
+ pushState();
+ statement.setVariableScope(currentScope);
+ super.visitBlockStatement(statement);
+ popState();
}
- private void checkFinalFieldAccess(Expression expression) {
- // currently not looking for PropertyExpression: dealt with at runtime using ReadOnlyPropertyException
- if (!(expression instanceof VariableExpression) && !(expression instanceof TupleExpression)) return;
- if (expression instanceof TupleExpression) {
- TupleExpression list = (TupleExpression) expression;
- for (Expression e : list.getExpressions()) {
- checkForFinal(expression, (VariableExpression) e);
- }
- } else {
- checkForFinal(expression, (VariableExpression) expression);
- }
+ @Override
+ public void visitCatchStatement(final CatchStatement statement) {
+ pushState();
+ Parameter parameter = statement.getVariable();
+ parameter.setInStaticContext(currentScope.isInStaticContext());
+ declare(parameter, statement);
+ super.visitCatchStatement(statement);
+ popState();
}
- // TODO handle local variables
- private void checkForFinal(final Expression expression, VariableExpression ve) {
- Variable v = ve.getAccessedVariable();
- if (v != null) {
- boolean isFinal = isFinal(v.getModifiers());
- boolean isParameter = v instanceof Parameter;
- if (isFinal && isParameter) {
- addError("Cannot assign a value to final variable '" + v.getName() + "'", expression);
- }
- }
+ @Override
+ public void visitForLoop(final ForStatement statement) {
+ pushState();
+ statement.setVariableScope(currentScope);
+ Parameter parameter = statement.getVariable();
+ parameter.setInStaticContext(currentScope.isInStaticContext());
+ if (parameter != ForStatement.FOR_LOOP_DUMMY) declare(parameter, statement);
+ super.visitForLoop(statement);
+ popState();
}
@Override
- public void visitVariableExpression(VariableExpression expression) {
- String name = expression.getName();
- Variable v = checkVariableNameForDeclaration(name, expression);
- if (v == null) return;
- expression.setAccessedVariable(v);
- checkVariableContextAccess(v, expression);
+ public void visitIfElse(final IfStatement statement) {
+ statement.getBooleanExpression().visit(this);
+ pushState();
+ statement.getIfBlock().visit(this);
+ popState();
+ pushState();
+ statement.getElseBlock().visit(this);
+ popState();
}
+ // expressions:
+
@Override
- public void visitPropertyExpression(PropertyExpression expression) {
- expression.getObjectExpression().visit(this);
- expression.getProperty().visit(this);
- checkPropertyOnExplicitThis(expression);
+ public void visitBinaryExpression(final BinaryExpression expression) {
+ super.visitBinaryExpression(expression);
+
+ if (Types.isAssignment(expression.getOperation().getType())) {
+ checkFinalFieldAccess(expression.getLeftExpression());
+ }
}
@Override
- public void visitClosureExpression(ClosureExpression expression) {
+ public void visitClosureExpression(final ClosureExpression expression) {
pushState();
expression.setVariableScope(currentScope);
@@ -439,163 +455,113 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
popState();
}
- private void markClosureSharedVariables() {
- VariableScope scope = currentScope;
- for (Iterator<Variable> it = scope.getReferencedLocalVariablesIterator(); it.hasNext(); ) {
- it.next().setClosureSharedVariable(true);
- }
- }
-
- @Override
- public void visitCatchStatement(CatchStatement statement) {
- pushState();
- Parameter p = statement.getVariable();
- p.setInStaticContext(currentScope.isInStaticContext());
- declare(p, statement);
- super.visitCatchStatement(statement);
- popState();
- }
-
@Override
- public void visitFieldExpression(FieldExpression expression) {
- String name = expression.getFieldName();
- //TODO: change that to get the correct scope
- Variable v = checkVariableNameForDeclaration(name, expression);
- checkVariableContextAccess(v, expression);
- }
-
- // ------------------------------
- // class visit
- // ------------------------------
-
- @Override
- public void visitClass(ClassNode node) {
- // AIC are already done, doing them here again will lead to wrong scopes
- if (isAnonymous(node)) return;
+ public void visitConstructorCallExpression(final ConstructorCallExpression expression) {
+ isSpecialConstructorCall = expression.isSpecialCall();
+ super.visitConstructorCallExpression(expression);
+ isSpecialConstructorCall = false;
+ if (!expression.isUsingAnonymousInnerClass()) return;
pushState();
+ InnerClassNode innerClass = (InnerClassNode) expression.getType();
+ innerClass.setVariableScope(currentScope);
+ currentScope.setClassScope(innerClass);
+ currentScope.setInStaticContext(false);
+ for (MethodNode method : innerClass.getMethods()) {
+ Parameter[] parameters = method.getParameters();
+ if (parameters.length == 0) {
+ parameters = null; // null means no implicit "it"
+ }
+ visitClosureExpression(new ClosureExpression(parameters, method.getCode()));
+ }
- prepareVisit(node);
-
- super.visitClass(node);
- if (recurseInnerClasses) {
- Iterator<InnerClassNode> innerClasses = node.getInnerClasses();
- while (innerClasses.hasNext()) {
- visitClass(innerClasses.next());
+ for (FieldNode field : innerClass.getFields()) {
+ Expression initExpression = field.getInitialExpression();
+ pushState(field.isStatic());
+ if (initExpression != null) {
+ if (initExpression.isSynthetic() && initExpression instanceof VariableExpression
+ && ((VariableExpression) initExpression).getAccessedVariable() instanceof Parameter) {
+ // GROOVY-6834: accessing a parameter which is not yet seen in scope
+ popState();
+ continue;
+ }
+ initExpression.visit(this);
}
+ popState();
}
- popState();
- }
- /**
- * Sets the current class node context.
- */
- public void prepareVisit(ClassNode node) {
- currentClass = node;
- currentScope.setClassScope(node);
+ for (Statement initStatement : innerClass.getObjectInitializerStatements()) {
+ initStatement.visit(this);
+ }
+ markClosureSharedVariables();
+ popState();
}
@Override
- protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
- pushState(node.isStatic());
- inConstructor = isConstructor;
- node.setVariableScope(currentScope);
- visitAnnotations(node);
+ public void visitDeclarationExpression(final DeclarationExpression expression) {
+ visitAnnotations(expression);
+ // visit right side first to prevent the use of a variable before its declaration
+ expression.getRightExpression().visit(this);
- // GROOVY-2156
- Parameter[] parameters = node.getParameters();
- for (Parameter parameter : parameters) {
- visitAnnotations(parameter);
+ if (expression.isMultipleAssignmentDeclaration()) {
+ TupleExpression list = expression.getTupleExpression();
+ for (Expression listExpression : list.getExpressions()) {
+ declare((VariableExpression) listExpression);
+ }
+ } else {
+ declare(expression.getVariableExpression());
}
+ }
- declare(node.getParameters(), node);
- visitClassCodeContainer(node.getCode());
-
- popState();
+ @Override
+ public void visitFieldExpression(final FieldExpression expression) {
+ String name = expression.getFieldName();
+ //TODO: change that to get the correct scope
+ Variable variable = checkVariableNameForDeclaration(name, expression);
+ checkVariableContextAccess(variable, expression);
}
@Override
- public void visitMethodCallExpression(MethodCallExpression call) {
- if (call.isImplicitThis() && call.getMethod() instanceof ConstantExpression) {
- ConstantExpression methodNameConstant = (ConstantExpression) call.getMethod();
+ public void visitMethodCallExpression(final MethodCallExpression expression) {
+ if (expression.isImplicitThis() && expression.getMethod() instanceof ConstantExpression) {
+ ConstantExpression methodNameConstant = (ConstantExpression) expression.getMethod();
String methodName = methodNameConstant.getText();
if (methodName == null) {
throw new GroovyBugError("method name is null");
}
- Variable v = checkVariableNameForDeclaration(methodName, call);
- if (v != null && !(v instanceof DynamicVariable)) {
- checkVariableContextAccess(v, call);
+ Variable variable = checkVariableNameForDeclaration(methodName, expression);
+ if (variable != null && !(variable instanceof DynamicVariable)) {
+ checkVariableContextAccess(variable, expression);
}
- if (v instanceof VariableExpression || v instanceof Parameter) {
- VariableExpression object = new VariableExpression(v);
+ if (variable instanceof VariableExpression || variable instanceof Parameter) {
+ VariableExpression object = new VariableExpression(variable);
object.setSourcePosition(methodNameConstant);
- call.setObjectExpression(object);
+ expression.setObjectExpression(object);
ConstantExpression method = new ConstantExpression("call");
method.setSourcePosition(methodNameConstant); // important for GROOVY-4344
- call.setImplicitThis(false);
- call.setMethod(method);
- }
-
- }
- super.visitMethodCallExpression(call);
- }
-
- @Override
- public void visitConstructorCallExpression(ConstructorCallExpression call) {
- isSpecialConstructorCall = call.isSpecialCall();
- super.visitConstructorCallExpression(call);
- isSpecialConstructorCall = false;
- if (!call.isUsingAnonymousInnerClass()) return;
-
- pushState();
- InnerClassNode innerClass = (InnerClassNode) call.getType();
- innerClass.setVariableScope(currentScope);
- currentScope.setClassScope(innerClass);
- currentScope.setInStaticContext(false);
- for (MethodNode method : innerClass.getMethods()) {
- Parameter[] parameters = method.getParameters();
- if (parameters.length == 0)
- parameters = null; // null means no implicit "it"
- ClosureExpression cl = new ClosureExpression(parameters, method.getCode());
- visitClosureExpression(cl);
- }
-
- for (FieldNode field : innerClass.getFields()) {
- Expression expression = field.getInitialExpression();
- pushState(field.isStatic());
- if (expression != null) {
- if (expression.isSynthetic() && expression instanceof VariableExpression &&
- ((VariableExpression) expression).getAccessedVariable() instanceof Parameter) {
- // GROOVY-6834: accessing a parameter which is not yet seen in scope
- popState();
- continue;
- }
- expression.visit(this);
+ expression.setImplicitThis(false);
+ expression.setMethod(method);
}
- popState();
}
-
- for (Statement statement : innerClass.getObjectInitializerStatements()) {
- statement.visit(this);
- }
- markClosureSharedVariables();
- popState();
+ super.visitMethodCallExpression(expression);
}
@Override
- public void visitProperty(PropertyNode node) {
- pushState(node.isStatic());
- super.visitProperty(node);
- popState();
+ public void visitPropertyExpression(final PropertyExpression expression) {
+ expression.getObjectExpression().visit(this);
+ expression.getProperty().visit(this);
+ checkPropertyOnExplicitThis(expression);
}
@Override
- public void visitField(FieldNode node) {
- pushState(node.isStatic());
- super.visitField(node);
- popState();
+ public void visitVariableExpression(final VariableExpression expression) {
+ String name = expression.getName();
+ Variable variable = checkVariableNameForDeclaration(name, expression);
+ if (variable == null) return;
+ expression.setAccessedVariable(variable);
+ checkVariableContextAccess(variable, expression);
}
}