001: /**
002: * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
003: */package net.sourceforge.pmd.typeresolution.visitors;
004:
005: import org.objectweb.asm.AnnotationVisitor;
006: import org.objectweb.asm.Attribute;
007: import org.objectweb.asm.ClassVisitor;
008: import org.objectweb.asm.FieldVisitor;
009: import org.objectweb.asm.Label;
010: import org.objectweb.asm.MethodVisitor;
011: import org.objectweb.asm.Type;
012: import org.objectweb.asm.signature.SignatureReader;
013: import org.objectweb.asm.signature.SignatureVisitor;
014:
015: import java.util.ArrayList;
016: import java.util.HashMap;
017: import java.util.List;
018: import java.util.Map;
019:
020: public class PMDASMVisitor implements ClassVisitor {
021:
022: private Map<String, String> packages = new HashMap<String, String>();
023:
024: private AnnotationVisitor annotationVisitor = new PMDAnnotationVisitor(
025: this );
026:
027: private FieldVisitor fieldVisitor = new PMDFieldVisitor(this );
028:
029: private SignatureVisitor sigVisitor = new PMDSignatureVisitor(this );
030:
031: private MethodVisitor methodVisitor = new PMDMethodVisitor(this );
032:
033: public List<String> innerClasses;
034:
035: public Map<String, String> getPackages() {
036: return packages;
037: }
038:
039: public List<String> getInnerClasses() {
040: return innerClasses;
041: }
042:
043: private String parseClassName(String name) {
044: if (name == null) {
045: return null;
046: }
047:
048: String className = name;
049: int n = name.lastIndexOf('/');
050: if (n > -1) {
051: className = name.substring(n + 1);
052: }
053: name = name.replace('/', '.');
054: packages.put(className, name);
055: n = className.indexOf('$');
056: if (n > -1) {
057: //TODO I don't think the first one, with Class$Inner is needed - come back and check
058: packages.put(className.substring(n + 1), name);
059: packages.put(className.replace('$', '.'), name);
060: }
061:
062: return name;
063: }
064:
065: private void parseClassName(String[] names) {
066: if (names != null) {
067: for (String s : names) {
068: parseClassName(s);
069: }
070: }
071: }
072:
073: private void extractSignature(String sig) {
074: if (sig != null) {
075: new SignatureReader(sig).accept(sigVisitor);
076: }
077: }
078:
079: /* Start ClassVisitor implementations */
080:
081: public void visit(int version, int access, String name, String sig,
082: String super Name, String[] interfaces) {
083: parseClassName(name);
084: parseClassName(interfaces);
085: if (sig != null) {
086: extractSignature(sig);
087: }
088: }
089:
090: public AnnotationVisitor visitAnnotation(String desc,
091: boolean visible) {
092: addType(Type.getType(desc));
093: return annotationVisitor;
094: }
095:
096: public FieldVisitor visitField(int access, String name,
097: String desc, String sig, Object value) {
098: if (sig != null) {
099: extractSignature(sig);
100: }
101:
102: addType(Type.getType(desc));
103: if (value instanceof Type) {
104: addType((Type) value);
105: }
106: return fieldVisitor;
107: }
108:
109: public MethodVisitor visitMethod(int access, String name,
110: 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,
123: 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: }
160: }
161:
162: public void visitAttribute(Attribute attr) {
163: }
164:
165: /*
166: * Start visitors
167: */
168:
169: private static class PMDFieldVisitor implements FieldVisitor {
170:
171: private PMDASMVisitor parent;
172:
173: public PMDFieldVisitor(PMDASMVisitor visitor) {
174: parent = visitor;
175: }
176:
177: public AnnotationVisitor visitAnnotation(String desc,
178: boolean visible) {
179: parent.addType(Type.getType(desc));
180: return parent.annotationVisitor;
181: }
182:
183: public void visitAttribute(Attribute attr) {
184: }
185:
186: public void visitEnd() {
187: }
188: }
189:
190: private static class PMDAnnotationVisitor implements
191: AnnotationVisitor {
192: private PMDASMVisitor parent;
193:
194: public PMDAnnotationVisitor(PMDASMVisitor visitor) {
195: parent = visitor;
196: }
197:
198: public AnnotationVisitor visitAnnotation(String name,
199: String desc) {
200: parent.addType(Type.getType(desc));
201: return this ;
202: }
203:
204: public void visitEnum(String name, String desc, String value) {
205: parent.addType(Type.getType(desc));
206: }
207:
208: public AnnotationVisitor visitArray(String name) {
209: return this ;
210: }
211:
212: public void visitEnd() {
213: }
214:
215: public void visit(String name, Object value) {
216: if (value instanceof Type) {
217: parent.addType((Type) value);
218: }
219: }
220: }
221:
222: private static class PMDSignatureVisitor implements
223: SignatureVisitor {
224: private PMDASMVisitor parent;
225:
226: public PMDSignatureVisitor(PMDASMVisitor visitor) {
227: this .parent = visitor;
228: }
229:
230: public void visitFormalTypeParameter(String name) {
231: }
232:
233: public SignatureVisitor visitClassBound() {
234: return this ;
235: }
236:
237: public SignatureVisitor visitInterfaceBound() {
238: return this ;
239: }
240:
241: public SignatureVisitor visitSuperclass() {
242: return this ;
243: }
244:
245: public SignatureVisitor visitInterface() {
246: return this ;
247: }
248:
249: public SignatureVisitor visitParameterType() {
250: return this ;
251: }
252:
253: public SignatureVisitor visitReturnType() {
254: return this ;
255: }
256:
257: public SignatureVisitor visitExceptionType() {
258: return this ;
259: }
260:
261: public void visitBaseType(char descriptor) {
262: }
263:
264: public void visitTypeVariable(String name) {
265: }
266:
267: public SignatureVisitor visitArrayType() {
268: return this ;
269: }
270:
271: public void visitClassType(String name) {
272: parent.parseClassName(name);
273: }
274:
275: public void visitInnerClassType(String name) {
276: parent.parseClassName(name);
277: }
278:
279: public void visitTypeArgument() {
280: }
281:
282: public SignatureVisitor visitTypeArgument(char wildcard) {
283: return this ;
284: }
285:
286: public void visitEnd() {
287: }
288: }
289:
290: private static class PMDMethodVisitor implements MethodVisitor {
291: private PMDASMVisitor parent;
292:
293: public PMDMethodVisitor(PMDASMVisitor visitor) {
294: parent = visitor;
295: }
296:
297: public AnnotationVisitor visitParameterAnnotation(
298: int parameter, String desc, boolean visible) {
299: parent.addType(Type.getType(desc));
300: return parent.annotationVisitor;
301: }
302:
303: public AnnotationVisitor visitAnnotation(String name,
304: 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,
318: String name, String desc) {
319: parent.parseClassName(owner);
320: parent.addType(Type.getType(desc));
321: }
322:
323: public void visitMethodInsn(int opcode, String owner,
324: String name, String desc) {
325: parent.parseClassName(owner);
326: parent.addMethodDesc(desc);
327: }
328:
329: /**
330: * the constant to be loaded on the stack. This parameter must be a non null
331: * Integer, a Float, a Long, a Double a String (or a Type for .class
332: * constants, for classes whose version is 49.0 or more).
333: *
334: * @see org.objectweb.asm.MethodVisitor#visitLdcInsn(java.lang.Object)
335: */
336: public void visitLdcInsn(Object cst) {
337: if (cst instanceof Type) {
338: parent.addType((Type) cst);
339: } else if (cst instanceof String) {
340: parent.parseClassName((String) cst);
341: }
342: }
343:
344: public void visitMultiANewArrayInsn(String desc, int dims) {
345: parent.addType(Type.getType(desc));
346: }
347:
348: public void visitLocalVariable(String name, String desc,
349: String sig, Label start, Label end, int index) {
350: parent.extractSignature(sig);
351: }
352:
353: public void visitCode() {
354: }
355:
356: public void visitFrame(int type, int nLocal, Object[] local,
357: int nStack, Object[] stack) {
358: }
359:
360: public void visitInsn(int opcode) {
361: }
362:
363: public void visitIntInsn(int opcode, int operand) {
364: }
365:
366: public void visitVarInsn(int opcode, int var) {
367: }
368:
369: public void visitJumpInsn(int opcode, Label label) {
370: }
371:
372: public void visitLabel(Label label) {
373: }
374:
375: public void visitIincInsn(int var, int increment) {
376: }
377:
378: public void visitTableSwitchInsn(int min, int max, Label dflt,
379: Label[] labels) {
380: }
381:
382: public void visitLookupSwitchInsn(Label dflt, int[] keys,
383: Label[] labels) {
384: }
385:
386: public void visitTryCatchBlock(Label start, Label end,
387: Label handler, String type) {
388: parent.parseClassName(type);
389: }
390:
391: public void visitLineNumber(int line, Label start) {
392: }
393:
394: public void visitMaxs(int maxStack, int maxLocals) {
395: }
396:
397: public AnnotationVisitor visitAnnotationDefault() {
398: return parent.annotationVisitor;
399: }
400:
401: public AnnotationVisitor visitAnnotation(String desc,
402: boolean visible) {
403: parent.addType(Type.getType(desc));
404: return parent.annotationVisitor;
405: }
406:
407: public void visitEnd() {
408: }
409:
410: public void visitAttribute(Attribute attr) {
411: }
412:
413: }
414: }
|