KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > pmd > symboltable > ScopeAndDeclarationFinder


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 JavaDoc;
9 import java.util.Stack JavaDoc;
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 JavaDoc scopes = new Stack JavaDoc();
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     private void addScope(Scope newScope, SimpleNode node) {
41         newScope.setParent((Scope) scopes.peek());
42         scopes.push(newScope);
43         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     private void createLocalScope(SimpleNode node) {
55         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     private void createMethodScope(SimpleNode node) {
67         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     private void createClassScope(SimpleNode node) {
79         if (node instanceof ASTClassOrInterfaceBodyDeclaration) {
80             addScope(new ClassScope(), node);
81         } else {
82             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     private void createSourceFileScope(SimpleNode node) {
93         // When we do full symbol resolution, we'll need to add a truly top-level GlobalScope.
94
Scope scope;
95         List JavaDoc packages = node.findChildrenOfType(ASTPackageDeclaration.class);
96         if (!packages.isEmpty()) {
97             Node n = (Node) packages.get(0);
98             scope = new SourceFileScope(((SimpleNode) n.jjtGetChild(0)).getImage());
99         } else {
100             scope = new SourceFileScope();
101         }
102         scopes.push(scope);
103         node.setScope(scope);
104     }
105
106     public Object JavaDoc visit(ASTCompilationUnit node, Object JavaDoc data) {
107         createSourceFileScope(node);
108         cont(node);
109         return data;
110     }
111
112     public Object JavaDoc visit(ASTClassOrInterfaceDeclaration node, Object JavaDoc data) {
113         createClassScope(node);
114         Scope s = ((SimpleNode) node.jjtGetParent()).getScope();
115         s.addDeclaration(new ClassNameDeclaration(node));
116         cont(node);
117         return data;
118     }
119
120     public Object JavaDoc visit(ASTEnumDeclaration node, Object JavaDoc data) {
121         createClassScope(node);
122         cont(node);
123         return data;
124     }
125
126     public Object JavaDoc visit(ASTClassOrInterfaceBodyDeclaration node, Object JavaDoc data) {
127         if (node.isAnonymousInnerClass() || node.isEnumChild()) {
128             createClassScope(node);
129             cont(node);
130         } else {
131             super.visit(node, data);
132         }
133         return data;
134     }
135
136     public Object JavaDoc visit(ASTBlock node, Object JavaDoc data) {
137         createLocalScope(node);
138         cont(node);
139         return data;
140     }
141
142     public Object JavaDoc visit(ASTCatchStatement node, Object JavaDoc data) {
143         createLocalScope(node);
144         cont(node);
145         return data;
146     }
147
148     public Object JavaDoc visit(ASTFinallyStatement node, Object JavaDoc data) {
149         createLocalScope(node);
150         cont(node);
151         return data;
152     }
153
154     public Object JavaDoc visit(ASTConstructorDeclaration node, Object JavaDoc data) {
155         createMethodScope(node);
156         cont(node);
157         return data;
158     }
159
160     public Object JavaDoc visit(ASTMethodDeclaration node, Object JavaDoc data) {
161         createMethodScope(node);
162         ASTMethodDeclarator md = (ASTMethodDeclarator) node.getFirstChildOfType(ASTMethodDeclarator.class);
163         node.getScope().getEnclosingClassScope().addDeclaration(new MethodNameDeclaration(md));
164         cont(node);
165         return data;
166     }
167
168     public Object JavaDoc visit(ASTTryStatement node, Object JavaDoc data) {
169         createLocalScope(node);
170         cont(node);
171         return data;
172     }
173
174     // TODO - what about while loops and do loops?
175
public Object JavaDoc visit(ASTForStatement node, Object JavaDoc data) {
176         createLocalScope(node);
177         cont(node);
178         return data;
179     }
180
181     public Object JavaDoc visit(ASTIfStatement node, Object JavaDoc data) {
182         createLocalScope(node);
183         cont(node);
184         return data;
185     }
186
187     public Object JavaDoc visit(ASTVariableDeclaratorId node, Object JavaDoc data) {
188         VariableNameDeclaration decl = new VariableNameDeclaration(node);
189         node.getScope().addDeclaration(decl);
190         node.setNameDeclaration(decl);
191         return super.visit(node, data);
192     }
193
194     public Object JavaDoc visit(ASTSwitchStatement node, Object JavaDoc data) {
195         createLocalScope(node);
196         cont(node);
197         return data;
198     }
199
200     private void cont(SimpleJavaNode node) {
201         super.visit(node, null);
202         scopes.pop();
203     }
204 }
205
Popular Tags