1 /* 2 * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.javac.jvm; 27 28 import java.io.*; 29 import java.net.URI; 30 import java.net.URISyntaxException; 31 import java.nio.CharBuffer; 32 import java.nio.file.ClosedFileSystemException; 33 import java.util.Arrays; 34 import java.util.EnumSet; 35 import java.util.HashMap; 36 import java.util.HashSet; 37 import java.util.Map; 38 import java.util.Set; 39 import java.util.function.BiFunction; 40 import java.util.function.IntFunction; 41 import java.util.function.Predicate; 42 43 import javax.lang.model.element.Modifier; 44 import javax.lang.model.element.NestingKind; 45 import javax.tools.JavaFileManager; 46 import javax.tools.JavaFileObject; 47 48 import com.sun.tools.javac.code.Source; 49 import com.sun.tools.javac.code.Source.Feature; 50 import com.sun.tools.javac.comp.Annotate; 51 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter; 52 import com.sun.tools.javac.code.*; 53 import com.sun.tools.javac.code.Directive.*; 54 import com.sun.tools.javac.code.Lint.LintCategory; 55 import com.sun.tools.javac.code.Scope.WriteableScope; 56 import com.sun.tools.javac.code.Symbol.*; 57 import com.sun.tools.javac.code.Symtab; 58 import com.sun.tools.javac.code.Type.*; 59 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata; 60 import com.sun.tools.javac.file.BaseFileManager; 61 import com.sun.tools.javac.file.PathFileObject; 62 import com.sun.tools.javac.jvm.ClassFile.Version; 63 import com.sun.tools.javac.jvm.PoolConstant.NameAndType; 64 import com.sun.tools.javac.main.Option; 65 import com.sun.tools.javac.resources.CompilerProperties.Fragments; 66 import com.sun.tools.javac.resources.CompilerProperties.Warnings; 67 import com.sun.tools.javac.util.*; 68 import com.sun.tools.javac.util.ByteBuffer.UnderflowException; 69 import com.sun.tools.javac.util.DefinedBy.Api; 70 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 71 import com.sun.tools.javac.util.JCDiagnostic.Fragment; 72 73 import static com.sun.tools.javac.code.Flags.*; 74 import static com.sun.tools.javac.code.Kinds.Kind.*; 75 76 import com.sun.tools.javac.code.Scope.LookupKind; 77 78 import static com.sun.tools.javac.code.TypeTag.ARRAY; 79 import static com.sun.tools.javac.code.TypeTag.CLASS; 80 import static com.sun.tools.javac.code.TypeTag.TYPEVAR; 81 import static com.sun.tools.javac.jvm.ClassFile.*; 82 import static com.sun.tools.javac.jvm.ClassFile.Version.*; 83 84 import static com.sun.tools.javac.main.Option.PARAMETERS; 85 86 /** This class provides operations to read a classfile into an internal 87 * representation. The internal representation is anchored in a 88 * ClassSymbol which contains in its scope symbol representations 89 * for all other definitions in the classfile. Top-level Classes themselves 90 * appear as members of the scopes of PackageSymbols. 91 * 92 * <p><b>This is NOT part of any supported API. 93 * If you write code that depends on this, you do so at your own risk. 94 * This code and its internal interfaces are subject to change or 95 * deletion without notice.</b> 96 */ 97 public class ClassReader { 98 /** The context key for the class reader. */ 99 protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>(); 100 101 public static final int INITIAL_BUFFER_SIZE = 0x0fff0; 102 103 private final Annotate annotate; 104 105 /** Switch: verbose output. 106 */ 107 boolean verbose; 108 109 /** Switch: allow modules. 110 */ 111 boolean allowModules; 112 113 /** Switch: allow sealed 114 */ 115 boolean allowSealedTypes; 116 117 /** Switch: allow records 118 */ 119 boolean allowRecords; 120 121 /** Lint option: warn about classfile issues 122 */ 123 boolean lintClassfile; 124 125 /** Switch: warn (instead of error) on illegal UTF-8 126 */ 127 boolean warnOnIllegalUtf8; 128 129 /** Switch: preserve parameter names from the variable table. 130 */ 131 public boolean saveParameterNames; 132 133 /** 134 * The currently selected profile. 135 */ 136 public final Profile profile; 137 138 /** The log to use for verbose output 139 */ 140 final Log log; 141 142 /** The symbol table. */ 143 Symtab syms; 144 145 Types types; 146 147 /** The name table. */ 148 final Names names; 149 150 /** Access to files 151 */ 152 private final JavaFileManager fileManager; 153 154 /** Factory for diagnostics 155 */ 156 JCDiagnostic.Factory diagFactory; 157 158 DeferredCompletionFailureHandler dcfh; 159 160 /** 161 * Support for preview language features. 162 */ 163 Preview preview; 164 165 /** The current scope where type variables are entered. 166 */ 167 protected WriteableScope typevars; 168 169 private List<InterimUsesDirective> interimUses = List.nil(); 170 private List<InterimProvidesDirective> interimProvides = List.nil(); 171 172 /** The path name of the class file currently being read. 173 */ 174 protected JavaFileObject currentClassFile = null; 175 176 /** The class or method currently being read. 177 */ 178 protected Symbol currentOwner = null; 179 180 /** The module containing the class currently being read. 181 */ 182 protected ModuleSymbol currentModule = null; 183 184 /** The buffer containing the currently read class file. 185 */ 186 ByteBuffer buf = new ByteBuffer(INITIAL_BUFFER_SIZE); 187 188 /** The current input pointer. 189 */ 190 protected int bp; 191 192 /** The pool reader. 193 */ 194 PoolReader poolReader; 195 196 /** The major version number of the class file being read. */ 197 int majorVersion; 198 /** The minor version number of the class file being read. */ 199 int minorVersion; 200 201 /** UTF-8 validation level */ 202 Convert.Validation utf8validation; 203 204 /** A table to hold the constant pool indices for method parameter 205 * names, as given in LocalVariableTable attributes. 206 */ 207 int[] parameterNameIndicesLvt; 208 209 /** 210 * A table to hold the constant pool indices for method parameter 211 * names, as given in the MethodParameters attribute. 212 */ 213 int[] parameterNameIndicesMp; 214 215 /** 216 * A table to hold the access flags of the method parameters. 217 */ 218 int[] parameterAccessFlags; 219 220 /** 221 * A table to hold annotations for method parameters. 222 */ 223 ParameterAnnotations[] parameterAnnotations; 224 225 /** 226 * A holder for parameter annotations. 227 */ 228 static class ParameterAnnotations { 229 List<CompoundAnnotationProxy> proxies; 230 231 void add(List<CompoundAnnotationProxy> newAnnotations) { 232 if (proxies == null) { 233 proxies = newAnnotations; 234 } else { 235 proxies = proxies.prependList(newAnnotations); 236 } 237 } 238 } 239 240 /** 241 * The set of attribute names for which warnings have been generated for the current class 242 */ 243 Set<Name> warnedAttrs = new HashSet<>(); 244 245 /** 246 * The prototype @Target Attribute.Compound if this class is an annotation annotated with 247 * {@code @Target} 248 */ 249 CompoundAnnotationProxy target; 250 251 /** 252 * The prototype @Repeatable Attribute.Compound if this class is an annotation annotated with 253 * {@code @Repeatable} 254 */ 255 CompoundAnnotationProxy repeatable; 256 257 /** Get the ClassReader instance for this invocation. */ 258 public static ClassReader instance(Context context) { 259 ClassReader instance = context.get(classReaderKey); 260 if (instance == null) 261 instance = new ClassReader(context); 262 return instance; 263 } 264 265 /** Construct a new class reader. */ 266 @SuppressWarnings("this-escape") 267 protected ClassReader(Context context) { 268 context.put(classReaderKey, this); 269 annotate = Annotate.instance(context); 270 names = Names.instance(context); 271 syms = Symtab.instance(context); 272 types = Types.instance(context); 273 fileManager = context.get(JavaFileManager.class); 274 if (fileManager == null) 275 throw new AssertionError("FileManager initialization error"); 276 diagFactory = JCDiagnostic.Factory.instance(context); 277 dcfh = DeferredCompletionFailureHandler.instance(context); 278 279 log = Log.instance(context); 280 281 Options options = Options.instance(context); 282 verbose = options.isSet(Option.VERBOSE); 283 284 Source source = Source.instance(context); 285 preview = Preview.instance(context); 286 allowModules = Feature.MODULES.allowedInSource(source); 287 allowRecords = Feature.RECORDS.allowedInSource(source); 288 allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source); 289 warnOnIllegalUtf8 = Feature.WARN_ON_ILLEGAL_UTF8.allowedInSource(source); 290 291 saveParameterNames = options.isSet(PARAMETERS); 292 293 profile = Profile.instance(context); 294 295 typevars = WriteableScope.create(syms.noSymbol); 296 297 lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE); 298 299 initAttributeReaders(); 300 } 301 302 /** Add member to class unless it is synthetic. 303 */ 304 private void enterMember(ClassSymbol c, Symbol sym) { 305 // Synthetic members are not entered -- reason lost to history (optimization?). 306 // Lambda methods must be entered because they may have inner classes (which reference them) 307 if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda)) 308 c.members_field.enter(sym); 309 } 310 311 /************************************************************************ 312 * Error Diagnoses 313 ***********************************************************************/ 314 315 public ClassFinder.BadClassFile badClassFile(String key, Object... args) { 316 return badClassFile(diagFactory.fragment(key, args)); 317 } 318 319 public ClassFinder.BadClassFile badClassFile(Fragment fragment) { 320 return badClassFile(diagFactory.fragment(fragment)); 321 } 322 323 public ClassFinder.BadClassFile badClassFile(JCDiagnostic diagnostic) { 324 return new ClassFinder.BadClassFile ( 325 currentOwner.enclClass(), 326 currentClassFile, 327 diagnostic, 328 diagFactory, 329 dcfh); 330 } 331 332 public ClassFinder.BadEnclosingMethodAttr badEnclosingMethod(Symbol sym) { 333 return new ClassFinder.BadEnclosingMethodAttr ( 334 currentOwner.enclClass(), 335 currentClassFile, 336 diagFactory.fragment(Fragments.BadEnclosingMethod(sym)), 337 diagFactory, 338 dcfh); 339 } 340 341 /************************************************************************ 342 * Buffer Access 343 ***********************************************************************/ 344 345 /** Read a character. 346 */ 347 char nextChar() { 348 char res; 349 try { 350 res = buf.getChar(bp); 351 } catch (UnderflowException e) { 352 throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength())); 353 } 354 bp += 2; 355 return res; 356 } 357 358 /** Read a byte. 359 */ 360 int nextByte() { 361 try { 362 return buf.getByte(bp++) & 0xFF; 363 } catch (UnderflowException e) { 364 throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength())); 365 } 366 } 367 368 /** Read an integer. 369 */ 370 int nextInt() { 371 int res; 372 try { 373 res = buf.getInt(bp); 374 } catch (UnderflowException e) { 375 throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength())); 376 } 377 bp += 4; 378 return res; 379 } 380 381 /************************************************************************ 382 * Constant Pool Access 383 ***********************************************************************/ 384 385 /** Read module_flags. 386 */ 387 Set<ModuleFlags> readModuleFlags(int flags) { 388 Set<ModuleFlags> set = EnumSet.noneOf(ModuleFlags.class); 389 for (ModuleFlags f : ModuleFlags.values()) { 390 if ((flags & f.value) != 0) 391 set.add(f); 392 } 393 return set; 394 } 395 396 /** Read resolution_flags. 397 */ 398 Set<ModuleResolutionFlags> readModuleResolutionFlags(int flags) { 399 Set<ModuleResolutionFlags> set = EnumSet.noneOf(ModuleResolutionFlags.class); 400 for (ModuleResolutionFlags f : ModuleResolutionFlags.values()) { 401 if ((flags & f.value) != 0) 402 set.add(f); 403 } 404 return set; 405 } 406 407 /** Read exports_flags. 408 */ 409 Set<ExportsFlag> readExportsFlags(int flags) { 410 Set<ExportsFlag> set = EnumSet.noneOf(ExportsFlag.class); 411 for (ExportsFlag f: ExportsFlag.values()) { 412 if ((flags & f.value) != 0) 413 set.add(f); 414 } 415 return set; 416 } 417 418 /** Read opens_flags. 419 */ 420 Set<OpensFlag> readOpensFlags(int flags) { 421 Set<OpensFlag> set = EnumSet.noneOf(OpensFlag.class); 422 for (OpensFlag f: OpensFlag.values()) { 423 if ((flags & f.value) != 0) 424 set.add(f); 425 } 426 return set; 427 } 428 429 /** Read requires_flags. 430 */ 431 Set<RequiresFlag> readRequiresFlags(int flags) { 432 Set<RequiresFlag> set = EnumSet.noneOf(RequiresFlag.class); 433 for (RequiresFlag f: RequiresFlag.values()) { 434 if ((flags & f.value) != 0) 435 set.add(f); 436 } 437 return set; 438 } 439 440 /************************************************************************ 441 * Reading Types 442 ***********************************************************************/ 443 444 /** The unread portion of the currently read type is 445 * signature[sigp..siglimit-1]. 446 */ 447 byte[] signature; 448 int sigp; 449 int siglimit; 450 boolean sigEnterPhase = false; 451 452 /** Convert signature to type, where signature is a byte array segment. 453 */ 454 Type sigToType(byte[] sig, int offset, int len) { 455 signature = sig; 456 sigp = offset; 457 siglimit = offset + len; 458 return sigToType(); 459 } 460 461 /** Convert signature to type, where signature is implicit. 462 */ 463 Type sigToType() { 464 switch ((char) signature[sigp]) { 465 case 'T': 466 sigp++; 467 int start = sigp; 468 while (signature[sigp] != ';') sigp++; 469 sigp++; 470 return sigEnterPhase 471 ? Type.noType 472 : findTypeVar(readName(signature, start, sigp - 1 - start)); 473 case '+': { 474 sigp++; 475 Type t = sigToType(); 476 return new WildcardType(t, BoundKind.EXTENDS, syms.boundClass); 477 } 478 case '*': 479 sigp++; 480 return new WildcardType(syms.objectType, BoundKind.UNBOUND, 481 syms.boundClass); 482 case '-': { 483 sigp++; 484 Type t = sigToType(); 485 return new WildcardType(t, BoundKind.SUPER, syms.boundClass); 486 } 487 case 'B': 488 sigp++; 489 return syms.byteType; 490 case 'C': 491 sigp++; 492 return syms.charType; 493 case 'D': 494 sigp++; 495 return syms.doubleType; 496 case 'F': 497 sigp++; 498 return syms.floatType; 499 case 'I': 500 sigp++; 501 return syms.intType; 502 case 'J': 503 sigp++; 504 return syms.longType; 505 case 'L': 506 { 507 // int oldsigp = sigp; 508 Type t = classSigToType(); 509 if (sigp < siglimit && signature[sigp] == '.') 510 throw badClassFile("deprecated inner class signature syntax " + 511 "(please recompile from source)"); 512 /* 513 System.err.println(" decoded " + 514 new String(signature, oldsigp, sigp-oldsigp) + 515 " => " + t + " outer " + t.outer()); 516 */ 517 return t; 518 } 519 case 'S': 520 sigp++; 521 return syms.shortType; 522 case 'V': 523 sigp++; 524 return syms.voidType; 525 case 'Z': 526 sigp++; 527 return syms.booleanType; 528 case '[': 529 sigp++; 530 return new ArrayType(sigToType(), syms.arrayClass); 531 case '(': 532 sigp++; 533 List<Type> argtypes = sigToTypes(')'); 534 Type restype = sigToType(); 535 List<Type> thrown = List.nil(); 536 while (sigp < siglimit && signature[sigp] == '^') { 537 sigp++; 538 thrown = thrown.prepend(sigToType()); 539 } 540 // if there is a typevar in the throws clause we should state it. 541 for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) { 542 if (l.head.hasTag(TYPEVAR)) { 543 l.head.tsym.flags_field |= THROWS; 544 } 545 } 546 return new MethodType(argtypes, 547 restype, 548 thrown.reverse(), 549 syms.methodClass); 550 case '<': 551 typevars = typevars.dup(currentOwner); 552 Type poly = new ForAll(sigToTypeParams(), sigToType()); 553 typevars = typevars.leave(); 554 return poly; 555 default: 556 throw badClassFile("bad.signature", quoteBadSignature()); 557 } 558 } 559 560 byte[] signatureBuffer = new byte[0]; 561 int sbp = 0; 562 /** Convert class signature to type, where signature is implicit. 563 */ 564 Type classSigToType() { 565 if (signature[sigp] != 'L') 566 throw badClassFile("bad.class.signature", quoteBadSignature()); 567 sigp++; 568 Type outer = Type.noType; 569 int startSbp = sbp; 570 571 while (true) { 572 final byte c = signature[sigp++]; 573 switch (c) { 574 575 case ';': { // end 576 ClassSymbol t = enterClass(readName(signatureBuffer, 577 startSbp, 578 sbp - startSbp)); 579 580 try { 581 return (outer == Type.noType) ? 582 t.erasure(types) : 583 new ClassType(outer, List.nil(), t); 584 } finally { 585 sbp = startSbp; 586 } 587 } 588 589 case '<': // generic arguments 590 ClassSymbol t = enterClass(readName(signatureBuffer, 591 startSbp, 592 sbp - startSbp)); 593 outer = new ClassType(outer, sigToTypes('>'), t) { 594 boolean completed = false; 595 @Override @DefinedBy(Api.LANGUAGE_MODEL) 596 public Type getEnclosingType() { 597 if (!completed) { 598 completed = true; 599 tsym.apiComplete(); 600 Type enclosingType = tsym.type.getEnclosingType(); 601 if (enclosingType != Type.noType) { 602 List<Type> typeArgs = 603 super.getEnclosingType().allparams(); 604 List<Type> typeParams = 605 enclosingType.allparams(); 606 if (typeParams.length() != typeArgs.length()) { 607 // no "rare" types 608 super.setEnclosingType(types.erasure(enclosingType)); 609 } else { 610 super.setEnclosingType(types.subst(enclosingType, 611 typeParams, 612 typeArgs)); 613 } 614 } else { 615 super.setEnclosingType(Type.noType); 616 } 617 } 618 return super.getEnclosingType(); 619 } 620 @Override 621 public void setEnclosingType(Type outer) { 622 throw new UnsupportedOperationException(); 623 } 624 }; 625 switch (signature[sigp++]) { 626 case ';': 627 if (sigp < siglimit && signature[sigp] == '.') { 628 // support old-style GJC signatures 629 // The signature produced was 630 // Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>; 631 // rather than say 632 // Lfoo/Outer<Lfoo/X;>.Inner<Lfoo/Y;>; 633 // so we skip past ".Lfoo/Outer$" 634 sigp += (sbp - startSbp) + // "foo/Outer" 635 3; // ".L" and "$" 636 signatureBuffer[sbp++] = (byte)'$'; 637 break; 638 } else { 639 sbp = startSbp; 640 return outer; 641 } 642 case '.': 643 signatureBuffer[sbp++] = (byte)'$'; 644 break; 645 default: 646 throw new AssertionError(signature[sigp-1]); 647 } 648 continue; 649 650 case '.': 651 //we have seen an enclosing non-generic class 652 if (outer != Type.noType) { 653 t = enterClass(readName(signatureBuffer, 654 startSbp, 655 sbp - startSbp)); 656 outer = new ClassType(outer, List.nil(), t); 657 } 658 signatureBuffer[sbp++] = (byte)'$'; 659 continue; 660 case '/': 661 signatureBuffer[sbp++] = (byte)'.'; 662 continue; 663 default: 664 signatureBuffer[sbp++] = c; 665 continue; 666 } 667 } 668 } 669 670 /** Quote a bogus signature for display inside an error message. 671 */ 672 String quoteBadSignature() { 673 String sigString; 674 try { 675 sigString = Convert.utf2string(signature, sigp, siglimit - sigp, Convert.Validation.NONE); 676 } catch (InvalidUtfException e) { 677 throw new AssertionError(e); 678 } 679 if (sigString.length() > 32) 680 sigString = sigString.substring(0, 32) + "..."; 681 return "\"" + sigString + "\""; 682 } 683 684 /** Convert (implicit) signature to list of types 685 * until `terminator' is encountered. 686 */ 687 List<Type> sigToTypes(char terminator) { 688 List<Type> head = List.of(null); 689 List<Type> tail = head; 690 while (signature[sigp] != terminator) 691 tail = tail.setTail(List.of(sigToType())); 692 sigp++; 693 return head.tail; 694 } 695 696 /** Convert signature to type parameters, where signature is a byte 697 * array segment. 698 */ 699 List<Type> sigToTypeParams(byte[] sig, int offset, int len) { 700 signature = sig; 701 sigp = offset; 702 siglimit = offset + len; 703 return sigToTypeParams(); 704 } 705 706 /** Convert signature to type parameters, where signature is implicit. 707 */ 708 List<Type> sigToTypeParams() { 709 List<Type> tvars = List.nil(); 710 if (signature[sigp] == '<') { 711 sigp++; 712 int start = sigp; 713 sigEnterPhase = true; 714 while (signature[sigp] != '>') 715 tvars = tvars.prepend(sigToTypeParam()); 716 sigEnterPhase = false; 717 sigp = start; 718 while (signature[sigp] != '>') 719 sigToTypeParam(); 720 sigp++; 721 } 722 return tvars.reverse(); 723 } 724 725 /** Convert (implicit) signature to type parameter. 726 */ 727 Type sigToTypeParam() { 728 int start = sigp; 729 while (signature[sigp] != ':') sigp++; 730 Name name = readName(signature, start, sigp - start); 731 TypeVar tvar; 732 if (sigEnterPhase) { 733 tvar = new TypeVar(name, currentOwner, syms.botType); 734 typevars.enter(tvar.tsym); 735 } else { 736 tvar = (TypeVar)findTypeVar(name); 737 } 738 List<Type> bounds = List.nil(); 739 boolean allInterfaces = false; 740 if (signature[sigp] == ':' && signature[sigp+1] == ':') { 741 sigp++; 742 allInterfaces = true; 743 } 744 while (signature[sigp] == ':') { 745 sigp++; 746 bounds = bounds.prepend(sigToType()); 747 } 748 if (!sigEnterPhase) { 749 types.setBounds(tvar, bounds.reverse(), allInterfaces); 750 } 751 return tvar; 752 } 753 754 /** Find type variable with given name in `typevars' scope. 755 */ 756 Type findTypeVar(Name name) { 757 Symbol s = typevars.findFirst(name); 758 if (s != null) { 759 return s.type; 760 } else { 761 if (readingClassAttr) { 762 // While reading the class attribute, the supertypes 763 // might refer to a type variable from an enclosing element 764 // (method or class). 765 // If the type variable is defined in the enclosing class, 766 // we can actually find it in 767 // currentOwner.owner.type.getTypeArguments() 768 // However, until we have read the enclosing method attribute 769 // we don't know for sure if this owner is correct. It could 770 // be a method and there is no way to tell before reading the 771 // enclosing method attribute. 772 TypeVar t = new TypeVar(name, currentOwner, syms.botType); 773 missingTypeVariables = missingTypeVariables.prepend(t); 774 // System.err.println("Missing type var " + name); 775 return t; 776 } 777 throw badClassFile("undecl.type.var", name); 778 } 779 } 780 781 private Name readName(byte[] buf, int off, int len) { 782 try { 783 return names.fromUtf(buf, off, len, utf8validation); 784 } catch (InvalidUtfException e) { 785 if (warnOnIllegalUtf8) { 786 log.warning(Warnings.InvalidUtf8InClassfile(currentClassFile, 787 Fragments.BadUtf8ByteSequenceAt(sigp))); 788 return names.fromUtfLax(buf, off, len); 789 } 790 throw badClassFile(Fragments.BadUtf8ByteSequenceAt(sigp)); 791 } 792 } 793 794 /************************************************************************ 795 * Reading Attributes 796 ***********************************************************************/ 797 798 protected enum AttributeKind { CLASS, MEMBER } 799 800 protected abstract class AttributeReader { 801 protected AttributeReader(Name name, ClassFile.Version version, Set<AttributeKind> kinds) { 802 this.name = name; 803 this.version = version; 804 this.kinds = kinds; 805 } 806 807 protected boolean accepts(AttributeKind kind) { 808 if (kinds.contains(kind)) { 809 if (majorVersion > version.major || (majorVersion == version.major && minorVersion >= version.minor)) 810 return true; 811 812 if (lintClassfile && !warnedAttrs.contains(name)) { 813 JavaFileObject prev = log.useSource(currentClassFile); 814 try { 815 log.warning(LintCategory.CLASSFILE, (DiagnosticPosition) null, 816 Warnings.FutureAttr(name, version.major, version.minor, majorVersion, minorVersion)); 817 } finally { 818 log.useSource(prev); 819 } 820 warnedAttrs.add(name); 821 } 822 } 823 return false; 824 } 825 826 protected abstract void read(Symbol sym, int attrLen); 827 828 protected final Name name; 829 protected final ClassFile.Version version; 830 protected final Set<AttributeKind> kinds; 831 } 832 833 protected Set<AttributeKind> CLASS_ATTRIBUTE = 834 EnumSet.of(AttributeKind.CLASS); 835 protected Set<AttributeKind> MEMBER_ATTRIBUTE = 836 EnumSet.of(AttributeKind.MEMBER); 837 protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE = 838 EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER); 839 840 protected Map<Name, AttributeReader> attributeReaders = new HashMap<>(); 841 842 private void initAttributeReaders() { 843 AttributeReader[] readers = { 844 // v45.3 attributes 845 846 new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) { 847 protected void read(Symbol sym, int attrLen) { 848 if (saveParameterNames) 849 ((MethodSymbol)sym).code = readCode(sym); 850 else 851 bp = bp + attrLen; 852 } 853 }, 854 855 new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) { 856 protected void read(Symbol sym, int attrLen) { 857 Object v = poolReader.getConstant(nextChar()); 858 // Ignore ConstantValue attribute if field not final. 859 if ((sym.flags() & FINAL) == 0) { 860 return; 861 } 862 VarSymbol var = (VarSymbol) sym; 863 switch (var.type.getTag()) { 864 case BOOLEAN: 865 case BYTE: 866 case CHAR: 867 case SHORT: 868 case INT: 869 checkType(var, Integer.class, v); 870 break; 871 case LONG: 872 checkType(var, Long.class, v); 873 break; 874 case FLOAT: 875 checkType(var, Float.class, v); 876 break; 877 case DOUBLE: 878 checkType(var, Double.class, v); 879 break; 880 case CLASS: 881 if (var.type.tsym == syms.stringType.tsym) { 882 checkType(var, String.class, v); 883 } else { 884 throw badClassFile("bad.constant.value.type", var.type); 885 } 886 break; 887 default: 888 // ignore ConstantValue attribute if type is not primitive or String 889 return; 890 } 891 if (v instanceof Integer intVal && !var.type.getTag().checkRange(intVal)) { 892 throw badClassFile("bad.constant.range", v, var, var.type); 893 } 894 var.setData(v); 895 } 896 897 void checkType(Symbol var, Class<?> clazz, Object value) { 898 if (!clazz.isInstance(value)) { 899 throw badClassFile("bad.constant.value", value, var, clazz.getSimpleName()); 900 } 901 } 902 }, 903 904 new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 905 protected void read(Symbol sym, int attrLen) { 906 Symbol s = sym.owner.kind == MDL ? sym.owner : sym; 907 908 s.flags_field |= DEPRECATED; 909 } 910 }, 911 912 new AttributeReader(names.Exceptions, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 913 protected void read(Symbol sym, int attrLen) { 914 int nexceptions = nextChar(); 915 List<Type> thrown = List.nil(); 916 for (int j = 0; j < nexceptions; j++) 917 thrown = thrown.prepend(poolReader.getClass(nextChar()).type); 918 if (sym.type.getThrownTypes().isEmpty()) 919 sym.type.asMethodType().thrown = thrown.reverse(); 920 } 921 }, 922 923 new AttributeReader(names.InnerClasses, V45_3, CLASS_ATTRIBUTE) { 924 protected void read(Symbol sym, int attrLen) { 925 ClassSymbol c = (ClassSymbol) sym; 926 if (currentModule.module_info == c) { 927 //prevent entering the classes too soon: 928 skipInnerClasses(); 929 } else { 930 readInnerClasses(c); 931 } 932 } 933 }, 934 935 new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 936 protected void read(Symbol sym, int attrLen) { 937 int newbp = bp + attrLen; 938 if (saveParameterNames) { 939 // Pick up parameter names from the variable table. 940 // Parameter names are not explicitly identified as such, 941 // but all parameter name entries in the LocalVariableTable 942 // have a start_pc of 0. Therefore, we record the name 943 // indices of all slots with a start_pc of zero in the 944 // parameterNameIndices array. 945 // Note that this implicitly honors the JVMS spec that 946 // there may be more than one LocalVariableTable, and that 947 // there is no specified ordering for the entries. 948 int numEntries = nextChar(); 949 for (int i = 0; i < numEntries; i++) { 950 int start_pc = nextChar(); 951 int length = nextChar(); 952 int nameIndex = nextChar(); 953 int sigIndex = nextChar(); 954 int register = nextChar(); 955 if (start_pc == 0) { 956 // ensure array large enough 957 if (register >= parameterNameIndicesLvt.length) { 958 int newSize = 959 Math.max(register + 1, parameterNameIndicesLvt.length + 8); 960 parameterNameIndicesLvt = 961 Arrays.copyOf(parameterNameIndicesLvt, newSize); 962 } 963 parameterNameIndicesLvt[register] = nameIndex; 964 } 965 } 966 } 967 bp = newbp; 968 } 969 }, 970 971 new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) { 972 protected void read(Symbol sym, int attrLen) { 973 ClassSymbol c = (ClassSymbol) sym; 974 Name n = poolReader.getName(nextChar()); 975 c.sourcefile = new SourceFileObject(n); 976 // If the class is a toplevel class, originating from a Java source file, 977 // but the class name does not match the file name, then it is 978 // an auxiliary class. 979 String sn = n.toString(); 980 if (c.owner.kind == PCK && 981 sn.endsWith(".java") && 982 !sn.equals(c.name.toString()+".java")) { 983 c.flags_field |= AUXILIARY; 984 } 985 } 986 }, 987 988 new AttributeReader(names.Synthetic, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 989 protected void read(Symbol sym, int attrLen) { 990 sym.flags_field |= SYNTHETIC; 991 } 992 }, 993 994 // standard v49 attributes 995 996 new AttributeReader(names.EnclosingMethod, V49, CLASS_ATTRIBUTE) { 997 protected void read(Symbol sym, int attrLen) { 998 int newbp = bp + attrLen; 999 readEnclosingMethodAttr(sym); 1000 bp = newbp; 1001 } 1002 }, 1003 1004 new AttributeReader(names.Signature, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1005 protected void read(Symbol sym, int attrLen) { 1006 if (sym.kind == TYP) { 1007 ClassSymbol c = (ClassSymbol) sym; 1008 readingClassAttr = true; 1009 try { 1010 ClassType ct1 = (ClassType)c.type; 1011 Assert.check(c == currentOwner); 1012 ct1.typarams_field = poolReader.getName(nextChar()) 1013 .map(ClassReader.this::sigToTypeParams); 1014 ct1.supertype_field = sigToType(); 1015 ListBuffer<Type> is = new ListBuffer<>(); 1016 while (sigp != siglimit) is.append(sigToType()); 1017 ct1.interfaces_field = is.toList(); 1018 } finally { 1019 readingClassAttr = false; 1020 } 1021 } else { 1022 List<Type> thrown = sym.type.getThrownTypes(); 1023 sym.type = poolReader.getType(nextChar()); 1024 //- System.err.println(" # " + sym.type); 1025 if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty()) 1026 sym.type.asMethodType().thrown = thrown; 1027 1028 } 1029 } 1030 }, 1031 1032 // v49 annotation attributes 1033 1034 new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1035 protected void read(Symbol sym, int attrLen) { 1036 attachAnnotationDefault(sym); 1037 } 1038 }, 1039 1040 new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1041 protected void read(Symbol sym, int attrLen) { 1042 attachAnnotations(sym); 1043 } 1044 }, 1045 1046 new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1047 protected void read(Symbol sym, int attrLen) { 1048 readParameterAnnotations(sym); 1049 } 1050 }, 1051 1052 new AttributeReader(names.RuntimeVisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1053 protected void read(Symbol sym, int attrLen) { 1054 attachAnnotations(sym); 1055 } 1056 }, 1057 1058 new AttributeReader(names.RuntimeVisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1059 protected void read(Symbol sym, int attrLen) { 1060 readParameterAnnotations(sym); 1061 } 1062 }, 1063 1064 // additional "legacy" v49 attributes, superseded by flags 1065 1066 new AttributeReader(names.Annotation, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1067 protected void read(Symbol sym, int attrLen) { 1068 sym.flags_field |= ANNOTATION; 1069 } 1070 }, 1071 1072 new AttributeReader(names.Bridge, V49, MEMBER_ATTRIBUTE) { 1073 protected void read(Symbol sym, int attrLen) { 1074 sym.flags_field |= BRIDGE; 1075 } 1076 }, 1077 1078 new AttributeReader(names.Enum, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1079 protected void read(Symbol sym, int attrLen) { 1080 sym.flags_field |= ENUM; 1081 } 1082 }, 1083 1084 new AttributeReader(names.Varargs, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1085 protected void read(Symbol sym, int attrLen) { 1086 sym.flags_field |= VARARGS; 1087 } 1088 }, 1089 1090 new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { 1091 protected void read(Symbol sym, int attrLen) { 1092 attachTypeAnnotations(sym); 1093 } 1094 }, 1095 1096 new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { 1097 protected void read(Symbol sym, int attrLen) { 1098 attachTypeAnnotations(sym); 1099 } 1100 }, 1101 1102 // The following attributes for a Code attribute are not currently handled 1103 // StackMapTable 1104 // SourceDebugExtension 1105 // LineNumberTable 1106 // LocalVariableTypeTable 1107 1108 // standard v52 attributes 1109 1110 new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) { 1111 protected void read(Symbol sym, int attrlen) { 1112 int newbp = bp + attrlen; 1113 if (saveParameterNames) { 1114 int numEntries = nextByte(); 1115 parameterNameIndicesMp = new int[numEntries]; 1116 parameterAccessFlags = new int[numEntries]; 1117 int index = 0; 1118 for (int i = 0; i < numEntries; i++) { 1119 int nameIndex = nextChar(); 1120 int flags = nextChar(); 1121 if ((flags & (Flags.MANDATED | Flags.SYNTHETIC)) != 0) { 1122 continue; 1123 } 1124 parameterNameIndicesMp[index] = nameIndex; 1125 parameterAccessFlags[index] = flags; 1126 index++; 1127 } 1128 } 1129 bp = newbp; 1130 } 1131 }, 1132 1133 // standard v53 attributes 1134 1135 new AttributeReader(names.Module, V53, CLASS_ATTRIBUTE) { 1136 @Override 1137 protected boolean accepts(AttributeKind kind) { 1138 return super.accepts(kind) && allowModules; 1139 } 1140 protected void read(Symbol sym, int attrLen) { 1141 if (sym.kind == TYP && sym.owner.kind == MDL) { 1142 ModuleSymbol msym = (ModuleSymbol) sym.owner; 1143 ListBuffer<Directive> directives = new ListBuffer<>(); 1144 1145 Name moduleName = poolReader.peekModuleName(nextChar(), ClassReader.this::readName); 1146 if (currentModule.name != moduleName) { 1147 throw badClassFile("module.name.mismatch", moduleName, currentModule.name); 1148 } 1149 1150 Set<ModuleFlags> moduleFlags = readModuleFlags(nextChar()); 1151 msym.flags.addAll(moduleFlags); 1152 msym.version = optPoolEntry(nextChar(), poolReader::getName, null); 1153 1154 ListBuffer<RequiresDirective> requires = new ListBuffer<>(); 1155 int nrequires = nextChar(); 1156 for (int i = 0; i < nrequires; i++) { 1157 ModuleSymbol rsym = poolReader.getModule(nextChar()); 1158 Set<RequiresFlag> flags = readRequiresFlags(nextChar()); 1159 if (rsym == syms.java_base && majorVersion >= V54.major) { 1160 if (flags.contains(RequiresFlag.TRANSITIVE)) { 1161 throw badClassFile("bad.requires.flag", RequiresFlag.TRANSITIVE); 1162 } 1163 if (flags.contains(RequiresFlag.STATIC_PHASE)) { 1164 throw badClassFile("bad.requires.flag", RequiresFlag.STATIC_PHASE); 1165 } 1166 } 1167 nextChar(); // skip compiled version 1168 requires.add(new RequiresDirective(rsym, flags)); 1169 } 1170 msym.requires = requires.toList(); 1171 directives.addAll(msym.requires); 1172 1173 ListBuffer<ExportsDirective> exports = new ListBuffer<>(); 1174 int nexports = nextChar(); 1175 for (int i = 0; i < nexports; i++) { 1176 PackageSymbol p = poolReader.getPackage(nextChar()); 1177 Set<ExportsFlag> flags = readExportsFlags(nextChar()); 1178 int nto = nextChar(); 1179 List<ModuleSymbol> to; 1180 if (nto == 0) { 1181 to = null; 1182 } else { 1183 ListBuffer<ModuleSymbol> lb = new ListBuffer<>(); 1184 for (int t = 0; t < nto; t++) 1185 lb.append(poolReader.getModule(nextChar())); 1186 to = lb.toList(); 1187 } 1188 exports.add(new ExportsDirective(p, to, flags)); 1189 } 1190 msym.exports = exports.toList(); 1191 directives.addAll(msym.exports); 1192 ListBuffer<OpensDirective> opens = new ListBuffer<>(); 1193 int nopens = nextChar(); 1194 if (nopens != 0 && msym.flags.contains(ModuleFlags.OPEN)) { 1195 throw badClassFile("module.non.zero.opens", currentModule.name); 1196 } 1197 for (int i = 0; i < nopens; i++) { 1198 PackageSymbol p = poolReader.getPackage(nextChar()); 1199 Set<OpensFlag> flags = readOpensFlags(nextChar()); 1200 int nto = nextChar(); 1201 List<ModuleSymbol> to; 1202 if (nto == 0) { 1203 to = null; 1204 } else { 1205 ListBuffer<ModuleSymbol> lb = new ListBuffer<>(); 1206 for (int t = 0; t < nto; t++) 1207 lb.append(poolReader.getModule(nextChar())); 1208 to = lb.toList(); 1209 } 1210 opens.add(new OpensDirective(p, to, flags)); 1211 } 1212 msym.opens = opens.toList(); 1213 directives.addAll(msym.opens); 1214 1215 msym.directives = directives.toList(); 1216 1217 ListBuffer<InterimUsesDirective> uses = new ListBuffer<>(); 1218 int nuses = nextChar(); 1219 for (int i = 0; i < nuses; i++) { 1220 Name srvc = poolReader.peekClassName(nextChar(), this::classNameMapper); 1221 uses.add(new InterimUsesDirective(srvc)); 1222 } 1223 interimUses = uses.toList(); 1224 1225 ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>(); 1226 int nprovides = nextChar(); 1227 for (int p = 0; p < nprovides; p++) { 1228 Name srvc = poolReader.peekClassName(nextChar(), this::classNameMapper); 1229 int nimpls = nextChar(); 1230 ListBuffer<Name> impls = new ListBuffer<>(); 1231 for (int i = 0; i < nimpls; i++) { 1232 impls.append(poolReader.peekClassName(nextChar(), this::classNameMapper)); 1233 provides.add(new InterimProvidesDirective(srvc, impls.toList())); 1234 } 1235 } 1236 interimProvides = provides.toList(); 1237 } 1238 } 1239 1240 private Name classNameMapper(byte[] arr, int offset, int length) throws InvalidUtfException { 1241 byte[] buf = ClassFile.internalize(arr, offset, length); 1242 try { 1243 return names.fromUtf(buf, 0, buf.length, utf8validation); 1244 } catch (InvalidUtfException e) { 1245 if (warnOnIllegalUtf8) { 1246 log.warning(Warnings.InvalidUtf8InClassfile(currentClassFile, 1247 Fragments.BadUtf8ByteSequenceAt(e.getOffset()))); 1248 return names.fromUtfLax(buf, 0, buf.length); 1249 } 1250 throw e; 1251 } 1252 } 1253 }, 1254 1255 new AttributeReader(names.ModuleResolution, V53, CLASS_ATTRIBUTE) { 1256 @Override 1257 protected boolean accepts(AttributeKind kind) { 1258 return super.accepts(kind) && allowModules; 1259 } 1260 protected void read(Symbol sym, int attrLen) { 1261 if (sym.kind == TYP && sym.owner.kind == MDL) { 1262 ModuleSymbol msym = (ModuleSymbol) sym.owner; 1263 msym.resolutionFlags.addAll(readModuleResolutionFlags(nextChar())); 1264 } 1265 } 1266 }, 1267 1268 new AttributeReader(names.Record, V58, CLASS_ATTRIBUTE) { 1269 @Override 1270 protected boolean accepts(AttributeKind kind) { 1271 return super.accepts(kind) && allowRecords; 1272 } 1273 protected void read(Symbol sym, int attrLen) { 1274 if (sym.kind == TYP) { 1275 sym.flags_field |= RECORD; 1276 } 1277 int componentCount = nextChar(); 1278 ListBuffer<RecordComponent> components = new ListBuffer<>(); 1279 for (int i = 0; i < componentCount; i++) { 1280 Name name = poolReader.getName(nextChar()); 1281 Type type = poolReader.getType(nextChar()); 1282 RecordComponent c = new RecordComponent(name, type, sym); 1283 readAttrs(c, AttributeKind.MEMBER); 1284 components.add(c); 1285 } 1286 ((ClassSymbol) sym).setRecordComponents(components.toList()); 1287 } 1288 }, 1289 new AttributeReader(names.PermittedSubclasses, V59, CLASS_ATTRIBUTE) { 1290 @Override 1291 protected boolean accepts(AttributeKind kind) { 1292 return super.accepts(kind) && allowSealedTypes; 1293 } 1294 protected void read(Symbol sym, int attrLen) { 1295 if (sym.kind == TYP) { 1296 ListBuffer<Symbol> subtypes = new ListBuffer<>(); 1297 int numberOfPermittedSubtypes = nextChar(); 1298 for (int i = 0; i < numberOfPermittedSubtypes; i++) { 1299 subtypes.add(poolReader.getClass(nextChar())); 1300 } 1301 ((ClassSymbol)sym).permitted = subtypes.toList(); 1302 } 1303 } 1304 }, 1305 }; 1306 1307 for (AttributeReader r: readers) 1308 attributeReaders.put(r.name, r); 1309 } 1310 1311 protected void readEnclosingMethodAttr(Symbol sym) { 1312 // sym is a nested class with an "Enclosing Method" attribute 1313 // remove sym from it's current owners scope and place it in 1314 // the scope specified by the attribute 1315 sym.owner.members().remove(sym); 1316 ClassSymbol self = (ClassSymbol)sym; 1317 ClassSymbol c = poolReader.getClass(nextChar()); 1318 NameAndType nt = optPoolEntry(nextChar(), poolReader::getNameAndType, null); 1319 1320 if (c.members_field == null || c.kind != TYP) 1321 throw badClassFile("bad.enclosing.class", self, c); 1322 1323 MethodSymbol m = findMethod(nt, c.members_field, self.flags()); 1324 if (nt != null && m == null) 1325 throw badEnclosingMethod(self); 1326 1327 self.name = simpleBinaryName(self.flatname, c.flatname) ; 1328 self.owner = m != null ? m : c; 1329 if (self.name.isEmpty()) 1330 self.fullname = names.empty; 1331 else 1332 self.fullname = ClassSymbol.formFullName(self.name, self.owner); 1333 1334 if (m != null) { 1335 ((ClassType)sym.type).setEnclosingType(m.type); 1336 } else if ((self.flags_field & STATIC) == 0) { 1337 ((ClassType)sym.type).setEnclosingType(c.type); 1338 } else { 1339 ((ClassType)sym.type).setEnclosingType(Type.noType); 1340 } 1341 enterTypevars(self, self.type); 1342 if (!missingTypeVariables.isEmpty()) { 1343 ListBuffer<Type> typeVars = new ListBuffer<>(); 1344 for (Type typevar : missingTypeVariables) { 1345 typeVars.append(findTypeVar(typevar.tsym.name)); 1346 } 1347 foundTypeVariables = typeVars.toList(); 1348 } else { 1349 foundTypeVariables = List.nil(); 1350 } 1351 } 1352 1353 // See java.lang.Class 1354 private Name simpleBinaryName(Name self, Name enclosing) { 1355 if (!self.startsWith(enclosing)) { 1356 throw badClassFile("bad.enclosing.method", self); 1357 } 1358 1359 String simpleBinaryName = self.toString().substring(enclosing.toString().length()); 1360 if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$') 1361 throw badClassFile("bad.enclosing.method", self); 1362 int index = 1; 1363 while (index < simpleBinaryName.length() && 1364 isAsciiDigit(simpleBinaryName.charAt(index))) 1365 index++; 1366 return names.fromString(simpleBinaryName.substring(index)); 1367 } 1368 1369 private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) { 1370 if (nt == null) 1371 return null; 1372 1373 MethodType type = nt.type.asMethodType(); 1374 1375 for (Symbol sym : scope.getSymbolsByName(nt.name)) { 1376 if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type)) 1377 return (MethodSymbol)sym; 1378 } 1379 1380 if (nt.name != names.init) 1381 // not a constructor 1382 return null; 1383 if ((flags & INTERFACE) != 0) 1384 // no enclosing instance 1385 return null; 1386 if (nt.type.getParameterTypes().isEmpty()) 1387 // no parameters 1388 return null; 1389 1390 // A constructor of an inner class. 1391 // Remove the first argument (the enclosing instance) 1392 nt = new NameAndType(nt.name, new MethodType(nt.type.getParameterTypes().tail, 1393 nt.type.getReturnType(), 1394 nt.type.getThrownTypes(), 1395 syms.methodClass)); 1396 // Try searching again 1397 return findMethod(nt, scope, flags); 1398 } 1399 1400 /** Similar to Types.isSameType but avoids completion */ 1401 private boolean isSameBinaryType(MethodType mt1, MethodType mt2) { 1402 List<Type> types1 = types.erasure(mt1.getParameterTypes()) 1403 .prepend(types.erasure(mt1.getReturnType())); 1404 List<Type> types2 = mt2.getParameterTypes().prepend(mt2.getReturnType()); 1405 while (!types1.isEmpty() && !types2.isEmpty()) { 1406 if (types1.head.tsym != types2.head.tsym) 1407 return false; 1408 types1 = types1.tail; 1409 types2 = types2.tail; 1410 } 1411 return types1.isEmpty() && types2.isEmpty(); 1412 } 1413 1414 /** 1415 * Character.isDigit answers <tt>true</tt> to some non-ascii 1416 * digits. This one does not. <b>copied from java.lang.Class</b> 1417 */ 1418 private static boolean isAsciiDigit(char c) { 1419 return '0' <= c && c <= '9'; 1420 } 1421 1422 /** Read member attributes. 1423 */ 1424 void readMemberAttrs(Symbol sym) { 1425 readAttrs(sym, AttributeKind.MEMBER); 1426 } 1427 1428 void readAttrs(Symbol sym, AttributeKind kind) { 1429 char ac = nextChar(); 1430 for (int i = 0; i < ac; i++) { 1431 Name attrName = poolReader.getName(nextChar()); 1432 int attrLen = nextInt(); 1433 AttributeReader r = attributeReaders.get(attrName); 1434 if (r != null && r.accepts(kind)) 1435 r.read(sym, attrLen); 1436 else { 1437 bp = bp + attrLen; 1438 } 1439 } 1440 } 1441 1442 private boolean readingClassAttr = false; 1443 private List<Type> missingTypeVariables = List.nil(); 1444 private List<Type> foundTypeVariables = List.nil(); 1445 1446 /** Read class attributes. 1447 */ 1448 void readClassAttrs(ClassSymbol c) { 1449 readAttrs(c, AttributeKind.CLASS); 1450 } 1451 1452 /** Read code block. 1453 */ 1454 Code readCode(Symbol owner) { 1455 nextChar(); // max_stack 1456 nextChar(); // max_locals 1457 final int code_length = nextInt(); 1458 bp += code_length; 1459 final char exception_table_length = nextChar(); 1460 bp += exception_table_length * 8; 1461 readMemberAttrs(owner); 1462 return null; 1463 } 1464 1465 /************************************************************************ 1466 * Reading Java-language annotations 1467 ***********************************************************************/ 1468 1469 /** 1470 * Save annotations. 1471 */ 1472 List<CompoundAnnotationProxy> readAnnotations() { 1473 int numAttributes = nextChar(); 1474 ListBuffer<CompoundAnnotationProxy> annotations = new ListBuffer<>(); 1475 for (int i = 0; i < numAttributes; i++) { 1476 annotations.append(readCompoundAnnotation()); 1477 } 1478 return annotations.toList(); 1479 } 1480 1481 /** Attach annotations. 1482 */ 1483 void attachAnnotations(final Symbol sym) { 1484 attachAnnotations(sym, readAnnotations()); 1485 } 1486 1487 /** 1488 * Attach annotations. 1489 */ 1490 void attachAnnotations(final Symbol sym, List<CompoundAnnotationProxy> annotations) { 1491 if (annotations.isEmpty()) { 1492 return; 1493 } 1494 ListBuffer<CompoundAnnotationProxy> proxies = new ListBuffer<>(); 1495 for (CompoundAnnotationProxy proxy : annotations) { 1496 if (proxy.type.tsym.flatName() == syms.proprietaryType.tsym.flatName()) 1497 sym.flags_field |= PROPRIETARY; 1498 else if (proxy.type.tsym.flatName() == syms.profileType.tsym.flatName()) { 1499 if (profile != Profile.DEFAULT) { 1500 for (Pair<Name, Attribute> v : proxy.values) { 1501 if (v.fst == names.value && v.snd instanceof Attribute.Constant constant) { 1502 if (constant.type == syms.intType && ((Integer) constant.value) > profile.value) { 1503 sym.flags_field |= NOT_IN_PROFILE; 1504 } 1505 } 1506 } 1507 } 1508 } else if (proxy.type.tsym.flatName() == syms.previewFeatureInternalType.tsym.flatName()) { 1509 sym.flags_field |= PREVIEW_API; 1510 setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE); 1511 } else if (proxy.type.tsym.flatName() == syms.valueBasedInternalType.tsym.flatName()) { 1512 Assert.check(sym.kind == TYP); 1513 sym.flags_field |= VALUE_BASED; 1514 } else if (proxy.type.tsym.flatName() == syms.restrictedType.tsym.flatName()) { 1515 Assert.check(sym.kind == MTH); 1516 sym.flags_field |= RESTRICTED; 1517 } else { 1518 if (proxy.type.tsym == syms.annotationTargetType.tsym) { 1519 target = proxy; 1520 } else if (proxy.type.tsym == syms.repeatableType.tsym) { 1521 repeatable = proxy; 1522 } else if (proxy.type.tsym == syms.deprecatedType.tsym) { 1523 sym.flags_field |= (DEPRECATED | DEPRECATED_ANNOTATION); 1524 setFlagIfAttributeTrue(proxy, sym, names.forRemoval, DEPRECATED_REMOVAL); 1525 } else if (proxy.type.tsym == syms.previewFeatureType.tsym) { 1526 sym.flags_field |= PREVIEW_API; 1527 setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE); 1528 } else if (proxy.type.tsym == syms.valueBasedType.tsym && sym.kind == TYP) { 1529 sym.flags_field |= VALUE_BASED; 1530 } else if (proxy.type.tsym == syms.restrictedType.tsym) { 1531 Assert.check(sym.kind == MTH); 1532 sym.flags_field |= RESTRICTED; 1533 } 1534 proxies.append(proxy); 1535 } 1536 } 1537 annotate.normal(new AnnotationCompleter(sym, proxies.toList())); 1538 } 1539 //where: 1540 private void setFlagIfAttributeTrue(CompoundAnnotationProxy proxy, Symbol sym, Name attribute, long flag) { 1541 for (Pair<Name, Attribute> v : proxy.values) { 1542 if (v.fst == attribute && v.snd instanceof Attribute.Constant constant) { 1543 if (constant.type == syms.booleanType && ((Integer) constant.value) != 0) { 1544 sym.flags_field |= flag; 1545 } 1546 } 1547 } 1548 } 1549 1550 /** Read parameter annotations. 1551 */ 1552 void readParameterAnnotations(Symbol meth) { 1553 int numParameters; 1554 try { 1555 numParameters = buf.getByte(bp++) & 0xFF; 1556 } catch (UnderflowException e) { 1557 throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength())); 1558 } 1559 if (parameterAnnotations == null) { 1560 parameterAnnotations = new ParameterAnnotations[numParameters]; 1561 } else if (parameterAnnotations.length != numParameters) { 1562 throw badClassFile("bad.runtime.invisible.param.annotations", meth); 1563 } 1564 for (int pnum = 0; pnum < numParameters; pnum++) { 1565 if (parameterAnnotations[pnum] == null) { 1566 parameterAnnotations[pnum] = new ParameterAnnotations(); 1567 } 1568 parameterAnnotations[pnum].add(readAnnotations()); 1569 } 1570 } 1571 1572 void attachTypeAnnotations(final Symbol sym) { 1573 int numAttributes = nextChar(); 1574 if (numAttributes != 0) { 1575 ListBuffer<TypeAnnotationProxy> proxies = new ListBuffer<>(); 1576 for (int i = 0; i < numAttributes; i++) 1577 proxies.append(readTypeAnnotation()); 1578 annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList())); 1579 } 1580 } 1581 1582 /** Attach the default value for an annotation element. 1583 */ 1584 void attachAnnotationDefault(final Symbol sym) { 1585 final MethodSymbol meth = (MethodSymbol)sym; // only on methods 1586 final Attribute value = readAttributeValue(); 1587 1588 // The default value is set later during annotation. It might 1589 // be the case that the Symbol sym is annotated _after_ the 1590 // repeating instances that depend on this default value, 1591 // because of this we set an interim value that tells us this 1592 // element (most likely) has a default. 1593 // 1594 // Set interim value for now, reset just before we do this 1595 // properly at annotate time. 1596 meth.defaultValue = value; 1597 annotate.normal(new AnnotationDefaultCompleter(meth, value)); 1598 } 1599 1600 Type readTypeOrClassSymbol(int i) { 1601 return readTypeToProxy(i); 1602 } 1603 Type readTypeToProxy(int i) { 1604 if (currentModule.module_info == currentOwner) { 1605 return new ProxyType(i); 1606 } else { 1607 return poolReader.getType(i); 1608 } 1609 } 1610 1611 CompoundAnnotationProxy readCompoundAnnotation() { 1612 Type t; 1613 if (currentModule.module_info == currentOwner) { 1614 int cpIndex = nextChar(); 1615 t = new ProxyType(cpIndex); 1616 } else { 1617 t = readTypeOrClassSymbol(nextChar()); 1618 } 1619 int numFields = nextChar(); 1620 ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>(); 1621 for (int i=0; i<numFields; i++) { 1622 Name name = poolReader.getName(nextChar()); 1623 Attribute value = readAttributeValue(); 1624 pairs.append(new Pair<>(name, value)); 1625 } 1626 return new CompoundAnnotationProxy(t, pairs.toList()); 1627 } 1628 1629 TypeAnnotationProxy readTypeAnnotation() { 1630 TypeAnnotationPosition position = readPosition(); 1631 CompoundAnnotationProxy proxy = readCompoundAnnotation(); 1632 1633 return new TypeAnnotationProxy(proxy, position); 1634 } 1635 1636 TypeAnnotationPosition readPosition() { 1637 int tag = nextByte(); // TargetType tag is a byte 1638 1639 if (!TargetType.isValidTargetTypeValue(tag)) 1640 throw badClassFile("bad.type.annotation.value", String.format("0x%02X", tag)); 1641 1642 TargetType type = TargetType.fromTargetTypeValue(tag); 1643 1644 switch (type) { 1645 // instanceof 1646 case INSTANCEOF: { 1647 final int offset = nextChar(); 1648 final TypeAnnotationPosition position = 1649 TypeAnnotationPosition.instanceOf(readTypePath()); 1650 position.offset = offset; 1651 return position; 1652 } 1653 // new expression 1654 case NEW: { 1655 final int offset = nextChar(); 1656 final TypeAnnotationPosition position = 1657 TypeAnnotationPosition.newObj(readTypePath()); 1658 position.offset = offset; 1659 return position; 1660 } 1661 // constructor/method reference receiver 1662 case CONSTRUCTOR_REFERENCE: { 1663 final int offset = nextChar(); 1664 final TypeAnnotationPosition position = 1665 TypeAnnotationPosition.constructorRef(readTypePath()); 1666 position.offset = offset; 1667 return position; 1668 } 1669 case METHOD_REFERENCE: { 1670 final int offset = nextChar(); 1671 final TypeAnnotationPosition position = 1672 TypeAnnotationPosition.methodRef(readTypePath()); 1673 position.offset = offset; 1674 return position; 1675 } 1676 // local variable 1677 case LOCAL_VARIABLE: { 1678 final int table_length = nextChar(); 1679 final int[] newLvarOffset = new int[table_length]; 1680 final int[] newLvarLength = new int[table_length]; 1681 final int[] newLvarIndex = new int[table_length]; 1682 1683 for (int i = 0; i < table_length; ++i) { 1684 newLvarOffset[i] = nextChar(); 1685 newLvarLength[i] = nextChar(); 1686 newLvarIndex[i] = nextChar(); 1687 } 1688 1689 final TypeAnnotationPosition position = 1690 TypeAnnotationPosition.localVariable(readTypePath()); 1691 position.lvarOffset = newLvarOffset; 1692 position.lvarLength = newLvarLength; 1693 position.lvarIndex = newLvarIndex; 1694 return position; 1695 } 1696 // resource variable 1697 case RESOURCE_VARIABLE: { 1698 final int table_length = nextChar(); 1699 final int[] newLvarOffset = new int[table_length]; 1700 final int[] newLvarLength = new int[table_length]; 1701 final int[] newLvarIndex = new int[table_length]; 1702 1703 for (int i = 0; i < table_length; ++i) { 1704 newLvarOffset[i] = nextChar(); 1705 newLvarLength[i] = nextChar(); 1706 newLvarIndex[i] = nextChar(); 1707 } 1708 1709 final TypeAnnotationPosition position = 1710 TypeAnnotationPosition.resourceVariable(readTypePath()); 1711 position.lvarOffset = newLvarOffset; 1712 position.lvarLength = newLvarLength; 1713 position.lvarIndex = newLvarIndex; 1714 return position; 1715 } 1716 // exception parameter 1717 case EXCEPTION_PARAMETER: { 1718 final int exception_index = nextChar(); 1719 final TypeAnnotationPosition position = 1720 TypeAnnotationPosition.exceptionParameter(readTypePath()); 1721 position.setExceptionIndex(exception_index); 1722 return position; 1723 } 1724 // method receiver 1725 case METHOD_RECEIVER: 1726 return TypeAnnotationPosition.methodReceiver(readTypePath()); 1727 // type parameter 1728 case CLASS_TYPE_PARAMETER: { 1729 final int parameter_index = nextByte(); 1730 return TypeAnnotationPosition 1731 .typeParameter(readTypePath(), parameter_index); 1732 } 1733 case METHOD_TYPE_PARAMETER: { 1734 final int parameter_index = nextByte(); 1735 return TypeAnnotationPosition 1736 .methodTypeParameter(readTypePath(), parameter_index); 1737 } 1738 // type parameter bound 1739 case CLASS_TYPE_PARAMETER_BOUND: { 1740 final int parameter_index = nextByte(); 1741 final int bound_index = nextByte(); 1742 return TypeAnnotationPosition 1743 .typeParameterBound(readTypePath(), parameter_index, 1744 bound_index); 1745 } 1746 case METHOD_TYPE_PARAMETER_BOUND: { 1747 final int parameter_index = nextByte(); 1748 final int bound_index = nextByte(); 1749 return TypeAnnotationPosition 1750 .methodTypeParameterBound(readTypePath(), parameter_index, 1751 bound_index); 1752 } 1753 // class extends or implements clause 1754 case CLASS_EXTENDS: { 1755 final int type_index = nextChar(); 1756 return TypeAnnotationPosition.classExtends(readTypePath(), 1757 type_index); 1758 } 1759 // throws 1760 case THROWS: { 1761 final int type_index = nextChar(); 1762 return TypeAnnotationPosition.methodThrows(readTypePath(), 1763 type_index); 1764 } 1765 // method parameter 1766 case METHOD_FORMAL_PARAMETER: { 1767 final int parameter_index = nextByte(); 1768 return TypeAnnotationPosition.methodParameter(readTypePath(), 1769 parameter_index); 1770 } 1771 // type cast 1772 case CAST: { 1773 final int offset = nextChar(); 1774 final int type_index = nextByte(); 1775 final TypeAnnotationPosition position = 1776 TypeAnnotationPosition.typeCast(readTypePath(), type_index); 1777 position.offset = offset; 1778 return position; 1779 } 1780 // method/constructor/reference type argument 1781 case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: { 1782 final int offset = nextChar(); 1783 final int type_index = nextByte(); 1784 final TypeAnnotationPosition position = TypeAnnotationPosition 1785 .constructorInvocationTypeArg(readTypePath(), type_index); 1786 position.offset = offset; 1787 return position; 1788 } 1789 case METHOD_INVOCATION_TYPE_ARGUMENT: { 1790 final int offset = nextChar(); 1791 final int type_index = nextByte(); 1792 final TypeAnnotationPosition position = TypeAnnotationPosition 1793 .methodInvocationTypeArg(readTypePath(), type_index); 1794 position.offset = offset; 1795 return position; 1796 } 1797 case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: { 1798 final int offset = nextChar(); 1799 final int type_index = nextByte(); 1800 final TypeAnnotationPosition position = TypeAnnotationPosition 1801 .constructorRefTypeArg(readTypePath(), type_index); 1802 position.offset = offset; 1803 return position; 1804 } 1805 case METHOD_REFERENCE_TYPE_ARGUMENT: { 1806 final int offset = nextChar(); 1807 final int type_index = nextByte(); 1808 final TypeAnnotationPosition position = TypeAnnotationPosition 1809 .methodRefTypeArg(readTypePath(), type_index); 1810 position.offset = offset; 1811 return position; 1812 } 1813 // We don't need to worry about these 1814 case METHOD_RETURN: 1815 return TypeAnnotationPosition.methodReturn(readTypePath()); 1816 case FIELD: 1817 return TypeAnnotationPosition.field(readTypePath()); 1818 case UNKNOWN: 1819 throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!"); 1820 default: 1821 throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + type); 1822 } 1823 } 1824 1825 List<TypeAnnotationPosition.TypePathEntry> readTypePath() { 1826 int len = nextByte(); 1827 ListBuffer<Integer> loc = new ListBuffer<>(); 1828 for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i) 1829 loc = loc.append(nextByte()); 1830 1831 return TypeAnnotationPosition.getTypePathFromBinary(loc.toList()); 1832 1833 } 1834 1835 /** 1836 * Helper function to read an optional pool entry (with given function); this is used while parsing 1837 * InnerClasses and EnclosingMethod attributes, as well as when parsing supertype descriptor, 1838 * as per JVMS. 1839 */ 1840 <Z> Z optPoolEntry(int index, IntFunction<Z> poolFunc, Z defaultValue) { 1841 return (index == 0) ? 1842 defaultValue : 1843 poolFunc.apply(index); 1844 } 1845 1846 Attribute readAttributeValue() { 1847 char c; 1848 try { 1849 c = (char)buf.getByte(bp++); 1850 } catch (UnderflowException e) { 1851 throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength())); 1852 } 1853 switch (c) { 1854 case 'B': 1855 return new Attribute.Constant(syms.byteType, poolReader.getConstant(nextChar())); 1856 case 'C': 1857 return new Attribute.Constant(syms.charType, poolReader.getConstant(nextChar())); 1858 case 'D': 1859 return new Attribute.Constant(syms.doubleType, poolReader.getConstant(nextChar())); 1860 case 'F': 1861 return new Attribute.Constant(syms.floatType, poolReader.getConstant(nextChar())); 1862 case 'I': 1863 return new Attribute.Constant(syms.intType, poolReader.getConstant(nextChar())); 1864 case 'J': 1865 return new Attribute.Constant(syms.longType, poolReader.getConstant(nextChar())); 1866 case 'S': 1867 return new Attribute.Constant(syms.shortType, poolReader.getConstant(nextChar())); 1868 case 'Z': 1869 return new Attribute.Constant(syms.booleanType, poolReader.getConstant(nextChar())); 1870 case 's': 1871 return new Attribute.Constant(syms.stringType, poolReader.getName(nextChar()).toString()); 1872 case 'e': 1873 return new EnumAttributeProxy(readTypeToProxy(nextChar()), poolReader.getName(nextChar())); 1874 case 'c': 1875 return new ClassAttributeProxy(readTypeOrClassSymbol(nextChar())); 1876 case '[': { 1877 int n = nextChar(); 1878 ListBuffer<Attribute> l = new ListBuffer<>(); 1879 for (int i=0; i<n; i++) 1880 l.append(readAttributeValue()); 1881 return new ArrayAttributeProxy(l.toList()); 1882 } 1883 case '@': 1884 return readCompoundAnnotation(); 1885 default: 1886 throw new AssertionError("unknown annotation tag '" + c + "'"); 1887 } 1888 } 1889 1890 interface ProxyVisitor extends Attribute.Visitor { 1891 void visitEnumAttributeProxy(EnumAttributeProxy proxy); 1892 void visitClassAttributeProxy(ClassAttributeProxy proxy); 1893 void visitArrayAttributeProxy(ArrayAttributeProxy proxy); 1894 void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy); 1895 } 1896 1897 static class EnumAttributeProxy extends Attribute { 1898 Type enumType; 1899 Name enumerator; 1900 public EnumAttributeProxy(Type enumType, Name enumerator) { 1901 super(null); 1902 this.enumType = enumType; 1903 this.enumerator = enumerator; 1904 } 1905 public void accept(Visitor v) { ((ProxyVisitor)v).visitEnumAttributeProxy(this); } 1906 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1907 public String toString() { 1908 return "/*proxy enum*/" + enumType + "." + enumerator; 1909 } 1910 } 1911 1912 static class ClassAttributeProxy extends Attribute { 1913 Type classType; 1914 public ClassAttributeProxy(Type classType) { 1915 super(null); 1916 this.classType = classType; 1917 } 1918 public void accept(Visitor v) { ((ProxyVisitor)v).visitClassAttributeProxy(this); } 1919 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1920 public String toString() { 1921 return "/*proxy class*/" + classType + ".class"; 1922 } 1923 } 1924 1925 static class ArrayAttributeProxy extends Attribute { 1926 List<Attribute> values; 1927 ArrayAttributeProxy(List<Attribute> values) { 1928 super(null); 1929 this.values = values; 1930 } 1931 public void accept(Visitor v) { ((ProxyVisitor)v).visitArrayAttributeProxy(this); } 1932 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1933 public String toString() { 1934 return "{" + values + "}"; 1935 } 1936 } 1937 1938 /** A temporary proxy representing a compound attribute. 1939 */ 1940 static class CompoundAnnotationProxy extends Attribute { 1941 final List<Pair<Name,Attribute>> values; 1942 public CompoundAnnotationProxy(Type type, 1943 List<Pair<Name,Attribute>> values) { 1944 super(type); 1945 this.values = values; 1946 } 1947 public void accept(Visitor v) { ((ProxyVisitor)v).visitCompoundAnnotationProxy(this); } 1948 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1949 public String toString() { 1950 StringBuilder buf = new StringBuilder(); 1951 buf.append("@"); 1952 buf.append(type.tsym.getQualifiedName()); 1953 buf.append("/*proxy*/{"); 1954 boolean first = true; 1955 for (List<Pair<Name,Attribute>> v = values; 1956 v.nonEmpty(); v = v.tail) { 1957 Pair<Name,Attribute> value = v.head; 1958 if (!first) buf.append(","); 1959 first = false; 1960 buf.append(value.fst); 1961 buf.append("="); 1962 buf.append(value.snd); 1963 } 1964 buf.append("}"); 1965 return buf.toString(); 1966 } 1967 } 1968 1969 /** A temporary proxy representing a type annotation. 1970 */ 1971 static class TypeAnnotationProxy { 1972 final CompoundAnnotationProxy compound; 1973 final TypeAnnotationPosition position; 1974 public TypeAnnotationProxy(CompoundAnnotationProxy compound, 1975 TypeAnnotationPosition position) { 1976 this.compound = compound; 1977 this.position = position; 1978 } 1979 } 1980 1981 class AnnotationDeproxy implements ProxyVisitor { 1982 private ClassSymbol requestingOwner; 1983 1984 AnnotationDeproxy(ClassSymbol owner) { 1985 this.requestingOwner = owner; 1986 } 1987 1988 List<Attribute.Compound> deproxyCompoundList(List<CompoundAnnotationProxy> pl) { 1989 // also must fill in types!!!! 1990 ListBuffer<Attribute.Compound> buf = new ListBuffer<>(); 1991 for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l=l.tail) { 1992 buf.append(deproxyCompound(l.head)); 1993 } 1994 return buf.toList(); 1995 } 1996 1997 Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) { 1998 Type annotationType = resolvePossibleProxyType(a.type); 1999 ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = new ListBuffer<>(); 2000 for (List<Pair<Name,Attribute>> l = a.values; 2001 l.nonEmpty(); 2002 l = l.tail) { 2003 MethodSymbol meth = findAccessMethod(annotationType, l.head.fst); 2004 buf.append(new Pair<>(meth, deproxy(meth.type.getReturnType(), l.head.snd))); 2005 } 2006 return new Attribute.Compound(annotationType, buf.toList()); 2007 } 2008 2009 MethodSymbol findAccessMethod(Type container, Name name) { 2010 CompletionFailure failure = null; 2011 try { 2012 for (Symbol sym : container.tsym.members().getSymbolsByName(name)) { 2013 if (sym.kind == MTH && sym.type.getParameterTypes().length() == 0) 2014 return (MethodSymbol) sym; 2015 } 2016 } catch (CompletionFailure ex) { 2017 failure = ex; 2018 } 2019 // The method wasn't found: emit a warning and recover 2020 JavaFileObject prevSource = log.useSource(requestingOwner.classfile); 2021 try { 2022 if (lintClassfile) { 2023 if (failure == null) { 2024 log.warning(Warnings.AnnotationMethodNotFound(container, name)); 2025 } else { 2026 log.warning(Warnings.AnnotationMethodNotFoundReason(container, 2027 name, 2028 failure.getDetailValue()));//diagnostic, if present 2029 } 2030 } 2031 } finally { 2032 log.useSource(prevSource); 2033 } 2034 // Construct a new method type and symbol. Use bottom 2035 // type (typeof null) as return type because this type is 2036 // a subtype of all reference types and can be converted 2037 // to primitive types by unboxing. 2038 MethodType mt = new MethodType(List.nil(), 2039 syms.botType, 2040 List.nil(), 2041 syms.methodClass); 2042 return new MethodSymbol(PUBLIC | ABSTRACT, name, mt, container.tsym); 2043 } 2044 2045 Attribute result; 2046 Type type; 2047 Attribute deproxy(Type t, Attribute a) { 2048 Type oldType = type; 2049 try { 2050 type = t; 2051 a.accept(this); 2052 return result; 2053 } finally { 2054 type = oldType; 2055 } 2056 } 2057 2058 // implement Attribute.Visitor below 2059 2060 public void visitConstant(Attribute.Constant value) { 2061 // assert value.type == type; 2062 result = value; 2063 } 2064 2065 public void visitClass(Attribute.Class clazz) { 2066 result = clazz; 2067 } 2068 2069 public void visitEnum(Attribute.Enum e) { 2070 throw new AssertionError(); // shouldn't happen 2071 } 2072 2073 public void visitCompound(Attribute.Compound compound) { 2074 throw new AssertionError(); // shouldn't happen 2075 } 2076 2077 public void visitArray(Attribute.Array array) { 2078 throw new AssertionError(); // shouldn't happen 2079 } 2080 2081 public void visitError(Attribute.Error e) { 2082 throw new AssertionError(); // shouldn't happen 2083 } 2084 2085 public void visitEnumAttributeProxy(EnumAttributeProxy proxy) { 2086 // type.tsym.flatName() should == proxy.enumFlatName 2087 Type enumType = resolvePossibleProxyType(proxy.enumType); 2088 TypeSymbol enumTypeSym = enumType.tsym; 2089 VarSymbol enumerator = null; 2090 CompletionFailure failure = null; 2091 try { 2092 for (Symbol sym : enumTypeSym.members().getSymbolsByName(proxy.enumerator)) { 2093 if (sym.kind == VAR) { 2094 enumerator = (VarSymbol)sym; 2095 break; 2096 } 2097 } 2098 } 2099 catch (CompletionFailure ex) { 2100 failure = ex; 2101 } 2102 if (enumerator == null) { 2103 if (failure != null) { 2104 log.warning(Warnings.UnknownEnumConstantReason(currentClassFile, 2105 enumTypeSym, 2106 proxy.enumerator, 2107 failure.getDiagnostic())); 2108 } else { 2109 log.warning(Warnings.UnknownEnumConstant(currentClassFile, 2110 enumTypeSym, 2111 proxy.enumerator)); 2112 } 2113 result = new Attribute.Enum(enumTypeSym.type, 2114 new VarSymbol(0, proxy.enumerator, syms.botType, enumTypeSym)); 2115 } else { 2116 result = new Attribute.Enum(enumTypeSym.type, enumerator); 2117 } 2118 } 2119 2120 @Override 2121 public void visitClassAttributeProxy(ClassAttributeProxy proxy) { 2122 Type classType = resolvePossibleProxyType(proxy.classType); 2123 result = new Attribute.Class(types, classType); 2124 } 2125 2126 public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) { 2127 int length = proxy.values.length(); 2128 Attribute[] ats = new Attribute[length]; 2129 Type elemtype = types.elemtype(type); 2130 int i = 0; 2131 for (List<Attribute> p = proxy.values; p.nonEmpty(); p = p.tail) { 2132 ats[i++] = deproxy(elemtype, p.head); 2133 } 2134 result = new Attribute.Array(type, ats); 2135 } 2136 2137 public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) { 2138 result = deproxyCompound(proxy); 2139 } 2140 2141 Type resolvePossibleProxyType(Type t) { 2142 if (t instanceof ProxyType proxyType) { 2143 Assert.check(requestingOwner.owner.kind == MDL); 2144 ModuleSymbol prevCurrentModule = currentModule; 2145 currentModule = (ModuleSymbol) requestingOwner.owner; 2146 try { 2147 return proxyType.resolve(); 2148 } finally { 2149 currentModule = prevCurrentModule; 2150 } 2151 } else { 2152 return t; 2153 } 2154 } 2155 } 2156 2157 class AnnotationDefaultCompleter extends AnnotationDeproxy implements Runnable { 2158 final MethodSymbol sym; 2159 final Attribute value; 2160 final JavaFileObject classFile = currentClassFile; 2161 2162 AnnotationDefaultCompleter(MethodSymbol sym, Attribute value) { 2163 super(currentOwner.kind == MTH 2164 ? currentOwner.enclClass() : (ClassSymbol)currentOwner); 2165 this.sym = sym; 2166 this.value = value; 2167 } 2168 2169 @Override 2170 public void run() { 2171 JavaFileObject previousClassFile = currentClassFile; 2172 try { 2173 // Reset the interim value set earlier in 2174 // attachAnnotationDefault(). 2175 sym.defaultValue = null; 2176 currentClassFile = classFile; 2177 sym.defaultValue = deproxy(sym.type.getReturnType(), value); 2178 } finally { 2179 currentClassFile = previousClassFile; 2180 } 2181 } 2182 2183 @Override 2184 public String toString() { 2185 return " ClassReader store default for " + sym.owner + "." + sym + " is " + value; 2186 } 2187 } 2188 2189 class AnnotationCompleter extends AnnotationDeproxy implements Runnable { 2190 final Symbol sym; 2191 final List<CompoundAnnotationProxy> l; 2192 final JavaFileObject classFile; 2193 2194 AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) { 2195 super(currentOwner.kind == MTH 2196 ? currentOwner.enclClass() : (ClassSymbol)currentOwner); 2197 if (sym.kind == TYP && sym.owner.kind == MDL) { 2198 this.sym = sym.owner; 2199 } else { 2200 this.sym = sym; 2201 } 2202 this.l = l; 2203 this.classFile = currentClassFile; 2204 } 2205 2206 @Override 2207 public void run() { 2208 JavaFileObject previousClassFile = currentClassFile; 2209 try { 2210 currentClassFile = classFile; 2211 List<Attribute.Compound> newList = deproxyCompoundList(l); 2212 for (Attribute.Compound attr : newList) { 2213 if (attr.type.tsym == syms.deprecatedType.tsym) { 2214 sym.flags_field |= (DEPRECATED | DEPRECATED_ANNOTATION); 2215 Attribute forRemoval = attr.member(names.forRemoval); 2216 if (forRemoval instanceof Attribute.Constant constant) { 2217 if (constant.type == syms.booleanType && ((Integer) constant.value) != 0) { 2218 sym.flags_field |= DEPRECATED_REMOVAL; 2219 } 2220 } 2221 } 2222 } 2223 if (sym.annotationsPendingCompletion()) { 2224 sym.setDeclarationAttributes(newList); 2225 } else { 2226 sym.appendAttributes(newList); 2227 } 2228 } finally { 2229 currentClassFile = previousClassFile; 2230 } 2231 } 2232 2233 @Override 2234 public String toString() { 2235 return " ClassReader annotate " + sym.owner + "." + sym + " with " + l; 2236 } 2237 } 2238 2239 class TypeAnnotationCompleter extends AnnotationCompleter { 2240 2241 List<TypeAnnotationProxy> proxies; 2242 2243 TypeAnnotationCompleter(Symbol sym, 2244 List<TypeAnnotationProxy> proxies) { 2245 super(sym, List.nil()); 2246 this.proxies = proxies; 2247 } 2248 2249 List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) { 2250 ListBuffer<Attribute.TypeCompound> buf = new ListBuffer<>(); 2251 for (TypeAnnotationProxy proxy: proxies) { 2252 Attribute.Compound compound = deproxyCompound(proxy.compound); 2253 Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position); 2254 buf.add(typeCompound); 2255 } 2256 return buf.toList(); 2257 } 2258 2259 @Override 2260 public void run() { 2261 JavaFileObject previousClassFile = currentClassFile; 2262 try { 2263 currentClassFile = classFile; 2264 List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies); 2265 sym.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes())); 2266 addTypeAnnotationsToSymbol(sym, newList); 2267 } finally { 2268 currentClassFile = previousClassFile; 2269 } 2270 } 2271 } 2272 2273 /** 2274 * Rewrites types in the given symbol to include type annotations. 2275 * 2276 * <p>The list of type annotations includes annotations for all types in the signature of the 2277 * symbol. Associating the annotations with the correct type requires interpreting the JVMS 2278 * 4.7.20-A target_type to locate the correct type to rewrite, and then interpreting the JVMS 2279 * 4.7.20.2 type_path to associate the annotation with the correct contained type. 2280 */ 2281 private static void addTypeAnnotationsToSymbol( 2282 Symbol s, List<Attribute.TypeCompound> attributes) { 2283 new TypeAnnotationSymbolVisitor(attributes).visit(s, null); 2284 } 2285 2286 private static class TypeAnnotationSymbolVisitor 2287 extends Types.DefaultSymbolVisitor<Void, Void> { 2288 2289 private final List<Attribute.TypeCompound> attributes; 2290 2291 private TypeAnnotationSymbolVisitor(List<Attribute.TypeCompound> attributes) { 2292 this.attributes = attributes; 2293 } 2294 2295 @Override 2296 public Void visitClassSymbol(Symbol.ClassSymbol s, Void unused) { 2297 ClassType t = (ClassType) s.type; 2298 int i = 0; 2299 ListBuffer<Type> interfaces = new ListBuffer<>(); 2300 for (Type itf : t.interfaces_field) { 2301 interfaces.add(addTypeAnnotations(itf, classExtends(i++))); 2302 } 2303 t.interfaces_field = interfaces.toList(); 2304 t.supertype_field = addTypeAnnotations(t.supertype_field, classExtends(65535)); 2305 if (t.typarams_field != null) { 2306 t.typarams_field = 2307 rewriteTypeParameters( 2308 t.typarams_field, TargetType.CLASS_TYPE_PARAMETER_BOUND); 2309 } 2310 return null; 2311 } 2312 2313 @Override 2314 public Void visitMethodSymbol(Symbol.MethodSymbol s, Void unused) { 2315 Type t = s.type; 2316 if (t.hasTag(TypeTag.FORALL)) { 2317 Type.ForAll fa = (Type.ForAll) t; 2318 fa.tvars = rewriteTypeParameters(fa.tvars, TargetType.METHOD_TYPE_PARAMETER_BOUND); 2319 t = fa.qtype; 2320 } 2321 MethodType mt = (MethodType) t; 2322 ListBuffer<Type> argtypes = new ListBuffer<>(); 2323 int i = 0; 2324 for (Symbol.VarSymbol param : s.params) { 2325 param.type = addTypeAnnotations(param.type, methodFormalParameter(i++)); 2326 argtypes.add(param.type); 2327 } 2328 mt.argtypes = argtypes.toList(); 2329 ListBuffer<Type> thrown = new ListBuffer<>(); 2330 i = 0; 2331 for (Type thrownType : mt.thrown) { 2332 thrown.add(addTypeAnnotations(thrownType, thrownType(i++))); 2333 } 2334 mt.thrown = thrown.toList(); 2335 mt.restype = addTypeAnnotations(mt.restype, TargetType.METHOD_RETURN); 2336 2337 Type recvtype = mt.recvtype != null ? mt.recvtype : s.implicitReceiverType(); 2338 if (recvtype != null) { 2339 Type annotated = addTypeAnnotations(recvtype, TargetType.METHOD_RECEIVER); 2340 if (annotated != recvtype) { 2341 mt.recvtype = annotated; 2342 } 2343 } 2344 return null; 2345 } 2346 2347 @Override 2348 public Void visitVarSymbol(Symbol.VarSymbol s, Void unused) { 2349 s.type = addTypeAnnotations(s.type, TargetType.FIELD); 2350 return null; 2351 } 2352 2353 @Override 2354 public Void visitSymbol(Symbol s, Void unused) { 2355 return null; 2356 } 2357 2358 private List<Type> rewriteTypeParameters(List<Type> tvars, TargetType boundType) { 2359 ListBuffer<Type> tvarbuf = new ListBuffer<>(); 2360 int typeVariableIndex = 0; 2361 for (Type tvar : tvars) { 2362 Type bound = tvar.getUpperBound(); 2363 if (bound.isCompound()) { 2364 ClassType ct = (ClassType) bound; 2365 int boundIndex = 0; 2366 if (ct.supertype_field != null) { 2367 ct.supertype_field = 2368 addTypeAnnotations( 2369 ct.supertype_field, 2370 typeParameterBound( 2371 boundType, typeVariableIndex, boundIndex++)); 2372 } 2373 ListBuffer<Type> itfbuf = new ListBuffer<>(); 2374 for (Type itf : ct.interfaces_field) { 2375 itfbuf.add( 2376 addTypeAnnotations( 2377 itf, 2378 typeParameterBound( 2379 boundType, typeVariableIndex, boundIndex++))); 2380 } 2381 ct.interfaces_field = itfbuf.toList(); 2382 } else { 2383 bound = 2384 addTypeAnnotations( 2385 bound, 2386 typeParameterBound( 2387 boundType, 2388 typeVariableIndex, 2389 bound.isInterface() ? 1 : 0)); 2390 } 2391 ((TypeVar) tvar).setUpperBound(bound); 2392 tvarbuf.add(tvar); 2393 typeVariableIndex++; 2394 } 2395 return tvarbuf.toList(); 2396 } 2397 2398 private Type addTypeAnnotations(Type type, TargetType targetType) { 2399 return addTypeAnnotations(type, pos -> pos.type == targetType); 2400 } 2401 2402 private Type addTypeAnnotations(Type type, Predicate<TypeAnnotationPosition> filter) { 2403 Assert.checkNonNull(type); 2404 2405 // Find type annotations that match the given target type 2406 ListBuffer<Attribute.TypeCompound> filtered = new ListBuffer<>(); 2407 for (Attribute.TypeCompound attribute : this.attributes) { 2408 if (filter.test(attribute.position)) { 2409 filtered.add(attribute); 2410 } 2411 } 2412 if (filtered.isEmpty()) { 2413 return type; 2414 } 2415 2416 // Group the matching annotations by their type path. Each group of annotations will be 2417 // added to a type at that location. 2418 Map<List<TypeAnnotationPosition.TypePathEntry>, ListBuffer<Attribute.TypeCompound>> 2419 attributesByPath = new HashMap<>(); 2420 for (Attribute.TypeCompound attribute : filtered.toList()) { 2421 attributesByPath 2422 .computeIfAbsent(attribute.position.location, k -> new ListBuffer<>()) 2423 .add(attribute); 2424 } 2425 2426 // Search the structure of the type to find the contained types at each type path 2427 Map<Type, List<Attribute.TypeCompound>> attributesByType = new HashMap<>(); 2428 new TypeAnnotationLocator(attributesByPath, attributesByType).visit(type, List.nil()); 2429 2430 // Rewrite the type and add the annotations 2431 type = new TypeAnnotationTypeMapping(attributesByType).visit(type, null); 2432 Assert.check(attributesByType.isEmpty(), "Failed to apply annotations to types"); 2433 2434 return type; 2435 } 2436 2437 private static Predicate<TypeAnnotationPosition> typeParameterBound( 2438 TargetType targetType, int parameterIndex, int boundIndex) { 2439 return pos -> 2440 pos.type == targetType 2441 && pos.parameter_index == parameterIndex 2442 && pos.bound_index == boundIndex; 2443 } 2444 2445 private static Predicate<TypeAnnotationPosition> methodFormalParameter(int index) { 2446 return pos -> 2447 pos.type == TargetType.METHOD_FORMAL_PARAMETER && pos.parameter_index == index; 2448 } 2449 2450 private static Predicate<TypeAnnotationPosition> thrownType(int index) { 2451 return pos -> pos.type == TargetType.THROWS && pos.type_index == index; 2452 } 2453 2454 private static Predicate<TypeAnnotationPosition> classExtends(int index) { 2455 return pos -> pos.type == TargetType.CLASS_EXTENDS && pos.type_index == index; 2456 } 2457 } 2458 2459 /** 2460 * Visit all contained types, assembling a type path to represent the current location, and 2461 * record the types at each type path that need to be annotated. 2462 */ 2463 private static class TypeAnnotationLocator 2464 extends Types.DefaultTypeVisitor<Void, List<TypeAnnotationPosition.TypePathEntry>> { 2465 private final Map<List<TypeAnnotationPosition.TypePathEntry>, 2466 ListBuffer<Attribute.TypeCompound>> attributesByPath; 2467 private final Map<Type, List<Attribute.TypeCompound>> attributesByType; 2468 2469 private TypeAnnotationLocator( 2470 Map<List<TypeAnnotationPosition.TypePathEntry>, ListBuffer<Attribute.TypeCompound>> 2471 attributesByPath, 2472 Map<Type, List<Attribute.TypeCompound>> attributesByType) { 2473 this.attributesByPath = attributesByPath; 2474 this.attributesByType = attributesByType; 2475 } 2476 2477 @Override 2478 public Void visitClassType(ClassType t, List<TypeAnnotationPosition.TypePathEntry> path) { 2479 // As described in JVMS 4.7.20.2, type annotations on nested types are located with 2480 // 'left-to-right' steps starting on 'the outermost part of the type for which a type 2481 // annotation is admissible'. So the current path represents the outermost containing 2482 // type of the type being visited, and we add type path steps for every contained nested 2483 // type. 2484 List<ClassType> enclosing = List.nil(); 2485 for (Type curr = t; 2486 curr != null && curr != Type.noType; 2487 curr = curr.getEnclosingType()) { 2488 enclosing = enclosing.prepend((ClassType) curr); 2489 } 2490 for (ClassType te : enclosing) { 2491 if (te.typarams_field != null) { 2492 int i = 0; 2493 for (Type typaram : te.typarams_field) { 2494 visit(typaram, path.append(new TypeAnnotationPosition.TypePathEntry( 2495 TypeAnnotationPosition.TypePathEntryKind.TYPE_ARGUMENT, i++))); 2496 } 2497 } 2498 visitType(te, path); 2499 path = path.append(TypeAnnotationPosition.TypePathEntry.INNER_TYPE); 2500 } 2501 return null; 2502 } 2503 2504 @Override 2505 public Void visitWildcardType( 2506 WildcardType t, List<TypeAnnotationPosition.TypePathEntry> path) { 2507 visit(t.type, path.append(TypeAnnotationPosition.TypePathEntry.WILDCARD)); 2508 return super.visitWildcardType(t, path); 2509 } 2510 2511 @Override 2512 public Void visitArrayType(ArrayType t, List<TypeAnnotationPosition.TypePathEntry> path) { 2513 visit(t.elemtype, path.append(TypeAnnotationPosition.TypePathEntry.ARRAY)); 2514 return super.visitArrayType(t, path); 2515 } 2516 2517 @Override 2518 public Void visitType(Type t, List<TypeAnnotationPosition.TypePathEntry> path) { 2519 ListBuffer<Attribute.TypeCompound> attributes = attributesByPath.remove(path); 2520 if (attributes != null) { 2521 attributesByType.put(t, attributes.toList()); 2522 } 2523 return null; 2524 } 2525 } 2526 2527 /** A type mapping that rewrites the type to include type annotations. */ 2528 private static class TypeAnnotationTypeMapping extends Type.StructuralTypeMapping<Void> { 2529 2530 private final Map<Type, List<Attribute.TypeCompound>> attributesByType; 2531 2532 private TypeAnnotationTypeMapping( 2533 Map<Type, List<Attribute.TypeCompound>> attributesByType) { 2534 this.attributesByType = attributesByType; 2535 } 2536 2537 private <T extends Type> Type reannotate(T t, BiFunction<T, Void, Type> f) { 2538 // We're relying on object identify of Type instances to record where the annotations 2539 // need to be added, so we have to retrieve the annotations for each type before 2540 // rewriting it, and then add them after its contained types have been rewritten. 2541 List<Attribute.TypeCompound> attributes = attributesByType.remove(t); 2542 Type mapped = f.apply(t, null); 2543 if (attributes == null) { 2544 return mapped; 2545 } 2546 // Runtime-visible and -invisible annotations are completed separately, so if the same 2547 // type has annotations from both it will get annotated twice. 2548 TypeMetadata.Annotations existing = mapped.getMetadata(TypeMetadata.Annotations.class); 2549 if (existing != null) { 2550 existing.annotationBuffer().addAll(attributes); 2551 return mapped; 2552 } 2553 return mapped.annotatedType(attributes); 2554 } 2555 2556 @Override 2557 public Type visitClassType(ClassType t, Void unused) { 2558 return reannotate(t, super::visitClassType); 2559 } 2560 2561 @Override 2562 public Type visitWildcardType(WildcardType t, Void unused) { 2563 return reannotate(t, super::visitWildcardType); 2564 } 2565 2566 @Override 2567 public Type visitArrayType(ArrayType t, Void unused) { 2568 return reannotate(t, super::visitArrayType); 2569 } 2570 2571 @Override 2572 public Type visitType(Type t, Void unused) { 2573 return reannotate(t, (x, u) -> x); 2574 } 2575 } 2576 2577 /************************************************************************ 2578 * Reading Symbols 2579 ***********************************************************************/ 2580 2581 /** Read a field. 2582 */ 2583 VarSymbol readField() { 2584 char rawFlags = nextChar(); 2585 long flags = adjustFieldFlags(rawFlags); 2586 Name name = poolReader.getName(nextChar()); 2587 Type type = poolReader.getType(nextChar()); 2588 VarSymbol v = new VarSymbol(flags, name, type, currentOwner); 2589 readMemberAttrs(v); 2590 if (Integer.bitCount(rawFlags & (PUBLIC | PRIVATE | PROTECTED)) > 1 || 2591 Integer.bitCount(rawFlags & (FINAL | VOLATILE)) > 1) 2592 throw badClassFile("illegal.flag.combo", Flags.toString((long)rawFlags), "field", v); 2593 return v; 2594 } 2595 2596 /** Read a method. 2597 */ 2598 MethodSymbol readMethod() { 2599 char rawFlags = nextChar(); 2600 long flags = adjustMethodFlags(rawFlags); 2601 Name name = poolReader.getName(nextChar()); 2602 Type type = poolReader.getType(nextChar()); 2603 if (currentOwner.isInterface() && 2604 (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) { 2605 if (majorVersion > Version.V52.major || 2606 (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) { 2607 if ((flags & (STATIC | PRIVATE)) == 0) { 2608 currentOwner.flags_field |= DEFAULT; 2609 flags |= DEFAULT | ABSTRACT; 2610 } 2611 } else { 2612 //protect against ill-formed classfiles 2613 throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface", 2614 Integer.toString(majorVersion), 2615 Integer.toString(minorVersion)); 2616 } 2617 } 2618 validateMethodType(name, type); 2619 if (name == names.init && currentOwner.hasOuterInstance()) { 2620 // Sometimes anonymous classes don't have an outer 2621 // instance, however, there is no reliable way to tell so 2622 // we never strip this$n 2623 // ditto for local classes. Local classes that have an enclosing method set 2624 // won't pass the "hasOuterInstance" check above, but those that don't have an 2625 // enclosing method (i.e. from initializers) will pass that check. 2626 boolean local = !currentOwner.owner.members().includes(currentOwner, LookupKind.NON_RECURSIVE); 2627 if (!currentOwner.name.isEmpty() && !local) 2628 type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()), 2629 type.getReturnType(), 2630 type.getThrownTypes(), 2631 syms.methodClass); 2632 } 2633 MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner); 2634 if (types.isSignaturePolymorphic(m)) { 2635 m.flags_field |= SIGNATURE_POLYMORPHIC; 2636 } 2637 if (saveParameterNames) 2638 initParameterNames(m); 2639 Symbol prevOwner = currentOwner; 2640 currentOwner = m; 2641 try { 2642 readMemberAttrs(m); 2643 } finally { 2644 currentOwner = prevOwner; 2645 } 2646 validateMethodType(name, m.type); 2647 setParameters(m, type); 2648 2649 if (Integer.bitCount(rawFlags & (PUBLIC | PRIVATE | PROTECTED)) > 1) 2650 throw badClassFile("illegal.flag.combo", Flags.toString((long)rawFlags), "method", m); 2651 if ((flags & VARARGS) != 0) { 2652 final Type last = type.getParameterTypes().last(); 2653 if (last == null || !last.hasTag(ARRAY)) { 2654 m.flags_field &= ~VARARGS; 2655 throw badClassFile("malformed.vararg.method", m); 2656 } 2657 } 2658 2659 return m; 2660 } 2661 2662 void validateMethodType(Name name, Type t) { 2663 if ((!t.hasTag(TypeTag.METHOD) && !t.hasTag(TypeTag.FORALL)) || 2664 (name == names.init && !t.getReturnType().hasTag(TypeTag.VOID))) { 2665 throw badClassFile("method.descriptor.invalid", name); 2666 } 2667 } 2668 2669 private List<Type> adjustMethodParams(long flags, List<Type> args) { 2670 if (args.isEmpty()) { 2671 return args; 2672 } 2673 boolean isVarargs = (flags & VARARGS) != 0; 2674 if (isVarargs) { 2675 Type varargsElem = args.last(); 2676 ListBuffer<Type> adjustedArgs = new ListBuffer<>(); 2677 for (Type t : args) { 2678 adjustedArgs.append(t != varargsElem ? 2679 t : 2680 ((ArrayType)t).makeVarargs()); 2681 } 2682 args = adjustedArgs.toList(); 2683 } 2684 return args.tail; 2685 } 2686 2687 /** 2688 * Init the parameter names array. 2689 * Parameter names are currently inferred from the names in the 2690 * LocalVariableTable attributes of a Code attribute. 2691 * (Note: this means parameter names are currently not available for 2692 * methods without a Code attribute.) 2693 * This method initializes an array in which to store the name indexes 2694 * of parameter names found in LocalVariableTable attributes. It is 2695 * slightly supersized to allow for additional slots with a start_pc of 0. 2696 */ 2697 void initParameterNames(MethodSymbol sym) { 2698 // make allowance for synthetic parameters. 2699 final int excessSlots = 4; 2700 int expectedParameterSlots = 2701 Code.width(sym.type.getParameterTypes()) + excessSlots; 2702 if (parameterNameIndicesLvt == null 2703 || parameterNameIndicesLvt.length < expectedParameterSlots) { 2704 parameterNameIndicesLvt = new int[expectedParameterSlots]; 2705 } else 2706 Arrays.fill(parameterNameIndicesLvt, 0); 2707 } 2708 2709 /** 2710 * Set the parameters for a method symbol, including any names and 2711 * annotations that were read. 2712 * 2713 * <p>The type of the symbol may have changed while reading the 2714 * method attributes (see the Signature attribute). This may be 2715 * because of generic information or because anonymous synthetic 2716 * parameters were added. The original type (as read from the 2717 * method descriptor) is used to help guess the existence of 2718 * anonymous synthetic parameters. 2719 */ 2720 void setParameters(MethodSymbol sym, Type jvmType) { 2721 int firstParamLvt = ((sym.flags() & STATIC) == 0) ? 1 : 0; 2722 // the code in readMethod may have skipped the first 2723 // parameter when setting up the MethodType. If so, we 2724 // make a corresponding allowance here for the position of 2725 // the first parameter. Note that this assumes the 2726 // skipped parameter has a width of 1 -- i.e. it is not 2727 // a double width type (long or double.) 2728 if (sym.name == names.init && currentOwner.hasOuterInstance()) { 2729 // Sometimes anonymous classes don't have an outer 2730 // instance, however, there is no reliable way to tell so 2731 // we never strip this$n 2732 if (!currentOwner.name.isEmpty()) 2733 firstParamLvt += 1; 2734 } 2735 2736 if (sym.type != jvmType) { 2737 // reading the method attributes has caused the 2738 // symbol's type to be changed. (i.e. the Signature 2739 // attribute.) This may happen if there are hidden 2740 // (synthetic) parameters in the descriptor, but not 2741 // in the Signature. The position of these hidden 2742 // parameters is unspecified; for now, assume they are 2743 // at the beginning, and so skip over them. The 2744 // primary case for this is two hidden parameters 2745 // passed into Enum constructors. 2746 int skip = Code.width(jvmType.getParameterTypes()) 2747 - Code.width(sym.type.getParameterTypes()); 2748 firstParamLvt += skip; 2749 } 2750 Set<Name> paramNames = new HashSet<>(); 2751 ListBuffer<VarSymbol> params = new ListBuffer<>(); 2752 // we maintain two index pointers, one for the LocalVariableTable attribute 2753 // and the other for the MethodParameters attribute. 2754 // This is needed as the MethodParameters attribute may contain 2755 // name_index = 0 in which case we want to fall back to the LocalVariableTable. 2756 // In such case, we still want to read the flags from the MethodParameters with that index. 2757 int nameIndexLvt = firstParamLvt; 2758 int nameIndexMp = 0; 2759 int annotationIndex = 0; 2760 for (Type t: sym.type.getParameterTypes()) { 2761 VarSymbol param = parameter(nameIndexMp, nameIndexLvt, t, sym, paramNames); 2762 params.append(param); 2763 if (parameterAnnotations != null) { 2764 ParameterAnnotations annotations = parameterAnnotations[annotationIndex]; 2765 if (annotations != null && annotations.proxies != null 2766 && !annotations.proxies.isEmpty()) { 2767 annotate.normal(new AnnotationCompleter(param, annotations.proxies)); 2768 } 2769 } 2770 nameIndexLvt += Code.width(t); 2771 nameIndexMp++; 2772 annotationIndex++; 2773 } 2774 if (parameterAnnotations != null && parameterAnnotations.length != annotationIndex) { 2775 throw badClassFile("bad.runtime.invisible.param.annotations", sym); 2776 } 2777 Assert.checkNull(sym.params); 2778 sym.params = params.toList(); 2779 parameterAnnotations = null; 2780 parameterNameIndicesLvt = null; 2781 parameterNameIndicesMp = null; 2782 parameterAccessFlags = null; 2783 } 2784 2785 /** 2786 * Creates the parameter at the position {@code mpIndex} in the parameter list of the owning method. 2787 * Flags are optionally read from the MethodParameters attribute. 2788 * Names are optionally read from the MethodParameters attribute. If the constant pool index 2789 * of the name is 0, then the name is optionally read from the LocalVariableTable attribute. 2790 * @param mpIndex the index of the parameter in the MethodParameters attribute 2791 * @param lvtIndex the index of the parameter in the LocalVariableTable attribute 2792 */ 2793 private VarSymbol parameter(int mpIndex, int lvtIndex, Type t, MethodSymbol owner, Set<Name> exclude) { 2794 long flags = PARAMETER; 2795 Name argName; 2796 if (parameterAccessFlags != null && mpIndex < parameterAccessFlags.length 2797 && parameterAccessFlags[mpIndex] != 0) { 2798 flags |= parameterAccessFlags[mpIndex]; 2799 } 2800 if (parameterNameIndicesMp != null 2801 // if name_index is 0, then we might still get a name from the LocalVariableTable 2802 && parameterNameIndicesMp[mpIndex] != 0) { 2803 argName = optPoolEntry(parameterNameIndicesMp[mpIndex], poolReader::getName, names.empty); 2804 flags |= NAME_FILLED; 2805 } else if (parameterNameIndicesLvt != null && lvtIndex < parameterNameIndicesLvt.length 2806 && parameterNameIndicesLvt[lvtIndex] != 0) { 2807 argName = optPoolEntry(parameterNameIndicesLvt[lvtIndex], poolReader::getName, names.empty); 2808 flags |= NAME_FILLED; 2809 } else { 2810 String prefix = "arg"; 2811 while (true) { 2812 argName = names.fromString(prefix + exclude.size()); 2813 if (!exclude.contains(argName)) 2814 break; 2815 prefix += "$"; 2816 } 2817 } 2818 exclude.add(argName); 2819 return new ParamSymbol(flags, argName, t, owner); 2820 } 2821 2822 /** 2823 * skip n bytes 2824 */ 2825 void skipBytes(int n) { 2826 bp = bp + n; 2827 } 2828 2829 /** Skip a field or method 2830 */ 2831 void skipMember() { 2832 bp = bp + 6; 2833 char ac = nextChar(); 2834 for (int i = 0; i < ac; i++) { 2835 bp = bp + 2; 2836 int attrLen = nextInt(); 2837 bp = bp + attrLen; 2838 } 2839 } 2840 2841 void skipInnerClasses() { 2842 int n = nextChar(); 2843 for (int i = 0; i < n; i++) { 2844 nextChar(); 2845 nextChar(); 2846 nextChar(); 2847 nextChar(); 2848 } 2849 } 2850 2851 /** Enter type variables of this classtype and all enclosing ones in 2852 * `typevars'. 2853 */ 2854 protected void enterTypevars(Symbol sym, Type t) { 2855 if (t.getEnclosingType() != null) { 2856 if (!t.getEnclosingType().hasTag(TypeTag.NONE)) { 2857 enterTypevars(sym.owner, t.getEnclosingType()); 2858 } 2859 } else if (sym.kind == MTH && !sym.isStatic()) { 2860 enterTypevars(sym.owner, sym.owner.type); 2861 } 2862 for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail) { 2863 typevars.enter(xs.head.tsym); 2864 } 2865 } 2866 2867 protected ClassSymbol enterClass(Name name) { 2868 return syms.enterClass(currentModule, name); 2869 } 2870 2871 protected ClassSymbol enterClass(Name name, TypeSymbol owner) { 2872 return syms.enterClass(currentModule, name, owner); 2873 } 2874 2875 /** Read contents of a given class symbol `c'. Both external and internal 2876 * versions of an inner class are read. 2877 */ 2878 void readClass(ClassSymbol c) { 2879 ClassType ct = (ClassType)c.type; 2880 2881 // allocate scope for members 2882 c.members_field = WriteableScope.create(c); 2883 2884 // prepare type variable table 2885 typevars = typevars.dup(currentOwner); 2886 if (ct.getEnclosingType().hasTag(CLASS)) 2887 enterTypevars(c.owner, ct.getEnclosingType()); 2888 2889 // read flags, or skip if this is an inner class 2890 long f = nextChar(); 2891 long flags = adjustClassFlags(f); 2892 if ((flags & MODULE) == 0) { 2893 if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags; 2894 // read own class name and check that it matches 2895 currentModule = c.packge().modle; 2896 ClassSymbol self = poolReader.getClass(nextChar()); 2897 if (c != self) { 2898 throw badClassFile("class.file.wrong.class", 2899 self.flatname); 2900 } 2901 } else { 2902 if (majorVersion < Version.V53.major) { 2903 throw badClassFile("anachronistic.module.info", 2904 Integer.toString(majorVersion), 2905 Integer.toString(minorVersion)); 2906 } 2907 c.flags_field = flags; 2908 if (c.owner.kind != MDL) { 2909 throw badClassFile("module.info.definition.expected"); 2910 } 2911 currentModule = (ModuleSymbol) c.owner; 2912 int this_class = nextChar(); 2913 // temp, no check on this_class 2914 } 2915 2916 // class attributes must be read before class 2917 // skip ahead to read class attributes 2918 int startbp = bp; 2919 nextChar(); 2920 char interfaceCount = nextChar(); 2921 bp += interfaceCount * 2; 2922 char fieldCount = nextChar(); 2923 for (int i = 0; i < fieldCount; i++) skipMember(); 2924 char methodCount = nextChar(); 2925 for (int i = 0; i < methodCount; i++) skipMember(); 2926 readClassAttrs(c); 2927 2928 if (c.permitted != null && !c.permitted.isEmpty()) { 2929 c.flags_field |= SEALED; 2930 } 2931 2932 // reset and read rest of classinfo 2933 bp = startbp; 2934 int n = nextChar(); 2935 if ((flags & MODULE) != 0 && n > 0) { 2936 throw badClassFile("module.info.invalid.super.class"); 2937 } 2938 if (ct.supertype_field == null) 2939 ct.supertype_field = 2940 optPoolEntry(n, idx -> poolReader.getClass(idx).erasure(types), Type.noType); 2941 n = nextChar(); 2942 List<Type> is = List.nil(); 2943 for (int i = 0; i < n; i++) { 2944 Type _inter = poolReader.getClass(nextChar()).erasure(types); 2945 is = is.prepend(_inter); 2946 } 2947 if (ct.interfaces_field == null) 2948 ct.interfaces_field = is.reverse(); 2949 2950 Assert.check(fieldCount == nextChar()); 2951 for (int i = 0; i < fieldCount; i++) enterMember(c, readField()); 2952 Assert.check(methodCount == nextChar()); 2953 for (int i = 0; i < methodCount; i++) enterMember(c, readMethod()); 2954 if (c.isRecord()) { 2955 for (RecordComponent rc: c.getRecordComponents()) { 2956 rc.accessor = lookupMethod(c, rc.name, List.nil()); 2957 } 2958 } 2959 typevars = typevars.leave(); 2960 } 2961 2962 private MethodSymbol lookupMethod(TypeSymbol tsym, Name name, List<Type> argtypes) { 2963 for (Symbol s : tsym.members().getSymbolsByName(name, s -> s.kind == MTH)) { 2964 if (types.isSameTypes(s.type.getParameterTypes(), argtypes)) { 2965 return (MethodSymbol) s; 2966 } 2967 } 2968 return null; 2969 } 2970 2971 /** Read inner class info. For each inner/outer pair allocate a 2972 * member class. 2973 */ 2974 void readInnerClasses(ClassSymbol c) { 2975 int n = nextChar(); 2976 for (int i = 0; i < n; i++) { 2977 nextChar(); // skip inner class symbol 2978 int outerIdx = nextChar(); 2979 int nameIdx = nextChar(); 2980 ClassSymbol outer = optPoolEntry(outerIdx, poolReader::getClass, null); 2981 Name name = optPoolEntry(nameIdx, poolReader::getName, names.empty); 2982 if (name == null) name = names.empty; 2983 long flags = adjustClassFlags(nextChar()); 2984 if (outer != null) { // we have a member class 2985 if (name == names.empty) 2986 name = names.one; 2987 ClassSymbol member = enterClass(name, outer); 2988 if ((flags & STATIC) == 0) { 2989 ((ClassType)member.type).setEnclosingType(outer.type); 2990 if (member.erasure_field != null) 2991 ((ClassType)member.erasure_field).setEnclosingType(types.erasure(outer.type)); 2992 } 2993 if (c == outer && member.owner == c) { 2994 member.flags_field = flags; 2995 enterMember(c, member); 2996 } 2997 } 2998 } 2999 } 3000 3001 /** Read a class definition from the bytes in buf. 3002 */ 3003 private void readClassBuffer(ClassSymbol c) throws IOException { 3004 int magic = nextInt(); 3005 if (magic != JAVA_MAGIC) 3006 throw badClassFile("illegal.start.of.class.file"); 3007 3008 minorVersion = nextChar(); 3009 majorVersion = nextChar(); 3010 int maxMajor = Version.MAX().major; 3011 int maxMinor = Version.MAX().minor; 3012 boolean previewClassFile = 3013 minorVersion == ClassFile.PREVIEW_MINOR_VERSION; 3014 if (majorVersion > maxMajor || 3015 majorVersion * 1000 + minorVersion < 3016 Version.MIN().major * 1000 + Version.MIN().minor) { 3017 if (majorVersion == (maxMajor + 1) && !previewClassFile) 3018 log.warning(Warnings.BigMajorVersion(currentClassFile, 3019 majorVersion, 3020 maxMajor)); 3021 else 3022 throw badClassFile("wrong.version", 3023 Integer.toString(majorVersion), 3024 Integer.toString(minorVersion), 3025 Integer.toString(maxMajor), 3026 Integer.toString(maxMinor)); 3027 } 3028 utf8validation = majorVersion < V48.major ? Convert.Validation.PREJDK14 : Convert.Validation.STRICT; 3029 3030 if (previewClassFile) { 3031 if (!preview.isEnabled()) { 3032 log.error(preview.disabledError(currentClassFile, majorVersion)); 3033 } else { 3034 preview.warnPreview(c.classfile, majorVersion); 3035 } 3036 } 3037 3038 poolReader = new PoolReader(this, names, syms); 3039 bp = poolReader.readPool(buf, bp); 3040 if (signatureBuffer.length < bp) { 3041 int ns = Integer.highestOneBit(bp) << 1; 3042 signatureBuffer = new byte[ns]; 3043 } 3044 readClass(c); 3045 if (previewClassFile) { 3046 if ((c.flags_field & SYNTHETIC) != 0 && 3047 c.owner.kind == PCK && 3048 (c.flags_field & AUXILIARY) == 0 && 3049 (c.flags_field & FINAL) != 0) { 3050 c.flags_field |= UNNAMED_CLASS; 3051 } 3052 } 3053 } 3054 3055 public void readClassFile(ClassSymbol c) { 3056 currentOwner = c; 3057 currentClassFile = c.classfile; 3058 warnedAttrs.clear(); 3059 filling = true; 3060 target = null; 3061 repeatable = null; 3062 try { 3063 bp = 0; 3064 buf.reset(); 3065 try (InputStream input = c.classfile.openInputStream()) { 3066 buf.appendStream(input); 3067 } 3068 readClassBuffer(c); 3069 if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) { 3070 List<Type> missing = missingTypeVariables; 3071 List<Type> found = foundTypeVariables; 3072 missingTypeVariables = List.nil(); 3073 foundTypeVariables = List.nil(); 3074 interimUses = List.nil(); 3075 interimProvides = List.nil(); 3076 filling = false; 3077 ClassType ct = (ClassType)currentOwner.type; 3078 ct.supertype_field = 3079 types.subst(ct.supertype_field, missing, found); 3080 ct.interfaces_field = 3081 types.subst(ct.interfaces_field, missing, found); 3082 ct.typarams_field = 3083 types.substBounds(ct.typarams_field, missing, found); 3084 for (List<Type> types = ct.typarams_field; types.nonEmpty(); types = types.tail) { 3085 types.head.tsym.type = types.head; 3086 } 3087 } else if (missingTypeVariables.isEmpty() != 3088 foundTypeVariables.isEmpty()) { 3089 Name name = missingTypeVariables.head.tsym.name; 3090 throw badClassFile("undecl.type.var", name); 3091 } 3092 3093 if ((c.flags_field & Flags.ANNOTATION) != 0) { 3094 c.setAnnotationTypeMetadata(new AnnotationTypeMetadata(c, new CompleterDeproxy(c, target, repeatable))); 3095 } else { 3096 c.setAnnotationTypeMetadata(AnnotationTypeMetadata.notAnAnnotationType()); 3097 } 3098 3099 if (c == currentModule.module_info) { 3100 if (interimUses.nonEmpty() || interimProvides.nonEmpty()) { 3101 Assert.check(currentModule.isCompleted()); 3102 currentModule.usesProvidesCompleter = 3103 new UsesProvidesCompleter(currentModule, interimUses, interimProvides); 3104 } else { 3105 currentModule.uses = List.nil(); 3106 currentModule.provides = List.nil(); 3107 } 3108 } 3109 } catch (IOException | ClosedFileSystemException ex) { 3110 throw badClassFile("unable.to.access.file", ex.toString()); 3111 } catch (ArrayIndexOutOfBoundsException ex) { 3112 throw badClassFile("bad.class.file", c.flatname); 3113 } finally { 3114 interimUses = List.nil(); 3115 interimProvides = List.nil(); 3116 missingTypeVariables = List.nil(); 3117 foundTypeVariables = List.nil(); 3118 filling = false; 3119 } 3120 } 3121 3122 /** We can only read a single class file at a time; this 3123 * flag keeps track of when we are currently reading a class 3124 * file. 3125 */ 3126 public boolean filling = false; 3127 3128 /************************************************************************ 3129 * Adjusting flags 3130 ***********************************************************************/ 3131 3132 long adjustFieldFlags(long flags) { 3133 return flags; 3134 } 3135 3136 long adjustMethodFlags(long flags) { 3137 if ((flags & ACC_BRIDGE) != 0) { 3138 flags &= ~ACC_BRIDGE; 3139 flags |= BRIDGE; 3140 } 3141 if ((flags & ACC_VARARGS) != 0) { 3142 flags &= ~ACC_VARARGS; 3143 flags |= VARARGS; 3144 } 3145 return flags; 3146 } 3147 3148 long adjustClassFlags(long flags) { 3149 if ((flags & ACC_MODULE) != 0) { 3150 flags &= ~ACC_MODULE; 3151 flags |= MODULE; 3152 } 3153 return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded 3154 } 3155 3156 /** 3157 * A subclass of JavaFileObject for the sourcefile attribute found in a classfile. 3158 * The attribute is only the last component of the original filename, so is unlikely 3159 * to be valid as is, so operations other than those to access the name throw 3160 * UnsupportedOperationException 3161 */ 3162 private static class SourceFileObject implements JavaFileObject { 3163 3164 /** The file's name. 3165 */ 3166 private final Name name; 3167 3168 public SourceFileObject(Name name) { 3169 this.name = name; 3170 } 3171 3172 @Override @DefinedBy(Api.COMPILER) 3173 public URI toUri() { 3174 try { 3175 return new URI(null, name.toString(), null); 3176 } catch (URISyntaxException e) { 3177 throw new PathFileObject.CannotCreateUriError(name.toString(), e); 3178 } 3179 } 3180 3181 @Override @DefinedBy(Api.COMPILER) 3182 public String getName() { 3183 return name.toString(); 3184 } 3185 3186 @Override @DefinedBy(Api.COMPILER) 3187 public JavaFileObject.Kind getKind() { 3188 return BaseFileManager.getKind(getName()); 3189 } 3190 3191 @Override @DefinedBy(Api.COMPILER) 3192 public InputStream openInputStream() { 3193 throw new UnsupportedOperationException(); 3194 } 3195 3196 @Override @DefinedBy(Api.COMPILER) 3197 public OutputStream openOutputStream() { 3198 throw new UnsupportedOperationException(); 3199 } 3200 3201 @Override @DefinedBy(Api.COMPILER) 3202 public CharBuffer getCharContent(boolean ignoreEncodingErrors) { 3203 throw new UnsupportedOperationException(); 3204 } 3205 3206 @Override @DefinedBy(Api.COMPILER) 3207 public Reader openReader(boolean ignoreEncodingErrors) { 3208 throw new UnsupportedOperationException(); 3209 } 3210 3211 @Override @DefinedBy(Api.COMPILER) 3212 public Writer openWriter() { 3213 throw new UnsupportedOperationException(); 3214 } 3215 3216 @Override @DefinedBy(Api.COMPILER) 3217 public long getLastModified() { 3218 throw new UnsupportedOperationException(); 3219 } 3220 3221 @Override @DefinedBy(Api.COMPILER) 3222 public boolean delete() { 3223 throw new UnsupportedOperationException(); 3224 } 3225 3226 @Override @DefinedBy(Api.COMPILER) 3227 public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) { 3228 return true; // fail-safe mode 3229 } 3230 3231 @Override @DefinedBy(Api.COMPILER) 3232 public NestingKind getNestingKind() { 3233 return null; 3234 } 3235 3236 @Override @DefinedBy(Api.COMPILER) 3237 public Modifier getAccessLevel() { 3238 return null; 3239 } 3240 3241 /** 3242 * Check if two file objects are equal. 3243 * SourceFileObjects are just placeholder objects for the value of a 3244 * SourceFile attribute, and do not directly represent specific files. 3245 * Two SourceFileObjects are equal if their names are equal. 3246 */ 3247 @Override 3248 public boolean equals(Object other) { 3249 if (this == other) 3250 return true; 3251 return (other instanceof SourceFileObject sourceFileObject) 3252 && name.equals(sourceFileObject.name); 3253 } 3254 3255 @Override 3256 public int hashCode() { 3257 return name.hashCode(); 3258 } 3259 } 3260 3261 private class CompleterDeproxy implements AnnotationTypeCompleter { 3262 ClassSymbol proxyOn; 3263 CompoundAnnotationProxy target; 3264 CompoundAnnotationProxy repeatable; 3265 3266 public CompleterDeproxy(ClassSymbol c, CompoundAnnotationProxy target, 3267 CompoundAnnotationProxy repeatable) 3268 { 3269 this.proxyOn = c; 3270 this.target = target; 3271 this.repeatable = repeatable; 3272 } 3273 3274 @Override 3275 public void complete(ClassSymbol sym) { 3276 Assert.check(proxyOn == sym); 3277 Attribute.Compound theTarget = null, theRepeatable = null; 3278 AnnotationDeproxy deproxy; 3279 3280 try { 3281 if (target != null) { 3282 deproxy = new AnnotationDeproxy(proxyOn); 3283 theTarget = deproxy.deproxyCompound(target); 3284 } 3285 3286 if (repeatable != null) { 3287 deproxy = new AnnotationDeproxy(proxyOn); 3288 theRepeatable = deproxy.deproxyCompound(repeatable); 3289 } 3290 } catch (Exception e) { 3291 throw new CompletionFailure(sym, 3292 () -> ClassReader.this.diagFactory.fragment(Fragments.ExceptionMessage(e.getMessage())), 3293 dcfh); 3294 } 3295 3296 sym.getAnnotationTypeMetadata().setTarget(theTarget); 3297 sym.getAnnotationTypeMetadata().setRepeatable(theRepeatable); 3298 } 3299 } 3300 3301 private class ProxyType extends Type { 3302 3303 private final Name name; 3304 3305 public ProxyType(int index) { 3306 super(syms.noSymbol, List.nil()); 3307 this.name = poolReader.getName(index); 3308 } 3309 3310 @Override 3311 public TypeTag getTag() { 3312 return TypeTag.NONE; 3313 } 3314 3315 public Type resolve() { 3316 return name.map(ClassReader.this::sigToType); 3317 } 3318 3319 @Override @DefinedBy(Api.LANGUAGE_MODEL) 3320 public String toString() { 3321 return "<ProxyType>"; 3322 } 3323 3324 } 3325 3326 private static final class InterimUsesDirective { 3327 public final Name service; 3328 3329 public InterimUsesDirective(Name service) { 3330 this.service = service; 3331 } 3332 3333 } 3334 3335 private static final class InterimProvidesDirective { 3336 public final Name service; 3337 public final List<Name> impls; 3338 3339 public InterimProvidesDirective(Name service, List<Name> impls) { 3340 this.service = service; 3341 this.impls = impls; 3342 } 3343 3344 } 3345 3346 private final class UsesProvidesCompleter implements Completer { 3347 private final ModuleSymbol currentModule; 3348 private final List<InterimUsesDirective> interimUsesCopy; 3349 private final List<InterimProvidesDirective> interimProvidesCopy; 3350 3351 public UsesProvidesCompleter(ModuleSymbol currentModule, List<InterimUsesDirective> interimUsesCopy, List<InterimProvidesDirective> interimProvidesCopy) { 3352 this.currentModule = currentModule; 3353 this.interimUsesCopy = interimUsesCopy; 3354 this.interimProvidesCopy = interimProvidesCopy; 3355 } 3356 3357 @Override 3358 public void complete(Symbol sym) throws CompletionFailure { 3359 ListBuffer<Directive> directives = new ListBuffer<>(); 3360 directives.addAll(currentModule.directives); 3361 ListBuffer<UsesDirective> uses = new ListBuffer<>(); 3362 for (InterimUsesDirective interim : interimUsesCopy) { 3363 UsesDirective d = new UsesDirective(syms.enterClass(currentModule, interim.service)); 3364 uses.add(d); 3365 directives.add(d); 3366 } 3367 currentModule.uses = uses.toList(); 3368 ListBuffer<ProvidesDirective> provides = new ListBuffer<>(); 3369 for (InterimProvidesDirective interim : interimProvidesCopy) { 3370 ListBuffer<ClassSymbol> impls = new ListBuffer<>(); 3371 for (Name impl : interim.impls) { 3372 impls.append(syms.enterClass(currentModule, impl)); 3373 } 3374 ProvidesDirective d = new ProvidesDirective(syms.enterClass(currentModule, interim.service), 3375 impls.toList()); 3376 provides.add(d); 3377 directives.add(d); 3378 } 3379 currentModule.provides = provides.toList(); 3380 currentModule.directives = directives.toList(); 3381 } 3382 } 3383 }