Mergin jlahoda's fix of #8182450: javac aborts when generating ct.sym intermittently - Initialize the module system model even in presence of missing/broken module-infos; BadClassFiles should not immediatelly abort compilation anymore, but should be handled as if the classfile did not exist.
2 * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
26 package com.sun.tools.javac.main;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.LinkedHashMap;
34 import java.util.LinkedHashSet;
36 import java.util.MissingResourceException;
37 import java.util.Queue;
38 import java.util.ResourceBundle;
40 import java.util.function.Function;
42 import javax.annotation.processing.Processor;
43 import javax.lang.model.SourceVersion;
44 import javax.lang.model.element.ElementVisitor;
45 import javax.tools.DiagnosticListener;
46 import javax.tools.JavaFileManager;
47 import javax.tools.JavaFileObject;
48 import javax.tools.JavaFileObject.Kind;
49 import javax.tools.StandardLocation;
51 import com.sun.source.util.TaskEvent;
52 import com.sun.tools.javac.api.DuplicateClassChecker;
53 import com.sun.tools.javac.api.MultiTaskListener;
54 import com.sun.tools.javac.code.*;
55 import com.sun.tools.javac.code.Lint.LintCategory;
56 import com.sun.tools.javac.code.Symbol.ClassSymbol;
57 import com.sun.tools.javac.code.Symbol.CompletionFailure;
58 import com.sun.tools.javac.code.Symbol.PackageSymbol;
59 import com.sun.tools.javac.comp.*;
60 import com.sun.tools.javac.comp.CompileStates.CompileState;
61 import com.sun.tools.javac.file.JavacFileManager;
62 import com.sun.tools.javac.jvm.*;
63 import com.sun.tools.javac.parser.*;
64 import com.sun.tools.javac.platform.PlatformDescription;
65 import com.sun.tools.javac.processing.*;
66 import com.sun.tools.javac.tree.*;
67 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
68 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
69 import com.sun.tools.javac.tree.JCTree.JCExpression;
70 import com.sun.tools.javac.tree.JCTree.JCLambda;
71 import com.sun.tools.javac.tree.JCTree.JCMemberReference;
72 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
73 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
74 import com.sun.tools.javac.util.*;
75 import com.sun.tools.javac.util.DefinedBy.Api;
76 import com.sun.tools.javac.util.JCDiagnostic.Factory;
77 import com.sun.tools.javac.util.Log.DiagnosticHandler;
78 import com.sun.tools.javac.util.Log.DiscardDiagnosticHandler;
79 import com.sun.tools.javac.util.Log.WriterKind;
81 import static com.sun.tools.javac.code.Kinds.Kind.*;
83 import com.sun.tools.javac.code.Symbol.ModuleSymbol;
84 import com.sun.tools.javac.resources.CompilerProperties.Errors;
85 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
87 import static com.sun.tools.javac.code.TypeTag.CLASS;
88 import static com.sun.tools.javac.main.Option.*;
89 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
90 import java.util.Iterator;
92 import static javax.tools.StandardLocation.CLASS_OUTPUT;
94 import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
96 /** This class could be the main entry point for GJC when GJC is used as a
97 * component in a larger software system. It provides operations to
98 * construct a new compiler, and to run a new compiler on a set of source
101 * <p><b>This is NOT part of any supported API.
102 * If you write code that depends on this, you do so at your own risk.
103 * This code and its internal interfaces are subject to change or
104 * deletion without notice.</b>
106 public class JavaCompiler {
107 /** The context key for the compiler. */
108 public static final Context.Key<JavaCompiler> compilerKey = new Context.Key<>();
110 /** Get the JavaCompiler instance for this context. */
111 public static JavaCompiler instance(Context context) {
112 JavaCompiler instance = context.get(compilerKey);
113 if (instance == null)
114 instance = new JavaCompiler(context);
118 /** The current version number as a string.
120 public static String version() {
121 return version("release"); // mm.nn.oo[-milestone]
124 /** The current full version number as a string.
126 public static String fullVersion() {
127 return version("full"); // mm.mm.oo[-milestone]-build
130 private static final String versionRBName = "com.sun.tools.javac.resources.version";
131 private static ResourceBundle versionRB;
133 private static String version(String key) {
134 if (versionRB == null) {
136 versionRB = ResourceBundle.getBundle(versionRBName);
137 } catch (MissingResourceException e) {
138 return Log.getLocalizedString("version.not.available");
142 return versionRB.getString(key);
144 catch (MissingResourceException e) {
145 return Log.getLocalizedString("version.not.available");
150 * Control how the compiler's latter phases (attr, flow, desugar, generate)
151 * are connected. Each individual file is processed by each phase in turn,
152 * but with different compile policies, you can control the order in which
153 * each class is processed through its next phase.
155 * <p>Generally speaking, the compiler will "fail fast" in the face of
156 * errors, although not aggressively so. flow, desugar, etc become no-ops
157 * once any errors have occurred. No attempt is currently made to determine
158 * if it might be safe to process a class through its next phase because
159 * it does not depend on any unrelated errors that might have occurred.
161 protected static enum CompilePolicy {
163 * Just attribute the parse trees.
168 * Just attribute and do flow analysis on the parse trees.
169 * This should catch most user errors.
174 * Attribute everything, then do flow analysis for everything,
175 * then desugar everything, and only then generate output.
176 * This means no output will be generated if there are any
177 * errors in any classes.
182 * Groups the classes for each source file together, then process
183 * each group in a manner equivalent to the {@code SIMPLE} policy.
184 * This means no output will be generated if there are any
185 * errors in any of the classes in a source file.
190 * Completely process each entry on the todo list in turn.
191 * -- this is the same for 1.5.
192 * Means output might be generated for some classes in a compilation unit
197 static CompilePolicy decode(String option) {
199 return DEFAULT_COMPILE_POLICY;
200 else if (option.equals("attr"))
202 else if (option.equals("check"))
204 else if (option.equals("simple"))
206 else if (option.equals("byfile"))
208 else if (option.equals("bytodo"))
211 return DEFAULT_COMPILE_POLICY;
215 private static final CompilePolicy DEFAULT_COMPILE_POLICY = CompilePolicy.BY_TODO;
217 protected static enum ImplicitSourcePolicy {
218 /** Don't generate or process implicitly read source files. */
220 /** Generate classes for implicitly read source files. */
222 /** Like CLASS, but generate warnings if annotation processing occurs */
225 static ImplicitSourcePolicy decode(String option) {
228 else if (option.equals("none"))
230 else if (option.equals("class"))
237 /** The log to be used for error reporting.
241 /** Factory for creating diagnostic objects
243 JCDiagnostic.Factory diagFactory;
245 /** The tree factory module.
247 protected TreeMaker make;
249 /** The class finder.
251 protected ClassFinder finder;
253 /** The class reader.
255 protected ClassReader reader;
257 /** The class writer.
259 protected ClassWriter writer;
261 /** The native header writer.
263 protected JNIWriter jniWriter;
265 /** The module for the symbol table entry phases.
267 protected Enter enter;
269 /** The symbol table.
271 protected Symtab syms;
273 /** The language version.
275 protected Source source;
277 /** The module for code generation.
283 protected Names names;
293 /** The flow analyzer.
297 /** The modules visitor
299 protected Modules modules;
301 /** The module finder
303 protected ModuleFinder moduleFinder;
305 /** The diagnostics factory
307 protected JCDiagnostic.Factory diags;
310 /** The error repairer.
312 public Repair repair;
316 protected TransTypes transTypes;
318 /** The syntactic sugar desweetener.
320 protected Lower lower;
322 /** The annotation annotator.
324 protected Annotate annotate;
326 /** Force a completion failure on this name
328 protected final Name completionFailureName;
332 protected Types types;
334 /** Access to file objects.
336 protected JavaFileManager fileManager;
338 /** Factory for parsers.
340 protected ParserFactory parserFactory;
342 /** Broadcasting listener for progress events
344 protected MultiTaskListener taskListener;
347 * SourceCompleter that delegates to the readSourceFile method of this class.
349 protected final Symbol.Completer sourceCompleter =
350 sym -> readSourceFile((ClassSymbol) sym);
353 * Command line options.
355 protected Options options;
357 protected Context context;
360 * Flag set if any annotation processing occurred.
362 protected boolean annotationProcessingOccurred;
365 * Flag set if any implicit source files read.
367 protected boolean implicitSourceFilesRead;
369 private boolean enterDone;
371 protected CompileStates compileStates;
373 protected Map<JavaFileObject, JCCompilationUnit> notYetEntered;
375 public boolean skipAnnotationProcessing = false;
377 private final DuplicateClassChecker duplicateClassChecker;
378 public List<JCCompilationUnit> toProcessAnnotations = List.nil();
380 /** Construct a new compiler using a shared context.
382 public JavaCompiler(Context context) {
383 this.context = context;
384 context.put(compilerKey, this);
386 // if fileManager not already set, register the JavacFileManager to be used
387 if (context.get(JavaFileManager.class) == null)
388 JavacFileManager.preRegister(context);
390 names = Names.instance(context);
391 log = Log.instance(context);
392 diagFactory = JCDiagnostic.Factory.instance(context);
393 finder = ClassFinder.instance(context);
394 reader = ClassReader.instance(context);
395 make = TreeMaker.instance(context);
396 writer = ClassWriter.instance(context);
397 jniWriter = JNIWriter.instance(context);
398 enter = Enter.instance(context);
399 todo = Todo.instance(context);
401 fileManager = context.get(JavaFileManager.class);
402 parserFactory = ParserFactory.instance(context);
403 compileStates = CompileStates.instance(context);
406 // catch completion problems with predefineds
407 syms = Symtab.instance(context);
408 } catch (CompletionFailure ex) {
409 // inlined Check.completionError as it is not initialized yet
410 log.error("cant.access", ex.sym, ex.getDetailValue());
412 source = Source.instance(context);
413 attr = Attr.instance(context);
414 chk = Check.instance(context);
415 gen = Gen.instance(context);
416 flow = Flow.instance(context);
417 repair = Repair.instance(context);
418 transTypes = TransTypes.instance(context);
419 lower = Lower.instance(context);
420 annotate = Annotate.instance(context);
421 types = Types.instance(context);
422 taskListener = MultiTaskListener.instance(context);
423 modules = Modules.instance(context);
424 moduleFinder = ModuleFinder.instance(context);
425 diags = Factory.instance(context);
426 duplicateClassChecker = context.get(DuplicateClassChecker.class);
428 finder.sourceCompleter = sourceCompleter;
429 modules.findPackageInFile = this::findPackageInFile;
430 moduleFinder.moduleNameFromSourceReader = this::readModuleName;
432 options = Options.instance(context);
434 verbose = options.isSet(VERBOSE);
435 sourceOutput = options.isSet(PRINTSOURCE); // used to be -s
436 lineDebugInfo = options.isUnset(G_CUSTOM) ||
437 options.isSet(G_CUSTOM, "lines");
438 genEndPos = options.isSet(XJCOV) ||
439 (context.get(DiagnosticListener.class) != null && options.get("backgroundCompilation") == null);
440 devVerbose = options.isSet("dev");
441 processPcks = options.isSet("process.packages");
442 werror = options.isSet(WERROR);
443 keepComments = options.getBoolean("keepComments");
445 verboseCompilePolicy = options.isSet("verboseCompilePolicy");
447 if (options.isSet("should-stop.at") &&
448 CompileState.valueOf(options.get("should-stop.at")) == CompileState.ATTR)
449 compilePolicy = CompilePolicy.ATTR_ONLY;
451 compilePolicy = CompilePolicy.decode(options.get("compilePolicy"));
453 implicitSourcePolicy = ImplicitSourcePolicy.decode(options.get("-implicit"));
455 completionFailureName =
456 options.isSet("failcomplete")
457 ? names.fromString(options.get("failcomplete"))
460 shouldStopPolicyIfError =
461 options.isSet("should-stop.at") // backwards compatible
462 ? CompileState.valueOf(options.get("should-stop.at"))
463 : options.isSet("should-stop.ifError")
464 ? CompileState.valueOf(options.get("should-stop.ifError"))
466 shouldStopPolicyIfNoError =
467 options.isSet("should-stop.ifNoError")
468 ? CompileState.valueOf(options.get("should-stop.ifNoError"))
469 : CompileState.GENERATE;
471 if (options.isUnset("diags.legacy"))
472 log.setDiagnosticFormatter(RichDiagnosticFormatter.instance(context));
474 PlatformDescription platformProvider = context.get(PlatformDescription.class);
476 if (platformProvider != null)
477 closeables = closeables.prepend(platformProvider);
479 silentFail = new Symbol(ABSENT_TYP, 0, names.empty, Type.noType, syms.rootPackage) {
480 @DefinedBy(Api.LANGUAGE_MODEL)
481 public <R, P> R accept(ElementVisitor<R, P> v, P p) {
482 return v.visitUnknown(this, p);
485 public boolean exists() {
497 public boolean verbose;
499 /** Emit plain Java source files rather than class files.
501 public boolean sourceOutput;
504 /** Generate code with the LineNumberTable attribute for debugging
506 public boolean lineDebugInfo;
508 /** Switch: should we store the ending positions?
510 public boolean genEndPos;
512 /** Switch: should we debug ignored exceptions
514 protected boolean devVerbose;
516 /** Switch: should we (annotation) process packages as well
518 protected boolean processPcks;
520 /** Switch: treat warnings as errors
522 protected boolean werror;
524 /** Switch: is annotation processing requested explicitly via
525 * CompilationTask.setProcessors?
527 protected boolean explicitAnnotationProcessingRequested = false;
530 * The policy for the order in which to perform the compilation
532 protected CompilePolicy compilePolicy;
535 * The policy for what to do with implicitly read source files
537 protected ImplicitSourcePolicy implicitSourcePolicy;
540 * Report activity related to compilePolicy
542 public boolean verboseCompilePolicy;
545 * Policy of how far to continue compilation after errors have occurred.
546 * Set this to minimum CompileState (INIT) to stop as soon as possible
549 public CompileState shouldStopPolicyIfError;
552 * Policy of how far to continue compilation when no errors have occurred.
553 * Set this to maximum CompileState (GENERATE) to perform full compilation.
554 * Set this lower to perform partial compilation, such as -proc:only.
556 public CompileState shouldStopPolicyIfNoError;
558 /** A queue of all as yet unattributed classes.
562 /** A list of items to be closed when the compilation is complete.
564 public List<Closeable> closeables = List.nil();
566 /** The set of currently compiled inputfiles, needed to ensure
567 * we don't accidentally overwrite an input file when -s is set.
568 * initialized by `compile'.
570 protected Set<JavaFileObject> inputFiles = new HashSet<>();
572 /** Used by the resolveBinaryNameOrIdent to say that the given type cannot be found, and that
573 * an error has already been produced about that.
575 private final Symbol silentFail;
577 protected boolean shouldStop(CompileState cs) {
578 CompileState shouldStopPolicy = (errorCount() > 0 || unrecoverableError())
579 ? shouldStopPolicyIfError
580 : shouldStopPolicyIfNoError;
581 return cs.isAfter(shouldStopPolicy);
584 /** The number of errors reported so far.
586 public int errorCount() {
587 if (werror && log.nerrors == 0 && log.nwarnings > 0) {
588 log.error("warnings.and.werror");
593 protected final <T> Queue<T> stopIfError(CompileState cs, Queue<T> queue) {
594 return shouldStop(cs) ? new ListBuffer<T>() : queue;
597 protected final <T> List<T> stopIfError(CompileState cs, List<T> list) {
598 return shouldStop(cs) ? List.nil() : list;
601 /** The number of warnings reported so far.
603 public int warningCount() {
604 return log.nwarnings;
607 /** Try to open input stream with given name.
608 * Report an error if this fails.
609 * @param filename The file name of the input stream to be opened.
611 public CharSequence readSource(JavaFileObject filename) {
613 inputFiles.add(filename);
614 return filename.getCharContent(false);
615 } catch (IOException e) {
616 log.error("error.reading.file", filename, JavacFileManager.getMessage(e));
621 /** Parse contents of input stream.
622 * @param filename The name of the file from which input stream comes.
623 * @param content The characters to be parsed.
625 protected JCCompilationUnit parse(JavaFileObject filename, CharSequence content) {
627 JCCompilationUnit tree = make.TopLevel(List.nil());
628 if (content != null) {
630 log.printVerbose("parsing.started", filename);
632 if (!taskListener.isEmpty()) {
633 TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, filename);
634 taskListener.started(e);
638 Parser parser = parserFactory.newParser(content, keepComments(), genEndPos,
639 lineDebugInfo, filename != null && filename.isNameCompatible("module-info", Kind.SOURCE));
640 tree = parser.parseCompilationUnit();
642 log.printVerbose("parsing.done", Long.toString(elapsed(msec)));
646 tree.sourcefile = filename;
648 if (content != null && !taskListener.isEmpty()) {
649 TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, tree);
650 taskListener.finished(e);
656 public boolean keepComments = false;
657 protected boolean keepComments() {
658 return keepComments || sourceOutput;
662 /** Parse contents of file.
663 * @param filename The name of the file to be parsed.
666 public JCTree.JCCompilationUnit parse(String filename) {
667 JavacFileManager fm = (JavacFileManager)fileManager;
668 return parse(fm.getJavaFileObjectsFromStrings(List.of(filename)).iterator().next());
671 /** Parse contents of file.
672 * @param filename The name of the file to be parsed.
674 public JCTree.JCCompilationUnit parse(JavaFileObject filename) {
675 JavaFileObject prev = log.useSource(filename);
677 JCTree.JCCompilationUnit t = parse(filename, readSource(filename));
678 if (t.endPositions != null)
679 log.setEndPosTable(filename, t.endPositions);
686 /** Resolve an identifier which may be the binary name of a class or
687 * the Java name of a class or package.
688 * @param name The name to resolve
690 public Symbol resolveBinaryNameOrIdent(String name) {
693 int sep = name.indexOf('/');
695 msym = modules.getDefaultModule();
697 } else if (source.allowModules()) {
698 Name modName = names.fromString(name.substring(0, sep));
700 msym = moduleFinder.findModule(modName);
701 typeName = name.substring(sep + 1);
703 log.error(Errors.InvalidModuleSpecifier(name));
707 return resolveBinaryNameOrIdent(msym, typeName);
710 /** Resolve an identifier which may be the binary name of a class or
711 * the Java name of a class or package.
712 * @param msym The module in which the search should be performed
713 * @param name The name to resolve
715 public Symbol resolveBinaryNameOrIdent(ModuleSymbol msym, String name) {
717 Name flatname = names.fromString(name.replace("/", "."));
718 return finder.loadClass(msym, flatname);
719 } catch (CompletionFailure ignore) {
720 return resolveIdent(msym, name);
724 /** Resolve an identifier.
725 * @param msym The module in which the search should be performed
726 * @param name The identifier to resolve
728 public Symbol resolveIdent(ModuleSymbol msym, String name) {
730 return syms.errSymbol;
731 JavaFileObject prev = log.useSource(null);
732 Log.DiagnosticHandler discardHandler = new Log.DiscardDiagnosticHandler(log);
733 Log.DeferredDiagnosticHandler deferredHandler = deferredDiagnosticHandler;
734 deferredDiagnosticHandler = null;
736 JCExpression tree = null;
737 for (String s : name.split("\\.", -1)) {
738 if (!SourceVersion.isIdentifier(s)) // TODO: check for keywords
739 return syms.errSymbol;
740 tree = (tree == null) ? make.Ident(names.fromString(s))
741 : make.Select(tree, names.fromString(s));
743 JCCompilationUnit toplevel =
744 make.TopLevel(List.nil());
745 toplevel.modle = msym;
746 toplevel.packge = msym.unnamedPackage;
747 Symbol ret = attr.attribIdent(tree, toplevel);
748 if (!skipAnnotationProcessing && deferredDiagnosticHandler != null && toProcessAnnotations.nonEmpty())
749 processAnnotations(List.<JCCompilationUnit>nil());
752 deferredDiagnosticHandler = deferredHandler;
753 log.popDiagnosticHandler(discardHandler);
758 /** Generate code and emit a class file for a given class
759 * @param env The attribution environment of the outermost class
760 * containing this class.
761 * @param cdef The class definition from which code is generated.
763 JavaFileObject genCode(Env<AttrContext> env, JCClassDecl cdef) throws IOException {
765 if (gen.genClass(env, cdef))
766 return writer.writeClass(cdef.sym);
767 } catch (ClassWriter.PoolOverflow ex) {
768 log.error(cdef.pos(), "limit.pool");
769 } catch (ClassWriter.StringOverflow ex) {
770 log.error(cdef.pos(), "limit.string.overflow",
771 ex.value.substring(0, 20));
772 } catch (CompletionFailure ex) {
773 chk.completionError(cdef.pos(), ex);
778 /** Emit plain Java source for a class.
779 * @param env The attribution environment of the outermost class
780 * containing this class.
781 * @param cdef The class definition to be printed.
783 JavaFileObject printSource(Env<AttrContext> env, JCClassDecl cdef) throws IOException {
784 JavaFileObject outFile
785 = fileManager.getJavaFileForOutput(CLASS_OUTPUT,
786 cdef.sym.flatname.toString(),
787 JavaFileObject.Kind.SOURCE,
789 if (inputFiles.contains(outFile)) {
790 log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile);
793 try (BufferedWriter out = new BufferedWriter(outFile.openWriter())) {
794 new Pretty(out, true).printUnit(env.toplevel, cdef);
796 log.printVerbose("wrote.file", outFile);
802 /** Compile a source file that has been accessed by the class finder.
803 * @param c The class the source file of which needs to be compiled.
805 private void readSourceFile(ClassSymbol c) throws CompletionFailure {
806 readSourceFile(null, c);
809 /** Compile a ClassSymbol from source, optionally using the given compilation unit as
811 * @param tree the compilation unit in which the given ClassSymbol resides,
812 * or null if should be parsed from source
813 * @param c the ClassSymbol to complete
815 public void readSourceFile(JCCompilationUnit tree, ClassSymbol c) throws CompletionFailure {
816 if (completionFailureName == c.fullname) {
817 throw new CompletionFailure(c, "user-selected completion failure by class name");
819 JavaFileObject filename = c.classfile;
821 if (tree == null && notYetEntered != null) {
822 tree = notYetEntered.remove(filename);
825 JavaFileObject prev = log.useSource(filename);
827 tree = parse(filename, filename.getCharContent(false));
828 } catch (IOException e) {
829 log.error("error.reading.file", filename, JavacFileManager.getMessage(e));
830 tree = make.TopLevel(List.<JCTree>nil());
836 if (!taskListener.isEmpty()) {
837 TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree);
838 taskListener.started(e);
841 Log.DeferredDiagnosticHandler h = null;
842 if (!skipAnnotationProcessing && processAnnotations && deferredDiagnosticHandler == null)
843 deferredDiagnosticHandler = h = new Log.DeferredDiagnosticHandler(log);
846 // Process module declarations.
847 // If module resolution fails, ignore trees, and if trying to
848 // complete a specific symbol, throw CompletionFailure.
849 // Note that if module resolution failed, we may not even
850 // have enough modules available to access java.lang, and
851 // so risk getting FatalError("no.java.lang") from MemberEnter.
852 if (!modules.enter(List.of(tree), c)) {
853 throw new CompletionFailure(c, diags.fragment("cant.resolve.modules"));
856 enter.complete(List.of(tree), c);
858 if (!taskListener.isEmpty()) {
859 TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree);
860 taskListener.finished(e);
863 if (enter.getEnv(c) == null) {
865 tree.sourcefile.isNameCompatible("package-info",
866 JavaFileObject.Kind.SOURCE);
867 boolean isModuleInfo =
868 tree.sourcefile.isNameCompatible("module-info",
869 JavaFileObject.Kind.SOURCE);
871 if (enter.getEnv(tree.modle) == null) {
873 log.popDiagnosticHandler(h);
874 deferredDiagnosticHandler = null;
877 diagFactory.fragment("file.does.not.contain.module");
878 throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
880 } else if (isPkgInfo) {
881 if (enter.getEnv(tree.packge) == null) {
883 log.popDiagnosticHandler(h);
884 deferredDiagnosticHandler = null;
887 diagFactory.fragment("file.does.not.contain.package",
889 throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
893 log.popDiagnosticHandler(h);
894 deferredDiagnosticHandler = null;
897 diagFactory.fragment("file.doesnt.contain.class",
898 c.getQualifiedName());
899 throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
903 if (!skipAnnotationProcessing && processAnnotations && checkEntered(tree)) {
904 JCCompilationUnit t = tree;
906 if (annotate.annotationsBlocked() || annotate.isFlushing()) {
907 toProcessAnnotations = toProcessAnnotations.prepend(t);
909 skipAnnotationProcessing = true;
911 processAnnotations(List.of(t));
913 skipAnnotationProcessing = false;
919 implicitSourceFilesRead = true;
922 private boolean checkEntered(JCCompilationUnit unit) {
923 for (JCTree node : unit.defs) {
924 if (node.hasTag(JCTree.Tag.CLASSDEF)) {
925 if (((JCClassDecl) node).sym == null) {
933 /** Track when the JavaCompiler has been used to compile something. */
934 private boolean hasBeenUsed = false;
935 private long start_msec = 0;
936 public long elapsed_msec = 0;
938 public void compile(List<JavaFileObject> sourceFileObject)
940 compile(sourceFileObject, List.nil(), null, List.nil());
944 * Main method: compile a list of files, return all compiled classes
946 * @param sourceFileObjects file objects to be compiled
947 * @param classnames class names to process for annotations
948 * @param processors user provided annotation processors to bypass
949 * discovery, {@code null} means that no processors were provided
950 * @param addModules additional root modules to be used during
953 public void compile(Collection<JavaFileObject> sourceFileObjects,
954 Collection<String> classnames,
955 Iterable<? extends Processor> processors,
956 Collection<String> addModules)
958 if (!taskListener.isEmpty()) {
959 taskListener.started(new TaskEvent(TaskEvent.Kind.COMPILATION));
962 if (processors != null && processors.iterator().hasNext())
963 explicitAnnotationProcessingRequested = true;
964 // as a JavaCompiler can only be used once, throw an exception if
965 // it has been used before.
970 // forcibly set the equivalent of -Xlint:-options, so that no further
971 // warnings about command line options are generated from this point on
972 options.put(XLINT_CUSTOM.primaryName + "-" + LintCategory.OPTIONS.option, "true");
973 options.remove(XLINT_CUSTOM.primaryName + LintCategory.OPTIONS.option);
978 initProcessAnnotations(processors, sourceFileObjects, classnames);
980 for (String className : classnames) {
981 int sep = className.indexOf('/');
983 modules.addExtraAddModules(className.substring(0, sep));
987 for (String moduleName : addModules) {
988 modules.addExtraAddModules(moduleName);
991 // These method calls must be chained to avoid memory leaks
994 stopIfError(CompileState.PARSE,
995 initModules(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))))
1000 // If it's safe to do so, skip attr / flow / gen for implicit classes
1001 if (taskListener.isEmpty() &&
1002 implicitSourcePolicy == ImplicitSourcePolicy.NONE) {
1003 todo.retainFiles(inputFiles);
1006 switch (compilePolicy) {
1012 flow(attribute(todo));
1016 generate(desugar(flow(attribute(todo))));
1020 Queue<Queue<Env<AttrContext>>> q = todo.groupByFile();
1021 while (!q.isEmpty() && !shouldStop(CompileState.ATTR)) {
1022 generate(desugar(flow(attribute(q.remove()))));
1028 while (!todo.isEmpty())
1029 generate(desugar(flow(attribute(todo.remove()))));
1033 Assert.error("unknown compile policy");
1035 } catch (Abort ex) {
1037 ex.printStackTrace(System.err);
1040 elapsed_msec = elapsed(start_msec);
1041 log.printVerbose("total", Long.toString(elapsed_msec));
1044 reportDeferredDiagnostics();
1046 if (!log.hasDiagnosticListener()) {
1047 printCount("error", errorCount());
1048 printCount("warn", warningCount());
1050 if (!taskListener.isEmpty()) {
1051 taskListener.finished(new TaskEvent(TaskEvent.Kind.COMPILATION));
1054 if (procEnvImpl != null)
1055 procEnvImpl.close();
1059 protected void checkReusable() {
1060 throw new AssertionError("attempt to reuse JavaCompiler");
1064 * The list of classes explicitly supplied on the command line for compilation.
1065 * Not always populated.
1067 private List<JCClassDecl> rootClasses;
1070 * Parses a list of files.
1072 public List<JCCompilationUnit> parseFiles(Iterable<JavaFileObject> fileObjects) {
1073 if (shouldStop(CompileState.PARSE))
1077 ListBuffer<JCCompilationUnit> trees = new ListBuffer<>();
1078 Set<JavaFileObject> filesSoFar = new HashSet<>();
1079 for (JavaFileObject fileObject : fileObjects) {
1080 if (!filesSoFar.contains(fileObject)) {
1081 filesSoFar.add(fileObject);
1082 trees.append(parse(fileObject));
1085 return trees.toList();
1089 * Enter the symbols found in a list of parse trees if the compilation
1090 * is expected to proceed beyond anno processing into attr.
1091 * As a side-effect, this puts elements on the "todo" list.
1092 * Also stores a list of all top level classes in rootClasses.
1094 public List<JCCompilationUnit> enterTreesIfNeeded(List<JCCompilationUnit> roots) {
1095 if (shouldStop(CompileState.ATTR))
1097 return enterTrees(initModules(roots));
1100 public List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots) {
1101 modules.initModules(roots);
1102 if (roots.isEmpty()) {
1109 * Enter the symbols found in a list of parse trees.
1110 * As a side-effect, this puts elements on the "todo" list.
1111 * Also stores a list of all top level classes in rootClasses.
1113 public List<JCCompilationUnit> enterTrees(List<JCCompilationUnit> roots) {
1114 //enter symbols for all files
1115 if (!taskListener.isEmpty()) {
1116 for (JCCompilationUnit unit: roots) {
1117 TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit);
1118 taskListener.started(e);
1126 if (!taskListener.isEmpty()) {
1127 for (JCCompilationUnit unit: roots) {
1128 TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit);
1129 taskListener.finished(e);
1133 // If generating source, or if tracking public apis,
1134 // then remember the classes declared in
1135 // the original compilation units listed on the command line.
1137 ListBuffer<JCClassDecl> cdefs = new ListBuffer<>();
1138 for (JCCompilationUnit unit : roots) {
1139 for (List<JCTree> defs = unit.defs;
1142 if (defs.head instanceof JCClassDecl) {
1143 cdefs.append((JCClassDecl) defs.head);
1147 rootClasses = cdefs.toList();
1150 // Ensure the input files have been recorded. Although this is normally
1151 // done by readSource, it may not have been done if the trees were read
1152 // in a prior round of annotation processing, and the trees have been
1153 // cleaned and are being reused.
1154 for (JCCompilationUnit unit : roots) {
1155 inputFiles.add(unit.sourcefile);
1161 public void initNotYetEntered(Map<JavaFileObject, JCCompilationUnit> notYetEntered) {
1162 this.notYetEntered = notYetEntered;
1166 * Set to true to enable skeleton annotation processing code.
1167 * Currently, we assume this variable will be replaced more
1168 * advanced logic to figure out if annotation processing is
1171 public boolean processAnnotations = false;
1173 public Log.DeferredDiagnosticHandler deferredDiagnosticHandler;
1176 * Object to handle annotation processing.
1178 private JavacProcessingEnvironment procEnvImpl = null;
1181 * Check if we should process annotations.
1182 * If so, and if no scanner is yet registered, then set up the DocCommentScanner
1183 * to catch doc comments, and set keepComments so the parser records them in
1184 * the compilation unit.
1186 * @param processors user provided annotation processors to bypass
1187 * discovery, {@code null} means that no processors were provided
1189 public void initProcessAnnotations(Iterable<? extends Processor> processors,
1190 Collection<? extends JavaFileObject> initialFiles,
1191 Collection<String> initialClassNames) {
1192 // Process annotations if processing is not disabled and there
1193 // is at least one Processor available.
1194 if (options.isSet(PROC, "none")) {
1195 processAnnotations = false;
1196 } else if (procEnvImpl == null) {
1197 procEnvImpl = JavacProcessingEnvironment.instance(context);
1198 procEnvImpl.setProcessors(processors);
1199 processAnnotations = procEnvImpl.atLeastOneProcessor();
1201 if (processAnnotations) {
1202 options.put("parameters", "parameters");
1203 reader.saveParameterNames = true;
1204 keepComments = true;
1206 if (!taskListener.isEmpty())
1207 taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
1208 deferredDiagnosticHandler = new Log.DeferredDiagnosticHandler(log);
1209 procEnvImpl.getFiler().setInitialState(initialFiles, initialClassNames);
1210 } else { // free resources
1211 procEnvImpl.close();
1216 // TODO: called by JavacTaskImpl
1217 public void processAnnotations(List<JCCompilationUnit> roots) {
1218 processAnnotations(roots, List.nil());
1222 * Process any annotations found in the specified compilation units.
1223 * @param roots a list of compilation units
1225 // Implementation note: when this method is called, log.deferredDiagnostics
1226 // will have been set true by initProcessAnnotations, meaning that any diagnostics
1227 // that are reported will go into the log.deferredDiagnostics queue.
1228 // By the time this method exits, log.deferDiagnostics must be set back to false,
1229 // and all deferredDiagnostics must have been handled: i.e. either reported
1230 // or determined to be transient, and therefore suppressed.
1231 public void processAnnotations(List<JCCompilationUnit> roots,
1232 Collection<String> classnames) {
1233 List<JCCompilationUnit> currentRoots = toProcessAnnotations.prependList(roots);
1234 toProcessAnnotations = List.nil();
1235 if (shouldStop(CompileState.PROCESS)) {
1236 // Errors were encountered.
1237 // Unless all the errors are resolve errors, the errors were parse errors
1238 // or other errors during enter which cannot be fixed by running
1239 // any annotation processors.
1240 if (unrecoverableError()) {
1241 deferredDiagnosticHandler.reportDeferredDiagnostics();
1242 log.popDiagnosticHandler(deferredDiagnosticHandler);
1243 deferredDiagnosticHandler = null;
1248 // ASSERT: processAnnotations and procEnvImpl should have been set up by
1249 // by initProcessAnnotations
1251 // NOTE: The !classnames.isEmpty() checks should be refactored to Main.
1253 if (!processAnnotations) {
1254 // If there are no annotation processors present, and
1255 // annotation processing is to occur with compilation,
1257 if (options.isSet(PROC, "only")) {
1258 log.warning("proc.proc-only.requested.no.procs");
1261 // If not processing annotations, classnames must be empty
1262 if (!classnames.isEmpty()) {
1263 log.error("proc.no.explicit.annotation.processing.requested",
1266 Assert.checkNull(deferredDiagnosticHandler);
1267 return ; // continue regular compilation
1270 Assert.checkNonNull(deferredDiagnosticHandler);
1273 List<ClassSymbol> classSymbols = List.nil();
1274 List<PackageSymbol> pckSymbols = List.nil();
1275 if (!classnames.isEmpty()) {
1276 // Check for explicit request for annotation
1278 if (!explicitAnnotationProcessingRequested()) {
1279 log.error("proc.no.explicit.annotation.processing.requested",
1281 deferredDiagnosticHandler.reportDeferredDiagnostics();
1282 log.popDiagnosticHandler(deferredDiagnosticHandler);
1283 deferredDiagnosticHandler = null;
1284 return ; // TODO: Will this halt compilation?
1286 boolean errors = false;
1287 for (String nameStr : classnames) {
1288 Symbol sym = resolveBinaryNameOrIdent(nameStr);
1290 (sym.kind == PCK && !processPcks) ||
1291 sym.kind == ABSENT_TYP) {
1292 if (sym != silentFail)
1293 log.error(Errors.ProcCantFindClass(nameStr));
1298 if (sym.kind == PCK)
1301 if (sym.kind == PCK)
1302 pckSymbols = pckSymbols.prepend((PackageSymbol)sym);
1304 classSymbols = classSymbols.prepend((ClassSymbol)sym);
1307 Assert.check(sym.kind == PCK);
1308 log.warning(Warnings.ProcPackageDoesNotExist(nameStr));
1309 pckSymbols = pckSymbols.prepend((PackageSymbol)sym);
1310 } catch (CompletionFailure e) {
1311 log.error(Errors.ProcCantFindClass(nameStr));
1317 deferredDiagnosticHandler.reportDeferredDiagnostics();
1318 log.popDiagnosticHandler(deferredDiagnosticHandler);
1319 deferredDiagnosticHandler = null;
1324 final boolean hasOrigin = currentRoots.nonEmpty();
1326 fileManager.handleOption("apt-origin", Collections.singleton(currentRoots.head.getSourceFile().toUri().toString()).iterator()); //NOI18N
1329 annotationProcessingOccurred =
1330 procEnvImpl.doProcessing(currentRoots,
1333 deferredDiagnosticHandler);
1334 // doProcessing will have handled deferred diagnostics
1337 fileManager.handleOption("apt-origin", Collections.singletonList("").iterator()); //NOI18N
1340 } catch (CompletionFailure ex) {
1341 log.error("cant.access", ex.sym, ex.getDetailValue());
1342 if (deferredDiagnosticHandler != null) {
1343 deferredDiagnosticHandler.reportDeferredDiagnostics();
1344 log.popDiagnosticHandler(deferredDiagnosticHandler);
1345 deferredDiagnosticHandler = null;
1350 private boolean unrecoverableError() {
1351 if (deferredDiagnosticHandler != null) {
1352 for (JCDiagnostic d: deferredDiagnosticHandler.getDiagnostics()) {
1353 if (d.getKind() == JCDiagnostic.Kind.ERROR && !d.isFlagSet(RECOVERABLE))
1360 boolean explicitAnnotationProcessingRequested() {
1362 explicitAnnotationProcessingRequested ||
1363 explicitAnnotationProcessingRequested(options);
1366 static boolean explicitAnnotationProcessingRequested(Options options) {
1368 options.isSet(PROCESSOR) ||
1369 options.isSet(PROCESSOR_PATH) ||
1370 options.isSet(PROCESSOR_MODULE_PATH) ||
1371 options.isSet(PROC, "only") ||
1372 options.isSet(XPRINT);
1375 public void setDeferredDiagnosticHandler(Log.DeferredDiagnosticHandler deferredDiagnosticHandler) {
1376 this.deferredDiagnosticHandler = deferredDiagnosticHandler;
1380 * Attribute a list of parse trees, such as found on the "todo" list.
1381 * Note that attributing classes may cause additional files to be
1382 * parsed and entered via the SourceCompleter.
1383 * Attribution of the entries in the list does not stop if any errors occur.
1384 * @return a list of environments for attribute classes.
1386 public Queue<Env<AttrContext>> attribute(Queue<Env<AttrContext>> envs) {
1387 ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
1388 while (!envs.isEmpty())
1389 results.append(attribute(envs.remove()));
1390 return stopIfError(CompileState.ATTR, results);
1394 * Attribute a parse tree.
1395 * @return the attributed parse tree
1397 public Env<AttrContext> attribute(Env<AttrContext> env) {
1398 if (compileStates.isDone(env, CompileState.ATTR))
1401 if (verboseCompilePolicy)
1402 printNote("[attribute " + env.enclClass.sym + "]");
1404 log.printVerbose("checking.attribution", env.enclClass.sym);
1406 if (!taskListener.isEmpty()) {
1407 TaskEvent e = new TaskEvent(TaskEvent.Kind.ANALYZE, env.toplevel, env.enclClass.sym);
1408 taskListener.started(e);
1411 JavaFileObject prev = log.useSource(
1412 env.enclClass.sym.sourcefile != null ?
1413 env.enclClass.sym.sourcefile :
1414 env.toplevel.sourcefile);
1417 if (!shouldStop(CompileState.ATTR)) {
1418 //if in fail-over mode, ensure that AST expression nodes
1419 //are correctly initialized (e.g. they have a type/symbol)
1420 attr.postAttr(env.tree);
1422 compileStates.put(env, CompileState.ATTR);
1425 log.useSource(prev);
1432 * Perform dataflow checks on attributed parse trees.
1433 * These include checks for definite assignment and unreachable statements.
1434 * If any errors occur, an empty list will be returned.
1435 * @return the list of attributed parse trees
1437 public Queue<Env<AttrContext>> flow(Queue<Env<AttrContext>> envs) {
1438 ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
1439 for (Env<AttrContext> env: envs) {
1442 return stopIfError(CompileState.FLOW, results);
1446 * Perform dataflow checks on an attributed parse tree.
1448 public Queue<Env<AttrContext>> flow(Env<AttrContext> env) {
1449 ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
1451 return stopIfError(CompileState.FLOW, results);
1455 * Perform dataflow checks on an attributed parse tree.
1457 protected void flow(Env<AttrContext> env, Queue<Env<AttrContext>> results) {
1458 if (compileStates.isDone(env, CompileState.FLOW)) {
1464 if (shouldStop(CompileState.FLOW))
1467 if (verboseCompilePolicy)
1468 printNote("[flow " + env.enclClass.sym + "]");
1469 JavaFileObject prev = log.useSource(
1470 env.enclClass.sym.sourcefile != null ?
1471 env.enclClass.sym.sourcefile :
1472 env.toplevel.sourcefile);
1474 make.at(Position.FIRSTPOS);
1475 TreeMaker localMake = make.forToplevel(env.toplevel);
1476 flow.analyzeTree(env, localMake);
1477 compileStates.put(env, CompileState.FLOW);
1479 if (shouldStop(CompileState.FLOW))
1485 log.useSource(prev);
1489 if (!taskListener.isEmpty()) {
1490 TaskEvent e = new TaskEvent(TaskEvent.Kind.ANALYZE, env.toplevel, env.enclClass.sym);
1491 taskListener.finished(e);
1496 public boolean doRepair = true; // Allows for switching off repair. For test purposes only.
1499 * Prepare attributed parse trees, in conjunction with their attribution contexts,
1500 * for source or code generation.
1501 * If any errors occur, an empty list will be returned.
1502 * @return a list containing the classes to be generated
1504 public Queue<Pair<Env<AttrContext>, JCClassDecl>> desugar(Queue<Env<AttrContext>> envs) {
1505 ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results = new ListBuffer<>();
1506 for (Env<AttrContext> env: envs)
1507 desugar(env, results);
1508 return stopIfError(CompileState.FLOW, results);
1511 HashMap<Env<AttrContext>, Queue<Pair<Env<AttrContext>, JCClassDecl>>> desugaredEnvs = new HashMap<>();
1514 * Prepare attributed parse trees, in conjunction with their attribution contexts,
1515 * for source or code generation. If the file was not listed on the command line,
1516 * the current implicitSourcePolicy is taken into account.
1517 * The preparation stops as soon as an error is found.
1519 protected void desugar(final Env<AttrContext> env, Queue<Pair<Env<AttrContext>, JCClassDecl>> results) {
1520 if (shouldStop(CompileState.TRANSTYPES))
1523 if (implicitSourcePolicy == ImplicitSourcePolicy.NONE
1524 && !inputFiles.contains(env.toplevel.sourcefile)) {
1528 if (!modules.multiModuleMode && env.toplevel.modle != modules.getDefaultModule()) {
1529 //can only generate classfiles for a single module:
1533 if (duplicateClassChecker != null && env.tree.hasTag(JCTree.Tag.CLASSDEF) && duplicateClassChecker.check(((JCClassDecl)env.tree).sym.fullname,
1534 env.enclClass.sym.sourcefile != null
1535 ? env.enclClass.sym.sourcefile
1536 : env.toplevel.sourcefile)) {
1540 if (compileStates.isDone(env, CompileState.LOWER)) {
1541 results.addAll(desugaredEnvs.get(env));
1546 * Ensure that superclasses of C are desugared before C itself. This is
1547 * required for two reasons: (i) as erasure (TransTypes) destroys
1548 * information needed in flow analysis and (ii) as some checks carried
1549 * out during lowering require that all synthetic fields/methods have
1550 * already been added to C and its superclasses.
1552 class ScanNested extends TreeScanner {
1553 Set<Env<AttrContext>> dependencies = new LinkedHashSet<>();
1554 protected boolean hasLambdas;
1556 public void visitClassDef(JCClassDecl node) {
1557 if (node.sym != null) {
1558 Type st = types.supertype(node.sym.type);
1559 boolean envForSuperTypeFound = false;
1560 while (!envForSuperTypeFound && st != null && st.hasTag(CLASS)) {
1561 ClassSymbol c = st.tsym.outermostClass();
1562 Env<AttrContext> stEnv = enter.getEnv(c);
1563 if (stEnv != null && env != stEnv) {
1564 if (dependencies.add(stEnv)) {
1565 boolean prevHasLambdas = hasLambdas;
1570 * ignore any updates to hasLambdas made during
1571 * the nested scan, this ensures an initalized
1572 * LambdaToMethod is available only to those
1573 * classes that contain lambdas
1575 hasLambdas = prevHasLambdas;
1578 envForSuperTypeFound = true;
1580 st = types.supertype(st);
1583 super.visitClassDef(node);
1586 public void visitLambda(JCLambda tree) {
1588 super.visitLambda(tree);
1591 public void visitReference(JCMemberReference tree) {
1593 super.visitReference(tree);
1596 ScanNested scanner = new ScanNested();
1597 scanner.scan(env.tree);
1598 for (Env<AttrContext> dep: scanner.dependencies) {
1599 if (!compileStates.isDone(dep, CompileState.FLOW))
1600 desugaredEnvs.put(dep, desugar(flow(attribute(dep))));
1603 //We need to check for error another time as more classes might
1604 //have been attributed and analyzed at this stage
1605 if (shouldStop(CompileState.TRANSTYPES))
1608 if (verboseCompilePolicy)
1609 printNote("[desugar " + env.enclClass.sym + "]");
1611 JavaFileObject prev = log.useSource(env.enclClass.sym.sourcefile != null ?
1612 env.enclClass.sym.sourcefile :
1613 env.toplevel.sourcefile);
1615 //save tree prior to rewriting
1616 JCTree untranslated = env.tree;
1618 make.at(Position.FIRSTPOS);
1619 TreeMaker localMake = make.forToplevel(env.toplevel);
1621 if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF) || env.tree.hasTag(JCTree.Tag.MODULEDEF)) {
1622 if (!(sourceOutput)) {
1623 if (shouldStop(CompileState.LOWER))
1625 List<JCTree> def = lower.translateTopLevelClass(env, env.tree, localMake);
1626 if (def.head != null) {
1627 Assert.check(def.tail.isEmpty());
1628 results.add(new Pair<>(env, (JCClassDecl)def.head));
1635 env.tree = repair.translateTopLevelClass(env, env.tree, localMake);
1637 if (shouldStop(CompileState.TRANSTYPES))
1640 env.tree = transTypes.translateTopLevelClass(env.tree, localMake);
1641 compileStates.put(env, CompileState.TRANSTYPES);
1643 if (source.allowLambda() && scanner.hasLambdas) {
1644 if (shouldStop(CompileState.UNLAMBDA))
1647 env.tree = LambdaToMethod.instance(context).translateTopLevelClass(env, env.tree, localMake);
1648 compileStates.put(env, CompileState.UNLAMBDA);
1651 if (shouldStop(CompileState.LOWER))
1655 //emit standard Java source file, only for compilation
1656 //units enumerated explicitly on the command line
1657 JCClassDecl cdef = (JCClassDecl)env.tree;
1658 if (untranslated instanceof JCClassDecl &&
1659 rootClasses.contains((JCClassDecl)untranslated)) {
1660 results.add(new Pair<>(env, cdef));
1665 //translate out inner classes
1666 List<JCTree> cdefs = lower.translateTopLevelClass(env, env.tree, localMake);
1667 compileStates.put(env, CompileState.LOWER);
1669 if (shouldStop(CompileState.LOWER))
1672 //generate code for each class
1673 for (List<JCTree> l = cdefs; l.nonEmpty(); l = l.tail) {
1674 JCClassDecl cdef = (JCClassDecl)l.head;
1675 results.add(new Pair<>(env, cdef));
1679 log.useSource(prev);
1684 /** Generates the source or class file for a list of classes.
1685 * The decision to generate a source file or a class file is
1686 * based upon the compiler's options.
1687 * Generation stops if an error occurs while writing files.
1689 public void generate(Queue<Pair<Env<AttrContext>, JCClassDecl>> queue) {
1690 generate(queue, null);
1693 public void generate(Queue<Pair<Env<AttrContext>, JCClassDecl>> queue, Queue<JavaFileObject> results) {
1694 if (shouldStop(CompileState.GENERATE))
1697 for (Pair<Env<AttrContext>, JCClassDecl> x: queue) {
1698 Env<AttrContext> env = x.fst;
1699 JCClassDecl cdef = x.snd;
1701 if (verboseCompilePolicy) {
1702 printNote("[generate " + (sourceOutput ? " source" : "code") + " " + cdef.sym + "]");
1705 if (!taskListener.isEmpty()) {
1706 TaskEvent e = new TaskEvent(TaskEvent.Kind.GENERATE, env.toplevel, cdef.sym);
1707 taskListener.started(e);
1710 JavaFileObject prev = log.useSource(env.enclClass.sym.sourcefile != null ?
1711 env.enclClass.sym.sourcefile :
1712 env.toplevel.sourcefile);
1714 JavaFileObject file = null;
1716 file = printSource(env, cdef);
1720 } catch (LinkageError ex) {
1721 log.error(cdef.pos(), "class.cant.write",
1722 cdef.sym, ex.getMessage());
1724 file = genCode(env, cdef);
1726 if (results != null && file != null)
1728 } catch (IOException ex) {
1729 log.error(cdef.pos(), "class.cant.write",
1730 cdef.sym, ex.getMessage());
1733 log.useSource(prev);
1736 if (!taskListener.isEmpty()) {
1737 TaskEvent e = new TaskEvent(TaskEvent.Kind.GENERATE, env.toplevel, cdef.sym);
1738 taskListener.finished(e);
1743 private void writeHeader(JCClassDecl cdef) throws IOException {
1744 if (fileManager.hasLocation(StandardLocation.NATIVE_HEADER_OUTPUT)
1745 && jniWriter.needsHeader(cdef.sym)) {
1746 jniWriter.write(cdef.sym);
1751 Map<JCCompilationUnit, Queue<Env<AttrContext>>> groupByFile(Queue<Env<AttrContext>> envs) {
1752 // use a LinkedHashMap to preserve the order of the original list as much as possible
1753 Map<JCCompilationUnit, Queue<Env<AttrContext>>> map = new LinkedHashMap<>();
1754 for (Env<AttrContext> env: envs) {
1755 Queue<Env<AttrContext>> sublist = map.get(env.toplevel);
1756 if (sublist == null) {
1757 sublist = new ListBuffer<>();
1758 map.put(env.toplevel, sublist);
1765 JCClassDecl removeMethodBodies(JCClassDecl cdef) {
1766 final boolean isInterface = (cdef.mods.flags & Flags.INTERFACE) != 0;
1767 class MethodBodyRemover extends TreeTranslator {
1769 public void visitMethodDef(JCMethodDecl tree) {
1770 tree.mods.flags &= ~Flags.SYNCHRONIZED;
1771 for (JCVariableDecl vd : tree.params)
1772 vd.mods.flags &= ~Flags.FINAL;
1774 super.visitMethodDef(tree);
1777 public void visitVarDef(JCVariableDecl tree) {
1778 if (tree.init != null && tree.init.type.constValue() == null)
1780 super.visitVarDef(tree);
1783 public void visitClassDef(JCClassDecl tree) {
1784 ListBuffer<JCTree> newdefs = new ListBuffer<>();
1785 for (List<JCTree> it = tree.defs; it.tail != null; it = it.tail) {
1787 switch (t.getTag()) {
1790 (((JCClassDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
1791 (((JCClassDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCClassDecl) t).sym.packge().getQualifiedName() == names.java_lang)
1796 (((JCMethodDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
1797 ((JCMethodDecl) t).sym.name == names.init ||
1798 (((JCMethodDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCMethodDecl) t).sym.packge().getQualifiedName() == names.java_lang)
1802 if (isInterface || (((JCVariableDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
1803 (((JCVariableDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCVariableDecl) t).sym.packge().getQualifiedName() == names.java_lang)
1810 tree.defs = newdefs.toList();
1811 super.visitClassDef(tree);
1814 MethodBodyRemover r = new MethodBodyRemover();
1815 return r.translate(cdef);
1818 public void reportDeferredDiagnostics() {
1819 if (errorCount() == 0
1820 && annotationProcessingOccurred
1821 && implicitSourceFilesRead
1822 && implicitSourcePolicy == ImplicitSourcePolicy.UNSET) {
1823 if (explicitAnnotationProcessingRequested())
1824 log.warning("proc.use.implicit");
1826 log.warning("proc.use.proc.or.implicit");
1828 chk.reportDeferredDiagnostics();
1829 if (log.compressedOutput) {
1830 log.mandatoryNote(null, "compressed.diags");
1834 public void enterDone() {
1836 annotate.enterDone();
1839 public boolean isEnterDone() {
1843 private Name readModuleName(JavaFileObject fo) {
1844 return parseAndGetName(fo, t -> {
1845 JCModuleDecl md = t.getModuleDecl();
1847 return md != null ? TreeInfo.fullName(md.getName()) : null;
1851 private Name findPackageInFile(JavaFileObject fo) {
1852 return parseAndGetName(fo, t -> t.getPackage() != null ?
1853 TreeInfo.fullName(t.getPackage().getPackageName()) : null);
1856 private Name parseAndGetName(JavaFileObject fo,
1857 Function<JCTree.JCCompilationUnit, Name> tree2Name) {
1858 DiagnosticHandler dh = new DiscardDiagnosticHandler(log);
1860 JCTree.JCCompilationUnit t = parse(fo, fo.getCharContent(false));
1861 return tree2Name.apply(t);
1862 } catch (IOException e) {
1865 log.popDiagnosticHandler(dh);
1869 public void resetEnterDone() {
1873 /** Close the compiler, flushing the logs
1875 public void close() {
1885 parserFactory = null;
1899 fileManager.flush();
1900 if (procEnvImpl != null)
1901 procEnvImpl.close();
1903 } catch (IOException e) {
1910 for (Closeable c: closeables) {
1913 } catch (IOException e) {
1914 // When javac uses JDK 7 as a baseline, this code would be
1915 // better written to set any/all exceptions from all the
1916 // Closeables as suppressed exceptions on the FatalError
1918 JCDiagnostic msg = diagFactory.fragment("fatal.err.cant.close");
1919 throw new FatalError(msg, e);
1922 closeables = List.nil();
1926 protected void printNote(String lines) {
1927 log.printRawLines(Log.WriterKind.NOTICE, lines);
1930 /** Print numbers of errors and warnings.
1932 public void printCount(String kind, int count) {
1936 key = "count." + kind;
1938 key = "count." + kind + ".plural";
1939 log.printLines(WriterKind.ERROR, key, String.valueOf(count));
1940 log.flush(Log.WriterKind.ERROR);
1944 private static long now() {
1945 return System.currentTimeMillis();
1948 private static long elapsed(long then) {
1949 return now() - then;
1952 public void newRound(final Set<? extends JCCompilationUnit> treesToClean) {
1953 for (JCCompilationUnit treeToClean : treesToClean) {
1954 if (treeToClean.sourcefile != null) {
1955 inputFiles.remove(treeToClean.sourcefile);
1958 for (Iterator<Env<AttrContext>> it = todo.iterator(); it.hasNext();) {
1959 final Env<AttrContext> env = it.next();
1960 if (treesToClean.contains(env.toplevel)) {