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