18d33366c01a84f9b79b500254cb53cb333c0991
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / Signature.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v0.5 
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v05.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  ******************************************************************************/
11 package net.sourceforge.phpdt.core;
12
13 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
14 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
15 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
16 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
17
18 /**
19  * Provides methods for encoding and decoding type and method signature strings.
20  * <p>
21  * The syntax for a type signature is:
22  * <pre>
23  * typeSignature ::=
24  *     "B"  // byte
25  *   | "C"  // char
26  *   | "D"  // double
27  *   | "F"  // float
28  *   | "I"  // int
29  *   | "J"  // long
30  *   | "S"  // short
31  *   | "V"  // void
32  *   | "Z"  // boolean
33  *   | "L" + binaryTypeName + ";"  // resolved named type (i.e., in compiled code)
34  *   | "Q" + sourceTypeName + ";"  // unresolved named type (i.e., in source code)
35  *   | "[" + typeSignature  // array of type denoted by typeSignature
36  * </pre>
37  * </p>
38  * <p>
39  * Examples:
40  * <ul>
41  *   <li><code>"[[I"</code> denotes <code>int[][]</code></li>
42  *   <li><code>"Ljava.lang.String;"</code> denotes <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> in source code</li>
45  *   <li><code>"[QString"</code> denotes <code>String[]</code> in source code</li>
46  * </ul>
47  * </p>
48  * <p>
49  * The syntax for a method signature is:
50  * <pre>
51  * methodSignature ::= "(" + paramTypeSignature* + ")" + returnTypeSignature
52  * paramTypeSignature ::= typeSignature
53  * returnTypeSignature ::= typeSignature
54  * </pre>
55  * <p>
56  * Examples:
57  * <ul>
58  *   <li><code>"()I"</code> denotes <code>int foo()</code></li>
59  *   <li><code>"([Ljava.lang.String;)V"</code> denotes <code>void foo(java.lang.String[])</code> in compiled code</li>
60  *   <li><code>"(QString;)QObject;"</code> denotes <code>Object foo(String)</code> in source code</li>
61  * </ul>
62  * </p>
63  * <p>
64  * This class provides static methods and constants only; it is not intended to be
65  * instantiated or subclassed by clients.
66  * </p>
67  */
68 public final class Signature {
69
70         /**
71          * Character constant indicating the primitive type boolean in a signature.
72          * Value is <code>'Z'</code>.
73          */
74         public static final char C_BOOLEAN              = 'Z';
75
76         /**
77          * Character constant indicating the primitive type byte in a signature.
78          * Value is <code>'B'</code>.
79          */
80         public static final char C_BYTE                 = 'B';
81
82         /**
83          * Character constant indicating the primitive type char in a signature.
84          * Value is <code>'C'</code>.
85          */
86         public static final char C_CHAR                 = 'C';
87
88         /**
89          * Character constant indicating the primitive type double in a signature.
90          * Value is <code>'D'</code>.
91          */
92         public static final char C_DOUBLE               = 'D';
93
94         /**
95          * Character constant indicating the primitive type float in a signature.
96          * Value is <code>'F'</code>.
97          */
98         public static final char C_FLOAT                = 'F';
99
100         /**
101          * Character constant indicating the primitive type int in a signature.
102          * Value is <code>'I'</code>.
103          */
104         public static final char C_INT                  = 'I';
105         
106         /**
107          * Character constant indicating the semicolon in a signature.
108          * Value is <code>';'</code>.
109          */
110         public static final char C_SEMICOLON                    = ';';
111
112         /**
113          * Character constant indicating the primitive type long in a signature.
114          * Value is <code>'J'</code>.
115          */
116         public static final char C_LONG                 = 'J';
117         
118         /**
119          * Character constant indicating the primitive type short in a signature.
120          * Value is <code>'S'</code>.
121          */
122         public static final char C_SHORT                = 'S';
123         
124         /**
125          * Character constant indicating result type void in a signature.
126          * Value is <code>'V'</code>.
127          */
128         public static final char C_VOID                 = 'V';
129         
130         /** 
131          * Character constant indicating the dot in a signature. 
132          * Value is <code>'.'</code>.
133          */
134         public static final char C_DOT                  = '.';
135         
136         /** 
137          * Character constant indicating the dollar in a signature.
138          * Value is <code>'$'</code>.
139          */
140         public static final char C_DOLLAR                       = '$';
141
142         /** 
143          * Character constant indicating an array type in a signature.
144          * Value is <code>'['</code>.
145          */
146         public static final char C_ARRAY                = '[';
147
148         /** 
149          * Character constant indicating the start of a resolved, named type in a 
150          * signature. Value is <code>'L'</code>.
151          */
152         public static final char C_RESOLVED             = 'L';
153
154         /** 
155          * Character constant indicating the start of an unresolved, named type in a
156          * signature. Value is <code>'Q'</code>.
157          */
158         public static final char C_UNRESOLVED   = 'Q';
159
160         /**
161          * Character constant indicating the end of a named type in a signature. 
162          * Value is <code>';'</code>.
163          */
164         public static final char C_NAME_END             = ';';
165
166         /**
167          * Character constant indicating the start of a parameter type list in a
168          * signature. Value is <code>'('</code>.
169          */
170         public static final char C_PARAM_START  = '(';
171
172         /**
173          * Character constant indicating the end of a parameter type list in a 
174          * signature. Value is <code>')'</code>.
175          */
176         public static final char C_PARAM_END    = ')';
177
178         /**
179          * String constant for the signature of the primitive type boolean.
180          * Value is <code>"Z"</code>.
181          */
182         public static final String SIG_BOOLEAN          = "Z"; //$NON-NLS-1$
183
184         /**
185          * String constant for the signature of the primitive type byte. 
186          * Value is <code>"B"</code>.
187          */
188         public static final String SIG_BYTE             = "B"; //$NON-NLS-1$
189
190         /**
191          * String constant for the signature of the primitive type char.
192          * Value is <code>"C"</code>.
193          */
194         public static final String SIG_CHAR             = "C"; //$NON-NLS-1$
195
196         /**
197          * String constant for the signature of the primitive type double.
198          * Value is <code>"D"</code>.
199          */
200         public static final String SIG_DOUBLE           = "D"; //$NON-NLS-1$
201
202         /**
203          * String constant for the signature of the primitive type float.
204          * Value is <code>"F"</code>.
205          */
206         public static final String SIG_FLOAT            = "F"; //$NON-NLS-1$
207
208         /**
209          * String constant for the signature of the primitive type int.
210          * Value is <code>"I"</code>.
211          */
212         public static final String SIG_INT                      = "I"; //$NON-NLS-1$
213
214         /**
215          * String constant for the signature of the primitive type long.
216          * Value is <code>"J"</code>.
217          */
218         public static final String SIG_LONG                     = "J"; //$NON-NLS-1$
219
220         /**
221          * String constant for the signature of the primitive type short.
222          * Value is <code>"S"</code>.
223          */
224         public static final String SIG_SHORT            = "S"; //$NON-NLS-1$
225
226         /** String constant for the signature of result type void.
227          * Value is <code>"V"</code>.
228          */
229         public static final String SIG_VOID                     = "V"; //$NON-NLS-1$
230         
231         private static final char[] NO_CHAR = new char[0];
232         private static final char[][] NO_CHAR_CHAR = new char[0][];
233         private static final char[] BOOLEAN = {'b', 'o', 'o', 'l', 'e', 'a', 'n'};
234         private static final char[] BYTE = {'b', 'y', 't', 'e'};
235         private static final char[] CHAR = {'c', 'h', 'a', 'r'};
236         private static final char[] DOUBLE = {'d', 'o', 'u', 'b', 'l', 'e'};
237         private static final char[] FLOAT = {'f', 'l', 'o', 'a', 't'};
238         private static final char[] INT = {'i', 'n', 't'};
239         private static final char[] LONG = {'l', 'o', 'n', 'g'};
240         private static final char[] SHORT = {'s', 'h', 'o', 'r', 't'};
241         private static final char[] VOID = {'v', 'o', 'i', 'd'};
242         
243         
244 /**
245  * Not instantiable.
246  */
247 private Signature() {}
248
249 private static long copyType(char[] signature, int sigPos, char[] dest, int index, boolean fullyQualifyTypeNames) {
250         int arrayCount = 0;
251         loop: while (true) {
252                 switch (signature[sigPos++]) {
253                         case C_ARRAY :
254                                 arrayCount++;
255                                 break;
256                         case C_BOOLEAN :
257                                 int length = BOOLEAN.length;
258                                 System.arraycopy(BOOLEAN, 0, dest, index, length);
259                                 index += length;
260                                 break loop;
261                         case C_BYTE :
262                                 length = BYTE.length;
263                                 System.arraycopy(BYTE, 0, dest, index, length);
264                                 index += length;
265                                 break loop;
266                         case C_CHAR :
267                                 length = CHAR.length;
268                                 System.arraycopy(CHAR, 0, dest, index, length);
269                                 index += length;
270                                 break loop;
271                         case C_DOUBLE :
272                                 length = DOUBLE.length;
273                                 System.arraycopy(DOUBLE, 0, dest, index, length);
274                                 index += length;
275                                 break loop;
276                         case C_FLOAT :
277                                 length = FLOAT.length;
278                                 System.arraycopy(FLOAT, 0, dest, index, length);
279                                 index += length;
280                                 break loop;
281                         case C_INT :
282                                 length = INT.length;
283                                 System.arraycopy(INT, 0, dest, index, length);
284                                 index += length;
285                                 break loop;
286                         case C_LONG :
287                                 length = LONG.length;
288                                 System.arraycopy(LONG, 0, dest, index, length);
289                                 index += length;
290                                 break loop;
291                         case C_SHORT :
292                                 length = SHORT.length;
293                                 System.arraycopy(SHORT, 0, dest, index, length);
294                                 index += length;
295                                 break loop;
296                         case C_VOID :
297                                 length = VOID.length;
298                                 System.arraycopy(VOID, 0, dest, index, length);
299                                 index += length;
300                                 break loop;
301                         case C_RESOLVED :
302                         case C_UNRESOLVED :
303                                 int end = CharOperation.indexOf(C_SEMICOLON, signature, sigPos);
304                                 if (end == -1) throw new IllegalArgumentException();
305                                 int start;
306                                 if (fullyQualifyTypeNames) {
307                                         start = sigPos;
308                                 } else {
309                                         start = CharOperation.lastIndexOf(C_DOT, signature, sigPos, end)+1;
310                                         if (start == 0) start = sigPos;
311                                 } 
312                                 length = end-start;
313                                 System.arraycopy(signature, start, dest, index, length);
314                                 sigPos = end+1;
315                                 index += length;
316                                 break loop;
317                 }
318         }
319         while (arrayCount-- > 0) {
320                 dest[index++] = '[';
321                 dest[index++] = ']';
322         }
323         return (((long) index) << 32) + sigPos;
324 }
325 /**
326  * Creates a new type signature with the given amount of array nesting added 
327  * to the given type signature.
328  *
329  * @param typeSignature the type signature
330  * @param arrayCount the desired number of levels of array nesting
331  * @return the encoded array type signature
332  * 
333  * @since 2.0
334  */
335 public static char[] createArraySignature(char[] typeSignature, int arrayCount) {
336         if (arrayCount == 0) return typeSignature;
337         int sigLength = typeSignature.length;
338         char[] result = new char[arrayCount + sigLength];
339         for (int i = 0; i < arrayCount; i++) {
340                 result[i] = C_ARRAY;
341         }
342         System.arraycopy(typeSignature, 0, result, arrayCount, sigLength);
343         return result;
344 }
345 /**
346  * Creates a new type signature with the given amount of array nesting added 
347  * to the given type signature.
348  *
349  * @param typeSignature the type signature
350  * @param arrayCount the desired number of levels of array nesting
351  * @return the encoded array type signature
352  */
353 public static String createArraySignature(String typeSignature, int arrayCount) {
354         return new String(createArraySignature(typeSignature.toCharArray(), arrayCount));
355 }
356 /**
357  * Creates a method signature from the given parameter and return type 
358  * signatures. The encoded method signature is dot-based.
359  *
360  * @param parameterTypes the list of parameter type signatures
361  * @param returnType the return type signature
362  * @return the encoded method signature
363  * 
364  * @since 2.0
365  */
366 public static char[] createMethodSignature(char[][] parameterTypes, char[] returnType) {
367         int parameterTypesLength = parameterTypes.length;
368         int parameterLength = 0;
369         for (int i = 0; i < parameterTypesLength; i++) {
370                 parameterLength += parameterTypes[i].length;
371                 
372         }
373         int returnTypeLength = returnType.length;
374         char[] result = new char[1 + parameterLength + 1 + returnTypeLength];
375         result[0] = C_PARAM_START;
376         int index = 1;
377         for (int i = 0; i < parameterTypesLength; i++) {
378                 char[] parameterType = parameterTypes[i];
379                 int length = parameterType.length;
380                 System.arraycopy(parameterType, 0, result, index, length);
381                 index += length;
382         }
383         result[index] = C_PARAM_END;
384         System.arraycopy(returnType, 0, result, index+1, returnTypeLength);
385         return result;
386 }
387 /**
388  * Creates a method signature from the given parameter and return type 
389  * signatures. The encoded method signature is dot-based.
390  *
391  * @param parameterTypes the list of parameter type signatures
392  * @param returnType the return type signature
393  * @return the encoded method signature
394  */
395 public static String createMethodSignature(String[] parameterTypes, String returnType) {
396         int parameterTypesLenth = parameterTypes.length;
397         char[][] parameters = new char[parameterTypesLenth][];
398         for (int i = 0; i < parameterTypesLenth; i++) {
399                 parameters[i] = parameterTypes[i].toCharArray();
400         }
401         return new String(createMethodSignature(parameters, returnType.toCharArray()));
402 }
403 /**
404  * Creates a new type signature from the given type name encoded as a character
405  * array. This method is equivalent to
406  * <code>createTypeSignature(new String(typeName),isResolved)</code>, although
407  * more efficient for callers with character arrays rather than strings. If the 
408  * type name is qualified, then it is expected to be dot-based.
409  *
410  * @param typeName the possibly qualified type name
411  * @param isResolved <code>true</code> if the type name is to be considered
412  *   resolved (for example, a type name from a binary class file), and 
413  *   <code>false</code> if the type name is to be considered unresolved
414  *   (for example, a type name found in source code)
415  * @return the encoded type signature
416  * @see #createTypeSignature(java.lang.String,boolean)
417  */
418 public static String createTypeSignature(char[] typeName, boolean isResolved) {
419         return new String(createCharArrayTypeSignature(typeName, isResolved));
420 }
421 /**
422  * Creates a new type signature from the given type name encoded as a character
423  * array. This method is equivalent to
424  * <code>createTypeSignature(new String(typeName),isResolved).toCharArray()</code>, although
425  * more efficient for callers with character arrays rather than strings. If the 
426  * type name is qualified, then it is expected to be dot-based.
427  *
428  * @param typeName the possibly qualified type name
429  * @param isResolved <code>true</code> if the type name is to be considered
430  *   resolved (for example, a type name from a binary class file), and 
431  *   <code>false</code> if the type name is to be considered unresolved
432  *   (for example, a type name found in source code)
433  * @return the encoded type signature
434  * @see #createTypeSignature(java.lang.String,boolean)
435  * 
436  * @since 2.0
437  */
438 public static char[] createCharArrayTypeSignature(char[] typeName, boolean isResolved) {
439         try {
440                 Scanner scanner = new Scanner();
441                 scanner.setSource(typeName);
442                 int token = scanner.getNextToken();
443                 boolean primitive = true;
444                 char primitiveSig = ' ';
445                 StringBuffer sig = null;
446                 int arrayCount = 0;
447                 switch (token) {
448                         case ITerminalSymbols.TokenNameIdentifier :
449                                 char[] idSource = scanner.getCurrentIdentifierSource();
450                                 sig = new StringBuffer(idSource.length);
451                                 sig.append(idSource);
452                                 primitive = false;
453                                 break;
454 //                      case ITerminalSymbols.TokenNameboolean :
455 //                              primitiveSig = Signature.C_BOOLEAN;
456 //                              break;
457 //                      case ITerminalSymbols.TokenNamebyte :
458 //                              primitiveSig = Signature.C_BYTE;
459 //                              break;
460 //                      case ITerminalSymbols.TokenNamechar :
461 //                              primitiveSig = Signature.C_CHAR;
462 //                              break;
463 //                      case ITerminalSymbols.TokenNamedouble :
464 //                              primitiveSig = Signature.C_DOUBLE;
465 //                              break;
466 //                      case ITerminalSymbols.TokenNamefloat :
467 //                              primitiveSig = Signature.C_FLOAT;
468 //                              break;
469 //                      case ITerminalSymbols.TokenNameint :
470 //                              primitiveSig = Signature.C_INT;
471 //                              break;
472 //                      case ITerminalSymbols.TokenNamelong :
473 //                              primitiveSig = Signature.C_LONG;
474 //                              break;
475 //                      case ITerminalSymbols.TokenNameshort :
476 //                              primitiveSig = Signature.C_SHORT;
477 //                              break;
478 //                      case ITerminalSymbols.TokenNamevoid :
479 //                              primitiveSig = Signature.C_VOID;
480 //                              break;
481                         default :
482                                 throw new IllegalArgumentException();
483                 }
484                 token = scanner.getNextToken();
485                 while (!primitive && token == ITerminalSymbols.TokenNameDOT) {
486                         sig.append(scanner.getCurrentIdentifierSource());
487                         token = scanner.getNextToken();
488                         if (token == ITerminalSymbols.TokenNameIdentifier) {
489                                 sig.append(scanner.getCurrentIdentifierSource());
490                                 token = scanner.getNextToken();
491                         } else {
492                                 throw new IllegalArgumentException();
493                         }
494                 }
495                 while (token == ITerminalSymbols.TokenNameLBRACKET) {
496                         token = scanner.getNextToken();
497                         if (token != ITerminalSymbols.TokenNameRBRACKET)
498                                 throw new IllegalArgumentException();
499                         arrayCount++;
500                         token = scanner.getNextToken();
501                 }
502                 if (token != ITerminalSymbols.TokenNameEOF)
503                         throw new IllegalArgumentException();
504                 char[] result;
505                 if (primitive) {
506                         result = new char[arrayCount+1];
507                         result[arrayCount] = primitiveSig;
508                 } else {
509                         int sigLength = sig.length(); 
510                         int resultLength = arrayCount + 1 + sigLength + 1; // e.g. '[[[Ljava.lang.String;'
511                         result = new char[resultLength];
512                         sig.getChars(0, sigLength, result, arrayCount + 1);
513                         result[arrayCount] = isResolved ? C_RESOLVED : C_UNRESOLVED;
514                         result[resultLength-1] = C_NAME_END;
515                 }
516                 for (int i = 0; i < arrayCount; i++) {
517                         result[i] = C_ARRAY;
518                 }
519                 return result;
520         } catch (InvalidInputException e) {
521                 throw new IllegalArgumentException();
522         }
523 }
524 /**
525  * Creates a new type signature from the given type name. If the type name is qualified,
526  * then it is expected to be dot-based.
527  * <p>
528  * For example:
529  * <pre>
530  * <code>
531  * createTypeSignature("int", hucairz) -> "I"
532  * createTypeSignature("java.lang.String", true) -> "Ljava.lang.String;"
533  * createTypeSignature("String", false) -> "QString;"
534  * createTypeSignature("java.lang.String", false) -> "Qjava.lang.String;"
535  * createTypeSignature("int []", false) -> "[I"
536  * </code>
537  * </pre>
538  * </p>
539  *
540  * @param typeName the possibly qualified type name
541  * @param isResolved <code>true</code> if the type name is to be considered
542  *   resolved (for example, a type name from a binary class file), and 
543  *   <code>false</code> if the type name is to be considered unresolved
544  *   (for example, a type name found in source code)
545  * @return the encoded type signature
546  */
547 public static String createTypeSignature(String typeName, boolean isResolved) {
548         return createTypeSignature(typeName.toCharArray(), isResolved);
549 }
550 /**
551  * Returns the array count (array nesting depth) of the given type signature.
552  *
553  * @param typeSignature the type signature
554  * @return the array nesting depth, or 0 if not an array
555  * @exception IllegalArgumentException if the signature is not syntactically
556  *   correct
557  * 
558  * @since 2.0
559  */
560 public static int getArrayCount(char[] typeSignature) throws IllegalArgumentException { 
561         try {
562                 int count = 0;
563                 while (typeSignature[count] == C_ARRAY) {
564                         ++count;
565                 }
566                 return count;
567         } catch (ArrayIndexOutOfBoundsException e) { // signature is syntactically incorrect if last character is C_ARRAY
568                 throw new IllegalArgumentException();
569         }
570 }
571 /**
572  * Returns the array count (array nesting depth) of the given type signature.
573  *
574  * @param typeSignature the type signature
575  * @return the array nesting depth, or 0 if not an array
576  * @exception IllegalArgumentException if the signature is not syntactically
577  *   correct
578  */
579 public static int getArrayCount(String typeSignature) throws IllegalArgumentException {
580         return getArrayCount(typeSignature.toCharArray());
581 }
582 /**
583  * Returns the type signature without any array nesting.
584  * <p>
585  * For example:
586  * <pre>
587  * <code>
588  * getElementType({'[', '[', 'I'}) --> {'I'}.
589  * </code>
590  * </pre>
591  * </p>
592  * 
593  * @param typeSignature the type signature
594  * @return the type signature without arrays
595  * @exception IllegalArgumentException if the signature is not syntactically
596  *   correct
597  * 
598  * @since 2.0
599  */
600 public static char[] getElementType(char[] typeSignature) throws IllegalArgumentException {
601         int count = getArrayCount(typeSignature);
602         if (count == 0) return typeSignature;
603         int length = typeSignature.length;
604         char[] result = new char[length-count];
605         System.arraycopy(typeSignature, count, result, 0, length-count);
606         return result;
607 }
608 /**
609  * Returns the type signature without any array nesting.
610  * <p>
611  * For example:
612  * <pre>
613  * <code>
614  * getElementType("[[I") --> "I".
615  * </code>
616  * </pre>
617  * </p>
618  * 
619  * @param typeSignature the type signature
620  * @return the type signature without arrays
621  * @exception IllegalArgumentException if the signature is not syntactically
622  *   correct
623  */
624 public static String getElementType(String typeSignature) throws IllegalArgumentException {
625         return new String(getElementType(typeSignature.toCharArray()));
626 }
627 /**
628  * Returns the number of parameter types in the given method signature.
629  *
630  * @param methodSignature the method signature
631  * @return the number of parameters
632  * @exception IllegalArgumentException if the signature is not syntactically
633  *   correct
634  * @since 2.0
635  */
636 public static int getParameterCount(char[] methodSignature) throws IllegalArgumentException {
637         try {
638                 int count = 0;
639                 int i = CharOperation.indexOf(C_PARAM_START, methodSignature) + 1;
640                 if (i == 0)
641                         throw new IllegalArgumentException();
642                 for (;;) {
643                         char c = methodSignature[i++];
644                         switch (c) {
645                                 case C_ARRAY :
646                                         break;
647                                 case C_BOOLEAN :
648                                 case C_BYTE :
649                                 case C_CHAR :
650                                 case C_DOUBLE :
651                                 case C_FLOAT :
652                                 case C_INT :
653                                 case C_LONG :
654                                 case C_SHORT :
655                                 case C_VOID :
656                                         ++count;
657                                         break;
658                                 case C_RESOLVED :
659                                 case C_UNRESOLVED :
660                                         i = CharOperation.indexOf(C_SEMICOLON, methodSignature, i) + 1;
661                                         if (i == 0)
662                                                 throw new IllegalArgumentException();
663                                         ++count;
664                                         break;
665                                 case C_PARAM_END :
666                                         return count;
667                                 default :
668                                         throw new IllegalArgumentException();
669                         }
670                 }
671         } catch (ArrayIndexOutOfBoundsException e) {
672                 throw new IllegalArgumentException();
673         }
674 }
675 /**
676  * Returns the number of parameter types in the given method signature.
677  *
678  * @param methodSignature the method signature
679  * @return the number of parameters
680  * @exception IllegalArgumentException if the signature is not syntactically
681  *   correct
682  */
683 public static int getParameterCount(String methodSignature) throws IllegalArgumentException {
684         return getParameterCount(methodSignature.toCharArray());
685 }
686 /**
687  * Extracts the parameter type signatures from the given method signature. 
688  * The method signature is expected to be dot-based.
689  *
690  * @param methodSignature the method signature
691  * @return the list of parameter type signatures
692  * @exception IllegalArgumentException if the signature is syntactically
693  *   incorrect
694  * 
695  * @since 2.0
696  */
697 public static char[][] getParameterTypes(char[] methodSignature) throws IllegalArgumentException {
698         try {
699                 int count = getParameterCount(methodSignature);
700                 char[][] result = new char[count][];
701                 if (count == 0)
702                         return result;
703                 int i = CharOperation.indexOf(C_PARAM_START, methodSignature) + 1;
704                 count = 0;
705                 int start = i;
706                 for (;;) {
707                         char c = methodSignature[i++];
708                         switch (c) {
709                                 case C_ARRAY :
710                                         // array depth is i - start;
711                                         break;
712                                 case C_BOOLEAN :
713                                 case C_BYTE :
714                                 case C_CHAR :
715                                 case C_DOUBLE :
716                                 case C_FLOAT :
717                                 case C_INT :
718                                 case C_LONG :
719                                 case C_SHORT :
720                                 case C_VOID :
721                                         // common case of base types
722                                         if (i - start == 1) {
723                                                 switch (c) {
724                                                         case C_BOOLEAN :
725                                                                 result[count++] = new char[] {C_BOOLEAN};
726                                                                 break;
727                                                         case C_BYTE :
728                                                                 result[count++] = new char[] {C_BYTE};
729                                                                 break;
730                                                         case C_CHAR :
731                                                                 result[count++] = new char[] {C_CHAR};
732                                                                 break;
733                                                         case C_DOUBLE :
734                                                                 result[count++] = new char[] {C_DOUBLE};
735                                                                 break;
736                                                         case C_FLOAT :
737                                                                 result[count++] = new char[] {C_FLOAT};
738                                                                 break;
739                                                         case C_INT :
740                                                                 result[count++] = new char[] {C_INT};
741                                                                 break;
742                                                         case C_LONG :
743                                                                 result[count++] = new char[] {C_LONG};
744                                                                 break;
745                                                         case C_SHORT :
746                                                                 result[count++] = new char[] {C_SHORT};
747                                                                 break;
748                                                         case C_VOID :
749                                                                 result[count++] = new char[] {C_VOID};
750                                                                 break;
751                                                 }
752                                         } else {
753                                                 result[count++] = CharOperation.subarray(methodSignature, start, i);
754                                         }
755                                         start = i;
756                                         break;
757                                 case C_RESOLVED :
758                                 case C_UNRESOLVED :
759                                         i = CharOperation.indexOf(C_SEMICOLON, methodSignature, i) + 1;
760                                         if (i == 0)
761                                                 throw new IllegalArgumentException();
762                                         result[count++] = CharOperation.subarray(methodSignature, start, i);
763                                         start = i;
764                                         break;
765                                 case C_PARAM_END:
766                                         return result;
767                                 default :
768                                         throw new IllegalArgumentException();
769                         }
770                 }
771         } catch (ArrayIndexOutOfBoundsException e) {
772                 throw new IllegalArgumentException();
773         }
774 }
775 /**
776  * Extracts the parameter type signatures from the given method signature. 
777  * The method signature is expected to be dot-based.
778  *
779  * @param methodSignature the method signature
780  * @return the list of parameter type signatures
781  * @exception IllegalArgumentException if the signature is syntactically
782  *   incorrect
783  */
784 public static String[] getParameterTypes(String methodSignature) throws IllegalArgumentException {
785         char[][] parameterTypes = getParameterTypes(methodSignature.toCharArray());
786         int length = parameterTypes.length;
787         String[] result = new String[length];
788         for (int i = 0; i < length; i++) {
789                 result[i] = new String(parameterTypes[i]);
790         }
791         return result;
792 }
793 /**
794  * Returns a char array containing all but the last segment of the given 
795  * dot-separated qualified name. Returns the empty char array if it is not qualified.
796  * <p>
797  * For example:
798  * <pre>
799  * <code>
800  * getQualifier({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g'}
801  * getQualifier({'O', 'u', 't', 'e', 'r', '.', 'I', 'n', 'n', 'e', 'r'}) -> {'O', 'u', 't', 'e', 'r'}
802  * </code>
803  * </pre>
804  * </p>
805  *
806  * @param name the name
807  * @return the qualifier prefix, or the empty char array if the name contains no
808  *   dots
809  * 
810  * @since 2.0
811  */
812 public static char[] getQualifier(char[] name) {
813         int lastDot = CharOperation.lastIndexOf(C_DOT, name);
814         if (lastDot == -1) {
815                 return NO_CHAR; //$NON-NLS-1$
816         }
817         return CharOperation.subarray(name, 0, lastDot);
818 }
819 /**
820  * Returns a string containing all but the last segment of the given 
821  * dot-separated qualified name. Returns the empty string if it is not qualified.
822  * <p>
823  * For example:
824  * <pre>
825  * <code>
826  * getQualifier("java.lang.Object") -> "java.lang"
827  * getQualifier("Outer.Inner") -> "Outer"
828  * </code>
829  * </pre>
830  * </p>
831  *
832  * @param name the name
833  * @return the qualifier prefix, or the empty string if the name contains no
834  *   dots
835  */
836 public static String getQualifier(String name) {
837         return new String(getQualifier(name.toCharArray()));
838 }
839 /**
840  * Extracts the return type from the given method signature. The method signature is 
841  * expected to be dot-based.
842  *
843  * @param methodSignature the method signature
844  * @return the type signature of the return type
845  * @exception IllegalArgumentException if the signature is syntactically
846  *   incorrect
847  * 
848  * @since 2.0
849  */
850 public static char[] getReturnType(char[] methodSignature) throws IllegalArgumentException {
851         int i = CharOperation.lastIndexOf(C_PARAM_END, methodSignature);
852         if (i == -1) {
853                 throw new IllegalArgumentException();
854         }
855         return CharOperation.subarray(methodSignature, i + 1, methodSignature.length);
856 }
857 /**
858  * Extracts the return type from the given method signature. The method signature is 
859  * expected to be dot-based.
860  *
861  * @param methodSignature the method signature
862  * @return the type signature of the return type
863  * @exception IllegalArgumentException if the signature is syntactically
864  *   incorrect
865  */
866 public static String getReturnType(String methodSignature) throws IllegalArgumentException {
867         return new String(getReturnType(methodSignature.toCharArray()));
868 }
869 /**
870  * Returns the last segment of the given dot-separated qualified name.
871  * Returns the given name if it is not qualified.
872  * <p>
873  * For example:
874  * <pre>
875  * <code>
876  * getSimpleName({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'O', 'b', 'j', 'e', 'c', 't'}
877  * </code>
878  * </pre>
879  * </p>
880  *
881  * @param name the name
882  * @return the last segment of the qualified name
883  * 
884  * @since 2.0
885  */
886 public static char[] getSimpleName(char[] name) {
887         int lastDot = CharOperation.lastIndexOf(C_DOT, name);
888         if (lastDot == -1) {
889                 return name;
890         }
891         return CharOperation.subarray(name, lastDot + 1, name.length);
892 }
893 /**
894  * Returns the last segment of the given dot-separated qualified name.
895  * Returns the given name if it is not qualified.
896  * <p>
897  * For example:
898  * <pre>
899  * <code>
900  * getSimpleName("java.lang.Object") -> "Object"
901  * </code>
902  * </pre>
903  * </p>
904  *
905  * @param name the name
906  * @return the last segment of the qualified name
907  */
908 public static String getSimpleName(String name) {
909         return new String(getSimpleName(name.toCharArray()));
910 }
911 /**
912  * Returns all segments of the given dot-separated qualified name.
913  * Returns an array with only the given name if it is not qualified.
914  * Returns an empty array if the name is empty.
915  * <p>
916  * For example:
917  * <pre>
918  * <code>
919  * 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'}}
920  * getSimpleNames({'O', 'b', 'j', 'e', 'c', 't'}) -> {{'O', 'b', 'j', 'e', 'c', 't'}}
921  * getSimpleNames("") -> {}
922  * </code>
923  * </pre>
924  *
925  * @param name the name
926  * @return the list of simple names, possibly empty
927  * 
928  * @since 2.0
929  */
930 public static char[][] getSimpleNames(char[] name) {
931         if (name.length == 0) {
932                 return NO_CHAR_CHAR;
933         }
934         int dot = CharOperation.indexOf(C_DOT, name);
935         if (dot == -1) {
936                 return new char[][] {name};
937         }
938         int n = 1;
939         while ((dot = CharOperation.indexOf(C_DOT, name, dot + 1)) != -1) {
940                 ++n;
941         }
942         char[][] result = new char[n + 1][];
943         int segStart = 0;
944         for (int i = 0; i < n; ++i) {
945                 dot = CharOperation.indexOf(C_DOT, name, segStart);
946                 result[i] = CharOperation.subarray(name, segStart, dot);
947                 segStart = dot + 1;
948         }
949         result[n] = CharOperation.subarray(name, segStart, name.length);
950         return result;
951 }
952 /**
953  * Returns all segments of the given dot-separated qualified name.
954  * Returns an array with only the given name if it is not qualified.
955  * Returns an empty array if the name is empty.
956  * <p>
957  * For example:
958  * <pre>
959  * <code>
960  * getSimpleNames("java.lang.Object") -> {"java", "lang", "Object"}
961  * getSimpleNames("Object") -> {"Object"}
962  * getSimpleNames("") -> {}
963  * </code>
964  * </pre>
965  *
966  * @param name the name
967  * @return the list of simple names, possibly empty
968  */
969 public static String[] getSimpleNames(String name) {
970         char[][] simpleNames = getSimpleNames(name.toCharArray());
971         int length = simpleNames.length;
972         String[] result = new String[length];
973         for (int i = 0; i < length; i++) {
974                 result[i] = new String(simpleNames[i]);
975         }
976         return result;
977 }
978 /**
979  * Converts the given method signature to a readable form. The method signature is expected to
980  * be dot-based.
981  * <p>
982  * For example:
983  * <pre>
984  * <code>
985  * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
986  * </code>
987  * </pre>
988  * </p>
989  * 
990  * @param methodSignature the method signature to convert
991  * @param methodName the name of the method to insert in the result, or 
992  *   <code>null</code> if no method name is to be included
993  * @param parameterNames the parameter names to insert in the result, or 
994  *   <code>null</code> if no parameter names are to be included; if supplied,
995  *   the number of parameter names must match that of the method signature
996  * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
997  *   qualified, and <code>false</code> to use only simple names
998  * @param includeReturnType <code>true</code> if the return type is to be
999  *   included
1000  * @return the char array representation of the method signature
1001  * 
1002  * @since 2.0
1003  */
1004 public static char[] toCharArray(char[] methodSignature, char[] methodName, char[][] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) {
1005         try {
1006                 int firstParen = CharOperation.indexOf(C_PARAM_START, methodSignature);
1007                 if (firstParen == -1) throw new IllegalArgumentException();
1008                 
1009                 int sigLength = methodSignature.length;
1010                 
1011                 // compute result length
1012                 
1013                 // method signature
1014                 int paramCount = 0;
1015                 int lastParen = -1;
1016                 int resultLength = 0;
1017                 signature: for (int i = firstParen; i < sigLength; i++) {
1018                         switch (methodSignature[i]) {
1019                                 case C_ARRAY :
1020                                         resultLength += 2; // []
1021                                         continue signature;
1022                                 case C_BOOLEAN :
1023                                         resultLength += BOOLEAN.length;
1024                                         break;
1025                                 case C_BYTE :
1026                                         resultLength += BYTE.length;
1027                                         break;
1028                                 case C_CHAR :
1029                                         resultLength += CHAR.length;
1030                                         break;
1031                                 case C_DOUBLE :
1032                                         resultLength += DOUBLE.length;
1033                                         break;
1034                                 case C_FLOAT :
1035                                         resultLength += FLOAT.length;
1036                                         break;
1037                                 case C_INT :
1038                                         resultLength += INT.length;
1039                                         break;
1040                                 case C_LONG :
1041                                         resultLength += LONG.length;
1042                                         break;
1043                                 case C_SHORT :
1044                                         resultLength += SHORT.length;
1045                                         break;
1046                                 case C_VOID :
1047                                         resultLength += VOID.length;
1048                                         break;
1049                                 case C_RESOLVED :
1050                                 case C_UNRESOLVED :
1051                                         int end = CharOperation.indexOf(C_SEMICOLON, methodSignature, i);
1052                                         if (end == -1) throw new IllegalArgumentException();
1053                                         int start;
1054                                         if (fullyQualifyTypeNames) {
1055                                                 start = i+1;
1056                                         } else {
1057                                                 start = CharOperation.lastIndexOf(C_DOT, methodSignature, i, end) + 1;
1058                                                 if (start == 0) start = i+1;
1059                                         } 
1060                                         resultLength += end-start;
1061                                         i = end;
1062                                         break;
1063                                 case C_PARAM_START :
1064                                         // add space for "("
1065                                         resultLength++;
1066                                         continue signature;
1067                                 case C_PARAM_END :
1068                                         lastParen = i;
1069                                         if (includeReturnType) {
1070                                                 if (paramCount > 0) {
1071                                                         // remove space for ", " that was added with last parameter and remove space that is going to be added for ", " after return type 
1072                                                         // and add space for ") "
1073                                                         resultLength -= 2;
1074                                                 } //else
1075                                                         // remove space that is going to be added for ", " after return type 
1076                                                         // and add space for ") "
1077                                                         // -> noop
1078                                                 
1079                                                 // decrement param count because it is going to be added for return type
1080                                                 paramCount--;
1081                                                 continue signature;
1082                                         } else {
1083                                                 if (paramCount > 0) {
1084                                                         // remove space for ", " that was added with last parameter and add space for ")"
1085                                                         resultLength--;
1086                                                 } else {
1087                                                         // add space for ")"
1088                                                         resultLength++;
1089                                                 }
1090                                                 break signature;
1091                                         }
1092                                 default :
1093                                         throw new IllegalArgumentException();
1094                         }
1095                         resultLength += 2; // add space for ", "
1096                         paramCount++;
1097                 }
1098                 
1099                 // parameter names
1100                 int parameterNamesLength = parameterNames == null ? 0 : parameterNames.length;
1101                 for (int i = 0; i <parameterNamesLength; i++) {
1102                         resultLength += parameterNames[i].length + 1; // parameter name + space
1103                 }
1104                 
1105                 // selector
1106                 int selectorLength = methodName == null ? 0 : methodName.length;
1107                 resultLength += selectorLength;
1108                 
1109                 // create resulting char array
1110                 char[] result = new char[resultLength];
1111                 
1112                 // returned type
1113                 int index = 0;
1114                 if (includeReturnType) {
1115                         long pos = copyType(methodSignature, lastParen+1, result, index, fullyQualifyTypeNames);
1116                         index = (int) (pos >>> 32);
1117                         result[index++] = ' ';
1118                 }
1119                 
1120                 // selector
1121                 if (methodName != null) {
1122                         System.arraycopy(methodName, 0, result, index, selectorLength);
1123                         index += selectorLength;
1124                 }
1125                 
1126                 // parameters
1127                 result[index++] = C_PARAM_START;
1128                 int sigPos = firstParen+1;
1129                 for (int i = 0; i < paramCount; i++) {
1130                         long pos = copyType(methodSignature, sigPos, result, index, fullyQualifyTypeNames);
1131                         index = (int) (pos >>> 32);
1132                         sigPos = (int)pos;
1133                         if (parameterNames != null) {
1134                                 result[index++] = ' ';
1135                                 char[] parameterName = parameterNames[i];
1136                                 int paramLength = parameterName.length;
1137                                 System.arraycopy(parameterName, 0, result, index, paramLength);
1138                                 index += paramLength;
1139                         }
1140                         if (i != paramCount-1) {
1141                                 result[index++] = ',';
1142                                 result[index++] = ' ';
1143                         }
1144                 }
1145                 if (sigPos >= sigLength) {
1146                         throw new IllegalArgumentException(); // should be on last paren
1147                 }
1148                 result[index++] = C_PARAM_END;
1149                 
1150                 return result;
1151         } catch (ArrayIndexOutOfBoundsException e) {
1152                 throw new IllegalArgumentException();
1153         }               
1154 }
1155 /**
1156  * Converts the given type signature to a readable string. The signature is expected to
1157  * be dot-based.
1158  * 
1159  * <p>
1160  * For example:
1161  * <pre>
1162  * <code>
1163  * 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', '[', ']'}
1164  * toString({'I'}) -> {'i', 'n', 't'}
1165  * </code>
1166  * </pre>
1167  * </p>
1168  * <p>
1169  * Note: This method assumes that a type signature containing a <code>'$'</code>
1170  * is an inner type signature. While this is correct in most cases, someone could 
1171  * define a non-inner type name containing a <code>'$'</code>. Handling this 
1172  * correctly in all cases would have required resolving the signature, which 
1173  * generally not feasible.
1174  * </p>
1175  *
1176  * @param signature the type signature
1177  * @return the string representation of the type
1178  * @exception IllegalArgumentException if the signature is not syntactically
1179  *   correct
1180  * 
1181  * @since 2.0
1182  */
1183 public static char[] toCharArray(char[] signature) throws IllegalArgumentException {
1184         try {
1185                 int sigLength = signature.length;
1186
1187                 if (sigLength == 0 || signature[0] == C_PARAM_START) {
1188                         return toCharArray(signature, NO_CHAR, null, true, true);
1189                 }
1190                 
1191                 // compute result length
1192                 int resultLength = 0;
1193                 int index = -1;
1194                 while (signature[++index] == C_ARRAY) {
1195                         resultLength += 2; // []
1196                 }
1197                 switch (signature[index]) {
1198                         case C_BOOLEAN :
1199                                 resultLength += BOOLEAN.length;
1200                                 break;
1201                         case C_BYTE :
1202                                 resultLength += BYTE.length;
1203                                 break;
1204                         case C_CHAR :
1205                                 resultLength += CHAR.length;
1206                                 break;
1207                         case C_DOUBLE :
1208                                 resultLength += DOUBLE.length;
1209                                 break;
1210                         case C_FLOAT :
1211                                 resultLength += FLOAT.length;
1212                                 break;
1213                         case C_INT :
1214                                 resultLength += INT.length;
1215                                 break;
1216                         case C_LONG :
1217                                 resultLength += LONG.length;
1218                                 break;
1219                         case C_SHORT :
1220                                 resultLength += SHORT.length;
1221                                 break;
1222                         case C_VOID :
1223                                 resultLength += VOID.length;
1224                                 break;
1225                         case C_RESOLVED :
1226                         case C_UNRESOLVED :
1227                                 int end = CharOperation.indexOf(C_SEMICOLON, signature, index);
1228                                 if (end == -1) throw new IllegalArgumentException();
1229                                 int start = index + 1;
1230                                 resultLength += end-start;
1231                                 break;
1232                         default :
1233                                 throw new IllegalArgumentException();
1234                 }
1235                 
1236                 char[] result = new char[resultLength];
1237                 copyType(signature, 0, result, 0, true);
1238
1239                 /**
1240                  * Converts '$' separated type signatures into '.' separated type signature.
1241                  * NOTE: This assumes that the type signature is an inner type signature.
1242                  *       This is true in most cases, but someone can define a non-inner type 
1243                  *       name containing a '$'. However to tell the difference, we would have
1244                  *       to resolve the signature, which cannot be done at this point.
1245                  */
1246                 CharOperation.replace(result, C_DOLLAR, C_DOT);
1247
1248                 return result;
1249         } catch (ArrayIndexOutOfBoundsException e) {
1250                 throw new IllegalArgumentException();
1251         }       
1252 }
1253 /**
1254  * Converts the given array of qualified name segments to a qualified name.
1255  * <p>
1256  * For example:
1257  * <pre>
1258  * <code>
1259  * 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'}
1260  * toQualifiedName({{'O', 'b', 'j', 'e', 'c', 't'}}) -> {'O', 'b', 'j', 'e', 'c', 't'}
1261  * toQualifiedName({{}}) -> {}
1262  * </code>
1263  * </pre>
1264  * </p>
1265  *
1266  * @param segments the list of name segments, possibly empty
1267  * @return the dot-separated qualified name, or the empty string
1268  * 
1269  * @since 2.0
1270  */
1271 public static char[] toQualifiedName(char[][] segments) {
1272         int length = segments.length;
1273         if (length == 0) return NO_CHAR;
1274         if (length == 1) return segments[0];
1275         
1276         int resultLength = 0;
1277         for (int i = 0; i < length; i++) {
1278                 resultLength += segments[i].length+1;
1279         }
1280         resultLength--;
1281         char[] result = new char[resultLength];
1282         int index = 0;
1283         for (int i = 0; i < length; i++) {
1284                 char[] segment = segments[i];
1285                 int segmentLength = segment.length;
1286                 System.arraycopy(segment, 0, result, index, segmentLength);
1287                 index += segmentLength;
1288                 if (i != length-1) {
1289                         result[index++] = C_DOT;
1290                 }
1291         }
1292         return result;
1293 }
1294 /**
1295  * Converts the given array of qualified name segments to a qualified name.
1296  * <p>
1297  * For example:
1298  * <pre>
1299  * <code>
1300  * toQualifiedName(new String[] {"java", "lang", "Object"}) -> "java.lang.Object"
1301  * toQualifiedName(new String[] {"Object"}) -> "Object"
1302  * toQualifiedName(new String[0]) -> ""
1303  * </code>
1304  * </pre>
1305  * </p>
1306  *
1307  * @param segments the list of name segments, possibly empty
1308  * @return the dot-separated qualified name, or the empty string
1309  */
1310 public static String toQualifiedName(String[] segments) {
1311         int length = segments.length;
1312         char[][] charArrays = new char[length][];
1313         for (int i = 0; i < length; i++) {
1314                 charArrays[i] = segments[i].toCharArray();
1315         }
1316         return new String(toQualifiedName(charArrays));
1317 }
1318 /**
1319  * Converts the given type signature to a readable string. The signature is expected to
1320  * be dot-based.
1321  * 
1322  * <p>
1323  * For example:
1324  * <pre>
1325  * <code>
1326  * toString("[Ljava.lang.String;") -> "java.lang.String[]"
1327  * toString("I") -> "int"
1328  * </code>
1329  * </pre>
1330  * </p>
1331  * <p>
1332  * Note: This method assumes that a type signature containing a <code>'$'</code>
1333  * is an inner type signature. While this is correct in most cases, someone could 
1334  * define a non-inner type name containing a <code>'$'</code>. Handling this 
1335  * correctly in all cases would have required resolving the signature, which 
1336  * generally not feasible.
1337  * </p>
1338  *
1339  * @param signature the type signature
1340  * @return the string representation of the type
1341  * @exception IllegalArgumentException if the signature is not syntactically
1342  *   correct
1343  */
1344 public static String toString(String signature) throws IllegalArgumentException {
1345         return new String(toCharArray(signature.toCharArray()));
1346 }
1347 /**
1348  * Converts the given method signature to a readable string. The method signature is expected to
1349  * be dot-based.
1350  * <p>
1351  * For example:
1352  * <pre>
1353  * <code>
1354  * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
1355  * </code>
1356  * </pre>
1357  * </p>
1358  * 
1359  * @param methodSignature the method signature to convert
1360  * @param methodName the name of the method to insert in the result, or 
1361  *   <code>null</code> if no method name is to be included
1362  * @param parameterNames the parameter names to insert in the result, or 
1363  *   <code>null</code> if no parameter names are to be included; if supplied,
1364  *   the number of parameter names must match that of the method signature
1365  * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
1366  *   qualified, and <code>false</code> to use only simple names
1367  * @param includeReturnType <code>true</code> if the return type is to be
1368  *   included
1369  * @return the string representation of the method signature
1370  */
1371 public static String toString(String methodSignature, String methodName, String[] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) {
1372         char[][] params;
1373         if (parameterNames == null) {
1374                 params = null;
1375         } else {
1376                 int paramLength = parameterNames.length;
1377                 params = new char[paramLength][];
1378                 for (int i = 0; i < paramLength; i++) {
1379                         params[i] = parameterNames[i].toCharArray();
1380                 }
1381         }
1382         return new String(toCharArray(methodSignature.toCharArray(), methodName == null ? null : methodName.toCharArray(), params, fullyQualifyTypeNames, includeReturnType));
1383 }
1384 }