1 /*
2  * Copyright (c) 1997, 2018, 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 package jdk.javadoc.internal.doclets.formats.html;
27 
28 import jdk.javadoc.internal.doclets.formats.html.markup.Table;
29 import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
30 
31 import java.util.*;
32 
33 import javax.lang.model.element.Element;
34 import javax.lang.model.element.ExecutableElement;
35 import javax.lang.model.element.TypeElement;
36 
37 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
38 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
39 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
40 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
41 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
42 import jdk.javadoc.internal.doclets.toolkit.ConstructorWriter;
43 import jdk.javadoc.internal.doclets.toolkit.Content;
44 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
45 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
46 
47 import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
48 
49 
50 /**
51  * Writes constructor documentation.
52  *
53  *  <p><b>This is NOT part of any supported API.
54  *  If you write code that depends on this, you do so at your own risk.
55  *  This code and its internal interfaces are subject to change or
56  *  deletion without notice.</b>
57  *
58  * @author Robert Field
59  * @author Atul M Dambalkar
60  * @author Bhavesh Patel (Modified)
61  */
62 public class ConstructorWriterImpl extends AbstractExecutableMemberWriter
63     implements ConstructorWriter, MemberSummaryWriter {
64 
65     private boolean foundNonPubConstructor = false;
66 
67     /**
68      * Construct a new ConstructorWriterImpl.
69      *
70      * @param writer The writer for the class that the constructors belong to.
71      * @param typeElement the class being documented.
72      */
ConstructorWriterImpl(SubWriterHolderWriter writer, TypeElement typeElement)73     public ConstructorWriterImpl(SubWriterHolderWriter writer, TypeElement typeElement) {
74         super(writer, typeElement);
75 
76         VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement);
77         List<? extends Element> constructors = vmt.getVisibleMembers(CONSTRUCTORS);
78 
79         for (Element constructor : constructors) {
80             if (utils.isProtected(constructor) || utils.isPrivate(constructor)) {
81                 setFoundNonPubConstructor(true);
82             }
83         }
84     }
85 
86     /**
87      * Construct a new ConstructorWriterImpl.
88      *
89      * @param writer The writer for the class that the constructors belong to.
90      */
ConstructorWriterImpl(SubWriterHolderWriter writer)91     public ConstructorWriterImpl(SubWriterHolderWriter writer) {
92         super(writer);
93     }
94 
95     /**
96      * {@inheritDoc}
97      */
98     @Override
getMemberSummaryHeader(TypeElement typeElement, Content memberSummaryTree)99     public Content getMemberSummaryHeader(TypeElement typeElement,
100             Content memberSummaryTree) {
101         memberSummaryTree.addContent(HtmlConstants.START_OF_CONSTRUCTOR_SUMMARY);
102         Content memberTree = writer.getMemberTreeHeader();
103         writer.addSummaryHeader(this, typeElement, memberTree);
104         return memberTree;
105     }
106 
107     /**
108      * {@inheritDoc}
109      */
110     @Override
addMemberTree(Content memberSummaryTree, Content memberTree)111     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
112         writer.addMemberTree(memberSummaryTree, memberTree);
113     }
114 
115     /**
116      * {@inheritDoc}
117      */
118     @Override
getConstructorDetailsTreeHeader(TypeElement typeElement, Content memberDetailsTree)119     public Content getConstructorDetailsTreeHeader(TypeElement typeElement,
120             Content memberDetailsTree) {
121         memberDetailsTree.addContent(HtmlConstants.START_OF_CONSTRUCTOR_DETAILS);
122         Content constructorDetailsTree = writer.getMemberTreeHeader();
123         constructorDetailsTree.addContent(links.createAnchor(
124                 SectionName.CONSTRUCTOR_DETAIL));
125         Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING,
126                 contents.constructorDetailsLabel);
127         constructorDetailsTree.addContent(heading);
128         return constructorDetailsTree;
129     }
130 
131     /**
132      * {@inheritDoc}
133      */
134     @Override
getConstructorDocTreeHeader(ExecutableElement constructor, Content constructorDetailsTree)135     public Content getConstructorDocTreeHeader(ExecutableElement constructor,
136             Content constructorDetailsTree) {
137         String erasureAnchor;
138         if ((erasureAnchor = getErasureAnchor(constructor)) != null) {
139             constructorDetailsTree.addContent(links.createAnchor((erasureAnchor)));
140         }
141         constructorDetailsTree.addContent(links.createAnchor(writer.getAnchor(constructor)));
142         Content constructorDocTree = writer.getMemberTreeHeader();
143         Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING);
144         heading.addContent(name(constructor));
145         constructorDocTree.addContent(heading);
146         return constructorDocTree;
147     }
148 
149     /**
150      * {@inheritDoc}
151      */
152     @Override
getSignature(ExecutableElement constructor)153     public Content getSignature(ExecutableElement constructor) {
154         Content pre = new HtmlTree(HtmlTag.PRE);
155         writer.addAnnotationInfo(constructor, pre);
156         int annotationLength = pre.charCount();
157         addModifiers(constructor, pre);
158         if (configuration.linksource) {
159             Content constructorName = new StringContent(name(constructor));
160             writer.addSrcLink(constructor, constructorName, pre);
161         } else {
162             addName(name(constructor), pre);
163         }
164         int indent = pre.charCount() - annotationLength;
165         addParameters(constructor, pre, indent);
166         addExceptions(constructor, pre, indent);
167         return pre;
168     }
169 
170     /**
171      * {@inheritDoc}
172      */
173     @Override
addDeprecated(ExecutableElement constructor, Content constructorDocTree)174     public void addDeprecated(ExecutableElement constructor, Content constructorDocTree) {
175         addDeprecatedInfo(constructor, constructorDocTree);
176     }
177 
178     /**
179      * {@inheritDoc}
180      */
181     @Override
addComments(ExecutableElement constructor, Content constructorDocTree)182     public void addComments(ExecutableElement constructor, Content constructorDocTree) {
183         addComment(constructor, constructorDocTree);
184     }
185 
186     /**
187      * {@inheritDoc}
188      */
189     @Override
addTags(ExecutableElement constructor, Content constructorDocTree)190     public void addTags(ExecutableElement constructor, Content constructorDocTree) {
191         writer.addTagsInfo(constructor, constructorDocTree);
192     }
193 
194     /**
195      * {@inheritDoc}
196      */
197     @Override
getConstructorDetails(Content constructorDetailsTree)198     public Content getConstructorDetails(Content constructorDetailsTree) {
199         if (configuration.allowTag(HtmlTag.SECTION)) {
200             HtmlTree htmlTree = HtmlTree.SECTION(getMemberTree(constructorDetailsTree));
201             return htmlTree;
202         }
203         return getMemberTree(constructorDetailsTree);
204     }
205 
206     /**
207      * {@inheritDoc}
208      */
209     @Override
getConstructorDoc(Content constructorDocTree, boolean isLastContent)210     public Content getConstructorDoc(Content constructorDocTree,
211             boolean isLastContent) {
212         return getMemberTree(constructorDocTree, isLastContent);
213     }
214 
215     /**
216      * Let the writer know whether a non public constructor was found.
217      *
218      * @param foundNonPubConstructor true if we found a non public constructor.
219      */
220     @Override
setFoundNonPubConstructor(boolean foundNonPubConstructor)221     public void setFoundNonPubConstructor(boolean foundNonPubConstructor) {
222         this.foundNonPubConstructor = foundNonPubConstructor;
223     }
224 
225     /**
226      * {@inheritDoc}
227      */
228     @Override
addSummaryLabel(Content memberTree)229     public void addSummaryLabel(Content memberTree) {
230         Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING,
231                 contents.constructorSummaryLabel);
232         memberTree.addContent(label);
233     }
234 
235     /**
236      * {@inheritDoc}
237      */
238     @Override
getSummaryTableHeader(Element member)239     public TableHeader getSummaryTableHeader(Element member) {
240         if (foundNonPubConstructor) {
241             return new TableHeader(contents.modifierLabel, contents.constructorLabel,
242                     contents.descriptionLabel);
243         } else {
244             return new TableHeader(contents.constructorLabel, contents.descriptionLabel);
245         }
246     }
247 
248     @Override
createSummaryTable()249     protected Table createSummaryTable() {
250         List<HtmlStyle> bodyRowStyles;
251         int rowScopeColumn;
252 
253         if (foundNonPubConstructor) {
254             bodyRowStyles = Arrays.asList(HtmlStyle.colFirst, HtmlStyle.colConstructorName,
255                     HtmlStyle.colLast);
256             rowScopeColumn = 1;
257         } else {
258             bodyRowStyles = Arrays.asList(HtmlStyle.colConstructorName, HtmlStyle.colLast);
259             rowScopeColumn = 0;
260         }
261 
262         String summary =  resources.getText("doclet.Member_Table_Summary",
263                 resources.getText("doclet.Constructor_Summary"),
264                 resources.getText("doclet.constructors"));
265 
266         return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
267                 .setSummary(summary)
268                 .setCaption(contents.constructors)
269                 .setHeader(getSummaryTableHeader(typeElement))
270                 .setRowScopeColumn(rowScopeColumn)
271                 .setColumnStyles(bodyRowStyles)
272                 .setUseTBody(false);  // temporary? compatibility mode for TBody
273     }
274 
275     /**
276      * {@inheritDoc}
277      */
278     @Override
addSummaryAnchor(TypeElement typeElement, Content memberTree)279     public void addSummaryAnchor(TypeElement typeElement, Content memberTree) {
280         memberTree.addContent(links.createAnchor(SectionName.CONSTRUCTOR_SUMMARY));
281     }
282 
283     /**
284      * {@inheritDoc}
285      */
286     @Override
addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree)287     public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) {
288     }
289 
290     /**
291      * {@inheritDoc}
292      */
293     @Override
addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree)294     public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) {
295     }
296 
297     /**
298      * {@inheritDoc}
299      */
300     @Override
addSummaryType(Element member, Content tdSummaryType)301     protected void addSummaryType(Element member, Content tdSummaryType) {
302         if (foundNonPubConstructor) {
303             Content code = new HtmlTree(HtmlTag.CODE);
304             if (utils.isProtected(member)) {
305                 code.addContent("protected ");
306             } else if (utils.isPrivate(member)) {
307                 code.addContent("private ");
308             } else if (utils.isPublic(member)) {
309                 code.addContent(Contents.SPACE);
310             } else {
311                 code.addContent(
312                         configuration.getText("doclet.Package_private"));
313             }
314             tdSummaryType.addContent(code);
315         }
316     }
317 }
318