1
2
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
28 private int typeType;
29
30
31 private Class<?> type;
32
33
34 private int arrayDimensions = 0;
35
36
37 private Class<?> fieldType;
38
39
40 private Class<?> returnType;
41
42
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
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 }