KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > core > Signature


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  * IBM Corporation - added J2SE 1.5 support
11  *******************************************************************************/

12 package org.eclipse.jdt.core;
13
14 import java.util.ArrayList JavaDoc;
15
16 import org.eclipse.jdt.core.compiler.CharOperation;
17 import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
18 import org.eclipse.jdt.internal.core.util.Util;
19
20
21 /**
22  * Provides methods for encoding and decoding type and method signature strings.
23  * <p>
24  * Signatures obtained from parsing source files (i.e. files with one of the
25  * {@link JavaCore#getJavaLikeExtensions() Java-like extensions}) differ subtly
26  * from ones obtained from pre-compiled binary (".class") files in class names are
27  * usually left unresolved in the former. For example, the normal resolved form
28  * of the type "String" embeds the class's package name ("Ljava.lang.String;"
29  * or "Ljava/lang/String;"), whereas the unresolved form contains only what is
30  * written "QString;".
31  * </p>
32  * <p>
33  * Generic types introduce to the Java language in J2SE 1.5 add three new
34  * facets to signatures: type variables, parameterized types with type arguments,
35  * and formal type parameters. <i>Rich</i> signatures containing these facets
36  * only occur when dealing with code that makes overt use of the new language
37  * features. All other code, and certainly all Java code written or compiled
38  * with J2SE 1.4 or earlier, involved only <i>simple</i> signatures.
39  * </p>
40  * <p>
41  * Note that the "Q" and "!" formats are specific to Eclipse; the remainder
42  * are specified in the JVM spec.
43  * </p>
44  * <p>
45  * The syntax for a type signature is:
46  * <pre>
47  * TypeSignature ::=
48  * "B" // byte
49  * | "C" // char
50  * | "D" // double
51  * | "F" // float
52  * | "I" // int
53  * | "J" // long
54  * | "S" // short
55  * | "V" // void
56  * | "Z" // boolean
57  * | "T" + Identifier + ";" // type variable
58  * | "[" + TypeSignature // array X[]
59  * | "!" + TypeSignature // capture-of ?
60  * | ResolvedClassTypeSignature
61  * | UnresolvedClassTypeSignature
62  *
63  * ResolvedClassTypeSignature ::= // resolved named type (in compiled code)
64  * "L" + Identifier + OptionalTypeArguments
65  * ( ( "." | "/" ) + Identifier + OptionalTypeArguments )* + ";"
66  * | OptionalTypeParameters + "L" + Identifier +
67  * ( ( "." | "/" ) + Identifier )* + ";"
68  *
69  * UnresolvedClassTypeSignature ::= // unresolved named type (in source code)
70  * "Q" + Identifier + OptionalTypeArguments
71  * ( ( "." | "/" ) + Identifier + OptionalTypeArguments )* + ";"
72  * | OptionalTypeParameters "Q" + Identifier +
73  * ( ( "." | "/" ) + Identifier )* + ";"
74  *
75  * OptionalTypeArguments ::=
76  * "&lt;" + TypeArgument+ + "&gt;"
77  * |
78  *
79  * TypeArgument ::=
80  * | TypeSignature
81  * | "*" // wildcard ?
82  * | "+" TypeSignature // wildcard ? extends X
83  * | "-" TypeSignature // wildcard ? super X
84  *
85  * OptionalTypeParameters ::=
86  * "&lt;" + FormalTypeParameterSignature+ + "&gt;"
87  * |
88  * </pre>
89  * </p>
90  * <p>
91  * Examples:
92  * <ul>
93  * <li><code>"[[I"</code> denotes <code>int[][]</code></li>
94  * <li><code>"Ljava.lang.String;"</code> denotes <code>java.lang.String</code> in compiled code</li>
95  * <li><code>"QString;"</code> denotes <code>String</code> in source code</li>
96  * <li><code>"Qjava.lang.String;"</code> denotes <code>java.lang.String</code> in source code</li>
97  * <li><code>"[QString;"</code> denotes <code>String[]</code> in source code</li>
98  * <li><code>"QMap&lt;QString;*&gt;;"</code> denotes <code>Map&lt;String,?&gt;</code> in source code</li>
99  * <li><code>"Qjava.util.List&ltTV;&gt;;"</code> denotes <code>java.util.List&lt;V&gt;</code> in source code</li>
100  * <li><code>"&ltE;&gt;Ljava.util.List;"</code> denotes <code>&lt;E&gt;java.util.List</code> in source code</li>
101  * </ul>
102  * </p>
103  * <p>
104  * The syntax for a method signature is:
105  * <pre>
106  * MethodSignature ::= OptionalTypeParameters + "(" + ParamTypeSignature* + ")" + ReturnTypeSignature
107  * ParamTypeSignature ::= TypeSignature
108  * ReturnTypeSignature ::= TypeSignature
109  * </pre>
110  * <p>
111  * Examples:
112  * <ul>
113  * <li><code>"()I"</code> denotes <code>int foo()</code></li>
114  * <li><code>"([Ljava.lang.String;)V"</code> denotes <code>void foo(java.lang.String[])</code> in compiled code</li>
115  * <li><code>"(QString;)QObject;"</code> denotes <code>Object foo(String)</code> in source code</li>
116  * </ul>
117  * </p>
118  * <p>
119  * The syntax for a formal type parameter signature is:
120  * <pre>
121  * FormalTypeParameterSignature ::=
122  * TypeVariableName + OptionalClassBound + InterfaceBound*
123  * TypeVariableName ::= Identifier
124  * OptionalClassBound ::=
125  * ":"
126  * | ":" + TypeSignature
127  * InterfaceBound ::=
128  * ":" + TypeSignature
129  * </pre>
130  * <p>
131  * Examples:
132  * <ul>
133  * <li><code>"X:"</code> denotes <code>X</code></li>
134  * <li><code>"X:QReader;"</code> denotes <code>X extends Reader</code> in source code</li>
135  * <li><code>"X:QReader;:QSerializable;"</code> denotes <code>X extends Reader & Serializable</code> in source code</li>
136  * </ul>
137  * </p>
138  * <p>
139  * This class provides static methods and constants only; it is not intended to be
140  * instantiated or subclassed by clients.
141  * </p>
142  */

143 public final class Signature {
144
145     /**
146      * Character constant indicating the primitive type boolean in a signature.
147      * Value is <code>'Z'</code>.
148      */

149     public static final char C_BOOLEAN = 'Z';
150
151     /**
152      * Character constant indicating the primitive type byte in a signature.
153      * Value is <code>'B'</code>.
154      */

155     public static final char C_BYTE = 'B';
156
157     /**
158      * Character constant indicating the primitive type char in a signature.
159      * Value is <code>'C'</code>.
160      */

161     public static final char C_CHAR = 'C';
162
163     /**
164      * Character constant indicating the primitive type double in a signature.
165      * Value is <code>'D'</code>.
166      */

167     public static final char C_DOUBLE = 'D';
168
169     /**
170      * Character constant indicating the primitive type float in a signature.
171      * Value is <code>'F'</code>.
172      */

173     public static final char C_FLOAT = 'F';
174
175     /**
176      * Character constant indicating the primitive type int in a signature.
177      * Value is <code>'I'</code>.
178      */

179     public static final char C_INT = 'I';
180     
181     /**
182      * Character constant indicating the semicolon in a signature.
183      * Value is <code>';'</code>.
184      */

185     public static final char C_SEMICOLON = ';';
186
187     /**
188      * Character constant indicating the colon in a signature.
189      * Value is <code>':'</code>.
190      * @since 3.0
191      */

192     public static final char C_COLON = ':';
193
194     /**
195      * Character constant indicating the primitive type long in a signature.
196      * Value is <code>'J'</code>.
197      */

198     public static final char C_LONG = 'J';
199     
200     /**
201      * Character constant indicating the primitive type short in a signature.
202      * Value is <code>'S'</code>.
203      */

204     public static final char C_SHORT = 'S';
205     
206     /**
207      * Character constant indicating result type void in a signature.
208      * Value is <code>'V'</code>.
209      */

210     public static final char C_VOID = 'V';
211     
212     /**
213      * Character constant indicating the start of a resolved type variable in a
214      * signature. Value is <code>'T'</code>.
215      * @since 3.0
216      */

217     public static final char C_TYPE_VARIABLE = 'T';
218     
219     /**
220      * Character constant indicating an unbound wildcard type argument
221      * in a signature.
222      * Value is <code>'*'</code>.
223      * @since 3.0
224      */

225     public static final char C_STAR = '*';
226     
227     /**
228      * Character constant indicating an exception in a signature.
229      * Value is <code>'^'</code>.
230      * @since 3.1
231      */

232     public static final char C_EXCEPTION_START = '^';
233     
234     /**
235      * Character constant indicating a bound wildcard type argument
236      * in a signature with extends clause.
237      * Value is <code>'+'</code>.
238      * @since 3.1
239      */

240     public static final char C_EXTENDS = '+';
241
242     /**
243      * Character constant indicating a bound wildcard type argument
244      * in a signature with super clause.
245      * Value is <code>'-'</code>.
246      * @since 3.1
247      */

248     public static final char C_SUPER = '-';
249     
250     /**
251      * Character constant indicating the dot in a signature.
252      * Value is <code>'.'</code>.
253      */

254     public static final char C_DOT = '.';
255     
256     /**
257      * Character constant indicating the dollar in a signature.
258      * Value is <code>'$'</code>.
259      */

260     public static final char C_DOLLAR = '$';
261
262     /**
263      * Character constant indicating an array type in a signature.
264      * Value is <code>'['</code>.
265      */

266     public static final char C_ARRAY = '[';
267
268     /**
269      * Character constant indicating the start of a resolved, named type in a
270      * signature. Value is <code>'L'</code>.
271      */

272     public static final char C_RESOLVED = 'L';
273
274     /**
275      * Character constant indicating the start of an unresolved, named type in a
276      * signature. Value is <code>'Q'</code>.
277      */

278     public static final char C_UNRESOLVED = 'Q';
279
280     /**
281      * Character constant indicating the end of a named type in a signature.
282      * Value is <code>';'</code>.
283      */

284     public static final char C_NAME_END = ';';
285
286     /**
287      * Character constant indicating the start of a parameter type list in a
288      * signature. Value is <code>'('</code>.
289      */

290     public static final char C_PARAM_START = '(';
291
292     /**
293      * Character constant indicating the end of a parameter type list in a
294      * signature. Value is <code>')'</code>.
295      */

296     public static final char C_PARAM_END = ')';
297
298     /**
299      * Character constant indicating the start of a formal type parameter
300      * (or type argument) list in a signature. Value is <code>'&lt;'</code>.
301      * @since 3.0
302      */

303     public static final char C_GENERIC_START = '<';
304
305     /**
306      * Character constant indicating the end of a generic type list in a
307      * signature. Value is <code>'&gt;'</code>.
308      * @since 3.0
309      */

310     public static final char C_GENERIC_END = '>';
311
312     /**
313      * Character constant indicating a capture of a wildcard type in a
314      * signature. Value is <code>'!'</code>.
315      * @since 3.1
316      */

317     public static final char C_CAPTURE = '!';
318     
319     /**
320      * String constant for the signature of the primitive type boolean.
321      * Value is <code>"Z"</code>.
322      */

323     public static final String JavaDoc SIG_BOOLEAN = "Z"; //$NON-NLS-1$
324

325     /**
326      * String constant for the signature of the primitive type byte.
327      * Value is <code>"B"</code>.
328      */

329     public static final String JavaDoc SIG_BYTE = "B"; //$NON-NLS-1$
330

331     /**
332      * String constant for the signature of the primitive type char.
333      * Value is <code>"C"</code>.
334      */

335     public static final String JavaDoc SIG_CHAR = "C"; //$NON-NLS-1$
336

337     /**
338      * String constant for the signature of the primitive type double.
339      * Value is <code>"D"</code>.
340      */

341     public static final String JavaDoc SIG_DOUBLE = "D"; //$NON-NLS-1$
342

343     /**
344      * String constant for the signature of the primitive type float.
345      * Value is <code>"F"</code>.
346      */

347     public static final String JavaDoc SIG_FLOAT = "F"; //$NON-NLS-1$
348

349     /**
350      * String constant for the signature of the primitive type int.
351      * Value is <code>"I"</code>.
352      */

353     public static final String JavaDoc SIG_INT = "I"; //$NON-NLS-1$
354

355     /**
356      * String constant for the signature of the primitive type long.
357      * Value is <code>"J"</code>.
358      */

359     public static final String JavaDoc SIG_LONG = "J"; //$NON-NLS-1$
360

361     /**
362      * String constant for the signature of the primitive type short.
363      * Value is <code>"S"</code>.
364      */

365     public static final String JavaDoc SIG_SHORT = "S"; //$NON-NLS-1$
366

367     /** String constant for the signature of result type void.
368      * Value is <code>"V"</code>.
369      */

370     public static final String JavaDoc SIG_VOID = "V"; //$NON-NLS-1$
371

372
373     /**
374      * Kind constant for a class type signature.
375      * @see #getTypeSignatureKind(String)
376      * @since 3.0
377      */

378     public static final int CLASS_TYPE_SIGNATURE = 1;
379
380     /**
381      * Kind constant for a base (primitive or void) type signature.
382      * @see #getTypeSignatureKind(String)
383      * @since 3.0
384      */

385     public static final int BASE_TYPE_SIGNATURE = 2;
386
387     /**
388      * Kind constant for a type variable signature.
389      * @see #getTypeSignatureKind(String)
390      * @since 3.0
391      */

392     public static final int TYPE_VARIABLE_SIGNATURE = 3;
393
394     /**
395      * Kind constant for an array type signature.
396      * @see #getTypeSignatureKind(String)
397      * @since 3.0
398      */

399     public static final int ARRAY_TYPE_SIGNATURE = 4;
400     
401     /**
402      * Kind constant for a wildcard type signature.
403      * @see #getTypeSignatureKind(String)
404      * @since 3.1
405      */

406     public static final int WILDCARD_TYPE_SIGNATURE = 5;
407
408     /**
409      * Kind constant for the capture of a wildcard type signature.
410      * @see #getTypeSignatureKind(String)
411      * @since 3.1
412      */

413     public static final int CAPTURE_TYPE_SIGNATURE = 6;
414
415     private static final char[] BOOLEAN = "boolean".toCharArray(); //$NON-NLS-1$
416
private static final char[] BYTE = "byte".toCharArray(); //$NON-NLS-1$
417
private static final char[] CHAR = "char".toCharArray(); //$NON-NLS-1$
418
private static final char[] DOUBLE = "double".toCharArray(); //$NON-NLS-1$
419
private static final char[] FLOAT = "float".toCharArray(); //$NON-NLS-1$
420
private static final char[] INT = "int".toCharArray(); //$NON-NLS-1$
421
private static final char[] LONG = "long".toCharArray(); //$NON-NLS-1$
422
private static final char[] SHORT = "short".toCharArray(); //$NON-NLS-1$
423
private static final char[] VOID = "void".toCharArray(); //$NON-NLS-1$
424
private static final char[] EXTENDS = "extends".toCharArray(); //$NON-NLS-1$
425
private static final char[] SUPER = "super".toCharArray(); //$NON-NLS-1$
426
private static final char[] CAPTURE = "capture-of".toCharArray(); //$NON-NLS-1$
427

428 private Signature() {
429     // Not instantiable
430
}
431
432 private static int checkName(char[] name, char[] typeName, int pos, int length) {
433     if (CharOperation.fragmentEquals(name, typeName, pos, true)) {
434         pos += name.length;
435         if (pos == length) return pos;
436         char currentChar = typeName[pos];
437         switch (currentChar) {
438             case ' ' :
439             case '.' :
440             case '<' :
441             case '>' :
442             case '[' :
443             case ',' :
444                 return pos;
445             default:
446                 if (ScannerHelper.isWhitespace(currentChar))
447                     return pos;
448                 
449         }
450     }
451     return -1;
452 }
453
454 /**
455  * Creates a new type signature with the given amount of array nesting added
456  * to the given type signature.
457  *
458  * @param typeSignature the type signature
459  * @param arrayCount the desired number of levels of array nesting
460  * @return the encoded array type signature
461  *
462  * @since 2.0
463  */

464 public static char[] createArraySignature(char[] typeSignature, int arrayCount) {
465     if (arrayCount == 0) return typeSignature;
466     int sigLength = typeSignature.length;
467     char[] result = new char[arrayCount + sigLength];
468     for (int i = 0; i < arrayCount; i++) {
469         result[i] = C_ARRAY;
470     }
471     System.arraycopy(typeSignature, 0, result, arrayCount, sigLength);
472     return result;
473 }
474 /**
475  * Creates a new type signature with the given amount of array nesting added
476  * to the given type signature.
477  *
478  * @param typeSignature the type signature
479  * @param arrayCount the desired number of levels of array nesting
480  * @return the encoded array type signature
481  */

482 public static String JavaDoc createArraySignature(String JavaDoc typeSignature, int arrayCount) {
483     return new String JavaDoc(createArraySignature(typeSignature.toCharArray(), arrayCount));
484 }
485
486 /**
487  * Creates a method signature from the given parameter and return type
488  * signatures. The encoded method signature is dot-based.
489  *
490  * @param parameterTypes the list of parameter type signatures
491  * @param returnType the return type signature
492  * @return the encoded method signature
493  *
494  * @since 2.0
495  */

496 public static char[] createMethodSignature(char[][] parameterTypes, char[] returnType) {
497     int parameterTypesLength = parameterTypes.length;
498     int parameterLength = 0;
499     for (int i = 0; i < parameterTypesLength; i++) {
500         parameterLength += parameterTypes[i].length;
501         
502     }
503     int returnTypeLength = returnType.length;
504     char[] result = new char[1 + parameterLength + 1 + returnTypeLength];
505     result[0] = C_PARAM_START;
506     int index = 1;
507     for (int i = 0; i < parameterTypesLength; i++) {
508         char[] parameterType = parameterTypes[i];
509         int length = parameterType.length;
510         System.arraycopy(parameterType, 0, result, index, length);
511         index += length;
512     }
513     result[index] = C_PARAM_END;
514     System.arraycopy(returnType, 0, result, index+1, returnTypeLength);
515     return result;
516 }
517
518 /**
519  * Creates a method signature from the given parameter and return type
520  * signatures. The encoded method signature is dot-based. This method
521  * is equivalent to
522  * <code>createMethodSignature(parameterTypes, returnType)</code>.
523  *
524  * @param parameterTypes the list of parameter type signatures
525  * @param returnType the return type signature
526  * @return the encoded method signature
527  * @see Signature#createMethodSignature(char[][], char[])
528  */

529 public static String JavaDoc createMethodSignature(String JavaDoc[] parameterTypes, String JavaDoc returnType) {
530     int parameterTypesLenth = parameterTypes.length;
531     char[][] parameters = new char[parameterTypesLenth][];
532     for (int i = 0; i < parameterTypesLenth; i++) {
533         parameters[i] = parameterTypes[i].toCharArray();
534     }
535     return new String JavaDoc(createMethodSignature(parameters, returnType.toCharArray()));
536 }
537
538 /**
539  * Creates a new type parameter signature with the given name and bounds.
540  *
541  * @param typeParameterName the type parameter name
542  * @param boundSignatures the signatures of associated bounds or empty array if none
543  * @return the encoded type parameter signature
544  *
545  * @since 3.1
546  */

547 public static char[] createTypeParameterSignature(char[] typeParameterName, char[][] boundSignatures) {
548     int length = boundSignatures.length;
549     if (length == 0) {
550         return CharOperation.append(typeParameterName, C_COLON); // param signature with no bounds still gets trailing colon
551
}
552     int boundsSize = 0;
553     for (int i = 0; i < length; i++) {
554         boundsSize += boundSignatures[i].length + 1;
555     }
556     int nameLength = typeParameterName.length;
557     char[] result = new char[nameLength + boundsSize];
558     System.arraycopy(typeParameterName, 0, result, 0, nameLength);
559     int index = nameLength;
560     for (int i = 0; i < length; i++) {
561         result[index++] = C_COLON;
562         int boundLength = boundSignatures[i].length;
563         System.arraycopy(boundSignatures[i], 0, result, index, boundLength);
564         index += boundLength;
565     }
566     return result;
567 }
568
569 /**
570  * Creates a new type parameter signature with the given name and bounds.
571  *
572  * @param typeParameterName the type parameter name
573  * @param boundSignatures the signatures of associated bounds or empty array if none
574  * @return the encoded type parameter signature
575  *
576  * @since 3.1
577  */

578 public static String JavaDoc createTypeParameterSignature(String JavaDoc typeParameterName, String JavaDoc[] boundSignatures) {
579     int length = boundSignatures.length;
580     char[][] boundSignatureChars = new char[length][];
581     for (int i = 0; i < length; i++) {
582         boundSignatureChars[i] = boundSignatures[i].toCharArray();
583     }
584     return new String JavaDoc(createTypeParameterSignature(typeParameterName.toCharArray(), boundSignatureChars));
585 }
586
587 /**
588  * Creates a new type signature from the given type name encoded as a character
589  * array. The type name may contain primitive types, array types or parameterized types.
590  * This method is equivalent to
591  * <code>createTypeSignature(new String(typeName),isResolved)</code>, although
592  * more efficient for callers with character arrays rather than strings. If the
593  * type name is qualified, then it is expected to be dot-based.
594  *
595  * @param typeName the possibly qualified type name
596  * @param isResolved <code>true</code> if the type name is to be considered
597  * resolved (for example, a type name from a binary class file), and
598  * <code>false</code> if the type name is to be considered unresolved
599  * (for example, a type name found in source code)
600  * @return the encoded type signature
601  * @see #createTypeSignature(java.lang.String,boolean)
602  */

603 public static String JavaDoc createTypeSignature(char[] typeName, boolean isResolved) {
604     return new String JavaDoc(createCharArrayTypeSignature(typeName, isResolved));
605 }
606
607 /**
608  * Creates a new type signature from the given type name encoded as a character
609  * array. The type name may contain primitive types or array types or parameterized types.
610  * This method is equivalent to
611  * <code>createTypeSignature(new String(typeName),isResolved).toCharArray()</code>,
612  * although more efficient for callers with character arrays rather than strings.
613  * If the type name is qualified, then it is expected to be dot-based.
614  *
615  * @param typeName the possibly qualified type name
616  * @param isResolved <code>true</code> if the type name is to be considered
617  * resolved (for example, a type name from a binary class file), and
618  * <code>false</code> if the type name is to be considered unresolved
619  * (for example, a type name found in source code)
620  * @return the encoded type signature
621  * @see #createTypeSignature(java.lang.String,boolean)
622  *
623  * @since 2.0
624  */

625 public static char[] createCharArrayTypeSignature(char[] typeName, boolean isResolved) {
626     if (typeName == null) throw new IllegalArgumentException JavaDoc("null"); //$NON-NLS-1$
627
int length = typeName.length;
628     if (length == 0) throw new IllegalArgumentException JavaDoc(new String JavaDoc(typeName));
629     StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(5);
630     int pos = encodeTypeSignature(typeName, 0, isResolved, length, buffer);
631     pos = consumeWhitespace(typeName, pos, length);
632     if (pos < length) throw new IllegalArgumentException JavaDoc(new String JavaDoc(typeName));
633     char[] result = new char[length = buffer.length()];
634     buffer.getChars(0, length, result, 0);
635     return result;
636 }
637 private static int consumeWhitespace(char[] typeName, int pos, int length) {
638     while (pos < length) {
639         char currentChar = typeName[pos];
640         if (currentChar != ' ' && !CharOperation.isWhitespace(currentChar)) {
641             break;
642         }
643         pos++;
644     }
645     return pos;
646 }
647 private static int encodeQualifiedName(char[] typeName, int pos, int length, StringBuffer JavaDoc buffer) {
648     int count = 0;
649     char lastAppendedChar = 0;
650     nameLoop: while (pos < length) {
651         char currentChar = typeName[pos];
652         switch (currentChar) {
653             case '<' :
654             case '>' :
655             case '[' :
656             case ',' :
657                 break nameLoop;
658             case '.' :
659                 buffer.append(C_DOT);
660                 lastAppendedChar = C_DOT;
661                 count++;
662                 break;
663             default:
664                 if (currentChar == ' ' || ScannerHelper.isWhitespace(currentChar)) {
665                     if (lastAppendedChar == C_DOT) { // allow spaces after a dot
666
pos = consumeWhitespace(typeName, pos, length) - 1; // will be incremented
667
break;
668                     }
669                     // allow spaces before a dot
670
int checkPos = checkNextChar(typeName, '.', pos, length, true);
671                     if (checkPos > 0) {
672                         buffer.append(C_DOT); // process dot immediately to avoid one iteration
673
lastAppendedChar = C_DOT;
674                         count++;
675                         pos = checkPos;
676                         break;
677                     }
678                     break nameLoop;
679                 }
680                 buffer.append(currentChar);
681                 lastAppendedChar = currentChar;
682                 count++;
683                 break;
684         }
685         pos++;
686     }
687     if (count == 0) throw new IllegalArgumentException JavaDoc(new String JavaDoc(typeName));
688     return pos;
689 }
690
691 private static int encodeArrayDimension(char[] typeName, int pos, int length, StringBuffer JavaDoc buffer) {
692     int checkPos;
693     while (pos < length && (checkPos = checkNextChar(typeName, '[', pos, length, true)) > 0) {
694         pos = checkNextChar(typeName, ']', checkPos, length, false);
695         buffer.append(C_ARRAY);
696     }
697     return pos;
698 }
699 private static int checkArrayDimension(char[] typeName, int pos, int length) {
700     int genericBalance = 0;
701     while (pos < length) {
702         switch(typeName[pos]) {
703             case '<' :
704                 genericBalance++;
705                 break;
706             case ',' :
707                 if (genericBalance == 0) return -1;
708                 break;
709             case '>':
710                 if (genericBalance == 0) return -1;
711                 genericBalance--;
712                 break;
713             case '[':
714                 if (genericBalance == 0) {
715                     return pos;
716                 }
717         }
718         pos++;
719     }
720     return -1;
721 }
722 private static int checkNextChar(char[] typeName, char expectedChar, int pos, int length, boolean isOptional) {
723     pos = consumeWhitespace(typeName, pos, length);
724     if (pos < length && typeName[pos] == expectedChar)
725         return pos + 1;
726     if (!isOptional) throw new IllegalArgumentException JavaDoc(new String JavaDoc(typeName));
727     return -1;
728 }
729
730 private static int encodeTypeSignature(char[] typeName, int start, boolean isResolved, int length, StringBuffer JavaDoc buffer) {
731     int pos = start;
732     pos = consumeWhitespace(typeName, pos, length);
733     if (pos >= length) throw new IllegalArgumentException JavaDoc(new String JavaDoc(typeName));
734     int checkPos;
735     char currentChar = typeName[pos];
736     switch (currentChar) {
737         // primitive type?
738
case 'b' :
739             checkPos = checkName(BOOLEAN, typeName, pos, length);
740             if (checkPos > 0) {
741                 pos = encodeArrayDimension(typeName, checkPos, length, buffer);
742                 buffer.append(C_BOOLEAN);
743                 return pos;
744             }
745             checkPos = checkName(BYTE, typeName, pos, length);
746             if (checkPos > 0) {
747                 pos = encodeArrayDimension(typeName, checkPos, length, buffer);
748                 buffer.append(C_BYTE);
749                 return pos;
750             }
751             break;
752         case 'd':
753             checkPos = checkName(DOUBLE, typeName, pos, length);
754             if (checkPos > 0) {
755                 pos = encodeArrayDimension(typeName, checkPos, length, buffer);
756                 buffer.append(C_DOUBLE);
757                 return pos;
758             }
759             break;
760         case 'f':
761             checkPos = checkName(FLOAT, typeName, pos, length);
762             if (checkPos > 0) {
763                 pos = encodeArrayDimension(typeName, checkPos, length, buffer);
764                 buffer.append(C_FLOAT);
765                 return pos;
766             }
767             break;
768         case 'i':
769             checkPos = checkName(INT, typeName, pos, length);
770             if (checkPos > 0) {
771                 pos = encodeArrayDimension(typeName, checkPos, length, buffer);
772                 buffer.append(C_INT);
773                 return pos;
774             }
775             break;
776         case 'l':
777             checkPos = checkName(LONG, typeName, pos, length);
778             if (checkPos > 0) {
779                 pos = encodeArrayDimension(typeName, checkPos, length, buffer);
780                 buffer.append(C_LONG);
781                 return pos;
782             }
783             break;
784         case 's':
785             checkPos = checkName(SHORT, typeName, pos, length);
786             if (checkPos > 0) {
787                 pos = encodeArrayDimension(typeName, checkPos, length, buffer);
788                 buffer.append(C_SHORT);
789                 return pos;
790             }
791             break;
792         case 'v':
793             checkPos = checkName(VOID, typeName, pos, length);
794             if (checkPos > 0) {
795                 pos = encodeArrayDimension(typeName, checkPos, length, buffer);
796                 buffer.append(C_VOID);
797                 return pos;
798             }
799             break;
800         case 'c':
801             checkPos = checkName(CHAR, typeName, pos, length);
802             if (checkPos > 0) {
803                 pos = encodeArrayDimension(typeName, checkPos, length, buffer);
804                 buffer.append(C_CHAR);
805                 return pos;
806             } else {
807                 checkPos = checkName(CAPTURE, typeName, pos, length);
808                 if (checkPos > 0) {
809                     pos = consumeWhitespace(typeName, checkPos, length);
810                     if (typeName[pos] != '?') {
811                         break;
812                     }
813                 } else {
814                     break;
815                 }
816             }
817             buffer.append(C_CAPTURE);
818             // fall-thru for wildcard part of capture typecheckPos
819
case '?':
820             // wildcard
821
pos = consumeWhitespace(typeName, pos+1, length);
822             checkPos = checkName(EXTENDS, typeName, pos, length);
823             if (checkPos > 0) {
824                 buffer.append(C_EXTENDS);
825                 pos = encodeTypeSignature(typeName, checkPos, isResolved, length, buffer);
826                 return pos;
827             }
828             checkPos = checkName(SUPER, typeName, pos, length);
829             if (checkPos > 0) {
830                 buffer.append(C_SUPER);
831                 pos = encodeTypeSignature(typeName, checkPos, isResolved, length, buffer);
832                 return pos;
833             }
834             buffer.append(C_STAR);
835             return pos;
836     }
837     // non primitive type
838
checkPos = checkArrayDimension(typeName, pos, length);
839     int end;
840     if (checkPos > 0) {
841         end = encodeArrayDimension(typeName, checkPos, length, buffer);
842     } else {
843         end = -1;
844     }
845     buffer.append(isResolved ? C_RESOLVED : C_UNRESOLVED);
846     while (true) { // loop on qualifiedName[<args>][.qualifiedName[<args>]*
847
pos = encodeQualifiedName(typeName, pos, length, buffer);
848         checkPos = checkNextChar(typeName, '<', pos, length, true);
849         if (checkPos > 0) {
850             buffer.append(C_GENERIC_START);
851             pos = encodeTypeSignature(typeName, checkPos, isResolved, length, buffer);
852             while ((checkPos = checkNextChar(typeName, ',', pos, length, true)) > 0) {
853                 pos = encodeTypeSignature(typeName, checkPos, isResolved, length, buffer);
854             }
855             pos = checkNextChar(typeName, '>', pos, length, false);
856             buffer.append(C_GENERIC_END);
857         }
858         checkPos = checkNextChar(typeName, '.', pos, length, true);
859         if (checkPos > 0) {
860             buffer.append(C_DOT);
861             pos = checkPos;
862         } else {
863             break;
864         }
865     }
866     buffer.append(C_NAME_END);
867     if (end > 0) pos = end; // skip array dimension which were preprocessed
868
return pos;
869 }
870
871 /**
872  * Creates a new type signature from the given type name. If the type name is qualified,
873  * then it is expected to be dot-based. The type name may contain primitive
874  * types or array types. However, parameterized types are not supported.
875  * <p>
876  * For example:
877  * <pre>
878  * <code>
879  * createTypeSignature("int", hucairz) -> "I"
880  * createTypeSignature("java.lang.String", true) -> "Ljava.lang.String;"
881  * createTypeSignature("String", false) -> "QString;"
882  * createTypeSignature("java.lang.String", false) -> "Qjava.lang.String;"
883  * createTypeSignature("int []", false) -> "[I"
884  * </code>
885  * </pre>
886  * </p>
887  *
888  * @param typeName the possibly qualified type name
889  * @param isResolved <code>true</code> if the type name is to be considered
890  * resolved (for example, a type name from a binary class file), and
891  * <code>false</code> if the type name is to be considered unresolved
892  * (for example, a type name found in source code)
893  * @return the encoded type signature
894  */

895 public static String JavaDoc createTypeSignature(String JavaDoc typeName, boolean isResolved) {
896     return createTypeSignature(typeName == null ? null : typeName.toCharArray(), isResolved);
897 }
898
899 /**
900  * Returns the array count (array nesting depth) of the given type signature.
901  *
902  * @param typeSignature the type signature
903  * @return the array nesting depth, or 0 if not an array
904  * @exception IllegalArgumentException if the signature is not syntactically
905  * correct
906  *
907  * @since 2.0
908  */

909 public static int getArrayCount(char[] typeSignature) throws IllegalArgumentException JavaDoc {
910     try {
911         int count = 0;
912         while (typeSignature[count] == C_ARRAY) {
913             ++count;
914         }
915         return count;
916     } catch (ArrayIndexOutOfBoundsException JavaDoc e) { // signature is syntactically incorrect if last character is C_ARRAY
917
throw new IllegalArgumentException JavaDoc();
918     }
919 }
920 /**
921  * Returns the array count (array nesting depth) of the given type signature.
922  *
923  * @param typeSignature the type signature
924  * @return the array nesting depth, or 0 if not an array
925  * @exception IllegalArgumentException if the signature is not syntactically
926  * correct
927  */

928 public static int getArrayCount(String JavaDoc typeSignature) throws IllegalArgumentException JavaDoc {
929     return getArrayCount(typeSignature.toCharArray());
930 }
931 /**
932  * Returns the type signature without any array nesting.
933  * <p>
934  * For example:
935  * <pre>
936  * <code>
937  * getElementType({'[', '[', 'I'}) --> {'I'}.
938  * </code>
939  * </pre>
940  * </p>
941  *
942  * @param typeSignature the type signature
943  * @return the type signature without arrays
944  * @exception IllegalArgumentException if the signature is not syntactically
945  * correct
946  *
947  * @since 2.0
948  */

949 public static char[] getElementType(char[] typeSignature) throws IllegalArgumentException JavaDoc {
950     int count = getArrayCount(typeSignature);
951     if (count == 0) return typeSignature;
952     int length = typeSignature.length;
953     char[] result = new char[length-count];
954     System.arraycopy(typeSignature, count, result, 0, length-count);
955     return result;
956 }
957 /**
958  * Returns the type signature without any array nesting.
959  * <p>
960  * For example:
961  * <pre>
962  * <code>
963  * getElementType("[[I") --> "I".
964  * </code>
965  * </pre>
966  * </p>
967  *
968  * @param typeSignature the type signature
969  * @return the type signature without arrays
970  * @exception IllegalArgumentException if the signature is not syntactically
971  * correct
972  */

973 public static String JavaDoc getElementType(String JavaDoc typeSignature) throws IllegalArgumentException JavaDoc {
974     return new String JavaDoc(getElementType(typeSignature.toCharArray()));
975 }
976 /**
977  * Returns the number of parameter types in the given method signature.
978  *
979  * @param methodSignature the method signature
980  * @return the number of parameters
981  * @exception IllegalArgumentException if the signature is not syntactically
982  * correct
983  * @since 2.0
984  */

985 public static int getParameterCount(char[] methodSignature) throws IllegalArgumentException JavaDoc {
986     try {
987         int count = 0;
988         int i = CharOperation.indexOf(C_PARAM_START, methodSignature);
989         if (i < 0) {
990             throw new IllegalArgumentException JavaDoc();
991         } else {
992             i++;
993         }
994         for (;;) {
995             if (methodSignature[i] == C_PARAM_END) {
996                 return count;
997             }
998             int e= Util.scanTypeSignature(methodSignature, i);
999             if (e < 0) {
1000                throw new IllegalArgumentException JavaDoc();
1001            } else {
1002                i = e + 1;
1003            }
1004            count++;
1005        }
1006    } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
1007        throw new IllegalArgumentException JavaDoc();
1008    }
1009}
1010
1011/**
1012 * Returns the kind of type signature encoded by the given string.
1013 *
1014 * @param typeSignature the type signature string
1015 * @return the kind of type signature; one of the kind constants:
1016 * {@link #ARRAY_TYPE_SIGNATURE}, {@link #CLASS_TYPE_SIGNATURE},
1017 * {@link #BASE_TYPE_SIGNATURE}, or {@link #TYPE_VARIABLE_SIGNATURE},
1018 * or (since 3.1) {@link #WILDCARD_TYPE_SIGNATURE} or {@link #CAPTURE_TYPE_SIGNATURE}
1019 * @exception IllegalArgumentException if this is not a type signature
1020 * @since 3.0
1021 */

1022public static int getTypeSignatureKind(char[] typeSignature) {
1023    // need a minimum 1 char
1024
if (typeSignature.length < 1) {
1025        throw new IllegalArgumentException JavaDoc();
1026    }
1027    char c = typeSignature[0];
1028    if (c == C_GENERIC_START) {
1029        int count = 1;
1030        for (int i = 1, length = typeSignature.length; i < length; i++) {
1031            switch (typeSignature[i]) {
1032                case C_GENERIC_START:
1033                    count++;
1034                    break;
1035                case C_GENERIC_END:
1036                    count--;
1037                    break;
1038            }
1039            if (count == 0) {
1040                if (i+1 < length)
1041                    c = typeSignature[i+1];
1042                break;
1043            }
1044        }
1045    }
1046    switch (c) {
1047        case C_ARRAY :
1048            return ARRAY_TYPE_SIGNATURE;
1049        case C_RESOLVED :
1050        case C_UNRESOLVED :
1051            return CLASS_TYPE_SIGNATURE;
1052        case C_TYPE_VARIABLE :
1053            return TYPE_VARIABLE_SIGNATURE;
1054        case C_BOOLEAN :
1055        case C_BYTE :
1056        case C_CHAR :
1057        case C_DOUBLE :
1058        case C_FLOAT :
1059        case C_INT :
1060        case C_LONG :
1061        case C_SHORT :
1062        case C_VOID :
1063            return BASE_TYPE_SIGNATURE;
1064        case C_STAR :
1065        case C_SUPER :
1066        case C_EXTENDS :
1067            return WILDCARD_TYPE_SIGNATURE;
1068        case C_CAPTURE :
1069            return CAPTURE_TYPE_SIGNATURE;
1070        default :
1071            throw new IllegalArgumentException JavaDoc();
1072    }
1073}
1074
1075/**
1076 * Returns the kind of type signature encoded by the given string.
1077 *
1078 * @param typeSignature the type signature string
1079 * @return the kind of type signature; one of the kind constants:
1080 * {@link #ARRAY_TYPE_SIGNATURE}, {@link #CLASS_TYPE_SIGNATURE},
1081 * {@link #BASE_TYPE_SIGNATURE}, or {@link #TYPE_VARIABLE_SIGNATURE},
1082 * or (since 3.1) {@link #WILDCARD_TYPE_SIGNATURE} or {@link #CAPTURE_TYPE_SIGNATURE}
1083 * @exception IllegalArgumentException if this is not a type signature
1084 * @since 3.0
1085 */

1086public static int getTypeSignatureKind(String JavaDoc typeSignature) {
1087    // need a minimum 1 char
1088
if (typeSignature.length() < 1) {
1089        throw new IllegalArgumentException JavaDoc();
1090    }
1091    char c = typeSignature.charAt(0);
1092    if (c == C_GENERIC_START) {
1093        int count = 1;
1094        for (int i = 1, length = typeSignature.length(); i < length; i++) {
1095            switch (typeSignature.charAt(i)) {
1096                case C_GENERIC_START:
1097                    count++;
1098                    break;
1099                case C_GENERIC_END:
1100                    count--;
1101                    break;
1102            }
1103            if (count == 0) {
1104                if (i+1 < length)
1105                    c = typeSignature.charAt(i+1);
1106                break;
1107            }
1108        }
1109    }
1110    switch (c) {
1111        case C_ARRAY :
1112            return ARRAY_TYPE_SIGNATURE;
1113        case C_RESOLVED :
1114        case C_UNRESOLVED :
1115            return CLASS_TYPE_SIGNATURE;
1116        case C_TYPE_VARIABLE :
1117            return TYPE_VARIABLE_SIGNATURE;
1118        case C_BOOLEAN :
1119        case C_BYTE :
1120        case C_CHAR :
1121        case C_DOUBLE :
1122        case C_FLOAT :
1123        case C_INT :
1124        case C_LONG :
1125        case C_SHORT :
1126        case C_VOID :
1127            return BASE_TYPE_SIGNATURE;
1128        case C_STAR :
1129        case C_SUPER :
1130        case C_EXTENDS :
1131            return WILDCARD_TYPE_SIGNATURE;
1132        case C_CAPTURE :
1133            return CAPTURE_TYPE_SIGNATURE;
1134        default :
1135            throw new IllegalArgumentException JavaDoc();
1136    }
1137}
1138
1139/**
1140 * Returns the number of parameter types in the given method signature.
1141 *
1142 * @param methodSignature the method signature
1143 * @return the number of parameters
1144 * @exception IllegalArgumentException if the signature is not syntactically
1145 * correct
1146 */

1147public static int getParameterCount(String JavaDoc methodSignature) throws IllegalArgumentException JavaDoc {
1148    return getParameterCount(methodSignature.toCharArray());
1149}
1150
1151/**
1152 * Extracts the parameter type signatures from the given method signature.
1153 * The method signature is expected to be dot-based.
1154 *
1155 * @param methodSignature the method signature
1156 * @return the list of parameter type signatures
1157 * @exception IllegalArgumentException if the signature is syntactically
1158 * incorrect
1159 *
1160 * @since 2.0
1161 */

1162public static char[][] getParameterTypes(char[] methodSignature) throws IllegalArgumentException JavaDoc {
1163    try {
1164        int count = getParameterCount(methodSignature);
1165        char[][] result = new char[count][];
1166        if (count == 0) {
1167            return result;
1168        }
1169        int i = CharOperation.indexOf(C_PARAM_START, methodSignature);
1170        if (i < 0) {
1171            throw new IllegalArgumentException JavaDoc();
1172        } else {
1173            i++;
1174        }
1175        int t = 0;
1176        for (;;) {
1177            if (methodSignature[i] == C_PARAM_END) {
1178                return result;
1179            }
1180            int e = Util.scanTypeSignature(methodSignature, i);
1181            if (e < 0) {
1182                throw new IllegalArgumentException JavaDoc();
1183            }
1184            result[t] = CharOperation.subarray(methodSignature, i, e + 1);
1185            t++;
1186            i = e + 1;
1187        }
1188    } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
1189        throw new IllegalArgumentException JavaDoc();
1190    }
1191}
1192
1193/**
1194 * Extracts the parameter type signatures from the given method signature.
1195 * The method signature is expected to be dot-based.
1196 *
1197 * @param methodSignature the method signature
1198 * @return the list of parameter type signatures
1199 * @exception IllegalArgumentException if the signature is syntactically
1200 * incorrect
1201 */

1202public static String JavaDoc[] getParameterTypes(String JavaDoc methodSignature) throws IllegalArgumentException JavaDoc {
1203    char[][] parameterTypes = getParameterTypes(methodSignature.toCharArray());
1204    return CharOperation.toStrings(parameterTypes);
1205}
1206
1207/**
1208 * Extracts the thrown exception type signatures from the given method signature if any
1209 * The method signature is expected to be dot-based.
1210 *
1211 * @param methodSignature the method signature
1212 * @return the list of thrown exception type signatures
1213 * @exception IllegalArgumentException if the signature is syntactically
1214 * incorrect
1215 *
1216 * @since 3.1
1217 */

1218public static String JavaDoc[] getThrownExceptionTypes(String JavaDoc methodSignature) throws IllegalArgumentException JavaDoc {
1219    char[][] parameterTypes = getThrownExceptionTypes(methodSignature.toCharArray());
1220    return CharOperation.toStrings(parameterTypes);
1221}
1222
1223/**
1224 * Extracts the thrown exception type signatures from the given method signature if any
1225 * The method signature is expected to be dot-based.
1226 *
1227 * @param methodSignature the method signature
1228 * @return the list of thrown exception type signatures
1229 * @exception IllegalArgumentException if the signature is syntactically
1230 * incorrect
1231 *
1232 * @since 3.1
1233 */

1234public static char[][] getThrownExceptionTypes(char[] methodSignature) throws IllegalArgumentException JavaDoc {
1235    // skip type parameters
1236
int exceptionStart = CharOperation.indexOf(C_EXCEPTION_START, methodSignature);
1237    if (exceptionStart == -1) {
1238        int paren = CharOperation.lastIndexOf(C_PARAM_END, methodSignature);
1239        if (paren == -1) {
1240            throw new IllegalArgumentException JavaDoc();
1241        }
1242        // ignore return type
1243
exceptionStart = Util.scanTypeSignature(methodSignature, paren+1) + 1;
1244        int length = methodSignature.length;
1245        if (exceptionStart == length) return CharOperation.NO_CHAR_CHAR;
1246        throw new IllegalArgumentException JavaDoc();
1247    }
1248    int length = methodSignature.length;
1249    int i = exceptionStart;
1250    ArrayList JavaDoc exceptionList = new ArrayList JavaDoc(1);
1251    while (i < length) {
1252        if (methodSignature[i] == C_EXCEPTION_START) {
1253            exceptionStart++;
1254            i++;
1255        } else {
1256            throw new IllegalArgumentException JavaDoc();
1257        }
1258        i = Util.scanTypeSignature(methodSignature, i) + 1;
1259        exceptionList.add(CharOperation.subarray(methodSignature, exceptionStart,i));
1260        exceptionStart = i;
1261    }
1262    char[][] result;
1263    exceptionList.toArray(result = new char[exceptionList.size()][]);
1264    return result;
1265}
1266
1267/**
1268 * Extracts the type argument signatures from the given type signature.
1269 * Returns an empty array if the type signature is not a parameterized type signature.
1270 *
1271 * @param parameterizedTypeSignature the parameterized type signature
1272 * @return the signatures of the type arguments
1273 * @exception IllegalArgumentException if the signature is syntactically incorrect
1274 *
1275 * @since 3.1
1276 */

1277public static char[][] getTypeArguments(char[] parameterizedTypeSignature) throws IllegalArgumentException JavaDoc {
1278    int length = parameterizedTypeSignature.length;
1279    if (length < 2 || parameterizedTypeSignature[length-2] != C_GENERIC_END)
1280        // cannot have type arguments otherwise signature would end by ">;"
1281
return CharOperation.NO_CHAR_CHAR;
1282    int count = 1; // start to count generic end/start peers
1283
int start = length - 2;
1284    while (start >= 0 && count > 0) {
1285        switch (parameterizedTypeSignature[--start]) {
1286            case C_GENERIC_START:
1287                count--;
1288                break;
1289            case C_GENERIC_END:
1290                count++;
1291                break;
1292        }
1293    }
1294    if (start < 0) // invalid number of generic start/end
1295
throw new IllegalArgumentException JavaDoc();
1296    ArrayList JavaDoc args = new ArrayList JavaDoc();
1297    int p = start + 1;
1298    while (true) {
1299        if (p >= parameterizedTypeSignature.length) {
1300            throw new IllegalArgumentException JavaDoc();
1301        }
1302        char c = parameterizedTypeSignature[p];
1303        if (c == C_GENERIC_END) {
1304            int size = args.size();
1305            char[][] result = new char[size][];
1306            args.toArray(result);
1307            return result;
1308        }
1309        int e = Util.scanTypeArgumentSignature(parameterizedTypeSignature, p);
1310        args.add(CharOperation.subarray(parameterizedTypeSignature, p, e+1));
1311        p = e + 1;
1312    }
1313}
1314
1315/**
1316 * Extracts the type argument signatures from the given type signature.
1317 * Returns an empty array if the type signature is not a parameterized type signature.
1318 *
1319 * @param parameterizedTypeSignature the parameterized type signature
1320 * @return the signatures of the type arguments
1321 * @exception IllegalArgumentException if the signature is syntactically incorrect
1322 *
1323 * @since 3.1
1324 */

1325public static String JavaDoc[] getTypeArguments(String JavaDoc parameterizedTypeSignature) throws IllegalArgumentException JavaDoc {
1326    char[][] args = getTypeArguments(parameterizedTypeSignature.toCharArray());
1327    return CharOperation.toStrings(args);
1328}
1329
1330/**
1331 * Extracts the type erasure signature from the given parameterized type signature.
1332 * Returns the given type signature if it is not parameterized.
1333 *
1334 * @param parameterizedTypeSignature the parameterized type signature
1335 * @return the signature of the type erasure
1336 * @exception IllegalArgumentException if the signature is syntactically
1337 * incorrect
1338 *
1339 * @since 3.1
1340 */

1341public static char[] getTypeErasure(char[] parameterizedTypeSignature) throws IllegalArgumentException JavaDoc {
1342    int end = CharOperation.indexOf(C_GENERIC_START, parameterizedTypeSignature);
1343    if (end == -1) return parameterizedTypeSignature;
1344    int length = parameterizedTypeSignature.length;
1345    char[] result = new char[length];
1346    int pos = 0;
1347    int start = 0;
1348    int deep= 0;
1349    for (int idx=end; idx<length; idx++) {
1350        switch (parameterizedTypeSignature[idx]) {
1351            case C_GENERIC_START:
1352                if (deep == 0) {
1353                    int size = idx-start;
1354                    System.arraycopy(parameterizedTypeSignature, start, result, pos, size);
1355                    end = idx;
1356                    pos += size;
1357                }
1358                deep++;
1359                break;
1360            case C_GENERIC_END:
1361                deep--;
1362                if (deep < 0) throw new IllegalArgumentException JavaDoc();
1363                if (deep == 0) start = idx+1;
1364                break;
1365        }
1366    }
1367    if (deep > 0) throw new IllegalArgumentException JavaDoc();
1368    int size = pos+length-start;
1369    char[] resized = new char[size];
1370    System.arraycopy(result, 0, resized, 0, pos);
1371    System.arraycopy(parameterizedTypeSignature, start, resized, pos, length-start);
1372    return resized;
1373}
1374
1375/**
1376 * Extracts the type erasure signature from the given parameterized type signature.
1377 * Returns the given type signature if it is not parameterized.
1378 *
1379 * @param parameterizedTypeSignature the parameterized type signature
1380 * @return the signature of the type erasure
1381 * @exception IllegalArgumentException if the signature is syntactically
1382 * incorrect
1383 *
1384 * @since 3.1
1385 */

1386public static String JavaDoc getTypeErasure(String JavaDoc parameterizedTypeSignature) throws IllegalArgumentException JavaDoc {
1387    return new String JavaDoc(getTypeErasure(parameterizedTypeSignature.toCharArray()));
1388}
1389
1390/**
1391 * Extracts the type parameter signatures from the given method or type signature.
1392 * The method or type signature is expected to be dot-based.
1393 *
1394 * @param methodOrTypeSignature the method or type signature
1395 * @return the list of type parameter signatures
1396 * @exception IllegalArgumentException if the signature is syntactically
1397 * incorrect
1398 *
1399 * @since 3.1
1400 */

1401public static char[][] getTypeParameters(char[] methodOrTypeSignature) throws IllegalArgumentException JavaDoc {
1402    try {
1403        int length = methodOrTypeSignature.length;
1404        if (length == 0) return CharOperation.NO_CHAR_CHAR;
1405        if (methodOrTypeSignature[0] != C_GENERIC_START) return CharOperation.NO_CHAR_CHAR;
1406        
1407        ArrayList JavaDoc paramList = new ArrayList JavaDoc(1);
1408        int paramStart = 1, i = 1; // start after leading '<'
1409
while (i < length) {
1410            if (methodOrTypeSignature[i] == C_GENERIC_END) {
1411                int size = paramList.size();
1412                if (size == 0) throw new IllegalArgumentException JavaDoc();
1413                char[][] result;
1414                paramList.toArray(result = new char[size][]);
1415                return result;
1416            }
1417            i = CharOperation.indexOf(C_COLON, methodOrTypeSignature, i);
1418            if (i < 0 || i >= length)
1419                throw new IllegalArgumentException JavaDoc();
1420            // iterate over bounds
1421
while (methodOrTypeSignature[i] == ':') {
1422                i++; // skip colon
1423
switch (methodOrTypeSignature[i]) {
1424                    case ':':
1425                        // no class bound
1426
break;
1427                    case C_GENERIC_END:
1428                        break;
1429                    case C_RESOLVED:
1430                        try {
1431                            i = Util.scanClassTypeSignature(methodOrTypeSignature, i);
1432                            i++; // position at start of next param if any
1433
} catch (IllegalArgumentException JavaDoc e) {
1434                            // not a class type signature -> it is a new type parameter
1435
}
1436                        break;
1437                    case C_ARRAY:
1438                        try {
1439                            i = Util.scanArrayTypeSignature(methodOrTypeSignature, i);
1440                            i++; // position at start of next param if any
1441
} catch (IllegalArgumentException JavaDoc e) {
1442                            // not an array type signature -> it is a new type parameter
1443
}
1444                        break;
1445                    case C_TYPE_VARIABLE:
1446                        try {
1447                            i = Util.scanTypeVariableSignature(methodOrTypeSignature, i);
1448                            i++; // position at start of next param if any
1449
} catch (IllegalArgumentException JavaDoc e) {
1450                            // not a type variable signature -> it is a new type parameter
1451
}
1452                        break;
1453                    // default: another type parameter is starting
1454
}
1455            }
1456            paramList.add(CharOperation.subarray(methodOrTypeSignature, paramStart, i));
1457            paramStart = i; // next param start from here
1458
}
1459    } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
1460        // invalid signature, fall through
1461
}
1462    throw new IllegalArgumentException JavaDoc();
1463}
1464/**
1465 * Extracts the type parameter signatures from the given method or type signature.
1466 * The method or type signature is expected to be dot-based.
1467 *
1468 * @param methodOrTypeSignature the method or type signature
1469 * @return the list of type parameter signatures
1470 * @exception IllegalArgumentException if the signature is syntactically
1471 * incorrect
1472 *
1473 * @since 3.1
1474 */

1475public static String JavaDoc[] getTypeParameters(String JavaDoc methodOrTypeSignature) throws IllegalArgumentException JavaDoc {
1476    char[][] params = getTypeParameters(methodOrTypeSignature.toCharArray());
1477    return CharOperation.toStrings(params);
1478}
1479
1480/**
1481 * Extracts the type variable name from the given formal type parameter
1482 * signature. The signature is expected to be dot-based.
1483 *
1484 * @param formalTypeParameterSignature the formal type parameter signature
1485 * @return the name of the type variable
1486 * @exception IllegalArgumentException if the signature is syntactically
1487 * incorrect
1488 * @since 3.0
1489 */

1490public static String JavaDoc getTypeVariable(String JavaDoc formalTypeParameterSignature) throws IllegalArgumentException JavaDoc {
1491    return new String JavaDoc(getTypeVariable(formalTypeParameterSignature.toCharArray()));
1492}
1493
1494/**
1495 * Extracts the type variable name from the given formal type parameter
1496 * signature. The signature is expected to be dot-based.
1497 *
1498 * @param formalTypeParameterSignature the formal type parameter signature
1499 * @return the name of the type variable
1500 * @exception IllegalArgumentException if the signature is syntactically
1501 * incorrect
1502 * @since 3.0
1503 */

1504public static char[] getTypeVariable(char[] formalTypeParameterSignature) throws IllegalArgumentException JavaDoc {
1505    int p = CharOperation.indexOf(C_COLON, formalTypeParameterSignature);
1506    if (p < 0) {
1507        // no ":" means can't be a formal type parameter signature
1508
throw new IllegalArgumentException JavaDoc();
1509    }
1510    return CharOperation.subarray(formalTypeParameterSignature, 0, p);
1511}
1512
1513/**
1514 * Extracts the class and interface bounds from the given formal type
1515 * parameter signature. The class bound, if present, is listed before
1516 * the interface bounds. The signature is expected to be dot-based.
1517 *
1518 * @param formalTypeParameterSignature the formal type parameter signature
1519 * @return the (possibly empty) list of type signatures for the bounds
1520 * @exception IllegalArgumentException if the signature is syntactically
1521 * incorrect
1522 * @since 3.0
1523 */

1524public static char[][] getTypeParameterBounds(char[] formalTypeParameterSignature) throws IllegalArgumentException JavaDoc {
1525    int p1 = CharOperation.indexOf(C_COLON, formalTypeParameterSignature);
1526    if (p1 < 0) {
1527        // no ":" means can't be a formal type parameter signature
1528
throw new IllegalArgumentException JavaDoc();
1529    }
1530    if (p1 == formalTypeParameterSignature.length - 1) {
1531        // no class or interface bounds
1532
return CharOperation.NO_CHAR_CHAR;
1533    }
1534    int p2 = CharOperation.indexOf(C_COLON, formalTypeParameterSignature, p1 + 1);
1535    char[] classBound;
1536    if (p2 < 0) {
1537        // no interface bounds
1538
classBound = CharOperation.subarray(formalTypeParameterSignature, p1 + 1, formalTypeParameterSignature.length);
1539        return new char[][] {classBound};
1540    }
1541    if (p2 == p1 + 1) {
1542        // no class bound, but 1 or more interface bounds
1543
classBound = null;
1544    } else {
1545        classBound = CharOperation.subarray(formalTypeParameterSignature, p1 + 1, p2);
1546    }
1547    char[][] interfaceBounds = CharOperation.splitOn(C_COLON, formalTypeParameterSignature, p2 + 1, formalTypeParameterSignature.length);
1548    if (classBound == null) {
1549        return interfaceBounds;
1550    }
1551    int resultLength = interfaceBounds.length + 1;
1552    char[][] result = new char[resultLength][];
1553    result[0] = classBound;
1554    System.arraycopy(interfaceBounds, 0, result, 1, interfaceBounds.length);
1555    return result;
1556}
1557
1558/**
1559 * Extracts the class and interface bounds from the given formal type
1560 * parameter signature. The class bound, if present, is listed before
1561 * the interface bounds. The signature is expected to be dot-based.
1562 *
1563 * @param formalTypeParameterSignature the formal type parameter signature
1564 * @return the (possibly empty) list of type signatures for the bounds
1565 * @exception IllegalArgumentException if the signature is syntactically
1566 * incorrect
1567 * @since 3.0
1568 */

1569public static String JavaDoc[] getTypeParameterBounds(String JavaDoc formalTypeParameterSignature) throws IllegalArgumentException JavaDoc {
1570    char[][] bounds = getTypeParameterBounds(formalTypeParameterSignature.toCharArray());
1571    return CharOperation.toStrings(bounds);
1572}
1573
1574/**
1575 * Returns a char array containing all but the last segment of the given
1576 * dot-separated qualified name. Returns the empty char array if it is not qualified.
1577 * <p>
1578 * For example:
1579 * <pre>
1580 * <code>
1581 * getQualifier({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g'}
1582 * getQualifier({'O', 'u', 't', 'e', 'r', '.', 'I', 'n', 'n', 'e', 'r'}) -> {'O', 'u', 't', 'e', 'r'}
1583 * getQualifier({'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l', '.', 'L', 'i', 's', 't', '<', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', '>'}) -> {'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l'}
1584 * </code>
1585 * </pre>
1586 * </p>
1587 *
1588 * @param name the name
1589 * @return the qualifier prefix, or the empty char array if the name contains no
1590 * dots
1591 * @exception NullPointerException if name is null
1592 * @since 2.0
1593 */

1594public static char[] getQualifier(char[] name) {
1595    int firstGenericStart = CharOperation.indexOf(C_GENERIC_START, name);
1596    int lastDot = CharOperation.lastIndexOf(C_DOT, name, 0, firstGenericStart == -1 ? name.length-1 : firstGenericStart);
1597    if (lastDot == -1) {
1598        return CharOperation.NO_CHAR;
1599    }
1600    return CharOperation.subarray(name, 0, lastDot);
1601}
1602/**
1603 * Returns a string containing all but the last segment of the given
1604 * dot-separated qualified name. Returns the empty string if it is not qualified.
1605 * <p>
1606 * For example:
1607 * <pre>
1608 * <code>
1609 * getQualifier("java.lang.Object") -&gt; "java.lang"
1610 * getQualifier("Outer.Inner") -&gt; "Outer"
1611 * getQualifier("java.util.List&lt;java.lang.String&gt;") -&gt; "java.util"
1612 * </code>
1613 * </pre>
1614 * </p>
1615 *
1616 * @param name the name
1617 * @return the qualifier prefix, or the empty string if the name contains no
1618 * dots
1619 * @exception NullPointerException if name is null
1620 */

1621public static String JavaDoc getQualifier(String JavaDoc name) {
1622    char[] qualifier = getQualifier(name.toCharArray());
1623    if (qualifier.length == 0) return org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING;
1624    return new String JavaDoc(qualifier);
1625}
1626/**
1627 * Extracts the return type from the given method signature. The method signature is
1628 * expected to be dot-based.
1629 *
1630 * @param methodSignature the method signature
1631 * @return the type signature of the return type
1632 * @exception IllegalArgumentException if the signature is syntactically
1633 * incorrect
1634 *
1635 * @since 2.0
1636 */

1637public static char[] getReturnType(char[] methodSignature) throws IllegalArgumentException JavaDoc {
1638    // skip type parameters
1639
int paren = CharOperation.lastIndexOf(C_PARAM_END, methodSignature);
1640    if (paren == -1) {
1641        throw new IllegalArgumentException JavaDoc();
1642    }
1643    // there could be thrown exceptions behind, thus scan one type exactly
1644
int last = Util.scanTypeSignature(methodSignature, paren+1);
1645    return CharOperation.subarray(methodSignature, paren + 1, last+1);
1646}
1647/**
1648 * Extracts the return type from the given method signature. The method signature is
1649 * expected to be dot-based.
1650 *
1651 * @param methodSignature the method signature
1652 * @return the type signature of the return type
1653 * @exception IllegalArgumentException if the signature is syntactically
1654 * incorrect
1655 */

1656public static String JavaDoc getReturnType(String JavaDoc methodSignature) throws IllegalArgumentException JavaDoc {
1657    return new String JavaDoc(getReturnType(methodSignature.toCharArray()));
1658}
1659/**
1660 * Returns package fragment of a type signature. The package fragment separator must be '.'
1661 * and the type fragment separator must be '$'.
1662 * <p>
1663 * For example:
1664 * <pre>
1665 * <code>
1666 * getSignatureQualifier({'L', 'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l', '.', 'M', 'a', 'p', '$', 'E', 'n', 't', 'r', 'y', ';'}) -> {'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l'}
1667 * </code>
1668 * </pre>
1669 * </p>
1670 *
1671 * @param typeSignature the type signature
1672 * @return the package fragment (separators are '.')
1673 * @since 3.1
1674 */

1675public static char[] getSignatureQualifier(char[] typeSignature) {
1676    if(typeSignature == null) return CharOperation.NO_CHAR;
1677    
1678    char[] qualifiedType = Signature.toCharArray(typeSignature);
1679    
1680    int dotCount = 0;
1681    indexFound: for(int i = 0; i < typeSignature.length; i++) {
1682        switch(typeSignature[i]) {
1683            case C_DOT:
1684                dotCount++;
1685                break;
1686            case C_GENERIC_START:
1687                break indexFound;
1688            case C_DOLLAR:
1689                break indexFound;
1690        }
1691    }
1692    
1693    if(dotCount > 0) {
1694        for(int i = 0; i < qualifiedType.length; i++) {
1695            if(qualifiedType[i] == '.') {
1696                dotCount--;
1697            }
1698            if(dotCount <= 0) {
1699                return CharOperation.subarray(qualifiedType, 0, i);
1700            }
1701        }
1702    }
1703    return CharOperation.NO_CHAR;
1704}
1705/**
1706 * Returns package fragment of a type signature. The package fragment separator must be '.'
1707 * and the type fragment separator must be '$'.
1708 * <p>
1709 * For example:
1710 * <pre>
1711 * <code>
1712 * getSignatureQualifier("Ljava.util.Map$Entry") -> "java.util"
1713 * </code>
1714 * </pre>
1715 * </p>
1716 *
1717 * @param typeSignature the type signature
1718 * @return the package fragment (separators are '.')
1719 * @since 3.1
1720 */

1721public static String JavaDoc getSignatureQualifier(String JavaDoc typeSignature) {
1722    return new String JavaDoc(getSignatureQualifier(typeSignature == null ? null : typeSignature.toCharArray()));
1723}
1724/**
1725 * Returns type fragment of a type signature. The package fragment separator must be '.'
1726 * and the type fragment separator must be '$'.
1727 * <p>
1728 * For example:
1729 * <pre>
1730 * <code>
1731 * getSignatureSimpleName({'L', 'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l', '.', 'M', 'a', 'p', '$', 'E', 'n', 't', 'r', 'y', ';'}) -> {'M', 'a', 'p', '.', 'E', 'n', 't', 'r', 'y'}
1732 * </code>
1733 * </pre>
1734 * </p>
1735 *
1736 * @param typeSignature the type signature
1737 * @return the type fragment (separators are '.')
1738 * @since 3.1
1739 */

1740public static char[] getSignatureSimpleName(char[] typeSignature) {
1741    if(typeSignature == null) return CharOperation.NO_CHAR;
1742    
1743    char[] qualifiedType = Signature.toCharArray(typeSignature);
1744    
1745    int dotCount = 0;
1746    indexFound: for(int i = 0; i < typeSignature.length; i++) {
1747        switch(typeSignature[i]) {
1748            case C_DOT:
1749                dotCount++;
1750                break;
1751            case C_GENERIC_START:
1752                break indexFound;
1753            case C_DOLLAR:
1754                break indexFound;
1755        }
1756    }
1757    
1758    if(dotCount > 0) {
1759        for(int i = 0; i < qualifiedType.length; i++) {
1760            if(qualifiedType[i] == '.') {
1761                dotCount--;
1762            }
1763            if(dotCount <= 0) {
1764                return CharOperation.subarray(qualifiedType, i + 1, qualifiedType.length);
1765            }
1766        }
1767    }
1768    return qualifiedType;
1769}
1770/**
1771 * Returns type fragment of a type signature. The package fragment separator must be '.'
1772 * and the type fragment separator must be '$'.
1773 * <p>
1774 * For example:
1775 * <pre>
1776 * <code>
1777 * getSignatureSimpleName("Ljava.util.Map$Entry") -> "Map.Entry"
1778 * </code>
1779 * </pre>
1780 * </p>
1781 *
1782 * @param typeSignature the type signature
1783 * @return the type fragment (separators are '.')
1784 * @since 3.1
1785 */

1786public static String JavaDoc getSignatureSimpleName(String JavaDoc typeSignature) {
1787    return new String JavaDoc(getSignatureSimpleName(typeSignature == null ? null : typeSignature.toCharArray()));
1788}
1789    
1790/**
1791 * Returns the last segment of the given dot-separated qualified name.
1792 * Returns the given name if it is not qualified.
1793 * <p>
1794 * For example:
1795 * <pre>
1796 * <code>
1797 * getSimpleName({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'O', 'b', 'j', 'e', 'c', 't'}
1798 * </code>
1799 * </pre>
1800 * </p>
1801 *
1802 * @param name the name
1803 * @return the last segment of the qualified name
1804 * @exception NullPointerException if name is null
1805 * @since 2.0
1806 */

1807public static char[] getSimpleName(char[] name) {
1808
1809    int lastDot = -1, lastGenericStart = -1, lastGenericEnd = -1;
1810    int depth = 0;
1811    int length = name.length;
1812    lastDotLookup: for (int i = length -1; i >= 0; i--) {
1813        switch (name[i]) {
1814            case '.':
1815                if (depth == 0) {
1816                    lastDot = i;
1817                    break lastDotLookup;
1818                }
1819                break;
1820            case '<':
1821                depth--;
1822                if (depth == 0) lastGenericStart = i;
1823                break;
1824            case '>':
1825                if (depth == 0) lastGenericEnd = i;
1826                depth++;
1827                break;
1828        }
1829    }
1830    if (lastGenericStart < 0) {
1831        if (lastDot < 0) {
1832            return name;
1833        }
1834        return CharOperation.subarray(name, lastDot + 1, length);
1835    }
1836    StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(10);
1837    int nameStart = lastDot < 0 ? 0 : lastDot+1;
1838    buffer.append(name, nameStart, lastGenericStart - nameStart);
1839    appendArgumentSimpleNames(name, lastGenericStart, lastGenericEnd, buffer);
1840    buffer.append(name, lastGenericEnd+1, length-lastGenericEnd-1); // copy trailing portion, may contain dimensions
1841
char[] result = new char[length = buffer.length()];
1842    buffer.getChars(0, length, result, 0);
1843    return result;
1844}
1845/**
1846 * Returns the last segment of the given dot-separated qualified name.
1847 * Returns the given name if it is not qualified.
1848 * <p>
1849 * For example:
1850 * <pre>
1851 * <code>
1852 * getSimpleName("java.lang.Object") -&gt; "Object"
1853 * </code>
1854 * <code>
1855 * getSimpleName("java.util.Map&lt;java.lang.String, java.lang.Object&gt;") -&gt; "Map&lt;String,Object&gt;"
1856 * </code>
1857 * </pre>
1858 * </p>
1859 *
1860 * @param name the name
1861 * @return the last segment of the qualified name
1862 * @exception NullPointerException if name is null
1863 */

1864public static String JavaDoc getSimpleName(String JavaDoc name) {
1865    int lastDot = -1, lastGenericStart = -1, lastGenericEnd = -1;
1866    int depth = 0;
1867    int length = name.length();
1868    lastDotLookup: for (int i = length -1; i >= 0; i--) {
1869        switch (name.charAt(i)) {
1870            case '.':
1871                if (depth == 0) {
1872                    lastDot = i;
1873                    break lastDotLookup;
1874                }
1875                break;
1876            case '<':
1877                depth--;
1878                if (depth == 0) lastGenericStart = i;
1879                break;
1880            case '>':
1881                if (depth == 0) lastGenericEnd = i;
1882                depth++;
1883                break;
1884        }
1885    }
1886    if (lastGenericStart < 0) {
1887        if (lastDot < 0) {
1888            return name;
1889        }
1890        return name.substring(lastDot + 1, length);
1891    }
1892    StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(10);
1893    char[] nameChars = name.toCharArray();
1894    int nameStart = lastDot < 0 ? 0 : lastDot+1;
1895    buffer.append(nameChars, nameStart, lastGenericStart - nameStart);
1896    appendArgumentSimpleNames(nameChars, lastGenericStart, lastGenericEnd, buffer);
1897    buffer.append(nameChars, lastGenericEnd+1, length-lastGenericEnd-1); // copy trailing portion, may contain dimensions
1898
return buffer.toString();
1899}
1900
1901private static void appendSimpleName(char[] name, int start, int end, StringBuffer JavaDoc buffer) {
1902    int lastDot = -1, lastGenericStart = -1, lastGenericEnd = -1;
1903    int depth = 0;
1904    if (name[start] == '?') { // wildcard
1905
buffer.append("?"); //$NON-NLS-1$
1906
int index = consumeWhitespace(name, start+1, end+1);
1907        switch (name[index]) {
1908            case 'e' :
1909                int checkPos = checkName(EXTENDS, name, index, end);
1910                if (checkPos > 0) {
1911                    buffer.append(' ').append(EXTENDS).append(' ');
1912                    index = consumeWhitespace(name, checkPos, end+1);
1913                }
1914                break;
1915            case 's' :
1916                checkPos = checkName(SUPER, name, index, end+1);
1917                if (checkPos > 0) {
1918                    buffer.append(' ').append(SUPER).append(' ');
1919                    index = consumeWhitespace(name, checkPos, end+1);
1920                }
1921                break;
1922        }
1923        start = index; // leading segment got processed
1924
}
1925    lastDotLookup: for (int i = end; i >= start; i--) {
1926        switch (name[i]) {
1927            case '.':
1928                if (depth == 0) {
1929                    lastDot = i;
1930                    char c = name[start];
1931                    if (c == C_EXTENDS || c == C_SUPER) {
1932                        buffer.append(c);
1933                    }
1934                    break lastDotLookup;
1935                }
1936                break;
1937            case '<':
1938                depth--;
1939                if (depth == 0) lastGenericStart = i;
1940                break;
1941            case '>':
1942                if (depth == 0) lastGenericEnd = i;
1943                depth++;
1944                break;
1945        }
1946    }
1947    int nameStart = lastDot < 0 ? start : lastDot+1;
1948    int nameEnd = lastGenericStart < 0 ? end+1 : lastGenericStart;
1949    buffer.append(name, nameStart, nameEnd - nameStart);
1950    if (lastGenericStart >= 0) {
1951        appendArgumentSimpleNames(name, lastGenericStart, lastGenericEnd, buffer);
1952        buffer.append(name, lastGenericEnd+1, end - lastGenericEnd); // copy trailing portion, may contain dimensions
1953
}
1954}
1955// <x.y.z, a.b<c>.d<e.f>> --> <z,d<f>>
1956
private static void appendArgumentSimpleNames(char[] name, int start, int end, StringBuffer JavaDoc buffer) {
1957    buffer.append('<');
1958    int depth = 0;
1959    int argumentStart = -1;
1960    int argumentCount = 0;
1961    for (int i = start; i <= end; i++) {
1962        switch(name[i]) {
1963            case '<' :
1964                depth++;
1965                if (depth == 1) {
1966                    argumentStart = i+1;
1967                }
1968                break;
1969            case '>' :
1970                if (depth == 1) {
1971                    if (argumentCount > 0) buffer.append(',');
1972                    appendSimpleName(name, argumentStart, i-1, buffer);
1973                    argumentCount++;
1974                }
1975                depth--;
1976                break;
1977            case ',' :
1978                if (depth == 1) {
1979                    if (argumentCount > 0) buffer.append(',');
1980                    appendSimpleName(name, argumentStart, i-1, buffer);
1981                    argumentCount++;
1982                    argumentStart = i+1;
1983                }
1984                break;
1985        }
1986    }
1987    buffer.append('>');
1988}
1989/**
1990 * Returns all segments of the given dot-separated qualified name.
1991 * Returns an array with only the given name if it is not qualified.
1992 * Returns an empty array if the name is empty.
1993 * <p>
1994 * For example:
1995 * <pre>
1996 * <code>
1997 * 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'}}
1998 * getSimpleNames({'O', 'b', 'j', 'e', 'c', 't'}) -> {{'O', 'b', 'j', 'e', 'c', 't'}}
1999 * getSimpleNames({}) -> {}
2000 * getSimpleNames({'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l', '.', 'L', 'i', 's', 't', '<', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', '>'}) -> {{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'L', 'i', 's', 't', '<', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g'}}
2001 * </code>
2002 * </pre>
2003 *
2004 * @param name the name
2005 * @return the list of simple names, possibly empty
2006 * @exception NullPointerException if name is null
2007 * @since 2.0
2008 */

2009public static char[][] getSimpleNames(char[] name) {
2010    int length = name == null ? 0 : name.length;
2011    if (length == 0)
2012        return CharOperation.NO_CHAR_CHAR;
2013    
2014    int wordCount = 1;
2015    countingWords: for (int i = 0; i < length; i++)
2016        switch(name[i]) {
2017            case C_DOT:
2018                wordCount++;
2019                break;
2020            case C_GENERIC_START:
2021                break countingWords;
2022        }
2023    char[][] split = new char[wordCount][];
2024    int last = 0, currentWord = 0;
2025    for (int i = 0; i < length; i++) {
2026        if (name[i] == C_GENERIC_START) break;
2027        if (name[i] == C_DOT) {
2028            split[currentWord] = new char[i - last];
2029            System.arraycopy(
2030                name,
2031                last,
2032                split[currentWord++],
2033                0,
2034                i - last);
2035            last = i + 1;
2036        }
2037    }
2038    split[currentWord] = new char[length - last];
2039    System.arraycopy(name, last, split[currentWord], 0, length - last);
2040    return split;
2041}
2042/**
2043 * Returns all segments of the given dot-separated qualified name.
2044 * Returns an array with only the given name if it is not qualified.
2045 * Returns an empty array if the name is empty.
2046 * <p>
2047 * For example:
2048 * <pre>
2049 * <code>
2050 * getSimpleNames("java.lang.Object") -&gt; {"java", "lang", "Object"}
2051 * getSimpleNames("Object") -&gt; {"Object"}
2052 * getSimpleNames("") -&gt; {}
2053 * getSimpleNames("java.util.List&lt;java.lang.String&gt;") -&gt;
2054 * {"java", "util", "List&lt;java.lang.String&gt;"}
2055 * </code>
2056 * </pre>
2057 *
2058 * @param name the name
2059 * @return the list of simple names, possibly empty
2060 * @exception NullPointerException if name is null
2061 */

2062public static String JavaDoc[] getSimpleNames(String JavaDoc name) {
2063    return CharOperation.toStrings(getSimpleNames(name.toCharArray()));
2064}
2065
2066/**
2067 * Removes any capture information from the given type or method signature
2068 * and returns the resulting signature.
2069 * Returns the type or method signature itself if no capture information is
2070 * present.
2071 * <p>
2072 * For example (using equivalent string-based method):
2073 * <pre>
2074 * <code>
2075 * removeCapture("LTest&lt;!+Ljava.lang.Throwable;&gt;;")
2076 * will return: "LTest&lt;+Ljava.lang.Throwable;&gt;;"
2077 * </code>
2078 * </pre>
2079 * </p>
2080 *
2081 * @param methodOrTypeSignature the signature which may have been captured
2082 * @return a new signature without capture information or the signature itself
2083 * if no specific capture information is present
2084 * @exception NullPointerException if <code>methodOrTypeSignature</code> is null
2085 *
2086 * @since 3.1
2087 */

2088public static char[] removeCapture(char[] methodOrTypeSignature) {
2089    return CharOperation.remove(methodOrTypeSignature, C_CAPTURE);
2090}
2091    
2092/**
2093 * Removes any capture information from the given type or method signature
2094 * and returns the resulting signature.
2095 * Returns the type or method signature itself if no capture information is
2096 * present.
2097 * <p>
2098 * For example:
2099 * <pre>
2100 * <code>
2101 * removeCapture("LTest&lt;!+Ljava.lang.Throwable;&gt;;")
2102 * will return: "LTest&lt;+Ljava.lang.Throwable;&gt;;"
2103 * </code>
2104 * </pre>
2105 * </p>
2106 *
2107 * @param methodOrTypeSignature the signature which may have been captured
2108 * @return a new signature without capture information or the signature itself
2109 * if no specific capture information is present
2110 * @exception NullPointerException if <code>methodOrTypeSignature</code> is null
2111 *
2112 * @since 3.1
2113 */

2114public static String JavaDoc removeCapture(String JavaDoc methodOrTypeSignature) {
2115    char[] array = methodOrTypeSignature.toCharArray();
2116    char[] result = removeCapture(array);
2117    if (array == result) return methodOrTypeSignature;
2118    return new String JavaDoc(result);
2119}
2120
2121/**
2122 * Converts the given method signature to a readable form. The method signature is expected to
2123 * be dot-based.
2124 * <p>
2125 * For example:
2126 * <pre>
2127 * <code>
2128 * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
2129 * </code>
2130 * </pre>
2131 * </p>
2132 *
2133 * @param methodSignature the method signature to convert
2134 * @param methodName the name of the method to insert in the result, or
2135 * <code>null</code> if no method name is to be included
2136 * @param parameterNames the parameter names to insert in the result, or
2137 * <code>null</code> if no parameter names are to be included; if supplied,
2138 * the number of parameter names must match that of the method signature
2139 * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
2140 * qualified, and <code>false</code> to use only simple names
2141 * @param includeReturnType <code>true</code> if the return type is to be
2142 * included
2143 * @return the char array representation of the method signature
2144 *
2145 * @since 2.0
2146 */

2147public static char[] toCharArray(char[] methodSignature, char[] methodName, char[][] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) {
2148    return toCharArray(methodSignature, methodName, parameterNames, fullyQualifyTypeNames, includeReturnType, false);
2149}
2150/**
2151 * Converts the given method signature to a readable form. The method signature is expected to
2152 * be dot-based.
2153 * <p>
2154 * For example:
2155 * <pre>
2156 * <code>
2157 * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
2158 * </code>
2159 * </pre>
2160 * </p>
2161 *
2162 * @param methodSignature the method signature to convert
2163 * @param methodName the name of the method to insert in the result, or
2164 * <code>null</code> if no method name is to be included
2165 * @param parameterNames the parameter names to insert in the result, or
2166 * <code>null</code> if no parameter names are to be included; if supplied,
2167 * the number of parameter names must match that of the method signature
2168 * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
2169 * qualified, and <code>false</code> to use only simple names
2170 * @param includeReturnType <code>true</code> if the return type is to be
2171 * included
2172 * @param isVargArgs <code>true</code> if the last argument should be displayed as a
2173 * variable argument, <code>false</code> otherwise.
2174 * @return the char array representation of the method signature
2175 *
2176 * @since 3.1
2177 */

2178public static char[] toCharArray(char[] methodSignature, char[] methodName, char[][] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType, boolean isVargArgs) {
2179    int firstParen = CharOperation.indexOf(C_PARAM_START, methodSignature);
2180    if (firstParen == -1) {
2181        throw new IllegalArgumentException JavaDoc();
2182    }
2183    
2184    StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(methodSignature.length + 10);
2185    
2186    // return type
2187
if (includeReturnType) {
2188        char[] rts = getReturnType(methodSignature);
2189        appendTypeSignature(rts, 0 , fullyQualifyTypeNames, buffer);
2190        buffer.append(' ');
2191    }
2192    
2193    // selector
2194
if (methodName != null) {
2195        buffer.append(methodName);
2196    }
2197    
2198    // parameters
2199
buffer.append('(');
2200    char[][] pts = getParameterTypes(methodSignature);
2201    for (int i = 0, max = pts.length; i < max; i++) {
2202        if (i == max - 1) {
2203            appendTypeSignature(pts[i], 0 , fullyQualifyTypeNames, buffer, isVargArgs);
2204        } else {
2205            appendTypeSignature(pts[i], 0 , fullyQualifyTypeNames, buffer);
2206        }
2207        if (parameterNames != null) {
2208            buffer.append(' ');
2209            buffer.append(parameterNames[i]);
2210        }
2211        if (i != pts.length - 1) {
2212            buffer.append(',');
2213            buffer.append(' ');
2214        }
2215    }
2216    buffer.append(')');
2217    char[] result = new char[buffer.length()];
2218    buffer.getChars(0, buffer.length(), result, 0);
2219    return result;
2220}
2221/**
2222 * Converts the given type signature to a readable string. The signature is expected to
2223 * be dot-based.
2224 *
2225 * <p>
2226 * For example:
2227 * <pre>
2228 * <code>
2229 * 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', '[', ']'}
2230 * toString({'I'}) -> {'i', 'n', 't'}
2231 * toString({'+', 'L', 'O', 'b', 'j', 'e', 'c', 't', ';'}) -> {'?', ' ', 'e', 'x', 't', 'e', 'n', 'd', 's', ' ', 'O', 'b', 'j', 'e', 'c', 't'}
2232 * </code>
2233 * </pre>
2234 * </p>
2235 * <p>
2236 * Note: This method assumes that a type signature containing a <code>'$'</code>
2237 * is an inner type signature. While this is correct in most cases, someone could
2238 * define a non-inner type name containing a <code>'$'</code>. Handling this
2239 * correctly in all cases would have required resolving the signature, which
2240 * generally not feasible.
2241 * </p>
2242 *
2243 * @param signature the type signature
2244 * @return the string representation of the type
2245 * @exception IllegalArgumentException if the signature is not syntactically
2246 * correct
2247 *
2248 * @since 2.0
2249 */

2250public static char[] toCharArray(char[] signature) throws IllegalArgumentException JavaDoc {
2251        int sigLength = signature.length;
2252        if (sigLength == 0 || signature[0] == C_PARAM_START || signature[0] == C_GENERIC_START) {
2253            return toCharArray(signature, CharOperation.NO_CHAR, null, true, true);
2254        }
2255        
2256        StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(signature.length + 10);
2257        appendTypeSignature(signature, 0, true, buffer);
2258        char[] result = new char[buffer.length()];
2259        buffer.getChars(0, buffer.length(), result, 0);
2260        return result;
2261}
2262
2263/**
2264 * Scans the given string for a type signature starting at the given
2265 * index and appends it to the given buffer, and returns the index of the last
2266 * character.
2267 *
2268 * @param string the signature string
2269 * @param start the 0-based character index of the first character
2270 * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
2271 * qualified, and <code>false</code> to use only simple names
2272 * @param buffer the string buffer to append to
2273 * @return the 0-based character index of the last character
2274 * @exception IllegalArgumentException if this is not a type signature
2275 * @see Util#scanTypeSignature(char[], int)
2276 */

2277private static int appendTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer JavaDoc buffer) {
2278    return appendTypeSignature(string, start, fullyQualifyTypeNames, buffer, false);
2279}
2280/**
2281 * Scans the given string for a type signature starting at the given
2282 * index and appends it to the given buffer, and returns the index of the last
2283 * character.
2284 *
2285 * @param string the signature string
2286 * @param start the 0-based character index of the first character
2287 * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
2288 * qualified, and <code>false</code> to use only simple names
2289 * @param buffer the string buffer to append to
2290 * @param isVarArgs <code>true</code> if the type must be displayed as a
2291 * variable argument, <code>false</code> otherwise. In this case, the type must be an array type
2292 * @return the 0-based character index of the last character
2293 * @exception IllegalArgumentException if this is not a type signature, or if isVarArgs is <code>true</code>,
2294 * and the type is not an array type signature.
2295 * @see Util#scanTypeSignature(char[], int)
2296 */

2297private static int appendTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer JavaDoc buffer, boolean isVarArgs) {
2298    // need a minimum 1 char
2299
if (start >= string.length) {
2300        throw new IllegalArgumentException JavaDoc();
2301    }
2302    char c = string[start];
2303    if (isVarArgs) {
2304        switch (c) {
2305            case C_ARRAY :
2306                return appendArrayTypeSignature(string, start, fullyQualifyTypeNames, buffer, true);
2307            case C_RESOLVED :
2308            case C_UNRESOLVED :
2309            case C_TYPE_VARIABLE :
2310            case C_BOOLEAN :
2311            case C_BYTE :
2312            case C_CHAR :
2313            case C_DOUBLE :
2314            case C_FLOAT :
2315            case C_INT :
2316            case C_LONG :
2317            case C_SHORT :
2318            case C_VOID :
2319            case C_STAR:
2320            case C_EXTENDS:
2321            case C_SUPER:
2322            case C_CAPTURE:
2323            default:
2324                throw new IllegalArgumentException JavaDoc(); // a var args is an array type
2325
}
2326    } else {
2327        switch (c) {
2328            case C_ARRAY :
2329                return appendArrayTypeSignature(string, start, fullyQualifyTypeNames, buffer);
2330            case C_RESOLVED :
2331            case C_UNRESOLVED :
2332                return appendClassTypeSignature(string, start, fullyQualifyTypeNames, buffer);
2333            case C_TYPE_VARIABLE :
2334                int e = Util.scanTypeVariableSignature(string, start);
2335                buffer.append(string, start + 1, e - start - 1);
2336                return e;
2337            case C_BOOLEAN :
2338                buffer.append(BOOLEAN);
2339                return start;
2340            case C_BYTE :
2341                buffer.append(BYTE);
2342                return start;
2343            case C_CHAR :
2344                buffer.append(CHAR);
2345                return start;
2346            case C_DOUBLE :
2347                buffer.append(DOUBLE);
2348                return start;
2349            case C_FLOAT :
2350                buffer.append(FLOAT);
2351                return start;
2352            case C_INT :
2353                buffer.append(INT);
2354                return start;
2355            case C_LONG :
2356                buffer.append(LONG);
2357                return start;
2358            case C_SHORT :
2359                buffer.append(SHORT);
2360                return start;
2361            case C_VOID :
2362                buffer.append(VOID);
2363                return start;
2364            case C_CAPTURE :
2365                return appendCaptureTypeSignature(string, start, fullyQualifyTypeNames, buffer);
2366            case C_STAR:
2367            case C_EXTENDS:
2368            case C_SUPER:
2369                return appendTypeArgumentSignature(string, start, fullyQualifyTypeNames, buffer);
2370            default :
2371                throw new IllegalArgumentException JavaDoc();
2372        }
2373    }
2374}
2375/**
2376 * Scans the given string for an array type signature starting at the given
2377 * index and appends it to the given buffer, and returns the index of the last
2378 * character.
2379 *
2380 * @param string the signature string
2381 * @param start the 0-based character index of the first character
2382 * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
2383 * qualified, and <code>false</code> to use only simple names
2384 * @return the 0-based character index of the last character
2385 * @exception IllegalArgumentException if this is not an array type signature
2386 * @see Util#scanArrayTypeSignature(char[], int)
2387 */

2388private static int appendArrayTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer JavaDoc buffer) {
2389    return appendArrayTypeSignature(string, start, fullyQualifyTypeNames, buffer, false);
2390}
2391/**
2392 * Scans the given string for an array type signature starting at the given
2393 * index and appends it to the given buffer, and returns the index of the last
2394 * character.
2395 *
2396 * @param string the signature string
2397 * @param start the 0-based character index of the first character
2398 * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
2399 * qualified, and <code>false</code> to use only simple names
2400 * @return the 0-based character index of the last character
2401 * @exception IllegalArgumentException if this is not an array type signature
2402 * @see Util#scanArrayTypeSignature(char[], int)
2403 */

2404private static int appendCaptureTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer JavaDoc buffer) {
2405    // need a minimum 2 char
2406
if (start >= string.length - 1) {
2407        throw new IllegalArgumentException JavaDoc();
2408    }
2409    char c = string[start];
2410    if (c != C_CAPTURE) {
2411        throw new IllegalArgumentException JavaDoc();
2412    }
2413    buffer.append(CAPTURE).append(' ');
2414    return appendTypeArgumentSignature(string, start + 1, fullyQualifyTypeNames, buffer);
2415}
2416
2417/**
2418 * Scans the given string for an array type signature starting at the given
2419 * index and appends it to the given buffer, and returns the index of the last
2420 * character.
2421 *
2422 * @param string the signature string
2423 * @param start the 0-based character index of the first character
2424 * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
2425 * qualified, and <code>false</code> to use only simple names
2426 * @param isVarArgs <code>true</code> if the array type must be displayed as a
2427 * variable argument, <code>false</code> otherwise
2428 * @return the 0-based character index of the last character
2429 * @exception IllegalArgumentException if this is not an array type signature
2430 * @see Util#scanArrayTypeSignature(char[], int)
2431 */

2432private static int appendArrayTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer JavaDoc buffer, boolean isVarArgs) {
2433    int length = string.length;
2434    // need a minimum 2 char
2435
if (start >= length - 1) {
2436        throw new IllegalArgumentException JavaDoc();
2437    }
2438    char c = string[start];
2439    if (c != C_ARRAY) {
2440        throw new IllegalArgumentException JavaDoc();
2441    }
2442    
2443    int index = start;
2444    c = string[++index];
2445    while(c == C_ARRAY) {
2446        // need a minimum 2 char
2447
if (index >= length - 1) {
2448            throw new IllegalArgumentException JavaDoc();
2449        }
2450        c = string[++index];
2451    }
2452    
2453    int e = appendTypeSignature(string, index, fullyQualifyTypeNames, buffer);
2454    
2455    for(int i = 1, dims = index - start; i < dims; i++) {
2456        buffer.append('[').append(']');
2457    }
2458    
2459    if (isVarArgs) {
2460        buffer.append('.').append('.').append('.');
2461    } else {
2462        buffer.append('[').append(']');
2463    }
2464    return e;
2465}
2466/**
2467 * Scans the given string for a class type signature starting at the given
2468 * index and appends it to the given buffer, and returns the index of the last
2469 * character.
2470 *
2471 * @param string the signature string
2472 * @param start the 0-based character index of the first character
2473 * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
2474 * qualified, and <code>false</code> to use only simple names
2475 * @param buffer the string buffer to append to
2476 * @return the 0-based character index of the last character
2477 * @exception IllegalArgumentException if this is not a class type signature
2478 * @see Util#scanClassTypeSignature(char[], int)
2479 */

2480private static int appendClassTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer JavaDoc buffer) {
2481    // need a minimum 3 chars "Lx;"
2482
if (start >= string.length - 2) {
2483        throw new IllegalArgumentException JavaDoc();
2484    }
2485    // must start in "L" or "Q"
2486
char c = string[start];
2487    if (c != C_RESOLVED && c != C_UNRESOLVED) {
2488        throw new IllegalArgumentException JavaDoc();
2489    }
2490    boolean resolved = (c == C_RESOLVED);
2491    boolean removePackageQualifiers = !fullyQualifyTypeNames;
2492    if (!resolved) {
2493        // keep everything in an unresolved name
2494
removePackageQualifiers = false;
2495    }
2496    int p = start + 1;
2497    int checkpoint = buffer.length();
2498    int innerTypeStart = -1;
2499    boolean inAnonymousType = false;
2500    while (true) {
2501        if (p >= string.length) {
2502            throw new IllegalArgumentException JavaDoc();
2503        }
2504        c = string[p];
2505        switch(c) {
2506            case C_SEMICOLON :
2507                // all done
2508
return p;
2509            case C_GENERIC_START :
2510                int e = appendTypeArgumentSignatures(string, p, fullyQualifyTypeNames, buffer);
2511                // once we hit type arguments there are no more package prefixes
2512
removePackageQualifiers = false;
2513                p = e;
2514                break;
2515            case C_DOT :
2516                if (removePackageQualifiers) {
2517                    // erase package prefix
2518
buffer.setLength(checkpoint);
2519                } else {
2520                    buffer.append('.');
2521                }
2522                break;
2523             case '/' :
2524                if (removePackageQualifiers) {
2525                    // erase package prefix
2526
buffer.setLength(checkpoint);
2527                } else {
2528                    buffer.append('/');
2529                }
2530                break;
2531             case C_DOLLAR :
2532                innerTypeStart = buffer.length();
2533                inAnonymousType = false;
2534                if (resolved) {
2535                    // once we hit "$" there are no more package prefixes
2536
removePackageQualifiers = false;
2537                    /**
2538                     * Convert '$' in resolved type signatures into '.'.
2539                     * NOTE: This assumes that the type signature is an inner type
2540                     * signature. This is true in most cases, but someone can define a
2541                     * non-inner type name containing a '$'.
2542                     */

2543                    buffer.append('.');
2544                }
2545                break;
2546             default :
2547                if (innerTypeStart != -1 && !inAnonymousType && Character.isDigit(c)) {
2548                    inAnonymousType = true;
2549                    buffer.setLength(innerTypeStart); // remove '.'
2550
buffer.insert(checkpoint, "new "); //$NON-NLS-1$
2551
buffer.append("(){}"); //$NON-NLS-1$
2552
}
2553                if (!inAnonymousType)
2554                    buffer.append(c);
2555                innerTypeStart = -1;
2556        }
2557        p++;
2558    }
2559}
2560
2561/**
2562 * Scans the given string for a list of type arguments signature starting at the
2563 * given index and appends it to the given buffer, and returns the index of the
2564 * last character.
2565 *
2566 * @param string the signature string
2567 * @param start the 0-based character index of the first character
2568 * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
2569 * qualified, and <code>false</code> to use only simple names
2570 * @param buffer the string buffer to append to
2571 * @return the 0-based character index of the last character
2572 * @exception IllegalArgumentException if this is not a list of type argument
2573 * signatures
2574 * @see Util#scanTypeArgumentSignatures(char[], int)
2575 */

2576private static int appendTypeArgumentSignatures(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer JavaDoc buffer) {
2577    // need a minimum 2 char "<>"
2578
if (start >= string.length - 1) {
2579        throw new IllegalArgumentException JavaDoc();
2580    }
2581    char c = string[start];
2582    if (c != C_GENERIC_START) {
2583        throw new IllegalArgumentException JavaDoc();
2584    }
2585    buffer.append('<');
2586    int p = start + 1;
2587    int count = 0;
2588    while (true) {
2589        if (p >= string.length) {
2590            throw new IllegalArgumentException JavaDoc();
2591        }
2592        c = string[p];
2593        if (c == C_GENERIC_END) {
2594            buffer.append('>');
2595            return p;
2596        }
2597        if (count != 0) {
2598            buffer.append(',');
2599        }
2600        int e = appendTypeArgumentSignature(string, p, fullyQualifyTypeNames, buffer);
2601        count++;
2602        p = e + 1;
2603    }
2604}
2605
2606/**
2607 * Scans the given string for a type argument signature starting at the given
2608 * index and appends it to the given buffer, and returns the index of the last
2609 * character.
2610 *
2611 * @param string the signature string
2612 * @param start the 0-based character index of the first character
2613 * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
2614 * qualified, and <code>false</code> to use only simple names
2615 * @param buffer the string buffer to append to
2616 * @return the 0-based character index of the last character
2617 * @exception IllegalArgumentException if this is not a type argument signature
2618 * @see Util#scanTypeArgumentSignature(char[], int)
2619 */

2620private static int appendTypeArgumentSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer JavaDoc buffer) {
2621    // need a minimum 1 char
2622
if (start >= string.length) {
2623        throw new IllegalArgumentException JavaDoc();
2624    }
2625    char c = string[start];
2626    switch(c) {
2627        case C_STAR :
2628            buffer.append('?');
2629            return start;
2630        case C_EXTENDS :
2631            buffer.append("? extends "); //$NON-NLS-1$
2632
return appendTypeSignature(string, start + 1, fullyQualifyTypeNames, buffer);
2633        case C_SUPER :
2634            buffer.append("? super "); //$NON-NLS-1$
2635
return appendTypeSignature(string, start + 1, fullyQualifyTypeNames, buffer);
2636        default :
2637            return appendTypeSignature(string, start, fullyQualifyTypeNames, buffer);
2638    }
2639}
2640
2641/**
2642 * Converts the given array of qualified name segments to a qualified name.
2643 * <p>
2644 * For example:
2645 * <pre>
2646 * <code>
2647 * 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'}
2648 * toQualifiedName({{'O', 'b', 'j', 'e', 'c', 't'}}) -> {'O', 'b', 'j', 'e', 'c', 't'}
2649 * toQualifiedName({{}}) -> {}
2650 * </code>
2651 * </pre>
2652 * </p>
2653 *
2654 * @param segments the list of name segments, possibly empty
2655 * @return the dot-separated qualified name, or the empty string
2656 *
2657 * @since 2.0
2658 */

2659public static char[] toQualifiedName(char[][] segments) {
2660    int length = segments.length;
2661    if (length == 0) return CharOperation.NO_CHAR;
2662    if (length == 1) return segments[0];
2663    
2664    int resultLength = 0;
2665    for (int i = 0; i < length; i++) {
2666        resultLength += segments[i].length+1;
2667    }
2668    resultLength--;
2669    char[] result = new char[resultLength];
2670    int index = 0;
2671    for (int i = 0; i < length; i++) {
2672        char[] segment = segments[i];
2673        int segmentLength = segment.length;
2674        System.arraycopy(segment, 0, result, index, segmentLength);
2675        index += segmentLength;
2676        if (i != length-1) {
2677            result[index++] = C_DOT;
2678        }
2679    }
2680    return result;
2681}
2682/**
2683 * Converts the given array of qualified name segments to a qualified name.
2684 * <p>
2685 * For example:
2686 * <pre>
2687 * <code>
2688 * toQualifiedName(new String[] {"java", "lang", "Object"}) -> "java.lang.Object"
2689 * toQualifiedName(new String[] {"Object"}) -> "Object"
2690 * toQualifiedName(new String[0]) -> ""
2691 * </code>
2692 * </pre>
2693 * </p>
2694 *
2695 * @param segments the list of name segments, possibly empty
2696 * @return the dot-separated qualified name, or the empty string
2697 */

2698public static String JavaDoc toQualifiedName(String JavaDoc[] segments) {
2699    int length = segments.length;
2700    char[][] charArrays = new char[length][];
2701    for (int i = 0; i < length; i++) {
2702        charArrays[i] = segments[i].toCharArray();
2703    }
2704    return new String JavaDoc(toQualifiedName(charArrays));
2705}
2706/**
2707 * Converts the given type signature to a readable string. The signature is expected to
2708 * be dot-based.
2709 *
2710 * <p>
2711 * For example:
2712 * <pre>
2713 * <code>
2714 * toString("[Ljava.lang.String;") -> "java.lang.String[]"
2715 * toString("I") -> "int"
2716 * toString("+QObject;") -> "? extends Object"
2717 * </code>
2718 * </pre>
2719 * </p>
2720 * <p>
2721 * Note: This method assumes that a type signature containing a <code>'$'</code>
2722 * is an inner type signature. While this is correct in most cases, someone could
2723 * define a non-inner type name containing a <code>'$'</code>. Handling this
2724 * correctly in all cases would have required resolving the signature, which
2725 * generally not feasible.
2726 * </p>
2727 *
2728 * @param signature the type signature
2729 * @return the string representation of the type
2730 * @exception IllegalArgumentException if the signature is not syntactically
2731 * correct
2732 */

2733public static String JavaDoc toString(String JavaDoc signature) throws IllegalArgumentException JavaDoc {
2734    return new String JavaDoc(toCharArray(signature.toCharArray()));
2735}
2736/**
2737 * Converts the given method signature to a readable string. The method signature is expected to
2738 * be dot-based.
2739 *
2740 * @param methodSignature the method signature to convert
2741 * @param methodName the name of the method to insert in the result, or
2742 * <code>null</code> if no method name is to be included
2743 * @param parameterNames the parameter names to insert in the result, or
2744 * <code>null</code> if no parameter names are to be included; if supplied,
2745 * the number of parameter names must match that of the method signature
2746 * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
2747 * qualified, and <code>false</code> to use only simple names
2748 * @param includeReturnType <code>true</code> if the return type is to be
2749 * included
2750 * @see #toCharArray(char[], char[], char[][], boolean, boolean)
2751 * @return the string representation of the method signature
2752 */

2753public static String JavaDoc toString(String JavaDoc methodSignature, String JavaDoc methodName, String JavaDoc[] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) {
2754    return toString(methodSignature, methodName, parameterNames, fullyQualifyTypeNames, includeReturnType, false);
2755}
2756/**
2757 * Converts the given method signature to a readable string. The method signature is expected to
2758 * be dot-based.
2759 *
2760 * @param methodSignature the method signature to convert
2761 * @param methodName the name of the method to insert in the result, or
2762 * <code>null</code> if no method name is to be included
2763 * @param parameterNames the parameter names to insert in the result, or
2764 * <code>null</code> if no parameter names are to be included; if supplied,
2765 * the number of parameter names must match that of the method signature
2766 * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
2767 * qualified, and <code>false</code> to use only simple names
2768 * @param includeReturnType <code>true</code> if the return type is to be
2769 * included
2770 * @param isVarArgs <code>true</code> if the last argument should be displayed as a
2771 * variable argument, <code>false</code> otherwise
2772 * @see #toCharArray(char[], char[], char[][], boolean, boolean)
2773 * @return the string representation of the method signature
2774 *
2775 * @since 3.1
2776 */

2777public static String JavaDoc toString(String JavaDoc methodSignature, String JavaDoc methodName, String JavaDoc[] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType, boolean isVarArgs) {
2778    char[][] params;
2779    if (parameterNames == null) {
2780        params = null;
2781    } else {
2782        int paramLength = parameterNames.length;
2783        params = new char[paramLength][];
2784        for (int i = 0; i < paramLength; i++) {
2785            params[i] = parameterNames[i].toCharArray();
2786        }
2787    }
2788    return new String JavaDoc(toCharArray(methodSignature.toCharArray(), methodName == null ? null : methodName.toCharArray(), params, fullyQualifyTypeNames, includeReturnType, isVarArgs));
2789}
2790}
2791
Popular Tags