1
2
3
4 package net.sourceforge.pmd.lang.java.symboltable;
5
6 import java.util.Stack;
7
8 import net.sourceforge.pmd.lang.ast.Node;
9 import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration;
10 import net.sourceforge.pmd.lang.java.ast.ASTBlock;
11 import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement;
12 import net.sourceforge.pmd.lang.java.ast.ASTCatchStatement;
13 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration;
14 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
15 import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
16 import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
17 import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration;
18 import net.sourceforge.pmd.lang.java.ast.ASTFinallyStatement;
19 import net.sourceforge.pmd.lang.java.ast.ASTForStatement;
20 import net.sourceforge.pmd.lang.java.ast.ASTFormalParameters;
21 import net.sourceforge.pmd.lang.java.ast.ASTIfStatement;
22 import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
23 import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator;
24 import net.sourceforge.pmd.lang.java.ast.ASTPackageDeclaration;
25 import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement;
26 import net.sourceforge.pmd.lang.java.ast.ASTTryStatement;
27 import net.sourceforge.pmd.lang.java.ast.ASTTypeParameters;
28 import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
29 import net.sourceforge.pmd.lang.java.ast.AbstractJavaNode;
30 import net.sourceforge.pmd.lang.java.ast.JavaNode;
31 import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter;
32
33
34
35
36
37
38
39
40
41
42
43
44
45 public class ScopeAndDeclarationFinder extends JavaParserVisitorAdapter {
46
47
48
49
50
51 private Stack<Scope> scopes = new Stack<Scope>();
52
53
54
55
56
57
58
59
60
61
62 private void addScope(Scope newScope, JavaNode node) {
63 newScope.setParent(scopes.peek());
64 scopes.push(newScope);
65 node.setScope(newScope);
66 }
67
68
69
70
71
72
73
74
75
76 private void createLocalScope(JavaNode node) {
77 addScope(new LocalScope(), node);
78 }
79
80
81
82
83
84
85
86
87
88 private void createMethodScope(JavaNode node) {
89 addScope(new MethodScope(node), node);
90 }
91
92
93
94
95
96
97
98
99
100 private void createClassScope(JavaNode node) {
101 if (node instanceof ASTClassOrInterfaceBodyDeclaration) {
102 addScope(new ClassScope(), node);
103 } else {
104 addScope(new ClassScope(node.getImage()), node);
105 }
106 }
107
108
109
110
111
112
113
114 private void createSourceFileScope(ASTCompilationUnit node) {
115
116 Scope scope;
117 ASTPackageDeclaration n = node.getPackageDeclaration();
118 if (n != null) {
119 scope = new SourceFileScope(n.jjtGetChild(0).getImage());
120 } else {
121 scope = new SourceFileScope();
122 }
123 scopes.push(scope);
124 node.setScope(scope);
125 }
126
127 @Override
128 public Object visit(ASTCompilationUnit node, Object data) {
129 createSourceFileScope(node);
130 cont(node);
131 return data;
132 }
133
134 @Override
135 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
136 createClassScope(node);
137 Scope s = ((JavaNode)node.jjtGetParent()).getScope();
138 s.addDeclaration(new ClassNameDeclaration(node));
139 cont(node);
140 return data;
141 }
142
143 @Override
144 public Object visit(ASTEnumDeclaration node, Object data) {
145 createClassScope(node);
146 cont(node);
147 return data;
148 }
149
150 @Override
151 public Object visit(ASTAnnotationTypeDeclaration node, Object data) {
152 createClassScope(node);
153 cont(node);
154 return data;
155 }
156
157 @Override
158 public Object visit(ASTClassOrInterfaceBodyDeclaration node, Object data) {
159 if (node.isAnonymousInnerClass() || node.isEnumChild()) {
160 createClassScope(node);
161 cont(node);
162 } else {
163 super.visit(node, data);
164 }
165 return data;
166 }
167
168 @Override
169 public Object visit(ASTBlock node, Object data) {
170 createLocalScope(node);
171 cont(node);
172 return data;
173 }
174
175 @Override
176 public Object visit(ASTCatchStatement node, Object data) {
177 createLocalScope(node);
178 cont(node);
179 return data;
180 }
181
182 @Override
183 public Object visit(ASTFinallyStatement node, Object data) {
184 createLocalScope(node);
185 cont(node);
186 return data;
187 }
188
189 @Override
190 public Object visit(ASTConstructorDeclaration node, Object data) {
191
192
193
194
195 createMethodScope(node);
196
197 Scope methodScope = node.getScope();
198
199 Node formalParameters = node.jjtGetChild(0);
200 int i = 1;
201 int n = node.jjtGetNumChildren();
202 if (!(formalParameters instanceof ASTFormalParameters)) {
203 visit((ASTTypeParameters) formalParameters, data);
204 formalParameters = node.jjtGetChild(1);
205 i++;
206 }
207 visit((ASTFormalParameters) formalParameters, data);
208
209 Scope localScope = null;
210 for (; i < n; i++) {
211 JavaNode b = (JavaNode) node.jjtGetChild(i);
212 if (b instanceof ASTBlockStatement) {
213 if (localScope == null) {
214 createLocalScope(node);
215 localScope = node.getScope();
216 }
217 b.setScope(localScope);
218 visit(b, data);
219 } else {
220 visit(b, data);
221 }
222 }
223 if (localScope != null) {
224
225 scopes.pop();
226
227
228 node.setScope(methodScope);
229 }
230
231 scopes.pop();
232
233 return data;
234 }
235
236 @Override
237 public Object visit(ASTMethodDeclaration node, Object data) {
238 createMethodScope(node);
239 ASTMethodDeclarator md = node.getFirstChildOfType(ASTMethodDeclarator.class);
240 node.getScope().getEnclosingClassScope().addDeclaration(new MethodNameDeclaration(md));
241 cont(node);
242 return data;
243 }
244
245 @Override
246 public Object visit(ASTTryStatement node, Object data) {
247 createLocalScope(node);
248 cont(node);
249 return data;
250 }
251
252
253 @Override
254 public Object visit(ASTForStatement node, Object data) {
255 createLocalScope(node);
256 cont(node);
257 return data;
258 }
259
260 @Override
261 public Object visit(ASTIfStatement node, Object data) {
262 createLocalScope(node);
263 cont(node);
264 return data;
265 }
266
267 @Override
268 public Object visit(ASTVariableDeclaratorId node, Object data) {
269 VariableNameDeclaration decl = new VariableNameDeclaration(node);
270 node.getScope().addDeclaration(decl);
271 node.setNameDeclaration(decl);
272 return super.visit(node, data);
273 }
274
275 @Override
276 public Object visit(ASTSwitchStatement node, Object data) {
277 createLocalScope(node);
278 cont(node);
279 return data;
280 }
281
282 private void cont(AbstractJavaNode node) {
283 super.visit(node, null);
284 scopes.pop();
285 }
286 }