Skip to content

Commit

Permalink
8277300: Issues with javadoc support for preview features
Browse files Browse the repository at this point in the history
Reviewed-by: prappo, jjg
  • Loading branch information
lahodaj committed Feb 18, 2022
1 parent 138a171 commit 834d55c
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2022, 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
Expand Down Expand Up @@ -89,18 +89,29 @@ protected Content getClassLink(LinkInfo linkInfo) {
}
Content label = classLinkInfo.getClassLinkLabel(configuration);
Set<ElementFlag> flags;
Element target;
Element previewTarget;
boolean showPreview = !classLinkInfo.skipPreview;
if (!hasWhere && showPreview) {
flags = utils.elementFlags(typeElement);
target = typeElement;
previewTarget = typeElement;
} else if ((classLinkInfo.context == HtmlLinkInfo.Kind.SEE_TAG || classLinkInfo.context == HtmlLinkInfo.Kind.MEMBER_DEPRECATED_PREVIEW) &&
classLinkInfo.targetMember != null && showPreview) {
flags = utils.elementFlags(classLinkInfo.targetMember);
target = classLinkInfo.targetMember;
TypeElement enclosing = utils.getEnclosingTypeElement(classLinkInfo.targetMember);
Set<ElementFlag> enclosingFlags = utils.elementFlags(enclosing);
if (flags.contains(ElementFlag.PREVIEW) && enclosingFlags.contains(ElementFlag.PREVIEW)) {
if (enclosing.equals(m_writer.getCurrentPageElement())) {
//skip the PREVIEW tag:
flags = EnumSet.copyOf(flags);
flags.remove(ElementFlag.PREVIEW);
}
previewTarget = enclosing;
} else {
previewTarget = classLinkInfo.targetMember;
}
} else {
flags = EnumSet.noneOf(ElementFlag.class);
target = null;
previewTarget = null;
}

Content link = new ContentBuilder();
Expand All @@ -115,7 +126,7 @@ protected Content getClassLink(LinkInfo linkInfo) {
title));
if (flags.contains(ElementFlag.PREVIEW)) {
link.add(HtmlTree.SUP(m_writer.links.createLink(
filename.fragment(m_writer.htmlIds.forPreviewSection(target).name()),
filename.fragment(m_writer.htmlIds.forPreviewSection(previewTarget).name()),
m_writer.contents.previewMark)));
}
return link;
Expand All @@ -130,7 +141,7 @@ protected Content getClassLink(LinkInfo linkInfo) {
if (flags.contains(ElementFlag.PREVIEW)) {
link.add(HtmlTree.SUP(m_writer.getCrossClassLink(
typeElement,
m_writer.htmlIds.forPreviewSection(target).name(),
m_writer.htmlIds.forPreviewSection(previewTarget).name(),
m_writer.contents.previewMark,
null, false)));
}
Expand Down Expand Up @@ -192,7 +203,7 @@ protected Content getTypeParameterLinks(LinkInfo linkInfo) {
*/
protected Content getTypeParameterLink(LinkInfo linkInfo, TypeMirror typeParam) {
HtmlLinkInfo typeLinkInfo = new HtmlLinkInfo(m_writer.configuration,
((HtmlLinkInfo) linkInfo).getContext(), typeParam).skipPreview(true);
((HtmlLinkInfo) linkInfo).getContext(), typeParam);
typeLinkInfo.excludeTypeBounds = linkInfo.excludeTypeBounds;
typeLinkInfo.excludeTypeParameterLinks = linkInfo.excludeTypeParameterLinks;
typeLinkInfo.linkToSelf = linkInfo.linkToSelf;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.IndexItem;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
import jdk.javadoc.internal.doclets.toolkit.util.Utils.PreviewFlagProvider;

/**
* The taglet writer that writes HTML.
Expand Down Expand Up @@ -435,12 +436,18 @@ protected Content snippetTagOutput(Element element, SnippetTree tag, StyledText
int idx = line.indexOf(strippedLine);
assert idx >= 0; // because the stripped line is a substring of the line being stripped
Text whitespace = Text.of(utils.normalizeNewlines(line.substring(0, idx)));
// If the leading whitespace is not excluded from the link,
// browsers might exhibit unwanted behavior. For example, a
// browser might display hand-click cursor while user hovers
// over that whitespace portion of the line; or use
// underline decoration.
c = new ContentBuilder(whitespace, htmlWriter.linkToContent(element, e, t, strippedLine));
//disable preview tagging inside the snippets:
PreviewFlagProvider prevPreviewProvider = utils.setPreviewFlagProvider(el -> false);
try {
// If the leading whitespace is not excluded from the link,
// browsers might exhibit unwanted behavior. For example, a
// browser might display hand-click cursor while user hovers
// over that whitespace portion of the line; or use
// underline decoration.
c = new ContentBuilder(whitespace, htmlWriter.linkToContent(element, e, t, strippedLine));
} finally {
utils.setPreviewFlagProvider(prevPreviewProvider);
}
// We don't care about trailing whitespace.
} else {
c = HtmlTree.SPAN(Text.of(text));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2022, 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
Expand Down Expand Up @@ -3053,9 +3053,11 @@ public String toString() {
*/
public boolean isPreviewAPI(Element el) {
boolean parentPreviewAPI = false;
Element enclosing = el.getEnclosingElement();
if (enclosing != null && (enclosing.getKind().isClass() || enclosing.getKind().isInterface())) {
parentPreviewAPI = configuration.workArounds.isPreviewAPI(enclosing);
if (!isClassOrInterface(el)) {
Element enclosing = el.getEnclosingElement();
if (isClassOrInterface(enclosing)) {
parentPreviewAPI = configuration.workArounds.isPreviewAPI(enclosing);
}
}
boolean previewAPI = configuration.workArounds.isPreviewAPI(el);
return !parentPreviewAPI && previewAPI;
Expand All @@ -3082,18 +3084,12 @@ public boolean isReflectivePreviewAPI(Element el) {
*/
public Set<ElementFlag> elementFlags(Element el) {
Set<ElementFlag> flags = EnumSet.noneOf(ElementFlag.class);
PreviewSummary previewAPIs = declaredUsingPreviewAPIs(el);

if (isDeprecated(el)) {
flags.add(ElementFlag.DEPRECATED);
}

if ((!previewLanguageFeaturesUsed(el).isEmpty() ||
configuration.workArounds.isPreviewAPI(el) ||
!previewAPIs.previewAPI.isEmpty() ||
!previewAPIs.reflectivePreviewAPI.isEmpty() ||
!previewAPIs.declaredUsingPreviewFeature.isEmpty()) &&
!hasNoProviewAnnotation(el)) {
if (previewFlagProvider.isPreview(el)) {
flags.add(ElementFlag.PREVIEW);
}

Expand All @@ -3109,9 +3105,42 @@ public enum ElementFlag {
PREVIEW
}

private boolean hasNoProviewAnnotation(Element el) {
private boolean isClassOrInterface(Element el) {
return el != null && (el.getKind().isClass() || el.getKind().isInterface());
}

private boolean hasNoPreviewAnnotation(Element el) {
return el.getAnnotationMirrors()
.stream()
.anyMatch(am -> "jdk.internal.javac.NoPreview".equals(getQualifiedTypeName(am.getAnnotationType())));
}

private PreviewFlagProvider previewFlagProvider = new PreviewFlagProvider() {
@Override
public boolean isPreview(Element el) {
PreviewSummary previewAPIs = declaredUsingPreviewAPIs(el);
Element enclosing = el.getEnclosingElement();

return ( !previewLanguageFeaturesUsed(el).isEmpty()
|| configuration.workArounds.isPreviewAPI(el)
|| ( !isClassOrInterface(el) && isClassOrInterface(enclosing)
&& configuration.workArounds.isPreviewAPI(enclosing))
|| !previewAPIs.previewAPI.isEmpty()
|| !previewAPIs.reflectivePreviewAPI.isEmpty()
|| !previewAPIs.declaredUsingPreviewFeature.isEmpty())
&& !hasNoPreviewAnnotation(el);
}
};

public PreviewFlagProvider setPreviewFlagProvider(PreviewFlagProvider provider) {
Objects.requireNonNull(provider);
PreviewFlagProvider old = previewFlagProvider;
previewFlagProvider = provider;
return old;
}

public interface PreviewFlagProvider {
public boolean isPreview(Element el);
}

}
27 changes: 23 additions & 4 deletions test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2022, 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
Expand All @@ -23,7 +23,7 @@

/*
* @test
* @bug 8250768 8261976
* @bug 8250768 8261976 8277300
* @summary test generated docs for items declared using preview
* @library ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
Expand All @@ -33,8 +33,6 @@
*/

import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.ResourceBundle;
import javadoc.tester.JavadocTester;

public class TestPreview extends JavadocTester {
Expand Down Expand Up @@ -101,4 +99,25 @@ public void testPreviewAPIJavadoc() {
</div>
""");
}

@Test
public void test8277300() {
javadoc("-d", "out-8277300",
"--add-exports", "java.base/jdk.internal.javac=api2",
"--source-path", Paths.get(testSrc, "api2").toAbsolutePath().toString(),
"--show-packages=all",
"api2/api");
checkExit(Exit.OK);

checkOutput("api2/api/API.html", true,
"<p><a href=\"#test()\"><code>test()</code></a></p>",
"<p><a href=\"#testNoPreviewInSig()\"><code>testNoPreviewInSig()</code></a></p>",
"title=\"class or interface in java.util\" class=\"external-link\">List</a>&lt;<a href=\"API.html\" title=\"class in api\">API</a><sup><a href=\"#preview-api.API\">PREVIEW</a></sup>&gt;");
checkOutput("api2/api/API2.html", true,
"<a href=\"API.html#test()\"><code>API.test()</code></a><sup><a href=\"API.html#preview-api.API\">PREVIEW</a></sup>",
"<a href=\"API.html#testNoPreviewInSig()\"><code>API.testNoPreviewInSig()</code></a><sup><a href=\"API.html#preview-api.API\">PREVIEW</a></sup>",
"<a href=\"API3.html#test()\"><code>API3.test()</code></a><sup><a href=\"API3.html#preview-test()\">PREVIEW</a></sup>");
checkOutput("api2/api/API3.html", true,
"<div class=\"block\"><a href=\"#test()\"><code>test()</code></a><sup><a href=\"#preview-test()\">PREVIEW</a></sup></div>");
}
}
46 changes: 46 additions & 0 deletions test/langtools/jdk/javadoc/doclet/testPreview/api2/api/API.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2022, 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.
*/

package api;

import java.util.List;
import jdk.internal.javac.PreviewFeature;
import jdk.internal.javac.PreviewFeature.Feature;

/**
* <p>{@link API#test()}</p>
* <p>{@link API#testNoPreviewInSig()}</p>
*/
@PreviewFeature(feature=Feature.TEST, reflective=false)
public class API {

public API test() {
return null;
}

public void testNoPreviewInSig() {
}

public void typeArgs(List<API> api) {
}
}
33 changes: 33 additions & 0 deletions test/langtools/jdk/javadoc/doclet/testPreview/api2/api/API2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2022, 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.
*/

package api;

/**
* <p>{@link API#test()}
* <p>{@link API#testNoPreviewInSig()}
* <p>{@link API3#test()}
*/
public class API2 {

}
39 changes: 39 additions & 0 deletions test/langtools/jdk/javadoc/doclet/testPreview/api2/api/API3.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2022, 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.
*/

package api;

import jdk.internal.javac.PreviewFeature;
import jdk.internal.javac.PreviewFeature.Feature;

/**
* {@link API3#test()}
*/
public class API3 {

@PreviewFeature(feature=Feature.TEST, reflective=false)
public void test() {
return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2022, 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.
*/
module api2 {
exports api;
}

1 comment on commit 834d55c

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

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

Please sign in to comment.