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.IntFunction;
40
41 import javax.lang.model.element.Modifier;
42 import javax.lang.model.element.NestingKind;
43 import javax.tools.JavaFileManager;
44 import javax.tools.JavaFileObject;
45
46 import com.sun.tools.javac.code.Source.Feature;
47 import com.sun.tools.javac.comp.Annotate;
48 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
49 import com.sun.tools.javac.code.*;
50 import com.sun.tools.javac.code.Directive.*;
51 import com.sun.tools.javac.code.Lint.LintCategory;
52 import com.sun.tools.javac.code.Scope.WriteableScope;
53 import com.sun.tools.javac.code.Symbol.*;
54 import com.sun.tools.javac.code.Symtab;
55 import com.sun.tools.javac.code.Type.*;
56 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
57 import com.sun.tools.javac.file.BaseFileManager;
58 import com.sun.tools.javac.file.PathFileObject;
59 import com.sun.tools.javac.jvm.ClassFile.Version;
60 import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
61 import com.sun.tools.javac.main.Option;
62 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
63 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
64 import com.sun.tools.javac.util.*;
65 import com.sun.tools.javac.util.DefinedBy.Api;
66 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
88 * If you write code that depends on this, you do so at your own risk.
89 * This code and its internal interfaces are subject to change or
90 * deletion without notice.</b>
91 */
92 public class ClassReader {
93 /** The context key for the class reader. */
94 protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
95
96 public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
97
98 private final Annotate annotate;
99
100 /** Switch: verbose output.
101 */
102 boolean verbose;
103
104 /** Switch: allow modules.
105 */
106 boolean allowModules;
107
108 /** Switch: allow sealed
109 */
110 boolean allowSealedTypes;
111
112 /** Switch: allow records
113 */
114 boolean allowRecords;
115
116 /** Lint option: warn about classfile issues
117 */
118 boolean lintClassfile;
119
120 /** Switch: preserve parameter names from the variable table.
121 */
122 public boolean saveParameterNames;
123
124 /**
125 * The currently selected profile.
126 */
127 public final Profile profile;
260 protected ClassReader(Context context) {
261 context.put(classReaderKey, this);
262 annotate = Annotate.instance(context);
263 names = Names.instance(context);
264 syms = Symtab.instance(context);
265 types = Types.instance(context);
266 fileManager = context.get(JavaFileManager.class);
267 if (fileManager == null)
268 throw new AssertionError("FileManager initialization error");
269 diagFactory = JCDiagnostic.Factory.instance(context);
270 dcfh = DeferredCompletionFailureHandler.instance(context);
271
272 log = Log.instance(context);
273
274 Options options = Options.instance(context);
275 verbose = options.isSet(Option.VERBOSE);
276
277 Source source = Source.instance(context);
278 preview = Preview.instance(context);
279 allowModules = Feature.MODULES.allowedInSource(source);
280 allowRecords = Feature.RECORDS.allowedInSource(source);
281 allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
282
283 saveParameterNames = options.isSet(PARAMETERS);
284
285 profile = Profile.instance(context);
286
287 typevars = WriteableScope.create(syms.noSymbol);
288
289 lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
290
291 initAttributeReaders();
292 }
293
294 /** Add member to class unless it is synthetic.
295 */
296 private void enterMember(ClassSymbol c, Symbol sym) {
297 // Synthetic members are not entered -- reason lost to history (optimization?).
298 // Lambda methods must be entered because they may have inner classes (which reference them)
299 if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda))
455 return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
456 }
457 case 'B':
458 sigp++;
459 return syms.byteType;
460 case 'C':
461 sigp++;
462 return syms.charType;
463 case 'D':
464 sigp++;
465 return syms.doubleType;
466 case 'F':
467 sigp++;
468 return syms.floatType;
469 case 'I':
470 sigp++;
471 return syms.intType;
472 case 'J':
473 sigp++;
474 return syms.longType;
475 case 'L':
476 {
477 // int oldsigp = sigp;
478 Type t = classSigToType();
479 if (sigp < siglimit && signature[sigp] == '.')
480 throw badClassFile("deprecated inner class signature syntax " +
481 "(please recompile from source)");
482 /*
483 System.err.println(" decoded " +
484 new String(signature, oldsigp, sigp-oldsigp) +
485 " => " + t + " outer " + t.outer());
486 */
487 return t;
488 }
489 case 'S':
490 sigp++;
491 return syms.shortType;
492 case 'V':
493 sigp++;
494 return syms.voidType;
516 return new MethodType(argtypes,
517 restype,
518 thrown.reverse(),
519 syms.methodClass);
520 case '<':
521 typevars = typevars.dup(currentOwner);
522 Type poly = new ForAll(sigToTypeParams(), sigToType());
523 typevars = typevars.leave();
524 return poly;
525 default:
526 throw badClassFile("bad.signature",
527 Convert.utf2string(signature, sigp, 10));
528 }
529 }
530
531 byte[] signatureBuffer = new byte[0];
532 int sbp = 0;
533 /** Convert class signature to type, where signature is implicit.
534 */
535 Type classSigToType() {
536 if (signature[sigp] != 'L')
537 throw badClassFile("bad.class.signature",
538 Convert.utf2string(signature, sigp, 10));
539 sigp++;
540 Type outer = Type.noType;
541 int startSbp = sbp;
542
543 while (true) {
544 final byte c = signature[sigp++];
545 switch (c) {
546
547 case ';': { // end
548 ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
549 startSbp,
550 sbp - startSbp));
551
552 try {
553 return (outer == Type.noType) ?
554 t.erasure(types) :
555 new ClassType(outer, List.nil(), t);
556 } finally {
557 sbp = startSbp;
558 }
559 }
560
561 case '<': // generic arguments
562 ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
563 startSbp,
564 sbp - startSbp));
565 outer = new ClassType(outer, sigToTypes('>'), t) {
566 boolean completed = false;
567 @Override @DefinedBy(Api.LANGUAGE_MODEL)
568 public Type getEnclosingType() {
569 if (!completed) {
570 completed = true;
571 tsym.apiComplete();
572 Type enclosingType = tsym.type.getEnclosingType();
573 if (enclosingType != Type.noType) {
574 List<Type> typeArgs =
575 super.getEnclosingType().allparams();
576 List<Type> typeParams =
577 enclosingType.allparams();
578 if (typeParams.length() != typeArgs.length()) {
579 // no "rare" types
580 super.setEnclosingType(types.erasure(enclosingType));
581 } else {
582 super.setEnclosingType(types.subst(enclosingType,
583 typeParams,
584 typeArgs));
585 }
608 signatureBuffer[sbp++] = (byte)'$';
609 break;
610 } else {
611 sbp = startSbp;
612 return outer;
613 }
614 case '.':
615 signatureBuffer[sbp++] = (byte)'$';
616 break;
617 default:
618 throw new AssertionError(signature[sigp-1]);
619 }
620 continue;
621
622 case '.':
623 //we have seen an enclosing non-generic class
624 if (outer != Type.noType) {
625 t = enterClass(names.fromUtf(signatureBuffer,
626 startSbp,
627 sbp - startSbp));
628 outer = new ClassType(outer, List.nil(), t);
629 }
630 signatureBuffer[sbp++] = (byte)'$';
631 continue;
632 case '/':
633 signatureBuffer[sbp++] = (byte)'.';
634 continue;
635 default:
636 signatureBuffer[sbp++] = c;
637 continue;
638 }
639 }
640 }
641
642 /** Convert (implicit) signature to list of types
643 * until `terminator' is encountered.
644 */
645 List<Type> sigToTypes(char terminator) {
646 List<Type> head = List.of(null);
647 List<Type> tail = head;
648 while (signature[sigp] != terminator)
773 protected final Name name;
774 protected final ClassFile.Version version;
775 protected final Set<AttributeKind> kinds;
776 }
777
778 protected Set<AttributeKind> CLASS_ATTRIBUTE =
779 EnumSet.of(AttributeKind.CLASS);
780 protected Set<AttributeKind> MEMBER_ATTRIBUTE =
781 EnumSet.of(AttributeKind.MEMBER);
782 protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
783 EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
784
785 protected Map<Name, AttributeReader> attributeReaders = new HashMap<>();
786
787 private void initAttributeReaders() {
788 AttributeReader[] readers = {
789 // v45.3 attributes
790
791 new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
792 protected void read(Symbol sym, int attrLen) {
793 if (saveParameterNames)
794 ((MethodSymbol)sym).code = readCode(sym);
795 else
796 bp = bp + attrLen;
797 }
798 },
799
800 new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
801 protected void read(Symbol sym, int attrLen) {
802 Object v = poolReader.getConstant(nextChar());
803 // Ignore ConstantValue attribute if field not final.
804 if ((sym.flags() & FINAL) == 0) {
805 return;
806 }
807 VarSymbol var = (VarSymbol) sym;
808 switch (var.type.getTag()) {
809 case BOOLEAN:
810 case BYTE:
811 case CHAR:
812 case SHORT:
953 ClassSymbol c = (ClassSymbol) sym;
954 readingClassAttr = true;
955 try {
956 ClassType ct1 = (ClassType)c.type;
957 Assert.check(c == currentOwner);
958 ct1.typarams_field = poolReader.getName(nextChar())
959 .map(ClassReader.this::sigToTypeParams);
960 ct1.supertype_field = sigToType();
961 ListBuffer<Type> is = new ListBuffer<>();
962 while (sigp != siglimit) is.append(sigToType());
963 ct1.interfaces_field = is.toList();
964 } finally {
965 readingClassAttr = false;
966 }
967 } else {
968 List<Type> thrown = sym.type.getThrownTypes();
969 sym.type = poolReader.getType(nextChar());
970 //- System.err.println(" # " + sym.type);
971 if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
972 sym.type.asMethodType().thrown = thrown;
973
974 }
975 }
976 },
977
978 // v49 annotation attributes
979
980 new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
981 protected void read(Symbol sym, int attrLen) {
982 attachAnnotationDefault(sym);
983 }
984 },
985
986 new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
987 protected void read(Symbol sym, int attrLen) {
988 attachAnnotations(sym);
989 }
990 },
991
992 new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
2211 */
2212 MethodSymbol readMethod() {
2213 long flags = adjustMethodFlags(nextChar());
2214 Name name = poolReader.getName(nextChar());
2215 Type type = poolReader.getType(nextChar());
2216 if (currentOwner.isInterface() &&
2217 (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
2218 if (majorVersion > Version.V52.major ||
2219 (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
2220 if ((flags & (STATIC | PRIVATE)) == 0) {
2221 currentOwner.flags_field |= DEFAULT;
2222 flags |= DEFAULT | ABSTRACT;
2223 }
2224 } else {
2225 //protect against ill-formed classfiles
2226 throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
2227 Integer.toString(majorVersion),
2228 Integer.toString(minorVersion));
2229 }
2230 }
2231 validateMethodType(name, type);
2232 if (name == names.init && currentOwner.hasOuterInstance()) {
2233 // Sometimes anonymous classes don't have an outer
2234 // instance, however, there is no reliable way to tell so
2235 // we never strip this$n
2236 // ditto for local classes. Local classes that have an enclosing method set
2237 // won't pass the "hasOuterInstance" check above, but those that don't have an
2238 // enclosing method (i.e. from initializers) will pass that check.
2239 boolean local = !currentOwner.owner.members().includes(currentOwner, LookupKind.NON_RECURSIVE);
2240 if (!currentOwner.name.isEmpty() && !local)
2241 type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
2242 type.getReturnType(),
2243 type.getThrownTypes(),
2244 syms.methodClass);
2245 }
2246 MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
2247 if (types.isSignaturePolymorphic(m)) {
2248 m.flags_field |= SIGNATURE_POLYMORPHIC;
2249 }
2250 if (saveParameterNames)
2723 return flags;
2724 }
2725
2726 long adjustMethodFlags(long flags) {
2727 if ((flags & ACC_BRIDGE) != 0) {
2728 flags &= ~ACC_BRIDGE;
2729 flags |= BRIDGE;
2730 }
2731 if ((flags & ACC_VARARGS) != 0) {
2732 flags &= ~ACC_VARARGS;
2733 flags |= VARARGS;
2734 }
2735 return flags;
2736 }
2737
2738 long adjustClassFlags(long flags) {
2739 if ((flags & ACC_MODULE) != 0) {
2740 flags &= ~ACC_MODULE;
2741 flags |= MODULE;
2742 }
2743 return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
2744 }
2745
2746 /**
2747 * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2748 * The attribute is only the last component of the original filename, so is unlikely
2749 * to be valid as is, so operations other than those to access the name throw
2750 * UnsupportedOperationException
2751 */
2752 private static class SourceFileObject implements JavaFileObject {
2753
2754 /** The file's name.
2755 */
2756 private final Name name;
2757
2758 public SourceFileObject(Name name) {
2759 this.name = name;
2760 }
2761
2762 @Override @DefinedBy(Api.COMPILER)
2763 public URI toUri() {
|
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.IntFunction;
40
41 import javax.lang.model.element.Modifier;
42 import javax.lang.model.element.NestingKind;
43 import javax.tools.JavaFileManager;
44 import javax.tools.JavaFileObject;
45
46 import com.sun.tools.javac.code.Source.Feature;
47 import com.sun.tools.javac.code.Type.ClassType.Flavor;
48 import com.sun.tools.javac.comp.Annotate;
49 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
50 import com.sun.tools.javac.code.*;
51 import com.sun.tools.javac.code.Directive.*;
52 import com.sun.tools.javac.code.Lint.LintCategory;
53 import com.sun.tools.javac.code.Scope.WriteableScope;
54 import com.sun.tools.javac.code.Symbol.*;
55 import com.sun.tools.javac.code.Symtab;
56 import com.sun.tools.javac.code.Type.*;
57 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
58 import com.sun.tools.javac.file.BaseFileManager;
59 import com.sun.tools.javac.file.PathFileObject;
60 import com.sun.tools.javac.jvm.ClassFile.Version;
61 import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
62 import com.sun.tools.javac.main.Option;
63 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
64 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
65 import com.sun.tools.javac.util.*;
66 import com.sun.tools.javac.util.DefinedBy.Api;
67 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
89 * If you write code that depends on this, you do so at your own risk.
90 * This code and its internal interfaces are subject to change or
91 * deletion without notice.</b>
92 */
93 public class ClassReader {
94 /** The context key for the class reader. */
95 protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
96
97 public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
98
99 private final Annotate annotate;
100
101 /** Switch: verbose output.
102 */
103 boolean verbose;
104
105 /** Switch: allow modules.
106 */
107 boolean allowModules;
108
109 /** Switch: allow primitive classes.
110 */
111 boolean allowPrimitiveClasses;
112
113 /** Switch: allow value classes.
114 */
115 boolean allowValueClasses;
116
117 /** Switch: allow sealed
118 */
119 boolean allowSealedTypes;
120
121 /** Switch: allow records
122 */
123 boolean allowRecords;
124
125 /** Lint option: warn about classfile issues
126 */
127 boolean lintClassfile;
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;
269 protected ClassReader(Context context) {
270 context.put(classReaderKey, this);
271 annotate = Annotate.instance(context);
272 names = Names.instance(context);
273 syms = Symtab.instance(context);
274 types = Types.instance(context);
275 fileManager = context.get(JavaFileManager.class);
276 if (fileManager == null)
277 throw new AssertionError("FileManager initialization error");
278 diagFactory = JCDiagnostic.Factory.instance(context);
279 dcfh = DeferredCompletionFailureHandler.instance(context);
280
281 log = Log.instance(context);
282
283 Options options = Options.instance(context);
284 verbose = options.isSet(Option.VERBOSE);
285
286 Source source = Source.instance(context);
287 preview = Preview.instance(context);
288 allowModules = Feature.MODULES.allowedInSource(source);
289 allowPrimitiveClasses = (!preview.isPreview(Feature.PRIMITIVE_CLASSES) || preview.isEnabled()) &&
290 Feature.PRIMITIVE_CLASSES.allowedInSource(source);
291 allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
292 Feature.VALUE_CLASSES.allowedInSource(source);
293 allowRecords = Feature.RECORDS.allowedInSource(source);
294 allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
295
296 saveParameterNames = options.isSet(PARAMETERS);
297
298 profile = Profile.instance(context);
299
300 typevars = WriteableScope.create(syms.noSymbol);
301
302 lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
303
304 initAttributeReaders();
305 }
306
307 /** Add member to class unless it is synthetic.
308 */
309 private void enterMember(ClassSymbol c, Symbol sym) {
310 // Synthetic members are not entered -- reason lost to history (optimization?).
311 // Lambda methods must be entered because they may have inner classes (which reference them)
312 if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda))
468 return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
469 }
470 case 'B':
471 sigp++;
472 return syms.byteType;
473 case 'C':
474 sigp++;
475 return syms.charType;
476 case 'D':
477 sigp++;
478 return syms.doubleType;
479 case 'F':
480 sigp++;
481 return syms.floatType;
482 case 'I':
483 sigp++;
484 return syms.intType;
485 case 'J':
486 sigp++;
487 return syms.longType;
488 case 'Q':
489 case 'L':
490 {
491 // int oldsigp = sigp;
492 Type t = classSigToType();
493 if (sigp < siglimit && signature[sigp] == '.')
494 throw badClassFile("deprecated inner class signature syntax " +
495 "(please recompile from source)");
496 /*
497 System.err.println(" decoded " +
498 new String(signature, oldsigp, sigp-oldsigp) +
499 " => " + t + " outer " + t.outer());
500 */
501 return t;
502 }
503 case 'S':
504 sigp++;
505 return syms.shortType;
506 case 'V':
507 sigp++;
508 return syms.voidType;
530 return new MethodType(argtypes,
531 restype,
532 thrown.reverse(),
533 syms.methodClass);
534 case '<':
535 typevars = typevars.dup(currentOwner);
536 Type poly = new ForAll(sigToTypeParams(), sigToType());
537 typevars = typevars.leave();
538 return poly;
539 default:
540 throw badClassFile("bad.signature",
541 Convert.utf2string(signature, sigp, 10));
542 }
543 }
544
545 byte[] signatureBuffer = new byte[0];
546 int sbp = 0;
547 /** Convert class signature to type, where signature is implicit.
548 */
549 Type classSigToType() {
550 byte prefix = signature[sigp];
551 if (prefix != 'L' && prefix != 'Q')
552 throw badClassFile("bad.class.signature",
553 Convert.utf2string(signature, sigp, 10));
554 sigp++;
555 Type outer = Type.noType;
556 Name name;
557 ClassType.Flavor flavor;
558 int startSbp = sbp;
559
560 while (true) {
561 final byte c = signature[sigp++];
562 switch (c) {
563
564 case ';': { // end
565 ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
566 startSbp,
567 sbp - startSbp));
568
569 // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
570 flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
571 try {
572 if (outer == Type.noType) {
573 ClassType et = (ClassType) t.erasure(types);
574 // Todo: This spews out more objects than before, i.e no reuse with identical flavor
575 return new ClassType(et.getEnclosingType(), List.nil(), et.tsym, et.getMetadata(), flavor);
576 }
577 return new ClassType(outer, List.nil(), t, TypeMetadata.EMPTY, flavor);
578 } finally {
579 sbp = startSbp;
580 }
581 }
582
583 case '<': // generic arguments
584 ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
585 startSbp,
586 sbp - startSbp));
587 // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
588 flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
589 outer = new ClassType(outer, sigToTypes('>'), t, TypeMetadata.EMPTY, flavor) {
590 boolean completed = false;
591 @Override @DefinedBy(Api.LANGUAGE_MODEL)
592 public Type getEnclosingType() {
593 if (!completed) {
594 completed = true;
595 tsym.apiComplete();
596 Type enclosingType = tsym.type.getEnclosingType();
597 if (enclosingType != Type.noType) {
598 List<Type> typeArgs =
599 super.getEnclosingType().allparams();
600 List<Type> typeParams =
601 enclosingType.allparams();
602 if (typeParams.length() != typeArgs.length()) {
603 // no "rare" types
604 super.setEnclosingType(types.erasure(enclosingType));
605 } else {
606 super.setEnclosingType(types.subst(enclosingType,
607 typeParams,
608 typeArgs));
609 }
632 signatureBuffer[sbp++] = (byte)'$';
633 break;
634 } else {
635 sbp = startSbp;
636 return outer;
637 }
638 case '.':
639 signatureBuffer[sbp++] = (byte)'$';
640 break;
641 default:
642 throw new AssertionError(signature[sigp-1]);
643 }
644 continue;
645
646 case '.':
647 //we have seen an enclosing non-generic class
648 if (outer != Type.noType) {
649 t = enterClass(names.fromUtf(signatureBuffer,
650 startSbp,
651 sbp - startSbp));
652 // We are seeing QFoo; or LFoo; The name itself does not shine any light on default val-refness
653 flavor = prefix == 'L' ? Flavor.L_TypeOf_X : Flavor.Q_TypeOf_X;
654 outer = new ClassType(outer, List.nil(), t, TypeMetadata.EMPTY, flavor);
655 }
656 signatureBuffer[sbp++] = (byte)'$';
657 continue;
658 case '/':
659 signatureBuffer[sbp++] = (byte)'.';
660 continue;
661 default:
662 signatureBuffer[sbp++] = c;
663 continue;
664 }
665 }
666 }
667
668 /** Convert (implicit) signature to list of types
669 * until `terminator' is encountered.
670 */
671 List<Type> sigToTypes(char terminator) {
672 List<Type> head = List.of(null);
673 List<Type> tail = head;
674 while (signature[sigp] != terminator)
799 protected final Name name;
800 protected final ClassFile.Version version;
801 protected final Set<AttributeKind> kinds;
802 }
803
804 protected Set<AttributeKind> CLASS_ATTRIBUTE =
805 EnumSet.of(AttributeKind.CLASS);
806 protected Set<AttributeKind> MEMBER_ATTRIBUTE =
807 EnumSet.of(AttributeKind.MEMBER);
808 protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
809 EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
810
811 protected Map<Name, AttributeReader> attributeReaders = new HashMap<>();
812
813 private void initAttributeReaders() {
814 AttributeReader[] readers = {
815 // v45.3 attributes
816
817 new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
818 protected void read(Symbol sym, int attrLen) {
819 if (allowPrimitiveClasses) {
820 if (sym.isConstructor() && ((MethodSymbol) sym).type.getParameterTypes().size() == 0) {
821 int code_length = buf.getInt(bp + 4);
822 if ((code_length == 1 && buf.getByte( bp + 8) == (byte) ByteCodes.return_) ||
823 (code_length == 5 && buf.getByte(bp + 8) == ByteCodes.aload_0 &&
824 buf.getByte( bp + 9) == (byte) ByteCodes.invokespecial &&
825 buf.getByte( bp + 12) == (byte) ByteCodes.return_)) {
826 sym.flags_field |= EMPTYNOARGCONSTR;
827 }
828 }
829 }
830 if (saveParameterNames)
831 ((MethodSymbol)sym).code = readCode(sym);
832 else
833 bp = bp + attrLen;
834 }
835 },
836
837 new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
838 protected void read(Symbol sym, int attrLen) {
839 Object v = poolReader.getConstant(nextChar());
840 // Ignore ConstantValue attribute if field not final.
841 if ((sym.flags() & FINAL) == 0) {
842 return;
843 }
844 VarSymbol var = (VarSymbol) sym;
845 switch (var.type.getTag()) {
846 case BOOLEAN:
847 case BYTE:
848 case CHAR:
849 case SHORT:
990 ClassSymbol c = (ClassSymbol) sym;
991 readingClassAttr = true;
992 try {
993 ClassType ct1 = (ClassType)c.type;
994 Assert.check(c == currentOwner);
995 ct1.typarams_field = poolReader.getName(nextChar())
996 .map(ClassReader.this::sigToTypeParams);
997 ct1.supertype_field = sigToType();
998 ListBuffer<Type> is = new ListBuffer<>();
999 while (sigp != siglimit) is.append(sigToType());
1000 ct1.interfaces_field = is.toList();
1001 } finally {
1002 readingClassAttr = false;
1003 }
1004 } else {
1005 List<Type> thrown = sym.type.getThrownTypes();
1006 sym.type = poolReader.getType(nextChar());
1007 //- System.err.println(" # " + sym.type);
1008 if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
1009 sym.type.asMethodType().thrown = thrown;
1010 // Map value class factory methods back to constructors for the benefit of earlier pipeline stages
1011 if (sym.kind == MTH && sym.name == names.init && !sym.type.getReturnType().hasTag(TypeTag.VOID)) {
1012 sym.type = new MethodType(sym.type.getParameterTypes(),
1013 syms.voidType,
1014 sym.type.getThrownTypes(),
1015 syms.methodClass);
1016 }
1017
1018 }
1019 }
1020 },
1021
1022 // v49 annotation attributes
1023
1024 new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1025 protected void read(Symbol sym, int attrLen) {
1026 attachAnnotationDefault(sym);
1027 }
1028 },
1029
1030 new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1031 protected void read(Symbol sym, int attrLen) {
1032 attachAnnotations(sym);
1033 }
1034 },
1035
1036 new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
2255 */
2256 MethodSymbol readMethod() {
2257 long flags = adjustMethodFlags(nextChar());
2258 Name name = poolReader.getName(nextChar());
2259 Type type = poolReader.getType(nextChar());
2260 if (currentOwner.isInterface() &&
2261 (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
2262 if (majorVersion > Version.V52.major ||
2263 (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
2264 if ((flags & (STATIC | PRIVATE)) == 0) {
2265 currentOwner.flags_field |= DEFAULT;
2266 flags |= DEFAULT | ABSTRACT;
2267 }
2268 } else {
2269 //protect against ill-formed classfiles
2270 throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
2271 Integer.toString(majorVersion),
2272 Integer.toString(minorVersion));
2273 }
2274 }
2275 if (name == names.init && ((flags & STATIC) != 0)) {
2276 flags &= ~STATIC;
2277 type = new MethodType(type.getParameterTypes(),
2278 syms.voidType,
2279 type.getThrownTypes(),
2280 syms.methodClass);
2281 }
2282 validateMethodType(name, type);
2283 if (name == names.init && currentOwner.hasOuterInstance()) {
2284 // Sometimes anonymous classes don't have an outer
2285 // instance, however, there is no reliable way to tell so
2286 // we never strip this$n
2287 // ditto for local classes. Local classes that have an enclosing method set
2288 // won't pass the "hasOuterInstance" check above, but those that don't have an
2289 // enclosing method (i.e. from initializers) will pass that check.
2290 boolean local = !currentOwner.owner.members().includes(currentOwner, LookupKind.NON_RECURSIVE);
2291 if (!currentOwner.name.isEmpty() && !local)
2292 type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
2293 type.getReturnType(),
2294 type.getThrownTypes(),
2295 syms.methodClass);
2296 }
2297 MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
2298 if (types.isSignaturePolymorphic(m)) {
2299 m.flags_field |= SIGNATURE_POLYMORPHIC;
2300 }
2301 if (saveParameterNames)
2774 return flags;
2775 }
2776
2777 long adjustMethodFlags(long flags) {
2778 if ((flags & ACC_BRIDGE) != 0) {
2779 flags &= ~ACC_BRIDGE;
2780 flags |= BRIDGE;
2781 }
2782 if ((flags & ACC_VARARGS) != 0) {
2783 flags &= ~ACC_VARARGS;
2784 flags |= VARARGS;
2785 }
2786 return flags;
2787 }
2788
2789 long adjustClassFlags(long flags) {
2790 if ((flags & ACC_MODULE) != 0) {
2791 flags &= ~ACC_MODULE;
2792 flags |= MODULE;
2793 }
2794 if ((flags & ACC_PRIMITIVE) != 0) {
2795 flags &= ~ACC_PRIMITIVE;
2796 if (allowPrimitiveClasses) {
2797 flags |= PRIMITIVE_CLASS;
2798 }
2799 }
2800 if ((flags & ACC_VALUE) != 0) {
2801 flags &= ~ACC_VALUE;
2802 if (allowValueClasses) {
2803 flags |= VALUE_CLASS;
2804 }
2805 }
2806 if ((flags & ACC_IDENTITY) != 0) {
2807 flags &= ~ACC_IDENTITY;
2808 flags |= IDENTITY_TYPE;
2809 }
2810 return flags;
2811 }
2812
2813 /**
2814 * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2815 * The attribute is only the last component of the original filename, so is unlikely
2816 * to be valid as is, so operations other than those to access the name throw
2817 * UnsupportedOperationException
2818 */
2819 private static class SourceFileObject implements JavaFileObject {
2820
2821 /** The file's name.
2822 */
2823 private final Name name;
2824
2825 public SourceFileObject(Name name) {
2826 this.name = name;
2827 }
2828
2829 @Override @DefinedBy(Api.COMPILER)
2830 public URI toUri() {
|