8259216: javadoc omits method receiver for any nested type annotation

Reviewed-by: hannesw
This commit is contained in:
liach 2021-01-15 15:12:34 +00:00 committed by Hannes Wallnöfer
parent bcf20a0dcc
commit eb7fa00690
3 changed files with 78 additions and 34 deletions

View File

@ -27,7 +27,6 @@ package jdk.javadoc.internal.doclets.formats.html;
import java.util.List; import java.util.List;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element; import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind; import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.ExecutableElement;
@ -38,7 +37,7 @@ import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType; import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable; import javax.lang.model.type.TypeVariable;
import javax.lang.model.util.SimpleTypeVisitor9; import javax.lang.model.util.SimpleTypeVisitor14;
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
@ -152,24 +151,56 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
} }
/** /**
* Add the receiver annotations information. * Add the receiver information.
*
* <p>Note: receivers can only have type-use annotations.</p>
* *
* @param member the member to write receiver annotations for. * @param member the member to write receiver annotations for.
* @param rcvrType the receiver type. * @param rcvrType the receiver type.
* @param annotationMirrors list of annotation descriptions.
* @param tree the content tree to which the information will be added. * @param tree the content tree to which the information will be added.
*/ */
protected void addReceiverAnnotations(ExecutableElement member, TypeMirror rcvrType, protected void addReceiver(ExecutableElement member, TypeMirror rcvrType, Content tree) {
List<? extends AnnotationMirror> annotationMirrors, Content tree) { var info = new LinkInfoImpl(configuration, RECEIVER_TYPE, rcvrType);
tree.add(writer.getAnnotationInfo(member.getReceiverType().getAnnotationMirrors(), false)); info.linkToSelf = false;
tree.add(Entity.NO_BREAK_SPACE); tree.add(writer.getLink(info));
tree.add(utils.getTypeName(rcvrType, false));
LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, RECEIVER_TYPE, rcvrType);
tree.add(writer.getTypeParameterLinks(linkInfo));
tree.add(Entity.NO_BREAK_SPACE); tree.add(Entity.NO_BREAK_SPACE);
if (member.getKind() == ElementKind.CONSTRUCTOR) {
tree.add(utils.getTypeName(rcvrType, false));
tree.add(".");
}
tree.add("this"); tree.add("this");
} }
/**
* Returns {@code true} if a receiver type is annotated anywhere in its type for
* inclusion in member details.
*
* @param receiverType the receiver type.
* @return {@code true} if the receiver is annotated
*/
protected boolean isAnnotatedReceiver(TypeMirror receiverType) {
return new SimpleTypeVisitor14<Boolean, Void>() {
@Override
protected Boolean defaultAction(TypeMirror e, Void unused) {
return utils.isAnnotated(e);
}
@Override
public Boolean visitDeclared(DeclaredType t, Void unused) {
if (super.visitDeclared(t, unused) || visit(t.getEnclosingType())) {
return true;
}
for (var e : t.getTypeArguments()) {
if (visit(e)) {
return true;
}
}
return false;
}
}.visit(receiverType);
}
/** /**
* Add all the parameters for the executable member. * Add all the parameters for the executable member.
@ -199,9 +230,8 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
String sep = ""; String sep = "";
List<? extends VariableElement> parameters = member.getParameters(); List<? extends VariableElement> parameters = member.getParameters();
TypeMirror rcvrType = member.getReceiverType(); TypeMirror rcvrType = member.getReceiverType();
if (includeAnnotations && rcvrType != null && utils.isAnnotated(rcvrType)) { if (includeAnnotations && rcvrType != null && isAnnotatedReceiver(rcvrType)) {
List<? extends AnnotationMirror> annotationMirrors = rcvrType.getAnnotationMirrors(); addReceiver(member, rcvrType, paramTree);
addReceiverAnnotations(member, rcvrType, annotationMirrors, paramTree);
sep = "," + DocletConstants.NL + " "; sep = "," + DocletConstants.NL + " ";
} }
int paramstart; int paramstart;

View File

@ -85,7 +85,7 @@ import javax.lang.model.util.ElementKindVisitor14;
import javax.lang.model.util.Elements; import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleAnnotationValueVisitor14; import javax.lang.model.util.SimpleAnnotationValueVisitor14;
import javax.lang.model.util.SimpleElementVisitor14; import javax.lang.model.util.SimpleElementVisitor14;
import javax.lang.model.util.SimpleTypeVisitor9; import javax.lang.model.util.SimpleTypeVisitor14;
import javax.lang.model.util.TypeKindVisitor9; import javax.lang.model.util.TypeKindVisitor9;
import javax.lang.model.util.Types; import javax.lang.model.util.Types;
import javax.tools.FileObject; import javax.tools.FileObject;
@ -628,7 +628,7 @@ public class Utils {
} }
public boolean isPrimitive(TypeMirror t) { public boolean isPrimitive(TypeMirror t) {
return new SimpleTypeVisitor9<Boolean, Void>() { return new SimpleTypeVisitor14<Boolean, Void>() {
@Override @Override
public Boolean visitNoType(NoType t, Void p) { public Boolean visitNoType(NoType t, Void p) {
@ -733,7 +733,7 @@ public class Utils {
} }
public String getTypeSignature(TypeMirror t, boolean qualifiedName, boolean noTypeParameters) { public String getTypeSignature(TypeMirror t, boolean qualifiedName, boolean noTypeParameters) {
return new SimpleTypeVisitor9<StringBuilder, Void>() { return new SimpleTypeVisitor14<StringBuilder, Void>() {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
@Override @Override
@ -1211,7 +1211,7 @@ public class Utils {
* or null if it is a primitive type. * or null if it is a primitive type.
*/ */
public TypeElement asTypeElement(TypeMirror t) { public TypeElement asTypeElement(TypeMirror t) {
return new SimpleTypeVisitor9<TypeElement, Void>() { return new SimpleTypeVisitor14<TypeElement, Void>() {
@Override @Override
public TypeElement visitDeclared(DeclaredType t, Void p) { public TypeElement visitDeclared(DeclaredType t, Void p) {
@ -1267,7 +1267,7 @@ public class Utils {
* @return the type's dimension information as a string. * @return the type's dimension information as a string.
*/ */
public String getDimension(TypeMirror t) { public String getDimension(TypeMirror t) {
return new SimpleTypeVisitor9<String, Void>() { return new SimpleTypeVisitor14<String, Void>() {
StringBuilder dimension = new StringBuilder(); StringBuilder dimension = new StringBuilder();
@Override @Override
public String visitArray(ArrayType t, Void p) { public String visitArray(ArrayType t, Void p) {
@ -1379,7 +1379,7 @@ public class Utils {
private final Map<String, String> kindNameMap = new HashMap<>(); private final Map<String, String> kindNameMap = new HashMap<>();
public String getTypeName(TypeMirror t, boolean fullyQualified) { public String getTypeName(TypeMirror t, boolean fullyQualified) {
return new SimpleTypeVisitor9<String, Void>() { return new SimpleTypeVisitor14<String, Void>() {
@Override @Override
public String visitArray(ArrayType t, Void p) { public String visitArray(ArrayType t, Void p) {
@ -1764,7 +1764,7 @@ public class Utils {
* @return the fully qualified name of Reference type or the primitive name * @return the fully qualified name of Reference type or the primitive name
*/ */
public String getQualifiedTypeName(TypeMirror t) { public String getQualifiedTypeName(TypeMirror t) {
return new SimpleTypeVisitor9<String, Void>() { return new SimpleTypeVisitor14<String, Void>() {
@Override @Override
public String visitDeclared(DeclaredType t, Void p) { public String visitDeclared(DeclaredType t, Void p) {
return getFullyQualifiedName(t.asElement()); return getFullyQualifiedName(t.asElement());

View File

@ -24,7 +24,7 @@
/* /*
* @test * @test
* @bug 8005091 8009686 8025633 8026567 6469562 8071982 8071984 8162363 8175200 8186332 8182765 * @bug 8005091 8009686 8025633 8026567 6469562 8071982 8071984 8162363 8175200 8186332 8182765
* 8187288 8241969 * 8187288 8241969 8259216
* @summary Make sure that type annotations are displayed correctly * @summary Make sure that type annotations are displayed correctly
* @library ../../lib * @library ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool * @modules jdk.javadoc/jdk.javadoc.internal.tool
@ -371,7 +371,7 @@ public class TestTypeAnnotations extends JavadocTester {
""" """
<div class="member-signature"><span class="return-type">void</span>&nbsp;<span c\ <div class="member-signature"><span class="return-type">void</span>&nbsp;<span c\
lass="element-name">withException</span>&#8203;<span class="parameters">(<a href\ lass="element-name">withException</span>&#8203;<span class="parameters">(<a href\
="RcvrA.html" title="annotation in typeannos">@RcvrA</a>&nbsp;DefaultUnmodified&\ ="RcvrA.html" title="annotation in typeannos">@RcvrA</a> DefaultUnmodified&\
nbsp;this)</span> nbsp;this)</span>
throws <span class="exceptions">java.lang.Exception</span></div>""", throws <span class="exceptions">java.lang.Exception</span></div>""",
@ -379,14 +379,14 @@ public class TestTypeAnnotations extends JavadocTester {
<div class="member-signature"><span class="return-type">java.lang.String</span>&\ <div class="member-signature"><span class="return-type">java.lang.String</span>&\
nbsp;<span class="element-name">nonVoid</span>&#8203;<span class="parameters">(<a href="\ nbsp;<span class="element-name">nonVoid</span>&#8203;<span class="parameters">(<a href="\
RcvrA.html" title="annotation in typeannos">@RcvrA</a> <a href="RcvrB.html" titl\ RcvrA.html" title="annotation in typeannos">@RcvrA</a> <a href="RcvrB.html" titl\
e="annotation in typeannos">@RcvrB</a>("m")&nbsp;DefaultUnmodified&nbsp;this)</s\ e="annotation in typeannos">@RcvrB</a>("m") DefaultUnmodified&nbsp;this)</s\
pan></div>""", pan></div>""",
""" """
<div class="member-signature"><span class="type-parameters">&lt;T extends java.l\ <div class="member-signature"><span class="type-parameters">&lt;T extends java.l\
ang.Runnable&gt;</span>&nbsp;<span class="return-type">void</span>&nbsp;<span cl\ ang.Runnable&gt;</span>&nbsp;<span class="return-type">void</span>&nbsp;<span cl\
ass="element-name">accept</span>&#8203;<span class="parameters">(<a href="RcvrA.\ ass="element-name">accept</span>&#8203;<span class="parameters">(<a href="RcvrA.\
html" title="annotation in typeannos">@RcvrA</a>&nbsp;DefaultUnmodified&nbsp;thi\ html" title="annotation in typeannos">@RcvrA</a> DefaultUnmodified&nbsp;thi\
s, s,
T&nbsp;r)</span> T&nbsp;r)</span>
throws <span class="exceptions">java.lang.Exception</span></div>"""); throws <span class="exceptions">java.lang.Exception</span></div>""");
@ -396,14 +396,14 @@ public class TestTypeAnnotations extends JavadocTester {
<div class="member-signature"><span class="modifiers">public final</span>&nbsp;<\ <div class="member-signature"><span class="modifiers">public final</span>&nbsp;<\
span class="return-type">java.lang.String</span>&nbsp;<span class="element-name">nonVoid\ span class="return-type">java.lang.String</span>&nbsp;<span class="element-name">nonVoid\
</span>&#8203;<span class="parameters">(<a href="RcvrA.html" title="annotation i\ </span>&#8203;<span class="parameters">(<a href="RcvrA.html" title="annotation i\
n typeannos">@RcvrA</a>&nbsp;PublicModified&nbsp;this)</span></div>""", n typeannos">@RcvrA</a> PublicModified&nbsp;this)</span></div>""",
""" """
<div class="member-signature"><span class="modifiers">public final</span>&nbsp;<\ <div class="member-signature"><span class="modifiers">public final</span>&nbsp;<\
span class="type-parameters">&lt;T extends java.lang.Runnable&gt;</span>&nbsp;<s\ span class="type-parameters">&lt;T extends java.lang.Runnable&gt;</span>&nbsp;<s\
pan class="return-type">void</span>&nbsp;<span class="element-name">accept</span>&#8203;\ pan class="return-type">void</span>&nbsp;<span class="element-name">accept</span>&#8203;\
<span class="parameters">(<a href="RcvrA.html" title="annotation in typea\ <span class="parameters">(<a href="RcvrA.html" title="annotation in typea\
nnos">@RcvrA</a>&nbsp;PublicModified&nbsp;this, nnos">@RcvrA</a> PublicModified&nbsp;this,
T&nbsp;r)</span> T&nbsp;r)</span>
throws <span class="exceptions">java.lang.Exception</span></div>"""); throws <span class="exceptions">java.lang.Exception</span></div>""");
@ -412,7 +412,7 @@ public class TestTypeAnnotations extends JavadocTester {
<div class="member-signature"><span class="type-parameters">&lt;T extends java.l\ <div class="member-signature"><span class="type-parameters">&lt;T extends java.l\
ang.Runnable&gt;</span>&nbsp;<span class="return-type">void</span>&nbsp;<span cl\ ang.Runnable&gt;</span>&nbsp;<span class="return-type">void</span>&nbsp;<span cl\
ass="element-name">accept</span>&#8203;<span class="parameters">(<a href="RcvrB.\ ass="element-name">accept</span>&#8203;<span class="parameters">(<a href="RcvrB.\
html" title="annotation in typeannos">@RcvrB</a>("m")&nbsp;WithValue&nbsp;this, html" title="annotation in typeannos">@RcvrB</a>("m") WithValue&nbsp;this,
T&nbsp;r)</span> T&nbsp;r)</span>
throws <span class="exceptions">java.lang.Exception</span></div>"""); throws <span class="exceptions">java.lang.Exception</span></div>""");
@ -427,15 +427,28 @@ public class TestTypeAnnotations extends JavadocTester {
""" """
<div class="member-signature"><span class="return-type">void</span>&nbsp;<span c\ <div class="member-signature"><span class="return-type">void</span>&nbsp;<span c\
lass="element-name">field</span>&#8203;<span class="parameters">(<a href="RcvrA.\ lass="element-name">field</span>&#8203;<span class="parameters">(<a href="RcvrA.\
html" title="annotation in typeannos">@RcvrA</a>&nbsp;WithBody&nbsp;this)</span>\ html" title="annotation in typeannos">@RcvrA</a> WithBody&nbsp;this)</span>\
</div>"""); </div>""");
checkOutput("typeannos/Generic2.html", true, checkOutput("typeannos/Generic2.html", true,
"""
<div class="member-signature"><span class="return-type">void</span>&nbsp;<span c\
lass="element-name">test1</span>()</div>""",
""" """
<div class="member-signature"><span class="return-type">void</span>&nbsp;<span c\ <div class="member-signature"><span class="return-type">void</span>&nbsp;<span c\
lass="element-name">test2</span>&#8203;<span class="parameters">(<a href="RcvrA.\ lass="element-name">test2</span>&#8203;<span class="parameters">(<a href="RcvrA.\
html" title="annotation in typeannos">@RcvrA</a>&nbsp;Generic2&lt;X&gt;&nbsp;thi\ html" title="annotation in typeannos">@RcvrA</a> Generic2&lt;X&gt;&nbsp;thi\
s)</span></div>"""); s)</span></div>""",
"""
<div class="member-signature"><span class="return-type">void</span>&nbsp;<span c\
lass="element-name">test3</span>&#8203;<span class="parameters">(Generic2&lt;<a \
href="RcvrA.html" title="annotation in typeannos">@RcvrA</a> X&gt;&nbsp;this)</s\
pan></div>""",
"""
<div class="member-signature"><span class="return-type">void</span>&nbsp;<span cl\
ass="element-name">test4</span>&#8203;<span class="parameters">(<a href="RcvrA.ht\
ml" title="annotation in typeannos">@RcvrA</a> Generic2&lt;<a href="RcvrA.html" t\
itle="annotation in typeannos">@RcvrA</a> X&gt;&nbsp;this)</span></div>""");
// Test for repeated type annotations (RepeatedAnnotations.java). // Test for repeated type annotations (RepeatedAnnotations.java).
@ -535,7 +548,8 @@ public class TestTypeAnnotations extends JavadocTester {
nnotation in typeannos">@RepTypeUseA</a> <a href="RepTypeUseA.html" title="annot\ nnotation in typeannos">@RepTypeUseA</a> <a href="RepTypeUseA.html" title="annot\
ation in typeannos">@RepTypeUseA</a> <a href="RepTypeUseB.html" title="annotatio\ ation in typeannos">@RepTypeUseA</a> <a href="RepTypeUseB.html" title="annotatio\
n in typeannos">@RepTypeUseB</a> <a href="RepTypeUseB.html" title="annotation in\ n in typeannos">@RepTypeUseB</a> <a href="RepTypeUseB.html" title="annotation in\
typeannos">@RepTypeUseB</a>&nbsp;RepeatingOnConstructor&nbsp;this, typeannos">@RepTypeUseB</a> <a href="RepeatingOnConstructor.html" title="class \
in typeannos">RepeatingOnConstructor</a>&nbsp;RepeatingOnConstructor.this,
<a href="RepParameterA.html" title="annotation in typeannos">@RepParameterA</a> \ <a href="RepParameterA.html" title="annotation in typeannos">@RepParameterA</a> \
<a href="RepParameterA.html" title="annotation in typeannos">@RepParameterA</a> \ <a href="RepParameterA.html" title="annotation in typeannos">@RepParameterA</a> \
<a href="RepParameterB.html" title="annotation in typeannos">@RepParameterB</a> \ <a href="RepParameterB.html" title="annotation in typeannos">@RepParameterB</a> \
@ -743,7 +757,7 @@ public class TestTypeAnnotations extends JavadocTester {
RepTypeUseA</a> <a href="RepTypeUseA.html" title="annotation in typeannos">@RepT\ RepTypeUseA</a> <a href="RepTypeUseA.html" title="annotation in typeannos">@RepT\
ypeUseA</a> <a href="RepTypeUseB.html" title="annotation in typeannos">@RepTypeU\ ypeUseA</a> <a href="RepTypeUseB.html" title="annotation in typeannos">@RepTypeU\
seB</a> <a href="RepTypeUseB.html" title="annotation in typeannos">@RepTypeUseB<\ seB</a> <a href="RepTypeUseB.html" title="annotation in typeannos">@RepTypeUseB<\
/a>&nbsp;RepeatingOnMethod&nbsp;this, /a> RepeatingOnMethod&nbsp;this,
<a href="RepParameterA.html" title="annotation in typeannos">@RepParameterA</a> \ <a href="RepParameterA.html" title="annotation in typeannos">@RepParameterA</a> \
<a href="RepParameterA.html" title="annotation in typeannos">@RepParameterA</a> \ <a href="RepParameterA.html" title="annotation in typeannos">@RepParameterA</a> \
<a href="RepParameterB.html" title="annotation in typeannos">@RepParameterB</a> \ <a href="RepParameterB.html" title="annotation in typeannos">@RepParameterB</a> \
@ -781,7 +795,7 @@ public class TestTypeAnnotations extends JavadocTester {
on in typeannos">@RepTypeUseA</a> <a href="RepTypeUseA.html" title="annotation i\ on in typeannos">@RepTypeUseA</a> <a href="RepTypeUseA.html" title="annotation i\
n typeannos">@RepTypeUseA</a> <a href="RepTypeUseB.html" title="annotation in ty\ n typeannos">@RepTypeUseA</a> <a href="RepTypeUseB.html" title="annotation in ty\
peannos">@RepTypeUseB</a> <a href="RepTypeUseB.html" title="annotation in typean\ peannos">@RepTypeUseB</a> <a href="RepTypeUseB.html" title="annotation in typean\
nos">@RepTypeUseB</a>&nbsp;RepeatingOnTypeParametersBoundsTypeArgumentsOnMethod&\ nos">@RepTypeUseB</a> RepeatingOnTypeParametersBoundsTypeArgumentsOnMethod&\
lt;<a href="RepTypeUseA.html" title="annotation in typeannos">@RepTypeUseA</a> <\ lt;<a href="RepTypeUseA.html" title="annotation in typeannos">@RepTypeUseA</a> <\
a href="RepTypeUseA.html" title="annotation in typeannos">@RepTypeUseA</a> <a hr\ a href="RepTypeUseA.html" title="annotation in typeannos">@RepTypeUseA</a> <a hr\
ef="RepTypeUseB.html" title="annotation in typeannos">@RepTypeUseB</a> <a href="\ ef="RepTypeUseB.html" title="annotation in typeannos">@RepTypeUseB</a> <a href="\