DPrinter.java revision 3162:f164d4c2d33e
1251876Speter/* 2251876Speter * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 3251876Speter * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4251876Speter * 5251876Speter * This code is free software; you can redistribute it and/or modify it 6251876Speter * under the terms of the GNU General Public License version 2 only, as 7251876Speter * published by the Free Software Foundation. 8251876Speter * 9251876Speter * This code is distributed in the hope that it will be useful, but WITHOUT 10251876Speter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11251876Speter * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12251876Speter * version 2 for more details (a copy is included in the LICENSE file that 13251876Speter * accompanied this code). 14251876Speter * 15251876Speter * You should have received a copy of the GNU General Public License version 16251876Speter * 2 along with this work; if not, write to the Free Software Foundation, 17251876Speter * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18251876Speter * 19251876Speter * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20251876Speter * or visit www.oracle.com if you need additional information or have any 21251876Speter * questions. 22251876Speter */ 23251876Speter 24251876Speter/* @test 25251876Speter * @bug 8043484 8007307 26251876Speter * @summary Make sure DPrinter.java compiles 27251876Speter * @modules jdk.compiler/com.sun.tools.javac.api 28251876Speter * jdk.compiler/com.sun.tools.javac.code 29251876Speter * jdk.compiler/com.sun.tools.javac.tree 30251876Speter * jdk.compiler/com.sun.tools.javac.util 31251876Speter * @compile DPrinter.java 32251876Speter */ 33251876Speter 34251876Speterimport java.io.File; 35251876Speterimport java.io.IOException; 36251876Speterimport java.io.PrintWriter; 37251876Speterimport java.lang.reflect.Field; 38251876Speterimport java.lang.reflect.Method; 39251876Speterimport java.util.ArrayList; 40251876Speterimport java.util.Arrays; 41251876Speterimport java.util.Collection; 42251876Speterimport java.util.EnumSet; 43251876Speterimport java.util.HashMap; 44251876Speterimport java.util.List; 45251876Speterimport java.util.Locale; 46251876Speterimport java.util.Map; 47251876Speterimport java.util.Set; 48251876Speter 49251876Speterimport javax.lang.model.element.Name; 50251876Speterimport javax.lang.model.element.TypeElement; 51251876Speterimport javax.tools.FileObject; 52251876Speterimport javax.tools.JavaCompiler; 53251876Speterimport javax.tools.JavaFileObject; 54251876Speterimport javax.tools.StandardJavaFileManager; 55251876Speterimport javax.tools.StandardLocation; 56251876Speterimport javax.tools.ToolProvider; 57251876Speter 58251876Speterimport com.sun.source.doctree.*; 59251876Speterimport com.sun.source.util.JavacTask; 60251876Speterimport com.sun.source.util.TaskEvent; 61251876Speterimport com.sun.source.util.TaskListener; 62251876Speterimport com.sun.source.util.Trees; 63251876Speterimport com.sun.tools.javac.api.JavacTrees; 64251876Speterimport com.sun.tools.javac.code.SymbolMetadata; 65251876Speterimport com.sun.tools.javac.code.Attribute; 66251876Speterimport com.sun.tools.javac.code.Flags; 67251876Speterimport com.sun.tools.javac.code.Kinds; 68251876Speterimport com.sun.tools.javac.code.Printer; 69251876Speterimport com.sun.tools.javac.code.Scope; 70251876Speterimport com.sun.tools.javac.code.Scope.CompoundScope; 71251876Speterimport com.sun.tools.javac.code.Symbol; 72251876Speterimport com.sun.tools.javac.code.Symbol.*; 73251876Speterimport com.sun.tools.javac.code.Type; 74251876Speterimport com.sun.tools.javac.code.Type.*; 75251876Speterimport com.sun.tools.javac.code.TypeTag; 76251876Speterimport com.sun.tools.javac.tree.JCTree; 77251876Speterimport com.sun.tools.javac.tree.JCTree.*; 78251876Speterimport com.sun.tools.javac.tree.Pretty; 79251876Speterimport com.sun.tools.javac.tree.TreeInfo; 80251876Speterimport com.sun.tools.javac.tree.TreeScanner; 81251876Speterimport com.sun.tools.javac.util.Assert; 82251876Speterimport com.sun.tools.javac.util.Context; 83251876Speterimport com.sun.tools.javac.util.Convert; 84251876Speterimport com.sun.tools.javac.util.Log; 85251876Speter 86251876Speter 87251876Speter/** 88251876Speter * Debug printer for javac internals, for when toString() just isn't enough. 89251876Speter * 90251876Speter * <p> 91251876Speter * The printer provides an API to generate structured views of javac objects, 92251876Speter * such as AST nodes, symbol, types and annotations. Various aspects of the 93251876Speter * output can be configured, such as whether to show nulls, empty lists, or 94251876Speter * a compressed representation of the source code. Visitors are used to walk 95251876Speter * object hierarchies, and can be replaced with custom visitors if the default 96251876Speter * visitors are not flexible enough. 97251876Speter * 98251876Speter * <p> 99251876Speter * In general, nodes are printed with an initial line identifying the node 100251876Speter * followed by indented lines for the child nodes. Currently, graphs are 101251876Speter * represented by printing a spanning subtree. 102251876Speter * 103251876Speter * <p> 104251876Speter * The printer can be accessed via a simple command-line utility, 105251876Speter * which makes it easy to see the internal representation of source code, 106251876Speter * such as simple test programs, during the compilation pipeline. 107251876Speter * 108251876Speter * <p><b>This is NOT part of any supported API. 109251876Speter * If you write code that depends on this, you do so at your own risk. 110251876Speter * This code and its internal interfaces are subject to change or 111251876Speter * deletion without notice.</b> 112251876Speter */ 113251876Speter 114251876Speterpublic class DPrinter { 115251876Speter protected final PrintWriter out; 116251876Speter protected final Trees trees; 117251876Speter protected Printer printer; 118251876Speter protected boolean showEmptyItems = true; 119251876Speter protected boolean showNulls = true; 120251876Speter protected boolean showPositions = false; 121251876Speter protected boolean showSrc; 122251876Speter protected boolean showTreeSymbols; 123251876Speter protected boolean showTreeTypes; 124251876Speter protected int maxSrcLength = 32; 125251876Speter protected Locale locale = Locale.getDefault(); 126251876Speter protected static final String NULL = "#null"; 127251876Speter 128251876Speter // <editor-fold defaultstate="collapsed" desc="Configuration"> 129251876Speter 130251876Speter public static DPrinter instance(Context context) { 131251876Speter DPrinter dp = context.get(DPrinter.class); 132251876Speter if (dp == null) { 133251876Speter dp = new DPrinter(context); 134251876Speter } 135251876Speter return dp; 136251876Speter 137251876Speter } 138251876Speter 139251876Speter protected DPrinter(Context context) { 140251876Speter context.put(DPrinter.class, this); 141251876Speter out = context.get(Log.outKey); 142251876Speter trees = JavacTrees.instance(context); 143251876Speter } 144251876Speter 145251876Speter public DPrinter(PrintWriter out, Trees trees) { 146251876Speter this.out = out; 147251876Speter this.trees = trees; 148251876Speter } 149251876Speter 150251876Speter public DPrinter emptyItems(boolean showEmptyItems) { 151251876Speter this.showEmptyItems = showEmptyItems; 152251876Speter return this; 153251876Speter } 154251876Speter 155251876Speter public DPrinter nulls(boolean showNulls) { 156251876Speter this.showNulls = showNulls; 157251876Speter return this; 158251876Speter } 159251876Speter 160251876Speter public DPrinter positions(boolean showPositions) { 161251876Speter this.showPositions = showPositions; 162251876Speter return this; 163251876Speter } 164251876Speter 165251876Speter public DPrinter source(boolean showSrc) { 166251876Speter this.showSrc = showSrc; 167251876Speter return this; 168251876Speter } 169251876Speter 170251876Speter public DPrinter source(int maxSrcLength) { 171251876Speter this.showSrc = true; 172251876Speter this.maxSrcLength = maxSrcLength; 173251876Speter return this; 174251876Speter } 175251876Speter 176251876Speter public DPrinter treeSymbols(boolean showTreeSymbols) { 177251876Speter this.showTreeSymbols = showTreeSymbols; 178251876Speter return this; 179251876Speter } 180251876Speter 181251876Speter public DPrinter treeTypes(boolean showTreeTypes) { 182251876Speter this.showTreeTypes = showTreeTypes; 183251876Speter return this; 184251876Speter } 185251876Speter 186251876Speter public DPrinter typeSymbolPrinter(Printer p) { 187251876Speter printer = p; 188251876Speter return this; 189251876Speter } 190251876Speter 191251876Speter // </editor-fold> 192251876Speter 193251876Speter // <editor-fold defaultstate="collapsed" desc="Printing"> 194251876Speter 195251876Speter protected enum Details { 196251876Speter /** A one-line non-recursive summary */ 197251876Speter SUMMARY, 198251876Speter /** Multi-line, possibly recursive. */ 199251876Speter FULL 200251876Speter }; 201251876Speter 202251876Speter public void printAnnotations(String label, SymbolMetadata annotations) { 203251876Speter printAnnotations(label, annotations, Details.FULL); 204251876Speter } 205251876Speter 206251876Speter protected void printAnnotations(String label, SymbolMetadata annotations, Details details) { 207251876Speter if (annotations == null) { 208251876Speter printNull(label); 209251876Speter } else { 210251876Speter // no SUMMARY format currently available to use 211251876Speter 212251876Speter // use reflection to get at private fields 213251876Speter Object DECL_NOT_STARTED = getField(null, SymbolMetadata.class, "DECL_NOT_STARTED"); 214251876Speter Object DECL_IN_PROGRESS = getField(null, SymbolMetadata.class, "DECL_IN_PROGRESS"); 215251876Speter Object attributes = getField(annotations, SymbolMetadata.class, "attributes"); 216251876Speter Object type_attributes = getField(annotations, SymbolMetadata.class, "type_attributes"); 217251876Speter 218251876Speter if (!showEmptyItems) { 219251876Speter if (attributes instanceof List && ((List) attributes).isEmpty() 220251876Speter && attributes != DECL_NOT_STARTED 221251876Speter && attributes != DECL_IN_PROGRESS 222251876Speter && type_attributes instanceof List && ((List) type_attributes).isEmpty()) 223251876Speter return; 224251876Speter } 225251876Speter 226251876Speter printString(label, hashString(annotations)); 227251876Speter 228251876Speter indent(+1); 229251876Speter if (attributes == DECL_NOT_STARTED) 230251876Speter printString("attributes", "DECL_NOT_STARTED"); 231251876Speter else if (attributes == DECL_IN_PROGRESS) 232251876Speter printString("attributes", "DECL_IN_PROGRESS"); 233251876Speter else if (attributes instanceof List) 234251876Speter printList("attributes", (List) attributes); 235251876Speter else 236251876Speter printObject("attributes", attributes, Details.SUMMARY); 237251876Speter 238251876Speter if (attributes instanceof List) 239251876Speter printList("type_attributes", (List) type_attributes); 240251876Speter else 241251876Speter printObject("type_attributes", type_attributes, Details.SUMMARY); 242251876Speter indent(-1); 243251876Speter } 244251876Speter } 245251876Speter 246251876Speter public void printAttribute(String label, Attribute attr) { 247251876Speter if (attr == null) { 248251876Speter printNull(label); 249251876Speter } else { 250251876Speter printString(label, attr.getClass().getSimpleName()); 251251876Speter 252251876Speter indent(+1); 253251876Speter attr.accept(attrVisitor); 254251876Speter indent(-1); 255251876Speter } 256251876Speter } 257251876Speter 258251876Speter public void printDocTree(String label, DocTree tree) { 259251876Speter if (tree == null) { 260251876Speter printNull(label); 261251876Speter } else { 262251876Speter indent(); 263251876Speter out.print(label); 264251876Speter out.println(": " + tree.getClass().getSimpleName() + "," + tree.getKind()); 265251876Speter 266251876Speter indent(+1); 267251876Speter tree.accept(docTreeVisitor, null); 268251876Speter indent(-1); 269251876Speter } 270251876Speter } 271251876Speter 272251876Speter public void printFileObject(String label, FileObject fo) { 273251876Speter if (fo == null) { 274251876Speter printNull(label); 275251876Speter } else { 276251876Speter printString(label, fo.getName()); 277251876Speter } 278251876Speter } 279251876Speter 280251876Speter protected <T> void printImplClass(T item, Class<? extends T> stdImplClass) { 281251876Speter if (item.getClass() != stdImplClass) 282251876Speter printString("impl", item.getClass().getName()); 283251876Speter } 284251876Speter 285251876Speter public void printInt(String label, int i) { 286251876Speter printString(label, String.valueOf(i)); 287251876Speter } 288251876Speter 289251876Speter public void printLimitedEscapedString(String label, String text) { 290251876Speter String s = Convert.quote(text); 291251876Speter if (s.length() > maxSrcLength) { 292251876Speter String trim = "[...]"; 293251876Speter int head = (maxSrcLength - trim.length()) * 2 / 3; 294251876Speter int tail = maxSrcLength - trim.length() - head; 295251876Speter s = s.substring(0, head) + trim + s.substring(s.length() - tail); 296251876Speter } 297251876Speter printString(label, s); 298251876Speter } 299251876Speter 300251876Speter public void printList(String label, List<?> list) { 301251876Speter if (list == null) { 302251876Speter printNull(label); 303251876Speter } else if (!list.isEmpty() || showEmptyItems) { 304251876Speter printString(label, "[" + list.size() + "]"); 305251876Speter 306251876Speter indent(+1); 307251876Speter int i = 0; 308251876Speter for (Object item: list) { 309251876Speter printObject(String.valueOf(i++), item, Details.FULL); 310251876Speter } 311251876Speter indent(-1); 312251876Speter } 313251876Speter } 314251876Speter 315251876Speter public void printName(String label, Name name) { 316262253Speter if (name == null) { 317251876Speter printNull(label); 318251876Speter } else { 319251876Speter printString(label, name.toString()); 320251876Speter } 321262253Speter } 322251876Speter 323251876Speter public void printNull(String label) { 324251876Speter if (showNulls) 325251876Speter printString(label, NULL); 326262253Speter } 327251876Speter 328251876Speter protected void printObject(String label, Object item, Details details) { 329251876Speter if (item == null) { 330251876Speter printNull(label); 331251876Speter } else if (item instanceof Attribute) { 332251876Speter printAttribute(label, (Attribute) item); 333262253Speter } else if (item instanceof Symbol) { 334251876Speter printSymbol(label, (Symbol) item, details); 335251876Speter } else if (item instanceof Type) { 336251876Speter printType(label, (Type) item, details); 337251876Speter } else if (item instanceof JCTree) { 338251876Speter printTree(label, (JCTree) item); 339251876Speter } else if (item instanceof DocTree) { 340251876Speter printDocTree(label, (DocTree) item); 341251876Speter } else if (item instanceof List) { 342251876Speter printList(label, (List) item); 343251876Speter } else if (item instanceof Name) { 344251876Speter printName(label, (Name) item); 345251876Speter } else if (item instanceof Scope) { 346251876Speter printScope(label, (Scope) item); 347251876Speter } else { 348251876Speter printString(label, String.valueOf(item)); 349251876Speter } 350251876Speter } 351251876Speter 352251876Speter public void printScope(String label, Scope scope) { 353251876Speter printScope(label, scope, Details.FULL); 354251876Speter } 355251876Speter 356251876Speter public void printScope(String label, Scope scope, Details details) { 357251876Speter if (scope == null) { 358251876Speter 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 visitIdentifier(IdentifierTree node, Void p) { 1048 printName("name", node.getName()); 1049 return visitTree(node, null); 1050 } 1051 1052 public Void visitIndex(IndexTree node, Void p) { 1053 printString("kind", node.getKind().name()); 1054 printDocTree("term", node.getSearchTerm()); 1055 printList("desc", node.getDescription()); 1056 return visitInlineTag(node, p); 1057 } 1058 1059 public Void visitInheritDoc(InheritDocTree node, Void p) { 1060 return visitInlineTag(node, null); 1061 } 1062 1063 public Void visitLink(LinkTree node, Void p) { 1064 printString("kind", node.getKind().name()); 1065 printDocTree("ref", node.getReference()); 1066 printList("list", node.getLabel()); 1067 return visitInlineTag(node, null); 1068 } 1069 1070 public Void visitLiteral(LiteralTree node, Void p) { 1071 printString("kind", node.getKind().name()); 1072 printDocTree("body", node.getBody()); 1073 return visitInlineTag(node, null); 1074 } 1075 1076 public Void visitParam(ParamTree node, Void p) { 1077 printString("isTypeParameter", String.valueOf(node.isTypeParameter())); 1078 printString("kind", node.getKind().name()); 1079 printList("desc", node.getDescription()); 1080 return visitBlockTag(node, null); 1081 } 1082 1083 public Void visitReference(ReferenceTree node, Void p) { 1084 printString("signature", node.getSignature()); 1085 return visitTree(node, null); 1086 } 1087 1088 public Void visitReturn(ReturnTree node, Void p) { 1089 printList("desc", node.getDescription()); 1090 return visitBlockTag(node, null); 1091 } 1092 1093 public Void visitSee(SeeTree node, Void p) { 1094 printList("ref", node.getReference()); 1095 return visitBlockTag(node, null); 1096 } 1097 1098 public Void visitSerial(SerialTree node, Void p) { 1099 printList("desc", node.getDescription()); 1100 return visitBlockTag(node, null); 1101 } 1102 1103 public Void visitSerialData(SerialDataTree node, Void p) { 1104 printList("desc", node.getDescription()); 1105 return visitBlockTag(node, null); 1106 } 1107 1108 public Void visitSerialField(SerialFieldTree node, Void p) { 1109 printDocTree("name", node.getName()); 1110 printDocTree("type", node.getType()); 1111 printList("desc", node.getDescription()); 1112 return visitBlockTag(node, null); 1113 } 1114 1115 public Void visitSince(SinceTree node, Void p) { 1116 printList("body", node.getBody()); 1117 return visitBlockTag(node, null); 1118 } 1119 1120 public Void visitStartElement(StartElementTree node, Void p) { 1121 printName("name", node.getName()); 1122 printList("attrs", node.getAttributes()); 1123 printString("selfClosing", String.valueOf(node.isSelfClosing())); 1124 return visitBlockTag(node, null); 1125 } 1126 1127 public Void visitText(TextTree node, Void p) { 1128 printLimitedEscapedString("body", node.getBody()); 1129 return visitTree(node, null); 1130 } 1131 1132 public Void visitThrows(ThrowsTree node, Void p) { 1133 printDocTree("name", node.getExceptionName()); 1134 printList("desc", node.getDescription()); 1135 return visitBlockTag(node, null); 1136 } 1137 1138 public Void visitUnknownBlockTag(UnknownBlockTagTree node, Void p) { 1139 printString("name", node.getTagName()); 1140 printList("content", node.getContent()); 1141 return visitBlockTag(node, null); 1142 } 1143 1144 public Void visitUnknownInlineTag(UnknownInlineTagTree node, Void p) { 1145 printString("name", node.getTagName()); 1146 printList("content", node.getContent()); 1147 return visitInlineTag(node, null); 1148 } 1149 1150 public Void visitValue(ValueTree node, Void p) { 1151 printDocTree("value", node.getReference()); 1152 return visitInlineTag(node, null); 1153 } 1154 1155 public Void visitVersion(VersionTree node, Void p) { 1156 printList("body", node.getBody()); 1157 return visitBlockTag(node, null); 1158 } 1159 1160 public Void visitOther(DocTree node, Void p) { 1161 return visitTree(node, null); 1162 } 1163 1164 public Void visitBlockTag(DocTree node, Void p) { 1165 return visitTree(node, null); 1166 } 1167 1168 public Void visitInlineTag(DocTree node, Void p) { 1169 return visitTree(node, null); 1170 } 1171 1172 public Void visitTree(DocTree node, Void p) { 1173 return null; 1174 } 1175 } 1176 1177 // </editor-fold> 1178 1179 // <editor-fold defaultstate="collapsed" desc="Symbol visitor"> 1180 1181 protected Symbol.Visitor<Void,Void> symVisitor = new SymbolVisitor(); 1182 1183 /** 1184 * Default visitor class for Symbol objects. 1185 * Note: each visitXYZ method ends by calling the corresponding 1186 * visit method for its superclass. 1187 */ 1188 class SymbolVisitor implements Symbol.Visitor<Void,Void> { 1189 @Override 1190 public Void visitClassSymbol(ClassSymbol sym, Void ignore) { 1191 printName("fullname", sym.fullname); 1192 printName("flatname", sym.flatname); 1193 printScope("members", sym.members_field); 1194 printFileObject("sourcefile", sym.sourcefile); 1195 printFileObject("classfile", sym.classfile); 1196 // trans-local? 1197 // pool? 1198 return visitTypeSymbol(sym, null); 1199 } 1200 1201 @Override 1202 public Void visitMethodSymbol(MethodSymbol sym, Void ignore) { 1203 // code 1204 printList("params", sym.params); 1205 printList("savedParameterNames", sym.savedParameterNames); 1206 return visitSymbol(sym, null); 1207 } 1208 1209 @Override 1210 public Void visitPackageSymbol(PackageSymbol sym, Void ignore) { 1211 printName("fullname", sym.fullname); 1212 printScope("members", sym.members_field); 1213 printSymbol("package-info", sym.package_info, Details.SUMMARY); 1214 return visitTypeSymbol(sym, null); 1215 } 1216 1217 @Override 1218 public Void visitOperatorSymbol(OperatorSymbol sym, Void ignore) { 1219 printInt("opcode", sym.opcode); 1220 return visitMethodSymbol(sym, null); 1221 } 1222 1223 @Override 1224 public Void visitVarSymbol(VarSymbol sym, Void ignore) { 1225 printInt("pos", sym.pos); 1226 printInt("adm", sym.adr); 1227 // data is a private field, and the standard accessors may 1228 // mutate it as part of lazy evaluation. Therefore, use 1229 // reflection to get the raw data. 1230 printObject("data", getField(sym, VarSymbol.class, "data"), Details.SUMMARY); 1231 return visitSymbol(sym, null); 1232 } 1233 1234 @Override 1235 public Void visitTypeSymbol(TypeSymbol sym, Void ignore) { 1236 return visitSymbol(sym, null); 1237 } 1238 1239 @Override 1240 public Void visitSymbol(Symbol sym, Void ignore) { 1241 return null; 1242 } 1243 } 1244 1245 // </editor-fold> 1246 1247 // <editor-fold defaultstate="collapsed" desc="Type visitor"> 1248 1249 protected Type.Visitor<Void,Void> typeVisitor = new TypeVisitor(); 1250 1251 /** 1252 * Default visitor class for Type objects. 1253 * Note: each visitXYZ method ends by calling the corresponding 1254 * visit method for its superclass. 1255 */ 1256 public class TypeVisitor implements Type.Visitor<Void,Void> { 1257 public Void visitArrayType(ArrayType type, Void ignore) { 1258 printType("elemType", type.elemtype, Details.FULL); 1259 return visitType(type, null); 1260 } 1261 1262 public Void visitCapturedType(CapturedType type, Void ignore) { 1263 printType("wildcard", type.wildcard, Details.FULL); 1264 return visitTypeVar(type, null); 1265 } 1266 1267 public Void visitClassType(ClassType type, Void ignore) { 1268 printType("outer", type.getEnclosingType(), Details.SUMMARY); 1269 printList("typarams", type.typarams_field); 1270 printList("allparams", type.allparams_field); 1271 printType("supertype", type.supertype_field, Details.SUMMARY); 1272 printList("interfaces", type.interfaces_field); 1273 printList("allinterfaces", type.all_interfaces_field); 1274 return visitType(type, null); 1275 } 1276 1277 public Void visitErrorType(ErrorType type, Void ignore) { 1278 printType("originalType", type.getOriginalType(), Details.FULL); 1279 return visitClassType(type, null); 1280 } 1281 1282 public Void visitForAll(ForAll type, Void ignore) { 1283 printList("tvars", type.tvars); 1284 return visitDelegatedType(type); 1285 } 1286 1287 public Void visitMethodType(MethodType type, Void ignore) { 1288 printList("argtypes", type.argtypes); 1289 printType("restype", type.restype, Details.FULL); 1290 printList("thrown", type.thrown); 1291 printType("recvtype", type.recvtype, Details.FULL); 1292 return visitType(type, null); 1293 } 1294 1295 public Void visitPackageType(PackageType type, Void ignore) { 1296 return visitType(type, null); 1297 } 1298 1299 public Void visitTypeVar(TypeVar type, Void ignore) { 1300 // For TypeVars (and not subtypes), the bound should always be 1301 // null or bot. So, only print the bound for subtypes of TypeVar, 1302 // or if the bound is (erroneously) not null or bot. 1303 if (!type.hasTag(TypeTag.TYPEVAR) 1304 || !(type.bound == null || type.bound.hasTag(TypeTag.BOT))) { 1305 printType("bound", type.bound, Details.FULL); 1306 } 1307 printType("lower", type.lower, Details.FULL); 1308 return visitType(type, null); 1309 } 1310 1311 public Void visitUndetVar(UndetVar type, Void ignore) { 1312 for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values()) 1313 printList("bounds." + ib, type.getBounds(ib)); 1314 printInt("declaredCount", type.declaredCount); 1315 printType("inst", type.getInst(), Details.SUMMARY); 1316 return visitDelegatedType(type); 1317 } 1318 1319 public Void visitWildcardType(WildcardType type, Void ignore) { 1320 printType("type", type.type, Details.SUMMARY); 1321 printString("kind", type.kind.name()); 1322 printType("bound", type.bound, Details.SUMMARY); 1323 return visitType(type, null); 1324 } 1325 1326 protected Void visitDelegatedType(DelegatedType type) { 1327 printType("qtype", type.qtype, Details.FULL); 1328 return visitType(type, null); 1329 } 1330 1331 public Void visitType(Type type, Void ignore) { 1332 return null; 1333 } 1334 } 1335 1336 // </editor-fold> 1337 1338 // <editor-fold defaultstate="collapsed" desc="Attribute (annotations) visitor"> 1339 1340 protected Attribute.Visitor attrVisitor = new AttributeVisitor(); 1341 1342 /** 1343 * Default visitor class for Attribute (annotation) objects. 1344 */ 1345 public class AttributeVisitor implements Attribute.Visitor { 1346 1347 public void visitConstant(Attribute.Constant a) { 1348 printObject("value", a.value, Details.SUMMARY); 1349 visitAttribute(a); 1350 } 1351 1352 public void visitClass(Attribute.Class a) { 1353 printObject("classType", a.classType, Details.SUMMARY); 1354 visitAttribute(a); 1355 } 1356 1357 public void visitCompound(Attribute.Compound a) { 1358 if (a instanceof Attribute.TypeCompound) { 1359 Attribute.TypeCompound ta = (Attribute.TypeCompound) a; 1360 // consider a custom printer? 1361 printObject("position", ta.position, Details.SUMMARY); 1362 } 1363 printObject("synthesized", a.isSynthesized(), Details.SUMMARY); 1364 printList("values", a.values); 1365 visitAttribute(a); 1366 } 1367 1368 public void visitArray(Attribute.Array a) { 1369 printList("values", Arrays.asList(a.values)); 1370 visitAttribute(a); 1371 } 1372 1373 public void visitEnum(Attribute.Enum a) { 1374 printSymbol("value", a.value, Details.SUMMARY); 1375 visitAttribute(a); 1376 } 1377 1378 public void visitError(Attribute.Error a) { 1379 visitAttribute(a); 1380 } 1381 1382 public void visitAttribute(Attribute a) { 1383 printType("type", a.type, Details.SUMMARY); 1384 } 1385 1386 } 1387 // </editor-fold> 1388 1389 // <editor-fold defaultstate="collapsed" desc="Utility front end"> 1390 1391 /** 1392 * Utility class to invoke DPrinter from the command line. 1393 */ 1394 static class Main { 1395 public static void main(String... args) throws IOException { 1396 Main m = new Main(); 1397 PrintWriter out = new PrintWriter(System.out); 1398 try { 1399 if (args.length == 0) 1400 m.usage(out); 1401 else 1402 m.run(out, args); 1403 } finally { 1404 out.flush(); 1405 } 1406 } 1407 1408 void usage(PrintWriter out) { 1409 out.println("Usage:"); 1410 out.println(" java " + Main.class.getName() + " mode [options] [javac-options]"); 1411 out.print("where mode is one of: "); 1412 String sep = ""; 1413 for (Handler h: getHandlers().values()) { 1414 out.print(sep); 1415 out.print(h.name); 1416 sep = ", "; 1417 } 1418 out.println(); 1419 out.println("and where options include:"); 1420 out.println(" -before PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); 1421 out.println(" -after PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); 1422 out.println(" -showPositions"); 1423 out.println(" -showSource"); 1424 out.println(" -showTreeSymbols"); 1425 out.println(" -showTreeTypes"); 1426 out.println(" -hideEmptyItems"); 1427 out.println(" -hideNulls"); 1428 } 1429 1430 void run(PrintWriter out, String... args) throws IOException { 1431 JavaCompiler c = ToolProvider.getSystemJavaCompiler(); 1432 StandardJavaFileManager fm = c.getStandardFileManager(null, null, null); 1433 1434 // DPrinter options 1435 final Set<TaskEvent.Kind> before = EnumSet.noneOf(TaskEvent.Kind.class); 1436 final Set<TaskEvent.Kind> after = EnumSet.noneOf(TaskEvent.Kind.class); 1437 boolean showPositions = false; 1438 boolean showSource = false; 1439 boolean showTreeSymbols = false; 1440 boolean showTreeTypes = false; 1441 boolean showEmptyItems = true; 1442 boolean showNulls = true; 1443 1444 // javac options 1445 Collection<String> options = new ArrayList<String>(); 1446 Collection<File> files = new ArrayList<File>(); 1447 String classpath = null; 1448 String classoutdir = null; 1449 1450 final Handler h = getHandlers().get(args[0]); 1451 if (h == null) 1452 throw new IllegalArgumentException(args[0]); 1453 1454 for (int i = 1; i < args.length; i++) { 1455 String arg = args[i]; 1456 if (arg.equals("-before") && i + 1 < args.length) { 1457 before.add(getKind(args[++i])); 1458 } else if (arg.equals("-after") && i + 1 < args.length) { 1459 after.add(getKind(args[++i])); 1460 } else if (arg.equals("-showPositions")) { 1461 showPositions = true; 1462 } else if (arg.equals("-showSource")) { 1463 showSource = true; 1464 } else if (arg.equals("-showTreeSymbols")) { 1465 showTreeSymbols = true; 1466 } else if (arg.equals("-showTreeTypes")) { 1467 showTreeTypes = true; 1468 } else if (arg.equals("-hideEmptyLists")) { 1469 showEmptyItems = false; 1470 } else if (arg.equals("-hideNulls")) { 1471 showNulls = false; 1472 } else if (arg.equals("-classpath") && i + 1 < args.length) { 1473 classpath = args[++i]; 1474 } else if (arg.equals("-d") && i + 1 < args.length) { 1475 classoutdir = args[++i]; 1476 } else if (arg.startsWith("-")) { 1477 int n = c.isSupportedOption(arg); 1478 if (n < 0) throw new IllegalArgumentException(arg); 1479 options.add(arg); 1480 while (n > 0) options.add(args[++i]); 1481 } else if (arg.endsWith(".java")) { 1482 files.add(new File(arg)); 1483 } 1484 } 1485 1486 if (classoutdir != null) { 1487 fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(classoutdir))); 1488 } 1489 1490 if (classpath != null) { 1491 Collection<File> path = new ArrayList<File>(); 1492 for (String p: classpath.split(File.pathSeparator)) { 1493 if (p.isEmpty()) continue; 1494 File f = new File(p); 1495 if (f.exists()) path.add(f); 1496 } 1497 fm.setLocation(StandardLocation.CLASS_PATH, path); 1498 } 1499 Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files); 1500 1501 JavacTask task = (JavacTask) c.getTask(out, fm, null, options, null, fos); 1502 final Trees trees = Trees.instance(task); 1503 1504 final DPrinter dprinter = new DPrinter(out, trees); 1505 dprinter.source(showSource) 1506 .emptyItems(showEmptyItems) 1507 .nulls(showNulls) 1508 .positions(showPositions) 1509 .treeSymbols(showTreeSymbols) 1510 .treeTypes(showTreeTypes); 1511 1512 if (before.isEmpty() && after.isEmpty()) { 1513 if (h.name.equals("trees") && !showTreeSymbols && !showTreeTypes) 1514 after.add(TaskEvent.Kind.PARSE); 1515 else 1516 after.add(TaskEvent.Kind.ANALYZE); 1517 } 1518 1519 task.addTaskListener(new TaskListener() { 1520 public void started(TaskEvent e) { 1521 if (before.contains(e.getKind())) 1522 handle(e); 1523 } 1524 1525 public void finished(TaskEvent e) { 1526 if (after.contains(e.getKind())) 1527 handle(e); 1528 } 1529 1530 private void handle(TaskEvent e) { 1531 JCCompilationUnit unit = (JCCompilationUnit) e.getCompilationUnit(); 1532 switch (e.getKind()) { 1533 case PARSE: 1534 case ENTER: 1535 h.handle(e.getSourceFile().getName(), 1536 unit, unit, 1537 dprinter); 1538 break; 1539 1540 default: 1541 TypeElement elem = e.getTypeElement(); 1542 h.handle(elem.toString(), 1543 unit, (JCTree) trees.getTree(elem), 1544 dprinter); 1545 break; 1546 } 1547 } 1548 }); 1549 1550 task.call(); 1551 } 1552 1553 TaskEvent.Kind getKind(String s) { 1554 return TaskEvent.Kind.valueOf(s.toUpperCase()); 1555 } 1556 1557 static protected abstract class Handler { 1558 final String name; 1559 Handler(String name) { 1560 this.name = name; 1561 } 1562 abstract void handle(String label, 1563 JCCompilationUnit unit, JCTree tree, 1564 DPrinter dprinter); 1565 } 1566 1567 Map<String,Handler> getHandlers() { 1568 Map<String,Handler> map = new HashMap<String, Handler>(); 1569 for (Handler h: defaultHandlers) { 1570 map.put(h.name, h); 1571 } 1572 return map; 1573 } 1574 1575 protected final Handler[] defaultHandlers = { 1576 new Handler("trees") { 1577 @Override 1578 void handle(String name, JCCompilationUnit unit, JCTree tree, DPrinter dprinter) { 1579 dprinter.printTree(name, tree); 1580 dprinter.out.println(); 1581 } 1582 }, 1583 1584 new Handler("doctrees") { 1585 @Override 1586 void handle(final String name, final JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1587 TreeScanner ds = new DeclScanner() { 1588 public void visitDecl(JCTree tree, Symbol sym) { 1589 DocTree dt = unit.docComments.getCommentTree(tree); 1590 if (dt != null) { 1591 String label = (sym == null) ? Pretty.toSimpleString(tree) : sym.name.toString(); 1592 dprinter.printDocTree(label, dt); 1593 dprinter.out.println(); 1594 } 1595 } 1596 }; 1597 ds.scan(tree); 1598 } 1599 }, 1600 1601 new Handler("symbols") { 1602 @Override 1603 void handle(String name, JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1604 TreeScanner ds = new DeclScanner() { 1605 public void visitDecl(JCTree tree, Symbol sym) { 1606 String label = (sym == null) ? Pretty.toSimpleString(tree) : sym.name.toString(); 1607 dprinter.printSymbol(label, sym); 1608 dprinter.out.println(); 1609 } 1610 }; 1611 ds.scan(tree); 1612 } 1613 }, 1614 1615 new Handler("types") { 1616 @Override 1617 void handle(String name, JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1618 TreeScanner ts = new TreeScanner() { 1619 @Override 1620 public void scan(JCTree tree) { 1621 if (tree == null) { 1622 return; 1623 } 1624 if (tree.type != null) { 1625 String label = Pretty.toSimpleString(tree); 1626 dprinter.printType(label, tree.type); 1627 dprinter.out.println(); 1628 } 1629 super.scan(tree); 1630 } 1631 }; 1632 ts.scan(tree); 1633 } 1634 } 1635 }; 1636 } 1637 1638 protected static abstract class DeclScanner extends TreeScanner { 1639 @Override 1640 public void visitClassDef(JCClassDecl tree) { 1641 visitDecl(tree, tree.sym); 1642 super.visitClassDef(tree); 1643 } 1644 1645 @Override 1646 public void visitMethodDef(JCMethodDecl tree) { 1647 visitDecl(tree, tree.sym); 1648 super.visitMethodDef(tree); 1649 } 1650 1651 @Override 1652 public void visitVarDef(JCVariableDecl tree) { 1653 visitDecl(tree, tree.sym); 1654 super.visitVarDef(tree); 1655 } 1656 1657 protected abstract void visitDecl(JCTree tree, Symbol sym); 1658 } 1659 1660 // </editor-fold> 1661 1662} 1663