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.Opcodes;
13 import org.objectweb.asm.Type;
14 import org.objectweb.asm.signature.SignatureReader;
15 import org.objectweb.asm.signature.SignatureVisitor;
16
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 import java.util.List;
20 import java.util.Map;
21
22 public class PMDASMVisitor extends ClassVisitor {
23
24 public PMDASMVisitor() {
25 super(Opcodes.ASM4);
26 }
27
28 private Map<String, String> packages = new HashMap<String, String>();
29
30 private AnnotationVisitor annotationVisitor = new PMDAnnotationVisitor(this);
31
32 private FieldVisitor fieldVisitor = new PMDFieldVisitor(this);
33
34 private SignatureVisitor sigVisitor = new PMDSignatureVisitor(this);
35
36 private MethodVisitor methodVisitor = new PMDMethodVisitor(this);
37
38 public List<String> innerClasses;
39
40 public Map<String, String> getPackages() {
41 return packages;
42 }
43
44 public List<String> getInnerClasses() {
45 return innerClasses;
46 }
47
48 private String parseClassName(String name) {
49 if (name == null) {
50 return null;
51 }
52
53 String className = name;
54 int n = name.lastIndexOf('/');
55 if (n > -1) {
56 className = name.substring(n + 1);
57 }
58 name = name.replace('/', '.');
59 packages.put(className, name);
60 n = className.indexOf('$');
61 if (n > -1) {
62
63 packages.put(className.substring(n + 1), name);
64 packages.put(className.replace('$', '.'), name);
65 }
66
67 return name;
68 }
69
70 private void parseClassName(String[] names) {
71 if (names != null) {
72 for (String s : names) {
73 parseClassName(s);
74 }
75 }
76 }
77
78 private void extractSignature(String sig) {
79 if (sig != null) {
80 new SignatureReader(sig).accept(sigVisitor);
81 }
82 }
83
84
85
86 public void visit(int version, int access, String name, String sig, String superName, String[] interfaces) {
87 parseClassName(name);
88 parseClassName(interfaces);
89 if (sig != null) {
90 extractSignature(sig);
91 }
92 }
93
94 public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
95 addType(Type.getType(desc));
96 return annotationVisitor;
97 }
98
99 public FieldVisitor visitField(int access, String name, String desc, String sig, Object value) {
100 if (sig != null) {
101 extractSignature(sig);
102 }
103
104 addType(Type.getType(desc));
105 if (value instanceof Type) {
106 addType((Type) value);
107 }
108 return fieldVisitor;
109 }
110
111 public MethodVisitor visitMethod(int access, String name, String desc, String sig, String[] exceptions) {
112 if (sig != null) {
113 extractSignature(sig);
114 }
115 addMethodDesc(desc);
116 parseClassName(exceptions);
117 return methodVisitor;
118 }
119
120 public void visitSource(String source, String debug) {
121 }
122
123 public void visitInnerClass(String name, String outerName, String innerName, int access) {
124 if (innerClasses == null) {
125 innerClasses = new ArrayList<String>();
126 }
127 if (!innerClasses.contains(name.replace('/', '.'))) {
128 innerClasses.add(name.replace('/', '.'));
129 }
130 packages.put(innerName, name.replace('/', '.'));
131 }
132
133 public void visitOuterClass(String owner, String name, String desc) {
134 }
135
136 public void visitEnd() {
137 }
138
139 private void addMethodDesc(String desc) {
140 addTypes(desc);
141 addType(Type.getReturnType(desc));
142 }
143
144 private void addTypes(String desc) {
145 Type[] types = Type.getArgumentTypes(desc);
146 for (Type type : types) {
147 addType(type);
148 }
149 }
150
151 private void addType(Type t) {
152 switch (t.getSort()) {
153 case Type.ARRAY:
154 addType(t.getElementType());
155 break;
156 case Type.OBJECT:
157 parseClassName(t.getClassName().replace('.', '/'));
158 break;
159 default:
160
161 break;
162 }
163 }
164
165 public void visitAttribute(Attribute attr) {
166 }
167
168
169
170
171
172 private static class PMDFieldVisitor extends FieldVisitor {
173
174 private PMDASMVisitor parent;
175
176 public PMDFieldVisitor(PMDASMVisitor visitor) {
177 super(Opcodes.ASM4);
178 parent = visitor;
179 }
180
181 public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
182 parent.addType(Type.getType(desc));
183 return parent.annotationVisitor;
184 }
185
186 public void visitAttribute(Attribute attr) {
187 }
188
189 public void visitEnd() {
190 }
191 }
192
193 private static class PMDAnnotationVisitor extends AnnotationVisitor {
194 private PMDASMVisitor parent;
195
196 public PMDAnnotationVisitor(PMDASMVisitor visitor) {
197 super(Opcodes.ASM4);
198 parent = visitor;
199 }
200
201 public AnnotationVisitor visitAnnotation(String name, String desc) {
202 parent.addType(Type.getType(desc));
203 return this;
204 }
205
206 public void visitEnum(String name, String desc, String value) {
207 parent.addType(Type.getType(desc));
208 }
209
210 public AnnotationVisitor visitArray(String name) {
211 return this;
212 }
213
214 public void visitEnd() {
215 }
216
217 public void visit(String name, Object value) {
218 if (value instanceof Type) {
219 parent.addType((Type) value);
220 }
221 }
222 }
223
224 private static class PMDSignatureVisitor extends SignatureVisitor {
225 private PMDASMVisitor parent;
226
227 public PMDSignatureVisitor(PMDASMVisitor visitor) {
228 super(Opcodes.ASM4);
229 this.parent = visitor;
230 }
231
232 public void visitFormalTypeParameter(String name) {
233 }
234
235 public SignatureVisitor visitClassBound() {
236 return this;
237 }
238
239 public SignatureVisitor visitInterfaceBound() {
240 return this;
241 }
242
243 public SignatureVisitor visitSuperclass() {
244 return this;
245 }
246
247 public SignatureVisitor visitInterface() {
248 return this;
249 }
250
251 public SignatureVisitor visitParameterType() {
252 return this;
253 }
254
255 public SignatureVisitor visitReturnType() {
256 return this;
257 }
258
259 public SignatureVisitor visitExceptionType() {
260 return this;
261 }
262
263 public void visitBaseType(char descriptor) {
264 }
265
266 public void visitTypeVariable(String name) {
267 }
268
269 public SignatureVisitor visitArrayType() {
270 return this;
271 }
272
273 public void visitClassType(String name) {
274 parent.parseClassName(name);
275 }
276
277 public void visitInnerClassType(String name) {
278 parent.parseClassName(name);
279 }
280
281 public void visitTypeArgument() {
282 }
283
284 public SignatureVisitor visitTypeArgument(char wildcard) {
285 return this;
286 }
287
288 public void visitEnd() {
289 }
290 }
291
292 private static class PMDMethodVisitor extends MethodVisitor {
293 private PMDASMVisitor parent;
294
295 public PMDMethodVisitor(PMDASMVisitor visitor) {
296 super(Opcodes.ASM4);
297 parent = visitor;
298 }
299
300 public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
301 parent.addType(Type.getType(desc));
302 return parent.annotationVisitor;
303 }
304
305 public AnnotationVisitor visitAnnotation(String name, String desc) {
306 parent.addType(Type.getType(desc));
307 return parent.annotationVisitor;
308 }
309
310 public void visitTypeInsn(int opcode, String desc) {
311 if (desc.charAt(0) == '[') {
312 parent.addType(Type.getType(desc));
313 } else {
314 parent.parseClassName(desc);
315 }
316 }
317
318 public void visitFieldInsn(int opcode, String owner, String name, String desc) {
319 parent.parseClassName(owner);
320 parent.addType(Type.getType(desc));
321 }
322
323 public void visitMethodInsn(int opcode, String owner, String name, String desc) {
324 parent.parseClassName(owner);
325 parent.addMethodDesc(desc);
326 }
327
328
329
330
331
332
333
334
335 public void visitLdcInsn(Object cst) {
336 if (cst instanceof Type) {
337 parent.addType((Type) cst);
338 } else if (cst instanceof String) {
339 parent.parseClassName((String) cst);
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 }