8384065: Improve wrapping of link labels in the table of contents

Reviewed-by: nbenalla
This commit is contained in:
Hannes Wallnöfer 2026-06-08 10:57:57 +00:00
parent 70ba725b07
commit 2d2d59dfcf
7 changed files with 93 additions and 19 deletions

View File

@ -137,6 +137,26 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
.title(title)));
}
/**
* Returns a label for the given element to be used the table of contents sidebar.
*
* @param executableElement method or constructor
* @return the link label
*/
protected Content getTOCLabel(ExecutableElement executableElement) {
var signature = utils.makeSignature(executableElement, typeElement, false, true);
var label = new ContentBuilder(Text.of(utils.getSimpleName(executableElement)));
// Insert line break opportunity before first parameter.
if (signature.length() > 2) {
label.add(Text.of(signature.substring(0, 1)))
.add(HtmlTree.WBR())
.add(Text.of(signature.substring(1)));
} else {
label.add(signature);
}
return label;
}
/**
* Adds the generic type parameters.
*

View File

@ -119,9 +119,7 @@ public class ConstructorWriter extends AbstractExecutableMemberWriter {
constructorContent.add(div);
memberList.add(getMemberListItem(constructorContent));
writer.tableOfContents.addLink(htmlIds.forMember(currentConstructor).getFirst(),
Text.of(utils.getSimpleName(constructor)
+ utils.makeSignature(currentConstructor, typeElement, false, true)),
TableOfContents.Level.SECOND);
getTOCLabel(currentConstructor), TableOfContents.Level.SECOND);
}
Content constructorDetails = getConstructorDetails(constructorDetailsHeader, memberList);
target.add(constructorDetails);

View File

@ -118,9 +118,7 @@ public class MethodWriter extends AbstractExecutableMemberWriter {
methodContent.add(div);
memberList.add(writer.getMemberListItem(methodContent));
writer.tableOfContents.addLink(htmlIds.forMember(currentMethod).getFirst(),
Text.of(utils.getSimpleName(method)
+ utils.makeSignature(currentMethod, typeElement, false, true)),
TableOfContents.Level.SECOND);
getTOCLabel(currentMethod), TableOfContents.Level.SECOND);
}
Content methodDetails = getMethodDetails(methodDetailsHeader, memberList);
detailsList.add(methodDetails);

View File

@ -661,9 +661,12 @@ a.current-selection {
}
nav.toc a {
display: block;
padding: 8px;
padding: 7px 8px;
overflow: hidden;
text-overflow: ellipsis;
text-wrap: balance;
text-indent: 0.5em hanging;
line-height: 1.35;
}
nav.toc ol.toc-list ol.toc-list a {
padding-left: 24px;
@ -940,6 +943,9 @@ div.checkboxes > label > input {
.col-first, .col-second, .col-constructor-name {
overflow: auto;
}
.col-constructor-name, .method-summary .col-second {
text-indent: 0.5em hanging;
}
body:not(.class-declaration-page) .col-first a:link,
.col-summary-item-name a:link {
font-weight:bold;

View File

@ -103,9 +103,9 @@ public class TestErasure extends JavadocTester {
checkOutput("Foo.html", true, """
<li><a href="#constructor-detail" tabindex="0">Constructor Details</a>
<ol class="toc-list">
<li><a href="#%3Cinit%3E(T)" tabindex="0">Foo(T)</a></li>
<li><a href="#%3Cinit%3E(X)" tabindex="0">Foo(T)</a></li>
<li><a href="#%3Cinit%3E(Y)" tabindex="0">Foo(T)</a></li>
<li><a href="#%3Cinit%3E(T)" tabindex="0">Foo(<wbr>T)</a></li>
<li><a href="#%3Cinit%3E(X)" tabindex="0">Foo(<wbr>T)</a></li>
<li><a href="#%3Cinit%3E(Y)" tabindex="0">Foo(<wbr>T)</a></li>
</ol>
</li>""");
checkOutput("index-all.html", true, """
@ -145,9 +145,9 @@ public class TestErasure extends JavadocTester {
checkOutput("Foo.html", true, """
<li><a href="#method-detail" tabindex="0">Method Details</a>
<ol class="toc-list">
<li><a href="#m(T)" tabindex="0">m(T)</a></li>
<li><a href="#m(X)" tabindex="0">m(T)</a></li>
<li><a href="#m(Y)" tabindex="0">m(T)</a></li>
<li><a href="#m(T)" tabindex="0">m(<wbr>T)</a></li>
<li><a href="#m(X)" tabindex="0">m(<wbr>T)</a></li>
<li><a href="#m(Y)" tabindex="0">m(<wbr>T)</a></li>
</ol>
</li>""");
checkOutput("index-all.html", true, """
@ -210,8 +210,8 @@ public class TestErasure extends JavadocTester {
checkOutput("Foo.html", true, """
<li><a href="#constructor-detail" tabindex="0">Constructor Details</a>
<ol class="toc-list">
<li><a href="#%3Cinit%3E(T)" tabindex="0">Foo(T)</a></li>
<li><a href="#%3Cinit%3E(X)" tabindex="0">Foo(T)</a></li>
<li><a href="#%3Cinit%3E(T)" tabindex="0">Foo(<wbr>T)</a></li>
<li><a href="#%3Cinit%3E(X)" tabindex="0">Foo(<wbr>T)</a></li>
</ol>
</li>""");
checkOutput("index-all.html", true, """
@ -242,8 +242,8 @@ public class TestErasure extends JavadocTester {
checkOutput("Foo.html", true, """
<li><a href="#method-detail" tabindex="0">Method Details</a>
<ol class="toc-list">
<li><a href="#m(T)" tabindex="0">m(T)</a></li>
<li><a href="#m(X)" tabindex="0">m(T)</a></li>
<li><a href="#m(T)" tabindex="0">m(<wbr>T)</a></li>
<li><a href="#m(X)" tabindex="0">m(<wbr>T)</a></li>
</ol>
</li>""");
checkOutput("index-all.html", true, """

View File

@ -25,7 +25,7 @@
* @test
* @bug 7025314 8023700 7198273 8025633 8026567 8081854 8196027 8182765
* 8196200 8196202 8223378 8258659 8261976 8320458 8329537 8350638
* 8342705 8371021 8373526
* 8342705 8371021 8373526 8384065
* @summary Make sure the Next/Prev Class links iterate through all types.
* Make sure the navagation is 2 columns, not 3.
* @library /tools/lib ../../lib
@ -172,6 +172,36 @@ public class TestNavigation extends JavadocTester {
tb.writeJavaFiles(src,
"""
package pkg1; public class A {
/**
* Empty ctor
*/
public A() {}
/**
* Single param ctor
*/
public A(int i) {}
/**
* A ctor with many params
*/
public A(int i, int j, int x, int y, String s, boolean b) {}
/**
* A method without parameters
*/
public void noParams() {}
/**
* A method with a single parameter
*/
public void oneParam(String s) {}
/**
* A method with lots of parameters
*/
public void manyParams(String s, int i, int j, boolean b, double d, double e) {}
/**
* Class with members.
*/
@ -217,6 +247,29 @@ public class TestNavigation extends JavadocTester {
"pkg1");
checkExit(Exit.OK);
checkOrder("pkg1/A.html",
"""
<ol class="toc-list" tabindex="-1">
<li><a href="#" tabindex="0">Description</a></li>
<li><a href="#nested-class-summary" tabindex="0">Nested Class Summary</a></li>
<li><a href="#constructor-summary" tabindex="0">Constructor Summary</a></li>
<li><a href="#method-summary" tabindex="0">Method Summary</a></li>
<li><a href="#constructor-detail" tabindex="0">Constructor Details</a>
<ol class="toc-list">
<li><a href="#%3Cinit%3E()" tabindex="0">A()</a></li>
<li><a href="#%3Cinit%3E(int)" tabindex="0">A(<wbr>int)</a></li>
<li><a href="#%3Cinit%3E(int,int,int,int,java.lang.String,boolean)" tabindex="0">A(<wbr>int, int, int, int, String, boolean)</a></li>
</ol>
</li>
<li><a href="#method-detail" tabindex="0">Method Details</a>
<ol class="toc-list">
<li><a href="#noParams()" tabindex="0">noParams()</a></li>
<li><a href="#oneParam(java.lang.String)" tabindex="0">oneParam(<wbr>String)</a></li>
<li><a href="#manyParams(java.lang.String,int,int,boolean,double,double)" tabindex="0">manyParams(<wbr>String, int, int, boolean, double, double)</a></li>
</ol>
</li>
</ol>""");
checkOrder("pkg1/A.X.html",
"""
<ol class="sub-nav-list">

View File

@ -288,7 +288,6 @@ public class TestStylesheet extends JavadocTester {
"field-summary",
"member-details",
"method-details",
"method-summary",
// the following provide the ability to optionally override components of the
// memberSignature structure
"name",