1
2
3
4 package net.sourceforge.pmd.lang.java.typeresolution.visitors;
5
6 import org.objectweb.asm.AnnotationVisitor;
7 import org.objectweb.asm.Attribute;
8 import org.objectweb.asm.ClassVisitor;
9 import org.objectweb.asm.FieldVisitor;
10 import org.objectweb.asm.Label;
11 import org.objectweb.asm.MethodVisitor;
12 import org.objectweb.asm.Type;
13 import org.objectweb.asm.signature.SignatureReader;
14 import org.objectweb.asm.signature.SignatureVisitor;
15
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20
21 public class PMDASMVisitor implements ClassVisitor {
22
23 private Map<String, String> packages = new HashMap<String, String>();
24
25 private AnnotationVisitor annotationVisitor = new PMDAnnotationVisitor(this);
26
27 private FieldVisitor fieldVisitor = new PMDFieldVisitor(this);
28
29 private SignatureVisitor sigVisitor = new PMDSignatureVisitor(this);
30
31 private MethodVisitor methodVisitor = new PMDMethodVisitor(this);
32
33 public List<String> innerClasses;
34
35 public Map<String, String> getPackages() {
36 return packages;
37 }
38
39 public List<String> getInnerClasses() {
40 return innerClasses;
41 }
42
43 private String parseClassName(String name) {
44 if (name == null) {
45 return null;
46 }
47
48 String className = name;
49 int n = name.lastIndexOf('/');
50 if (n > -1) {
51 className = name.substring(n + 1);
52 }
53 name = name.replace('/', '.');
54 packages.put(className, name);
55 n = className.indexOf('$');
56 if (n > -1) {
57
58 packages.put(className.substring(n + 1), name);
59 packages.put(className.replace('$', '.'), name);
60 }
61
62 return name;
63 }
64
65 private void parseClassName(String[] names) {
66 if (names != null) {
67 for (String s : names) {
68 parseClassName(s);
69 }
70 }
71 }
72
73 private void extractSignature(String sig) {
74 if (sig != null) {
75 new SignatureReader(sig).accept(sigVisitor);
76 }
77 }
78
79
80
81 public void visit(int version, int access, String name, String sig, String superName, String[] interfaces) {
82 parseClassName(name);
83 parseClassName(interfaces);
84 if (sig != null) {
85 extractSignature(sig);
86 }
87 }
88
89 public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
90 addType(Type.getType(desc));
91 return annotationVisitor;
92 }
93
94 public FieldVisitor visitField(int access, String name, String desc, String sig, Object value) {
95 if (sig != null) {
96 extractSignature(sig);
97 }
98
99 addType(Type.getType(desc));
100 if (value instanceof Type) {
101 addType((Type) value);
102 }
103 return fieldVisitor;
104 }
105
106 public MethodVisitor visitMethod(int access, String name, String desc, String sig, String[] exceptions) {
107 if (sig != null) {
108 extractSignature(sig);
109 }
110 addMethodDesc(desc);
111 parseClassName(exceptions);
112 return methodVisitor;
113 }
114
115 public void visitSource(String source, String debug) {
116 }
117
118 public void visitInnerClass(String name, String outerName, String innerName, int access) {
119 if (innerClasses == null) {
120 innerClasses = new ArrayList<String>();
121 }
122 if (!innerClasses.contains(name.replace('/', '.'))) {
123 innerClasses.add(name.replace('/', '.'));
124 }
125 packages.put(innerName, name.replace('/', '.'));
126 }
127
128 public void visitOuterClass(String owner, String name, String desc) {
129 }
130
131 public void visitEnd() {
132 }
133
134 private void addMethodDesc(String desc) {
135 addTypes(desc);
136 addType(Type.getReturnType(desc));
137 }
138
139 private void addTypes(String desc) {
140 Type[] types = Type.getArgumentTypes(desc);
141 for (Type type : types) {
142 addType(type);
143 }
144 }
145
146 private void addType(Type t) {
147 switch (t.getSort()) {
148 case Type.ARRAY:
149 addType(t.getElementType());
150 break;
151 case Type.OBJECT:
152 parseClassName(t.getClassName().replace('.', '/'));
153 break;
154 default:
155
156 break;
157 }
158 }
159
160 public void visitAttribute(Attribute attr) {
161 }
162
163
164
165
166
167 private static class PMDFieldVisitor implements FieldVisitor {
168
169 private PMDASMVisitor parent;
170
171 public PMDFieldVisitor(PMDASMVisitor visitor) {
172 parent = visitor;
173 }
174
175 public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
176 parent.addType(Type.getType(desc));
177 return parent.annotationVisitor;
178 }
179
180 public void visitAttribute(Attribute attr) {
181 }
182
183 public void visitEnd() {
184 }
185 }
186
187 private static class PMDAnnotationVisitor implements AnnotationVisitor {
188 private PMDASMVisitor parent;
189
190 public PMDAnnotationVisitor(PMDASMVisitor visitor) {
191 parent = visitor;
192 }
193
194 public AnnotationVisitor visitAnnotation(String name, String desc) {
195 parent.addType(Type.getType(desc));
196 return this;
197 }
198
199 public void visitEnum(String name, String desc, String value) {
200 parent.addType(Type.getType(desc));
201 }
202
203 public AnnotationVisitor visitArray(String name) {
204 return this;
205 }
206
207 public void visitEnd() {
208 }
209
210 public void visit(String name, Object value) {
211 if (value instanceof Type) {
212 parent.addType((Type) value);
213 }
214 }
215 }
216
217 private static class PMDSignatureVisitor implements SignatureVisitor {
218 private PMDASMVisitor parent;
219
220 public PMDSignatureVisitor(PMDASMVisitor visitor) {
221 this.parent = visitor;
222 }
223
224 public void visitFormalTypeParameter(String name) {
225 }
226
227 public SignatureVisitor visitClassBound() {
228 return this;
229 }
230
231 public SignatureVisitor visitInterfaceBound() {
232 return this;
233 }
234
235 public SignatureVisitor visitSuperclass() {
236 return this;
237 }
238
239 public SignatureVisitor visitInterface() {
240 return this;
241 }
242
243 public SignatureVisitor visitParameterType() {
244 return this;
245 }
246
247 public SignatureVisitor visitReturnType() {
248 return this;
249 }
250
251 public SignatureVisitor visitExceptionType() {
252 return this;
253 }
254
255 public void visitBaseType(char descriptor) {
256 }
257
258 public void visitTypeVariable(String name) {
259 }
260
261 public SignatureVisitor visitArrayType() {
262 return this;
263 }
264
265 public void visitClassType(String name) {
266 parent.parseClassName(name);
267 }
268
269 public void visitInnerClassType(String name) {
270 parent.parseClassName(name);
271 }
272
273 public void visitTypeArgument() {
274 }
275
276 public SignatureVisitor visitTypeArgument(char wildcard) {
277 return this;
278 }
279
280 public void visitEnd() {
281 }
282 }
283
284 private static class PMDMethodVisitor implements MethodVisitor {
285 private PMDASMVisitor parent;
286
287 public PMDMethodVisitor(PMDASMVisitor visitor) {
288 parent = visitor;
289 }
290
291 public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
292 parent.addType(Type.getType(desc));
293 return parent.annotationVisitor;
294 }
295
296 public AnnotationVisitor visitAnnotation(String name, String desc) {
297 parent.addType(Type.getType(desc));
298 return parent.annotationVisitor;
299 }
300
301 public void visitTypeInsn(int opcode, String desc) {
302 if (desc.charAt(0) == '[') {
303 parent.addType(Type.getType(desc));
304 } else {
305 parent.parseClassName(desc);
306 }
307 }
308
309 public void visitFieldInsn(int opcode, String owner, String name, String desc) {
310 parent.parseClassName(owner);
311 parent.addType(Type.getType(desc));
312 }
313
314 public void visitMethodInsn(int opcode, String owner, String name, String desc) {
315 parent.parseClassName(owner);
316 parent.addMethodDesc(desc);
317 }
318
319
320
321
322
323
324
325
326 public void visitLdcInsn(Object cst) {
327 if (cst instanceof Type) {
328 parent.addType((Type) cst);
329 } else if (cst instanceof String) {
330 parent.parseClassName((String) cst);
331 }
332 }
333 public void visitMultiANewArrayInsn(String desc, int dims) {
334 parent.addType(Type.getType(desc));
335 }
336
337 public void visitLocalVariable(String name, String desc, String sig, Label start, Label end, int index) {
338 parent.extractSignature(sig);
339 }
340
341 public void visitCode() {
342 }
343
344 public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
345 }
346
347 public void visitInsn(int opcode) {
348 }
349
350 public void visitIntInsn(int opcode, int operand) {
351 }
352
353 public void visitVarInsn(int opcode, int var) {
354 }
355
356 public void visitJumpInsn(int opcode, Label label) {
357 }
358
359 public void visitLabel(Label label) {
360 }
361
362 public void visitIincInsn(int var, int increment) {
363 }
364
365 public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
366 }
367
368 public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
369 }
370
371 public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
372 parent.parseClassName(type);
373 }
374
375 public void visitLineNumber(int line, Label start) {
376 }
377
378 public void visitMaxs(int maxStack, int maxLocals) {
379 }
380
381 public AnnotationVisitor visitAnnotationDefault() {
382 return parent.annotationVisitor;
383 }
384
385 public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
386 parent.addType(Type.getType(desc));
387 return parent.annotationVisitor;
388 }
389
390 public void visitEnd() {
391 }
392
393 public void visitAttribute(Attribute attr) {
394 }
395
396 }
397 }