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.toolkit.builders;
27
28 import javax.lang.model.element.PackageElement;
29 import javax.lang.model.element.TypeElement;
30
31 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
32 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
33 import jdk.javadoc.internal.doclets.toolkit.Content;
34 import jdk.javadoc.internal.doclets.toolkit.DocFilesHandler;
35 import jdk.javadoc.internal.doclets.toolkit.DocletException;
36 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
37 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
38
39 /**
40 * Builds the summary for a given class.
41 *
42 * <p><b>This is NOT part of any supported API.
43 * If you write code that depends on this, you do so at your own risk.
44 * This code and its internal interfaces are subject to change or
45 * deletion without notice.</b>
46 *
47 * @author Jamie Ho
48 * @author Bhavesh Patel (Modified)
49 */
50 public class ClassBuilder extends AbstractBuilder {
51
52 /**
53 * The class being documented.
54 */
55 private final TypeElement typeElement;
56
57 /**
58 * The doclet specific writer.
59 */
60 private final ClassWriter writer;
61
62 /**
63 * Keep track of whether or not this typeElement is an interface.
64 */
65 private final boolean isInterface;
66
67 /**
68 * Keep track of whether or not this typeElement is an enum.
69 */
70 private final boolean isEnum;
71
72 /**
73 * The content tree for the class documentation.
74 */
75 private Content contentTree;
76
77 private final Utils utils;
78
79 /**
80 * Construct a new ClassBuilder.
81 *
82 * @param context the build context
83 * @param typeElement the class being documented.
84 * @param writer the doclet specific writer.
85 */
86 private ClassBuilder(Context context, TypeElement typeElement, ClassWriter writer) {
87 super(context);
88 this.typeElement = typeElement;
89 this.writer = writer;
90 this.utils = configuration.utils;
91 if (utils.isInterface(typeElement)) {
92 isInterface = true;
93 isEnum = false;
94 } else if (utils.isEnum(typeElement)) {
95 isInterface = false;
96 isEnum = true;
97 utils.setEnumDocumentation(typeElement);
98 } else {
99 isInterface = false;
100 isEnum = false;
101 }
102 }
103
104 /**
105 * Constructs a new ClassBuilder.
106 *
107 * @param context the build context
108 * @param typeElement the class being documented.
109 * @param writer the doclet specific writer.
110 * @return the new ClassBuilder
111 */
112 public static ClassBuilder getInstance(Context context, TypeElement typeElement, ClassWriter writer) {
113 return new ClassBuilder(context, typeElement, writer);
114 }
115
116 /**
117 * {@inheritDoc}
118 */
119 @Override
120 public void build() throws DocletException {
121 buildClassDoc(contentTree);
122 }
123
124 /**
125 * Handles the {@literal <TypeElement>} tag.
126 *
127 * @param contentTree the content tree to which the documentation will be added
128 * @throws DocletException if there is a problem while building the documentation
129 */
130 protected void buildClassDoc(Content contentTree) throws DocletException {
131 String key;
132 if (isInterface) {
133 key = "doclet.Interface";
134 } else if (isEnum) {
135 key = "doclet.Enum";
136 } else {
137 key = "doclet.Class";
138 }
139 contentTree = writer.getHeader(resources.getText(key) + " "
140 + utils.getSimpleName(typeElement));
141 Content classContentTree = writer.getClassContentHeader();
142
143 buildClassTree(classContentTree);
144 buildClassInfo(classContentTree);
145 buildMemberSummary(classContentTree);
146 buildMemberDetails(classContentTree);
147
148 writer.addClassContentTree(contentTree, classContentTree);
149 writer.addFooter(contentTree);
150 writer.printDocument(contentTree);
151 copyDocFiles();
152 }
153
154 /**
155 * Build the class tree documentation.
156 *
157 * @param classContentTree the content tree to which the documentation will be added
158 */
159 protected void buildClassTree(Content classContentTree) {
160 writer.addClassTree(classContentTree);
161 }
162
163 /**
164 * Build the class information tree documentation.
165 *
166 * @param classContentTree the content tree to which the documentation will be added
167 * @throws DocletException if there is a problem while building the documentation
168 */
169 protected void buildClassInfo(Content classContentTree) throws DocletException {
170 Content classInfoTree = new ContentBuilder();
171 buildTypeParamInfo(classInfoTree);
172 buildSuperInterfacesInfo(classInfoTree);
173 buildImplementedInterfacesInfo(classInfoTree);
174 buildSubClassInfo(classInfoTree);
175 buildSubInterfacesInfo(classInfoTree);
176 buildInterfaceUsageInfo(classInfoTree);
177 buildNestedClassInfo(classInfoTree);
178 buildFunctionalInterfaceInfo(classInfoTree);
179 buildClassSignature(classInfoTree);
180 buildDeprecationInfo(classInfoTree);
181 buildClassDescription(classInfoTree);
182 buildClassTagInfo(classInfoTree);
183
184 classContentTree.add(writer.getClassInfo(classInfoTree));
185 }
186
187 /**
188 * Build the type parameters of this class.
189 *
190 * @param classInfoTree the content tree to which the documentation will be added
191 */
192 protected void buildTypeParamInfo(Content classInfoTree) {
193 writer.addTypeParamInfo(classInfoTree);
194 }
195
196 /**
197 * If this is an interface, list all super interfaces.
198 *
199 * @param classInfoTree the content tree to which the documentation will be added
200 */
201 protected void buildSuperInterfacesInfo(Content classInfoTree) {
202 writer.addSuperInterfacesInfo(classInfoTree);
203 }
204
205 /**
206 * If this is a class, list all interfaces implemented by this class.
207 *
208 * @param classInfoTree the content tree to which the documentation will be added
209 */
210 protected void buildImplementedInterfacesInfo(Content classInfoTree) {
211 writer.addImplementedInterfacesInfo(classInfoTree);
212 }
213
374 }
375
376 /**
377 * Build the constructor documentation.
378 *
379 * @param memberDetailsTree the content tree to which the documentation will be added
380 * @throws DocletException if there is a problem while building the documentation
381 */
382 protected void buildConstructorDetails(Content memberDetailsTree) throws DocletException {
383 builderFactory.getConstructorBuilder(writer).build(memberDetailsTree);
384 }
385
386 /**
387 * Build the method documentation.
388 *
389 * @param memberDetailsTree the content tree to which the documentation will be added
390 * @throws DocletException if there is a problem while building the documentation
391 */
392 protected void buildMethodDetails(Content memberDetailsTree) throws DocletException {
393 builderFactory.getMethodBuilder(writer).build(memberDetailsTree);
394 }
395 }
|
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.toolkit.builders;
27
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Objects;
31 import java.util.Set;
32 import java.util.stream.Collectors;
33
34 import javax.lang.model.element.Element;
35 import javax.lang.model.element.ExecutableElement;
36 import javax.lang.model.element.Name;
37 import javax.lang.model.element.PackageElement;
38 import javax.lang.model.element.TypeElement;
39 import javax.lang.model.element.VariableElement;
40 import javax.lang.model.type.TypeMirror;
41 import javax.lang.model.util.Elements;
42
43 import com.sun.source.tree.MethodTree;
44 import com.sun.source.tree.Tree;
45 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
46 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
47 import jdk.javadoc.internal.doclets.toolkit.CommentUtils;
48 import jdk.javadoc.internal.doclets.toolkit.Content;
49 import jdk.javadoc.internal.doclets.toolkit.DocFilesHandler;
50 import jdk.javadoc.internal.doclets.toolkit.DocletException;
51 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
52 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
53
54 /**
55 * Builds the summary for a given class.
56 *
57 * <p><b>This is NOT part of any supported API.
58 * If you write code that depends on this, you do so at your own risk.
59 * This code and its internal interfaces are subject to change or
60 * deletion without notice.</b>
61 *
62 * @author Jamie Ho
63 * @author Bhavesh Patel (Modified)
64 */
65 public class ClassBuilder extends AbstractBuilder {
66
67 /**
68 * The class being documented.
69 */
70 private final TypeElement typeElement;
71
72 /**
73 * The doclet specific writer.
74 */
75 private final ClassWriter writer;
76
77 /**
78 * Keep track of whether or not this typeElement is an interface.
79 */
80 private final boolean isInterface;
81
82 /**
83 * Keep track of whether or not this typeElement is an enum.
84 */
85 private final boolean isEnum;
86
87 /**
88 * Keep track of whether or not this typeElement is an record.
89 */
90 private final boolean isRecord;
91
92 /**
93 * The content tree for the class documentation.
94 */
95 private Content contentTree;
96
97 private final Utils utils;
98
99 /**
100 * Construct a new ClassBuilder.
101 *
102 * @param context the build context
103 * @param typeElement the class being documented.
104 * @param writer the doclet specific writer.
105 */
106 private ClassBuilder(Context context, TypeElement typeElement, ClassWriter writer) {
107 super(context);
108 this.typeElement = typeElement;
109 this.writer = writer;
110 this.utils = configuration.utils;
111 if (utils.isInterface(typeElement)) {
112 isInterface = true;
113 isEnum = false;
114 isRecord = false;
115 } else if (utils.isEnum(typeElement)) {
116 isInterface = false;
117 isEnum = true;
118 isRecord = false;
119 setEnumDocumentation(typeElement);
120 } else if (utils.isRecord(typeElement)) {
121 isInterface = false;
122 isEnum = false;
123 isRecord = true;
124 setRecordDocumentation(typeElement);
125 } else {
126 isInterface = false;
127 isEnum = false;
128 isRecord = false;
129 }
130 }
131
132 /**
133 * Constructs a new ClassBuilder.
134 *
135 * @param context the build context
136 * @param typeElement the class being documented.
137 * @param writer the doclet specific writer.
138 * @return the new ClassBuilder
139 */
140 public static ClassBuilder getInstance(Context context, TypeElement typeElement, ClassWriter writer) {
141 return new ClassBuilder(context, typeElement, writer);
142 }
143
144 /**
145 * {@inheritDoc}
146 */
147 @Override
148 public void build() throws DocletException {
149 buildClassDoc(contentTree);
150 }
151
152 /**
153 * Handles the {@literal <TypeElement>} tag.
154 *
155 * @param contentTree the content tree to which the documentation will be added
156 * @throws DocletException if there is a problem while building the documentation
157 */
158 protected void buildClassDoc(Content contentTree) throws DocletException {
159 String key;
160 if (isInterface) {
161 key = "doclet.Interface";
162 } else if (isEnum) {
163 key = "doclet.Enum";
164 } else if (isRecord) {
165 key = "doclet.Record";
166 } else {
167 key = "doclet.Class";
168 }
169 contentTree = writer.getHeader(resources.getText(key) + " "
170 + utils.getSimpleName(typeElement));
171 Content classContentTree = writer.getClassContentHeader();
172
173 buildClassTree(classContentTree);
174 buildClassInfo(classContentTree);
175 buildMemberSummary(classContentTree);
176 buildMemberDetails(classContentTree);
177
178 writer.addClassContentTree(contentTree, classContentTree);
179 writer.addFooter(contentTree);
180 writer.printDocument(contentTree);
181 copyDocFiles();
182 }
183
184 /**
185 * Build the class tree documentation.
186 *
187 * @param classContentTree the content tree to which the documentation will be added
188 */
189 protected void buildClassTree(Content classContentTree) {
190 writer.addClassTree(classContentTree);
191 }
192
193 /**
194 * Build the class information tree documentation.
195 *
196 * @param classContentTree the content tree to which the documentation will be added
197 * @throws DocletException if there is a problem while building the documentation
198 */
199 protected void buildClassInfo(Content classContentTree) throws DocletException {
200 Content classInfoTree = new ContentBuilder();
201 buildParamInfo(classInfoTree);
202 buildSuperInterfacesInfo(classInfoTree);
203 buildImplementedInterfacesInfo(classInfoTree);
204 buildSubClassInfo(classInfoTree);
205 buildSubInterfacesInfo(classInfoTree);
206 buildInterfaceUsageInfo(classInfoTree);
207 buildNestedClassInfo(classInfoTree);
208 buildFunctionalInterfaceInfo(classInfoTree);
209 buildClassSignature(classInfoTree);
210 buildDeprecationInfo(classInfoTree);
211 buildClassDescription(classInfoTree);
212 buildClassTagInfo(classInfoTree);
213
214 classContentTree.add(writer.getClassInfo(classInfoTree));
215 }
216
217 /**
218 * Build the type parameters and state components of this class.
219 *
220 * @param classInfoTree the content tree to which the documentation will be added
221 */
222 protected void buildParamInfo(Content classInfoTree) {
223 writer.addParamInfo(classInfoTree);
224 }
225
226 /**
227 * If this is an interface, list all super interfaces.
228 *
229 * @param classInfoTree the content tree to which the documentation will be added
230 */
231 protected void buildSuperInterfacesInfo(Content classInfoTree) {
232 writer.addSuperInterfacesInfo(classInfoTree);
233 }
234
235 /**
236 * If this is a class, list all interfaces implemented by this class.
237 *
238 * @param classInfoTree the content tree to which the documentation will be added
239 */
240 protected void buildImplementedInterfacesInfo(Content classInfoTree) {
241 writer.addImplementedInterfacesInfo(classInfoTree);
242 }
243
404 }
405
406 /**
407 * Build the constructor documentation.
408 *
409 * @param memberDetailsTree the content tree to which the documentation will be added
410 * @throws DocletException if there is a problem while building the documentation
411 */
412 protected void buildConstructorDetails(Content memberDetailsTree) throws DocletException {
413 builderFactory.getConstructorBuilder(writer).build(memberDetailsTree);
414 }
415
416 /**
417 * Build the method documentation.
418 *
419 * @param memberDetailsTree the content tree to which the documentation will be added
420 * @throws DocletException if there is a problem while building the documentation
421 */
422 protected void buildMethodDetails(Content memberDetailsTree) throws DocletException {
423 builderFactory.getMethodBuilder(writer).build(memberDetailsTree);
424 }
425
426 /**
427 * The documentation for values() and valueOf() in Enums are set by the
428 * doclet only iff the user or overridden methods are missing.
429 * @param elem the enum element
430 */
431 private void setEnumDocumentation(TypeElement elem) {
432 CommentUtils cmtUtils = configuration.cmtUtils;
433 for (ExecutableElement ee : utils.getMethods(elem)) {
434 if (!utils.getFullBody(ee).isEmpty()) // ignore if already set
435 continue;
436 Name name = ee.getSimpleName();
437 if (name.contentEquals("values") && ee.getParameters().isEmpty()) {
438 utils.removeCommentHelper(ee); // purge previous entry
439 cmtUtils.setEnumValuesTree(ee);
440 } else if (name.contentEquals("valueOf") && ee.getParameters().size() == 1) {
441 // TODO: check parameter type
442 utils.removeCommentHelper(ee); // purge previous entry
443 cmtUtils.setEnumValueOfTree(ee);
444 }
445 }
446 }
447
448 /**
449 * Sets the documentation as needed for the mandated parts of a record type.
450 * This includes the canonical constructor, methods like {@code equals},
451 * {@code hashCode}, {@code toString}, the accessor methods, and the underlying
452 * field.
453 * @param elem the record element
454 */
455
456 @SuppressWarnings("preview")
457 private void setRecordDocumentation(TypeElement elem) {
458 CommentUtils cmtUtils = configuration.cmtUtils;
459 Set<Name> componentNames = elem.getRecordComponents().stream()
460 .map(Element::getSimpleName)
461 .collect(Collectors.toSet());
462
463 for (ExecutableElement ee : utils.getConstructors(elem)) {
464 if (utils.isCanonicalRecordConstructor(ee)) {
465 if (utils.getFullBody(ee).isEmpty()) {
466 utils.removeCommentHelper(ee); // purge previous entry
467 cmtUtils.setRecordConstructorTree(ee);
468 }
469 // only one canonical constructor; no longer need to keep looking
470 break;
471 }
472 }
473
474 for (VariableElement ve : utils.getFields(elem)) {
475 // The fields for the record component cannot be declared by the
476 // user and so cannot have any pre-existing comment.
477 Name name = ve.getSimpleName();
478 if (componentNames.contains(name)) {
479 utils.removeCommentHelper(ve); // purge previous entry
480 cmtUtils.setRecordFieldTree(ve);
481 }
482 }
483
484 TypeMirror objectType = utils.elementUtils.getTypeElement("java.lang.Object").asType();
485
486 for (ExecutableElement ee : utils.getMethods(elem)) {
487 if (!utils.getFullBody(ee).isEmpty()) {
488 continue;
489 }
490
491 Name name = ee.getSimpleName();
492 List<? extends VariableElement> params = ee.getParameters();
493 if (name.contentEquals("equals")) {
494 if (params.size() == 1 && utils.typeUtils.isSameType(params.get(0).asType(), objectType)) {
495 utils.removeCommentHelper(ee); // purge previous entry
496 cmtUtils.setRecordEqualsTree(ee);
497 }
498 } else if (name.contentEquals("hashCode")) {
499 if (params.isEmpty()) {
500 utils.removeCommentHelper(ee); // purge previous entry
501 cmtUtils.setRecordHashCodeTree(ee);
502 }
503 } else if (name.contentEquals("toString")) {
504 if (params.isEmpty()) {
505 utils.removeCommentHelper(ee); // purge previous entry
506 cmtUtils.setRecordToStringTree(ee);
507 }
508 } else if (componentNames.contains(name)) {
509 if (params.isEmpty()) {
510 utils.removeCommentHelper(ee); // purge previous entry
511 cmtUtils.setRecordAccessorTree(ee);
512 }
513 }
514 }
515
516 }
517 }
|