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