Skip to content
This repository has been archived by the owner on Sep 19, 2023. It is now read-only.
/ jdk19 Public archive

Commit

Permalink
8067757: Incorrect HTML generation for copied javadoc with multiple @…
Browse files Browse the repository at this point in the history
…throws tags

Reviewed-by: jjg
  • Loading branch information
Pavel Rappo committed Jul 4, 2022
1 parent 0dff327 commit f640fc5
Show file tree
Hide file tree
Showing 5 changed files with 405 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ public Content throwsTagOutput(Element element, ThrowsTree throwsTag, TypeMirror
excName = htmlWriter.getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.MEMBER,
substituteType));
} else if (exception == null) {
excName = new RawHtml(ch.getExceptionName(throwsTag).toString());
excName = new RawHtml(throwsTag.getExceptionName().toString());
} else if (exception.asType() == null) {
excName = new RawHtml(utils.getFullyQualifiedName(exception));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@

import jdk.javadoc.doclet.Taglet.Location;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
import jdk.javadoc.internal.doclets.toolkit.util.DocFinder;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;

/**
* A taglet that processes {@link ThrowsTree}, which represents
Expand All @@ -64,14 +62,14 @@ public ThrowsTaglet() {

@Override
public void inherit(DocFinder.Input input, DocFinder.Output output) {
Utils utils = input.utils;
var utils = input.utils;
Element target;
CommentHelper ch = utils.getCommentHelper(input.element);
var ch = utils.getCommentHelper(input.element);
if (input.tagId == null) {
var tag = (ThrowsTree) input.docTreeInfo.docTree();
target = ch.getException(tag);
input.tagId = target == null
? ch.getExceptionName(tag).getSignature()
? tag.getExceptionName().getSignature()
: utils.getFullyQualifiedName(target);
} else {
target = input.utils.findClass(input.element, input.tagId);
Expand All @@ -97,20 +95,20 @@ public void inherit(DocFinder.Input input, DocFinder.Output output) {

@Override
public Content getAllBlockTagOutput(Element holder, TagletWriter writer) {
Utils utils = writer.configuration().utils;
var utils = writer.configuration().utils;
var executable = (ExecutableElement) holder;
ExecutableType instantiatedType = utils.asInstantiatedMethodType(
writer.getCurrentPageElement(), executable);
List<? extends TypeMirror> thrownTypes = instantiatedType.getThrownTypes();
Map<String, TypeMirror> typeSubstitutions = getSubstitutedThrownTypes(
writer.configuration().utils.typeUtils,
utils.typeUtils,
executable.getThrownTypes(),
thrownTypes);
Map<List<ThrowsTree>, ExecutableElement> tagsMap = new LinkedHashMap<>();
tagsMap.put(utils.getThrowsTrees(executable), executable);
Map<ThrowsTree, ExecutableElement> tagsMap = new LinkedHashMap<>();
utils.getThrowsTrees(executable).forEach(t -> tagsMap.put(t, executable));
Content result = writer.getOutputInstance();
Set<String> alreadyDocumented = new HashSet<>();
result.add(throwsTagsOutput(tagsMap, writer, alreadyDocumented, typeSubstitutions, true));
result.add(throwsTagsOutput(tagsMap, alreadyDocumented, typeSubstitutions, writer));
result.add(inheritThrowsDocumentation(executable, thrownTypes, alreadyDocumented, typeSubstitutions, writer));
result.add(linkToUndocumentedDeclaredExceptions(thrownTypes, alreadyDocumented, writer));
return result;
Expand Down Expand Up @@ -145,45 +143,48 @@ private Map<String, TypeMirror> getSubstitutedThrownTypes(Types types,
/**
* Returns the generated content for a collection of {@code @throws} tags.
*
* @param throwsTags the collection of tags to be converted
* @param throwsTags the tags to be converted; each tag is mapped to
* a method it appears on
* @param alreadyDocumented the set of exceptions that have already been
* documented and thus must not be documented by
* this method. All exceptions documented by this
* method will be added to this set upon the
* method's return.
* @param writer the taglet-writer used by the doclet
* @param alreadyDocumented the set of exceptions that have already been documented
* @param allowDuplicates {@code true} if we allow duplicate tags to be documented
* @return the generated content for the tags
*/
protected Content throwsTagsOutput(Map<List<ThrowsTree>, ExecutableElement> throwsTags,
TagletWriter writer,
Set<String> alreadyDocumented,
Map<String, TypeMirror> typeSubstitutions,
boolean allowDuplicates) {
Utils utils = writer.configuration().utils;
private Content throwsTagsOutput(Map<ThrowsTree, ExecutableElement> throwsTags,
Set<String> alreadyDocumented,
Map<String, TypeMirror> typeSubstitutions,
TagletWriter writer) {
var utils = writer.configuration().utils;
Content result = writer.getOutputInstance();
for (Entry<List<ThrowsTree>, ExecutableElement> entry : throwsTags.entrySet()) {
var documentedInThisCall = new HashSet<String>();
for (Entry<ThrowsTree, ExecutableElement> entry : throwsTags.entrySet()) {
Element e = entry.getValue();
CommentHelper ch = utils.getCommentHelper(e);
for (ThrowsTree tag : entry.getKey()) {
Element te = ch.getException(tag);
String excName = ch.getExceptionName(tag).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()))) {
continue;
}
if (alreadyDocumented.isEmpty()) {
result.add(writer.getThrowsHeader());
}
result.add(writer.throwsTagOutput(e, tag, substituteType));
if (substituteType != null) {
alreadyDocumented.add(substituteType.toString());
} else {
alreadyDocumented.add(te != null
? utils.getFullyQualifiedName(te, false)
: excName);
}
var ch = utils.getCommentHelper(e);
ThrowsTree tag = entry.getKey();
Element te = ch.getException(tag);
String excName = tag.getExceptionName().toString();
TypeMirror substituteType = typeSubstitutions.get(excName);
if (alreadyDocumented.contains(excName)
|| (te != null && alreadyDocumented.contains(utils.getFullyQualifiedName(te, false)))
|| (substituteType != null && alreadyDocumented.contains(substituteType.toString()))) {
continue;
}
if (alreadyDocumented.isEmpty() && documentedInThisCall.isEmpty()) {
result.add(writer.getThrowsHeader());
}
result.add(writer.throwsTagOutput(e, tag, substituteType));
if (substituteType != null) {
documentedInThisCall.add(substituteType.toString());
} else {
documentedInThisCall.add(te != null
? utils.getFullyQualifiedName(te, false)
: excName);
}
}
alreadyDocumented.addAll(documentedInThisCall);
return result;
}

Expand All @@ -205,8 +206,8 @@ private Content inheritThrowsDocumentation(ExecutableElement holder,
assert holder.getKind() == ElementKind.CONSTRUCTOR : holder.getKind();
return result;
}
Utils utils = writer.configuration().utils;
Map<List<ThrowsTree>, ExecutableElement> declaredExceptionTags = new LinkedHashMap<>();
var utils = writer.configuration().utils;
Map<ThrowsTree, ExecutableElement> declaredExceptionTags = new LinkedHashMap<>();
for (TypeMirror declaredExceptionType : declaredExceptionTypes) {
var input = new DocFinder.Input(utils, holder, this,
utils.getTypeName(declaredExceptionType, false));
Expand All @@ -220,22 +221,20 @@ private Content inheritThrowsDocumentation(ExecutableElement holder,
if (inheritedDoc.holder == null) {
inheritedDoc.holder = holder;
}
List<ThrowsTree> inheritedTags = inheritedDoc.tagList.stream()
.map(t -> (ThrowsTree) t)
.toList();
declaredExceptionTags.put(inheritedTags, (ExecutableElement) inheritedDoc.holder);
var h = (ExecutableElement) inheritedDoc.holder;
inheritedDoc.tagList.forEach(t -> declaredExceptionTags.put((ThrowsTree) t, h));
}
}
result.add(throwsTagsOutput(declaredExceptionTags, writer, alreadyDocumented,
typeSubstitutions, false));
result.add(throwsTagsOutput(declaredExceptionTags, alreadyDocumented, typeSubstitutions,
writer));
return result;
}

private Content linkToUndocumentedDeclaredExceptions(List<? extends TypeMirror> declaredExceptionTypes,
Set<String> alreadyDocumented,
TagletWriter writer) {
// TODO: assert declaredExceptionTypes are instantiated
Utils utils = writer.configuration().utils;
var utils = writer.configuration().utils;
Content result = writer.getOutputInstance();
for (TypeMirror declaredExceptionType : declaredExceptionTypes) {
TypeElement te = utils.asTypeElement(declaredExceptionType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -547,10 +547,6 @@ public List<? extends DocTree> getReference(DocTree dtree) {
return dtree.getKind() == SEE ? ((SeeTree)dtree).getReference() : null;
}

public ReferenceTree getExceptionName(ThrowsTree tt) {
return tt.getExceptionName();
}

public IdentifierTree getName(DocTree dtree) {
switch (dtree.getKind()) {
case PARAM:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public void test1() {
checkExit(Exit.OK);

// The method should not inherit the IOOBE throws tag from the abstract class,
// for now keep keep this bug compatible, should fix this correctly in
// for now keep this bug compatible, should fix this correctly in
// the future.
checkOutput("pkg/Extender.html", false, "java.lang.IndexOutOfBoundsException");
}
Expand Down
Loading

1 comment on commit f640fc5

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.