diff options
author | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2004-10-18 18:53:57 +0000 |
---|---|---|
committer | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2004-10-18 18:53:57 +0000 |
commit | 86309c3ef22ce216bc861974bfe13b07aafe09f1 (patch) | |
tree | 92bb3d1e1cd8c51ef0a745f783b1f9a4ad46fe10 /src/main | |
parent | 56c38f0ea0572dda6fdf7fcbe4762ca785bb359d (diff) | |
download | javassist-86309c3ef22ce216bc861974bfe13b07aafe09f1.tar.gz javassist-86309c3ef22ce216bc861974bfe13b07aafe09f1.zip |
reformatted.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@143 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main')
-rw-r--r-- | src/main/javassist/CannotCompileException.java | 17 | ||||
-rw-r--r-- | src/main/javassist/bytecode/Descriptor.java | 1230 | ||||
-rw-r--r-- | src/main/javassist/compiler/CodeGen.java | 2 |
3 files changed, 611 insertions, 638 deletions
diff --git a/src/main/javassist/CannotCompileException.java b/src/main/javassist/CannotCompileException.java index f01a79a0..04266281 100644 --- a/src/main/javassist/CannotCompileException.java +++ b/src/main/javassist/CannotCompileException.java @@ -33,6 +33,8 @@ public class CannotCompileException extends Exception { /** * Constructs a CannotCompileException with a message. + * + * @param msg the message. */ public CannotCompileException(String msg) { super(msg); @@ -41,7 +43,10 @@ public class CannotCompileException extends Exception { } /** - * Constructs a CannotCompileException with an <code>Exception</code>. + * Constructs a CannotCompileException with an <code>Exception</code> + * representing the cause. + * + * @param e the cause. */ public CannotCompileException(Throwable e) { super("by " + e.toString()); @@ -49,6 +54,13 @@ public class CannotCompileException extends Exception { cause = e; } + /** + * Constructs a CannotCompileException with a detailed message + * and an <code>Exception</code> representing the cause. + * + * @param msg the message. + * @param e the cause. + */ public CannotCompileException(String msg, Throwable e) { this(msg); cause = e; @@ -66,8 +78,7 @@ public class CannotCompileException extends Exception { * Constructs a CannotCompileException with an <code>CompileError</code>. */ public CannotCompileException(CompileError e) { - super("[source error] " + e.getMessage(), e); - message = null; + this("[source error] " + e.getMessage(), e); } /** diff --git a/src/main/javassist/bytecode/Descriptor.java b/src/main/javassist/bytecode/Descriptor.java index 1128d7e3..1b07548c 100644 --- a/src/main/javassist/bytecode/Descriptor.java +++ b/src/main/javassist/bytecode/Descriptor.java @@ -19,660 +19,622 @@ import javassist.ClassPool; import javassist.CtClass; import javassist.CtPrimitiveType; import javassist.NotFoundException; - import java.util.Map; /** * A support class for dealing with descriptors. - * <p/> + * * <p>See chapter 4.3 in "The Java Virtual Machine Specification (2nd ed.)" */ -public class Descriptor -{ - /** - * Converts a class name into the internal representation used in - * the JVM. - * <p/> - * <p>Note that <code>toJvmName(toJvmName(s))</code> is equivalent - * to <code>toJvmName(s)</code>. - */ - public static String toJvmName(String classname) - { - return classname.replace('.', '/'); - } - - /** - * Converts a class name from the internal representation used in - * the JVM to the normal one used in Java. - */ - public static String toJavaName(String classname) - { - return classname.replace('/', '.'); - } - - /** - * Returns the internal representation of the class name in the - * JVM. - */ - public static String toJvmName(CtClass clazz) - { - if (clazz.isArray()) - return of(clazz); - else - return toJvmName(clazz.getName()); - } - - /** - * Converts to a Java class name from a descriptor - */ - public static String toClassName(String descriptor) - { - if (descriptor.equals("V")) return "void"; - if (descriptor.equals("I")) return "int"; - if (descriptor.equals("B")) return "byte"; - if (descriptor.equals("J")) return "long"; - if (descriptor.equals("D")) return "double"; - if (descriptor.equals("F")) return "float"; - if (descriptor.equals("C")) return "char"; - if (descriptor.equals("S")) return "short"; - if (descriptor.equals("Z")) return "boolean"; - String newname = toJavaName(descriptor); - return newname.substring(1, newname.length() - 1); - } - - /** - * Converts to a descriptor from a Java class name - */ - public static String of(String classname) - { - if (classname.equals("void")) return "V"; - if (classname.equals("int")) return "I"; - if (classname.equals("byte")) return "B"; - if (classname.equals("long")) return "J"; - if (classname.equals("double")) return "D"; - if (classname.equals("float")) return "F"; - if (classname.equals("char")) return "C"; - if (classname.equals("short")) return "S"; - if (classname.equals("boolean")) return "Z"; - return "L" + toJvmName(classname) + ";"; - } - - /** - * Substitutes a class name - * in the given descriptor string. - * - * @param desc descriptor string - * @param oldname replaced JVM class name - * @param newname substituted JVM class name - * @see Descriptor#toJvmName(String) - */ - public static String rename(String desc, - String oldname, String newname) - { - if (desc.indexOf(oldname) < 0) - return desc; - - StringBuffer newdesc = new StringBuffer(); - int head = 0; - int i = 0; - for (; ;) - { - int j = desc.indexOf('L', i); - if (j < 0) - break; - else if (desc.startsWith(oldname, j + 1) - && desc.charAt(j + oldname.length() + 1) == ';') - { - newdesc.append(desc.substring(head, j)); +public class Descriptor { + /** + * Converts a class name into the internal representation used in + * the JVM. + * + * <p>Note that <code>toJvmName(toJvmName(s))</code> is equivalent + * to <code>toJvmName(s)</code>. + */ + public static String toJvmName(String classname) { + return classname.replace('.', '/'); + } + + /** + * Converts a class name from the internal representation used in + * the JVM to the normal one used in Java. + */ + public static String toJavaName(String classname) { + return classname.replace('/', '.'); + } + + /** + * Returns the internal representation of the class name in the + * JVM. + */ + public static String toJvmName(CtClass clazz) { + if (clazz.isArray()) + return of(clazz); + else + return toJvmName(clazz.getName()); + } + + /** + * Converts to a Java class name from a descriptor + */ + public static String toClassName(String descriptor) { + if (descriptor.equals("V")) + return "void"; + else if (descriptor.equals("I")) + return "int"; + else if (descriptor.equals("B")) + return "byte"; + else if (descriptor.equals("J")) + return "long"; + else if (descriptor.equals("D")) + return "double"; + else if (descriptor.equals("F")) + return "float"; + else if (descriptor.equals("C")) + return "char"; + else if (descriptor.equals("S")) + return "short"; + else if (descriptor.equals("Z")) + return "boolean"; + else { + String newname = toJavaName(descriptor); + return newname.substring(1, newname.length() - 1); + } + } + + /** + * Converts to a descriptor from a Java class name + */ + public static String of(String classname) { + if (classname.equals("void")) + return "V"; + else if (classname.equals("int")) + return "I"; + else if (classname.equals("byte")) + return "B"; + else if (classname.equals("long")) + return "J"; + else if (classname.equals("double")) + return "D"; + else if (classname.equals("float")) + return "F"; + else if (classname.equals("char")) + return "C"; + else if (classname.equals("short")) + return "S"; + else if (classname.equals("boolean")) + return "Z"; + else + return "L" + toJvmName(classname) + ";"; + } + + /** + * Substitutes a class name + * in the given descriptor string. + * + * @param desc descriptor string + * @param oldname replaced JVM class name + * @param newname substituted JVM class name + * + * @see Descriptor#toJvmName(String) + */ + public static String rename(String desc, String oldname, String newname) { + if (desc.indexOf(oldname) < 0) + return desc; + + StringBuffer newdesc = new StringBuffer(); + int head = 0; + int i = 0; + for (;;) { + int j = desc.indexOf('L', i); + if (j < 0) + break; + else if (desc.startsWith(oldname, j + 1) + && desc.charAt(j + oldname.length() + 1) == ';') { + newdesc.append(desc.substring(head, j)); + newdesc.append('L'); + newdesc.append(newname); + newdesc.append(';'); + head = i = j + oldname.length() + 2; + } + else { + i = desc.indexOf(';', j) + 1; + if (i < 1) + break; // ';' was not found. + } + } + + if (head == 0) + return desc; + else { + int len = desc.length(); + if (head < len) + newdesc.append(desc.substring(head, len)); + + return newdesc.toString(); + } + } + + /** + * Substitutes class names in the given descriptor string + * according to the given <code>map</code>. + * + * @param map a map between replaced and substituted + * JVM class names. + * @see Descriptor#toJvmName(String) + */ + public static String rename(String desc, Map map) { + if (map == null) + return desc; + + StringBuffer newdesc = new StringBuffer(); + int head = 0; + int i = 0; + for (;;) { + int j = desc.indexOf('L', i); + if (j < 0) + break; + + int k = desc.indexOf(';', j); + if (k < 0) + break; + + i = k + 1; + String name = desc.substring(j + 1, k); + String name2 = (String)map.get(name); + if (name2 != null) { + newdesc.append(desc.substring(head, j)); + newdesc.append('L'); + newdesc.append(name2); + newdesc.append(';'); + head = i; + } + } + + if (head == 0) + return desc; + else { + int len = desc.length(); + if (head < len) + newdesc.append(desc.substring(head, len)); + + return newdesc.toString(); + } + } + + /** + * Returns the descriptor representing the given type. + */ + public static String of(CtClass type) { + StringBuffer sbuf = new StringBuffer(); + toDescriptor(sbuf, type); + return sbuf.toString(); + } + + private static void toDescriptor(StringBuffer desc, CtClass type) { + if (type.isArray()) { + desc.append('['); + try { + toDescriptor(desc, type.getComponentType()); + } + catch (NotFoundException e) { + desc.append('L'); + String name = type.getName(); + desc.append(toJvmName(name.substring(0, name.length() - 2))); + desc.append(';'); + } + } + else if (type.isPrimitive()) { + CtPrimitiveType pt = (CtPrimitiveType)type; + desc.append(pt.getDescriptor()); + } + else { // class type + desc.append('L'); + desc.append(type.getName().replace('.', '/')); + desc.append(';'); + } + } + + /** + * Returns the descriptor representing a constructor receiving + * the given parameter types. + * + * @param paramTypes parameter types + */ + public static String ofConstructor(CtClass[] paramTypes) { + return ofMethod(CtClass.voidType, paramTypes); + } + + /** + * Returns the descriptor representing a method that receives + * the given parameter types and returns the given type. + * + * @param returnType return type + * @param paramTypes parameter types + */ + public static String ofMethod(CtClass returnType, CtClass[] paramTypes) { + StringBuffer desc = new StringBuffer(); + desc.append('('); + if (paramTypes != null) { + int n = paramTypes.length; + for (int i = 0; i < n; ++i) + toDescriptor(desc, paramTypes[i]); + } + + desc.append(')'); + if (returnType != null) + toDescriptor(desc, returnType); + + return desc.toString(); + } + + /** + * Returns the descriptor representing a list of parameter types. + * For example, if the given parameter types are two <code>int</code>, + * then this method returns <code>"(II)"</code>. + * + * @param paramTypes parameter types + */ + public static String ofParameters(CtClass[] paramTypes) { + return ofMethod(null, paramTypes); + } + + /** + * Appends a parameter type to the parameter list represented + * by the given descriptor. + * + * <p><code>classname</code> must not be an array type. + * + * @param classname parameter type (not primitive type) + * @param desc descriptor + */ + public static String appendParameter(String classname, String desc) { + int i = desc.indexOf(')'); + if (i < 0) + return desc; + else { + StringBuffer newdesc = new StringBuffer(); + newdesc.append(desc.substring(0, i)); newdesc.append('L'); - newdesc.append(newname); + newdesc.append(classname.replace('.', '/')); newdesc.append(';'); - head = i = j + oldname.length() + 2; - } - else - { - i = desc.indexOf(';', j) + 1; - if (i < 1) - break; // ';' was not found. - } - } - - if (head == 0) - return desc; - else - { - int len = desc.length(); - if (head < len) - newdesc.append(desc.substring(head, len)); - - return newdesc.toString(); - } - } - - /** - * Substitutes class names in the given descriptor string - * according to the given <code>map</code>. - * - * @param map a map between replaced and substituted - * JVM class names. - * @see Descriptor#toJvmName(String) - */ - public static String rename(String desc, Map map) - { - if (map == null) - return desc; - - StringBuffer newdesc = new StringBuffer(); - int head = 0; - int i = 0; - for (; ;) - { - int j = desc.indexOf('L', i); - if (j < 0) - break; - - int k = desc.indexOf(';', j); - if (k < 0) - break; - - i = k + 1; - String name = desc.substring(j + 1, k); - String name2 = (String) map.get(name); - if (name2 != null) - { - newdesc.append(desc.substring(head, j)); + newdesc.append(desc.substring(i)); + return newdesc.toString(); + } + } + + /** + * Inserts a parameter type at the beginning of the parameter + * list represented + * by the given descriptor. + * + * <p><code>classname</code> must not be an array type. + * + * @param classname parameter type (not primitive type) + * @param desc descriptor + */ + public static String insertParameter(String classname, String desc) { + if (desc.charAt(0) != '(') + return desc; + else + return "(L" + classname.replace('.', '/') + ';' + + desc.substring(1); + } + + /** + * Changes the return type included in the given descriptor. + * + * <p><code>classname</code> must not be an array type. + * + * @param classname return type + * @param desc descriptor + */ + public static String changeReturnType(String classname, String desc) { + int i = desc.indexOf(')'); + if (i < 0) + return desc; + else { + StringBuffer newdesc = new StringBuffer(); + newdesc.append(desc.substring(0, i + 1)); newdesc.append('L'); - newdesc.append(name2); + newdesc.append(classname.replace('.', '/')); newdesc.append(';'); - head = i; - } - } - - if (head == 0) - return desc; - else - { - int len = desc.length(); - if (head < len) - newdesc.append(desc.substring(head, len)); - - return newdesc.toString(); - } - } - - /** - * Returns the descriptor representing the given type. - */ - public static String of(CtClass type) - { - StringBuffer sbuf = new StringBuffer(); - toDescriptor(sbuf, type); - return sbuf.toString(); - } - - private static void toDescriptor(StringBuffer desc, CtClass type) - { - if (type.isArray()) - { - desc.append('['); - try - { - toDescriptor(desc, type.getComponentType()); - } - catch (NotFoundException e) - { - desc.append('L'); - String name = type.getName(); - desc.append(toJvmName(name.substring(0, name.length() - 2))); - desc.append(';'); - } - } - else if (type.isPrimitive()) - { - CtPrimitiveType pt = (CtPrimitiveType) type; - desc.append(pt.getDescriptor()); - } - else - { // class type - desc.append('L'); - desc.append(type.getName().replace('.', '/')); - desc.append(';'); - } - } - - /** - * Returns the descriptor representing a constructor receiving - * the given parameter types. - * - * @param paramTypes parameter types - */ - public static String ofConstructor(CtClass[] paramTypes) - { - return ofMethod(CtClass.voidType, paramTypes); - } - - /** - * Returns the descriptor representing a method that receives - * the given parameter types and returns the given type. - * - * @param returnType return type - * @param paramTypes parameter types - */ - public static String ofMethod(CtClass returnType, CtClass[] paramTypes) - { - StringBuffer desc = new StringBuffer(); - desc.append('('); - if (paramTypes != null) - { - int n = paramTypes.length; - for (int i = 0; i < n; ++i) - toDescriptor(desc, paramTypes[i]); - } - - desc.append(')'); - if (returnType != null) - toDescriptor(desc, returnType); - - return desc.toString(); - } - - /** - * Returns the descriptor representing a list of parameter types. - * For example, if the given parameter types are two <code>int</code>, - * then this method returns <code>"(II)"</code>. - * - * @param paramTypes parameter types - */ - public static String ofParameters(CtClass[] paramTypes) - { - return ofMethod(null, paramTypes); - } - - /** - * Appends a parameter type to the parameter list represented - * by the given descriptor. - * <p/> - * <p><code>classname</code> must not be an array type. - * - * @param classname parameter type (not primitive type) - * @param desc descriptor - */ - public static String appendParameter(String classname, - String desc) - { - int i = desc.indexOf(')'); - if (i < 0) - return desc; - else - { - StringBuffer newdesc = new StringBuffer(); - newdesc.append(desc.substring(0, i)); - newdesc.append('L'); - newdesc.append(classname.replace('.', '/')); - newdesc.append(';'); - newdesc.append(desc.substring(i)); - return newdesc.toString(); - } - } - - /** - * Inserts a parameter type at the beginning of the parameter - * list represented - * by the given descriptor. - * <p/> - * <p><code>classname</code> must not be an array type. - * - * @param classname parameter type (not primitive type) - * @param desc descriptor - */ - public static String insertParameter(String classname, - String desc) - { - if (desc.charAt(0) != '(') - return desc; - else - return "(L" + classname.replace('.', '/') + ';' - + desc.substring(1); - } - - /** - * Changes the return type included in the given descriptor. - * <p/> - * <p><code>classname</code> must not be an array type. - * - * @param classname return type - * @param desc descriptor - */ - public static String changeReturnType(String classname, String desc) - { - int i = desc.indexOf(')'); - if (i < 0) - return desc; - else - { - StringBuffer newdesc = new StringBuffer(); - newdesc.append(desc.substring(0, i + 1)); - newdesc.append('L'); - newdesc.append(classname.replace('.', '/')); - newdesc.append(';'); - return newdesc.toString(); - } - } - - /** - * Returns the <code>CtClass</code> objects representing the parameter - * types specified by the given descriptor. - * - * @param desc descriptor - * @param cp the class pool used for obtaining - * a <code>CtClass</code> object. - */ - public static CtClass[] getParameterTypes(String desc, ClassPool cp) - throws NotFoundException - { - if (desc.charAt(0) != '(') - return null; - else - { - int num = numOfParameters(desc); - CtClass[] args = new CtClass[num]; - int n = 0; - int i = 1; - do - { - i = toCtClass(cp, desc, i, args, n++); - } while (i > 0); - return args; - } - } - - /** - * Returns true if the list of the parameter types of desc1 is equal to - * that of desc2. - * For example, "(II)V" and "(II)I" are equal. - */ - public static boolean eqParamTypes(String desc1, String desc2) - { - if (desc1.charAt(0) != '(') - return false; - - for (int i = 0; true; ++i) - { - char c = desc1.charAt(i); - if (c != desc2.charAt(i)) + return newdesc.toString(); + } + } + + /** + * Returns the <code>CtClass</code> objects representing the parameter + * types specified by the given descriptor. + * + * @param desc descriptor + * @param cp the class pool used for obtaining + * a <code>CtClass</code> object. + */ + public static CtClass[] getParameterTypes(String desc, ClassPool cp) + throws NotFoundException + { + if (desc.charAt(0) != '(') + return null; + else { + int num = numOfParameters(desc); + CtClass[] args = new CtClass[num]; + int n = 0; + int i = 1; + do { + i = toCtClass(cp, desc, i, args, n++); + } while (i > 0); + return args; + } + } + + /** + * Returns true if the list of the parameter types of desc1 is equal to + * that of desc2. + * For example, "(II)V" and "(II)I" are equal. + */ + public static boolean eqParamTypes(String desc1, String desc2) { + if (desc1.charAt(0) != '(') return false; - if (c == ')') - return true; - } - } - - /** - * Returns the signature of the given descriptor. The signature does - * not include the return type. For example, the signature of "(I)V" - * is "(I)". - */ - public static String getParamDescriptor(String decl) - { - return decl.substring(0, decl.indexOf(')') + 1); - } - - /** - * Returns the <code>CtClass</code> object representing the return - * type specified by the given descriptor. - * - * @param desc descriptor - * @param cp the class pool used for obtaining - * a <code>CtClass</code> object. - */ - public static CtClass getReturnType(String desc, ClassPool cp) - throws NotFoundException - { - int i = desc.indexOf(')'); - if (i < 0) - return null; - else - { - CtClass[] type = new CtClass[1]; - toCtClass(cp, desc, i + 1, type, 0); - return type[0]; - } - } - - /** - * Returns the number of the prameters included in the given - * descriptor. - * - * @param desc descriptor - */ - public static int numOfParameters(String desc) - { - int n = 0; - int i = 1; - for (; ;) - { - char c = desc.charAt(i); - if (c == ')') - break; + for (int i = 0; true; ++i) { + char c = desc1.charAt(i); + if (c != desc2.charAt(i)) + return false; - while (c == '[') - c = desc.charAt(++i); - - if (c == 'L') - { - i = desc.indexOf(';', i) + 1; - if (i <= 0) - throw new IndexOutOfBoundsException("bad descriptor"); - } - else - ++i; - - ++n; - } - - return n; - } - - /** - * Returns a <code>CtClass</code> object representing the type - * specified by the given descriptor. - * <p/> - * <p>This method works even if the package-class separator is - * not <code>/</code> but <code>.</code> (period). For example, - * it accepts <code>Ljava.lang.Object;</code> - * as well as <code>Ljava/lang/Object;</code>. - * - * @param desc descriptor - * @param cp the class pool used for obtaining - * a <code>CtClass</code> object. - */ - public static CtClass toCtClass(String desc, ClassPool cp) - throws NotFoundException - { - CtClass[] clazz = new CtClass[1]; - int res = toCtClass(cp, desc, 0, clazz, 0); - if (res >= 0) - return clazz[0]; - else - { - // maybe, you forgot to surround the class name with - // L and ;. It violates the protocol, but I'm tolerant... - return cp.get(desc.replace('/', '.')); - } - } - - private static int toCtClass(ClassPool cp, String desc, int i, - CtClass[] args, int n) - throws NotFoundException - { - int i2; - String name; - - int arrayDim = 0; - char c = desc.charAt(i); - while (c == '[') - { - ++arrayDim; - c = desc.charAt(++i); - } - - if (c == 'L') - { - i2 = desc.indexOf(';', ++i); - name = desc.substring(i, i2++).replace('/', '.'); - } - else - { - CtClass type = toPrimitiveClass(c); - if (type == null) - return -1; // error - - i2 = i + 1; - if (arrayDim == 0) - { - args[n] = type; - return i2; // neither an array type or a class type - } - else - name = type.getName(); - } - - if (arrayDim > 0) - { - StringBuffer sbuf = new StringBuffer(name); - while (arrayDim-- > 0) - sbuf.append("[]"); - - name = sbuf.toString(); - } - - args[n] = cp.get(name); - return i2; - } - - private static CtClass toPrimitiveClass(char c) - { - CtClass type = null; - switch (c) - { - case 'Z': - type = CtClass.booleanType; - break; - case 'C': - type = CtClass.charType; - break; - case 'B': - type = CtClass.byteType; - break; - case 'S': - type = CtClass.shortType; - break; - case 'I': - type = CtClass.intType; - break; - case 'J': - type = CtClass.longType; - break; - case 'F': - type = CtClass.floatType; - break; - case 'D': - type = CtClass.doubleType; - break; - case 'V': - type = CtClass.voidType; - break; - } - - return type; - } - - /** - * Computes the dimension of the array represented by the given - * descriptor. For example, if the descriptor is <code>"[[I"</code>, - * then this method returns 2. - * - * @param desc the descriptor. - * @return 0 if the descriptor does not represent an array type. - */ - public static int arrayDimension(String desc) - { - int dim = 0; - while (desc.charAt(dim) == '[') - ++dim; - - return dim; - } - - /** - * Returns the descriptor of the type of the array component. - * For example, if the given descriptor is - * <code>"[[Ljava/lang/String;"</code> and the given dimension is 2, - * then this method returns <code>"Ljava/lang/String;"</code>. - * - * @param desc the descriptor. - * @param dim the array dimension. - */ - public static String toArrayComponent(String desc, int dim) - { - return desc.substring(dim); - } - - /** - * Computes the data size specified by the given descriptor. - * For example, if the descriptor is "D", this method returns 2. - * <p/> - * <p>If the descriptor represents a method type, this method returns - * (the size of the returned value) - (the sum of the data sizes - * of all the parameters). For example, if the descriptor is - * "(I)D", then this method returns 1 (= 2 - 1). - * - * @param desc descriptor - */ - public static int dataSize(String desc) - { - int n = 0; - char c = desc.charAt(0); - if (c == '(') - { - int i = 1; - for (; ;) - { - c = desc.charAt(i); if (c == ')') - { - c = desc.charAt(i + 1); - break; - } + return true; + } + } + + /** + * Returns the signature of the given descriptor. The signature does + * not include the return type. For example, the signature of "(I)V" + * is "(I)". + */ + public static String getParamDescriptor(String decl) { + return decl.substring(0, decl.indexOf(')') + 1); + } + + /** + * Returns the <code>CtClass</code> object representing the return + * type specified by the given descriptor. + * + * @param desc descriptor + * @param cp the class pool used for obtaining + * a <code>CtClass</code> object. + */ + public static CtClass getReturnType(String desc, ClassPool cp) + throws NotFoundException + { + int i = desc.indexOf(')'); + if (i < 0) + return null; + else { + CtClass[] type = new CtClass[1]; + toCtClass(cp, desc, i + 1, type, 0); + return type[0]; + } + } + + /** + * Returns the number of the prameters included in the given + * descriptor. + * + * @param desc descriptor + */ + public static int numOfParameters(String desc) { + int n = 0; + int i = 1; + for (;;) { + char c = desc.charAt(i); + if (c == ')') + break; - boolean array = false; while (c == '[') - { - array = true; - c = desc.charAt(++i); - } + c = desc.charAt(++i); - if (c == 'L') - { - i = desc.indexOf(';', i) + 1; - if (i <= 0) - throw new IndexOutOfBoundsException("bad descriptor"); + if (c == 'L') { + i = desc.indexOf(';', i) + 1; + if (i <= 0) + throw new IndexOutOfBoundsException("bad descriptor"); } else - ++i; - - if (!array && (c == 'J' || c == 'D')) - n -= 2; + ++i; + + ++n; + } + + return n; + } + + /** + * Returns a <code>CtClass</code> object representing the type + * specified by the given descriptor. + * + * <p>This method works even if the package-class separator is + * not <code>/</code> but <code>.</code> (period). For example, + * it accepts <code>Ljava.lang.Object;</code> + * as well as <code>Ljava/lang/Object;</code>. + * + * @param desc descriptor + * @param cp the class pool used for obtaining + * a <code>CtClass</code> object. + */ + public static CtClass toCtClass(String desc, ClassPool cp) + throws NotFoundException + { + CtClass[] clazz = new CtClass[1]; + int res = toCtClass(cp, desc, 0, clazz, 0); + if (res >= 0) + return clazz[0]; + else { + // maybe, you forgot to surround the class name with + // L and ;. It violates the protocol, but I'm tolerant... + return cp.get(desc.replace('/', '.')); + } + } + + private static int toCtClass(ClassPool cp, String desc, int i, + CtClass[] args, int n) + throws NotFoundException + { + int i2; + String name; + + int arrayDim = 0; + char c = desc.charAt(i); + while (c == '[') { + ++arrayDim; + c = desc.charAt(++i); + } + + if (c == 'L') { + i2 = desc.indexOf(';', ++i); + name = desc.substring(i, i2++).replace('/', '.'); + } + else { + CtClass type = toPrimitiveClass(c); + if (type == null) + return -1; // error + + i2 = i + 1; + if (arrayDim == 0) { + args[n] = type; + return i2; // neither an array type or a class type + } else - --n; - } - } + name = type.getName(); + } + + if (arrayDim > 0) { + StringBuffer sbuf = new StringBuffer(name); + while (arrayDim-- > 0) + sbuf.append("[]"); + + name = sbuf.toString(); + } + + args[n] = cp.get(name); + return i2; + } + + private static CtClass toPrimitiveClass(char c) { + CtClass type = null; + switch (c) { + case 'Z' : + type = CtClass.booleanType; + break; + case 'C' : + type = CtClass.charType; + break; + case 'B' : + type = CtClass.byteType; + break; + case 'S' : + type = CtClass.shortType; + break; + case 'I' : + type = CtClass.intType; + break; + case 'J' : + type = CtClass.longType; + break; + case 'F' : + type = CtClass.floatType; + break; + case 'D' : + type = CtClass.doubleType; + break; + case 'V' : + type = CtClass.voidType; + break; + } + + return type; + } + + /** + * Computes the dimension of the array represented by the given + * descriptor. For example, if the descriptor is <code>"[[I"</code>, + * then this method returns 2. + * + * @param desc the descriptor. + * @return 0 if the descriptor does not represent an array type. + */ + public static int arrayDimension(String desc) { + int dim = 0; + while (desc.charAt(dim) == '[') + ++dim; + + return dim; + } + + /** + * Returns the descriptor of the type of the array component. + * For example, if the given descriptor is + * <code>"[[Ljava/lang/String;"</code> and the given dimension is 2, + * then this method returns <code>"Ljava/lang/String;"</code>. + * + * @param desc the descriptor. + * @param dim the array dimension. + */ + public static String toArrayComponent(String desc, int dim) { + return desc.substring(dim); + } + + /** + * Computes the data size specified by the given descriptor. + * For example, if the descriptor is "D", this method returns 2. + * + * <p>If the descriptor represents a method type, this method returns + * (the size of the returned value) - (the sum of the data sizes + * of all the parameters). For example, if the descriptor is + * "(I)D", then this method returns 1 (= 2 - 1). + * + * @param desc descriptor + */ + public static int dataSize(String desc) { + int n = 0; + char c = desc.charAt(0); + if (c == '(') { + int i = 1; + for (;;) { + c = desc.charAt(i); + if (c == ')') { + c = desc.charAt(i + 1); + break; + } + + boolean array = false; + while (c == '[') { + array = true; + c = desc.charAt(++i); + } + + if (c == 'L') { + i = desc.indexOf(';', i) + 1; + if (i <= 0) + throw new IndexOutOfBoundsException("bad descriptor"); + } + else + ++i; + + if (!array && (c == 'J' || c == 'D')) + n -= 2; + else + --n; + } + } - if (c == 'J' || c == 'D') - n += 2; - else if (c != 'V') - ++n; + if (c == 'J' || c == 'D') + n += 2; + else if (c != 'V') + ++n; - return n; - } + return n; + } } diff --git a/src/main/javassist/compiler/CodeGen.java b/src/main/javassist/compiler/CodeGen.java index 221cbfcd..3308a242 100644 --- a/src/main/javassist/compiler/CodeGen.java +++ b/src/main/javassist/compiler/CodeGen.java @@ -1370,7 +1370,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { bytecode.addIconst(0); } else if (token == CALL) // method call - fatal(); + fatal(); else { expr.oprand1().accept(this); int type = typePrecedence(exprType); |