Wed, 06 Apr 2011 19:30:57 -0700
7033809: Rename "disjunctive" to "union" in javax.lang.model
Reviewed-by: mcimadamore, jjg
1 /*
2 * Copyright (c) 1999, 2011, 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 /** 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.defaultValue != null) {
463 print(" default ");
464 printExpr(tree.defaultValue);
465 }
466 if (tree.body != null) {
467 print(" ");
468 printStat(tree.body);
469 } else {
470 print(";");
471 }
472 } catch (IOException e) {
473 throw new UncheckedIOException(e);
474 }
475 }
477 public void visitVarDef(JCVariableDecl tree) {
478 try {
479 if (docComments != null && docComments.get(tree) != null) {
480 println(); align();
481 }
482 printDocComment(tree);
483 if ((tree.mods.flags & ENUM) != 0) {
484 print("/*public static final*/ ");
485 print(tree.name);
486 if (tree.init != null) {
487 if (sourceOutput && tree.init.getTag() == JCTree.NEWCLASS) {
488 print(" /*enum*/ ");
489 JCNewClass init = (JCNewClass) tree.init;
490 if (init.args != null && init.args.nonEmpty()) {
491 print("(");
492 print(init.args);
493 print(")");
494 }
495 if (init.def != null && init.def.defs != null) {
496 print(" ");
497 printBlock(init.def.defs);
498 }
499 return;
500 }
501 print(" /* = ");
502 printExpr(tree.init);
503 print(" */");
504 }
505 } else {
506 printExpr(tree.mods);
507 if ((tree.mods.flags & VARARGS) != 0) {
508 printExpr(((JCArrayTypeTree) tree.vartype).elemtype);
509 print("... " + tree.name);
510 } else {
511 printExpr(tree.vartype);
512 print(" " + tree.name);
513 }
514 if (tree.init != null) {
515 print(" = ");
516 printExpr(tree.init);
517 }
518 if (prec == TreeInfo.notExpression) print(";");
519 }
520 } catch (IOException e) {
521 throw new UncheckedIOException(e);
522 }
523 }
525 public void visitSkip(JCSkip tree) {
526 try {
527 print(";");
528 } catch (IOException e) {
529 throw new UncheckedIOException(e);
530 }
531 }
533 public void visitBlock(JCBlock tree) {
534 try {
535 printFlags(tree.flags);
536 printBlock(tree.stats);
537 } catch (IOException e) {
538 throw new UncheckedIOException(e);
539 }
540 }
542 public void visitDoLoop(JCDoWhileLoop tree) {
543 try {
544 print("do ");
545 printStat(tree.body);
546 align();
547 print(" while ");
548 if (tree.cond.getTag() == JCTree.PARENS) {
549 printExpr(tree.cond);
550 } else {
551 print("(");
552 printExpr(tree.cond);
553 print(")");
554 }
555 print(";");
556 } catch (IOException e) {
557 throw new UncheckedIOException(e);
558 }
559 }
561 public void visitWhileLoop(JCWhileLoop tree) {
562 try {
563 print("while ");
564 if (tree.cond.getTag() == JCTree.PARENS) {
565 printExpr(tree.cond);
566 } else {
567 print("(");
568 printExpr(tree.cond);
569 print(")");
570 }
571 print(" ");
572 printStat(tree.body);
573 } catch (IOException e) {
574 throw new UncheckedIOException(e);
575 }
576 }
578 public void visitForLoop(JCForLoop tree) {
579 try {
580 print("for (");
581 if (tree.init.nonEmpty()) {
582 if (tree.init.head.getTag() == JCTree.VARDEF) {
583 printExpr(tree.init.head);
584 for (List<JCStatement> l = tree.init.tail; l.nonEmpty(); l = l.tail) {
585 JCVariableDecl vdef = (JCVariableDecl)l.head;
586 print(", " + vdef.name + " = ");
587 printExpr(vdef.init);
588 }
589 } else {
590 printExprs(tree.init);
591 }
592 }
593 print("; ");
594 if (tree.cond != null) printExpr(tree.cond);
595 print("; ");
596 printExprs(tree.step);
597 print(") ");
598 printStat(tree.body);
599 } catch (IOException e) {
600 throw new UncheckedIOException(e);
601 }
602 }
604 public void visitForeachLoop(JCEnhancedForLoop tree) {
605 try {
606 print("for (");
607 printExpr(tree.var);
608 print(" : ");
609 printExpr(tree.expr);
610 print(") ");
611 printStat(tree.body);
612 } catch (IOException e) {
613 throw new UncheckedIOException(e);
614 }
615 }
617 public void visitLabelled(JCLabeledStatement tree) {
618 try {
619 print(tree.label + ": ");
620 printStat(tree.body);
621 } catch (IOException e) {
622 throw new UncheckedIOException(e);
623 }
624 }
626 public void visitSwitch(JCSwitch tree) {
627 try {
628 print("switch ");
629 if (tree.selector.getTag() == JCTree.PARENS) {
630 printExpr(tree.selector);
631 } else {
632 print("(");
633 printExpr(tree.selector);
634 print(")");
635 }
636 print(" {");
637 println();
638 printStats(tree.cases);
639 align();
640 print("}");
641 } catch (IOException e) {
642 throw new UncheckedIOException(e);
643 }
644 }
646 public void visitCase(JCCase tree) {
647 try {
648 if (tree.pat == null) {
649 print("default");
650 } else {
651 print("case ");
652 printExpr(tree.pat);
653 }
654 print(": ");
655 println();
656 indent();
657 printStats(tree.stats);
658 undent();
659 align();
660 } catch (IOException e) {
661 throw new UncheckedIOException(e);
662 }
663 }
665 public void visitSynchronized(JCSynchronized tree) {
666 try {
667 print("synchronized ");
668 if (tree.lock.getTag() == JCTree.PARENS) {
669 printExpr(tree.lock);
670 } else {
671 print("(");
672 printExpr(tree.lock);
673 print(")");
674 }
675 print(" ");
676 printStat(tree.body);
677 } catch (IOException e) {
678 throw new UncheckedIOException(e);
679 }
680 }
682 public void visitTry(JCTry tree) {
683 try {
684 print("try ");
685 if (tree.resources.nonEmpty()) {
686 print("(");
687 boolean first = true;
688 for (JCTree var : tree.resources) {
689 if (!first) {
690 println();
691 indent();
692 }
693 printStat(var);
694 first = false;
695 }
696 print(") ");
697 }
698 printStat(tree.body);
699 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
700 printStat(l.head);
701 }
702 if (tree.finalizer != null) {
703 print(" finally ");
704 printStat(tree.finalizer);
705 }
706 } catch (IOException e) {
707 throw new UncheckedIOException(e);
708 }
709 }
711 public void visitCatch(JCCatch tree) {
712 try {
713 print(" catch (");
714 printExpr(tree.param);
715 print(") ");
716 printStat(tree.body);
717 } catch (IOException e) {
718 throw new UncheckedIOException(e);
719 }
720 }
722 public void visitConditional(JCConditional tree) {
723 try {
724 open(prec, TreeInfo.condPrec);
725 printExpr(tree.cond, TreeInfo.condPrec);
726 print(" ? ");
727 printExpr(tree.truepart, TreeInfo.condPrec);
728 print(" : ");
729 printExpr(tree.falsepart, TreeInfo.condPrec);
730 close(prec, TreeInfo.condPrec);
731 } catch (IOException e) {
732 throw new UncheckedIOException(e);
733 }
734 }
736 public void visitIf(JCIf tree) {
737 try {
738 print("if ");
739 if (tree.cond.getTag() == JCTree.PARENS) {
740 printExpr(tree.cond);
741 } else {
742 print("(");
743 printExpr(tree.cond);
744 print(")");
745 }
746 print(" ");
747 printStat(tree.thenpart);
748 if (tree.elsepart != null) {
749 print(" else ");
750 printStat(tree.elsepart);
751 }
752 } catch (IOException e) {
753 throw new UncheckedIOException(e);
754 }
755 }
757 public void visitExec(JCExpressionStatement tree) {
758 try {
759 printExpr(tree.expr);
760 if (prec == TreeInfo.notExpression) print(";");
761 } catch (IOException e) {
762 throw new UncheckedIOException(e);
763 }
764 }
766 public void visitBreak(JCBreak tree) {
767 try {
768 print("break");
769 if (tree.label != null) print(" " + tree.label);
770 print(";");
771 } catch (IOException e) {
772 throw new UncheckedIOException(e);
773 }
774 }
776 public void visitContinue(JCContinue tree) {
777 try {
778 print("continue");
779 if (tree.label != null) print(" " + tree.label);
780 print(";");
781 } catch (IOException e) {
782 throw new UncheckedIOException(e);
783 }
784 }
786 public void visitReturn(JCReturn tree) {
787 try {
788 print("return");
789 if (tree.expr != null) {
790 print(" ");
791 printExpr(tree.expr);
792 }
793 print(";");
794 } catch (IOException e) {
795 throw new UncheckedIOException(e);
796 }
797 }
799 public void visitThrow(JCThrow tree) {
800 try {
801 print("throw ");
802 printExpr(tree.expr);
803 print(";");
804 } catch (IOException e) {
805 throw new UncheckedIOException(e);
806 }
807 }
809 public void visitAssert(JCAssert tree) {
810 try {
811 print("assert ");
812 printExpr(tree.cond);
813 if (tree.detail != null) {
814 print(" : ");
815 printExpr(tree.detail);
816 }
817 print(";");
818 } catch (IOException e) {
819 throw new UncheckedIOException(e);
820 }
821 }
823 public void visitApply(JCMethodInvocation tree) {
824 try {
825 if (!tree.typeargs.isEmpty()) {
826 if (tree.meth.getTag() == JCTree.SELECT) {
827 JCFieldAccess left = (JCFieldAccess)tree.meth;
828 printExpr(left.selected);
829 print(".<");
830 printExprs(tree.typeargs);
831 print(">" + left.name);
832 } else {
833 print("<");
834 printExprs(tree.typeargs);
835 print(">");
836 printExpr(tree.meth);
837 }
838 } else {
839 printExpr(tree.meth);
840 }
841 print("(");
842 printExprs(tree.args);
843 print(")");
844 } catch (IOException e) {
845 throw new UncheckedIOException(e);
846 }
847 }
849 public void visitNewClass(JCNewClass tree) {
850 try {
851 if (tree.encl != null) {
852 printExpr(tree.encl);
853 print(".");
854 }
855 print("new ");
856 if (!tree.typeargs.isEmpty()) {
857 print("<");
858 printExprs(tree.typeargs);
859 print(">");
860 }
861 printExpr(tree.clazz);
862 print("(");
863 printExprs(tree.args);
864 print(")");
865 if (tree.def != null) {
866 Name enclClassNamePrev = enclClassName;
867 enclClassName =
868 tree.def.name != null ? tree.def.name :
869 tree.type != null && tree.type.tsym.name != tree.type.tsym.name.table.names.empty
870 ? tree.type.tsym.name : null;
871 if ((tree.def.mods.flags & Flags.ENUM) != 0) print("/*enum*/");
872 printBlock(tree.def.defs);
873 enclClassName = enclClassNamePrev;
874 }
875 } catch (IOException e) {
876 throw new UncheckedIOException(e);
877 }
878 }
880 public void visitNewArray(JCNewArray tree) {
881 try {
882 if (tree.elemtype != null) {
883 print("new ");
884 JCTree elem = tree.elemtype;
885 if (elem.getTag() == JCTree.TYPEARRAY)
886 printBaseElementType((JCArrayTypeTree) elem);
887 else
888 printExpr(elem);
889 for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
890 print("[");
891 printExpr(l.head);
892 print("]");
893 }
894 if (elem instanceof JCArrayTypeTree)
895 printBrackets((JCArrayTypeTree) elem);
896 }
897 if (tree.elems != null) {
898 if (tree.elemtype != null) print("[]");
899 print("{");
900 printExprs(tree.elems);
901 print("}");
902 }
903 } catch (IOException e) {
904 throw new UncheckedIOException(e);
905 }
906 }
908 public void visitParens(JCParens tree) {
909 try {
910 print("(");
911 printExpr(tree.expr);
912 print(")");
913 } catch (IOException e) {
914 throw new UncheckedIOException(e);
915 }
916 }
918 public void visitAssign(JCAssign tree) {
919 try {
920 open(prec, TreeInfo.assignPrec);
921 printExpr(tree.lhs, TreeInfo.assignPrec + 1);
922 print(" = ");
923 printExpr(tree.rhs, TreeInfo.assignPrec);
924 close(prec, TreeInfo.assignPrec);
925 } catch (IOException e) {
926 throw new UncheckedIOException(e);
927 }
928 }
930 public String operatorName(int tag) {
931 switch(tag) {
932 case JCTree.POS: return "+";
933 case JCTree.NEG: return "-";
934 case JCTree.NOT: return "!";
935 case JCTree.COMPL: return "~";
936 case JCTree.PREINC: return "++";
937 case JCTree.PREDEC: return "--";
938 case JCTree.POSTINC: return "++";
939 case JCTree.POSTDEC: return "--";
940 case JCTree.NULLCHK: return "<*nullchk*>";
941 case JCTree.OR: return "||";
942 case JCTree.AND: return "&&";
943 case JCTree.EQ: return "==";
944 case JCTree.NE: return "!=";
945 case JCTree.LT: return "<";
946 case JCTree.GT: return ">";
947 case JCTree.LE: return "<=";
948 case JCTree.GE: return ">=";
949 case JCTree.BITOR: return "|";
950 case JCTree.BITXOR: return "^";
951 case JCTree.BITAND: return "&";
952 case JCTree.SL: return "<<";
953 case JCTree.SR: return ">>";
954 case JCTree.USR: return ">>>";
955 case JCTree.PLUS: return "+";
956 case JCTree.MINUS: return "-";
957 case JCTree.MUL: return "*";
958 case JCTree.DIV: return "/";
959 case JCTree.MOD: return "%";
960 default: throw new Error();
961 }
962 }
964 public void visitAssignop(JCAssignOp tree) {
965 try {
966 open(prec, TreeInfo.assignopPrec);
967 printExpr(tree.lhs, TreeInfo.assignopPrec + 1);
968 print(" " + operatorName(tree.getTag() - JCTree.ASGOffset) + "= ");
969 printExpr(tree.rhs, TreeInfo.assignopPrec);
970 close(prec, TreeInfo.assignopPrec);
971 } catch (IOException e) {
972 throw new UncheckedIOException(e);
973 }
974 }
976 public void visitUnary(JCUnary tree) {
977 try {
978 int ownprec = TreeInfo.opPrec(tree.getTag());
979 String opname = operatorName(tree.getTag());
980 open(prec, ownprec);
981 if (tree.getTag() <= JCTree.PREDEC) {
982 print(opname);
983 printExpr(tree.arg, ownprec);
984 } else {
985 printExpr(tree.arg, ownprec);
986 print(opname);
987 }
988 close(prec, ownprec);
989 } catch (IOException e) {
990 throw new UncheckedIOException(e);
991 }
992 }
994 public void visitBinary(JCBinary tree) {
995 try {
996 int ownprec = TreeInfo.opPrec(tree.getTag());
997 String opname = operatorName(tree.getTag());
998 open(prec, ownprec);
999 printExpr(tree.lhs, ownprec);
1000 print(" " + opname + " ");
1001 printExpr(tree.rhs, ownprec + 1);
1002 close(prec, ownprec);
1003 } catch (IOException e) {
1004 throw new UncheckedIOException(e);
1005 }
1006 }
1008 public void visitTypeCast(JCTypeCast tree) {
1009 try {
1010 open(prec, TreeInfo.prefixPrec);
1011 print("(");
1012 printExpr(tree.clazz);
1013 print(")");
1014 printExpr(tree.expr, TreeInfo.prefixPrec);
1015 close(prec, TreeInfo.prefixPrec);
1016 } catch (IOException e) {
1017 throw new UncheckedIOException(e);
1018 }
1019 }
1021 public void visitTypeTest(JCInstanceOf tree) {
1022 try {
1023 open(prec, TreeInfo.ordPrec);
1024 printExpr(tree.expr, TreeInfo.ordPrec);
1025 print(" instanceof ");
1026 printExpr(tree.clazz, TreeInfo.ordPrec + 1);
1027 close(prec, TreeInfo.ordPrec);
1028 } catch (IOException e) {
1029 throw new UncheckedIOException(e);
1030 }
1031 }
1033 public void visitIndexed(JCArrayAccess tree) {
1034 try {
1035 printExpr(tree.indexed, TreeInfo.postfixPrec);
1036 print("[");
1037 printExpr(tree.index);
1038 print("]");
1039 } catch (IOException e) {
1040 throw new UncheckedIOException(e);
1041 }
1042 }
1044 public void visitSelect(JCFieldAccess tree) {
1045 try {
1046 printExpr(tree.selected, TreeInfo.postfixPrec);
1047 print("." + tree.name);
1048 } catch (IOException e) {
1049 throw new UncheckedIOException(e);
1050 }
1051 }
1053 public void visitIdent(JCIdent tree) {
1054 try {
1055 print(tree.name);
1056 } catch (IOException e) {
1057 throw new UncheckedIOException(e);
1058 }
1059 }
1061 public void visitLiteral(JCLiteral tree) {
1062 try {
1063 switch (tree.typetag) {
1064 case TypeTags.INT:
1065 print(tree.value.toString());
1066 break;
1067 case TypeTags.LONG:
1068 print(tree.value + "L");
1069 break;
1070 case TypeTags.FLOAT:
1071 print(tree.value + "F");
1072 break;
1073 case TypeTags.DOUBLE:
1074 print(tree.value.toString());
1075 break;
1076 case TypeTags.CHAR:
1077 print("\'" +
1078 Convert.quote(
1079 String.valueOf((char)((Number)tree.value).intValue())) +
1080 "\'");
1081 break;
1082 case TypeTags.BOOLEAN:
1083 print(((Number)tree.value).intValue() == 1 ? "true" : "false");
1084 break;
1085 case TypeTags.BOT:
1086 print("null");
1087 break;
1088 default:
1089 print("\"" + Convert.quote(tree.value.toString()) + "\"");
1090 break;
1091 }
1092 } catch (IOException e) {
1093 throw new UncheckedIOException(e);
1094 }
1095 }
1097 public void visitTypeIdent(JCPrimitiveTypeTree tree) {
1098 try {
1099 switch(tree.typetag) {
1100 case TypeTags.BYTE:
1101 print("byte");
1102 break;
1103 case TypeTags.CHAR:
1104 print("char");
1105 break;
1106 case TypeTags.SHORT:
1107 print("short");
1108 break;
1109 case TypeTags.INT:
1110 print("int");
1111 break;
1112 case TypeTags.LONG:
1113 print("long");
1114 break;
1115 case TypeTags.FLOAT:
1116 print("float");
1117 break;
1118 case TypeTags.DOUBLE:
1119 print("double");
1120 break;
1121 case TypeTags.BOOLEAN:
1122 print("boolean");
1123 break;
1124 case TypeTags.VOID:
1125 print("void");
1126 break;
1127 default:
1128 print("error");
1129 break;
1130 }
1131 } catch (IOException e) {
1132 throw new UncheckedIOException(e);
1133 }
1134 }
1136 public void visitTypeArray(JCArrayTypeTree tree) {
1137 try {
1138 printBaseElementType(tree);
1139 printBrackets(tree);
1140 } catch (IOException e) {
1141 throw new UncheckedIOException(e);
1142 }
1143 }
1145 // Prints the inner element type of a nested array
1146 private void printBaseElementType(JCTree tree) throws IOException {
1147 printExpr(TreeInfo.innermostType(tree));
1148 }
1150 // prints the brackets of a nested array in reverse order
1151 private void printBrackets(JCArrayTypeTree tree) throws IOException {
1152 JCTree elem;
1153 while (true) {
1154 elem = tree.elemtype;
1155 print("[]");
1156 if (elem.getTag() != JCTree.TYPEARRAY) break;
1157 tree = (JCArrayTypeTree) elem;
1158 }
1159 }
1161 public void visitTypeApply(JCTypeApply tree) {
1162 try {
1163 printExpr(tree.clazz);
1164 print("<");
1165 printExprs(tree.arguments);
1166 print(">");
1167 } catch (IOException e) {
1168 throw new UncheckedIOException(e);
1169 }
1170 }
1172 public void visitTypeUnion(JCTypeUnion tree) {
1173 try {
1174 printExprs(tree.alternatives, " | ");
1175 } catch (IOException e) {
1176 throw new UncheckedIOException(e);
1177 }
1178 }
1180 public void visitTypeParameter(JCTypeParameter tree) {
1181 try {
1182 print(tree.name);
1183 if (tree.bounds.nonEmpty()) {
1184 print(" extends ");
1185 printExprs(tree.bounds, " & ");
1186 }
1187 } catch (IOException e) {
1188 throw new UncheckedIOException(e);
1189 }
1190 }
1192 @Override
1193 public void visitWildcard(JCWildcard tree) {
1194 try {
1195 print(tree.kind);
1196 if (tree.kind.kind != BoundKind.UNBOUND)
1197 printExpr(tree.inner);
1198 } catch (IOException e) {
1199 throw new UncheckedIOException(e);
1200 }
1201 }
1203 @Override
1204 public void visitTypeBoundKind(TypeBoundKind tree) {
1205 try {
1206 print(String.valueOf(tree.kind));
1207 } catch (IOException e) {
1208 throw new UncheckedIOException(e);
1209 }
1210 }
1212 public void visitErroneous(JCErroneous tree) {
1213 try {
1214 print("(ERROR)");
1215 } catch (IOException e) {
1216 throw new UncheckedIOException(e);
1217 }
1218 }
1220 public void visitLetExpr(LetExpr tree) {
1221 try {
1222 print("(let " + tree.defs + " in " + tree.expr + ")");
1223 } catch (IOException e) {
1224 throw new UncheckedIOException(e);
1225 }
1226 }
1228 public void visitModifiers(JCModifiers mods) {
1229 try {
1230 printAnnotations(mods.annotations);
1231 printFlags(mods.flags);
1232 } catch (IOException e) {
1233 throw new UncheckedIOException(e);
1234 }
1235 }
1237 public void visitAnnotation(JCAnnotation tree) {
1238 try {
1239 print("@");
1240 printExpr(tree.annotationType);
1241 print("(");
1242 printExprs(tree.args);
1243 print(")");
1244 } catch (IOException e) {
1245 throw new UncheckedIOException(e);
1246 }
1247 }
1249 public void visitTree(JCTree tree) {
1250 try {
1251 print("(UNKNOWN: " + tree + ")");
1252 println();
1253 } catch (IOException e) {
1254 throw new UncheckedIOException(e);
1255 }
1256 }
1258 }