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 }