8288058: Broken links on constant-values page

Reviewed-by: prappo
This commit is contained in:
Jonathan Gibbons 2022-06-28 15:58:12 +00:00
parent a814293e1f
commit c42b796f91
8 changed files with 301 additions and 143 deletions
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets
test/langtools/jdk/javadoc/doclet
testConstantValuesPage
testHtmlVersion

@ -26,7 +26,6 @@
package jdk.javadoc.internal.doclets.formats.html; package jdk.javadoc.internal.doclets.formats.html;
import java.util.Collection; import java.util.Collection;
import java.util.Set;
import javax.lang.model.element.Modifier; import javax.lang.model.element.Modifier;
import javax.lang.model.element.PackageElement; import javax.lang.model.element.PackageElement;
@ -97,20 +96,16 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons
} }
@Override @Override
public void addLinkToPackageContent(PackageElement pkg, public void addLinkToPackageContent(String abbrevPackageName, Content content) {
Set<PackageElement> printedPackageHeaders, Content content) {
//add link to summary //add link to summary
Content link; Content link;
if (pkg.isUnnamed()) { if (abbrevPackageName.isEmpty()) {
link = links.createLink(HtmlIds.UNNAMED_PACKAGE_ANCHOR, link = links.createLink(HtmlIds.UNNAMED_PACKAGE_ANCHOR,
contents.defaultPackageLabel, ""); contents.defaultPackageLabel, "");
} else { } else {
String parsedPackageName = utils.parsePackageName(pkg); Content packageNameContent = Text.of(abbrevPackageName + ".*");
Content packageNameContent = Text.of(parsedPackageName + ".*"); link = links.createLink(DocLink.fragment(abbrevPackageName),
link = links.createLink(DocLink.fragment(parsedPackageName),
packageNameContent, ""); packageNameContent, "");
PackageElement abbrevPkg = configuration.workArounds.getAbbreviatedPackageElement(pkg);
printedPackageHeaders.add(abbrevPkg);
} }
content.add(HtmlTree.LI(link)); content.add(HtmlTree.LI(link));
} }
@ -136,26 +131,25 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons
} }
@Override @Override
public void addPackageName(PackageElement pkg, Content toContent, boolean first) { public void addPackageGroup(String abbrevPackageName, Content toContent) {
Content pkgNameContent; Content headingContent;
HtmlId anchorName; HtmlId anchorName;
if (!first) { if (abbrevPackageName.isEmpty()) {
toContent.add(summarySection);
}
if (pkg.isUnnamed()) {
anchorName = HtmlIds.UNNAMED_PACKAGE_ANCHOR; anchorName = HtmlIds.UNNAMED_PACKAGE_ANCHOR;
pkgNameContent = contents.defaultPackageLabel; headingContent = contents.defaultPackageLabel;
} else { } else {
String parsedPackageName = utils.parsePackageName(pkg); anchorName = htmlIds.forPackageName(abbrevPackageName);
anchorName = htmlIds.forPackage(pkg); headingContent = new ContentBuilder(
pkgNameContent = getPackageLabel(parsedPackageName); getPackageLabel(abbrevPackageName),
Text.of(".*"));
} }
var headingContent = Text.of(".*"); var heading = HtmlTree.HEADING_TITLE(
var heading = HtmlTree.HEADING_TITLE(Headings.ConstantsSummary.PACKAGE_HEADING, Headings.ConstantsSummary.PACKAGE_HEADING,
pkgNameContent); headingContent);
heading.add(headingContent);
summarySection = HtmlTree.SECTION(HtmlStyle.constantsSummary, heading) summarySection = HtmlTree.SECTION(HtmlStyle.constantsSummary, heading)
.setId(anchorName); .setId(anchorName);
toContent.add(summarySection);
} }
@Override @Override
@ -175,7 +169,7 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons
currentTypeElement = typeElement; currentTypeElement = typeElement;
//generate links backward only to public classes. //generate links backward only to public classes.
Content classlink = (utils.isPublic(typeElement) || utils.isProtected(typeElement)) ? Content classLink = (utils.isPublic(typeElement) || utils.isProtected(typeElement)) ?
getLink(new HtmlLinkInfo(configuration, getLink(new HtmlLinkInfo(configuration,
HtmlLinkInfo.Kind.CONSTANT_SUMMARY, typeElement)) : HtmlLinkInfo.Kind.CONSTANT_SUMMARY, typeElement)) :
Text.of(utils.getFullyQualifiedName(typeElement)); Text.of(utils.getFullyQualifiedName(typeElement));
@ -186,7 +180,7 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons
caption.add(enclosingPackage.getQualifiedName()); caption.add(enclosingPackage.getQualifiedName());
caption.add("."); caption.add(".");
} }
caption.add(classlink); caption.add(classLink);
Table table = new Table(HtmlStyle.summaryTable) Table table = new Table(HtmlStyle.summaryTable)
.setCaption(caption) .setCaption(caption)
@ -245,9 +239,6 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons
@Override @Override
public void addConstantSummaries(Content content) { public void addConstantSummaries(Content content) {
if (summarySection != null) {
content.add(summarySection);
}
bodyContents.addMainContent(content); bodyContents.addMainContent(content);
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -134,6 +134,19 @@ public class HtmlIds {
: HtmlId.of(element.getQualifiedName().toString()); : HtmlId.of(element.getQualifiedName().toString());
} }
/**
* Returns an id for a package name.
*
* @param pkgName the package name
*
* @return the id
*/
HtmlId forPackageName(String pkgName) {
return pkgName.isEmpty()
? UNNAMED_PACKAGE_ANCHOR
: HtmlId.of(pkgName);
}
/** /**
* Returns an id for a class or interface. * Returns an id for a class or interface.
* *

@ -55,13 +55,10 @@ public interface ConstantsSummaryWriter {
/** /**
* Adds the given package name link to the constant content list. * Adds the given package name link to the constant content list.
* *
* @param pkg the {@link PackageElement} to index. * @param abbrevPackageName the abbreviated package name
* @param writtenPackageHeaders the set of package headers that have already * @param content the content to which the link will be added
* been indexed, we want to index utmost once.
* @param content the content to which the link will be added
*/ */
void addLinkToPackageContent(PackageElement pkg, Set<PackageElement> writtenPackageHeaders, void addLinkToPackageContent(String abbrevPackageName, Content content);
Content content);
/** /**
* Add the content list to the documentation. * Add the content list to the documentation.
@ -78,17 +75,12 @@ public interface ConstantsSummaryWriter {
Content getConstantSummaries(); Content getConstantSummaries();
/** /**
* Adds the given package name. * Adds a header for the given abbreviated package name.
* *
* @param pkg the parsed package name. We only Write the * @param abbrevPackageName the abbreviated package name
* first 2 directory levels of the package
* name. For example, java.lang.ref would be
* indexed as java.lang.*.
* @param toContent the summaries documentation * @param toContent the summaries documentation
* @param first true if the first package is listed
* be written
*/ */
void addPackageName(PackageElement pkg, Content toContent, boolean first); void addPackageGroup(String abbrevPackageName, Content toContent);
/** /**
* Get the class summary header for the constants summary. * Get the class summary header for the constants summary.

@ -500,22 +500,6 @@ public class WorkArounds {
} }
} }
// TODO: we need to eliminate this, as it is hacky.
/**
* Returns a representation of the package truncated to two levels.
* For instance if the given package represents foo.bar.baz will return
* a representation of foo.bar
* @param pkg the PackageElement
* @return an abbreviated PackageElement
*/
public PackageElement getAbbreviatedPackageElement(PackageElement pkg) {
String parsedPackageName = utils.parsePackageName(pkg);
ModuleElement encl = (ModuleElement) pkg.getEnclosingElement();
return encl == null
? utils.elementUtils.getPackageElement(parsedPackageName)
: ((JavacElements) utils.elementUtils).getPackageElement(encl, parsedPackageName);
}
public boolean isPreviewAPI(Element el) { public boolean isPreviewAPI(Element el) {
Symbol sym = (Symbol) el; Symbol sym = (Symbol) el;
return (sym.flags() & Flags.PREVIEW_API) != 0; return (sym.flags() & Flags.PREVIEW_API) != 0;

@ -45,10 +45,10 @@ import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.
public class ConstantsSummaryBuilder extends AbstractBuilder { public class ConstantsSummaryBuilder extends AbstractBuilder {
/** /**
* The maximum number of package directories shown in the constant * The maximum number of package directories shown in the headings of
* value index. * the constant values contents list and headings.
*/ */
public static final int MAX_CONSTANT_VALUE_INDEX_LENGTH = 2; private static final int MAX_CONSTANT_VALUE_INDEX_LENGTH = 2;
/** /**
* The writer used to write the results. * The writer used to write the results.
@ -56,14 +56,14 @@ public class ConstantsSummaryBuilder extends AbstractBuilder {
protected ConstantsSummaryWriter writer; protected ConstantsSummaryWriter writer;
/** /**
* The set of TypeElements that have constant fields. * The set of type elements that have constant fields.
*/ */
protected final Set<TypeElement> typeElementsWithConstFields; protected final Set<TypeElement> typeElementsWithConstFields;
/** /**
* The set of printed package headers. * The set of package-group headings.
*/ */
protected final Set<PackageElement> printedPackageHeaders; protected final Set<String> packageGroupHeadings;
/** /**
* The current package being documented. * The current package being documented.
@ -76,25 +76,20 @@ public class ConstantsSummaryBuilder extends AbstractBuilder {
private TypeElement currentClass; private TypeElement currentClass;
/** /**
* True if first package is listed. * Constructs a new {@code ConstantsSummaryBuilder}.
*/
private boolean first = true;
/**
* Construct a new ConstantsSummaryBuilder.
* *
* @param context the build context. * @param context the build context
*/ */
private ConstantsSummaryBuilder(Context context) { private ConstantsSummaryBuilder(Context context) {
super(context); super(context);
this.typeElementsWithConstFields = new HashSet<>(); this.typeElementsWithConstFields = new HashSet<>();
this.printedPackageHeaders = new TreeSet<>(utils.comparators.makePackageComparator()); this.packageGroupHeadings = new TreeSet<>(utils::compareStrings);
} }
/** /**
* Construct a ConstantsSummaryBuilder. * Constructs a {@code ConstantsSummaryBuilder}.
* *
* @param context the build context. * @param context the build context
* @return the new ConstantsSummaryBuilder * @return the new ConstantsSummaryBuilder
*/ */
public static ConstantsSummaryBuilder getInstance(Context context) { public static ConstantsSummaryBuilder getInstance(Context context) {
@ -117,7 +112,7 @@ public class ConstantsSummaryBuilder extends AbstractBuilder {
} }
/** /**
* Build the constant summary. * Builds the constant summary page.
* *
* @throws DocletException if there is a problem while building the documentation * @throws DocletException if there is a problem while building the documentation
*/ */
@ -132,56 +127,55 @@ public class ConstantsSummaryBuilder extends AbstractBuilder {
} }
/** /**
* Build the list of packages. * Builds the list of contents for the groups of packages appearing in the constants summary page.
*/ */
protected void buildContents() { protected void buildContents() {
Content contentList = writer.getContentsHeader(); Content contentList = writer.getContentsHeader();
printedPackageHeaders.clear(); packageGroupHeadings.clear();
for (PackageElement pkg : configuration.packages) { for (PackageElement pkg : configuration.packages) {
if (hasConstantField(pkg) && !hasPrintedPackageIndex(pkg)) { String abbrevPackageName = getAbbrevPackageName(pkg);
writer.addLinkToPackageContent(pkg, printedPackageHeaders, contentList); if (hasConstantField(pkg) && !packageGroupHeadings.contains(abbrevPackageName)) {
writer.addLinkToPackageContent(abbrevPackageName, contentList);
packageGroupHeadings.add(abbrevPackageName);
} }
} }
writer.addContentsList(contentList); writer.addContentsList(contentList);
} }
/** /**
* Build the summary for each documented package. * Builds the summary for each documented package.
* *
* @throws DocletException if there is a problem while building the documentation * @throws DocletException if there is a problem while building the documentation
*/ */
protected void buildConstantSummaries() throws DocletException { protected void buildConstantSummaries() throws DocletException {
printedPackageHeaders.clear(); packageGroupHeadings.clear();
Content summaries = writer.getConstantSummaries(); Content summaries = writer.getConstantSummaries();
for (PackageElement aPackage : configuration.packages) { for (PackageElement aPackage : configuration.packages) {
if (hasConstantField(aPackage)) { if (hasConstantField(aPackage)) {
currentPackage = aPackage; currentPackage = aPackage;
//Build the documentation for the current package. //Build the documentation for the current package.
buildPackageHeader(summaries); buildPackageHeader(summaries);
buildClassConstantSummary(); buildClassConstantSummary();
first = false;
} }
} }
writer.addConstantSummaries(summaries); writer.addConstantSummaries(summaries);
} }
/** /**
* Build the header for the given package. * Builds the header for the given package.
* *
* @param target the content to which the package header will be added * @param target the content to which the package header will be added
*/ */
protected void buildPackageHeader(Content target) { protected void buildPackageHeader(Content target) {
PackageElement abbrevPkg = configuration.workArounds.getAbbreviatedPackageElement(currentPackage); String abbrevPkgName = getAbbrevPackageName(currentPackage);
if (!printedPackageHeaders.contains(abbrevPkg)) { if (!packageGroupHeadings.contains(abbrevPkgName)) {
writer.addPackageName(currentPackage, target, first); writer.addPackageGroup(abbrevPkgName, target);
printedPackageHeaders.add(abbrevPkg); packageGroupHeadings.add(abbrevPkgName);
} }
} }
/** /**
* Build the summary for the current class. * Builds the summary for the current class.
* *
* @throws DocletException if there is a problem while building the documentation * @throws DocletException if there is a problem while building the documentation
*/ */
@ -206,20 +200,18 @@ public class ConstantsSummaryBuilder extends AbstractBuilder {
} }
/** /**
* Build the summary of constant members in the class. * Builds the summary of constant members in the class.
* *
* @param target the content to which the constant members table * @param target the content to which the table of constant members will be added
* will be added
*/ */
protected void buildConstantMembers(Content target) { protected void buildConstantMembers(Content target) {
new ConstantFieldBuilder(currentClass).buildMembersSummary(target); new ConstantFieldBuilder(currentClass).buildMembersSummary(target);
} }
/** /**
* Return true if the given package has constant fields to document. * {@return true if the given package has constant fields to document}
* *
* @param pkg the package being checked. * @param pkg the package to be checked
* @return true if the given package has constant fields to document.
*/ */
private boolean hasConstantField(PackageElement pkg) { private boolean hasConstantField(PackageElement pkg) {
SortedSet<TypeElement> classes = !pkg.isUnnamed() SortedSet<TypeElement> classes = !pkg.isUnnamed()
@ -235,10 +227,9 @@ public class ConstantsSummaryBuilder extends AbstractBuilder {
} }
/** /**
* Return true if the given class has constant fields to document. * {@return true if the given class has constant fields to document}
* *
* @param typeElement the class being checked. * @param typeElement the class to be checked
* @return true if the given package has constant fields to document.
*/ */
private boolean hasConstantField (TypeElement typeElement) { private boolean hasConstantField (TypeElement typeElement) {
VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement); VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement);
@ -254,33 +245,36 @@ public class ConstantsSummaryBuilder extends AbstractBuilder {
} }
/** /**
* Return true if the given package name has been printed. Also * {@return the abbreviated name for a package, containing the leading segments of the name}
* return true if the root of this package has been printed.
* *
* @param pkg the name of the package to check. * @param pkg the package
*/ */
private boolean hasPrintedPackageIndex(PackageElement pkg) { public String getAbbrevPackageName(PackageElement pkg) {
for (PackageElement printedPkg : printedPackageHeaders) { if (pkg.isUnnamed()) {
if (utils.getPackageName(pkg).startsWith(utils.parsePackageName(printedPkg))) { return "";
return true;
}
} }
return false;
String packageName = utils.getPackageName(pkg);
int index = -1;
for (int j = 0; j < MAX_CONSTANT_VALUE_INDEX_LENGTH; j++) {
index = packageName.indexOf(".", index + 1);
}
return index == -1 ? packageName : packageName.substring(0, index);
} }
/** /**
* Print the table of constants. * Builder for the table of fields with constant values.
*/ */
private class ConstantFieldBuilder { private class ConstantFieldBuilder {
/** /**
* The typeElement that we are examining constants for. * The type element that we are examining constants for.
*/ */
protected TypeElement typeElement; protected TypeElement typeElement;
/** /**
* Construct a ConstantFieldSubWriter. * Constructs a {@code ConstantFieldBuilder}.
* @param typeElement the typeElement that we are examining constants for. * @param typeElement the type element that we are examining constants for
*/ */
public ConstantFieldBuilder(TypeElement typeElement) { public ConstantFieldBuilder(TypeElement typeElement) {
this.typeElement = typeElement; this.typeElement = typeElement;
@ -289,8 +283,7 @@ public class ConstantsSummaryBuilder extends AbstractBuilder {
/** /**
* Builds the table of constants for a given class. * Builds the table of constants for a given class.
* *
* @param target the content to which the class constants table * @param target the content to which the table of class constants will be added
* will be added
*/ */
protected void buildMembersSummary(Content target) { protected void buildMembersSummary(Content target) {
SortedSet<VariableElement> members = members(); SortedSet<VariableElement> members = members();
@ -300,8 +293,7 @@ public class ConstantsSummaryBuilder extends AbstractBuilder {
} }
/** /**
* Returns a set of visible constant fields for the given type. * {@return a set of visible constant fields for the given type}
* @return the set of visible constant fields for the given type.
*/ */
protected SortedSet<VariableElement> members() { protected SortedSet<VariableElement> members() {
VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement); VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement);

@ -124,7 +124,6 @@ import static javax.lang.model.element.ElementKind.*;
import static javax.lang.model.type.TypeKind.*; import static javax.lang.model.type.TypeKind.*;
import static com.sun.source.doctree.DocTree.Kind.*; import static com.sun.source.doctree.DocTree.Kind.*;
import static jdk.javadoc.internal.doclets.toolkit.builders.ConstantsSummaryBuilder.MAX_CONSTANT_VALUE_INDEX_LENGTH;
/** /**
* Utilities Class for Doclets. * Utilities Class for Doclets.
@ -905,22 +904,6 @@ public class Utils {
return searchResult; return searchResult;
} }
/**
* Parse the package name. We only want to display package name up to
* 2 levels.
*/
public String parsePackageName(PackageElement p) {
String pkgname = p.isUnnamed() ? "" : getPackageName(p);
int index = -1;
for (int j = 0; j < MAX_CONSTANT_VALUE_INDEX_LENGTH; j++) {
index = pkgname.indexOf(".", index + 1);
}
if (index != -1) {
pkgname = pkgname.substring(0, index);
}
return pkgname;
}
/** /**
* Given an annotation, return true if it should be documented and false * Given an annotation, return true if it should be documented and false
* otherwise. * otherwise.

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,16 +23,18 @@
/* /*
* @test * @test
* @bug 4681599 * @bug 4681599 8288058
* @summary Test to make sure that constant values page does not get * @summary Tests for the Constant Values page.
* generated when doclet has nothing to document. * @library /tools/lib ../../lib
* @library ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool * @modules jdk.javadoc/jdk.javadoc.internal.tool
* @build javadoc.tester.* * @build toolbox.ToolBox javadoc.tester.*
* @run main TestConstantValuesPage * @run main TestConstantValuesPage
*/ */
import java.nio.file.Path;
import javadoc.tester.JavadocTester; import javadoc.tester.JavadocTester;
import toolbox.ToolBox;
public class TestConstantValuesPage extends JavadocTester { public class TestConstantValuesPage extends JavadocTester {
@ -41,8 +43,14 @@ public class TestConstantValuesPage extends JavadocTester {
tester.runTests(); tester.runTests();
} }
ToolBox tb = new ToolBox();
/**
* Test to make sure that constant values page does not get
* generated when doclet has nothing to document.
*/
@Test @Test
public void test() { public void testNoPage() {
javadoc("-d", "out", javadoc("-d", "out",
"-sourcepath", testSrc, "-sourcepath", testSrc,
"foo"); "foo");
@ -50,5 +58,200 @@ public class TestConstantValuesPage extends JavadocTester {
checkOutput(Output.OUT, false, checkOutput(Output.OUT, false,
"constant-values.html..."); "constant-values.html...");
checkFiles(false, "constant-values.html");
}
/**
* Tests the "contents" list for a group of named packages in the unnamed module.
*/
@Test
public void testIndexNamed(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"""
package p1.p2a.p3a;
public class CA {
public static final int ia = 1;
public static final String sa = "string";
}
""",
"""
package p1.p2a.p3b;
public class CB {
public static final int ib = 1;
public static final String sb = "string";
}
""",
"""
package p1.p2b.p3c;
public class CC {
public static final int ic = 1;
public static final String sc = "string";
}
""",
"""
package p2;
public class CD {
public static final int id = 1;
public static final String sd = "string";
}
""");
setAutomaticCheckLinks(true); // ensure link-checking enabled for this test
javadoc("-d", base.resolve("api").toString(),
"-Xdoclint:none",
"-sourcepath", src.toString(),
"p1.p2a.p3a", "p1.p2a.p3b", "p1.p2b.p3c");
checkExit(Exit.OK);
checkOutput("constant-values.html", true,
"""
<section class="packages">
<h2 title="Contents">Contents</h2>
<ul>
<li><a href="#p1.p2a">p1.p2a.*</a></li>
<li><a href="#p1.p2b">p1.p2b.*</a></li>
</ul>
</section>""");
}
/**
* Tests the "contents" list for the unnamed package in the unnamed module.
*/
@Test
public void testIndexUnnamed(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"""
public class C {
public static final int ia = 1;
public static final String sa = "string";
}
""");
setAutomaticCheckLinks(true); // ensure link-checking enabled for this test
javadoc("-d", base.resolve("api").toString(),
"-Xdoclint:none",
"-sourcepath", src.toString(),
src.resolve("C.java").toString());
checkExit(Exit.OK);
checkOutput("constant-values.html", true,
"""
<section class="packages">
<h2 title="Contents">Contents</h2>
<ul>
<li><a href="#unnamed-package">Unnamed Package</a></li>
</ul>
</section>""");
}
/**
* Tests the "contents" list for a group of named and unnamed packages in the unnamed module.
*/
@Test
public void testMixed(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"""
package p1.p2a.p3a;
public class CA {
public static final int ia = 1;
public static final String sa = "string";
}
""",
"""
public class C {
public static final int ia = 1;
public static final String sa = "string";
}
""");
setAutomaticCheckLinks(true); // ensure link-checking enabled for this test
javadoc("-d", base.resolve("api").toString(),
"-Xdoclint:none",
"-sourcepath", src.toString(),
"p1.p2a.p3a", src.resolve("C.java").toString());
checkExit(Exit.OK);
checkOutput("constant-values.html", true,
"""
<section class="packages">
<h2 title="Contents">Contents</h2>
<ul>
<li><a href="#unnamed-package">Unnamed Package</a></li>
<li><a href="#p1.p2a">p1.p2a.*</a></li>
</ul>
</section>""");
}
/**
* Tests the "contents" list for a group of named packages in named modules.
*/
@Test
public void testModules(Path base) throws Exception {
Path src = base.resolve("src");
Path src_mA = src.resolve("mA");
tb.writeJavaFiles(src_mA,
"""
module mA {
exports p.a;
exports p.q.r1;
}
""",
"""
package p.a;
public class CA {
public static final int iA = 1;
}
""",
"""
package p.q.r1;
public class C1 {
public static final int i1 = 1;
}
""");
Path src_mB = src.resolve("mB");
tb.writeJavaFiles(src_mB,
"""
module mB {
exports p.b;
exports p.q.r2;
}
""",
"""
package p.b;
public class CB {
public static final int iB = 1;
}
""",
"""
package p.q.r2;
public class C2 {
public static final int i2 = 1;
}
""");
setAutomaticCheckLinks(true); // ensure link-checking enabled for this test
javadoc("-d", base.resolve("api").toString(),
"-Xdoclint:none",
"--module-source-path", src.toString(),
"--module", "mA,mB");
checkExit(Exit.OK);
checkOutput("constant-values.html", true,
"""
<section class="packages">
<h2 title="Contents">Contents</h2>
<ul>
<li><a href="#p.a">p.a.*</a></li>
<li><a href="#p.b">p.b.*</a></li>
<li><a href="#p.q">p.q.*</a></li>
</ul>
</section>""");
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -197,7 +197,7 @@ public class TestHtmlVersion extends JavadocTester {
""", """,
""" """
<section class="constants-summary" id="pkg"> <section class="constants-summary" id="pkg">
<h2 title="pkg">pkg.*</h2> <h2 title="pkg.*">pkg.*</h2>
""", """,
""" """
<footer role="contentinfo">""", <footer role="contentinfo">""",