pretty.java

来自「是一款用JAVA 编写的编译器 具有很强的编译功能」· Java 代码 · 共 1,225 行 · 第 1/3 页

JAVA
1,225
字号
/* * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */package com.sun.tools.javac.tree;import java.io.*;import java.util.*;import com.sun.tools.javac.util.*;import com.sun.tools.javac.util.List;import com.sun.tools.javac.code.*;import com.sun.tools.javac.code.Symbol.*;import com.sun.tools.javac.tree.JCTree.*;import static com.sun.tools.javac.code.Flags.*;/** Prints out a tree as an indented Java source program. * *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If *  you write code that depends on this, you do so at your own risk. *  This code and its internal interfaces are subject to change or *  deletion without notice.</b> */public class Pretty extends JCTree.Visitor {    public Pretty(Writer out, boolean sourceOutput) {        this.out = out;        this.sourceOutput = sourceOutput;    }    /** Set when we are producing source output.  If we're not     *  producing source output, we can sometimes give more detail in     *  the output even though that detail would not be valid java     *  soruce.     */    private final boolean sourceOutput;    /** The output stream on which trees are printed.     */    Writer out;    /** Indentation width (can be reassigned from outside).     */    public int width = 4;    /** The current left margin.     */    int lmargin = 0;    /** The enclosing class name.     */    Name enclClassName;    /** A hashtable mapping trees to their documentation comments     *  (can be null)     */    Map<JCTree, String> docComments = null;    /** Align code to be indented to left margin.     */    void align() throws IOException {        for (int i = 0; i < lmargin; i++) out.write(" ");    }    /** Increase left margin by indentation width.     */    void indent() {        lmargin = lmargin + width;    }    /** Decrease left margin by indentation width.     */    void undent() {        lmargin = lmargin - width;    }    /** Enter a new precedence level. Emit a `(' if new precedence level     *  is less than precedence level so far.     *  @param contextPrec    The precedence level in force so far.     *  @param ownPrec        The new precedence level.     */    void open(int contextPrec, int ownPrec) throws IOException {        if (ownPrec < contextPrec) out.write("(");    }    /** Leave precedence level. Emit a `(' if inner precedence level     *  is less than precedence level we revert to.     *  @param contextPrec    The precedence level we revert to.     *  @param ownPrec        The inner precedence level.     */    void close(int contextPrec, int ownPrec) throws IOException {        if (ownPrec < contextPrec) out.write(")");    }    /** Print string, replacing all non-ascii character with unicode escapes.     */    public void print(Object s) throws IOException {        out.write(Convert.escapeUnicode(s.toString()));    }    /** Print new line.     */    public void println() throws IOException {        out.write(lineSep);    }    String lineSep = System.getProperty("line.separator");    /**************************************************************************     * Traversal methods     *************************************************************************/    /** Exception to propogate IOException through visitXXX methods */    private static class UncheckedIOException extends Error {	static final long serialVersionUID = -4032692679158424751L;        UncheckedIOException(IOException e) {            super(e.getMessage(), e);        }    }    /** Visitor argument: the current precedence level.     */    int prec;    /** Visitor method: print expression tree.     *  @param prec  The current precedence level.     */    public void printExpr(JCTree tree, int prec) throws IOException {        int prevPrec = this.prec;        try {            this.prec = prec;            if (tree == null) print("/*missing*/");            else {                tree.accept(this);            }        } catch (UncheckedIOException ex) {            IOException e = new IOException(ex.getMessage());            e.initCause(ex);            throw e;        } finally {            this.prec = prevPrec;        }    }    /** Derived visitor method: print expression tree at minimum precedence level     *  for expression.     */    public void printExpr(JCTree tree) throws IOException {        printExpr(tree, TreeInfo.noPrec);    }    /** Derived visitor method: print statement tree.     */    public void printStat(JCTree tree) throws IOException {        printExpr(tree, TreeInfo.notExpression);    }    /** Derived visitor method: print list of expression trees, separated by given string.     *  @param sep the separator string     */    public <T extends JCTree> void printExprs(List<T> trees, String sep) throws IOException {        if (trees.nonEmpty()) {            printExpr(trees.head);            for (List<T> l = trees.tail; l.nonEmpty(); l = l.tail) {                print(sep);                printExpr(l.head);            }        }    }    /** Derived visitor method: print list of expression trees, separated by commas.     */    public <T extends JCTree> void printExprs(List<T> trees) throws IOException {        printExprs(trees, ", ");    }    /** Derived visitor method: print list of statements, each on a separate line.     */    public void printStats(List<? extends JCTree> trees) throws IOException {        for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) {            align();            printStat(l.head);            println();        }    }    /** Print a set of modifiers.     */    public void printFlags(long flags) throws IOException {        if ((flags & SYNTHETIC) != 0) print("/*synthetic*/ ");        print(TreeInfo.flagNames(flags));        if ((flags & StandardFlags) != 0) print(" ");        if ((flags & ANNOTATION) != 0) print("@");    }    public void printAnnotations(List<JCAnnotation> trees) throws IOException {        for (List<JCAnnotation> l = trees; l.nonEmpty(); l = l.tail) {            printStat(l.head);            println();            align();        }    }    /** Print documentation comment, if it exists     *  @param tree    The tree for which a documentation comment should be printed.     */    public void printDocComment(JCTree tree) throws IOException {        if (docComments != null) {            String dc = docComments.get(tree);            if (dc != null) {                print("/**"); println();                int pos = 0;                int endpos = lineEndPos(dc, pos);                while (pos < dc.length()) {                    align();                    print(" *");                    if (pos < dc.length() && dc.charAt(pos) > ' ') print(" ");                    print(dc.substring(pos, endpos)); println();                    pos = endpos + 1;                    endpos = lineEndPos(dc, pos);                }                align(); print(" */"); println();                align();            }        }    }//where    static int lineEndPos(String s, int start) {        int pos = s.indexOf('\n', start);        if (pos < 0) pos = s.length();        return pos;    }    /** If type parameter list is non-empty, print it enclosed in "<...>" brackets.     */    public void printTypeParameters(List<JCTypeParameter> trees) throws IOException {        if (trees.nonEmpty()) {            print("<");            printExprs(trees);            print(">");        }    }    /** Print a block.     */    public void printBlock(List<? extends JCTree> stats) throws IOException {        print("{");        println();        indent();        printStats(stats);        undent();        align();        print("}");    }    /** Print a block.     */    public void printEnumBody(List<JCTree> stats) throws IOException {        print("{");        println();        indent();        boolean first = true;        for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) {            if (isEnumerator(l.head)) {                if (!first) {                    print(",");                    println();                }                align();                printStat(l.head);                first = false;            }        }        print(";");        println();        for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) {            if (!isEnumerator(l.head)) {                align();                printStat(l.head);                println();            }        }        undent();        align();        print("}");    }    /** Is the given tree an enumerator definition? */    boolean isEnumerator(JCTree t) {        return t.getTag() == JCTree.VARDEF && (((JCVariableDecl) t).mods.flags & ENUM) != 0;    }    /** Print unit consisting of package clause and import statements in toplevel,     *  followed by class definition. if class definition == null,     *  print all definitions in toplevel.     *  @param tree     The toplevel tree     *  @param cdef     The class definition, which is assumed to be part of the     *                  toplevel tree.     */    public void printUnit(JCCompilationUnit tree, JCClassDecl cdef) throws IOException {        docComments = tree.docComments;        printDocComment(tree);        if (tree.pid != null) {            print("package ");            printExpr(tree.pid);            print(";");            println();        }        boolean firstImport = true;        for (List<JCTree> l = tree.defs;        l.nonEmpty() && (cdef == null || l.head.getTag() == JCTree.IMPORT);        l = l.tail) {            if (l.head.getTag() == JCTree.IMPORT) {                JCImport imp = (JCImport)l.head;                Name name = TreeInfo.name(imp.qualid);                if (name == name.table.asterisk ||                        cdef == null ||                        isUsed(TreeInfo.symbol(imp.qualid), cdef)) {                    if (firstImport) {                        firstImport = false;                        println();                    }                    printStat(imp);                }            } else {                printStat(l.head);            }        }        if (cdef != null) {            printStat(cdef);            println();        }    }    // where    boolean isUsed(final Symbol t, JCTree cdef) {        class UsedVisitor extends TreeScanner {            public void scan(JCTree tree) {                if (tree!=null && !result) tree.accept(this);            }            boolean result = false;            public void visitIdent(JCIdent tree) {                if (tree.sym == t) result = true;            }        }        UsedVisitor v = new UsedVisitor();        v.scan(cdef);        return v.result;    }    /**************************************************************************     * Visitor methods     *************************************************************************/    public void visitTopLevel(JCCompilationUnit tree) {        try {            printUnit(tree, null);        } catch (IOException e) {            throw new UncheckedIOException(e);        }    }    public void visitImport(JCImport tree) {        try {            print("import ");            if (tree.staticImport) print("static ");            printExpr(tree.qualid);            print(";");            println();        } catch (IOException e) {            throw new UncheckedIOException(e);        }    }    public void visitClassDef(JCClassDecl tree) {        try {            println(); align();            printDocComment(tree);            printAnnotations(tree.mods.annotations);            printFlags(tree.mods.flags & ~INTERFACE);            Name enclClassNamePrev = enclClassName;            enclClassName = tree.name;            if ((tree.mods.flags & INTERFACE) != 0) {                print("interface " + tree.name);                printTypeParameters(tree.typarams);                if (tree.implementing.nonEmpty()) {                    print(" extends ");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?