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.logKey).getWriter(Log.WriterKind.STDERR); 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 visitProvides(ProvidesTree node, Void p) { 1089 printString("kind", node.getKind().name()); 1090 printDocTree("serviceType", node.getServiceType()); 1091 printList("description", node.getDescription()); 1092 return visitBlockTag(node, null); 1093 } 1094 1095 public Void visitReference(ReferenceTree node, Void p) { 1096 printString("signature", node.getSignature()); 1097 return visitTree(node, null); 1098 } 1099 1100 public Void visitReturn(ReturnTree node, Void p) { 1101 printList("desc", node.getDescription()); 1102 return visitBlockTag(node, null); 1103 } 1104 1105 public Void visitSee(SeeTree node, Void p) { 1106 printList("ref", node.getReference()); 1107 return visitBlockTag(node, null); 1108 } 1109 1110 public Void visitSerial(SerialTree node, Void p) { 1111 printList("desc", node.getDescription()); 1112 return visitBlockTag(node, null); 1113 } 1114 1115 public Void visitSerialData(SerialDataTree node, Void p) { 1116 printList("desc", node.getDescription()); 1117 return visitBlockTag(node, null); 1118 } 1119 1120 public Void visitSerialField(SerialFieldTree node, Void p) { 1121 printDocTree("name", node.getName()); 1122 printDocTree("type", node.getType()); 1123 printList("desc", node.getDescription()); 1124 return visitBlockTag(node, null); 1125 } 1126 1127 public Void visitSince(SinceTree node, Void p) { 1128 printList("body", node.getBody()); 1129 return visitBlockTag(node, null); 1130 } 1131 1132 public Void visitStartElement(StartElementTree node, Void p) { 1133 printName("name", node.getName()); 1134 printList("attrs", node.getAttributes()); 1135 printString("selfClosing", String.valueOf(node.isSelfClosing())); 1136 return visitBlockTag(node, null); 1137 } 1138 1139 public Void visitText(TextTree node, Void p) { 1140 printLimitedEscapedString("body", node.getBody()); 1141 return visitTree(node, null); 1142 } 1143 1144 public Void visitThrows(ThrowsTree node, Void p) { 1145 printDocTree("name", node.getExceptionName()); 1146 printList("desc", node.getDescription()); 1147 return visitBlockTag(node, null); 1148 } 1149 1150 public Void visitUnknownBlockTag(UnknownBlockTagTree node, Void p) { 1151 printString("name", node.getTagName()); 1152 printList("content", node.getContent()); 1153 return visitBlockTag(node, null); 1154 } 1155 1156 public Void visitUnknownInlineTag(UnknownInlineTagTree node, Void p) { 1157 printString("name", node.getTagName()); 1158 printList("content", node.getContent()); 1159 return visitInlineTag(node, null); 1160 } 1161 1162 public Void visitUses(UsesTree node, Void p) { 1163 printString("kind", node.getKind().name()); 1164 printDocTree("serviceType", node.getServiceType()); 1165 printList("description", node.getDescription()); 1166 return visitBlockTag(node, null); 1167 } 1168 1169 public Void visitValue(ValueTree node, Void p) { 1170 printDocTree("value", node.getReference()); 1171 return visitInlineTag(node, null); 1172 } 1173 1174 public Void visitVersion(VersionTree node, Void p) { 1175 printList("body", node.getBody()); 1176 return visitBlockTag(node, null); 1177 } 1178 1179 public Void visitOther(DocTree node, Void p) { 1180 return visitTree(node, null); 1181 } 1182 1183 public Void visitBlockTag(DocTree node, Void p) { 1184 return visitTree(node, null); 1185 } 1186 1187 public Void visitInlineTag(DocTree node, Void p) { 1188 return visitTree(node, null); 1189 } 1190 1191 public Void visitTree(DocTree node, Void p) { 1192 return null; 1193 } 1194 } 1195 1196 // </editor-fold> 1197 1198 // <editor-fold defaultstate="collapsed" desc="Symbol visitor"> 1199 1200 protected Symbol.Visitor<Void,Void> symVisitor = new SymbolVisitor(); 1201 1202 /** 1203 * Default visitor class for Symbol objects. 1204 * Note: each visitXYZ method ends by calling the corresponding 1205 * visit method for its superclass. 1206 */ 1207 class SymbolVisitor implements Symbol.Visitor<Void,Void> { 1208 @Override 1209 public Void visitClassSymbol(ClassSymbol sym, Void ignore) { 1210 printName("fullname", sym.fullname); 1211 printName("flatname", sym.flatname); 1212 printScope("members", sym.members_field); 1213 printFileObject("sourcefile", sym.sourcefile); 1214 printFileObject("classfile", sym.classfile); 1215 // trans-local? 1216 // pool? 1217 return visitTypeSymbol(sym, null); 1218 } 1219 1220 @Override 1221 public Void visitMethodSymbol(MethodSymbol sym, Void ignore) { 1222 // code 1223 printList("params", sym.params); 1224 printList("savedParameterNames", sym.savedParameterNames); 1225 return visitSymbol(sym, null); 1226 } 1227 1228 @Override 1229 public Void visitPackageSymbol(PackageSymbol sym, Void ignore) { 1230 printName("fullname", sym.fullname); 1231 printScope("members", sym.members_field); 1232 printSymbol("package-info", sym.package_info, Details.SUMMARY); 1233 return visitTypeSymbol(sym, null); 1234 } 1235 1236 @Override 1237 public Void visitOperatorSymbol(OperatorSymbol sym, Void ignore) { 1238 printInt("opcode", sym.opcode); 1239 return visitMethodSymbol(sym, null); 1240 } 1241 1242 @Override 1243 public Void visitVarSymbol(VarSymbol sym, Void ignore) { 1244 printInt("pos", sym.pos); 1245 printInt("adm", sym.adr); 1246 // data is a private field, and the standard accessors may 1247 // mutate it as part of lazy evaluation. Therefore, use 1248 // reflection to get the raw data. 1249 printObject("data", getField(sym, VarSymbol.class, "data"), Details.SUMMARY); 1250 return visitSymbol(sym, null); 1251 } 1252 1253 @Override 1254 public Void visitTypeSymbol(TypeSymbol sym, Void ignore) { 1255 return visitSymbol(sym, null); 1256 } 1257 1258 @Override 1259 public Void visitSymbol(Symbol sym, Void ignore) { 1260 return null; 1261 } 1262 } 1263 1264 // </editor-fold> 1265 1266 // <editor-fold defaultstate="collapsed" desc="Type visitor"> 1267 1268 protected Type.Visitor<Void,Void> typeVisitor = new TypeVisitor(); 1269 1270 /** 1271 * Default visitor class for Type objects. 1272 * Note: each visitXYZ method ends by calling the corresponding 1273 * visit method for its superclass. 1274 */ 1275 public class TypeVisitor implements Type.Visitor<Void,Void> { 1276 public Void visitArrayType(ArrayType type, Void ignore) { 1277 printType("elemType", type.elemtype, Details.FULL); 1278 return visitType(type, null); 1279 } 1280 1281 public Void visitCapturedType(CapturedType type, Void ignore) { 1282 printType("wildcard", type.wildcard, Details.FULL); 1283 return visitTypeVar(type, null); 1284 } 1285 1286 public Void visitClassType(ClassType type, Void ignore) { 1287 printType("outer", type.getEnclosingType(), Details.SUMMARY); 1288 printList("typarams", type.typarams_field); 1289 printList("allparams", type.allparams_field); 1290 printType("supertype", type.supertype_field, Details.SUMMARY); 1291 printList("interfaces", type.interfaces_field); 1292 printList("allinterfaces", type.all_interfaces_field); 1293 return visitType(type, null); 1294 } 1295 1296 public Void visitErrorType(ErrorType type, Void ignore) { 1297 printType("originalType", type.getOriginalType(), Details.FULL); 1298 return visitClassType(type, null); 1299 } 1300 1301 public Void visitForAll(ForAll type, Void ignore) { 1302 printList("tvars", type.tvars); 1303 return visitDelegatedType(type); 1304 } 1305 1306 public Void visitMethodType(MethodType type, Void ignore) { 1307 printList("argtypes", type.argtypes); 1308 printType("restype", type.restype, Details.FULL); 1309 printList("thrown", type.thrown); 1310 printType("recvtype", type.recvtype, Details.FULL); 1311 return visitType(type, null); 1312 } 1313 1314 public Void visitModuleType(ModuleType type, Void ignore) { 1315 return visitType(type, null); 1316 } 1317 1318 public Void visitPackageType(PackageType type, Void ignore) { 1319 return visitType(type, null); 1320 } 1321 1322 public Void visitTypeVar(TypeVar type, Void ignore) { 1323 // For TypeVars (and not subtypes), the bound should always be 1324 // null or bot. So, only print the bound for subtypes of TypeVar, 1325 // or if the bound is (erroneously) not null or bot. 1326 if (!type.hasTag(TypeTag.TYPEVAR) 1327 || !(type.bound == null || type.bound.hasTag(TypeTag.BOT))) { 1328 printType("bound", type.bound, Details.FULL); 1329 } 1330 printType("lower", type.lower, Details.FULL); 1331 return visitType(type, null); 1332 } 1333 1334 public Void visitUndetVar(UndetVar type, Void ignore) { 1335 for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values()) 1336 printList("bounds." + ib, type.getBounds(ib)); 1337 printInt("declaredCount", type.declaredCount); 1338 printType("inst", type.getInst(), Details.SUMMARY); 1339 return visitDelegatedType(type); 1340 } 1341 1342 public Void visitWildcardType(WildcardType type, Void ignore) { 1343 printType("type", type.type, Details.SUMMARY); 1344 printString("kind", type.kind.name()); 1345 printType("bound", type.bound, Details.SUMMARY); 1346 return visitType(type, null); 1347 } 1348 1349 protected Void visitDelegatedType(DelegatedType type) { 1350 printType("qtype", type.qtype, Details.FULL); 1351 return visitType(type, null); 1352 } 1353 1354 public Void visitType(Type type, Void ignore) { 1355 return null; 1356 } 1357 } 1358 1359 // </editor-fold> 1360 1361 // <editor-fold defaultstate="collapsed" desc="Attribute (annotations) visitor"> 1362 1363 protected Attribute.Visitor attrVisitor = new AttributeVisitor(); 1364 1365 /** 1366 * Default visitor class for Attribute (annotation) objects. 1367 */ 1368 public class AttributeVisitor implements Attribute.Visitor { 1369 1370 public void visitConstant(Attribute.Constant a) { 1371 printObject("value", a.value, Details.SUMMARY); 1372 visitAttribute(a); 1373 } 1374 1375 public void visitClass(Attribute.Class a) { 1376 printObject("classType", a.classType, Details.SUMMARY); 1377 visitAttribute(a); 1378 } 1379 1380 public void visitCompound(Attribute.Compound a) { 1381 if (a instanceof Attribute.TypeCompound) { 1382 Attribute.TypeCompound ta = (Attribute.TypeCompound) a; 1383 // consider a custom printer? 1384 printObject("position", ta.position, Details.SUMMARY); 1385 } 1386 printObject("synthesized", a.isSynthesized(), Details.SUMMARY); 1387 printList("values", a.values); 1388 visitAttribute(a); 1389 } 1390 1391 public void visitArray(Attribute.Array a) { 1392 printList("values", Arrays.asList(a.values)); 1393 visitAttribute(a); 1394 } 1395 1396 public void visitEnum(Attribute.Enum a) { 1397 printSymbol("value", a.value, Details.SUMMARY); 1398 visitAttribute(a); 1399 } 1400 1401 public void visitError(Attribute.Error a) { 1402 visitAttribute(a); 1403 } 1404 1405 public void visitAttribute(Attribute a) { 1406 printType("type", a.type, Details.SUMMARY); 1407 } 1408 1409 } 1410 // </editor-fold> 1411 1412 // <editor-fold defaultstate="collapsed" desc="Utility front end"> 1413 1414 /** 1415 * Utility class to invoke DPrinter from the command line. 1416 */ 1417 static class Main { 1418 public static void main(String... args) throws IOException { 1419 Main m = new Main(); 1420 PrintWriter out = new PrintWriter(System.out); 1421 try { 1422 if (args.length == 0) 1423 m.usage(out); 1424 else 1425 m.run(out, args); 1426 } finally { 1427 out.flush(); 1428 } 1429 } 1430 1431 void usage(PrintWriter out) { 1432 out.println("Usage:"); 1433 out.println(" java " + Main.class.getName() + " mode [options] [javac-options]"); 1434 out.print("where mode is one of: "); 1435 String sep = ""; 1436 for (Handler h: getHandlers().values()) { 1437 out.print(sep); 1438 out.print(h.name); 1439 sep = ", "; 1440 } 1441 out.println(); 1442 out.println("and where options include:"); 1443 out.println(" -before PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); 1444 out.println(" -after PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); 1445 out.println(" -showPositions"); 1446 out.println(" -showSource"); 1447 out.println(" -showTreeSymbols"); 1448 out.println(" -showTreeTypes"); 1449 out.println(" -hideEmptyItems"); 1450 out.println(" -hideNulls"); 1451 } 1452 1453 void run(PrintWriter out, String... args) throws IOException { 1454 JavaCompiler c = ToolProvider.getSystemJavaCompiler(); 1455 StandardJavaFileManager fm = c.getStandardFileManager(null, null, null); 1456 1457 // DPrinter options 1458 final Set<TaskEvent.Kind> before = EnumSet.noneOf(TaskEvent.Kind.class); 1459 final Set<TaskEvent.Kind> after = EnumSet.noneOf(TaskEvent.Kind.class); 1460 boolean showPositions = false; 1461 boolean showSource = false; 1462 boolean showTreeSymbols = false; 1463 boolean showTreeTypes = false; 1464 boolean showEmptyItems = true; 1465 boolean showNulls = true; 1466 1467 // javac options 1468 Collection<String> options = new ArrayList<String>(); 1469 Collection<File> files = new ArrayList<File>(); 1470 String classpath = null; 1471 String classoutdir = null; 1472 1473 final Handler h = getHandlers().get(args[0]); 1474 if (h == null) 1475 throw new IllegalArgumentException(args[0]); 1476 1477 for (int i = 1; i < args.length; i++) { 1478 String arg = args[i]; 1479 if (arg.equals("-before") && i + 1 < args.length) { 1480 before.add(getKind(args[++i])); 1481 } else if (arg.equals("-after") && i + 1 < args.length) { 1482 after.add(getKind(args[++i])); 1483 } else if (arg.equals("-showPositions")) { 1484 showPositions = true; 1485 } else if (arg.equals("-showSource")) { 1486 showSource = true; 1487 } else if (arg.equals("-showTreeSymbols")) { 1488 showTreeSymbols = true; 1489 } else if (arg.equals("-showTreeTypes")) { 1490 showTreeTypes = true; 1491 } else if (arg.equals("-hideEmptyLists")) { 1492 showEmptyItems = false; 1493 } else if (arg.equals("-hideNulls")) { 1494 showNulls = false; 1495 } else if (arg.equals("-classpath") && i + 1 < args.length) { 1496 classpath = args[++i]; 1497 } else if (arg.equals("-d") && i + 1 < args.length) { 1498 classoutdir = args[++i]; 1499 } else if (arg.startsWith("-")) { 1500 int n = c.isSupportedOption(arg); 1501 if (n < 0) throw new IllegalArgumentException(arg); 1502 options.add(arg); 1503 while (n > 0) options.add(args[++i]); 1504 } else if (arg.endsWith(".java")) { 1505 files.add(new File(arg)); 1506 } 1507 } 1508 1509 if (classoutdir != null) { 1510 fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(classoutdir))); 1511 } 1512 1513 if (classpath != null) { 1514 Collection<File> path = new ArrayList<File>(); 1515 for (String p: classpath.split(File.pathSeparator)) { 1516 if (p.isEmpty()) continue; 1517 File f = new File(p); 1518 if (f.exists()) path.add(f); 1519 } 1520 fm.setLocation(StandardLocation.CLASS_PATH, path); 1521 } 1522 Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files); 1523 1524 JavacTask task = (JavacTask) c.getTask(out, fm, null, options, null, fos); 1525 final Trees trees = Trees.instance(task); 1526 1527 final DPrinter dprinter = new DPrinter(out, trees); 1528 dprinter.source(showSource) 1529 .emptyItems(showEmptyItems) 1530 .nulls(showNulls) 1531 .positions(showPositions) 1532 .treeSymbols(showTreeSymbols) 1533 .treeTypes(showTreeTypes); 1534 1535 if (before.isEmpty() && after.isEmpty()) { 1536 if (h.name.equals("trees") && !showTreeSymbols && !showTreeTypes) 1537 after.add(TaskEvent.Kind.PARSE); 1538 else 1539 after.add(TaskEvent.Kind.ANALYZE); 1540 } 1541 1542 task.addTaskListener(new TaskListener() { 1543 public void started(TaskEvent e) { 1544 if (before.contains(e.getKind())) 1545 handle(e); 1546 } 1547 1548 public void finished(TaskEvent e) { 1549 if (after.contains(e.getKind())) 1550 handle(e); 1551 } 1552 1553 private void handle(TaskEvent e) { 1554 JCCompilationUnit unit = (JCCompilationUnit) e.getCompilationUnit(); 1555 switch (e.getKind()) { 1556 case PARSE: 1557 case ENTER: 1558 h.handle(e.getSourceFile().getName(), 1559 unit, unit, 1560 dprinter); 1561 break; 1562 1563 default: 1564 TypeElement elem = e.getTypeElement(); 1565 h.handle(elem.toString(), 1566 unit, (JCTree) trees.getTree(elem), 1567 dprinter); 1568 break; 1569 } 1570 } 1571 }); 1572 1573 task.call(); 1574 } 1575 1576 TaskEvent.Kind getKind(String s) { 1577 return TaskEvent.Kind.valueOf(s.toUpperCase()); 1578 } 1579 1580 static protected abstract class Handler { 1581 final String name; 1582 Handler(String name) { 1583 this.name = name; 1584 } 1585 abstract void handle(String label, 1586 JCCompilationUnit unit, JCTree tree, 1587 DPrinter dprinter); 1588 } 1589 1590 Map<String,Handler> getHandlers() { 1591 Map<String,Handler> map = new HashMap<String, Handler>(); 1592 for (Handler h: defaultHandlers) { 1593 map.put(h.name, h); 1594 } 1595 return map; 1596 } 1597 1598 protected final Handler[] defaultHandlers = { 1599 new Handler("trees") { 1600 @Override 1601 void handle(String name, JCCompilationUnit unit, JCTree tree, DPrinter dprinter) { 1602 dprinter.printTree(name, tree); 1603 dprinter.out.println(); 1604 } 1605 }, 1606 1607 new Handler("doctrees") { 1608 @Override 1609 void handle(final String name, final JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1610 TreeScanner ds = new DeclScanner() { 1611 public void visitDecl(JCTree tree, Symbol sym) { 1612 DocTree dt = unit.docComments.getCommentTree(tree); 1613 if (dt != null) { 1614 String label = (sym == null) ? Pretty.toSimpleString(tree) : sym.name.toString(); 1615 dprinter.printDocTree(label, dt); 1616 dprinter.out.println(); 1617 } 1618 } 1619 }; 1620 ds.scan(tree); 1621 } 1622 }, 1623 1624 new Handler("symbols") { 1625 @Override 1626 void handle(String name, JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1627 TreeScanner ds = new DeclScanner() { 1628 public void visitDecl(JCTree tree, Symbol sym) { 1629 String label = (sym == null) ? Pretty.toSimpleString(tree) : sym.name.toString(); 1630 dprinter.printSymbol(label, sym); 1631 dprinter.out.println(); 1632 } 1633 }; 1634 ds.scan(tree); 1635 } 1636 }, 1637 1638 new Handler("types") { 1639 @Override 1640 void handle(String name, JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1641 TreeScanner ts = new TreeScanner() { 1642 @Override 1643 public void scan(JCTree tree) { 1644 if (tree == null) { 1645 return; 1646 } 1647 if (tree.type != null) { 1648 String label = Pretty.toSimpleString(tree); 1649 dprinter.printType(label, tree.type); 1650 dprinter.out.println(); 1651 } 1652 super.scan(tree); 1653 } 1654 }; 1655 ts.scan(tree); 1656 } 1657 } 1658 }; 1659 } 1660 1661 protected static abstract class DeclScanner extends TreeScanner { 1662 @Override 1663 public void visitClassDef(JCClassDecl tree) { 1664 visitDecl(tree, tree.sym); 1665 super.visitClassDef(tree); 1666 } 1667 1668 @Override 1669 public void visitMethodDef(JCMethodDecl tree) { 1670 visitDecl(tree, tree.sym); 1671 super.visitMethodDef(tree); 1672 } 1673 1674 @Override 1675 public void visitVarDef(JCVariableDecl tree) { 1676 visitDecl(tree, tree.sym); 1677 super.visitVarDef(tree); 1678 } 1679 1680 protected abstract void visitDecl(JCTree tree, Symbol sym); 1681 } 1682 1683 // </editor-fold> 1684 1685} 1686