javacompiler.java
来自「是一款用JAVA 编写的编译器 具有很强的编译功能」· Java 代码 · 共 1,491 行 · 第 1/4 页
JAVA
1,491 行
} } /** * Prepare attributed parse trees, in conjunction with their attribution contexts, * for source or code generation. * If any errors occur, an empty list will be returned. * @returns a list containing the classes to be generated */ public List<Pair<Env<AttrContext>, JCClassDecl>> desugar(List<Env<AttrContext>> envs) { ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results = lb(); for (List<Env<AttrContext>> l = envs; l.nonEmpty(); l = l.tail) desugar(l.head, results); return stopIfError(results); } /** * Prepare attributed parse trees, in conjunction with their attribution contexts, * for source or code generation. If the file was not listed on the command line, * the current implicitSourcePolicy is taken into account. * The preparation stops as soon as an error is found. */ protected void desugar(Env<AttrContext> env, ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results) { if (errorCount() > 0) return; if (implicitSourcePolicy == ImplicitSourcePolicy.NONE && !inputFiles.contains(env.toplevel.sourcefile)) { return; } if (desugarLater(env)) { if (verboseCompilePolicy) log.printLines(log.noticeWriter, "[defer " + env.enclClass.sym + "]"); todo.append(env); return; } deferredSugar.remove(env); if (verboseCompilePolicy) log.printLines(log.noticeWriter, "[desugar " + env.enclClass.sym + "]"); JavaFileObject prev = log.useSource(env.enclClass.sym.sourcefile != null ? env.enclClass.sym.sourcefile : env.toplevel.sourcefile); try { //save tree prior to rewriting JCTree untranslated = env.tree; make.at(Position.FIRSTPOS); TreeMaker localMake = make.forToplevel(env.toplevel); if (env.tree instanceof JCCompilationUnit) { if (!(stubOutput || sourceOutput || printFlat)) { List<JCTree> pdef = lower.translateTopLevelClass(env, env.tree, localMake); if (pdef.head != null) { assert pdef.tail.isEmpty(); results.append(new Pair<Env<AttrContext>, JCClassDecl>(env, (JCClassDecl)pdef.head)); } } return; } if (stubOutput) { //emit stub Java source file, only for compilation //units enumerated explicitly on the command line JCClassDecl cdef = (JCClassDecl)env.tree; if (untranslated instanceof JCClassDecl && rootClasses.contains((JCClassDecl)untranslated) && ((cdef.mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 || cdef.sym.packge().getQualifiedName() == names.java_lang)) { results.append(new Pair<Env<AttrContext>, JCClassDecl>(env, removeMethodBodies(cdef))); } return; } env.tree = transTypes.translateTopLevelClass(env.tree, localMake); if (errorCount() != 0) return; if (sourceOutput) { //emit standard Java source file, only for compilation //units enumerated explicitly on the command line JCClassDecl cdef = (JCClassDecl)env.tree; if (untranslated instanceof JCClassDecl && rootClasses.contains((JCClassDecl)untranslated)) { results.append(new Pair<Env<AttrContext>, JCClassDecl>(env, cdef)); } return; } //translate out inner classes List<JCTree> cdefs = lower.translateTopLevelClass(env, env.tree, localMake); if (errorCount() != 0) return; //generate code for each class for (List<JCTree> l = cdefs; l.nonEmpty(); l = l.tail) { JCClassDecl cdef = (JCClassDecl)l.head; results.append(new Pair<Env<AttrContext>, JCClassDecl>(env, cdef)); } } finally { log.useSource(prev); } } /** * Determine if a class needs to be desugared later. As erasure * (TransTypes) destroys information needed in flow analysis, we * need to ensure that supertypes are translated before derived * types are translated. */ public boolean desugarLater(final Env<AttrContext> env) { if (compilePolicy == CompilePolicy.BY_FILE) return false; if (!devVerbose && deferredSugar.contains(env)) // guarantee that compiler terminates return false; class ScanNested extends TreeScanner { Set<Symbol> externalSupers = new HashSet<Symbol>(); public void visitClassDef(JCClassDecl node) { Type st = types.supertype(node.sym.type); if (st.tag == TypeTags.CLASS) { ClassSymbol c = st.tsym.outermostClass(); Env<AttrContext> stEnv = enter.getEnv(c); if (stEnv != null && env != stEnv) externalSupers.add(st.tsym); } super.visitClassDef(node); } } ScanNested scanner = new ScanNested(); scanner.scan(env.tree); if (scanner.externalSupers.isEmpty()) return false; if (!deferredSugar.add(env) && devVerbose) { throw new AssertionError(env.enclClass.sym + " was deferred, " + "second time has these external super types " + scanner.externalSupers); } return true; } /** Generates the source or class file for a list of classes. * The decision to generate a source file or a class file is * based upon the compiler's options. * Generation stops if an error occurs while writing files. */ public void generate(List<Pair<Env<AttrContext>, JCClassDecl>> list) { generate(list, null); } public void generate(List<Pair<Env<AttrContext>, JCClassDecl>> list, ListBuffer<JavaFileObject> results) { boolean usePrintSource = (stubOutput || sourceOutput || printFlat); for (List<Pair<Env<AttrContext>, JCClassDecl>> l = list; l.nonEmpty(); l = l.tail) { Pair<Env<AttrContext>, JCClassDecl> x = l.head; Env<AttrContext> env = x.fst; JCClassDecl cdef = x.snd; if (verboseCompilePolicy) { log.printLines(log.noticeWriter, "[generate " + (usePrintSource ? " source" : "code") + " " + env.enclClass.sym + "]"); } if (taskListener != null) { TaskEvent e = new TaskEvent(TaskEvent.Kind.GENERATE, env.toplevel, cdef.sym); taskListener.started(e); } JavaFileObject prev = log.useSource(env.enclClass.sym.sourcefile != null ? env.enclClass.sym.sourcefile : env.toplevel.sourcefile); try { JavaFileObject file; if (usePrintSource) file = printSource(env, cdef); else file = genCode(env, cdef); if (results != null && file != null) results.append(file); } catch (IOException ex) { log.error(cdef.pos(), "class.cant.write", cdef.sym, ex.getMessage()); return; } finally { log.useSource(prev); } if (taskListener != null) { TaskEvent e = new TaskEvent(TaskEvent.Kind.GENERATE, env.toplevel, cdef.sym); taskListener.finished(e); } } } // where Map<JCCompilationUnit, List<Env<AttrContext>>> groupByFile(List<Env<AttrContext>> list) { // use a LinkedHashMap to preserve the order of the original list as much as possible Map<JCCompilationUnit, List<Env<AttrContext>>> map = new LinkedHashMap<JCCompilationUnit, List<Env<AttrContext>>>(); Set<JCCompilationUnit> fixupSet = new HashSet<JCTree.JCCompilationUnit>(); for (List<Env<AttrContext>> l = list; l.nonEmpty(); l = l.tail) { Env<AttrContext> env = l.head; List<Env<AttrContext>> sublist = map.get(env.toplevel); if (sublist == null) sublist = List.of(env); else { // this builds the list for the file in reverse order, so make a note // to reverse the list before returning. sublist = sublist.prepend(env); fixupSet.add(env.toplevel); } map.put(env.toplevel, sublist); } // fixup any lists that need reversing back to the correct order for (JCTree.JCCompilationUnit tree: fixupSet) map.put(tree, map.get(tree).reverse()); return map; } JCClassDecl removeMethodBodies(JCClassDecl cdef) { final boolean isInterface = (cdef.mods.flags & Flags.INTERFACE) != 0; class MethodBodyRemover extends TreeTranslator { public void visitMethodDef(JCMethodDecl tree) { tree.mods.flags &= ~Flags.SYNCHRONIZED; for (JCVariableDecl vd : tree.params) vd.mods.flags &= ~Flags.FINAL; tree.body = null; super.visitMethodDef(tree); } public void visitVarDef(JCVariableDecl tree) { if (tree.init != null && tree.init.type.constValue() == null) tree.init = null; super.visitVarDef(tree); } public void visitClassDef(JCClassDecl tree) { ListBuffer<JCTree> newdefs = lb(); for (List<JCTree> it = tree.defs; it.tail != null; it = it.tail) { JCTree t = it.head; switch (t.getTag()) { case JCTree.CLASSDEF: if (isInterface || (((JCClassDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 || (((JCClassDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCClassDecl) t).sym.packge().getQualifiedName() == names.java_lang) newdefs.append(t); break; case JCTree.METHODDEF: if (isInterface || (((JCMethodDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 || ((JCMethodDecl) t).sym.name == names.init || (((JCMethodDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCMethodDecl) t).sym.packge().getQualifiedName() == names.java_lang) newdefs.append(t); break; case JCTree.VARDEF: if (isInterface || (((JCVariableDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 || (((JCVariableDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCVariableDecl) t).sym.packge().getQualifiedName() == names.java_lang) newdefs.append(t); break; default: break; } } tree.defs = newdefs.toList(); super.visitClassDef(tree); } } MethodBodyRemover r = new MethodBodyRemover(); return r.translate(cdef); } public void reportDeferredDiagnostics() { if (annotationProcessingOccurred && implicitSourceFilesRead && implicitSourcePolicy == ImplicitSourcePolicy.UNSET) { if (explicitAnnotationProcessingRequested()) log.warning("proc.use.implicit"); else log.warning("proc.use.proc.or.implicit"); } chk.reportDeferredDiagnostics(); } /** Close the compiler, flushing the logs */ public void close() { close(true); } private void close(boolean disposeNames) { rootClasses = null; reader = null; make = null; writer = null; enter = null; if (todo != null) todo.clear(); todo = null; parserFactory = null; syms = null; source = null; attr = null; chk = null; gen = null; flow = null; transTypes = null; lower = null; annotate = null; types = null; log.flush(); try { fileManager.flush(); } catch (IOException e) { throw new Abort(e); } finally { if (names != null && disposeNames) names.dispose(); names = null; } } /** Output for "-verbose" option. * @param key The key to look up the correct internationalized string. * @param arg An argument for substitution into the output string. */ protected void printVerbose(String key, Object arg) { Log.printLines(log.noticeWriter, log.getLocalizedString("verbose." + key, arg)); } /** Print numbers of errors and warnings. */ protected void printCount(String kind, int count) { if (count != 0) { String text; if (count == 1) text = log.getLocalizedString("count." + kind, String.valueOf(count)); else text = log.getLocalizedString("count." + kind + ".plural", String.valueOf(count)); Log.printLines(log.errWriter, text); log.errWriter.flush(); } } private static long now() { return System.currentTimeMillis(); } private static long elapsed(long then) { return now() - then; } public void initRound(JavaCompiler prev) { keepComments = prev.keepComments; start_msec = prev.start_msec; hasBeenUsed = true; } public static void enableLogging() { Logger logger = Logger.getLogger(com.sun.tools.javac.Main.class.getPackage().getName()); logger.setLevel(Level.ALL); for (Handler h : logger.getParent().getHandlers()) { h.setLevel(Level.ALL); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?