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 + ",nextSibling:" + entryToString(getField(e, e.getClass(), "nextSibling"), table, true) 441 + ",prevSibling:" + entryToString(getField(e, e.getClass(), "prevSibling"), table, true) 442 + ((sym.owner != scope.owner) 443 ? (",BOGUS[" + sym.owner + "," + scope.owner + "]") 444 : "") 445 + ")"; 446 } 447 indexOf(T[] array, T item)448 <T> int indexOf(T[] array, T item) { 449 for (int i = 0; i < array.length; i++) { 450 if (array[i] == item) 451 return i; 452 } 453 return -1; 454 } 455 printSource(String label, JCTree tree)456 public void printSource(String label, JCTree tree) { 457 printString(label, Pretty.toSimpleString(tree, maxSrcLength)); 458 } 459 printString(String label, String text)460 public void printString(String label, String text) { 461 indent(); 462 out.print(label); 463 out.print(": "); 464 out.print(text); 465 out.println(); 466 } 467 printSymbol(String label, Symbol symbol)468 public void printSymbol(String label, Symbol symbol) { 469 printSymbol(label, symbol, Details.FULL); 470 } 471 printSymbol(String label, Symbol sym, Details details)472 protected void printSymbol(String label, Symbol sym, Details details) { 473 if (sym == null) { 474 printNull(label); 475 } else { 476 switch (details) { 477 case SUMMARY: 478 printString(label, toString(sym)); 479 break; 480 481 case FULL: 482 indent(); 483 out.print(label); 484 out.println(": " + 485 info(sym.getClass(), 486 String.format("0x%x--%s", sym.kind.ordinal(), Kinds.kindName(sym)), 487 sym.getKind()) 488 + " " + sym.name 489 + " " + hashString(sym)); 490 491 indent(+1); 492 if (showSrc) { 493 JCTree tree = (JCTree) trees.getTree(sym); 494 if (tree != null) 495 printSource("src", tree); 496 } 497 printString("flags", String.format("0x%x--%s", 498 sym.flags_field, Flags.toString(sym.flags_field))); 499 printObject("completer", sym.completer, Details.SUMMARY); // what if too long? 500 printSymbol("owner", sym.owner, Details.SUMMARY); 501 printType("type", sym.type, Details.SUMMARY); 502 printType("erasure", sym.erasure_field, Details.SUMMARY); 503 sym.accept(symVisitor, null); 504 printAnnotations("annotations", sym.getMetadata(), Details.SUMMARY); 505 indent(-1); 506 } 507 } 508 } 509 toString(Symbol sym)510 protected String toString(Symbol sym) { 511 return (printer != null) ? printer.visit(sym, locale) : String.valueOf(sym); 512 } 513 printTree(String label, JCTree tree)514 protected void printTree(String label, JCTree tree) { 515 if (tree == null) { 516 printNull(label); 517 } else { 518 indent(); 519 String ext; 520 try { 521 ext = tree.getKind().name(); 522 } catch (Throwable t) { 523 ext = "n/a"; 524 } 525 out.print(label + ": " + info(tree.getClass(), tree.getTag(), ext)); 526 if (showPositions) { 527 // We can always get start position, but to get end position 528 // and/or line+offset, we would need a JCCompilationUnit 529 out.print(" pos:" + tree.pos); 530 } 531 if (showTreeTypes && tree.type != null) 532 out.print(" type:" + toString(tree.type)); 533 Symbol sym; 534 if (showTreeSymbols && (sym = TreeInfo.symbolFor(tree)) != null) 535 out.print(" sym:" + toString(sym)); 536 out.println(); 537 538 indent(+1); 539 if (showSrc) { 540 indent(); 541 out.println("src: " + Pretty.toSimpleString(tree, maxSrcLength)); 542 } 543 tree.accept(treeVisitor); 544 indent(-1); 545 } 546 } 547 printType(String label, Type type)548 public void printType(String label, Type type) { 549 printType(label, type, Details.FULL); 550 } 551 printType(String label, Type type, Details details)552 protected void printType(String label, Type type, Details details) { 553 if (type == null) 554 printNull(label); 555 else { 556 switch (details) { 557 case SUMMARY: 558 printString(label, toString(type)); 559 break; 560 561 case FULL: 562 indent(); 563 out.print(label); 564 out.println(": " + info(type.getClass(), type.getTag(), type.getKind()) 565 + " " + hashString(type)); 566 567 indent(+1); 568 printSymbol("tsym", type.tsym, Details.SUMMARY); 569 printObject("constValue", type.constValue(), Details.SUMMARY); 570 printObject("annotations", type.getAnnotationMirrors(), Details.SUMMARY); 571 type.accept(typeVisitor, null); 572 indent(-1); 573 } 574 } 575 } 576 toString(Type type)577 protected String toString(Type type) { 578 return (printer != null) ? printer.visit(type, locale) : String.valueOf(type); 579 } 580 hashString(Object obj)581 protected String hashString(Object obj) { 582 return String.format("#%x", obj.hashCode()); 583 } 584 info(Class<?> clazz, Object internal, Object external)585 protected String info(Class<?> clazz, Object internal, Object external) { 586 return String.format("%s,%s,%s", clazz.getSimpleName(), internal, external); 587 } 588 589 private int indent = 0; 590 indent()591 protected void indent() { 592 for (int i = 0; i < indent; i++) { 593 out.print(" "); 594 } 595 } 596 indent(int n)597 protected void indent(int n) { 598 indent += n; 599 } 600 getField(Object o, Class<?> clazz, String name)601 protected Object getField(Object o, Class<?> clazz, String name) { 602 try { 603 Field f = clazz.getDeclaredField(name); 604 boolean prev = f.isAccessible(); 605 f.setAccessible(true); 606 try { 607 return f.get(o); 608 } finally { 609 f.setAccessible(prev); 610 } 611 } catch (ReflectiveOperationException e) { 612 return e; 613 } catch (SecurityException e) { 614 return e; 615 } 616 } 617 callMethod(Object o, Class<?> clazz, String name)618 protected Object callMethod(Object o, Class<?> clazz, String name) { 619 try { 620 Method m = clazz.getDeclaredMethod(name); 621 boolean prev = m.isAccessible(); 622 m.setAccessible(true); 623 try { 624 return m.invoke(o); 625 } finally { 626 m.setAccessible(prev); 627 } 628 } catch (ReflectiveOperationException e) { 629 return e; 630 } catch (SecurityException e) { 631 return e; 632 } 633 } 634 635 // </editor-fold> 636 637 // <editor-fold defaultstate="collapsed" desc="JCTree visitor methods"> 638 639 protected JCTree.Visitor treeVisitor = new TreeVisitor(); 640 641 /** 642 * Default visitor class for JCTree (AST) objects. 643 */ 644 public class TreeVisitor extends JCTree.Visitor { 645 @Override visitTopLevel(JCCompilationUnit tree)646 public void visitTopLevel(JCCompilationUnit tree) { 647 printList("packageAnnotations", tree.getPackageAnnotations()); 648 printList("defs", tree.defs); 649 } 650 651 @Override visitPackageDef(JCPackageDecl tree)652 public void visitPackageDef(JCPackageDecl tree) { 653 printTree("pid", tree.pid); 654 } 655 656 @Override visitImport(JCImport tree)657 public void visitImport(JCImport tree) { 658 printTree("qualid", tree.qualid); 659 } 660 661 @Override visitClassDef(JCClassDecl tree)662 public void visitClassDef(JCClassDecl tree) { 663 printName("name", tree.name); 664 printTree("mods", tree.mods); 665 printList("typarams", tree.typarams); 666 printTree("extending", tree.extending); 667 printList("implementing", tree.implementing); 668 printList("defs", tree.defs); 669 } 670 671 @Override visitMethodDef(JCMethodDecl tree)672 public void visitMethodDef(JCMethodDecl tree) { 673 printName("name", tree.name); 674 printTree("mods", tree.mods); 675 printTree("restype", tree.restype); 676 printList("typarams", tree.typarams); 677 printTree("recvparam", tree.recvparam); 678 printList("params", tree.params); 679 printList("thrown", tree.thrown); 680 printTree("defaultValue", tree.defaultValue); 681 printTree("body", tree.body); 682 } 683 684 @Override visitVarDef(JCVariableDecl tree)685 public void visitVarDef(JCVariableDecl tree) { 686 printName("name", tree.name); 687 printTree("mods", tree.mods); 688 printTree("vartype", tree.vartype); 689 printTree("init", tree.init); 690 } 691 692 @Override visitSkip(JCSkip tree)693 public void visitSkip(JCSkip tree) { 694 } 695 696 @Override visitBlock(JCBlock tree)697 public void visitBlock(JCBlock tree) { 698 printList("stats", tree.stats); 699 } 700 701 @Override visitDoLoop(JCDoWhileLoop tree)702 public void visitDoLoop(JCDoWhileLoop tree) { 703 printTree("body", tree.body); 704 printTree("cond", tree.cond); 705 } 706 707 @Override visitWhileLoop(JCWhileLoop tree)708 public void visitWhileLoop(JCWhileLoop tree) { 709 printTree("cond", tree.cond); 710 printTree("body", tree.body); 711 } 712 713 @Override visitForLoop(JCForLoop tree)714 public void visitForLoop(JCForLoop tree) { 715 printList("init", tree.init); 716 printTree("cond", tree.cond); 717 printList("step", tree.step); 718 printTree("body", tree.body); 719 } 720 721 @Override visitForeachLoop(JCEnhancedForLoop tree)722 public void visitForeachLoop(JCEnhancedForLoop tree) { 723 printTree("var", tree.var); 724 printTree("expr", tree.expr); 725 printTree("body", tree.body); 726 } 727 728 @Override visitLabelled(JCLabeledStatement tree)729 public void visitLabelled(JCLabeledStatement tree) { 730 printTree("body", tree.body); 731 } 732 733 @Override visitSwitch(JCSwitch tree)734 public void visitSwitch(JCSwitch tree) { 735 printTree("selector", tree.selector); 736 printList("cases", tree.cases); 737 } 738 739 @Override visitCase(JCCase tree)740 public void visitCase(JCCase tree) { 741 printList("labels", tree.labels); 742 printList("stats", tree.stats); 743 } 744 745 @Override visitSynchronized(JCSynchronized tree)746 public void visitSynchronized(JCSynchronized tree) { 747 printTree("lock", tree.lock); 748 printTree("body", tree.body); 749 } 750 751 @Override visitTry(JCTry tree)752 public void visitTry(JCTry tree) { 753 printList("resources", tree.resources); 754 printTree("body", tree.body); 755 printList("catchers", tree.catchers); 756 printTree("finalizer", tree.finalizer); 757 } 758 759 @Override visitCatch(JCCatch tree)760 public void visitCatch(JCCatch tree) { 761 printTree("param", tree.param); 762 printTree("body", tree.body); 763 } 764 765 @Override visitConditional(JCConditional tree)766 public void visitConditional(JCConditional tree) { 767 printTree("cond", tree.cond); 768 printTree("truepart", tree.truepart); 769 printTree("falsepart", tree.falsepart); 770 } 771 772 @Override visitIf(JCIf tree)773 public void visitIf(JCIf tree) { 774 printTree("cond", tree.cond); 775 printTree("thenpart", tree.thenpart); 776 printTree("elsepart", tree.elsepart); 777 } 778 779 @Override visitExec(JCExpressionStatement tree)780 public void visitExec(JCExpressionStatement tree) { 781 printTree("expr", tree.expr); 782 } 783 784 @Override visitBreak(JCBreak tree)785 public void visitBreak(JCBreak tree) { 786 printName("label", tree.label); 787 } 788 789 @Override visitYield(JCYield tree)790 public void visitYield(JCYield tree) { 791 printTree("value", tree.value); 792 } 793 794 @Override visitContinue(JCContinue tree)795 public void visitContinue(JCContinue tree) { 796 printName("label", tree.label); 797 } 798 799 @Override visitReturn(JCReturn tree)800 public void visitReturn(JCReturn tree) { 801 printTree("expr", tree.expr); 802 } 803 804 @Override visitThrow(JCThrow tree)805 public void visitThrow(JCThrow tree) { 806 printTree("expr", tree.expr); 807 } 808 809 @Override visitAssert(JCAssert tree)810 public void visitAssert(JCAssert tree) { 811 printTree("cond", tree.cond); 812 printTree("detail", tree.detail); 813 } 814 815 @Override visitApply(JCMethodInvocation tree)816 public void visitApply(JCMethodInvocation tree) { 817 printList("typeargs", tree.typeargs); 818 printTree("meth", tree.meth); 819 printList("args", tree.args); 820 } 821 822 @Override visitNewClass(JCNewClass tree)823 public void visitNewClass(JCNewClass tree) { 824 printTree("encl", tree.encl); 825 printList("typeargs", tree.typeargs); 826 printTree("clazz", tree.clazz); 827 printList("args", tree.args); 828 printTree("def", tree.def); 829 } 830 831 @Override visitNewArray(JCNewArray tree)832 public void visitNewArray(JCNewArray tree) { 833 printList("annotations", tree.annotations); 834 printTree("elemtype", tree.elemtype); 835 printList("dims", tree.dims); 836 printList("dimAnnotations", tree.dimAnnotations); 837 printList("elems", tree.elems); 838 } 839 840 @Override visitLambda(JCLambda tree)841 public void visitLambda(JCLambda tree) { 842 printTree("body", tree.body); 843 printList("params", tree.params); 844 } 845 846 @Override visitParens(JCParens tree)847 public void visitParens(JCParens tree) { 848 printTree("expr", tree.expr); 849 } 850 851 @Override visitAssign(JCAssign tree)852 public void visitAssign(JCAssign tree) { 853 printTree("lhs", tree.lhs); 854 printTree("rhs", tree.rhs); 855 } 856 857 @Override visitAssignop(JCAssignOp tree)858 public void visitAssignop(JCAssignOp tree) { 859 printTree("lhs", tree.lhs); 860 printTree("rhs", tree.rhs); 861 } 862 863 @Override visitUnary(JCUnary tree)864 public void visitUnary(JCUnary tree) { 865 printTree("arg", tree.arg); 866 } 867 868 @Override visitBinary(JCBinary tree)869 public void visitBinary(JCBinary tree) { 870 printTree("lhs", tree.lhs); 871 printTree("rhs", tree.rhs); 872 } 873 874 @Override visitTypeCast(JCTypeCast tree)875 public void visitTypeCast(JCTypeCast tree) { 876 printTree("clazz", tree.clazz); 877 printTree("expr", tree.expr); 878 } 879 880 @Override visitTypeTest(JCInstanceOf tree)881 public void visitTypeTest(JCInstanceOf tree) { 882 printTree("expr", tree.expr); 883 printTree("pattern", tree.pattern); 884 } 885 886 @Override visitIndexed(JCArrayAccess tree)887 public void visitIndexed(JCArrayAccess tree) { 888 printTree("indexed", tree.indexed); 889 printTree("index", tree.index); 890 } 891 892 @Override visitSelect(JCFieldAccess tree)893 public void visitSelect(JCFieldAccess tree) { 894 printTree("selected", tree.selected); 895 } 896 897 @Override visitReference(JCMemberReference tree)898 public void visitReference(JCMemberReference tree) { 899 printTree("expr", tree.expr); 900 printList("typeargs", tree.typeargs); 901 } 902 903 @Override visitIdent(JCIdent tree)904 public void visitIdent(JCIdent tree) { 905 printName("name", tree.name); 906 } 907 908 @Override visitLiteral(JCLiteral tree)909 public void visitLiteral(JCLiteral tree) { 910 printString("value", Pretty.toSimpleString(tree, 32)); 911 } 912 913 @Override visitTypeIdent(JCPrimitiveTypeTree tree)914 public void visitTypeIdent(JCPrimitiveTypeTree tree) { 915 printString("typetag", tree.typetag.name()); 916 } 917 918 @Override visitTypeArray(JCArrayTypeTree tree)919 public void visitTypeArray(JCArrayTypeTree tree) { 920 printTree("elemtype", tree.elemtype); 921 } 922 923 @Override visitTypeApply(JCTypeApply tree)924 public void visitTypeApply(JCTypeApply tree) { 925 printTree("clazz", tree.clazz); 926 printList("arguments", tree.arguments); 927 } 928 929 @Override visitTypeUnion(JCTypeUnion tree)930 public void visitTypeUnion(JCTypeUnion tree) { 931 printList("alternatives", tree.alternatives); 932 } 933 934 @Override visitTypeIntersection(JCTypeIntersection tree)935 public void visitTypeIntersection(JCTypeIntersection tree) { 936 printList("bounds", tree.bounds); 937 } 938 939 @Override visitTypeParameter(JCTypeParameter tree)940 public void visitTypeParameter(JCTypeParameter tree) { 941 printName("name", tree.name); 942 printList("annotations", tree.annotations); 943 printList("bounds", tree.bounds); 944 } 945 946 @Override visitWildcard(JCWildcard tree)947 public void visitWildcard(JCWildcard tree) { 948 printTree("kind", tree.kind); 949 printTree("inner", tree.inner); 950 } 951 952 @Override visitTypeBoundKind(TypeBoundKind tree)953 public void visitTypeBoundKind(TypeBoundKind tree) { 954 printString("kind", tree.kind.name()); 955 } 956 957 @Override visitModifiers(JCModifiers tree)958 public void visitModifiers(JCModifiers tree) { 959 printList("annotations", tree.annotations); 960 printString("flags", String.valueOf(Flags.asFlagSet(tree.flags))); 961 } 962 963 @Override visitAnnotation(JCAnnotation tree)964 public void visitAnnotation(JCAnnotation tree) { 965 printTree("annotationType", tree.annotationType); 966 printList("args", tree.args); 967 } 968 969 @Override visitAnnotatedType(JCAnnotatedType tree)970 public void visitAnnotatedType(JCAnnotatedType tree) { 971 printList("annotations", tree.annotations); 972 printTree("underlyingType", tree.underlyingType); 973 } 974 975 @Override visitErroneous(JCErroneous tree)976 public void visitErroneous(JCErroneous tree) { 977 printList("errs", tree.errs); 978 } 979 980 @Override visitLetExpr(LetExpr tree)981 public void visitLetExpr(LetExpr tree) { 982 printList("defs", tree.defs); 983 printTree("expr", tree.expr); 984 } 985 986 @Override visitTree(JCTree tree)987 public void visitTree(JCTree tree) { 988 Assert.error(); 989 } 990 } 991 992 // </editor-fold> 993 994 // <editor-fold defaultstate="collapsed" desc="DocTree visitor"> 995 996 protected DocTreeVisitor<Void,Void> docTreeVisitor = new DefaultDocTreeVisitor(); 997 998 /** 999 * Default visitor class for DocTree objects. 1000 * Note: each visitXYZ method ends by calling the corresponding 1001 * visit method for its superclass. 1002 */ 1003 class DefaultDocTreeVisitor implements DocTreeVisitor<Void,Void> { 1004 visitAttribute(AttributeTree node, Void p)1005 public Void visitAttribute(AttributeTree node, Void p) { 1006 printName("name", node.getName()); 1007 printString("vkind", node.getValueKind().name()); 1008 printList("value", node.getValue()); 1009 return visitTree(node, null); 1010 } 1011 visitAuthor(AuthorTree node, Void p)1012 public Void visitAuthor(AuthorTree node, Void p) { 1013 printList("name", node.getName()); 1014 return visitBlockTag(node, null); 1015 } 1016 visitComment(CommentTree node, Void p)1017 public Void visitComment(CommentTree node, Void p) { 1018 printLimitedEscapedString("body", node.getBody()); 1019 return visitTree(node, null); 1020 } 1021 visitDeprecated(DeprecatedTree node, Void p)1022 public Void visitDeprecated(DeprecatedTree node, Void p) { 1023 printList("body", node.getBody()); 1024 return visitBlockTag(node, null); 1025 } 1026 visitDocComment(DocCommentTree node, Void p)1027 public Void visitDocComment(DocCommentTree node, Void p) { 1028 printList("firstSentence", node.getFirstSentence()); 1029 printList("body", node.getBody()); 1030 printList("tags", node.getBlockTags()); 1031 return visitTree(node, null); 1032 } 1033 visitDocRoot(DocRootTree node, Void p)1034 public Void visitDocRoot(DocRootTree node, Void p) { 1035 return visitInlineTag(node, null); 1036 } 1037 1038 @Override visitDocType(DocTypeTree node, Void aVoid)1039 public Void visitDocType(DocTypeTree node, Void aVoid) { 1040 printLimitedEscapedString("body", node.getText()); 1041 return visitTree(node, null); 1042 } 1043 visitEndElement(EndElementTree node, Void p)1044 public Void visitEndElement(EndElementTree node, Void p) { 1045 printName("name", node.getName()); 1046 return visitTree(node, null); 1047 } 1048 visitEntity(EntityTree node, Void p)1049 public Void visitEntity(EntityTree node, Void p) { 1050 printName("name", node.getName()); 1051 return visitTree(node, null); 1052 } 1053 visitErroneous(ErroneousTree node, Void p)1054 public Void visitErroneous(ErroneousTree node, Void p) { 1055 printLimitedEscapedString("body", node.getBody()); 1056 printString("diag", node.getDiagnostic().getMessage(Locale.getDefault())); 1057 return visitTree(node, null); 1058 } 1059 visitHidden(HiddenTree node, Void p)1060 public Void visitHidden(HiddenTree node, Void p) { 1061 printList("body", node.getBody()); 1062 return visitBlockTag(node, null); 1063 } 1064 visitIdentifier(IdentifierTree node, Void p)1065 public Void visitIdentifier(IdentifierTree node, Void p) { 1066 printName("name", node.getName()); 1067 return visitTree(node, null); 1068 } 1069 visitIndex(IndexTree node, Void p)1070 public Void visitIndex(IndexTree node, Void p) { 1071 printString("kind", node.getKind().name()); 1072 printDocTree("term", node.getSearchTerm()); 1073 printList("desc", node.getDescription()); 1074 return visitInlineTag(node, p); 1075 } 1076 visitInheritDoc(InheritDocTree node, Void p)1077 public Void visitInheritDoc(InheritDocTree node, Void p) { 1078 return visitInlineTag(node, null); 1079 } 1080 visitLink(LinkTree node, Void p)1081 public Void visitLink(LinkTree node, Void p) { 1082 printString("kind", node.getKind().name()); 1083 printDocTree("ref", node.getReference()); 1084 printList("list", node.getLabel()); 1085 return visitInlineTag(node, null); 1086 } 1087 visitLiteral(LiteralTree node, Void p)1088 public Void visitLiteral(LiteralTree node, Void p) { 1089 printString("kind", node.getKind().name()); 1090 printDocTree("body", node.getBody()); 1091 return visitInlineTag(node, null); 1092 } 1093 visitParam(ParamTree node, Void p)1094 public Void visitParam(ParamTree node, Void p) { 1095 printString("isTypeParameter", String.valueOf(node.isTypeParameter())); 1096 printString("kind", node.getKind().name()); 1097 printList("desc", node.getDescription()); 1098 return visitBlockTag(node, null); 1099 } 1100 visitProvides(ProvidesTree node, Void p)1101 public Void visitProvides(ProvidesTree node, Void p) { 1102 printString("kind", node.getKind().name()); 1103 printDocTree("serviceType", node.getServiceType()); 1104 printList("description", node.getDescription()); 1105 return visitBlockTag(node, null); 1106 } 1107 visitReference(ReferenceTree node, Void p)1108 public Void visitReference(ReferenceTree node, Void p) { 1109 printString("signature", node.getSignature()); 1110 return visitTree(node, null); 1111 } 1112 visitReturn(ReturnTree node, Void p)1113 public Void visitReturn(ReturnTree node, Void p) { 1114 printList("desc", node.getDescription()); 1115 return visitBlockTag(node, null); 1116 } 1117 visitSee(SeeTree node, Void p)1118 public Void visitSee(SeeTree node, Void p) { 1119 printList("ref", node.getReference()); 1120 return visitBlockTag(node, null); 1121 } 1122 visitSerial(SerialTree node, Void p)1123 public Void visitSerial(SerialTree node, Void p) { 1124 printList("desc", node.getDescription()); 1125 return visitBlockTag(node, null); 1126 } 1127 visitSerialData(SerialDataTree node, Void p)1128 public Void visitSerialData(SerialDataTree node, Void p) { 1129 printList("desc", node.getDescription()); 1130 return visitBlockTag(node, null); 1131 } 1132 visitSerialField(SerialFieldTree node, Void p)1133 public Void visitSerialField(SerialFieldTree node, Void p) { 1134 printDocTree("name", node.getName()); 1135 printDocTree("type", node.getType()); 1136 printList("desc", node.getDescription()); 1137 return visitBlockTag(node, null); 1138 } 1139 visitSince(SinceTree node, Void p)1140 public Void visitSince(SinceTree node, Void p) { 1141 printList("body", node.getBody()); 1142 return visitBlockTag(node, null); 1143 } 1144 visitStartElement(StartElementTree node, Void p)1145 public Void visitStartElement(StartElementTree node, Void p) { 1146 printName("name", node.getName()); 1147 printList("attrs", node.getAttributes()); 1148 printString("selfClosing", String.valueOf(node.isSelfClosing())); 1149 return visitBlockTag(node, null); 1150 } 1151 visitSummary(SummaryTree node, Void p)1152 public Void visitSummary(SummaryTree node, Void p) { 1153 printString("name", node.getTagName()); 1154 printList("summary", node.getSummary()); 1155 return visitInlineTag(node, null); 1156 } 1157 visitText(TextTree node, Void p)1158 public Void visitText(TextTree node, Void p) { 1159 printLimitedEscapedString("body", node.getBody()); 1160 return visitTree(node, null); 1161 } 1162 visitThrows(ThrowsTree node, Void p)1163 public Void visitThrows(ThrowsTree node, Void p) { 1164 printDocTree("name", node.getExceptionName()); 1165 printList("desc", node.getDescription()); 1166 return visitBlockTag(node, null); 1167 } 1168 visitUnknownBlockTag(UnknownBlockTagTree node, Void p)1169 public Void visitUnknownBlockTag(UnknownBlockTagTree node, Void p) { 1170 printString("name", node.getTagName()); 1171 printList("content", node.getContent()); 1172 return visitBlockTag(node, null); 1173 } 1174 visitUnknownInlineTag(UnknownInlineTagTree node, Void p)1175 public Void visitUnknownInlineTag(UnknownInlineTagTree node, Void p) { 1176 printString("name", node.getTagName()); 1177 printList("content", node.getContent()); 1178 return visitInlineTag(node, null); 1179 } 1180 visitUses(UsesTree node, Void p)1181 public Void visitUses(UsesTree node, Void p) { 1182 printString("kind", node.getKind().name()); 1183 printDocTree("serviceType", node.getServiceType()); 1184 printList("description", node.getDescription()); 1185 return visitBlockTag(node, null); 1186 } 1187 visitValue(ValueTree node, Void p)1188 public Void visitValue(ValueTree node, Void p) { 1189 printDocTree("value", node.getReference()); 1190 return visitInlineTag(node, null); 1191 } 1192 visitVersion(VersionTree node, Void p)1193 public Void visitVersion(VersionTree node, Void p) { 1194 printList("body", node.getBody()); 1195 return visitBlockTag(node, null); 1196 } 1197 visitOther(DocTree node, Void p)1198 public Void visitOther(DocTree node, Void p) { 1199 return visitTree(node, null); 1200 } 1201 visitBlockTag(DocTree node, Void p)1202 public Void visitBlockTag(DocTree node, Void p) { 1203 return visitTree(node, null); 1204 } 1205 visitInlineTag(DocTree node, Void p)1206 public Void visitInlineTag(DocTree node, Void p) { 1207 return visitTree(node, null); 1208 } 1209 visitTree(DocTree node, Void p)1210 public Void visitTree(DocTree node, Void p) { 1211 return null; 1212 } 1213 } 1214 1215 // </editor-fold> 1216 1217 // <editor-fold defaultstate="collapsed" desc="Symbol visitor"> 1218 1219 protected Symbol.Visitor<Void,Void> symVisitor = new SymbolVisitor(); 1220 1221 /** 1222 * Default visitor class for Symbol objects. 1223 * Note: each visitXYZ method ends by calling the corresponding 1224 * visit method for its superclass. 1225 */ 1226 class SymbolVisitor implements Symbol.Visitor<Void,Void> { 1227 @Override visitClassSymbol(ClassSymbol sym, Void ignore)1228 public Void visitClassSymbol(ClassSymbol sym, Void ignore) { 1229 printName("fullname", sym.fullname); 1230 printName("flatname", sym.flatname); 1231 printScope("members", sym.members_field); 1232 printFileObject("sourcefile", sym.sourcefile); 1233 printFileObject("classfile", sym.classfile); 1234 // trans-local? 1235 // pool? 1236 return visitTypeSymbol(sym, null); 1237 } 1238 1239 @Override visitMethodSymbol(MethodSymbol sym, Void ignore)1240 public Void visitMethodSymbol(MethodSymbol sym, Void ignore) { 1241 // code 1242 printList("params", sym.params); 1243 return visitSymbol(sym, null); 1244 } 1245 1246 @Override visitPackageSymbol(PackageSymbol sym, Void ignore)1247 public Void visitPackageSymbol(PackageSymbol sym, Void ignore) { 1248 printName("fullname", sym.fullname); 1249 printScope("members", sym.members_field); 1250 printSymbol("package-info", sym.package_info, Details.SUMMARY); 1251 return visitTypeSymbol(sym, null); 1252 } 1253 1254 @Override visitOperatorSymbol(OperatorSymbol sym, Void ignore)1255 public Void visitOperatorSymbol(OperatorSymbol sym, Void ignore) { 1256 printInt("opcode", sym.opcode); 1257 return visitMethodSymbol(sym, null); 1258 } 1259 1260 @Override visitVarSymbol(VarSymbol sym, Void ignore)1261 public Void visitVarSymbol(VarSymbol sym, Void ignore) { 1262 printInt("pos", sym.pos); 1263 printInt("adm", sym.adr); 1264 // data is a private field, and the standard accessors may 1265 // mutate it as part of lazy evaluation. Therefore, use 1266 // reflection to get the raw data. 1267 printObject("data", getField(sym, VarSymbol.class, "data"), Details.SUMMARY); 1268 return visitSymbol(sym, null); 1269 } 1270 1271 @Override visitTypeSymbol(TypeSymbol sym, Void ignore)1272 public Void visitTypeSymbol(TypeSymbol sym, Void ignore) { 1273 return visitSymbol(sym, null); 1274 } 1275 1276 @Override visitSymbol(Symbol sym, Void ignore)1277 public Void visitSymbol(Symbol sym, Void ignore) { 1278 return null; 1279 } 1280 } 1281 1282 // </editor-fold> 1283 1284 // <editor-fold defaultstate="collapsed" desc="Type visitor"> 1285 1286 protected Type.Visitor<Void,Void> typeVisitor = new TypeVisitor(); 1287 1288 /** 1289 * Default visitor class for Type objects. 1290 * Note: each visitXYZ method ends by calling the corresponding 1291 * visit method for its superclass. 1292 */ 1293 public class TypeVisitor implements Type.Visitor<Void,Void> { visitArrayType(ArrayType type, Void ignore)1294 public Void visitArrayType(ArrayType type, Void ignore) { 1295 printType("elemType", type.elemtype, Details.FULL); 1296 return visitType(type, null); 1297 } 1298 visitCapturedType(CapturedType type, Void ignore)1299 public Void visitCapturedType(CapturedType type, Void ignore) { 1300 printType("wildcard", type.wildcard, Details.FULL); 1301 return visitTypeVar(type, null); 1302 } 1303 visitClassType(ClassType type, Void ignore)1304 public Void visitClassType(ClassType type, Void ignore) { 1305 printType("outer", type.getEnclosingType(), Details.SUMMARY); 1306 printList("typarams", type.typarams_field); 1307 printList("allparams", type.allparams_field); 1308 printType("supertype", type.supertype_field, Details.SUMMARY); 1309 printList("interfaces", type.interfaces_field); 1310 printList("allinterfaces", type.all_interfaces_field); 1311 return visitType(type, null); 1312 } 1313 visitErrorType(ErrorType type, Void ignore)1314 public Void visitErrorType(ErrorType type, Void ignore) { 1315 printType("originalType", type.getOriginalType(), Details.FULL); 1316 return visitClassType(type, null); 1317 } 1318 visitForAll(ForAll type, Void ignore)1319 public Void visitForAll(ForAll type, Void ignore) { 1320 printList("tvars", type.tvars); 1321 return visitDelegatedType(type); 1322 } 1323 visitMethodType(MethodType type, Void ignore)1324 public Void visitMethodType(MethodType type, Void ignore) { 1325 printList("argtypes", type.argtypes); 1326 printType("restype", type.restype, Details.FULL); 1327 printList("thrown", type.thrown); 1328 printType("recvtype", type.recvtype, Details.FULL); 1329 return visitType(type, null); 1330 } 1331 visitModuleType(ModuleType type, Void ignore)1332 public Void visitModuleType(ModuleType type, Void ignore) { 1333 return visitType(type, null); 1334 } 1335 visitPackageType(PackageType type, Void ignore)1336 public Void visitPackageType(PackageType type, Void ignore) { 1337 return visitType(type, null); 1338 } 1339 visitTypeVar(TypeVar type, Void ignore)1340 public Void visitTypeVar(TypeVar type, Void ignore) { 1341 // For TypeVars (and not subtypes), the bound should always be 1342 // null or bot. So, only print the bound for subtypes of TypeVar, 1343 // or if the bound is (erroneously) not null or bot. 1344 if (!type.hasTag(TypeTag.TYPEVAR) 1345 || !(type.getUpperBound() == null || type.getUpperBound().hasTag(TypeTag.BOT))) { 1346 printType("bound", type.getUpperBound(), Details.FULL); 1347 } 1348 printType("lower", type.lower, Details.FULL); 1349 return visitType(type, null); 1350 } 1351 visitUndetVar(UndetVar type, Void ignore)1352 public Void visitUndetVar(UndetVar type, Void ignore) { 1353 for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values()) 1354 printList("bounds." + ib, type.getBounds(ib)); 1355 printInt("declaredCount", type.declaredCount); 1356 printType("inst", type.getInst(), Details.SUMMARY); 1357 return visitDelegatedType(type); 1358 } 1359 visitWildcardType(WildcardType type, Void ignore)1360 public Void visitWildcardType(WildcardType type, Void ignore) { 1361 printType("type", type.type, Details.SUMMARY); 1362 printString("kind", type.kind.name()); 1363 printType("bound", type.bound, Details.SUMMARY); 1364 return visitType(type, null); 1365 } 1366 visitDelegatedType(DelegatedType type)1367 protected Void visitDelegatedType(DelegatedType type) { 1368 printType("qtype", type.qtype, Details.FULL); 1369 return visitType(type, null); 1370 } 1371 visitType(Type type, Void ignore)1372 public Void visitType(Type type, Void ignore) { 1373 return null; 1374 } 1375 } 1376 1377 // </editor-fold> 1378 1379 // <editor-fold defaultstate="collapsed" desc="Attribute (annotations) visitor"> 1380 1381 protected Attribute.Visitor attrVisitor = new AttributeVisitor(); 1382 1383 /** 1384 * Default visitor class for Attribute (annotation) objects. 1385 */ 1386 public class AttributeVisitor implements Attribute.Visitor { 1387 visitConstant(Attribute.Constant a)1388 public void visitConstant(Attribute.Constant a) { 1389 printObject("value", a.value, Details.SUMMARY); 1390 visitAttribute(a); 1391 } 1392 visitClass(Attribute.Class a)1393 public void visitClass(Attribute.Class a) { 1394 printObject("classType", a.classType, Details.SUMMARY); 1395 visitAttribute(a); 1396 } 1397 visitCompound(Attribute.Compound a)1398 public void visitCompound(Attribute.Compound a) { 1399 if (a instanceof Attribute.TypeCompound) { 1400 Attribute.TypeCompound ta = (Attribute.TypeCompound) a; 1401 // consider a custom printer? 1402 printObject("position", ta.position, Details.SUMMARY); 1403 } 1404 printObject("synthesized", a.isSynthesized(), Details.SUMMARY); 1405 printList("values", a.values); 1406 visitAttribute(a); 1407 } 1408 visitArray(Attribute.Array a)1409 public void visitArray(Attribute.Array a) { 1410 printList("values", Arrays.asList(a.values)); 1411 visitAttribute(a); 1412 } 1413 visitEnum(Attribute.Enum a)1414 public void visitEnum(Attribute.Enum a) { 1415 printSymbol("value", a.value, Details.SUMMARY); 1416 visitAttribute(a); 1417 } 1418 visitError(Attribute.Error a)1419 public void visitError(Attribute.Error a) { 1420 visitAttribute(a); 1421 } 1422 visitAttribute(Attribute a)1423 public void visitAttribute(Attribute a) { 1424 printType("type", a.type, Details.SUMMARY); 1425 } 1426 1427 } 1428 // </editor-fold> 1429 1430 // <editor-fold defaultstate="collapsed" desc="Utility front end"> 1431 1432 /** 1433 * Utility class to invoke DPrinter from the command line. 1434 */ 1435 static class Main { main(String... args)1436 public static void main(String... args) throws IOException { 1437 Main m = new Main(); 1438 PrintWriter out = new PrintWriter(System.out); 1439 try { 1440 if (args.length == 0) 1441 m.usage(out); 1442 else 1443 m.run(out, args); 1444 } finally { 1445 out.flush(); 1446 } 1447 } 1448 usage(PrintWriter out)1449 void usage(PrintWriter out) { 1450 out.println("Usage:"); 1451 out.println(" java " + Main.class.getName() + " mode [options] [javac-options]"); 1452 out.print("where mode is one of: "); 1453 String sep = ""; 1454 for (Handler h: getHandlers().values()) { 1455 out.print(sep); 1456 out.print(h.name); 1457 sep = ", "; 1458 } 1459 out.println(); 1460 out.println("and where options include:"); 1461 out.println(" -before PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); 1462 out.println(" -after PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); 1463 out.println(" -showPositions"); 1464 out.println(" -showSource"); 1465 out.println(" -showTreeSymbols"); 1466 out.println(" -showTreeTypes"); 1467 out.println(" -hideEmptyItems"); 1468 out.println(" -hideNulls"); 1469 } 1470 run(PrintWriter out, String... args)1471 void run(PrintWriter out, String... args) throws IOException { 1472 JavaCompiler c = ToolProvider.getSystemJavaCompiler(); 1473 StandardJavaFileManager fm = c.getStandardFileManager(null, null, null); 1474 1475 // DPrinter options 1476 final Set<TaskEvent.Kind> before = EnumSet.noneOf(TaskEvent.Kind.class); 1477 final Set<TaskEvent.Kind> after = EnumSet.noneOf(TaskEvent.Kind.class); 1478 boolean showPositions = false; 1479 boolean showSource = false; 1480 boolean showTreeSymbols = false; 1481 boolean showTreeTypes = false; 1482 boolean showEmptyItems = true; 1483 boolean showNulls = true; 1484 1485 // javac options 1486 Collection<String> options = new ArrayList<String>(); 1487 Collection<File> files = new ArrayList<File>(); 1488 String classpath = null; 1489 String classoutdir = null; 1490 1491 final Handler h = getHandlers().get(args[0]); 1492 if (h == null) 1493 throw new IllegalArgumentException(args[0]); 1494 1495 for (int i = 1; i < args.length; i++) { 1496 String arg = args[i]; 1497 if (arg.equals("-before") && i + 1 < args.length) { 1498 before.add(getKind(args[++i])); 1499 } else if (arg.equals("-after") && i + 1 < args.length) { 1500 after.add(getKind(args[++i])); 1501 } else if (arg.equals("-showPositions")) { 1502 showPositions = true; 1503 } else if (arg.equals("-showSource")) { 1504 showSource = true; 1505 } else if (arg.equals("-showTreeSymbols")) { 1506 showTreeSymbols = true; 1507 } else if (arg.equals("-showTreeTypes")) { 1508 showTreeTypes = true; 1509 } else if (arg.equals("-hideEmptyLists")) { 1510 showEmptyItems = false; 1511 } else if (arg.equals("-hideNulls")) { 1512 showNulls = false; 1513 } else if (arg.equals("-classpath") && i + 1 < args.length) { 1514 classpath = args[++i]; 1515 } else if (arg.equals("-d") && i + 1 < args.length) { 1516 classoutdir = args[++i]; 1517 } else if (arg.startsWith("-")) { 1518 int n = c.isSupportedOption(arg); 1519 if (n < 0) throw new IllegalArgumentException(arg); 1520 options.add(arg); 1521 while (n > 0) options.add(args[++i]); 1522 } else if (arg.endsWith(".java")) { 1523 files.add(new File(arg)); 1524 } 1525 } 1526 1527 if (classoutdir != null) { 1528 fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(classoutdir))); 1529 } 1530 1531 if (classpath != null) { 1532 Collection<File> path = new ArrayList<File>(); 1533 for (String p: classpath.split(File.pathSeparator)) { 1534 if (p.isEmpty()) continue; 1535 File f = new File(p); 1536 if (f.exists()) path.add(f); 1537 } 1538 fm.setLocation(StandardLocation.CLASS_PATH, path); 1539 } 1540 Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files); 1541 1542 JavacTask task = (JavacTask) c.getTask(out, fm, null, options, null, fos); 1543 final Trees trees = Trees.instance(task); 1544 1545 final DPrinter dprinter = new DPrinter(out, trees); 1546 dprinter.source(showSource) 1547 .emptyItems(showEmptyItems) 1548 .nulls(showNulls) 1549 .positions(showPositions) 1550 .treeSymbols(showTreeSymbols) 1551 .treeTypes(showTreeTypes); 1552 1553 if (before.isEmpty() && after.isEmpty()) { 1554 if (h.name.equals("trees") && !showTreeSymbols && !showTreeTypes) 1555 after.add(TaskEvent.Kind.PARSE); 1556 else 1557 after.add(TaskEvent.Kind.ANALYZE); 1558 } 1559 1560 task.addTaskListener(new TaskListener() { 1561 public void started(TaskEvent e) { 1562 if (before.contains(e.getKind())) 1563 handle(e); 1564 } 1565 1566 public void finished(TaskEvent e) { 1567 if (after.contains(e.getKind())) 1568 handle(e); 1569 } 1570 1571 private void handle(TaskEvent e) { 1572 JCCompilationUnit unit = (JCCompilationUnit) e.getCompilationUnit(); 1573 switch (e.getKind()) { 1574 case PARSE: 1575 case ENTER: 1576 h.handle(e.getSourceFile().getName(), 1577 unit, unit, 1578 dprinter); 1579 break; 1580 1581 default: 1582 TypeElement elem = e.getTypeElement(); 1583 h.handle(elem.toString(), 1584 unit, (JCTree) trees.getTree(elem), 1585 dprinter); 1586 break; 1587 } 1588 } 1589 }); 1590 1591 task.call(); 1592 } 1593 getKind(String s)1594 TaskEvent.Kind getKind(String s) { 1595 return TaskEvent.Kind.valueOf(s.toUpperCase()); 1596 } 1597 1598 static protected abstract class Handler { 1599 final String name; Handler(String name)1600 Handler(String name) { 1601 this.name = name; 1602 } handle(String label, JCCompilationUnit unit, JCTree tree, DPrinter dprinter)1603 abstract void handle(String label, 1604 JCCompilationUnit unit, JCTree tree, 1605 DPrinter dprinter); 1606 } 1607 getHandlers()1608 Map<String,Handler> getHandlers() { 1609 Map<String,Handler> map = new HashMap<String, Handler>(); 1610 for (Handler h: defaultHandlers) { 1611 map.put(h.name, h); 1612 } 1613 return map; 1614 } 1615 1616 protected final Handler[] defaultHandlers = { 1617 new Handler("trees") { 1618 @Override 1619 void handle(String name, JCCompilationUnit unit, JCTree tree, DPrinter dprinter) { 1620 dprinter.printTree(name, tree); 1621 dprinter.out.println(); 1622 } 1623 }, 1624 1625 new Handler("doctrees") { 1626 @Override 1627 void handle(final String name, final JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1628 TreeScanner ds = new DeclScanner() { 1629 public void visitDecl(JCTree tree, Symbol sym) { 1630 DocTree dt = unit.docComments.getCommentTree(tree); 1631 if (dt != null) { 1632 String label = (sym == null) ? Pretty.toSimpleString(tree) : sym.name.toString(); 1633 dprinter.printDocTree(label, dt); 1634 dprinter.out.println(); 1635 } 1636 } 1637 }; 1638 ds.scan(tree); 1639 } 1640 }, 1641 1642 new Handler("symbols") { 1643 @Override 1644 void handle(String name, JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1645 TreeScanner ds = new DeclScanner() { 1646 public void visitDecl(JCTree tree, Symbol sym) { 1647 String label = (sym == null) ? Pretty.toSimpleString(tree) : sym.name.toString(); 1648 dprinter.printSymbol(label, sym); 1649 dprinter.out.println(); 1650 } 1651 }; 1652 ds.scan(tree); 1653 } 1654 }, 1655 1656 new Handler("types") { 1657 @Override 1658 void handle(String name, JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1659 TreeScanner ts = new TreeScanner() { 1660 @Override 1661 public void scan(JCTree tree) { 1662 if (tree == null) { 1663 return; 1664 } 1665 if (tree.type != null) { 1666 String label = Pretty.toSimpleString(tree); 1667 dprinter.printType(label, tree.type); 1668 dprinter.out.println(); 1669 } 1670 super.scan(tree); 1671 } 1672 }; 1673 ts.scan(tree); 1674 } 1675 } 1676 }; 1677 } 1678 1679 protected static abstract class DeclScanner extends TreeScanner { 1680 @Override visitClassDef(JCClassDecl tree)1681 public void visitClassDef(JCClassDecl tree) { 1682 visitDecl(tree, tree.sym); 1683 super.visitClassDef(tree); 1684 } 1685 1686 @Override visitMethodDef(JCMethodDecl tree)1687 public void visitMethodDef(JCMethodDecl tree) { 1688 visitDecl(tree, tree.sym); 1689 super.visitMethodDef(tree); 1690 } 1691 1692 @Override visitVarDef(JCVariableDecl tree)1693 public void visitVarDef(JCVariableDecl tree) { 1694 visitDecl(tree, tree.sym); 1695 super.visitVarDef(tree); 1696 } 1697 visitDecl(JCTree tree, Symbol sym)1698 protected abstract void visitDecl(JCTree tree, Symbol sym); 1699 } 1700 1701 // </editor-fold> 1702 1703 } 1704