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:
30 * | "L" + binaryTypeName + ";" // resolved named type (in compiled code)
31 * | "Q" + sourceTypeName + ";" // unresolved named type (in source code)
32 * | "[" + typeSignature // array of type denoted by typeSignature
38 * <li><code>"[[I"</code> denotes <code>int[][]</code></li>
39 * <li><code>"Ljava.lang.String;"</code> denotes <code>java.lang.String</code> in compiled code</li>
40 * <li><code>"QString"</code> denotes <code>String</code> in source code</li>
41 * <li><code>"Qjava.lang.String"</code> denotes <code>java.lang.String</code> in source code</li>
42 * <li><code>"[QString"</code> denotes <code>String[]</code> in source code</li>
46 * The syntax for a method signature is:
48 * methodSignature ::= "(" + paramTypeSignature* + ")" + returnTypeSignature
49 * paramTypeSignature ::= typeSignature
50 * returnTypeSignature ::= typeSignature
55 * <li><code>"()I"</code> denotes <code>int foo()</code></li>
56 * <li><code>"([Ljava.lang.String;)V"</code> denotes <code>void foo(java.lang.String[])</code> in compiled code</li>
57 * <li><code>"(QString;)QObject;"</code> denotes <code>Object foo(String)</code> in source code</li>
61 * This class provides static methods and constants only; it is not intended to be
62 * instantiated or subclassed by clients.
65 public final class Signature {
68 * Character constant indicating the primitive type boolean in a signature.
69 * Value is <code>'Z'</code>.
71 public static final char C_BOOLEAN = 'Z';
74 * Character constant indicating the primitive type byte in a signature.
75 * Value is <code>'B'</code>.
77 public static final char C_BYTE = 'B';
80 * Character constant indicating the primitive type char in a signature.
81 * Value is <code>'C'</code>.
83 public static final char C_CHAR = 'C';
86 * Character constant indicating the primitive type double in a signature.
87 * Value is <code>'D'</code>.
89 public static final char C_DOUBLE = 'D';
92 * Character constant indicating the primitive type float in a signature.
93 * Value is <code>'F'</code>.
95 public static final char C_FLOAT = 'F';
98 * Character constant indicating the primitive type int in a signature.
99 * Value is <code>'I'</code>.
101 public static final char C_INT = 'I';
104 * Character constant indicating the semicolon in a signature.
105 * Value is <code>';'</code>.
107 public static final char C_SEMICOLON = ';';
110 * Character constant indicating the primitive type long in a signature.
111 * Value is <code>'J'</code>.
113 public static final char C_LONG = 'J';
116 * Character constant indicating the primitive type short in a signature.
117 * Value is <code>'S'</code>.
119 public static final char C_SHORT = 'S';
122 * Character constant indicating result type void in a signature.
123 * Value is <code>'V'</code>.
125 public static final char C_VOID = 'V';
128 * Character constant indicating the dot in a signature.
129 * Value is <code>'.'</code>.
131 public static final char C_DOT = '.';
134 * Character constant indicating the dollar in a signature.
135 * Value is <code>'$'</code>.
137 public static final char C_DOLLAR = '$';
140 * Character constant indicating an array type in a signature.
141 * Value is <code>'['</code>.
143 public static final char C_ARRAY = '[';
146 * Character constant indicating the start of a resolved, named type in a
147 * signature. Value is <code>'L'</code>.
149 public static final char C_RESOLVED = 'L';
152 * Character constant indicating the start of an unresolved, named type in a
153 * signature. Value is <code>'Q'</code>.
155 public static final char C_UNRESOLVED = 'Q';
158 * Character constant indicating the end of a named type in a signature.
159 * Value is <code>';'</code>.
161 public static final char C_NAME_END = ';';
164 * Character constant indicating the start of a parameter type list in a
165 * signature. Value is <code>'('</code>.
167 public static final char C_PARAM_START = '(';
170 * Character constant indicating the end of a parameter type list in a
171 * signature. Value is <code>')'</code>.
173 public static final char C_PARAM_END = ')';
176 * String constant for the signature of the primitive type boolean.
177 * Value is <code>"Z"</code>.
179 public static final String SIG_BOOLEAN = "Z"; //$NON-NLS-1$
182 * String constant for the signature of the primitive type byte.
183 * Value is <code>"B"</code>.
185 public static final String SIG_BYTE = "B"; //$NON-NLS-1$
188 * String constant for the signature of the primitive type char.
189 * Value is <code>"C"</code>.
191 public static final String SIG_CHAR = "C"; //$NON-NLS-1$
194 * String constant for the signature of the primitive type double.
195 * Value is <code>"D"</code>.
197 public static final String SIG_DOUBLE = "D"; //$NON-NLS-1$
200 * String constant for the signature of the primitive type float.
201 * Value is <code>"F"</code>.
203 public static final String SIG_FLOAT = "F"; //$NON-NLS-1$
206 * String constant for the signature of the primitive type int.
207 * Value is <code>"I"</code>.
209 public static final String SIG_INT = "I"; //$NON-NLS-1$
212 * String constant for the signature of the primitive type long.
213 * Value is <code>"J"</code>.
215 public static final String SIG_LONG = "J"; //$NON-NLS-1$
218 * String constant for the signature of the primitive type short.
219 * Value is <code>"S"</code>.
221 public static final String SIG_SHORT = "S"; //$NON-NLS-1$
223 /** String constant for the signature of result type void.
224 * Value is <code>"V"</code>.
226 public static final String SIG_VOID = "V"; //$NON-NLS-1$
228 private static final char[] BOOLEAN = {'b', 'o', 'o', 'l', 'e', 'a', 'n'};
229 private static final char[] BYTE = {'b', 'y', 't', 'e'};
230 private static final char[] CHAR = {'c', 'h', 'a', 'r'};
231 private static final char[] DOUBLE = {'d', 'o', 'u', 'b', 'l', 'e'};
232 private static final char[] FLOAT = {'f', 'l', 'o', 'a', 't'};
233 private static final char[] INT = {'i', 'n', 't'};
234 private static final char[] LONG = {'l', 'o', 'n', 'g'};
235 private static final char[] SHORT = {'s', 'h', 'o', 'r', 't'};
236 private static final char[] VOID = {'v', 'o', 'i', 'd'};
238 private static final String EMPTY = new String(CharOperation.NO_CHAR);
243 private Signature() {}
245 private static long copyType(char[] signature, int sigPos, char[] dest, int index, boolean fullyQualifyTypeNames) {
248 switch (signature[sigPos++]) {
253 int length = BOOLEAN.length;
254 System.arraycopy(BOOLEAN, 0, dest, index, length);
258 length = BYTE.length;
259 System.arraycopy(BYTE, 0, dest, index, length);
263 length = CHAR.length;
264 System.arraycopy(CHAR, 0, dest, index, length);
268 length = DOUBLE.length;
269 System.arraycopy(DOUBLE, 0, dest, index, length);
273 length = FLOAT.length;
274 System.arraycopy(FLOAT, 0, dest, index, length);
279 System.arraycopy(INT, 0, dest, index, length);
283 length = LONG.length;
284 System.arraycopy(LONG, 0, dest, index, length);
288 length = SHORT.length;
289 System.arraycopy(SHORT, 0, dest, index, length);
293 length = VOID.length;
294 System.arraycopy(VOID, 0, dest, index, length);
299 int end = CharOperation.indexOf(C_SEMICOLON, signature, sigPos);
300 if (end == -1) throw new IllegalArgumentException();
302 if (fullyQualifyTypeNames) {
305 start = CharOperation.lastIndexOf(C_DOT, signature, sigPos, end)+1;
306 if (start == 0) start = sigPos;
309 System.arraycopy(signature, start, dest, index, length);
315 while (arrayCount-- > 0) {
319 return (((long) index) << 32) + sigPos;
322 * Creates a new type signature with the given amount of array nesting added
323 * to the given type signature.
325 * @param typeSignature the type signature
326 * @param arrayCount the desired number of levels of array nesting
327 * @return the encoded array type signature
331 public static char[] createArraySignature(char[] typeSignature, int arrayCount) {
332 if (arrayCount == 0) return typeSignature;
333 int sigLength = typeSignature.length;
334 char[] result = new char[arrayCount + sigLength];
335 for (int i = 0; i < arrayCount; i++) {
338 System.arraycopy(typeSignature, 0, result, arrayCount, sigLength);
342 * Creates a new type signature with the given amount of array nesting added
343 * to the given type signature.
345 * @param typeSignature the type signature
346 * @param arrayCount the desired number of levels of array nesting
347 * @return the encoded array type signature
349 public static String createArraySignature(String typeSignature, int arrayCount) {
350 return new String(createArraySignature(typeSignature.toCharArray(), arrayCount));
353 * Creates a method signature from the given parameter and return type
354 * signatures. The encoded method signature is dot-based.
356 * @param parameterTypes the list of parameter type signatures
357 * @param returnType the return type signature
358 * @return the encoded method signature
362 public static char[] createMethodSignature(char[][] parameterTypes, char[] returnType) {
363 int parameterTypesLength = parameterTypes.length;
364 int parameterLength = 0;
365 for (int i = 0; i < parameterTypesLength; i++) {
366 parameterLength += parameterTypes[i].length;
369 int returnTypeLength = returnType.length;
370 char[] result = new char[1 + parameterLength + 1 + returnTypeLength];
371 result[0] = C_PARAM_START;
373 for (int i = 0; i < parameterTypesLength; i++) {
374 char[] parameterType = parameterTypes[i];
375 int length = parameterType.length;
376 System.arraycopy(parameterType, 0, result, index, length);
379 result[index] = C_PARAM_END;
380 System.arraycopy(returnType, 0, result, index+1, returnTypeLength);
384 * Creates a method signature from the given parameter and return type
385 * signatures. The encoded method signature is dot-based.
387 * @param parameterTypes the list of parameter type signatures
388 * @param returnType the return type signature
389 * @return the encoded method signature
391 public static String createMethodSignature(String[] parameterTypes, String returnType) {
392 int parameterTypesLenth = parameterTypes.length;
393 char[][] parameters = new char[parameterTypesLenth][];
394 for (int i = 0; i < parameterTypesLenth; i++) {
395 parameters[i] = parameterTypes[i].toCharArray();
397 return new String(createMethodSignature(parameters, returnType.toCharArray()));
400 * Creates a new type signature from the given type name encoded as a character
401 * array. This method is equivalent to
402 * <code>createTypeSignature(new String(typeName),isResolved)</code>, although
403 * more efficient for callers with character arrays rather than strings. If the
404 * type name is qualified, then it is expected to be dot-based.
406 * @param typeName the possibly qualified type name
407 * @param isResolved <code>true</code> if the type name is to be considered
408 * resolved (for example, a type name from a binary class file), and
409 * <code>false</code> if the type name is to be considered unresolved
410 * (for example, a type name found in source code)
411 * @return the encoded type signature
412 * @see #createTypeSignature(java.lang.String,boolean)
414 public static String createTypeSignature(char[] typeName, boolean isResolved) {
415 return new String(createCharArrayTypeSignature(typeName, isResolved));
418 * Creates a new type signature from the given type name encoded as a character
419 * array. This method is equivalent to
420 * <code>createTypeSignature(new String(typeName),isResolved).toCharArray()</code>, although
421 * more efficient for callers with character arrays rather than strings. If the
422 * type name is qualified, then it is expected to be dot-based.
424 * @param typeName the possibly qualified type name
425 * @param isResolved <code>true</code> if the type name is to be considered
426 * resolved (for example, a type name from a binary class file), and
427 * <code>false</code> if the type name is to be considered unresolved
428 * (for example, a type name found in source code)
429 * @return the encoded type signature
430 * @see #createTypeSignature(java.lang.String,boolean)
434 public static char[] createCharArrayTypeSignature(char[] typeName, boolean isResolved) {
436 if (typeName == null) throw new IllegalArgumentException("null"); //$NON-NLS-1$
437 int length = typeName.length;
438 if (length == 0) throw new IllegalArgumentException(new String(typeName));
440 int arrayCount = CharOperation.occurencesOf('[', typeName);
443 switch (typeName[0]) {
446 if (CharOperation.fragmentEquals(BOOLEAN, typeName, 0, true)) {
447 sig = new char[arrayCount+1];
448 sig[arrayCount] = C_BOOLEAN;
450 } else if (CharOperation.fragmentEquals(BYTE, typeName, 0, true)) {
451 sig = new char[arrayCount+1];
452 sig[arrayCount] = C_BYTE;
456 if (CharOperation.fragmentEquals(CHAR, typeName, 0, true)) {
457 sig = new char[arrayCount+1];
458 sig[arrayCount] = C_CHAR;
462 if (CharOperation.fragmentEquals(DOUBLE, typeName, 0, true)) {
463 sig = new char[arrayCount+1];
464 sig[arrayCount] = C_DOUBLE;
468 if (CharOperation.fragmentEquals(FLOAT, typeName, 0, true)) {
469 sig = new char[arrayCount+1];
470 sig[arrayCount] = C_FLOAT;
474 if (CharOperation.fragmentEquals(INT, typeName, 0, true)) {
475 sig = new char[arrayCount+1];
476 sig[arrayCount] = C_INT;
480 if (CharOperation.fragmentEquals(LONG, typeName, 0, true)) {
481 sig = new char[arrayCount+1];
482 sig[arrayCount] = C_LONG;
486 if (CharOperation.fragmentEquals(SHORT, typeName, 0, true)) {
487 sig = new char[arrayCount+1];
488 sig[arrayCount] = C_SHORT;
492 if (CharOperation.fragmentEquals(VOID, typeName, 0, true)) {
493 sig = new char[arrayCount+1];
494 sig[arrayCount] = C_VOID;
498 // non primitive type
499 int sigLength = arrayCount + 1 + length + 1; // for example '[[[Ljava.lang.String;'
500 sig = new char[sigLength];
501 int sigIndex = arrayCount+1; // index in sig
502 int startID = 0; // start of current ID in typeName
503 int index = 0; // index in typeName
504 while (index < length) {
505 char currentChar = typeName[index];
506 switch (currentChar) {
508 if (startID == -1) throw new IllegalArgumentException(new String(typeName));
509 if (startID < index) {
510 sig = CharOperation.append(sig, sigIndex, typeName, startID, index);
511 sigIndex += index-startID;
513 sig[sigIndex++] = C_DOT;
519 if (startID < index) {
520 sig = CharOperation.append(sig, sigIndex, typeName, startID, index);
521 sigIndex += index-startID;
523 startID = -1; // no more id after []
528 if (startID != -1 && CharOperation.isWhitespace(currentChar)) {
529 if (startID < index) {
530 sig = CharOperation.append(sig, sigIndex, typeName, startID, index);
531 sigIndex += index-startID;
540 if (startID != -1 && startID < index) {
541 sig = CharOperation.append(sig, sigIndex, typeName, startID, index);
542 sigIndex += index-startID;
545 // add L (or Q) at the beigininig and ; at the end
546 sig[arrayCount] = isResolved ? C_RESOLVED : C_UNRESOLVED;
547 sig[sigIndex++] = C_NAME_END;
550 if (sigLength > sigIndex) {
551 System.arraycopy(sig, 0, sig = new char[sigIndex], 0, sigIndex);
556 for (int i = 0; i < arrayCount; i++) {
563 * Creates a new type signature from the given type name. If the type name is qualified,
564 * then it is expected to be dot-based.
569 * createTypeSignature("int", hucairz) -> "I"
570 * createTypeSignature("java.lang.String", true) -> "Ljava.lang.String;"
571 * createTypeSignature("String", false) -> "QString;"
572 * createTypeSignature("java.lang.String", false) -> "Qjava.lang.String;"
573 * createTypeSignature("int []", false) -> "[I"
578 * @param typeName the possibly qualified type name
579 * @param isResolved <code>true</code> if the type name is to be considered
580 * resolved (for example, a type name from a binary class file), and
581 * <code>false</code> if the type name is to be considered unresolved
582 * (for example, a type name found in source code)
583 * @return the encoded type signature
585 public static String createTypeSignature(String typeName, boolean isResolved) {
586 return createTypeSignature(typeName == null ? null : typeName.toCharArray(), isResolved);
589 * Returns the array count (array nesting depth) of the given type signature.
591 * @param typeSignature the type signature
592 * @return the array nesting depth, or 0 if not an array
593 * @exception IllegalArgumentException if the signature is not syntactically
598 public static int getArrayCount(char[] typeSignature) throws IllegalArgumentException {
601 while (typeSignature[count] == C_ARRAY) {
605 } catch (ArrayIndexOutOfBoundsException e) { // signature is syntactically incorrect if last character is C_ARRAY
606 throw new IllegalArgumentException();
610 * Returns the array count (array nesting depth) of the given type signature.
612 * @param typeSignature the type signature
613 * @return the array nesting depth, or 0 if not an array
614 * @exception IllegalArgumentException if the signature is not syntactically
617 public static int getArrayCount(String typeSignature) throws IllegalArgumentException {
618 return getArrayCount(typeSignature.toCharArray());
621 * Returns the type signature without any array nesting.
626 * getElementType({'[', '[', 'I'}) --> {'I'}.
631 * @param typeSignature the type signature
632 * @return the type signature without arrays
633 * @exception IllegalArgumentException if the signature is not syntactically
638 public static char[] getElementType(char[] typeSignature) throws IllegalArgumentException {
639 int count = getArrayCount(typeSignature);
640 if (count == 0) return typeSignature;
641 int length = typeSignature.length;
642 char[] result = new char[length-count];
643 System.arraycopy(typeSignature, count, result, 0, length-count);
647 * Returns the type signature without any array nesting.
652 * getElementType("[[I") --> "I".
657 * @param typeSignature the type signature
658 * @return the type signature without arrays
659 * @exception IllegalArgumentException if the signature is not syntactically
662 public static String getElementType(String typeSignature) throws IllegalArgumentException {
663 return new String(getElementType(typeSignature.toCharArray()));
666 * Returns the number of parameter types in the given method signature.
668 * @param methodSignature the method signature
669 * @return the number of parameters
670 * @exception IllegalArgumentException if the signature is not syntactically
674 public static int getParameterCount(char[] methodSignature) throws IllegalArgumentException {
677 int i = CharOperation.indexOf(C_PARAM_START, methodSignature) + 1;
679 throw new IllegalArgumentException();
681 char c = methodSignature[i++];
698 i = CharOperation.indexOf(C_SEMICOLON, methodSignature, i) + 1;
700 throw new IllegalArgumentException();
706 throw new IllegalArgumentException();
709 } catch (ArrayIndexOutOfBoundsException e) {
710 throw new IllegalArgumentException();
714 * Returns the number of parameter types in the given method signature.
716 * @param methodSignature the method signature
717 * @return the number of parameters
718 * @exception IllegalArgumentException if the signature is not syntactically
721 public static int getParameterCount(String methodSignature) throws IllegalArgumentException {
722 return getParameterCount(methodSignature.toCharArray());
725 * Extracts the parameter type signatures from the given method signature.
726 * The method signature is expected to be dot-based.
728 * @param methodSignature the method signature
729 * @return the list of parameter type signatures
730 * @exception IllegalArgumentException if the signature is syntactically
735 public static char[][] getParameterTypes(char[] methodSignature) throws IllegalArgumentException {
737 int count = getParameterCount(methodSignature);
738 char[][] result = new char[count][];
741 int i = CharOperation.indexOf(C_PARAM_START, methodSignature) + 1;
745 char c = methodSignature[i++];
748 // array depth is i - start;
759 // common case of base types
760 if (i - start == 1) {
763 result[count++] = new char[] {C_BOOLEAN};
766 result[count++] = new char[] {C_BYTE};
769 result[count++] = new char[] {C_CHAR};
772 result[count++] = new char[] {C_DOUBLE};
775 result[count++] = new char[] {C_FLOAT};
778 result[count++] = new char[] {C_INT};
781 result[count++] = new char[] {C_LONG};
784 result[count++] = new char[] {C_SHORT};
787 result[count++] = new char[] {C_VOID};
791 result[count++] = CharOperation.subarray(methodSignature, start, i);
797 i = CharOperation.indexOf(C_SEMICOLON, methodSignature, i) + 1;
799 throw new IllegalArgumentException();
800 result[count++] = CharOperation.subarray(methodSignature, start, i);
806 throw new IllegalArgumentException();
809 } catch (ArrayIndexOutOfBoundsException e) {
810 throw new IllegalArgumentException();
814 * Extracts the parameter type signatures from the given method signature.
815 * The method signature is expected to be dot-based.
817 * @param methodSignature the method signature
818 * @return the list of parameter type signatures
819 * @exception IllegalArgumentException if the signature is syntactically
822 public static String[] getParameterTypes(String methodSignature) throws IllegalArgumentException {
823 char[][] parameterTypes = getParameterTypes(methodSignature.toCharArray());
824 int length = parameterTypes.length;
825 String[] result = new String[length];
826 for (int i = 0; i < length; i++) {
827 result[i] = new String(parameterTypes[i]);
832 * Returns a char array containing all but the last segment of the given
833 * dot-separated qualified name. Returns the empty char array if it is not qualified.
838 * getQualifier({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g'}
839 * getQualifier({'O', 'u', 't', 'e', 'r', '.', 'I', 'n', 'n', 'e', 'r'}) -> {'O', 'u', 't', 'e', 'r'}
844 * @param name the name
845 * @return the qualifier prefix, or the empty char array if the name contains no
847 * @exception NullPointerException if name is null
850 public static char[] getQualifier(char[] name) {
851 int lastDot = CharOperation.lastIndexOf(C_DOT, name);
853 return CharOperation.NO_CHAR;
855 return CharOperation.subarray(name, 0, lastDot);
858 * Returns a string containing all but the last segment of the given
859 * dot-separated qualified name. Returns the empty string if it is not qualified.
864 * getQualifier("java.lang.Object") -> "java.lang"
865 * getQualifier("Outer.Inner") -> "Outer"
870 * @param name the name
871 * @return the qualifier prefix, or the empty string if the name contains no
873 * @exception NullPointerException if name is null
875 public static String getQualifier(String name) {
876 int lastDot = name.lastIndexOf(C_DOT);
880 return name.substring(0, lastDot);
883 * Extracts the return type from the given method signature. The method signature is
884 * expected to be dot-based.
886 * @param methodSignature the method signature
887 * @return the type signature of the return type
888 * @exception IllegalArgumentException if the signature is syntactically
893 public static char[] getReturnType(char[] methodSignature) throws IllegalArgumentException {
894 int i = CharOperation.lastIndexOf(C_PARAM_END, methodSignature);
896 throw new IllegalArgumentException();
898 return CharOperation.subarray(methodSignature, i + 1, methodSignature.length);
901 * Extracts the return type from the given method signature. The method signature is
902 * expected to be dot-based.
904 * @param methodSignature the method signature
905 * @return the type signature of the return type
906 * @exception IllegalArgumentException if the signature is syntactically
909 public static String getReturnType(String methodSignature) throws IllegalArgumentException {
910 return new String(getReturnType(methodSignature.toCharArray()));
913 * Returns the last segment of the given dot-separated qualified name.
914 * Returns the given name if it is not qualified.
919 * getSimpleName({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'O', 'b', 'j', 'e', 'c', 't'}
924 * @param name the name
925 * @return the last segment of the qualified name
926 * @exception NullPointerException if name is null
929 public static char[] getSimpleName(char[] name) {
930 int lastDot = CharOperation.lastIndexOf(C_DOT, name);
934 return CharOperation.subarray(name, lastDot + 1, name.length);
937 * Returns the last segment of the given dot-separated qualified name.
938 * Returns the given name if it is not qualified.
943 * getSimpleName("java.lang.Object") -> "Object"
948 * @param name the name
949 * @return the last segment of the qualified name
950 * @exception NullPointerException if name is null
952 public static String getSimpleName(String name) {
953 int lastDot = name.lastIndexOf(C_DOT);
957 return name.substring(lastDot + 1, name.length());
960 * Returns all segments of the given dot-separated qualified name.
961 * Returns an array with only the given name if it is not qualified.
962 * Returns an empty array if the name is empty.
967 * 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'}}
968 * getSimpleNames({'O', 'b', 'j', 'e', 'c', 't'}) -> {{'O', 'b', 'j', 'e', 'c', 't'}}
969 * getSimpleNames("") -> {}
973 * @param name the name
974 * @return the list of simple names, possibly empty
975 * @exception NullPointerException if name is null
978 public static char[][] getSimpleNames(char[] name) {
979 if (name.length == 0) {
980 return CharOperation.NO_CHAR_CHAR;
982 int dot = CharOperation.indexOf(C_DOT, name);
984 return new char[][] {name};
987 while ((dot = CharOperation.indexOf(C_DOT, name, dot + 1)) != -1) {
990 char[][] result = new char[n + 1][];
992 for (int i = 0; i < n; ++i) {
993 dot = CharOperation.indexOf(C_DOT, name, segStart);
994 result[i] = CharOperation.subarray(name, segStart, dot);
997 result[n] = CharOperation.subarray(name, segStart, name.length);
1001 * Returns all segments of the given dot-separated qualified name.
1002 * Returns an array with only the given name if it is not qualified.
1003 * Returns an empty array if the name is empty.
1008 * getSimpleNames("java.lang.Object") -> {"java", "lang", "Object"}
1009 * getSimpleNames("Object") -> {"Object"}
1010 * getSimpleNames("") -> {}
1014 * @param name the name
1015 * @return the list of simple names, possibly empty
1016 * @exception NullPointerException if name is null
1018 public static String[] getSimpleNames(String name) {
1019 char[][] simpleNames = getSimpleNames(name.toCharArray());
1020 int length = simpleNames.length;
1021 String[] result = new String[length];
1022 for (int i = 0; i < length; i++) {
1023 result[i] = new String(simpleNames[i]);
1028 * Converts the given method signature to a readable form. The method signature is expected to
1034 * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
1039 * @param methodSignature the method signature to convert
1040 * @param methodName the name of the method to insert in the result, or
1041 * <code>null</code> if no method name is to be included
1042 * @param parameterNames the parameter names to insert in the result, or
1043 * <code>null</code> if no parameter names are to be included; if supplied,
1044 * the number of parameter names must match that of the method signature
1045 * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
1046 * qualified, and <code>false</code> to use only simple names
1047 * @param includeReturnType <code>true</code> if the return type is to be
1049 * @return the char array representation of the method signature
1053 public static char[] toCharArray(char[] methodSignature, char[] methodName, char[][] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) {
1055 int firstParen = CharOperation.indexOf(C_PARAM_START, methodSignature);
1056 if (firstParen == -1) throw new IllegalArgumentException();
1058 int sigLength = methodSignature.length;
1060 // compute result length
1065 int resultLength = 0;
1066 signature: for (int i = firstParen; i < sigLength; i++) {
1067 switch (methodSignature[i]) {
1069 resultLength += 2; // []
1072 resultLength += BOOLEAN.length;
1075 resultLength += BYTE.length;
1078 resultLength += CHAR.length;
1081 resultLength += DOUBLE.length;
1084 resultLength += FLOAT.length;
1087 resultLength += INT.length;
1090 resultLength += LONG.length;
1093 resultLength += SHORT.length;
1096 resultLength += VOID.length;
1100 int end = CharOperation.indexOf(C_SEMICOLON, methodSignature, i);
1101 if (end == -1) throw new IllegalArgumentException();
1103 if (fullyQualifyTypeNames) {
1106 start = CharOperation.lastIndexOf(C_DOT, methodSignature, i, end) + 1;
1107 if (start == 0) start = i+1;
1109 resultLength += end-start;
1112 case C_PARAM_START :
1113 // add space for "("
1118 if (includeReturnType) {
1119 if (paramCount > 0) {
1120 // remove space for ", " that was added with last parameter and remove space that is going to be added for ", " after return type
1121 // and add space for ") "
1124 // remove space that is going to be added for ", " after return type
1125 // and add space for ") "
1128 // decrement param count because it is going to be added for return type
1132 if (paramCount > 0) {
1133 // remove space for ", " that was added with last parameter and add space for ")"
1136 // add space for ")"
1142 throw new IllegalArgumentException();
1144 resultLength += 2; // add space for ", "
1149 int parameterNamesLength = parameterNames == null ? 0 : parameterNames.length;
1150 for (int i = 0; i <parameterNamesLength; i++) {
1151 resultLength += parameterNames[i].length + 1; // parameter name + space
1155 int selectorLength = methodName == null ? 0 : methodName.length;
1156 resultLength += selectorLength;
1158 // create resulting char array
1159 char[] result = new char[resultLength];
1163 if (includeReturnType) {
1164 long pos = copyType(methodSignature, lastParen+1, result, index, fullyQualifyTypeNames);
1165 index = (int) (pos >>> 32);
1166 result[index++] = ' ';
1170 if (methodName != null) {
1171 System.arraycopy(methodName, 0, result, index, selectorLength);
1172 index += selectorLength;
1176 result[index++] = C_PARAM_START;
1177 int sigPos = firstParen+1;
1178 for (int i = 0; i < paramCount; i++) {
1179 long pos = copyType(methodSignature, sigPos, result, index, fullyQualifyTypeNames);
1180 index = (int) (pos >>> 32);
1182 if (parameterNames != null) {
1183 result[index++] = ' ';
1184 char[] parameterName = parameterNames[i];
1185 int paramLength = parameterName.length;
1186 System.arraycopy(parameterName, 0, result, index, paramLength);
1187 index += paramLength;
1189 if (i != paramCount-1) {
1190 result[index++] = ',';
1191 result[index++] = ' ';
1194 if (sigPos >= sigLength) {
1195 throw new IllegalArgumentException(); // should be on last paren
1197 result[index++] = C_PARAM_END;
1200 } catch (ArrayIndexOutOfBoundsException e) {
1201 throw new IllegalArgumentException();
1205 * Converts the given type signature to a readable string. The signature is expected to
1212 * 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', '[', ']'}
1213 * toString({'I'}) -> {'i', 'n', 't'}
1218 * Note: This method assumes that a type signature containing a <code>'$'</code>
1219 * is an inner type signature. While this is correct in most cases, someone could
1220 * define a non-inner type name containing a <code>'$'</code>. Handling this
1221 * correctly in all cases would have required resolving the signature, which
1222 * generally not feasible.
1225 * @param signature the type signature
1226 * @return the string representation of the type
1227 * @exception IllegalArgumentException if the signature is not syntactically
1232 public static char[] toCharArray(char[] signature) throws IllegalArgumentException {
1234 int sigLength = signature.length;
1236 if (sigLength == 0 || signature[0] == C_PARAM_START) {
1237 return toCharArray(signature, CharOperation.NO_CHAR, null, true, true);
1240 // compute result length
1241 int resultLength = 0;
1243 while (signature[++index] == C_ARRAY) {
1244 resultLength += 2; // []
1246 switch (signature[index]) {
1248 resultLength += BOOLEAN.length;
1251 resultLength += BYTE.length;
1254 resultLength += CHAR.length;
1257 resultLength += DOUBLE.length;
1260 resultLength += FLOAT.length;
1263 resultLength += INT.length;
1266 resultLength += LONG.length;
1269 resultLength += SHORT.length;
1272 resultLength += VOID.length;
1276 int end = CharOperation.indexOf(C_SEMICOLON, signature, index);
1277 if (end == -1) throw new IllegalArgumentException();
1278 int start = index + 1;
1279 resultLength += end-start;
1282 throw new IllegalArgumentException();
1285 char[] result = new char[resultLength];
1286 copyType(signature, 0, result, 0, true);
1289 * Converts '$' separated type signatures into '.' separated type signature.
1290 * NOTE: This assumes that the type signature is an inner type signature.
1291 * This is true in most cases, but someone can define a non-inner type
1292 * name containing a '$'. However to tell the difference, we would have
1293 * to resolve the signature, which cannot be done at this point.
1295 CharOperation.replace(result, C_DOLLAR, C_DOT);
1298 } catch (ArrayIndexOutOfBoundsException e) {
1299 throw new IllegalArgumentException();
1303 * Converts the given array of qualified name segments to a qualified name.
1308 * 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'}
1309 * toQualifiedName({{'O', 'b', 'j', 'e', 'c', 't'}}) -> {'O', 'b', 'j', 'e', 'c', 't'}
1310 * toQualifiedName({{}}) -> {}
1315 * @param segments the list of name segments, possibly empty
1316 * @return the dot-separated qualified name, or the empty string
1320 public static char[] toQualifiedName(char[][] segments) {
1321 int length = segments.length;
1322 if (length == 0) return CharOperation.NO_CHAR;
1323 if (length == 1) return segments[0];
1325 int resultLength = 0;
1326 for (int i = 0; i < length; i++) {
1327 resultLength += segments[i].length+1;
1330 char[] result = new char[resultLength];
1332 for (int i = 0; i < length; i++) {
1333 char[] segment = segments[i];
1334 int segmentLength = segment.length;
1335 System.arraycopy(segment, 0, result, index, segmentLength);
1336 index += segmentLength;
1337 if (i != length-1) {
1338 result[index++] = C_DOT;
1344 * Converts the given array of qualified name segments to a qualified name.
1349 * toQualifiedName(new String[] {"java", "lang", "Object"}) -> "java.lang.Object"
1350 * toQualifiedName(new String[] {"Object"}) -> "Object"
1351 * toQualifiedName(new String[0]) -> ""
1356 * @param segments the list of name segments, possibly empty
1357 * @return the dot-separated qualified name, or the empty string
1359 public static String toQualifiedName(String[] segments) {
1360 int length = segments.length;
1361 char[][] charArrays = new char[length][];
1362 for (int i = 0; i < length; i++) {
1363 charArrays[i] = segments[i].toCharArray();
1365 return new String(toQualifiedName(charArrays));
1368 * Converts the given type signature to a readable string. The signature is expected to
1375 * toString("[Ljava.lang.String;") -> "java.lang.String[]"
1376 * toString("I") -> "int"
1381 * Note: This method assumes that a type signature containing a <code>'$'</code>
1382 * is an inner type signature. While this is correct in most cases, someone could
1383 * define a non-inner type name containing a <code>'$'</code>. Handling this
1384 * correctly in all cases would have required resolving the signature, which
1385 * generally not feasible.
1388 * @param signature the type signature
1389 * @return the string representation of the type
1390 * @exception IllegalArgumentException if the signature is not syntactically
1393 public static String toString(String signature) throws IllegalArgumentException {
1394 return new String(toCharArray(signature.toCharArray()));
1397 * Converts the given method signature to a readable string. The method signature is expected to
1403 * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
1408 * @param methodSignature the method signature to convert
1409 * @param methodName the name of the method to insert in the result, or
1410 * <code>null</code> if no method name is to be included
1411 * @param parameterNames the parameter names to insert in the result, or
1412 * <code>null</code> if no parameter names are to be included; if supplied,
1413 * the number of parameter names must match that of the method signature
1414 * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
1415 * qualified, and <code>false</code> to use only simple names
1416 * @param includeReturnType <code>true</code> if the return type is to be
1418 * @return the string representation of the method signature
1420 public static String toString(String methodSignature, String methodName, String[] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) {
1422 if (parameterNames == null) {
1425 int paramLength = parameterNames.length;
1426 params = new char[paramLength][];
1427 for (int i = 0; i < paramLength; i++) {
1428 params[i] = parameterNames[i].toCharArray();
1431 return new String(toCharArray(methodSignature.toCharArray(), methodName == null ? null : methodName.toCharArray(), params, fullyQualifyTypeNames, includeReturnType));