Tue, 19 Oct 2010 15:02:48 -0700
6987760: remove 308 support from JDK7
Reviewed-by: darcy, mcimadamore
1 /*
2 * Copyright (c) 1999, 2008, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * 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 supported API.
43 * If 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 * source.
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 public void printTypeAnnotations(List<JCTypeAnnotation> trees) throws IOException {
228 if (trees.nonEmpty())
229 print(" ");
230 for (List<JCTypeAnnotation> l = trees; l.nonEmpty(); l = l.tail) {
231 printExpr(l.head);
232 print(" ");
233 }
234 }
236 /** Print documentation comment, if it exists
237 * @param tree The tree for which a documentation comment should be printed.
238 */
239 public void printDocComment(JCTree tree) throws IOException {
240 if (docComments != null) {
241 String dc = docComments.get(tree);
242 if (dc != null) {
243 print("/**"); println();
244 int pos = 0;
245 int endpos = lineEndPos(dc, pos);
246 while (pos < dc.length()) {
247 align();
248 print(" *");
249 if (pos < dc.length() && dc.charAt(pos) > ' ') print(" ");
250 print(dc.substring(pos, endpos)); println();
251 pos = endpos + 1;
252 endpos = lineEndPos(dc, pos);
253 }
254 align(); print(" */"); println();
255 align();
256 }
257 }
258 }
259 //where
260 static int lineEndPos(String s, int start) {
261 int pos = s.indexOf('\n', start);
262 if (pos < 0) pos = s.length();
263 return pos;
264 }
266 /** If type parameter list is non-empty, print it enclosed in "<...>" brackets.
267 */
268 public void printTypeParameters(List<JCTypeParameter> trees) throws IOException {
269 if (trees.nonEmpty()) {
270 print("<");
271 printExprs(trees);
272 print(">");
273 }
274 }
276 /** Print a block.
277 */
278 public void printBlock(List<? extends JCTree> stats) throws IOException {
279 print("{");
280 println();
281 indent();
282 printStats(stats);
283 undent();
284 align();
285 print("}");
286 }
288 /** Print a block.
289 */
290 public void printEnumBody(List<JCTree> stats) throws IOException {
291 print("{");
292 println();
293 indent();
294 boolean first = true;
295 for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) {
296 if (isEnumerator(l.head)) {
297 if (!first) {
298 print(",");
299 println();
300 }
301 align();
302 printStat(l.head);
303 first = false;
304 }
305 }
306 print(";");
307 println();
308 for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) {
309 if (!isEnumerator(l.head)) {
310 align();
311 printStat(l.head);
312 println();
313 }
314 }
315 undent();
316 align();
317 print("}");
318 }
320 /** Is the given tree an enumerator definition? */
321 boolean isEnumerator(JCTree t) {
322 return t.getTag() == JCTree.VARDEF && (((JCVariableDecl) t).mods.flags & ENUM) != 0;
323 }
325 /** Print unit consisting of package clause and import statements in toplevel,
326 * followed by class definition. if class definition == null,
327 * print all definitions in toplevel.
328 * @param tree The toplevel tree
329 * @param cdef The class definition, which is assumed to be part of the
330 * toplevel tree.
331 */
332 public void printUnit(JCCompilationUnit tree, JCClassDecl cdef) throws IOException {
333 docComments = tree.docComments;
334 printDocComment(tree);
335 if (tree.pid != null) {
336 print("package ");
337 printExpr(tree.pid);
338 print(";");
339 println();
340 }
341 boolean firstImport = true;
342 for (List<JCTree> l = tree.defs;
343 l.nonEmpty() && (cdef == null || l.head.getTag() == JCTree.IMPORT);
344 l = l.tail) {
345 if (l.head.getTag() == JCTree.IMPORT) {
346 JCImport imp = (JCImport)l.head;
347 Name name = TreeInfo.name(imp.qualid);
348 if (name == name.table.names.asterisk ||
349 cdef == null ||
350 isUsed(TreeInfo.symbol(imp.qualid), cdef)) {
351 if (firstImport) {
352 firstImport = false;
353 println();
354 }
355 printStat(imp);
356 }
357 } else {
358 printStat(l.head);
359 }
360 }
361 if (cdef != null) {
362 printStat(cdef);
363 println();
364 }
365 }
366 // where
367 boolean isUsed(final Symbol t, JCTree cdef) {
368 class UsedVisitor extends TreeScanner {
369 public void scan(JCTree tree) {
370 if (tree!=null && !result) tree.accept(this);
371 }
372 boolean result = false;
373 public void visitIdent(JCIdent tree) {
374 if (tree.sym == t) result = true;
375 }
376 }
377 UsedVisitor v = new UsedVisitor();
378 v.scan(cdef);
379 return v.result;
380 }
382 /**************************************************************************
383 * Visitor methods
384 *************************************************************************/
386 public void visitTopLevel(JCCompilationUnit tree) {
387 try {
388 printUnit(tree, null);
389 } catch (IOException e) {
390 throw new UncheckedIOException(e);
391 }
392 }
394 public void visitImport(JCImport tree) {
395 try {
396 print("import ");
397 if (tree.staticImport) print("static ");
398 printExpr(tree.qualid);
399 print(";");
400 println();
401 } catch (IOException e) {
402 throw new UncheckedIOException(e);
403 }
404 }
406 public void visitClassDef(JCClassDecl tree) {
407 try {
408 println(); align();
409 printDocComment(tree);
410 printAnnotations(tree.mods.annotations);
411 printFlags(tree.mods.flags & ~INTERFACE);
412 Name enclClassNamePrev = enclClassName;
413 enclClassName = tree.name;
414 if ((tree.mods.flags & INTERFACE) != 0) {
415 print("interface " + tree.name);
416 printTypeParameters(tree.typarams);
417 if (tree.implementing.nonEmpty()) {
418 print(" extends ");
419 printExprs(tree.implementing);
420 }
421 } else {
422 if ((tree.mods.flags & ENUM) != 0)
423 print("enum " + tree.name);
424 else
425 print("class " + tree.name);
426 printTypeParameters(tree.typarams);
427 if (tree.extending != null) {
428 print(" extends ");
429 printExpr(tree.extending);
430 }
431 if (tree.implementing.nonEmpty()) {
432 print(" implements ");
433 printExprs(tree.implementing);
434 }
435 }
436 print(" ");
437 if ((tree.mods.flags & ENUM) != 0) {
438 printEnumBody(tree.defs);
439 } else {
440 printBlock(tree.defs);
441 }
442 enclClassName = enclClassNamePrev;
443 } catch (IOException e) {
444 throw new UncheckedIOException(e);
445 }
446 }
448 public void visitMethodDef(JCMethodDecl tree) {
449 try {
450 // when producing source output, omit anonymous constructors
451 if (tree.name == tree.name.table.names.init &&
452 enclClassName == null &&
453 sourceOutput) return;
454 println(); align();
455 printDocComment(tree);
456 printExpr(tree.mods);
457 printTypeParameters(tree.typarams);
458 if (tree.name == tree.name.table.names.init) {
459 print(enclClassName != null ? enclClassName : tree.name);
460 } else {
461 printExpr(tree.restype);
462 print(" " + tree.name);
463 }
464 print("(");
465 printExprs(tree.params);
466 print(")");
467 if (tree.thrown.nonEmpty()) {
468 print(" throws ");
469 printExprs(tree.thrown);
470 }
471 if (tree.defaultValue != null) {
472 print(" default ");
473 printExpr(tree.defaultValue);
474 }
475 if (tree.body != null) {
476 print(" ");
477 printStat(tree.body);
478 } else {
479 print(";");
480 }
481 } catch (IOException e) {
482 throw new UncheckedIOException(e);
483 }
484 }
486 public void visitVarDef(JCVariableDecl tree) {
487 try {
488 if (docComments != null && docComments.get(tree) != null) {
489 println(); align();
490 }
491 printDocComment(tree);
492 if ((tree.mods.flags & ENUM) != 0) {
493 print("/*public static final*/ ");
494 print(tree.name);
495 if (tree.init != null) {
496 if (sourceOutput && tree.init.getTag() == JCTree.NEWCLASS) {
497 print(" /*enum*/ ");
498 JCNewClass init = (JCNewClass) tree.init;
499 if (init.args != null && init.args.nonEmpty()) {
500 print("(");
501 print(init.args);
502 print(")");
503 }
504 if (init.def != null && init.def.defs != null) {
505 print(" ");
506 printBlock(init.def.defs);
507 }
508 return;
509 }
510 print(" /* = ");
511 printExpr(tree.init);
512 print(" */");
513 }
514 } else {
515 printExpr(tree.mods);
516 if ((tree.mods.flags & VARARGS) != 0) {
517 printExpr(((JCArrayTypeTree) tree.vartype).elemtype);
518 print("... " + tree.name);
519 } else {
520 printExpr(tree.vartype);
521 print(" " + tree.name);
522 }
523 if (tree.init != null) {
524 print(" = ");
525 printExpr(tree.init);
526 }
527 if (prec == TreeInfo.notExpression) print(";");
528 }
529 } catch (IOException e) {
530 throw new UncheckedIOException(e);
531 }
532 }
534 public void visitSkip(JCSkip tree) {
535 try {
536 print(";");
537 } catch (IOException e) {
538 throw new UncheckedIOException(e);
539 }
540 }
542 public void visitBlock(JCBlock tree) {
543 try {
544 printFlags(tree.flags);
545 printBlock(tree.stats);
546 } catch (IOException e) {
547 throw new UncheckedIOException(e);
548 }
549 }
551 public void visitDoLoop(JCDoWhileLoop tree) {
552 try {
553 print("do ");
554 printStat(tree.body);
555 align();
556 print(" while ");
557 if (tree.cond.getTag() == JCTree.PARENS) {
558 printExpr(tree.cond);
559 } else {
560 print("(");
561 printExpr(tree.cond);
562 print(")");
563 }
564 print(";");
565 } catch (IOException e) {
566 throw new UncheckedIOException(e);
567 }
568 }
570 public void visitWhileLoop(JCWhileLoop tree) {
571 try {
572 print("while ");
573 if (tree.cond.getTag() == JCTree.PARENS) {
574 printExpr(tree.cond);
575 } else {
576 print("(");
577 printExpr(tree.cond);
578 print(")");
579 }
580 print(" ");
581 printStat(tree.body);
582 } catch (IOException e) {
583 throw new UncheckedIOException(e);
584 }
585 }
587 public void visitForLoop(JCForLoop tree) {
588 try {
589 print("for (");
590 if (tree.init.nonEmpty()) {
591 if (tree.init.head.getTag() == JCTree.VARDEF) {
592 printExpr(tree.init.head);
593 for (List<JCStatement> l = tree.init.tail; l.nonEmpty(); l = l.tail) {
594 JCVariableDecl vdef = (JCVariableDecl)l.head;
595 print(", " + vdef.name + " = ");
596 printExpr(vdef.init);
597 }
598 } else {
599 printExprs(tree.init);
600 }
601 }
602 print("; ");
603 if (tree.cond != null) printExpr(tree.cond);
604 print("; ");
605 printExprs(tree.step);
606 print(") ");
607 printStat(tree.body);
608 } catch (IOException e) {
609 throw new UncheckedIOException(e);
610 }
611 }
613 public void visitForeachLoop(JCEnhancedForLoop tree) {
614 try {
615 print("for (");
616 printExpr(tree.var);
617 print(" : ");
618 printExpr(tree.expr);
619 print(") ");
620 printStat(tree.body);
621 } catch (IOException e) {
622 throw new UncheckedIOException(e);
623 }
624 }
626 public void visitLabelled(JCLabeledStatement tree) {
627 try {
628 print(tree.label + ": ");
629 printStat(tree.body);
630 } catch (IOException e) {
631 throw new UncheckedIOException(e);
632 }
633 }
635 public void visitSwitch(JCSwitch tree) {
636 try {
637 print("switch ");
638 if (tree.selector.getTag() == JCTree.PARENS) {
639 printExpr(tree.selector);
640 } else {
641 print("(");
642 printExpr(tree.selector);
643 print(")");
644 }
645 print(" {");
646 println();
647 printStats(tree.cases);
648 align();
649 print("}");
650 } catch (IOException e) {
651 throw new UncheckedIOException(e);
652 }
653 }
655 public void visitCase(JCCase tree) {
656 try {
657 if (tree.pat == null) {
658 print("default");
659 } else {
660 print("case ");
661 printExpr(tree.pat);
662 }
663 print(": ");
664 println();
665 indent();
666 printStats(tree.stats);
667 undent();
668 align();
669 } catch (IOException e) {
670 throw new UncheckedIOException(e);
671 }
672 }
674 public void visitSynchronized(JCSynchronized tree) {
675 try {
676 print("synchronized ");
677 if (tree.lock.getTag() == JCTree.PARENS) {
678 printExpr(tree.lock);
679 } else {
680 print("(");
681 printExpr(tree.lock);
682 print(")");
683 }
684 print(" ");
685 printStat(tree.body);
686 } catch (IOException e) {
687 throw new UncheckedIOException(e);
688 }
689 }
691 public void visitTry(JCTry tree) {
692 try {
693 print("try ");
694 if (tree.resources.nonEmpty()) {
695 print("(");
696 boolean first = true;
697 for (JCTree var : tree.resources) {
698 if (!first) {
699 println();
700 indent();
701 }
702 printStat(var);
703 first = false;
704 }
705 print(") ");
706 }
707 printStat(tree.body);
708 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
709 printStat(l.head);
710 }
711 if (tree.finalizer != null) {
712 print(" finally ");
713 printStat(tree.finalizer);
714 }
715 } catch (IOException e) {
716 throw new UncheckedIOException(e);
717 }
718 }
720 public void visitCatch(JCCatch tree) {
721 try {
722 print(" catch (");
723 printExpr(tree.param);
724 print(") ");
725 printStat(tree.body);
726 } catch (IOException e) {
727 throw new UncheckedIOException(e);
728 }
729 }
731 public void visitConditional(JCConditional tree) {
732 try {
733 open(prec, TreeInfo.condPrec);
734 printExpr(tree.cond, TreeInfo.condPrec);
735 print(" ? ");
736 printExpr(tree.truepart, TreeInfo.condPrec);
737 print(" : ");
738 printExpr(tree.falsepart, TreeInfo.condPrec);
739 close(prec, TreeInfo.condPrec);
740 } catch (IOException e) {
741 throw new UncheckedIOException(e);
742 }
743 }
745 public void visitIf(JCIf tree) {
746 try {
747 print("if ");
748 if (tree.cond.getTag() == JCTree.PARENS) {
749 printExpr(tree.cond);
750 } else {
751 print("(");
752 printExpr(tree.cond);
753 print(")");
754 }
755 print(" ");
756 printStat(tree.thenpart);
757 if (tree.elsepart != null) {
758 print(" else ");
759 printStat(tree.elsepart);
760 }
761 } catch (IOException e) {
762 throw new UncheckedIOException(e);
763 }
764 }
766 public void visitExec(JCExpressionStatement tree) {
767 try {
768 printExpr(tree.expr);
769 if (prec == TreeInfo.notExpression) print(";");
770 } catch (IOException e) {
771 throw new UncheckedIOException(e);
772 }
773 }
775 public void visitBreak(JCBreak tree) {
776 try {
777 print("break");
778 if (tree.label != null) print(" " + tree.label);
779 print(";");
780 } catch (IOException e) {
781 throw new UncheckedIOException(e);
782 }
783 }
785 public void visitContinue(JCContinue tree) {
786 try {
787 print("continue");
788 if (tree.label != null) print(" " + tree.label);
789 print(";");
790 } catch (IOException e) {
791 throw new UncheckedIOException(e);
792 }
793 }
795 public void visitReturn(JCReturn tree) {
796 try {
797 print("return");
798 if (tree.expr != null) {
799 print(" ");
800 printExpr(tree.expr);
801 }
802 print(";");
803 } catch (IOException e) {
804 throw new UncheckedIOException(e);
805 }
806 }
808 public void visitThrow(JCThrow tree) {
809 try {
810 print("throw ");
811 printExpr(tree.expr);
812 print(";");
813 } catch (IOException e) {
814 throw new UncheckedIOException(e);
815 }
816 }
818 public void visitAssert(JCAssert tree) {
819 try {
820 print("assert ");
821 printExpr(tree.cond);
822 if (tree.detail != null) {
823 print(" : ");
824 printExpr(tree.detail);
825 }
826 print(";");
827 } catch (IOException e) {
828 throw new UncheckedIOException(e);
829 }
830 }
832 public void visitApply(JCMethodInvocation tree) {
833 try {
834 if (!tree.typeargs.isEmpty()) {
835 if (tree.meth.getTag() == JCTree.SELECT) {
836 JCFieldAccess left = (JCFieldAccess)tree.meth;
837 printExpr(left.selected);
838 print(".<");
839 printExprs(tree.typeargs);
840 print(">" + left.name);
841 } else {
842 print("<");
843 printExprs(tree.typeargs);
844 print(">");
845 printExpr(tree.meth);
846 }
847 } else {
848 printExpr(tree.meth);
849 }
850 print("(");
851 printExprs(tree.args);
852 print(")");
853 } catch (IOException e) {
854 throw new UncheckedIOException(e);
855 }
856 }
858 public void visitNewClass(JCNewClass tree) {
859 try {
860 if (tree.encl != null) {
861 printExpr(tree.encl);
862 print(".");
863 }
864 print("new ");
865 if (!tree.typeargs.isEmpty()) {
866 print("<");
867 printExprs(tree.typeargs);
868 print(">");
869 }
870 printExpr(tree.clazz);
871 print("(");
872 printExprs(tree.args);
873 print(")");
874 if (tree.def != null) {
875 Name enclClassNamePrev = enclClassName;
876 enclClassName =
877 tree.def.name != null ? tree.def.name :
878 tree.type != null && tree.type.tsym.name != tree.type.tsym.name.table.names.empty
879 ? tree.type.tsym.name : null;
880 if ((tree.def.mods.flags & Flags.ENUM) != 0) print("/*enum*/");
881 printBlock(tree.def.defs);
882 enclClassName = enclClassNamePrev;
883 }
884 } catch (IOException e) {
885 throw new UncheckedIOException(e);
886 }
887 }
889 public void visitNewArray(JCNewArray tree) {
890 try {
891 if (tree.elemtype != null) {
892 print("new ");
893 printTypeAnnotations(tree.annotations);
894 JCTree elem = tree.elemtype;
895 printBaseElementType(elem);
896 boolean isElemAnnoType = elem instanceof JCAnnotatedType;
897 int i = 0;
898 List<List<JCTypeAnnotation>> da = tree.dimAnnotations;
899 for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
900 if (da.size() > i) {
901 printTypeAnnotations(da.get(i));
902 }
903 print("[");
904 i++;
905 printExpr(l.head);
906 print("]");
907 }
908 if (tree.elems != null) {
909 if (isElemAnnoType) {
910 printTypeAnnotations(((JCAnnotatedType)tree.elemtype).annotations);
911 }
912 print("[]");
913 }
914 if (isElemAnnoType)
915 elem = ((JCAnnotatedType)elem).underlyingType;
916 if (elem instanceof JCArrayTypeTree)
917 printBrackets((JCArrayTypeTree) elem);
918 }
919 if (tree.elems != null) {
920 print("{");
921 printExprs(tree.elems);
922 print("}");
923 }
924 } catch (IOException e) {
925 throw new UncheckedIOException(e);
926 }
927 }
929 public void visitParens(JCParens tree) {
930 try {
931 print("(");
932 printExpr(tree.expr);
933 print(")");
934 } catch (IOException e) {
935 throw new UncheckedIOException(e);
936 }
937 }
939 public void visitAssign(JCAssign tree) {
940 try {
941 open(prec, TreeInfo.assignPrec);
942 printExpr(tree.lhs, TreeInfo.assignPrec + 1);
943 print(" = ");
944 printExpr(tree.rhs, TreeInfo.assignPrec);
945 close(prec, TreeInfo.assignPrec);
946 } catch (IOException e) {
947 throw new UncheckedIOException(e);
948 }
949 }
951 public String operatorName(int tag) {
952 switch(tag) {
953 case JCTree.POS: return "+";
954 case JCTree.NEG: return "-";
955 case JCTree.NOT: return "!";
956 case JCTree.COMPL: return "~";
957 case JCTree.PREINC: return "++";
958 case JCTree.PREDEC: return "--";
959 case JCTree.POSTINC: return "++";
960 case JCTree.POSTDEC: return "--";
961 case JCTree.NULLCHK: return "<*nullchk*>";
962 case JCTree.OR: return "||";
963 case JCTree.AND: return "&&";
964 case JCTree.EQ: return "==";
965 case JCTree.NE: return "!=";
966 case JCTree.LT: return "<";
967 case JCTree.GT: return ">";
968 case JCTree.LE: return "<=";
969 case JCTree.GE: return ">=";
970 case JCTree.BITOR: return "|";
971 case JCTree.BITXOR: return "^";
972 case JCTree.BITAND: return "&";
973 case JCTree.SL: return "<<";
974 case JCTree.SR: return ">>";
975 case JCTree.USR: return ">>>";
976 case JCTree.PLUS: return "+";
977 case JCTree.MINUS: return "-";
978 case JCTree.MUL: return "*";
979 case JCTree.DIV: return "/";
980 case JCTree.MOD: return "%";
981 default: throw new Error();
982 }
983 }
985 public void visitAssignop(JCAssignOp tree) {
986 try {
987 open(prec, TreeInfo.assignopPrec);
988 printExpr(tree.lhs, TreeInfo.assignopPrec + 1);
989 print(" " + operatorName(tree.getTag() - JCTree.ASGOffset) + "= ");
990 printExpr(tree.rhs, TreeInfo.assignopPrec);
991 close(prec, TreeInfo.assignopPrec);
992 } catch (IOException e) {
993 throw new UncheckedIOException(e);
994 }
995 }
997 public void visitUnary(JCUnary tree) {
998 try {
999 int ownprec = TreeInfo.opPrec(tree.getTag());
1000 String opname = operatorName(tree.getTag());
1001 open(prec, ownprec);
1002 if (tree.getTag() <= JCTree.PREDEC) {
1003 print(opname);
1004 printExpr(tree.arg, ownprec);
1005 } else {
1006 printExpr(tree.arg, ownprec);
1007 print(opname);
1008 }
1009 close(prec, ownprec);
1010 } catch (IOException e) {
1011 throw new UncheckedIOException(e);
1012 }
1013 }
1015 public void visitBinary(JCBinary tree) {
1016 try {
1017 int ownprec = TreeInfo.opPrec(tree.getTag());
1018 String opname = operatorName(tree.getTag());
1019 open(prec, ownprec);
1020 printExpr(tree.lhs, ownprec);
1021 print(" " + opname + " ");
1022 printExpr(tree.rhs, ownprec + 1);
1023 close(prec, ownprec);
1024 } catch (IOException e) {
1025 throw new UncheckedIOException(e);
1026 }
1027 }
1029 public void visitTypeCast(JCTypeCast tree) {
1030 try {
1031 open(prec, TreeInfo.prefixPrec);
1032 print("(");
1033 printExpr(tree.clazz);
1034 print(")");
1035 printExpr(tree.expr, TreeInfo.prefixPrec);
1036 close(prec, TreeInfo.prefixPrec);
1037 } catch (IOException e) {
1038 throw new UncheckedIOException(e);
1039 }
1040 }
1042 public void visitTypeTest(JCInstanceOf tree) {
1043 try {
1044 open(prec, TreeInfo.ordPrec);
1045 printExpr(tree.expr, TreeInfo.ordPrec);
1046 print(" instanceof ");
1047 printExpr(tree.clazz, TreeInfo.ordPrec + 1);
1048 close(prec, TreeInfo.ordPrec);
1049 } catch (IOException e) {
1050 throw new UncheckedIOException(e);
1051 }
1052 }
1054 public void visitIndexed(JCArrayAccess tree) {
1055 try {
1056 printExpr(tree.indexed, TreeInfo.postfixPrec);
1057 print("[");
1058 printExpr(tree.index);
1059 print("]");
1060 } catch (IOException e) {
1061 throw new UncheckedIOException(e);
1062 }
1063 }
1065 public void visitSelect(JCFieldAccess tree) {
1066 try {
1067 printExpr(tree.selected, TreeInfo.postfixPrec);
1068 print("." + tree.name);
1069 } catch (IOException e) {
1070 throw new UncheckedIOException(e);
1071 }
1072 }
1074 public void visitIdent(JCIdent tree) {
1075 try {
1076 print(tree.name);
1077 } catch (IOException e) {
1078 throw new UncheckedIOException(e);
1079 }
1080 }
1082 public void visitLiteral(JCLiteral tree) {
1083 try {
1084 switch (tree.typetag) {
1085 case TypeTags.INT:
1086 print(tree.value.toString());
1087 break;
1088 case TypeTags.LONG:
1089 print(tree.value + "L");
1090 break;
1091 case TypeTags.FLOAT:
1092 print(tree.value + "F");
1093 break;
1094 case TypeTags.DOUBLE:
1095 print(tree.value.toString());
1096 break;
1097 case TypeTags.CHAR:
1098 print("\'" +
1099 Convert.quote(
1100 String.valueOf((char)((Number)tree.value).intValue())) +
1101 "\'");
1102 break;
1103 case TypeTags.BOOLEAN:
1104 print(((Number)tree.value).intValue() == 1 ? "true" : "false");
1105 break;
1106 case TypeTags.BOT:
1107 print("null");
1108 break;
1109 default:
1110 print("\"" + Convert.quote(tree.value.toString()) + "\"");
1111 break;
1112 }
1113 } catch (IOException e) {
1114 throw new UncheckedIOException(e);
1115 }
1116 }
1118 public void visitTypeIdent(JCPrimitiveTypeTree tree) {
1119 try {
1120 switch(tree.typetag) {
1121 case TypeTags.BYTE:
1122 print("byte");
1123 break;
1124 case TypeTags.CHAR:
1125 print("char");
1126 break;
1127 case TypeTags.SHORT:
1128 print("short");
1129 break;
1130 case TypeTags.INT:
1131 print("int");
1132 break;
1133 case TypeTags.LONG:
1134 print("long");
1135 break;
1136 case TypeTags.FLOAT:
1137 print("float");
1138 break;
1139 case TypeTags.DOUBLE:
1140 print("double");
1141 break;
1142 case TypeTags.BOOLEAN:
1143 print("boolean");
1144 break;
1145 case TypeTags.VOID:
1146 print("void");
1147 break;
1148 default:
1149 print("error");
1150 break;
1151 }
1152 } catch (IOException e) {
1153 throw new UncheckedIOException(e);
1154 }
1155 }
1157 public void visitTypeArray(JCArrayTypeTree tree) {
1158 try {
1159 printBaseElementType(tree);
1160 printBrackets(tree);
1161 } catch (IOException e) {
1162 throw new UncheckedIOException(e);
1163 }
1164 }
1166 // Prints the inner element type of a nested array
1167 private void printBaseElementType(JCTree tree) throws IOException {
1168 printExpr(TreeInfo.innermostType(tree));
1169 }
1171 // prints the brackets of a nested array in reverse order
1172 private void printBrackets(JCArrayTypeTree tree) throws IOException {
1173 JCTree elem;
1174 while (true) {
1175 elem = tree.elemtype;
1176 if (elem.getTag() == JCTree.ANNOTATED_TYPE) {
1177 JCAnnotatedType atype = (JCAnnotatedType) elem;
1178 printTypeAnnotations(atype.annotations);
1179 elem = atype.underlyingType;
1180 }
1181 print("[]");
1182 if (elem.getTag() != JCTree.TYPEARRAY) break;
1183 tree = (JCArrayTypeTree) elem;
1184 }
1185 }
1187 public void visitTypeApply(JCTypeApply tree) {
1188 try {
1189 printExpr(tree.clazz);
1190 print("<");
1191 printExprs(tree.arguments);
1192 print(">");
1193 } catch (IOException e) {
1194 throw new UncheckedIOException(e);
1195 }
1196 }
1198 public void visitTypeDisjoint(JCTypeDisjoint tree) {
1199 try {
1200 printExprs(tree.components, " | ");
1201 } catch (IOException e) {
1202 throw new UncheckedIOException(e);
1203 }
1204 }
1206 public void visitTypeParameter(JCTypeParameter tree) {
1207 try {
1208 print(tree.name);
1209 if (tree.bounds.nonEmpty()) {
1210 print(" extends ");
1211 printExprs(tree.bounds, " & ");
1212 }
1213 } catch (IOException e) {
1214 throw new UncheckedIOException(e);
1215 }
1216 }
1218 @Override
1219 public void visitWildcard(JCWildcard tree) {
1220 try {
1221 print(tree.kind);
1222 if (tree.kind.kind != BoundKind.UNBOUND)
1223 printExpr(tree.inner);
1224 } catch (IOException e) {
1225 throw new UncheckedIOException(e);
1226 }
1227 }
1229 @Override
1230 public void visitTypeBoundKind(TypeBoundKind tree) {
1231 try {
1232 print(String.valueOf(tree.kind));
1233 } catch (IOException e) {
1234 throw new UncheckedIOException(e);
1235 }
1236 }
1238 public void visitErroneous(JCErroneous tree) {
1239 try {
1240 print("(ERROR)");
1241 } catch (IOException e) {
1242 throw new UncheckedIOException(e);
1243 }
1244 }
1246 public void visitLetExpr(LetExpr tree) {
1247 try {
1248 print("(let " + tree.defs + " in " + tree.expr + ")");
1249 } catch (IOException e) {
1250 throw new UncheckedIOException(e);
1251 }
1252 }
1254 public void visitModifiers(JCModifiers mods) {
1255 try {
1256 printAnnotations(mods.annotations);
1257 printFlags(mods.flags);
1258 } catch (IOException e) {
1259 throw new UncheckedIOException(e);
1260 }
1261 }
1263 public void visitAnnotation(JCAnnotation tree) {
1264 try {
1265 print("@");
1266 printExpr(tree.annotationType);
1267 print("(");
1268 printExprs(tree.args);
1269 print(")");
1270 } catch (IOException e) {
1271 throw new UncheckedIOException(e);
1272 }
1273 }
1275 public void visitAnnotatedType(JCAnnotatedType tree) {
1276 try {
1277 printTypeAnnotations(tree.annotations);
1278 printExpr(tree.underlyingType);
1279 } catch (IOException e) {
1280 throw new UncheckedIOException(e);
1281 }
1282 }
1284 public void visitTree(JCTree tree) {
1285 try {
1286 print("(UNKNOWN: " + tree + ")");
1287 println();
1288 } catch (IOException e) {
1289 throw new UncheckedIOException(e);
1290 }
1291 }
1293 }