Clover coverage report - PMD - 3.3
Coverage timestamp: Thu Sep 15 2005 17:59:57 EDT
file stats: LOC: 180   Methods: 14
NCLOC: 128   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
ClassScope.java 68.4% 76.5% 92.9% 75.8%
coverage 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.ASTName;
 7    import net.sourceforge.pmd.ast.SimpleNode;
 8    import net.sourceforge.pmd.util.Applier;
 9   
 10    import java.util.ArrayList;
 11    import java.util.HashMap;
 12    import java.util.Iterator;
 13    import java.util.List;
 14    import java.util.Map;
 15   
 16    public class ClassScope extends AbstractScope {
 17   
 18    protected Map classNames = new HashMap();
 19    protected Map methodNames = new HashMap();
 20    protected Map variableNames = new HashMap();
 21   
 22    // FIXME - this breaks given sufficiently nested code
 23    private static int anonymousInnerClassCounter = 1;
 24    private String className;
 25   
 26  888 public ClassScope(String className) {
 27  888 this.className = className;
 28  888 anonymousInnerClassCounter = 1;
 29    }
 30   
 31    /**
 32    * This is only for anonymous inner classes
 33    * <p/>
 34    * FIXME - should have name like Foo$1, not Anonymous$1
 35    * to get this working right, the parent scope needs
 36    * to be passed in when instantiating a ClassScope
 37    */
 38  11 public ClassScope() {
 39    //this.className = getParent().getEnclosingClassScope().getClassName() + "$" + String.valueOf(anonymousInnerClassCounter);
 40  11 this.className = "Anonymous$" + String.valueOf(anonymousInnerClassCounter);
 41  11 anonymousInnerClassCounter++;
 42    }
 43   
 44  289 public void addDeclaration(VariableNameDeclaration variableDecl) {
 45  289 if (variableNames.containsKey(variableDecl)) {
 46  0 throw new RuntimeException(variableDecl + " is already in the symbol table");
 47    }
 48  289 variableNames.put(variableDecl, new ArrayList());
 49    }
 50   
 51  217 public NameDeclaration addVariableNameOccurrence(NameOccurrence occurrence) {
 52  217 NameDeclaration decl = findVariableHere(occurrence);
 53  217 if (decl != null && occurrence.isMethodOrConstructorInvocation()) {
 54  69 List nameOccurrences = (List) methodNames.get(decl);
 55  69 if (nameOccurrences == null) {
 56    // TODO may be a class name: Foo.this.super();
 57    } else {
 58  69 nameOccurrences.add(occurrence);
 59  69 SimpleNode n = occurrence.getLocation();
 60  69 if (n instanceof ASTName) {
 61  49 ((ASTName)n).setNameDeclaration(decl);
 62    } // TODO what to do with PrimarySuffix case?
 63    }
 64   
 65  148 } else if (decl != null && !occurrence.isThisOrSuper()) {
 66  97 List nameOccurrences = (List) variableNames.get(decl);
 67  97 if (nameOccurrences == null) {
 68    // TODO may be a class name
 69    } else {
 70  97 nameOccurrences.add(occurrence);
 71  97 SimpleNode n = occurrence.getLocation();
 72  97 if (n instanceof ASTName) {
 73  78 ((ASTName)n).setNameDeclaration(decl);
 74    } // TODO what to do with PrimarySuffix case?
 75    }
 76    }
 77  217 return decl;
 78    }
 79   
 80  57 public Map getVariableDeclarations() {
 81  57 VariableUsageFinderFunction f = new VariableUsageFinderFunction(variableNames);
 82  57 Applier.apply(f, variableNames.keySet().iterator());
 83  57 return f.getUsed();
 84    }
 85   
 86  22 public Map getMethodDeclarations() {
 87  22 return methodNames;
 88    }
 89   
 90  1 public Map getClassDeclarations() {
 91  1 return classNames;
 92    }
 93   
 94  1475 public ClassScope getEnclosingClassScope() {
 95  1475 return this;
 96    }
 97   
 98  692 public String getClassName() {
 99  692 return this.className;
 100    }
 101   
 102  687 public void addDeclaration(MethodNameDeclaration decl) {
 103  687 methodNames.put(decl, new ArrayList());
 104    }
 105   
 106  54 public void addDeclaration(ClassNameDeclaration decl) {
 107  54 classNames.put(decl, new ArrayList());
 108    }
 109   
 110  1036 protected NameDeclaration findVariableHere(NameOccurrence occurrence) {
 111  1036 if (occurrence.isThisOrSuper() || occurrence.getImage().equals(className)) {
 112  171 if (variableNames.isEmpty() && methodNames.isEmpty()) {
 113    // this could happen if you do this:
 114    // public class Foo {
 115    // private String x = super.toString();
 116    // }
 117  0 return null;
 118    }
 119    // return any name declaration, since all we really want is to get the scope
 120    // for example, if there's a
 121    // public class Foo {
 122    // private static final int X = 2;
 123    // private int y = Foo.X;
 124    // }
 125    // we'll look up Foo just to get a handle to the class scope
 126    // and then we'll look up X.
 127  171 if (!variableNames.isEmpty()) {
 128  81 return (NameDeclaration)variableNames.keySet().iterator().next();
 129    }
 130  90 return (NameDeclaration) methodNames.keySet().iterator().next();
 131    }
 132   
 133  865 if (occurrence.isMethodOrConstructorInvocation()) {
 134  406 for (Iterator i = methodNames.keySet().iterator(); i.hasNext();) {
 135  422 MethodNameDeclaration mnd = (MethodNameDeclaration)i.next();
 136  422 if (mnd.getImage().equals(occurrence.getImage())) {
 137  214 int args = occurrence.getArgumentCount();
 138  214 if (args == mnd.getParameterCount()) {
 139    // FIXME if several methods have the same name
 140    // and parameter count, only one will get caught here
 141    // we need to make some attempt at type lookup and discrimination
 142    // or, failing that, mark this as a usage of all those methods
 143  207 return mnd;
 144    }
 145    }
 146    }
 147  199 return null;
 148    }
 149   
 150  459 List images = new ArrayList();
 151  459 images.add(occurrence.getImage());
 152  459 if (occurrence.getImage().startsWith(className)) {
 153  1 images.add(clipClassName(occurrence.getImage()));
 154    }
 155  459 ImageFinderFunction finder = new ImageFinderFunction(images);
 156  459 Applier.apply(finder, variableNames.keySet().iterator());
 157  459 return finder.getDecl();
 158    }
 159   
 160  0 public String toString() {
 161  0 String res = "ClassScope (" + className + "): ";
 162  0 if (!classNames.isEmpty()) res += "(" + glomNames(classNames.keySet().iterator()) + ")";
 163  0 if (!methodNames.isEmpty()) {
 164  0 Iterator i = methodNames.keySet().iterator();
 165  0 while (i.hasNext()) {
 166  0 MethodNameDeclaration mnd = (MethodNameDeclaration)i.next();
 167  0 res += mnd.toString();
 168  0 int usages = ((List)methodNames.get(mnd)).size();
 169  0 res += "(begins at line " + mnd.getNode().getBeginLine() + ", " + usages + " usages)";
 170  0 res += ",";
 171    }
 172    }
 173  0 if (!variableNames.isEmpty()) res += "(" + glomNames(variableNames.keySet().iterator()) + ")";
 174  0 return res;
 175    }
 176   
 177  1 private String clipClassName(String in) {
 178  1 return in.substring(in.indexOf('.') + 1);
 179    }
 180    }