Tue, 09 Oct 2012 19:31:58 -0700
8000208: fix langtools javadoc comment issues
Reviewed-by: bpatel, mcimadamore
1 /*
2 * Copyright (c) 1997, 2012, 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.formats.html;
28 import java.lang.reflect.Modifier;
29 import java.util.*;
31 import com.sun.javadoc.*;
32 import com.sun.tools.doclets.formats.html.markup.*;
33 import com.sun.tools.doclets.internal.toolkit.*;
34 import com.sun.tools.doclets.internal.toolkit.taglets.*;
35 import com.sun.tools.doclets.internal.toolkit.util.*;
37 /**
38 * The base class for member writers.
39 *
40 * @author Robert Field
41 * @author Atul M Dambalkar
42 * @author Jamie Ho (Re-write)
43 * @author Bhavesh Patel (Modified)
44 */
45 public abstract class AbstractMemberWriter {
47 protected boolean printedSummaryHeader = false;
48 protected final SubWriterHolderWriter writer;
49 protected final ClassDoc classdoc;
50 public final boolean nodepr;
52 public AbstractMemberWriter(SubWriterHolderWriter writer,
53 ClassDoc classdoc) {
54 this.writer = writer;
55 this.nodepr = configuration().nodeprecated;
56 this.classdoc = classdoc;
57 }
59 public AbstractMemberWriter(SubWriterHolderWriter writer) {
60 this(writer, null);
61 }
63 /*** abstracts ***/
65 /**
66 * Add the summary label for the member.
67 *
68 * @param memberTree the content tree to which the label will be added
69 */
70 public abstract void addSummaryLabel(Content memberTree);
72 /**
73 * Get the summary for the member summary table.
74 *
75 * @return a string for the table summary
76 */
77 public abstract String getTableSummary();
79 /**
80 * Get the caption for the member summary table.
81 *
82 * @return a string for the table caption
83 */
84 public abstract String getCaption();
86 /**
87 * Get the summary table header for the member.
88 *
89 * @param member the member to be documented
90 * @return the summary table header
91 */
92 public abstract String[] getSummaryTableHeader(ProgramElementDoc member);
94 /**
95 * Add inherited summary lable for the member.
96 *
97 * @param cd the class doc to which to link to
98 * @param inheritedTree the content tree to which the inherited summary label will be added
99 */
100 public abstract void addInheritedSummaryLabel(ClassDoc cd, Content inheritedTree);
102 /**
103 * Add the anchor for the summary section of the member.
104 *
105 * @param cd the class doc to be documented
106 * @param memberTree the content tree to which the summary anchor will be added
107 */
108 public abstract void addSummaryAnchor(ClassDoc cd, Content memberTree);
110 /**
111 * Add the anchor for the inherited summary section of the member.
112 *
113 * @param cd the class doc to be documented
114 * @param inheritedTree the content tree to which the inherited summary anchor will be added
115 */
116 public abstract void addInheritedSummaryAnchor(ClassDoc cd, Content inheritedTree);
118 /**
119 * Add the summary type for the member.
120 *
121 * @param member the member to be documented
122 * @param tdSummaryType the content tree to which the type will be added
123 */
124 protected abstract void addSummaryType(ProgramElementDoc member,
125 Content tdSummaryType);
127 /**
128 * Add the summary link for the member.
129 *
130 * @param cd the class doc to be documented
131 * @param member the member to be documented
132 * @param tdSummary the content tree to which the link will be added
133 */
134 protected void addSummaryLink(ClassDoc cd, ProgramElementDoc member,
135 Content tdSummary) {
136 addSummaryLink(LinkInfoImpl.CONTEXT_MEMBER, cd, member, tdSummary);
137 }
139 /**
140 * Add the summary link for the member.
141 *
142 * @param context the id of the context where the link will be printed
143 * @param cd the class doc to be documented
144 * @param member the member to be documented
145 * @param tdSummary the content tree to which the summary link will be added
146 */
147 protected abstract void addSummaryLink(int context,
148 ClassDoc cd, ProgramElementDoc member, Content tdSummary);
150 /**
151 * Add the inherited summary link for the member.
152 *
153 * @param cd the class doc to be documented
154 * @param member the member to be documented
155 * @param linksTree the content tree to which the inherited summary link will be added
156 */
157 protected abstract void addInheritedSummaryLink(ClassDoc cd,
158 ProgramElementDoc member, Content linksTree);
160 /**
161 * Get the deprecated link.
162 *
163 * @param member the member being linked to
164 * @return a content tree representing the link
165 */
166 protected abstract Content getDeprecatedLink(ProgramElementDoc member);
168 /**
169 * Get the navigation summary link.
170 *
171 * @param cd the class doc to be documented
172 * @param link true if its a link else the label to be printed
173 * @return a content tree for the navigation summary link.
174 */
175 protected abstract Content getNavSummaryLink(ClassDoc cd, boolean link);
177 /**
178 * Add the navigation detail link.
179 *
180 * @param link true if its a link else the label to be printed
181 * @param liNav the content tree to which the navigation detail link will be added
182 */
183 protected abstract void addNavDetailLink(boolean link, Content liNav);
185 /*** ***/
187 protected void print(String str) {
188 writer.print(str);
189 writer.displayLength += str.length();
190 }
192 protected void print(char ch) {
193 writer.print(ch);
194 writer.displayLength++;
195 }
197 protected void strong(String str) {
198 writer.strong(str);
199 writer.displayLength += str.length();
200 }
202 /**
203 * Add the member name to the content tree and modifies the display length.
204 *
205 * @param name the member name to be added to the content tree.
206 * @param htmltree the content tree to which the name will be added.
207 */
208 protected void addName(String name, Content htmltree) {
209 htmltree.addContent(name);
210 writer.displayLength += name.length();
211 }
213 /**
214 * Return a string describing the access modifier flags.
215 * Don't include native or synchronized.
216 *
217 * The modifier names are returned in canonical order, as
218 * specified by <em>The Java Language Specification</em>.
219 */
220 protected String modifierString(MemberDoc member) {
221 int ms = member.modifierSpecifier();
222 int no = Modifier.NATIVE | Modifier.SYNCHRONIZED;
223 return Modifier.toString(ms & ~no);
224 }
226 protected String typeString(MemberDoc member) {
227 String type = "";
228 if (member instanceof MethodDoc) {
229 type = ((MethodDoc)member).returnType().toString();
230 } else if (member instanceof FieldDoc) {
231 type = ((FieldDoc)member).type().toString();
232 }
233 return type;
234 }
236 /**
237 * Add the modifier for the member.
238 *
239 * @param member the member for which teh modifier will be added.
240 * @param htmltree the content tree to which the modifier information will be added.
241 */
242 protected void addModifiers(MemberDoc member, Content htmltree) {
243 String mod = modifierString(member);
244 // According to JLS, we should not be showing public modifier for
245 // interface methods.
246 if ((member.isField() || member.isMethod()) &&
247 writer instanceof ClassWriterImpl &&
248 ((ClassWriterImpl) writer).getClassDoc().isInterface()) {
249 mod = Util.replaceText(mod, "public", "").trim();
250 }
251 if(mod.length() > 0) {
252 htmltree.addContent(mod);
253 htmltree.addContent(writer.getSpace());
254 }
255 }
257 protected String makeSpace(int len) {
258 if (len <= 0) {
259 return "";
260 }
261 StringBuffer sb = new StringBuffer(len);
262 for(int i = 0; i < len; i++) {
263 sb.append(' ');
264 }
265 return sb.toString();
266 }
268 /**
269 * Add the modifier and type for the member in the member summary.
270 *
271 * @param member the member to add the type for
272 * @param type the type to add
273 * @param tdSummaryType the content tree to which the modified and type will be added
274 */
275 protected void addModifierAndType(ProgramElementDoc member, Type type,
276 Content tdSummaryType) {
277 HtmlTree code = new HtmlTree(HtmlTag.CODE);
278 addModifier(member, code);
279 if (type == null) {
280 if (member.isClass()) {
281 code.addContent("class");
282 } else {
283 code.addContent("interface");
284 }
285 code.addContent(writer.getSpace());
286 } else {
287 if (member instanceof ExecutableMemberDoc &&
288 ((ExecutableMemberDoc) member).typeParameters().length > 0) {
289 //Code to avoid ugly wrapping in member summary table.
290 int displayLength = ((AbstractExecutableMemberWriter) this).addTypeParameters(
291 (ExecutableMemberDoc) member, code);
292 if (displayLength > 10) {
293 code.addContent(new HtmlTree(HtmlTag.BR));
294 }
295 code.addContent(new RawHtml(
296 writer.getLink(new LinkInfoImpl(
297 LinkInfoImpl.CONTEXT_SUMMARY_RETURN_TYPE, type))));
298 } else {
299 code.addContent(new RawHtml(
300 writer.getLink(new LinkInfoImpl(
301 LinkInfoImpl.CONTEXT_SUMMARY_RETURN_TYPE, type))));
302 }
304 }
305 tdSummaryType.addContent(code);
306 }
308 private void printModifier(ProgramElementDoc member) {
309 if (member.isProtected()) {
310 print("protected ");
311 } else if (member.isPrivate()) {
312 print("private ");
313 } else if (!member.isPublic()) { // Package private
314 writer.printText("doclet.Package_private");
315 print(" ");
316 }
317 if (member.isMethod() && ((MethodDoc)member).isAbstract()) {
318 print("abstract ");
319 }
320 if (member.isStatic()) {
321 print("static");
322 }
323 }
325 /**
326 * Add the modifier for the member.
327 *
328 * @param member the member to add the type for
329 * @param code the content tree to which the modified will be added
330 */
331 private void addModifier(ProgramElementDoc member, Content code) {
332 if (member.isProtected()) {
333 code.addContent("protected ");
334 } else if (member.isPrivate()) {
335 code.addContent("private ");
336 } else if (!member.isPublic()) { // Package private
337 code.addContent(configuration().getText("doclet.Package_private"));
338 code.addContent(" ");
339 }
340 if (member.isMethod() && ((MethodDoc)member).isAbstract()) {
341 code.addContent("abstract ");
342 }
343 if (member.isStatic()) {
344 code.addContent("static ");
345 }
346 }
348 /**
349 * Add the deprecated information for the given member.
350 *
351 * @param member the member being documented.
352 * @param contentTree the content tree to which the deprecated information will be added.
353 */
354 protected void addDeprecatedInfo(ProgramElementDoc member, Content contentTree) {
355 String output = (new DeprecatedTaglet()).getTagletOutput(member,
356 writer.getTagletWriterInstance(false)).toString().trim();
357 if (!output.isEmpty()) {
358 Content deprecatedContent = new RawHtml(output);
359 Content div = HtmlTree.DIV(HtmlStyle.block, deprecatedContent);
360 contentTree.addContent(div);
361 }
362 }
364 /**
365 * Add the comment for the given member.
366 *
367 * @param member the member being documented.
368 * @param htmltree the content tree to which the comment will be added.
369 */
370 protected void addComment(ProgramElementDoc member, Content htmltree) {
371 if (member.inlineTags().length > 0) {
372 writer.addInlineComment(member, htmltree);
373 }
374 }
376 protected String name(ProgramElementDoc member) {
377 return member.name();
378 }
380 /**
381 * Get the header for the section.
382 *
383 * @param member the member being documented.
384 * @return a header content for the section.
385 */
386 protected Content getHead(MemberDoc member) {
387 Content memberContent = new RawHtml(member.name());
388 Content heading = HtmlTree.HEADING(HtmlConstants.MEMBER_HEADING, memberContent);
389 return heading;
390 }
392 /**
393 * Return true if the given <code>ProgramElement</code> is inherited
394 * by the class that is being documented.
395 *
396 * @param ped The <code>ProgramElement</code> being checked.
397 * return true if the <code>ProgramElement</code> is being inherited and
398 * false otherwise.
399 */
400 protected boolean isInherited(ProgramElementDoc ped){
401 if(ped.isPrivate() || (ped.isPackagePrivate() &&
402 ! ped.containingPackage().equals(classdoc.containingPackage()))){
403 return false;
404 }
405 return true;
406 }
408 /**
409 * Add deprecated information to the documentation tree
410 *
411 * @param deprmembers list of deprecated members
412 * @param headingKey the caption for the deprecated members table
413 * @param tableSummary the summary for the deprecated members table
414 * @param tableHeader table headers for the deprecated members table
415 * @param contentTree the content tree to which the deprecated members table will be added
416 */
417 protected void addDeprecatedAPI(List<Doc> deprmembers, String headingKey,
418 String tableSummary, String[] tableHeader, Content contentTree) {
419 if (deprmembers.size() > 0) {
420 Content table = HtmlTree.TABLE(0, 3, 0, tableSummary,
421 writer.getTableCaption(configuration().getText(headingKey)));
422 table.addContent(writer.getSummaryTableHeader(tableHeader, "col"));
423 Content tbody = new HtmlTree(HtmlTag.TBODY);
424 for (int i = 0; i < deprmembers.size(); i++) {
425 ProgramElementDoc member =(ProgramElementDoc)deprmembers.get(i);
426 HtmlTree td = HtmlTree.TD(HtmlStyle.colOne, getDeprecatedLink(member));
427 if (member.tags("deprecated").length > 0)
428 writer.addInlineDeprecatedComment(member,
429 member.tags("deprecated")[0], td);
430 HtmlTree tr = HtmlTree.TR(td);
431 if (i%2 == 0)
432 tr.addStyle(HtmlStyle.altColor);
433 else
434 tr.addStyle(HtmlStyle.rowColor);
435 tbody.addContent(tr);
436 }
437 table.addContent(tbody);
438 Content li = HtmlTree.LI(HtmlStyle.blockList, table);
439 Content ul = HtmlTree.UL(HtmlStyle.blockList, li);
440 contentTree.addContent(ul);
441 }
442 }
444 /**
445 * Add use information to the documentation tree.
446 *
447 * @param mems list of program elements for which the use information will be added
448 * @param heading the section heading
449 * @param tableSummary the summary for the use table
450 * @param contentTree the content tree to which the use information will be added
451 */
452 protected void addUseInfo(List<? extends ProgramElementDoc> mems,
453 String heading, String tableSummary, Content contentTree) {
454 if (mems == null) {
455 return;
456 }
457 List<? extends ProgramElementDoc> members = mems;
458 boolean printedUseTableHeader = false;
459 if (members.size() > 0) {
460 Content table = HtmlTree.TABLE(0, 3, 0, tableSummary,
461 writer.getTableCaption(heading));
462 Content tbody = new HtmlTree(HtmlTag.TBODY);
463 Iterator<? extends ProgramElementDoc> it = members.iterator();
464 for (int i = 0; it.hasNext(); i++) {
465 ProgramElementDoc pgmdoc = it.next();
466 ClassDoc cd = pgmdoc.containingClass();
467 if (!printedUseTableHeader) {
468 table.addContent(writer.getSummaryTableHeader(
469 this.getSummaryTableHeader(pgmdoc), "col"));
470 printedUseTableHeader = true;
471 }
472 HtmlTree tr = new HtmlTree(HtmlTag.TR);
473 if (i % 2 == 0) {
474 tr.addStyle(HtmlStyle.altColor);
475 } else {
476 tr.addStyle(HtmlStyle.rowColor);
477 }
478 HtmlTree tdFirst = new HtmlTree(HtmlTag.TD);
479 tdFirst.addStyle(HtmlStyle.colFirst);
480 writer.addSummaryType(this, pgmdoc, tdFirst);
481 tr.addContent(tdFirst);
482 HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
483 tdLast.addStyle(HtmlStyle.colLast);
484 if (cd != null && !(pgmdoc instanceof ConstructorDoc)
485 && !(pgmdoc instanceof ClassDoc)) {
486 HtmlTree name = new HtmlTree(HtmlTag.SPAN);
487 name.addStyle(HtmlStyle.strong);
488 name.addContent(cd.name() + ".");
489 tdLast.addContent(name);
490 }
491 addSummaryLink(pgmdoc instanceof ClassDoc ?
492 LinkInfoImpl.CONTEXT_CLASS_USE : LinkInfoImpl.CONTEXT_MEMBER,
493 cd, pgmdoc, tdLast);
494 writer.addSummaryLinkComment(this, pgmdoc, tdLast);
495 tr.addContent(tdLast);
496 tbody.addContent(tr);
497 }
498 table.addContent(tbody);
499 contentTree.addContent(table);
500 }
501 }
503 /**
504 * Add the navigation detail link.
505 *
506 * @param members the members to be linked
507 * @param liNav the content tree to which the navigation detail link will be added
508 */
509 protected void addNavDetailLink(List<?> members, Content liNav) {
510 addNavDetailLink(members.size() > 0 ? true : false, liNav);
511 }
513 /**
514 * Add the navigation summary link.
515 *
516 * @param members members to be linked
517 * @param visibleMemberMap the visible inherited members map
518 * @param liNav the content tree to which the navigation summary link will be added
519 */
520 protected void addNavSummaryLink(List<?> members,
521 VisibleMemberMap visibleMemberMap, Content liNav) {
522 if (members.size() > 0) {
523 liNav.addContent(getNavSummaryLink(null, true));
524 return;
525 }
526 ClassDoc icd = classdoc.superclass();
527 while (icd != null) {
528 List<?> inhmembers = visibleMemberMap.getMembersFor(icd);
529 if (inhmembers.size() > 0) {
530 liNav.addContent(getNavSummaryLink(icd, true));
531 return;
532 }
533 icd = icd.superclass();
534 }
535 liNav.addContent(getNavSummaryLink(null, false));
536 }
538 protected void serialWarning(SourcePosition pos, String key, String a1, String a2) {
539 if (configuration().serialwarn) {
540 ConfigurationImpl.getInstance().getDocletSpecificMsg().warning(pos, key, a1, a2);
541 }
542 }
544 public ProgramElementDoc[] eligibleMembers(ProgramElementDoc[] members) {
545 return nodepr? Util.excludeDeprecatedMembers(members): members;
546 }
548 public ConfigurationImpl configuration() {
549 return writer.configuration;
550 }
552 /**
553 * Add the member summary for the given class.
554 *
555 * @param classDoc the class that is being documented
556 * @param member the member being documented
557 * @param firstSentenceTags the first sentence tags to be added to the summary
558 * @param tableTree the content tree to which the documentation will be added
559 * @param counter the counter for determing style for the table row
560 */
561 public void addMemberSummary(ClassDoc classDoc, ProgramElementDoc member,
562 Tag[] firstSentenceTags, Content tableTree, int counter) {
563 HtmlTree tdSummaryType = new HtmlTree(HtmlTag.TD);
564 tdSummaryType.addStyle(HtmlStyle.colFirst);
565 writer.addSummaryType(this, member, tdSummaryType);
566 HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
567 setSummaryColumnStyle(tdSummary);
568 addSummaryLink(classDoc, member, tdSummary);
569 writer.addSummaryLinkComment(this, member, firstSentenceTags, tdSummary);
570 HtmlTree tr = HtmlTree.TR(tdSummaryType);
571 tr.addContent(tdSummary);
572 if (counter%2 == 0)
573 tr.addStyle(HtmlStyle.altColor);
574 else
575 tr.addStyle(HtmlStyle.rowColor);
576 tableTree.addContent(tr);
577 }
579 /**
580 * Set the style for the summary column.
581 *
582 * @param tdTree the column for which the style will be set
583 */
584 public void setSummaryColumnStyle(HtmlTree tdTree) {
585 tdTree.addStyle(HtmlStyle.colLast);
586 }
588 /**
589 * Add inherited member summary for the given class and member.
590 *
591 * @param classDoc the class the inherited member belongs to
592 * @param nestedClass the inherited member that is summarized
593 * @param isFirst true if this is the first member in the list
594 * @param isLast true if this is the last member in the list
595 * @param linksTree the content tree to which the summary will be added
596 */
597 public void addInheritedMemberSummary(ClassDoc classDoc,
598 ProgramElementDoc nestedClass, boolean isFirst, boolean isLast,
599 Content linksTree) {
600 writer.addInheritedMemberSummary(this, classDoc, nestedClass, isFirst,
601 linksTree);
602 }
604 /**
605 * Get the inherited summary header for the given class.
606 *
607 * @param classDoc the class the inherited member belongs to
608 * @return a content tree for the inherited summary header
609 */
610 public Content getInheritedSummaryHeader(ClassDoc classDoc) {
611 Content inheritedTree = writer.getMemberTreeHeader();
612 writer.addInheritedSummaryHeader(this, classDoc, inheritedTree);
613 return inheritedTree;
614 }
616 /**
617 * Get the inherited summary links tree.
618 *
619 * @return a content tree for the inherited summary links
620 */
621 public Content getInheritedSummaryLinksTree() {
622 return new HtmlTree(HtmlTag.CODE);
623 }
625 /**
626 * Get the summary table tree for the given class.
627 *
628 * @param classDoc the class for which the summary table is generated
629 * @return a content tree for the summary table
630 */
631 public Content getSummaryTableTree(ClassDoc classDoc) {
632 return writer.getSummaryTableTree(this, classDoc);
633 }
635 /**
636 * Get the member tree to be documented.
637 *
638 * @param memberTree the content tree of member to be documented
639 * @return a content tree that will be added to the class documentation
640 */
641 public Content getMemberTree(Content memberTree) {
642 return writer.getMemberTree(memberTree);
643 }
645 /**
646 * Get the member tree to be documented.
647 *
648 * @param memberTree the content tree of member to be documented
649 * @param isLastContent true if the content to be added is the last content
650 * @return a content tree that will be added to the class documentation
651 */
652 public Content getMemberTree(Content memberTree, boolean isLastContent) {
653 if (isLastContent)
654 return HtmlTree.UL(HtmlStyle.blockListLast, memberTree);
655 else
656 return HtmlTree.UL(HtmlStyle.blockList, memberTree);
657 }
658 }