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