src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MemberSummaryBuilder.java

Sun, 24 Feb 2013 11:36:58 -0800

author
jjg
date
Sun, 24 Feb 2013 11:36:58 -0800
changeset 1606
ccbe7ffdd867
parent 1417
522a1ee72340
child 1866
26437287529d
permissions
-rw-r--r--

7112427: The doclet needs to be able to generate JavaFX documentation.
Reviewed-by: jjg
Contributed-by: jan.valenta@oracle.com

     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 the optional members.
   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 buildAnnotationTypeOptionalMemberSummary(XMLNode node, Content memberSummaryTree) {
   222         MemberSummaryWriter writer =
   223                 memberSummaryWriters[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL];
   224         VisibleMemberMap visibleMemberMap =
   225                 visibleMemberMaps[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL];
   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 buildAnnotationTypeRequiredMemberSummary(XMLNode node, Content memberSummaryTree) {
   236         MemberSummaryWriter writer =
   237                 memberSummaryWriters[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_REQUIRED];
   238         VisibleMemberMap visibleMemberMap =
   239                 visibleMemberMaps[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_REQUIRED];
   240         addSummary(writer, visibleMemberMap, false, memberSummaryTree);
   241     }
   243     /**
   244      * Build the summary for the fields.
   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 buildFieldsSummary(XMLNode node, Content memberSummaryTree) {
   250         MemberSummaryWriter writer =
   251                 memberSummaryWriters[VisibleMemberMap.FIELDS];
   252         VisibleMemberMap visibleMemberMap =
   253                 visibleMemberMaps[VisibleMemberMap.FIELDS];
   254         addSummary(writer, visibleMemberMap, true, memberSummaryTree);
   255     }
   257     /**
   258      * Build the summary for the fields.
   259      */
   260     public void buildPropertiesSummary(XMLNode node, Content memberSummaryTree) {
   261         MemberSummaryWriter writer =
   262                 memberSummaryWriters[VisibleMemberMap.PROPERTIES];
   263         VisibleMemberMap visibleMemberMap =
   264                 visibleMemberMaps[VisibleMemberMap.PROPERTIES];
   265         addSummary(writer, visibleMemberMap, true, memberSummaryTree);
   266     }
   268     /**
   269      * Build the summary for the nested classes.
   270      *
   271      * @param node the XML element that specifies which components to document
   272      * @param memberSummaryTree the content tree to which the documentation will be added
   273      */
   274     public void buildNestedClassesSummary(XMLNode node, Content memberSummaryTree) {
   275         MemberSummaryWriter writer =
   276                 memberSummaryWriters[VisibleMemberMap.INNERCLASSES];
   277         VisibleMemberMap visibleMemberMap =
   278                 visibleMemberMaps[VisibleMemberMap.INNERCLASSES];
   279         addSummary(writer, visibleMemberMap, true, memberSummaryTree);
   280     }
   282     /**
   283      * Build the method summary.
   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 buildMethodsSummary(XMLNode node, Content memberSummaryTree) {
   289         MemberSummaryWriter writer =
   290                 memberSummaryWriters[VisibleMemberMap.METHODS];
   291         VisibleMemberMap visibleMemberMap =
   292                 visibleMemberMaps[VisibleMemberMap.METHODS];
   293         addSummary(writer, visibleMemberMap, true, memberSummaryTree);
   294     }
   296     /**
   297      * Build the constructor 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 buildConstructorsSummary(XMLNode node, Content memberSummaryTree) {
   303         MemberSummaryWriter writer =
   304                 memberSummaryWriters[VisibleMemberMap.CONSTRUCTORS];
   305         VisibleMemberMap visibleMemberMap =
   306                 visibleMemberMaps[VisibleMemberMap.CONSTRUCTORS];
   307         addSummary(writer, visibleMemberMap, false, memberSummaryTree);
   308     }
   310     /**
   311      * Build the member summary for the given members.
   312      *
   313      * @param writer the summary writer to write the output.
   314      * @param visibleMemberMap the given members to summarize.
   315      * @param summaryTreeList list of content trees to which the documentation will be added
   316      */
   317     private void buildSummary(MemberSummaryWriter writer,
   318             VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
   319         List<ProgramElementDoc> members = new ArrayList<ProgramElementDoc>(visibleMemberMap.getLeafClassMembers(
   320                 configuration));
   321         if (members.size() > 0) {
   322             Collections.sort(members);
   323             List<Content> tableContents = new LinkedList<Content>();
   324             for (int i = 0; i < members.size(); i++) {
   325                 ProgramElementDoc member = members.get(i);
   326                 final ProgramElementDoc propertyDoc =
   327                             visibleMemberMap.getPropertyMemberDoc(member);
   328                 if (propertyDoc != null) {
   329                     processProperty(visibleMemberMap, member, propertyDoc);
   330                 }
   331                 Tag[] firstSentenceTags = member.firstSentenceTags();
   332                 if (member instanceof MethodDoc && firstSentenceTags.length == 0) {
   333                     //Inherit comments from overriden or implemented method if
   334                     //necessary.
   335                     DocFinder.Output inheritedDoc =
   336                             DocFinder.search(new DocFinder.Input((MethodDoc) member));
   337                     if (inheritedDoc.holder != null
   338                             && inheritedDoc.holder.firstSentenceTags().length > 0) {
   339                         firstSentenceTags = inheritedDoc.holder.firstSentenceTags();
   340                     }
   341                 }
   342                 writer.addMemberSummary(classDoc, member, firstSentenceTags,
   343                         tableContents, i);
   344             }
   345             summaryTreeList.add(writer.getSummaryTableTree(classDoc, tableContents));
   346         }
   347     }
   349     /**
   350      * Process the property method, property setter and/or property getter
   351      * comment text so that it contains the documentation from
   352      * the property field. The method adds the leading sentence,
   353      * copied documentation including the defaultValue tag and
   354      * the see tags if the appropriate property getter and setter are
   355      * available.
   356      *
   357      * @param visibleMemberMap the members information.
   358      * @param member the member which is to be augmented.
   359      * @param propertyDoc the original property documentation.
   360      */
   361     private void processProperty(VisibleMemberMap visibleMemberMap,
   362                                  ProgramElementDoc member,
   363                                  ProgramElementDoc propertyDoc) {
   364         StringBuilder commentTextBuilder = new StringBuilder();
   365         final boolean isSetter = isSetter(member);
   366         final boolean isGetter = isGetter(member);
   367         if (isGetter || isSetter) {
   368             //add "[GS]ets the value of the property PROPERTY_NAME."
   369             if (isSetter) {
   370                 commentTextBuilder.append(
   371                         MessageFormat.format(
   372                                 configuration.getText("doclet.PropertySetterWithName"),
   373                                 Util.propertyNameFromMethodName(member.name())));
   374             }
   375             if (isGetter) {
   376                 commentTextBuilder.append(
   377                         MessageFormat.format(
   378                                 configuration.getText("doclet.PropertyGetterWithName"),
   379                                 Util.propertyNameFromMethodName(member.name())));
   380             }
   381             if (propertyDoc.commentText() != null
   382                         && !propertyDoc.commentText().isEmpty()) {
   383                 commentTextBuilder.append(" \n @propertyDescription ");
   384             }
   385         }
   386         commentTextBuilder.append(propertyDoc.commentText());
   388         Tag[] tags = propertyDoc.tags("@defaultValue");
   389         if (tags != null) {
   390             for (Tag tag: tags) {
   391                 commentTextBuilder.append("\n")
   392                                   .append(tag.name())
   393                                   .append(" ")
   394                                   .append(tag.text());
   395             }
   396         }
   398         //add @see tags
   399         if (!isGetter && !isSetter) {
   400             MethodDoc getter = (MethodDoc) visibleMemberMap.getGetterForProperty(member);
   401             MethodDoc setter = (MethodDoc) visibleMemberMap.getSetterForProperty(member);
   403             if ((null != getter)
   404                     && (commentTextBuilder.indexOf("@see #" + getter.name()) == -1)) {
   405                 commentTextBuilder.append("\n @see #")
   406                                   .append(getter.name())
   407                                   .append("() ");
   408             }
   410             if ((null != setter)
   411                     && (commentTextBuilder.indexOf("@see #" + setter.name()) == -1)) {
   412                 String typeName = setter.parameters()[0].typeName();
   413                 // Removal of type parameters and package information.
   414                 typeName = typeName.split("<")[0];
   415                 if (typeName.contains(".")) {
   416                     typeName = typeName.substring(typeName.lastIndexOf(".") + 1);
   417                 }
   418                 commentTextBuilder.append("\n @see #").append(setter.name());
   420                 if (setter.parameters()[0].type().asTypeVariable() == null) {
   421                     commentTextBuilder.append("(").append(typeName).append(")");
   422                 }
   423                 commentTextBuilder.append(" \n");
   424             }
   425         }
   426         member.setRawCommentText(commentTextBuilder.toString());
   427     }
   428     /**
   429      * Test whether the method is a getter.
   430      * @param ped property method documentation. Needs to be either property
   431      * method, property getter, or property setter.
   432      * @return true if the given documentation belongs to a getter.
   433      */
   434     private boolean isGetter(ProgramElementDoc ped) {
   435         final String pedName = ped.name();
   436         return pedName.startsWith("get") || pedName.startsWith("is");
   437     }
   439     /**
   440      * Test whether the method is a setter.
   441      * @param ped property method documentation. Needs to be either property
   442      * method, property getter, or property setter.
   443      * @return true if the given documentation belongs to a setter.
   444      */
   445     private boolean isSetter(ProgramElementDoc ped) {
   446         return ped.name().startsWith("set");
   447     }
   449     /**
   450      * Build the inherited member summary for the given methods.
   451      *
   452      * @param writer the writer for this member summary.
   453      * @param visibleMemberMap the map for the members to document.
   454      * @param summaryTreeList list of content trees to which the documentation will be added
   455      */
   456     private void buildInheritedSummary(MemberSummaryWriter writer,
   457             VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
   458         for (Iterator<ClassDoc> iter = visibleMemberMap.getVisibleClassesList().iterator();
   459                 iter.hasNext();) {
   460             ClassDoc inhclass = iter.next();
   461             if (! (inhclass.isPublic() ||
   462                     Util.isLinkable(inhclass, configuration))) {
   463                 continue;
   464             }
   465             if (inhclass == classDoc) {
   466                 continue;
   467             }
   468             List<ProgramElementDoc> inhmembers = visibleMemberMap.getMembersFor(inhclass);
   469             if (inhmembers.size() > 0) {
   470                 Collections.sort(inhmembers);
   471                 Content inheritedTree = writer.getInheritedSummaryHeader(inhclass);
   472                 Content linksTree = writer.getInheritedSummaryLinksTree();
   473                 for (int j = 0; j < inhmembers.size(); ++j) {
   474                     writer.addInheritedMemberSummary(
   475                             inhclass.isPackagePrivate() &&
   476                             ! Util.isLinkable(inhclass, configuration) ?
   477                             classDoc : inhclass,
   478                             inhmembers.get(j),
   479                             j == 0,
   480                             j == inhmembers.size() - 1, linksTree);
   481                 }
   482                 inheritedTree.addContent(linksTree);
   483                 summaryTreeList.add(writer.getMemberTree(inheritedTree));
   484             }
   485         }
   486     }
   488     /**
   489      * Add the summary for the documentation.
   490      *
   491      * @param writer the writer for this member summary.
   492      * @param visibleMemberMap the map for the members to document.
   493      * @param showInheritedSummary true if inherited summary should be documented
   494      * @param memberSummaryTree the content tree to which the documentation will be added
   495      */
   496     private void addSummary(MemberSummaryWriter writer,
   497             VisibleMemberMap visibleMemberMap, boolean showInheritedSummary,
   498             Content memberSummaryTree) {
   499         LinkedList<Content> summaryTreeList = new LinkedList<Content>();
   500         buildSummary(writer, visibleMemberMap, summaryTreeList);
   501         if (showInheritedSummary)
   502             buildInheritedSummary(writer, visibleMemberMap, summaryTreeList);
   503         if (!summaryTreeList.isEmpty()) {
   504             Content memberTree = writer.getMemberSummaryHeader(
   505                     classDoc, memberSummaryTree);
   506             for (int i = 0; i < summaryTreeList.size(); i++) {
   507                 memberTree.addContent(summaryTreeList.get(i));
   508             }
   509             memberSummaryTree.addContent(writer.getMemberTree(memberTree));
   510         }
   511     }
   512 }

mercurial