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