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