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