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

Tue, 09 Oct 2012 19:10:00 -0700

author
jjg
date
Tue, 09 Oct 2012 19:10:00 -0700
changeset 1357
c75be5bc5283
parent 554
9d9f26857129
child 1358
fc123bdeddb8
permissions
-rw-r--r--

8000663: clean up langtools imports
Reviewed-by: darcy

     1 /*
     2  * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.tools.doclets.internal.toolkit.taglets;
    28 import java.util.*;
    30 import com.sun.javadoc.*;
    31 import com.sun.tools.doclets.internal.toolkit.util.*;
    33 /**
    34  * A taglet that represents the @param tag.
    35  *
    36  * This code is not part of an API.
    37  * It is implementation that is subject to change.
    38  * Do not use it as an API
    39  *
    40  * @author Jamie Ho
    41  * @since 1.4
    42  */
    43 public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
    45     /**
    46      * Construct a ParamTaglet.
    47      */
    48     public ParamTaglet() {
    49         name = "param";
    50     }
    52     /**
    53      * Given an array of <code>Parameter</code>s, return
    54      * a name/rank number map.  If the array is null, then
    55      * null is returned.
    56      * @param params The array of parmeters (from type or executable member) to
    57      *               check.
    58      * @return a name-rank number map.
    59      */
    60     private static Map<String,String> getRankMap(Object[] params){
    61         if (params == null) {
    62             return null;
    63         }
    64         HashMap<String,String> result = new HashMap<String,String>();
    65         for (int i = 0; i < params.length; i++) {
    66             String name = params[i] instanceof Parameter ?
    67                 ((Parameter) params[i]).name() :
    68                 ((TypeVariable) params[i]).typeName();
    69             result.put(name, String.valueOf(i));
    70         }
    71         return result;
    72     }
    74     /**
    75      * {@inheritDoc}
    76      */
    77     public void inherit(DocFinder.Input input, DocFinder.Output output) {
    78         if (input.tagId == null) {
    79             input.isTypeVariableParamTag = ((ParamTag) input.tag).isTypeParameter();
    80             Object[] parameters = input.isTypeVariableParamTag ?
    81                 (Object[]) ((MethodDoc) input.tag.holder()).typeParameters() :
    82                 (Object[]) ((MethodDoc) input.tag.holder()).parameters();
    83             String target = ((ParamTag) input.tag).parameterName();
    84             int i;
    85             for (i = 0; i < parameters.length; i++) {
    86                 String name = parameters[i] instanceof Parameter ?
    87                     ((Parameter) parameters[i]).name() :
    88                     ((TypeVariable) parameters[i]).typeName();
    89                 if (name.equals(target)) {
    90                     input.tagId = String.valueOf(i);
    91                     break;
    92                 }
    93             }
    94             if (i == parameters.length) {
    95                 //Someone used {@inheritDoc} on an invalid @param tag.
    96                 //We don't know where to inherit from.
    97                 //XXX: in the future when Configuration is available here,
    98                 //print a warning for this mistake.
    99                 return;
   100             }
   101         }
   102         ParamTag[] tags = input.isTypeVariableParamTag ?
   103             input.method.typeParamTags() : input.method.paramTags();
   104         Map<String, String> rankMap = getRankMap(input.isTypeVariableParamTag ?
   105             (Object[]) input.method.typeParameters() :
   106             (Object[]) input.method.parameters());
   107         for (int i = 0; i < tags.length; i++) {
   108             if (rankMap.containsKey(tags[i].parameterName()) &&
   109                     rankMap.get(tags[i].parameterName()).equals((input.tagId))) {
   110                 output.holder = input.method;
   111                 output.holderTag = tags[i];
   112                 output.inlineTags = input.isFirstSentence ?
   113                     tags[i].firstSentenceTags() : tags[i].inlineTags();
   114                 return;
   115             }
   116         }
   117     }
   119     /**
   120      * {@inheritDoc}
   121      */
   122     public boolean inField() {
   123         return false;
   124     }
   126     /**
   127      * {@inheritDoc}
   128      */
   129     public boolean inMethod() {
   130         return true;
   131     }
   133     /**
   134      * {@inheritDoc}
   135      */
   136     public boolean inOverview() {
   137         return false;
   138     }
   140     /**
   141      * {@inheritDoc}
   142      */
   143     public boolean inPackage() {
   144         return false;
   145     }
   147     /**
   148      * {@inheritDoc}
   149      */
   150     public boolean inType() {
   151         return true;
   152     }
   154     /**
   155      * {@inheritDoc}
   156      */
   157     public boolean isInlineTag() {
   158         return false;
   159     }
   161     /**
   162      * Given an array of <code>ParamTag</code>s,return its string representation.
   163      * @param holder the member that holds the param tags.
   164      * @param writer the TagletWriter that will write this tag.
   165      * @return the TagletOutput representation of these <code>ParamTag</code>s.
   166      */
   167     public TagletOutput getTagletOutput(Doc holder, TagletWriter writer) {
   168         if (holder instanceof ExecutableMemberDoc) {
   169             ExecutableMemberDoc member = (ExecutableMemberDoc) holder;
   170             TagletOutput output = getTagletOutput(false, member, writer,
   171                 member.typeParameters(), member.typeParamTags());
   172             output.appendOutput(getTagletOutput(true, member, writer,
   173                 member.parameters(), member.paramTags()));
   174             return output;
   175         } else {
   176             ClassDoc classDoc = (ClassDoc) holder;
   177             return getTagletOutput(false, classDoc, writer,
   178                 classDoc.typeParameters(), classDoc.typeParamTags());
   179         }
   180     }
   182     /**
   183      * Given an array of <code>ParamTag</code>s,return its string representation.
   184      * Try to inherit the param tags that are missing.
   185      *
   186      * @param doc               the doc that holds the param tags.
   187      * @param writer            the TagletWriter that will write this tag.
   188      * @param formalParameters  The array of parmeters (from type or executable
   189      *                          member) to check.
   190      *
   191      * @return the TagletOutput representation of these <code>ParamTag</code>s.
   192      */
   193     private TagletOutput getTagletOutput(boolean isNonTypeParams, Doc holder,
   194             TagletWriter writer, Object[] formalParameters, ParamTag[] paramTags) {
   195         TagletOutput result = writer.getOutputInstance();
   196         Set<String> alreadyDocumented = new HashSet<String>();
   197         if (paramTags.length > 0) {
   198             result.appendOutput(
   199                 processParamTags(isNonTypeParams, paramTags,
   200                 getRankMap(formalParameters), writer, alreadyDocumented)
   201             );
   202         }
   203         if (alreadyDocumented.size() != formalParameters.length) {
   204             //Some parameters are missing corresponding @param tags.
   205             //Try to inherit them.
   206             result.appendOutput(getInheritedTagletOutput (isNonTypeParams, holder,
   207                 writer, formalParameters, alreadyDocumented));
   208         }
   209         return result;
   210     }
   212     /**
   213      * Loop through each indivitual parameter.  It it does not have a
   214      * corresponding param tag, try to inherit it.
   215      */
   216     private TagletOutput getInheritedTagletOutput(boolean isNonTypeParams, Doc holder,
   217             TagletWriter writer, Object[] formalParameters,
   218             Set<String> alreadyDocumented) {
   219         TagletOutput result = writer.getOutputInstance();
   220         if ((! alreadyDocumented.contains(null)) &&
   221                 holder instanceof MethodDoc) {
   222             for (int i = 0; i < formalParameters.length; i++) {
   223                 if (alreadyDocumented.contains(String.valueOf(i))) {
   224                     continue;
   225                 }
   226                 //This parameter does not have any @param documentation.
   227                 //Try to inherit it.
   228                 DocFinder.Output inheritedDoc =
   229                     DocFinder.search(new DocFinder.Input((MethodDoc) holder, this,
   230                         String.valueOf(i), ! isNonTypeParams));
   231                 if (inheritedDoc.inlineTags != null &&
   232                         inheritedDoc.inlineTags.length > 0) {
   233                     result.appendOutput(
   234                         processParamTag(isNonTypeParams, writer,
   235                             (ParamTag) inheritedDoc.holderTag,
   236                             isNonTypeParams ?
   237                                 ((Parameter) formalParameters[i]).name():
   238                                 ((TypeVariable) formalParameters[i]).typeName(),
   239                             alreadyDocumented.size() == 0));
   240                 }
   241                 alreadyDocumented.add(String.valueOf(i));
   242             }
   243         }
   244         return result;
   245     }
   247     /**
   248      * Given an array of <code>Tag</code>s representing this custom
   249      * tag, return its string representation.  Print a warning for param
   250      * tags that do not map to parameters.  Print a warning for param
   251      * tags that are duplicated.
   252      *
   253      * @param paramTags the array of <code>ParamTag</code>s to convert.
   254      * @param writer the TagletWriter that will write this tag.
   255      * @param alreadyDocumented the set of exceptions that have already
   256      *        been documented.
   257      * @param rankMap a {@link java.util.Map} which holds ordering
   258      *                    information about the parameters.
   259      * @param nameMap a {@link java.util.Map} which holds a mapping
   260      *                of a rank of a parameter to its name.  This is
   261      *                used to ensure that the right name is used
   262      *                when parameter documentation is inherited.
   263      * @return the TagletOutput representation of this <code>Tag</code>.
   264      */
   265     private TagletOutput processParamTags(boolean isNonTypeParams,
   266             ParamTag[] paramTags, Map<String, String> rankMap, TagletWriter writer,
   267             Set<String> alreadyDocumented) {
   268         TagletOutput result = writer.getOutputInstance();
   269         if (paramTags.length > 0) {
   270             for (int i = 0; i < paramTags.length; ++i) {
   271                 ParamTag pt = paramTags[i];
   272                 String paramName = isNonTypeParams ?
   273                     pt.parameterName() : "<" + pt.parameterName() + ">";
   274                 if (! rankMap.containsKey(pt.parameterName())) {
   275                     writer.getMsgRetriever().warning(pt.position(),
   276                         isNonTypeParams ?
   277                             "doclet.Parameters_warn" :
   278                             "doclet.Type_Parameters_warn",
   279                         paramName);
   280                 }
   281                 String rank = rankMap.get(pt.parameterName());
   282                 if (rank != null && alreadyDocumented.contains(rank)) {
   283                     writer.getMsgRetriever().warning(pt.position(),
   284                        isNonTypeParams ?
   285                            "doclet.Parameters_dup_warn" :
   286                            "doclet.Type_Parameters_dup_warn",
   287                        paramName);
   288                 }
   289                 result.appendOutput(processParamTag(isNonTypeParams, writer, pt,
   290                      pt.parameterName(), alreadyDocumented.size() == 0));
   291                 alreadyDocumented.add(rank);
   292             }
   293         }
   294         return result;
   295     }
   296     /**
   297      * Convert the individual ParamTag into TagletOutput.
   298      *
   299      * @param isNonTypeParams true if this is just a regular param tag.  False
   300      *                        if this is a type param tag.
   301      * @param writer          the taglet writer for output writing.
   302      * @param paramTag        the tag whose inline tags will be printed.
   303      * @param name            the name of the parameter.  We can't rely on
   304      *                        the name in the param tag because we might be
   305      *                        inheriting documentation.
   306      * @param isFirstParam    true if this is the first param tag being printed.
   307      *
   308      */
   309     private TagletOutput processParamTag(boolean isNonTypeParams,
   310             TagletWriter writer, ParamTag paramTag, String name,
   311             boolean isFirstParam) {
   312         TagletOutput result = writer.getOutputInstance();
   313         String header = writer.configuration().getText(
   314             isNonTypeParams ? "doclet.Parameters" : "doclet.TypeParameters");
   315         if (isFirstParam) {
   316             result.appendOutput(writer.getParamHeader(header));
   317         }
   318         result.appendOutput(writer.paramTagOutput(paramTag,
   319             name));
   320         return result;
   321     }
   322 }

mercurial