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.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      // The type of the current Type
27      private int typeType;
28  
29      // The current Type identified.
30      private Class<?> type;
31  
32      // The number of dimensions on an array for the current Type.
33      private int arrayDimensions = 0;
34  
35      // Completed Field Type is stored here
36      private Class<?> fieldType;
37  
38      // Completed Return Type is stored here
39      private Class<?> returnType;
40  
41      // Completed Parameter Types are stored here
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 		// Is there another way to get Array Classes?
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 }