src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ParamTaglet.java

Thu, 31 Aug 2017 15:17:03 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:17:03 +0800
changeset 2525
2eb010b6cb22
parent 1751
ca8808c88f94
parent 0
959103a6100f
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 2001, 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.taglets;
    28 import java.util.*;
    30 import com.sun.javadoc.*;
    31 import com.sun.tools.doclets.internal.toolkit.Content;
    32 import com.sun.tools.doclets.internal.toolkit.util.*;
    34 /**
    35  * A taglet that represents the @param tag.
    36  *
    37  *  <p><b>This is NOT part of any supported API.
    38  *  If you write code that depends on this, you do so at your own risk.
    39  *  This code and its internal interfaces are subject to change or
    40  *  deletion without notice.</b>
    41  *
    42  * @author Jamie Ho
    43  * @since 1.4
    44  */
    45 public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
    47     /**
    48      * Construct a ParamTaglet.
    49      */
    50     public ParamTaglet() {
    51         name = "param";
    52     }
    54     /**
    55      * Given an array of <code>Parameter</code>s, return
    56      * a name/rank number map.  If the array is null, then
    57      * null is returned.
    58      * @param params The array of parmeters (from type or executable member) to
    59      *               check.
    60      * @return a name-rank number map.
    61      */
    62     private static Map<String,String> getRankMap(Object[] params){
    63         if (params == null) {
    64             return null;
    65         }
    66         HashMap<String,String> result = new HashMap<String,String>();
    67         for (int i = 0; i < params.length; i++) {
    68             String name = params[i] instanceof Parameter ?
    69                 ((Parameter) params[i]).name() :
    70                 ((TypeVariable) params[i]).typeName();
    71             result.put(name, String.valueOf(i));
    72         }
    73         return result;
    74     }
    76     /**
    77      * {@inheritDoc}
    78      */
    79     public void inherit(DocFinder.Input input, DocFinder.Output output) {
    80         if (input.tagId == null) {
    81             input.isTypeVariableParamTag = ((ParamTag) input.tag).isTypeParameter();
    82             Object[] parameters = input.isTypeVariableParamTag ?
    83                 (Object[]) ((MethodDoc) input.tag.holder()).typeParameters() :
    84                 (Object[]) ((MethodDoc) input.tag.holder()).parameters();
    85             String target = ((ParamTag) input.tag).parameterName();
    86             int i;
    87             for (i = 0; i < parameters.length; i++) {
    88                 String name = parameters[i] instanceof Parameter ?
    89                     ((Parameter) parameters[i]).name() :
    90                     ((TypeVariable) parameters[i]).typeName();
    91                 if (name.equals(target)) {
    92                     input.tagId = String.valueOf(i);
    93                     break;
    94                 }
    95             }
    96             if (i == parameters.length) {
    97                 //Someone used {@inheritDoc} on an invalid @param tag.
    98                 //We don't know where to inherit from.
    99                 //XXX: in the future when Configuration is available here,
   100                 //print a warning for this mistake.
   101                 return;
   102             }
   103         }
   104         ParamTag[] tags = input.isTypeVariableParamTag ?
   105             ((MethodDoc)input.element).typeParamTags() : ((MethodDoc)input.element).paramTags();
   106         Map<String, String> rankMap = getRankMap(input.isTypeVariableParamTag ?
   107             (Object[]) ((MethodDoc)input.element).typeParameters() :
   108             (Object[]) ((MethodDoc)input.element).parameters());
   109         for (int i = 0; i < tags.length; i++) {
   110             if (rankMap.containsKey(tags[i].parameterName()) &&
   111                     rankMap.get(tags[i].parameterName()).equals((input.tagId))) {
   112                 output.holder = input.element;
   113                 output.holderTag = tags[i];
   114                 output.inlineTags = input.isFirstSentence ?
   115                     tags[i].firstSentenceTags() : tags[i].inlineTags();
   116                 return;
   117             }
   118         }
   119     }
   121     /**
   122      * {@inheritDoc}
   123      */
   124     public boolean inField() {
   125         return false;
   126     }
   128     /**
   129      * {@inheritDoc}
   130      */
   131     public boolean inMethod() {
   132         return true;
   133     }
   135     /**
   136      * {@inheritDoc}
   137      */
   138     public boolean inOverview() {
   139         return false;
   140     }
   142     /**
   143      * {@inheritDoc}
   144      */
   145     public boolean inPackage() {
   146         return false;
   147     }
   149     /**
   150      * {@inheritDoc}
   151      */
   152     public boolean inType() {
   153         return true;
   154     }
   156     /**
   157      * {@inheritDoc}
   158      */
   159     public boolean isInlineTag() {
   160         return false;
   161     }
   163     /**
   164      * Given an array of <code>ParamTag</code>s,return its string representation.
   165      * @param holder the member that holds the param tags.
   166      * @param writer the TagletWriter that will write this tag.
   167      * @return the TagletOutput representation of these <code>ParamTag</code>s.
   168      */
   169     public Content getTagletOutput(Doc holder, TagletWriter writer) {
   170         if (holder instanceof ExecutableMemberDoc) {
   171             ExecutableMemberDoc member = (ExecutableMemberDoc) holder;
   172             Content output = getTagletOutput(false, member, writer,
   173                 member.typeParameters(), member.typeParamTags());
   174             output.addContent(getTagletOutput(true, member, writer,
   175                 member.parameters(), member.paramTags()));
   176             return output;
   177         } else {
   178             ClassDoc classDoc = (ClassDoc) holder;
   179             return getTagletOutput(false, classDoc, writer,
   180                 classDoc.typeParameters(), classDoc.typeParamTags());
   181         }
   182     }
   184     /**
   185      * Given an array of <code>ParamTag</code>s,return its string representation.
   186      * Try to inherit the param tags that are missing.
   187      *
   188      * @param holder            the doc that holds the param tags.
   189      * @param writer            the TagletWriter that will write this tag.
   190      * @param formalParameters  The array of parmeters (from type or executable
   191      *                          member) to check.
   192      *
   193      * @return the TagletOutput representation of these <code>ParamTag</code>s.
   194      */
   195     private Content getTagletOutput(boolean isNonTypeParams, Doc holder,
   196             TagletWriter writer, Object[] formalParameters, ParamTag[] paramTags) {
   197         Content result = writer.getOutputInstance();
   198         Set<String> alreadyDocumented = new HashSet<String>();
   199         if (paramTags.length > 0) {
   200             result.addContent(
   201                 processParamTags(isNonTypeParams, paramTags,
   202                 getRankMap(formalParameters), writer, alreadyDocumented)
   203             );
   204         }
   205         if (alreadyDocumented.size() != formalParameters.length) {
   206             //Some parameters are missing corresponding @param tags.
   207             //Try to inherit them.
   208             result.addContent(getInheritedTagletOutput (isNonTypeParams, holder,
   209                 writer, formalParameters, alreadyDocumented));
   210         }
   211         return result;
   212     }
   214     /**
   215      * Loop through each indivitual parameter.  It it does not have a
   216      * corresponding param tag, try to inherit it.
   217      */
   218     private Content getInheritedTagletOutput(boolean isNonTypeParams, Doc holder,
   219             TagletWriter writer, Object[] formalParameters,
   220             Set<String> alreadyDocumented) {
   221         Content result = writer.getOutputInstance();
   222         if ((! alreadyDocumented.contains(null)) &&
   223                 holder instanceof MethodDoc) {
   224             for (int i = 0; i < formalParameters.length; i++) {
   225                 if (alreadyDocumented.contains(String.valueOf(i))) {
   226                     continue;
   227                 }
   228                 //This parameter does not have any @param documentation.
   229                 //Try to inherit it.
   230                 DocFinder.Output inheritedDoc =
   231                     DocFinder.search(new DocFinder.Input((MethodDoc) holder, this,
   232                         String.valueOf(i), ! isNonTypeParams));
   233                 if (inheritedDoc.inlineTags != null &&
   234                         inheritedDoc.inlineTags.length > 0) {
   235                     result.addContent(
   236                         processParamTag(isNonTypeParams, writer,
   237                             (ParamTag) inheritedDoc.holderTag,
   238                             isNonTypeParams ?
   239                                 ((Parameter) formalParameters[i]).name():
   240                                 ((TypeVariable) formalParameters[i]).typeName(),
   241                             alreadyDocumented.size() == 0));
   242                 }
   243                 alreadyDocumented.add(String.valueOf(i));
   244             }
   245         }
   246         return result;
   247     }
   249     /**
   250      * Given an array of <code>Tag</code>s representing this custom
   251      * tag, return its string representation.  Print a warning for param
   252      * tags that do not map to parameters.  Print a warning for param
   253      * tags that are duplicated.
   254      *
   255      * @param paramTags the array of <code>ParamTag</code>s to convert.
   256      * @param writer the TagletWriter that will write this tag.
   257      * @param alreadyDocumented the set of exceptions that have already
   258      *        been documented.
   259      * @param rankMap a {@link java.util.Map} which holds ordering
   260      *                    information about the parameters.
   261      * @param rankMap a {@link java.util.Map} which holds a mapping
   262      *                of a rank of a parameter to its name.  This is
   263      *                used to ensure that the right name is used
   264      *                when parameter documentation is inherited.
   265      * @return the Content representation of this <code>Tag</code>.
   266      */
   267     private Content processParamTags(boolean isNonTypeParams,
   268             ParamTag[] paramTags, Map<String, String> rankMap, TagletWriter writer,
   269             Set<String> alreadyDocumented) {
   270         Content result = writer.getOutputInstance();
   271         if (paramTags.length > 0) {
   272             for (int i = 0; i < paramTags.length; ++i) {
   273                 ParamTag pt = paramTags[i];
   274                 String paramName = isNonTypeParams ?
   275                     pt.parameterName() : "<" + pt.parameterName() + ">";
   276                 if (! rankMap.containsKey(pt.parameterName())) {
   277                     writer.getMsgRetriever().warning(pt.position(),
   278                         isNonTypeParams ?
   279                             "doclet.Parameters_warn" :
   280                             "doclet.Type_Parameters_warn",
   281                         paramName);
   282                 }
   283                 String rank = rankMap.get(pt.parameterName());
   284                 if (rank != null && alreadyDocumented.contains(rank)) {
   285                     writer.getMsgRetriever().warning(pt.position(),
   286                        isNonTypeParams ?
   287                            "doclet.Parameters_dup_warn" :
   288                            "doclet.Type_Parameters_dup_warn",
   289                        paramName);
   290                 }
   291                 result.addContent(processParamTag(isNonTypeParams, writer, pt,
   292                      pt.parameterName(), alreadyDocumented.size() == 0));
   293                 alreadyDocumented.add(rank);
   294             }
   295         }
   296         return result;
   297     }
   298     /**
   299      * Convert the individual ParamTag into Content.
   300      *
   301      * @param isNonTypeParams true if this is just a regular param tag.  False
   302      *                        if this is a type param tag.
   303      * @param writer          the taglet writer for output writing.
   304      * @param paramTag        the tag whose inline tags will be printed.
   305      * @param name            the name of the parameter.  We can't rely on
   306      *                        the name in the param tag because we might be
   307      *                        inheriting documentation.
   308      * @param isFirstParam    true if this is the first param tag being printed.
   309      *
   310      */
   311     private Content processParamTag(boolean isNonTypeParams,
   312             TagletWriter writer, ParamTag paramTag, String name,
   313             boolean isFirstParam) {
   314         Content result = writer.getOutputInstance();
   315         String header = writer.configuration().getText(
   316             isNonTypeParams ? "doclet.Parameters" : "doclet.TypeParameters");
   317         if (isFirstParam) {
   318             result.addContent(writer.getParamHeader(header));
   319         }
   320         result.addContent(writer.paramTagOutput(paramTag,
   321             name));
   322         return result;
   323     }
   324 }

mercurial