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