/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package net.sourceforge.phpdt.core; import net.sourceforge.phpdt.core.compiler.CharOperation; /** * Provides methods for encoding and decoding type and method signature strings. *

* The syntax for a type signature is: * *

 *  typeSignature ::=
 *      "B"  // byte
 *    | "C"  // char
 *    | "D"  // double
 *    | "F"  // float
 *    | "I"  // int
 *    | "J"  // long
 *    | "S"  // short
 *    | "V"  // void
 *    | "Z"  // boolean
 *    | "L" + binaryTypeName + ";"  // resolved named type (in compiled code)
 *    | "Q" + sourceTypeName + ";"  // unresolved named type (in source code)
 *    | "[" + typeSignature  // array of type denoted by typeSignature
 * 
* *

*

* Examples: *

*

*

* The syntax for a method signature is: * *

 *  methodSignature ::= "(" + paramTypeSignature* + ")" + returnTypeSignature
 *  paramTypeSignature ::= typeSignature
 *  returnTypeSignature ::= typeSignature
 * 
* *

* Examples: *

*

*

* This class provides static methods and constants only; it is not intended to * be instantiated or subclassed by clients. *

*/ public final class Signature { /** * Character constant indicating the primitive type boolean in a signature. * Value is 'Z'. */ public static final char C_BOOLEAN = 'Z'; /** * Character constant indicating the primitive type byte in a signature. * Value is 'B'. */ public static final char C_BYTE = 'B'; /** * Character constant indicating the primitive type char in a signature. * Value is 'C'. */ public static final char C_CHAR = 'C'; /** * Character constant indicating the primitive type double in a signature. * Value is 'D'. */ public static final char C_DOUBLE = 'D'; /** * Character constant indicating the primitive type float in a signature. * Value is 'F'. */ public static final char C_FLOAT = 'F'; /** * Character constant indicating the primitive type int in a signature. * Value is 'I'. */ public static final char C_INT = 'I'; /** * Character constant indicating the semicolon in a signature. Value is * ';'. */ public static final char C_SEMICOLON = ';'; /** * Character constant indicating the primitive type long in a signature. * Value is 'J'. */ public static final char C_LONG = 'J'; /** * Character constant indicating the primitive type short in a signature. * Value is 'S'. */ public static final char C_SHORT = 'S'; /** * Character constant indicating result type void in a signature. Value is * 'V'. */ public static final char C_VOID = 'V'; /** * Character constant indicating the dot in a signature. Value is * '.'. */ public static final char C_DOT = '.'; /** * Character constant indicating the dollar in a signature. Value is * '$'. */ public static final char C_DOLLAR = '$'; /** * Character constant indicating an array type in a signature. Value is * '['. */ public static final char C_ARRAY = '['; /** * Character constant indicating the start of a resolved, named type in a * signature. Value is 'L'. */ public static final char C_RESOLVED = 'L'; /** * Character constant indicating the start of an unresolved, named type in a * signature. Value is 'Q'. */ public static final char C_UNRESOLVED = 'Q'; /** * Character constant indicating the end of a named type in a signature. * Value is ';'. */ public static final char C_NAME_END = ';'; /** * Character constant indicating the start of a parameter type list in a * signature. Value is '('. */ public static final char C_PARAM_START = '('; /** * Character constant indicating the end of a parameter type list in a * signature. Value is ')'. */ public static final char C_PARAM_END = ')'; /** * String constant for the signature of the primitive type boolean. Value is * "Z". */ public static final String SIG_BOOLEAN = "Z"; //$NON-NLS-1$ /** * String constant for the signature of the primitive type byte. Value is * "B". */ public static final String SIG_BYTE = "B"; //$NON-NLS-1$ /** * String constant for the signature of the primitive type char. Value is * "C". */ public static final String SIG_CHAR = "C"; //$NON-NLS-1$ /** * String constant for the signature of the primitive type double. Value is * "D". */ public static final String SIG_DOUBLE = "D"; //$NON-NLS-1$ /** * String constant for the signature of the primitive type float. Value is * "F". */ public static final String SIG_FLOAT = "F"; //$NON-NLS-1$ /** * String constant for the signature of the primitive type int. Value is * "I". */ public static final String SIG_INT = "I"; //$NON-NLS-1$ /** * String constant for the signature of the primitive type long. Value is * "J". */ public static final String SIG_LONG = "J"; //$NON-NLS-1$ /** * String constant for the signature of the primitive type short. Value is * "S". */ public static final String SIG_SHORT = "S"; //$NON-NLS-1$ /** * String constant for the signature of result type void. Value is * "V". */ public static final String SIG_VOID = "V"; //$NON-NLS-1$ private static final char[] BOOLEAN = { 'b', 'o', 'o', 'l', 'e', 'a', 'n' }; private static final char[] BYTE = { 'b', 'y', 't', 'e' }; private static final char[] CHAR = { 'c', 'h', 'a', 'r' }; private static final char[] DOUBLE = { 'd', 'o', 'u', 'b', 'l', 'e' }; private static final char[] FLOAT = { 'f', 'l', 'o', 'a', 't' }; private static final char[] INT = { 'i', 'n', 't' }; private static final char[] LONG = { 'l', 'o', 'n', 'g' }; private static final char[] SHORT = { 's', 'h', 'o', 'r', 't' }; private static final char[] VOID = { 'v', 'o', 'i', 'd' }; private static final String EMPTY = new String(CharOperation.NO_CHAR); /** * Not instantiable. */ private Signature() { } private static long copyType(char[] signature, int sigPos, char[] dest, int index, boolean fullyQualifyTypeNames) { int arrayCount = 0; loop: while (true) { switch (signature[sigPos++]) { case C_ARRAY: arrayCount++; break; case C_BOOLEAN: int length = BOOLEAN.length; System.arraycopy(BOOLEAN, 0, dest, index, length); index += length; break loop; case C_BYTE: length = BYTE.length; System.arraycopy(BYTE, 0, dest, index, length); index += length; break loop; case C_CHAR: length = CHAR.length; System.arraycopy(CHAR, 0, dest, index, length); index += length; break loop; case C_DOUBLE: length = DOUBLE.length; System.arraycopy(DOUBLE, 0, dest, index, length); index += length; break loop; case C_FLOAT: length = FLOAT.length; System.arraycopy(FLOAT, 0, dest, index, length); index += length; break loop; case C_INT: length = INT.length; System.arraycopy(INT, 0, dest, index, length); index += length; break loop; case C_LONG: length = LONG.length; System.arraycopy(LONG, 0, dest, index, length); index += length; break loop; case C_SHORT: length = SHORT.length; System.arraycopy(SHORT, 0, dest, index, length); index += length; break loop; case C_VOID: length = VOID.length; System.arraycopy(VOID, 0, dest, index, length); index += length; break loop; case C_RESOLVED: case C_UNRESOLVED: int end = CharOperation.indexOf(C_SEMICOLON, signature, sigPos); if (end == -1) throw new IllegalArgumentException(); int start; if (fullyQualifyTypeNames) { start = sigPos; } else { start = CharOperation.lastIndexOf(C_DOT, signature, sigPos, end) + 1; if (start == 0) start = sigPos; } length = end - start; System.arraycopy(signature, start, dest, index, length); sigPos = end + 1; index += length; break loop; } } while (arrayCount-- > 0) { dest[index++] = '['; dest[index++] = ']'; } return (((long) index) << 32) + sigPos; } /** * Creates a new type signature with the given amount of array nesting added * to the given type signature. * * @param typeSignature * the type signature * @param arrayCount * the desired number of levels of array nesting * @return the encoded array type signature * * @since 2.0 */ public static char[] createArraySignature(char[] typeSignature, int arrayCount) { if (arrayCount == 0) return typeSignature; int sigLength = typeSignature.length; char[] result = new char[arrayCount + sigLength]; for (int i = 0; i < arrayCount; i++) { result[i] = C_ARRAY; } System.arraycopy(typeSignature, 0, result, arrayCount, sigLength); return result; } /** * Creates a new type signature with the given amount of array nesting added * to the given type signature. * * @param typeSignature * the type signature * @param arrayCount * the desired number of levels of array nesting * @return the encoded array type signature */ public static String createArraySignature(String typeSignature, int arrayCount) { return new String(createArraySignature(typeSignature.toCharArray(), arrayCount)); } /** * Creates a method signature from the given parameter and return type * signatures. The encoded method signature is dot-based. * * @param parameterTypes * the list of parameter type signatures * @param returnType * the return type signature * @return the encoded method signature * * @since 2.0 */ public static char[] createMethodSignature(char[][] parameterTypes, char[] returnType) { int parameterTypesLength = parameterTypes.length; int parameterLength = 0; for (int i = 0; i < parameterTypesLength; i++) { parameterLength += parameterTypes[i].length; } int returnTypeLength = returnType.length; char[] result = new char[1 + parameterLength + 1 + returnTypeLength]; result[0] = C_PARAM_START; int index = 1; for (int i = 0; i < parameterTypesLength; i++) { char[] parameterType = parameterTypes[i]; int length = parameterType.length; System.arraycopy(parameterType, 0, result, index, length); index += length; } result[index] = C_PARAM_END; System.arraycopy(returnType, 0, result, index + 1, returnTypeLength); return result; } /** * Creates a method signature from the given parameter and return type * signatures. The encoded method signature is dot-based. * * @param parameterTypes * the list of parameter type signatures * @param returnType * the return type signature * @return the encoded method signature */ public static String createMethodSignature(String[] parameterTypes, String returnType) { int parameterTypesLenth = parameterTypes.length; char[][] parameters = new char[parameterTypesLenth][]; for (int i = 0; i < parameterTypesLenth; i++) { parameters[i] = parameterTypes[i].toCharArray(); } return new String(createMethodSignature(parameters, returnType .toCharArray())); } /** * Creates a new type signature from the given type name encoded as a * character array. This method is equivalent to * createTypeSignature(new String(typeName),isResolved), * although more efficient for callers with character arrays rather than * strings. If the type name is qualified, then it is expected to be * dot-based. * * @param typeName * the possibly qualified type name * @param isResolved * true if the type name is to be considered * resolved (for example, a type name from a binary class file), * and false if the type name is to be considered * unresolved (for example, a type name found in source code) * @return the encoded type signature * @see #createTypeSignature(java.lang.String,boolean) */ public static String createTypeSignature(char[] typeName, boolean isResolved) { return new String(createCharArrayTypeSignature(typeName, isResolved)); } /** * Creates a new type signature from the given type name encoded as a * character array. This method is equivalent to * createTypeSignature(new String(typeName),isResolved).toCharArray(), * although more efficient for callers with character arrays rather than * strings. If the type name is qualified, then it is expected to be * dot-based. * * @param typeName * the possibly qualified type name * @param isResolved * true if the type name is to be considered * resolved (for example, a type name from a binary class file), * and false if the type name is to be considered * unresolved (for example, a type name found in source code) * @return the encoded type signature * @see #createTypeSignature(java.lang.String,boolean) * * @since 2.0 */ public static char[] createCharArrayTypeSignature(char[] typeName, boolean isResolved) { if (typeName == null) throw new IllegalArgumentException("null"); //$NON-NLS-1$ int length = typeName.length; if (length == 0) throw new IllegalArgumentException(new String(typeName)); int arrayCount = CharOperation.occurencesOf('[', typeName); char[] sig; switch (typeName[0]) { // primitive type? case 'b': if (CharOperation.fragmentEquals(BOOLEAN, typeName, 0, true)) { sig = new char[arrayCount + 1]; sig[arrayCount] = C_BOOLEAN; break; } else if (CharOperation.fragmentEquals(BYTE, typeName, 0, true)) { sig = new char[arrayCount + 1]; sig[arrayCount] = C_BYTE; break; } case 'c': if (CharOperation.fragmentEquals(CHAR, typeName, 0, true)) { sig = new char[arrayCount + 1]; sig[arrayCount] = C_CHAR; break; } case 'd': if (CharOperation.fragmentEquals(DOUBLE, typeName, 0, true)) { sig = new char[arrayCount + 1]; sig[arrayCount] = C_DOUBLE; break; } case 'f': if (CharOperation.fragmentEquals(FLOAT, typeName, 0, true)) { sig = new char[arrayCount + 1]; sig[arrayCount] = C_FLOAT; break; } case 'i': if (CharOperation.fragmentEquals(INT, typeName, 0, true)) { sig = new char[arrayCount + 1]; sig[arrayCount] = C_INT; break; } case 'l': if (CharOperation.fragmentEquals(LONG, typeName, 0, true)) { sig = new char[arrayCount + 1]; sig[arrayCount] = C_LONG; break; } case 's': if (CharOperation.fragmentEquals(SHORT, typeName, 0, true)) { sig = new char[arrayCount + 1]; sig[arrayCount] = C_SHORT; break; } case 'v': if (CharOperation.fragmentEquals(VOID, typeName, 0, true)) { sig = new char[arrayCount + 1]; sig[arrayCount] = C_VOID; break; } default: // non primitive type int sigLength = arrayCount + 1 + length + 1; // for example // '[[[Ljava.lang.String;' sig = new char[sigLength]; int sigIndex = arrayCount + 1; // index in sig int startID = 0; // start of current ID in typeName int index = 0; // index in typeName while (index < length) { char currentChar = typeName[index]; switch (currentChar) { case '.': if (startID == -1) throw new IllegalArgumentException(new String(typeName)); if (startID < index) { sig = CharOperation.append(sig, sigIndex, typeName, startID, index); sigIndex += index - startID; } sig[sigIndex++] = C_DOT; index++; startID = index; break; case '[': if (startID != -1) { if (startID < index) { sig = CharOperation.append(sig, sigIndex, typeName, startID, index); sigIndex += index - startID; } startID = -1; // no more id after [] } index++; break; default: if (startID != -1 && CharOperation.isWhitespace(currentChar)) { if (startID < index) { sig = CharOperation.append(sig, sigIndex, typeName, startID, index); sigIndex += index - startID; } startID = index + 1; } index++; break; } } // last id if (startID != -1 && startID < index) { sig = CharOperation.append(sig, sigIndex, typeName, startID, index); sigIndex += index - startID; } // add L (or Q) at the beigininig and ; at the end sig[arrayCount] = isResolved ? C_RESOLVED : C_UNRESOLVED; sig[sigIndex++] = C_NAME_END; // resize if needed if (sigLength > sigIndex) { System.arraycopy(sig, 0, sig = new char[sigIndex], 0, sigIndex); } } // add array info for (int i = 0; i < arrayCount; i++) { sig[i] = C_ARRAY; } return sig; } /** * Creates a new type signature from the given type name. If the type name * is qualified, then it is expected to be dot-based. *

* For example: * *

	 * 
	 *  createTypeSignature("int", hucairz) -> "I"
	 *  createTypeSignature("java.lang.String", true) -> "Ljava.lang.String;"
	 *  createTypeSignature("String", false) -> "QString;"
	 *  createTypeSignature("java.lang.String", false) -> "Qjava.lang.String;"
	 *  createTypeSignature("int []", false) -> "[I"
	 * 
	 * 
* *

* * @param typeName * the possibly qualified type name * @param isResolved * true if the type name is to be considered * resolved (for example, a type name from a binary class file), * and false if the type name is to be considered * unresolved (for example, a type name found in source code) * @return the encoded type signature */ public static String createTypeSignature(String typeName, boolean isResolved) { return createTypeSignature(typeName == null ? null : typeName .toCharArray(), isResolved); } /** * Returns the array count (array nesting depth) of the given type * signature. * * @param typeSignature * the type signature * @return the array nesting depth, or 0 if not an array * @exception IllegalArgumentException * if the signature is not syntactically correct * * @since 2.0 */ public static int getArrayCount(char[] typeSignature) throws IllegalArgumentException { try { int count = 0; while (typeSignature[count] == C_ARRAY) { ++count; } return count; } catch (ArrayIndexOutOfBoundsException e) { // signature is // syntactically // incorrect if last // character is C_ARRAY throw new IllegalArgumentException(); } } /** * Returns the array count (array nesting depth) of the given type * signature. * * @param typeSignature * the type signature * @return the array nesting depth, or 0 if not an array * @exception IllegalArgumentException * if the signature is not syntactically correct */ public static int getArrayCount(String typeSignature) throws IllegalArgumentException { return getArrayCount(typeSignature.toCharArray()); } /** * Returns the type signature without any array nesting. *

* For example: * *

	 * 
	 *  getElementType({'[', '[', 'I'}) --> {'I'}.
	 * 
	 * 
* *

* * @param typeSignature * the type signature * @return the type signature without arrays * @exception IllegalArgumentException * if the signature is not syntactically correct * * @since 2.0 */ public static char[] getElementType(char[] typeSignature) throws IllegalArgumentException { int count = getArrayCount(typeSignature); if (count == 0) return typeSignature; int length = typeSignature.length; char[] result = new char[length - count]; System.arraycopy(typeSignature, count, result, 0, length - count); return result; } /** * Returns the type signature without any array nesting. *

* For example: * *

	 * 
	 *  getElementType("[[I") --> "I".
	 * 
	 * 
* *

* * @param typeSignature * the type signature * @return the type signature without arrays * @exception IllegalArgumentException * if the signature is not syntactically correct */ // public static String getElementType(String typeSignature) // throws IllegalArgumentException { // return new String(getElementType(typeSignature.toCharArray())); // } /** * Returns the number of parameter types in the given method signature. * * @param methodSignature * the method signature * @return the number of parameters * @exception IllegalArgumentException * if the signature is not syntactically correct * @since 2.0 */ public static int getParameterCount(char[] methodSignature) throws IllegalArgumentException { try { int count = 0; int i = CharOperation.indexOf(C_PARAM_START, methodSignature) + 1; if (i == 0) throw new IllegalArgumentException(); for (;;) { char c = methodSignature[i++]; switch (c) { case C_ARRAY: break; case C_BOOLEAN: case C_BYTE: case C_CHAR: case C_DOUBLE: case C_FLOAT: case C_INT: case C_LONG: case C_SHORT: case C_VOID: ++count; break; case C_RESOLVED: case C_UNRESOLVED: i = CharOperation.indexOf(C_SEMICOLON, methodSignature, i) + 1; if (i == 0) throw new IllegalArgumentException(); ++count; break; case C_PARAM_END: return count; default: throw new IllegalArgumentException(); } } } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException(); } } /** * Returns the number of parameter types in the given method signature. * * @param methodSignature * the method signature * @return the number of parameters * @exception IllegalArgumentException * if the signature is not syntactically correct */ // public static int getParameterCount(String methodSignature) // throws IllegalArgumentException { // return getParameterCount(methodSignature.toCharArray()); // } /** * Extracts the parameter type signatures from the given method signature. * The method signature is expected to be dot-based. * * @param methodSignature * the method signature * @return the list of parameter type signatures * @exception IllegalArgumentException * if the signature is syntactically incorrect * * @since 2.0 */ public static char[][] getParameterTypes(char[] methodSignature) throws IllegalArgumentException { try { int count = getParameterCount(methodSignature); char[][] result = new char[count][]; if (count == 0) return result; int i = CharOperation.indexOf(C_PARAM_START, methodSignature) + 1; count = 0; int start = i; for (;;) { char c = methodSignature[i++]; switch (c) { case C_ARRAY: // array depth is i - start; break; case C_BOOLEAN: case C_BYTE: case C_CHAR: case C_DOUBLE: case C_FLOAT: case C_INT: case C_LONG: case C_SHORT: case C_VOID: // common case of base types if (i - start == 1) { switch (c) { case C_BOOLEAN: result[count++] = new char[] { C_BOOLEAN }; break; case C_BYTE: result[count++] = new char[] { C_BYTE }; break; case C_CHAR: result[count++] = new char[] { C_CHAR }; break; case C_DOUBLE: result[count++] = new char[] { C_DOUBLE }; break; case C_FLOAT: result[count++] = new char[] { C_FLOAT }; break; case C_INT: result[count++] = new char[] { C_INT }; break; case C_LONG: result[count++] = new char[] { C_LONG }; break; case C_SHORT: result[count++] = new char[] { C_SHORT }; break; case C_VOID: result[count++] = new char[] { C_VOID }; break; } } else { result[count++] = CharOperation.subarray( methodSignature, start, i); } start = i; break; case C_RESOLVED: case C_UNRESOLVED: i = CharOperation.indexOf(C_SEMICOLON, methodSignature, i) + 1; if (i == 0) throw new IllegalArgumentException(); result[count++] = CharOperation.subarray(methodSignature, start, i); start = i; break; case C_PARAM_END: return result; default: throw new IllegalArgumentException(); } } } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException(); } } /** * Extracts the parameter type signatures from the given method signature. * The method signature is expected to be dot-based. * * @param methodSignature * the method signature * @return the list of parameter type signatures * @exception IllegalArgumentException * if the signature is syntactically incorrect */ public static String[] getParameterTypes(String methodSignature) throws IllegalArgumentException { char[][] parameterTypes = getParameterTypes(methodSignature .toCharArray()); int length = parameterTypes.length; String[] result = new String[length]; for (int i = 0; i < length; i++) { result[i] = new String(parameterTypes[i]); } return result; } /** * Returns a char array containing all but the last segment of the given * dot-separated qualified name. Returns the empty char array if it is not * qualified. *

* For example: * *

	 * 
	 *  getQualifier({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g'}
	 *  getQualifier({'O', 'u', 't', 'e', 'r', '.', 'I', 'n', 'n', 'e', 'r'}) -> {'O', 'u', 't', 'e', 'r'}
	 * 
	 * 
* *

* * @param name * the name * @return the qualifier prefix, or the empty char array if the name * contains no dots * @exception NullPointerException * if name is null * @since 2.0 */ // public static char[] getQualifier(char[] name) { // int lastDot = CharOperation.lastIndexOf(C_DOT, name); // if (lastDot == -1) { // return CharOperation.NO_CHAR; // } // return CharOperation.subarray(name, 0, lastDot); // } /** * Returns a string containing all but the last segment of the given * dot-separated qualified name. Returns the empty string if it is not * qualified. *

* For example: * *

	 * 
	 *  getQualifier("java.lang.Object") -> "java.lang"
	 *  getQualifier("Outer.Inner") -> "Outer"
	 * 
	 * 
* *

* * @param name * the name * @return the qualifier prefix, or the empty string if the name contains no * dots * @exception NullPointerException * if name is null */ public static String getQualifier(String name) { int lastDot = name.lastIndexOf(C_DOT); if (lastDot == -1) { return EMPTY; } return name.substring(0, lastDot); } /** * Extracts the return type from the given method signature. The method * signature is expected to be dot-based. * * @param methodSignature * the method signature * @return the type signature of the return type * @exception IllegalArgumentException * if the signature is syntactically incorrect * * @since 2.0 */ public static char[] getReturnType(char[] methodSignature) throws IllegalArgumentException { int i = CharOperation.lastIndexOf(C_PARAM_END, methodSignature); if (i == -1) { throw new IllegalArgumentException(); } return CharOperation.subarray(methodSignature, i + 1, methodSignature.length); } /** * Extracts the return type from the given method signature. The method * signature is expected to be dot-based. * * @param methodSignature * the method signature * @return the type signature of the return type * @exception IllegalArgumentException * if the signature is syntactically incorrect */ public static String getReturnType(String methodSignature) throws IllegalArgumentException { return new String(getReturnType(methodSignature.toCharArray())); } /** * Returns the last segment of the given dot-separated qualified name. * Returns the given name if it is not qualified. *

* For example: * *

	 * 
	 *  getSimpleName({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'O', 'b', 'j', 'e', 'c', 't'}
	 * 
	 * 
* *

* * @param name * the name * @return the last segment of the qualified name * @exception NullPointerException * if name is null * @since 2.0 */ // public static char[] getSimpleName(char[] name) { // int lastDot = CharOperation.lastIndexOf(C_DOT, name); // if (lastDot == -1) { // return name; // } // return CharOperation.subarray(name, lastDot + 1, name.length); // } /** * Returns the last segment of the given dot-separated qualified name. * Returns the given name if it is not qualified. *

* For example: * *

	 * 
	 *  getSimpleName("java.lang.Object") -> "Object"
	 * 
	 * 
* *

* * @param name * the name * @return the last segment of the qualified name * @exception NullPointerException * if name is null */ public static String getSimpleName(String name) { int lastDot = name.lastIndexOf(C_DOT); if (lastDot == -1) { return name; } return name.substring(lastDot + 1, name.length()); } /** * Returns all segments of the given dot-separated qualified name. Returns * an array with only the given name if it is not qualified. Returns an * empty array if the name is empty. *

* For example: * *

	 * 
	 *  getSimpleNames({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'O', 'b', 'j', 'e', 'c', 't'}}
	 *  getSimpleNames({'O', 'b', 'j', 'e', 'c', 't'}) -> {{'O', 'b', 'j', 'e', 'c', 't'}}
	 *  getSimpleNames("") -> {}
	 * 
	 * 
* * @param name * the name * @return the list of simple names, possibly empty * @exception NullPointerException * if name is null * @since 2.0 */ public static char[][] getSimpleNames(char[] name) { if (name.length == 0) { return CharOperation.NO_CHAR_CHAR; } int dot = CharOperation.indexOf(C_DOT, name); if (dot == -1) { return new char[][] { name }; } int n = 1; while ((dot = CharOperation.indexOf(C_DOT, name, dot + 1)) != -1) { ++n; } char[][] result = new char[n + 1][]; int segStart = 0; for (int i = 0; i < n; ++i) { dot = CharOperation.indexOf(C_DOT, name, segStart); result[i] = CharOperation.subarray(name, segStart, dot); segStart = dot + 1; } result[n] = CharOperation.subarray(name, segStart, name.length); return result; } /** * Returns all segments of the given dot-separated qualified name. Returns * an array with only the given name if it is not qualified. Returns an * empty array if the name is empty. *

* For example: * *

	 * 
	 *  getSimpleNames("java.lang.Object") -> {"java", "lang", "Object"}
	 *  getSimpleNames("Object") -> {"Object"}
	 *  getSimpleNames("") -> {}
	 * 
	 * 
* * @param name * the name * @return the list of simple names, possibly empty * @exception NullPointerException * if name is null */ public static String[] getSimpleNames(String name) { char[][] simpleNames = getSimpleNames(name.toCharArray()); int length = simpleNames.length; String[] result = new String[length]; for (int i = 0; i < length; i++) { result[i] = new String(simpleNames[i]); } return result; } /** * Converts the given method signature to a readable form. The method * signature is expected to be dot-based. *

* For example: * *

	 * 
	 *  toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
	 * 
	 * 
* *

* * @param methodSignature * the method signature to convert * @param methodName * the name of the method to insert in the result, or * null if no method name is to be included * @param parameterNames * the parameter names to insert in the result, or * null if no parameter names are to be included; * if supplied, the number of parameter names must match that of * the method signature * @param fullyQualifyTypeNames * true if type names should be fully qualified, * and false to use only simple names * @param includeReturnType * true if the return type is to be included * @return the char array representation of the method signature * * @since 2.0 */ public static char[] toCharArray(char[] methodSignature, char[] methodName, char[][] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) { try { int firstParen = CharOperation.indexOf(C_PARAM_START, methodSignature); if (firstParen == -1) throw new IllegalArgumentException(); int sigLength = methodSignature.length; // compute result length // method signature int paramCount = 0; int lastParen = -1; int resultLength = 0; signature: for (int i = firstParen; i < sigLength; i++) { switch (methodSignature[i]) { case C_ARRAY: resultLength += 2; // [] continue signature; case C_BOOLEAN: resultLength += BOOLEAN.length; break; case C_BYTE: resultLength += BYTE.length; break; case C_CHAR: resultLength += CHAR.length; break; case C_DOUBLE: resultLength += DOUBLE.length; break; case C_FLOAT: resultLength += FLOAT.length; break; case C_INT: resultLength += INT.length; break; case C_LONG: resultLength += LONG.length; break; case C_SHORT: resultLength += SHORT.length; break; case C_VOID: resultLength += VOID.length; break; case C_RESOLVED: case C_UNRESOLVED: int end = CharOperation.indexOf(C_SEMICOLON, methodSignature, i); if (end == -1) throw new IllegalArgumentException(); int start; if (fullyQualifyTypeNames) { start = i + 1; } else { start = CharOperation.lastIndexOf(C_DOT, methodSignature, i, end) + 1; if (start == 0) start = i + 1; } resultLength += end - start; i = end; break; case C_PARAM_START: // add space for "(" resultLength++; continue signature; case C_PARAM_END: lastParen = i; if (includeReturnType) { if (paramCount > 0) { // remove space for ", " that was added with last // parameter and remove space that is going to be // added for ", " after return type // and add space for ") " resultLength -= 2; } // else // remove space that is going to be added for ", " after // return type // and add space for ") " // -> noop // decrement param count because it is going to be added // for return type paramCount--; continue signature; } else { if (paramCount > 0) { // remove space for ", " that was added with last // parameter and add space for ")" resultLength--; } else { // add space for ")" resultLength++; } break signature; } default: throw new IllegalArgumentException(); } resultLength += 2; // add space for ", " paramCount++; } // parameter names int parameterNamesLength = parameterNames == null ? 0 : parameterNames.length; for (int i = 0; i < parameterNamesLength; i++) { resultLength += parameterNames[i].length + 1; // parameter // name + space } // selector int selectorLength = methodName == null ? 0 : methodName.length; resultLength += selectorLength; // create resulting char array char[] result = new char[resultLength]; // returned type int index = 0; if (includeReturnType) { long pos = copyType(methodSignature, lastParen + 1, result, index, fullyQualifyTypeNames); index = (int) (pos >>> 32); result[index++] = ' '; } // selector if (methodName != null) { System.arraycopy(methodName, 0, result, index, selectorLength); index += selectorLength; } // parameters result[index++] = C_PARAM_START; int sigPos = firstParen + 1; for (int i = 0; i < paramCount; i++) { long pos = copyType(methodSignature, sigPos, result, index, fullyQualifyTypeNames); index = (int) (pos >>> 32); sigPos = (int) pos; if (parameterNames != null) { result[index++] = ' '; char[] parameterName = parameterNames[i]; int paramLength = parameterName.length; System.arraycopy(parameterName, 0, result, index, paramLength); index += paramLength; } if (i != paramCount - 1) { result[index++] = ','; result[index++] = ' '; } } if (sigPos >= sigLength) { throw new IllegalArgumentException(); // should be on last // paren } result[index++] = C_PARAM_END; return result; } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException(); } } /** * Converts the given type signature to a readable string. The signature is * expected to be dot-based. * *

* For example: * *

	 * 
	 *  toString({'[', 'L', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', ';'}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', '[', ']'}
	 *  toString({'I'}) -> {'i', 'n', 't'}
	 * 
	 * 
* *

*

* Note: This method assumes that a type signature containing a * '$' is an inner type signature. While this is correct in * most cases, someone could define a non-inner type name containing a * '$'. Handling this correctly in all cases would have * required resolving the signature, which generally not feasible. *

* * @param signature * the type signature * @return the string representation of the type * @exception IllegalArgumentException * if the signature is not syntactically correct * * @since 2.0 */ // public static char[] toCharArray(char[] signature) // throws IllegalArgumentException { // try { // int sigLength = signature.length; // // if (sigLength == 0 || signature[0] == C_PARAM_START) { // return toCharArray(signature, CharOperation.NO_CHAR, null, // true, true); // } // // // compute result length // int resultLength = 0; // int index = -1; // while (signature[++index] == C_ARRAY) { // resultLength += 2; // [] // } // switch (signature[index]) { // case C_BOOLEAN: // resultLength += BOOLEAN.length; // break; // case C_BYTE: // resultLength += BYTE.length; // break; // case C_CHAR: // resultLength += CHAR.length; // break; // case C_DOUBLE: // resultLength += DOUBLE.length; // break; // case C_FLOAT: // resultLength += FLOAT.length; // break; // case C_INT: // resultLength += INT.length; // break; // case C_LONG: // resultLength += LONG.length; // break; // case C_SHORT: // resultLength += SHORT.length; // break; // case C_VOID: // resultLength += VOID.length; // break; // case C_RESOLVED: // case C_UNRESOLVED: // int end = CharOperation.indexOf(C_SEMICOLON, signature, index); // if (end == -1) // throw new IllegalArgumentException(); // int start = index + 1; // resultLength += end - start; // break; // default: // throw new IllegalArgumentException(); // } // // char[] result = new char[resultLength]; // copyType(signature, 0, result, 0, true); // // /** // * Converts '$' separated type signatures into '.' separated type // * signature. NOTE: This assumes that the type signature is an inner // * type signature. This is true in most cases, but someone can // * define a non-inner type name containing a '$'. However to tell // * the difference, we would have to resolve the signature, which // * cannot be done at this point. // */ // CharOperation.replace(result, C_DOLLAR, C_DOT); // // return result; // } catch (ArrayIndexOutOfBoundsException e) { // throw new IllegalArgumentException(); // } // } /** * Converts the given array of qualified name segments to a qualified name. *

* For example: * *

	 * 
	 *  toQualifiedName({{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'O', 'b', 'j', 'e', 'c', 't'}}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}
	 *  toQualifiedName({{'O', 'b', 'j', 'e', 'c', 't'}}) -> {'O', 'b', 'j', 'e', 'c', 't'}
	 *  toQualifiedName({{}}) -> {}
	 * 
	 * 
* *

* * @param segments * the list of name segments, possibly empty * @return the dot-separated qualified name, or the empty string * * @since 2.0 */ public static char[] toQualifiedName(char[][] segments) { int length = segments.length; if (length == 0) return CharOperation.NO_CHAR; if (length == 1) return segments[0]; int resultLength = 0; for (int i = 0; i < length; i++) { resultLength += segments[i].length + 1; } resultLength--; char[] result = new char[resultLength]; int index = 0; for (int i = 0; i < length; i++) { char[] segment = segments[i]; int segmentLength = segment.length; System.arraycopy(segment, 0, result, index, segmentLength); index += segmentLength; if (i != length - 1) { result[index++] = C_DOT; } } return result; } /** * Converts the given array of qualified name segments to a qualified name. *

* For example: * *

	 * 
	 *  toQualifiedName(new String[] {"java", "lang", "Object"}) -> "java.lang.Object"
	 *  toQualifiedName(new String[] {"Object"}) -> "Object"
	 *  toQualifiedName(new String[0]) -> ""
	 * 
	 * 
* *

* * @param segments * the list of name segments, possibly empty * @return the dot-separated qualified name, or the empty string */ // public static String toQualifiedName(String[] segments) { // int length = segments.length; // char[][] charArrays = new char[length][]; // for (int i = 0; i < length; i++) { // charArrays[i] = segments[i].toCharArray(); // } // return new String(toQualifiedName(charArrays)); // } /** * Converts the given type signature to a readable string. The signature is * expected to be dot-based. * *

* For example: * *

	 * 
	 *  toString("[Ljava.lang.String;") -> "java.lang.String[]"
	 *  toString("I") -> "int"
	 * 
	 * 
* *

*

* Note: This method assumes that a type signature containing a * '$' is an inner type signature. While this is correct in * most cases, someone could define a non-inner type name containing a * '$'. Handling this correctly in all cases would have * required resolving the signature, which generally not feasible. *

* * @param signature * the type signature * @return the string representation of the type * @exception IllegalArgumentException * if the signature is not syntactically correct */ public static String toString(String signature) throws IllegalArgumentException { // return new String(toCharArray(signature.toCharArray())); return ""; } /** * Converts the given method signature to a readable string. The method * signature is expected to be dot-based. *

* For example: * *

	 * 
	 *  toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
	 * 
	 * 
* *

* * @param methodSignature * the method signature to convert * @param methodName * the name of the method to insert in the result, or * null if no method name is to be included * @param parameterNames * the parameter names to insert in the result, or * null if no parameter names are to be included; * if supplied, the number of parameter names must match that of * the method signature * @param fullyQualifyTypeNames * true if type names should be fully qualified, * and false to use only simple names * @param includeReturnType * true if the return type is to be included * @return the string representation of the method signature */ public static String toString(String methodSignature, String methodName, String[] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) { char[][] params; if (parameterNames == null) { params = null; } else { int paramLength = parameterNames.length; params = new char[paramLength][]; for (int i = 0; i < paramLength; i++) { params[i] = parameterNames[i].toCharArray(); } } return new String(toCharArray(methodSignature.toCharArray(), methodName == null ? null : methodName.toCharArray(), params, fullyQualifyTypeNames, includeReturnType)); } }