1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.core;
13 import net.sourceforge.phpdt.core.compiler.CharOperation;
16 * Provides methods for encoding and decoding type and method signature strings.
18 * The syntax for a type signature is:
22 * "B" // byte
23 * | "C" // char
24 * | "D" // double
25 * | "F" // float
26 * | "I" // int
27 * | "J" // long
28 * | "S" // short
29 * | "V" // void
30 * | "Z" // boolean
31 * | "L" + binaryTypeName + ";" // resolved named type (in compiled code)
32 * | "Q" + sourceTypeName + ";" // unresolved named type (in source code)
33 * | "[" + typeSignature // array of type denoted by typeSignature
40 * <li><code>"[[I"</code> denotes <code>int[][]</code></li>
41 * <li><code>"Ljava.lang.String;"</code> denotes
42 * <code>java.lang.String</code> in compiled code</li>
43 * <li><code>"QString"</code> denotes <code>String</code> in source code</li>
44 * <li><code>"Qjava.lang.String"</code> denotes <code>java.lang.String</code>
46 * <li><code>"[QString"</code> denotes <code>String[]</code> in source code</li>
50 * The syntax for a method signature is:
53 * methodSignature ::= "(" + paramTypeSignature* + ")" + returnTypeSignature
54 * paramTypeSignature ::= typeSignature
55 * returnTypeSignature ::= typeSignature
61 * <li><code>"()I"</code> denotes <code>int foo()</code></li>
62 * <li><code>"([Ljava.lang.String;)V"</code> denotes
63 * <code>void foo(java.lang.String[])</code> in compiled code</li>
64 * <li><code>"(QString;)QObject;"</code> denotes
65 * <code>Object foo(String)</code> in source code</li>
69 * This class provides static methods and constants only; it is not intended to
70 * be instantiated or subclassed by clients.
73 public final class Signature {
76 * Character constant indicating the primitive type boolean in a signature.
77 * Value is <code>'Z'</code>.
79 public static final char C_BOOLEAN = 'Z';
82 * Character constant indicating the primitive type byte in a signature.
83 * Value is <code>'B'</code>.
85 public static final char C_BYTE = 'B';
88 * Character constant indicating the primitive type char in a signature.
89 * Value is <code>'C'</code>.
91 public static final char C_CHAR = 'C';
94 * Character constant indicating the primitive type double in a signature.
95 * Value is <code>'D'</code>.
97 public static final char C_DOUBLE = 'D';
100 * Character constant indicating the primitive type float in a signature.
101 * Value is <code>'F'</code>.
103 public static final char C_FLOAT = 'F';
106 * Character constant indicating the primitive type int in a signature.
107 * Value is <code>'I'</code>.
109 public static final char C_INT = 'I';
112 * Character constant indicating the semicolon in a signature. Value is
115 public static final char C_SEMICOLON = ';';
118 * Character constant indicating the primitive type long in a signature.
119 * Value is <code>'J'</code>.
121 public static final char C_LONG = 'J';
124 * Character constant indicating the primitive type short in a signature.
125 * Value is <code>'S'</code>.
127 public static final char C_SHORT = 'S';
130 * Character constant indicating result type void in a signature. Value is
133 public static final char C_VOID = 'V';
136 * Character constant indicating the dot in a signature. Value is
139 public static final char C_DOT = '.';
142 * Character constant indicating the dollar in a signature. Value is
145 public static final char C_DOLLAR = '$';
148 * Character constant indicating an array type in a signature. Value is
151 public static final char C_ARRAY = '[';
154 * Character constant indicating the start of a resolved, named type in a
155 * signature. Value is <code>'L'</code>.
157 public static final char C_RESOLVED = 'L';
160 * Character constant indicating the start of an unresolved, named type in a
161 * signature. Value is <code>'Q'</code>.
163 public static final char C_UNRESOLVED = 'Q';
166 * Character constant indicating the end of a named type in a signature.
167 * Value is <code>';'</code>.
169 public static final char C_NAME_END = ';';
172 * Character constant indicating the start of a parameter type list in a
173 * signature. Value is <code>'('</code>.
175 public static final char C_PARAM_START = '(';
178 * Character constant indicating the end of a parameter type list in a
179 * signature. Value is <code>')'</code>.
181 public static final char C_PARAM_END = ')';
184 * String constant for the signature of the primitive type boolean. Value is
187 public static final String SIG_BOOLEAN = "Z"; //$NON-NLS-1$
190 * String constant for the signature of the primitive type byte. Value is
193 public static final String SIG_BYTE = "B"; //$NON-NLS-1$
196 * String constant for the signature of the primitive type char. Value is
199 public static final String SIG_CHAR = "C"; //$NON-NLS-1$
202 * String constant for the signature of the primitive type double. Value is
205 public static final String SIG_DOUBLE = "D"; //$NON-NLS-1$
208 * String constant for the signature of the primitive type float. Value is
211 public static final String SIG_FLOAT = "F"; //$NON-NLS-1$
214 * String constant for the signature of the primitive type int. Value is
217 public static final String SIG_INT = "I"; //$NON-NLS-1$
220 * String constant for the signature of the primitive type long. Value is
223 public static final String SIG_LONG = "J"; //$NON-NLS-1$
226 * String constant for the signature of the primitive type short. Value is
229 public static final String SIG_SHORT = "S"; //$NON-NLS-1$
232 * String constant for the signature of result type void. Value is
235 public static final String SIG_VOID = "V"; //$NON-NLS-1$
237 private static final char[] BOOLEAN = { 'b', 'o', 'o', 'l', 'e', 'a', 'n' };
239 private static final char[] BYTE = { 'b', 'y', 't', 'e' };
241 private static final char[] CHAR = { 'c', 'h', 'a', 'r' };
243 private static final char[] DOUBLE = { 'd', 'o', 'u', 'b', 'l', 'e' };
245 private static final char[] FLOAT = { 'f', 'l', 'o', 'a', 't' };
247 private static final char[] INT = { 'i', 'n', 't' };
249 private static final char[] LONG = { 'l', 'o', 'n', 'g' };
251 private static final char[] SHORT = { 's', 'h', 'o', 'r', 't' };
253 private static final char[] VOID = { 'v', 'o', 'i', 'd' };
255 private static final String EMPTY = new String(CharOperation.NO_CHAR);
260 private Signature() {
263 private static long copyType(char[] signature, int sigPos, char[] dest,
264 int index, boolean fullyQualifyTypeNames) {
267 switch (signature[sigPos++]) {
272 int length = BOOLEAN.length;
273 System.arraycopy(BOOLEAN, 0, dest, index, length);
277 length = BYTE.length;
278 System.arraycopy(BYTE, 0, dest, index, length);
282 length = CHAR.length;
283 System.arraycopy(CHAR, 0, dest, index, length);
287 length = DOUBLE.length;
288 System.arraycopy(DOUBLE, 0, dest, index, length);
292 length = FLOAT.length;
293 System.arraycopy(FLOAT, 0, dest, index, length);
298 System.arraycopy(INT, 0, dest, index, length);
302 length = LONG.length;
303 System.arraycopy(LONG, 0, dest, index, length);
307 length = SHORT.length;
308 System.arraycopy(SHORT, 0, dest, index, length);
312 length = VOID.length;
313 System.arraycopy(VOID, 0, dest, index, length);
318 int end = CharOperation.indexOf(C_SEMICOLON, signature, sigPos);
320 throw new IllegalArgumentException();
322 if (fullyQualifyTypeNames) {
325 start = CharOperation.lastIndexOf(C_DOT, signature, sigPos,
330 length = end - start;
331 System.arraycopy(signature, start, dest, index, length);
337 while (arrayCount-- > 0) {
341 return (((long) index) << 32) + sigPos;
345 * Creates a new type signature with the given amount of array nesting added
346 * to the given type signature.
348 * @param typeSignature
351 * the desired number of levels of array nesting
352 * @return the encoded array type signature
356 public static char[] createArraySignature(char[] typeSignature,
359 return typeSignature;
360 int sigLength = typeSignature.length;
361 char[] result = new char[arrayCount + sigLength];
362 for (int i = 0; i < arrayCount; i++) {
365 System.arraycopy(typeSignature, 0, result, arrayCount, sigLength);
370 * Creates a new type signature with the given amount of array nesting added
371 * to the given type signature.
373 * @param typeSignature
376 * the desired number of levels of array nesting
377 * @return the encoded array type signature
379 public static String createArraySignature(String typeSignature,
381 return new String(createArraySignature(typeSignature.toCharArray(),
386 * Creates a method signature from the given parameter and return type
387 * signatures. The encoded method signature is dot-based.
389 * @param parameterTypes
390 * the list of parameter type signatures
392 * the return type signature
393 * @return the encoded method signature
397 public static char[] createMethodSignature(char[][] parameterTypes,
399 int parameterTypesLength = parameterTypes.length;
400 int parameterLength = 0;
401 for (int i = 0; i < parameterTypesLength; i++) {
402 parameterLength += parameterTypes[i].length;
405 int returnTypeLength = returnType.length;
406 char[] result = new char[1 + parameterLength + 1 + returnTypeLength];
407 result[0] = C_PARAM_START;
409 for (int i = 0; i < parameterTypesLength; i++) {
410 char[] parameterType = parameterTypes[i];
411 int length = parameterType.length;
412 System.arraycopy(parameterType, 0, result, index, length);
415 result[index] = C_PARAM_END;
416 System.arraycopy(returnType, 0, result, index + 1, returnTypeLength);
421 * Creates a method signature from the given parameter and return type
422 * signatures. The encoded method signature is dot-based.
424 * @param parameterTypes
425 * the list of parameter type signatures
427 * the return type signature
428 * @return the encoded method signature
430 public static String createMethodSignature(String[] parameterTypes,
432 int parameterTypesLenth = parameterTypes.length;
433 char[][] parameters = new char[parameterTypesLenth][];
434 for (int i = 0; i < parameterTypesLenth; i++) {
435 parameters[i] = parameterTypes[i].toCharArray();
437 return new String(createMethodSignature(parameters, returnType
442 * Creates a new type signature from the given type name encoded as a
443 * character array. This method is equivalent to
444 * <code>createTypeSignature(new String(typeName),isResolved)</code>,
445 * although more efficient for callers with character arrays rather than
446 * strings. If the type name is qualified, then it is expected to be
450 * the possibly qualified type name
452 * <code>true</code> if the type name is to be considered
453 * resolved (for example, a type name from a binary class file),
454 * and <code>false</code> if the type name is to be considered
455 * unresolved (for example, a type name found in source code)
456 * @return the encoded type signature
457 * @see #createTypeSignature(java.lang.String,boolean)
459 public static String createTypeSignature(char[] typeName, boolean isResolved) {
460 return new String(createCharArrayTypeSignature(typeName, isResolved));
464 * Creates a new type signature from the given type name encoded as a
465 * character array. This method is equivalent to
466 * <code>createTypeSignature(new String(typeName),isResolved).toCharArray()</code>,
467 * although more efficient for callers with character arrays rather than
468 * strings. If the type name is qualified, then it is expected to be
472 * the possibly qualified type name
474 * <code>true</code> if the type name is to be considered
475 * resolved (for example, a type name from a binary class file),
476 * and <code>false</code> if the type name is to be considered
477 * unresolved (for example, a type name found in source code)
478 * @return the encoded type signature
479 * @see #createTypeSignature(java.lang.String,boolean)
483 public static char[] createCharArrayTypeSignature(char[] typeName,
484 boolean isResolved) {
486 if (typeName == null)
487 throw new IllegalArgumentException("null"); //$NON-NLS-1$
488 int length = typeName.length;
490 throw new IllegalArgumentException(new String(typeName));
492 int arrayCount = CharOperation.occurencesOf('[', typeName);
495 switch (typeName[0]) {
498 if (CharOperation.fragmentEquals(BOOLEAN, typeName, 0, true)) {
499 sig = new char[arrayCount + 1];
500 sig[arrayCount] = C_BOOLEAN;
502 } else if (CharOperation.fragmentEquals(BYTE, typeName, 0, true)) {
503 sig = new char[arrayCount + 1];
504 sig[arrayCount] = C_BYTE;
508 if (CharOperation.fragmentEquals(CHAR, typeName, 0, true)) {
509 sig = new char[arrayCount + 1];
510 sig[arrayCount] = C_CHAR;
514 if (CharOperation.fragmentEquals(DOUBLE, typeName, 0, true)) {
515 sig = new char[arrayCount + 1];
516 sig[arrayCount] = C_DOUBLE;
520 if (CharOperation.fragmentEquals(FLOAT, typeName, 0, true)) {
521 sig = new char[arrayCount + 1];
522 sig[arrayCount] = C_FLOAT;
526 if (CharOperation.fragmentEquals(INT, typeName, 0, true)) {
527 sig = new char[arrayCount + 1];
528 sig[arrayCount] = C_INT;
532 if (CharOperation.fragmentEquals(LONG, typeName, 0, true)) {
533 sig = new char[arrayCount + 1];
534 sig[arrayCount] = C_LONG;
538 if (CharOperation.fragmentEquals(SHORT, typeName, 0, true)) {
539 sig = new char[arrayCount + 1];
540 sig[arrayCount] = C_SHORT;
544 if (CharOperation.fragmentEquals(VOID, typeName, 0, true)) {
545 sig = new char[arrayCount + 1];
546 sig[arrayCount] = C_VOID;
550 // non primitive type
551 int sigLength = arrayCount + 1 + length + 1; // for example
552 // '[[[Ljava.lang.String;'
553 sig = new char[sigLength];
554 int sigIndex = arrayCount + 1; // index in sig
555 int startID = 0; // start of current ID in typeName
556 int index = 0; // index in typeName
557 while (index < length) {
558 char currentChar = typeName[index];
559 switch (currentChar) {
562 throw new IllegalArgumentException(new String(typeName));
563 if (startID < index) {
564 sig = CharOperation.append(sig, sigIndex, typeName,
566 sigIndex += index - startID;
568 sig[sigIndex++] = C_DOT;
574 if (startID < index) {
575 sig = CharOperation.append(sig, sigIndex, typeName,
577 sigIndex += index - startID;
579 startID = -1; // no more id after []
585 && CharOperation.isWhitespace(currentChar)) {
586 if (startID < index) {
587 sig = CharOperation.append(sig, sigIndex, typeName,
589 sigIndex += index - startID;
598 if (startID != -1 && startID < index) {
599 sig = CharOperation.append(sig, sigIndex, typeName, startID,
601 sigIndex += index - startID;
604 // add L (or Q) at the beigininig and ; at the end
605 sig[arrayCount] = isResolved ? C_RESOLVED : C_UNRESOLVED;
606 sig[sigIndex++] = C_NAME_END;
609 if (sigLength > sigIndex) {
610 System.arraycopy(sig, 0, sig = new char[sigIndex], 0, sigIndex);
615 for (int i = 0; i < arrayCount; i++) {
623 * Creates a new type signature from the given type name. If the type name
624 * is qualified, then it is expected to be dot-based.
630 * createTypeSignature("int", hucairz) -> "I"
631 * createTypeSignature("java.lang.String", true) -> "Ljava.lang.String;"
632 * createTypeSignature("String", false) -> "QString;"
633 * createTypeSignature("java.lang.String", false) -> "Qjava.lang.String;"
634 * createTypeSignature("int []", false) -> "[I"
641 * the possibly qualified type name
643 * <code>true</code> if the type name is to be considered
644 * resolved (for example, a type name from a binary class file),
645 * and <code>false</code> if the type name is to be considered
646 * unresolved (for example, a type name found in source code)
647 * @return the encoded type signature
649 public static String createTypeSignature(String typeName, boolean isResolved) {
650 return createTypeSignature(typeName == null ? null : typeName
651 .toCharArray(), isResolved);
655 * Returns the array count (array nesting depth) of the given type
658 * @param typeSignature
660 * @return the array nesting depth, or 0 if not an array
661 * @exception IllegalArgumentException
662 * if the signature is not syntactically correct
666 public static int getArrayCount(char[] typeSignature)
667 throws IllegalArgumentException {
670 while (typeSignature[count] == C_ARRAY) {
674 } catch (ArrayIndexOutOfBoundsException e) { // signature is
677 // character is C_ARRAY
678 throw new IllegalArgumentException();
683 * Returns the array count (array nesting depth) of the given type
686 * @param typeSignature
688 * @return the array nesting depth, or 0 if not an array
689 * @exception IllegalArgumentException
690 * if the signature is not syntactically correct
692 public static int getArrayCount(String typeSignature)
693 throws IllegalArgumentException {
694 return getArrayCount(typeSignature.toCharArray());
698 * Returns the type signature without any array nesting.
704 * getElementType({'[', '[', 'I'}) --> {'I'}.
710 * @param typeSignature
712 * @return the type signature without arrays
713 * @exception IllegalArgumentException
714 * if the signature is not syntactically correct
718 public static char[] getElementType(char[] typeSignature)
719 throws IllegalArgumentException {
720 int count = getArrayCount(typeSignature);
722 return typeSignature;
723 int length = typeSignature.length;
724 char[] result = new char[length - count];
725 System.arraycopy(typeSignature, count, result, 0, length - count);
730 * Returns the type signature without any array nesting.
736 * getElementType("[[I") --> "I".
742 * @param typeSignature
744 * @return the type signature without arrays
745 * @exception IllegalArgumentException
746 * if the signature is not syntactically correct
748 public static String getElementType(String typeSignature)
749 throws IllegalArgumentException {
750 return new String(getElementType(typeSignature.toCharArray()));
754 * Returns the number of parameter types in the given method signature.
756 * @param methodSignature
757 * the method signature
758 * @return the number of parameters
759 * @exception IllegalArgumentException
760 * if the signature is not syntactically correct
763 public static int getParameterCount(char[] methodSignature)
764 throws IllegalArgumentException {
767 int i = CharOperation.indexOf(C_PARAM_START, methodSignature) + 1;
769 throw new IllegalArgumentException();
771 char c = methodSignature[i++];
788 i = CharOperation.indexOf(C_SEMICOLON, methodSignature, i) + 1;
790 throw new IllegalArgumentException();
796 throw new IllegalArgumentException();
799 } catch (ArrayIndexOutOfBoundsException e) {
800 throw new IllegalArgumentException();
805 * Returns the number of parameter types in the given method signature.
807 * @param methodSignature
808 * the method signature
809 * @return the number of parameters
810 * @exception IllegalArgumentException
811 * if the signature is not syntactically correct
813 public static int getParameterCount(String methodSignature)
814 throws IllegalArgumentException {
815 return getParameterCount(methodSignature.toCharArray());
819 * Extracts the parameter type signatures from the given method signature.
820 * The method signature is expected to be dot-based.
822 * @param methodSignature
823 * the method signature
824 * @return the list of parameter type signatures
825 * @exception IllegalArgumentException
826 * if the signature is syntactically incorrect
830 public static char[][] getParameterTypes(char[] methodSignature)
831 throws IllegalArgumentException {
833 int count = getParameterCount(methodSignature);
834 char[][] result = new char[count][];
837 int i = CharOperation.indexOf(C_PARAM_START, methodSignature) + 1;
841 char c = methodSignature[i++];
844 // array depth is i - start;
855 // common case of base types
856 if (i - start == 1) {
859 result[count++] = new char[] { C_BOOLEAN };
862 result[count++] = new char[] { C_BYTE };
865 result[count++] = new char[] { C_CHAR };
868 result[count++] = new char[] { C_DOUBLE };
871 result[count++] = new char[] { C_FLOAT };
874 result[count++] = new char[] { C_INT };
877 result[count++] = new char[] { C_LONG };
880 result[count++] = new char[] { C_SHORT };
883 result[count++] = new char[] { C_VOID };
887 result[count++] = CharOperation.subarray(
888 methodSignature, start, i);
894 i = CharOperation.indexOf(C_SEMICOLON, methodSignature, i) + 1;
896 throw new IllegalArgumentException();
897 result[count++] = CharOperation.subarray(methodSignature,
904 throw new IllegalArgumentException();
907 } catch (ArrayIndexOutOfBoundsException e) {
908 throw new IllegalArgumentException();
913 * Extracts the parameter type signatures from the given method signature.
914 * The method signature is expected to be dot-based.
916 * @param methodSignature
917 * the method signature
918 * @return the list of parameter type signatures
919 * @exception IllegalArgumentException
920 * if the signature is syntactically incorrect
922 public static String[] getParameterTypes(String methodSignature)
923 throws IllegalArgumentException {
924 char[][] parameterTypes = getParameterTypes(methodSignature
926 int length = parameterTypes.length;
927 String[] result = new String[length];
928 for (int i = 0; i < length; i++) {
929 result[i] = new String(parameterTypes[i]);
935 * Returns a char array containing all but the last segment of the given
936 * dot-separated qualified name. Returns the empty char array if it is not
943 * getQualifier({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g'}
944 * getQualifier({'O', 'u', 't', 'e', 'r', '.', 'I', 'n', 'n', 'e', 'r'}) -> {'O', 'u', 't', 'e', 'r'}
952 * @return the qualifier prefix, or the empty char array if the name
954 * @exception NullPointerException
958 public static char[] getQualifier(char[] name) {
959 int lastDot = CharOperation.lastIndexOf(C_DOT, name);
961 return CharOperation.NO_CHAR;
963 return CharOperation.subarray(name, 0, lastDot);
967 * Returns a string containing all but the last segment of the given
968 * dot-separated qualified name. Returns the empty string if it is not
975 * getQualifier("java.lang.Object") -> "java.lang"
976 * getQualifier("Outer.Inner") -> "Outer"
984 * @return the qualifier prefix, or the empty string if the name contains no
986 * @exception NullPointerException
989 public static String getQualifier(String name) {
990 int lastDot = name.lastIndexOf(C_DOT);
994 return name.substring(0, lastDot);
998 * Extracts the return type from the given method signature. The method
999 * signature is expected to be dot-based.
1001 * @param methodSignature
1002 * the method signature
1003 * @return the type signature of the return type
1004 * @exception IllegalArgumentException
1005 * if the signature is syntactically incorrect
1009 public static char[] getReturnType(char[] methodSignature)
1010 throws IllegalArgumentException {
1011 int i = CharOperation.lastIndexOf(C_PARAM_END, methodSignature);
1013 throw new IllegalArgumentException();
1015 return CharOperation.subarray(methodSignature, i + 1,
1016 methodSignature.length);
1020 * Extracts the return type from the given method signature. The method
1021 * signature is expected to be dot-based.
1023 * @param methodSignature
1024 * the method signature
1025 * @return the type signature of the return type
1026 * @exception IllegalArgumentException
1027 * if the signature is syntactically incorrect
1029 public static String getReturnType(String methodSignature)
1030 throws IllegalArgumentException {
1031 return new String(getReturnType(methodSignature.toCharArray()));
1035 * Returns the last segment of the given dot-separated qualified name.
1036 * Returns the given name if it is not qualified.
1042 * getSimpleName({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'O', 'b', 'j', 'e', 'c', 't'}
1050 * @return the last segment of the qualified name
1051 * @exception NullPointerException
1055 public static char[] getSimpleName(char[] name) {
1056 int lastDot = CharOperation.lastIndexOf(C_DOT, name);
1057 if (lastDot == -1) {
1060 return CharOperation.subarray(name, lastDot + 1, name.length);
1064 * Returns the last segment of the given dot-separated qualified name.
1065 * Returns the given name if it is not qualified.
1071 * getSimpleName("java.lang.Object") -> "Object"
1079 * @return the last segment of the qualified name
1080 * @exception NullPointerException
1083 public static String getSimpleName(String name) {
1084 int lastDot = name.lastIndexOf(C_DOT);
1085 if (lastDot == -1) {
1088 return name.substring(lastDot + 1, name.length());
1092 * Returns all segments of the given dot-separated qualified name. Returns
1093 * an array with only the given name if it is not qualified. Returns an
1094 * empty array if the name is empty.
1100 * 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'}}
1101 * getSimpleNames({'O', 'b', 'j', 'e', 'c', 't'}) -> {{'O', 'b', 'j', 'e', 'c', 't'}}
1102 * getSimpleNames("") -> {}
1108 * @return the list of simple names, possibly empty
1109 * @exception NullPointerException
1113 public static char[][] getSimpleNames(char[] name) {
1114 if (name.length == 0) {
1115 return CharOperation.NO_CHAR_CHAR;
1117 int dot = CharOperation.indexOf(C_DOT, name);
1119 return new char[][] { name };
1122 while ((dot = CharOperation.indexOf(C_DOT, name, dot + 1)) != -1) {
1125 char[][] result = new char[n + 1][];
1127 for (int i = 0; i < n; ++i) {
1128 dot = CharOperation.indexOf(C_DOT, name, segStart);
1129 result[i] = CharOperation.subarray(name, segStart, dot);
1132 result[n] = CharOperation.subarray(name, segStart, name.length);
1137 * Returns all segments of the given dot-separated qualified name. Returns
1138 * an array with only the given name if it is not qualified. Returns an
1139 * empty array if the name is empty.
1145 * getSimpleNames("java.lang.Object") -> {"java", "lang", "Object"}
1146 * getSimpleNames("Object") -> {"Object"}
1147 * getSimpleNames("") -> {}
1153 * @return the list of simple names, possibly empty
1154 * @exception NullPointerException
1157 public static String[] getSimpleNames(String name) {
1158 char[][] simpleNames = getSimpleNames(name.toCharArray());
1159 int length = simpleNames.length;
1160 String[] result = new String[length];
1161 for (int i = 0; i < length; i++) {
1162 result[i] = new String(simpleNames[i]);
1168 * Converts the given method signature to a readable form. The method
1169 * signature is expected to be dot-based.
1175 * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
1181 * @param methodSignature
1182 * the method signature to convert
1184 * the name of the method to insert in the result, or
1185 * <code>null</code> if no method name is to be included
1186 * @param parameterNames
1187 * the parameter names to insert in the result, or
1188 * <code>null</code> if no parameter names are to be included;
1189 * if supplied, the number of parameter names must match that of
1190 * the method signature
1191 * @param fullyQualifyTypeNames
1192 * <code>true</code> if type names should be fully qualified,
1193 * and <code>false</code> to use only simple names
1194 * @param includeReturnType
1195 * <code>true</code> if the return type is to be included
1196 * @return the char array representation of the method signature
1200 public static char[] toCharArray(char[] methodSignature, char[] methodName,
1201 char[][] parameterNames, boolean fullyQualifyTypeNames,
1202 boolean includeReturnType) {
1204 int firstParen = CharOperation.indexOf(C_PARAM_START,
1206 if (firstParen == -1)
1207 throw new IllegalArgumentException();
1209 int sigLength = methodSignature.length;
1211 // compute result length
1216 int resultLength = 0;
1217 signature: for (int i = firstParen; i < sigLength; i++) {
1218 switch (methodSignature[i]) {
1220 resultLength += 2; // []
1223 resultLength += BOOLEAN.length;
1226 resultLength += BYTE.length;
1229 resultLength += CHAR.length;
1232 resultLength += DOUBLE.length;
1235 resultLength += FLOAT.length;
1238 resultLength += INT.length;
1241 resultLength += LONG.length;
1244 resultLength += SHORT.length;
1247 resultLength += VOID.length;
1251 int end = CharOperation.indexOf(C_SEMICOLON,
1252 methodSignature, i);
1254 throw new IllegalArgumentException();
1256 if (fullyQualifyTypeNames) {
1259 start = CharOperation.lastIndexOf(C_DOT,
1260 methodSignature, i, end) + 1;
1264 resultLength += end - start;
1268 // add space for "("
1273 if (includeReturnType) {
1274 if (paramCount > 0) {
1275 // remove space for ", " that was added with last
1276 // parameter and remove space that is going to be
1277 // added for ", " after return type
1278 // and add space for ") "
1281 // remove space that is going to be added for ", " after
1283 // and add space for ") "
1286 // decrement param count because it is going to be added
1291 if (paramCount > 0) {
1292 // remove space for ", " that was added with last
1293 // parameter and add space for ")"
1296 // add space for ")"
1302 throw new IllegalArgumentException();
1304 resultLength += 2; // add space for ", "
1309 int parameterNamesLength = parameterNames == null ? 0
1310 : parameterNames.length;
1311 for (int i = 0; i < parameterNamesLength; i++) {
1312 resultLength += parameterNames[i].length + 1; // parameter
1317 int selectorLength = methodName == null ? 0 : methodName.length;
1318 resultLength += selectorLength;
1320 // create resulting char array
1321 char[] result = new char[resultLength];
1325 if (includeReturnType) {
1326 long pos = copyType(methodSignature, lastParen + 1, result,
1327 index, fullyQualifyTypeNames);
1328 index = (int) (pos >>> 32);
1329 result[index++] = ' ';
1333 if (methodName != null) {
1334 System.arraycopy(methodName, 0, result, index, selectorLength);
1335 index += selectorLength;
1339 result[index++] = C_PARAM_START;
1340 int sigPos = firstParen + 1;
1341 for (int i = 0; i < paramCount; i++) {
1342 long pos = copyType(methodSignature, sigPos, result, index,
1343 fullyQualifyTypeNames);
1344 index = (int) (pos >>> 32);
1346 if (parameterNames != null) {
1347 result[index++] = ' ';
1348 char[] parameterName = parameterNames[i];
1349 int paramLength = parameterName.length;
1350 System.arraycopy(parameterName, 0, result, index,
1352 index += paramLength;
1354 if (i != paramCount - 1) {
1355 result[index++] = ',';
1356 result[index++] = ' ';
1359 if (sigPos >= sigLength) {
1360 throw new IllegalArgumentException(); // should be on last
1363 result[index++] = C_PARAM_END;
1366 } catch (ArrayIndexOutOfBoundsException e) {
1367 throw new IllegalArgumentException();
1372 * Converts the given type signature to a readable string. The signature is
1373 * expected to be dot-based.
1380 * 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', '[', ']'}
1381 * toString({'I'}) -> {'i', 'n', 't'}
1387 * Note: This method assumes that a type signature containing a
1388 * <code>'$'</code> is an inner type signature. While this is correct in
1389 * most cases, someone could define a non-inner type name containing a
1390 * <code>'$'</code>. Handling this correctly in all cases would have
1391 * required resolving the signature, which generally not feasible.
1395 * the type signature
1396 * @return the string representation of the type
1397 * @exception IllegalArgumentException
1398 * if the signature is not syntactically correct
1402 public static char[] toCharArray(char[] signature)
1403 throws IllegalArgumentException {
1405 int sigLength = signature.length;
1407 if (sigLength == 0 || signature[0] == C_PARAM_START) {
1408 return toCharArray(signature, CharOperation.NO_CHAR, null,
1412 // compute result length
1413 int resultLength = 0;
1415 while (signature[++index] == C_ARRAY) {
1416 resultLength += 2; // []
1418 switch (signature[index]) {
1420 resultLength += BOOLEAN.length;
1423 resultLength += BYTE.length;
1426 resultLength += CHAR.length;
1429 resultLength += DOUBLE.length;
1432 resultLength += FLOAT.length;
1435 resultLength += INT.length;
1438 resultLength += LONG.length;
1441 resultLength += SHORT.length;
1444 resultLength += VOID.length;
1448 int end = CharOperation.indexOf(C_SEMICOLON, signature, index);
1450 throw new IllegalArgumentException();
1451 int start = index + 1;
1452 resultLength += end - start;
1455 throw new IllegalArgumentException();
1458 char[] result = new char[resultLength];
1459 copyType(signature, 0, result, 0, true);
1462 * Converts '$' separated type signatures into '.' separated type
1463 * signature. NOTE: This assumes that the type signature is an inner
1464 * type signature. This is true in most cases, but someone can
1465 * define a non-inner type name containing a '$'. However to tell
1466 * the difference, we would have to resolve the signature, which
1467 * cannot be done at this point.
1469 CharOperation.replace(result, C_DOLLAR, C_DOT);
1472 } catch (ArrayIndexOutOfBoundsException e) {
1473 throw new IllegalArgumentException();
1478 * Converts the given array of qualified name segments to a qualified name.
1484 * 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'}
1485 * toQualifiedName({{'O', 'b', 'j', 'e', 'c', 't'}}) -> {'O', 'b', 'j', 'e', 'c', 't'}
1486 * toQualifiedName({{}}) -> {}
1493 * the list of name segments, possibly empty
1494 * @return the dot-separated qualified name, or the empty string
1498 public static char[] toQualifiedName(char[][] segments) {
1499 int length = segments.length;
1501 return CharOperation.NO_CHAR;
1505 int resultLength = 0;
1506 for (int i = 0; i < length; i++) {
1507 resultLength += segments[i].length + 1;
1510 char[] result = new char[resultLength];
1512 for (int i = 0; i < length; i++) {
1513 char[] segment = segments[i];
1514 int segmentLength = segment.length;
1515 System.arraycopy(segment, 0, result, index, segmentLength);
1516 index += segmentLength;
1517 if (i != length - 1) {
1518 result[index++] = C_DOT;
1525 * Converts the given array of qualified name segments to a qualified name.
1531 * toQualifiedName(new String[] {"java", "lang", "Object"}) -> "java.lang.Object"
1532 * toQualifiedName(new String[] {"Object"}) -> "Object"
1533 * toQualifiedName(new String[0]) -> ""
1540 * the list of name segments, possibly empty
1541 * @return the dot-separated qualified name, or the empty string
1543 public static String toQualifiedName(String[] segments) {
1544 int length = segments.length;
1545 char[][] charArrays = new char[length][];
1546 for (int i = 0; i < length; i++) {
1547 charArrays[i] = segments[i].toCharArray();
1549 return new String(toQualifiedName(charArrays));
1553 * Converts the given type signature to a readable string. The signature is
1554 * expected to be dot-based.
1561 * toString("[Ljava.lang.String;") -> "java.lang.String[]"
1562 * toString("I") -> "int"
1568 * Note: This method assumes that a type signature containing a
1569 * <code>'$'</code> is an inner type signature. While this is correct in
1570 * most cases, someone could define a non-inner type name containing a
1571 * <code>'$'</code>. Handling this correctly in all cases would have
1572 * required resolving the signature, which generally not feasible.
1576 * the type signature
1577 * @return the string representation of the type
1578 * @exception IllegalArgumentException
1579 * if the signature is not syntactically correct
1581 public static String toString(String signature)
1582 throws IllegalArgumentException {
1583 // return new String(toCharArray(signature.toCharArray()));
1588 * Converts the given method signature to a readable string. The method
1589 * signature is expected to be dot-based.
1595 * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
1601 * @param methodSignature
1602 * the method signature to convert
1604 * the name of the method to insert in the result, or
1605 * <code>null</code> if no method name is to be included
1606 * @param parameterNames
1607 * the parameter names to insert in the result, or
1608 * <code>null</code> if no parameter names are to be included;
1609 * if supplied, the number of parameter names must match that of
1610 * the method signature
1611 * @param fullyQualifyTypeNames
1612 * <code>true</code> if type names should be fully qualified,
1613 * and <code>false</code> to use only simple names
1614 * @param includeReturnType
1615 * <code>true</code> if the return type is to be included
1616 * @return the string representation of the method signature
1618 public static String toString(String methodSignature, String methodName,
1619 String[] parameterNames, boolean fullyQualifyTypeNames,
1620 boolean includeReturnType) {
1622 if (parameterNames == null) {
1625 int paramLength = parameterNames.length;
1626 params = new char[paramLength][];
1627 for (int i = 0; i < paramLength; i++) {
1628 params[i] = parameterNames[i].toCharArray();
1631 return new String(toCharArray(methodSignature.toCharArray(),
1632 methodName == null ? null : methodName.toCharArray(), params,
1633 fullyQualifyTypeNames, includeReturnType));