DPrinter.java revision 2877:62e285806e83
1/* 2 * Copyright (c) 2013, 2015, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/* @test 25 * @bug 8043484 8007307 26 * @summary Make sure DPrinter.java compiles 27 * @compile DPrinter.java 28 */ 29 30import java.io.File; 31import java.io.IOException; 32import java.io.PrintWriter; 33import java.lang.reflect.Field; 34import java.lang.reflect.Method; 35import java.util.ArrayList; 36import java.util.Arrays; 37import java.util.Collection; 38import java.util.EnumSet; 39import java.util.HashMap; 40import java.util.List; 41import java.util.Locale; 42import java.util.Map; 43import java.util.Set; 44 45import javax.lang.model.element.Name; 46import javax.lang.model.element.TypeElement; 47import javax.tools.FileObject; 48import javax.tools.JavaCompiler; 49import javax.tools.JavaFileObject; 50import javax.tools.StandardJavaFileManager; 51import javax.tools.StandardLocation; 52import javax.tools.ToolProvider; 53 54import com.sun.source.doctree.*; 55import com.sun.source.util.JavacTask; 56import com.sun.source.util.TaskEvent; 57import com.sun.source.util.TaskListener; 58import com.sun.source.util.Trees; 59import com.sun.tools.javac.api.JavacTrees; 60import com.sun.tools.javac.code.SymbolMetadata; 61import com.sun.tools.javac.code.Attribute; 62import com.sun.tools.javac.code.Flags; 63import com.sun.tools.javac.code.Kinds; 64import com.sun.tools.javac.code.Printer; 65import com.sun.tools.javac.code.Scope; 66import com.sun.tools.javac.code.Scope.CompoundScope; 67import com.sun.tools.javac.code.Symbol; 68import com.sun.tools.javac.code.Symbol.*; 69import com.sun.tools.javac.code.Type; 70import com.sun.tools.javac.code.Type.*; 71import com.sun.tools.javac.code.TypeTag; 72import com.sun.tools.javac.tree.JCTree; 73import com.sun.tools.javac.tree.JCTree.*; 74import com.sun.tools.javac.tree.Pretty; 75import com.sun.tools.javac.tree.TreeInfo; 76import com.sun.tools.javac.tree.TreeScanner; 77import com.sun.tools.javac.util.Assert; 78import com.sun.tools.javac.util.Context; 79import com.sun.tools.javac.util.Convert; 80import com.sun.tools.javac.util.Log; 81 82 83/** 84 * Debug printer for javac internals, for when toString() just isn't enough. 85 * 86 * <p> 87 * The printer provides an API to generate structured views of javac objects, 88 * such as AST nodes, symbol, types and annotations. Various aspects of the 89 * output can be configured, such as whether to show nulls, empty lists, or 90 * a compressed representation of the source code. Visitors are used to walk 91 * object hierarchies, and can be replaced with custom visitors if the default 92 * visitors are not flexible enough. 93 * 94 * <p> 95 * In general, nodes are printed with an initial line identifying the node 96 * followed by indented lines for the child nodes. Currently, graphs are 97 * represented by printing a spanning subtree. 98 * 99 * <p> 100 * The printer can be accessed via a simple command-line utility, 101 * which makes it easy to see the internal representation of source code, 102 * such as simple test programs, during the compilation pipeline. 103 * 104 * <p><b>This is NOT part of any supported API. 105 * If you write code that depends on this, you do so at your own risk. 106 * This code and its internal interfaces are subject to change or 107 * deletion without notice.</b> 108 */ 109 110public class DPrinter { 111 protected final PrintWriter out; 112 protected final Trees trees; 113 protected Printer printer; 114 protected boolean showEmptyItems = true; 115 protected boolean showNulls = true; 116 protected boolean showPositions = false; 117 protected boolean showSrc; 118 protected boolean showTreeSymbols; 119 protected boolean showTreeTypes; 120 protected int maxSrcLength = 32; 121 protected Locale locale = Locale.getDefault(); 122 protected static final String NULL = "#null"; 123 124 // <editor-fold defaultstate="collapsed" desc="Configuration"> 125 126 public static DPrinter instance(Context context) { 127 DPrinter dp = context.get(DPrinter.class); 128 if (dp == null) { 129 dp = new DPrinter(context); 130 } 131 return dp; 132 133 } 134 135 protected DPrinter(Context context) { 136 context.put(DPrinter.class, this); 137 out = context.get(Log.outKey); 138 trees = JavacTrees.instance(context); 139 } 140 141 public DPrinter(PrintWriter out, Trees trees) { 142 this.out = out; 143 this.trees = trees; 144 } 145 146 public DPrinter emptyItems(boolean showEmptyItems) { 147 this.showEmptyItems = showEmptyItems; 148 return this; 149 } 150 151 public DPrinter nulls(boolean showNulls) { 152 this.showNulls = showNulls; 153 return this; 154 } 155 156 public DPrinter positions(boolean showPositions) { 157 this.showPositions = showPositions; 158 return this; 159 } 160 161 public DPrinter source(boolean showSrc) { 162 this.showSrc = showSrc; 163 return this; 164 } 165 166 public DPrinter source(int maxSrcLength) { 167 this.showSrc = true; 168 this.maxSrcLength = maxSrcLength; 169 return this; 170 } 171 172 public DPrinter treeSymbols(boolean showTreeSymbols) { 173 this.showTreeSymbols = showTreeSymbols; 174 return this; 175 } 176 177 public DPrinter treeTypes(boolean showTreeTypes) { 178 this.showTreeTypes = showTreeTypes; 179 return this; 180 } 181 182 public DPrinter typeSymbolPrinter(Printer p) { 183 printer = p; 184 return this; 185 } 186 187 // </editor-fold> 188 189 // <editor-fold defaultstate="collapsed" desc="Printing"> 190 191 protected enum Details { 192 /** A one-line non-recursive summary */ 193 SUMMARY, 194 /** Multi-line, possibly recursive. */ 195 FULL 196 }; 197 198 public void printAnnotations(String label, SymbolMetadata annotations) { 199 printAnnotations(label, annotations, Details.FULL); 200 } 201 202 protected void printAnnotations(String label, SymbolMetadata annotations, Details details) { 203 if (annotations == null) { 204 printNull(label); 205 } else { 206 // no SUMMARY format currently available to use 207 208 // use reflection to get at private fields 209 Object DECL_NOT_STARTED = getField(null, SymbolMetadata.class, "DECL_NOT_STARTED"); 210 Object DECL_IN_PROGRESS = getField(null, SymbolMetadata.class, "DECL_IN_PROGRESS"); 211 Object attributes = getField(annotations, SymbolMetadata.class, "attributes"); 212 Object type_attributes = getField(annotations, SymbolMetadata.class, "type_attributes"); 213 214 if (!showEmptyItems) { 215 if (attributes instanceof List && ((List) attributes).isEmpty() 216 && attributes != DECL_NOT_STARTED 217 && attributes != DECL_IN_PROGRESS 218 && type_attributes instanceof List && ((List) type_attributes).isEmpty()) 219 return; 220 } 221 222 printString(label, hashString(annotations)); 223 224 indent(+1); 225 if (attributes == DECL_NOT_STARTED) 226 printString("attributes", "DECL_NOT_STARTED"); 227 else if (attributes == DECL_IN_PROGRESS) 228 printString("attributes", "DECL_IN_PROGRESS"); 229 else if (attributes instanceof List) 230 printList("attributes", (List) attributes); 231 else 232 printObject("attributes", attributes, Details.SUMMARY); 233 234 if (attributes instanceof List) 235 printList("type_attributes", (List) type_attributes); 236 else 237 printObject("type_attributes", type_attributes, Details.SUMMARY); 238 indent(-1); 239 } 240 } 241 242 public void printAttribute(String label, Attribute attr) { 243 if (attr == null) { 244 printNull(label); 245 } else { 246 printString(label, attr.getClass().getSimpleName()); 247 248 indent(+1); 249 attr.accept(attrVisitor); 250 indent(-1); 251 } 252 } 253 254 public void printDocTree(String label, DocTree tree) { 255 if (tree == null) { 256 printNull(label); 257 } else { 258 indent(); 259 out.print(label); 260 out.println(": " + tree.getClass().getSimpleName() + "," + tree.getKind()); 261 262 indent(+1); 263 tree.accept(docTreeVisitor, null); 264 indent(-1); 265 } 266 } 267 268 public void printFileObject(String label, FileObject fo) { 269 if (fo == null) { 270 printNull(label); 271 } else { 272 printString(label, fo.getName()); 273 } 274 } 275 276 protected <T> void printImplClass(T item, Class<? extends T> stdImplClass) { 277 if (item.getClass() != stdImplClass) 278 printString("impl", item.getClass().getName()); 279 } 280 281 public void printInt(String label, int i) { 282 printString(label, String.valueOf(i)); 283 } 284 285 public void printLimitedEscapedString(String label, String text) { 286 String s = Convert.quote(text); 287 if (s.length() > maxSrcLength) { 288 String trim = "[...]"; 289 int head = (maxSrcLength - trim.length()) * 2 / 3; 290 int tail = maxSrcLength - trim.length() - head; 291 s = s.substring(0, head) + trim + s.substring(s.length() - tail); 292 } 293 printString(label, s); 294 } 295 296 public void printList(String label, List<?> list) { 297 if (list == null) { 298 printNull(label); 299 } else if (!list.isEmpty() || showEmptyItems) { 300 printString(label, "[" + list.size() + "]"); 301 302 indent(+1); 303 int i = 0; 304 for (Object item: list) { 305 printObject(String.valueOf(i++), item, Details.FULL); 306 } 307 indent(-1); 308 } 309 } 310 311 public void printName(String label, Name name) { 312 if (name == null) { 313 printNull(label); 314 } else { 315 printString(label, name.toString()); 316 } 317 } 318 319 public void printNull(String label) { 320 if (showNulls) 321 printString(label, NULL); 322 } 323 324 protected void printObject(String label, Object item, Details details) { 325 if (item == null) { 326 printNull(label); 327 } else if (item instanceof Attribute) { 328 printAttribute(label, (Attribute) item); 329 } else if (item instanceof Symbol) { 330 printSymbol(label, (Symbol) item, details); 331 } else if (item instanceof Type) { 332 printType(label, (Type) item, details); 333 } else if (item instanceof JCTree) { 334 printTree(label, (JCTree) item); 335 } else if (item instanceof DocTree) { 336 printDocTree(label, (DocTree) item); 337 } else if (item instanceof List) { 338 printList(label, (List) item); 339 } else if (item instanceof Name) { 340 printName(label, (Name) item); 341 } else if (item instanceof Scope) { 342 printScope(label, (Scope) item); 343 } else { 344 printString(label, String.valueOf(item)); 345 } 346 } 347 348 public void printScope(String label, Scope scope) { 349 printScope(label, scope, Details.FULL); 350 } 351 352 public void printScope(String label, Scope scope, Details details) { 353 if (scope == null) { 354 printNull(label); 355 } else { 356 switch (details) { 357 case SUMMARY: { 358 indent(); 359 out.print(label); 360 out.print(": ["); 361 String sep = ""; 362 for (Symbol sym: scope.getSymbols()) { 363 out.print(sep); 364 out.print(sym.name); 365 sep = ","; 366 } 367 out.println("]"); 368 break; 369 } 370 371 case FULL: { 372 indent(); 373 out.println(label); 374 375 indent(+1); 376 printFullScopeImpl(scope); 377 indent(-1); 378 break; 379 } 380 } 381 } 382 } 383 384 void printFullScopeImpl(Scope scope) { 385 indent(); 386 out.println(scope.getClass().getName()); 387 printSymbol("owner", scope.owner, Details.SUMMARY); 388 if (SCOPE_IMPL_CLASS.equals(scope.getClass().getName())) { 389 printScope("next", (Scope) getField(scope, scope.getClass(), "next"), Details.SUMMARY); 390 printObject("shared", getField(scope, scope.getClass(), "shared"), Details.SUMMARY); 391 Object[] table = (Object[]) getField(scope, scope.getClass(), "table"); 392 for (int i = 0; i < table.length; i++) { 393 if (i > 0) 394 out.print(", "); 395 else 396 indent(); 397 out.print(i + ":" + entryToString(table[i], table, false)); 398 } 399 out.println(); 400 } else if (FILTER_SCOPE_CLASS.equals(scope.getClass().getName())) { 401 printScope("origin", 402 (Scope) getField(scope, scope.getClass(), "origin"), Details.FULL); 403 } else if (scope instanceof CompoundScope) { 404 printList("delegates", (List<?>) getField(scope, CompoundScope.class, "subScopes")); 405 } else { 406 for (Symbol sym : scope.getSymbols()) { 407 printSymbol(sym.name.toString(), sym, Details.SUMMARY); 408 } 409 } 410 } 411 //where: 412 static final String SCOPE_IMPL_CLASS = "com.sun.tools.javac.code.Scope$ScopeImpl"; 413 static final String FILTER_SCOPE_CLASS = "com.sun.tools.javac.code.Scope$FilterImportScope"; 414 415 /** 416 * Create a string showing the contents of an entry, using the table 417 * to help identify cross-references to other entries in the table. 418 * @param e the entry to be shown 419 * @param table the table containing the other entries 420 */ 421 String entryToString(Object e, Object[] table, boolean ref) { 422 if (e == null) 423 return "null"; 424 Symbol sym = (Symbol) getField(e, e.getClass(), "sym"); 425 if (sym == null) 426 return "sent"; // sentinel 427 if (ref) { 428 int index = indexOf(table, e); 429 if (index != -1) 430 return String.valueOf(index); 431 } 432 Scope scope = (Scope) getField(e, e.getClass(), "scope"); 433 return "(" + sym.name + ":" + sym 434 + ",shdw:" + entryToString(callMethod(e, e.getClass(), "next"), table, true) 435 + ",sibl:" + entryToString(getField(e, e.getClass(), "sibling"), table, true) 436 + ((sym.owner != scope.owner) 437 ? (",BOGUS[" + sym.owner + "," + scope.owner + "]") 438 : "") 439 + ")"; 440 } 441 442 <T> int indexOf(T[] array, T item) { 443 for (int i = 0; i < array.length; i++) { 444 if (array[i] == item) 445 return i; 446 } 447 return -1; 448 } 449 450 public void printSource(String label, JCTree tree) { 451 printString(label, Pretty.toSimpleString(tree, maxSrcLength)); 452 } 453 454 public void printString(String label, String text) { 455 indent(); 456 out.print(label); 457 out.print(": "); 458 out.print(text); 459 out.println(); 460 } 461 462 public void printSymbol(String label, Symbol symbol) { 463 printSymbol(label, symbol, Details.FULL); 464 } 465 466 protected void printSymbol(String label, Symbol sym, Details details) { 467 if (sym == null) { 468 printNull(label); 469 } else { 470 switch (details) { 471 case SUMMARY: 472 printString(label, toString(sym)); 473 break; 474 475 case FULL: 476 indent(); 477 out.print(label); 478 out.println(": " + 479 info(sym.getClass(), 480 String.format("0x%x--%s", sym.kind.ordinal(), Kinds.kindName(sym)), 481 sym.getKind()) 482 + " " + sym.name 483 + " " + hashString(sym)); 484 485 indent(+1); 486 if (showSrc) { 487 JCTree tree = (JCTree) trees.getTree(sym); 488 if (tree != null) 489 printSource("src", tree); 490 } 491 printString("flags", String.format("0x%x--%s", 492 sym.flags_field, Flags.toString(sym.flags_field))); 493 printObject("completer", sym.completer, Details.SUMMARY); // what if too long? 494 printSymbol("owner", sym.owner, Details.SUMMARY); 495 printType("type", sym.type, Details.SUMMARY); 496 printType("erasure", sym.erasure_field, Details.SUMMARY); 497 sym.accept(symVisitor, null); 498 printAnnotations("annotations", sym.getMetadata(), Details.SUMMARY); 499 indent(-1); 500 } 501 } 502 } 503 504 protected String toString(Symbol sym) { 505 return (printer != null) ? printer.visit(sym, locale) : String.valueOf(sym); 506 } 507 508 protected void printTree(String label, JCTree tree) { 509 if (tree == null) { 510 printNull(label); 511 } else { 512 indent(); 513 String ext; 514 try { 515 ext = tree.getKind().name(); 516 } catch (Throwable t) { 517 ext = "n/a"; 518 } 519 out.print(label + ": " + info(tree.getClass(), tree.getTag(), ext)); 520 if (showPositions) { 521 // We can always get start position, but to get end position 522 // and/or line+offset, we would need a JCCompilationUnit 523 out.print(" pos:" + tree.pos); 524 } 525 if (showTreeTypes && tree.type != null) 526 out.print(" type:" + toString(tree.type)); 527 Symbol sym; 528 if (showTreeSymbols && (sym = TreeInfo.symbolFor(tree)) != null) 529 out.print(" sym:" + toString(sym)); 530 out.println(); 531 532 indent(+1); 533 if (showSrc) { 534 indent(); 535 out.println("src: " + Pretty.toSimpleString(tree, maxSrcLength)); 536 } 537 tree.accept(treeVisitor); 538 indent(-1); 539 } 540 } 541 542 public void printType(String label, Type type) { 543 printType(label, type, Details.FULL); 544 } 545 546 protected void printType(String label, Type type, Details details) { 547 if (type == null) 548 printNull(label); 549 else { 550 switch (details) { 551 case SUMMARY: 552 printString(label, toString(type)); 553 break; 554 555 case FULL: 556 indent(); 557 out.print(label); 558 out.println(": " + info(type.getClass(), type.getTag(), type.getKind()) 559 + " " + hashString(type)); 560 561 indent(+1); 562 printSymbol("tsym", type.tsym, Details.SUMMARY); 563 printObject("constValue", type.constValue(), Details.SUMMARY); 564 printObject("annotations", type.getAnnotationMirrors(), Details.SUMMARY); 565 type.accept(typeVisitor, null); 566 indent(-1); 567 } 568 } 569 } 570 571 protected String toString(Type type) { 572 return (printer != null) ? printer.visit(type, locale) : String.valueOf(type); 573 } 574 575 protected String hashString(Object obj) { 576 return String.format("#%x", obj.hashCode()); 577 } 578 579 protected String info(Class<?> clazz, Object internal, Object external) { 580 return String.format("%s,%s,%s", clazz.getSimpleName(), internal, external); 581 } 582 583 private int indent = 0; 584 585 protected void indent() { 586 for (int i = 0; i < indent; i++) { 587 out.print(" "); 588 } 589 } 590 591 protected void indent(int n) { 592 indent += n; 593 } 594 595 protected Object getField(Object o, Class<?> clazz, String name) { 596 try { 597 Field f = clazz.getDeclaredField(name); 598 boolean prev = f.isAccessible(); 599 f.setAccessible(true); 600 try { 601 return f.get(o); 602 } finally { 603 f.setAccessible(prev); 604 } 605 } catch (ReflectiveOperationException e) { 606 return e; 607 } catch (SecurityException e) { 608 return e; 609 } 610 } 611 612 protected Object callMethod(Object o, Class<?> clazz, String name) { 613 try { 614 Method m = clazz.getDeclaredMethod(name); 615 boolean prev = m.isAccessible(); 616 m.setAccessible(true); 617 try { 618 return m.invoke(o); 619 } finally { 620 m.setAccessible(prev); 621 } 622 } catch (ReflectiveOperationException e) { 623 return e; 624 } catch (SecurityException e) { 625 return e; 626 } 627 } 628 629 // </editor-fold> 630 631 // <editor-fold defaultstate="collapsed" desc="JCTree visitor methods"> 632 633 protected JCTree.Visitor treeVisitor = new TreeVisitor(); 634 635 /** 636 * Default visitor class for JCTree (AST) objects. 637 */ 638 public class TreeVisitor extends JCTree.Visitor { 639 @Override 640 public void visitTopLevel(JCCompilationUnit tree) { 641 printList("packageAnnotations", tree.getPackageAnnotations()); 642 printList("defs", tree.defs); 643 } 644 645 @Override 646 public void visitPackageDef(JCPackageDecl tree) { 647 printTree("pid", tree.pid); 648 } 649 650 @Override 651 public void visitImport(JCImport tree) { 652 printTree("qualid", tree.qualid); 653 } 654 655 @Override 656 public void visitClassDef(JCClassDecl tree) { 657 printName("name", tree.name); 658 printTree("mods", tree.mods); 659 printList("typarams", tree.typarams); 660 printTree("extending", tree.extending); 661 printList("implementing", tree.implementing); 662 printList("defs", tree.defs); 663 } 664 665 @Override 666 public void visitMethodDef(JCMethodDecl tree) { 667 printName("name", tree.name); 668 printTree("mods", tree.mods); 669 printTree("restype", tree.restype); 670 printList("typarams", tree.typarams); 671 printTree("recvparam", tree.recvparam); 672 printList("params", tree.params); 673 printList("thrown", tree.thrown); 674 printTree("defaultValue", tree.defaultValue); 675 printTree("body", tree.body); 676 } 677 678 @Override 679 public void visitVarDef(JCVariableDecl tree) { 680 printName("name", tree.name); 681 printTree("mods", tree.mods); 682 printTree("vartype", tree.vartype); 683 printTree("init", tree.init); 684 } 685 686 @Override 687 public void visitSkip(JCSkip tree) { 688 } 689 690 @Override 691 public void visitBlock(JCBlock tree) { 692 printList("stats", tree.stats); 693 } 694 695 @Override 696 public void visitDoLoop(JCDoWhileLoop tree) { 697 printTree("body", tree.body); 698 printTree("cond", tree.cond); 699 } 700 701 @Override 702 public void visitWhileLoop(JCWhileLoop tree) { 703 printTree("cond", tree.cond); 704 printTree("body", tree.body); 705 } 706 707 @Override 708 public void visitForLoop(JCForLoop tree) { 709 printList("init", tree.init); 710 printTree("cond", tree.cond); 711 printList("step", tree.step); 712 printTree("body", tree.body); 713 } 714 715 @Override 716 public void visitForeachLoop(JCEnhancedForLoop tree) { 717 printTree("var", tree.var); 718 printTree("expr", tree.expr); 719 printTree("body", tree.body); 720 } 721 722 @Override 723 public void visitLabelled(JCLabeledStatement tree) { 724 printTree("body", tree.body); 725 } 726 727 @Override 728 public void visitSwitch(JCSwitch tree) { 729 printTree("selector", tree.selector); 730 printList("cases", tree.cases); 731 } 732 733 @Override 734 public void visitCase(JCCase tree) { 735 printTree("pat", tree.pat); 736 printList("stats", tree.stats); 737 } 738 739 @Override 740 public void visitSynchronized(JCSynchronized tree) { 741 printTree("lock", tree.lock); 742 printTree("body", tree.body); 743 } 744 745 @Override 746 public void visitTry(JCTry tree) { 747 printList("resources", tree.resources); 748 printTree("body", tree.body); 749 printList("catchers", tree.catchers); 750 printTree("finalizer", tree.finalizer); 751 } 752 753 @Override 754 public void visitCatch(JCCatch tree) { 755 printTree("param", tree.param); 756 printTree("body", tree.body); 757 } 758 759 @Override 760 public void visitConditional(JCConditional tree) { 761 printTree("cond", tree.cond); 762 printTree("truepart", tree.truepart); 763 printTree("falsepart", tree.falsepart); 764 } 765 766 @Override 767 public void visitIf(JCIf tree) { 768 printTree("cond", tree.cond); 769 printTree("thenpart", tree.thenpart); 770 printTree("elsepart", tree.elsepart); 771 } 772 773 @Override 774 public void visitExec(JCExpressionStatement tree) { 775 printTree("expr", tree.expr); 776 } 777 778 @Override 779 public void visitBreak(JCBreak tree) { 780 printName("label", tree.label); 781 } 782 783 @Override 784 public void visitContinue(JCContinue tree) { 785 printName("label", tree.label); 786 } 787 788 @Override 789 public void visitReturn(JCReturn tree) { 790 printTree("expr", tree.expr); 791 } 792 793 @Override 794 public void visitThrow(JCThrow tree) { 795 printTree("expr", tree.expr); 796 } 797 798 @Override 799 public void visitAssert(JCAssert tree) { 800 printTree("cond", tree.cond); 801 printTree("detail", tree.detail); 802 } 803 804 @Override 805 public void visitApply(JCMethodInvocation tree) { 806 printList("typeargs", tree.typeargs); 807 printTree("meth", tree.meth); 808 printList("args", tree.args); 809 } 810 811 @Override 812 public void visitNewClass(JCNewClass tree) { 813 printTree("encl", tree.encl); 814 printList("typeargs", tree.typeargs); 815 printTree("clazz", tree.clazz); 816 printList("args", tree.args); 817 printTree("def", tree.def); 818 } 819 820 @Override 821 public void visitNewArray(JCNewArray tree) { 822 printList("annotations", tree.annotations); 823 printTree("elemtype", tree.elemtype); 824 printList("dims", tree.dims); 825 printList("dimAnnotations", tree.dimAnnotations); 826 printList("elems", tree.elems); 827 } 828 829 @Override 830 public void visitLambda(JCLambda tree) { 831 printTree("body", tree.body); 832 printList("params", tree.params); 833 } 834 835 @Override 836 public void visitParens(JCParens tree) { 837 printTree("expr", tree.expr); 838 } 839 840 @Override 841 public void visitAssign(JCAssign tree) { 842 printTree("lhs", tree.lhs); 843 printTree("rhs", tree.rhs); 844 } 845 846 @Override 847 public void visitAssignop(JCAssignOp tree) { 848 printTree("lhs", tree.lhs); 849 printTree("rhs", tree.rhs); 850 } 851 852 @Override 853 public void visitUnary(JCUnary tree) { 854 printTree("arg", tree.arg); 855 } 856 857 @Override 858 public void visitBinary(JCBinary tree) { 859 printTree("lhs", tree.lhs); 860 printTree("rhs", tree.rhs); 861 } 862 863 @Override 864 public void visitTypeCast(JCTypeCast tree) { 865 printTree("clazz", tree.clazz); 866 printTree("expr", tree.expr); 867 } 868 869 @Override 870 public void visitTypeTest(JCInstanceOf tree) { 871 printTree("expr", tree.expr); 872 printTree("clazz", tree.clazz); 873 } 874 875 @Override 876 public void visitIndexed(JCArrayAccess tree) { 877 printTree("indexed", tree.indexed); 878 printTree("index", tree.index); 879 } 880 881 @Override 882 public void visitSelect(JCFieldAccess tree) { 883 printTree("selected", tree.selected); 884 } 885 886 @Override 887 public void visitReference(JCMemberReference tree) { 888 printTree("expr", tree.expr); 889 printList("typeargs", tree.typeargs); 890 } 891 892 @Override 893 public void visitIdent(JCIdent tree) { 894 printName("name", tree.name); 895 } 896 897 @Override 898 public void visitLiteral(JCLiteral tree) { 899 printString("value", Pretty.toSimpleString(tree, 32)); 900 } 901 902 @Override 903 public void visitTypeIdent(JCPrimitiveTypeTree tree) { 904 printString("typetag", tree.typetag.name()); 905 } 906 907 @Override 908 public void visitTypeArray(JCArrayTypeTree tree) { 909 printTree("elemtype", tree.elemtype); 910 } 911 912 @Override 913 public void visitTypeApply(JCTypeApply tree) { 914 printTree("clazz", tree.clazz); 915 printList("arguments", tree.arguments); 916 } 917 918 @Override 919 public void visitTypeUnion(JCTypeUnion tree) { 920 printList("alternatives", tree.alternatives); 921 } 922 923 @Override 924 public void visitTypeIntersection(JCTypeIntersection tree) { 925 printList("bounds", tree.bounds); 926 } 927 928 @Override 929 public void visitTypeParameter(JCTypeParameter tree) { 930 printName("name", tree.name); 931 printList("annotations", tree.annotations); 932 printList("bounds", tree.bounds); 933 } 934 935 @Override 936 public void visitWildcard(JCWildcard tree) { 937 printTree("kind", tree.kind); 938 printTree("inner", tree.inner); 939 } 940 941 @Override 942 public void visitTypeBoundKind(TypeBoundKind tree) { 943 printString("kind", tree.kind.name()); 944 } 945 946 @Override 947 public void visitModifiers(JCModifiers tree) { 948 printList("annotations", tree.annotations); 949 printString("flags", String.valueOf(Flags.asFlagSet(tree.flags))); 950 } 951 952 @Override 953 public void visitAnnotation(JCAnnotation tree) { 954 printTree("annotationType", tree.annotationType); 955 printList("args", tree.args); 956 } 957 958 @Override 959 public void visitAnnotatedType(JCAnnotatedType tree) { 960 printList("annotations", tree.annotations); 961 printTree("underlyingType", tree.underlyingType); 962 } 963 964 @Override 965 public void visitErroneous(JCErroneous tree) { 966 printList("errs", tree.errs); 967 } 968 969 @Override 970 public void visitLetExpr(LetExpr tree) { 971 printList("defs", tree.defs); 972 printTree("expr", tree.expr); 973 } 974 975 @Override 976 public void visitTree(JCTree tree) { 977 Assert.error(); 978 } 979 } 980 981 // </editor-fold> 982 983 // <editor-fold defaultstate="collapsed" desc="DocTree visitor"> 984 985 protected DocTreeVisitor<Void,Void> docTreeVisitor = new DefaultDocTreeVisitor(); 986 987 /** 988 * Default visitor class for DocTree objects. 989 * Note: each visitXYZ method ends by calling the corresponding 990 * visit method for its superclass. 991 */ 992 class DefaultDocTreeVisitor implements DocTreeVisitor<Void,Void> { 993 994 public Void visitAttribute(AttributeTree node, Void p) { 995 printName("name", node.getName()); 996 printString("vkind", node.getValueKind().name()); 997 printList("value", node.getValue()); 998 return visitTree(node, null); 999 } 1000 1001 public Void visitAuthor(AuthorTree node, Void p) { 1002 printList("name", node.getName()); 1003 return visitBlockTag(node, null); 1004 } 1005 1006 public Void visitComment(CommentTree node, Void p) { 1007 printLimitedEscapedString("body", node.getBody()); 1008 return visitTree(node, null); 1009 } 1010 1011 public Void visitDeprecated(DeprecatedTree node, Void p) { 1012 printList("body", node.getBody()); 1013 return visitBlockTag(node, null); 1014 } 1015 1016 public Void visitDocComment(DocCommentTree node, Void p) { 1017 printList("firstSentence", node.getFirstSentence()); 1018 printList("body", node.getBody()); 1019 printList("tags", node.getBlockTags()); 1020 return visitTree(node, null); 1021 } 1022 1023 public Void visitDocRoot(DocRootTree node, Void p) { 1024 return visitInlineTag(node, null); 1025 } 1026 1027 public Void visitEndElement(EndElementTree node, Void p) { 1028 printName("name", node.getName()); 1029 return visitTree(node, null); 1030 } 1031 1032 public Void visitEntity(EntityTree node, Void p) { 1033 printName("name", node.getName()); 1034 return visitTree(node, null); 1035 } 1036 1037 public Void visitErroneous(ErroneousTree node, Void p) { 1038 printLimitedEscapedString("body", node.getBody()); 1039 printString("diag", node.getDiagnostic().getMessage(Locale.getDefault())); 1040 return visitTree(node, null); 1041 } 1042 1043 public Void visitIdentifier(IdentifierTree node, Void p) { 1044 printName("name", node.getName()); 1045 return visitTree(node, null); 1046 } 1047 1048 public Void visitInheritDoc(InheritDocTree node, Void p) { 1049 return visitInlineTag(node, null); 1050 } 1051 1052 public Void visitLink(LinkTree node, Void p) { 1053 printString("kind", node.getKind().name()); 1054 printDocTree("ref", node.getReference()); 1055 printList("list", node.getLabel()); 1056 return visitInlineTag(node, null); 1057 } 1058 1059 public Void visitLiteral(LiteralTree node, Void p) { 1060 printString("kind", node.getKind().name()); 1061 printDocTree("body", node.getBody()); 1062 return visitInlineTag(node, null); 1063 } 1064 1065 public Void visitParam(ParamTree node, Void p) { 1066 printString("isTypeParameter", String.valueOf(node.isTypeParameter())); 1067 printString("kind", node.getKind().name()); 1068 printList("desc", node.getDescription()); 1069 return visitBlockTag(node, null); 1070 } 1071 1072 public Void visitReference(ReferenceTree node, Void p) { 1073 printString("signature", node.getSignature()); 1074 return visitTree(node, null); 1075 } 1076 1077 public Void visitReturn(ReturnTree node, Void p) { 1078 printList("desc", node.getDescription()); 1079 return visitBlockTag(node, null); 1080 } 1081 1082 public Void visitSee(SeeTree node, Void p) { 1083 printList("ref", node.getReference()); 1084 return visitBlockTag(node, null); 1085 } 1086 1087 public Void visitSerial(SerialTree node, Void p) { 1088 printList("desc", node.getDescription()); 1089 return visitBlockTag(node, null); 1090 } 1091 1092 public Void visitSerialData(SerialDataTree node, Void p) { 1093 printList("desc", node.getDescription()); 1094 return visitBlockTag(node, null); 1095 } 1096 1097 public Void visitSerialField(SerialFieldTree node, Void p) { 1098 printDocTree("name", node.getName()); 1099 printDocTree("type", node.getType()); 1100 printList("desc", node.getDescription()); 1101 return visitBlockTag(node, null); 1102 } 1103 1104 public Void visitSince(SinceTree node, Void p) { 1105 printList("body", node.getBody()); 1106 return visitBlockTag(node, null); 1107 } 1108 1109 public Void visitStartElement(StartElementTree node, Void p) { 1110 printName("name", node.getName()); 1111 printList("attrs", node.getAttributes()); 1112 printString("selfClosing", String.valueOf(node.isSelfClosing())); 1113 return visitBlockTag(node, null); 1114 } 1115 1116 public Void visitText(TextTree node, Void p) { 1117 printLimitedEscapedString("body", node.getBody()); 1118 return visitTree(node, null); 1119 } 1120 1121 public Void visitThrows(ThrowsTree node, Void p) { 1122 printDocTree("name", node.getExceptionName()); 1123 printList("desc", node.getDescription()); 1124 return visitBlockTag(node, null); 1125 } 1126 1127 public Void visitUnknownBlockTag(UnknownBlockTagTree node, Void p) { 1128 printString("name", node.getTagName()); 1129 printList("content", node.getContent()); 1130 return visitBlockTag(node, null); 1131 } 1132 1133 public Void visitUnknownInlineTag(UnknownInlineTagTree node, Void p) { 1134 printString("name", node.getTagName()); 1135 printList("content", node.getContent()); 1136 return visitInlineTag(node, null); 1137 } 1138 1139 public Void visitValue(ValueTree node, Void p) { 1140 printDocTree("value", node.getReference()); 1141 return visitInlineTag(node, null); 1142 } 1143 1144 public Void visitVersion(VersionTree node, Void p) { 1145 printList("body", node.getBody()); 1146 return visitBlockTag(node, null); 1147 } 1148 1149 public Void visitOther(DocTree node, Void p) { 1150 return visitTree(node, null); 1151 } 1152 1153 public Void visitBlockTag(DocTree node, Void p) { 1154 return visitTree(node, null); 1155 } 1156 1157 public Void visitInlineTag(DocTree node, Void p) { 1158 return visitTree(node, null); 1159 } 1160 1161 public Void visitTree(DocTree node, Void p) { 1162 return null; 1163 } 1164 } 1165 1166 // </editor-fold> 1167 1168 // <editor-fold defaultstate="collapsed" desc="Symbol visitor"> 1169 1170 protected Symbol.Visitor<Void,Void> symVisitor = new SymbolVisitor(); 1171 1172 /** 1173 * Default visitor class for Symbol objects. 1174 * Note: each visitXYZ method ends by calling the corresponding 1175 * visit method for its superclass. 1176 */ 1177 class SymbolVisitor implements Symbol.Visitor<Void,Void> { 1178 @Override 1179 public Void visitClassSymbol(ClassSymbol sym, Void ignore) { 1180 printName("fullname", sym.fullname); 1181 printName("flatname", sym.flatname); 1182 printScope("members", sym.members_field); 1183 printFileObject("sourcefile", sym.sourcefile); 1184 printFileObject("classfile", sym.classfile); 1185 // trans-local? 1186 // pool? 1187 return visitTypeSymbol(sym, null); 1188 } 1189 1190 @Override 1191 public Void visitMethodSymbol(MethodSymbol sym, Void ignore) { 1192 // code 1193 printList("params", sym.params); 1194 printList("savedParameterNames", sym.savedParameterNames); 1195 return visitSymbol(sym, null); 1196 } 1197 1198 @Override 1199 public Void visitPackageSymbol(PackageSymbol sym, Void ignore) { 1200 printName("fullname", sym.fullname); 1201 printScope("members", sym.members_field); 1202 printSymbol("package-info", sym.package_info, Details.SUMMARY); 1203 return visitTypeSymbol(sym, null); 1204 } 1205 1206 @Override 1207 public Void visitOperatorSymbol(OperatorSymbol sym, Void ignore) { 1208 printInt("opcode", sym.opcode); 1209 return visitMethodSymbol(sym, null); 1210 } 1211 1212 @Override 1213 public Void visitVarSymbol(VarSymbol sym, Void ignore) { 1214 printInt("pos", sym.pos); 1215 printInt("adm", sym.adr); 1216 // data is a private field, and the standard accessors may 1217 // mutate it as part of lazy evaluation. Therefore, use 1218 // reflection to get the raw data. 1219 printObject("data", getField(sym, VarSymbol.class, "data"), Details.SUMMARY); 1220 return visitSymbol(sym, null); 1221 } 1222 1223 @Override 1224 public Void visitTypeSymbol(TypeSymbol sym, Void ignore) { 1225 return visitSymbol(sym, null); 1226 } 1227 1228 @Override 1229 public Void visitSymbol(Symbol sym, Void ignore) { 1230 return null; 1231 } 1232 } 1233 1234 // </editor-fold> 1235 1236 // <editor-fold defaultstate="collapsed" desc="Type visitor"> 1237 1238 protected Type.Visitor<Void,Void> typeVisitor = new TypeVisitor(); 1239 1240 /** 1241 * Default visitor class for Type objects. 1242 * Note: each visitXYZ method ends by calling the corresponding 1243 * visit method for its superclass. 1244 */ 1245 public class TypeVisitor implements Type.Visitor<Void,Void> { 1246 public Void visitArrayType(ArrayType type, Void ignore) { 1247 printType("elemType", type.elemtype, Details.FULL); 1248 return visitType(type, null); 1249 } 1250 1251 public Void visitCapturedType(CapturedType type, Void ignore) { 1252 printType("wildcard", type.wildcard, Details.FULL); 1253 return visitTypeVar(type, null); 1254 } 1255 1256 public Void visitClassType(ClassType type, Void ignore) { 1257 printType("outer", type.getEnclosingType(), Details.SUMMARY); 1258 printList("typarams", type.typarams_field); 1259 printList("allparams", type.allparams_field); 1260 printType("supertype", type.supertype_field, Details.SUMMARY); 1261 printList("interfaces", type.interfaces_field); 1262 printList("allinterfaces", type.all_interfaces_field); 1263 return visitType(type, null); 1264 } 1265 1266 public Void visitErrorType(ErrorType type, Void ignore) { 1267 printType("originalType", type.getOriginalType(), Details.FULL); 1268 return visitClassType(type, null); 1269 } 1270 1271 public Void visitForAll(ForAll type, Void ignore) { 1272 printList("tvars", type.tvars); 1273 return visitDelegatedType(type); 1274 } 1275 1276 public Void visitMethodType(MethodType type, Void ignore) { 1277 printList("argtypes", type.argtypes); 1278 printType("restype", type.restype, Details.FULL); 1279 printList("thrown", type.thrown); 1280 return visitType(type, null); 1281 } 1282 1283 public Void visitPackageType(PackageType type, Void ignore) { 1284 return visitType(type, null); 1285 } 1286 1287 public Void visitTypeVar(TypeVar type, Void ignore) { 1288 // For TypeVars (and not subtypes), the bound should always be 1289 // null or bot. So, only print the bound for subtypes of TypeVar, 1290 // or if the bound is (erroneously) not null or bot. 1291 if (!type.hasTag(TypeTag.TYPEVAR) 1292 || !(type.bound == null || type.bound.hasTag(TypeTag.BOT))) { 1293 printType("bound", type.bound, Details.FULL); 1294 } 1295 printType("lower", type.lower, Details.FULL); 1296 return visitType(type, null); 1297 } 1298 1299 public Void visitUndetVar(UndetVar type, Void ignore) { 1300 for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values()) 1301 printList("bounds." + ib, type.getBounds(ib)); 1302 printInt("declaredCount", type.declaredCount); 1303 printType("inst", type.inst, Details.SUMMARY); 1304 return visitDelegatedType(type); 1305 } 1306 1307 public Void visitWildcardType(WildcardType type, Void ignore) { 1308 printType("type", type.type, Details.SUMMARY); 1309 printString("kind", type.kind.name()); 1310 printType("bound", type.bound, Details.SUMMARY); 1311 return visitType(type, null); 1312 } 1313 1314 protected Void visitDelegatedType(DelegatedType type) { 1315 printType("qtype", type.qtype, Details.FULL); 1316 return visitType(type, null); 1317 } 1318 1319 public Void visitType(Type type, Void ignore) { 1320 return null; 1321 } 1322 } 1323 1324 // </editor-fold> 1325 1326 // <editor-fold defaultstate="collapsed" desc="Attribute (annotations) visitor"> 1327 1328 protected Attribute.Visitor attrVisitor = new AttributeVisitor(); 1329 1330 /** 1331 * Default visitor class for Attribute (annotation) objects. 1332 */ 1333 public class AttributeVisitor implements Attribute.Visitor { 1334 1335 public void visitConstant(Attribute.Constant a) { 1336 printObject("value", a.value, Details.SUMMARY); 1337 visitAttribute(a); 1338 } 1339 1340 public void visitClass(Attribute.Class a) { 1341 printObject("classType", a.classType, Details.SUMMARY); 1342 visitAttribute(a); 1343 } 1344 1345 public void visitCompound(Attribute.Compound a) { 1346 if (a instanceof Attribute.TypeCompound) { 1347 Attribute.TypeCompound ta = (Attribute.TypeCompound) a; 1348 // consider a custom printer? 1349 printObject("position", ta.position, Details.SUMMARY); 1350 } 1351 printObject("synthesized", a.isSynthesized(), Details.SUMMARY); 1352 printList("values", a.values); 1353 visitAttribute(a); 1354 } 1355 1356 public void visitArray(Attribute.Array a) { 1357 printList("values", Arrays.asList(a.values)); 1358 visitAttribute(a); 1359 } 1360 1361 public void visitEnum(Attribute.Enum a) { 1362 printSymbol("value", a.value, Details.SUMMARY); 1363 visitAttribute(a); 1364 } 1365 1366 public void visitError(Attribute.Error a) { 1367 visitAttribute(a); 1368 } 1369 1370 public void visitAttribute(Attribute a) { 1371 printType("type", a.type, Details.SUMMARY); 1372 } 1373 1374 } 1375 // </editor-fold> 1376 1377 // <editor-fold defaultstate="collapsed" desc="Utility front end"> 1378 1379 /** 1380 * Utility class to invoke DPrinter from the command line. 1381 */ 1382 static class Main { 1383 public static void main(String... args) throws IOException { 1384 Main m = new Main(); 1385 PrintWriter out = new PrintWriter(System.out); 1386 try { 1387 if (args.length == 0) 1388 m.usage(out); 1389 else 1390 m.run(out, args); 1391 } finally { 1392 out.flush(); 1393 } 1394 } 1395 1396 void usage(PrintWriter out) { 1397 out.println("Usage:"); 1398 out.println(" java " + Main.class.getName() + " mode [options] [javac-options]"); 1399 out.print("where mode is one of: "); 1400 String sep = ""; 1401 for (Handler h: getHandlers().values()) { 1402 out.print(sep); 1403 out.print(h.name); 1404 sep = ", "; 1405 } 1406 out.println(); 1407 out.println("and where options include:"); 1408 out.println(" -before PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); 1409 out.println(" -after PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); 1410 out.println(" -showPositions"); 1411 out.println(" -showSource"); 1412 out.println(" -showTreeSymbols"); 1413 out.println(" -showTreeTypes"); 1414 out.println(" -hideEmptyItems"); 1415 out.println(" -hideNulls"); 1416 } 1417 1418 void run(PrintWriter out, String... args) throws IOException { 1419 JavaCompiler c = ToolProvider.getSystemJavaCompiler(); 1420 StandardJavaFileManager fm = c.getStandardFileManager(null, null, null); 1421 1422 // DPrinter options 1423 final Set<TaskEvent.Kind> before = EnumSet.noneOf(TaskEvent.Kind.class); 1424 final Set<TaskEvent.Kind> after = EnumSet.noneOf(TaskEvent.Kind.class); 1425 boolean showPositions = false; 1426 boolean showSource = false; 1427 boolean showTreeSymbols = false; 1428 boolean showTreeTypes = false; 1429 boolean showEmptyItems = true; 1430 boolean showNulls = true; 1431 1432 // javac options 1433 Collection<String> options = new ArrayList<String>(); 1434 Collection<File> files = new ArrayList<File>(); 1435 String classpath = null; 1436 String classoutdir = null; 1437 1438 final Handler h = getHandlers().get(args[0]); 1439 if (h == null) 1440 throw new IllegalArgumentException(args[0]); 1441 1442 for (int i = 1; i < args.length; i++) { 1443 String arg = args[i]; 1444 if (arg.equals("-before") && i + 1 < args.length) { 1445 before.add(getKind(args[++i])); 1446 } else if (arg.equals("-after") && i + 1 < args.length) { 1447 after.add(getKind(args[++i])); 1448 } else if (arg.equals("-showPositions")) { 1449 showPositions = true; 1450 } else if (arg.equals("-showSource")) { 1451 showSource = true; 1452 } else if (arg.equals("-showTreeSymbols")) { 1453 showTreeSymbols = true; 1454 } else if (arg.equals("-showTreeTypes")) { 1455 showTreeTypes = true; 1456 } else if (arg.equals("-hideEmptyLists")) { 1457 showEmptyItems = false; 1458 } else if (arg.equals("-hideNulls")) { 1459 showNulls = false; 1460 } else if (arg.equals("-classpath") && i + 1 < args.length) { 1461 classpath = args[++i]; 1462 } else if (arg.equals("-d") && i + 1 < args.length) { 1463 classoutdir = args[++i]; 1464 } else if (arg.startsWith("-")) { 1465 int n = c.isSupportedOption(arg); 1466 if (n < 0) throw new IllegalArgumentException(arg); 1467 options.add(arg); 1468 while (n > 0) options.add(args[++i]); 1469 } else if (arg.endsWith(".java")) { 1470 files.add(new File(arg)); 1471 } 1472 } 1473 1474 if (classoutdir != null) { 1475 fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(classoutdir))); 1476 } 1477 1478 if (classpath != null) { 1479 Collection<File> path = new ArrayList<File>(); 1480 for (String p: classpath.split(File.pathSeparator)) { 1481 if (p.isEmpty()) continue; 1482 File f = new File(p); 1483 if (f.exists()) path.add(f); 1484 } 1485 fm.setLocation(StandardLocation.CLASS_PATH, path); 1486 } 1487 Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files); 1488 1489 JavacTask task = (JavacTask) c.getTask(out, fm, null, options, null, fos); 1490 final Trees trees = Trees.instance(task); 1491 1492 final DPrinter dprinter = new DPrinter(out, trees); 1493 dprinter.source(showSource) 1494 .emptyItems(showEmptyItems) 1495 .nulls(showNulls) 1496 .positions(showPositions) 1497 .treeSymbols(showTreeSymbols) 1498 .treeTypes(showTreeTypes); 1499 1500 if (before.isEmpty() && after.isEmpty()) { 1501 if (h.name.equals("trees") && !showTreeSymbols && !showTreeTypes) 1502 after.add(TaskEvent.Kind.PARSE); 1503 else 1504 after.add(TaskEvent.Kind.ANALYZE); 1505 } 1506 1507 task.addTaskListener(new TaskListener() { 1508 public void started(TaskEvent e) { 1509 if (before.contains(e.getKind())) 1510 handle(e); 1511 } 1512 1513 public void finished(TaskEvent e) { 1514 if (after.contains(e.getKind())) 1515 handle(e); 1516 } 1517 1518 private void handle(TaskEvent e) { 1519 JCCompilationUnit unit = (JCCompilationUnit) e.getCompilationUnit(); 1520 switch (e.getKind()) { 1521 case PARSE: 1522 case ENTER: 1523 h.handle(e.getSourceFile().getName(), 1524 unit, unit, 1525 dprinter); 1526 break; 1527 1528 default: 1529 TypeElement elem = e.getTypeElement(); 1530 h.handle(elem.toString(), 1531 unit, (JCTree) trees.getTree(elem), 1532 dprinter); 1533 break; 1534 } 1535 } 1536 }); 1537 1538 task.call(); 1539 } 1540 1541 TaskEvent.Kind getKind(String s) { 1542 return TaskEvent.Kind.valueOf(s.toUpperCase()); 1543 } 1544 1545 static protected abstract class Handler { 1546 final String name; 1547 Handler(String name) { 1548 this.name = name; 1549 } 1550 abstract void handle(String label, 1551 JCCompilationUnit unit, JCTree tree, 1552 DPrinter dprinter); 1553 } 1554 1555 Map<String,Handler> getHandlers() { 1556 Map<String,Handler> map = new HashMap<String, Handler>(); 1557 for (Handler h: defaultHandlers) { 1558 map.put(h.name, h); 1559 } 1560 return map; 1561 } 1562 1563 protected final Handler[] defaultHandlers = { 1564 new Handler("trees") { 1565 @Override 1566 void handle(String name, JCCompilationUnit unit, JCTree tree, DPrinter dprinter) { 1567 dprinter.printTree(name, tree); 1568 dprinter.out.println(); 1569 } 1570 }, 1571 1572 new Handler("doctrees") { 1573 @Override 1574 void handle(final String name, final JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1575 TreeScanner ds = new DeclScanner() { 1576 public void visitDecl(JCTree tree, Symbol sym) { 1577 DocTree dt = unit.docComments.getCommentTree(tree); 1578 if (dt != null) { 1579 String label = (sym == null) ? Pretty.toSimpleString(tree) : sym.name.toString(); 1580 dprinter.printDocTree(label, dt); 1581 dprinter.out.println(); 1582 } 1583 } 1584 }; 1585 ds.scan(tree); 1586 } 1587 }, 1588 1589 new Handler("symbols") { 1590 @Override 1591 void handle(String name, JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1592 TreeScanner ds = new DeclScanner() { 1593 public void visitDecl(JCTree tree, Symbol sym) { 1594 String label = (sym == null) ? Pretty.toSimpleString(tree) : sym.name.toString(); 1595 dprinter.printSymbol(label, sym); 1596 dprinter.out.println(); 1597 } 1598 }; 1599 ds.scan(tree); 1600 } 1601 }, 1602 1603 new Handler("types") { 1604 @Override 1605 void handle(String name, JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1606 TreeScanner ts = new TreeScanner() { 1607 @Override 1608 public void scan(JCTree tree) { 1609 if (tree == null) { 1610 return; 1611 } 1612 if (tree.type != null) { 1613 String label = Pretty.toSimpleString(tree); 1614 dprinter.printType(label, tree.type); 1615 dprinter.out.println(); 1616 } 1617 super.scan(tree); 1618 } 1619 }; 1620 ts.scan(tree); 1621 } 1622 } 1623 }; 1624 } 1625 1626 protected static abstract class DeclScanner extends TreeScanner { 1627 @Override 1628 public void visitClassDef(JCClassDecl tree) { 1629 visitDecl(tree, tree.sym); 1630 super.visitClassDef(tree); 1631 } 1632 1633 @Override 1634 public void visitMethodDef(JCMethodDecl tree) { 1635 visitDecl(tree, tree.sym); 1636 super.visitMethodDef(tree); 1637 } 1638 1639 @Override 1640 public void visitVarDef(JCVariableDecl tree) { 1641 visitDecl(tree, tree.sym); 1642 super.visitVarDef(tree); 1643 } 1644 1645 protected abstract void visitDecl(JCTree tree, Symbol sym); 1646 } 1647 1648 // </editor-fold> 1649 1650} 1651