View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.dcd.asm;
5   
6   import java.lang.reflect.Array;
7   import java.util.ArrayList;
8   import java.util.List;
9   
10  import net.sourceforge.pmd.dcd.ClassLoaderUtil;
11  
12  import org.objectweb.asm.Opcodes;
13  import org.objectweb.asm.signature.SignatureVisitor;
14  
15  public class TypeSignatureVisitor extends SignatureVisitor {
16  
17      private static final boolean TRACE = false;
18  
19      private static final int NO_TYPE = 0;
20  
21      private static final int FIELD_TYPE = 1;
22  
23      private static final int RETURN_TYPE = 2;
24  
25      private static final int PARAMETER_TYPE = 3;
26  
27      // The type of the current Type
28      private int typeType;
29  
30      // The current Type identified.
31      private Class<?> type;
32  
33      // The number of dimensions on an array for the current Type.
34      private int arrayDimensions = 0;
35  
36      // Completed Field Type is stored here
37      private Class<?> fieldType;
38  
39      // Completed Return Type is stored here
40      private Class<?> returnType;
41  
42      // Completed Parameter Types are stored here
43      private List<Class<?>> parameterTypes = new ArrayList<Class<?>>(0);
44  
45      private final PrintVisitor p;
46      protected void println(String s) {
47          p.println(s);
48      }
49      protected void printlnIndent(String s) {
50          p.printlnIndent(s);
51      }
52  
53      public TypeSignatureVisitor() {
54          super(Opcodes.ASM4);
55          p = new PrintVisitor();
56  	init();
57      }
58  
59      public TypeSignatureVisitor(PrintVisitor parent) {
60  	super(Opcodes.ASM4);
61  	p = new PrintVisitor(parent);
62  	init();
63      }
64  
65      public void init() {
66  	typeType = FIELD_TYPE;
67  	type = null;
68  	arrayDimensions = 0;
69  	parameterTypes.clear();
70      }
71  
72      public Class<?> getFieldType() {
73  	popType();
74  	if (fieldType == null) {
75  	    throw new RuntimeException();
76  	}
77  	return fieldType;
78      }
79  
80      public Class<?> getMethodReturnType() {
81  	popType();
82  	if (returnType == null) {
83  	    throw new RuntimeException();
84  	}
85  	return returnType;
86      }
87  
88      public Class<?>[] getMethodParameterTypes() {
89  	popType();
90  	if (parameterTypes == null) {
91  	    throw new RuntimeException();
92  	}
93  	if (parameterTypes != null) {
94  	    return parameterTypes.toArray(new Class<?>[parameterTypes.size()]);
95  	} else {
96  	    return null;
97  	}
98      }
99  
100     private void pushType(int type) {
101 	this.typeType = type;
102     }
103 
104     private void popType() {
105 	switch (typeType) {
106 	case NO_TYPE:
107 	    break;
108 	case FIELD_TYPE:
109 	    fieldType = getType();
110 	    break;
111 	case RETURN_TYPE:
112 	    returnType = getType();
113 	    break;
114 	case PARAMETER_TYPE:
115 	    parameterTypes.add(getType());
116 	    break;
117 	default:
118 	    throw new RuntimeException("Unknown type type: " + typeType);
119 	}
120 
121 	typeType = NO_TYPE;
122 	type = null;
123 	arrayDimensions = 0;
124     }
125 
126     private Class<?> getType() {
127 	Class<?> type = null;
128 	if (this.type != null) {
129 	    type = this.type;
130 	    for (int i = 0; i < arrayDimensions; i++) {
131 		// Is there another way to get Array Classes?
132 		Object array = Array.newInstance(type, 0);
133 		type = array.getClass();
134 	    }
135 	}
136 	return type;
137     }
138 
139     public SignatureVisitor visitArrayType() {
140 	if (TRACE) {
141 	    println("visitArrayType:");
142 	}
143 	arrayDimensions++;
144 	return this;
145     }
146 
147     public void visitBaseType(char descriptor) {
148 	if (TRACE) {
149 	    println("visitBaseType:");
150 	    printlnIndent("descriptor: " + descriptor);
151 	}
152 	switch (descriptor) {
153 	case 'B':
154 	    type = Byte.TYPE;
155 	    break;
156 	case 'C':
157 	    type = Character.TYPE;
158 	    break;
159 	case 'D':
160 	    type = Double.TYPE;
161 	    break;
162 	case 'F':
163 	    type = Float.TYPE;
164 	    break;
165 	case 'I':
166 	    type = Integer.TYPE;
167 	    break;
168 	case 'J':
169 	    type = Long.TYPE;
170 	    break;
171 	case 'S':
172 	    type = Short.TYPE;
173 	    break;
174 	case 'Z':
175 	    type = Boolean.TYPE;
176 	    break;
177 	case 'V':
178 	    type = Void.TYPE;
179 	    break;
180 	default:
181 	    throw new RuntimeException("Unknown baseType descriptor: " + descriptor);
182 	}
183     }
184 
185     public SignatureVisitor visitClassBound() {
186 	if (TRACE) {
187 	    println("visitClassBound:");
188 	}
189 	return this;
190     }
191 
192     public void visitClassType(String name) {
193 	if (TRACE) {
194 	    println("visitClassType:");
195 	    printlnIndent("name: " + name);
196 	}
197 	name = ClassLoaderUtil.fromInternalForm(name);
198 	this.type = ClassLoaderUtil.getClass(name);
199     }
200 
201     public void visitEnd() {
202 	if (TRACE) {
203 	    println("visitEnd:");
204 	}
205 	popType();
206     }
207 
208     public SignatureVisitor visitExceptionType() {
209 	if (TRACE) {
210 	    println("visitExceptionType:");
211 	}
212 	return this;
213     }
214 
215     public void visitFormalTypeParameter(String name) {
216 	if (TRACE) {
217 	    println("visitFormalTypeParameter:");
218 	    printlnIndent("name: " + name);
219 	}
220     }
221 
222     public void visitInnerClassType(String name) {
223 	if (TRACE) {
224 	    println("visitInnerClassType:");
225 	    printlnIndent("name: " + name);
226 	}
227     }
228 
229     public SignatureVisitor visitInterface() {
230 	if (TRACE) {
231 	    println("visitInterface:");
232 	}
233 	return this;
234     }
235 
236     public SignatureVisitor visitInterfaceBound() {
237 	if (TRACE) {
238 	    println("visitInterfaceBound:");
239 	}
240 	return this;
241     }
242 
243     public SignatureVisitor visitParameterType() {
244 	if (TRACE) {
245 	    println("visitParameterType:");
246 	}
247 	popType();
248 	pushType(PARAMETER_TYPE);
249 	return this;
250     }
251 
252     public SignatureVisitor visitReturnType() {
253 	if (TRACE) {
254 	    println("visitReturnType:");
255 	}
256 	popType();
257 	pushType(RETURN_TYPE);
258 	return this;
259     }
260 
261     public SignatureVisitor visitSuperclass() {
262 	if (TRACE) {
263 	    println("visitSuperclass:");
264 	}
265 	return this;
266     }
267 
268     public void visitTypeArgument() {
269 	if (TRACE) {
270 	    println("visitTypeArgument:");
271 	}
272     }
273 
274     public SignatureVisitor visitTypeArgument(char wildcard) {
275 	if (TRACE) {
276 	    println("visitTypeArgument:");
277 	    printlnIndent("wildcard: " + wildcard);
278 	}
279 	return this;
280     }
281 
282     public void visitTypeVariable(String name) {
283 	if (TRACE) {
284 	    println("visitTypeVariable:");
285 	    printlnIndent("name: " + name);
286 	}
287     }
288 }