Wed, 27 Apr 2016 01:34:52 +0800
Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17
1 /*
2 * Copyright (c) 2003, 2013, 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 */
26 package com.sun.tools.doclets.internal.toolkit.builders;
28 import java.util.*;
29 import java.text.MessageFormat;
31 import com.sun.javadoc.*;
32 import com.sun.tools.doclets.internal.toolkit.*;
33 import com.sun.tools.doclets.internal.toolkit.util.*;
35 /**
36 * Builds the member summary.
37 *
38 * <p><b>This is NOT part of any supported API.
39 * If you write code that depends on this, you do so at your own risk.
40 * This code and its internal interfaces are subject to change or
41 * deletion without notice.</b>
42 *
43 * @author Jamie Ho
44 * @author Bhavesh Patel (Modified)
45 * @since 1.5
46 */
47 public class MemberSummaryBuilder extends AbstractMemberBuilder {
49 /**
50 * The XML root for this builder.
51 */
52 public static final String NAME = "MemberSummary";
54 /**
55 * The visible members for the given class.
56 */
57 private final VisibleMemberMap[] visibleMemberMaps;
59 /**
60 * The member summary writers for the given class.
61 */
62 private MemberSummaryWriter[] memberSummaryWriters;
64 /**
65 * The type being documented.
66 */
67 private final ClassDoc classDoc;
69 /**
70 * Construct a new MemberSummaryBuilder.
71 *
72 * @param classWriter the writer for the class whose members are being
73 * summarized.
74 * @param context the build context.
75 */
76 private MemberSummaryBuilder(Context context, ClassDoc classDoc) {
77 super(context);
78 this.classDoc = classDoc;
79 visibleMemberMaps =
80 new VisibleMemberMap[VisibleMemberMap.NUM_MEMBER_TYPES];
81 for (int i = 0; i < VisibleMemberMap.NUM_MEMBER_TYPES; i++) {
82 visibleMemberMaps[i] =
83 new VisibleMemberMap(
84 classDoc,
85 i,
86 configuration);
87 }
88 }
90 /**
91 * Construct a new MemberSummaryBuilder.
92 *
93 * @param classWriter the writer for the class whose members are being
94 * summarized.
95 * @param context the build context.
96 */
97 public static MemberSummaryBuilder getInstance(
98 ClassWriter classWriter, Context context)
99 throws Exception {
100 MemberSummaryBuilder builder = new MemberSummaryBuilder(context,
101 classWriter.getClassDoc());
102 builder.memberSummaryWriters =
103 new MemberSummaryWriter[VisibleMemberMap.NUM_MEMBER_TYPES];
104 WriterFactory wf = context.configuration.getWriterFactory();
105 for (int i = 0; i < VisibleMemberMap.NUM_MEMBER_TYPES; i++) {
106 builder.memberSummaryWriters[i] =
107 builder.visibleMemberMaps[i].noVisibleMembers() ?
108 null :
109 wf.getMemberSummaryWriter(classWriter, i);
110 }
111 return builder;
112 }
114 /**
115 * Construct a new MemberSummaryBuilder.
116 *
117 * @param annotationTypeWriter the writer for the class whose members are
118 * being summarized.
119 * @param configuration the current configuration of the doclet.
120 */
121 public static MemberSummaryBuilder getInstance(
122 AnnotationTypeWriter annotationTypeWriter, Context context)
123 throws Exception {
124 MemberSummaryBuilder builder = new MemberSummaryBuilder(context,
125 annotationTypeWriter.getAnnotationTypeDoc());
126 builder.memberSummaryWriters =
127 new MemberSummaryWriter[VisibleMemberMap.NUM_MEMBER_TYPES];
128 WriterFactory wf = context.configuration.getWriterFactory();
129 for (int i = 0; i < VisibleMemberMap.NUM_MEMBER_TYPES; i++) {
130 builder.memberSummaryWriters[i] =
131 builder.visibleMemberMaps[i].noVisibleMembers()?
132 null :
133 wf.getMemberSummaryWriter(
134 annotationTypeWriter, i);
135 }
136 return builder;
137 }
139 /**
140 * {@inheritDoc}
141 */
142 public String getName() {
143 return NAME;
144 }
146 /**
147 * Return the specified visible member map.
148 *
149 * @param type the type of visible member map to return.
150 * @return the specified visible member map.
151 * @throws ArrayIndexOutOfBoundsException when the type is invalid.
152 * @see VisibleMemberMap
153 */
154 public VisibleMemberMap getVisibleMemberMap(int type) {
155 return visibleMemberMaps[type];
156 }
158 /**
159 * Return the specified member summary writer.
160 *
161 * @param type the type of member summary writer to return.
162 * @return the specified member summary writer.
163 * @throws ArrayIndexOutOfBoundsException when the type is invalid.
164 * @see VisibleMemberMap
165 */
166 public MemberSummaryWriter getMemberSummaryWriter(int type) {
167 return memberSummaryWriters[type];
168 }
170 /**
171 * Returns a list of methods that will be documented for the given class.
172 * This information can be used for doclet specific documentation
173 * generation.
174 *
175 * @param type the type of members to return.
176 * @return a list of methods that will be documented.
177 * @see VisibleMemberMap
178 */
179 public List<ProgramElementDoc> members(int type) {
180 return visibleMemberMaps[type].getLeafClassMembers(configuration);
181 }
183 /**
184 * Return true it there are any members to summarize.
185 *
186 * @return true if there are any members to summarize.
187 */
188 public boolean hasMembersToDocument() {
189 if (classDoc instanceof AnnotationTypeDoc) {
190 return ((AnnotationTypeDoc) classDoc).elements().length > 0;
191 }
192 for (int i = 0; i < VisibleMemberMap.NUM_MEMBER_TYPES; i++) {
193 VisibleMemberMap members = visibleMemberMaps[i];
194 if (!members.noVisibleMembers()) {
195 return true;
196 }
197 }
198 return false;
199 }
201 /**
202 * Build the summary for the enum constants.
203 *
204 * @param node the XML element that specifies which components to document
205 * @param memberSummaryTree the content tree to which the documentation will be added
206 */
207 public void buildEnumConstantsSummary(XMLNode node, Content memberSummaryTree) {
208 MemberSummaryWriter writer =
209 memberSummaryWriters[VisibleMemberMap.ENUM_CONSTANTS];
210 VisibleMemberMap visibleMemberMap =
211 visibleMemberMaps[VisibleMemberMap.ENUM_CONSTANTS];
212 addSummary(writer, visibleMemberMap, false, memberSummaryTree);
213 }
215 /**
216 * Build the summary for fields.
217 *
218 * @param node the XML element that specifies which components to document
219 * @param memberSummaryTree the content tree to which the documentation will be added
220 */
221 public void buildAnnotationTypeFieldsSummary(XMLNode node, Content memberSummaryTree) {
222 MemberSummaryWriter writer =
223 memberSummaryWriters[VisibleMemberMap.ANNOTATION_TYPE_FIELDS];
224 VisibleMemberMap visibleMemberMap =
225 visibleMemberMaps[VisibleMemberMap.ANNOTATION_TYPE_FIELDS];
226 addSummary(writer, visibleMemberMap, false, memberSummaryTree);
227 }
229 /**
230 * Build the summary for the optional members.
231 *
232 * @param node the XML element that specifies which components to document
233 * @param memberSummaryTree the content tree to which the documentation will be added
234 */
235 public void buildAnnotationTypeOptionalMemberSummary(XMLNode node, Content memberSummaryTree) {
236 MemberSummaryWriter writer =
237 memberSummaryWriters[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL];
238 VisibleMemberMap visibleMemberMap =
239 visibleMemberMaps[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL];
240 addSummary(writer, visibleMemberMap, false, memberSummaryTree);
241 }
243 /**
244 * Build the summary for the optional members.
245 *
246 * @param node the XML element that specifies which components to document
247 * @param memberSummaryTree the content tree to which the documentation will be added
248 */
249 public void buildAnnotationTypeRequiredMemberSummary(XMLNode node, Content memberSummaryTree) {
250 MemberSummaryWriter writer =
251 memberSummaryWriters[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_REQUIRED];
252 VisibleMemberMap visibleMemberMap =
253 visibleMemberMaps[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_REQUIRED];
254 addSummary(writer, visibleMemberMap, false, memberSummaryTree);
255 }
257 /**
258 * Build the summary for the fields.
259 *
260 * @param node the XML element that specifies which components to document
261 * @param memberSummaryTree the content tree to which the documentation will be added
262 */
263 public void buildFieldsSummary(XMLNode node, Content memberSummaryTree) {
264 MemberSummaryWriter writer =
265 memberSummaryWriters[VisibleMemberMap.FIELDS];
266 VisibleMemberMap visibleMemberMap =
267 visibleMemberMaps[VisibleMemberMap.FIELDS];
268 addSummary(writer, visibleMemberMap, true, memberSummaryTree);
269 }
271 /**
272 * Build the summary for the fields.
273 */
274 public void buildPropertiesSummary(XMLNode node, Content memberSummaryTree) {
275 MemberSummaryWriter writer =
276 memberSummaryWriters[VisibleMemberMap.PROPERTIES];
277 VisibleMemberMap visibleMemberMap =
278 visibleMemberMaps[VisibleMemberMap.PROPERTIES];
279 addSummary(writer, visibleMemberMap, true, memberSummaryTree);
280 }
282 /**
283 * Build the summary for the nested classes.
284 *
285 * @param node the XML element that specifies which components to document
286 * @param memberSummaryTree the content tree to which the documentation will be added
287 */
288 public void buildNestedClassesSummary(XMLNode node, Content memberSummaryTree) {
289 MemberSummaryWriter writer =
290 memberSummaryWriters[VisibleMemberMap.INNERCLASSES];
291 VisibleMemberMap visibleMemberMap =
292 visibleMemberMaps[VisibleMemberMap.INNERCLASSES];
293 addSummary(writer, visibleMemberMap, true, memberSummaryTree);
294 }
296 /**
297 * Build the method summary.
298 *
299 * @param node the XML element that specifies which components to document
300 * @param memberSummaryTree the content tree to which the documentation will be added
301 */
302 public void buildMethodsSummary(XMLNode node, Content memberSummaryTree) {
303 MemberSummaryWriter writer =
304 memberSummaryWriters[VisibleMemberMap.METHODS];
305 VisibleMemberMap visibleMemberMap =
306 visibleMemberMaps[VisibleMemberMap.METHODS];
307 addSummary(writer, visibleMemberMap, true, memberSummaryTree);
308 }
310 /**
311 * Build the constructor summary.
312 *
313 * @param node the XML element that specifies which components to document
314 * @param memberSummaryTree the content tree to which the documentation will be added
315 */
316 public void buildConstructorsSummary(XMLNode node, Content memberSummaryTree) {
317 MemberSummaryWriter writer =
318 memberSummaryWriters[VisibleMemberMap.CONSTRUCTORS];
319 VisibleMemberMap visibleMemberMap =
320 visibleMemberMaps[VisibleMemberMap.CONSTRUCTORS];
321 addSummary(writer, visibleMemberMap, false, memberSummaryTree);
322 }
324 /**
325 * Build the member summary for the given members.
326 *
327 * @param writer the summary writer to write the output.
328 * @param visibleMemberMap the given members to summarize.
329 * @param summaryTreeList list of content trees to which the documentation will be added
330 */
331 private void buildSummary(MemberSummaryWriter writer,
332 VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
333 List<ProgramElementDoc> members = new ArrayList<ProgramElementDoc>(visibleMemberMap.getLeafClassMembers(
334 configuration));
335 if (members.size() > 0) {
336 Collections.sort(members);
337 List<Content> tableContents = new LinkedList<Content>();
338 for (int i = 0; i < members.size(); i++) {
339 ProgramElementDoc member = members.get(i);
340 final ProgramElementDoc propertyDoc =
341 visibleMemberMap.getPropertyMemberDoc(member);
342 if (propertyDoc != null) {
343 processProperty(visibleMemberMap, member, propertyDoc);
344 }
345 Tag[] firstSentenceTags = member.firstSentenceTags();
346 if (member instanceof MethodDoc && firstSentenceTags.length == 0) {
347 //Inherit comments from overriden or implemented method if
348 //necessary.
349 DocFinder.Output inheritedDoc =
350 DocFinder.search(new DocFinder.Input((MethodDoc) member));
351 if (inheritedDoc.holder != null
352 && inheritedDoc.holder.firstSentenceTags().length > 0) {
353 firstSentenceTags = inheritedDoc.holder.firstSentenceTags();
354 }
355 }
356 writer.addMemberSummary(classDoc, member, firstSentenceTags,
357 tableContents, i);
358 }
359 summaryTreeList.add(writer.getSummaryTableTree(classDoc, tableContents));
360 }
361 }
363 /**
364 * Process the property method, property setter and/or property getter
365 * comment text so that it contains the documentation from
366 * the property field. The method adds the leading sentence,
367 * copied documentation including the defaultValue tag and
368 * the see tags if the appropriate property getter and setter are
369 * available.
370 *
371 * @param visibleMemberMap the members information.
372 * @param member the member which is to be augmented.
373 * @param propertyDoc the original property documentation.
374 */
375 private void processProperty(VisibleMemberMap visibleMemberMap,
376 ProgramElementDoc member,
377 ProgramElementDoc propertyDoc) {
378 StringBuilder commentTextBuilder = new StringBuilder();
379 final boolean isSetter = isSetter(member);
380 final boolean isGetter = isGetter(member);
381 if (isGetter || isSetter) {
382 //add "[GS]ets the value of the property PROPERTY_NAME."
383 if (isSetter) {
384 commentTextBuilder.append(
385 MessageFormat.format(
386 configuration.getText("doclet.PropertySetterWithName"),
387 Util.propertyNameFromMethodName(configuration, member.name())));
388 }
389 if (isGetter) {
390 commentTextBuilder.append(
391 MessageFormat.format(
392 configuration.getText("doclet.PropertyGetterWithName"),
393 Util.propertyNameFromMethodName(configuration, member.name())));
394 }
395 if (propertyDoc.commentText() != null
396 && !propertyDoc.commentText().isEmpty()) {
397 commentTextBuilder.append(" \n @propertyDescription ");
398 }
399 }
400 commentTextBuilder.append(propertyDoc.commentText());
402 // copy certain tags
403 List<Tag> allTags = new LinkedList<Tag>();
404 String[] tagNames = {"@defaultValue", "@since"};
405 for (String tagName: tagNames) {
406 Tag[] tags = propertyDoc.tags(tagName);
407 if (tags != null) {
408 allTags.addAll(Arrays.asList(tags));
409 }
410 }
411 for (Tag tag: allTags) {
412 commentTextBuilder.append("\n")
413 .append(tag.name())
414 .append(" ")
415 .append(tag.text());
416 }
418 //add @see tags
419 if (!isGetter && !isSetter) {
420 MethodDoc getter = (MethodDoc) visibleMemberMap.getGetterForProperty(member);
421 MethodDoc setter = (MethodDoc) visibleMemberMap.getSetterForProperty(member);
423 if ((null != getter)
424 && (commentTextBuilder.indexOf("@see #" + getter.name()) == -1)) {
425 commentTextBuilder.append("\n @see #")
426 .append(getter.name())
427 .append("() ");
428 }
430 if ((null != setter)
431 && (commentTextBuilder.indexOf("@see #" + setter.name()) == -1)) {
432 String typeName = setter.parameters()[0].typeName();
433 // Removal of type parameters and package information.
434 typeName = typeName.split("<")[0];
435 if (typeName.contains(".")) {
436 typeName = typeName.substring(typeName.lastIndexOf(".") + 1);
437 }
438 commentTextBuilder.append("\n @see #").append(setter.name());
440 if (setter.parameters()[0].type().asTypeVariable() == null) {
441 commentTextBuilder.append("(").append(typeName).append(")");
442 }
443 commentTextBuilder.append(" \n");
444 }
445 }
446 member.setRawCommentText(commentTextBuilder.toString());
447 }
448 /**
449 * Test whether the method is a getter.
450 * @param ped property method documentation. Needs to be either property
451 * method, property getter, or property setter.
452 * @return true if the given documentation belongs to a getter.
453 */
454 private boolean isGetter(ProgramElementDoc ped) {
455 final String pedName = ped.name();
456 return pedName.startsWith("get") || pedName.startsWith("is");
457 }
459 /**
460 * Test whether the method is a setter.
461 * @param ped property method documentation. Needs to be either property
462 * method, property getter, or property setter.
463 * @return true if the given documentation belongs to a setter.
464 */
465 private boolean isSetter(ProgramElementDoc ped) {
466 return ped.name().startsWith("set");
467 }
469 /**
470 * Build the inherited member summary for the given methods.
471 *
472 * @param writer the writer for this member summary.
473 * @param visibleMemberMap the map for the members to document.
474 * @param summaryTreeList list of content trees to which the documentation will be added
475 */
476 private void buildInheritedSummary(MemberSummaryWriter writer,
477 VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
478 for (Iterator<ClassDoc> iter = visibleMemberMap.getVisibleClassesList().iterator();
479 iter.hasNext();) {
480 ClassDoc inhclass = iter.next();
481 if (! (inhclass.isPublic() ||
482 Util.isLinkable(inhclass, configuration))) {
483 continue;
484 }
485 if (inhclass == classDoc) {
486 continue;
487 }
488 List<ProgramElementDoc> inhmembers = visibleMemberMap.getMembersFor(inhclass);
489 if (inhmembers.size() > 0) {
490 Collections.sort(inhmembers);
491 Content inheritedTree = writer.getInheritedSummaryHeader(inhclass);
492 Content linksTree = writer.getInheritedSummaryLinksTree();
493 for (int j = 0; j < inhmembers.size(); ++j) {
494 writer.addInheritedMemberSummary(
495 inhclass.isPackagePrivate() &&
496 ! Util.isLinkable(inhclass, configuration) ?
497 classDoc : inhclass,
498 inhmembers.get(j),
499 j == 0,
500 j == inhmembers.size() - 1, linksTree);
501 }
502 inheritedTree.addContent(linksTree);
503 summaryTreeList.add(writer.getMemberTree(inheritedTree));
504 }
505 }
506 }
508 /**
509 * Add the summary for the documentation.
510 *
511 * @param writer the writer for this member summary.
512 * @param visibleMemberMap the map for the members to document.
513 * @param showInheritedSummary true if inherited summary should be documented
514 * @param memberSummaryTree the content tree to which the documentation will be added
515 */
516 private void addSummary(MemberSummaryWriter writer,
517 VisibleMemberMap visibleMemberMap, boolean showInheritedSummary,
518 Content memberSummaryTree) {
519 LinkedList<Content> summaryTreeList = new LinkedList<Content>();
520 buildSummary(writer, visibleMemberMap, summaryTreeList);
521 if (showInheritedSummary)
522 buildInheritedSummary(writer, visibleMemberMap, summaryTreeList);
523 if (!summaryTreeList.isEmpty()) {
524 Content memberTree = writer.getMemberSummaryHeader(
525 classDoc, memberSummaryTree);
526 for (int i = 0; i < summaryTreeList.size(); i++) {
527 memberTree.addContent(summaryTreeList.get(i));
528 }
529 memberSummaryTree.addContent(writer.getMemberTree(memberTree));
530 }
531 }
532 }