diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java index 59f981d7cac..b6c56dd47b0 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java @@ -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); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java index a7a23b07170..2c1ab3ae882 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java @@ -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"); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java index 2461567d932..1adff39ff1a 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java @@ -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); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java index 3ee4f327a95..2269f2a4a55 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java @@ -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 } /** diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java index 6235a03f124..75e60be8cf3 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java @@ -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(); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index cc02115d247..492743a704b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -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); + } + } + } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java index 8e14d02b4e0..5237811ab8e 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java @@ -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. * diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java index 93e860e275f..df9dd9b77ae 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java @@ -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 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 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; } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriter.java index 5f8fdfe1010..4cb066f0adf 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriter.java @@ -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()) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java index fb75d36946b..9b5b5fc0848 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java @@ -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: diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/RestrictedListWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/RestrictedListWriter.java new file mode 100644 index 00000000000..bfd062706a9 --- /dev/null +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/RestrictedListWriter.java @@ -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 { + + /** + * 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); + } +} diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java index 379bd72209f..08743dcba2f 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java @@ -113,6 +113,7 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { protected void addIndexComment(Element member, List firstSentenceTags, Content tdSummaryContent) { addPreviewSummary(member, tdSummaryContent); + addRestrictedSummary(member, tdSummaryContent); List deprs = utils.getDeprecatedTrees(member); Content div; if (utils.isDeprecated(member)) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SummaryListWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SummaryListWriter.java index a4e43dffb76..f69d8078b47 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SummaryListWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SummaryListWriter.java @@ -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 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 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 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 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 table, String headingKey); + protected void addTableTabs(Table table, String headingKey) {} } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactory.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactory.java index e0db835554a..064fff0879d 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactory.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactory.java @@ -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} */ diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java index 58d9204ec6b..c6e1263d665 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java @@ -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. */ diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties index 1e517e4e0f0..b83768ea31a 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties @@ -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. diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css index bb5e423ce2b..a55e6d53c0b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css @@ -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; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java index 0aa425e54dc..3580f13e3f5 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java @@ -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; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties index ddc639133ff..e90bc63e6a5 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties @@ -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 diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java index 0bf681c045b..9388566ea3d 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java @@ -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"); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/RestrictedAPIListBuilder.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/RestrictedAPIListBuilder.java new file mode 100644 index 00000000000..caf89cabebe --- /dev/null +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/RestrictedAPIListBuilder.java @@ -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(); + } +} diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java index 76963686e8a..da021d5c84f 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java @@ -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) { diff --git a/test/langtools/jdk/javadoc/doclet/testRestricted/TestRestricted.java b/test/langtools/jdk/javadoc/doclet/testRestricted/TestRestricted.java new file mode 100644 index 00000000000..b9dd80d61fb --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testRestricted/TestRestricted.java @@ -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, + """ +
    +
  • restrictedMethod()RESTRICTED
  • +
  • restrictedPreviewMethod()\ + PREVIEW RESTRICTED
  • """, + """ +
    Restricted.
    +
    Restricted method.
    """, + """ +
    Preview.
    +
    Restricted.
    +
    Restricted preview method.
    """, + """ +

    restrictedMethod

    +
    +
    sealed void restrictedMethod\ + ()
    +
    restrictedMethod is a restricted method of the Java platf\ + orm. +
    Programs can only use restrictedMethod\ + when access to restricted methods is enabled.
    +
    Restricted methods are unsafe, and, if used incorre\ + ctly, might crash the JVM or result in memory corruption.
    +
    """, + """ +

    restrictedPreviewMethod

    +
    +
    sealed int restrictedPreviewMethod<\ + /span>()
    +
    restrictedPreviewMethod is a preview API of the Java platfo\ + rm. +
    Programs can only use restrictedPreviewMethod when preview features are enabled.
    +
    Preview features may be removed in a future release, o\ + r upgraded to permanent features of the Java platform.
    +
    +
    restrictedPreviewMethod is a restricted method of \ + the Java platform. +
    Programs can only use restrictedPreviewMethod\ + when access to restricted methods is enabled.
    +
    Restricted methods are unsafe, and, if used incorre\ + ctly, might crash the JVM or result in memory corruption.
    +
    """); + + // Test link on index page + checkOutput("index-all.html", true, + """ + Restricted Methods"""); + + // Test restricted methods list + checkOutput("restricted-list.html", true, + """ +

    Restricted Methods

    +
    +
      +
    • +
      +
      Methods
      +
      +
      Method
      +
      Description
      + +
      +
      Restricted method.
      +
      + +
      +
      Restricted preview method.
      +
      """); + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java b/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java index 59649c53d48..d1bf5a4f2b3 100644 --- a/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java +++ b/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java @@ -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;