1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/tree/Pretty.java Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,1224 @@ 1.4 +/* 1.5 + * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Sun designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Sun in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.25 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.26 + * have any questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.javac.tree; 1.30 + 1.31 +import java.io.*; 1.32 +import java.util.*; 1.33 + 1.34 +import com.sun.tools.javac.util.*; 1.35 +import com.sun.tools.javac.util.List; 1.36 +import com.sun.tools.javac.code.*; 1.37 + 1.38 +import com.sun.tools.javac.code.Symbol.*; 1.39 +import com.sun.tools.javac.tree.JCTree.*; 1.40 + 1.41 +import static com.sun.tools.javac.code.Flags.*; 1.42 + 1.43 +/** Prints out a tree as an indented Java source program. 1.44 + * 1.45 + * <p><b>This is NOT part of any API supported by Sun Microsystems. If 1.46 + * you write code that depends on this, you do so at your own risk. 1.47 + * This code and its internal interfaces are subject to change or 1.48 + * deletion without notice.</b> 1.49 + */ 1.50 +public class Pretty extends JCTree.Visitor { 1.51 + 1.52 + public Pretty(Writer out, boolean sourceOutput) { 1.53 + this.out = out; 1.54 + this.sourceOutput = sourceOutput; 1.55 + } 1.56 + 1.57 + /** Set when we are producing source output. If we're not 1.58 + * producing source output, we can sometimes give more detail in 1.59 + * the output even though that detail would not be valid java 1.60 + * soruce. 1.61 + */ 1.62 + private final boolean sourceOutput; 1.63 + 1.64 + /** The output stream on which trees are printed. 1.65 + */ 1.66 + Writer out; 1.67 + 1.68 + /** Indentation width (can be reassigned from outside). 1.69 + */ 1.70 + public int width = 4; 1.71 + 1.72 + /** The current left margin. 1.73 + */ 1.74 + int lmargin = 0; 1.75 + 1.76 + /** The enclosing class name. 1.77 + */ 1.78 + Name enclClassName; 1.79 + 1.80 + /** A hashtable mapping trees to their documentation comments 1.81 + * (can be null) 1.82 + */ 1.83 + Map<JCTree, String> docComments = null; 1.84 + 1.85 + /** Align code to be indented to left margin. 1.86 + */ 1.87 + void align() throws IOException { 1.88 + for (int i = 0; i < lmargin; i++) out.write(" "); 1.89 + } 1.90 + 1.91 + /** Increase left margin by indentation width. 1.92 + */ 1.93 + void indent() { 1.94 + lmargin = lmargin + width; 1.95 + } 1.96 + 1.97 + /** Decrease left margin by indentation width. 1.98 + */ 1.99 + void undent() { 1.100 + lmargin = lmargin - width; 1.101 + } 1.102 + 1.103 + /** Enter a new precedence level. Emit a `(' if new precedence level 1.104 + * is less than precedence level so far. 1.105 + * @param contextPrec The precedence level in force so far. 1.106 + * @param ownPrec The new precedence level. 1.107 + */ 1.108 + void open(int contextPrec, int ownPrec) throws IOException { 1.109 + if (ownPrec < contextPrec) out.write("("); 1.110 + } 1.111 + 1.112 + /** Leave precedence level. Emit a `(' if inner precedence level 1.113 + * is less than precedence level we revert to. 1.114 + * @param contextPrec The precedence level we revert to. 1.115 + * @param ownPrec The inner precedence level. 1.116 + */ 1.117 + void close(int contextPrec, int ownPrec) throws IOException { 1.118 + if (ownPrec < contextPrec) out.write(")"); 1.119 + } 1.120 + 1.121 + /** Print string, replacing all non-ascii character with unicode escapes. 1.122 + */ 1.123 + public void print(Object s) throws IOException { 1.124 + out.write(Convert.escapeUnicode(s.toString())); 1.125 + } 1.126 + 1.127 + /** Print new line. 1.128 + */ 1.129 + public void println() throws IOException { 1.130 + out.write(lineSep); 1.131 + } 1.132 + 1.133 + String lineSep = System.getProperty("line.separator"); 1.134 + 1.135 + /************************************************************************** 1.136 + * Traversal methods 1.137 + *************************************************************************/ 1.138 + 1.139 + /** Exception to propogate IOException through visitXXX methods */ 1.140 + private static class UncheckedIOException extends Error { 1.141 + static final long serialVersionUID = -4032692679158424751L; 1.142 + UncheckedIOException(IOException e) { 1.143 + super(e.getMessage(), e); 1.144 + } 1.145 + } 1.146 + 1.147 + /** Visitor argument: the current precedence level. 1.148 + */ 1.149 + int prec; 1.150 + 1.151 + /** Visitor method: print expression tree. 1.152 + * @param prec The current precedence level. 1.153 + */ 1.154 + public void printExpr(JCTree tree, int prec) throws IOException { 1.155 + int prevPrec = this.prec; 1.156 + try { 1.157 + this.prec = prec; 1.158 + if (tree == null) print("/*missing*/"); 1.159 + else { 1.160 + tree.accept(this); 1.161 + } 1.162 + } catch (UncheckedIOException ex) { 1.163 + IOException e = new IOException(ex.getMessage()); 1.164 + e.initCause(ex); 1.165 + throw e; 1.166 + } finally { 1.167 + this.prec = prevPrec; 1.168 + } 1.169 + } 1.170 + 1.171 + /** Derived visitor method: print expression tree at minimum precedence level 1.172 + * for expression. 1.173 + */ 1.174 + public void printExpr(JCTree tree) throws IOException { 1.175 + printExpr(tree, TreeInfo.noPrec); 1.176 + } 1.177 + 1.178 + /** Derived visitor method: print statement tree. 1.179 + */ 1.180 + public void printStat(JCTree tree) throws IOException { 1.181 + printExpr(tree, TreeInfo.notExpression); 1.182 + } 1.183 + 1.184 + /** Derived visitor method: print list of expression trees, separated by given string. 1.185 + * @param sep the separator string 1.186 + */ 1.187 + public <T extends JCTree> void printExprs(List<T> trees, String sep) throws IOException { 1.188 + if (trees.nonEmpty()) { 1.189 + printExpr(trees.head); 1.190 + for (List<T> l = trees.tail; l.nonEmpty(); l = l.tail) { 1.191 + print(sep); 1.192 + printExpr(l.head); 1.193 + } 1.194 + } 1.195 + } 1.196 + 1.197 + /** Derived visitor method: print list of expression trees, separated by commas. 1.198 + */ 1.199 + public <T extends JCTree> void printExprs(List<T> trees) throws IOException { 1.200 + printExprs(trees, ", "); 1.201 + } 1.202 + 1.203 + /** Derived visitor method: print list of statements, each on a separate line. 1.204 + */ 1.205 + public void printStats(List<? extends JCTree> trees) throws IOException { 1.206 + for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) { 1.207 + align(); 1.208 + printStat(l.head); 1.209 + println(); 1.210 + } 1.211 + } 1.212 + 1.213 + /** Print a set of modifiers. 1.214 + */ 1.215 + public void printFlags(long flags) throws IOException { 1.216 + if ((flags & SYNTHETIC) != 0) print("/*synthetic*/ "); 1.217 + print(TreeInfo.flagNames(flags)); 1.218 + if ((flags & StandardFlags) != 0) print(" "); 1.219 + if ((flags & ANNOTATION) != 0) print("@"); 1.220 + } 1.221 + 1.222 + public void printAnnotations(List<JCAnnotation> trees) throws IOException { 1.223 + for (List<JCAnnotation> l = trees; l.nonEmpty(); l = l.tail) { 1.224 + printStat(l.head); 1.225 + println(); 1.226 + align(); 1.227 + } 1.228 + } 1.229 + 1.230 + /** Print documentation comment, if it exists 1.231 + * @param tree The tree for which a documentation comment should be printed. 1.232 + */ 1.233 + public void printDocComment(JCTree tree) throws IOException { 1.234 + if (docComments != null) { 1.235 + String dc = docComments.get(tree); 1.236 + if (dc != null) { 1.237 + print("/**"); println(); 1.238 + int pos = 0; 1.239 + int endpos = lineEndPos(dc, pos); 1.240 + while (pos < dc.length()) { 1.241 + align(); 1.242 + print(" *"); 1.243 + if (pos < dc.length() && dc.charAt(pos) > ' ') print(" "); 1.244 + print(dc.substring(pos, endpos)); println(); 1.245 + pos = endpos + 1; 1.246 + endpos = lineEndPos(dc, pos); 1.247 + } 1.248 + align(); print(" */"); println(); 1.249 + align(); 1.250 + } 1.251 + } 1.252 + } 1.253 +//where 1.254 + static int lineEndPos(String s, int start) { 1.255 + int pos = s.indexOf('\n', start); 1.256 + if (pos < 0) pos = s.length(); 1.257 + return pos; 1.258 + } 1.259 + 1.260 + /** If type parameter list is non-empty, print it enclosed in "<...>" brackets. 1.261 + */ 1.262 + public void printTypeParameters(List<JCTypeParameter> trees) throws IOException { 1.263 + if (trees.nonEmpty()) { 1.264 + print("<"); 1.265 + printExprs(trees); 1.266 + print(">"); 1.267 + } 1.268 + } 1.269 + 1.270 + /** Print a block. 1.271 + */ 1.272 + public void printBlock(List<? extends JCTree> stats) throws IOException { 1.273 + print("{"); 1.274 + println(); 1.275 + indent(); 1.276 + printStats(stats); 1.277 + undent(); 1.278 + align(); 1.279 + print("}"); 1.280 + } 1.281 + 1.282 + /** Print a block. 1.283 + */ 1.284 + public void printEnumBody(List<JCTree> stats) throws IOException { 1.285 + print("{"); 1.286 + println(); 1.287 + indent(); 1.288 + boolean first = true; 1.289 + for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) { 1.290 + if (isEnumerator(l.head)) { 1.291 + if (!first) { 1.292 + print(","); 1.293 + println(); 1.294 + } 1.295 + align(); 1.296 + printStat(l.head); 1.297 + first = false; 1.298 + } 1.299 + } 1.300 + print(";"); 1.301 + println(); 1.302 + for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) { 1.303 + if (!isEnumerator(l.head)) { 1.304 + align(); 1.305 + printStat(l.head); 1.306 + println(); 1.307 + } 1.308 + } 1.309 + undent(); 1.310 + align(); 1.311 + print("}"); 1.312 + } 1.313 + 1.314 + /** Is the given tree an enumerator definition? */ 1.315 + boolean isEnumerator(JCTree t) { 1.316 + return t.getTag() == JCTree.VARDEF && (((JCVariableDecl) t).mods.flags & ENUM) != 0; 1.317 + } 1.318 + 1.319 + /** Print unit consisting of package clause and import statements in toplevel, 1.320 + * followed by class definition. if class definition == null, 1.321 + * print all definitions in toplevel. 1.322 + * @param tree The toplevel tree 1.323 + * @param cdef The class definition, which is assumed to be part of the 1.324 + * toplevel tree. 1.325 + */ 1.326 + public void printUnit(JCCompilationUnit tree, JCClassDecl cdef) throws IOException { 1.327 + docComments = tree.docComments; 1.328 + printDocComment(tree); 1.329 + if (tree.pid != null) { 1.330 + print("package "); 1.331 + printExpr(tree.pid); 1.332 + print(";"); 1.333 + println(); 1.334 + } 1.335 + boolean firstImport = true; 1.336 + for (List<JCTree> l = tree.defs; 1.337 + l.nonEmpty() && (cdef == null || l.head.getTag() == JCTree.IMPORT); 1.338 + l = l.tail) { 1.339 + if (l.head.getTag() == JCTree.IMPORT) { 1.340 + JCImport imp = (JCImport)l.head; 1.341 + Name name = TreeInfo.name(imp.qualid); 1.342 + if (name == name.table.asterisk || 1.343 + cdef == null || 1.344 + isUsed(TreeInfo.symbol(imp.qualid), cdef)) { 1.345 + if (firstImport) { 1.346 + firstImport = false; 1.347 + println(); 1.348 + } 1.349 + printStat(imp); 1.350 + } 1.351 + } else { 1.352 + printStat(l.head); 1.353 + } 1.354 + } 1.355 + if (cdef != null) { 1.356 + printStat(cdef); 1.357 + println(); 1.358 + } 1.359 + } 1.360 + // where 1.361 + boolean isUsed(final Symbol t, JCTree cdef) { 1.362 + class UsedVisitor extends TreeScanner { 1.363 + public void scan(JCTree tree) { 1.364 + if (tree!=null && !result) tree.accept(this); 1.365 + } 1.366 + boolean result = false; 1.367 + public void visitIdent(JCIdent tree) { 1.368 + if (tree.sym == t) result = true; 1.369 + } 1.370 + } 1.371 + UsedVisitor v = new UsedVisitor(); 1.372 + v.scan(cdef); 1.373 + return v.result; 1.374 + } 1.375 + 1.376 + /************************************************************************** 1.377 + * Visitor methods 1.378 + *************************************************************************/ 1.379 + 1.380 + public void visitTopLevel(JCCompilationUnit tree) { 1.381 + try { 1.382 + printUnit(tree, null); 1.383 + } catch (IOException e) { 1.384 + throw new UncheckedIOException(e); 1.385 + } 1.386 + } 1.387 + 1.388 + public void visitImport(JCImport tree) { 1.389 + try { 1.390 + print("import "); 1.391 + if (tree.staticImport) print("static "); 1.392 + printExpr(tree.qualid); 1.393 + print(";"); 1.394 + println(); 1.395 + } catch (IOException e) { 1.396 + throw new UncheckedIOException(e); 1.397 + } 1.398 + } 1.399 + 1.400 + public void visitClassDef(JCClassDecl tree) { 1.401 + try { 1.402 + println(); align(); 1.403 + printDocComment(tree); 1.404 + printAnnotations(tree.mods.annotations); 1.405 + printFlags(tree.mods.flags & ~INTERFACE); 1.406 + Name enclClassNamePrev = enclClassName; 1.407 + enclClassName = tree.name; 1.408 + if ((tree.mods.flags & INTERFACE) != 0) { 1.409 + print("interface " + tree.name); 1.410 + printTypeParameters(tree.typarams); 1.411 + if (tree.implementing.nonEmpty()) { 1.412 + print(" extends "); 1.413 + printExprs(tree.implementing); 1.414 + } 1.415 + } else { 1.416 + if ((tree.mods.flags & ENUM) != 0) 1.417 + print("enum " + tree.name); 1.418 + else 1.419 + print("class " + tree.name); 1.420 + printTypeParameters(tree.typarams); 1.421 + if (tree.extending != null) { 1.422 + print(" extends "); 1.423 + printExpr(tree.extending); 1.424 + } 1.425 + if (tree.implementing.nonEmpty()) { 1.426 + print(" implements "); 1.427 + printExprs(tree.implementing); 1.428 + } 1.429 + } 1.430 + print(" "); 1.431 + if ((tree.mods.flags & ENUM) != 0) { 1.432 + printEnumBody(tree.defs); 1.433 + } else { 1.434 + printBlock(tree.defs); 1.435 + } 1.436 + enclClassName = enclClassNamePrev; 1.437 + } catch (IOException e) { 1.438 + throw new UncheckedIOException(e); 1.439 + } 1.440 + } 1.441 + 1.442 + public void visitMethodDef(JCMethodDecl tree) { 1.443 + try { 1.444 + // when producing source output, omit anonymous constructors 1.445 + if (tree.name == tree.name.table.init && 1.446 + enclClassName == null && 1.447 + sourceOutput) return; 1.448 + println(); align(); 1.449 + printDocComment(tree); 1.450 + printExpr(tree.mods); 1.451 + printTypeParameters(tree.typarams); 1.452 + if (tree.name == tree.name.table.init) { 1.453 + print(enclClassName != null ? enclClassName : tree.name); 1.454 + } else { 1.455 + printExpr(tree.restype); 1.456 + print(" " + tree.name); 1.457 + } 1.458 + print("("); 1.459 + printExprs(tree.params); 1.460 + print(")"); 1.461 + if (tree.thrown.nonEmpty()) { 1.462 + print(" throws "); 1.463 + printExprs(tree.thrown); 1.464 + } 1.465 + if (tree.body != null) { 1.466 + print(" "); 1.467 + printStat(tree.body); 1.468 + } else { 1.469 + print(";"); 1.470 + } 1.471 + } catch (IOException e) { 1.472 + throw new UncheckedIOException(e); 1.473 + } 1.474 + } 1.475 + 1.476 + public void visitVarDef(JCVariableDecl tree) { 1.477 + try { 1.478 + if (docComments != null && docComments.get(tree) != null) { 1.479 + println(); align(); 1.480 + } 1.481 + printDocComment(tree); 1.482 + if ((tree.mods.flags & ENUM) != 0) { 1.483 + print("/*public static final*/ "); 1.484 + print(tree.name); 1.485 + if (tree.init != null) { 1.486 + print(" /* = "); 1.487 + printExpr(tree.init); 1.488 + print(" */"); 1.489 + } 1.490 + } else { 1.491 + printExpr(tree.mods); 1.492 + if ((tree.mods.flags & VARARGS) != 0) { 1.493 + printExpr(((JCArrayTypeTree) tree.vartype).elemtype); 1.494 + print("... " + tree.name); 1.495 + } else { 1.496 + printExpr(tree.vartype); 1.497 + print(" " + tree.name); 1.498 + } 1.499 + if (tree.init != null) { 1.500 + print(" = "); 1.501 + printExpr(tree.init); 1.502 + } 1.503 + if (prec == TreeInfo.notExpression) print(";"); 1.504 + } 1.505 + } catch (IOException e) { 1.506 + throw new UncheckedIOException(e); 1.507 + } 1.508 + } 1.509 + 1.510 + public void visitSkip(JCSkip tree) { 1.511 + try { 1.512 + print(";"); 1.513 + } catch (IOException e) { 1.514 + throw new UncheckedIOException(e); 1.515 + } 1.516 + } 1.517 + 1.518 + public void visitBlock(JCBlock tree) { 1.519 + try { 1.520 + printFlags(tree.flags); 1.521 + printBlock(tree.stats); 1.522 + } catch (IOException e) { 1.523 + throw new UncheckedIOException(e); 1.524 + } 1.525 + } 1.526 + 1.527 + public void visitDoLoop(JCDoWhileLoop tree) { 1.528 + try { 1.529 + print("do "); 1.530 + printStat(tree.body); 1.531 + align(); 1.532 + print(" while "); 1.533 + if (tree.cond.getTag() == JCTree.PARENS) { 1.534 + printExpr(tree.cond); 1.535 + } else { 1.536 + print("("); 1.537 + printExpr(tree.cond); 1.538 + print(")"); 1.539 + } 1.540 + print(";"); 1.541 + } catch (IOException e) { 1.542 + throw new UncheckedIOException(e); 1.543 + } 1.544 + } 1.545 + 1.546 + public void visitWhileLoop(JCWhileLoop tree) { 1.547 + try { 1.548 + print("while "); 1.549 + if (tree.cond.getTag() == JCTree.PARENS) { 1.550 + printExpr(tree.cond); 1.551 + } else { 1.552 + print("("); 1.553 + printExpr(tree.cond); 1.554 + print(")"); 1.555 + } 1.556 + print(" "); 1.557 + printStat(tree.body); 1.558 + } catch (IOException e) { 1.559 + throw new UncheckedIOException(e); 1.560 + } 1.561 + } 1.562 + 1.563 + public void visitForLoop(JCForLoop tree) { 1.564 + try { 1.565 + print("for ("); 1.566 + if (tree.init.nonEmpty()) { 1.567 + if (tree.init.head.getTag() == JCTree.VARDEF) { 1.568 + printExpr(tree.init.head); 1.569 + for (List<JCStatement> l = tree.init.tail; l.nonEmpty(); l = l.tail) { 1.570 + JCVariableDecl vdef = (JCVariableDecl)l.head; 1.571 + print(", " + vdef.name + " = "); 1.572 + printExpr(vdef.init); 1.573 + } 1.574 + } else { 1.575 + printExprs(tree.init); 1.576 + } 1.577 + } 1.578 + print("; "); 1.579 + if (tree.cond != null) printExpr(tree.cond); 1.580 + print("; "); 1.581 + printExprs(tree.step); 1.582 + print(") "); 1.583 + printStat(tree.body); 1.584 + } catch (IOException e) { 1.585 + throw new UncheckedIOException(e); 1.586 + } 1.587 + } 1.588 + 1.589 + public void visitForeachLoop(JCEnhancedForLoop tree) { 1.590 + try { 1.591 + print("for ("); 1.592 + printExpr(tree.var); 1.593 + print(" : "); 1.594 + printExpr(tree.expr); 1.595 + print(") "); 1.596 + printStat(tree.body); 1.597 + } catch (IOException e) { 1.598 + throw new UncheckedIOException(e); 1.599 + } 1.600 + } 1.601 + 1.602 + public void visitLabelled(JCLabeledStatement tree) { 1.603 + try { 1.604 + print(tree.label + ": "); 1.605 + printStat(tree.body); 1.606 + } catch (IOException e) { 1.607 + throw new UncheckedIOException(e); 1.608 + } 1.609 + } 1.610 + 1.611 + public void visitSwitch(JCSwitch tree) { 1.612 + try { 1.613 + print("switch "); 1.614 + if (tree.selector.getTag() == JCTree.PARENS) { 1.615 + printExpr(tree.selector); 1.616 + } else { 1.617 + print("("); 1.618 + printExpr(tree.selector); 1.619 + print(")"); 1.620 + } 1.621 + print(" {"); 1.622 + println(); 1.623 + printStats(tree.cases); 1.624 + align(); 1.625 + print("}"); 1.626 + } catch (IOException e) { 1.627 + throw new UncheckedIOException(e); 1.628 + } 1.629 + } 1.630 + 1.631 + public void visitCase(JCCase tree) { 1.632 + try { 1.633 + if (tree.pat == null) { 1.634 + print("default"); 1.635 + } else { 1.636 + print("case "); 1.637 + printExpr(tree.pat); 1.638 + } 1.639 + print(": "); 1.640 + println(); 1.641 + indent(); 1.642 + printStats(tree.stats); 1.643 + undent(); 1.644 + align(); 1.645 + } catch (IOException e) { 1.646 + throw new UncheckedIOException(e); 1.647 + } 1.648 + } 1.649 + 1.650 + public void visitSynchronized(JCSynchronized tree) { 1.651 + try { 1.652 + print("synchronized "); 1.653 + if (tree.lock.getTag() == JCTree.PARENS) { 1.654 + printExpr(tree.lock); 1.655 + } else { 1.656 + print("("); 1.657 + printExpr(tree.lock); 1.658 + print(")"); 1.659 + } 1.660 + print(" "); 1.661 + printStat(tree.body); 1.662 + } catch (IOException e) { 1.663 + throw new UncheckedIOException(e); 1.664 + } 1.665 + } 1.666 + 1.667 + public void visitTry(JCTry tree) { 1.668 + try { 1.669 + print("try "); 1.670 + printStat(tree.body); 1.671 + for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { 1.672 + printStat(l.head); 1.673 + } 1.674 + if (tree.finalizer != null) { 1.675 + print(" finally "); 1.676 + printStat(tree.finalizer); 1.677 + } 1.678 + } catch (IOException e) { 1.679 + throw new UncheckedIOException(e); 1.680 + } 1.681 + } 1.682 + 1.683 + public void visitCatch(JCCatch tree) { 1.684 + try { 1.685 + print(" catch ("); 1.686 + printExpr(tree.param); 1.687 + print(") "); 1.688 + printStat(tree.body); 1.689 + } catch (IOException e) { 1.690 + throw new UncheckedIOException(e); 1.691 + } 1.692 + } 1.693 + 1.694 + public void visitConditional(JCConditional tree) { 1.695 + try { 1.696 + open(prec, TreeInfo.condPrec); 1.697 + printExpr(tree.cond, TreeInfo.condPrec); 1.698 + print(" ? "); 1.699 + printExpr(tree.truepart, TreeInfo.condPrec); 1.700 + print(" : "); 1.701 + printExpr(tree.falsepart, TreeInfo.condPrec); 1.702 + close(prec, TreeInfo.condPrec); 1.703 + } catch (IOException e) { 1.704 + throw new UncheckedIOException(e); 1.705 + } 1.706 + } 1.707 + 1.708 + public void visitIf(JCIf tree) { 1.709 + try { 1.710 + print("if "); 1.711 + if (tree.cond.getTag() == JCTree.PARENS) { 1.712 + printExpr(tree.cond); 1.713 + } else { 1.714 + print("("); 1.715 + printExpr(tree.cond); 1.716 + print(")"); 1.717 + } 1.718 + print(" "); 1.719 + printStat(tree.thenpart); 1.720 + if (tree.elsepart != null) { 1.721 + print(" else "); 1.722 + printStat(tree.elsepart); 1.723 + } 1.724 + } catch (IOException e) { 1.725 + throw new UncheckedIOException(e); 1.726 + } 1.727 + } 1.728 + 1.729 + public void visitExec(JCExpressionStatement tree) { 1.730 + try { 1.731 + printExpr(tree.expr); 1.732 + if (prec == TreeInfo.notExpression) print(";"); 1.733 + } catch (IOException e) { 1.734 + throw new UncheckedIOException(e); 1.735 + } 1.736 + } 1.737 + 1.738 + public void visitBreak(JCBreak tree) { 1.739 + try { 1.740 + print("break"); 1.741 + if (tree.label != null) print(" " + tree.label); 1.742 + print(";"); 1.743 + } catch (IOException e) { 1.744 + throw new UncheckedIOException(e); 1.745 + } 1.746 + } 1.747 + 1.748 + public void visitContinue(JCContinue tree) { 1.749 + try { 1.750 + print("continue"); 1.751 + if (tree.label != null) print(" " + tree.label); 1.752 + print(";"); 1.753 + } catch (IOException e) { 1.754 + throw new UncheckedIOException(e); 1.755 + } 1.756 + } 1.757 + 1.758 + public void visitReturn(JCReturn tree) { 1.759 + try { 1.760 + print("return"); 1.761 + if (tree.expr != null) { 1.762 + print(" "); 1.763 + printExpr(tree.expr); 1.764 + } 1.765 + print(";"); 1.766 + } catch (IOException e) { 1.767 + throw new UncheckedIOException(e); 1.768 + } 1.769 + } 1.770 + 1.771 + public void visitThrow(JCThrow tree) { 1.772 + try { 1.773 + print("throw "); 1.774 + printExpr(tree.expr); 1.775 + print(";"); 1.776 + } catch (IOException e) { 1.777 + throw new UncheckedIOException(e); 1.778 + } 1.779 + } 1.780 + 1.781 + public void visitAssert(JCAssert tree) { 1.782 + try { 1.783 + print("assert "); 1.784 + printExpr(tree.cond); 1.785 + if (tree.detail != null) { 1.786 + print(" : "); 1.787 + printExpr(tree.detail); 1.788 + } 1.789 + print(";"); 1.790 + } catch (IOException e) { 1.791 + throw new UncheckedIOException(e); 1.792 + } 1.793 + } 1.794 + 1.795 + public void visitApply(JCMethodInvocation tree) { 1.796 + try { 1.797 + if (!tree.typeargs.isEmpty()) { 1.798 + if (tree.meth.getTag() == JCTree.SELECT) { 1.799 + JCFieldAccess left = (JCFieldAccess)tree.meth; 1.800 + printExpr(left.selected); 1.801 + print(".<"); 1.802 + printExprs(tree.typeargs); 1.803 + print(">" + left.name); 1.804 + } else { 1.805 + print("<"); 1.806 + printExprs(tree.typeargs); 1.807 + print(">"); 1.808 + printExpr(tree.meth); 1.809 + } 1.810 + } else { 1.811 + printExpr(tree.meth); 1.812 + } 1.813 + print("("); 1.814 + printExprs(tree.args); 1.815 + print(")"); 1.816 + } catch (IOException e) { 1.817 + throw new UncheckedIOException(e); 1.818 + } 1.819 + } 1.820 + 1.821 + public void visitNewClass(JCNewClass tree) { 1.822 + try { 1.823 + if (tree.encl != null) { 1.824 + printExpr(tree.encl); 1.825 + print("."); 1.826 + } 1.827 + print("new "); 1.828 + if (!tree.typeargs.isEmpty()) { 1.829 + print("<"); 1.830 + printExprs(tree.typeargs); 1.831 + print(">"); 1.832 + } 1.833 + printExpr(tree.clazz); 1.834 + print("("); 1.835 + printExprs(tree.args); 1.836 + print(")"); 1.837 + if (tree.def != null) { 1.838 + Name enclClassNamePrev = enclClassName; 1.839 + enclClassName = 1.840 + tree.def.name != null ? tree.def.name : 1.841 + tree.type != null && tree.type.tsym.name != tree.type.tsym.name.table.empty ? tree.type.tsym.name : 1.842 + null; 1.843 + if ((tree.def.mods.flags & Flags.ENUM) != 0) print("/*enum*/"); 1.844 + printBlock(tree.def.defs); 1.845 + enclClassName = enclClassNamePrev; 1.846 + } 1.847 + } catch (IOException e) { 1.848 + throw new UncheckedIOException(e); 1.849 + } 1.850 + } 1.851 + 1.852 + public void visitNewArray(JCNewArray tree) { 1.853 + try { 1.854 + if (tree.elemtype != null) { 1.855 + print("new "); 1.856 + JCTree elem = tree.elemtype; 1.857 + if (elem instanceof JCArrayTypeTree) 1.858 + printBaseElementType((JCArrayTypeTree) elem); 1.859 + else 1.860 + printExpr(elem); 1.861 + for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) { 1.862 + print("["); 1.863 + printExpr(l.head); 1.864 + print("]"); 1.865 + } 1.866 + if (elem instanceof JCArrayTypeTree) 1.867 + printBrackets((JCArrayTypeTree) elem); 1.868 + } 1.869 + if (tree.elems != null) { 1.870 + if (tree.elemtype != null) print("[]"); 1.871 + print("{"); 1.872 + printExprs(tree.elems); 1.873 + print("}"); 1.874 + } 1.875 + } catch (IOException e) { 1.876 + throw new UncheckedIOException(e); 1.877 + } 1.878 + } 1.879 + 1.880 + public void visitParens(JCParens tree) { 1.881 + try { 1.882 + print("("); 1.883 + printExpr(tree.expr); 1.884 + print(")"); 1.885 + } catch (IOException e) { 1.886 + throw new UncheckedIOException(e); 1.887 + } 1.888 + } 1.889 + 1.890 + public void visitAssign(JCAssign tree) { 1.891 + try { 1.892 + open(prec, TreeInfo.assignPrec); 1.893 + printExpr(tree.lhs, TreeInfo.assignPrec + 1); 1.894 + print(" = "); 1.895 + printExpr(tree.rhs, TreeInfo.assignPrec); 1.896 + close(prec, TreeInfo.assignPrec); 1.897 + } catch (IOException e) { 1.898 + throw new UncheckedIOException(e); 1.899 + } 1.900 + } 1.901 + 1.902 + public String operatorName(int tag) { 1.903 + switch(tag) { 1.904 + case JCTree.POS: return "+"; 1.905 + case JCTree.NEG: return "-"; 1.906 + case JCTree.NOT: return "!"; 1.907 + case JCTree.COMPL: return "~"; 1.908 + case JCTree.PREINC: return "++"; 1.909 + case JCTree.PREDEC: return "--"; 1.910 + case JCTree.POSTINC: return "++"; 1.911 + case JCTree.POSTDEC: return "--"; 1.912 + case JCTree.NULLCHK: return "<*nullchk*>"; 1.913 + case JCTree.OR: return "||"; 1.914 + case JCTree.AND: return "&&"; 1.915 + case JCTree.EQ: return "=="; 1.916 + case JCTree.NE: return "!="; 1.917 + case JCTree.LT: return "<"; 1.918 + case JCTree.GT: return ">"; 1.919 + case JCTree.LE: return "<="; 1.920 + case JCTree.GE: return ">="; 1.921 + case JCTree.BITOR: return "|"; 1.922 + case JCTree.BITXOR: return "^"; 1.923 + case JCTree.BITAND: return "&"; 1.924 + case JCTree.SL: return "<<"; 1.925 + case JCTree.SR: return ">>"; 1.926 + case JCTree.USR: return ">>>"; 1.927 + case JCTree.PLUS: return "+"; 1.928 + case JCTree.MINUS: return "-"; 1.929 + case JCTree.MUL: return "*"; 1.930 + case JCTree.DIV: return "/"; 1.931 + case JCTree.MOD: return "%"; 1.932 + default: throw new Error(); 1.933 + } 1.934 + } 1.935 + 1.936 + public void visitAssignop(JCAssignOp tree) { 1.937 + try { 1.938 + open(prec, TreeInfo.assignopPrec); 1.939 + printExpr(tree.lhs, TreeInfo.assignopPrec + 1); 1.940 + print(" " + operatorName(tree.getTag() - JCTree.ASGOffset) + "= "); 1.941 + printExpr(tree.rhs, TreeInfo.assignopPrec); 1.942 + close(prec, TreeInfo.assignopPrec); 1.943 + } catch (IOException e) { 1.944 + throw new UncheckedIOException(e); 1.945 + } 1.946 + } 1.947 + 1.948 + public void visitUnary(JCUnary tree) { 1.949 + try { 1.950 + int ownprec = TreeInfo.opPrec(tree.getTag()); 1.951 + String opname = operatorName(tree.getTag()); 1.952 + open(prec, ownprec); 1.953 + if (tree.getTag() <= JCTree.PREDEC) { 1.954 + print(opname); 1.955 + printExpr(tree.arg, ownprec); 1.956 + } else { 1.957 + printExpr(tree.arg, ownprec); 1.958 + print(opname); 1.959 + } 1.960 + close(prec, ownprec); 1.961 + } catch (IOException e) { 1.962 + throw new UncheckedIOException(e); 1.963 + } 1.964 + } 1.965 + 1.966 + public void visitBinary(JCBinary tree) { 1.967 + try { 1.968 + int ownprec = TreeInfo.opPrec(tree.getTag()); 1.969 + String opname = operatorName(tree.getTag()); 1.970 + open(prec, ownprec); 1.971 + printExpr(tree.lhs, ownprec); 1.972 + print(" " + opname + " "); 1.973 + printExpr(tree.rhs, ownprec + 1); 1.974 + close(prec, ownprec); 1.975 + } catch (IOException e) { 1.976 + throw new UncheckedIOException(e); 1.977 + } 1.978 + } 1.979 + 1.980 + public void visitTypeCast(JCTypeCast tree) { 1.981 + try { 1.982 + open(prec, TreeInfo.prefixPrec); 1.983 + print("("); 1.984 + printExpr(tree.clazz); 1.985 + print(")"); 1.986 + printExpr(tree.expr, TreeInfo.prefixPrec); 1.987 + close(prec, TreeInfo.prefixPrec); 1.988 + } catch (IOException e) { 1.989 + throw new UncheckedIOException(e); 1.990 + } 1.991 + } 1.992 + 1.993 + public void visitTypeTest(JCInstanceOf tree) { 1.994 + try { 1.995 + open(prec, TreeInfo.ordPrec); 1.996 + printExpr(tree.expr, TreeInfo.ordPrec); 1.997 + print(" instanceof "); 1.998 + printExpr(tree.clazz, TreeInfo.ordPrec + 1); 1.999 + close(prec, TreeInfo.ordPrec); 1.1000 + } catch (IOException e) { 1.1001 + throw new UncheckedIOException(e); 1.1002 + } 1.1003 + } 1.1004 + 1.1005 + public void visitIndexed(JCArrayAccess tree) { 1.1006 + try { 1.1007 + printExpr(tree.indexed, TreeInfo.postfixPrec); 1.1008 + print("["); 1.1009 + printExpr(tree.index); 1.1010 + print("]"); 1.1011 + } catch (IOException e) { 1.1012 + throw new UncheckedIOException(e); 1.1013 + } 1.1014 + } 1.1015 + 1.1016 + public void visitSelect(JCFieldAccess tree) { 1.1017 + try { 1.1018 + printExpr(tree.selected, TreeInfo.postfixPrec); 1.1019 + print("." + tree.name); 1.1020 + } catch (IOException e) { 1.1021 + throw new UncheckedIOException(e); 1.1022 + } 1.1023 + } 1.1024 + 1.1025 + public void visitIdent(JCIdent tree) { 1.1026 + try { 1.1027 + print(tree.name); 1.1028 + } catch (IOException e) { 1.1029 + throw new UncheckedIOException(e); 1.1030 + } 1.1031 + } 1.1032 + 1.1033 + public void visitLiteral(JCLiteral tree) { 1.1034 + try { 1.1035 + switch (tree.typetag) { 1.1036 + case TypeTags.INT: 1.1037 + print(tree.value.toString()); 1.1038 + break; 1.1039 + case TypeTags.LONG: 1.1040 + print(tree.value + "L"); 1.1041 + break; 1.1042 + case TypeTags.FLOAT: 1.1043 + print(tree.value + "F"); 1.1044 + break; 1.1045 + case TypeTags.DOUBLE: 1.1046 + print(tree.value.toString()); 1.1047 + break; 1.1048 + case TypeTags.CHAR: 1.1049 + print("\'" + 1.1050 + Convert.quote( 1.1051 + String.valueOf((char)((Number)tree.value).intValue())) + 1.1052 + "\'"); 1.1053 + break; 1.1054 + case TypeTags.BOOLEAN: 1.1055 + print(((Number)tree.value).intValue() == 1 ? "true" : "false"); 1.1056 + break; 1.1057 + case TypeTags.BOT: 1.1058 + print("null"); 1.1059 + break; 1.1060 + default: 1.1061 + print("\"" + Convert.quote(tree.value.toString()) + "\""); 1.1062 + break; 1.1063 + } 1.1064 + } catch (IOException e) { 1.1065 + throw new UncheckedIOException(e); 1.1066 + } 1.1067 + } 1.1068 + 1.1069 + public void visitTypeIdent(JCPrimitiveTypeTree tree) { 1.1070 + try { 1.1071 + switch(tree.typetag) { 1.1072 + case TypeTags.BYTE: 1.1073 + print("byte"); 1.1074 + break; 1.1075 + case TypeTags.CHAR: 1.1076 + print("char"); 1.1077 + break; 1.1078 + case TypeTags.SHORT: 1.1079 + print("short"); 1.1080 + break; 1.1081 + case TypeTags.INT: 1.1082 + print("int"); 1.1083 + break; 1.1084 + case TypeTags.LONG: 1.1085 + print("long"); 1.1086 + break; 1.1087 + case TypeTags.FLOAT: 1.1088 + print("float"); 1.1089 + break; 1.1090 + case TypeTags.DOUBLE: 1.1091 + print("double"); 1.1092 + break; 1.1093 + case TypeTags.BOOLEAN: 1.1094 + print("boolean"); 1.1095 + break; 1.1096 + case TypeTags.VOID: 1.1097 + print("void"); 1.1098 + break; 1.1099 + default: 1.1100 + print("error"); 1.1101 + break; 1.1102 + } 1.1103 + } catch (IOException e) { 1.1104 + throw new UncheckedIOException(e); 1.1105 + } 1.1106 + } 1.1107 + 1.1108 + public void visitTypeArray(JCArrayTypeTree tree) { 1.1109 + try { 1.1110 + printBaseElementType(tree); 1.1111 + printBrackets(tree); 1.1112 + } catch (IOException e) { 1.1113 + throw new UncheckedIOException(e); 1.1114 + } 1.1115 + } 1.1116 + 1.1117 + // Prints the inner element type of a nested array 1.1118 + private void printBaseElementType(JCArrayTypeTree tree) throws IOException { 1.1119 + JCTree elem = tree.elemtype; 1.1120 + while (elem instanceof JCWildcard) 1.1121 + elem = ((JCWildcard) elem).inner; 1.1122 + if (elem instanceof JCArrayTypeTree) 1.1123 + printBaseElementType((JCArrayTypeTree) elem); 1.1124 + else 1.1125 + printExpr(elem); 1.1126 + } 1.1127 + 1.1128 + // prints the brackets of a nested array in reverse order 1.1129 + private void printBrackets(JCArrayTypeTree tree) throws IOException { 1.1130 + JCTree elem; 1.1131 + while (true) { 1.1132 + elem = tree.elemtype; 1.1133 + print("[]"); 1.1134 + if (!(elem instanceof JCArrayTypeTree)) break; 1.1135 + tree = (JCArrayTypeTree) elem; 1.1136 + } 1.1137 + } 1.1138 + 1.1139 + public void visitTypeApply(JCTypeApply tree) { 1.1140 + try { 1.1141 + printExpr(tree.clazz); 1.1142 + print("<"); 1.1143 + printExprs(tree.arguments); 1.1144 + print(">"); 1.1145 + } catch (IOException e) { 1.1146 + throw new UncheckedIOException(e); 1.1147 + } 1.1148 + } 1.1149 + 1.1150 + public void visitTypeParameter(JCTypeParameter tree) { 1.1151 + try { 1.1152 + print(tree.name); 1.1153 + if (tree.bounds.nonEmpty()) { 1.1154 + print(" extends "); 1.1155 + printExprs(tree.bounds, " & "); 1.1156 + } 1.1157 + } catch (IOException e) { 1.1158 + throw new UncheckedIOException(e); 1.1159 + } 1.1160 + } 1.1161 + 1.1162 + @Override 1.1163 + public void visitWildcard(JCWildcard tree) { 1.1164 + try { 1.1165 + print(tree.kind); 1.1166 + if (tree.kind.kind != BoundKind.UNBOUND) 1.1167 + printExpr(tree.inner); 1.1168 + } catch (IOException e) { 1.1169 + throw new UncheckedIOException(e); 1.1170 + } 1.1171 + } 1.1172 + 1.1173 + @Override 1.1174 + public void visitTypeBoundKind(TypeBoundKind tree) { 1.1175 + try { 1.1176 + print(String.valueOf(tree.kind)); 1.1177 + } catch (IOException e) { 1.1178 + throw new UncheckedIOException(e); 1.1179 + } 1.1180 + } 1.1181 + 1.1182 + public void visitErroneous(JCErroneous tree) { 1.1183 + try { 1.1184 + print("(ERROR)"); 1.1185 + } catch (IOException e) { 1.1186 + throw new UncheckedIOException(e); 1.1187 + } 1.1188 + } 1.1189 + 1.1190 + public void visitLetExpr(LetExpr tree) { 1.1191 + try { 1.1192 + print("(let " + tree.defs + " in " + tree.expr + ")"); 1.1193 + } catch (IOException e) { 1.1194 + throw new UncheckedIOException(e); 1.1195 + } 1.1196 + } 1.1197 + 1.1198 + public void visitModifiers(JCModifiers mods) { 1.1199 + try { 1.1200 + printAnnotations(mods.annotations); 1.1201 + printFlags(mods.flags); 1.1202 + } catch (IOException e) { 1.1203 + throw new UncheckedIOException(e); 1.1204 + } 1.1205 + } 1.1206 + 1.1207 + public void visitAnnotation(JCAnnotation tree) { 1.1208 + try { 1.1209 + print("@"); 1.1210 + printExpr(tree.annotationType); 1.1211 + print("("); 1.1212 + printExprs(tree.args); 1.1213 + print(")"); 1.1214 + } catch (IOException e) { 1.1215 + throw new UncheckedIOException(e); 1.1216 + } 1.1217 + } 1.1218 + 1.1219 + public void visitTree(JCTree tree) { 1.1220 + try { 1.1221 + print("(UNKNOWN: " + tree + ")"); 1.1222 + println(); 1.1223 + } catch (IOException e) { 1.1224 + throw new UncheckedIOException(e); 1.1225 + } 1.1226 + } 1.1227 +}