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