001/*
002 * JDrupes MDoclet
003 * Copyright (C) 2021 Michael N. Lipp
004 * 
005 * This program is free software; you can redistribute it and/or modify it 
006 * under the terms of the GNU Affero General Public License as published by 
007 * the Free Software Foundation; either version 3 of the License, or 
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful, but 
011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
013 * for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License along 
016 * with this program; if not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jdrupes.mdoclet;
020
021import java.util.ArrayList;
022import java.util.List;
023
024import com.sun.source.doctree.DocCommentTree;
025import com.sun.source.doctree.DocTree;
026import com.sun.source.doctree.DocTreeVisitor;
027import com.sun.tools.javac.tree.DCTree;
028
029/**
030 * Feeds the results of the methods through the {@link TreeConverter}
031 * where appropriate.
032 * 
033 * With JDK 11, {@link DocCommentTreeWrapper} only had to implement
034 * {@link DocCommentTree}. Starting with (at least) JDK 15, javadoc
035 * casts (without check) {@link DocCommentTree} instances to
036 * {@link DCTree.DCDocComment} when reporting errors e.g. about
037 * a missing link target. That's the only reason why the
038 * wrapper extends {@link DCTree.DCDocComment}.
039 */
040public class DocCommentTreeWrapper extends DCTree.DCDocComment
041        implements DocCommentTree {
042
043    private DocCommentTree tree;
044    private TreeConverter treeConverter;
045    private List<DocTree> fullBody;
046    private List<DocTree> firstSentence;
047    private List<DocTree> body;
048    private List<DocTree> blockTags;
049
050    public DocCommentTreeWrapper(MDoclet doclet, MDocletEnvironment environment,
051            DocCommentTree tree) {
052        super(tree instanceof DCTree.DCDocComment
053            ? ((DCTree.DCDocComment) tree).comment
054            : null,
055            null, null, null, null, null, null);
056        this.tree = tree;
057        treeConverter = new TreeConverter(doclet.getProcessor(),
058            environment.getDocTrees().getDocTreeFactory(),
059            environment.getElementUtils());
060    }
061
062    /**
063     * Overridden by {@link DCTree.DCDocComment}, restore to default.
064     */
065    @Override
066    public List<? extends DocTree> getFullBody() {
067        if (fullBody == null) {
068            fullBody = new ArrayList<>();
069            fullBody.addAll(getFirstSentence());
070            fullBody.addAll(getBody());
071        }
072        return fullBody;
073    }
074
075    /**
076     * {@inheritDoc}
077     * 
078     * @see com.sun.source.doctree.DocCommentTree#getFirstSentence()
079     */
080    public List<? extends DocTree> getFirstSentence() {
081        if (firstSentence == null) {
082            firstSentence
083                = treeConverter.convertFragment(tree.getFirstSentence());
084        }
085        return firstSentence;
086    }
087
088    /**
089     * {@inheritDoc}
090     * 
091     * @see com.sun.source.doctree.DocCommentTree#getBody()
092     */
093    public List<? extends DocTree> getBody() {
094        if (body == null) {
095            body = treeConverter.convertDescription(tree.getBody());
096        }
097        return body;
098    }
099
100    /**
101     * {@inheritDoc}
102     * 
103     * @see com.sun.source.doctree.DocCommentTree#getBlockTags()
104     */
105    public List<? extends DocTree> getBlockTags() {
106        if (blockTags == null) {
107            List<? extends DocTree> origTags = tree.getBlockTags();
108            blockTags = new ArrayList<>();
109            for (DocTree tree : origTags) {
110                treeConverter.convertTag(blockTags, tree);
111            }
112        }
113        return blockTags;
114    }
115
116    /**
117     * {@inheritDoc}
118     * 
119     * @see com.sun.source.doctree.DocCommentTree#getPreamble()
120     */
121    public List<? extends DocTree> getPreamble() {
122        return tree.getPreamble();
123    }
124
125    /**
126     * {@inheritDoc}
127     * 
128     * @see com.sun.source.doctree.DocCommentTree#getPostamble()
129     */
130    public List<? extends DocTree> getPostamble() {
131        return tree.getPostamble();
132    }
133
134    /**
135     * {@inheritDoc}
136     * 
137     * @see com.sun.source.doctree.DocTree#getKind()
138     */
139    public Kind getKind() {
140        return tree.getKind();
141    }
142
143    /**
144     * {@inheritDoc}
145     * 
146     * @see com.sun.source.doctree.DocTree#accept(com.sun.source.doctree.DocTreeVisitor, java.lang.Object)
147     */
148    public <R, D> R accept(DocTreeVisitor<R, D> visitor, D data) {
149        // Work around NPE when reporting param related problems.
150        if (tree instanceof DCTree.DCDocComment
151            && visitor.getClass().getName()
152                .equals("com.sun.source.util.DocTreePath$1PathFinder")) {
153            return visitor.visitDocComment(this, data);
154        }
155        return tree.accept(visitor, data);
156    }
157
158}