8223358: Incorrect HTML structure in annotation pages

Reviewed-by: jjg
This commit is contained in:
Hannes Wallnöfer 2021-11-09 20:11:18 +00:00
parent a60e91259b
commit 055de6f566
18 changed files with 268 additions and 443 deletions

@ -26,6 +26,7 @@
package jdk.javadoc.internal.doclets.formats.html; package jdk.javadoc.internal.doclets.formats.html;
import javax.lang.model.SourceVersion; import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element; import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeElement;
@ -36,39 +37,71 @@ import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.Text; import jdk.javadoc.internal.doclets.formats.html.markup.Text;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeRequiredMemberWriter; import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeMemberWriter;
import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
/** /**
* Writes annotation type required member documentation in HTML format. * Writes annotation interface member documentation in HTML format.
* *
* <p><b>This is NOT part of any supported API. * <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk. * If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or * This code and its internal interfaces are subject to change or
* deletion without notice.</b> * deletion without notice.</b>
*/ */
public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter public class AnnotationTypeMemberWriterImpl extends AbstractMemberWriter
implements AnnotationTypeRequiredMemberWriter, MemberSummaryWriter { implements AnnotationTypeMemberWriter, MemberSummaryWriter {
/** /**
* Construct a new AnnotationTypeRequiredMemberWriterImpl. * We generate separate summaries for required and optional annotation interface members,
* so we need dedicated writer instances for each kind. For the details section, a single
* shared list is generated so a special {@code ANY} value is provided for this case.
*/
enum Kind {
OPTIONAL,
REQUIRED,
ANY
}
private final Kind kind;
/**
* Constructs a new AnnotationTypeMemberWriterImpl for any kind of member.
*
* @param writer The writer for the class that the member belongs to.
*/
public AnnotationTypeMemberWriterImpl(SubWriterHolderWriter writer) {
super(writer);
this.kind = Kind.ANY;
}
/**
* Constructs a new AnnotationTypeMemberWriterImpl for a specific kind of member.
* *
* @param writer the writer that will write the output. * @param writer the writer that will write the output.
* @param annotationType the AnnotationType that holds this member. * @param annotationType the AnnotationType that holds this member.
* @param kind the kind of annotation interface members to handle.
*/ */
public AnnotationTypeRequiredMemberWriterImpl(SubWriterHolderWriter writer, public AnnotationTypeMemberWriterImpl(SubWriterHolderWriter writer,
TypeElement annotationType) { TypeElement annotationType,
Kind kind) {
super(writer, annotationType); super(writer, annotationType);
this.kind = kind;
} }
@Override @Override
public Content getMemberSummaryHeader(TypeElement typeElement, public Content getMemberSummaryHeader(TypeElement typeElement,
Content memberSummaryTree) { Content memberSummaryTree) {
memberSummaryTree.add(selectComment( switch (kind) {
MarkerComments.START_OF_ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY, case OPTIONAL -> memberSummaryTree.add(selectComment(
MarkerComments.START_OF_ANNOTATION_INTERFACE_REQUIRED_MEMBER_SUMMARY)); MarkerComments.START_OF_ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY,
MarkerComments.START_OF_ANNOTATION_INTERFACE_OPTIONAL_MEMBER_SUMMARY));
case REQUIRED -> memberSummaryTree.add(selectComment(
MarkerComments.START_OF_ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY,
MarkerComments.START_OF_ANNOTATION_INTERFACE_REQUIRED_MEMBER_SUMMARY));
case ANY -> throw new UnsupportedOperationException("unsupported member kind");
}
Content memberTree = new ContentBuilder(); Content memberTree = new ContentBuilder();
writer.addSummaryHeader(this, memberTree); writer.addSummaryHeader(this, memberTree);
return memberTree; return memberTree;
@ -82,7 +115,12 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter
@Override @Override
public void addSummary(Content summariesList, Content content) { public void addSummary(Content summariesList, Content content) {
writer.addSummary(HtmlStyle.memberSummary, writer.addSummary(HtmlStyle.memberSummary,
HtmlIds.ANNOTATION_TYPE_REQUIRED_ELEMENT_SUMMARY, summariesList, content); switch (kind) {
case REQUIRED -> HtmlIds.ANNOTATION_TYPE_REQUIRED_ELEMENT_SUMMARY;
case OPTIONAL -> HtmlIds.ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY;
case ANY -> throw new UnsupportedOperationException("unsupported member kind");
},
summariesList, content);
} }
@Override @Override
@ -95,12 +133,9 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter
@Override @Override
public Content getAnnotationDetailsTreeHeader() { public Content getAnnotationDetailsTreeHeader() {
Content memberDetailsTree = new ContentBuilder(); Content memberDetailsTree = new ContentBuilder();
if (!writer.printedAnnotationHeading) { Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, contents.annotationTypeDetailsLabel);
contents.annotationTypeDetailsLabel); memberDetailsTree.add(heading);
memberDetailsTree.add(heading);
writer.printedAnnotationHeading = true;
}
return memberDetailsTree; return memberDetailsTree;
} }
@ -151,7 +186,11 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter
@Override @Override
public void addSummaryLabel(Content memberTree) { public void addSummaryLabel(Content memberTree) {
HtmlTree label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, HtmlTree label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING,
contents.annotateTypeRequiredMemberSummaryLabel); switch (kind) {
case REQUIRED -> contents.annotateTypeRequiredMemberSummaryLabel;
case OPTIONAL -> contents.annotateTypeOptionalMemberSummaryLabel;
case ANY -> throw new UnsupportedOperationException("unsupported member kind");
});
memberTree.add(label); memberTree.add(label);
} }
@ -159,15 +198,24 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter
* Get the caption for the summary table. * Get the caption for the summary table.
* @return the caption * @return the caption
*/ */
// Overridden by AnnotationTypeOptionalMemberWriterImpl
protected Content getCaption() { protected Content getCaption() {
return contents.getContent("doclet.Annotation_Type_Required_Members"); return contents.getContent(
switch (kind) {
case REQUIRED -> "doclet.Annotation_Type_Required_Members";
case OPTIONAL -> "doclet.Annotation_Type_Optional_Members";
case ANY -> throw new UnsupportedOperationException("unsupported member kind");
});
} }
@Override @Override
public TableHeader getSummaryTableHeader(Element member) { public TableHeader getSummaryTableHeader(Element member) {
return new TableHeader(contents.modifierAndTypeLabel, return new TableHeader(contents.modifierAndTypeLabel,
contents.annotationTypeRequiredMemberLabel, contents.descriptionLabel); switch (kind) {
case REQUIRED -> contents.annotationTypeRequiredMemberLabel;
case OPTIONAL -> contents.annotationTypeOptionalMemberLabel;
case ANY -> throw new UnsupportedOperationException("unsupported member kind");
},
contents.descriptionLabel);
} }
@Override @Override
@ -219,4 +267,17 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter
? utils.getReturnType(typeElement, (ExecutableElement) member) ? utils.getReturnType(typeElement, (ExecutableElement) member)
: member.asType(); : member.asType();
} }
public void addDefaultValueInfo(Element member, Content annotationDocTree) {
if (utils.isAnnotationType(member)) {
ExecutableElement ee = (ExecutableElement) member;
AnnotationValue value = ee.getDefaultValue();
if (value != null) {
Content dl = HtmlTree.DL(HtmlStyle.notes);
dl.add(HtmlTree.DT(contents.default_));
dl.add(HtmlTree.DD(Text.of(value.toString())));
annotationDocTree.add(dl);
}
}
}
} }

@ -1,113 +0,0 @@
/*
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.javadoc.internal.doclets.formats.html;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.Text;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeOptionalMemberWriter;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
/**
* Writes annotation type optional member documentation in HTML format.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class AnnotationTypeOptionalMemberWriterImpl extends
AnnotationTypeRequiredMemberWriterImpl
implements AnnotationTypeOptionalMemberWriter, MemberSummaryWriter {
/**
* Construct a new AnnotationTypeOptionalMemberWriterImpl.
*
* @param writer the writer that will write the output.
* @param annotationType the AnnotationType that holds this member.
*/
public AnnotationTypeOptionalMemberWriterImpl(SubWriterHolderWriter writer,
TypeElement annotationType) {
super(writer, annotationType);
}
@Override
public Content getMemberSummaryHeader(TypeElement typeElement,
Content memberSummaryTree) {
memberSummaryTree.add(selectComment(
MarkerComments.START_OF_ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY,
MarkerComments.START_OF_ANNOTATION_INTERFACE_OPTIONAL_MEMBER_SUMMARY));
Content memberTree = new ContentBuilder();
writer.addSummaryHeader(this, memberTree);
return memberTree;
}
@Override
public void addSummary(Content summariesList, Content content) {
writer.addSummary(HtmlStyle.memberSummary,
HtmlIds.ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY, summariesList, content);
}
@Override
public void addDefaultValueInfo(Element member, Content annotationDocTree) {
if (utils.isAnnotationType(member)) {
ExecutableElement ee = (ExecutableElement) member;
AnnotationValue value = ee.getDefaultValue();
if (value != null) {
Content dl = HtmlTree.DL(HtmlStyle.notes);
dl.add(HtmlTree.DT(contents.default_));
dl.add(HtmlTree.DD(Text.of(value.toString())));
annotationDocTree.add(dl);
}
}
}
@Override
public void addSummaryLabel(Content memberTree) {
Content label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING,
contents.annotateTypeOptionalMemberSummaryLabel);
memberTree.add(label);
}
@Override
protected Content getCaption() {
return contents.getContent("doclet.Annotation_Type_Optional_Members");
}
@Override
public TableHeader getSummaryTableHeader(Element member) {
return new TableHeader(contents.modifierAndTypeLabel,
contents.annotationTypeOptionalMemberLabel, contents.descriptionLabel);
}
}

@ -177,11 +177,6 @@ public class HtmlDocletWriter {
protected final HtmlIds htmlIds; protected final HtmlIds htmlIds;
/**
* To check whether annotation heading is printed or not.
*/
protected boolean printedAnnotationHeading = false;
/** /**
* To check whether the repeated annotations is documented or not. * To check whether the repeated annotations is documented or not.
*/ */

@ -442,6 +442,8 @@ public class HtmlIds {
case FIELDS -> FIELD_SUMMARY; case FIELDS -> FIELD_SUMMARY;
case CONSTRUCTORS -> CONSTRUCTOR_SUMMARY; case CONSTRUCTORS -> CONSTRUCTOR_SUMMARY;
case METHODS -> METHOD_SUMMARY; case METHODS -> METHOD_SUMMARY;
// We generate separate summaries for optional and required annotation members
case ANNOTATION_TYPE_MEMBER -> throw new IllegalArgumentException("unsupported member kind");
case ANNOTATION_TYPE_MEMBER_OPTIONAL -> ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY; case ANNOTATION_TYPE_MEMBER_OPTIONAL -> ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY;
case ANNOTATION_TYPE_MEMBER_REQUIRED -> ANNOTATION_TYPE_REQUIRED_ELEMENT_SUMMARY; case ANNOTATION_TYPE_MEMBER_REQUIRED -> ANNOTATION_TYPE_REQUIRED_ELEMENT_SUMMARY;
case PROPERTIES -> PROPERTY_SUMMARY; case PROPERTIES -> PROPERTY_SUMMARY;

@ -389,19 +389,9 @@ public class Navigation {
if (documentedPage == PageMode.CLASS) { if (documentedPage == PageMode.CLASS) {
List<Content> listContents = new ArrayList<>(); List<Content> listContents = new ArrayList<>();
VisibleMemberTable vmt = configuration.getVisibleMemberTable((TypeElement) element); VisibleMemberTable vmt = configuration.getVisibleMemberTable((TypeElement) element);
if (element.getKind() == ElementKind.ANNOTATION_TYPE) { Set<VisibleMemberTable.Kind> detailSet = VisibleMemberTable.Kind.forDetailsOf(element.getKind());
// Handle annotation interfaces separately as required and optional elements for (VisibleMemberTable.Kind kind : detailSet) {
// share a combined details section. addTypeDetailLink(kind, !vmt.getVisibleMembers(kind).isEmpty(), listContents);
addTypeDetailLink(FIELDS, !vmt.getVisibleMembers(FIELDS).isEmpty(), listContents);
boolean hasAnnotationElements =
!vmt.getVisibleMembers(ANNOTATION_TYPE_MEMBER_OPTIONAL).isEmpty()
|| !vmt.getVisibleMembers(ANNOTATION_TYPE_MEMBER_REQUIRED).isEmpty();
addTypeDetailLink(ANNOTATION_TYPE_MEMBER_REQUIRED, hasAnnotationElements, listContents);
} else {
Set<VisibleMemberTable.Kind> detailSet = VisibleMemberTable.Kind.forDetailsOf(element.getKind());
for (VisibleMemberTable.Kind kind : detailSet) {
addTypeDetailLink(kind, !vmt.getVisibleMembers(kind).isEmpty(), listContents);
}
} }
if (!listContents.isEmpty()) { if (!listContents.isEmpty()) {
if (nested) { if (nested) {
@ -432,10 +422,8 @@ public class Navigation {
case FIELDS -> links.createLink(HtmlIds.FIELD_DETAIL, contents.navField, link); case FIELDS -> links.createLink(HtmlIds.FIELD_DETAIL, contents.navField, link);
case METHODS -> links.createLink(HtmlIds.METHOD_DETAIL, contents.navMethod, link); case METHODS -> links.createLink(HtmlIds.METHOD_DETAIL, contents.navMethod, link);
case PROPERTIES -> links.createLink(HtmlIds.PROPERTY_DETAIL, contents.navProperty, link); case PROPERTIES -> links.createLink(HtmlIds.PROPERTY_DETAIL, contents.navProperty, link);
case ANNOTATION_TYPE_MEMBER_REQUIRED, case ANNOTATION_TYPE_MEMBER -> links.createLink(HtmlIds.ANNOTATION_TYPE_ELEMENT_DETAIL,
ANNOTATION_TYPE_MEMBER_OPTIONAL -> contents.navAnnotationTypeMember, link);
links.createLink(HtmlIds.ANNOTATION_TYPE_ELEMENT_DETAIL,
contents.navAnnotationTypeMember, link);
default -> Text.EMPTY; default -> Text.EMPTY;
}); });
} }

@ -254,7 +254,8 @@ public class SummaryListWriter<L extends SummaryAPIListBuilder> extends SubWrite
case ENUM_CONSTANT -> new EnumConstantWriterImpl(this); case ENUM_CONSTANT -> new EnumConstantWriterImpl(this);
case RECORD_COMPONENT -> case RECORD_COMPONENT ->
throw new AssertionError("Record components are not supported by SummaryListWriter!"); throw new AssertionError("Record components are not supported by SummaryListWriter!");
default -> new AnnotationTypeOptionalMemberWriterImpl(this, null); default ->
throw new UnsupportedOperationException("Unsupported element kind: " + e.getKind());
}; };
return writer.getSummaryLink(e); return writer.getSummaryLink(e);
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -31,8 +31,6 @@ import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.PackageElement; import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeElement;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeOptionalMemberWriter;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeRequiredMemberWriter;
import jdk.javadoc.internal.doclets.toolkit.ClassWriter; import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
import jdk.javadoc.internal.doclets.toolkit.ConstantsSummaryWriter; import jdk.javadoc.internal.doclets.toolkit.ConstantsSummaryWriter;
import jdk.javadoc.internal.doclets.toolkit.DocFilesHandler; import jdk.javadoc.internal.doclets.toolkit.DocFilesHandler;
@ -80,19 +78,27 @@ public class WriterFactoryImpl implements WriterFactory {
} }
@Override @Override
public AnnotationTypeOptionalMemberWriter getAnnotationTypeOptionalMemberWriter( public AnnotationTypeMemberWriterImpl getAnnotationTypeMemberWriter(
ClassWriter classWriter) { ClassWriter classWriter) {
TypeElement te = classWriter.getTypeElement(); TypeElement te = classWriter.getTypeElement();
return new AnnotationTypeOptionalMemberWriterImpl( return new AnnotationTypeMemberWriterImpl(
(ClassWriterImpl) classWriter, te); (ClassWriterImpl) classWriter, te, AnnotationTypeMemberWriterImpl.Kind.ANY);
} }
@Override @Override
public AnnotationTypeRequiredMemberWriter getAnnotationTypeRequiredMemberWriter( public AnnotationTypeMemberWriterImpl getAnnotationTypeOptionalMemberWriter(
ClassWriter classWriter) { ClassWriter classWriter) {
TypeElement te = classWriter.getTypeElement(); TypeElement te = classWriter.getTypeElement();
return new AnnotationTypeRequiredMemberWriterImpl( return new AnnotationTypeMemberWriterImpl(
(ClassWriterImpl) classWriter, te); (ClassWriterImpl) classWriter, te, AnnotationTypeMemberWriterImpl.Kind.OPTIONAL);
}
@Override
public AnnotationTypeMemberWriterImpl getAnnotationTypeRequiredMemberWriter(
ClassWriter classWriter) {
TypeElement te = classWriter.getTypeElement();
return new AnnotationTypeMemberWriterImpl(
(ClassWriterImpl) classWriter, te, AnnotationTypeMemberWriterImpl.Kind.REQUIRED);
} }
@Override @Override
@ -132,11 +138,9 @@ public class WriterFactoryImpl implements WriterFactory {
case ENUM_CONSTANTS: case ENUM_CONSTANTS:
return getEnumConstantWriter(classWriter); return getEnumConstantWriter(classWriter);
case ANNOTATION_TYPE_MEMBER_OPTIONAL: case ANNOTATION_TYPE_MEMBER_OPTIONAL:
return (AnnotationTypeOptionalMemberWriterImpl) return getAnnotationTypeOptionalMemberWriter(classWriter);
getAnnotationTypeOptionalMemberWriter(classWriter);
case ANNOTATION_TYPE_MEMBER_REQUIRED: case ANNOTATION_TYPE_MEMBER_REQUIRED:
return (AnnotationTypeRequiredMemberWriterImpl) return getAnnotationTypeRequiredMemberWriter(classWriter);
getAnnotationTypeRequiredMemberWriter(classWriter);
case FIELDS: case FIELDS:
return getFieldWriter(classWriter); return getFieldWriter(classWriter);
case PROPERTIES: case PROPERTIES:

@ -36,31 +36,31 @@ import javax.lang.model.element.Element;
* deletion without notice.</b> * deletion without notice.</b>
*/ */
public interface AnnotationTypeRequiredMemberWriter extends MemberWriter { public interface AnnotationTypeMemberWriter extends MemberWriter {
/** /**
* Add the annotation type member tree header. * Adds the annotation type member tree header.
* *
* @return content tree for the member tree header * @return content tree for the member tree header
*/ */
Content getMemberTreeHeader(); Content getMemberTreeHeader();
/** /**
* Add the annotation type details marker. * Adds the annotation type details marker.
* *
* @param memberDetails the content tree representing details marker * @param memberDetails the content tree representing details marker
*/ */
void addAnnotationDetailsMarker(Content memberDetails); void addAnnotationDetailsMarker(Content memberDetails);
/** /**
* Add the annotation type details tree header. * Adds the annotation type details tree header.
* *
* @return content tree for the annotation details header * @return content tree for the annotation details header
*/ */
Content getAnnotationDetailsTreeHeader(); Content getAnnotationDetailsTreeHeader();
/** /**
* Get the annotation type documentation tree header. * Gets the annotation type documentation tree header.
* *
* @param member the annotation type being documented * @param member the annotation type being documented
* @return content tree for the annotation type documentation header * @return content tree for the annotation type documentation header
@ -68,7 +68,7 @@ public interface AnnotationTypeRequiredMemberWriter extends MemberWriter {
Content getAnnotationDocTreeHeader(Element member); Content getAnnotationDocTreeHeader(Element member);
/** /**
* Get the annotation type details tree. * Gets the annotation type details tree.
* *
* @param annotationDetailsTreeHeader the content tree representing annotation type details header * @param annotationDetailsTreeHeader the content tree representing annotation type details header
* @param annotationDetailsTree the content tree representing annotation type details * @param annotationDetailsTree the content tree representing annotation type details
@ -77,7 +77,7 @@ public interface AnnotationTypeRequiredMemberWriter extends MemberWriter {
Content getAnnotationDetails(Content annotationDetailsTreeHeader, Content annotationDetailsTree); Content getAnnotationDetails(Content annotationDetailsTreeHeader, Content annotationDetailsTree);
/** /**
* Get the signature for the given member. * Gets the signature for the given member.
* *
* @param member the member being documented * @param member the member being documented
* @return content tree for the annotation type signature * @return content tree for the annotation type signature
@ -85,7 +85,7 @@ public interface AnnotationTypeRequiredMemberWriter extends MemberWriter {
Content getSignature(Element member); Content getSignature(Element member);
/** /**
* Add the deprecated output for the given member. * Adds the deprecated output for the given member.
* *
* @param member the member being documented * @param member the member being documented
* @param annotationDocTree content tree to which the deprecated information will be added * @param annotationDocTree content tree to which the deprecated information will be added
@ -93,15 +93,15 @@ public interface AnnotationTypeRequiredMemberWriter extends MemberWriter {
void addDeprecated(Element member, Content annotationDocTree); void addDeprecated(Element member, Content annotationDocTree);
/** /**
* Add the preview output for the given member. * Adds the preview output for the given member.
* *
* @param member the member being documented * @param member the member being documented
* @param annotationDocTree content tree to which the preview information will be added * @param contentTree content tree to which the preview information will be added
*/ */
void addPreview(Element member, Content contentTree); void addPreview(Element member, Content contentTree);
/** /**
* Add the comments for the given member. * Adds the comments for the given member.
* *
* @param member the member being documented * @param member the member being documented
* @param annotationDocTree the content tree to which the comments will be added * @param annotationDocTree the content tree to which the comments will be added
@ -109,10 +109,18 @@ public interface AnnotationTypeRequiredMemberWriter extends MemberWriter {
void addComments(Element member, Content annotationDocTree); void addComments(Element member, Content annotationDocTree);
/** /**
* Add the tags for the given member. * Adds the tags for the given member.
* *
* @param member the member being documented * @param member the member being documented
* @param annotationDocTree the content tree to which the tags will be added * @param annotationDocTree the content tree to which the tags will be added
*/ */
void addTags(Element member, Content annotationDocTree); void addTags(Element member, Content annotationDocTree);
/**
* Adds the default value documentation if the member has one.
*
* @param member the member being documented
* @param annotationDocTree content tree to which the default value will be added
*/
void addDefaultValueInfo(Element member, Content annotationDocTree);
} }

@ -1,49 +0,0 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.javadoc.internal.doclets.toolkit;
import javax.lang.model.element.Element;
/**
* The interface for writing annotation type optional member output.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public interface AnnotationTypeOptionalMemberWriter extends
AnnotationTypeRequiredMemberWriter {
/**
* Add the the default value documentation.
*
* @param member the member being documented
* @param annotationDocTree content tree to which the default value will be added
*/
void addDefaultValueInfo(Element member, Content annotationDocTree);
}

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -89,6 +89,16 @@ public interface WriterFactory {
*/ */
MethodWriter getMethodWriter(ClassWriter classWriter); MethodWriter getMethodWriter(ClassWriter classWriter);
/**
* Return the annotation type member writer for a given annotation
* type, or null if this writer is not supported by the doclet.
*
* @param classWriter the writer for the annotation type being documented
* @return the member writer
*/
AnnotationTypeMemberWriter getAnnotationTypeMemberWriter(
ClassWriter classWriter);
/** /**
* Return the annotation type optional member writer for a given annotation * Return the annotation type optional member writer for a given annotation
* type, or null if this writer is not supported by the doclet. * type, or null if this writer is not supported by the doclet.
@ -96,7 +106,7 @@ public interface WriterFactory {
* @param classWriter the writer for the annotation type being documented * @param classWriter the writer for the annotation type being documented
* @return the member writer * @return the member writer
*/ */
AnnotationTypeOptionalMemberWriter getAnnotationTypeOptionalMemberWriter( AnnotationTypeMemberWriter getAnnotationTypeOptionalMemberWriter(
ClassWriter classWriter); ClassWriter classWriter);
/** /**
@ -106,7 +116,7 @@ public interface WriterFactory {
* @param classWriter the writer for the annotation type being documented * @param classWriter the writer for the annotation type being documented
* @return the member writer * @return the member writer
*/ */
AnnotationTypeRequiredMemberWriter getAnnotationTypeRequiredMemberWriter( AnnotationTypeMemberWriter getAnnotationTypeRequiredMemberWriter(
ClassWriter classWriter); ClassWriter classWriter);
/** /**

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -94,7 +94,7 @@ public abstract class AbstractMemberBuilder extends AbstractBuilder {
* @param kind of members * @param kind of members
* @return a list of members * @return a list of members
*/ */
protected List<? extends Element> getVisibleMembers(Kind kind) { protected List<Element> getVisibleMembers(Kind kind) {
return visibleMemberTable.getVisibleMembers(kind); return visibleMemberTable.getVisibleMembers(kind);
} }
} }

@ -29,13 +29,11 @@ import java.util.*;
import javax.lang.model.element.Element; import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeElement;
import jdk.javadoc.internal.doclets.formats.html.AbstractMemberWriter;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeRequiredMemberWriter; import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeMemberWriter;
import jdk.javadoc.internal.doclets.toolkit.BaseOptions; import jdk.javadoc.internal.doclets.toolkit.BaseOptions;
import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.DocletException; import jdk.javadoc.internal.doclets.toolkit.DocletException;
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*; import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
@ -47,18 +45,17 @@ import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.
* This code and its internal interfaces are subject to change or * This code and its internal interfaces are subject to change or
* deletion without notice.</b> * deletion without notice.</b>
*/ */
public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder { public class AnnotationTypeMemberBuilder extends AbstractMemberBuilder {
/** /**
* The writer to output the member documentation. * The writer to output the member documentation.
*/ */
protected AnnotationTypeRequiredMemberWriter writer; protected AnnotationTypeMemberWriter writer;
/** /**
* The list of members being documented. * The list of members being documented.
*/ */
protected List<? extends Element> members; protected List<Element> members;
/** /**
* The index of the current member that is being documented at this point * The index of the current member that is being documented at this point
@ -72,15 +69,15 @@ public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder {
* @param context the build context. * @param context the build context.
* @param typeElement the class whose members are being documented. * @param typeElement the class whose members are being documented.
* @param writer the doclet specific writer. * @param writer the doclet specific writer.
* @param memberType the kind of member this builder processes.
*/ */
protected AnnotationTypeRequiredMemberBuilder(Context context, protected AnnotationTypeMemberBuilder(Context context,
TypeElement typeElement, TypeElement typeElement,
AnnotationTypeRequiredMemberWriter writer, AnnotationTypeMemberWriter writer) {
VisibleMemberTable.Kind memberType) {
super(context, typeElement); super(context, typeElement);
this.writer = Objects.requireNonNull(writer); this.writer = Objects.requireNonNull(writer);
this.members = getVisibleMembers(memberType); // In contrast to the annotation interface member summaries the details generated
// by this builder share a single list for both required and optional members.
this.members = getVisibleMembers(ANNOTATION_TYPE_MEMBER);
} }
@ -92,11 +89,11 @@ public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder {
* @param writer the doclet specific writer. * @param writer the doclet specific writer.
* @return an instance of this object * @return an instance of this object
*/ */
public static AnnotationTypeRequiredMemberBuilder getInstance( public static AnnotationTypeMemberBuilder getInstance(
Context context, TypeElement typeElement, Context context, TypeElement typeElement,
AnnotationTypeRequiredMemberWriter writer) { AnnotationTypeMemberWriter writer) {
return new AnnotationTypeRequiredMemberBuilder(context, typeElement, return new AnnotationTypeMemberBuilder(context, typeElement,
writer, ANNOTATION_TYPE_MEMBER_REQUIRED); writer);
} }
/** /**
@ -110,18 +107,7 @@ public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder {
@Override @Override
public void build(Content contentTree) throws DocletException { public void build(Content contentTree) throws DocletException {
buildAnnotationTypeRequiredMember(contentTree); buildAnnotationTypeMember(contentTree);
}
/**
* Build the annotation type required member documentation.
*
* @param memberDetailsTree the content tree to which the documentation will be added
* @throws DocletException if there is a problem while building the documentation
*/
protected void buildAnnotationTypeRequiredMember(Content memberDetailsTree)
throws DocletException {
buildAnnotationTypeMember(memberDetailsTree);
} }
/** /**
@ -156,6 +142,7 @@ public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder {
buildPreviewInfo(annotationDocTree); buildPreviewInfo(annotationDocTree);
buildMemberComments(annotationDocTree); buildMemberComments(annotationDocTree);
buildTagInfo(annotationDocTree); buildTagInfo(annotationDocTree);
buildDefaultValueInfo(annotationDocTree);
} }
/** /**
@ -206,13 +193,22 @@ public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder {
writer.addTags(currentMember, annotationDocTree); writer.addTags(currentMember, annotationDocTree);
} }
/**
* Build the default value for this optional member.
*
* @param annotationDocTree the content tree to which the documentation will be added
*/
protected void buildDefaultValueInfo(Content annotationDocTree) {
writer.addDefaultValueInfo(currentMember, annotationDocTree);
}
/** /**
* Return the annotation type required member writer for this builder. * Return the annotation type required member writer for this builder.
* *
* @return the annotation type required member constant writer for this * @return the annotation type required member constant writer for this
* builder. * builder.
*/ */
public AnnotationTypeRequiredMemberWriter getWriter() { public AnnotationTypeMemberWriter getWriter() {
return writer; return writer;
} }
} }

@ -1,112 +0,0 @@
/*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.javadoc.internal.doclets.toolkit.builders;
import javax.lang.model.element.TypeElement;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeOptionalMemberWriter;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeRequiredMemberWriter;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.DocletException;
import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
/**
* Builds documentation for optional annotation type members.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class AnnotationTypeOptionalMemberBuilder extends AnnotationTypeRequiredMemberBuilder {
/**
* Construct a new AnnotationTypeMemberBuilder.
*
* @param context the build context.
* @param typeElement the class whose members are being documented.
* @param writer the doclet specific writer.
*/
private AnnotationTypeOptionalMemberBuilder(Context context,
TypeElement typeElement,
AnnotationTypeOptionalMemberWriter writer) {
super(context, typeElement, writer, ANNOTATION_TYPE_MEMBER_OPTIONAL);
}
/**
* Construct a new AnnotationTypeMemberBuilder.
*
* @param context the build context.
* @param typeElement the class whose members are being documented.
* @param writer the doclet specific writer.
* @return the new AnnotationTypeMemberBuilder
*/
public static AnnotationTypeOptionalMemberBuilder getInstance(
Context context, TypeElement typeElement,
AnnotationTypeOptionalMemberWriter writer) {
return new AnnotationTypeOptionalMemberBuilder(context,
typeElement, writer);
}
@Override
public void build(Content contentTree) throws DocletException {
buildAnnotationTypeOptionalMember(contentTree);
}
/**
* Build the annotation type optional member documentation.
*
* @param memberDetailsTree the content tree to which the documentation will be added
* @throws DocletException if there is a problem while building the documentation
*/
protected void buildAnnotationTypeOptionalMember(Content memberDetailsTree)
throws DocletException {
buildAnnotationTypeMember(memberDetailsTree);
}
@Override
protected void buildAnnotationTypeMemberChildren(Content annotationDocTree) {
super.buildAnnotationTypeMemberChildren(annotationDocTree);
buildDefaultValueInfo(annotationDocTree);
}
/**
* Build the default value for this optional member.
*
* @param annotationDocTree the content tree to which the documentation will be added
*/
protected void buildDefaultValueInfo(Content annotationDocTree) {
((AnnotationTypeOptionalMemberWriter) writer).addDefaultValueInfo(currentMember,
annotationDocTree);
}
@Override
public AnnotationTypeRequiredMemberWriter getWriter() {
return writer;
}
}

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -38,9 +38,6 @@ import jdk.javadoc.internal.doclets.toolkit.PropertyWriter;
import jdk.javadoc.internal.doclets.toolkit.WriterFactory; import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
/** /**
* The factory for constructing builders. * The factory for constructing builders.
* *
@ -133,26 +130,11 @@ public class BuilderFactory {
* @return an instance of the annotation type member builder for the given * @return an instance of the annotation type member builder for the given
* annotation type. * annotation type.
*/ */
public AbstractMemberBuilder getAnnotationTypeOptionalMemberBuilder( public AbstractMemberBuilder getAnnotationTypeMemberBuilder(
ClassWriter classWriter) { ClassWriter classWriter) {
return AnnotationTypeOptionalMemberBuilder.getInstance(context, return AnnotationTypeMemberBuilder.getInstance(context,
classWriter.getTypeElement(), classWriter.getTypeElement(),
writerFactory.getAnnotationTypeOptionalMemberWriter(classWriter)); writerFactory.getAnnotationTypeMemberWriter(classWriter));
}
/**
* Return an instance of the annotation type member builder for the given
* class.
*
* @param classWriter the writer for the enclosing annotation type
* @return an instance of the annotation type member builder for the given
* annotation type.
*/
public AbstractMemberBuilder getAnnotationTypeRequiredMemberBuilder(
ClassWriter classWriter) {
return AnnotationTypeRequiredMemberBuilder.getInstance(context,
classWriter.getTypeElement(),
writerFactory.getAnnotationTypeRequiredMemberWriter(classWriter));
} }
/** /**

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -324,8 +324,7 @@ public class ClassBuilder extends AbstractBuilder {
buildPropertyDetails(detailsList); buildPropertyDetails(detailsList);
buildFieldDetails(detailsList); buildFieldDetails(detailsList);
buildConstructorDetails(detailsList); buildConstructorDetails(detailsList);
buildAnnotationTypeRequiredMemberDetails(detailsList); buildAnnotationTypeMemberDetails(detailsList);
buildAnnotationTypeOptionalMemberDetails(detailsList);
buildMethodDetails(detailsList); buildMethodDetails(detailsList);
classContentTree.add(writer.getMemberDetailsTree(detailsList)); classContentTree.add(writer.getMemberDetailsTree(detailsList));
@ -387,20 +386,9 @@ public class ClassBuilder extends AbstractBuilder {
* @param memberDetailsTree the content tree to which the documentation will be added * @param memberDetailsTree the content tree to which the documentation will be added
* @throws DocletException if there is a problem building the documentation * @throws DocletException if there is a problem building the documentation
*/ */
protected void buildAnnotationTypeOptionalMemberDetails(Content memberDetailsTree) protected void buildAnnotationTypeMemberDetails(Content memberDetailsTree)
throws DocletException { throws DocletException {
builderFactory.getAnnotationTypeOptionalMemberBuilder(writer).build(memberDetailsTree); builderFactory.getAnnotationTypeMemberBuilder(writer).build(memberDetailsTree);
}
/**
* Build the annotation type required member documentation.
*
* @param memberDetailsTree the content tree to which the documentation will be added
* @throws DocletException if there is a problem building the documentation
*/
protected void buildAnnotationTypeRequiredMemberDetails(Content memberDetailsTree)
throws DocletException {
builderFactory.getAnnotationTypeRequiredMemberBuilder(writer).build(memberDetailsTree);
} }
/** /**

@ -103,8 +103,9 @@ public class VisibleMemberTable {
FIELDS, FIELDS,
CONSTRUCTORS, CONSTRUCTORS,
METHODS, METHODS,
ANNOTATION_TYPE_MEMBER_OPTIONAL, ANNOTATION_TYPE_MEMBER,
ANNOTATION_TYPE_MEMBER_REQUIRED, ANNOTATION_TYPE_MEMBER_REQUIRED,
ANNOTATION_TYPE_MEMBER_OPTIONAL,
PROPERTIES; PROPERTIES;
private static final EnumSet<Kind> defaultSummarySet = EnumSet.of( private static final EnumSet<Kind> defaultSummarySet = EnumSet.of(
@ -112,11 +113,13 @@ public class VisibleMemberTable {
private static final EnumSet<Kind> enumSummarySet = EnumSet.of( private static final EnumSet<Kind> enumSummarySet = EnumSet.of(
NESTED_CLASSES, ENUM_CONSTANTS, FIELDS, METHODS); NESTED_CLASSES, ENUM_CONSTANTS, FIELDS, METHODS);
private static final EnumSet<Kind> annotationSummarySet = EnumSet.of( private static final EnumSet<Kind> annotationSummarySet = EnumSet.of(
FIELDS, ANNOTATION_TYPE_MEMBER_OPTIONAL, ANNOTATION_TYPE_MEMBER_REQUIRED); FIELDS, ANNOTATION_TYPE_MEMBER_REQUIRED, ANNOTATION_TYPE_MEMBER_OPTIONAL);
private static final EnumSet<Kind> defaultDetailSet = EnumSet.of( private static final EnumSet<Kind> defaultDetailSet = EnumSet.of(
FIELDS, CONSTRUCTORS, METHODS); FIELDS, CONSTRUCTORS, METHODS);
private static final EnumSet<Kind> enumDetailSet = EnumSet.of( private static final EnumSet<Kind> enumDetailSet = EnumSet.of(
ENUM_CONSTANTS, FIELDS, METHODS); ENUM_CONSTANTS, FIELDS, METHODS);
private static final EnumSet<Kind> annotationDetailSet = EnumSet.of(
FIELDS, ANNOTATION_TYPE_MEMBER);
/** /**
* {@return the set of possible member kinds for the summaries section of a type element} * {@return the set of possible member kinds for the summaries section of a type element}
@ -135,9 +138,11 @@ public class VisibleMemberTable {
* @param kind the kind of type element being documented * @param kind the kind of type element being documented
*/ */
public static Set<Kind> forDetailsOf(ElementKind kind) { public static Set<Kind> forDetailsOf(ElementKind kind) {
return kind == ElementKind.ENUM return switch (kind) {
? enumDetailSet case ANNOTATION_TYPE -> annotationDetailSet;
: defaultDetailSet; case ENUM -> enumDetailSet;
default -> defaultDetailSet;
};
} }
} }
@ -213,7 +218,7 @@ public class VisibleMemberTable {
* @param kind the member kind * @param kind the member kind
* @return a list of all visible members * @return a list of all visible members
*/ */
public List<? extends Element> getAllVisibleMembers(Kind kind) { public List<Element> getAllVisibleMembers(Kind kind) {
ensureInitialized(); ensureInitialized();
return visibleMembers.getOrDefault(kind, Collections.emptyList()); return visibleMembers.getOrDefault(kind, Collections.emptyList());
} }
@ -225,7 +230,7 @@ public class VisibleMemberTable {
* @param p the predicate used to filter the output * @param p the predicate used to filter the output
* @return a list of visible enclosed members * @return a list of visible enclosed members
*/ */
public List<? extends Element> getVisibleMembers(Kind kind, Predicate<Element> p) { public List<Element> getVisibleMembers(Kind kind, Predicate<Element> p) {
ensureInitialized(); ensureInitialized();
return visibleMembers.getOrDefault(kind, Collections.emptyList()).stream() return visibleMembers.getOrDefault(kind, Collections.emptyList()).stream()
@ -240,7 +245,7 @@ public class VisibleMemberTable {
* @param kind the member kind * @param kind the member kind
* @return a list of visible enclosed members * @return a list of visible enclosed members
*/ */
public List<? extends Element> getVisibleMembers(Kind kind) { public List<Element> getVisibleMembers(Kind kind) {
Predicate<Element> declaredAndLeafMembers = e -> { Predicate<Element> declaredAndLeafMembers = e -> {
TypeElement encl = utils.getEnclosingTypeElement(e); TypeElement encl = utils.getEnclosingTypeElement(e);
return encl == te || utils.isUndocumentedEnclosure(encl); return encl == te || utils.isUndocumentedEnclosure(encl);
@ -255,7 +260,7 @@ public class VisibleMemberTable {
* *
* @return a list of visible enclosed members in this type * @return a list of visible enclosed members in this type
*/ */
public List<? extends Element> getMembers(Kind kind) { public List<Element> getMembers(Kind kind) {
Predicate<Element> onlyLocallyDeclaredMembers = e -> utils.getEnclosingTypeElement(e) == te; Predicate<Element> onlyLocallyDeclaredMembers = e -> utils.getEnclosingTypeElement(e) == te;
return getVisibleMembers(kind, onlyLocallyDeclaredMembers); return getVisibleMembers(kind, onlyLocallyDeclaredMembers);
} }
@ -777,6 +782,7 @@ public class VisibleMemberTable {
case METHOD: case METHOD:
if (utils.isAnnotationType(te)) { if (utils.isAnnotationType(te)) {
ExecutableElement ee = (ExecutableElement) e; ExecutableElement ee = (ExecutableElement) e;
addMember(e, Kind.ANNOTATION_TYPE_MEMBER);
addMember(e, ee.getDefaultValue() == null addMember(e, ee.getDefaultValue() == null
? Kind.ANNOTATION_TYPE_MEMBER_REQUIRED ? Kind.ANNOTATION_TYPE_MEMBER_REQUIRED
: Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL); : Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);

@ -24,7 +24,7 @@
/* /*
* @test * @test
* @bug 4973609 8015249 8025633 8026567 6469561 8071982 8162363 8182765 8223364 * @bug 4973609 8015249 8025633 8026567 6469561 8071982 8162363 8182765 8223364
8242056 8261976 8242056 8261976 8223358
* @summary Make sure that annotation types with 0 members does not have * @summary Make sure that annotation types with 0 members does not have
* extra HR tags. * extra HR tags.
* @library ../../lib * @library ../../lib
@ -72,27 +72,84 @@ public class TestAnnotationTypes extends JavadocTester {
checkOutput("pkg/AnnotationType.html", true, checkOutput("pkg/AnnotationType.html", true,
""" """
<ul class="sub-nav-list">
<li>Summary:&nbsp;</li> <li>Summary:&nbsp;</li>
<li>Field&nbsp;|&nbsp;</li>""", <li>Field&nbsp;|&nbsp;</li>
<li><a href="#annotation-interface-required-element-summary">Required</a>&nbsp;|&nbsp;</li>
<li><a href="#annotation-interface-optional-element-summary">Optional</a></li>
</ul>""",
""" """
<ul class="sub-nav-list">
<li>Detail:&nbsp;</li> <li>Detail:&nbsp;</li>
<li>Field&nbsp;|&nbsp;</li>"""); <li>Field&nbsp;|&nbsp;</li>
<li><a href="#annotation-interface-element-detail">Element</a></li>
</ul>""");
checkOutput("pkg/AnnotationType.html", true, checkOutput("pkg/AnnotationType.html", true,
"<!-- ============ ANNOTATION INTERFACE MEMBER DETAIL =========== -->", """
"<ul class=\"member-list\">", <section class="summary">
"<li>", <ul class="summary-list">
""" <!-- =========== ANNOTATION INTERFACE REQUIRED MEMBER SUMMARY =========== -->
<section class="details" id="annotation-interface-element-detail">""", <li>
"<h2>Element Details</h2>", <section class="member-summary" id="annotation-interface-required-element-summary">
"</a>", <h2>Required Element Summary</h2>
"<ul class=\"member-list\">", <div class="caption"><span>Required Elements</span></div>
"<li>", <div class="summary-table three-column-summary">
""" <div class="table-header col-first">Modifier and Type</div>
<section class="detail" id="value()">""", <div class="table-header col-second">Required Element</div>
"<h3>value</h3>\n", <div class="table-header col-last">Description</div>
""" <div class="col-first even-row-color"><code>int</code></div>
<div class="member-signature"><span class="return-type">int</span>&nbsp;<span class="element-name">value</span></div>"""); <div class="col-second even-row-color"><code><a href="#value()" class="member-name-link">value</a></code></div>
<div class="col-last even-row-color">&nbsp;</div>
</div>
</section>
</li>
<!-- =========== ANNOTATION INTERFACE OPTIONAL MEMBER SUMMARY =========== -->
<li>
<section class="member-summary" id="annotation-interface-optional-element-summary">
<h2>Optional Element Summary</h2>
<div class="caption"><span>Optional Elements</span></div>
<div class="summary-table three-column-summary">
<div class="table-header col-first">Modifier and Type</div>
<div class="table-header col-second">Optional Element</div>
<div class="table-header col-last">Description</div>
<div class="col-first even-row-color"><code>java.lang.String</code></div>
<div class="col-second even-row-color"><code><a href="#optional()" class="member-name-link">optional</a></code></div>
<div class="col-last even-row-color">&nbsp;</div>
</div>
</section>
</li>
</ul>
</section>""",
"""
<section class="details" id="annotation-interface-element-detail">
<ul class="details-list">
<!-- ============ ANNOTATION INTERFACE MEMBER DETAIL =========== -->
<li>
<section class="member-details">
<h2>Element Details</h2>
<ul class="member-list">
<li>
<section class="detail" id="value()">
<h3>value</h3>
<div class="member-signature"><span class="return-type">int</span>&nbsp;<span class="element-name">value</span></div>
</section>
</li>
<li>
<section class="detail" id="optional()">
<h3>optional</h3>
<div class="member-signature"><span class="return-type">java.lang.String</span>&nbsp;<span class="element-name">optional</span></div>
<dl class="notes">
<dt>Default:</dt>
<dd>""</dd>
</dl>
</section>
</li>
</ul>
</section>
</li>
</ul>
</section>""");
checkOutput("pkg/AnnotationType.html", false, checkOutput("pkg/AnnotationType.html", false,
""" """

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -30,4 +30,5 @@ import java.lang.annotation.*;
*/ */
@Documented public @interface AnnotationType { @Documented public @interface AnnotationType {
int value(); int value();
String optional() default "";
} }