DocPretty.java revision 2571:10fc81ac75b4
125603Skjc/*
225603Skjc * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
3139823Simp * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
425603Skjc *
525603Skjc * This code is free software; you can redistribute it and/or modify it
625603Skjc * under the terms of the GNU General Public License version 2 only, as
725603Skjc * published by the Free Software Foundation.  Oracle designates this
825603Skjc * particular file as subject to the "Classpath" exception as provided
925603Skjc * by Oracle in the LICENSE file that accompanied this code.
1025603Skjc *
1125603Skjc * This code is distributed in the hope that it will be useful, but WITHOUT
1225603Skjc * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1325603Skjc * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1425603Skjc * version 2 for more details (a copy is included in the LICENSE file that
1525603Skjc * accompanied this code).
1625603Skjc *
1725603Skjc * You should have received a copy of the GNU General Public License version
1825603Skjc * 2 along with this work; if not, write to the Free Software Foundation,
1925603Skjc * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2025603Skjc *
2125603Skjc * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2225603Skjc * or visit www.oracle.com if you need additional information or have any
2325603Skjc * questions.
2425603Skjc */
2525603Skjc
2625603Skjcpackage com.sun.tools.javac.tree;
2725603Skjc
2825603Skjcimport java.io.Writer;
2925603Skjc
3025603Skjcimport com.sun.source.doctree.*;
3125603Skjcimport com.sun.source.doctree.AttributeTree.ValueKind;
3225603Skjcimport com.sun.tools.javac.util.Convert;
3354263Sshinimport java.io.IOException;
3425603Skjcimport java.util.List;
3525603Skjc
3625603Skjc/**
37116720Sharti * Prints out a doc comment tree.
38116720Sharti *
39116720Sharti *  <p><b>This is NOT part of any supported API.
4032350Seivind *  If you write code that depends on this, you do so at your own risk.
4154263Sshin *  This code and its internal interfaces are subject to change or
4232925Seivind *  deletion without notice.</b>
4332350Seivind */
4425603Skjcpublic class DocPretty implements DocTreeVisitor<Void,Void> {
4525603Skjc
46114201Sharti    /**
47114201Sharti     * The output stream on which trees are printed.
4825603Skjc     */
4925603Skjc    final Writer out;
5037939Skjc
5137939Skjc    /**
52114201Sharti     * The left margin.
53117630Sharti     */
5425603Skjc    int lmargin = 0;
5525603Skjc
5625603Skjc    public DocPretty(Writer out) {
5725603Skjc        this.out = out;
5825603Skjc    }
5925603Skjc
6025603Skjc    /** Visitor method: print expression tree.
6125603Skjc     */
6225603Skjc    public void print(DocTree tree) throws IOException {
6325603Skjc        try {
6425603Skjc            if (tree == null)
6537939Skjc                print("/*missing*/");
6625603Skjc            else {
6725603Skjc                tree.accept(this, null);
6825603Skjc            }
6925603Skjc        } catch (UncheckedIOException ex) {
7025603Skjc            throw new IOException(ex.getMessage(), ex);
7125603Skjc        }
72163606Srwatson    }
73163606Srwatson
74116741Sharti    /**
75116741Sharti     * Print string, replacing all non-ascii character with unicode escapes.
76116741Sharti     */
77116741Sharti    protected void print(Object s) throws IOException {
78116741Sharti        out.write(Convert.escapeUnicode(s.toString()));
79116741Sharti    }
80116741Sharti
81116741Sharti    /**
82116741Sharti     * Print list.
83116741Sharti     */
84116741Sharti    public void print(List<? extends DocTree> list) throws IOException {
85116741Sharti        for (DocTree t: list) {
86116741Sharti            print(t);
87116741Sharti        }
88118157Sharti    }
89116741Sharti
90116741Sharti    /**
91116741Sharti     * Print list., with separators
92116741Sharti     */
93116741Sharti    protected void print(List<? extends DocTree> list, String sep) throws IOException {
94116741Sharti        if (list.isEmpty())
95116741Sharti            return;
96116741Sharti        boolean first = true;
97118157Sharti        for (DocTree t: list) {
98116741Sharti            if (!first)
99114201Sharti                print(sep);
100114201Sharti            print(t);
101249132Smav            first = false;
102147256Sbrooks        }
10337939Skjc    }
104116720Sharti
10537939Skjc    /** Print new line.
10625603Skjc     */
107116720Sharti    protected void println() throws IOException {
10825603Skjc        out.write(lineSep);
10925603Skjc    }
11025603Skjc
11125603Skjc    protected void printTagName(DocTree node) throws IOException {
11225603Skjc        out.write("@");
11325603Skjc        out.write(node.getKind().tagName);
11425603Skjc    }
115191148Skmacy
11625603Skjc    final String lineSep = System.getProperty("line.separator");
11725603Skjc
11825603Skjc    /**************************************************************************
11925603Skjc     * Traversal methods
12025603Skjc     *************************************************************************/
121191148Skmacy
12225603Skjc    /** Exception to propagate IOException through visitXXX methods */
12325603Skjc    private static class UncheckedIOException extends Error {
124116720Sharti        static final long serialVersionUID = -4032692679158424751L;
125191148Skmacy        UncheckedIOException(IOException e) {
12625603Skjc            super(e.getMessage(), e);
12725603Skjc        }
12878249Speter    }
12925603Skjc
13059633Skjc
13125603Skjc    public Void visitAttribute(AttributeTree node, Void p) {
13237939Skjc        try {
13325603Skjc            print(node.getName());
13425603Skjc            String quote;
135105576Srwatson            switch (node.getValueKind()) {
136172930Srwatson                case EMPTY:
137105576Srwatson                    quote = null;
138105576Srwatson                    break;
139105576Srwatson                case UNQUOTED:
140105576Srwatson                    quote = "";
141148887Srwatson                    break;
142148887Srwatson                case SINGLE:
14325603Skjc                    quote = "'";
14425603Skjc                    break;
14525603Skjc                case DOUBLE:
14625603Skjc                    quote = "\"";
14725603Skjc                    break;
14825603Skjc                default:
14925603Skjc                    throw new AssertionError();
150116720Sharti            }
15137939Skjc            if (quote != null) {
15225603Skjc                print("=" + quote);
15337939Skjc                print(node.getValue());
154128636Sluigi                print(quote);
15546695Skjc            }
156112193Sharti        } catch (IOException e) {
15746695Skjc            throw new UncheckedIOException(e);
158112193Sharti        }
159191148Skmacy        return null;
16025603Skjc    }
16125603Skjc
16225603Skjc    public Void visitAuthor(AuthorTree node, Void p) {
16325603Skjc        try {
16425603Skjc            printTagName(node);
16525603Skjc            print(" ");
166128636Sluigi            print(node.getName());
16725603Skjc        } catch (IOException e) {
16837939Skjc            throw new UncheckedIOException(e);
16925603Skjc        }
17037939Skjc        return null;
17137939Skjc    }
17246695Skjc
17346695Skjc    public Void visitComment(CommentTree node, Void p) {
17437939Skjc        try {
17537939Skjc            print(node.getBody());
176116720Sharti        } catch (IOException e) {
177116720Sharti            throw new UncheckedIOException(e);
17837939Skjc        }
17937939Skjc        return null;
18025603Skjc    }
18125603Skjc
18225603Skjc    public Void visitDeprecated(DeprecatedTree node, Void p) {
18325603Skjc        try {
18425603Skjc            printTagName(node);
18525603Skjc            if (!node.getBody().isEmpty()) {
18625603Skjc                print(" ");
18725603Skjc                print(node.getBody());
18825603Skjc            }
18925603Skjc        } catch (IOException e) {
19025603Skjc            throw new UncheckedIOException(e);
191116720Sharti        }
192116720Sharti        return null;
193111119Simp    }
19425603Skjc
19525603Skjc    public Void visitDocComment(DocCommentTree node, Void p) {
19625603Skjc        try {
19725603Skjc            List<? extends DocTree> fs = node.getFirstSentence();
19825603Skjc            List<? extends DocTree> b = node.getBody();
19925603Skjc            List<? extends DocTree> t = node.getBlockTags();
20037939Skjc            print(fs);
20137939Skjc            if (!fs.isEmpty() && !b.isEmpty())
20237939Skjc                print(" ");
203116720Sharti            print(b);
20437939Skjc            if ((!fs.isEmpty() || !b.isEmpty()) && !t.isEmpty())
20537939Skjc                print("\n");
20637939Skjc            print(t, "\n");
20737939Skjc        } catch (IOException e) {
20825603Skjc            throw new UncheckedIOException(e);
20925603Skjc        }
21025603Skjc        return null;
211116741Sharti    }
212116741Sharti
213116741Sharti    public Void visitDocRoot(DocRootTree node, Void p) {
214116741Sharti        try {
215116741Sharti            print("{");
216116741Sharti            printTagName(node);
217116741Sharti            print("}");
218116741Sharti        } catch (IOException e) {
219116741Sharti            throw new UncheckedIOException(e);
220116741Sharti        }
22125603Skjc        return null;
22225603Skjc    }
22325603Skjc
22425603Skjc    public Void visitEndElement(EndElementTree node, Void p) {
225117629Sharti        try {
226117629Sharti            print("</");
22769152Sjlemon            print(node.getName());
22825603Skjc            print(">");
22925603Skjc        } catch (IOException e) {
23025603Skjc            throw new UncheckedIOException(e);
23125603Skjc        }
23225603Skjc        return null;
23325603Skjc    }
23425603Skjc
23525603Skjc    public Void visitEntity(EntityTree node, Void p) {
23625603Skjc        try {
23725603Skjc            print("&");
23825603Skjc            print(node.getName());
23925603Skjc            print(";");
24025603Skjc        } catch (IOException e) {
241116720Sharti            throw new UncheckedIOException(e);
242116720Sharti        }
24325603Skjc        return null;
244111888Sjlemon    }
245116720Sharti
24625603Skjc    public Void visitErroneous(ErroneousTree node, Void p) {
24725603Skjc        try {
24825603Skjc            print(node.getBody());
24925603Skjc        } catch (IOException e) {
25025603Skjc            throw new UncheckedIOException(e);
251105576Srwatson        }
252172930Srwatson        return null;
253105576Srwatson    }
25425603Skjc
25525603Skjc    public Void visitIdentifier(IdentifierTree node, Void p) {
256116741Sharti        try {
257116741Sharti            print(node.getName());
258116741Sharti        } catch (IOException e) {
259116741Sharti            throw new UncheckedIOException(e);
260116741Sharti        }
261116741Sharti        return null;
262116741Sharti    }
263116741Sharti
264116741Sharti    public Void visitInheritDoc(InheritDocTree node, Void p) {
265116741Sharti        try {
266116741Sharti            print("{");
267116741Sharti            printTagName(node);
268116741Sharti            print("}");
26925603Skjc        } catch (IOException e) {
27025603Skjc            throw new UncheckedIOException(e);
271148125Srwatson        }
272116720Sharti        return null;
273148125Srwatson    }
274148125Srwatson
275148125Srwatson    public Void visitLink(LinkTree node, Void p) {
276148125Srwatson        try {
277148125Srwatson            print("{");
278148125Srwatson            printTagName(node);
279148125Srwatson            print(" ");
28037939Skjc            print(node.getReference());
281111888Sjlemon            if (!node.getLabel().isEmpty()) {
28237939Skjc                print(" ");
283148125Srwatson                print(node.getLabel());
28425603Skjc            }
285116720Sharti            print("}");
286116720Sharti        } catch (IOException e) {
287116741Sharti            throw new UncheckedIOException(e);
28825603Skjc        }
28925603Skjc        return null;
29037939Skjc    }
29137939Skjc
29237939Skjc    public Void visitLiteral(LiteralTree node, Void p) {
29337939Skjc        try {
29437939Skjc            print("{");
295116720Sharti            printTagName(node);
29637939Skjc            print(" ");
29737939Skjc            print(node.getBody());
29837939Skjc            print("}");
29937939Skjc        } catch (IOException e) {
30037939Skjc            throw new UncheckedIOException(e);
301116720Sharti        }
302116720Sharti        return null;
303116720Sharti    }
30437939Skjc
30537939Skjc    public Void visitParam(ParamTree node, Void p) {
30637939Skjc        try {
30737939Skjc            printTagName(node);
30837939Skjc            print(" ");
30937939Skjc            if (node.isTypeParameter()) print("<");
31025603Skjc            print(node.getName());
31137939Skjc            if (node.isTypeParameter()) print(">");
312116720Sharti            if (!node.getDescription().isEmpty()) {
31325603Skjc                print(" ");
31437939Skjc                print(node.getDescription());
315111888Sjlemon            }
31637939Skjc        } catch (IOException e) {
31725603Skjc            throw new UncheckedIOException(e);
318116720Sharti        }
31937939Skjc        return null;
32037939Skjc    }
321111888Sjlemon
32237939Skjc    public Void visitReference(ReferenceTree node, Void p) {
32337939Skjc        try {
32437939Skjc            print(node.getSignature());
325116741Sharti        } catch (IOException e) {
326116741Sharti            throw new UncheckedIOException(e);
327116741Sharti        }
328116741Sharti        return null;
329116741Sharti    }
330116741Sharti
331116741Sharti    public Void visitReturn(ReturnTree node, Void p) {
33237939Skjc        try {
33337939Skjc            printTagName(node);
33425603Skjc            print(" ");
335223741Sbz            print(node.getDescription());
336111888Sjlemon        } catch (IOException e) {
33725603Skjc            throw new UncheckedIOException(e);
33825603Skjc        }
33925603Skjc        return null;
340114201Sharti    }
34125603Skjc
34225603Skjc    public Void visitSee(SeeTree node, Void p) {
343116720Sharti        try {
34425603Skjc            printTagName(node);
345111774Smdodd            boolean first = true;
346111774Smdodd            boolean needSep = true;
347147256Sbrooks            for (DocTree t: node.getReference()) {
34825603Skjc                if (needSep) print(" ");
34925603Skjc                needSep = (first && (t instanceof ReferenceTree));
35025603Skjc                first = false;
351114201Sharti                print(t);
35225603Skjc            }
35325603Skjc        } catch (IOException e) {
354106939Ssam            throw new UncheckedIOException(e);
355106939Ssam        }
356106939Ssam        return null;
35746695Skjc    }
35825603Skjc
359160035Syar    public Void visitSerial(SerialTree node, Void p) {
360160038Syar        try {
361160038Syar            printTagName(node);
36225603Skjc            if (!node.getDescription().isEmpty()) {
36325603Skjc                print(" ");
36425603Skjc                print(node.getDescription());
36525603Skjc            }
36625603Skjc        } catch (IOException e) {
36725603Skjc            throw new UncheckedIOException(e);
36825603Skjc        }
36937939Skjc        return null;
370114739Sharti    }
371114739Sharti
372116741Sharti    public Void visitSerialData(SerialDataTree node, Void p) {
373116741Sharti        try {
374116741Sharti            printTagName(node);
375116741Sharti            if (!node.getDescription().isEmpty()) {
376116741Sharti                print(" ");
37737939Skjc                print(node.getDescription());
378114201Sharti            }
379114201Sharti        } catch (IOException e) {
380114201Sharti            throw new UncheckedIOException(e);
381114201Sharti        }
382114201Sharti        return null;
383114201Sharti    }
384114201Sharti
385116741Sharti    public Void visitSerialField(SerialFieldTree node, Void p) {
386116741Sharti        try {
387116741Sharti            printTagName(node);
388116741Sharti            print(" ");
389114201Sharti            print(node.getName());
390114201Sharti            print(" ");
391114201Sharti            print(node.getType());
392117630Sharti            if (!node.getDescription().isEmpty()) {
393117630Sharti                print(" ");
394117630Sharti                print(node.getDescription());
395117630Sharti            }
396117630Sharti        } catch (IOException e) {
397117630Sharti            throw new UncheckedIOException(e);
398117630Sharti        }
399117630Sharti        return null;
400117630Sharti    }
401117630Sharti
402117630Sharti    public Void visitSince(SinceTree node, Void p) {
403117630Sharti        try {
404117630Sharti            printTagName(node);
405117630Sharti            print(" ");
406117630Sharti            print(node.getBody());
407117630Sharti        } catch (IOException e) {
408117630Sharti            throw new UncheckedIOException(e);
409117630Sharti        }
410117630Sharti        return null;
411117630Sharti    }
412117630Sharti
413117630Sharti    public Void visitStartElement(StartElementTree node, Void p) {
414117630Sharti        try {
415117630Sharti            print("<");
416117630Sharti            print(node.getName());
417117630Sharti            List<? extends DocTree> attrs = node.getAttributes();
418117630Sharti            if (!attrs.isEmpty()) {
419117630Sharti                print(" ");
420117630Sharti                print(attrs);
421117630Sharti                DocTree last = node.getAttributes().get(attrs.size() - 1);
422117630Sharti                if (node.isSelfClosing() && last instanceof AttributeTree
423117630Sharti                        && ((AttributeTree) last).getValueKind() == ValueKind.UNQUOTED)
424117630Sharti                    print(" ");
425117630Sharti            }
426117630Sharti            if (node.isSelfClosing())
427117630Sharti                print("/");
428117630Sharti            print(">");
429117630Sharti        } catch (IOException e) {
430117630Sharti            throw new UncheckedIOException(e);
431117630Sharti        }
432117630Sharti        return null;
433117630Sharti    }
434117630Sharti
435117630Sharti    public Void visitText(TextTree node, Void p) {
436117630Sharti        try {
437117630Sharti            print(node.getBody());
438117630Sharti        } catch (IOException e) {
439117630Sharti            throw new UncheckedIOException(e);
440117630Sharti        }
441117630Sharti        return null;
442117630Sharti    }
443117630Sharti
444117630Sharti    public Void visitThrows(ThrowsTree node, Void p) {
445117630Sharti        try {
446117630Sharti            printTagName(node);
447117630Sharti            print(" ");
448118157Sharti            print(node.getExceptionName());
449118157Sharti            if (!node.getDescription().isEmpty()) {
450118157Sharti                print(" ");
451118157Sharti                print(node.getDescription());
452118157Sharti            }
453118157Sharti        } catch (IOException e) {
454118157Sharti            throw new UncheckedIOException(e);
455118157Sharti        }
456118157Sharti        return null;
457118157Sharti    }
458118157Sharti
459118157Sharti    public Void visitUnknownBlockTag(UnknownBlockTagTree node, Void p) {
460118157Sharti        try {
461147256Sbrooks            print("@");
462147256Sbrooks            print(node.getTagName());
463147256Sbrooks            print(" ");
464147256Sbrooks            print(node.getContent());
465147256Sbrooks        } catch (IOException e) {
466147256Sbrooks            throw new UncheckedIOException(e);
467147256Sbrooks        }
468147256Sbrooks        return null;
469147256Sbrooks    }
470147256Sbrooks
471147256Sbrooks    public Void visitUnknownInlineTag(UnknownInlineTagTree node, Void p) {
472147256Sbrooks        try {
473147256Sbrooks            print("{");
474147256Sbrooks            print("@");
475147256Sbrooks            print(node.getTagName());
476147256Sbrooks            print(" ");
477147256Sbrooks            print(node.getContent());
478147256Sbrooks            print("}");
479147256Sbrooks        } catch (IOException e) {
480147256Sbrooks            throw new UncheckedIOException(e);
481147256Sbrooks        }
482147256Sbrooks        return null;
483147256Sbrooks    }
484147256Sbrooks
485147256Sbrooks    public Void visitValue(ValueTree node, Void p) {
486147256Sbrooks        try {
487147256Sbrooks            print("{");
488147256Sbrooks            printTagName(node);
489147256Sbrooks            if (node.getReference() != null) {
490147256Sbrooks                print(" ");
491147256Sbrooks                print(node.getReference());
492147256Sbrooks            }
493147256Sbrooks            print("}");
494147256Sbrooks        } catch (IOException e) {
495147256Sbrooks            throw new UncheckedIOException(e);
496114201Sharti        }
497114201Sharti        return null;
498147256Sbrooks    }
499114201Sharti
500114201Sharti    public Void visitVersion(VersionTree node, Void p) {
501114201Sharti        try {
502147256Sbrooks            printTagName(node);
503114201Sharti            print(" ");
504            print(node.getBody());
505        } catch (IOException e) {
506            throw new UncheckedIOException(e);
507        }
508        return null;
509    }
510
511    public Void visitOther(DocTree node, Void p) {
512        try {
513            print("(UNKNOWN: " + node + ")");
514            println();
515        } catch (IOException e) {
516            throw new UncheckedIOException(e);
517        }
518        return null;
519    }
520}
521