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 }