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