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