jdk

Форк
0
/
DPrinter.java 
1717 строк · 58.2 Кб
1
/*
2
 * Copyright (c) 2013, 2024, 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

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

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

146
    public DPrinter(PrintWriter out, Trees trees) {
147
        this.out = out;
148
        this.trees = trees;
149
    }
150

151
    public DPrinter emptyItems(boolean showEmptyItems) {
152
        this.showEmptyItems = showEmptyItems;
153
        return this;
154
    }
155

156
    public DPrinter nulls(boolean showNulls) {
157
        this.showNulls = showNulls;
158
        return this;
159
    }
160

161
    public DPrinter positions(boolean showPositions) {
162
        this.showPositions = showPositions;
163
        return this;
164
    }
165

166
    public DPrinter source(boolean showSrc) {
167
        this.showSrc = showSrc;
168
        return this;
169
    }
170

171
    public DPrinter source(int maxSrcLength) {
172
        this.showSrc = true;
173
        this.maxSrcLength = maxSrcLength;
174
        return this;
175
    }
176

177
    public DPrinter treeSymbols(boolean showTreeSymbols) {
178
        this.showTreeSymbols = showTreeSymbols;
179
        return this;
180
    }
181

182
    public DPrinter treeTypes(boolean showTreeTypes) {
183
        this.showTreeTypes = showTreeTypes;
184
        return this;
185
    }
186

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

203
    public void printAnnotations(String label, SymbolMetadata annotations) {
204
        printAnnotations(label, annotations, Details.FULL);
205
    }
206

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

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

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

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

281
    protected <T> void printImplClass(T item, Class<? extends T> stdImplClass) {
282
        if (item.getClass() != stdImplClass)
283
            printString("impl", item.getClass().getName());
284
    }
285

286
    public void printInt(String label, int i) {
287
        printString(label, String.valueOf(i));
288
    }
289

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

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

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

324
    public void printNull(String label) {
325
        if (showNulls)
326
            printString(label, NULL);
327
    }
328

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

353
    public void printScope(String label, Scope scope) {
354
        printScope(label, scope, Details.FULL);
355
    }
356

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

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
     */
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

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

456
    public void printSource(String label, JCTree tree) {
457
        printString(label, Pretty.toSimpleString(tree, maxSrcLength));
458
    }
459

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

468
    public void printSymbol(String label, Symbol symbol) {
469
        printSymbol(label, symbol, Details.FULL);
470
    }
471

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

510
    protected String toString(Symbol sym) {
511
        return (printer != null) ? printer.visit(sym, locale) : String.valueOf(sym);
512
    }
513

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

548
    public void printType(String label, Type type) {
549
        printType(label, type, Details.FULL);
550
    }
551

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

577
    protected String toString(Type type) {
578
        return (printer != null) ? printer.visit(type, locale) : String.valueOf(type);
579
    }
580

581
    protected String hashString(Object obj) {
582
        return String.format("#%x", obj.hashCode());
583
    }
584

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

591
    protected void indent() {
592
        for (int i = 0; i < indent; i++) {
593
            out.print("  ");
594
        }
595
    }
596

597
    protected void indent(int n) {
598
        indent += n;
599
    }
600

601
    protected Object getField(Object o, Class<?> clazz, String name) {
602
        try {
603
            Field f = clazz.getDeclaredField(name);
604
            @SuppressWarnings("deprecation")
605
            boolean prev = f.isAccessible();
606
            f.setAccessible(true);
607
            try {
608
                return f.get(o);
609
            } finally {
610
                f.setAccessible(prev);
611
            }
612
        } catch (ReflectiveOperationException e) {
613
            return e;
614
        } catch (SecurityException e) {
615
            return e;
616
        }
617
    }
618

619
    protected Object callMethod(Object o, Class<?> clazz, String name) {
620
        try {
621
            Method m = clazz.getDeclaredMethod(name);
622
            @SuppressWarnings("deprecation")
623
            boolean prev = m.isAccessible();
624
            m.setAccessible(true);
625
            try {
626
                return m.invoke(o);
627
            } finally {
628
                m.setAccessible(prev);
629
            }
630
        } catch (ReflectiveOperationException e) {
631
            return e;
632
        } catch (SecurityException e) {
633
            return e;
634
        }
635
    }
636

637
    // </editor-fold>
638

639
    // <editor-fold defaultstate="collapsed" desc="JCTree visitor methods">
640

641
    protected JCTree.Visitor treeVisitor = new TreeVisitor();
642

643
    /**
644
     * Default visitor class for JCTree (AST) objects.
645
     */
646
    public class TreeVisitor extends JCTree.Visitor {
647
        @Override
648
        public void visitTopLevel(JCCompilationUnit tree) {
649
            printList("packageAnnotations", tree.getPackageAnnotations());
650
            printList("defs", tree.defs);
651
        }
652

653
        @Override
654
        public void visitPackageDef(JCPackageDecl tree) {
655
            printTree("pid", tree.pid);
656
        }
657

658
        @Override
659
        public void visitImport(JCImport tree) {
660
            printTree("qualid", tree.qualid);
661
        }
662

663
        @Override
664
        public void visitClassDef(JCClassDecl tree) {
665
            printName("name", tree.name);
666
            printTree("mods", tree.mods);
667
            printList("typarams", tree.typarams);
668
            printTree("extending", tree.extending);
669
            printList("implementing", tree.implementing);
670
            printList("defs", tree.defs);
671
        }
672

673
        @Override
674
        public void visitMethodDef(JCMethodDecl tree) {
675
            printName("name", tree.name);
676
            printTree("mods", tree.mods);
677
            printTree("restype", tree.restype);
678
            printList("typarams", tree.typarams);
679
            printTree("recvparam", tree.recvparam);
680
            printList("params", tree.params);
681
            printList("thrown", tree.thrown);
682
            printTree("defaultValue", tree.defaultValue);
683
            printTree("body", tree.body);
684
        }
685

686
        @Override
687
        public void visitVarDef(JCVariableDecl tree) {
688
            printName("name", tree.name);
689
            printTree("mods", tree.mods);
690
            printTree("vartype", tree.vartype);
691
            printTree("init", tree.init);
692
        }
693

694
        @Override
695
        public void visitSkip(JCSkip tree) {
696
        }
697

698
        @Override
699
        public void visitBlock(JCBlock tree) {
700
            printList("stats", tree.stats);
701
        }
702

703
        @Override
704
        public void visitDoLoop(JCDoWhileLoop tree) {
705
            printTree("body", tree.body);
706
            printTree("cond", tree.cond);
707
        }
708

709
        @Override
710
        public void visitWhileLoop(JCWhileLoop tree) {
711
            printTree("cond", tree.cond);
712
            printTree("body", tree.body);
713
        }
714

715
        @Override
716
        public void visitForLoop(JCForLoop tree) {
717
            printList("init", tree.init);
718
            printTree("cond", tree.cond);
719
            printList("step", tree.step);
720
            printTree("body", tree.body);
721
        }
722

723
        @Override
724
        public void visitForeachLoop(JCEnhancedForLoop tree) {
725
            printTree("var", tree.var);
726
            printTree("expr", tree.expr);
727
            printTree("body", tree.body);
728
        }
729

730
        @Override
731
        public void visitLabelled(JCLabeledStatement tree) {
732
            printTree("body", tree.body);
733
        }
734

735
        @Override
736
        public void visitSwitch(JCSwitch tree) {
737
            printTree("selector", tree.selector);
738
            printList("cases", tree.cases);
739
        }
740

741
        @Override
742
        public void visitCase(JCCase tree) {
743
            printList("labels", tree.labels);
744
            printList("stats", tree.stats);
745
        }
746

747
        @Override
748
        public void visitSynchronized(JCSynchronized tree) {
749
            printTree("lock", tree.lock);
750
            printTree("body", tree.body);
751
        }
752

753
        @Override
754
        public void visitTry(JCTry tree) {
755
            printList("resources", tree.resources);
756
            printTree("body", tree.body);
757
            printList("catchers", tree.catchers);
758
            printTree("finalizer", tree.finalizer);
759
        }
760

761
        @Override
762
        public void visitCatch(JCCatch tree) {
763
            printTree("param", tree.param);
764
            printTree("body", tree.body);
765
        }
766

767
        @Override
768
        public void visitConditional(JCConditional tree) {
769
            printTree("cond", tree.cond);
770
            printTree("truepart", tree.truepart);
771
            printTree("falsepart", tree.falsepart);
772
        }
773

774
        @Override
775
        public void visitIf(JCIf tree) {
776
            printTree("cond", tree.cond);
777
            printTree("thenpart", tree.thenpart);
778
            printTree("elsepart", tree.elsepart);
779
        }
780

781
        @Override
782
        public void visitExec(JCExpressionStatement tree) {
783
            printTree("expr", tree.expr);
784
        }
785

786
        @Override
787
        public void visitBreak(JCBreak tree) {
788
            printName("label", tree.label);
789
        }
790

791
        @Override
792
        public void visitYield(JCYield tree) {
793
            printTree("value", tree.value);
794
        }
795

796
        @Override
797
        public void visitContinue(JCContinue tree) {
798
            printName("label", tree.label);
799
        }
800

801
        @Override
802
        public void visitReturn(JCReturn tree) {
803
            printTree("expr", tree.expr);
804
        }
805

806
        @Override
807
        public void visitThrow(JCThrow tree) {
808
            printTree("expr", tree.expr);
809
        }
810

811
        @Override
812
        public void visitAssert(JCAssert tree) {
813
            printTree("cond", tree.cond);
814
            printTree("detail", tree.detail);
815
        }
816

817
        @Override
818
        public void visitApply(JCMethodInvocation tree) {
819
            printList("typeargs", tree.typeargs);
820
            printTree("meth", tree.meth);
821
            printList("args", tree.args);
822
        }
823

824
        @Override
825
        public void visitNewClass(JCNewClass tree) {
826
            printTree("encl", tree.encl);
827
            printList("typeargs", tree.typeargs);
828
            printTree("clazz", tree.clazz);
829
            printList("args", tree.args);
830
            printTree("def", tree.def);
831
        }
832

833
        @Override
834
        public void visitNewArray(JCNewArray tree) {
835
            printList("annotations", tree.annotations);
836
            printTree("elemtype", tree.elemtype);
837
            printList("dims", tree.dims);
838
            printList("dimAnnotations", tree.dimAnnotations);
839
            printList("elems", tree.elems);
840
        }
841

842
        @Override
843
        public void visitLambda(JCLambda tree) {
844
            printTree("body", tree.body);
845
            printList("params", tree.params);
846
        }
847

848
        @Override
849
        public void visitParens(JCParens tree) {
850
            printTree("expr", tree.expr);
851
        }
852

853
        @Override
854
        public void visitAssign(JCAssign tree) {
855
            printTree("lhs", tree.lhs);
856
            printTree("rhs", tree.rhs);
857
        }
858

859
        @Override
860
        public void visitAssignop(JCAssignOp tree) {
861
            printTree("lhs", tree.lhs);
862
            printTree("rhs", tree.rhs);
863
        }
864

865
        @Override
866
        public void visitUnary(JCUnary tree) {
867
            printTree("arg", tree.arg);
868
        }
869

870
        @Override
871
        public void visitBinary(JCBinary tree) {
872
            printTree("lhs", tree.lhs);
873
            printTree("rhs", tree.rhs);
874
        }
875

876
        @Override
877
        public void visitTypeCast(JCTypeCast tree) {
878
            printTree("clazz", tree.clazz);
879
            printTree("expr", tree.expr);
880
        }
881

882
        @Override
883
        public void visitTypeTest(JCInstanceOf tree) {
884
            printTree("expr", tree.expr);
885
            printTree("pattern", tree.pattern);
886
        }
887

888
        @Override
889
        public void visitIndexed(JCArrayAccess tree) {
890
            printTree("indexed", tree.indexed);
891
            printTree("index", tree.index);
892
        }
893

894
        @Override
895
        public void visitSelect(JCFieldAccess tree) {
896
            printTree("selected", tree.selected);
897
        }
898

899
        @Override
900
        public void visitReference(JCMemberReference tree) {
901
            printTree("expr", tree.expr);
902
            printList("typeargs", tree.typeargs);
903
        }
904

905
        @Override
906
        public void visitIdent(JCIdent tree) {
907
            printName("name", tree.name);
908
        }
909

910
        @Override
911
        public void visitLiteral(JCLiteral tree) {
912
            printString("value", Pretty.toSimpleString(tree, 32));
913
        }
914

915
        @Override
916
        public void visitTypeIdent(JCPrimitiveTypeTree tree) {
917
            printString("typetag", tree.typetag.name());
918
        }
919

920
        @Override
921
        public void visitTypeArray(JCArrayTypeTree tree) {
922
            printTree("elemtype", tree.elemtype);
923
        }
924

925
        @Override
926
        public void visitTypeApply(JCTypeApply tree) {
927
            printTree("clazz", tree.clazz);
928
            printList("arguments", tree.arguments);
929
        }
930

931
        @Override
932
        public void visitTypeUnion(JCTypeUnion tree) {
933
            printList("alternatives", tree.alternatives);
934
        }
935

936
        @Override
937
        public void visitTypeIntersection(JCTypeIntersection tree) {
938
            printList("bounds", tree.bounds);
939
        }
940

941
        @Override
942
        public void visitTypeParameter(JCTypeParameter tree) {
943
            printName("name", tree.name);
944
            printList("annotations", tree.annotations);
945
            printList("bounds", tree.bounds);
946
        }
947

948
        @Override
949
        public void visitWildcard(JCWildcard tree) {
950
            printTree("kind", tree.kind);
951
            printTree("inner", tree.inner);
952
        }
953

954
        @Override
955
        public void visitTypeBoundKind(TypeBoundKind tree) {
956
            printString("kind", tree.kind.name());
957
        }
958

959
        @Override
960
        public void visitModifiers(JCModifiers tree) {
961
            printList("annotations", tree.annotations);
962
            printString("flags", String.valueOf(Flags.asFlagSet(tree.flags)));
963
        }
964

965
        @Override
966
        public void visitAnnotation(JCAnnotation tree) {
967
            printTree("annotationType", tree.annotationType);
968
            printList("args", tree.args);
969
        }
970

971
        @Override
972
        public void visitAnnotatedType(JCAnnotatedType tree) {
973
            printList("annotations", tree.annotations);
974
            printTree("underlyingType", tree.underlyingType);
975
        }
976

977
        @Override
978
        public void visitErroneous(JCErroneous tree) {
979
            printList("errs", tree.errs);
980
        }
981

982
        @Override
983
        public void visitLetExpr(LetExpr tree) {
984
            printList("defs", tree.defs);
985
            printTree("expr", tree.expr);
986
        }
987

988
        @Override
989
        public void visitTree(JCTree tree) {
990
            Assert.error();
991
        }
992
    }
993

994
    // </editor-fold>
995

996
    // <editor-fold defaultstate="collapsed" desc="DocTree visitor">
997

998
    protected DocTreeVisitor<Void,Void> docTreeVisitor = new DefaultDocTreeVisitor();
999

1000
    /**
1001
     * Default visitor class for DocTree objects.
1002
     * Note: each visitXYZ method ends by calling the corresponding
1003
     * visit method for its superclass.
1004
     */
1005
    class DefaultDocTreeVisitor implements DocTreeVisitor<Void,Void> {
1006

1007
        public Void visitAttribute(AttributeTree node, Void p) {
1008
            printName("name", node.getName());
1009
            printString("vkind", node.getValueKind().name());
1010
            printList("value", node.getValue());
1011
            return visitTree(node, null);
1012
        }
1013

1014
        public Void visitAuthor(AuthorTree node, Void p) {
1015
            printList("name", node.getName());
1016
            return visitBlockTag(node, null);
1017
        }
1018

1019
        public Void visitComment(CommentTree node, Void p) {
1020
            printLimitedEscapedString("body", node.getBody());
1021
            return visitTree(node, null);
1022
        }
1023

1024
        public Void visitDeprecated(DeprecatedTree node, Void p) {
1025
            printList("body", node.getBody());
1026
            return visitBlockTag(node, null);
1027
        }
1028

1029
        public Void visitDocComment(DocCommentTree node, Void p) {
1030
            printList("firstSentence", node.getFirstSentence());
1031
            printList("body", node.getBody());
1032
            printList("tags", node.getBlockTags());
1033
            return visitTree(node, null);
1034
        }
1035

1036
        public Void visitDocRoot(DocRootTree node, Void p) {
1037
            return visitInlineTag(node, null);
1038
        }
1039

1040
        @Override
1041
        public Void visitDocType(DocTypeTree node, Void aVoid) {
1042
            printLimitedEscapedString("body", node.getText());
1043
            return visitTree(node, null);
1044
        }
1045

1046
        public Void visitEndElement(EndElementTree node, Void p) {
1047
            printName("name", node.getName());
1048
            return visitTree(node, null);
1049
        }
1050

1051
        public Void visitEntity(EntityTree node, Void p) {
1052
            printName("name", node.getName());
1053
            return visitTree(node, null);
1054
        }
1055

1056
        public Void visitErroneous(ErroneousTree node, Void p) {
1057
            printLimitedEscapedString("body", node.getBody());
1058
            printString("diag", node.getDiagnostic().getMessage(Locale.getDefault()));
1059
            return visitTree(node, null);
1060
        }
1061

1062
        public Void visitHidden(HiddenTree node, Void p) {
1063
            printList("body", node.getBody());
1064
            return visitBlockTag(node, null);
1065
        }
1066

1067
        public Void visitIdentifier(IdentifierTree node, Void p) {
1068
            printName("name", node.getName());
1069
            return visitTree(node, null);
1070
        }
1071

1072
        public Void visitIndex(IndexTree node, Void p) {
1073
            printString("kind", node.getKind().name());
1074
            printDocTree("term", node.getSearchTerm());
1075
            printList("desc", node.getDescription());
1076
            return visitInlineTag(node, p);
1077
        }
1078

1079
        public Void visitInheritDoc(InheritDocTree node, Void p) {
1080
            return visitInlineTag(node, null);
1081
        }
1082

1083
        public Void visitLink(LinkTree node, Void p) {
1084
            printString("kind", node.getKind().name());
1085
            printDocTree("ref", node.getReference());
1086
            printList("list", node.getLabel());
1087
            return visitInlineTag(node, null);
1088
        }
1089

1090
        public Void visitLiteral(LiteralTree node, Void p) {
1091
            printString("kind", node.getKind().name());
1092
            printDocTree("body", node.getBody());
1093
            return visitInlineTag(node, null);
1094
        }
1095

1096
        public Void visitParam(ParamTree node, Void p) {
1097
            printString("isTypeParameter", String.valueOf(node.isTypeParameter()));
1098
            printString("kind", node.getKind().name());
1099
            printList("desc", node.getDescription());
1100
            return visitBlockTag(node, null);
1101
        }
1102

1103
        public Void visitProvides(ProvidesTree node, Void p) {
1104
            printString("kind", node.getKind().name());
1105
            printDocTree("serviceType", node.getServiceType());
1106
            printList("description", node.getDescription());
1107
            return visitBlockTag(node, null);
1108
        }
1109

1110
        public Void visitRawText(RawTextTree node, Void p) {
1111
            printLimitedEscapedString("content", node.getContent());
1112
            return visitTree(node, null);
1113
        }
1114

1115
        public Void visitReference(ReferenceTree node, Void p) {
1116
            printString("signature", node.getSignature());
1117
            return visitTree(node, null);
1118
        }
1119

1120
        public Void visitReturn(ReturnTree node, Void p) {
1121
            printList("desc", node.getDescription());
1122
            return visitBlockTag(node, null);
1123
        }
1124

1125
        public Void visitSee(SeeTree node, Void p) {
1126
            printList("ref", node.getReference());
1127
            return visitBlockTag(node, null);
1128
        }
1129

1130
        public Void visitSerial(SerialTree node, Void p) {
1131
            printList("desc", node.getDescription());
1132
            return visitBlockTag(node, null);
1133
        }
1134

1135
        public Void visitSerialData(SerialDataTree node, Void p) {
1136
            printList("desc", node.getDescription());
1137
            return visitBlockTag(node, null);
1138
        }
1139

1140
        public Void visitSerialField(SerialFieldTree node, Void p) {
1141
            printDocTree("name", node.getName());
1142
            printDocTree("type", node.getType());
1143
            printList("desc", node.getDescription());
1144
            return visitBlockTag(node, null);
1145
        }
1146

1147
        public Void visitSince(SinceTree node, Void p) {
1148
            printList("body", node.getBody());
1149
            return visitBlockTag(node, null);
1150
        }
1151

1152
        public Void visitSpec(SpecTree node, Void p) {
1153
            printDocTree("url", node.getURL());
1154
            printList("title", node.getTitle());
1155
            return visitBlockTag(node, null);
1156
        }
1157

1158
        public Void visitStartElement(StartElementTree node, Void p) {
1159
            printName("name", node.getName());
1160
            printList("attrs", node.getAttributes());
1161
            printString("selfClosing", String.valueOf(node.isSelfClosing()));
1162
            return visitBlockTag(node, null);
1163
        }
1164

1165
        public Void visitSummary(SummaryTree node, Void p) {
1166
            printString("name", node.getTagName());
1167
            printList("summary", node.getSummary());
1168
            return visitInlineTag(node, null);
1169
        }
1170

1171
        public Void visitText(TextTree node, Void p) {
1172
            printLimitedEscapedString("body", node.getBody());
1173
            return visitTree(node, null);
1174
        }
1175

1176
        public Void visitThrows(ThrowsTree node, Void p) {
1177
            printDocTree("name", node.getExceptionName());
1178
            printList("desc", node.getDescription());
1179
            return visitBlockTag(node, null);
1180
        }
1181

1182
        public Void visitUnknownBlockTag(UnknownBlockTagTree node, Void p) {
1183
            printString("name", node.getTagName());
1184
            printList("content", node.getContent());
1185
            return visitBlockTag(node, null);
1186
        }
1187

1188
        public Void visitUnknownInlineTag(UnknownInlineTagTree node, Void p) {
1189
            printString("name", node.getTagName());
1190
            printList("content", node.getContent());
1191
            return visitInlineTag(node, null);
1192
        }
1193

1194
        public Void visitUses(UsesTree node, Void p) {
1195
            printString("kind", node.getKind().name());
1196
            printDocTree("serviceType", node.getServiceType());
1197
            printList("description", node.getDescription());
1198
            return visitBlockTag(node, null);
1199
        }
1200

1201
        public Void visitValue(ValueTree node, Void p) {
1202
            printDocTree("format", node.getFormat());
1203
            printDocTree("value", node.getReference());
1204
            return visitInlineTag(node, null);
1205
        }
1206

1207
        public Void visitVersion(VersionTree node, Void p) {
1208
            printList("body", node.getBody());
1209
            return visitBlockTag(node, null);
1210
        }
1211

1212
        public Void visitOther(DocTree node, Void p) {
1213
            return visitTree(node, null);
1214
        }
1215

1216
        public Void visitBlockTag(DocTree node, Void p) {
1217
            return visitTree(node, null);
1218
        }
1219

1220
        public Void visitInlineTag(DocTree node, Void p) {
1221
            return visitTree(node, null);
1222
        }
1223

1224
        public Void visitTree(DocTree node, Void p) {
1225
            return null;
1226
        }
1227
    }
1228

1229
    // </editor-fold>
1230

1231
    // <editor-fold defaultstate="collapsed" desc="Symbol visitor">
1232

1233
    protected Symbol.Visitor<Void,Void> symVisitor = new SymbolVisitor();
1234

1235
    /**
1236
     * Default visitor class for Symbol objects.
1237
     * Note: each visitXYZ method ends by calling the corresponding
1238
     * visit method for its superclass.
1239
     */
1240
    class SymbolVisitor implements Symbol.Visitor<Void,Void> {
1241
        @Override
1242
        public Void visitClassSymbol(ClassSymbol sym, Void ignore) {
1243
            printName("fullname", sym.fullname);
1244
            printName("flatname", sym.flatname);
1245
            printScope("members", sym.members_field);
1246
            printFileObject("sourcefile", sym.sourcefile);
1247
            printFileObject("classfile", sym.classfile);
1248
            // trans-local?
1249
            // pool?
1250
            return visitTypeSymbol(sym, null);
1251
        }
1252

1253
        @Override
1254
        public Void visitMethodSymbol(MethodSymbol sym, Void ignore) {
1255
            // code
1256
            printList("params", sym.params);
1257
            return visitSymbol(sym, null);
1258
        }
1259

1260
        @Override
1261
        public Void visitPackageSymbol(PackageSymbol sym, Void ignore) {
1262
            printName("fullname", sym.fullname);
1263
            printScope("members", sym.members_field);
1264
            printSymbol("package-info", sym.package_info, Details.SUMMARY);
1265
            return visitTypeSymbol(sym, null);
1266
        }
1267

1268
        @Override
1269
        public Void visitOperatorSymbol(OperatorSymbol sym, Void ignore) {
1270
            printInt("opcode", sym.opcode);
1271
            return visitMethodSymbol(sym, null);
1272
        }
1273

1274
        @Override
1275
        public Void visitVarSymbol(VarSymbol sym, Void ignore) {
1276
            printInt("pos", sym.pos);
1277
            printInt("adm", sym.adr);
1278
            // data is a private field, and the standard accessors may
1279
            // mutate it as part of lazy evaluation. Therefore, use
1280
            // reflection to get the raw data.
1281
            printObject("data", getField(sym, VarSymbol.class, "data"), Details.SUMMARY);
1282
            return visitSymbol(sym, null);
1283
        }
1284

1285
        @Override
1286
        public Void visitTypeSymbol(TypeSymbol sym, Void ignore) {
1287
            return visitSymbol(sym, null);
1288
        }
1289

1290
        @Override
1291
        public Void visitSymbol(Symbol sym, Void ignore) {
1292
            return null;
1293
        }
1294
    }
1295

1296
    // </editor-fold>
1297

1298
    // <editor-fold defaultstate="collapsed" desc="Type visitor">
1299

1300
    protected Type.Visitor<Void,Void> typeVisitor = new TypeVisitor();
1301

1302
    /**
1303
     * Default visitor class for Type objects.
1304
     * Note: each visitXYZ method ends by calling the corresponding
1305
     * visit method for its superclass.
1306
     */
1307
    public class TypeVisitor implements Type.Visitor<Void,Void> {
1308
        public Void visitArrayType(ArrayType type, Void ignore) {
1309
            printType("elemType", type.elemtype, Details.FULL);
1310
            return visitType(type, null);
1311
        }
1312

1313
        public Void visitCapturedType(CapturedType type, Void ignore) {
1314
            printType("wildcard", type.wildcard, Details.FULL);
1315
            return visitTypeVar(type, null);
1316
        }
1317

1318
        public Void visitClassType(ClassType type, Void ignore) {
1319
            printType("outer", type.getEnclosingType(), Details.SUMMARY);
1320
            printList("typarams", type.typarams_field);
1321
            printList("allparams", type.allparams_field);
1322
            printType("supertype", type.supertype_field, Details.SUMMARY);
1323
            printList("interfaces", type.interfaces_field);
1324
            printList("allinterfaces", type.all_interfaces_field);
1325
            return visitType(type, null);
1326
        }
1327

1328
        public Void visitErrorType(ErrorType type, Void ignore) {
1329
            printType("originalType", type.getOriginalType(), Details.FULL);
1330
            return visitClassType(type, null);
1331
        }
1332

1333
        public Void visitForAll(ForAll type, Void ignore) {
1334
            printList("tvars", type.tvars);
1335
            return visitDelegatedType(type);
1336
        }
1337

1338
        public Void visitMethodType(MethodType type, Void ignore) {
1339
            printList("argtypes", type.argtypes);
1340
            printType("restype", type.restype, Details.FULL);
1341
            printList("thrown", type.thrown);
1342
            printType("recvtype", type.recvtype, Details.FULL);
1343
            return visitType(type, null);
1344
        }
1345

1346
        public Void visitModuleType(ModuleType type, Void ignore) {
1347
            return visitType(type, null);
1348
        }
1349

1350
        public Void visitPackageType(PackageType type, Void ignore) {
1351
            return visitType(type, null);
1352
        }
1353

1354
        public Void visitTypeVar(TypeVar type, Void ignore) {
1355
            // For TypeVars (and not subtypes), the bound should always be
1356
            // null or bot. So, only print the bound for subtypes of TypeVar,
1357
            // or if the bound is (erroneously) not null or bot.
1358
            if (!type.hasTag(TypeTag.TYPEVAR)
1359
                    || !(type.getUpperBound() == null || type.getUpperBound().hasTag(TypeTag.BOT))) {
1360
                printType("bound", type.getUpperBound(), Details.FULL);
1361
            }
1362
            printType("lower", type.lower, Details.FULL);
1363
            return visitType(type, null);
1364
        }
1365

1366
        public Void visitUndetVar(UndetVar type, Void ignore) {
1367
            for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values())
1368
                printList("bounds." + ib, type.getBounds(ib));
1369
            printInt("declaredCount", type.declaredCount);
1370
            printType("inst", type.getInst(), Details.SUMMARY);
1371
            return visitDelegatedType(type);
1372
        }
1373

1374
        public Void visitWildcardType(WildcardType type, Void ignore) {
1375
            printType("type", type.type, Details.SUMMARY);
1376
            printString("kind", type.kind.name());
1377
            printType("bound", type.bound, Details.SUMMARY);
1378
            return visitType(type, null);
1379
        }
1380

1381
        protected Void visitDelegatedType(DelegatedType type) {
1382
            printType("qtype", type.qtype, Details.FULL);
1383
            return visitType(type, null);
1384
        }
1385

1386
        public Void visitType(Type type, Void ignore) {
1387
            return null;
1388
        }
1389
    }
1390

1391
    // </editor-fold>
1392

1393
    // <editor-fold defaultstate="collapsed" desc="Attribute (annotations) visitor">
1394

1395
    protected Attribute.Visitor attrVisitor = new AttributeVisitor();
1396

1397
    /**
1398
     * Default visitor class for Attribute (annotation) objects.
1399
     */
1400
    public class AttributeVisitor implements Attribute.Visitor {
1401

1402
        public void visitConstant(Attribute.Constant a) {
1403
            printObject("value", a.value, Details.SUMMARY);
1404
            visitAttribute(a);
1405
        }
1406

1407
        public void visitClass(Attribute.Class a) {
1408
            printObject("classType", a.classType, Details.SUMMARY);
1409
            visitAttribute(a);
1410
        }
1411

1412
        public void visitCompound(Attribute.Compound a) {
1413
            if (a instanceof Attribute.TypeCompound) {
1414
                Attribute.TypeCompound ta = (Attribute.TypeCompound) a;
1415
                // consider a custom printer?
1416
                printObject("position", ta.position, Details.SUMMARY);
1417
            }
1418
            printObject("synthesized", a.isSynthesized(), Details.SUMMARY);
1419
            printList("values", a.values);
1420
            visitAttribute(a);
1421
        }
1422

1423
        public void visitArray(Attribute.Array a) {
1424
            printList("values", Arrays.asList(a.values));
1425
            visitAttribute(a);
1426
        }
1427

1428
        public void visitEnum(Attribute.Enum a) {
1429
            printSymbol("value", a.value, Details.SUMMARY);
1430
            visitAttribute(a);
1431
        }
1432

1433
        public void visitError(Attribute.Error a) {
1434
            visitAttribute(a);
1435
        }
1436

1437
        public void visitAttribute(Attribute a) {
1438
            printType("type", a.type, Details.SUMMARY);
1439
        }
1440

1441
    }
1442
    // </editor-fold>
1443

1444
    // <editor-fold defaultstate="collapsed" desc="Utility front end">
1445

1446
    /**
1447
     * Utility class to invoke DPrinter from the command line.
1448
     */
1449
    static class Main {
1450
        public static void main(String... args) throws IOException {
1451
            Main m = new Main();
1452
            PrintWriter out = new PrintWriter(System.out);
1453
            try {
1454
                if (args.length == 0)
1455
                    m.usage(out);
1456
                else
1457
                    m.run(out, args);
1458
            } finally {
1459
                out.flush();
1460
            }
1461
        }
1462

1463
        void usage(PrintWriter out) {
1464
            out.println("Usage:");
1465
            out.println("  java " + Main.class.getName() + " mode [options] [javac-options]");
1466
            out.print("where mode is one of: ");
1467
            String sep = "";
1468
            for (Handler h: getHandlers().values()) {
1469
                out.print(sep);
1470
                out.print(h.name);
1471
                sep = ", ";
1472
            }
1473
            out.println();
1474
            out.println("and where options include:");
1475
            out.println("  -before PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND");
1476
            out.println("  -after PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND");
1477
            out.println("  -showPositions");
1478
            out.println("  -showSource");
1479
            out.println("  -showTreeSymbols");
1480
            out.println("  -showTreeTypes");
1481
            out.println("  -hideEmptyItems");
1482
            out.println("  -hideNulls");
1483
        }
1484

1485
        void run(PrintWriter out, String... args) throws IOException {
1486
            JavaCompiler c = ToolProvider.getSystemJavaCompiler();
1487
            StandardJavaFileManager fm = c.getStandardFileManager(null, null, null);
1488

1489
            // DPrinter options
1490
            final Set<TaskEvent.Kind> before = EnumSet.noneOf(TaskEvent.Kind.class);
1491
            final Set<TaskEvent.Kind> after = EnumSet.noneOf(TaskEvent.Kind.class);
1492
            boolean showPositions = false;
1493
            boolean showSource = false;
1494
            boolean showTreeSymbols = false;
1495
            boolean showTreeTypes = false;
1496
            boolean showEmptyItems = true;
1497
            boolean showNulls = true;
1498

1499
            // javac options
1500
            Collection<String> options = new ArrayList<String>();
1501
            Collection<File> files = new ArrayList<File>();
1502
            String classpath = null;
1503
            String classoutdir = null;
1504

1505
            final Handler h = getHandlers().get(args[0]);
1506
            if (h == null)
1507
                throw new IllegalArgumentException(args[0]);
1508

1509
            for (int i = 1; i < args.length; i++) {
1510
                String arg = args[i];
1511
                if (arg.equals("-before") && i + 1 < args.length) {
1512
                    before.add(getKind(args[++i]));
1513
                } else if (arg.equals("-after") && i + 1 < args.length) {
1514
                    after.add(getKind(args[++i]));
1515
                } else if (arg.equals("-showPositions")) {
1516
                    showPositions = true;
1517
                } else if (arg.equals("-showSource")) {
1518
                    showSource = true;
1519
                } else if (arg.equals("-showTreeSymbols")) {
1520
                    showTreeSymbols = true;
1521
                } else if (arg.equals("-showTreeTypes")) {
1522
                    showTreeTypes = true;
1523
                } else if (arg.equals("-hideEmptyLists")) {
1524
                    showEmptyItems = false;
1525
                } else if (arg.equals("-hideNulls")) {
1526
                    showNulls = false;
1527
                } else if (arg.equals("-classpath") && i + 1 < args.length) {
1528
                    classpath = args[++i];
1529
                } else if (arg.equals("-d") && i + 1 < args.length) {
1530
                    classoutdir = args[++i];
1531
                } else if (arg.startsWith("-")) {
1532
                    int n = c.isSupportedOption(arg);
1533
                    if (n < 0) throw new IllegalArgumentException(arg);
1534
                    options.add(arg);
1535
                    while (n > 0) options.add(args[++i]);
1536
                } else if (arg.endsWith(".java")) {
1537
                    files.add(new File(arg));
1538
                }
1539
            }
1540

1541
            if (classoutdir != null) {
1542
                fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(classoutdir)));
1543
            }
1544

1545
            if (classpath != null) {
1546
                Collection<File> path = new ArrayList<File>();
1547
                for (String p: classpath.split(File.pathSeparator)) {
1548
                    if (p.isEmpty()) continue;
1549
                    File f = new File(p);
1550
                    if (f.exists()) path.add(f);
1551
                }
1552
                fm.setLocation(StandardLocation.CLASS_PATH, path);
1553
            }
1554
            Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files);
1555

1556
            JavacTask task = (JavacTask) c.getTask(out, fm, null, options, null, fos);
1557
            final Trees trees = Trees.instance(task);
1558

1559
            final DPrinter dprinter = new DPrinter(out, trees);
1560
            dprinter.source(showSource)
1561
                    .emptyItems(showEmptyItems)
1562
                    .nulls(showNulls)
1563
                    .positions(showPositions)
1564
                    .treeSymbols(showTreeSymbols)
1565
                    .treeTypes(showTreeTypes);
1566

1567
            if (before.isEmpty() && after.isEmpty()) {
1568
                if (h.name.equals("trees") && !showTreeSymbols && !showTreeTypes)
1569
                    after.add(TaskEvent.Kind.PARSE);
1570
                else
1571
                    after.add(TaskEvent.Kind.ANALYZE);
1572
            }
1573

1574
            task.addTaskListener(new TaskListener() {
1575
                public void started(TaskEvent e) {
1576
                    if (before.contains(e.getKind()))
1577
                        handle(e);
1578
                }
1579

1580
                public void finished(TaskEvent e) {
1581
                    if (after.contains(e.getKind()))
1582
                        handle(e);
1583
                }
1584

1585
                private void handle(TaskEvent e) {
1586
                    JCCompilationUnit unit = (JCCompilationUnit) e.getCompilationUnit();
1587
                     switch (e.getKind()) {
1588
                         case PARSE:
1589
                         case ENTER:
1590
                             h.handle(e.getSourceFile().getName(),
1591
                                     unit, unit,
1592
                                     dprinter);
1593
                             break;
1594

1595
                         default:
1596
                             TypeElement elem = e.getTypeElement();
1597
                             h.handle(elem.toString(),
1598
                                     unit, (JCTree) trees.getTree(elem),
1599
                                     dprinter);
1600
                             break;
1601
                     }
1602
                }
1603
            });
1604

1605
            task.call();
1606
        }
1607

1608
        TaskEvent.Kind getKind(String s) {
1609
            return TaskEvent.Kind.valueOf(s.toUpperCase());
1610
        }
1611

1612
        static protected abstract class Handler {
1613
            final String name;
1614
            Handler(String name) {
1615
                this.name = name;
1616
            }
1617
            abstract void handle(String label,
1618
                    JCCompilationUnit unit, JCTree tree,
1619
                    DPrinter dprinter);
1620
        }
1621

1622
        Map<String,Handler> getHandlers() {
1623
            Map<String,Handler> map = new HashMap<String, Handler>();
1624
            for (Handler h: defaultHandlers) {
1625
                map.put(h.name, h);
1626
            }
1627
            return map;
1628
        }
1629

1630
        protected final Handler[] defaultHandlers = {
1631
            new Handler("trees") {
1632
                @Override
1633
                void handle(String name, JCCompilationUnit unit, JCTree tree, DPrinter dprinter) {
1634
                    dprinter.printTree(name, tree);
1635
                    dprinter.out.println();
1636
                }
1637
            },
1638

1639
            new Handler("doctrees") {
1640
                @Override
1641
                void handle(final String name, final JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) {
1642
                    TreeScanner ds = new DeclScanner() {
1643
                        public void visitDecl(JCTree tree, Symbol sym) {
1644
                            DocTree dt = unit.docComments.getCommentTree(tree);
1645
                            if (dt != null) {
1646
                                String label = (sym == null) ? Pretty.toSimpleString(tree) : sym.name.toString();
1647
                                dprinter.printDocTree(label, dt);
1648
                                dprinter.out.println();
1649
                            }
1650
                        }
1651
                    };
1652
                    ds.scan(tree);
1653
                }
1654
            },
1655

1656
            new Handler("symbols") {
1657
                @Override
1658
                void handle(String name, JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) {
1659
                    TreeScanner ds = new DeclScanner() {
1660
                        public void visitDecl(JCTree tree, Symbol sym) {
1661
                            String label = (sym == null) ? Pretty.toSimpleString(tree) : sym.name.toString();
1662
                            dprinter.printSymbol(label, sym);
1663
                            dprinter.out.println();
1664
                        }
1665
                    };
1666
                    ds.scan(tree);
1667
                }
1668
            },
1669

1670
            new Handler("types") {
1671
                @Override
1672
                void handle(String name, JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) {
1673
                    TreeScanner ts = new TreeScanner() {
1674
                        @Override
1675
                        public void scan(JCTree tree) {
1676
                            if (tree == null) {
1677
                                return;
1678
                            }
1679
                            if (tree.type != null) {
1680
                                String label = Pretty.toSimpleString(tree);
1681
                                dprinter.printType(label, tree.type);
1682
                                dprinter.out.println();
1683
                            }
1684
                            super.scan(tree);
1685
                        }
1686
                    };
1687
                    ts.scan(tree);
1688
                }
1689
            }
1690
        };
1691
    }
1692

1693
    protected static abstract class DeclScanner extends TreeScanner {
1694
        @Override
1695
        public void visitClassDef(JCClassDecl tree) {
1696
            visitDecl(tree, tree.sym);
1697
            super.visitClassDef(tree);
1698
        }
1699

1700
        @Override
1701
        public void visitMethodDef(JCMethodDecl tree) {
1702
            visitDecl(tree, tree.sym);
1703
            super.visitMethodDef(tree);
1704
        }
1705

1706
        @Override
1707
        public void visitVarDef(JCVariableDecl tree) {
1708
            visitDecl(tree, tree.sym);
1709
            super.visitVarDef(tree);
1710
        }
1711

1712
        protected abstract void visitDecl(JCTree tree, Symbol sym);
1713
    }
1714

1715
    // </editor-fold>
1716

1717
}
1718

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.