8316972: Add javadoc support for restricted methods

Co-authored-by: Maurizio Cimadamore <mcimadamore@openjdk.org>
Reviewed-by: jjg
This commit is contained in:
Hannes Wallnöfer 2023-10-17 20:32:41 +00:00
parent 5145e5a40a
commit 0ba48ef4ab
24 changed files with 534 additions and 27 deletions

View File

@ -537,6 +537,16 @@ public abstract class AbstractMemberWriter {
writer.addPreviewInfo(member, content);
}
/**
* Add the restricted information for the given method.
*
* @param method the method being documented.
* @param content the content to which the preview information will be added.
*/
protected void addRestrictedInfo(ExecutableElement method, Content content) {
writer.addRestrictedInfo(method, content);
}
protected String name(Element member) {
return utils.getSimpleName(member);
}

View File

@ -157,6 +157,9 @@ public class Contents {
public final Content previewLabel;
public final Content previewMark;
public final Content previewPhrase;
public final Content restrictedMark;
public final Content restrictedMethods;
public final Content restrictedPhrase;
public final Content properties;
public final Content propertyLabel;
public final Content propertyDetailsLabel;
@ -303,6 +306,9 @@ public class Contents {
previewLabel = getContent("doclet.Preview_Label");
previewMark = getContent("doclet.Preview_Mark");
previewPhrase = getContent("doclet.Preview");
restrictedMark = getContent("doclet.Restricted_Mark");
restrictedMethods = getContent("doclet.Restricted_Methods");
restrictedPhrase = getContent("doclet.Restricted");
properties = getContent("doclet.Properties");
propertyLabel = getContent("doclet.Property");
propertyDetailsLabel = getContent("doclet.Property_Detail");

View File

@ -342,6 +342,15 @@ public class HelpWriter extends HtmlDocletWriter {
pageKindsSection.add(section);
}
// Restricted
if (configuration.conditionalPages.contains(HtmlConfiguration.ConditionalPage.RESTRICTED)) {
section = newHelpSection(contents.restrictedMethods, PageMode.RESTRICTED, subTOC);
Content restrictedBody = getContent("doclet.help.restricted.body",
links.createLink(DocPaths.RESTRICTED_LIST, resources.getText("doclet.Restricted_Methods")));
section.add(HtmlTree.P(restrictedBody));
pageKindsSection.add(section);
}
// Constant Field Values
if (configuration.conditionalPages.contains(HtmlConfiguration.ConditionalPage.CONSTANT_VALUES)) {
section = newHelpSection(contents.constantsSummaryTitle, PageMode.CONSTANT_VALUES, subTOC);

View File

@ -68,6 +68,7 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.NewAPIBuilder;
import jdk.javadoc.internal.doclets.toolkit.util.PreviewAPIListBuilder;
import jdk.javadoc.internal.doclets.toolkit.util.RestrictedAPIListBuilder;
import jdk.javadoc.internal.doclets.toolkit.util.SimpleDocletException;
/**
@ -139,6 +140,14 @@ public class HtmlConfiguration extends BaseConfiguration {
*/
protected NewAPIBuilder newAPIPageBuilder;
/**
* The collection of restricted methods, if any, to be displayed on the
* restricted-list page, or null if the page should not be generated.
* The page will not be generated if there are no restricted methods to be
* documented.
*/
protected RestrictedAPIListBuilder restrictedAPIListBuilder;
public Contents contents;
public final Messages messages;
@ -162,7 +171,8 @@ public class HtmlConfiguration extends BaseConfiguration {
// Note: this should (eventually) be merged with Navigation.PageMode,
// which performs a somewhat similar role
public enum ConditionalPage {
CONSTANT_VALUES, DEPRECATED, EXTERNAL_SPECS, PREVIEW, SERIALIZED_FORM, SYSTEM_PROPERTIES, NEW
CONSTANT_VALUES, DEPRECATED, EXTERNAL_SPECS, PREVIEW, RESTRICTED,
SERIALIZED_FORM, SYSTEM_PROPERTIES, NEW
}
/**

View File

@ -62,6 +62,7 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.NewAPIBuilder;
import jdk.javadoc.internal.doclets.toolkit.util.PreviewAPIListBuilder;
import jdk.javadoc.internal.doclets.toolkit.util.ResourceIOException;
import jdk.javadoc.internal.doclets.toolkit.util.RestrictedAPIListBuilder;
/**
* The class with "start" method, calls individual Writers.
@ -195,6 +196,11 @@ public class HtmlDoclet extends AbstractDoclet {
configuration.previewAPIListBuilder = previewBuilder;
configuration.conditionalPages.add(HtmlConfiguration.ConditionalPage.PREVIEW);
}
RestrictedAPIListBuilder restrictedBuilder = new RestrictedAPIListBuilder(configuration);
if (!restrictedBuilder.isEmpty()) {
configuration.restrictedAPIListBuilder = restrictedBuilder;
configuration.conditionalPages.add(HtmlConfiguration.ConditionalPage.RESTRICTED);
}
super.generateClassFiles(classTree);
}
@ -247,12 +253,14 @@ public class HtmlDoclet extends AbstractDoclet {
for (var cp : EnumSet.of(
HtmlConfiguration.ConditionalPage.DEPRECATED,
HtmlConfiguration.ConditionalPage.PREVIEW,
HtmlConfiguration.ConditionalPage.RESTRICTED,
HtmlConfiguration.ConditionalPage.NEW)) {
if (configuration.conditionalPages.contains(cp)) {
var w = switch (cp) {
case DEPRECATED -> writerFactory.newDeprecatedListWriter();
case NEW -> writerFactory.newNewAPIListWriter();
case PREVIEW -> writerFactory.newPreviewListWriter();
case RESTRICTED -> writerFactory.newRestrictedListWriter();
default -> throw new AssertionError();
};
w.buildPage();

View File

@ -2053,6 +2053,14 @@ public abstract class HtmlDocletWriter {
}
}
public void addRestrictedSummary(Element forWhat, Content target) {
if (utils.isRestrictedAPI(forWhat)) {
var div = HtmlTree.DIV(HtmlStyle.block);
div.add(HtmlTree.SPAN(HtmlStyle.restrictedLabel, contents.restrictedPhrase));
target.add(div);
}
}
public void addPreviewInfo(Element forWhat, Content target) {
if (utils.isPreviewAPI(forWhat)) {
//in Java platform:
@ -2203,4 +2211,24 @@ public abstract class HtmlDocletWriter {
return specURI;
}
public void addRestrictedInfo(ExecutableElement forWhat, Content target) {
if (utils.isRestrictedAPI(forWhat)) {
//in Java platform:
var restrictedDiv = HtmlTree.DIV(HtmlStyle.restrictedBlock);
restrictedDiv.setId(htmlIds.forRestrictedSection(forWhat));
String name = forWhat.getSimpleName().toString();
var nameCode = HtmlTree.CODE(Text.of(name));
String leadingNoteKey = "doclet.RestrictedLeadingNote";
Content leadingNote =
contents.getContent(leadingNoteKey, nameCode);
restrictedDiv.add(HtmlTree.SPAN(HtmlStyle.restrictedLabel,
leadingNote));
Content note1 = contents.getContent("doclet.RestrictedTrailingNote1", nameCode);
restrictedDiv.add(HtmlTree.DIV(HtmlStyle.restrictedComment, note1));
Content note2 = contents.getContent("doclet.RestrictedTrailingNote2", nameCode);
restrictedDiv.add(HtmlTree.DIV(HtmlStyle.restrictedComment, note2));
target.add(restrictedDiv);
}
}
}

View File

@ -489,6 +489,17 @@ public class HtmlIds {
});
}
/**
* Returns an id for the "restricted" section for an executable element.
*
* @param el the executable element
*
* @return the id
*/
public HtmlId forRestrictedSection(ExecutableElement el) {
return HtmlId.of("restricted-" + forMember(el).name());
}
/**
* Returns an id for the entry on the HELP page for a kind of generated page.
*

View File

@ -29,9 +29,11 @@ import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.type.ArrayType;
@ -42,6 +44,7 @@ import javax.lang.model.type.WildcardType;
import javax.lang.model.util.SimpleTypeVisitor14;
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.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.TagName;
import jdk.javadoc.internal.doclets.formats.html.markup.Text;
@ -235,12 +238,17 @@ public class HtmlLinkFactory {
}
Set<ElementFlag> flags;
Element previewTarget;
ExecutableElement restrictedTarget;
boolean showPreview = !linkInfo.isSkipPreview();
if (!hasFragment && showPreview) {
flags = utils.elementFlags(typeElement);
previewTarget = typeElement;
restrictedTarget = null;
} else if (linkInfo.getContext() == HtmlLinkInfo.Kind.SHOW_PREVIEW
&& linkInfo.getTargetMember() != null && showPreview) {
// We piggy back on whether to show preview info, for both preview AND
// restricted methods superscripts. That's because when e.g. we are generating a
// method summary we do not want either superscript.
flags = utils.elementFlags(linkInfo.getTargetMember());
TypeElement enclosing = utils.getEnclosingTypeElement(linkInfo.getTargetMember());
Set<ElementFlag> enclosingFlags = utils.elementFlags(enclosing);
@ -254,8 +262,14 @@ public class HtmlLinkFactory {
} else {
previewTarget = linkInfo.getTargetMember();
}
if (flags.contains(ElementFlag.RESTRICTED)) {
restrictedTarget = (ExecutableElement) linkInfo.getTargetMember();
} else {
restrictedTarget = null;
}
} else {
flags = EnumSet.noneOf(ElementFlag.class);
restrictedTarget = null;
previewTarget = null;
}
@ -269,10 +283,18 @@ public class HtmlLinkFactory {
label,
linkInfo.getStyle(),
title));
Content spacer = Text.EMPTY;
if (flags.contains(ElementFlag.PREVIEW)) {
link.add(HtmlTree.SUP(m_writer.links.createLink(
filename.fragment(m_writer.htmlIds.forPreviewSection(previewTarget).name()),
m_writer.contents.previewMark)));
spacer = Entity.NO_BREAK_SPACE;
}
if (flags.contains(ElementFlag.RESTRICTED)) {
link.add(spacer);
link.add(HtmlTree.SUP(m_writer.links.createLink(
filename.fragment(m_writer.htmlIds.forRestrictedSection(restrictedTarget).name()),
m_writer.contents.restrictedMark)));
}
return link;
}
@ -283,20 +305,36 @@ public class HtmlLinkFactory {
label, linkInfo.getStyle(), true);
if (crossLink != null) {
link.add(crossLink);
Content spacer = Text.EMPTY;
if (flags.contains(ElementFlag.PREVIEW)) {
link.add(HtmlTree.SUP(m_writer.getCrossClassLink(
typeElement,
m_writer.htmlIds.forPreviewSection(previewTarget).name(),
m_writer.contents.previewMark,
null, false)));
spacer = Entity.NO_BREAK_SPACE;
}
if (flags.contains(ElementFlag.RESTRICTED)) {
link.add(spacer);
link.add(HtmlTree.SUP(m_writer.getCrossClassLink(
typeElement,
m_writer.htmlIds.forRestrictedSection(restrictedTarget).name(),
m_writer.contents.restrictedMark,
null, false)));
}
return link;
}
}
// Can't link so just write label.
link.add(label);
Content spacer = Text.EMPTY;
if (flags.contains(ElementFlag.PREVIEW)) {
link.add(HtmlTree.SUP(m_writer.contents.previewMark));
spacer = Entity.NO_BREAK_SPACE;
}
if (flags.contains(ElementFlag.RESTRICTED)) {
link.add(spacer);
link.add(HtmlTree.SUP(m_writer.contents.restrictedMark));
}
return link;
}

View File

@ -109,6 +109,7 @@ public class MethodWriter extends AbstractExecutableMemberWriter {
buildSignature(div);
buildDeprecationInfo(div);
buildPreviewInfo(div);
buildRestrictedInfo(div);
buildMethodComments(div);
buildTagInfo(div);
methodContent.add(div);
@ -134,6 +135,15 @@ public class MethodWriter extends AbstractExecutableMemberWriter {
addPreview(currentMethod, target);
}
/**
* Builds the restricted method info.
*
* @param target the content to which the documentation will be added
*/
protected void buildRestrictedInfo(Content target) {
addRestricted(currentMethod, target);
}
/**
* Build the comments for the method. Do nothing if
* {@link BaseOptions#noComment()} is set to true.
@ -215,6 +225,10 @@ public class MethodWriter extends AbstractExecutableMemberWriter {
addPreviewInfo(method, content);
}
protected void addRestricted(ExecutableElement method, Content content) {
addRestrictedInfo(method, content);
}
protected void addComments(TypeMirror holderType, ExecutableElement method, Content methodContent) {
TypeElement holder = utils.asTypeElement(holderType);
if (!utils.getFullBody(method).isEmpty()) {

View File

@ -91,6 +91,7 @@ public class Navigation {
OVERVIEW,
PACKAGE,
PREVIEW,
RESTRICTED,
SERIALIZED_FORM,
SEARCH,
SYSTEM_PROPERTIES,
@ -316,6 +317,7 @@ public class Navigation {
case ALL_PACKAGES:
case CONSTANT_VALUES:
case EXTERNAL_SPECS:
case RESTRICTED:
case SERIALIZED_FORM:
case SEARCH:
case SYSTEM_PROPERTIES:

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2023, 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.Element;
import jdk.javadoc.internal.doclets.formats.html.Navigation.PageMode;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.IndexItem;
import jdk.javadoc.internal.doclets.toolkit.util.RestrictedAPIListBuilder;
/**
* Generate File to list all the restricted methods with the
* appropriate links.
*/
public class RestrictedListWriter extends SummaryListWriter<RestrictedAPIListBuilder> {
/**
* Constructor.
*
* @param configuration the configuration for this doclet
*/
public RestrictedListWriter(HtmlConfiguration configuration) {
super(configuration, DocPaths.RESTRICTED_LIST, configuration.restrictedAPIListBuilder);
if (configuration.restrictedAPIListBuilder != null) {
configuration.indexBuilder.add(IndexItem.of(IndexItem.Category.TAGS,
resources.getText("doclet.Restricted_Methods"), path));
}
}
@Override
protected PageMode getPageMode() {
return PageMode.RESTRICTED;
}
@Override
protected String getDescription() {
return "restricted methods";
}
@Override
protected boolean showContentsList() {
// This list contains only methods, no need to show list of element kinds.
return false;
}
@Override
protected Content getHeadContent() {
return configuration.contents.restrictedMethods;
}
@Override
protected String getTitleKey() {
return "doclet.Window_Restricted_List";
}
@Override
protected void addComments(Element e, Content desc) {
addSummaryComment(e, desc);
}
}

View File

@ -113,6 +113,7 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter {
protected void addIndexComment(Element member, List<? extends DocTree> firstSentenceTags,
Content tdSummaryContent) {
addPreviewSummary(member, tdSummaryContent);
addRestrictedSummary(member, tdSummaryContent);
List<? extends DeprecatedTree> deprs = utils.getDeprecatedTrees(member);
Content div;
if (utils.isDeprecated(member)) {

View File

@ -25,6 +25,7 @@
package jdk.javadoc.internal.doclets.formats.html;
import java.util.Arrays;
import java.util.SortedSet;
import javax.lang.model.element.Element;
@ -138,8 +139,10 @@ public abstract class SummaryListWriter<B extends SummaryAPIListBuilder> extends
HtmlStyle.title, getHeadContent());
content.add(HtmlTree.DIV(HtmlStyle.header, heading));
addContentSelectors(content);
content.add(HtmlTree.HEADING_TITLE(Headings.CONTENT_HEADING, contents.contentsHeading));
content.add(getContentsList());
if (showContentsList()) {
content.add(HtmlTree.HEADING_TITLE(Headings.CONTENT_HEADING, contents.contentsHeading));
content.add(getContentsList());
}
addExtraSection(content);
for (SummaryElementKind kind : SummaryElementKind.values()) {
if (builder.hasDocumentation(kind)) {
@ -184,6 +187,13 @@ public abstract class SummaryListWriter<B extends SummaryAPIListBuilder> extends
content.add(li);
}
/**
* {@return {@code true} if the contents list should be generated, {@code false} if not}
*/
protected boolean showContentsList() {
return true;
}
/**
* Get the contents list.
*
@ -304,21 +314,23 @@ public abstract class SummaryListWriter<B extends SummaryAPIListBuilder> extends
}
/**
* Subclasses allow the user to show or hide parts of the content in the page.
* This method should be used to add the UI to select the visible page content.
* Allow Subclasses to add a content selector UI such as a row of radio buttons
* near the top of the page. This method does not add anything.
*
* @param target the content to which the UI should be added
*/
protected abstract void addContentSelectors(Content target);
protected void addContentSelectors(Content target) {}
/**
* Some subclasses of this class display an extra column in their element tables.
* This methods allows them to return the content to show for {@code element}.
* Allow subclasses to add an extra table column for an element.
* This methods does not add any content by returning {@code null}.
*
* @param element the element
* @return content for extra content or null
*/
protected abstract Content getExtraContent(Element element);
protected Content getExtraContent(Element element) {
return null;
}
/**
* Gets the table header to use for a table with the first column identified by {@code headerKey}.
@ -352,10 +364,11 @@ public abstract class SummaryListWriter<B extends SummaryAPIListBuilder> extends
}
/**
* Allow subclasses to add extra tabs to the element tables.
* Allow subclasses to add extra tabs to the element tables. This method does not
* add any tabs.
*
* @param table the element table
* @param headingKey the key for the caption (default tab)
*/
protected abstract void addTableTabs(Table<Element> table, String headingKey);
protected void addTableTabs(Table<Element> table, String headingKey) {}
}

View File

@ -170,6 +170,13 @@ public class WriterFactory {
return new PreviewListWriter(configuration);
}
/**
* {@return a new writer for the list of restricted methods in this release}
*/
public HtmlDocletWriter newRestrictedListWriter() {
return new RestrictedListWriter(configuration);
}
/**
* {@return a new writer for the "search" page}
*/

View File

@ -382,6 +382,22 @@ public enum HtmlStyle {
*/
previewLabel,
/**
* The class for a block describing the "restricted" status of a declaration.
*/
restrictedBlock,
/**
* The class for the details in a block describing the "restricted" status of a declaration.
*/
restrictedComment,
/**
* The class for the "Restricted" label in a block describing the "restricted" status
* of a declaration.
*/
restrictedLabel,
/**
* The class for a list containing the tags of an element.
*/
@ -793,6 +809,11 @@ public enum HtmlStyle {
*/
previewListPage,
/**
* The class of the {@code body} element for the page listing restricted methods.
*/
restrictedListPage,
/**
* The class of the {@code body} element for the search page.
*/

View File

@ -85,6 +85,7 @@ doclet.navDeprecated=Deprecated
doclet.Window_Deprecated_List=Deprecated List
doclet.Window_New_List=New API List
doclet.Window_Preview_List=Preview List
doclet.Window_Restricted_List=Restricted Method List
doclet.Overrides=Overrides:
doclet.in_class=in class
doclet.Element_in=Element in {0}
@ -129,6 +130,8 @@ doclet.Preview_API_Checkbox_Label=Show preview API for:
doclet.Preview_JEP_URL=https://openjdk.org/jeps/{0}
doclet.Preview_Label=Preview
doclet.Preview_Mark=PREVIEW
doclet.Restricted_Methods=Restricted Methods
doclet.Restricted_Mark=RESTRICTED
doclet.Terminally_Deprecated=Terminally Deprecated
doclet.Terminally_Deprecated_Elements=Terminally Deprecated Elements
doclet.Terminally_Deprecated_In_Release=Terminally Deprecated in {0}
@ -303,6 +306,9 @@ doclet.help.preview.body=\
Preview APIs may be removed in future implementations.
doclet.help.new.body=\
The {0} page lists APIs that have been added in recent releases.
doclet.help.restricted.body=\
The {0} page lists all restricted methods. Restricted methods are unsafe, and, if used \
incorrectly, might crash the JVM or result in memory corruption.
doclet.help.index.head=\
Index
# 0: link to Index page; 1: list of links to pages
@ -410,6 +416,10 @@ doclet.ReflectivePreviewAPI={0} refers to one or more reflective preview APIs:
doclet.UsesDeclaredUsingPreview={0} refers to one or more types which are declared using a preview feature of the Java language: {1}.
doclet.PreviewTrailingNote1=Programs can only use {0} when preview features are enabled.
doclet.PreviewTrailingNote2=Preview features may be removed in a future release, or upgraded to permanent features of the Java platform.
doclet.RestrictedLeadingNote={0} is a restricted method of the Java platform.
doclet.RestrictedTrailingNote1=Programs can only use {0} when access to restricted methods is enabled.
doclet.RestrictedTrailingNote2=Restricted methods are unsafe, and, if used incorrectly, might crash \
the JVM or result in memory corruption.
doclet.Declared_Using_Preview.SEALED=Sealed Classes
doclet.Declared_Using_Preview.SEALED_PERMITS=Sealed Classes
doclet.PreviewPlatformLeadingNote={0} is a preview API of the Java platform.

View File

@ -647,24 +647,13 @@ div.block {
}
.deprecated-label, .description-from-type-label, .implementation-label, .member-name-link,
.module-label-in-package, .module-label-in-type, .package-label-in-type,
.package-hierarchy-label, .type-name-label, .type-name-link, .search-tag-link, .preview-label {
.package-hierarchy-label, .type-name-label, .type-name-link, .search-tag-link, .preview-label, .restricted-label {
font-weight:bold;
}
.deprecation-comment, .help-footnote, .preview-comment {
.deprecation-comment, .help-footnote, .preview-comment, .restricted-comment {
font-style:italic;
}
.deprecation-block {
font-size:1em;
font-family:var(--block-font-family);
border-style:solid;
border-width:thin;
border-radius:10px;
padding:10px;
margin-bottom:10px;
margin-right:10px;
display:inline-block;
}
.preview-block {
.deprecation-block, .preview-block, .restricted-block {
font-size:1em;
font-family:var(--block-font-family);
border-style:solid;

View File

@ -429,6 +429,11 @@ public class WorkArounds {
}
}
public boolean isRestrictedAPI(Element el) {
Symbol sym = (Symbol) el;
return sym.kind == MTH && (sym.flags() & Flags.RESTRICTED) != 0;
}
public boolean isPreviewAPI(Element el) {
Symbol sym = (Symbol) el;
return (sym.flags() & Flags.PREVIEW_API) != 0;

View File

@ -213,6 +213,7 @@ doclet.dest_dir_create=Creating destination directory: "{0}"
doclet.in={0} in {1}
doclet.Fields=Fields
doclet.Preview=Preview.
doclet.Restricted=Restricted.
doclet.Properties=Properties
doclet.Constructors=Constructors
doclet.Methods=Methods

View File

@ -148,6 +148,9 @@ public class DocPaths {
/** The name of the file for preview elements. */
public static final DocPath PREVIEW_LIST = DocPath.create("preview-list.html");
/** The name of the file for restricted methods. */
public static final DocPath RESTRICTED_LIST = DocPath.create("restricted-list.html");
/** The name of the directory for the resource files. */
public static final DocPath RESOURCE_FILES = DocPath.create("resource-files");

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2023, 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.util;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import javax.lang.model.element.Element;
/**
* Build list of all the restricted methods.
*/
public class RestrictedAPIListBuilder extends SummaryAPIListBuilder {
/**
* Constructor.
*
* @param configuration the current configuration of the doclet
*/
public RestrictedAPIListBuilder(BaseConfiguration configuration) {
super(configuration, configuration.utils::isRestrictedAPI);
buildSummaryAPIInfo();
}
}

View File

@ -2740,6 +2740,16 @@ public class Utils {
return isPreviewAPI(el) && configuration.workArounds.isReflectivePreviewAPI(el);
}
/**
* Checks whether the given ExecutableElement should be marked as a restricted API.
*
* @param el the element to check
* @return true if and only if the given element should be marked as a restricted API
*/
public boolean isRestrictedAPI(Element el) {
return configuration.workArounds.isRestrictedAPI(el);
}
/**
* Return all flags for the given Element.
*
@ -2753,6 +2763,10 @@ public class Utils {
flags.add(ElementFlag.DEPRECATED);
}
if (el.getKind() == ElementKind.METHOD && configuration.workArounds.isRestrictedAPI((ExecutableElement)el)) {
flags.add(ElementFlag.RESTRICTED);
}
if (previewFlagProvider.isPreview(el)) {
flags.add(ElementFlag.PREVIEW);
}
@ -2766,7 +2780,8 @@ public class Utils {
*/
public enum ElementFlag {
DEPRECATED,
PREVIEW
PREVIEW,
RESTRICTED
}
private boolean isClassOrInterface(Element el) {

View File

@ -0,0 +1,175 @@
/*
* Copyright (c) 2023, 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.
*
* 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.
*/
/*
* @test
* @bug 8316972
* @summary Add javadoc support for restricted methods
* @library /tools/lib ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
* @build toolbox.ToolBox javadoc.tester.*
* @run main TestRestricted
*/
import java.io.IOException;
import java.nio.file.Path;
import javadoc.tester.JavadocTester;
import toolbox.ToolBox;
public class TestRestricted extends JavadocTester {
public final ToolBox tb;
public static void main(String... args) throws Exception {
var tester = new TestRestricted();
tester.runTests();
}
public TestRestricted() {
tb = new ToolBox();
}
@Test
public void testRestricted(Path base) throws IOException {
var src = base.resolve("src");
tb.writeJavaFiles(src, """
package pkg;
import jdk.internal.javac.PreviewFeature;
import jdk.internal.javac.PreviewFeature.Feature;
import jdk.internal.javac.Restricted;
/**
* Interface containing restricted methods.
* @see #restrictedMethod()
* @see #restrictedPreviewMethod()
*/
public interface I {
/**
* Restricted method.
*/
@Restricted
public void restrictedMethod();
/**
* Restricted preview method.
*/
@PreviewFeature(feature=Feature.TEST)
@Restricted
public int restrictedPreviewMethod();
}
""");
javadoc("--enable-preview", "-source", System.getProperty("java.specification.version"),
"--add-exports", "java.base/jdk.internal.javac=ALL-UNNAMED",
"-d", base.resolve("api").toString(),
"-sourcepath", src.toString(),
"pkg");
checkExit(Exit.OK);
// Test restricted method note in class documentation
checkOutput("pkg/I.html", true,
"""
<ul class="tag-list-long">
<li><a href="#restrictedMethod()"><code>restrictedMethod()</code></a><sup><a href="\
#restricted-restrictedMethod()">RESTRICTED</a></sup></li>
<li><a href="#restrictedPreviewMethod()"><code>restrictedPreviewMethod()</code></a>\
<sup><a href="#preview-restrictedPreviewMethod()">PREVIEW</a></sup>&nbsp;<sup><a hr\
ef="#restricted-restrictedPreviewMethod()">RESTRICTED</a></sup></li>""",
"""
<div class="block"><span class="restricted-label">Restricted.</span></div>
<div class="block">Restricted method.</div>""",
"""
<div class="block"><span class="preview-label">Preview.</span></div>
<div class="block"><span class="restricted-label">Restricted.</span></div>
<div class="block">Restricted preview method.</div>""",
"""
<h3>restrictedMethod</h3>
<div class="horizontal-scroll">
<div class="member-signature"><span class="modifiers">sealed</span>&nbsp;<span clas\
s="return-type">void</span>&nbsp;<span class="element-name">restrictedMethod</span>\
()</div>
<div class="restricted-block" id="restricted-restrictedMethod()"><span class="restr\
icted-label"><code>restrictedMethod</code> is a restricted method of the Java platf\
orm.</span>
<div class="restricted-comment">Programs can only use <code>restrictedMethod</code>\
when access to restricted methods is enabled.</div>
<div class="restricted-comment">Restricted methods are unsafe, and, if used incorre\
ctly, might crash the JVM or result in memory corruption.</div>
</div>""",
"""
<h3>restrictedPreviewMethod</h3>
<div class="horizontal-scroll">
<div class="member-signature"><span class="modifiers">sealed</span>&nbsp;<span clas\
s="return-type">int</span>&nbsp;<span class="element-name">restrictedPreviewMethod<\
/span>()</div>
<div class="preview-block" id="preview-restrictedPreviewMethod()"><span class="prev\
iew-label"><code>restrictedPreviewMethod</code> is a preview API of the Java platfo\
rm.</span>
<div class="preview-comment">Programs can only use <code>restrictedPreviewMethod</c\
ode> when preview features are enabled.</div>
<div class="preview-comment">Preview features may be removed in a future release, o\
r upgraded to permanent features of the Java platform.</div>
</div>
<div class="restricted-block" id="restricted-restrictedPreviewMethod()"><span class\
="restricted-label"><code>restrictedPreviewMethod</code> is a restricted method of \
the Java platform.</span>
<div class="restricted-comment">Programs can only use <code>restrictedPreviewMethod\
</code> when access to restricted methods is enabled.</div>
<div class="restricted-comment">Restricted methods are unsafe, and, if used incorre\
ctly, might crash the JVM or result in memory corruption.</div>
</div>""");
// Test link on index page
checkOutput("index-all.html", true,
"""
<a href="restricted-list.html">Restricted&nbsp;Methods</a>""");
// Test restricted methods list
checkOutput("restricted-list.html", true,
"""
<h1 title="Restricted Methods" class="title">Restricted Methods</h1>
</div>
<ul class="block-list">
<li>
<div id="method">
<div class="caption"><span>Methods</span></div>
<div class="summary-table two-column-summary">
<div class="table-header col-first">Method</div>
<div class="table-header col-last">Description</div>
<div class="col-summary-item-name even-row-color"><a href="pkg/I.html#restrictedMet\
hod()">pkg.I.restrictedMethod()</a><sup><a href="pkg/I.html#restricted-restrictedMe\
thod()">RESTRICTED</a></sup></div>
<div class="col-last even-row-color">
<div class="block">Restricted method.</div>
</div>
<div class="col-summary-item-name odd-row-color"><a href="pkg/I.html#restrictedPrev\
iewMethod()">pkg.I.restrictedPreviewMethod()</a><sup><a href="pkg/I.html#preview-re\
strictedPreviewMethod()">PREVIEW</a></sup>&nbsp;<sup><a href="pkg/I.html#restricted\
-restrictedPreviewMethod()">RESTRICTED</a></sup></div>
<div class="col-last odd-row-color">
<div class="block">Restricted preview method.</div>
</div>""");
}
}

View File

@ -161,7 +161,7 @@ public class TestStylesheet extends JavadocTester {
font-weight:bold;
}""",
"""
.deprecation-block {
.deprecation-block, .preview-block, .restricted-block {
font-size:1em;
font-family:var(--block-font-family);
border-style:solid;