Clover coverage report - PMD - 3.7
Coverage timestamp: Wed May 31 2006 09:25:59 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  1176 public ClassScope(String className) {
 27  1176 this.className = className;
 28  1176 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  18 public ClassScope() {
 39    //this.className = getParent().getEnclosingClassScope().getClassName() + "$" + String.valueOf(anonymousInnerClassCounter);
 40  18 this.className = "Anonymous$" + String.valueOf(anonymousInnerClassCounter);
 41  18 anonymousInnerClassCounter++;
 42    }
 43   
 44  357 public void addDeclaration(VariableNameDeclaration variableDecl) {
 45  357 if (variableNames.containsKey(variableDecl)) {
 46  0 throw new RuntimeException(variableDecl + " is already in the symbol table");
 47    }
 48  357 variableNames.put(variableDecl, new ArrayList());
 49    }
 50   
 51  263 public NameDeclaration addVariableNameOccurrence(NameOccurrence occurrence) {
 52  263 NameDeclaration decl = findVariableHere(occurrence);
 53  263 if (decl != null && occurrence.isMethodOrConstructorInvocation()) {
 54  79 List nameOccurrences = (List) methodNames.get(decl);
 55  79 if (nameOccurrences == null) {
 56    // TODO may be a class name: Foo.this.super();
 57    } else {
 58  79 nameOccurrences.add(occurrence);
 59  79 SimpleNode n = occurrence.getLocation();
 60  79 if (n instanceof ASTName) {
 61  57 ((ASTName) n).setNameDeclaration(decl);
 62    } // TODO what to do with PrimarySuffix case?
 63    }
 64   
 65  184 } else if (decl != null && !occurrence.isThisOrSuper()) {
 66  130 List nameOccurrences = (List) variableNames.get(decl);
 67  130 if (nameOccurrences == null) {
 68    // TODO may be a class name
 69    } else {
 70  130 nameOccurrences.add(occurrence);
 71  130 SimpleNode n = occurrence.getLocation();
 72  130 if (n instanceof ASTName) {
 73  111 ((ASTName) n).setNameDeclaration(decl);
 74    } // TODO what to do with PrimarySuffix case?
 75    }
 76    }
 77  263 return decl;
 78    }
 79   
 80  66 public Map getVariableDeclarations() {
 81  66 VariableUsageFinderFunction f = new VariableUsageFinderFunction(variableNames);
 82  66 Applier.apply(f, variableNames.keySet().iterator());
 83  66 return f.getUsed();
 84    }
 85   
 86  38 public Map getMethodDeclarations() {
 87  38 return methodNames;
 88    }
 89   
 90  1 public Map getClassDeclarations() {
 91  1 return classNames;
 92    }
 93   
 94  2258 public ClassScope getEnclosingClassScope() {
 95  2258 return this;
 96    }
 97   
 98  914 public String getClassName() {
 99  914 return this.className;
 100    }
 101   
 102  935 public void addDeclaration(MethodNameDeclaration decl) {
 103  935 methodNames.put(decl, new ArrayList());
 104    }
 105   
 106  59 public void addDeclaration(ClassNameDeclaration decl) {
 107  59 classNames.put(decl, new ArrayList());
 108    }
 109   
 110  1623 protected NameDeclaration findVariableHere(NameOccurrence occurrence) {
 111  1623 if (occurrence.isThisOrSuper() || occurrence.getImage().equals(className)) {
 112  183 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  183 if (!variableNames.isEmpty()) {
 128  84 return (NameDeclaration) variableNames.keySet().iterator().next();
 129    }
 130  99 return (NameDeclaration) methodNames.keySet().iterator().next();
 131    }
 132   
 133  1440 if (occurrence.isMethodOrConstructorInvocation()) {
 134  789 for (Iterator i = methodNames.keySet().iterator(); i.hasNext();) {
 135  819 MethodNameDeclaration mnd = (MethodNameDeclaration) i.next();
 136  819 if (mnd.getImage().equals(occurrence.getImage())) {
 137  246 int args = occurrence.getArgumentCount();
 138  246 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  237 return mnd;
 144    }
 145    }
 146    }
 147  552 return null;
 148    }
 149   
 150  651 List images = new ArrayList();
 151  651 images.add(occurrence.getImage());
 152  651 if (occurrence.getImage().startsWith(className)) {
 153  1 images.add(clipClassName(occurrence.getImage()));
 154    }
 155  651 ImageFinderFunction finder = new ImageFinderFunction(images);
 156  651 Applier.apply(finder, variableNames.keySet().iterator());
 157  651 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    }