KickJava   Java API By Example, From Geeks To Geeks.

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


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 JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import java.util.Iterator JavaDoc;
13 import java.util.List JavaDoc;
14 import java.util.Map JavaDoc;
15
16 public class ClassScope extends AbstractScope {
17
18     protected Map JavaDoc classNames = new HashMap JavaDoc();
19     protected Map JavaDoc methodNames = new HashMap JavaDoc();
20     protected Map JavaDoc variableNames = new HashMap JavaDoc();
21
22     // FIXME - this breaks given sufficiently nested code
23
private static int anonymousInnerClassCounter = 1;
24     private String JavaDoc className;
25
26     public ClassScope(String JavaDoc className) {
27         this.className = className;
28         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     public ClassScope() {
39         //this.className = getParent().getEnclosingClassScope().getClassName() + "$" + String.valueOf(anonymousInnerClassCounter);
40
this.className = "Anonymous$" + anonymousInnerClassCounter;
41         anonymousInnerClassCounter++;
42     }
43
44     public void addDeclaration(VariableNameDeclaration variableDecl) {
45         if (variableNames.containsKey(variableDecl)) {
46             throw new RuntimeException JavaDoc(variableDecl + " is already in the symbol table");
47         }
48         variableNames.put(variableDecl, new ArrayList JavaDoc());
49     }
50
51     public NameDeclaration addVariableNameOccurrence(NameOccurrence occurrence) {
52         NameDeclaration decl = findVariableHere(occurrence);
53         if (decl != null && occurrence.isMethodOrConstructorInvocation()) {
54             List JavaDoc nameOccurrences = (List JavaDoc) methodNames.get(decl);
55             if (nameOccurrences == null) {
56                 // TODO may be a class name: Foo.this.super();
57
} else {
58                 nameOccurrences.add(occurrence);
59                 SimpleNode n = occurrence.getLocation();
60                 if (n instanceof ASTName) {
61                     ((ASTName) n).setNameDeclaration(decl);
62                 } // TODO what to do with PrimarySuffix case?
63
}
64
65         } else if (decl != null && !occurrence.isThisOrSuper()) {
66             List JavaDoc nameOccurrences = (List JavaDoc) variableNames.get(decl);
67             if (nameOccurrences == null) {
68                 // TODO may be a class name
69
} else {
70                 nameOccurrences.add(occurrence);
71                 SimpleNode n = occurrence.getLocation();
72                 if (n instanceof ASTName) {
73                     ((ASTName) n).setNameDeclaration(decl);
74                 } // TODO what to do with PrimarySuffix case?
75
}
76         }
77         return decl;
78     }
79
80     public Map JavaDoc getVariableDeclarations() {
81         VariableUsageFinderFunction f = new VariableUsageFinderFunction(variableNames);
82         Applier.apply(f, variableNames.keySet().iterator());
83         return f.getUsed();
84     }
85
86     public Map JavaDoc getMethodDeclarations() {
87         return methodNames;
88     }
89
90     public Map JavaDoc getClassDeclarations() {
91         return classNames;
92     }
93
94     public ClassScope getEnclosingClassScope() {
95         return this;
96     }
97
98     public String JavaDoc getClassName() {
99         return this.className;
100     }
101
102     public void addDeclaration(MethodNameDeclaration decl) {
103         methodNames.put(decl, new ArrayList JavaDoc());
104     }
105
106     public void addDeclaration(ClassNameDeclaration decl) {
107         classNames.put(decl, new ArrayList JavaDoc());
108     }
109
110     protected NameDeclaration findVariableHere(NameOccurrence occurrence) {
111         if (occurrence.isThisOrSuper() || occurrence.getImage().equals(className)) {
112             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
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
if (!variableNames.isEmpty()) {
128                 return (NameDeclaration) variableNames.keySet().iterator().next();
129             }
130             return (NameDeclaration) methodNames.keySet().iterator().next();
131         }
132
133         if (occurrence.isMethodOrConstructorInvocation()) {
134             for (Iterator JavaDoc i = methodNames.keySet().iterator(); i.hasNext();) {
135                 MethodNameDeclaration mnd = (MethodNameDeclaration) i.next();
136                 if (mnd.getImage().equals(occurrence.getImage())) {
137                     int args = occurrence.getArgumentCount();
138                     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
return mnd;
144                     }
145                 }
146             }
147             return null;
148         }
149
150         List JavaDoc images = new ArrayList JavaDoc();
151         images.add(occurrence.getImage());
152         if (occurrence.getImage().startsWith(className)) {
153             images.add(clipClassName(occurrence.getImage()));
154         }
155         ImageFinderFunction finder = new ImageFinderFunction(images);
156         Applier.apply(finder, variableNames.keySet().iterator());
157         return finder.getDecl();
158     }
159
160     public String JavaDoc toString() {
161         String JavaDoc res = "ClassScope (" + className + "): ";
162         if (!classNames.isEmpty()) res += "(" + glomNames(classNames.keySet().iterator()) + ")";
163         if (!methodNames.isEmpty()) {
164             Iterator JavaDoc i = methodNames.keySet().iterator();
165             while (i.hasNext()) {
166                 MethodNameDeclaration mnd = (MethodNameDeclaration) i.next();
167                 res += mnd.toString();
168                 int usages = ((List JavaDoc) methodNames.get(mnd)).size();
169                 res += "(begins at line " + mnd.getNode().getBeginLine() + ", " + usages + " usages)";
170                 res += ",";
171             }
172         }
173         if (!variableNames.isEmpty()) res += "(" + glomNames(variableNames.keySet().iterator()) + ")";
174         return res;
175     }
176
177     private String JavaDoc clipClassName(String JavaDoc in) {
178         return in.substring(in.indexOf('.') + 1);
179     }
180 }
181
Popular Tags