| 1 12 package org.eclipse.jdt.core; 13 14 import java.util.ArrayList ; 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 143 public final class Signature { 144 145 149 public static final char C_BOOLEAN = 'Z'; 150 151 155 public static final char C_BYTE = 'B'; 156 157 161 public static final char C_CHAR = 'C'; 162 163 167 public static final char C_DOUBLE = 'D'; 168 169 173 public static final char C_FLOAT = 'F'; 174 175 179 public static final char C_INT = 'I'; 180 181 185 public static final char C_SEMICOLON = ';'; 186 187 192 public static final char C_COLON = ':'; 193 194 198 public static final char C_LONG = 'J'; 199 200 204 public static final char C_SHORT = 'S'; 205 206 210 public static final char C_VOID = 'V'; 211 212 217 public static final char C_TYPE_VARIABLE = 'T'; 218 219 225 public static final char C_STAR = '*'; 226 227 232 public static final char C_EXCEPTION_START = '^'; 233 234 240 public static final char C_EXTENDS = '+'; 241 242 248 public static final char C_SUPER = '-'; 249 250 254 public static final char C_DOT = '.'; 255 256 260 public static final char C_DOLLAR = '$'; 261 262 266 public static final char C_ARRAY = '['; 267 268 272 public static final char C_RESOLVED = 'L'; 273 274 278 public static final char C_UNRESOLVED = 'Q'; 279 280 284 public static final char C_NAME_END = ';'; 285 286 290 public static final char C_PARAM_START = '('; 291 292 296 public static final char C_PARAM_END = ')'; 297 298 303 public static final char C_GENERIC_START = '<'; 304 305 310 public static final char C_GENERIC_END = '>'; 311 312 317 public static final char C_CAPTURE = '!'; 318 319 323 public static final String SIG_BOOLEAN = "Z"; 325 329 public static final String SIG_BYTE = "B"; 331 335 public static final String SIG_CHAR = "C"; 337 341 public static final String SIG_DOUBLE = "D"; 343 347 public static final String SIG_FLOAT = "F"; 349 353 public static final String SIG_INT = "I"; 355 359 public static final String SIG_LONG = "J"; 361 365 public static final String SIG_SHORT = "S"; 367 370 public static final String SIG_VOID = "V"; 372 373 378 public static final int CLASS_TYPE_SIGNATURE = 1; 379 380 385 public static final int BASE_TYPE_SIGNATURE = 2; 386 387 392 public static final int TYPE_VARIABLE_SIGNATURE = 3; 393 394 399 public static final int ARRAY_TYPE_SIGNATURE = 4; 400 401 406 public static final int WILDCARD_TYPE_SIGNATURE = 5; 407 408 413 public static final int CAPTURE_TYPE_SIGNATURE = 6; 414 415 private static final char[] BOOLEAN = "boolean".toCharArray(); private static final char[] BYTE = "byte".toCharArray(); private static final char[] CHAR = "char".toCharArray(); private static final char[] DOUBLE = "double".toCharArray(); private static final char[] FLOAT = "float".toCharArray(); private static final char[] INT = "int".toCharArray(); private static final char[] LONG = "long".toCharArray(); private static final char[] SHORT = "short".toCharArray(); private static final char[] VOID = "void".toCharArray(); private static final char[] EXTENDS = "extends".toCharArray(); private static final char[] SUPER = "super".toCharArray(); private static final char[] CAPTURE = "capture-of".toCharArray(); 428 private Signature() { 429 } 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 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 482 public static String createArraySignature(String typeSignature, int arrayCount) { 483 return new String (createArraySignature(typeSignature.toCharArray(), arrayCount)); 484 } 485 486 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 529 public static String createMethodSignature(String [] parameterTypes, String 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 (createMethodSignature(parameters, returnType.toCharArray())); 536 } 537 538 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); } 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 578 public static String createTypeParameterSignature(String typeParameterName, String [] 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 (createTypeParameterSignature(typeParameterName.toCharArray(), boundSignatureChars)); 585 } 586 587 603 public static String createTypeSignature(char[] typeName, boolean isResolved) { 604 return new String (createCharArrayTypeSignature(typeName, isResolved)); 605 } 606 607 625 public static char[] createCharArrayTypeSignature(char[] typeName, boolean isResolved) { 626 if (typeName == null) throw new IllegalArgumentException ("null"); int length = typeName.length; 628 if (length == 0) throw new IllegalArgumentException (new String (typeName)); 629 StringBuffer buffer = new StringBuffer (5); 630 int pos = encodeTypeSignature(typeName, 0, isResolved, length, buffer); 631 pos = consumeWhitespace(typeName, pos, length); 632 if (pos < length) throw new IllegalArgumentException (new String (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 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) { pos = consumeWhitespace(typeName, pos, length) - 1; break; 668 } 669 int checkPos = checkNextChar(typeName, '.', pos, length, true); 671 if (checkPos > 0) { 672 buffer.append(C_DOT); 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 (new String (typeName)); 688 return pos; 689 } 690 691 private static int encodeArrayDimension(char[] typeName, int pos, int length, StringBuffer 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 (new String (typeName)); 727 return -1; 728 } 729 730 private static int encodeTypeSignature(char[] typeName, int start, boolean isResolved, int length, StringBuffer buffer) { 731 int pos = start; 732 pos = consumeWhitespace(typeName, pos, length); 733 if (pos >= length) throw new IllegalArgumentException (new String (typeName)); 734 int checkPos; 735 char currentChar = typeName[pos]; 736 switch (currentChar) { 737 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 case '?': 820 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 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) { 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; return pos; 869 } 870 871 895 public static String createTypeSignature(String typeName, boolean isResolved) { 896 return createTypeSignature(typeName == null ? null : typeName.toCharArray(), isResolved); 897 } 898 899 909 public static int getArrayCount(char[] typeSignature) throws IllegalArgumentException { 910 try { 911 int count = 0; 912 while (typeSignature[count] == C_ARRAY) { 913 ++count; 914 } 915 return count; 916 } catch (ArrayIndexOutOfBoundsException e) {
|