com.redhat.ceylon.langtools.tools.javac.tree.Pretty Maven / Gradle / Ivy
/*
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.redhat.ceylon.langtools.tools.javac.tree;
import static com.redhat.ceylon.langtools.tools.javac.code.Flags.*;
import java.io.*;
import java.util.*;
import com.redhat.ceylon.langtools.tools.javac.code.*;
import com.redhat.ceylon.langtools.tools.javac.code.Symbol.*;
import com.redhat.ceylon.langtools.tools.javac.tree.JCTree.*;
import com.redhat.ceylon.langtools.tools.javac.util.*;
import com.redhat.ceylon.langtools.tools.javac.util.List;
/** Prints out a tree as an indented Java source program.
*
* This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.
*/
public class Pretty extends JCTree.Visitor {
public Pretty(Writer out, boolean sourceOutput) {
this.out = out;
this.sourceOutput = sourceOutput;
}
/** Set when we are producing source output. If we're not
* producing source output, we can sometimes give more detail in
* the output even though that detail would not be valid java
* source.
*/
private final boolean sourceOutput;
/** The output stream on which trees are printed.
*/
Writer out;
/** Indentation width (can be reassigned from outside).
*/
public int width = 4;
/** The current left margin.
*/
int lmargin = 0;
/** The enclosing class name.
*/
Name enclClassName;
/** A hashtable mapping trees to their documentation comments
* (can be null)
*/
Map docComments = null;
/** Align code to be indented to left margin.
*/
void align() throws IOException {
for (int i = 0; i < lmargin; i++) out.write(" ");
}
/** Increase left margin by indentation width.
*/
void indent() {
lmargin = lmargin + width;
}
/** Decrease left margin by indentation width.
*/
void undent() {
lmargin = lmargin - width;
}
/** Enter a new precedence level. Emit a `(' if new precedence level
* is less than precedence level so far.
* @param contextPrec The precedence level in force so far.
* @param ownPrec The new precedence level.
*/
void open(int contextPrec, int ownPrec) throws IOException {
if (ownPrec < contextPrec) out.write("(");
}
/** Leave precedence level. Emit a `(' if inner precedence level
* is less than precedence level we revert to.
* @param contextPrec The precedence level we revert to.
* @param ownPrec The inner precedence level.
*/
void close(int contextPrec, int ownPrec) throws IOException {
if (ownPrec < contextPrec) out.write(")");
}
/** Print string, replacing all non-ascii character with unicode escapes.
*/
public void print(Object s) throws IOException {
out.write(Convert.escapeUnicode(s.toString()));
}
/** Print new line.
*/
public void println() throws IOException {
out.write(lineSep);
}
String lineSep = System.getProperty("line.separator");
/**************************************************************************
* Traversal methods
*************************************************************************/
/** Exception to propogate IOException through visitXXX methods */
private static class UncheckedIOException extends Error {
static final long serialVersionUID = -4032692679158424751L;
UncheckedIOException(IOException e) {
super(e.getMessage(), e);
}
}
/** Visitor argument: the current precedence level.
*/
int prec;
/** Visitor method: print expression tree.
* @param prec The current precedence level.
*/
public void printExpr(JCTree tree, int prec) throws IOException {
int prevPrec = this.prec;
try {
this.prec = prec;
if (tree == null) print("/*missing*/");
else {
tree.accept(this);
}
} catch (UncheckedIOException ex) {
IOException e = new IOException(ex.getMessage());
e.initCause(ex);
throw e;
} finally {
this.prec = prevPrec;
}
}
/** Derived visitor method: print expression tree at minimum precedence level
* for expression.
*/
public void printExpr(JCTree tree) throws IOException {
printExpr(tree, TreeInfo.noPrec);
}
/** Derived visitor method: print statement tree.
*/
public void printStat(JCTree tree) throws IOException {
printExpr(tree, TreeInfo.notExpression);
}
/** Derived visitor method: print list of expression trees, separated by given string.
* @param sep the separator string
*/
public void printExprs(List trees, String sep) throws IOException {
if (trees.nonEmpty()) {
printExpr(trees.head);
for (List l = trees.tail; l.nonEmpty(); l = l.tail) {
print(sep);
if (sep.endsWith("\n")) {
align();
}
printExpr(l.head);
}
}
}
/** Derived visitor method: print list of expression trees, separated by commas.
*/
public void printExprs(List trees, boolean multiline) throws IOException {
if (multiline && trees.length() > 1) {
indent();
indent();
println();
align();
printExprs(trees, ",\n");
undent();
undent();
} else {
printExprs(trees, ", ");
}
}
public void printExprs(List trees) throws IOException {
printExprs(trees, false);
}
/** Derived visitor method: print list of statements, each on a separate line.
*/
public void printStats(List extends JCTree> trees) throws IOException {
for (List extends JCTree> l = trees; l.nonEmpty(); l = l.tail) {
align();
printStat(l.head);
println();
}
}
/** Print a set of modifiers.
*/
public void printFlags(long flags) throws IOException {
if ((flags & SYNTHETIC) != 0) print("/*synthetic*/ ");
print(TreeInfo.flagNames(flags));
if ((flags & StandardFlags) != 0) print(" ");
if ((flags & ANNOTATION) != 0) print("@");
}
public void printAnnotations(List trees) throws IOException {
for (List l = trees; l.nonEmpty(); l = l.tail) {
printStat(l.head);
println();
align();
}
}
/** Print documentation comment, if it exists
* @param tree The tree for which a documentation comment should be printed.
*/
public void printDocComment(JCTree tree) throws IOException {
if (docComments != null) {
String dc = docComments.get(tree);
if (dc != null) {
print("/**"); println();
int pos = 0;
int endpos = lineEndPos(dc, pos);
while (pos < dc.length()) {
align();
print(" *");
if (pos < dc.length() && dc.charAt(pos) > ' ') print(" ");
print(dc.substring(pos, endpos)); println();
pos = endpos + 1;
endpos = lineEndPos(dc, pos);
}
align(); print(" */"); println();
align();
}
}
}
//where
static int lineEndPos(String s, int start) {
int pos = s.indexOf('\n', start);
if (pos < 0) pos = s.length();
return pos;
}
/** If type parameter list is non-empty, print it enclosed in "<...>" brackets.
*/
public void printTypeParameters(List trees) throws IOException {
if (trees.nonEmpty()) {
print("<");
printExprs(trees);
print(">");
}
}
/** Print a block.
*/
public void printBlock(List extends JCTree> stats) throws IOException {
print("{");
println();
indent();
printStats(stats);
undent();
align();
print("}");
}
/** Print a block.
*/
public void printEnumBody(List stats) throws IOException {
print("{");
println();
indent();
boolean first = true;
for (List l = stats; l.nonEmpty(); l = l.tail) {
if (isEnumerator(l.head)) {
if (!first) {
print(",");
println();
}
align();
printStat(l.head);
first = false;
}
}
print(";");
println();
for (List l = stats; l.nonEmpty(); l = l.tail) {
if (!isEnumerator(l.head)) {
align();
printStat(l.head);
println();
}
}
undent();
align();
print("}");
}
/** Is the given tree an enumerator definition? */
boolean isEnumerator(JCTree t) {
return t.getTag() == JCTree.VARDEF && (((JCVariableDecl) t).mods.flags & ENUM) != 0;
}
/** Print unit consisting of package clause and import statements in toplevel,
* followed by class definition. if class definition == null,
* print all definitions in toplevel.
* @param tree The toplevel tree
* @param cdef The class definition, which is assumed to be part of the
* toplevel tree.
*/
public void printUnit(JCCompilationUnit tree, JCClassDecl cdef) throws IOException {
docComments = tree.docComments;
printDocComment(tree);
if (tree.pid != null) {
print("package ");
printExpr(tree.pid);
print(";");
println();
}
boolean firstImport = true;
for (List l = tree.defs;
l.nonEmpty() && (cdef == null || l.head.getTag() == JCTree.IMPORT);
l = l.tail) {
if (l.head.getTag() == JCTree.IMPORT) {
JCImport imp = (JCImport)l.head;
Name name = TreeInfo.name(imp.qualid);
if (name == name.table.names.asterisk ||
cdef == null ||
isUsed(TreeInfo.symbol(imp.qualid), cdef)) {
if (firstImport) {
firstImport = false;
println();
}
printStat(imp);
}
} else {
printStat(l.head);
}
}
if (cdef != null) {
printStat(cdef);
println();
}
}
// where
boolean isUsed(final Symbol t, JCTree cdef) {
class UsedVisitor extends TreeScanner {
public void scan(JCTree tree) {
if (tree!=null && !result) tree.accept(this);
}
boolean result = false;
public void visitIdent(JCIdent tree) {
if (tree.sym == t) result = true;
}
}
UsedVisitor v = new UsedVisitor();
v.scan(cdef);
return v.result;
}
/**************************************************************************
* Visitor methods
*************************************************************************/
public void visitTopLevel(JCCompilationUnit tree) {
try {
printUnit(tree, null);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitImport(JCImport tree) {
try {
print("import ");
if (tree.staticImport) print("static ");
printExpr(tree.qualid);
print(";");
println();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitClassDef(JCClassDecl tree) {
try {
println(); align();
printDocComment(tree);
printAnnotations(tree.mods.annotations);
printFlags(tree.mods.flags & ~INTERFACE);
Name enclClassNamePrev = enclClassName;
enclClassName = tree.name;
if ((tree.mods.flags & INTERFACE) != 0) {
print("interface " + tree.name);
printTypeParameters(tree.typarams);
if (tree.implementing.nonEmpty()) {
print(" extends ");
printExprs(tree.implementing);
}
} else {
if ((tree.mods.flags & ENUM) != 0)
print("enum " + tree.name);
else
print("class " + tree.name);
printTypeParameters(tree.typarams);
if (tree.extending != null) {
print(" extends ");
printExpr(tree.extending);
}
if (tree.implementing.nonEmpty()) {
print(" implements ");
printExprs(tree.implementing);
}
}
print(" ");
if ((tree.mods.flags & ENUM) != 0) {
printEnumBody(tree.defs);
} else {
printBlock(tree.defs);
}
enclClassName = enclClassNamePrev;
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitMethodDef(JCMethodDecl tree) {
try {
// when producing source output, omit anonymous constructors
if (tree.name == tree.name.table.names.init &&
enclClassName == null &&
sourceOutput) return;
println(); align();
printDocComment(tree);
printExpr(tree.mods);
printTypeParameters(tree.typarams);
if (tree.name == tree.name.table.names.init) {
print(enclClassName != null ? enclClassName : tree.name);
} else {
printExpr(tree.restype);
print(" " + tree.name);
}
print("(");
printExprs(tree.params);
print(")");
if (tree.thrown.nonEmpty()) {
print(" throws ");
printExprs(tree.thrown);
}
if (tree.defaultValue != null) {
print(" default ");
printExpr(tree.defaultValue);
}
if (tree.body != null) {
print(" ");
printStat(tree.body);
} else {
print(";");
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitVarDef(JCVariableDecl tree) {
try {
if (docComments != null && docComments.get(tree) != null) {
println(); align();
}
printDocComment(tree);
if ((tree.mods.flags & ENUM) != 0) {
print("/*public static final*/ ");
print(tree.name);
if (tree.init != null) {
if (sourceOutput && tree.init.getTag() == JCTree.NEWCLASS) {
print(" /*enum*/ ");
JCNewClass init = (JCNewClass) tree.init;
if (init.args != null && init.args.nonEmpty()) {
print("(");
print(init.args);
print(")");
}
if (init.def != null && init.def.defs != null) {
print(" ");
printBlock(init.def.defs);
}
return;
}
print(" /* = ");
printExpr(tree.init);
print(" */");
}
} else {
printExpr(tree.mods);
if ((tree.mods.flags & VARARGS) != 0) {
printExpr(((JCArrayTypeTree) tree.vartype).elemtype);
print("... " + tree.name);
} else {
printExpr(tree.vartype);
print(" " + tree.name);
}
if (tree.init != null) {
print(" = ");
printExpr(tree.init);
}
if (prec == TreeInfo.notExpression) print(";");
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitSkip(JCSkip tree) {
try {
print(";");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitBlock(JCBlock tree) {
try {
printFlags(tree.flags);
printBlock(tree.stats);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitDoLoop(JCDoWhileLoop tree) {
try {
print("do ");
printStat(tree.body);
align();
print(" while ");
if (tree.cond.getTag() == JCTree.PARENS) {
printExpr(tree.cond);
} else {
print("(");
printExpr(tree.cond);
print(")");
}
print(";");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitWhileLoop(JCWhileLoop tree) {
try {
print("while ");
if (tree.cond.getTag() == JCTree.PARENS) {
printExpr(tree.cond);
} else {
print("(");
printExpr(tree.cond);
print(")");
}
print(" ");
printStat(tree.body);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitForLoop(JCForLoop tree) {
try {
print("for (");
if (tree.init.nonEmpty()) {
if (tree.init.head.getTag() == JCTree.VARDEF) {
printExpr(tree.init.head);
for (List l = tree.init.tail; l.nonEmpty(); l = l.tail) {
JCVariableDecl vdef = (JCVariableDecl)l.head;
print(", " + vdef.name + " = ");
printExpr(vdef.init);
}
} else {
printExprs(tree.init);
}
}
print("; ");
if (tree.cond != null) printExpr(tree.cond);
print("; ");
printExprs(tree.step);
print(") ");
printStat(tree.body);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitForeachLoop(JCEnhancedForLoop tree) {
try {
print("for (");
printExpr(tree.var);
print(" : ");
printExpr(tree.expr);
print(") ");
printStat(tree.body);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitLabelled(JCLabeledStatement tree) {
try {
print(tree.label + ": ");
printStat(tree.body);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitSwitch(JCSwitch tree) {
try {
print("switch ");
if (tree.selector.getTag() == JCTree.PARENS) {
printExpr(tree.selector);
} else {
print("(");
printExpr(tree.selector);
print(")");
}
print(" {");
println();
printStats(tree.cases);
align();
print("}");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitCase(JCCase tree) {
try {
if (tree.pat == null) {
print("default");
} else {
print("case ");
printExpr(tree.pat);
}
print(": ");
println();
indent();
printStats(tree.stats);
undent();
align();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitSynchronized(JCSynchronized tree) {
try {
print("synchronized ");
if (tree.lock.getTag() == JCTree.PARENS) {
printExpr(tree.lock);
} else {
print("(");
printExpr(tree.lock);
print(")");
}
print(" ");
printStat(tree.body);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitTry(JCTry tree) {
try {
print("try ");
if (tree.resources.nonEmpty()) {
print("(");
boolean first = true;
for (JCTree var : tree.resources) {
if (!first) {
println();
indent();
}
printStat(var);
first = false;
}
print(") ");
}
printStat(tree.body);
for (List l = tree.catchers; l.nonEmpty(); l = l.tail) {
printStat(l.head);
}
if (tree.finalizer != null) {
print(" finally ");
printStat(tree.finalizer);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitCatch(JCCatch tree) {
try {
print(" catch (");
printExpr(tree.param);
print(") ");
printStat(tree.body);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitConditional(JCConditional tree) {
try {
open(prec, TreeInfo.condPrec);
printExpr(tree.cond, TreeInfo.condPrec);
print(" ? ");
printExpr(tree.truepart, TreeInfo.condPrec);
print(" : ");
printExpr(tree.falsepart, TreeInfo.condPrec);
close(prec, TreeInfo.condPrec);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitIf(JCIf tree) {
try {
print("if ");
if (tree.cond.getTag() == JCTree.PARENS) {
printExpr(tree.cond);
} else {
print("(");
printExpr(tree.cond);
print(")");
}
print(" ");
printStat(tree.thenpart);
if (tree.elsepart != null) {
print(" else ");
printStat(tree.elsepart);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitExec(JCExpressionStatement tree) {
try {
printExpr(tree.expr);
if (prec == TreeInfo.notExpression) print(";");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitBreak(JCBreak tree) {
try {
print("break");
if (tree.label != null) print(" " + tree.label);
print(";");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitContinue(JCContinue tree) {
try {
print("continue");
if (tree.label != null) print(" " + tree.label);
print(";");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitReturn(JCReturn tree) {
try {
print("return");
if (tree.expr != null) {
print(" ");
printExpr(tree.expr);
}
print(";");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitThrow(JCThrow tree) {
try {
print("throw ");
printExpr(tree.expr);
print(";");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitAssert(JCAssert tree) {
try {
print("assert ");
printExpr(tree.cond);
if (tree.detail != null) {
print(" : ");
printExpr(tree.detail);
}
print(";");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitApply(JCMethodInvocation tree) {
try {
if (!tree.typeargs.isEmpty()) {
if (tree.meth.getTag() == JCTree.SELECT) {
JCFieldAccess left = (JCFieldAccess)tree.meth;
if(left.selected.getTag() == JCTree.TYPECAST)
print("(");
printExpr(left.selected);
if(left.selected.getTag() == JCTree.TYPECAST)
print(")");
print(".<");
printExprs(tree.typeargs);
print(">" + left.name);
} else {
print("<");
printExprs(tree.typeargs);
print(">");
printExpr(tree.meth);
}
} else {
printExpr(tree.meth);
}
print("(");
printExprs(tree.args);
print(")");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitNewClass(JCNewClass tree) {
try {
if (tree.encl != null) {
printExpr(tree.encl);
print(".");
}
print("new ");
if (!tree.typeargs.isEmpty()) {
print("<");
printExprs(tree.typeargs);
print(">");
}
printExpr(tree.clazz);
print("(");
printExprs(tree.args);
print(")");
if (tree.def != null) {
if (!tree.def.mods.annotations.isEmpty()) {
println();
align();
printAnnotations(tree.def.mods.annotations);
}
Name enclClassNamePrev = enclClassName;
enclClassName =
tree.def.name != null ? tree.def.name :
tree.type != null && tree.type.tsym.name != tree.type.tsym.name.table.names.empty
? tree.type.tsym.name : null;
if ((tree.def.mods.flags & Flags.ENUM) != 0) print("/*enum*/");
printBlock(tree.def.defs);
enclClassName = enclClassNamePrev;
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitNewArray(JCNewArray tree) {
try {
if (tree.elemtype != null) {
print("new ");
JCTree elem = tree.elemtype;
if (elem.getTag() == JCTree.TYPEARRAY)
printBaseElementType((JCArrayTypeTree) elem);
else
printExpr(elem);
for (List l = tree.dims; l.nonEmpty(); l = l.tail) {
print("[");
printExpr(l.head);
print("]");
}
if (elem instanceof JCArrayTypeTree)
printBrackets((JCArrayTypeTree) elem);
}
if (tree.elems != null) {
if (tree.elemtype != null) print("[]");
print("{");
printExprs(tree.elems, true);
print("}");
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitParens(JCParens tree) {
try {
print("(");
printExpr(tree.expr);
print(")");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitAssign(JCAssign tree) {
try {
open(prec, TreeInfo.assignPrec);
printExpr(tree.lhs, TreeInfo.assignPrec + 1);
print(" = ");
printExpr(tree.rhs, TreeInfo.assignPrec);
close(prec, TreeInfo.assignPrec);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public String operatorName(int tag) {
switch(tag) {
case JCTree.POS: return "+";
case JCTree.NEG: return "-";
case JCTree.NOT: return "!";
case JCTree.COMPL: return "~";
case JCTree.PREINC: return "++";
case JCTree.PREDEC: return "--";
case JCTree.POSTINC: return "++";
case JCTree.POSTDEC: return "--";
case JCTree.NULLCHK: return "<*nullchk*>";
case JCTree.OR: return "||";
case JCTree.AND: return "&&";
case JCTree.EQ: return "==";
case JCTree.NE: return "!=";
case JCTree.LT: return "<";
case JCTree.GT: return ">";
case JCTree.LE: return "<=";
case JCTree.GE: return ">=";
case JCTree.BITOR: return "|";
case JCTree.BITXOR: return "^";
case JCTree.BITAND: return "&";
case JCTree.SL: return "<<";
case JCTree.SR: return ">>";
case JCTree.USR: return ">>>";
case JCTree.PLUS: return "+";
case JCTree.MINUS: return "-";
case JCTree.MUL: return "*";
case JCTree.DIV: return "/";
case JCTree.MOD: return "%";
default: throw new Error();
}
}
public void visitAssignop(JCAssignOp tree) {
try {
open(prec, TreeInfo.assignopPrec);
printExpr(tree.lhs, TreeInfo.assignopPrec + 1);
print(" " + operatorName(tree.getTag() - JCTree.ASGOffset) + "= ");
printExpr(tree.rhs, TreeInfo.assignopPrec);
close(prec, TreeInfo.assignopPrec);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitUnary(JCUnary tree) {
try {
int ownprec = TreeInfo.opPrec(tree.getTag());
String opname = operatorName(tree.getTag());
open(prec, ownprec);
if (tree.getTag() <= JCTree.PREDEC) {
print(opname);
printExpr(tree.arg, ownprec);
} else {
printExpr(tree.arg, ownprec);
print(opname);
}
close(prec, ownprec);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitBinary(JCBinary tree) {
try {
int ownprec = TreeInfo.opPrec(tree.getTag());
String opname = operatorName(tree.getTag());
open(prec, ownprec);
printExpr(tree.lhs, ownprec);
print(" " + opname + " ");
printExpr(tree.rhs, ownprec + 1);
close(prec, ownprec);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitTypeCast(JCTypeCast tree) {
try {
open(prec, TreeInfo.prefixPrec);
print("(");
printExpr(tree.clazz);
print(")");
printExpr(tree.expr, TreeInfo.prefixPrec);
close(prec, TreeInfo.prefixPrec);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitTypeTest(JCInstanceOf tree) {
try {
open(prec, TreeInfo.ordPrec);
printExpr(tree.expr, TreeInfo.ordPrec);
print(" instanceof ");
printExpr(tree.clazz, TreeInfo.ordPrec + 1);
close(prec, TreeInfo.ordPrec);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitIndexed(JCArrayAccess tree) {
try {
printExpr(tree.indexed, TreeInfo.postfixPrec);
print("[");
printExpr(tree.index);
print("]");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitSelect(JCFieldAccess tree) {
try {
printExpr(tree.selected, TreeInfo.postfixPrec);
print("." + tree.name);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitIdent(JCIdent tree) {
try {
// Added by Ceylon
if (tree instanceof JCIndyIdent) {
print(".");
JCIndyIdent indy = (JCIndyIdent)tree;
print("Indy[#");
printExpr(indy.bsmType);
print(".");
print(indy.bsmName.toString());
if (indy.bsmStatic.nonEmpty()) {
print(", ");
print(indy.bsmStatic.head);
for (List