1 19 package org.netbeans.modules.java.source.usages; 20 21 import com.sun.tools.javac.code.Attribute; 22 import com.sun.tools.javac.code.Attribute.Compound; 23 import com.sun.tools.javac.code.BoundKind; 24 import com.sun.tools.javac.code.Flags; 25 import static com.sun.tools.javac.code.Flags.*; 26 import static com.sun.tools.javac.code.Kinds.*; 27 import com.sun.tools.javac.code.Scope; 28 import com.sun.tools.javac.code.Source; 29 import com.sun.tools.javac.code.Symbol; 30 import com.sun.tools.javac.code.Symbol.ClassSymbol; 31 import com.sun.tools.javac.code.Symbol.CompletionFailure; 32 import com.sun.tools.javac.code.Symbol.MethodSymbol; 33 import com.sun.tools.javac.code.Symbol.PackageSymbol; 34 import com.sun.tools.javac.code.Symbol.VarSymbol; 35 import com.sun.tools.javac.code.Symtab; 36 import com.sun.tools.javac.code.Type; 37 import com.sun.tools.javac.code.Type.ArrayType; 38 import com.sun.tools.javac.code.Type.ClassType; 39 import com.sun.tools.javac.code.Type.ErrorType; 40 import com.sun.tools.javac.code.Type.ForAll; 41 import com.sun.tools.javac.code.Type.MethodType; 42 import com.sun.tools.javac.code.Type.TypeVar; 43 import com.sun.tools.javac.code.Type.WildcardType; 44 import com.sun.tools.javac.code.Types; 45 import static com.sun.tools.javac.code.TypeTags.*; 46 import com.sun.tools.javac.jvm.ClassReader; 47 import com.sun.tools.javac.model.JavacTypes; 48 import com.sun.tools.javac.util.Context; 49 import com.sun.tools.javac.util.List; 50 import com.sun.tools.javac.util.ListBuffer; 51 import com.sun.tools.javac.util.Log; 52 import com.sun.tools.javac.util.Name; 53 import com.sun.tools.javac.util.Name.Table; 54 import com.sun.tools.javac.util.Pair; 55 import com.sun.tools.javadoc.JavadocClassReader; 56 57 import java.io.BufferedReader ; 58 import java.io.IOException ; 59 import java.io.InputStreamReader ; 60 import java.io.Reader ; 61 import java.util.ArrayList ; 62 63 import javax.lang.model.element.ElementKind; 64 import javax.lang.model.element.TypeElement; 65 import javax.lang.model.type.TypeMirror; 66 import javax.tools.JavaFileObject; 67 68 import org.netbeans.modules.java.source.parsing.FileObjects; 69 import org.openide.ErrorManager; 70 71 75 public class SymbolClassReader extends JavadocClassReader { 76 77 public static void preRegister(final Context context, final boolean loadDocEnv) { 78 context.put(classReaderKey, new Context.Factory<ClassReader>() { 79 public ClassReader make() { 80 return new SymbolClassReader(context, loadDocEnv); 81 } 82 }); 83 } 84 85 private Symtab syms; 86 private Table table; 87 private Types types; 88 private JavacTypes jTypes; 89 private Log logger; 90 private Source source; 91 92 private char[] buffer; 93 private int currentBufferIndex; 94 95 private boolean readingClassSignature = false; 96 private boolean readingEnclMethod = false; 97 private List<Type> missingTypeVariables = List.nil(); 98 private List<Type> foundTypeVariables = List.nil(); 99 100 protected SymbolClassReader(Context context, boolean loadDocEnv) { 101 super(context, loadDocEnv); 102 syms = Symtab.instance(context); 103 table = Table.instance(context); 104 types = Types.instance(context); 105 jTypes = JavacTypes.instance(context); 106 logger = Log.instance(context); 107 source = Source.instance(context); 108 109 buffer = new char[127]; 110 } 111 112 private void addCharToBuffer(char c) { 113 if (currentBufferIndex >= buffer.length) { 114 char[] newBuffer = new char[buffer.length * 2]; 115 116 System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); 117 buffer = newBuffer; 118 } 119 buffer[currentBufferIndex++] = c; 120 } 121 122 private void clearBuffer() { 123 currentBufferIndex = 0; 124 } 125 126 private int bufferLength() { 127 return currentBufferIndex; 128 } 129 130 protected @Override void fillIn(ClassSymbol c) { 131 Symbol oldCurrentOwner = currentOwner; 132 try { 133 fillInImpl(c); 134 } finally { 135 currentOwner = oldCurrentOwner; 136 } 137 } 138 139 private boolean isSignatureFile (final JavaFileObject jfo) { 140 if (jfo instanceof FileObjects.Base) { 141 return ((FileObjects.Base)jfo).getExt().equals(FileObjects.SIG); 142 } 143 else { 144 return jfo.toUri().toString().endsWith('.'+FileObjects.SIG); 146 } 147 } 148 149 private void fillInImpl(ClassSymbol c) { 150 if (c.classfile == null || 151 c.classfile.getKind() != JavaFileObject.Kind.CLASS || 152 !isSignatureFile(c.classfile)) { 153 super.fillIn(c); 155 return ; 156 } 157 158 try { 159 final BufferedReader r = new BufferedReader (new InputStreamReader (c.classfile.openInputStream(), "UTF-8")); try { 161 int magic = r.read(); 162 if ( magic != 'G') { 163 throw new IOException ("Wrong signature file: " + c.classfile.toUri()); 164 } 165 fillInFromSig(c, r); 166 if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) { 167 List<Type> missing = missingTypeVariables; 168 List<Type> found = foundTypeVariables; 169 missingTypeVariables = List.nil(); 170 foundTypeVariables = List.nil(); 171 ClassType ct = (ClassType)currentOwner.type; 172 ct.supertype_field = 173 types.subst(ct.supertype_field, missing, found); 174 ct.interfaces_field = 175 types.subst(ct.interfaces_field, missing, found); 176 } else if (missingTypeVariables.isEmpty() != 177 foundTypeVariables.isEmpty()) { 178 Name name = missingTypeVariables.head.tsym.name; 179 throw badClassFile("undecl.type.var", name); 180 } 181 } finally { 182 try { 183 r.close(); 184 } catch (IOException ex) { 185 ErrorManager.getDefault().notify(ex); 186 } 187 missingTypeVariables = List.nil(); 188 foundTypeVariables = List.nil(); 189 } 190 } catch (IOException e) { 191 throw new CompletionFailure(c, e.getMessage()).initCause(e); 192 } 193 } 194 195 private void fillInFromSig(ClassSymbol c, Reader r) throws IOException { 196 ClassType ct = (ClassType)c.type; 197 198 c.members_field = new Scope(c); 200 201 currentOwner = c; 202 203 typevars = typevars.dup(currentOwner); 205 if (ct.getEnclosingType().tag == CLASS) enterTypevars(ct.getEnclosingType()); 206 207 long flags = readFlags(r) | Flags.FROMCLASS; 209 c.flags_field = flags; 210 211 int read = r.read(); 212 readingClassSignature = true; 213 try { 214 List<TypeVar> typevarsList; 216 217 if (read == '<') { 218 typevarsList = readTypeParamsWithName(r, c); 219 read = r.read(); 220 } else { 221 typevarsList = List.<TypeVar>nil(); 222 } 223 224 for (TypeVar tvar : typevarsList) { 225 typevars.enter(tvar.tsym); 226 } 227 228 ct.typarams_field = (List<Type>) ((List<?>) typevarsList); 229 230 assert read == 'N' : read; 231 232 Name name = readPlainNameIntoTable(r); 233 234 if (name != c.flatname) { 235 throw badClassFile("class.file.wrong.class", 236 name); 237 } 238 239 if ((read = r.read()) != ';') { 241 readEnclosingMethodAttr(r, c, read); 242 } 243 244 read = r.read(); 245 246 if (read != ';') { 247 ct.supertype_field = readType(r, read); } else { 249 ct.supertype_field = Type.noType; 251 } 252 253 if (ct.supertype_field.getClass() == Type.class) { 254 if (!ct.supertype_field.isPrimitive()) { 255 System.err.println("PROBLEM"); 256 System.err.println("c=" + c.flatname.toString()); 257 } 258 } 259 260 List<Type> superInterfaces = List.nil(); 262 263 while ((read = r.read()) != ';') { 264 superInterfaces = superInterfaces.prepend(readType(r, read)); } 266 267 ct.interfaces_field = superInterfaces.reverse(); 268 269 } finally { 270 readingClassSignature = false; 271 } 272 273 while ((read = r.read()) != ';') { 275 assert read == 'N'; 276 277 String innerClassName = readPlainName(r); 278 ClassSymbol innerClass = enterClass(findName(innerClassName), c); 279 280 markInnerClassOwner(c, innerClass); 281 } 282 283 read = r.read(); 284 285 assert read == '\n' || read == (-1) : c.classfile + ", char: " + ((char) read) + read; 286 287 Symbol s; 288 289 while ((s = readMember(r)) != null) { 290 enterMember(c, s); 291 } 292 293 c.attributes_field = readAnnotations(r); 294 295 typevars = typevars.leave(); 296 } 297 298 void readEnclosingMethodAttr(Reader r, ClassSymbol self, int read) throws IOException { 299 readingEnclMethod = true; 300 try{ 301 assert read == 'N' : read; 302 if (self.owner.kind == PCK) { 307 self.owner.members().remove(self); 308 } 309 ClassSymbol c = enterClass(readPlainNameIntoTable(r)); 310 MethodSymbol m = null; 311 read = r.read(); 312 if (read == 'N') { 313 Name methodName = readPlainNameIntoTable(r); 314 read = r.read(); 315 assert read == '(' : read; 316 List<Type> paramsTypes = List.nil(); 317 while ((read = r.read()) != ')') { 318 paramsTypes = paramsTypes.prepend(readType(r, read)); 319 } 320 paramsTypes = paramsTypes.reverse(); 321 read = r.read(); 322 assert read == '(' : read; 323 List<Type> throwsTypes = List.nil(); 324 while ((read = r.read()) != ')') { 325 throwsTypes = throwsTypes.prepend(readType(r, read)); 326 } 327 throwsTypes = throwsTypes.reverse(); 328 Type returnType = readType(r, r.read()); 329 assert (read = r.read()) == ';' : read; 330 MethodType methodType = new MethodType(paramsTypes, returnType, throwsTypes, syms.methodClass); 331 332 m = findMethod(methodName, methodType, c.members_field, self.flags()); 333 if (methodName != null && methodType != null && m == null) 334 throw badClassFile("bad.enclosing.method", self); 335 } 336 self.name = simpleBinaryName(self.flatname, c.flatname) ; 337 self.owner = m != null ? m : c; 338 if (self.name.len == 0) 339 self.fullname = null; 340 else 341 self.fullname = ClassSymbol.formFullName(self.name, self.owner); 342 343 if (m != null) { 344 ((ClassType)self.type).setEnclosingType(m.type); 345 } else if ((self.flags_field & STATIC) == 0) { 346 ((ClassType)self.type).setEnclosingType(c.type); 347 } else { 348 ((ClassType)self.type).setEnclosingType(Type.noType); 349 } 350 enterTypevars(self); 351 if (!missingTypeVariables.isEmpty()) { 352 ListBuffer<Type> typeVars = new ListBuffer<Type>(); 353 for (Type typevar : missingTypeVariables) { 354 typeVars.append(findTypeVar(typevar.tsym.name)); 355 } 356 foundTypeVariables = typeVars.toList(); 357 } else { 358 foundTypeVariables = List.nil(); 359 } 360 } finally { 361 readingEnclMethod = false; 362 } 363 } 364 365 private MethodSymbol findMethod(Name name, MethodType type, Scope scope, long flags) { 366 if (name == null || type == null) 367 return null; 368 369 for (Scope.Entry e = scope.lookup(name); e.scope != null; e = e.next()) 370 if (e.sym.kind == MTH && isSameBinaryType(e.sym.type.asMethodType(), type)) 371 return (MethodSymbol)e.sym; 372 373 if (name != table.init) 374 return null; 376 if ((flags & INTERFACE) != 0) 377 return null; 379 if (type.getParameterTypes().isEmpty()) 380 return null; 382 383 type = new MethodType(type.getParameterTypes().tail, 386 type.getReturnType(), 387 type.getThrownTypes(), 388 syms.methodClass); 389 return findMethod(name, type, scope, flags); 391 } 392 393 private void markInnerClassOwner(ClassSymbol owner, ClassSymbol innerClass) { 394 innerClass.complete(); 395 enterMember(owner, innerClass); 396 397 if ((innerClass.flags_field & STATIC) == 0) { 398 ((ClassType)innerClass.type).setEnclosingType(owner.type); 399 if (innerClass.erasure_field != null) 400 ((ClassType)innerClass.erasure_field).setEnclosingType(types.erasure(owner.type)); 401 } 402 } 403 404 private List<TypeVar> readTypeParamsWithName(Reader r, Symbol owner) throws IOException { 405 List<TypeVar> result = List.<TypeVar>nil(); 406 int read; 407 408 while ((read =r.read()) != '>') { 409 clearBuffer(); 410 411 addCharToBuffer((char) read); 412 413 while ((read = r.read()) != ':') { 414 addCharToBuffer((char) read); 415 } 416 417 Name typeName = findName(buffer, bufferLength()); 418 419 TypeVar tvar = null; 420 List<Type> last = null; 421 for (List<Type> l = missingTypeVariables; l.nonEmpty(); l = l.tail) { 422 if (typeName == l.head.tsym.name) { 423 tvar = (TypeVar)l.head; 424 if (last != null) 425 last.tail = l.tail; 426 else 427 missingTypeVariables = l.tail; 428 break; 429 } 430 last = l; 431 } 432 if (tvar == null) 433 tvar = new TypeVar(typeName, owner, syms.botType); 434 435 typevars.enter(tvar.tsym); 436 437 List<Type> bounds = List.<Type>nil(); 438 439 while ((read = r.read()) != ';') { 440 bounds = bounds.prepend(readType(r, read)); 441 } 442 443 bounds = bounds.reverse(); 444 445 types.setBounds(tvar, bounds, null); 446 447 result = result.prepend(tvar); 448 } 449 450 return result.reverse(); 451 } 452 453 private java.util.List <? extends TypeMirror> readTypeParams(Reader r) throws IOException { 454 java.util.List <TypeMirror> params = new java.util.ArrayList <TypeMirror>(); 455 int read; 456 457 while ((read = r.read()) != '>') { 458 params.add(readType(r, read)); 459 } 460 461 return params; 462 } 463 464 private String readPlainName(Reader r) throws IOException { 465 clearBuffer(); 466 467 int read; 468 469 while ((read = r.read()) != ';') { 470 addCharToBuffer((char) read); 471 } 472 473 return new String (buffer, 0, bufferLength()); 474 } 475 476 private String readName(Reader r) throws IOException { 477 int read = r.read(); 478 479 assert read == 'N' : (char) read; 480 481 return readPlainName(r); 482 } 483 484 private Name readPlainNameIntoTable(Reader r) throws IOException { 485 clearBuffer(); 486 487 int read; 488 489 while ((read = r.read()) != ';') { 490 addCharToBuffer((char) read); 491 } 492 493 return findName(buffer, bufferLength()); 494 } 495 496 private Name readNameIntoTable(Reader r) throws IOException { 497 int read = r.read(); 498 499 assert read == 'N' : (char) read; 500 501 return readPlainNameIntoTable(r); 502 } 503 504 private long readPlainFlags(Reader r) throws IOException { 505 return Long.parseLong(readPlainName(r), 16); 506 } 507 508 private long readFlags(Reader r) throws IOException { 509 int read = r.read(); 510 511 assert read == 'M'; 512 513 return readPlainFlags(r); 514 } 515 516 private Type readType(Reader r, int read) throws IOException { 517 switch (read) { 518 case 'Z': 519 return syms.booleanType; 520 case 'B': 521 return syms.byteType; 522 case 'S': 523 return syms.shortType; 524 case 'I': 525 return syms.intType; 526 case 'J': 527 return syms.longType; 528 case 'C': 529 return syms.charType; 530 case 'F': 531 return syms.floatType; 532 case 'D': 533 return syms.doubleType; 534 case 'V': 535 return syms.voidType; 536 case 'L': 537 return readReferenceType(r); 538 case '[': 539 return (Type) jTypes.getArrayType(readType(r, r.read())); 540 case 'R': 541 return new ErrorType(readPlainNameIntoTable(r), syms.noSymbol); 542 case 'Q': 543 return findTypeVar(readPlainNameIntoTable(r)); 544 case '+': 545 return new WildcardType(readType(r, r.read()), BoundKind.EXTENDS, syms.boundClass); 546 case '-': 547 return new WildcardType(readType(r, r.read()), BoundKind.SUPER, syms.boundClass); 548 case '?': 549 return new WildcardType(syms.objectType, BoundKind.UNBOUND, syms.boundClass); 550 default: 551 throw new IllegalArgumentException ("Completing: " + ((ClassSymbol) currentOwner).flatname.toString() + ", read=" + ((char) read) + ":" + read); 552 } 553 } 554 555 557 Type findTypeVar(Name name) { 558 Scope.Entry e = typevars.lookup(name); 559 if (e.scope != null) { 560 return e.sym.type; 561 } else { 562 if (readingClassSignature || readingEnclMethod) { 563 TypeVar t = new TypeVar(name, currentOwner, syms.botType); 574 missingTypeVariables = missingTypeVariables.prepend(t); 575 return t; 577 } 578 throw badClassFile("undecl.type.var", name); 579 } 580 } 581 582 private Name findName(CharSequence s) { 583 char[] data = s.toString().toCharArray(); 584 585 return findName(data, data.length); 586 } 587 588 private Name findName(char[] data, int len) { 589 return Name.fromChars(table, data, 0, len); 590 } 591 592 private Type readReferenceType(Reader r) throws IOException { 593 clearBuffer(); 594 595 int read; 596 597 while (";<".indexOf(read = r.read()) == (-1)) { 598 addCharToBuffer((char) read); 599 } 600 601 Name name = findName(buffer, bufferLength()); 602 ClassSymbol symbol = enterClass(name); 603 604 Symbol oldCurrentOwner = currentOwner; 605 java.util.List <? extends TypeMirror> typeParams = read == '<' ? readTypeParams(r) : null; Type result; 607 608 if (source.allowGenerics() && typeParams != null) { 609 result = new ClassType(symbol.type, List.from(typeParams.toArray(new Type[0])), symbol) { 610 boolean completed = false; 611 public Type getEnclosingType() { 612 if (!completed) { 613 completed = true; 614 tsym.complete(); 615 Type enclosingType = tsym.type.getEnclosingType(); 616 if (enclosingType != Type.noType) { 617 List<Type> typeArgs = 618 super.getEnclosingType().allparams(); 619 List<Type> typeParams = 620 enclosingType.allparams(); 621 if (typeParams.length() != typeArgs.length()) { 622 super.setEnclosingType(types.erasure(enclosingType)); 624 } else { 625 super.setEnclosingType(types.subst(enclosingType, 626 typeParams, 627 typeArgs)); 628 } 629 } else { 630 super.setEnclosingType(Type.noType); 631 } 632 } 633 return super.getEnclosingType(); 634 } 635 public void setEnclosingType(Type outer) { 636 throw new UnsupportedOperationException (); 637 } 638 }; 639 } else { 640 result = symbol.erasure(types); 641 } 642 643 currentOwner = oldCurrentOwner; 644 645 if (read == '<') { 646 read = r.read(); 647 assert read == ';' : (char) read; 648 } 649 650 return result; 651 } 652 653 private Symbol readMember(Reader r) throws IOException { 654 int read = r.read(); 655 656 if ('E' == read) { 657 return readExecutableMember(r); 658 } 659 660 if ('A' == read) { 661 return readField(r); 662 } 663 664 if ('W' == read) 665 return null; 666 667 if (read == (-1)) 668 return null; 669 670 throw new IllegalArgumentException ("Unknown type: " + read); 671 } 672 673 private Symbol readExecutableMember(Reader r) throws IOException { 674 long flags = readFlags(r); 675 676 typevars = typevars.dup(currentOwner); 677 678 List<TypeVar> typevarsList = null; 679 int read = r.read(); 680 681 if (read == '<') { 682 typevarsList = readTypeParamsWithName(r, null); 683 684 read = r.read(); 685 } 686 687 assert read == 'N' : read; 688 689 Name symbolName = readPlainNameIntoTable(r); 690 691 read = r.read(); 692 693 assert read == '(' : read; 694 695 List<VarSymbol> params = List.nil(); 696 List<Type> paramsTypes = List.nil(); 697 698 while ((read = r.read()) != ')') { 699 assert read == 'M'; 700 701 long argFlags = readPlainFlags(r); 702 Type argType = readType(r, r.read()); 703 Name argName = readNameIntoTable(r); 704 705 paramsTypes = paramsTypes.prepend(argType); 706 707 params = params.prepend(new VarSymbol(argFlags, argName, argType, null)); 708 } 709 710 paramsTypes = paramsTypes.reverse(); 711 params = params.reverse(); 712 read = r.read(); 713 714 assert read == '(' : read; 715 716 List<Type> throwsTypes = List.nil(); 717 718 while ((read = r.read()) != ')') { 719 throwsTypes = throwsTypes.prepend(readType(r, read)); 720 } 721 722 Type returnType = readType(r, r.read()); 723 Type methodType = new MethodType(paramsTypes, returnType, throwsTypes.reverse(), syms.methodClass);; 724 725 if (typevarsList != null) { 726 methodType = new ForAll((List<Type>) ((List<?>) typevarsList), methodType); 727 } 728 729 MethodSymbol method = new MethodSymbol(flags, symbolName, methodType, currentOwner); 730 731 method.params = params; 732 733 for (VarSymbol s : params) { 735 s.owner = method; 736 } 737 738 method.attributes_field = readAnnotations(r); 739 740 if ((read = r.read()) != ';') { 741 method.defaultValue = readAnnotationValue(methodType.getReturnType(), r, read); 742 } 743 744 typevars = typevars.leave(); 745 746 read = r.read(); 747 748 while (read == ' ') 749 read = r.read(); 750 751 assert read == '\n' || read == (-1) : read; 752 753 return method; 754 } 755 756 private Symbol readField(Reader r) throws IOException { 757 long flags = readFlags(r); 758 759 Type type = readType(r, r.read()); 760 Name name = readNameIntoTable(r); 761 762 Object constantValue = readConstantField(r); 763 764 VarSymbol field = new VarSymbol(flags, name, type, currentOwner); 765 766 field.setData(constantValue); 767 768 field.attributes_field = readAnnotations(r); 769 770 int read = r.read(); 771 772 while (read == ' ') 773 read = r.read(); 774 775 assert read == '\n' || read == (-1) : read; 776 777 return field; 778 } 779 780 private String readEscapedString(Reader r) throws IOException { 781 String value = readPlainName(r); 782 StringBuffer result = new StringBuffer (); 783 784 for (int cntr = 0; cntr < value.length(); cntr++) { 785 char c = value.charAt(cntr); 786 787 if (c == '\\') { 788 char next = value.charAt(cntr + 1); 789 790 switch (next) { 791 case '0': case '1': case '2': case '3': 792 case '4': case '5': case '6': case '7': 793 case '8': case '9': 794 result.append((char) Integer.parseInt(value.substring(cntr + 1, cntr + 5), 16)); 795 cntr += 4; 796 break; 797 case 'a': 798 result.append('@'); 799 cntr++; 800 break; 801 case 'b': 802 result.append(';'); 803 cntr++; 804 break; 805 case '\\': 806 result.append('\\'); 807 cntr++; 808 break; 809 default: 810 throw new IllegalStateException ("Unsupported escape: " + next); 811 } 812 } else { 813 result.append(c); 814 } 815 } 816 817 return result.toString(); 818 } 819 820 private Object readConstantField(Reader r) throws IOException { 821 Object result = null; 822 int read = r.read(); 823 824 switch (read) { 825 case 'Z': result = Boolean.parseBoolean(readPlainName(r)) ? Integer.valueOf(1) : Integer.valueOf(0); break; 826 case 'B': result = Integer.valueOf(readPlainName(r)); break; 827 case 'S': result = Integer.valueOf(readPlainName(r)); break; 828 case 'I': result = Integer.valueOf(readPlainName(r)); break; 829 case 'J': result = Long.valueOf(readPlainName(r)); break; 830 case 'C': result = new Integer (Character.valueOf(readEscapedString(r).charAt(0))); break; 831 case 'F': result = Float.valueOf(readPlainName(r)); break; 832 case 'D': result = Double.valueOf(readPlainName(r)); break; 833 case 'L': result = readEscapedString(r); break; 834 case 'X': 835 read = r.read(); 836 837 assert read == ';'; 838 break; 839 default: 840 throw badClassFile("Unknown constant type: " + (char) read); } 842 843 return result; 844 } 845 846 private List<Compound> readAnnotations(Reader r) throws IOException { 847 List<Compound> attributes = List.nil(); 848 int read; 849 850 while ((read = r.read()) != ';') { 851 attributes = attributes.prepend(readAnnotation(r, read)); 852 } 853 854 return attributes.reverse(); 855 } 856 857 private Compound readAnnotation(Reader r, int read) throws IOException { 858 Type annotationType = readType(r, read); 859 860 annotationType.complete(); 862 List<Pair<MethodSymbol, Attribute>> values = List.nil(); 863 864 while ((read = r.read()) != ';') { 865 assert read == 'N'; 866 867 String attributeName = readPlainName(r); 868 MethodSymbol ms = null; 869 870 for (Symbol m : ((ClassType) annotationType).asElement().getEnclosedElements()) { 871 if (m.getKind() == ElementKind.METHOD && attributeName.equals(m.getSimpleName().toString())) { 872 ms = (MethodSymbol) m; 873 break; 874 } 875 } 876 877 if (ms == null) { 878 throw new IllegalStateException ("invalid sig file: " + ((ClassSymbol) currentOwner).classfile + ", cannot find annotation attribute \"" + attributeName + " in " + ((TypeElement) ((ClassType) annotationType).asElement()).getQualifiedName()); 879 } 880 881 Attribute a = readAnnotationValue(ms.getReturnType(), r, r.read()); 882 values = values.prepend(new Pair<MethodSymbol, Attribute>(ms, a)); 883 } 884 885 return new Compound(annotationType, values.reverse()); 886 } 887 888 private Attribute readEnum(Reader r) throws IOException { 889 Type enumType = readType(r, r.read()); 890 Name constantName = readNameIntoTable(r); 891 VarSymbol constant = null; 892 893 for (Scope.Entry e = ((ClassType) enumType).tsym.members().lookup(constantName); e.scope != null; e = e.next()) { 894 if (e.sym.kind == VAR) { 895 constant = (VarSymbol)e.sym; 896 break; 897 } 898 } 899 if (constant == null) { 900 logger.error("unknown.enum.constant", currentClassFile, enumType, constant); 901 return new Attribute.Error(enumType); 902 } else { 903 return new Attribute.Enum(enumType, constant); 904 } 905 } 906 907 private Attribute readAnnotationValue(Type expectedType, Reader r, int read) throws IOException { 908 switch (read) { 909 case 'Z': return new Attribute.Constant(syms.booleanType, Boolean.parseBoolean(readPlainName(r)) ? Integer.valueOf(1) : Integer.valueOf(0)); 910 case 'B': return new Attribute.Constant(syms.byteType, Integer.parseInt(readPlainName(r))); 911 case 'S': return new Attribute.Constant(syms.shortType, Integer.parseInt(readPlainName(r))); 912 case 'I': return new Attribute.Constant(syms.intType, Integer.parseInt(readPlainName(r))); 913 case 'J': return new Attribute.Constant(syms.longType, Long.parseLong(readPlainName(r))); 914 case 'C': return new Attribute.Constant(syms.charType, Integer.valueOf(Character.valueOf(readEscapedString(r).charAt(0)))); 915 case 'F': return new Attribute.Constant(syms.floatType, Float.parseFloat(readPlainName(r))); 916 case 'D': return new Attribute.Constant(syms.doubleType, Double.parseDouble(readPlainName(r))); 917 case 'L': return new Attribute.Constant(syms.stringType, readEscapedString(r)); 918 case 'O': return readEnum(r); 919 case 'P': return readAnnotation(r, r.read()); 920 case '[': 921 java.util.List <Attribute> items = new ArrayList <Attribute>(); 922 923 while ((read = r.read()) != ';') { 924 items.add(readAnnotationValue(expectedType, r, read)); 925 } 926 927 return new Attribute.Array(((ArrayType) expectedType).getComponentType(), (Attribute[]) items.toArray(new Attribute[0])); 928 case 'Y': 929 return new Attribute.Class(types, readType(r, r.read())); 930 } 931 932 throw new IllegalStateException ("Completing: " + ((ClassSymbol) currentOwner).flatname.toString() + ", read=" + ((char) read) + ":" + read); 933 } 934 935 protected @Override void includeClassFile(PackageSymbol p, JavaFileObject file) { 937 super.includeClassFile(p, file); 938 } 939 940 } 941 | Popular Tags |