1
2
3
4 package net.sourceforge.pmd.lang.plsql.symboltable;
5
6 import java.util.ArrayList;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.logging.Logger;
10
11 import net.sourceforge.pmd.lang.ast.Node;
12 import net.sourceforge.pmd.lang.plsql.ast.ASTName;
13 import net.sourceforge.pmd.lang.plsql.ast.AbstractPLSQLNode;
14 import net.sourceforge.pmd.lang.symboltable.AbstractScope;
15 import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
16 import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
17
18 public class ClassScope extends AbstractScope {
19 private final static Logger LOGGER = Logger.getLogger(ClassScope.class.getName());
20
21
22 private static ThreadLocal<Integer> anonymousInnerClassCounter = new ThreadLocal<Integer>() {
23 protected Integer initialValue() { return Integer.valueOf(1); }
24 };
25
26 private String className;
27
28 public ClassScope(String className) {
29 this.className = AbstractPLSQLNode.getCanonicalImage(className);
30 anonymousInnerClassCounter.set(Integer.valueOf(1));
31 }
32
33
34
35
36
37
38
39
40 public ClassScope() {
41
42 int v = anonymousInnerClassCounter.get().intValue();
43 this.className = "Anonymous$" + v;
44 anonymousInnerClassCounter.set(v + 1);
45 }
46
47 @Override
48 public void addDeclaration(NameDeclaration declaration) {
49 if (declaration instanceof VariableNameDeclaration && getDeclarations().keySet().contains(declaration)) {
50 throw new RuntimeException(declaration + " is already in the symbol table");
51 }
52 super.addDeclaration(declaration);
53 }
54
55 @Override
56 public NameDeclaration addNameOccurrence(NameOccurrence occ) {
57 PLSQLNameOccurrence occurrence = (PLSQLNameOccurrence)occ;
58 NameDeclaration decl = findVariableHere(occurrence);
59 Map<MethodNameDeclaration, List<NameOccurrence>> methodNames = getMethodDeclarations();
60 if (decl != null && occurrence.isMethodOrConstructorInvocation()) {
61 List<NameOccurrence> nameOccurrences = methodNames.get(decl);
62 if (nameOccurrences == null) {
63
64 } else {
65 nameOccurrences.add(occurrence);
66 Node n = occurrence.getLocation();
67 if (n instanceof ASTName) {
68 ((ASTName) n).setNameDeclaration(decl);
69 }
70 }
71
72 } else if (decl != null && !occurrence.isThisOrSuper()) {
73 Map<VariableNameDeclaration, List<NameOccurrence>> variableNames = getVariableDeclarations();
74 List<NameOccurrence> nameOccurrences = variableNames.get(decl);
75 if (nameOccurrences == null) {
76
77 } else {
78 nameOccurrences.add(occurrence);
79 Node n = occurrence.getLocation();
80 if (n instanceof ASTName) {
81 ((ASTName) n).setNameDeclaration(decl);
82 }
83 }
84 }
85 return decl;
86 }
87
88 public Map<VariableNameDeclaration, List<NameOccurrence>> getVariableDeclarations() {
89 return getDeclarations(VariableNameDeclaration.class);
90 }
91
92 public Map<MethodNameDeclaration, List<NameOccurrence>> getMethodDeclarations() {
93 return getDeclarations(MethodNameDeclaration.class);
94 }
95
96 public Map<ClassNameDeclaration, List<NameOccurrence>> getClassDeclarations() {
97 return getDeclarations(ClassNameDeclaration.class);
98 }
99
100 public ClassScope getEnclosingClassScope() {
101 return this;
102 }
103
104 public String getClassName() {
105 return this.className;
106 }
107
108 protected NameDeclaration findVariableHere(PLSQLNameOccurrence occurrence) {
109 Map<VariableNameDeclaration, List<NameOccurrence>> variableDeclarations = getVariableDeclarations();
110 Map<MethodNameDeclaration, List<NameOccurrence>> methodDeclarations = getMethodDeclarations();
111 if (occurrence.isThisOrSuper() || occurrence.getImage().equals(className)) {
112 if (variableDeclarations.isEmpty() && methodDeclarations.isEmpty()) {
113
114
115
116
117 return null;
118 }
119
120
121
122
123
124
125
126
127 if (!variableDeclarations.isEmpty()) {
128 return variableDeclarations.keySet().iterator().next();
129 }
130 return methodDeclarations.keySet().iterator().next();
131 }
132
133 if (occurrence.isMethodOrConstructorInvocation()) {
134 for (MethodNameDeclaration mnd: methodDeclarations.keySet()) {
135 if (mnd.getImage().equals(occurrence.getImage())) {
136 int args = occurrence.getArgumentCount();
137 if (args == mnd.getParameterCount() || (mnd.isVarargs() && args >= mnd.getParameterCount() - 1)) {
138
139
140
141
142 return mnd;
143 }
144 }
145 }
146 return null;
147 }
148
149 List<String> images = new ArrayList<String>();
150 images.add(occurrence.getImage());
151
152 if (null==occurrence.getImage()) {
153 LOGGER.finest("occurrence==" +occurrence.toString()
154 + "with Argumanet Count == "+occurrence.getArgumentCount()
155 + " for className="+className
156 ) ;
157 }
158
159
160 if (occurrence.getImage().startsWith(className)) {
161 images.add(clipClassName(occurrence.getImage()));
162 }
163 ImageFinderFunction finder = new ImageFinderFunction(images);
164 Applier.apply(finder, getVariableDeclarations().keySet().iterator());
165 return finder.getDecl();
166 }
167
168 public String toString() {
169 String res = "ClassScope (" + className + "): ";
170 Map<ClassNameDeclaration, List<NameOccurrence>> classNames = getClassDeclarations();
171 Map<MethodNameDeclaration, List<NameOccurrence>> methodNames = getMethodDeclarations();
172 Map<VariableNameDeclaration, List<NameOccurrence>> variableNames = getVariableDeclarations();
173 if (!classNames.isEmpty()) {
174 res += "(" + classNames.keySet() + ")";
175 }
176 if (!methodNames.isEmpty()) {
177 for (MethodNameDeclaration mnd: methodNames.keySet()) {
178 res += mnd.toString();
179 int usages = methodNames.get(mnd).size();
180 res += "(begins at line " + mnd.getNode().getBeginLine() + ", " + usages + " usages)";
181 res += ",";
182 }
183 }
184 if (!variableNames.isEmpty()) {
185 res += "(" + variableNames.keySet() + ")";
186 }
187 return res;
188 }
189
190 private String clipClassName(String s) {
191 return s.substring(s.indexOf('.') + 1);
192 }
193 }