AbstractMemberWriter.java revision 3692:87b48a8fb3cf
1/*
2 * Copyright (c) 1997, 2016, 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
26package jdk.javadoc.internal.doclets.formats.html;
27
28import java.util.*;
29import java.util.stream.Collectors;
30
31import javax.lang.model.element.Element;
32import javax.lang.model.element.ExecutableElement;
33import javax.lang.model.element.Modifier;
34import javax.lang.model.element.TypeElement;
35import javax.lang.model.element.TypeParameterElement;
36import javax.lang.model.type.TypeMirror;
37
38import com.sun.source.doctree.DocTree;
39
40import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
41import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
42import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
43import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
44import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
45import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
46import jdk.javadoc.internal.doclets.toolkit.Content;
47import jdk.javadoc.internal.doclets.toolkit.Resources;
48import jdk.javadoc.internal.doclets.toolkit.taglets.DeprecatedTaglet;
49import jdk.javadoc.internal.doclets.toolkit.util.MethodTypes;
50import jdk.javadoc.internal.doclets.toolkit.util.Utils;
51import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
52
53import static javax.lang.model.element.Modifier.*;
54
55/**
56 * The base class for member writers.
57 *
58 *  <p><b>This is NOT part of any supported API.
59 *  If you write code that depends on this, you do so at your own risk.
60 *  This code and its internal interfaces are subject to change or
61 *  deletion without notice.</b>
62 *
63 * @author Robert Field
64 * @author Atul M Dambalkar
65 * @author Jamie Ho (Re-write)
66 * @author Bhavesh Patel (Modified)
67 */
68public abstract class AbstractMemberWriter {
69
70    protected final ConfigurationImpl configuration;
71    protected final Utils utils;
72    protected final SubWriterHolderWriter writer;
73    protected final Contents contents;
74    protected final Resources resources;
75
76    protected final TypeElement typeElement;
77    protected Map<String, Integer> typeMap = new LinkedHashMap<>();
78    protected Set<MethodTypes> methodTypes = EnumSet.noneOf(MethodTypes.class);
79    private int methodTypesOr = 0;
80    public final boolean nodepr;
81
82    protected boolean printedSummaryHeader = false;
83
84    public AbstractMemberWriter(SubWriterHolderWriter writer, TypeElement typeElement) {
85        this.configuration = writer.configuration;
86        this.writer = writer;
87        this.nodepr = configuration.nodeprecated;
88        this.typeElement = typeElement;
89        this.utils = configuration.utils;
90        this.contents = configuration.contents;
91        this.resources = configuration.resources;
92    }
93
94    public AbstractMemberWriter(SubWriterHolderWriter writer) {
95        this(writer, null);
96    }
97
98    /*** abstracts ***/
99
100    /**
101     * Add the summary label for the member.
102     *
103     * @param memberTree the content tree to which the label will be added
104     */
105    public abstract void addSummaryLabel(Content memberTree);
106
107    /**
108     * Get the summary for the member summary table.
109     *
110     * @return a string for the table summary
111     */
112    public abstract String getTableSummary();
113
114    /**
115     * Get the caption for the member summary table.
116     *
117     * @return a string for the table caption
118     */
119    public abstract Content getCaption();
120
121    /**
122     * Get the summary table header for the member.
123     *
124     * @param member the member to be documented
125     * @return the summary table header
126     */
127    public abstract List<String> getSummaryTableHeader(Element member);
128
129    /**
130     * Add inherited summary label for the member.
131     *
132     * @param typeElement the TypeElement to which to link to
133     * @param inheritedTree the content tree to which the inherited summary label will be added
134     */
135    public abstract void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree);
136
137    /**
138     * Add the anchor for the summary section of the member.
139     *
140     * @param typeElement the TypeElement to be documented
141     * @param memberTree the content tree to which the summary anchor will be added
142     */
143    public abstract void addSummaryAnchor(TypeElement typeElement, Content memberTree);
144
145    /**
146     * Add the anchor for the inherited summary section of the member.
147     *
148     * @param typeElement the TypeElement to be documented
149     * @param inheritedTree the content tree to which the inherited summary anchor will be added
150     */
151    public abstract void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree);
152
153    /**
154     * Add the summary type for the member.
155     *
156     * @param member the member to be documented
157     * @param tdSummaryType the content tree to which the type will be added
158     */
159    protected abstract void addSummaryType(Element member, Content tdSummaryType);
160
161    /**
162     * Add the summary link for the member.
163     *
164     * @param typeElement the TypeElement to be documented
165     * @param member the member to be documented
166     * @param tdSummary the content tree to which the link will be added
167     */
168    protected void addSummaryLink(TypeElement typeElement, Element member, Content tdSummary) {
169        addSummaryLink(LinkInfoImpl.Kind.MEMBER, typeElement, member, tdSummary);
170    }
171
172    /**
173     * Add the summary link for the member.
174     *
175     * @param context the id of the context where the link will be printed
176     * @param typeElement the TypeElement to be documented
177     * @param member the member to be documented
178     * @param tdSummary the content tree to which the summary link will be added
179     */
180    protected abstract void addSummaryLink(LinkInfoImpl.Kind context,
181            TypeElement typeElement, Element member, Content tdSummary);
182
183    /**
184     * Add the inherited summary link for the member.
185     *
186     * @param typeElement the TypeElement to be documented
187     * @param member the member to be documented
188     * @param linksTree the content tree to which the inherited summary link will be added
189     */
190    protected abstract void addInheritedSummaryLink(TypeElement typeElement,
191            Element member, Content linksTree);
192
193    /**
194     * Get the deprecated link.
195     *
196     * @param member the member being linked to
197     * @return a content tree representing the link
198     */
199    protected abstract Content getDeprecatedLink(Element member);
200
201    /**
202     * Get the navigation summary link.
203     *
204     * @param typeElement the TypeElement to be documented
205     * @param link true if its a link else the label to be printed
206     * @return a content tree for the navigation summary link.
207     */
208    protected abstract Content getNavSummaryLink(TypeElement typeElement, boolean link);
209
210    /**
211     * Add the navigation detail link.
212     *
213     * @param link true if its a link else the label to be printed
214     * @param liNav the content tree to which the navigation detail link will be added
215     */
216    protected abstract void addNavDetailLink(boolean link, Content liNav);
217
218    /**
219     * Add the member name to the content tree.
220     *
221     * @param name the member name to be added to the content tree.
222     * @param htmltree the content tree to which the name will be added.
223     */
224    protected void addName(String name, Content htmltree) {
225        htmltree.addContent(name);
226    }
227
228    /**
229     * Add the modifier for the member. The modifiers are ordered as specified
230     * by <em>The Java Language Specification</em>.
231     *
232     * @param member the member for which teh modifier will be added.
233     * @param htmltree the content tree to which the modifier information will be added.
234     */
235    protected void addModifiers(Element member, Content htmltree) {
236        Set<Modifier> set = new TreeSet<>(member.getModifiers());
237
238        // remove the ones we really don't need
239        set.remove(NATIVE);
240        set.remove(SYNCHRONIZED);
241        set.remove(STRICTFP);
242
243        // According to JLS, we should not be showing public modifier for
244        // interface methods.
245        if ((utils.isField(member) || utils.isMethod(member))
246            && ((writer instanceof ClassWriterImpl
247                 && utils.isInterface(((ClassWriterImpl) writer).getTypeElement())  ||
248                 writer instanceof AnnotationTypeWriterImpl) )) {
249            // Remove the implicit abstract and public modifiers
250            if (utils.isMethod(member) &&
251                (utils.isInterface(member.getEnclosingElement()) ||
252                 utils.isAnnotationType(member.getEnclosingElement()))) {
253                set.remove(ABSTRACT);
254                set.remove(PUBLIC);
255            }
256            if (!utils.isMethod(member)) {
257                set.remove(PUBLIC);
258            }
259        }
260        if (!set.isEmpty()) {
261            String mods = set.stream().map(m -> m.toString()).collect(Collectors.joining(" "));
262            htmltree.addContent(mods);
263            htmltree.addContent(Contents.SPACE);
264        }
265    }
266
267    protected CharSequence makeSpace(int len) {
268        if (len <= 0) {
269            return "";
270        }
271        StringBuilder sb = new StringBuilder(len);
272        for (int i = 0; i < len; i++) {
273            sb.append(' ');
274        }
275        return sb;
276    }
277
278    /**
279     * Add the modifier and type for the member in the member summary.
280     *
281     * @param member the member to add the type for
282     * @param type the type to add
283     * @param tdSummaryType the content tree to which the modified and type will be added
284     */
285    protected void addModifierAndType(Element member, TypeMirror type,
286            Content tdSummaryType) {
287        HtmlTree code = new HtmlTree(HtmlTag.CODE);
288        addModifier(member, code);
289        if (type == null) {
290            code.addContent(utils.isClass(member) ? "class" : "interface");
291            code.addContent(Contents.SPACE);
292        } else {
293            List<? extends TypeParameterElement> list = utils.isExecutableElement(member)
294                    ? ((ExecutableElement)member).getTypeParameters()
295                    : null;
296            if (list != null && !list.isEmpty()) {
297                Content typeParameters = ((AbstractExecutableMemberWriter) this)
298                        .getTypeParameters((ExecutableElement)member);
299                    code.addContent(typeParameters);
300                //Code to avoid ugly wrapping in member summary table.
301                if (typeParameters.charCount() > 10) {
302                    code.addContent(new HtmlTree(HtmlTag.BR));
303                } else {
304                    code.addContent(Contents.SPACE);
305                }
306                code.addContent(
307                        writer.getLink(new LinkInfoImpl(configuration,
308                        LinkInfoImpl.Kind.SUMMARY_RETURN_TYPE, type)));
309            } else {
310                code.addContent(
311                        writer.getLink(new LinkInfoImpl(configuration,
312                        LinkInfoImpl.Kind.SUMMARY_RETURN_TYPE, type)));
313            }
314
315        }
316        tdSummaryType.addContent(code);
317    }
318
319    /**
320     * Add the modifier for the member.
321     *
322     * @param member the member to add the type for
323     * @param code the content tree to which the modified will be added
324     */
325    private void addModifier(Element member, Content code) {
326        if (utils.isProtected(member)) {
327            code.addContent("protected ");
328        } else if (utils.isPrivate(member)) {
329            code.addContent("private ");
330        } else if (!utils.isPublic(member)) { // Package private
331            code.addContent(configuration.getText("doclet.Package_private"));
332            code.addContent(" ");
333        }
334        boolean isAnnotatedTypeElement = utils.isAnnotationType(member.getEnclosingElement());
335        if (!isAnnotatedTypeElement && utils.isMethod(member)) {
336            if (!utils.isInterface(member.getEnclosingElement()) && utils.isAbstract(member)) {
337                code.addContent("abstract ");
338            }
339            if (utils.isDefault(member)) {
340                code.addContent("default ");
341            }
342        }
343        if (utils.isStatic(member)) {
344            code.addContent("static ");
345        }
346    }
347
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(Element member, Content contentTree) {
355        Content output = (new DeprecatedTaglet()).getTagletOutput(member,
356            writer.getTagletWriterInstance(false));
357        if (!output.isEmpty()) {
358            Content deprecatedContent = output;
359            Content div = HtmlTree.DIV(HtmlStyle.block, deprecatedContent);
360            contentTree.addContent(div);
361        }
362    }
363
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(Element member, Content htmltree) {
371        if (!utils.getFullBody(member).isEmpty()) {
372            writer.addInlineComment(member, htmltree);
373        }
374    }
375
376    protected String name(Element member) {
377        return utils.getSimpleName(member);
378    }
379
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(Element member) {
387        Content memberContent = new StringContent(name(member));
388        Content heading = HtmlTree.HEADING(HtmlConstants.MEMBER_HEADING, memberContent);
389        return heading;
390    }
391
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     *@return true if inherited
400    */
401    protected boolean isInherited(Element ped){
402        return (!utils.isPrivate(ped) &&
403                (!utils.isPackagePrivate(ped) ||
404                    ped.getEnclosingElement().equals(ped.getEnclosingElement())));
405    }
406
407    /**
408     * Add deprecated information to the documentation tree
409     *
410     * @param deprmembers list of deprecated members
411     * @param headingKey the caption for the deprecated members table
412     * @param tableSummary the summary for the deprecated members table
413     * @param tableHeader table headers for the deprecated members table
414     * @param contentTree the content tree to which the deprecated members table will be added
415     */
416    protected void addDeprecatedAPI(Collection<Element> deprmembers, String headingKey,
417            String tableSummary, List<String> tableHeader, Content contentTree) {
418        if (deprmembers.size() > 0) {
419            Content caption = writer.getTableCaption(configuration.getContent(headingKey));
420            Content table = (configuration.isOutputHtml5())
421                    ? HtmlTree.TABLE(HtmlStyle.deprecatedSummary, caption)
422                    : HtmlTree.TABLE(HtmlStyle.deprecatedSummary, tableSummary, caption);
423            table.addContent(writer.getSummaryTableHeader(tableHeader, "col"));
424            Content tbody = new HtmlTree(HtmlTag.TBODY);
425            boolean altColor = true;
426            for (Element member : deprmembers) {
427                HtmlTree thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, getDeprecatedLink(member));
428                HtmlTree tr = HtmlTree.TR(thRow);
429                HtmlTree td = new HtmlTree(HtmlTag.TD);
430                td.addStyle(HtmlStyle.colLast);
431                List<? extends DocTree> deprTrees = utils.getBlockTags(member, DocTree.Kind.DEPRECATED);
432                if (!deprTrees.isEmpty()) {
433                    writer.addInlineDeprecatedComment(member, deprTrees.get(0), td);
434                }
435                tr.addContent(td);
436                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
437                altColor = !altColor;
438                tbody.addContent(tr);
439            }
440            table.addContent(tbody);
441            Content li = HtmlTree.LI(HtmlStyle.blockList, table);
442            Content ul = HtmlTree.UL(HtmlStyle.blockList, li);
443            contentTree.addContent(ul);
444        }
445    }
446
447    /**
448     * Add use information to the documentation tree.
449     *
450     * @param mems list of program elements for which the use information will be added
451     * @param heading the section heading
452     * @param tableSummary the summary for the use table
453     * @param contentTree the content tree to which the use information will be added
454     */
455    protected void addUseInfo(List<? extends Element> mems,
456            Content heading, String tableSummary, Content contentTree) {
457        if (mems == null || mems.isEmpty()) {
458            return;
459        }
460        List<? extends Element> members = mems;
461        boolean printedUseTableHeader = false;
462        if (members.size() > 0) {
463            Content caption = writer.getTableCaption(heading);
464            Content table = (configuration.isOutputHtml5())
465                    ? HtmlTree.TABLE(HtmlStyle.useSummary, caption)
466                    : HtmlTree.TABLE(HtmlStyle.useSummary, tableSummary, caption);
467            Content tbody = new HtmlTree(HtmlTag.TBODY);
468            boolean altColor = true;
469            for (Element element : members) {
470                TypeElement te = utils.getEnclosingTypeElement(element);
471                if (!printedUseTableHeader) {
472                    table.addContent(writer.getSummaryTableHeader(
473                            this.getSummaryTableHeader(element), "col"));
474                    printedUseTableHeader = true;
475                }
476                HtmlTree tr = new HtmlTree(HtmlTag.TR);
477                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
478                altColor = !altColor;
479                HtmlTree tdFirst = new HtmlTree(HtmlTag.TD);
480                tdFirst.addStyle(HtmlStyle.colFirst);
481                writer.addSummaryType(this, element, tdFirst);
482                tr.addContent(tdFirst);
483                HtmlTree thType = new HtmlTree(HtmlTag.TH);
484                thType.addStyle(HtmlStyle.colSecond);
485                thType.addAttr(HtmlAttr.SCOPE, "row");
486                if (te != null
487                        && !utils.isConstructor(element)
488                        && !utils.isClass(element)
489                        && !utils.isInterface(element)
490                        && !utils.isAnnotationType(element)) {
491                    HtmlTree name = new HtmlTree(HtmlTag.SPAN);
492                    name.addStyle(HtmlStyle.typeNameLabel);
493                    name.addContent(name(te) + ".");
494                    thType.addContent(name);
495                }
496                addSummaryLink(utils.isClass(element) || utils.isInterface(element)
497                        ? LinkInfoImpl.Kind.CLASS_USE
498                        : LinkInfoImpl.Kind.MEMBER,
499                        te, element, thType);
500                tr.addContent(thType);
501                HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
502                tdDesc.addStyle(HtmlStyle.colLast);
503                writer.addSummaryLinkComment(this, element, tdDesc);
504                tr.addContent(tdDesc);
505                tbody.addContent(tr);
506            }
507            table.addContent(tbody);
508            contentTree.addContent(table);
509        }
510    }
511
512    /**
513     * Add the navigation detail link.
514     *
515     * @param members the members to be linked
516     * @param liNav the content tree to which the navigation detail link will be added
517     */
518    protected void addNavDetailLink(SortedSet<Element> members, Content liNav) {
519        addNavDetailLink(!members.isEmpty(), liNav);
520    }
521
522    /**
523     * Add the navigation summary link.
524     *
525     * @param members members to be linked
526     * @param visibleMemberMap the visible inherited members map
527     * @param liNav the content tree to which the navigation summary link will be added
528     */
529    protected void addNavSummaryLink(SortedSet<? extends Element> members,
530            VisibleMemberMap visibleMemberMap, Content liNav) {
531        if (!members.isEmpty()) {
532            liNav.addContent(getNavSummaryLink(null, true));
533            return;
534        }
535
536        TypeElement superClass = utils.getSuperClass(typeElement);
537        while (superClass != null) {
538            if (visibleMemberMap.hasMembersFor(superClass)) {
539                liNav.addContent(getNavSummaryLink(superClass, true));
540                return;
541            }
542            superClass = utils.getSuperClass(superClass);
543        }
544        liNav.addContent(getNavSummaryLink(null, false));
545    }
546
547    protected void serialWarning(Element e, String key, String a1, String a2) {
548        if (configuration.serialwarn) {
549            configuration.messages.warning(e, key, a1, a2);
550        }
551    }
552
553    /**
554     * Add the member summary for the given class.
555     *
556     * @param tElement the class that is being documented
557     * @param member the member being documented
558     * @param firstSentenceTags the first sentence tags to be added to the summary
559     * @param tableContents the list of contents to which the documentation will be added
560     * @param counter the counter for determining id and style for the table row
561     */
562    public void addMemberSummary(TypeElement tElement, Element member,
563            List<? extends DocTree> firstSentenceTags, List<Content> tableContents, int counter) {
564        HtmlTree tdSummaryType = new HtmlTree(HtmlTag.TD);
565        tdSummaryType.addStyle(HtmlStyle.colFirst);
566        writer.addSummaryType(this, member, tdSummaryType);
567        HtmlTree tr = HtmlTree.TR(tdSummaryType);
568        HtmlTree thSummaryLink = new HtmlTree(HtmlTag.TH);
569        setSummaryColumnStyleAndScope(thSummaryLink);
570        addSummaryLink(tElement, member, thSummaryLink);
571        tr.addContent(thSummaryLink);
572        HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
573        tdDesc.addStyle(HtmlStyle.colLast);
574        writer.addSummaryLinkComment(this, member, firstSentenceTags, tdDesc);
575        tr.addContent(tdDesc);
576        if (utils.isMethod(member) && !utils.isAnnotationType(member)) {
577            int methodType = utils.isStatic(member) ? MethodTypes.STATIC.value() :
578                    MethodTypes.INSTANCE.value();
579            if (utils.isInterface(member.getEnclosingElement())) {
580                methodType = utils.isAbstract(member)
581                        ? methodType | MethodTypes.ABSTRACT.value()
582                        : methodType | MethodTypes.DEFAULT.value();
583            } else {
584                methodType = utils.isAbstract(member)
585                        ? methodType | MethodTypes.ABSTRACT.value()
586                        : methodType | MethodTypes.CONCRETE.value();
587            }
588            if (utils.isDeprecated(member) || utils.isDeprecated(typeElement)) {
589                methodType = methodType | MethodTypes.DEPRECATED.value();
590            }
591            methodTypesOr = methodTypesOr | methodType;
592            String tableId = "i" + counter;
593            typeMap.put(tableId, methodType);
594            tr.addAttr(HtmlAttr.ID, tableId);
595        }
596        if (counter%2 == 0)
597            tr.addStyle(HtmlStyle.altColor);
598        else
599            tr.addStyle(HtmlStyle.rowColor);
600        tableContents.add(tr);
601    }
602
603    /**
604     * Generate the method types set and return true if the method summary table
605     * needs to show tabs.
606     *
607     * @return true if the table should show tabs
608     */
609    public boolean showTabs() {
610        int value;
611        for (MethodTypes type : EnumSet.allOf(MethodTypes.class)) {
612            value = type.value();
613            if ((value & methodTypesOr) == value) {
614                methodTypes.add(type);
615            }
616        }
617        boolean showTabs = methodTypes.size() > 1;
618        if (showTabs) {
619            methodTypes.add(MethodTypes.ALL);
620        }
621        return showTabs;
622    }
623
624    /**
625     * Set the style and scope attribute for the summary column.
626     *
627     * @param thTree the column for which the style and scope attribute will be set
628     */
629    public void setSummaryColumnStyleAndScope(HtmlTree thTree) {
630        thTree.addStyle(HtmlStyle.colSecond);
631        thTree.addAttr(HtmlAttr.SCOPE, "row");
632    }
633
634    /**
635     * Add inherited member summary for the given class and member.
636     *
637     * @param tElement the class the inherited member belongs to
638     * @param nestedClass the inherited member that is summarized
639     * @param isFirst true if this is the first member in the list
640     * @param isLast true if this is the last member in the list
641     * @param linksTree the content tree to which the summary will be added
642     */
643    public void addInheritedMemberSummary(TypeElement tElement,
644            Element nestedClass, boolean isFirst, boolean isLast,
645            Content linksTree) {
646        writer.addInheritedMemberSummary(this, tElement, nestedClass, isFirst,
647                linksTree);
648    }
649
650    /**
651     * Get the inherited summary header for the given class.
652     *
653     * @param tElement the class the inherited member belongs to
654     * @return a content tree for the inherited summary header
655     */
656    public Content getInheritedSummaryHeader(TypeElement tElement) {
657        Content inheritedTree = writer.getMemberTreeHeader();
658        writer.addInheritedSummaryHeader(this, tElement, inheritedTree);
659        return inheritedTree;
660    }
661
662    /**
663     * Get the inherited summary links tree.
664     *
665     * @return a content tree for the inherited summary links
666     */
667    public Content getInheritedSummaryLinksTree() {
668        return new HtmlTree(HtmlTag.CODE);
669    }
670
671    /**
672     * Get the summary table tree for the given class.
673     *
674     * @param tElement the class for which the summary table is generated
675     * @param tableContents list of contents to be displayed in the summary table
676     * @return a content tree for the summary table
677     */
678    public Content getSummaryTableTree(TypeElement tElement, List<Content> tableContents) {
679        return writer.getSummaryTableTree(this, tElement, tableContents, showTabs());
680    }
681
682    /**
683     * Get the member tree to be documented.
684     *
685     * @param memberTree the content tree of member to be documented
686     * @return a content tree that will be added to the class documentation
687     */
688    public Content getMemberTree(Content memberTree) {
689        return writer.getMemberTree(memberTree);
690    }
691
692    /**
693     * Get the member tree to be documented.
694     *
695     * @param memberTree the content tree of member to be documented
696     * @param isLastContent true if the content to be added is the last content
697     * @return a content tree that will be added to the class documentation
698     */
699    public Content getMemberTree(Content memberTree, boolean isLastContent) {
700        if (isLastContent)
701            return HtmlTree.UL(HtmlStyle.blockListLast, memberTree);
702        else
703            return HtmlTree.UL(HtmlStyle.blockList, memberTree);
704    }
705}
706