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.util.Applier;
7
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12
13 public class ClassScope extends AbstractScope {
14
15 protected Map methodNames = new HashMap();
16 protected Map variableNames = new HashMap();
17
18
19 private static int anonymousInnerClassCounter = 1;
20 private String className;
21
22 public ClassScope(String className) {
23 this.className = className;
24 anonymousInnerClassCounter = 1;
25 }
26
27 /***
28 * This is only for anonymous inner classes
29 * <p/>
30 * FIXME - should have name like Foo$1, not Anonymous$1
31 * to get this working right, the parent scope needs
32 * to be passed in when instantiating a ClassScope
33 */
34 public ClassScope() {
35
36 this.className = "Anonymous$" + String.valueOf(anonymousInnerClassCounter);
37 anonymousInnerClassCounter++;
38 }
39
40 public void addDeclaration(VariableNameDeclaration variableDecl) {
41 if (variableNames.containsKey(variableDecl)) {
42 throw new RuntimeException("Variable " + variableDecl + " is already in the symbol table");
43 }
44 variableNames.put(variableDecl, new ArrayList());
45 }
46
47 public NameDeclaration addVariableNameOccurrence(NameOccurrence occurrence) {
48 NameDeclaration decl = findVariableHere(occurrence);
49 if (decl != null && !occurrence.isThisOrSuper()) {
50 List nameOccurrences = (List) variableNames.get(decl);
51 nameOccurrences.add(occurrence);
52 }
53 return decl;
54 }
55
56 public Map getVariableDeclarations() {
57 VariableUsageFinderFunction f = new VariableUsageFinderFunction(variableNames);
58 Applier.apply(f, variableNames.keySet().iterator());
59 return f.getUsed();
60 }
61
62 public ClassScope getEnclosingClassScope() {
63 return this;
64 }
65
66 public String getClassName() {
67 return this.className;
68 }
69
70 public void addDeclaration(MethodNameDeclaration decl) {
71 methodNames.put(decl, new ArrayList());
72 }
73
74 protected NameDeclaration findVariableHere(NameOccurrence occurrence) {
75 if (occurrence.isThisOrSuper() || occurrence.getImage().equals(className)) {
76 if (variableNames.isEmpty()) {
77
78
79
80
81 return null;
82 }
83
84
85
86
87
88
89
90
91 return (NameDeclaration) variableNames.keySet().iterator().next();
92 }
93
94 List images = new ArrayList();
95 images.add(occurrence.getImage());
96 if (occurrence.getImage().startsWith(className)) {
97 images.add(clipClassName(occurrence.getImage()));
98 }
99 ImageFinderFunction finder = new ImageFinderFunction(images);
100 Applier.apply(finder, variableNames.keySet().iterator());
101 return finder.getDecl();
102 }
103
104 public String toString() {
105 String res = "ClassScope:" + className + ":";
106 res += "\nmethods: " + super.glomNames(methodNames.keySet().iterator());
107 res += "\nvariables: " + super.glomNames(variableNames.keySet().iterator());
108 return res;
109 }
110
111 private String clipClassName(String in) {
112 int firstDot = in.indexOf('.');
113 return in.substring(firstDot + 1);
114 }
115 }