8331947: Preview creates checkbox for JEP-less preview feature
Reviewed-by: liach, prappo
This commit is contained in:
parent
8e903eeb1f
commit
765ad0e40b
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, 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
|
||||
@ -31,9 +31,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.ModuleElement;
|
||||
@ -48,15 +48,12 @@ import javax.tools.JavaFileManager.Location;
|
||||
|
||||
import com.sun.source.util.TreePath;
|
||||
import com.sun.tools.javac.code.Flags;
|
||||
import com.sun.tools.javac.code.Scope;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.code.Symbol.ClassSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.PackageSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.VarSymbol;
|
||||
import com.sun.tools.javac.comp.AttrContext;
|
||||
import com.sun.tools.javac.comp.Env;
|
||||
import com.sun.tools.javac.util.Names;
|
||||
import com.sun.tools.javac.util.Options;
|
||||
|
||||
@ -408,7 +405,7 @@ public class WorkArounds {
|
||||
* @param feature the name of the PreviewFeature.Feature enum value
|
||||
* @return the map of PreviewFeature.JEP annotation element values, or an empty map
|
||||
*/
|
||||
public Map<? extends ExecutableElement, ? extends AnnotationValue> getJepInfo(String feature) {
|
||||
public Map<String, Object> getJepInfo(String feature) {
|
||||
TypeElement featureType = elementUtils.getTypeElement("jdk.internal.javac.PreviewFeature.Feature");
|
||||
TypeElement jepType = elementUtils.getTypeElement("jdk.internal.javac.PreviewFeature.JEP");
|
||||
var featureVar = featureType.getEnclosedElements().stream()
|
||||
@ -416,7 +413,11 @@ public class WorkArounds {
|
||||
if (featureVar.isPresent()) {
|
||||
for (AnnotationMirror anno : featureVar.get().getAnnotationMirrors()) {
|
||||
if (anno.getAnnotationType().asElement().equals(jepType)) {
|
||||
return anno.getElementValues();
|
||||
return anno.getElementValues().entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(
|
||||
e -> e.getKey().getSimpleName().toString(),
|
||||
e -> e.getValue().getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2024, 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
|
||||
@ -47,7 +47,7 @@ public class DeprecatedAPIListBuilder extends SummaryAPIListBuilder {
|
||||
* @param since list of releases passed via <code>--since</code> option
|
||||
*/
|
||||
public DeprecatedAPIListBuilder(BaseConfiguration configuration, List<String> since) {
|
||||
super(configuration, configuration.utils::isDeprecated);
|
||||
super(configuration);
|
||||
this.foundReleases = new HashSet<>();
|
||||
buildSummaryAPIInfo();
|
||||
// The releases list is set to the intersection of releases defined via `--since` option
|
||||
@ -73,6 +73,11 @@ public class DeprecatedAPIListBuilder extends SummaryAPIListBuilder {
|
||||
return forRemoval;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean belongsToSummary(Element element) {
|
||||
return utils.isDeprecated(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleElement(Element e) {
|
||||
foundReleases.add(utils.getDeprecatedSince(e));
|
||||
|
@ -46,16 +46,17 @@ public class NewAPIBuilder extends SummaryAPIListBuilder {
|
||||
public final List<String> releases;
|
||||
|
||||
public NewAPIBuilder(BaseConfiguration configuration, List<String> releases) {
|
||||
super(configuration, element -> isNewAPI(element, configuration.utils, releases));
|
||||
super(configuration);
|
||||
this.releases = releases;
|
||||
buildSummaryAPIInfo();
|
||||
}
|
||||
|
||||
private static boolean isNewAPI(Element e, Utils utils, List<String> releases) {
|
||||
if (!utils.hasDocCommentTree(e)) {
|
||||
@Override
|
||||
protected boolean belongsToSummary(Element element) {
|
||||
if (!utils.hasDocCommentTree(element)) {
|
||||
return false;
|
||||
}
|
||||
var sinceTrees = utils.getBlockTags(e, SINCE, SinceTree.class);
|
||||
var sinceTrees = utils.getBlockTags(element, SINCE, SinceTree.class);
|
||||
if (sinceTrees.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2024, 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
|
||||
@ -27,14 +27,13 @@ package jdk.javadoc.internal.doclets.toolkit.util;
|
||||
|
||||
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
|
||||
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Build list of all the preview packages, classes, constructors, fields and methods.
|
||||
@ -43,6 +42,7 @@ public class PreviewAPIListBuilder extends SummaryAPIListBuilder {
|
||||
|
||||
private final Map<Element, JEP> elementJeps = new HashMap<>();
|
||||
private final Map<String, JEP> jeps = new HashMap<>();
|
||||
private static final JEP NULL_SENTINEL = new JEP(0, "", "");
|
||||
|
||||
/**
|
||||
* The JEP for a preview feature in this release.
|
||||
@ -60,40 +60,51 @@ public class PreviewAPIListBuilder extends SummaryAPIListBuilder {
|
||||
* @param configuration the current configuration of the doclet
|
||||
*/
|
||||
public PreviewAPIListBuilder(BaseConfiguration configuration) {
|
||||
super(configuration, configuration.utils::isPreviewAPI);
|
||||
super(configuration);
|
||||
buildSummaryAPIInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleElement(Element e) {
|
||||
String feature = Objects.requireNonNull(utils.getPreviewFeature(e),
|
||||
protected boolean belongsToSummary(Element element) {
|
||||
if (!utils.isPreviewAPI(element)) {
|
||||
return false;
|
||||
}
|
||||
String feature = Objects.requireNonNull(utils.getPreviewFeature(element),
|
||||
"Preview feature not specified").toString();
|
||||
JEP jep = jeps.computeIfAbsent(feature, (featureName) -> {
|
||||
Map<? extends ExecutableElement, ? extends AnnotationValue> anno = configuration.workArounds.getJepInfo(featureName);
|
||||
int number = 0;
|
||||
String title = "";
|
||||
String status = "Preview"; // Default value is not returned by the method we use above.
|
||||
for (var entry : anno.entrySet()) {
|
||||
if ("number".equals(entry.getKey().getSimpleName().toString())) {
|
||||
number = (int) entry.getValue().getValue();
|
||||
} else if ("title".equals(entry.getKey().getSimpleName().toString())) {
|
||||
title = (String) entry.getValue().getValue();
|
||||
} else if ("status".equals(entry.getKey().getSimpleName().toString())) {
|
||||
status = (String) entry.getValue().getValue();
|
||||
} else {
|
||||
throw new IllegalArgumentException(entry.getKey().getSimpleName().toString());
|
||||
JEP jep = jeps.computeIfAbsent(feature, featureName -> {
|
||||
Map<String, Object> jepInfo = configuration.workArounds.getJepInfo(featureName);
|
||||
if (!jepInfo.isEmpty()) {
|
||||
int number = 0;
|
||||
String title = "";
|
||||
String status = "Preview"; // Default value is not returned by the method we used above.
|
||||
for (var entry : jepInfo.entrySet()) {
|
||||
switch (entry.getKey()) {
|
||||
case "number" -> number = (int) entry.getValue();
|
||||
case "title" -> title = (String) entry.getValue();
|
||||
case "status" -> status = (String) entry.getValue();
|
||||
default -> throw new IllegalArgumentException(entry.getKey());
|
||||
}
|
||||
}
|
||||
return new JEP(number, title, status);
|
||||
}
|
||||
return new JEP(number, title, status);
|
||||
return NULL_SENTINEL;
|
||||
});
|
||||
elementJeps.put(e, jep);
|
||||
if (jep != NULL_SENTINEL) {
|
||||
elementJeps.put(element, jep);
|
||||
return true;
|
||||
}
|
||||
// Preview features without JEP are not included.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return a sorted set of preview feature JEPs in this release}
|
||||
*/
|
||||
public Set<JEP> getJEPs() {
|
||||
return new TreeSet<>(jeps.values());
|
||||
return jeps.values()
|
||||
.stream()
|
||||
.filter(jep -> jep != NULL_SENTINEL)
|
||||
.collect(Collectors.toCollection(TreeSet::new));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 2024, 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
|
||||
@ -41,7 +41,12 @@ public class RestrictedAPIListBuilder extends SummaryAPIListBuilder {
|
||||
* @param configuration the current configuration of the doclet
|
||||
*/
|
||||
public RestrictedAPIListBuilder(BaseConfiguration configuration) {
|
||||
super(configuration, configuration.utils::isRestrictedAPI);
|
||||
super(configuration);
|
||||
buildSummaryAPIInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean belongsToSummary(Element element) {
|
||||
return utils.isRestrictedAPI(element);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2024, 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
|
||||
@ -26,7 +26,6 @@
|
||||
package jdk.javadoc.internal.doclets.toolkit.util;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ModuleElement;
|
||||
@ -39,14 +38,13 @@ import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
|
||||
/**
|
||||
* Build list of all the summary packages, classes, constructors, fields and methods.
|
||||
*/
|
||||
public class SummaryAPIListBuilder {
|
||||
public abstract class SummaryAPIListBuilder {
|
||||
/**
|
||||
* List of summary type Lists.
|
||||
*/
|
||||
private final Map<SummaryElementKind, SortedSet<Element>> summaryMap;
|
||||
protected final BaseConfiguration configuration;
|
||||
protected final Utils utils;
|
||||
private final Predicate<Element> belongsToSummary;
|
||||
|
||||
public enum SummaryElementKind {
|
||||
MODULE,
|
||||
@ -69,11 +67,9 @@ public class SummaryAPIListBuilder {
|
||||
*
|
||||
* @param configuration the current configuration of the doclet
|
||||
*/
|
||||
public SummaryAPIListBuilder(BaseConfiguration configuration,
|
||||
Predicate<Element> belongsToSummary) {
|
||||
protected SummaryAPIListBuilder(BaseConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
this.utils = configuration.utils;
|
||||
this.belongsToSummary = belongsToSummary;
|
||||
summaryMap = new EnumMap<>(SummaryElementKind.class);
|
||||
for (SummaryElementKind kind : SummaryElementKind.values()) {
|
||||
summaryMap.put(kind, createSummarySet());
|
||||
@ -93,7 +89,7 @@ public class SummaryAPIListBuilder {
|
||||
SortedSet<ModuleElement> modules = configuration.modules;
|
||||
SortedSet<Element> mset = summaryMap.get(SummaryElementKind.MODULE);
|
||||
for (Element me : modules) {
|
||||
if (belongsToSummary.test(me)) {
|
||||
if (belongsToSummary(me)) {
|
||||
mset.add(me);
|
||||
handleElement(me);
|
||||
}
|
||||
@ -101,14 +97,14 @@ public class SummaryAPIListBuilder {
|
||||
SortedSet<PackageElement> packages = configuration.packages;
|
||||
SortedSet<Element> pset = summaryMap.get(SummaryElementKind.PACKAGE);
|
||||
for (Element pe : packages) {
|
||||
if (belongsToSummary.test(pe)) {
|
||||
if (belongsToSummary(pe)) {
|
||||
pset.add(pe);
|
||||
handleElement(pe);
|
||||
}
|
||||
}
|
||||
for (TypeElement te : configuration.getIncludedTypeElements()) {
|
||||
SortedSet<Element> eset;
|
||||
if (belongsToSummary.test(te)) {
|
||||
if (belongsToSummary(te)) {
|
||||
switch (te.getKind()) {
|
||||
case ANNOTATION_TYPE -> {
|
||||
eset = summaryMap.get(SummaryElementKind.ANNOTATION_TYPE);
|
||||
@ -149,7 +145,7 @@ public class SummaryAPIListBuilder {
|
||||
}
|
||||
if (utils.isRecord(te)) {
|
||||
for (RecordComponentElement component : te.getRecordComponents()) {
|
||||
if (belongsToSummary.test(component)) {
|
||||
if (belongsToSummary(component)) {
|
||||
throw new AssertionError("record components not supported in summary builders: " +
|
||||
"component: " + component.getSimpleName() +
|
||||
" of record: " + te.getQualifiedName());
|
||||
@ -164,6 +160,14 @@ public class SummaryAPIListBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method decides whether Element {@code element} should be included in this summary list.
|
||||
*
|
||||
* @param element an element
|
||||
* @return true if the element should be included
|
||||
*/
|
||||
protected abstract boolean belongsToSummary(Element element);
|
||||
|
||||
/**
|
||||
* Add the members into a single list of summary members.
|
||||
*
|
||||
@ -172,7 +176,7 @@ public class SummaryAPIListBuilder {
|
||||
*/
|
||||
private void composeSummaryList(SortedSet<Element> sset, List<? extends Element> members) {
|
||||
for (Element member : members) {
|
||||
if (belongsToSummary.test(member)) {
|
||||
if (belongsToSummary(member)) {
|
||||
sset.add(member);
|
||||
handleElement(member);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 8250768 8261976 8277300 8282452 8287597 8325325 8325874 8297879
|
||||
* 8331947
|
||||
* @summary test generated docs for items declared using preview
|
||||
* @library ../../lib
|
||||
* @modules jdk.javadoc/jdk.javadoc.internal.tool
|
||||
@ -156,6 +157,9 @@ public class TestPreview extends JavadocTester {
|
||||
<li><a href="package-summary.html">preview</a></li>
|
||||
<li><a href="Core.html" class="current-selection">Core</a></li>
|
||||
</ol>""");
|
||||
|
||||
// 8331947: Support preview features without JEP should not be included in Preview API page
|
||||
checkOutput("preview-list.html", false, "supportMethod");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2024, 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
|
||||
@ -34,4 +34,8 @@ public class NoPreview {
|
||||
|
||||
@PreviewFeature(feature=Feature.TEST)
|
||||
public static class T {}
|
||||
|
||||
// Preview support feature without JEP should not be listed
|
||||
@PreviewFeature(feature=Feature.LANGUAGE_MODEL)
|
||||
public void supportMethod() {}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user