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
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)
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 }
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) {
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() {
|
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;
66 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
67 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
68 import com.sun.tools.javac.tree.JCTree;
69 import com.sun.tools.javac.util.*;
70 import com.sun.tools.javac.util.ByteBuffer.UnderflowException;
71 import com.sun.tools.javac.util.DefinedBy.Api;
72 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
73 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
74
75 import static com.sun.tools.javac.code.Flags.*;
76 import static com.sun.tools.javac.code.Kinds.Kind.*;
77
78 import com.sun.tools.javac.code.Scope.LookupKind;
79
80 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
81 import static com.sun.tools.javac.code.TypeTag.ARRAY;
82 import static com.sun.tools.javac.code.TypeTag.CLASS;
83 import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
84 import static com.sun.tools.javac.jvm.ClassFile.*;
85 import static com.sun.tools.javac.jvm.ClassFile.Version.*;
86
87 import static com.sun.tools.javac.main.Option.PARAMETERS;
88
89 /** This class provides operations to read a classfile into an internal
90 * representation. The internal representation is anchored in a
91 * ClassSymbol which contains in its scope symbol representations
92 * for all other definitions in the classfile. Top-level Classes themselves
93 * appear as members of the scopes of PackageSymbols.
94 *
95 * <p><b>This is NOT part of any supported API.
96 * If you write code that depends on this, you do so at your own risk.
97 * This code and its internal interfaces are subject to change or
98 * deletion without notice.</b>
99 */
100 public class ClassReader {
101 /** The context key for the class reader. */
102 protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
103
104 public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
105
106 private final Annotate annotate;
107
108 /** Switch: verbose output.
109 */
110 boolean verbose;
111
112 /** Switch: allow modules.
113 */
114 boolean allowModules;
115
116 /** Switch: allow value classes.
117 */
118 boolean allowValueClasses;
119
120 /** Switch: allow sealed
121 */
122 boolean allowSealedTypes;
123
124 /** Switch: allow records
125 */
126 boolean allowRecords;
127
128 /** Lint option: warn about classfile issues
129 */
130 boolean lintClassfile;
131
132 /** Switch: warn (instead of error) on illegal UTF-8
133 */
134 boolean warnOnIllegalUtf8;
135
136 /** Switch: preserve parameter names from the variable table.
137 */
138 public boolean saveParameterNames;
139
274 protected ClassReader(Context context) {
275 context.put(classReaderKey, this);
276 annotate = Annotate.instance(context);
277 names = Names.instance(context);
278 syms = Symtab.instance(context);
279 types = Types.instance(context);
280 fileManager = context.get(JavaFileManager.class);
281 if (fileManager == null)
282 throw new AssertionError("FileManager initialization error");
283 diagFactory = JCDiagnostic.Factory.instance(context);
284 dcfh = DeferredCompletionFailureHandler.instance(context);
285
286 log = Log.instance(context);
287
288 Options options = Options.instance(context);
289 verbose = options.isSet(Option.VERBOSE);
290
291 Source source = Source.instance(context);
292 preview = Preview.instance(context);
293 allowModules = Feature.MODULES.allowedInSource(source);
294 allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
295 Feature.VALUE_CLASSES.allowedInSource(source);
296 allowRecords = Feature.RECORDS.allowedInSource(source);
297 allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
298 warnOnIllegalUtf8 = Feature.WARN_ON_ILLEGAL_UTF8.allowedInSource(source);
299
300 saveParameterNames = options.isSet(PARAMETERS);
301
302 profile = Profile.instance(context);
303
304 typevars = WriteableScope.create(syms.noSymbol);
305
306 lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
307
308 initAttributeReaders();
309 }
310
311 /** Add member to class unless it is synthetic.
312 */
313 private void enterMember(ClassSymbol c, Symbol sym) {
314 // Synthetic members are not entered -- reason lost to history (optimization?).
315 // Lambda methods must be entered because they may have inner classes (which reference them)
558 syms.methodClass);
559 case '<':
560 typevars = typevars.dup(currentOwner);
561 Type poly = new ForAll(sigToTypeParams(), sigToType());
562 typevars = typevars.leave();
563 return poly;
564 default:
565 throw badClassFile("bad.signature", quoteBadSignature());
566 }
567 }
568
569 byte[] signatureBuffer = new byte[0];
570 int sbp = 0;
571 /** Convert class signature to type, where signature is implicit.
572 */
573 Type classSigToType() {
574 if (signature[sigp] != 'L')
575 throw badClassFile("bad.class.signature", quoteBadSignature());
576 sigp++;
577 Type outer = Type.noType;
578 Name name;
579 int startSbp = sbp;
580
581 while (true) {
582 final byte c = signature[sigp++];
583 switch (c) {
584
585 case ';': { // end
586 ClassSymbol t = enterClass(readName(signatureBuffer,
587 startSbp,
588 sbp - startSbp));
589
590 try {
591 if (outer == Type.noType) {
592 ClassType et = (ClassType) t.erasure(types);
593 return new ClassType(et.getEnclosingType(), List.nil(), et.tsym, et.getMetadata());
594 }
595 return new ClassType(outer, List.nil(), t, List.nil());
596 } finally {
597 sbp = startSbp;
598 }
599 }
600
601 case '<': // generic arguments
602 ClassSymbol t = enterClass(readName(signatureBuffer,
603 startSbp,
604 sbp - startSbp));
605 outer = new ClassType(outer, sigToTypes('>'), t, List.nil()) {
606 boolean completed = false;
607 @Override @DefinedBy(Api.LANGUAGE_MODEL)
608 public Type getEnclosingType() {
609 if (!completed) {
610 completed = true;
611 tsym.apiComplete();
612 Type enclosingType = tsym.type.getEnclosingType();
613 if (enclosingType != Type.noType) {
614 List<Type> typeArgs =
615 super.getEnclosingType().allparams();
616 List<Type> typeParams =
617 enclosingType.allparams();
618 if (typeParams.length() != typeArgs.length()) {
619 // no "rare" types
620 super.setEnclosingType(types.erasure(enclosingType));
621 } else {
622 super.setEnclosingType(types.subst(enclosingType,
623 typeParams,
624 typeArgs));
625 }
648 signatureBuffer[sbp++] = (byte)'$';
649 break;
650 } else {
651 sbp = startSbp;
652 return outer;
653 }
654 case '.':
655 signatureBuffer[sbp++] = (byte)'$';
656 break;
657 default:
658 throw new AssertionError(signature[sigp-1]);
659 }
660 continue;
661
662 case '.':
663 //we have seen an enclosing non-generic class
664 if (outer != Type.noType) {
665 t = enterClass(readName(signatureBuffer,
666 startSbp,
667 sbp - startSbp));
668 outer = new ClassType(outer, List.nil(), t, List.nil());
669 }
670 signatureBuffer[sbp++] = (byte)'$';
671 continue;
672 case '/':
673 signatureBuffer[sbp++] = (byte)'.';
674 continue;
675 default:
676 signatureBuffer[sbp++] = c;
677 continue;
678 }
679 }
680 }
681
682 /** Quote a bogus signature for display inside an error message.
683 */
684 String quoteBadSignature() {
685 String sigString;
686 try {
687 sigString = Convert.utf2string(signature, sigp, siglimit - sigp, Convert.Validation.NONE);
688 } catch (InvalidUtfException e) {
3125 } finally {
3126 interimUses = List.nil();
3127 interimProvides = List.nil();
3128 missingTypeVariables = List.nil();
3129 foundTypeVariables = List.nil();
3130 filling = false;
3131 }
3132 }
3133
3134 /** We can only read a single class file at a time; this
3135 * flag keeps track of when we are currently reading a class
3136 * file.
3137 */
3138 public boolean filling = false;
3139
3140 /************************************************************************
3141 * Adjusting flags
3142 ***********************************************************************/
3143
3144 long adjustFieldFlags(long flags) {
3145 boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
3146 if (allowValueClasses && previewClassFile && (flags & ACC_STRICT) != 0) {
3147 flags &= ~ACC_STRICT;
3148 flags |= STRICT;
3149 }
3150 return flags;
3151 }
3152
3153 long adjustMethodFlags(long flags) {
3154 if ((flags & ACC_BRIDGE) != 0) {
3155 flags &= ~ACC_BRIDGE;
3156 flags |= BRIDGE;
3157 }
3158 if ((flags & ACC_VARARGS) != 0) {
3159 flags &= ~ACC_VARARGS;
3160 flags |= VARARGS;
3161 }
3162 return flags;
3163 }
3164
3165 long adjustClassFlags(long flags) {
3166 boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
3167 if ((flags & ACC_MODULE) != 0) {
3168 flags &= ~ACC_MODULE;
3169 flags |= MODULE;
3170 }
3171 if ((flags & ACC_IDENTITY) != 0 || (majorVersion < V66.major && (flags & INTERFACE) == 0)) {
3172 flags |= IDENTITY_TYPE;
3173 } else if ((flags & INTERFACE) == 0 && allowValueClasses && previewClassFile && majorVersion >= V66.major) {
3174 flags |= VALUE_CLASS;
3175 }
3176 flags &= ~ACC_IDENTITY; // ACC_IDENTITY and SYNCHRONIZED bits overloaded
3177 return flags;
3178 }
3179
3180 /**
3181 * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
3182 * The attribute is only the last component of the original filename, so is unlikely
3183 * to be valid as is, so operations other than those to access the name throw
3184 * UnsupportedOperationException
3185 */
3186 private static class SourceFileObject implements JavaFileObject {
3187
3188 /** The file's name.
3189 */
3190 private final Name name;
3191
3192 public SourceFileObject(Name name) {
3193 this.name = name;
3194 }
3195
3196 @Override @DefinedBy(Api.COMPILER)
3197 public URI toUri() {
|