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