1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package org.codehaus.groovy.classgen;
47
48 import java.util.Set;
49
50 import org.codehaus.groovy.ast.CodeVisitorSupport;
51 import org.codehaus.groovy.ast.Parameter;
52 import org.codehaus.groovy.ast.VariableScope;
53 import org.codehaus.groovy.ast.expr.BinaryExpression;
54 import org.codehaus.groovy.ast.expr.ClosureExpression;
55 import org.codehaus.groovy.ast.expr.Expression;
56 import org.codehaus.groovy.ast.expr.MethodCallExpression;
57 import org.codehaus.groovy.ast.expr.PostfixExpression;
58 import org.codehaus.groovy.ast.expr.PrefixExpression;
59 import org.codehaus.groovy.ast.expr.VariableExpression;
60 import org.codehaus.groovy.ast.stmt.ForStatement;
61
62 import org.codehaus.groovy.syntax.Types;
63
64 /***
65 * A visitor which figures out which variables are in scope
66 *
67 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
68 * @version $Revision: 1.12 $
69 */
70 public class VariableScopeCodeVisitor extends CodeVisitorSupport {
71
72 private VariableScope scope;
73
74 public VariableScopeCodeVisitor(VariableScope scope) {
75 this.scope = scope;
76 }
77
78 public Set getReferencedVariables() {
79 return scope.getReferencedVariables();
80 }
81
82 public Set getDeclaredVariables() {
83 return scope.getDeclaredVariables();
84 }
85
86
87
88 public void visitBinaryExpression(BinaryExpression expression) {
89 Expression leftExpression = expression.getLeftExpression();
90 if (expression.getOperation().isA(Types.ASSIGNMENT_OPERATOR) && leftExpression instanceof VariableExpression) {
91 declareVariable((VariableExpression) leftExpression);
92 }
93 else {
94 leftExpression.visit(this);
95 }
96 expression.getRightExpression().visit(this);
97 }
98
99 public void visitForLoop(ForStatement forLoop) {
100 declareVariable(forLoop.getVariable());
101
102 super.visitForLoop(forLoop);
103 }
104
105 public void visitClosureExpression(ClosureExpression expression) {
106 VariableScopeCodeVisitor visitor = createClosureVisitor(expression);
107 expression.getCode().visit(visitor);
108 }
109
110 public void visitVariableExpression(VariableExpression expression) {
111
112 String variable = expression.getName();
113
114
115
116
117
118 getReferencedVariables().add(variable);
119 }
120
121
122 public void visitPostfixExpression(PostfixExpression expression) {
123 Expression exp = expression.getExpression();
124 if (exp instanceof VariableExpression) {
125 declareVariable((VariableExpression) exp);
126 }
127 else {
128 exp.visit(this);
129 }
130 }
131
132 public void visitPrefixExpression(PrefixExpression expression) {
133 Expression exp = expression.getExpression();
134 if (exp instanceof VariableExpression) {
135 declareVariable((VariableExpression) exp);
136 }
137 else {
138 exp.visit(this);
139 }
140 }
141
142 public void visitMethodCallExpression(MethodCallExpression call) {
143 if (call.isImplicitThis()) {
144 getReferencedVariables().add(call.getMethod());
145 }
146 super.visitMethodCallExpression(call);
147 }
148
149 public void setParameters(Parameter[] parameters) {
150
151
152
153
154
155
156
157 for (int i = 0; i < parameters.length; i++) {
158 declareVariable(parameters[i].getName());
159 }
160 }
161
162 protected void declareVariable(VariableExpression varExp) {
163 String variable = varExp.getName();
164 declareVariable(variable);
165 }
166
167 protected void declareVariable(String variable) {
168
169
170
171
172
173
174 getDeclaredVariables().add(variable);
175 getReferencedVariables().add(variable);
176 }
177
178 protected VariableScopeCodeVisitor createClosureVisitor(ClosureExpression expression) {
179 VariableScope closureScope = new VariableScope(scope);
180 expression.setVariableScope(closureScope);
181 VariableScopeCodeVisitor answer = new VariableScopeCodeVisitor(closureScope);
182 answer.setParameters(expression.getParameters());
183 return answer;
184 }
185 }