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  		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 				// Is there another way to get Array Classes?
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 }