1
2
3
4 package net.sourceforge.pmd.lang.plsql.symboltable;
5
6 import java.util.Stack;
7 import java.util.logging.Level;
8 import java.util.logging.Logger;
9
10 import net.sourceforge.pmd.lang.plsql.ast.ASTBlock;
11 import net.sourceforge.pmd.lang.plsql.ast.ASTDeclarativeUnit;
12 import net.sourceforge.pmd.lang.plsql.ast.ASTForAllStatement;
13 import net.sourceforge.pmd.lang.plsql.ast.ASTForStatement;
14 import net.sourceforge.pmd.lang.plsql.ast.ASTID;
15 import net.sourceforge.pmd.lang.plsql.ast.ASTInput;
16 import net.sourceforge.pmd.lang.plsql.ast.ASTMethodDeclarator;
17 import net.sourceforge.pmd.lang.plsql.ast.ASTObjectDeclaration;
18 import net.sourceforge.pmd.lang.plsql.ast.ASTObjectNameDeclaration;
19 import net.sourceforge.pmd.lang.plsql.ast.ASTPackageBody;
20 import net.sourceforge.pmd.lang.plsql.ast.ASTPackageSpecification;
21 import net.sourceforge.pmd.lang.plsql.ast.ASTProgramUnit;
22 import net.sourceforge.pmd.lang.plsql.ast.ASTTriggerTimingPointSection;
23 import net.sourceforge.pmd.lang.plsql.ast.ASTTriggerUnit;
24 import net.sourceforge.pmd.lang.plsql.ast.ASTTypeMethod;
25 import net.sourceforge.pmd.lang.plsql.ast.ASTTypeSpecification;
26 import net.sourceforge.pmd.lang.plsql.ast.ASTVariableOrConstantDeclaratorId;
27 import net.sourceforge.pmd.lang.plsql.ast.PLSQLNode;
28 import net.sourceforge.pmd.lang.plsql.ast.PLSQLParserVisitorAdapter;
29 import net.sourceforge.pmd.lang.symboltable.Scope;
30
31
32
33
34
35
36
37
38
39
40
41
42
43 public class ScopeAndDeclarationFinder extends PLSQLParserVisitorAdapter {
44 private final static Logger LOGGER = Logger.getLogger(ScopeAndDeclarationFinder.class.getName());
45
46
47
48
49
50 private Stack<Scope> scopes = new Stack<Scope>();
51
52
53
54
55
56
57
58
59
60
61 private void addScope(Scope newScope, PLSQLNode node) {
62 newScope.setParent(scopes.peek());
63 scopes.push(newScope);
64 node.setScope(newScope);
65 }
66
67
68
69
70
71
72
73
74
75 private void createLocalScope(PLSQLNode node) {
76 addScope(new LocalScope(), node);
77 }
78
79
80
81
82
83
84
85
86
87 private void createMethodScope(PLSQLNode node) {
88 addScope(new MethodScope(node), node);
89 }
90
91
92
93
94
95
96
97
98
99 private void createClassScope(PLSQLNode node) {
100 if (node instanceof ASTDeclarativeUnit) {
101 addScope(new ClassScope(), node);
102 } else {
103 addScope(new ClassScope(node.getImage()), node);
104 }
105 }
106
107
108
109
110
111
112
113 private void createSourceFileScope(ASTInput node) {
114
115 Scope scope;
116
117 ASTObjectDeclaration n = null;
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(ASTInput node, Object data) {
129 createSourceFileScope(node);
130 cont(node);
131 return data;
132 }
133
134 @Override
135 public Object visit(ASTPackageSpecification node, Object data) {
136 createClassScope(node);
137 Scope s = ((PLSQLNode)node.jjtGetParent()).getScope();
138 s.addDeclaration(new ClassNameDeclaration(node));
139 cont(node);
140 return data;
141 }
142
143 @Override
144 public Object visit(ASTPackageBody node, Object data) {
145 createClassScope(node);
146 Scope s = ((PLSQLNode)node.jjtGetParent()).getScope();
147 s.addDeclaration(new ClassNameDeclaration(node));
148 cont(node);
149 return data;
150 }
151
152
153 @Override
154 public Object visit(ASTTypeSpecification node, Object data) {
155 createClassScope(node);
156 Scope s = ((PLSQLNode)node.jjtGetParent()).getScope();
157 s.addDeclaration(new ClassNameDeclaration(node));
158 cont(node);
159 return data;
160 }
161
162 @Override
163 public Object visit(ASTTriggerUnit node, Object data) {
164 createClassScope(node);
165 Scope s = ((PLSQLNode)node.jjtGetParent()).getScope();
166 s.addDeclaration(new ClassNameDeclaration(node));
167 cont(node);
168 return data;
169 }
170
171
172
173
174
175
176
177
178
179
180
181
182 @Override
183 public Object visit(ASTTriggerTimingPointSection node, Object data) {
184 createMethodScope(node);
185
186 node.getScope().getEnclosingScope(ClassScope.class).addDeclaration(new MethodNameDeclaration(node));
187 cont(node);
188 return data;
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205 @Override
206 public Object visit(ASTObjectDeclaration node, Object data) {
207 super.visit(node, data);
208 return data;
209 }
210
211 @Override
212 public Object visit(ASTBlock node, Object data) {
213 createLocalScope(node);
214 cont(node);
215 return data;
216 }
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278 @Override
279 public Object visit(ASTTypeMethod node, Object data) {
280 createMethodScope(node);
281 ASTMethodDeclarator md = node.getFirstChildOfType(ASTMethodDeclarator.class);
282
283 try
284 {
285 node.getScope().getEnclosingScope(ClassScope.class).addDeclaration(new MethodNameDeclaration(md));
286 }
287 catch (Exception e)
288 {
289
290 if (LOGGER.isLoggable(Level.FINEST)) {
291 LOGGER.finest("ProgramUnit getEnclosingClassScope Exception string=\""+e.getMessage()+"\"");
292 }
293 if("getEnclosingClassScope() called on SourceFileScope".equals(e.getMessage()))
294 {
295 if (LOGGER.isLoggable(Level.FINEST)) {
296 LOGGER.finest("ClassScope skipped for Schema-level method: methodName="
297 + node.getMethodName()
298 + "; Image=" + node.getImage()
299 );
300 }
301
302
303 ASTObjectNameDeclaration on = md.getFirstChildOfType(ASTObjectNameDeclaration.class);
304 if( 1 < on.jjtGetNumChildren())
305 {
306 ASTID schemaName = on.getFirstChildOfType(ASTID.class);
307 if (LOGGER.isLoggable(Level.FINEST)) {
308 LOGGER.finest("SchemaName for Schema-level method: methodName="
309 + node.getMethodName()
310 + "; Image=" + node.getImage()
311 + "is " + schemaName.getImage()
312 );
313 }
314
315 }
316 }
317 }
318 cont(node);
319 return data;
320 }
321
322 @Override
323 public Object visit(ASTProgramUnit node, Object data) {
324 createMethodScope(node);
325 ASTMethodDeclarator md = node.getFirstChildOfType(ASTMethodDeclarator.class);
326
327 try
328 {
329 node.getScope().getEnclosingScope(ClassScope.class).addDeclaration(new MethodNameDeclaration(md));
330 }
331 catch (Exception e)
332 {
333
334 if (LOGGER.isLoggable(Level.FINEST)) {
335 LOGGER.finest("ProgramUnit getEnclosingClassScope Exception string=\""+e.getMessage()+"\"");
336 }
337 if("getEnclosingClassScope() called on SourceFileScope".equals(e.getMessage()))
338 {
339 if (LOGGER.isLoggable(Level.FINEST)) {
340 LOGGER.finest("ClassScope skipped for Schema-level method: methodName="
341 + node.getMethodName()
342 + "; Image=" + node.getImage()
343 );
344 }
345
346
347 ASTObjectNameDeclaration on = md.getFirstChildOfType(ASTObjectNameDeclaration.class);
348 if( 1 < on.jjtGetNumChildren())
349 {
350 ASTID schemaName = on.getFirstChildOfType(ASTID.class);
351 if (LOGGER.isLoggable(Level.FINEST)) {
352 LOGGER.finest("SchemaName for Schema-level method: methodName="
353 + node.getMethodName()
354 + "; Image=" + node.getImage()
355 + "is " + schemaName.getImage()
356 );
357 }
358
359 }
360 }
361 }
362 cont(node);
363 return data;
364 }
365
366
367 @Override
368 public Object visit(ASTForStatement node, Object data) {
369 createLocalScope(node);
370 cont(node);
371 return data;
372 }
373
374 @Override
375 public Object visit(ASTForAllStatement node, Object data) {
376 createLocalScope(node);
377 cont(node);
378 return data;
379 }
380
381 @Override
382 public Object visit(ASTVariableOrConstantDeclaratorId node, Object data) {
383 VariableNameDeclaration decl = new VariableNameDeclaration(node);
384 node.getScope().addDeclaration(decl);
385 node.setNameDeclaration(decl);
386 return super.visit(node, data);
387 }
388
389
390
391
392
393
394
395
396 private void cont(PLSQLNode node) {
397 super.visit(node, null);
398 scopes.pop();
399 }
400 }