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