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