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 + -
显示快捷键?