Clover coverage report - PMD - 3.7
Coverage timestamp: Wed May 31 2006 09:25:59 EDT
file stats: LOC: 204   Methods: 20
NCLOC: 120   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
ScopeAndDeclarationFinder.java 100% 100% 100% 100%
coverage
 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  4023 private void addScope(Scope newScope, SimpleNode node) {
 41  4023 newScope.setParent((Scope) scopes.peek());
 42  4023 scopes.push(newScope);
 43  4023 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  1790 private void createLocalScope(SimpleNode node) {
 55  1790 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  1044 private void createMethodScope(SimpleNode node) {
 67  1044 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  1189 private void createClassScope(SimpleNode node) {
 79  1189 if (node instanceof ASTClassOrInterfaceBodyDeclaration) {
 80  16 addScope(new ClassScope(), node);
 81    } else {
 82  1173 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  1113 private void createSourceFileScope(SimpleNode node) {
 93    // When we do full symbol resolution, we'll need to add a truly top-level GlobalScope.
 94  1113 Scope scope;
 95  1113 List packages = node.findChildrenOfType(ASTPackageDeclaration.class);
 96  1113 if (!packages.isEmpty()) {
 97  12 Node n = (Node) packages.get(0);
 98  12 scope = new SourceFileScope(((SimpleNode) n.jjtGetChild(0)).getImage());
 99    } else {
 100  1101 scope = new SourceFileScope();
 101    }
 102  1113 scopes.push(scope);
 103  1113 node.setScope(scope);
 104    }
 105   
 106  1113 public Object visit(ASTCompilationUnit node, Object data) {
 107  1113 createSourceFileScope(node);
 108  1113 cont(node);
 109  1113 return data;
 110    }
 111   
 112  1169 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
 113  1169 createClassScope(node);
 114  1169 Scope s = ((SimpleNode) node.jjtGetParent()).getScope();
 115  1169 s.addDeclaration(new ClassNameDeclaration(node));
 116  1169 cont(node);
 117  1169 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  1481 public Object visit(ASTClassOrInterfaceBodyDeclaration node, Object data) {
 127  1481 if (node.isAnonymousInnerClass() || node.isEnumChild()) {
 128  16 createClassScope(node);
 129  16 cont(node);
 130    } else {
 131  1465 super.visit(node, data);
 132    }
 133  1481 return data;
 134    }
 135   
 136  1356 public Object visit(ASTBlock node, Object data) {
 137  1356 createLocalScope(node);
 138  1356 cont(node);
 139  1356 return data;
 140    }
 141   
 142  80 public Object visit(ASTCatchStatement node, Object data) {
 143  80 createLocalScope(node);
 144  80 cont(node);
 145  80 return data;
 146    }
 147   
 148  15 public Object visit(ASTFinallyStatement node, Object data) {
 149  15 createLocalScope(node);
 150  15 cont(node);
 151  15 return data;
 152    }
 153   
 154  109 public Object visit(ASTConstructorDeclaration node, Object data) {
 155  109 createMethodScope(node);
 156  109 cont(node);
 157  109 return data;
 158    }
 159   
 160  935 public Object visit(ASTMethodDeclaration node, Object data) {
 161  935 createMethodScope(node);
 162  935 ASTMethodDeclarator md = (ASTMethodDeclarator) node.getFirstChildOfType(ASTMethodDeclarator.class);
 163  935 node.getScope().getEnclosingClassScope().addDeclaration(new MethodNameDeclaration(md));
 164  935 cont(node);
 165  935 return data;
 166    }
 167   
 168  85 public Object visit(ASTTryStatement node, Object data) {
 169  85 createLocalScope(node);
 170  85 cont(node);
 171  85 return data;
 172    }
 173   
 174    // TODO - what about while loops and do loops?
 175  77 public Object visit(ASTForStatement node, Object data) {
 176  77 createLocalScope(node);
 177  77 cont(node);
 178  77 return data;
 179    }
 180   
 181  152 public Object visit(ASTIfStatement node, Object data) {
 182  152 createLocalScope(node);
 183  152 cont(node);
 184  152 return data;
 185    }
 186   
 187  1236 public Object visit(ASTVariableDeclaratorId node, Object data) {
 188  1236 VariableNameDeclaration decl = new VariableNameDeclaration(node);
 189  1236 node.getScope().addDeclaration(decl);
 190  1236 node.setNameDeclaration(decl);
 191  1236 return super.visit(node, data);
 192    }
 193   
 194  25 public Object visit(ASTSwitchStatement node, Object data) {
 195  25 createLocalScope(node);
 196  25 cont(node);
 197  25 return data;
 198    }
 199   
 200  5136 private void cont(SimpleJavaNode node) {
 201  5136 super.visit(node, null);
 202  5136 scopes.pop();
 203    }
 204    }