duke@1: /* ohair@798: * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. duke@1: */ duke@1: duke@1: package com.sun.tools.javac.tree; duke@1: duke@1: import java.io.*; duke@1: import java.util.*; duke@1: duke@1: import com.sun.tools.javac.util.*; duke@1: import com.sun.tools.javac.util.List; duke@1: import com.sun.tools.javac.code.*; duke@1: duke@1: import com.sun.tools.javac.code.Symbol.*; duke@1: import com.sun.tools.javac.tree.JCTree.*; duke@1: duke@1: import static com.sun.tools.javac.code.Flags.*; duke@1: duke@1: /** Prints out a tree as an indented Java source program. duke@1: * jjg@581: *

This is NOT part of any supported API. jjg@581: * If you write code that depends on this, you do so at your own risk. duke@1: * This code and its internal interfaces are subject to change or duke@1: * deletion without notice. duke@1: */ duke@1: public class Pretty extends JCTree.Visitor { duke@1: duke@1: public Pretty(Writer out, boolean sourceOutput) { duke@1: this.out = out; duke@1: this.sourceOutput = sourceOutput; duke@1: } duke@1: duke@1: /** Set when we are producing source output. If we're not duke@1: * producing source output, we can sometimes give more detail in duke@1: * the output even though that detail would not be valid java jjg@439: * source. duke@1: */ duke@1: private final boolean sourceOutput; duke@1: duke@1: /** The output stream on which trees are printed. duke@1: */ duke@1: Writer out; duke@1: duke@1: /** Indentation width (can be reassigned from outside). duke@1: */ duke@1: public int width = 4; duke@1: duke@1: /** The current left margin. duke@1: */ duke@1: int lmargin = 0; duke@1: duke@1: /** The enclosing class name. duke@1: */ duke@1: Name enclClassName; duke@1: duke@1: /** A hashtable mapping trees to their documentation comments duke@1: * (can be null) duke@1: */ duke@1: Map docComments = null; duke@1: duke@1: /** Align code to be indented to left margin. duke@1: */ duke@1: void align() throws IOException { duke@1: for (int i = 0; i < lmargin; i++) out.write(" "); duke@1: } duke@1: duke@1: /** Increase left margin by indentation width. duke@1: */ duke@1: void indent() { duke@1: lmargin = lmargin + width; duke@1: } duke@1: duke@1: /** Decrease left margin by indentation width. duke@1: */ duke@1: void undent() { duke@1: lmargin = lmargin - width; duke@1: } duke@1: duke@1: /** Enter a new precedence level. Emit a `(' if new precedence level duke@1: * is less than precedence level so far. duke@1: * @param contextPrec The precedence level in force so far. duke@1: * @param ownPrec The new precedence level. duke@1: */ duke@1: void open(int contextPrec, int ownPrec) throws IOException { duke@1: if (ownPrec < contextPrec) out.write("("); duke@1: } duke@1: duke@1: /** Leave precedence level. Emit a `(' if inner precedence level duke@1: * is less than precedence level we revert to. duke@1: * @param contextPrec The precedence level we revert to. duke@1: * @param ownPrec The inner precedence level. duke@1: */ duke@1: void close(int contextPrec, int ownPrec) throws IOException { duke@1: if (ownPrec < contextPrec) out.write(")"); duke@1: } duke@1: duke@1: /** Print string, replacing all non-ascii character with unicode escapes. duke@1: */ duke@1: public void print(Object s) throws IOException { duke@1: out.write(Convert.escapeUnicode(s.toString())); duke@1: } duke@1: duke@1: /** Print new line. duke@1: */ duke@1: public void println() throws IOException { duke@1: out.write(lineSep); duke@1: } duke@1: duke@1: String lineSep = System.getProperty("line.separator"); duke@1: duke@1: /************************************************************************** duke@1: * Traversal methods duke@1: *************************************************************************/ duke@1: duke@1: /** Exception to propogate IOException through visitXXX methods */ duke@1: private static class UncheckedIOException extends Error { duke@1: static final long serialVersionUID = -4032692679158424751L; duke@1: UncheckedIOException(IOException e) { duke@1: super(e.getMessage(), e); duke@1: } duke@1: } duke@1: duke@1: /** Visitor argument: the current precedence level. duke@1: */ duke@1: int prec; duke@1: duke@1: /** Visitor method: print expression tree. duke@1: * @param prec The current precedence level. duke@1: */ duke@1: public void printExpr(JCTree tree, int prec) throws IOException { duke@1: int prevPrec = this.prec; duke@1: try { duke@1: this.prec = prec; duke@1: if (tree == null) print("/*missing*/"); duke@1: else { duke@1: tree.accept(this); duke@1: } duke@1: } catch (UncheckedIOException ex) { duke@1: IOException e = new IOException(ex.getMessage()); duke@1: e.initCause(ex); duke@1: throw e; duke@1: } finally { duke@1: this.prec = prevPrec; duke@1: } duke@1: } duke@1: duke@1: /** Derived visitor method: print expression tree at minimum precedence level duke@1: * for expression. duke@1: */ duke@1: public void printExpr(JCTree tree) throws IOException { duke@1: printExpr(tree, TreeInfo.noPrec); duke@1: } duke@1: duke@1: /** Derived visitor method: print statement tree. duke@1: */ duke@1: public void printStat(JCTree tree) throws IOException { duke@1: printExpr(tree, TreeInfo.notExpression); duke@1: } duke@1: duke@1: /** Derived visitor method: print list of expression trees, separated by given string. duke@1: * @param sep the separator string duke@1: */ duke@1: public void printExprs(List trees, String sep) throws IOException { duke@1: if (trees.nonEmpty()) { duke@1: printExpr(trees.head); duke@1: for (List l = trees.tail; l.nonEmpty(); l = l.tail) { duke@1: print(sep); duke@1: printExpr(l.head); duke@1: } duke@1: } duke@1: } duke@1: duke@1: /** Derived visitor method: print list of expression trees, separated by commas. duke@1: */ duke@1: public void printExprs(List trees) throws IOException { duke@1: printExprs(trees, ", "); duke@1: } duke@1: duke@1: /** Derived visitor method: print list of statements, each on a separate line. duke@1: */ duke@1: public void printStats(List trees) throws IOException { duke@1: for (List l = trees; l.nonEmpty(); l = l.tail) { duke@1: align(); duke@1: printStat(l.head); duke@1: println(); duke@1: } duke@1: } duke@1: duke@1: /** Print a set of modifiers. duke@1: */ duke@1: public void printFlags(long flags) throws IOException { duke@1: if ((flags & SYNTHETIC) != 0) print("/*synthetic*/ "); duke@1: print(TreeInfo.flagNames(flags)); duke@1: if ((flags & StandardFlags) != 0) print(" "); duke@1: if ((flags & ANNOTATION) != 0) print("@"); duke@1: } duke@1: duke@1: public void printAnnotations(List trees) throws IOException { duke@1: for (List l = trees; l.nonEmpty(); l = l.tail) { duke@1: printStat(l.head); duke@1: println(); duke@1: align(); duke@1: } duke@1: } duke@1: jjg@308: public void printTypeAnnotations(List trees) throws IOException { jjg@308: if (trees.nonEmpty()) jjg@308: print(" "); jjg@308: for (List l = trees; l.nonEmpty(); l = l.tail) { jjg@308: printExpr(l.head); jjg@308: print(" "); jjg@308: } jjg@308: } jjg@308: duke@1: /** Print documentation comment, if it exists duke@1: * @param tree The tree for which a documentation comment should be printed. duke@1: */ duke@1: public void printDocComment(JCTree tree) throws IOException { duke@1: if (docComments != null) { duke@1: String dc = docComments.get(tree); duke@1: if (dc != null) { duke@1: print("/**"); println(); duke@1: int pos = 0; duke@1: int endpos = lineEndPos(dc, pos); duke@1: while (pos < dc.length()) { duke@1: align(); duke@1: print(" *"); duke@1: if (pos < dc.length() && dc.charAt(pos) > ' ') print(" "); duke@1: print(dc.substring(pos, endpos)); println(); duke@1: pos = endpos + 1; duke@1: endpos = lineEndPos(dc, pos); duke@1: } duke@1: align(); print(" */"); println(); duke@1: align(); duke@1: } duke@1: } duke@1: } duke@1: //where duke@1: static int lineEndPos(String s, int start) { duke@1: int pos = s.indexOf('\n', start); duke@1: if (pos < 0) pos = s.length(); duke@1: return pos; duke@1: } duke@1: duke@1: /** If type parameter list is non-empty, print it enclosed in "<...>" brackets. duke@1: */ duke@1: public void printTypeParameters(List trees) throws IOException { duke@1: if (trees.nonEmpty()) { duke@1: print("<"); duke@1: printExprs(trees); duke@1: print(">"); duke@1: } duke@1: } duke@1: duke@1: /** Print a block. duke@1: */ duke@1: public void printBlock(List stats) throws IOException { duke@1: print("{"); duke@1: println(); duke@1: indent(); duke@1: printStats(stats); duke@1: undent(); duke@1: align(); duke@1: print("}"); duke@1: } duke@1: duke@1: /** Print a block. duke@1: */ duke@1: public void printEnumBody(List stats) throws IOException { duke@1: print("{"); duke@1: println(); duke@1: indent(); duke@1: boolean first = true; duke@1: for (List l = stats; l.nonEmpty(); l = l.tail) { duke@1: if (isEnumerator(l.head)) { duke@1: if (!first) { duke@1: print(","); duke@1: println(); duke@1: } duke@1: align(); duke@1: printStat(l.head); duke@1: first = false; duke@1: } duke@1: } duke@1: print(";"); duke@1: println(); duke@1: for (List l = stats; l.nonEmpty(); l = l.tail) { duke@1: if (!isEnumerator(l.head)) { duke@1: align(); duke@1: printStat(l.head); duke@1: println(); duke@1: } duke@1: } duke@1: undent(); duke@1: align(); duke@1: print("}"); duke@1: } duke@1: duke@1: /** Is the given tree an enumerator definition? */ duke@1: boolean isEnumerator(JCTree t) { duke@1: return t.getTag() == JCTree.VARDEF && (((JCVariableDecl) t).mods.flags & ENUM) != 0; duke@1: } duke@1: duke@1: /** Print unit consisting of package clause and import statements in toplevel, duke@1: * followed by class definition. if class definition == null, duke@1: * print all definitions in toplevel. duke@1: * @param tree The toplevel tree duke@1: * @param cdef The class definition, which is assumed to be part of the duke@1: * toplevel tree. duke@1: */ duke@1: public void printUnit(JCCompilationUnit tree, JCClassDecl cdef) throws IOException { duke@1: docComments = tree.docComments; duke@1: printDocComment(tree); duke@1: if (tree.pid != null) { duke@1: print("package "); duke@1: printExpr(tree.pid); duke@1: print(";"); duke@1: println(); duke@1: } duke@1: boolean firstImport = true; duke@1: for (List l = tree.defs; duke@1: l.nonEmpty() && (cdef == null || l.head.getTag() == JCTree.IMPORT); duke@1: l = l.tail) { duke@1: if (l.head.getTag() == JCTree.IMPORT) { duke@1: JCImport imp = (JCImport)l.head; duke@1: Name name = TreeInfo.name(imp.qualid); jjg@113: if (name == name.table.names.asterisk || duke@1: cdef == null || duke@1: isUsed(TreeInfo.symbol(imp.qualid), cdef)) { duke@1: if (firstImport) { duke@1: firstImport = false; duke@1: println(); duke@1: } duke@1: printStat(imp); duke@1: } duke@1: } else { duke@1: printStat(l.head); duke@1: } duke@1: } duke@1: if (cdef != null) { duke@1: printStat(cdef); duke@1: println(); duke@1: } duke@1: } duke@1: // where duke@1: boolean isUsed(final Symbol t, JCTree cdef) { duke@1: class UsedVisitor extends TreeScanner { duke@1: public void scan(JCTree tree) { duke@1: if (tree!=null && !result) tree.accept(this); duke@1: } duke@1: boolean result = false; duke@1: public void visitIdent(JCIdent tree) { duke@1: if (tree.sym == t) result = true; duke@1: } duke@1: } duke@1: UsedVisitor v = new UsedVisitor(); duke@1: v.scan(cdef); duke@1: return v.result; duke@1: } duke@1: duke@1: /************************************************************************** duke@1: * Visitor methods duke@1: *************************************************************************/ duke@1: duke@1: public void visitTopLevel(JCCompilationUnit tree) { duke@1: try { duke@1: printUnit(tree, null); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitImport(JCImport tree) { duke@1: try { duke@1: print("import "); duke@1: if (tree.staticImport) print("static "); duke@1: printExpr(tree.qualid); duke@1: print(";"); duke@1: println(); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitClassDef(JCClassDecl tree) { duke@1: try { duke@1: println(); align(); duke@1: printDocComment(tree); duke@1: printAnnotations(tree.mods.annotations); duke@1: printFlags(tree.mods.flags & ~INTERFACE); duke@1: Name enclClassNamePrev = enclClassName; duke@1: enclClassName = tree.name; duke@1: if ((tree.mods.flags & INTERFACE) != 0) { duke@1: print("interface " + tree.name); duke@1: printTypeParameters(tree.typarams); duke@1: if (tree.implementing.nonEmpty()) { duke@1: print(" extends "); duke@1: printExprs(tree.implementing); duke@1: } duke@1: } else { duke@1: if ((tree.mods.flags & ENUM) != 0) duke@1: print("enum " + tree.name); duke@1: else duke@1: print("class " + tree.name); duke@1: printTypeParameters(tree.typarams); duke@1: if (tree.extending != null) { duke@1: print(" extends "); duke@1: printExpr(tree.extending); duke@1: } duke@1: if (tree.implementing.nonEmpty()) { duke@1: print(" implements "); duke@1: printExprs(tree.implementing); duke@1: } duke@1: } duke@1: print(" "); duke@1: if ((tree.mods.flags & ENUM) != 0) { duke@1: printEnumBody(tree.defs); duke@1: } else { duke@1: printBlock(tree.defs); duke@1: } duke@1: enclClassName = enclClassNamePrev; duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitMethodDef(JCMethodDecl tree) { duke@1: try { duke@1: // when producing source output, omit anonymous constructors jjg@113: if (tree.name == tree.name.table.names.init && duke@1: enclClassName == null && duke@1: sourceOutput) return; duke@1: println(); align(); duke@1: printDocComment(tree); duke@1: printExpr(tree.mods); duke@1: printTypeParameters(tree.typarams); jjg@113: if (tree.name == tree.name.table.names.init) { duke@1: print(enclClassName != null ? enclClassName : tree.name); duke@1: } else { duke@1: printExpr(tree.restype); duke@1: print(" " + tree.name); duke@1: } duke@1: print("("); duke@1: printExprs(tree.params); duke@1: print(")"); duke@1: if (tree.thrown.nonEmpty()) { duke@1: print(" throws "); duke@1: printExprs(tree.thrown); duke@1: } jjg@461: if (tree.defaultValue != null) { jjg@461: print(" default "); jjg@461: printExpr(tree.defaultValue); jjg@461: } duke@1: if (tree.body != null) { duke@1: print(" "); duke@1: printStat(tree.body); duke@1: } else { duke@1: print(";"); duke@1: } duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitVarDef(JCVariableDecl tree) { duke@1: try { duke@1: if (docComments != null && docComments.get(tree) != null) { duke@1: println(); align(); duke@1: } duke@1: printDocComment(tree); duke@1: if ((tree.mods.flags & ENUM) != 0) { duke@1: print("/*public static final*/ "); duke@1: print(tree.name); duke@1: if (tree.init != null) { jjg@439: if (sourceOutput && tree.init.getTag() == JCTree.NEWCLASS) { jjg@439: print(" /*enum*/ "); jjg@439: JCNewClass init = (JCNewClass) tree.init; jjg@439: if (init.args != null && init.args.nonEmpty()) { jjg@439: print("("); jjg@439: print(init.args); jjg@439: print(")"); jjg@439: } jjg@439: if (init.def != null && init.def.defs != null) { jjg@439: print(" "); jjg@439: printBlock(init.def.defs); jjg@439: } jjg@439: return; jjg@439: } duke@1: print(" /* = "); duke@1: printExpr(tree.init); duke@1: print(" */"); duke@1: } duke@1: } else { duke@1: printExpr(tree.mods); duke@1: if ((tree.mods.flags & VARARGS) != 0) { duke@1: printExpr(((JCArrayTypeTree) tree.vartype).elemtype); duke@1: print("... " + tree.name); duke@1: } else { duke@1: printExpr(tree.vartype); duke@1: print(" " + tree.name); duke@1: } duke@1: if (tree.init != null) { duke@1: print(" = "); duke@1: printExpr(tree.init); duke@1: } duke@1: if (prec == TreeInfo.notExpression) print(";"); duke@1: } duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitSkip(JCSkip tree) { duke@1: try { duke@1: print(";"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitBlock(JCBlock tree) { duke@1: try { duke@1: printFlags(tree.flags); duke@1: printBlock(tree.stats); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitDoLoop(JCDoWhileLoop tree) { duke@1: try { duke@1: print("do "); duke@1: printStat(tree.body); duke@1: align(); duke@1: print(" while "); duke@1: if (tree.cond.getTag() == JCTree.PARENS) { duke@1: printExpr(tree.cond); duke@1: } else { duke@1: print("("); duke@1: printExpr(tree.cond); duke@1: print(")"); duke@1: } duke@1: print(";"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitWhileLoop(JCWhileLoop tree) { duke@1: try { duke@1: print("while "); duke@1: if (tree.cond.getTag() == JCTree.PARENS) { duke@1: printExpr(tree.cond); duke@1: } else { duke@1: print("("); duke@1: printExpr(tree.cond); duke@1: print(")"); duke@1: } duke@1: print(" "); duke@1: printStat(tree.body); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitForLoop(JCForLoop tree) { duke@1: try { duke@1: print("for ("); duke@1: if (tree.init.nonEmpty()) { duke@1: if (tree.init.head.getTag() == JCTree.VARDEF) { duke@1: printExpr(tree.init.head); duke@1: for (List l = tree.init.tail; l.nonEmpty(); l = l.tail) { duke@1: JCVariableDecl vdef = (JCVariableDecl)l.head; duke@1: print(", " + vdef.name + " = "); duke@1: printExpr(vdef.init); duke@1: } duke@1: } else { duke@1: printExprs(tree.init); duke@1: } duke@1: } duke@1: print("; "); duke@1: if (tree.cond != null) printExpr(tree.cond); duke@1: print("; "); duke@1: printExprs(tree.step); duke@1: print(") "); duke@1: printStat(tree.body); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitForeachLoop(JCEnhancedForLoop tree) { duke@1: try { duke@1: print("for ("); duke@1: printExpr(tree.var); duke@1: print(" : "); duke@1: printExpr(tree.expr); duke@1: print(") "); duke@1: printStat(tree.body); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitLabelled(JCLabeledStatement tree) { duke@1: try { duke@1: print(tree.label + ": "); duke@1: printStat(tree.body); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitSwitch(JCSwitch tree) { duke@1: try { duke@1: print("switch "); duke@1: if (tree.selector.getTag() == JCTree.PARENS) { duke@1: printExpr(tree.selector); duke@1: } else { duke@1: print("("); duke@1: printExpr(tree.selector); duke@1: print(")"); duke@1: } duke@1: print(" {"); duke@1: println(); duke@1: printStats(tree.cases); duke@1: align(); duke@1: print("}"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitCase(JCCase tree) { duke@1: try { duke@1: if (tree.pat == null) { duke@1: print("default"); duke@1: } else { duke@1: print("case "); duke@1: printExpr(tree.pat); duke@1: } duke@1: print(": "); duke@1: println(); duke@1: indent(); duke@1: printStats(tree.stats); duke@1: undent(); duke@1: align(); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitSynchronized(JCSynchronized tree) { duke@1: try { duke@1: print("synchronized "); duke@1: if (tree.lock.getTag() == JCTree.PARENS) { duke@1: printExpr(tree.lock); duke@1: } else { duke@1: print("("); duke@1: printExpr(tree.lock); duke@1: print(")"); duke@1: } duke@1: print(" "); duke@1: printStat(tree.body); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitTry(JCTry tree) { duke@1: try { duke@1: print("try "); darcy@609: if (tree.resources.nonEmpty()) { darcy@609: print("("); darcy@609: boolean first = true; darcy@609: for (JCTree var : tree.resources) { darcy@609: if (!first) { darcy@609: println(); darcy@609: indent(); darcy@609: } darcy@609: printStat(var); darcy@609: first = false; darcy@609: } darcy@609: print(") "); darcy@609: } duke@1: printStat(tree.body); duke@1: for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { duke@1: printStat(l.head); duke@1: } duke@1: if (tree.finalizer != null) { duke@1: print(" finally "); duke@1: printStat(tree.finalizer); duke@1: } duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitCatch(JCCatch tree) { duke@1: try { duke@1: print(" catch ("); duke@1: printExpr(tree.param); duke@1: print(") "); duke@1: printStat(tree.body); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitConditional(JCConditional tree) { duke@1: try { duke@1: open(prec, TreeInfo.condPrec); duke@1: printExpr(tree.cond, TreeInfo.condPrec); duke@1: print(" ? "); duke@1: printExpr(tree.truepart, TreeInfo.condPrec); duke@1: print(" : "); duke@1: printExpr(tree.falsepart, TreeInfo.condPrec); duke@1: close(prec, TreeInfo.condPrec); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitIf(JCIf tree) { duke@1: try { duke@1: print("if "); duke@1: if (tree.cond.getTag() == JCTree.PARENS) { duke@1: printExpr(tree.cond); duke@1: } else { duke@1: print("("); duke@1: printExpr(tree.cond); duke@1: print(")"); duke@1: } duke@1: print(" "); duke@1: printStat(tree.thenpart); duke@1: if (tree.elsepart != null) { duke@1: print(" else "); duke@1: printStat(tree.elsepart); duke@1: } duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitExec(JCExpressionStatement tree) { duke@1: try { duke@1: printExpr(tree.expr); duke@1: if (prec == TreeInfo.notExpression) print(";"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitBreak(JCBreak tree) { duke@1: try { duke@1: print("break"); duke@1: if (tree.label != null) print(" " + tree.label); duke@1: print(";"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitContinue(JCContinue tree) { duke@1: try { duke@1: print("continue"); duke@1: if (tree.label != null) print(" " + tree.label); duke@1: print(";"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitReturn(JCReturn tree) { duke@1: try { duke@1: print("return"); duke@1: if (tree.expr != null) { duke@1: print(" "); duke@1: printExpr(tree.expr); duke@1: } duke@1: print(";"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitThrow(JCThrow tree) { duke@1: try { duke@1: print("throw "); duke@1: printExpr(tree.expr); duke@1: print(";"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitAssert(JCAssert tree) { duke@1: try { duke@1: print("assert "); duke@1: printExpr(tree.cond); duke@1: if (tree.detail != null) { duke@1: print(" : "); duke@1: printExpr(tree.detail); duke@1: } duke@1: print(";"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitApply(JCMethodInvocation tree) { duke@1: try { duke@1: if (!tree.typeargs.isEmpty()) { duke@1: if (tree.meth.getTag() == JCTree.SELECT) { duke@1: JCFieldAccess left = (JCFieldAccess)tree.meth; duke@1: printExpr(left.selected); duke@1: print(".<"); duke@1: printExprs(tree.typeargs); duke@1: print(">" + left.name); duke@1: } else { duke@1: print("<"); duke@1: printExprs(tree.typeargs); duke@1: print(">"); duke@1: printExpr(tree.meth); duke@1: } duke@1: } else { duke@1: printExpr(tree.meth); duke@1: } duke@1: print("("); duke@1: printExprs(tree.args); duke@1: print(")"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitNewClass(JCNewClass tree) { duke@1: try { duke@1: if (tree.encl != null) { duke@1: printExpr(tree.encl); duke@1: print("."); duke@1: } duke@1: print("new "); duke@1: if (!tree.typeargs.isEmpty()) { duke@1: print("<"); duke@1: printExprs(tree.typeargs); duke@1: print(">"); duke@1: } duke@1: printExpr(tree.clazz); duke@1: print("("); duke@1: printExprs(tree.args); duke@1: print(")"); duke@1: if (tree.def != null) { duke@1: Name enclClassNamePrev = enclClassName; duke@1: enclClassName = duke@1: tree.def.name != null ? tree.def.name : jjg@113: tree.type != null && tree.type.tsym.name != tree.type.tsym.name.table.names.empty jjg@113: ? tree.type.tsym.name : null; duke@1: if ((tree.def.mods.flags & Flags.ENUM) != 0) print("/*enum*/"); duke@1: printBlock(tree.def.defs); duke@1: enclClassName = enclClassNamePrev; duke@1: } duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitNewArray(JCNewArray tree) { duke@1: try { duke@1: if (tree.elemtype != null) { duke@1: print("new "); jjg@308: printTypeAnnotations(tree.annotations); duke@1: JCTree elem = tree.elemtype; jjg@308: printBaseElementType(elem); jjg@308: boolean isElemAnnoType = elem instanceof JCAnnotatedType; jjg@308: int i = 0; jjg@308: List> da = tree.dimAnnotations; duke@1: for (List l = tree.dims; l.nonEmpty(); l = l.tail) { jjg@308: if (da.size() > i) { jjg@308: printTypeAnnotations(da.get(i)); jjg@308: } duke@1: print("["); jjg@308: i++; duke@1: printExpr(l.head); duke@1: print("]"); duke@1: } jjg@308: if (tree.elems != null) { jjg@308: if (isElemAnnoType) { jjg@308: printTypeAnnotations(((JCAnnotatedType)tree.elemtype).annotations); jjg@308: } jjg@308: print("[]"); jjg@308: } jjg@308: if (isElemAnnoType) jjg@308: elem = ((JCAnnotatedType)elem).underlyingType; duke@1: if (elem instanceof JCArrayTypeTree) duke@1: printBrackets((JCArrayTypeTree) elem); duke@1: } duke@1: if (tree.elems != null) { duke@1: print("{"); duke@1: printExprs(tree.elems); duke@1: print("}"); duke@1: } duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitParens(JCParens tree) { duke@1: try { duke@1: print("("); duke@1: printExpr(tree.expr); duke@1: print(")"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitAssign(JCAssign tree) { duke@1: try { duke@1: open(prec, TreeInfo.assignPrec); duke@1: printExpr(tree.lhs, TreeInfo.assignPrec + 1); duke@1: print(" = "); duke@1: printExpr(tree.rhs, TreeInfo.assignPrec); duke@1: close(prec, TreeInfo.assignPrec); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public String operatorName(int tag) { duke@1: switch(tag) { duke@1: case JCTree.POS: return "+"; duke@1: case JCTree.NEG: return "-"; duke@1: case JCTree.NOT: return "!"; duke@1: case JCTree.COMPL: return "~"; duke@1: case JCTree.PREINC: return "++"; duke@1: case JCTree.PREDEC: return "--"; duke@1: case JCTree.POSTINC: return "++"; duke@1: case JCTree.POSTDEC: return "--"; duke@1: case JCTree.NULLCHK: return "<*nullchk*>"; duke@1: case JCTree.OR: return "||"; duke@1: case JCTree.AND: return "&&"; duke@1: case JCTree.EQ: return "=="; duke@1: case JCTree.NE: return "!="; duke@1: case JCTree.LT: return "<"; duke@1: case JCTree.GT: return ">"; duke@1: case JCTree.LE: return "<="; duke@1: case JCTree.GE: return ">="; duke@1: case JCTree.BITOR: return "|"; duke@1: case JCTree.BITXOR: return "^"; duke@1: case JCTree.BITAND: return "&"; duke@1: case JCTree.SL: return "<<"; duke@1: case JCTree.SR: return ">>"; duke@1: case JCTree.USR: return ">>>"; duke@1: case JCTree.PLUS: return "+"; duke@1: case JCTree.MINUS: return "-"; duke@1: case JCTree.MUL: return "*"; duke@1: case JCTree.DIV: return "/"; duke@1: case JCTree.MOD: return "%"; duke@1: default: throw new Error(); duke@1: } duke@1: } duke@1: duke@1: public void visitAssignop(JCAssignOp tree) { duke@1: try { duke@1: open(prec, TreeInfo.assignopPrec); duke@1: printExpr(tree.lhs, TreeInfo.assignopPrec + 1); duke@1: print(" " + operatorName(tree.getTag() - JCTree.ASGOffset) + "= "); duke@1: printExpr(tree.rhs, TreeInfo.assignopPrec); duke@1: close(prec, TreeInfo.assignopPrec); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitUnary(JCUnary tree) { duke@1: try { duke@1: int ownprec = TreeInfo.opPrec(tree.getTag()); duke@1: String opname = operatorName(tree.getTag()); duke@1: open(prec, ownprec); duke@1: if (tree.getTag() <= JCTree.PREDEC) { duke@1: print(opname); duke@1: printExpr(tree.arg, ownprec); duke@1: } else { duke@1: printExpr(tree.arg, ownprec); duke@1: print(opname); duke@1: } duke@1: close(prec, ownprec); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitBinary(JCBinary tree) { duke@1: try { duke@1: int ownprec = TreeInfo.opPrec(tree.getTag()); duke@1: String opname = operatorName(tree.getTag()); duke@1: open(prec, ownprec); duke@1: printExpr(tree.lhs, ownprec); duke@1: print(" " + opname + " "); duke@1: printExpr(tree.rhs, ownprec + 1); duke@1: close(prec, ownprec); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitTypeCast(JCTypeCast tree) { duke@1: try { duke@1: open(prec, TreeInfo.prefixPrec); duke@1: print("("); duke@1: printExpr(tree.clazz); duke@1: print(")"); duke@1: printExpr(tree.expr, TreeInfo.prefixPrec); duke@1: close(prec, TreeInfo.prefixPrec); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitTypeTest(JCInstanceOf tree) { duke@1: try { duke@1: open(prec, TreeInfo.ordPrec); duke@1: printExpr(tree.expr, TreeInfo.ordPrec); duke@1: print(" instanceof "); duke@1: printExpr(tree.clazz, TreeInfo.ordPrec + 1); duke@1: close(prec, TreeInfo.ordPrec); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitIndexed(JCArrayAccess tree) { duke@1: try { duke@1: printExpr(tree.indexed, TreeInfo.postfixPrec); duke@1: print("["); duke@1: printExpr(tree.index); duke@1: print("]"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitSelect(JCFieldAccess tree) { duke@1: try { duke@1: printExpr(tree.selected, TreeInfo.postfixPrec); duke@1: print("." + tree.name); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitIdent(JCIdent tree) { duke@1: try { duke@1: print(tree.name); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitLiteral(JCLiteral tree) { duke@1: try { duke@1: switch (tree.typetag) { duke@1: case TypeTags.INT: duke@1: print(tree.value.toString()); duke@1: break; duke@1: case TypeTags.LONG: duke@1: print(tree.value + "L"); duke@1: break; duke@1: case TypeTags.FLOAT: duke@1: print(tree.value + "F"); duke@1: break; duke@1: case TypeTags.DOUBLE: duke@1: print(tree.value.toString()); duke@1: break; duke@1: case TypeTags.CHAR: duke@1: print("\'" + duke@1: Convert.quote( duke@1: String.valueOf((char)((Number)tree.value).intValue())) + duke@1: "\'"); duke@1: break; duke@1: case TypeTags.BOOLEAN: duke@1: print(((Number)tree.value).intValue() == 1 ? "true" : "false"); duke@1: break; duke@1: case TypeTags.BOT: duke@1: print("null"); duke@1: break; duke@1: default: duke@1: print("\"" + Convert.quote(tree.value.toString()) + "\""); duke@1: break; duke@1: } duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitTypeIdent(JCPrimitiveTypeTree tree) { duke@1: try { duke@1: switch(tree.typetag) { duke@1: case TypeTags.BYTE: duke@1: print("byte"); duke@1: break; duke@1: case TypeTags.CHAR: duke@1: print("char"); duke@1: break; duke@1: case TypeTags.SHORT: duke@1: print("short"); duke@1: break; duke@1: case TypeTags.INT: duke@1: print("int"); duke@1: break; duke@1: case TypeTags.LONG: duke@1: print("long"); duke@1: break; duke@1: case TypeTags.FLOAT: duke@1: print("float"); duke@1: break; duke@1: case TypeTags.DOUBLE: duke@1: print("double"); duke@1: break; duke@1: case TypeTags.BOOLEAN: duke@1: print("boolean"); duke@1: break; duke@1: case TypeTags.VOID: duke@1: print("void"); duke@1: break; duke@1: default: duke@1: print("error"); duke@1: break; duke@1: } duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitTypeArray(JCArrayTypeTree tree) { duke@1: try { duke@1: printBaseElementType(tree); duke@1: printBrackets(tree); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: // Prints the inner element type of a nested array jjg@308: private void printBaseElementType(JCTree tree) throws IOException { jjg@470: printExpr(TreeInfo.innermostType(tree)); duke@1: } duke@1: duke@1: // prints the brackets of a nested array in reverse order duke@1: private void printBrackets(JCArrayTypeTree tree) throws IOException { duke@1: JCTree elem; duke@1: while (true) { duke@1: elem = tree.elemtype; jjg@308: if (elem.getTag() == JCTree.ANNOTATED_TYPE) { jjg@308: JCAnnotatedType atype = (JCAnnotatedType) elem; jjg@308: printTypeAnnotations(atype.annotations); jjg@308: elem = atype.underlyingType; jjg@308: } duke@1: print("[]"); jjg@308: if (elem.getTag() != JCTree.TYPEARRAY) break; duke@1: tree = (JCArrayTypeTree) elem; duke@1: } duke@1: } duke@1: duke@1: public void visitTypeApply(JCTypeApply tree) { duke@1: try { duke@1: printExpr(tree.clazz); duke@1: print("<"); duke@1: printExprs(tree.arguments); duke@1: print(">"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: jjg@724: public void visitTypeDisjunction(JCTypeDisjunction tree) { mcimadamore@550: try { jjg@724: printExprs(tree.alternatives, " | "); mcimadamore@550: } catch (IOException e) { mcimadamore@550: throw new UncheckedIOException(e); mcimadamore@550: } mcimadamore@550: } mcimadamore@550: duke@1: public void visitTypeParameter(JCTypeParameter tree) { duke@1: try { duke@1: print(tree.name); duke@1: if (tree.bounds.nonEmpty()) { duke@1: print(" extends "); duke@1: printExprs(tree.bounds, " & "); duke@1: } duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: @Override duke@1: public void visitWildcard(JCWildcard tree) { duke@1: try { duke@1: print(tree.kind); duke@1: if (tree.kind.kind != BoundKind.UNBOUND) duke@1: printExpr(tree.inner); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: @Override duke@1: public void visitTypeBoundKind(TypeBoundKind tree) { duke@1: try { duke@1: print(String.valueOf(tree.kind)); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitErroneous(JCErroneous tree) { duke@1: try { duke@1: print("(ERROR)"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitLetExpr(LetExpr tree) { duke@1: try { duke@1: print("(let " + tree.defs + " in " + tree.expr + ")"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitModifiers(JCModifiers mods) { duke@1: try { duke@1: printAnnotations(mods.annotations); duke@1: printFlags(mods.flags); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: duke@1: public void visitAnnotation(JCAnnotation tree) { duke@1: try { duke@1: print("@"); duke@1: printExpr(tree.annotationType); duke@1: print("("); duke@1: printExprs(tree.args); duke@1: print(")"); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } duke@1: jjg@308: public void visitAnnotatedType(JCAnnotatedType tree) { jjg@308: try { jjg@308: printTypeAnnotations(tree.annotations); jjg@308: printExpr(tree.underlyingType); jjg@308: } catch (IOException e) { jjg@308: throw new UncheckedIOException(e); jjg@308: } jjg@308: } jjg@308: duke@1: public void visitTree(JCTree tree) { duke@1: try { duke@1: print("(UNKNOWN: " + tree + ")"); duke@1: println(); duke@1: } catch (IOException e) { duke@1: throw new UncheckedIOException(e); duke@1: } duke@1: } jjg@308: duke@1: }