Clover coverage report - PMD - 3.9 Coverage timestamp: Tue Dec 19 2006 09:38:44 EST FRAMES NO FRAMES |
file stats: | LOC: | 204 |  | Methods: | 20
| NCLOC: | 120 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
ScopeAndDeclarationFinder.java | 100% | 100% | 100% | 100% |

1 |  | /**
2 |  | * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 |  | */
4 |  | package net.sourceforge.pmd.symboltable;
5 |  |
6 |  | import net.sourceforge.pmd.ast.*;
7 |  |
8 |  | import java.util.List;
9 |  | import java.util.Stack;
10 |  |
11 |  | /**
12 |  | * Visitor for scope creation.
13 |  | * Visits all nodes of an AST and creates scope objects for nodes representing
14 |  | * syntactic entities which may contain declarations. For example, a block
15 |  | * may contain variable definitions (which are declarations) and
16 |  | * therefore needs a scope object where these declarations can be associated,
17 |  | * whereas an expression can't contain declarations and therefore doesn't need
18 |  | * a scope object.
19 |  | * With the exception of global scopes, each scope object is linked to its
20 |  | * parent scope, which is the scope object of the next embedding syntactic
21 |  | * entity that has a scope.
22 |  | */
23 |  | public class ScopeAndDeclarationFinder extends JavaParserVisitorAdapter {
24 |  |
25 |  | /**
26 |  | * A stack of scopes reflecting the scope hierarchy when a node is visited.
27 |  | * This is used to set the parents of the created scopes correctly.
28 |  | */
29 |  | private Stack scopes = new Stack();
30 |  |
31 |  | /**
32 |  | * Sets the scope of a node and adjustes the scope stack accordingly.
33 |  | * The scope on top of the stack is set as the parent of the given scope,
34 |  | * which is then also stored on the scope stack.
35 |  | *
36 |  | * @param newScope the scope for the node.
37 |  | * @param node the AST node for which the scope is to be set.
38 |  | * @throws java.util.EmptyStackException if the scope stack is empty.
39 |  | */
40 | 4694 | private void addScope(Scope newScope, SimpleNode node) {
41 | 4694 | newScope.setParent((Scope) scopes.peek());
42 | 4694 | scopes.push(newScope);
43 | 4694 | node.setScope(newScope);
44 |  | }
45 |  |
46 |  | /**
47 |  | * Creates a new local scope for an AST node.
48 |  | * The scope on top of the stack is set as the parent of the new scope,
49 |  | * which is then also stored on the scope stack.
50 |  | *
51 |  | * @param node the AST node for which the scope has to be created.
52 |  | * @throws java.util.EmptyStackException if the scope stack is empty.
53 |  | */
54 | 2077 | private void createLocalScope(SimpleNode node) {
55 | 2077 | addScope(new LocalScope(), node);
56 |  | }
57 |  |
58 |  | /**
59 |  | * Creates a new method scope for an AST node.
60 |  | * The scope on top of the stack is set as the parent of the new scope,
61 |  | * which is then also stored on the scope stack.
62 |  | *
63 |  | * @param node the AST node for which the scope has to be created.
64 |  | * @throws java.util.EmptyStackException if the scope stack is empty.
65 |  | */
66 | 1217 | private void createMethodScope(SimpleNode node) {
67 | 1217 | addScope(new MethodScope(node), node);
68 |  | }
69 |  |
70 |  | /**
71 |  | * Creates a new class scope for an AST node.
72 |  | * The scope on top of the stack is set as the parent of the new scope,
73 |  | * which is then also stored on the scope stack.
74 |  | *
75 |  | * @param node the AST node for which the scope has to be created.
76 |  | * @throws java.util.EmptyStackException if the scope stack is empty.
77 |  | */
78 | 1400 | private void createClassScope(SimpleNode node) {
79 | 1400 | if (node instanceof ASTClassOrInterfaceBodyDeclaration) {
80 | 14 | addScope(new ClassScope(), node);
81 |  | } else {
82 | 1386 | addScope(new ClassScope(node.getImage()), node);
83 |  | }
84 |  | }
85 |  |
86 |  | /**
87 |  | * Creates a new global scope for an AST node.
88 |  | * The new scope is stored on the scope stack.
89 |  | *
90 |  | * @param node the AST node for which the scope has to be created.
91 |  | */
92 | 1315 | private void createSourceFileScope(SimpleNode node) {
93 |  | // When we do full symbol resolution, we'll need to add a truly top-level GlobalScope.
94 | 1315 | Scope scope;
95 | 1315 | List packages = node.findChildrenOfType(ASTPackageDeclaration.class);
96 | 1315 | if (!packages.isEmpty()) {
97 | 13 | Node n = (Node) packages.get(0);
98 | 13 | scope = new SourceFileScope(((SimpleNode) n.jjtGetChild(0)).getImage());
99 |  | } else {
100 | 1302 | scope = new SourceFileScope();
101 |  | }
102 | 1315 | scopes.push(scope);
103 | 1315 | node.setScope(scope);
104 |  | }
105 |  |
106 | 1315 | public Object visit(ASTCompilationUnit node, Object data) {
107 | 1315 | createSourceFileScope(node);
108 | 1315 | cont(node);
109 | 1315 | return data;
110 |  | }
111 |  |
112 | 1382 | public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
113 | 1382 | createClassScope(node);
114 | 1382 | Scope s = ((SimpleNode) node.jjtGetParent()).getScope();
115 | 1382 | s.addDeclaration(new ClassNameDeclaration(node));
116 | 1382 | cont(node);
117 | 1382 | return data;
118 |  | }
119 |  |
120 | 4 | public Object visit(ASTEnumDeclaration node, Object data) {
121 | 4 | createClassScope(node);
122 | 4 | cont(node);
123 | 4 | return data;
124 |  | }
125 |  |
126 | 1749 | public Object visit(ASTClassOrInterfaceBodyDeclaration node, Object data) {
127 | 1749 | if (node.isAnonymousInnerClass() || node.isEnumChild()) {
128 | 14 | createClassScope(node);
129 | 14 | cont(node);
130 |  | } else {
131 | 1735 | super.visit(node, data);
132 |  | }
133 | 1749 | return data;
134 |  | }
135 |  |
136 | 1579 | public Object visit(ASTBlock node, Object data) {
137 | 1579 | createLocalScope(node);
138 | 1579 | cont(node);
139 | 1579 | return data;
140 |  | }
141 |  |
142 | 89 | public Object visit(ASTCatchStatement node, Object data) {
143 | 89 | createLocalScope(node);
144 | 89 | cont(node);
145 | 89 | return data;
146 |  | }
147 |  |
148 | 18 | public Object visit(ASTFinallyStatement node, Object data) {
149 | 18 | createLocalScope(node);
150 | 18 | cont(node);
151 | 18 | return data;
152 |  | }
153 |  |
154 | 127 | public Object visit(ASTConstructorDeclaration node, Object data) {
155 | 127 | createMethodScope(node);
156 | 127 | cont(node);
157 | 127 | return data;
158 |  | }
159 |  |
160 | 1090 | public Object visit(ASTMethodDeclaration node, Object data) {
161 | 1090 | createMethodScope(node);
162 | 1090 | ASTMethodDeclarator md = (ASTMethodDeclarator) node.getFirstChildOfType(ASTMethodDeclarator.class);
163 | 1090 | node.getScope().getEnclosingClassScope().addDeclaration(new MethodNameDeclaration(md));
164 | 1090 | cont(node);
165 | 1090 | return data;
166 |  | }
167 |  |
168 | 97 | public Object visit(ASTTryStatement node, Object data) {
169 | 97 | createLocalScope(node);
170 | 97 | cont(node);
171 | 97 | return data;
172 |  | }
173 |  |
174 |  | // TODO - what about while loops and do loops?
175 | 81 | public Object visit(ASTForStatement node, Object data) {
176 | 81 | createLocalScope(node);
177 | 81 | cont(node);
178 | 81 | return data;
179 |  | }
180 |  |
181 | 187 | public Object visit(ASTIfStatement node, Object data) {
182 | 187 | createLocalScope(node);
183 | 187 | cont(node);
184 | 187 | return data;
185 |  | }
186 |  |
187 | 1452 | public Object visit(ASTVariableDeclaratorId node, Object data) {
188 | 1452 | VariableNameDeclaration decl = new VariableNameDeclaration(node);
189 | 1452 | node.getScope().addDeclaration(decl);
190 | 1452 | node.setNameDeclaration(decl);
191 | 1452 | return super.visit(node, data);
192 |  | }
193 |  |
194 | 26 | public Object visit(ASTSwitchStatement node, Object data) {
195 | 26 | createLocalScope(node);
196 | 26 | cont(node);
197 | 26 | return data;
198 |  | }
199 |  |
200 | 6009 | private void cont(SimpleJavaNode node) {
201 | 6009 | super.visit(node, null);
202 | 6009 | scopes.pop();
203 |  | }
204 |  | }