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