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