0001: /*
0002: * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025:
0026: package com.sun.tools.javac.tree;
0027:
0028: import java.io.*;
0029: import java.util.*;
0030:
0031: import com.sun.tools.javac.util.*;
0032: import com.sun.tools.javac.util.List;
0033: import com.sun.tools.javac.code.*;
0034:
0035: import com.sun.tools.javac.code.Symbol.*;
0036: import com.sun.tools.javac.tree.JCTree.*;
0037:
0038: import static com.sun.tools.javac.code.Flags.*;
0039:
0040: /** Prints out a tree as an indented Java source program.
0041: *
0042: * <p><b>This is NOT part of any API supported by Sun Microsystems. If
0043: * you write code that depends on this, you do so at your own risk.
0044: * This code and its internal interfaces are subject to change or
0045: * deletion without notice.</b>
0046: */
0047: @Version("@(#)Pretty.java 1.76 07/06/14")
0048: public class Pretty extends JCTree.Visitor {
0049:
0050: public Pretty(Writer out, boolean sourceOutput) {
0051: this .out = out;
0052: this .sourceOutput = sourceOutput;
0053: }
0054:
0055: /** Set when we are producing source output. If we're not
0056: * producing source output, we can sometimes give more detail in
0057: * the output even though that detail would not be valid java
0058: * soruce.
0059: */
0060: private final boolean sourceOutput;
0061:
0062: /** The output stream on which trees are printed.
0063: */
0064: Writer out;
0065:
0066: /** Indentation width (can be reassigned from outside).
0067: */
0068: public int width = 4;
0069:
0070: /** The current left margin.
0071: */
0072: int lmargin = 0;
0073:
0074: /** The enclosing class name.
0075: */
0076: Name enclClassName;
0077:
0078: /** A hashtable mapping trees to their documentation comments
0079: * (can be null)
0080: */
0081: Map<JCTree, String> docComments = null;
0082:
0083: /** Align code to be indented to left margin.
0084: */
0085: void align() throws IOException {
0086: for (int i = 0; i < lmargin; i++)
0087: out.write(" ");
0088: }
0089:
0090: /** Increase left margin by indentation width.
0091: */
0092: void indent() {
0093: lmargin = lmargin + width;
0094: }
0095:
0096: /** Decrease left margin by indentation width.
0097: */
0098: void undent() {
0099: lmargin = lmargin - width;
0100: }
0101:
0102: /** Enter a new precedence level. Emit a `(' if new precedence level
0103: * is less than precedence level so far.
0104: * @param contextPrec The precedence level in force so far.
0105: * @param ownPrec The new precedence level.
0106: */
0107: void open(int contextPrec, int ownPrec) throws IOException {
0108: if (ownPrec < contextPrec)
0109: out.write("(");
0110: }
0111:
0112: /** Leave precedence level. Emit a `(' if inner precedence level
0113: * is less than precedence level we revert to.
0114: * @param contextPrec The precedence level we revert to.
0115: * @param ownPrec The inner precedence level.
0116: */
0117: void close(int contextPrec, int ownPrec) throws IOException {
0118: if (ownPrec < contextPrec)
0119: out.write(")");
0120: }
0121:
0122: /** Print string, replacing all non-ascii character with unicode escapes.
0123: */
0124: public void print(Object s) throws IOException {
0125: out.write(Convert.escapeUnicode(s.toString()));
0126: }
0127:
0128: /** Print new line.
0129: */
0130: public void println() throws IOException {
0131: out.write(lineSep);
0132: }
0133:
0134: String lineSep = System.getProperty("line.separator");
0135:
0136: /**************************************************************************
0137: * Traversal methods
0138: *************************************************************************/
0139:
0140: /** Exception to propogate IOException through visitXXX methods */
0141: private static class UncheckedIOException extends Error {
0142: static final long serialVersionUID = -4032692679158424751L;
0143:
0144: UncheckedIOException(IOException e) {
0145: super (e.getMessage(), e);
0146: }
0147: }
0148:
0149: /** Visitor argument: the current precedence level.
0150: */
0151: int prec;
0152:
0153: /** Visitor method: print expression tree.
0154: * @param prec The current precedence level.
0155: */
0156: public void printExpr(JCTree tree, int prec) throws IOException {
0157: int prevPrec = this .prec;
0158: try {
0159: this .prec = prec;
0160: if (tree == null)
0161: print("/*missing*/");
0162: else {
0163: tree.accept(this );
0164: }
0165: } catch (UncheckedIOException ex) {
0166: IOException e = new IOException(ex.getMessage());
0167: e.initCause(ex);
0168: throw e;
0169: } finally {
0170: this .prec = prevPrec;
0171: }
0172: }
0173:
0174: /** Derived visitor method: print expression tree at minimum precedence level
0175: * for expression.
0176: */
0177: public void printExpr(JCTree tree) throws IOException {
0178: printExpr(tree, TreeInfo.noPrec);
0179: }
0180:
0181: /** Derived visitor method: print statement tree.
0182: */
0183: public void printStat(JCTree tree) throws IOException {
0184: printExpr(tree, TreeInfo.notExpression);
0185: }
0186:
0187: /** Derived visitor method: print list of expression trees, separated by given string.
0188: * @param sep the separator string
0189: */
0190: public <T extends JCTree> void printExprs(List<T> trees, String sep)
0191: throws IOException {
0192: if (trees.nonEmpty()) {
0193: printExpr(trees.head);
0194: for (List<T> l = trees.tail; l.nonEmpty(); l = l.tail) {
0195: print(sep);
0196: printExpr(l.head);
0197: }
0198: }
0199: }
0200:
0201: /** Derived visitor method: print list of expression trees, separated by commas.
0202: */
0203: public <T extends JCTree> void printExprs(List<T> trees)
0204: throws IOException {
0205: printExprs(trees, ", ");
0206: }
0207:
0208: /** Derived visitor method: print list of statements, each on a separate line.
0209: */
0210: public void printStats(List<? extends JCTree> trees)
0211: throws IOException {
0212: for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) {
0213: align();
0214: printStat(l.head);
0215: println();
0216: }
0217: }
0218:
0219: /** Print a set of modifiers.
0220: */
0221: public void printFlags(long flags) throws IOException {
0222: if ((flags & SYNTHETIC) != 0)
0223: print("/*synthetic*/ ");
0224: print(TreeInfo.flagNames(flags));
0225: if ((flags & StandardFlags) != 0)
0226: print(" ");
0227: if ((flags & ANNOTATION) != 0)
0228: print("@");
0229: }
0230:
0231: public void printAnnotations(List<JCAnnotation> trees)
0232: throws IOException {
0233: for (List<JCAnnotation> l = trees; l.nonEmpty(); l = l.tail) {
0234: printStat(l.head);
0235: println();
0236: align();
0237: }
0238: }
0239:
0240: /** Print documentation comment, if it exists
0241: * @param tree The tree for which a documentation comment should be printed.
0242: */
0243: public void printDocComment(JCTree tree) throws IOException {
0244: if (docComments != null) {
0245: String dc = docComments.get(tree);
0246: if (dc != null) {
0247: print("/**");
0248: println();
0249: int pos = 0;
0250: int endpos = lineEndPos(dc, pos);
0251: while (pos < dc.length()) {
0252: align();
0253: print(" *");
0254: if (pos < dc.length() && dc.charAt(pos) > ' ')
0255: print(" ");
0256: print(dc.substring(pos, endpos));
0257: println();
0258: pos = endpos + 1;
0259: endpos = lineEndPos(dc, pos);
0260: }
0261: align();
0262: print(" */");
0263: println();
0264: align();
0265: }
0266: }
0267: }
0268:
0269: //where
0270: static int lineEndPos(String s, int start) {
0271: int pos = s.indexOf('\n', start);
0272: if (pos < 0)
0273: pos = s.length();
0274: return pos;
0275: }
0276:
0277: /** If type parameter list is non-empty, print it enclosed in "<...>" brackets.
0278: */
0279: public void printTypeParameters(List<JCTypeParameter> trees)
0280: throws IOException {
0281: if (trees.nonEmpty()) {
0282: print("<");
0283: printExprs(trees);
0284: print(">");
0285: }
0286: }
0287:
0288: /** Print a block.
0289: */
0290: public void printBlock(List<? extends JCTree> stats)
0291: throws IOException {
0292: print("{");
0293: println();
0294: indent();
0295: printStats(stats);
0296: undent();
0297: align();
0298: print("}");
0299: }
0300:
0301: /** Print a block.
0302: */
0303: public void printEnumBody(List<JCTree> stats) throws IOException {
0304: print("{");
0305: println();
0306: indent();
0307: boolean first = true;
0308: for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) {
0309: if (isEnumerator(l.head)) {
0310: if (!first) {
0311: print(",");
0312: println();
0313: }
0314: align();
0315: printStat(l.head);
0316: first = false;
0317: }
0318: }
0319: print(";");
0320: println();
0321: for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) {
0322: if (!isEnumerator(l.head)) {
0323: align();
0324: printStat(l.head);
0325: println();
0326: }
0327: }
0328: undent();
0329: align();
0330: print("}");
0331: }
0332:
0333: /** Is the given tree an enumerator definition? */
0334: boolean isEnumerator(JCTree t) {
0335: return t.getTag() == JCTree.VARDEF
0336: && (((JCVariableDecl) t).mods.flags & ENUM) != 0;
0337: }
0338:
0339: /** Print unit consisting of package clause and import statements in toplevel,
0340: * followed by class definition. if class definition == null,
0341: * print all definitions in toplevel.
0342: * @param tree The toplevel tree
0343: * @param cdef The class definition, which is assumed to be part of the
0344: * toplevel tree.
0345: */
0346: public void printUnit(JCCompilationUnit tree, JCClassDecl cdef)
0347: throws IOException {
0348: docComments = tree.docComments;
0349: printDocComment(tree);
0350: if (tree.pid != null) {
0351: print("package ");
0352: printExpr(tree.pid);
0353: print(";");
0354: println();
0355: }
0356: boolean firstImport = true;
0357: for (List<JCTree> l = tree.defs; l.nonEmpty()
0358: && (cdef == null || l.head.getTag() == JCTree.IMPORT); l = l.tail) {
0359: if (l.head.getTag() == JCTree.IMPORT) {
0360: JCImport imp = (JCImport) l.head;
0361: Name name = TreeInfo.name(imp.qualid);
0362: if (name == name.table.asterisk || cdef == null
0363: || isUsed(TreeInfo.symbol(imp.qualid), cdef)) {
0364: if (firstImport) {
0365: firstImport = false;
0366: println();
0367: }
0368: printStat(imp);
0369: }
0370: } else {
0371: printStat(l.head);
0372: }
0373: }
0374: if (cdef != null) {
0375: printStat(cdef);
0376: println();
0377: }
0378: }
0379:
0380: // where
0381: boolean isUsed(final Symbol t, JCTree cdef) {
0382: class UsedVisitor extends TreeScanner {
0383: public void scan(JCTree tree) {
0384: if (tree != null && !result)
0385: tree.accept(this );
0386: }
0387:
0388: boolean result = false;
0389:
0390: public void visitIdent(JCIdent tree) {
0391: if (tree.sym == t)
0392: result = true;
0393: }
0394: }
0395: UsedVisitor v = new UsedVisitor();
0396: v.scan(cdef);
0397: return v.result;
0398: }
0399:
0400: /**************************************************************************
0401: * Visitor methods
0402: *************************************************************************/
0403:
0404: public void visitTopLevel(JCCompilationUnit tree) {
0405: try {
0406: printUnit(tree, null);
0407: } catch (IOException e) {
0408: throw new UncheckedIOException(e);
0409: }
0410: }
0411:
0412: public void visitImport(JCImport tree) {
0413: try {
0414: print("import ");
0415: if (tree.staticImport)
0416: print("static ");
0417: printExpr(tree.qualid);
0418: print(";");
0419: println();
0420: } catch (IOException e) {
0421: throw new UncheckedIOException(e);
0422: }
0423: }
0424:
0425: public void visitClassDef(JCClassDecl tree) {
0426: try {
0427: println();
0428: align();
0429: printDocComment(tree);
0430: printAnnotations(tree.mods.annotations);
0431: printFlags(tree.mods.flags & ~INTERFACE);
0432: Name enclClassNamePrev = enclClassName;
0433: enclClassName = tree.name;
0434: if ((tree.mods.flags & INTERFACE) != 0) {
0435: print("interface " + tree.name);
0436: printTypeParameters(tree.typarams);
0437: if (tree.implementing.nonEmpty()) {
0438: print(" extends ");
0439: printExprs(tree.implementing);
0440: }
0441: } else {
0442: if ((tree.mods.flags & ENUM) != 0)
0443: print("enum " + tree.name);
0444: else
0445: print("class " + tree.name);
0446: printTypeParameters(tree.typarams);
0447: if (tree.extending != null) {
0448: print(" extends ");
0449: printExpr(tree.extending);
0450: }
0451: if (tree.implementing.nonEmpty()) {
0452: print(" implements ");
0453: printExprs(tree.implementing);
0454: }
0455: }
0456: print(" ");
0457: if ((tree.mods.flags & ENUM) != 0) {
0458: printEnumBody(tree.defs);
0459: } else {
0460: printBlock(tree.defs);
0461: }
0462: enclClassName = enclClassNamePrev;
0463: } catch (IOException e) {
0464: throw new UncheckedIOException(e);
0465: }
0466: }
0467:
0468: public void visitMethodDef(JCMethodDecl tree) {
0469: try {
0470: // when producing source output, omit anonymous constructors
0471: if (tree.name == tree.name.table.init
0472: && enclClassName == null && sourceOutput)
0473: return;
0474: println();
0475: align();
0476: printDocComment(tree);
0477: printExpr(tree.mods);
0478: printTypeParameters(tree.typarams);
0479: if (tree.name == tree.name.table.init) {
0480: print(enclClassName != null ? enclClassName : tree.name);
0481: } else {
0482: printExpr(tree.restype);
0483: print(" " + tree.name);
0484: }
0485: print("(");
0486: printExprs(tree.params);
0487: print(")");
0488: if (tree.thrown.nonEmpty()) {
0489: print(" throws ");
0490: printExprs(tree.thrown);
0491: }
0492: if (tree.body != null) {
0493: print(" ");
0494: printStat(tree.body);
0495: } else {
0496: print(";");
0497: }
0498: } catch (IOException e) {
0499: throw new UncheckedIOException(e);
0500: }
0501: }
0502:
0503: public void visitVarDef(JCVariableDecl tree) {
0504: try {
0505: if (docComments != null && docComments.get(tree) != null) {
0506: println();
0507: align();
0508: }
0509: printDocComment(tree);
0510: if ((tree.mods.flags & ENUM) != 0) {
0511: print("/*public static final*/ ");
0512: print(tree.name);
0513: if (tree.init != null) {
0514: print(" /* = ");
0515: printExpr(tree.init);
0516: print(" */");
0517: }
0518: } else {
0519: printExpr(tree.mods);
0520: if ((tree.mods.flags & VARARGS) != 0) {
0521: printExpr(((JCArrayTypeTree) tree.vartype).elemtype);
0522: print("... " + tree.name);
0523: } else {
0524: printExpr(tree.vartype);
0525: print(" " + tree.name);
0526: }
0527: if (tree.init != null) {
0528: print(" = ");
0529: printExpr(tree.init);
0530: }
0531: if (prec == TreeInfo.notExpression)
0532: print(";");
0533: }
0534: } catch (IOException e) {
0535: throw new UncheckedIOException(e);
0536: }
0537: }
0538:
0539: public void visitSkip(JCSkip tree) {
0540: try {
0541: print(";");
0542: } catch (IOException e) {
0543: throw new UncheckedIOException(e);
0544: }
0545: }
0546:
0547: public void visitBlock(JCBlock tree) {
0548: try {
0549: printFlags(tree.flags);
0550: printBlock(tree.stats);
0551: } catch (IOException e) {
0552: throw new UncheckedIOException(e);
0553: }
0554: }
0555:
0556: public void visitDoLoop(JCDoWhileLoop tree) {
0557: try {
0558: print("do ");
0559: printStat(tree.body);
0560: align();
0561: print(" while ");
0562: if (tree.cond.getTag() == JCTree.PARENS) {
0563: printExpr(tree.cond);
0564: } else {
0565: print("(");
0566: printExpr(tree.cond);
0567: print(")");
0568: }
0569: print(";");
0570: } catch (IOException e) {
0571: throw new UncheckedIOException(e);
0572: }
0573: }
0574:
0575: public void visitWhileLoop(JCWhileLoop tree) {
0576: try {
0577: print("while ");
0578: if (tree.cond.getTag() == JCTree.PARENS) {
0579: printExpr(tree.cond);
0580: } else {
0581: print("(");
0582: printExpr(tree.cond);
0583: print(")");
0584: }
0585: print(" ");
0586: printStat(tree.body);
0587: } catch (IOException e) {
0588: throw new UncheckedIOException(e);
0589: }
0590: }
0591:
0592: public void visitForLoop(JCForLoop tree) {
0593: try {
0594: print("for (");
0595: if (tree.init.nonEmpty()) {
0596: if (tree.init.head.getTag() == JCTree.VARDEF) {
0597: printExpr(tree.init.head);
0598: for (List<JCStatement> l = tree.init.tail; l
0599: .nonEmpty(); l = l.tail) {
0600: JCVariableDecl vdef = (JCVariableDecl) l.head;
0601: print(", " + vdef.name + " = ");
0602: printExpr(vdef.init);
0603: }
0604: } else {
0605: printExprs(tree.init);
0606: }
0607: }
0608: print("; ");
0609: if (tree.cond != null)
0610: printExpr(tree.cond);
0611: print("; ");
0612: printExprs(tree.step);
0613: print(") ");
0614: printStat(tree.body);
0615: } catch (IOException e) {
0616: throw new UncheckedIOException(e);
0617: }
0618: }
0619:
0620: public void visitForeachLoop(JCEnhancedForLoop tree) {
0621: try {
0622: print("for (");
0623: printExpr(tree.var);
0624: print(" : ");
0625: printExpr(tree.expr);
0626: print(") ");
0627: printStat(tree.body);
0628: } catch (IOException e) {
0629: throw new UncheckedIOException(e);
0630: }
0631: }
0632:
0633: public void visitLabelled(JCLabeledStatement tree) {
0634: try {
0635: print(tree.label + ": ");
0636: printStat(tree.body);
0637: } catch (IOException e) {
0638: throw new UncheckedIOException(e);
0639: }
0640: }
0641:
0642: public void visitSwitch(JCSwitch tree) {
0643: try {
0644: print("switch ");
0645: if (tree.selector.getTag() == JCTree.PARENS) {
0646: printExpr(tree.selector);
0647: } else {
0648: print("(");
0649: printExpr(tree.selector);
0650: print(")");
0651: }
0652: print(" {");
0653: println();
0654: printStats(tree.cases);
0655: align();
0656: print("}");
0657: } catch (IOException e) {
0658: throw new UncheckedIOException(e);
0659: }
0660: }
0661:
0662: public void visitCase(JCCase tree) {
0663: try {
0664: if (tree.pat == null) {
0665: print("default");
0666: } else {
0667: print("case ");
0668: printExpr(tree.pat);
0669: }
0670: print(": ");
0671: println();
0672: indent();
0673: printStats(tree.stats);
0674: undent();
0675: align();
0676: } catch (IOException e) {
0677: throw new UncheckedIOException(e);
0678: }
0679: }
0680:
0681: public void visitSynchronized(JCSynchronized tree) {
0682: try {
0683: print("synchronized ");
0684: if (tree.lock.getTag() == JCTree.PARENS) {
0685: printExpr(tree.lock);
0686: } else {
0687: print("(");
0688: printExpr(tree.lock);
0689: print(")");
0690: }
0691: print(" ");
0692: printStat(tree.body);
0693: } catch (IOException e) {
0694: throw new UncheckedIOException(e);
0695: }
0696: }
0697:
0698: public void visitTry(JCTry tree) {
0699: try {
0700: print("try ");
0701: printStat(tree.body);
0702: for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
0703: printStat(l.head);
0704: }
0705: if (tree.finalizer != null) {
0706: print(" finally ");
0707: printStat(tree.finalizer);
0708: }
0709: } catch (IOException e) {
0710: throw new UncheckedIOException(e);
0711: }
0712: }
0713:
0714: public void visitCatch(JCCatch tree) {
0715: try {
0716: print(" catch (");
0717: printExpr(tree.param);
0718: print(") ");
0719: printStat(tree.body);
0720: } catch (IOException e) {
0721: throw new UncheckedIOException(e);
0722: }
0723: }
0724:
0725: public void visitConditional(JCConditional tree) {
0726: try {
0727: open(prec, TreeInfo.condPrec);
0728: printExpr(tree.cond, TreeInfo.condPrec);
0729: print(" ? ");
0730: printExpr(tree.truepart, TreeInfo.condPrec);
0731: print(" : ");
0732: printExpr(tree.falsepart, TreeInfo.condPrec);
0733: close(prec, TreeInfo.condPrec);
0734: } catch (IOException e) {
0735: throw new UncheckedIOException(e);
0736: }
0737: }
0738:
0739: public void visitIf(JCIf tree) {
0740: try {
0741: print("if ");
0742: if (tree.cond.getTag() == JCTree.PARENS) {
0743: printExpr(tree.cond);
0744: } else {
0745: print("(");
0746: printExpr(tree.cond);
0747: print(")");
0748: }
0749: print(" ");
0750: printStat(tree.thenpart);
0751: if (tree.elsepart != null) {
0752: print(" else ");
0753: printStat(tree.elsepart);
0754: }
0755: } catch (IOException e) {
0756: throw new UncheckedIOException(e);
0757: }
0758: }
0759:
0760: public void visitExec(JCExpressionStatement tree) {
0761: try {
0762: printExpr(tree.expr);
0763: if (prec == TreeInfo.notExpression)
0764: print(";");
0765: } catch (IOException e) {
0766: throw new UncheckedIOException(e);
0767: }
0768: }
0769:
0770: public void visitBreak(JCBreak tree) {
0771: try {
0772: print("break");
0773: if (tree.label != null)
0774: print(" " + tree.label);
0775: print(";");
0776: } catch (IOException e) {
0777: throw new UncheckedIOException(e);
0778: }
0779: }
0780:
0781: public void visitContinue(JCContinue tree) {
0782: try {
0783: print("continue");
0784: if (tree.label != null)
0785: print(" " + tree.label);
0786: print(";");
0787: } catch (IOException e) {
0788: throw new UncheckedIOException(e);
0789: }
0790: }
0791:
0792: public void visitReturn(JCReturn tree) {
0793: try {
0794: print("return");
0795: if (tree.expr != null) {
0796: print(" ");
0797: printExpr(tree.expr);
0798: }
0799: print(";");
0800: } catch (IOException e) {
0801: throw new UncheckedIOException(e);
0802: }
0803: }
0804:
0805: public void visitThrow(JCThrow tree) {
0806: try {
0807: print("throw ");
0808: printExpr(tree.expr);
0809: print(";");
0810: } catch (IOException e) {
0811: throw new UncheckedIOException(e);
0812: }
0813: }
0814:
0815: public void visitAssert(JCAssert tree) {
0816: try {
0817: print("assert ");
0818: printExpr(tree.cond);
0819: if (tree.detail != null) {
0820: print(" : ");
0821: printExpr(tree.detail);
0822: }
0823: print(";");
0824: } catch (IOException e) {
0825: throw new UncheckedIOException(e);
0826: }
0827: }
0828:
0829: public void visitApply(JCMethodInvocation tree) {
0830: try {
0831: if (!tree.typeargs.isEmpty()) {
0832: if (tree.meth.getTag() == JCTree.SELECT) {
0833: JCFieldAccess left = (JCFieldAccess) tree.meth;
0834: printExpr(left.selected);
0835: print(".<");
0836: printExprs(tree.typeargs);
0837: print(">" + left.name);
0838: } else {
0839: print("<");
0840: printExprs(tree.typeargs);
0841: print(">");
0842: printExpr(tree.meth);
0843: }
0844: } else {
0845: printExpr(tree.meth);
0846: }
0847: print("(");
0848: printExprs(tree.args);
0849: print(")");
0850: } catch (IOException e) {
0851: throw new UncheckedIOException(e);
0852: }
0853: }
0854:
0855: public void visitNewClass(JCNewClass tree) {
0856: try {
0857: if (tree.encl != null) {
0858: printExpr(tree.encl);
0859: print(".");
0860: }
0861: print("new ");
0862: if (!tree.typeargs.isEmpty()) {
0863: print("<");
0864: printExprs(tree.typeargs);
0865: print(">");
0866: }
0867: printExpr(tree.clazz);
0868: print("(");
0869: printExprs(tree.args);
0870: print(")");
0871: if (tree.def != null) {
0872: Name enclClassNamePrev = enclClassName;
0873: enclClassName = tree.def.name != null ? tree.def.name
0874: : tree.type != null
0875: && tree.type.tsym.name != tree.type.tsym.name.table.empty ? tree.type.tsym.name
0876: : null;
0877: if ((tree.def.mods.flags & Flags.ENUM) != 0)
0878: print("/*enum*/");
0879: printBlock(tree.def.defs);
0880: enclClassName = enclClassNamePrev;
0881: }
0882: } catch (IOException e) {
0883: throw new UncheckedIOException(e);
0884: }
0885: }
0886:
0887: public void visitNewArray(JCNewArray tree) {
0888: try {
0889: if (tree.elemtype != null) {
0890: print("new ");
0891: JCTree elem = tree.elemtype;
0892: if (elem instanceof JCArrayTypeTree)
0893: printBaseElementType((JCArrayTypeTree) elem);
0894: else
0895: printExpr(elem);
0896: for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
0897: print("[");
0898: printExpr(l.head);
0899: print("]");
0900: }
0901: if (elem instanceof JCArrayTypeTree)
0902: printBrackets((JCArrayTypeTree) elem);
0903: }
0904: if (tree.elems != null) {
0905: if (tree.elemtype != null)
0906: print("[]");
0907: print("{");
0908: printExprs(tree.elems);
0909: print("}");
0910: }
0911: } catch (IOException e) {
0912: throw new UncheckedIOException(e);
0913: }
0914: }
0915:
0916: public void visitParens(JCParens tree) {
0917: try {
0918: print("(");
0919: printExpr(tree.expr);
0920: print(")");
0921: } catch (IOException e) {
0922: throw new UncheckedIOException(e);
0923: }
0924: }
0925:
0926: public void visitAssign(JCAssign tree) {
0927: try {
0928: open(prec, TreeInfo.assignPrec);
0929: printExpr(tree.lhs, TreeInfo.assignPrec + 1);
0930: print(" = ");
0931: printExpr(tree.rhs, TreeInfo.assignPrec);
0932: close(prec, TreeInfo.assignPrec);
0933: } catch (IOException e) {
0934: throw new UncheckedIOException(e);
0935: }
0936: }
0937:
0938: public String operatorName(int tag) {
0939: switch (tag) {
0940: case JCTree.POS:
0941: return "+";
0942: case JCTree.NEG:
0943: return "-";
0944: case JCTree.NOT:
0945: return "!";
0946: case JCTree.COMPL:
0947: return "~";
0948: case JCTree.PREINC:
0949: return "++";
0950: case JCTree.PREDEC:
0951: return "--";
0952: case JCTree.POSTINC:
0953: return "++";
0954: case JCTree.POSTDEC:
0955: return "--";
0956: case JCTree.NULLCHK:
0957: return "<*nullchk*>";
0958: case JCTree.OR:
0959: return "||";
0960: case JCTree.AND:
0961: return "&&";
0962: case JCTree.EQ:
0963: return "==";
0964: case JCTree.NE:
0965: return "!=";
0966: case JCTree.LT:
0967: return "<";
0968: case JCTree.GT:
0969: return ">";
0970: case JCTree.LE:
0971: return "<=";
0972: case JCTree.GE:
0973: return ">=";
0974: case JCTree.BITOR:
0975: return "|";
0976: case JCTree.BITXOR:
0977: return "^";
0978: case JCTree.BITAND:
0979: return "&";
0980: case JCTree.SL:
0981: return "<<";
0982: case JCTree.SR:
0983: return ">>";
0984: case JCTree.USR:
0985: return ">>>";
0986: case JCTree.PLUS:
0987: return "+";
0988: case JCTree.MINUS:
0989: return "-";
0990: case JCTree.MUL:
0991: return "*";
0992: case JCTree.DIV:
0993: return "/";
0994: case JCTree.MOD:
0995: return "%";
0996: default:
0997: throw new Error();
0998: }
0999: }
1000:
1001: public void visitAssignop(JCAssignOp tree) {
1002: try {
1003: open(prec, TreeInfo.assignopPrec);
1004: printExpr(tree.lhs, TreeInfo.assignopPrec + 1);
1005: print(" " + operatorName(tree.getTag() - JCTree.ASGOffset)
1006: + "= ");
1007: printExpr(tree.rhs, TreeInfo.assignopPrec);
1008: close(prec, TreeInfo.assignopPrec);
1009: } catch (IOException e) {
1010: throw new UncheckedIOException(e);
1011: }
1012: }
1013:
1014: public void visitUnary(JCUnary tree) {
1015: try {
1016: int ownprec = TreeInfo.opPrec(tree.getTag());
1017: String opname = operatorName(tree.getTag());
1018: open(prec, ownprec);
1019: if (tree.getTag() <= JCTree.PREDEC) {
1020: print(opname);
1021: printExpr(tree.arg, ownprec);
1022: } else {
1023: printExpr(tree.arg, ownprec);
1024: print(opname);
1025: }
1026: close(prec, ownprec);
1027: } catch (IOException e) {
1028: throw new UncheckedIOException(e);
1029: }
1030: }
1031:
1032: public void visitBinary(JCBinary tree) {
1033: try {
1034: int ownprec = TreeInfo.opPrec(tree.getTag());
1035: String opname = operatorName(tree.getTag());
1036: open(prec, ownprec);
1037: printExpr(tree.lhs, ownprec);
1038: print(" " + opname + " ");
1039: printExpr(tree.rhs, ownprec + 1);
1040: close(prec, ownprec);
1041: } catch (IOException e) {
1042: throw new UncheckedIOException(e);
1043: }
1044: }
1045:
1046: public void visitTypeCast(JCTypeCast tree) {
1047: try {
1048: open(prec, TreeInfo.prefixPrec);
1049: print("(");
1050: printExpr(tree.clazz);
1051: print(")");
1052: printExpr(tree.expr, TreeInfo.prefixPrec);
1053: close(prec, TreeInfo.prefixPrec);
1054: } catch (IOException e) {
1055: throw new UncheckedIOException(e);
1056: }
1057: }
1058:
1059: public void visitTypeTest(JCInstanceOf tree) {
1060: try {
1061: open(prec, TreeInfo.ordPrec);
1062: printExpr(tree.expr, TreeInfo.ordPrec);
1063: print(" instanceof ");
1064: printExpr(tree.clazz, TreeInfo.ordPrec + 1);
1065: close(prec, TreeInfo.ordPrec);
1066: } catch (IOException e) {
1067: throw new UncheckedIOException(e);
1068: }
1069: }
1070:
1071: public void visitIndexed(JCArrayAccess tree) {
1072: try {
1073: printExpr(tree.indexed, TreeInfo.postfixPrec);
1074: print("[");
1075: printExpr(tree.index);
1076: print("]");
1077: } catch (IOException e) {
1078: throw new UncheckedIOException(e);
1079: }
1080: }
1081:
1082: public void visitSelect(JCFieldAccess tree) {
1083: try {
1084: printExpr(tree.selected, TreeInfo.postfixPrec);
1085: print("." + tree.name);
1086: } catch (IOException e) {
1087: throw new UncheckedIOException(e);
1088: }
1089: }
1090:
1091: public void visitIdent(JCIdent tree) {
1092: try {
1093: print(tree.name);
1094: } catch (IOException e) {
1095: throw new UncheckedIOException(e);
1096: }
1097: }
1098:
1099: public void visitLiteral(JCLiteral tree) {
1100: try {
1101: switch (tree.typetag) {
1102: case TypeTags.INT:
1103: print(tree.value.toString());
1104: break;
1105: case TypeTags.LONG:
1106: print(tree.value + "L");
1107: break;
1108: case TypeTags.FLOAT:
1109: print(tree.value + "F");
1110: break;
1111: case TypeTags.DOUBLE:
1112: print(tree.value.toString());
1113: break;
1114: case TypeTags.CHAR:
1115: print("\'"
1116: + Convert.quote(String
1117: .valueOf((char) ((Number) tree.value)
1118: .intValue())) + "\'");
1119: break;
1120: case TypeTags.BOOLEAN:
1121: print(((Number) tree.value).intValue() == 1 ? "true"
1122: : "false");
1123: break;
1124: case TypeTags.BOT:
1125: print("null");
1126: break;
1127: default:
1128: print("\"" + Convert.quote(tree.value.toString())
1129: + "\"");
1130: break;
1131: }
1132: } catch (IOException e) {
1133: throw new UncheckedIOException(e);
1134: }
1135: }
1136:
1137: public void visitTypeIdent(JCPrimitiveTypeTree tree) {
1138: try {
1139: switch (tree.typetag) {
1140: case TypeTags.BYTE:
1141: print("byte");
1142: break;
1143: case TypeTags.CHAR:
1144: print("char");
1145: break;
1146: case TypeTags.SHORT:
1147: print("short");
1148: break;
1149: case TypeTags.INT:
1150: print("int");
1151: break;
1152: case TypeTags.LONG:
1153: print("long");
1154: break;
1155: case TypeTags.FLOAT:
1156: print("float");
1157: break;
1158: case TypeTags.DOUBLE:
1159: print("double");
1160: break;
1161: case TypeTags.BOOLEAN:
1162: print("boolean");
1163: break;
1164: case TypeTags.VOID:
1165: print("void");
1166: break;
1167: default:
1168: print("error");
1169: break;
1170: }
1171: } catch (IOException e) {
1172: throw new UncheckedIOException(e);
1173: }
1174: }
1175:
1176: public void visitTypeArray(JCArrayTypeTree tree) {
1177: try {
1178: printBaseElementType(tree);
1179: printBrackets(tree);
1180: } catch (IOException e) {
1181: throw new UncheckedIOException(e);
1182: }
1183: }
1184:
1185: // Prints the inner element type of a nested array
1186: private void printBaseElementType(JCArrayTypeTree tree)
1187: throws IOException {
1188: JCTree elem = tree.elemtype;
1189: while (elem instanceof JCWildcard)
1190: elem = ((JCWildcard) elem).inner;
1191: if (elem instanceof JCArrayTypeTree)
1192: printBaseElementType((JCArrayTypeTree) elem);
1193: else
1194: printExpr(elem);
1195: }
1196:
1197: // prints the brackets of a nested array in reverse order
1198: private void printBrackets(JCArrayTypeTree tree) throws IOException {
1199: JCTree elem;
1200: while (true) {
1201: elem = tree.elemtype;
1202: print("[]");
1203: if (!(elem instanceof JCArrayTypeTree))
1204: break;
1205: tree = (JCArrayTypeTree) elem;
1206: }
1207: }
1208:
1209: public void visitTypeApply(JCTypeApply tree) {
1210: try {
1211: printExpr(tree.clazz);
1212: print("<");
1213: printExprs(tree.arguments);
1214: print(">");
1215: } catch (IOException e) {
1216: throw new UncheckedIOException(e);
1217: }
1218: }
1219:
1220: public void visitTypeParameter(JCTypeParameter tree) {
1221: try {
1222: print(tree.name);
1223: if (tree.bounds.nonEmpty()) {
1224: print(" extends ");
1225: printExprs(tree.bounds, " & ");
1226: }
1227: } catch (IOException e) {
1228: throw new UncheckedIOException(e);
1229: }
1230: }
1231:
1232: @Override
1233: public void visitWildcard(JCWildcard tree) {
1234: try {
1235: print(tree.kind);
1236: if (tree.kind.kind != BoundKind.UNBOUND)
1237: printExpr(tree.inner);
1238: } catch (IOException e) {
1239: throw new UncheckedIOException(e);
1240: }
1241: }
1242:
1243: @Override
1244: public void visitTypeBoundKind(TypeBoundKind tree) {
1245: try {
1246: print(String.valueOf(tree.kind));
1247: } catch (IOException e) {
1248: throw new UncheckedIOException(e);
1249: }
1250: }
1251:
1252: public void visitErroneous(JCErroneous tree) {
1253: try {
1254: print("(ERROR)");
1255: } catch (IOException e) {
1256: throw new UncheckedIOException(e);
1257: }
1258: }
1259:
1260: public void visitLetExpr(LetExpr tree) {
1261: try {
1262: print("(let " + tree.defs + " in " + tree.expr + ")");
1263: } catch (IOException e) {
1264: throw new UncheckedIOException(e);
1265: }
1266: }
1267:
1268: public void visitModifiers(JCModifiers mods) {
1269: try {
1270: printAnnotations(mods.annotations);
1271: printFlags(mods.flags);
1272: } catch (IOException e) {
1273: throw new UncheckedIOException(e);
1274: }
1275: }
1276:
1277: public void visitAnnotation(JCAnnotation tree) {
1278: try {
1279: print("@");
1280: printExpr(tree.annotationType);
1281: print("(");
1282: printExprs(tree.args);
1283: print(")");
1284: } catch (IOException e) {
1285: throw new UncheckedIOException(e);
1286: }
1287: }
1288:
1289: public void visitTree(JCTree tree) {
1290: try {
1291: print("(UNKNOWN: " + tree + ")");
1292: println();
1293: } catch (IOException e) {
1294: throw new UncheckedIOException(e);
1295: }
1296: }
1297: }
|