CommentUtils.java revision 3900:02e61db8289d
1/*
2 * Copyright (c) 2015, 2017, 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.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26/**
27 *  A utility class.
28 *
29 *  <p><b>This is NOT part of any supported API.
30 *  If you write code that depends on this, you do so at your own risk.
31 *  This code and its internal interfaces are subject to change or
32 *  deletion without notice.</b>
33 */
34
35package jdk.javadoc.internal.doclets.toolkit;
36
37import java.net.URI;
38import java.util.ArrayList;
39import java.util.HashMap;
40import java.util.List;
41
42import javax.lang.model.element.Element;
43import javax.lang.model.element.ExecutableElement;
44import javax.lang.model.element.Name;
45import javax.lang.model.element.PackageElement;
46import javax.lang.model.element.VariableElement;
47import javax.lang.model.util.Elements;
48import javax.tools.FileObject;
49import javax.tools.JavaFileObject;
50import javax.tools.SimpleJavaFileObject;
51
52import com.sun.source.doctree.DocCommentTree;
53import com.sun.source.doctree.DocTree;
54import com.sun.source.doctree.IdentifierTree;
55import com.sun.source.doctree.ReferenceTree;
56import com.sun.source.doctree.TextTree;
57import com.sun.source.util.DocTreeFactory;
58import com.sun.source.util.DocTreePath;
59import com.sun.source.util.DocTrees;
60import com.sun.source.util.TreePath;
61import com.sun.tools.javac.util.DefinedBy;
62import com.sun.tools.javac.util.DefinedBy.Api;
63import jdk.javadoc.internal.doclets.toolkit.util.Utils;
64
65public class CommentUtils {
66
67    final Configuration configuration;
68    final DocTreeFactory treeFactory;
69    final HashMap<Element, DocCommentDuo> dcTreesMap = new HashMap<>();
70    final DocTrees trees;
71    final Elements elementUtils;
72
73    protected CommentUtils(Configuration configuration) {
74        this.configuration = configuration;
75        trees = configuration.docEnv.getDocTrees();
76        treeFactory = trees.getDocTreeFactory();
77        elementUtils = configuration.docEnv.getElementUtils();
78    }
79
80    public List<? extends DocTree> makePropertyDescriptionTree(List<? extends DocTree> content) {
81        List<DocTree> out = new ArrayList<>();
82        Name name = elementUtils.getName("propertyDescription");
83        out.add(treeFactory.newUnknownBlockTagTree(name, content));
84        return out;
85    }
86
87    public List<? extends DocTree> makePropertyDescriptionTree(String content) {
88        List<DocTree> inlist = new ArrayList<>();
89        inlist.add(treeFactory.newCommentTree(content));
90        List<DocTree> out = new ArrayList<>();
91        Name name = elementUtils.getName("propertyDescription");
92        out.add(treeFactory.newUnknownBlockTagTree(name, inlist));
93        return out;
94    }
95
96    public List<? extends DocTree> makeFirstSentenceTree(String content) {
97        List<DocTree> out = new ArrayList<>();
98        out.add(treeFactory.newTextTree(content));
99        return out;
100    }
101
102    public DocTree makeSeeTree(String sig, Element e) {
103        List<DocTree> list = new ArrayList<>();
104        list.add(treeFactory.newReferenceTree(sig));
105        return treeFactory.newSeeTree(list);
106    }
107
108    public DocTree makeTextTree(String content) {
109        TextTree text = treeFactory.newTextTree(content);
110        return (DocTree) text;
111    }
112
113    public void setEnumValuesTree(Configuration config, Element e) {
114        Utils utils = config.utils;
115        String klassName = utils.getSimpleName(utils.getEnclosingTypeElement(e));
116
117        List<DocTree> fullBody = new ArrayList<>();
118        fullBody.add(treeFactory.newTextTree(config.getText("doclet.enum_values_doc.fullbody", klassName)));
119
120        List<DocTree> descriptions = new ArrayList<>();
121        descriptions.add(treeFactory.newTextTree(config.getText("doclet.enum_values_doc.return")));
122
123        List<DocTree> tags = new ArrayList<>();
124        tags.add(treeFactory.newReturnTree(descriptions));
125        DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, tags);
126        dcTreesMap.put(e, new DocCommentDuo(null, docTree));
127    }
128
129    public void setEnumValueOfTree(Configuration config, Element e) {
130
131        List<DocTree> fullBody = new ArrayList<>();
132        fullBody.add(treeFactory.newTextTree(config.getText("doclet.enum_valueof_doc.fullbody")));
133
134        List<DocTree> tags = new ArrayList<>();
135
136        List<DocTree> paramDescs = new ArrayList<>();
137        paramDescs.add(treeFactory.newTextTree(config.getText("doclet.enum_valueof_doc.param_name")));
138        ExecutableElement ee = (ExecutableElement) e;
139        java.util.List<? extends VariableElement> parameters = ee.getParameters();
140        VariableElement param = parameters.get(0);
141        IdentifierTree id = treeFactory.newIdentifierTree(elementUtils.getName(param.getSimpleName().toString()));
142        tags.add(treeFactory.newParamTree(false, id, paramDescs));
143
144        List<DocTree> returnDescs = new ArrayList<>();
145        returnDescs.add(treeFactory.newTextTree(config.getText("doclet.enum_valueof_doc.return")));
146        tags.add(treeFactory.newReturnTree(returnDescs));
147
148        List<DocTree> throwsDescs = new ArrayList<>();
149        throwsDescs.add(treeFactory.newTextTree(config.getText("doclet.enum_valueof_doc.throws_ila")));
150
151        ReferenceTree ref = treeFactory.newReferenceTree("java.lang.IllegalArgumentException");
152        tags.add(treeFactory.newThrowsTree(ref, throwsDescs));
153
154        throwsDescs = new ArrayList<>();
155        throwsDescs.add(treeFactory.newTextTree(config.getText("doclet.enum_valueof_doc.throws_npe")));
156
157        ref = treeFactory.newReferenceTree("java.lang.NullPointerException");
158        tags.add(treeFactory.newThrowsTree(ref, throwsDescs));
159
160        DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, tags);
161
162        dcTreesMap.put(e, new DocCommentDuo(null, docTree));
163    }
164
165    /*
166     * Returns the TreePath/DocCommentTree duo for synthesized element.
167     */
168    public DocCommentDuo getSyntheticCommentDuo(Element e) {
169        return dcTreesMap.get(e);
170    }
171
172    /*
173     * Returns the TreePath/DocCommentTree duo for html sources.
174     */
175    public DocCommentDuo getHtmlCommentDuo(Element e) {
176        FileObject fo = null;
177        PackageElement pe = null;
178        switch (e.getKind()) {
179            case OTHER:
180                fo = configuration.getOverviewPath();
181                pe = configuration.workArounds.getUnnamedPackage();
182                break;
183            case PACKAGE:
184                fo = configuration.workArounds.getJavaFileObject((PackageElement)e);
185                pe = (PackageElement)e;
186                break;
187            default:
188                return null;
189        }
190        if (fo == null) {
191            return null;
192        }
193
194        DocCommentTree dcTree = trees.getDocCommentTree(fo);
195        if (dcTree == null) {
196            return null;
197        }
198        DocTreePath treePath = trees.getDocTreePath(fo, pe);
199        return new DocCommentDuo(treePath.getTreePath(), dcTree);
200    }
201
202    public DocCommentTree parse(URI uri, String text) {
203        return trees.getDocCommentTree(new SimpleJavaFileObject(
204                uri, JavaFileObject.Kind.SOURCE) {
205            @Override @DefinedBy(Api.COMPILER)
206            public CharSequence getCharContent(boolean ignoreEncoding) {
207                return text;
208            }
209        });
210    }
211
212    public void setDocCommentTree(Element element, List<DocTree> fullBody,
213            List<DocTree> blockTags, Utils utils) {
214        DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, blockTags);
215        dcTreesMap.put(element, new DocCommentDuo(null, docTree));
216        // There maybe an entry with the original comments usually null,
217        // therefore remove that entry if it exists, and allow a new one
218        // to be reestablished.
219        utils.removeCommentHelper(element);
220    }
221
222    /**
223     * A simplistic container to transport a TreePath, DocCommentTree pair.
224     * Here is why we need this:
225     * a. not desirable to add javac's pair.
226     * b. DocTreePath is not a viable  option either, as a null TreePath is required
227     * to represent synthetic comments for Enum.values, valuesOf, javafx properties.
228     */
229    public static class DocCommentDuo {
230        public final TreePath treePath;
231        public final DocCommentTree dcTree;
232
233        public DocCommentDuo(TreePath treePath, DocCommentTree dcTree) {
234            this.treePath = treePath;
235            this.dcTree = dcTree;
236        }
237    }
238}
239