duke@1: /*
jjg@815: * Copyright (c) 1999, 2011, 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 extends JCTree> trees) throws IOException {
duke@1: for (List extends JCTree> 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:
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 extends JCTree> 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 ");
duke@1: JCTree elem = tree.elemtype;
jjg@815: if (elem.getTag() == JCTree.TYPEARRAY)
jjg@815: printBaseElementType((JCArrayTypeTree) elem);
jjg@815: else
jjg@815: printExpr(elem);
duke@1: for (List l = tree.dims; l.nonEmpty(); l = l.tail) {
duke@1: print("[");
duke@1: printExpr(l.head);
duke@1: print("]");
duke@1: }
duke@1: if (elem instanceof JCArrayTypeTree)
duke@1: printBrackets((JCArrayTypeTree) elem);
duke@1: }
duke@1: if (tree.elems != null) {
jjg@815: if (tree.elemtype != null) print("[]");
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;
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:
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: }