src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java
changeset 49879 601277b1d582
parent 48257 125716343184
child 52644 43efb4ca6d6c
equal deleted inserted replaced
49878:2422d4e027b0 49879:601277b1d582
     1 /*
     1 /*
     2  * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    25 
    25 
    26 package jdk.javadoc.internal.doclets.toolkit.builders;
    26 package jdk.javadoc.internal.doclets.toolkit.builders;
    27 
    27 
    28 import java.text.MessageFormat;
    28 import java.text.MessageFormat;
    29 import java.util.*;
    29 import java.util.*;
       
    30 import java.util.stream.Collectors;
    30 
    31 
    31 import javax.lang.model.element.Element;
    32 import javax.lang.model.element.Element;
    32 import javax.lang.model.element.ExecutableElement;
    33 import javax.lang.model.element.ExecutableElement;
    33 import javax.lang.model.element.TypeElement;
    34 import javax.lang.model.element.TypeElement;
    34 import javax.lang.model.element.VariableElement;
    35 import javax.lang.model.element.VariableElement;
    35 
    36 import javax.lang.model.util.ElementFilter;
       
    37 
       
    38 import com.sun.source.doctree.DocCommentTree;
    36 import com.sun.source.doctree.DocTree;
    39 import com.sun.source.doctree.DocTree;
    37 import com.sun.source.doctree.DocTree.Kind;
    40 import com.sun.source.doctree.DocTree.Kind;
    38 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
    41 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
    39 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
    42 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
    40 import jdk.javadoc.internal.doclets.toolkit.Content;
    43 import jdk.javadoc.internal.doclets.toolkit.Content;
    41 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
    44 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
    42 import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
    45 import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
    43 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
    46 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
    44 import jdk.javadoc.internal.doclets.toolkit.util.DocFinder;
    47 import jdk.javadoc.internal.doclets.toolkit.util.DocFinder;
    45 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
    48 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
    46 import jdk.javadoc.internal.doclets.toolkit.CommentUtils;
    49 import jdk.javadoc.internal.doclets.toolkit.CommentUtils;
       
    50 
       
    51 import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
    47 
    52 
    48 /**
    53 /**
    49  * Builds the member summary.
    54  * Builds the member summary.
    50  * There are two anonymous subtype variants of this builder, created
    55  * There are two anonymous subtype variants of this builder, created
    51  * in the {@link #getInstance} methods. One is for general types;
    56  * in the {@link #getInstance} methods. One is for general types;
    67     private final Comparator<Element> comparator;
    72     private final Comparator<Element> comparator;
    68 
    73 
    69     /**
    74     /**
    70      * The member summary writers for the given class.
    75      * The member summary writers for the given class.
    71      */
    76      */
    72     private final EnumMap<VisibleMemberMap.Kind, MemberSummaryWriter> memberSummaryWriters;
    77     private final EnumMap<VisibleMemberTable.Kind, MemberSummaryWriter> memberSummaryWriters;
    73 
    78 
    74     /**
    79     final PropertyHelper pHelper;
    75      * The type being documented.
       
    76      */
       
    77     protected final TypeElement typeElement;
       
    78 
    80 
    79     /**
    81     /**
    80      * Construct a new MemberSummaryBuilder.
    82      * Construct a new MemberSummaryBuilder.
    81      *
    83      *
    82      * @param context       the build context.
    84      * @param context       the build context.
    83      * @param typeElement   the type element.
    85      * @param typeElement   the type element.
    84      */
    86      */
    85     private MemberSummaryBuilder(Context context, TypeElement typeElement) {
    87     private MemberSummaryBuilder(Context context, TypeElement typeElement) {
    86         super(context);
    88         super(context, typeElement);
    87         this.typeElement = typeElement;
    89         memberSummaryWriters = new EnumMap<>(VisibleMemberTable.Kind.class);
    88         memberSummaryWriters = new EnumMap<>(VisibleMemberMap.Kind.class);
    90         comparator = utils.makeIndexUseComparator();
    89 
    91         pHelper = new PropertyHelper(this);
    90         comparator = utils.makeGeneralPurposeComparator();
       
    91     }
    92     }
    92 
    93 
    93     /**
    94     /**
    94      * Construct a new MemberSummaryBuilder for a general type.
    95      * Construct a new MemberSummaryBuilder for a general type.
    95      *
    96      *
   111                 buildMethodsSummary(contentTree);
   112                 buildMethodsSummary(contentTree);
   112             }
   113             }
   113 
   114 
   114             @Override
   115             @Override
   115             public boolean hasMembersToDocument() {
   116             public boolean hasMembersToDocument() {
   116                 for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
   117                 return visibleMemberTable.hasVisibleMembers();
   117                     VisibleMemberMap members = getVisibleMemberMap(kind);
       
   118                     if (!members.noVisibleMembers()) {
       
   119                         return true;
       
   120                     }
       
   121                 }
       
   122                 return false;
       
   123             }
   118             }
   124         };
   119         };
   125         WriterFactory wf = context.configuration.getWriterFactory();
   120         WriterFactory wf = context.configuration.getWriterFactory();
   126         for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
   121         for (VisibleMemberTable.Kind kind : VisibleMemberTable.Kind.values()) {
   127             MemberSummaryWriter msw = builder.getVisibleMemberMap(kind).noVisibleMembers()
   122             MemberSummaryWriter msw = builder.getVisibleMemberTable().hasVisibleMembers(kind)
   128                     ? null
   123                     ? wf.getMemberSummaryWriter(classWriter, kind)
   129                     : wf.getMemberSummaryWriter(classWriter, kind);
   124                     : null;
   130             builder.memberSummaryWriters.put(kind, msw);
   125             builder.memberSummaryWriters.put(kind, msw);
   131         }
   126         }
   132         return builder;
   127         return builder;
   133     }
   128     }
   134 
   129 
   155             public boolean hasMembersToDocument() {
   150             public boolean hasMembersToDocument() {
   156                 return !utils.getAnnotationMembers(typeElement).isEmpty();
   151                 return !utils.getAnnotationMembers(typeElement).isEmpty();
   157             }
   152             }
   158         };
   153         };
   159         WriterFactory wf = context.configuration.getWriterFactory();
   154         WriterFactory wf = context.configuration.getWriterFactory();
   160         for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
   155         for (VisibleMemberTable.Kind kind : VisibleMemberTable.Kind.values()) {
   161             MemberSummaryWriter msw = builder.getVisibleMemberMap(kind).noVisibleMembers()
   156             MemberSummaryWriter msw = builder.getVisibleMemberTable().hasVisibleMembers(kind)
   162                     ? null
   157                     ? wf.getMemberSummaryWriter(annotationTypeWriter, kind)
   163                     : wf.getMemberSummaryWriter(annotationTypeWriter, kind);
   158                     : null;
   164             builder.memberSummaryWriters.put(kind, msw);
   159             builder.memberSummaryWriters.put(kind, msw);
   165         }
   160         }
   166         return builder;
   161         return builder;
   167     }
   162     }
   168 
   163 
   169     /**
   164     /**
   170      * Return the specified visible member map.
   165      * Return the specified visible member map.
   171      *
   166      *
   172      * @param kind the kind of visible member map to return.
       
   173      * @return the specified visible member map.
   167      * @return the specified visible member map.
   174      * @throws ArrayIndexOutOfBoundsException when the type is invalid.
   168      * @throws ArrayIndexOutOfBoundsException when the type is invalid.
   175      * @see VisibleMemberMap
   169      * @see VisibleMemberTable
   176      */
   170      */
   177     public VisibleMemberMap getVisibleMemberMap(VisibleMemberMap.Kind kind) {
   171     public VisibleMemberTable getVisibleMemberTable() {
   178         return configuration.getVisibleMemberMap(typeElement, kind);
   172         return visibleMemberTable;
   179     }
   173     }
   180 
   174 
   181     /**.
   175     /**.
   182      * Return the specified member summary writer.
   176      * Return the specified member summary writer.
   183      *
   177      *
   184      * @param kind the kind of member summary writer to return.
   178      * @param kind the kind of member summary writer to return.
   185      * @return the specified member summary writer.
   179      * @return the specified member summary writer.
   186      * @throws ArrayIndexOutOfBoundsException when the type is invalid.
   180      * @throws ArrayIndexOutOfBoundsException when the type is invalid.
   187      * @see VisibleMemberMap
   181      * @see VisibleMemberTable
   188      */
   182      */
   189     public MemberSummaryWriter getMemberSummaryWriter(VisibleMemberMap.Kind kind) {
   183     public MemberSummaryWriter getMemberSummaryWriter(VisibleMemberTable.Kind kind) {
   190         return memberSummaryWriters.get(kind);
   184         return memberSummaryWriters.get(kind);
   191     }
   185     }
   192 
   186 
   193     /**
   187     /**
   194      * Returns a list of methods that will be documented for the given class.
   188      * Returns a list of methods that will be documented for the given class.
   195      * This information can be used for doclet specific documentation
   189      * This information can be used for doclet specific documentation
   196      * generation.
   190      * generation.
   197      *
   191      *
   198      * @param kind the kind of elements to return.
   192      * @param kind the kind of elements to return.
   199      * @return a list of methods that will be documented.
   193      * @return a list of methods that will be documented.
   200      * @see VisibleMemberMap
   194      * @see VisibleMemberTable
   201      */
   195      */
   202     public SortedSet<Element> members(VisibleMemberMap.Kind kind) {
   196     public SortedSet<Element> members(VisibleMemberTable.Kind kind) {
   203         TreeSet<Element> out = new TreeSet<>(comparator);
   197         TreeSet<Element> out = new TreeSet<>(comparator);
   204         out.addAll(getVisibleMemberMap(kind).getLeafMembers());
   198         out.addAll(getVisibleMembers(kind));
   205         return out;
   199         return out;
   206     }
   200     }
   207 
   201 
   208     /**
   202     /**
       
   203      * Returns true if there are members of the given kind, false otherwise.
       
   204      * @param kind
       
   205      * @return true if there are members of the given kind, false otherwise
       
   206      */
       
   207     public boolean hasMembers(VisibleMemberTable.Kind kind) {
       
   208         return !getVisibleMembers(kind).isEmpty();
       
   209     }
       
   210 
       
   211     /**
   209      * Build the summary for the enum constants.
   212      * Build the summary for the enum constants.
   210      *
   213      *
   211      * @param memberSummaryTree the content tree to which the documentation will be added
   214      * @param memberSummaryTree the content tree to which the documentation will be added
   212      */
   215      */
   213     protected void buildEnumConstantsSummary(Content memberSummaryTree) {
   216     protected void buildEnumConstantsSummary(Content memberSummaryTree) {
   214         MemberSummaryWriter writer =
   217         MemberSummaryWriter writer = memberSummaryWriters.get(ENUM_CONSTANTS);
   215                 memberSummaryWriters.get(VisibleMemberMap.Kind.ENUM_CONSTANTS);
   218         addSummary(writer, ENUM_CONSTANTS, false, memberSummaryTree);
   216         VisibleMemberMap visibleMemberMap =
       
   217                 getVisibleMemberMap(VisibleMemberMap.Kind.ENUM_CONSTANTS);
       
   218         addSummary(writer, visibleMemberMap, false, memberSummaryTree);
       
   219     }
   219     }
   220 
   220 
   221     /**
   221     /**
   222      * Build the summary for fields.
   222      * Build the summary for fields.
   223      *
   223      *
   224      * @param memberSummaryTree the content tree to which the documentation will be added
   224      * @param memberSummaryTree the content tree to which the documentation will be added
   225      */
   225      */
   226     protected void buildAnnotationTypeFieldsSummary(Content memberSummaryTree) {
   226     protected void buildAnnotationTypeFieldsSummary(Content memberSummaryTree) {
   227         MemberSummaryWriter writer =
   227         MemberSummaryWriter writer = memberSummaryWriters.get(ANNOTATION_TYPE_FIELDS);
   228                 memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS);
   228         addSummary(writer, ANNOTATION_TYPE_FIELDS, false, memberSummaryTree);
   229         VisibleMemberMap visibleMemberMap =
       
   230                 getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS);
       
   231         addSummary(writer, visibleMemberMap, false, memberSummaryTree);
       
   232     }
   229     }
   233 
   230 
   234     /**
   231     /**
   235      * Build the summary for the optional members.
   232      * Build the summary for the optional members.
   236      *
   233      *
   237      * @param memberSummaryTree the content tree to which the documentation will be added
   234      * @param memberSummaryTree the content tree to which the documentation will be added
   238      */
   235      */
   239     protected void buildAnnotationTypeOptionalMemberSummary(Content memberSummaryTree) {
   236     protected void buildAnnotationTypeOptionalMemberSummary(Content memberSummaryTree) {
   240         MemberSummaryWriter writer =
   237         MemberSummaryWriter writer = memberSummaryWriters.get(ANNOTATION_TYPE_MEMBER_OPTIONAL);
   241                 memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
   238         addSummary(writer, ANNOTATION_TYPE_MEMBER_OPTIONAL, false, memberSummaryTree);
   242         VisibleMemberMap visibleMemberMap =
       
   243                 getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
       
   244         addSummary(writer, visibleMemberMap, false, memberSummaryTree);
       
   245     }
   239     }
   246 
   240 
   247     /**
   241     /**
   248      * Build the summary for the optional members.
   242      * Build the summary for the optional members.
   249      *
   243      *
   250      * @param memberSummaryTree the content tree to which the documentation will be added
   244      * @param memberSummaryTree the content tree to which the documentation will be added
   251      */
   245      */
   252     protected void buildAnnotationTypeRequiredMemberSummary(Content memberSummaryTree) {
   246     protected void buildAnnotationTypeRequiredMemberSummary(Content memberSummaryTree) {
   253         MemberSummaryWriter writer =
   247         MemberSummaryWriter writer = memberSummaryWriters.get(ANNOTATION_TYPE_MEMBER_REQUIRED);
   254                 memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED);
   248         addSummary(writer, ANNOTATION_TYPE_MEMBER_REQUIRED, false, memberSummaryTree);
   255         VisibleMemberMap visibleMemberMap =
       
   256                 getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED);
       
   257         addSummary(writer, visibleMemberMap, false, memberSummaryTree);
       
   258     }
   249     }
   259 
   250 
   260     /**
   251     /**
   261      * Build the summary for the fields.
   252      * Build the summary for the fields.
   262      *
   253      *
   263      * @param memberSummaryTree the content tree to which the documentation will be added
   254      * @param memberSummaryTree the content tree to which the documentation will be added
   264      */
   255      */
   265     protected void buildFieldsSummary(Content memberSummaryTree) {
   256     protected void buildFieldsSummary(Content memberSummaryTree) {
   266         MemberSummaryWriter writer =
   257         MemberSummaryWriter writer = memberSummaryWriters.get(FIELDS);
   267                 memberSummaryWriters.get(VisibleMemberMap.Kind.FIELDS);
   258         addSummary(writer, FIELDS, true, memberSummaryTree);
   268         VisibleMemberMap visibleMemberMap =
       
   269                 getVisibleMemberMap(VisibleMemberMap.Kind.FIELDS);
       
   270         addSummary(writer, visibleMemberMap, true, memberSummaryTree);
       
   271     }
   259     }
   272 
   260 
   273     /**
   261     /**
   274      * Build the summary for the fields.
   262      * Build the summary for the fields.
   275      *
   263      *
   276      * @param memberSummaryTree the content tree to which the documentation will be added
   264      * @param memberSummaryTree the content tree to which the documentation will be added
   277      */
   265      */
   278     protected void buildPropertiesSummary(Content memberSummaryTree) {
   266     protected void buildPropertiesSummary(Content memberSummaryTree) {
   279         MemberSummaryWriter writer =
   267         MemberSummaryWriter writer = memberSummaryWriters.get(PROPERTIES);
   280                 memberSummaryWriters.get(VisibleMemberMap.Kind.PROPERTIES);
   268         addSummary(writer, PROPERTIES, true, memberSummaryTree);
   281         VisibleMemberMap visibleMemberMap =
       
   282                 getVisibleMemberMap(VisibleMemberMap.Kind.PROPERTIES);
       
   283         addSummary(writer, visibleMemberMap, true, memberSummaryTree);
       
   284     }
   269     }
   285 
   270 
   286     /**
   271     /**
   287      * Build the summary for the nested classes.
   272      * Build the summary for the nested classes.
   288      *
   273      *
   289      * @param memberSummaryTree the content tree to which the documentation will be added
   274      * @param memberSummaryTree the content tree to which the documentation will be added
   290      */
   275      */
   291     protected void buildNestedClassesSummary(Content memberSummaryTree) {
   276     protected void buildNestedClassesSummary(Content memberSummaryTree) {
   292         MemberSummaryWriter writer =
   277         MemberSummaryWriter writer = memberSummaryWriters.get(INNER_CLASSES);
   293                 memberSummaryWriters.get(VisibleMemberMap.Kind.INNER_CLASSES);
   278         addSummary(writer, INNER_CLASSES, true, memberSummaryTree);
   294         VisibleMemberMap visibleMemberMap =
       
   295                 getVisibleMemberMap(VisibleMemberMap.Kind.INNER_CLASSES);
       
   296         addSummary(writer, visibleMemberMap, true, memberSummaryTree);
       
   297     }
   279     }
   298 
   280 
   299     /**
   281     /**
   300      * Build the method summary.
   282      * Build the method summary.
   301      *
   283      *
   302      * @param memberSummaryTree the content tree to which the documentation will be added
   284      * @param memberSummaryTree the content tree to which the documentation will be added
   303      */
   285      */
   304     protected void buildMethodsSummary(Content memberSummaryTree) {
   286     protected void buildMethodsSummary(Content memberSummaryTree) {
   305         MemberSummaryWriter writer =
   287         MemberSummaryWriter writer = memberSummaryWriters.get(METHODS);
   306                 memberSummaryWriters.get(VisibleMemberMap.Kind.METHODS);
   288         addSummary(writer, METHODS, true, memberSummaryTree);
   307         VisibleMemberMap visibleMemberMap =
       
   308                getVisibleMemberMap(VisibleMemberMap.Kind.METHODS);
       
   309         addSummary(writer, visibleMemberMap, true, memberSummaryTree);
       
   310     }
   289     }
   311 
   290 
   312     /**
   291     /**
   313      * Build the constructor summary.
   292      * Build the constructor summary.
   314      *
   293      *
   315      * @param memberSummaryTree the content tree to which the documentation will be added
   294      * @param memberSummaryTree the content tree to which the documentation will be added
   316      */
   295      */
   317     protected void buildConstructorsSummary(Content memberSummaryTree) {
   296     protected void buildConstructorsSummary(Content memberSummaryTree) {
   318         MemberSummaryWriter writer =
   297         MemberSummaryWriter writer = memberSummaryWriters.get(CONSTRUCTORS);
   319                 memberSummaryWriters.get(VisibleMemberMap.Kind.CONSTRUCTORS);
   298         addSummary(writer, CONSTRUCTORS, false, memberSummaryTree);
   320         VisibleMemberMap visibleMemberMap =
       
   321                 getVisibleMemberMap(VisibleMemberMap.Kind.CONSTRUCTORS);
       
   322         addSummary(writer, visibleMemberMap, false, memberSummaryTree);
       
   323     }
   299     }
   324 
   300 
   325     /**
   301     /**
   326      * Build the member summary for the given members.
   302      * Build the member summary for the given members.
   327      *
   303      *
   328      * @param writer the summary writer to write the output.
   304      * @param writer the summary writer to write the output.
   329      * @param visibleMemberMap the given members to summarize.
   305      * @param kind the kind of  members to summarize.
   330      * @param summaryTreeList list of content trees to which the documentation will be added
   306      * @param summaryTreeList list of content trees to which the documentation will be added
   331      */
   307      */
   332     private void buildSummary(MemberSummaryWriter writer,
   308     private void buildSummary(MemberSummaryWriter writer,
   333             VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
   309             VisibleMemberTable.Kind kind, LinkedList<Content> summaryTreeList) {
   334         SortedSet<Element> members = asSortedSet(visibleMemberMap.getLeafMembers());
   310         SortedSet<? extends Element> members = asSortedSet(getVisibleMembers(kind));
   335         if (!members.isEmpty()) {
   311         if (!members.isEmpty()) {
   336             for (Element member : members) {
   312             for (Element member : members) {
   337                 final Element property = visibleMemberMap.getPropertyElement(member);
   313                 final Element property = pHelper.getPropertyElement(member);
   338                 if (property != null) {
   314                 if (property != null) {
   339                     processProperty(visibleMemberMap, member, property);
   315                     processProperty(member, property);
   340                 }
   316                 }
   341                 List<? extends DocTree> firstSentenceTags = utils.getFirstSentenceTrees(member);
   317                 List<? extends DocTree> firstSentenceTags = utils.getFirstSentenceTrees(member);
   342                 if (utils.isExecutableElement(member) && firstSentenceTags.isEmpty()) {
   318                 if (utils.isExecutableElement(member) && firstSentenceTags.isEmpty()) {
   343                     //Inherit comments from overriden or implemented method if
   319                     //Inherit comments from overriden or implemented method if
   344                     //necessary.
   320                     //necessary.
   365      * the property field. The method adds the leading sentence,
   341      * the property field. The method adds the leading sentence,
   366      * copied documentation including the defaultValue tag and
   342      * copied documentation including the defaultValue tag and
   367      * the see tags if the appropriate property getter and setter are
   343      * the see tags if the appropriate property getter and setter are
   368      * available.
   344      * available.
   369      *
   345      *
   370      * @param visibleMemberMap the members information.
       
   371      * @param member the member which is to be augmented.
   346      * @param member the member which is to be augmented.
   372      * @param property the original property documentation.
   347      * @param property the original property documentation.
   373      */
   348      */
   374     private void processProperty(VisibleMemberMap visibleMemberMap,
   349     private void processProperty(Element member,
   375                                  Element member,
       
   376                                  Element property) {
   350                                  Element property) {
   377         CommentUtils cmtutils = configuration.cmtUtils;
   351         CommentUtils cmtutils = configuration.cmtUtils;
   378         final boolean isSetter = isSetter(member);
   352         final boolean isSetter = isSetter(member);
   379         final boolean isGetter = isGetter(member);
   353         final boolean isGetter = isGetter(member);
   380 
   354 
   416             }
   390             }
   417         }
   391         }
   418 
   392 
   419         //add @see tags
   393         //add @see tags
   420         if (!isGetter && !isSetter) {
   394         if (!isGetter && !isSetter) {
   421             ExecutableElement getter = (ExecutableElement) visibleMemberMap.getGetterForProperty(member);
   395             ExecutableElement getter = pHelper.getGetterForProperty((ExecutableElement)member);
   422             ExecutableElement setter = (ExecutableElement) visibleMemberMap.getSetterForProperty(member);
   396             ExecutableElement setter = pHelper.getSetterForProperty((ExecutableElement)member);
   423 
   397 
   424             if (null != getter) {
   398             if (null != getter) {
   425                 StringBuilder sb = new StringBuilder("#");
   399                 StringBuilder sb = new StringBuilder("#");
   426                 sb.append(utils.getSimpleName(getter)).append("()");
   400                 sb.append(utils.getSimpleName(getter)).append("()");
   427                 blockTags.add(cmtutils.makeSeeTree(sb.toString(), getter));
   401                 blockTags.add(cmtutils.makeSeeTree(sb.toString(), getter));
   463 
   437 
   464     /**
   438     /**
   465      * Build the inherited member summary for the given methods.
   439      * Build the inherited member summary for the given methods.
   466      *
   440      *
   467      * @param writer the writer for this member summary.
   441      * @param writer the writer for this member summary.
   468      * @param visibleMemberMap the map for the members to document.
   442      * @param kind the kind of members to document.
   469      * @param summaryTreeList list of content trees to which the documentation will be added
   443      * @param summaryTreeList list of content trees to which the documentation will be added
   470      */
   444      */
   471     private void buildInheritedSummary(MemberSummaryWriter writer,
   445     private void buildInheritedSummary(MemberSummaryWriter writer,
   472             VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
   446             VisibleMemberTable.Kind kind, LinkedList<Content> summaryTreeList) {
   473         for (TypeElement inheritedClass : visibleMemberMap.getVisibleClasses()) {
   447         VisibleMemberTable visibleMemberTable = getVisibleMemberTable();
       
   448         SortedSet<? extends Element> inheritedMembersFromMap = asSortedSet(visibleMemberTable.getAllVisibleMembers(kind));
       
   449 
       
   450         for (TypeElement inheritedClass : visibleMemberTable.getVisibleTypeElements()) {
   474             if (!(utils.isPublic(inheritedClass) || utils.isLinkable(inheritedClass))) {
   451             if (!(utils.isPublic(inheritedClass) || utils.isLinkable(inheritedClass))) {
   475                 continue;
   452                 continue;
   476             }
   453             }
   477             if (inheritedClass == typeElement) {
   454             if (inheritedClass == typeElement) {
   478                 continue;
   455                 continue;
   479             }
   456             }
   480             SortedSet<Element> inheritedMembersFromMap = asSortedSet(
   457 
   481                     visibleMemberMap.getMembers(inheritedClass));
   458             List<Element> members = inheritedMembersFromMap.stream()
   482 
   459                     .filter(e -> utils.getEnclosingTypeElement(e) == inheritedClass)
   483             if (!inheritedMembersFromMap.isEmpty()) {
   460                     .collect(Collectors.toList());
       
   461             if (!members.isEmpty()) {
   484                 SortedSet<Element> inheritedMembers = new TreeSet<>(comparator);
   462                 SortedSet<Element> inheritedMembers = new TreeSet<>(comparator);
   485                 List<ExecutableElement> enclosedSuperMethods = utils.getMethods(inheritedClass);
   463                 inheritedMembers.addAll(members);
   486                 for (Element inheritedMember : inheritedMembersFromMap) {
       
   487                     if (visibleMemberMap.kind != VisibleMemberMap.Kind.METHODS) {
       
   488                         inheritedMembers.add(inheritedMember);
       
   489                         continue;
       
   490                     }
       
   491 
       
   492                     // Skip static methods in interfaces they are not inherited
       
   493                     if (utils.isInterface(inheritedClass) && utils.isStatic(inheritedMember))
       
   494                         continue;
       
   495 
       
   496                     // If applicable, filter those overridden methods that
       
   497                     // should not be documented in the summary/detail sections,
       
   498                     // and instead document them in the footnote. Care must be taken
       
   499                     // to handle JavaFX property methods, which have no source comments,
       
   500                     // but comments for these are synthesized on the output.
       
   501                     ExecutableElement inheritedMethod = (ExecutableElement)inheritedMember;
       
   502                     if (enclosedSuperMethods.stream()
       
   503                             .anyMatch(e -> utils.executableMembersEqual(inheritedMethod, e) &&
       
   504                                     (!utils.isSimpleOverride(e) || visibleMemberMap.getPropertyElement(e) != null))) {
       
   505                         inheritedMembers.add(inheritedMember);
       
   506                     }
       
   507                 }
       
   508 
       
   509                 Content inheritedTree = writer.getInheritedSummaryHeader(inheritedClass);
   464                 Content inheritedTree = writer.getInheritedSummaryHeader(inheritedClass);
   510                 Content linksTree = writer.getInheritedSummaryLinksTree();
   465                 Content linksTree = writer.getInheritedSummaryLinksTree();
   511                 addSummaryFootNote(inheritedClass, inheritedMembers, linksTree, writer);
   466                 addSummaryFootNote(inheritedClass, inheritedMembers, linksTree, writer);
   512                 inheritedTree.addContent(linksTree);
   467                 inheritedTree.addContent(linksTree);
   513                 summaryTreeList.add(writer.getMemberTree(inheritedTree));
   468                 summaryTreeList.add(writer.getMemberTree(inheritedTree));
   527 
   482 
   528     /**
   483     /**
   529      * Add the summary for the documentation.
   484      * Add the summary for the documentation.
   530      *
   485      *
   531      * @param writer the writer for this member summary.
   486      * @param writer the writer for this member summary.
   532      * @param visibleMemberMap the map for the members to document.
   487      * @param kind the kind of members to document.
   533      * @param showInheritedSummary true if inherited summary should be documented
   488      * @param showInheritedSummary true if inherited summary should be documented
   534      * @param memberSummaryTree the content tree to which the documentation will be added
   489      * @param memberSummaryTree the content tree to which the documentation will be added
   535      */
   490      */
   536     private void addSummary(MemberSummaryWriter writer,
   491     private void addSummary(MemberSummaryWriter writer,
   537             VisibleMemberMap visibleMemberMap, boolean showInheritedSummary,
   492             VisibleMemberTable.Kind kind, boolean showInheritedSummary,
   538             Content memberSummaryTree) {
   493             Content memberSummaryTree) {
   539         LinkedList<Content> summaryTreeList = new LinkedList<>();
   494         LinkedList<Content> summaryTreeList = new LinkedList<>();
   540         buildSummary(writer, visibleMemberMap, summaryTreeList);
   495         buildSummary(writer, kind, summaryTreeList);
   541         if (showInheritedSummary)
   496         if (showInheritedSummary)
   542             buildInheritedSummary(writer, visibleMemberMap, summaryTreeList);
   497             buildInheritedSummary(writer, kind, summaryTreeList);
   543         if (!summaryTreeList.isEmpty()) {
   498         if (!summaryTreeList.isEmpty()) {
   544             Content memberTree = writer.getMemberSummaryHeader(typeElement, memberSummaryTree);
   499             Content memberTree = writer.getMemberSummaryHeader(typeElement, memberSummaryTree);
   545             summaryTreeList.stream().forEach(memberTree::addContent);
   500             summaryTreeList.stream().forEach(memberTree::addContent);
   546             writer.addMemberTree(memberSummaryTree, memberTree);
   501             writer.addMemberTree(memberSummaryTree, memberTree);
   547         }
   502         }
   548     }
   503     }
   549 
   504 
   550     private SortedSet<Element> asSortedSet(Collection<Element> members) {
   505     private SortedSet<? extends Element> asSortedSet(Collection<? extends Element> members) {
   551         SortedSet<Element> out = new TreeSet<>(comparator);
   506         SortedSet<Element> out = new TreeSet<>(comparator);
   552         out.addAll(members);
   507         out.addAll(members);
   553         return out;
   508         return out;
   554     }
   509     }
       
   510 
       
   511     static class PropertyHelper {
       
   512 
       
   513         private final Map<Element, Element> classPropertiesMap = new HashMap<>();
       
   514 
       
   515         private final MemberSummaryBuilder  builder;
       
   516 
       
   517         PropertyHelper(MemberSummaryBuilder builder) {
       
   518             this.builder = builder;
       
   519             computeProperties();
       
   520         }
       
   521 
       
   522         private void computeProperties() {
       
   523             VisibleMemberTable vmt = builder.getVisibleMemberTable();
       
   524             List<ExecutableElement> props = ElementFilter.methodsIn(vmt.getVisibleMembers(PROPERTIES));
       
   525             for (ExecutableElement propertyMethod : props) {
       
   526                 ExecutableElement getter = vmt.getPropertyGetter(propertyMethod);
       
   527                 ExecutableElement setter = vmt.getPropertySetter(propertyMethod);
       
   528                 VariableElement field = vmt.getPropertyField(propertyMethod);
       
   529 
       
   530                 addToPropertiesMap(propertyMethod, field, getter, setter);
       
   531             }
       
   532         }
       
   533 
       
   534         private void addToPropertiesMap(ExecutableElement propertyMethod,
       
   535                                         VariableElement field,
       
   536                                         ExecutableElement getter,
       
   537                                         ExecutableElement setter) {
       
   538             if (field == null || builder.utils.getDocCommentTree(field) == null) {
       
   539                 addToPropertiesMap(propertyMethod, propertyMethod);
       
   540                 addToPropertiesMap(getter, propertyMethod);
       
   541                 addToPropertiesMap(setter, propertyMethod);
       
   542             } else {
       
   543                 addToPropertiesMap(propertyMethod, field);
       
   544                 addToPropertiesMap(getter, field);
       
   545                 addToPropertiesMap(setter, field);
       
   546             }
       
   547         }
       
   548 
       
   549         private void addToPropertiesMap(Element propertyMethod,
       
   550                                         Element commentSource) {
       
   551             if (null == propertyMethod || null == commentSource) {
       
   552                 return;
       
   553             }
       
   554             DocCommentTree docTree = builder.utils.getDocCommentTree(propertyMethod);
       
   555 
       
   556             /* The second condition is required for the property buckets. In
       
   557              * this case the comment is at the property method (not at the field)
       
   558              * and it needs to be listed in the map.
       
   559              */
       
   560             if ((docTree == null) || propertyMethod.equals(commentSource)) {
       
   561                 classPropertiesMap.put(propertyMethod, commentSource);
       
   562             }
       
   563         }
       
   564 
       
   565         /**
       
   566          * Returns the property field documentation belonging to the given member.
       
   567          * @param element the member for which the property documentation is needed.
       
   568          * @return the property field documentation, null if there is none.
       
   569          */
       
   570         public Element getPropertyElement(Element element) {
       
   571             return classPropertiesMap.get(element);
       
   572         }
       
   573 
       
   574         /**
       
   575          * Returns the getter documentation belonging to the given property method.
       
   576          * @param propertyMethod the method for which the getter is needed.
       
   577          * @return the getter documentation, null if there is none.
       
   578          */
       
   579         public ExecutableElement getGetterForProperty(ExecutableElement propertyMethod) {
       
   580             return builder.getVisibleMemberTable().getPropertyGetter(propertyMethod);
       
   581         }
       
   582 
       
   583         /**
       
   584          * Returns the setter documentation belonging to the given property method.
       
   585          * @param propertyMethod the method for which the setter is needed.
       
   586          * @return the setter documentation, null if there is none.
       
   587          */
       
   588         public ExecutableElement getSetterForProperty(ExecutableElement propertyMethod) {
       
   589             return builder.getVisibleMemberTable().getPropertySetter(propertyMethod);
       
   590         }
       
   591     }
   555 }
   592 }