8283864: Clean up DocFinder and friends

Reviewed-by: jjg
This commit is contained in:
Pavel Rappo 2022-04-14 15:09:47 +00:00
parent 9a00b432ea
commit 1cc3c330e3
11 changed files with 166 additions and 162 deletions

View File

@ -169,8 +169,8 @@ public class MethodBuilder extends AbstractMemberBuilder {
if (utils.getFullBody(currentMethod).isEmpty()) {
DocFinder.Output docs = DocFinder.search(configuration,
new DocFinder.Input(utils, currentMethod));
if (docs.inlineTags != null && !docs.inlineTags.isEmpty())
method = (ExecutableElement)docs.holder;
if (!docs.inlineTags.isEmpty())
method = (ExecutableElement) docs.holder;
}
TypeMirror containingType = method.getEnclosingElement().asType();
writer.addComments(containingType, method, methodContent);

View File

@ -26,8 +26,11 @@
package jdk.javadoc.internal.doclets.toolkit.taglets;
import java.util.EnumSet;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;
import com.sun.source.doctree.DocTree;
import jdk.javadoc.doclet.Taglet.Location;
@ -36,71 +39,81 @@ import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.Messages;
import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
import jdk.javadoc.internal.doclets.toolkit.util.DocFinder;
import jdk.javadoc.internal.doclets.toolkit.util.DocFinder.Input;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
/**
* An inline taglet representing the {@code {@inheritDoc}} tag. This tag should only
* be used with a method. It is used to inherit documentation from overridden
* and implemented methods.
* An inline taglet representing the {@code {@inheritDoc}} tag.
* It is used to copy documentation from superclass (but not superinterface)
* declarations and from overridden and implemented methods.
*/
public class InheritDocTaglet extends BaseTaglet {
/**
* Construct a new InheritDocTaglet.
*/
public InheritDocTaglet () {
public InheritDocTaglet() {
super(DocTree.Kind.INHERIT_DOC, true, EnumSet.of(Location.TYPE, Location.METHOD));
}
/**
* Given an element, a {@code DocTree} in the element's doc comment
* replace all occurrences of @inheritDoc with documentation from its
* replace all occurrences of {@code {@inheritDoc}} with documentation from its
* superclass or superinterface.
*
* @param writer the writer that is writing the output.
* @param e the {@link Element} that we are documenting.
* @param holderTag the tag that holds the inheritDoc tag or null for type
* (class) docs.
* @param isFirstSentence true if we only want to inherit the first sentence.
*
* @param holderTag
*
* either the tag that holds the {@code {@inheritDoc}} tag or {@code null},
* which can mean either of:
* <ul>
* <li>the tag is used on a class {@link jdk.javadoc.doclet.Taglet.Location#TYPE} declaration, or
* <li>the tag is used to copy the overall doc comment
* </ul>
*
* @param isFirstSentence true if we only want to inherit the first sentence
*/
private Content retrieveInheritedDocumentation(TagletWriter writer,
Element e, DocTree holderTag, boolean isFirstSentence) {
Element e,
DocTree holderTag,
boolean isFirstSentence) {
Content replacement = writer.getOutputInstance();
BaseConfiguration configuration = writer.configuration();
Messages messages = configuration.getMessages();
Utils utils = configuration.utils;
CommentHelper ch = utils.getCommentHelper(e);
Taglet inheritableTaglet = holderTag == null
Taglet taglet = holderTag == null
? null
: configuration.tagletManager.getTaglet(ch.getTagName(holderTag));
if (inheritableTaglet != null &&
!(inheritableTaglet instanceof InheritableTaglet)) {
String message = utils.getSimpleName(e) +
((utils.isExecutableElement(e))
? utils.flatSignature((ExecutableElement)e, writer.getCurrentPageElement())
: "");
//This tag does not support inheritance.
var path = writer.configuration().utils.getCommentHelper(e).getDocTreePath(holderTag);
messages.warning(path, "doclet.inheritDocWithinInappropriateTag", message);
return replacement;
if (taglet != null && !(taglet instanceof InheritableTaglet)) {
// This tag does not support inheritance.
var path = writer.configuration().utils.getCommentHelper(e).getDocTreePath(holderTag);
messages.warning(path, "doclet.inheritDocWithinInappropriateTag");
return replacement;
}
Input input = new DocFinder.Input(utils, e,
(InheritableTaglet) inheritableTaglet, new DocFinder.DocTreeInfo(holderTag, e),
isFirstSentence, true);
var input = new DocFinder.Input(utils, e, (InheritableTaglet) taglet,
new DocFinder.DocTreeInfo(holderTag, e), isFirstSentence, true);
DocFinder.Output inheritedDoc = DocFinder.search(configuration, input);
if (inheritedDoc.isValidInheritDocTag) {
if (!inheritedDoc.inlineTags.isEmpty()) {
replacement = writer.commentTagsToOutput(inheritedDoc.holder, inheritedDoc.holderTag,
inheritedDoc.inlineTags, isFirstSentence);
inheritedDoc.inlineTags, isFirstSentence);
}
} else {
String message = utils.getSimpleName(e) +
// This is to assert that we don't reach here for a class declaration.
// Indeed, every class except for java.lang.Object has a superclass.
// If we ever reach here, we would need a different warning; because
// the below warning is about method declarations, not class declarations.
// Unless @inheritDoc is used inside java.lang.Object itself,
// which would clearly be an error, we shouldn't reach here.
assert !(e instanceof TypeElement typeElement)
|| typeElement.getSuperclass().getKind() == TypeKind.NONE;
String signature = utils.getSimpleName(e) +
((utils.isExecutableElement(e))
? utils.flatSignature((ExecutableElement)e, writer.getCurrentPageElement())
: "");
messages.warning(e, "doclet.noInheritedDoc", message);
? utils.flatSignature((ExecutableElement) e, writer.getCurrentPageElement())
: e.toString());
messages.warning(e, "doclet.noInheritedDoc", signature);
}
return replacement;
}

View File

@ -28,7 +28,7 @@ package jdk.javadoc.internal.doclets.toolkit.taglets;
import jdk.javadoc.internal.doclets.toolkit.util.DocFinder;
/**
* A taglet should implement this interface if it supports an {@code @inheritDoc}
* A taglet should implement this interface if it supports an {@code {@inheritDoc}}
* tag or is automatically inherited if it is missing.
*/
public interface InheritableTaglet extends Taglet {

View File

@ -68,7 +68,7 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
* check.
* @return a name-rank number map.
*/
private static Map<String, String> getRankMap(Utils utils, List<? extends Element> params){
private static Map<String, String> getRankMap(Utils utils, List<? extends Element> params) {
if (params == null) {
return null;
}
@ -88,14 +88,14 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
public void inherit(DocFinder.Input input, DocFinder.Output output) {
Utils utils = input.utils;
if (input.tagId == null) {
input.isTypeVariableParamTag = ((ParamTree)input.docTreeInfo.docTree).isTypeParameter();
ExecutableElement ee = (ExecutableElement)input.docTreeInfo.element;
input.isTypeVariableParamTag = ((ParamTree) input.docTreeInfo.docTree()).isTypeParameter();
ExecutableElement ee = (ExecutableElement) input.docTreeInfo.element();
CommentHelper ch = utils.getCommentHelper(ee);
List<? extends Element> parameters = input.isTypeVariableParamTag
? ee.getTypeParameters()
: ee.getParameters();
String target = ch.getParameterName(input.docTreeInfo.docTree);
for (int i = 0 ; i < parameters.size(); i++) {
String target = ch.getParameterName(input.docTreeInfo.docTree());
for (int i = 0; i < parameters.size(); i++) {
Element e = parameters.get(i);
String pname = input.isTypeVariableParamTag
? utils.getTypeName(e.asType(), false)
@ -106,7 +106,7 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
}
}
}
ExecutableElement md = (ExecutableElement)input.element;
ExecutableElement md = (ExecutableElement) input.element;
CommentHelper ch = utils.getCommentHelper(md);
List<? extends DocTree> tags = input.isTypeVariableParamTag
? utils.getTypeParamTrees(md)
@ -132,14 +132,14 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
if (utils.isExecutableElement(holder)) {
ExecutableElement member = (ExecutableElement) holder;
Content output = getTagletOutput(ParamKind.TYPE_PARAMETER, member, writer,
member.getTypeParameters(), utils.getTypeParamTrees(member));
member.getTypeParameters(), utils.getTypeParamTrees(member));
output.add(getTagletOutput(ParamKind.PARAMETER, member, writer,
member.getParameters(), utils.getParamTrees(member)));
member.getParameters(), utils.getParamTrees(member)));
return output;
} else {
TypeElement typeElement = (TypeElement) holder;
Content output = getTagletOutput(ParamKind.TYPE_PARAMETER, typeElement, writer,
typeElement.getTypeParameters(), utils.getTypeParamTrees(typeElement));
typeElement.getTypeParameters(), utils.getTypeParamTrees(typeElement));
output.add(getTagletOutput(ParamKind.RECORD_COMPONENT, typeElement, writer,
typeElement.getRecordComponents(), utils.getParamTrees(typeElement)));
return output;
@ -157,8 +157,11 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
*
* @return the content representation of these {@code @param DocTree}s.
*/
private Content getTagletOutput(ParamKind kind, Element holder,
TagletWriter writer, List<? extends Element> formalParameters, List<? extends ParamTree> paramTags) {
private Content getTagletOutput(ParamKind kind,
Element holder,
TagletWriter writer,
List<? extends Element> formalParameters,
List<? extends ParamTree> paramTags) {
Content result = writer.getOutputInstance();
result.add(processParamTags(holder, kind, paramTags, formalParameters, writer));
return result;
@ -167,15 +170,18 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
/**
* Try to get the inherited taglet documentation for a specific parameter.
*/
private Content getInheritedTagletOutput(ParamKind kind, Element holder,
TagletWriter writer, Element param, int rank,
private Content getInheritedTagletOutput(ParamKind kind,
Element holder,
TagletWriter writer,
Element param,
int rank,
boolean isFirst) {
Utils utils = writer.configuration().utils;
Content result = writer.getOutputInstance();
Input input = new DocFinder.Input(writer.configuration().utils, holder, this,
Integer.toString(rank), kind == ParamKind.TYPE_PARAMETER);
DocFinder.Output inheritedDoc = DocFinder.search(writer.configuration(), input);
if (inheritedDoc.inlineTags != null && !inheritedDoc.inlineTags.isEmpty()) {
if (!inheritedDoc.inlineTags.isEmpty()) {
String lname = kind != ParamKind.TYPE_PARAMETER
? utils.getSimpleName(param)
: utils.getTypeName(param.asType(), false);
@ -197,20 +203,23 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
* @param writer the TagletWriter that will write this tag.
* @return the Content representation of this {@code @param DocTree}.
*/
private Content processParamTags(Element e, ParamKind kind, List<? extends ParamTree> paramTags,
List<? extends Element> formalParameters, TagletWriter writer) {
private Content processParamTags(Element e,
ParamKind kind,
List<? extends ParamTree> paramTags,
List<? extends Element> formalParameters,
TagletWriter writer) {
Map<String, ParamTree> documented = new HashMap<>();
Messages messages = writer.configuration().getMessages();
CommentHelper ch = writer.configuration().utils.getCommentHelper(e);
if (!paramTags.isEmpty()) {
Map<String,String> rankMap = getRankMap(writer.configuration().utils, formalParameters);
Map<String, String> rankMap = getRankMap(writer.configuration().utils, formalParameters);
for (ParamTree dt : paramTags) {
String name = ch.getParameterName(dt);
String paramName = kind == ParamKind.TYPE_PARAMETER ? "<" + name + ">" : name;
if (!rankMap.containsKey(name)) {
String key = switch (kind) {
case PARAMETER -> "doclet.Parameters_warn";
case TYPE_PARAMETER -> "doclet.TypeParameters_warn";
case PARAMETER -> "doclet.Parameters_warn";
case TYPE_PARAMETER -> "doclet.TypeParameters_warn";
case RECORD_COMPONENT -> "doclet.RecordComponents_warn";
};
messages.warning(ch.getDocTreePath(dt), key, paramName);
@ -269,9 +278,12 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
* @param isFirstParam true if this is the first param tag being printed.
*
*/
private Content processParamTag(Element e, ParamKind kind,
TagletWriter writer, ParamTree paramTag, String name,
boolean isFirstParam) {
private Content processParamTag(Element e,
ParamKind kind,
TagletWriter writer,
ParamTree paramTag,
String name,
boolean isFirstParam) {
Content result = writer.getOutputInstance();
if (isFirstParam) {
result.add(writer.getParamHeader(kind));

View File

@ -94,7 +94,7 @@ public class ReturnTaglet extends BaseTaglet implements InheritableTaglet {
List<? extends ReturnTree> tags = utils.getReturnTrees(holder);
// Make sure we are not using @return tag on method with void return type.
TypeMirror returnType = utils.getReturnType(writer.getCurrentPageElement(), (ExecutableElement)holder);
TypeMirror returnType = utils.getReturnType(writer.getCurrentPageElement(), (ExecutableElement) holder);
if (returnType != null && utils.isVoid(returnType)) {
if (!tags.isEmpty()) {
messages.warning(holder, "doclet.Return_tag_on_void_method");

View File

@ -52,7 +52,7 @@ public class SeeTaglet extends BaseTaglet implements InheritableTaglet {
public void inherit(DocFinder.Input input, DocFinder.Output output) {
List<? extends SeeTree> tags = input.utils.getSeeTrees(input.element);
if (!tags.isEmpty()) {
CommentHelper ch = input.utils.getCommentHelper(input.element);
CommentHelper ch = input.utils.getCommentHelper(input.element);
output.holder = input.element;
output.holderTag = tags.get(0);
output.inlineTags = input.isFirstSentence

View File

@ -55,8 +55,7 @@ import jdk.javadoc.internal.doclets.toolkit.util.Utils;
/**
* A taglet that represents the {@code @throws} tag.
*/
public class ThrowsTaglet extends BaseTaglet
implements InheritableTaglet {
public class ThrowsTaglet extends BaseTaglet implements InheritableTaglet {
public ThrowsTaglet() {
super(DocTree.Kind.THROWS, false, EnumSet.of(Location.CONSTRUCTOR, Location.METHOD));
@ -68,10 +67,10 @@ public class ThrowsTaglet extends BaseTaglet
Element exception;
CommentHelper ch = utils.getCommentHelper(input.element);
if (input.tagId == null) {
exception = input.docTreeInfo.docTree instanceof ThrowsTree tt
exception = input.docTreeInfo.docTree() instanceof ThrowsTree tt
? ch.getException(tt) : null;
input.tagId = exception == null
? ch.getExceptionName(input.docTreeInfo.docTree).getSignature()
? ch.getExceptionName(input.docTreeInfo.docTree()).getSignature()
: utils.getFullyQualifiedName(exception);
} else {
exception = input.utils.findClass(input.element, input.tagId);
@ -80,14 +79,14 @@ public class ThrowsTaglet extends BaseTaglet
for (ThrowsTree tt : input.utils.getThrowsTrees(input.element)) {
Element exc = ch.getException(tt);
if (exc != null && (input.tagId.equals(utils.getSimpleName(exc)) ||
(input.tagId.equals(utils.getFullyQualifiedName(exc))))) {
(input.tagId.equals(utils.getFullyQualifiedName(exc))))) {
output.holder = input.element;
output.holderTag = tt;
output.inlineTags = ch.getBody(output.holderTag);
output.tagList.add(tt);
} else if (exception != null && exc != null &&
utils.isTypeElement(exc) && utils.isTypeElement(exception) &&
utils.isSubclassOf((TypeElement)exc, (TypeElement)exception)) {
utils.isSubclassOf((TypeElement) exc, (TypeElement) exception)) {
output.tagList.add(tt);
}
}
@ -97,15 +96,16 @@ public class ThrowsTaglet extends BaseTaglet
* Add links for exceptions that are declared but not documented.
*/
private Content linkToUndocumentedDeclaredExceptions(List<? extends TypeMirror> declaredExceptionTypes,
Set<String> alreadyDocumented, TagletWriter writer) {
Set<String> alreadyDocumented,
TagletWriter writer) {
Utils utils = writer.configuration().utils;
Content result = writer.getOutputInstance();
//Add links to the exceptions declared but not documented.
for (TypeMirror declaredExceptionType : declaredExceptionTypes) {
TypeElement te = utils.asTypeElement(declaredExceptionType);
if (te != null &&
!alreadyDocumented.contains(declaredExceptionType.toString()) &&
!alreadyDocumented.contains(utils.getFullyQualifiedName(te, false))) {
!alreadyDocumented.contains(declaredExceptionType.toString()) &&
!alreadyDocumented.contains(utils.getFullyQualifiedName(te, false))) {
if (alreadyDocumented.isEmpty()) {
result.add(writer.getThrowsHeader());
}
@ -121,8 +121,10 @@ public class ThrowsTaglet extends BaseTaglet
* documented.
*/
private Content inheritThrowsDocumentation(Element holder,
List<? extends TypeMirror> declaredExceptionTypes, Set<String> alreadyDocumented,
Map<String, TypeMirror> typeSubstitutions, TagletWriter writer) {
List<? extends TypeMirror> declaredExceptionTypes,
Set<String> alreadyDocumented,
Map<String, TypeMirror> typeSubstitutions,
TagletWriter writer) {
Utils utils = writer.configuration().utils;
Content result = writer.getOutputInstance();
if (utils.isMethod(holder)) {
@ -157,7 +159,7 @@ public class ThrowsTaglet extends BaseTaglet
Utils utils = writer.configuration().utils;
ExecutableElement execHolder = (ExecutableElement) holder;
ExecutableType instantiatedType = utils.asInstantiatedMethodType(
writer.getCurrentPageElement(), (ExecutableElement)holder);
writer.getCurrentPageElement(), (ExecutableElement) holder);
List<? extends TypeMirror> thrownTypes = instantiatedType.getThrownTypes();
Map<String, TypeMirror> typeSubstitutions = getSubstitutedThrownTypes(
writer.configuration().utils.typeUtils,
@ -186,8 +188,10 @@ public class ThrowsTaglet extends BaseTaglet
* @return the generated content for the tags
*/
protected Content throwsTagsOutput(Map<List<? extends ThrowsTree>, ExecutableElement> throwTags,
TagletWriter writer, Set<String> alreadyDocumented,
Map<String,TypeMirror> typeSubstitutions, boolean allowDuplicates) {
TagletWriter writer,
Set<String> alreadyDocumented,
Map<String, TypeMirror> typeSubstitutions,
boolean allowDuplicates) {
Utils utils = writer.configuration().utils;
Content result = writer.getOutputInstance();
if (!throwTags.isEmpty()) {
@ -199,9 +203,9 @@ public class ThrowsTaglet extends BaseTaglet
String excName = ch.getExceptionName(dt).toString();
TypeMirror substituteType = typeSubstitutions.get(excName);
if ((!allowDuplicates) &&
(alreadyDocumented.contains(excName) ||
(te != null && alreadyDocumented.contains(utils.getFullyQualifiedName(te, false)))) ||
(substituteType != null && alreadyDocumented.contains(substituteType.toString()))) {
(alreadyDocumented.contains(excName) ||
(te != null && alreadyDocumented.contains(utils.getFullyQualifiedName(te, false)))) ||
(substituteType != null && alreadyDocumented.contains(substituteType.toString()))) {
continue;
}
if (alreadyDocumented.isEmpty()) {

View File

@ -25,7 +25,6 @@
package jdk.javadoc.internal.doclets.toolkit.util;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@ -578,10 +577,9 @@ public class CommentHelper {
public List<? extends DocTree> getTags(DocTree dtree) {
return new SimpleDocTreeVisitor<List<? extends DocTree>, Void>() {
List<? extends DocTree> asList(String content) {
List<DocTree> out = new ArrayList<>();
out.add(configuration.cmtUtils.makeTextTree(content));
return out;
private List<DocTree> asList(String content) {
return List.of(configuration.cmtUtils.makeTextTree(content));
}
@Override
@ -611,7 +609,7 @@ public class CommentHelper {
@Override
public List<? extends DocTree> visitProvides(ProvidesTree node, Void p) {
return node.getDescription();
return node.getDescription();
}
@Override
@ -631,7 +629,7 @@ public class CommentHelper {
@Override
public List<? extends DocTree> visitParam(ParamTree node, Void p) {
return node.getDescription();
return node.getDescription();
}
@Override
@ -661,7 +659,7 @@ public class CommentHelper {
@Override
public List<? extends DocTree> visitThrows(ThrowsTree node, Void p) {
return node.getDescription();
return node.getDescription();
}
@Override
@ -671,12 +669,12 @@ public class CommentHelper {
@Override
public List<? extends DocTree> visitUses(UsesTree node, Void p) {
return node.getDescription();
return node.getDescription();
}
@Override
protected List<? extends DocTree> defaultAction(DocTree node, Void p) {
return List.of();
return List.of();
}
}.visit(dtree, null);
}

View File

@ -41,87 +41,67 @@ import jdk.javadoc.internal.doclets.toolkit.taglets.InheritableTaglet;
*/
public class DocFinder {
public static final class DocTreeInfo {
public final DocTree docTree;
public final Element element;
public DocTreeInfo() {
this.docTree = null;
this.element = null;
}
public DocTreeInfo(DocTree docTree, Element baseElement) {
this.docTree = docTree;
this.element = baseElement;
}
@Override
public String toString() {
return "DocTreeInfo{" + "docTree=" + docTree + ", element=" + element + '}';
}
}
public record DocTreeInfo(DocTree docTree, Element element) { }
/**
* The class that encapsulates the input.
*/
public static class Input {
/**
* The element to search documentation from.
*/
public Element element;
/**
* The taglet to search for documentation on behalf of. Null if we want
* to search for overall documentation.
*/
public InheritableTaglet taglet = null;
public InheritableTaglet taglet;
/**
* The id of the tag to retrieve documentation for.
*/
public String tagId = null;
public String tagId;
/**
* The tag to retrieve documentation for. This is only used for the
* inheritDoc tag.
* {@code {@inheritDoc}} tag.
*/
public final DocTreeInfo docTreeInfo;
/**
* True if we only want to search for the first sentence.
*/
public boolean isFirstSentence = false;
public boolean isFirstSentence;
/**
* True if we are looking for documentation to replace the inheritDocTag.
* True if we are looking for documentation to replace the {@code {@inheritDoc}} tag.
*/
public boolean isInheritDocTag = false;
public boolean isInheritDocTag;
/**
* Used to distinguish between type variable param tags and regular
* param tags.
*/
public boolean isTypeVariableParamTag = false;
public boolean isTypeVariableParamTag;
public final Utils utils;
public Input(Utils utils, Element element, InheritableTaglet taglet, DocTreeInfo dtInfo,
boolean isFirstSentence, boolean isInheritDocTag) {
this.utils = utils;
this.element = element;
this.taglet = taglet;
this.isFirstSentence = isFirstSentence;
this.isInheritDocTag = isInheritDocTag;
this.docTreeInfo = dtInfo;
}
public Input(Utils utils, Element element, InheritableTaglet taglet, String tagId) {
public Input(Utils utils,
Element element,
InheritableTaglet taglet,
String tagId) {
this(utils, element);
this.taglet = taglet;
this.tagId = tagId;
}
public Input(Utils utils, Element element, InheritableTaglet taglet, String tagId,
boolean isTypeVariableParamTag) {
public Input(Utils utils,
Element element,
InheritableTaglet taglet,
String tagId,
boolean isTypeVariableParamTag) {
this(utils, element);
this.taglet = taglet;
this.tagId = tagId;
@ -134,32 +114,35 @@ public class DocFinder {
}
public Input(Utils utils, Element element) {
if (element == null)
throw new NullPointerException();
this.element = element;
this.element = Objects.requireNonNull(element);
this.utils = utils;
this.docTreeInfo = new DocTreeInfo();
this.docTreeInfo = new DocTreeInfo(null, null);
}
public Input(Utils utils, Element element, boolean isFirstSentence) {
this(utils, element);
public Input(Utils utils,
Element element,
InheritableTaglet taglet,
DocTreeInfo dtInfo,
boolean isFirstSentence,
boolean isInheritDocTag) {
this.utils = utils;
this.element = Objects.requireNonNull(element);
this.taglet = taglet;
this.isFirstSentence = isFirstSentence;
this.isInheritDocTag = isInheritDocTag;
this.docTreeInfo = dtInfo;
}
public Input copy(Utils utils) {
if (this.element == null) {
throw new NullPointerException();
}
Input clone = new Input(utils, this.element, this.taglet, this.docTreeInfo,
this.isFirstSentence, this.isInheritDocTag);
clone.tagId = this.tagId;
clone.isTypeVariableParamTag = this.isTypeVariableParamTag;
return clone;
private Input copy() {
var copy = new Input(utils, element, taglet, docTreeInfo,
isFirstSentence, isInheritDocTag);
copy.tagId = tagId;
copy.isTypeVariableParamTag = isTypeVariableParamTag;
return copy;
}
/**
* For debugging purposes
* @return string representation
* For debugging purposes.
*/
@Override
public String toString() {
@ -178,6 +161,7 @@ public class DocFinder {
* The class that encapsulates the output.
*/
public static class Output {
/**
* The tag that holds the documentation. Null if documentation
* is not held by a tag.
@ -185,7 +169,7 @@ public class DocFinder {
public DocTree holderTag;
/**
* The Doc object that holds the documentation.
* The element that holds the documentation.
*/
public Element holder;
@ -200,18 +184,16 @@ public class DocFinder {
public boolean isValidInheritDocTag = true;
/**
* When automatically inheriting throws tags, you sometime must inherit
* more than one tag. For example if the element declares that it throws
* IOException and the overridden element has throws tags for IOException and
* When automatically inheriting throws tags, you sometimes must inherit
* more than one tag. For example, if a method declares that it throws
* IOException and the overridden method has {@code @throws} tags for IOException and
* ZipException, both tags would be inherited because ZipException is a
* subclass of IOException. This subclass of DocFinder.Output allows
* multiple tag inheritance.
* subclass of IOException. This allows multiple tag inheritance.
*/
public List<DocTree> tagList = new ArrayList<>();
public final List<DocTree> tagList = new ArrayList<>();
/**
* Returns a string representation for debugging purposes
* @return string
* For debugging purposes.
*/
@Override
public String toString() {
@ -226,9 +208,7 @@ public class DocFinder {
/**
* Search for the requested comments in the given element. If it does not
* have comments, return documentation from the overridden element if possible.
* If the overridden element does not exist or does not have documentation to
* inherit, search for documentation to inherit from implemented methods.
* have comments, return the inherited comments if possible.
*
* @param input the input object used to perform the search.
*
@ -250,14 +230,15 @@ public class DocFinder {
input.taglet.inherit(input, output);
}
if (output.inlineTags != null && !output.inlineTags.isEmpty()) {
if (!output.inlineTags.isEmpty()) {
return output;
}
output.isValidInheritDocTag = false;
Input inheritedSearchInput = input.copy(configuration.utils);
Input inheritedSearchInput = input.copy();
inheritedSearchInput.isInheritDocTag = false;
if (utils.isMethod(input.element)) {
ExecutableElement overriddenMethod = utils.overriddenMethod((ExecutableElement) input.element);
ExecutableElement m = (ExecutableElement) input.element;
ExecutableElement overriddenMethod = utils.overriddenMethod(m);
if (overriddenMethod != null) {
inheritedSearchInput.element = overriddenMethod;
output = search(configuration, inheritedSearchInput);
@ -266,13 +247,9 @@ public class DocFinder {
return output;
}
}
//NOTE: When we fix the bug where ClassDoc.interfaceTypes() does
// not pass all implemented interfaces, we will use the
// appropriate element here.
TypeElement encl = utils.getEnclosingTypeElement(input.element);
VisibleMemberTable vmt = configuration.getVisibleMemberTable(encl);
List<ExecutableElement> implementedMethods =
vmt.getImplementedMethods((ExecutableElement)input.element);
List<ExecutableElement> implementedMethods = vmt.getImplementedMethods(m);
for (ExecutableElement implementedMethod : implementedMethods) {
inheritedSearchInput.element = implementedMethod;
output = search(configuration, inheritedSearchInput);

View File

@ -2500,7 +2500,7 @@ public class Utils {
}
public List<? extends ReturnTree> getReturnTrees(Element element) {
return new ArrayList<>(getBlockTags(element, RETURN, ReturnTree.class));
return getBlockTags(element, RETURN, ReturnTree.class);
}
public List<? extends UsesTree> getUsesTrees(Element element) {

View File

@ -202,7 +202,7 @@ public class VisibleMemberTable {
* a. The list may or may not contain simple overridden methods.
* A simple overridden method is one that overrides a super method
* with no specification changes as indicated by the existence of a
* sole {@code @inheritDoc} or devoid of any API comments.
* sole {@code {@inheritDoc}} or devoid of any API comments.
* <p>
* b.The list may contain (extra) members, inherited by inaccessible
* super types, primarily package private types. These members are