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