Wed, 20 May 2009 13:36:23 -0700
6827026: Change javac source and target default to 7
Reviewed-by: darcy, ohair
1 /*
2 * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
26 package com.sun.tools.javac.tree;
28 import java.io.*;
29 import java.util.*;
31 import com.sun.tools.javac.util.*;
32 import com.sun.tools.javac.util.List;
33 import com.sun.tools.javac.code.*;
35 import com.sun.tools.javac.code.Symbol.*;
36 import com.sun.tools.javac.tree.JCTree.*;
38 import static com.sun.tools.javac.code.Flags.*;
40 /** Prints out a tree as an indented Java source program.
41 *
42 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
43 * you write code that depends on this, you do so at your own risk.
44 * This code and its internal interfaces are subject to change or
45 * deletion without notice.</b>
46 */
47 public class Pretty extends JCTree.Visitor {
49 public Pretty(Writer out, boolean sourceOutput) {
50 this.out = out;
51 this.sourceOutput = sourceOutput;
52 }
54 /** Set when we are producing source output. If we're not
55 * producing source output, we can sometimes give more detail in
56 * the output even though that detail would not be valid java
57 * soruce.
58 */
59 private final boolean sourceOutput;
61 /** The output stream on which trees are printed.
62 */
63 Writer out;
65 /** Indentation width (can be reassigned from outside).
66 */
67 public int width = 4;
69 /** The current left margin.
70 */
71 int lmargin = 0;
73 /** The enclosing class name.
74 */
75 Name enclClassName;
77 /** A hashtable mapping trees to their documentation comments
78 * (can be null)
79 */
80 Map<JCTree, String> docComments = null;
82 /** Align code to be indented to left margin.
83 */
84 void align() throws IOException {
85 for (int i = 0; i < lmargin; i++) out.write(" ");
86 }
88 /** Increase left margin by indentation width.
89 */
90 void indent() {
91 lmargin = lmargin + width;
92 }
94 /** Decrease left margin by indentation width.
95 */
96 void undent() {
97 lmargin = lmargin - width;
98 }
100 /** Enter a new precedence level. Emit a `(' if new precedence level
101 * is less than precedence level so far.
102 * @param contextPrec The precedence level in force so far.
103 * @param ownPrec The new precedence level.
104 */
105 void open(int contextPrec, int ownPrec) throws IOException {
106 if (ownPrec < contextPrec) out.write("(");
107 }
109 /** Leave precedence level. Emit a `(' if inner precedence level
110 * is less than precedence level we revert to.
111 * @param contextPrec The precedence level we revert to.
112 * @param ownPrec The inner precedence level.
113 */
114 void close(int contextPrec, int ownPrec) throws IOException {
115 if (ownPrec < contextPrec) out.write(")");
116 }
118 /** Print string, replacing all non-ascii character with unicode escapes.
119 */
120 public void print(Object s) throws IOException {
121 out.write(Convert.escapeUnicode(s.toString()));
122 }
124 /** Print new line.
125 */
126 public void println() throws IOException {
127 out.write(lineSep);
128 }
130 String lineSep = System.getProperty("line.separator");
132 /**************************************************************************
133 * Traversal methods
134 *************************************************************************/
136 /** Exception to propogate IOException through visitXXX methods */
137 private static class UncheckedIOException extends Error {
138 static final long serialVersionUID = -4032692679158424751L;
139 UncheckedIOException(IOException e) {
140 super(e.getMessage(), e);
141 }
142 }
144 /** Visitor argument: the current precedence level.
145 */
146 int prec;
148 /** Visitor method: print expression tree.
149 * @param prec The current precedence level.
150 */
151 public void printExpr(JCTree tree, int prec) throws IOException {
152 int prevPrec = this.prec;
153 try {
154 this.prec = prec;
155 if (tree == null) print("/*missing*/");
156 else {
157 tree.accept(this);
158 }
159 } catch (UncheckedIOException ex) {
160 IOException e = new IOException(ex.getMessage());
161 e.initCause(ex);
162 throw e;
163 } finally {
164 this.prec = prevPrec;
165 }
166 }
168 /** Derived visitor method: print expression tree at minimum precedence level
169 * for expression.
170 */
171 public void printExpr(JCTree tree) throws IOException {
172 printExpr(tree, TreeInfo.noPrec);
173 }
175 /** Derived visitor method: print statement tree.
176 */
177 public void printStat(JCTree tree) throws IOException {
178 printExpr(tree, TreeInfo.notExpression);
179 }
181 /** Derived visitor method: print list of expression trees, separated by given string.
182 * @param sep the separator string
183 */
184 public <T extends JCTree> void printExprs(List<T> trees, String sep) throws IOException {
185 if (trees.nonEmpty()) {
186 printExpr(trees.head);
187 for (List<T> l = trees.tail; l.nonEmpty(); l = l.tail) {
188 print(sep);
189 printExpr(l.head);
190 }
191 }
192 }
194 /** Derived visitor method: print list of expression trees, separated by commas.
195 */
196 public <T extends JCTree> void printExprs(List<T> trees) throws IOException {
197 printExprs(trees, ", ");
198 }
200 /** Derived visitor method: print list of statements, each on a separate line.
201 */
202 public void printStats(List<? extends JCTree> trees) throws IOException {
203 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) {
204 align();
205 printStat(l.head);
206 println();
207 }
208 }
210 /** Print a set of modifiers.
211 */
212 public void printFlags(long flags) throws IOException {
213 if ((flags & SYNTHETIC) != 0) print("/*synthetic*/ ");
214 print(TreeInfo.flagNames(flags));
215 if ((flags & StandardFlags) != 0) print(" ");
216 if ((flags & ANNOTATION) != 0) print("@");
217 }
219 public void printAnnotations(List<JCAnnotation> trees) throws IOException {
220 for (List<JCAnnotation> l = trees; l.nonEmpty(); l = l.tail) {
221 printStat(l.head);
222 println();
223 align();
224 }
225 }
227 /** Print documentation comment, if it exists
228 * @param tree The tree for which a documentation comment should be printed.
229 */
230 public void printDocComment(JCTree tree) throws IOException {
231 if (docComments != null) {
232 String dc = docComments.get(tree);
233 if (dc != null) {
234 print("/**"); println();
235 int pos = 0;
236 int endpos = lineEndPos(dc, pos);
237 while (pos < dc.length()) {
238 align();
239 print(" *");
240 if (pos < dc.length() && dc.charAt(pos) > ' ') print(" ");
241 print(dc.substring(pos, endpos)); println();
242 pos = endpos + 1;
243 endpos = lineEndPos(dc, pos);
244 }
245 align(); print(" */"); println();
246 align();
247 }
248 }
249 }
250 //where
251 static int lineEndPos(String s, int start) {
252 int pos = s.indexOf('\n', start);
253 if (pos < 0) pos = s.length();
254 return pos;
255 }
257 /** If type parameter list is non-empty, print it enclosed in "<...>" brackets.
258 */
259 public void printTypeParameters(List<JCTypeParameter> trees) throws IOException {
260 if (trees.nonEmpty()) {
261 print("<");
262 printExprs(trees);
263 print(">");
264 }
265 }
267 /** Print a block.
268 */
269 public void printBlock(List<? extends JCTree> stats) throws IOException {
270 print("{");
271 println();
272 indent();
273 printStats(stats);
274 undent();
275 align();
276 print("}");
277 }
279 /** Print a block.
280 */
281 public void printEnumBody(List<JCTree> stats) throws IOException {
282 print("{");
283 println();
284 indent();
285 boolean first = true;
286 for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) {
287 if (isEnumerator(l.head)) {
288 if (!first) {
289 print(",");
290 println();
291 }
292 align();
293 printStat(l.head);
294 first = false;
295 }
296 }
297 print(";");
298 println();
299 for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) {
300 if (!isEnumerator(l.head)) {
301 align();
302 printStat(l.head);
303 println();
304 }
305 }
306 undent();
307 align();
308 print("}");
309 }
311 /** Is the given tree an enumerator definition? */
312 boolean isEnumerator(JCTree t) {
313 return t.getTag() == JCTree.VARDEF && (((JCVariableDecl) t).mods.flags & ENUM) != 0;
314 }
316 /** Print unit consisting of package clause and import statements in toplevel,
317 * followed by class definition. if class definition == null,
318 * print all definitions in toplevel.
319 * @param tree The toplevel tree
320 * @param cdef The class definition, which is assumed to be part of the
321 * toplevel tree.
322 */
323 public void printUnit(JCCompilationUnit tree, JCClassDecl cdef) throws IOException {
324 docComments = tree.docComments;
325 printDocComment(tree);
326 if (tree.pid != null) {
327 print("package ");
328 printExpr(tree.pid);
329 print(";");
330 println();
331 }
332 boolean firstImport = true;
333 for (List<JCTree> l = tree.defs;
334 l.nonEmpty() && (cdef == null || l.head.getTag() == JCTree.IMPORT);
335 l = l.tail) {
336 if (l.head.getTag() == JCTree.IMPORT) {
337 JCImport imp = (JCImport)l.head;
338 Name name = TreeInfo.name(imp.qualid);
339 if (name == name.table.names.asterisk ||
340 cdef == null ||
341 isUsed(TreeInfo.symbol(imp.qualid), cdef)) {
342 if (firstImport) {
343 firstImport = false;
344 println();
345 }
346 printStat(imp);
347 }
348 } else {
349 printStat(l.head);
350 }
351 }
352 if (cdef != null) {
353 printStat(cdef);
354 println();
355 }
356 }
357 // where
358 boolean isUsed(final Symbol t, JCTree cdef) {
359 class UsedVisitor extends TreeScanner {
360 public void scan(JCTree tree) {
361 if (tree!=null && !result) tree.accept(this);
362 }
363 boolean result = false;
364 public void visitIdent(JCIdent tree) {
365 if (tree.sym == t) result = true;
366 }
367 }
368 UsedVisitor v = new UsedVisitor();
369 v.scan(cdef);
370 return v.result;
371 }
373 /**************************************************************************
374 * Visitor methods
375 *************************************************************************/
377 public void visitTopLevel(JCCompilationUnit tree) {
378 try {
379 printUnit(tree, null);
380 } catch (IOException e) {
381 throw new UncheckedIOException(e);
382 }
383 }
385 public void visitImport(JCImport tree) {
386 try {
387 print("import ");
388 if (tree.staticImport) print("static ");
389 printExpr(tree.qualid);
390 print(";");
391 println();
392 } catch (IOException e) {
393 throw new UncheckedIOException(e);
394 }
395 }
397 public void visitClassDef(JCClassDecl tree) {
398 try {
399 println(); align();
400 printDocComment(tree);
401 printAnnotations(tree.mods.annotations);
402 printFlags(tree.mods.flags & ~INTERFACE);
403 Name enclClassNamePrev = enclClassName;
404 enclClassName = tree.name;
405 if ((tree.mods.flags & INTERFACE) != 0) {
406 print("interface " + tree.name);
407 printTypeParameters(tree.typarams);
408 if (tree.implementing.nonEmpty()) {
409 print(" extends ");
410 printExprs(tree.implementing);
411 }
412 } else {
413 if ((tree.mods.flags & ENUM) != 0)
414 print("enum " + tree.name);
415 else
416 print("class " + tree.name);
417 printTypeParameters(tree.typarams);
418 if (tree.extending != null) {
419 print(" extends ");
420 printExpr(tree.extending);
421 }
422 if (tree.implementing.nonEmpty()) {
423 print(" implements ");
424 printExprs(tree.implementing);
425 }
426 }
427 print(" ");
428 if ((tree.mods.flags & ENUM) != 0) {
429 printEnumBody(tree.defs);
430 } else {
431 printBlock(tree.defs);
432 }
433 enclClassName = enclClassNamePrev;
434 } catch (IOException e) {
435 throw new UncheckedIOException(e);
436 }
437 }
439 public void visitMethodDef(JCMethodDecl tree) {
440 try {
441 // when producing source output, omit anonymous constructors
442 if (tree.name == tree.name.table.names.init &&
443 enclClassName == null &&
444 sourceOutput) return;
445 println(); align();
446 printDocComment(tree);
447 printExpr(tree.mods);
448 printTypeParameters(tree.typarams);
449 if (tree.name == tree.name.table.names.init) {
450 print(enclClassName != null ? enclClassName : tree.name);
451 } else {
452 printExpr(tree.restype);
453 print(" " + tree.name);
454 }
455 print("(");
456 printExprs(tree.params);
457 print(")");
458 if (tree.thrown.nonEmpty()) {
459 print(" throws ");
460 printExprs(tree.thrown);
461 }
462 if (tree.body != null) {
463 print(" ");
464 printStat(tree.body);
465 } else {
466 print(";");
467 }
468 } catch (IOException e) {
469 throw new UncheckedIOException(e);
470 }
471 }
473 public void visitVarDef(JCVariableDecl tree) {
474 try {
475 if (docComments != null && docComments.get(tree) != null) {
476 println(); align();
477 }
478 printDocComment(tree);
479 if ((tree.mods.flags & ENUM) != 0) {
480 print("/*public static final*/ ");
481 print(tree.name);
482 if (tree.init != null) {
483 print(" /* = ");
484 printExpr(tree.init);
485 print(" */");
486 }
487 } else {
488 printExpr(tree.mods);
489 if ((tree.mods.flags & VARARGS) != 0) {
490 printExpr(((JCArrayTypeTree) tree.vartype).elemtype);
491 print("... " + tree.name);
492 } else {
493 printExpr(tree.vartype);
494 print(" " + tree.name);
495 }
496 if (tree.init != null) {
497 print(" = ");
498 printExpr(tree.init);
499 }
500 if (prec == TreeInfo.notExpression) print(";");
501 }
502 } catch (IOException e) {
503 throw new UncheckedIOException(e);
504 }
505 }
507 public void visitSkip(JCSkip tree) {
508 try {
509 print(";");
510 } catch (IOException e) {
511 throw new UncheckedIOException(e);
512 }
513 }
515 public void visitBlock(JCBlock tree) {
516 try {
517 printFlags(tree.flags);
518 printBlock(tree.stats);
519 } catch (IOException e) {
520 throw new UncheckedIOException(e);
521 }
522 }
524 public void visitDoLoop(JCDoWhileLoop tree) {
525 try {
526 print("do ");
527 printStat(tree.body);
528 align();
529 print(" while ");
530 if (tree.cond.getTag() == JCTree.PARENS) {
531 printExpr(tree.cond);
532 } else {
533 print("(");
534 printExpr(tree.cond);
535 print(")");
536 }
537 print(";");
538 } catch (IOException e) {
539 throw new UncheckedIOException(e);
540 }
541 }
543 public void visitWhileLoop(JCWhileLoop tree) {
544 try {
545 print("while ");
546 if (tree.cond.getTag() == JCTree.PARENS) {
547 printExpr(tree.cond);
548 } else {
549 print("(");
550 printExpr(tree.cond);
551 print(")");
552 }
553 print(" ");
554 printStat(tree.body);
555 } catch (IOException e) {
556 throw new UncheckedIOException(e);
557 }
558 }
560 public void visitForLoop(JCForLoop tree) {
561 try {
562 print("for (");
563 if (tree.init.nonEmpty()) {
564 if (tree.init.head.getTag() == JCTree.VARDEF) {
565 printExpr(tree.init.head);
566 for (List<JCStatement> l = tree.init.tail; l.nonEmpty(); l = l.tail) {
567 JCVariableDecl vdef = (JCVariableDecl)l.head;
568 print(", " + vdef.name + " = ");
569 printExpr(vdef.init);
570 }
571 } else {
572 printExprs(tree.init);
573 }
574 }
575 print("; ");
576 if (tree.cond != null) printExpr(tree.cond);
577 print("; ");
578 printExprs(tree.step);
579 print(") ");
580 printStat(tree.body);
581 } catch (IOException e) {
582 throw new UncheckedIOException(e);
583 }
584 }
586 public void visitForeachLoop(JCEnhancedForLoop tree) {
587 try {
588 print("for (");
589 printExpr(tree.var);
590 print(" : ");
591 printExpr(tree.expr);
592 print(") ");
593 printStat(tree.body);
594 } catch (IOException e) {
595 throw new UncheckedIOException(e);
596 }
597 }
599 public void visitLabelled(JCLabeledStatement tree) {
600 try {
601 print(tree.label + ": ");
602 printStat(tree.body);
603 } catch (IOException e) {
604 throw new UncheckedIOException(e);
605 }
606 }
608 public void visitSwitch(JCSwitch tree) {
609 try {
610 print("switch ");
611 if (tree.selector.getTag() == JCTree.PARENS) {
612 printExpr(tree.selector);
613 } else {
614 print("(");
615 printExpr(tree.selector);
616 print(")");
617 }
618 print(" {");
619 println();
620 printStats(tree.cases);
621 align();
622 print("}");
623 } catch (IOException e) {
624 throw new UncheckedIOException(e);
625 }
626 }
628 public void visitCase(JCCase tree) {
629 try {
630 if (tree.pat == null) {
631 print("default");
632 } else {
633 print("case ");
634 printExpr(tree.pat);
635 }
636 print(": ");
637 println();
638 indent();
639 printStats(tree.stats);
640 undent();
641 align();
642 } catch (IOException e) {
643 throw new UncheckedIOException(e);
644 }
645 }
647 public void visitSynchronized(JCSynchronized tree) {
648 try {
649 print("synchronized ");
650 if (tree.lock.getTag() == JCTree.PARENS) {
651 printExpr(tree.lock);
652 } else {
653 print("(");
654 printExpr(tree.lock);
655 print(")");
656 }
657 print(" ");
658 printStat(tree.body);
659 } catch (IOException e) {
660 throw new UncheckedIOException(e);
661 }
662 }
664 public void visitTry(JCTry tree) {
665 try {
666 print("try ");
667 printStat(tree.body);
668 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
669 printStat(l.head);
670 }
671 if (tree.finalizer != null) {
672 print(" finally ");
673 printStat(tree.finalizer);
674 }
675 } catch (IOException e) {
676 throw new UncheckedIOException(e);
677 }
678 }
680 public void visitCatch(JCCatch tree) {
681 try {
682 print(" catch (");
683 printExpr(tree.param);
684 print(") ");
685 printStat(tree.body);
686 } catch (IOException e) {
687 throw new UncheckedIOException(e);
688 }
689 }
691 public void visitConditional(JCConditional tree) {
692 try {
693 open(prec, TreeInfo.condPrec);
694 printExpr(tree.cond, TreeInfo.condPrec);
695 print(" ? ");
696 printExpr(tree.truepart, TreeInfo.condPrec);
697 print(" : ");
698 printExpr(tree.falsepart, TreeInfo.condPrec);
699 close(prec, TreeInfo.condPrec);
700 } catch (IOException e) {
701 throw new UncheckedIOException(e);
702 }
703 }
705 public void visitIf(JCIf tree) {
706 try {
707 print("if ");
708 if (tree.cond.getTag() == JCTree.PARENS) {
709 printExpr(tree.cond);
710 } else {
711 print("(");
712 printExpr(tree.cond);
713 print(")");
714 }
715 print(" ");
716 printStat(tree.thenpart);
717 if (tree.elsepart != null) {
718 print(" else ");
719 printStat(tree.elsepart);
720 }
721 } catch (IOException e) {
722 throw new UncheckedIOException(e);
723 }
724 }
726 public void visitExec(JCExpressionStatement tree) {
727 try {
728 printExpr(tree.expr);
729 if (prec == TreeInfo.notExpression) print(";");
730 } catch (IOException e) {
731 throw new UncheckedIOException(e);
732 }
733 }
735 public void visitBreak(JCBreak tree) {
736 try {
737 print("break");
738 if (tree.label != null) print(" " + tree.label);
739 print(";");
740 } catch (IOException e) {
741 throw new UncheckedIOException(e);
742 }
743 }
745 public void visitContinue(JCContinue tree) {
746 try {
747 print("continue");
748 if (tree.label != null) print(" " + tree.label);
749 print(";");
750 } catch (IOException e) {
751 throw new UncheckedIOException(e);
752 }
753 }
755 public void visitReturn(JCReturn tree) {
756 try {
757 print("return");
758 if (tree.expr != null) {
759 print(" ");
760 printExpr(tree.expr);
761 }
762 print(";");
763 } catch (IOException e) {
764 throw new UncheckedIOException(e);
765 }
766 }
768 public void visitThrow(JCThrow tree) {
769 try {
770 print("throw ");
771 printExpr(tree.expr);
772 print(";");
773 } catch (IOException e) {
774 throw new UncheckedIOException(e);
775 }
776 }
778 public void visitAssert(JCAssert tree) {
779 try {
780 print("assert ");
781 printExpr(tree.cond);
782 if (tree.detail != null) {
783 print(" : ");
784 printExpr(tree.detail);
785 }
786 print(";");
787 } catch (IOException e) {
788 throw new UncheckedIOException(e);
789 }
790 }
792 public void visitApply(JCMethodInvocation tree) {
793 try {
794 if (!tree.typeargs.isEmpty()) {
795 if (tree.meth.getTag() == JCTree.SELECT) {
796 JCFieldAccess left = (JCFieldAccess)tree.meth;
797 printExpr(left.selected);
798 print(".<");
799 printExprs(tree.typeargs);
800 print(">" + left.name);
801 } else {
802 print("<");
803 printExprs(tree.typeargs);
804 print(">");
805 printExpr(tree.meth);
806 }
807 } else {
808 printExpr(tree.meth);
809 }
810 print("(");
811 printExprs(tree.args);
812 print(")");
813 } catch (IOException e) {
814 throw new UncheckedIOException(e);
815 }
816 }
818 public void visitNewClass(JCNewClass tree) {
819 try {
820 if (tree.encl != null) {
821 printExpr(tree.encl);
822 print(".");
823 }
824 print("new ");
825 if (!tree.typeargs.isEmpty()) {
826 print("<");
827 printExprs(tree.typeargs);
828 print(">");
829 }
830 printExpr(tree.clazz);
831 print("(");
832 printExprs(tree.args);
833 print(")");
834 if (tree.def != null) {
835 Name enclClassNamePrev = enclClassName;
836 enclClassName =
837 tree.def.name != null ? tree.def.name :
838 tree.type != null && tree.type.tsym.name != tree.type.tsym.name.table.names.empty
839 ? tree.type.tsym.name : null;
840 if ((tree.def.mods.flags & Flags.ENUM) != 0) print("/*enum*/");
841 printBlock(tree.def.defs);
842 enclClassName = enclClassNamePrev;
843 }
844 } catch (IOException e) {
845 throw new UncheckedIOException(e);
846 }
847 }
849 public void visitNewArray(JCNewArray tree) {
850 try {
851 if (tree.elemtype != null) {
852 print("new ");
853 JCTree elem = tree.elemtype;
854 if (elem instanceof JCArrayTypeTree)
855 printBaseElementType((JCArrayTypeTree) elem);
856 else
857 printExpr(elem);
858 for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
859 print("[");
860 printExpr(l.head);
861 print("]");
862 }
863 if (elem instanceof JCArrayTypeTree)
864 printBrackets((JCArrayTypeTree) elem);
865 }
866 if (tree.elems != null) {
867 if (tree.elemtype != null) print("[]");
868 print("{");
869 printExprs(tree.elems);
870 print("}");
871 }
872 } catch (IOException e) {
873 throw new UncheckedIOException(e);
874 }
875 }
877 public void visitParens(JCParens tree) {
878 try {
879 print("(");
880 printExpr(tree.expr);
881 print(")");
882 } catch (IOException e) {
883 throw new UncheckedIOException(e);
884 }
885 }
887 public void visitAssign(JCAssign tree) {
888 try {
889 open(prec, TreeInfo.assignPrec);
890 printExpr(tree.lhs, TreeInfo.assignPrec + 1);
891 print(" = ");
892 printExpr(tree.rhs, TreeInfo.assignPrec);
893 close(prec, TreeInfo.assignPrec);
894 } catch (IOException e) {
895 throw new UncheckedIOException(e);
896 }
897 }
899 public String operatorName(int tag) {
900 switch(tag) {
901 case JCTree.POS: return "+";
902 case JCTree.NEG: return "-";
903 case JCTree.NOT: return "!";
904 case JCTree.COMPL: return "~";
905 case JCTree.PREINC: return "++";
906 case JCTree.PREDEC: return "--";
907 case JCTree.POSTINC: return "++";
908 case JCTree.POSTDEC: return "--";
909 case JCTree.NULLCHK: return "<*nullchk*>";
910 case JCTree.OR: return "||";
911 case JCTree.AND: return "&&";
912 case JCTree.EQ: return "==";
913 case JCTree.NE: return "!=";
914 case JCTree.LT: return "<";
915 case JCTree.GT: return ">";
916 case JCTree.LE: return "<=";
917 case JCTree.GE: return ">=";
918 case JCTree.BITOR: return "|";
919 case JCTree.BITXOR: return "^";
920 case JCTree.BITAND: return "&";
921 case JCTree.SL: return "<<";
922 case JCTree.SR: return ">>";
923 case JCTree.USR: return ">>>";
924 case JCTree.PLUS: return "+";
925 case JCTree.MINUS: return "-";
926 case JCTree.MUL: return "*";
927 case JCTree.DIV: return "/";
928 case JCTree.MOD: return "%";
929 default: throw new Error();
930 }
931 }
933 public void visitAssignop(JCAssignOp tree) {
934 try {
935 open(prec, TreeInfo.assignopPrec);
936 printExpr(tree.lhs, TreeInfo.assignopPrec + 1);
937 print(" " + operatorName(tree.getTag() - JCTree.ASGOffset) + "= ");
938 printExpr(tree.rhs, TreeInfo.assignopPrec);
939 close(prec, TreeInfo.assignopPrec);
940 } catch (IOException e) {
941 throw new UncheckedIOException(e);
942 }
943 }
945 public void visitUnary(JCUnary tree) {
946 try {
947 int ownprec = TreeInfo.opPrec(tree.getTag());
948 String opname = operatorName(tree.getTag());
949 open(prec, ownprec);
950 if (tree.getTag() <= JCTree.PREDEC) {
951 print(opname);
952 printExpr(tree.arg, ownprec);
953 } else {
954 printExpr(tree.arg, ownprec);
955 print(opname);
956 }
957 close(prec, ownprec);
958 } catch (IOException e) {
959 throw new UncheckedIOException(e);
960 }
961 }
963 public void visitBinary(JCBinary tree) {
964 try {
965 int ownprec = TreeInfo.opPrec(tree.getTag());
966 String opname = operatorName(tree.getTag());
967 open(prec, ownprec);
968 printExpr(tree.lhs, ownprec);
969 print(" " + opname + " ");
970 printExpr(tree.rhs, ownprec + 1);
971 close(prec, ownprec);
972 } catch (IOException e) {
973 throw new UncheckedIOException(e);
974 }
975 }
977 public void visitTypeCast(JCTypeCast tree) {
978 try {
979 open(prec, TreeInfo.prefixPrec);
980 print("(");
981 printExpr(tree.clazz);
982 print(")");
983 printExpr(tree.expr, TreeInfo.prefixPrec);
984 close(prec, TreeInfo.prefixPrec);
985 } catch (IOException e) {
986 throw new UncheckedIOException(e);
987 }
988 }
990 public void visitTypeTest(JCInstanceOf tree) {
991 try {
992 open(prec, TreeInfo.ordPrec);
993 printExpr(tree.expr, TreeInfo.ordPrec);
994 print(" instanceof ");
995 printExpr(tree.clazz, TreeInfo.ordPrec + 1);
996 close(prec, TreeInfo.ordPrec);
997 } catch (IOException e) {
998 throw new UncheckedIOException(e);
999 }
1000 }
1002 public void visitIndexed(JCArrayAccess tree) {
1003 try {
1004 printExpr(tree.indexed, TreeInfo.postfixPrec);
1005 print("[");
1006 printExpr(tree.index);
1007 print("]");
1008 } catch (IOException e) {
1009 throw new UncheckedIOException(e);
1010 }
1011 }
1013 public void visitSelect(JCFieldAccess tree) {
1014 try {
1015 printExpr(tree.selected, TreeInfo.postfixPrec);
1016 print("." + tree.name);
1017 } catch (IOException e) {
1018 throw new UncheckedIOException(e);
1019 }
1020 }
1022 public void visitIdent(JCIdent tree) {
1023 try {
1024 print(tree.name);
1025 } catch (IOException e) {
1026 throw new UncheckedIOException(e);
1027 }
1028 }
1030 public void visitLiteral(JCLiteral tree) {
1031 try {
1032 switch (tree.typetag) {
1033 case TypeTags.INT:
1034 print(tree.value.toString());
1035 break;
1036 case TypeTags.LONG:
1037 print(tree.value + "L");
1038 break;
1039 case TypeTags.FLOAT:
1040 print(tree.value + "F");
1041 break;
1042 case TypeTags.DOUBLE:
1043 print(tree.value.toString());
1044 break;
1045 case TypeTags.CHAR:
1046 print("\'" +
1047 Convert.quote(
1048 String.valueOf((char)((Number)tree.value).intValue())) +
1049 "\'");
1050 break;
1051 case TypeTags.BOOLEAN:
1052 print(((Number)tree.value).intValue() == 1 ? "true" : "false");
1053 break;
1054 case TypeTags.BOT:
1055 print("null");
1056 break;
1057 default:
1058 print("\"" + Convert.quote(tree.value.toString()) + "\"");
1059 break;
1060 }
1061 } catch (IOException e) {
1062 throw new UncheckedIOException(e);
1063 }
1064 }
1066 public void visitTypeIdent(JCPrimitiveTypeTree tree) {
1067 try {
1068 switch(tree.typetag) {
1069 case TypeTags.BYTE:
1070 print("byte");
1071 break;
1072 case TypeTags.CHAR:
1073 print("char");
1074 break;
1075 case TypeTags.SHORT:
1076 print("short");
1077 break;
1078 case TypeTags.INT:
1079 print("int");
1080 break;
1081 case TypeTags.LONG:
1082 print("long");
1083 break;
1084 case TypeTags.FLOAT:
1085 print("float");
1086 break;
1087 case TypeTags.DOUBLE:
1088 print("double");
1089 break;
1090 case TypeTags.BOOLEAN:
1091 print("boolean");
1092 break;
1093 case TypeTags.VOID:
1094 print("void");
1095 break;
1096 default:
1097 print("error");
1098 break;
1099 }
1100 } catch (IOException e) {
1101 throw new UncheckedIOException(e);
1102 }
1103 }
1105 public void visitTypeArray(JCArrayTypeTree tree) {
1106 try {
1107 printBaseElementType(tree);
1108 printBrackets(tree);
1109 } catch (IOException e) {
1110 throw new UncheckedIOException(e);
1111 }
1112 }
1114 // Prints the inner element type of a nested array
1115 private void printBaseElementType(JCArrayTypeTree tree) throws IOException {
1116 JCTree elem = tree.elemtype;
1117 while (elem instanceof JCWildcard)
1118 elem = ((JCWildcard) elem).inner;
1119 if (elem instanceof JCArrayTypeTree)
1120 printBaseElementType((JCArrayTypeTree) elem);
1121 else
1122 printExpr(elem);
1123 }
1125 // prints the brackets of a nested array in reverse order
1126 private void printBrackets(JCArrayTypeTree tree) throws IOException {
1127 JCTree elem;
1128 while (true) {
1129 elem = tree.elemtype;
1130 print("[]");
1131 if (!(elem instanceof JCArrayTypeTree)) break;
1132 tree = (JCArrayTypeTree) elem;
1133 }
1134 }
1136 public void visitTypeApply(JCTypeApply tree) {
1137 try {
1138 printExpr(tree.clazz);
1139 print("<");
1140 printExprs(tree.arguments);
1141 print(">");
1142 } catch (IOException e) {
1143 throw new UncheckedIOException(e);
1144 }
1145 }
1147 public void visitTypeParameter(JCTypeParameter tree) {
1148 try {
1149 print(tree.name);
1150 if (tree.bounds.nonEmpty()) {
1151 print(" extends ");
1152 printExprs(tree.bounds, " & ");
1153 }
1154 } catch (IOException e) {
1155 throw new UncheckedIOException(e);
1156 }
1157 }
1159 @Override
1160 public void visitWildcard(JCWildcard tree) {
1161 try {
1162 print(tree.kind);
1163 if (tree.kind.kind != BoundKind.UNBOUND)
1164 printExpr(tree.inner);
1165 } catch (IOException e) {
1166 throw new UncheckedIOException(e);
1167 }
1168 }
1170 @Override
1171 public void visitTypeBoundKind(TypeBoundKind tree) {
1172 try {
1173 print(String.valueOf(tree.kind));
1174 } catch (IOException e) {
1175 throw new UncheckedIOException(e);
1176 }
1177 }
1179 public void visitErroneous(JCErroneous tree) {
1180 try {
1181 print("(ERROR)");
1182 } catch (IOException e) {
1183 throw new UncheckedIOException(e);
1184 }
1185 }
1187 public void visitLetExpr(LetExpr tree) {
1188 try {
1189 print("(let " + tree.defs + " in " + tree.expr + ")");
1190 } catch (IOException e) {
1191 throw new UncheckedIOException(e);
1192 }
1193 }
1195 public void visitModifiers(JCModifiers mods) {
1196 try {
1197 printAnnotations(mods.annotations);
1198 printFlags(mods.flags);
1199 } catch (IOException e) {
1200 throw new UncheckedIOException(e);
1201 }
1202 }
1204 public void visitAnnotation(JCAnnotation tree) {
1205 try {
1206 print("@");
1207 printExpr(tree.annotationType);
1208 print("(");
1209 printExprs(tree.args);
1210 print(")");
1211 } catch (IOException e) {
1212 throw new UncheckedIOException(e);
1213 }
1214 }
1216 public void visitTree(JCTree tree) {
1217 try {
1218 print("(UNKNOWN: " + tree + ")");
1219 println();
1220 } catch (IOException e) {
1221 throw new UncheckedIOException(e);
1222 }
1223 }
1224 }