/** * Given a <code>MethodDoc</code> item, a <code>Tag</code> in the <code>MethodDoc</code> item and * a String, replace all occurrences of @inheritDoc with documentation from it's superclass or * superinterface. * * @param writer the writer that is writing the output. * @param md the {@link MethodDoc} that we are documenting. * @param holderTag the tag that holds the inheritDoc tag. * @param isFirstSentence true if we only want to inherit the first sentence. */ private TagletOutput retrieveInheritedDocumentation( TagletWriter writer, MethodDoc md, Tag holderTag, boolean isFirstSentence) { TagletOutput replacement = writer.getTagletOutputInstance(); Configuration configuration = writer.configuration(); Taglet inheritableTaglet = holderTag == null ? null : configuration.tagletManager.getTaglet(holderTag.name()); if (inheritableTaglet != null && !(inheritableTaglet instanceof InheritableTaglet)) { // This tag does not support inheritence. configuration.message.warning( md.position(), "doclet.noInheritedDoc", md.name() + md.flatSignature()); } DocFinder.Output inheritedDoc = DocFinder.search( new DocFinder.Input( md, (InheritableTaglet) inheritableTaglet, holderTag, isFirstSentence, true)); if (inheritedDoc.isValidInheritDocTag == false) { configuration.message.warning( md.position(), "doclet.noInheritedDoc", md.name() + md.flatSignature()); } else if (inheritedDoc.inlineTags.length > 0) { replacement = writer.commentTagsToOutput( inheritedDoc.holderTag, inheritedDoc.holder, inheritedDoc.inlineTags, isFirstSentence); } return replacement; }
/** {@inheritDoc} */ public Content getTagletOutput(Tag tag, TagletWriter writer) { ArrayList inlineTags = new ArrayList(); inlineTags.add(new TextTag(tag.holder(), "<b>")); inlineTags.addAll(Arrays.asList(tag.inlineTags())); inlineTags.add(new TextTag(tag.holder(), "</b>")); return writer.commentTagsToOutput(tag, (Tag[]) inlineTags.toArray(new Tag[] {})); }
/** * Loop through each indivitual parameter. It it does not have a corresponding param tag, try to * inherit it. */ private TagletOutput getInheritedTagletOutput( boolean isNonTypeParams, Doc holder, TagletWriter writer, Object[] formalParameters, Set alreadyDocumented) { TagletOutput result = writer.getOutputInstance(); if ((!alreadyDocumented.contains(null)) && holder instanceof MethodDoc) { for (int i = 0; i < formalParameters.length; i++) { if (alreadyDocumented.contains(String.valueOf(i))) { continue; } // This parameter does not have any @param documentation. // Try to inherit it. DocFinder.Output inheritedDoc = DocFinder.search( new DocFinder.Input((MethodDoc) holder, this, String.valueOf(i), !isNonTypeParams)); if (inheritedDoc.inlineTags != null && inheritedDoc.inlineTags.length > 0) { result.appendOutput( processParamTag( isNonTypeParams, writer, (ParamTag) inheritedDoc.holderTag, isNonTypeParams ? ((Parameter) formalParameters[i]).name() : ((TypeVariable) formalParameters[i]).typeName(), alreadyDocumented.size() == 0)); } alreadyDocumented.add(String.valueOf(i)); } } return result; }
/** Inherit throws documentation for exceptions that were declared but not documented. */ private TagletOutput inheritThrowsDocumentation( Doc holder, Type[] declaredExceptionTypes, Set<String> alreadyDocumented, TagletWriter writer) { TagletOutput result = writer.getOutputInstance(); if (holder instanceof MethodDoc) { Set<Tag> declaredExceptionTags = new LinkedHashSet<Tag>(); for (int j = 0; j < declaredExceptionTypes.length; j++) { DocFinder.Output inheritedDoc = DocFinder.search( new DocFinder.Input( (MethodDoc) holder, this, declaredExceptionTypes[j].typeName())); if (inheritedDoc.tagList.size() == 0) { inheritedDoc = DocFinder.search( new DocFinder.Input( (MethodDoc) holder, this, declaredExceptionTypes[j].qualifiedTypeName())); } declaredExceptionTags.addAll(inheritedDoc.tagList); } result.appendOutput( throwsTagsOutput( declaredExceptionTags.toArray(new ThrowsTag[] {}), writer, alreadyDocumented, false)); } return result; }
/** * Convert the individual ParamTag into TagletOutput. * * @param isNonTypeParams true if this is just a regular param tag. False if this is a type param * tag. * @param writer the taglet writer for output writing. * @param paramTag the tag whose inline tags will be printed. * @param name the name of the parameter. We can't rely on the name in the param tag because we * might be inheriting documentation. * @param isFirstParam true if this is the first param tag being printed. */ private TagletOutput processParamTag( boolean isNonTypeParams, TagletWriter writer, ParamTag paramTag, String name, boolean isFirstParam) { TagletOutput result = writer.getOutputInstance(); String header = writer .configuration() .getText(isNonTypeParams ? "doclet.Parameters" : "doclet.TypeParameters"); if (isFirstParam) { result.appendOutput(writer.getParamHeader(header)); } result.appendOutput(writer.paramTagOutput(paramTag, name)); return result; }
/** Add links for exceptions that are declared but not documented. */ private TagletOutput linkToUndocumentedDeclaredExceptions( Type[] declaredExceptionTypes, Set<String> alreadyDocumented, TagletWriter writer) { TagletOutput result = writer.getOutputInstance(); // Add links to the exceptions declared but not documented. for (int i = 0; i < declaredExceptionTypes.length; i++) { if (declaredExceptionTypes[i].asClassDoc() != null && !alreadyDocumented.contains(declaredExceptionTypes[i].asClassDoc().name()) && !alreadyDocumented.contains(declaredExceptionTypes[i].asClassDoc().qualifiedName())) { if (alreadyDocumented.size() == 0) { result.appendOutput(writer.getThrowsHeader()); } result.appendOutput(writer.throwsTagOutput(declaredExceptionTypes[i])); alreadyDocumented.add(declaredExceptionTypes[i].asClassDoc().name()); } } return result; }
/** * Given the <code>Tag</code> representation of this custom tag, return its string representation, * which is output to the generated page. * * @param tag the <code>Tag</code> representation of this custom tag. * @param tagletWriter the taglet writer for output. * @return the TagletOutput representation of this <code>Tag</code>. */ public TagletOutput getTagletOutput(Tag tag, TagletWriter tagletWriter) { if (!(tag.holder() instanceof MethodDoc)) { return tagletWriter.getOutputInstance(); } return tag.name().equals("@inheritDoc") ? retrieveInheritedDocumentation( tagletWriter, (MethodDoc) tag.holder(), null, tagletWriter.isFirstSentence) : retrieveInheritedDocumentation( tagletWriter, (MethodDoc) tag.holder(), tag, tagletWriter.isFirstSentence); }
/** * Given an array of <code>Tag</code>s representing this custom tag, return its string * representation. Print a warning for param tags that do not map to parameters. Print a warning * for param tags that are duplicated. * * @param paramTags the array of <code>ParamTag</code>s to convert. * @param writer the TagletWriter that will write this tag. * @param alreadyDocumented the set of exceptions that have already been documented. * @param rankMap a {@link java.util.Map} which holds ordering information about the parameters. * @param nameMap a {@link java.util.Map} which holds a mapping of a rank of a parameter to its * name. This is used to ensure that the right name is used when parameter documentation is * inherited. * @return the TagletOutput representation of this <code>Tag</code>. */ private TagletOutput processParamTags( boolean isNonTypeParams, ParamTag[] paramTags, Map rankMap, TagletWriter writer, Set alreadyDocumented) { TagletOutput result = writer.getOutputInstance(); if (paramTags.length > 0) { for (int i = 0; i < paramTags.length; ++i) { ParamTag pt = paramTags[i]; String paramName = isNonTypeParams ? pt.parameterName() : "<" + pt.parameterName() + ">"; if (!rankMap.containsKey(pt.parameterName())) { writer .getMsgRetriever() .warning( pt.position(), isNonTypeParams ? "doclet.Parameters_warn" : "doclet.Type_Parameters_warn", paramName); } String rank = (String) rankMap.get(pt.parameterName()); if (rank != null && alreadyDocumented.contains(rank)) { writer .getMsgRetriever() .warning( pt.position(), isNonTypeParams ? "doclet.Parameters_dup_warn" : "doclet.Type_Parameters_dup_warn", paramName); } result.appendOutput( processParamTag( isNonTypeParams, writer, pt, pt.parameterName(), alreadyDocumented.size() == 0)); alreadyDocumented.add(rank); } } return result; }
/** * Given an array of <code>Tag</code>s representing this custom tag, return its string * representation. * * @param throwTags the array of <code>ThrowsTag</code>s to convert. * @param writer the TagletWriter that will write this tag. * @param alreadyDocumented the set of exceptions that have already been documented. * @param allowDups True if we allow duplicate throws tags to be documented. * @return the TagletOutput representation of this <code>Tag</code>. */ protected TagletOutput throwsTagsOutput( ThrowsTag[] throwTags, TagletWriter writer, Set<String> alreadyDocumented, boolean allowDups) { TagletOutput result = writer.getOutputInstance(); if (throwTags.length > 0) { for (int i = 0; i < throwTags.length; ++i) { ThrowsTag tt = throwTags[i]; ClassDoc cd = tt.exception(); if ((!allowDups) && (alreadyDocumented.contains(tt.exceptionName()) || (cd != null && alreadyDocumented.contains(cd.qualifiedName())))) { continue; } if (alreadyDocumented.size() == 0) { result.appendOutput(writer.getThrowsHeader()); } result.appendOutput(writer.throwsTagOutput(tt)); alreadyDocumented.add(cd != null ? cd.qualifiedName() : tt.exceptionName()); } } return result; }
/** {@inheritDoc} */ public TagletOutput getTagletOutput(Doc holder, TagletWriter writer) { ExecutableMemberDoc execHolder = (ExecutableMemberDoc) holder; ThrowsTag[] tags = execHolder.throwsTags(); TagletOutput result = writer.getOutputInstance(); HashSet<String> alreadyDocumented = new HashSet<String>(); if (tags.length > 0) { result.appendOutput( throwsTagsOutput(execHolder.throwsTags(), writer, alreadyDocumented, true)); } result.appendOutput( inheritThrowsDocumentation( holder, execHolder.thrownExceptionTypes(), alreadyDocumented, writer)); result.appendOutput( linkToUndocumentedDeclaredExceptions( execHolder.thrownExceptionTypes(), alreadyDocumented, writer)); return result; }
/** * Given an array of <code>ParamTag</code>s,return its string representation. Try to inherit the * param tags that are missing. * * @param doc the doc that holds the param tags. * @param writer the TagletWriter that will write this tag. * @param formalParameters The array of parmeters (from type or executable member) to check. * @return the TagletOutput representation of these <code>ParamTag</code>s. */ private TagletOutput getTagletOutput( boolean isNonTypeParams, Doc holder, TagletWriter writer, Object[] formalParameters, ParamTag[] paramTags) { TagletOutput result = writer.getOutputInstance(); Set alreadyDocumented = new HashSet(); if (paramTags.length > 0) { result.appendOutput( processParamTags( isNonTypeParams, paramTags, getRankMap(formalParameters), writer, alreadyDocumented)); } if (alreadyDocumented.size() != formalParameters.length) { // Some parameters are missing corresponding @param tags. // Try to inherit them. result.appendOutput( getInheritedTagletOutput( isNonTypeParams, holder, writer, formalParameters, alreadyDocumented)); } return result; }
@Override String getText(TagletWriter tagletWriter) { return tagletWriter.configuration().getText("doclet.PropertySetter"); }