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

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