8342808: Javadoc should add whitespace between type parameters

Reviewed-by: hannesw
This commit is contained in:
Nizar Benalla 2024-11-27 15:36:02 +00:00
parent 0b704a2279
commit b89cba7517
12 changed files with 66 additions and 73 deletions

View File

@ -57,7 +57,6 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.html.Content;
import jdk.javadoc.internal.html.ContentBuilder;
import jdk.javadoc.internal.html.HtmlAttr;
import jdk.javadoc.internal.html.HtmlTag;
import jdk.javadoc.internal.html.HtmlTree;
import jdk.javadoc.internal.html.Text;
@ -78,6 +77,9 @@ public class ClassWriter extends SubWriterHolderWriter {
"java.lang.constant.ConstantDesc",
"java.io.Serializable");
/* Length threshold to determine whether to insert whitespace between type parameters */
protected static final int LONG_TYPE_PARAM = 8;
protected final TypeElement typeElement;
protected final ClassTree classTree;
@ -459,10 +461,17 @@ public class ClassWriter extends SubWriterHolderWriter {
.linkToSelf(false); // Let's not link to ourselves in the header
content.add("<");
var first = true;
boolean longTypeParams = typeParams.stream()
.map(t -> getLink(linkInfo.forType(t.asType())))
.anyMatch(t -> t.charCount() > ClassWriter.LONG_TYPE_PARAM);
for (TypeParameterElement t : typeParams) {
if (!first) {
if (longTypeParams) {
content.add(", ");
} else {
content.add(",").add(HtmlTree.WBR());
}
}
var typeParamLink = getLink(linkInfo.forType(t.asType()));
content.add(needsId
? HtmlTree.SPAN_ID(htmlIds.forTypeParam(t.getSimpleName().toString(), typeElement), typeParamLink)

View File

@ -401,12 +401,15 @@ public class HtmlLinkFactory {
}
links.add("<");
boolean many = false;
boolean longTypeParams = vars.stream()
.map(t -> getLink(linkInfo.forType(t)))
.anyMatch(t -> t.charCount() > ClassWriter.LONG_TYPE_PARAM);
for (TypeMirror t : vars) {
if (many) {
links.add(",");
links.add(HtmlTree.WBR());
if (linkInfo.addLineBreaksInTypeParameters()) {
links.add(Text.NL);
if (longTypeParams) {
links.add(", ");
} else {
links.add(",").add(HtmlTree.WBR());
}
}
links.add(getLink(linkInfo.forType(t)));

View File

@ -355,9 +355,6 @@ public class Signatures {
private Content parameters;
private Content exceptions;
// Threshold for length of type parameters before switching from inline to block representation.
private static final int TYPE_PARAMS_MAX_INLINE_LENGTH = 50;
// Threshold for combined length of modifiers, type params and return type before breaking
// it up with a line break before the return type.
private static final int RETURN_TYPE_MAX_LINE_LENGTH = 50;
@ -532,13 +529,7 @@ public class Signatures {
// Apply different wrapping strategies for type parameters
// depending on the combined length of type parameters and return type.
// Note return type will be null if this is a constructor.
int typeParamLength = typeParameters.charCount();
if (typeParamLength >= TYPE_PARAMS_MAX_INLINE_LENGTH) {
target.add(HtmlTree.SPAN(HtmlStyles.typeParametersLong, typeParameters));
} else {
target.add(HtmlTree.SPAN(HtmlStyles.typeParameters, typeParameters));
}
int lineLength = target.charCount() - lastLineSeparator;
int newLastLineSeparator = lastLineSeparator;

View File

@ -708,14 +708,6 @@ public enum HtmlStyles implements HtmlStyle {
*/
typeParameters,
/**
* The class of a {@code span} containing type parameters in the signature of an element,
* used when the type parameters are too long to be displayed inline.
* @implNote
* The threshold for choosing between {@code typeParameters} and {@code typeParametersLong}
* is 50 characters.
*/
typeParametersLong,
//</editor-fold>
//<editor-fold desc="search index and results">

View File

@ -793,7 +793,6 @@ div.block {
.type-signature {
margin-top: 0;
}
.member-signature .type-parameters-long,
.member-signature .parameters,
.member-signature .exceptions {
display: inline-block;

View File

@ -74,15 +74,15 @@ public class TestGenericTypeLink extends JavadocTester {
<li><code><a href="http://example.com/docs/api/java.base/java/util/Map.html" title="\
class or interface in java.util" class="external-link">Map</a>&lt;<a href="http://ex\
ample.com/docs/api/java.base/java/lang/String.html" title="class or interface in jav\
a.lang" class="external-link">String</a>,<wbr>? extends <a href="http://example.com/\
a.lang" class="external-link">String</a>, ? extends <a href="http://example.com/\
docs/api/java.base/java/lang/CharSequence.html" title="class or interface in java.la\
ng" class="external-link">CharSequence</a>&gt;</code></li>
<li><code><a href="http://example.com/docs/api/java.base/java/util/Map.html" title="\
class or interface in java.util" class="external-link">Map</a>&lt;<a href="http://ex\
ample.com/docs/api/java.base/java/lang/String.html" title="class or interface in jav\
a.lang" class="external-link">String</a>,<wbr>? super <a href="A.html" title="class \
a.lang" class="external-link">String</a>, ? super <a href="A.html" title="class \
in pkg1">A</a>&lt;<a href="http://example.com/docs/api/java.base/java/lang/String.ht\
ml" title="class or interface in java.lang" class="external-link">String</a>,<wbr>? \
ml" title="class or interface in java.lang" class="external-link">String</a>, ? \
extends <a href="http://example.com/docs/api/java.base/java/lang/RuntimeException.ht\
ml" title="class or interface in java.lang" class="external-link">RuntimeException</\
a>&gt;&gt;</code></li>
@ -97,7 +97,7 @@ public class TestGenericTypeLink extends JavadocTester {
"""
<div class="block"><code><a href="A.html" title="class in pkg1">A</a>&lt;<a href="h\
ttp://example.com/docs/api/java.base/java/lang/String.html" title="class or interfa\
ce in java.lang" class="external-link">String</a>,<wbr><a href="A.SomeException.htm\
ce in java.lang" class="external-link">String</a>, <a href="A.SomeException.htm\
l" title="class in pkg1">A.SomeException</a>&gt;</code>
<a href="http://example.com/docs/api/java.base/java/util/Map.html" title="class or\
interface in java.util" class="external-link">link to generic type with label</a>\
@ -109,7 +109,7 @@ public class TestGenericTypeLink extends JavadocTester {
<ul class="tag-list-long">
<li><code><a href="A.html" title="class in pkg1">A</a>&lt;<a href="http://example.c\
om/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang\
" class="external-link">String</a>,<wbr><a href="A.SomeException.html" title="class\
" class="external-link">String</a>, <a href="A.SomeException.html" title="class\
in pkg1">A.SomeException</a>&gt;</code></li>
<li><a href="http://example.com/docs/api/java.base/java/util/List.html" title="clas\
s or interface in java.util" class="external-link">Link to generic type with label<\
@ -126,17 +126,17 @@ public class TestGenericTypeLink extends JavadocTester {
<ul class="tag-list-long">
<li><code><a href="A.html" title="class in pkg1">A</a>&lt;<a href="http://exampl\
e.com/docs/api/java.base/java/lang/String.html" title="class or interface in jav\
a.lang" class="external-link">String</a>,<wbr><a href="http://example.com/docs/a\
a.lang" class="external-link">String</a>, <a href="http://example.com/docs/a\
pi/java.base/java/lang/RuntimeException.html" title="class or interface in java.\
lang" class="external-link">RuntimeException</a>&gt;.<a href="A.Inner.html" titl\
e="class in pkg1">Inner</a></code></li>
<li><code><a href="A.html" title="class in pkg1">A</a>&lt;<a href="A.html" title\
="class in pkg1">A</a>&lt;<a href="http://example.com/docs/api/java.base/java/la\
ng/String.html" title="class or interface in java.lang" class="external-link">St\
ring</a>,<wbr><a href="http://example.com/docs/api/java.base/java/lang/RuntimeEx\
ring</a>, <a href="http://example.com/docs/api/java.base/java/lang/RuntimeEx\
ception.html" title="class or interface in java.lang" class="external-link">Runt\
imeException</a>&gt;.<a href="A.Inner.html" title="class in pkg1">Inner</a>,<wbr\
><a href="A.SomeException.html" title="class in pkg1">A.SomeException</a>&gt;</c\
imeException</a>&gt;.<a href="A.Inner.html" title="class in pkg1">Inner</a>, \
<a href="A.SomeException.html" title="class in pkg1">A.SomeException</a>&gt;</c\
ode></li>
</ul>
</dd>
@ -148,8 +148,8 @@ public class TestGenericTypeLink extends JavadocTester {
/a></code></span></div>
<div class="block">Here's a generic link: <code><a href="A.html" title="class in\
pkg1">A</a>&lt;<a href="http://example.com/docs/api/java.base/java/lang/Object.\
html" title="class or interface in java.lang" class="external-link">Object</a>,<\
wbr><a href="http://example.com/docs/api/java.base/java/lang/RuntimeException.ht\
html" title="class or interface in java.lang" class="external-link">Object</a>, \
<a href="http://example.com/docs/api/java.base/java/lang/RuntimeException.ht\
ml" title="class or interface in java.lang" class="external-link">RuntimeExcepti\
on</a>&gt;.<a href="A.Inner.html" title="class in pkg1">Inner</a>""");
}
@ -213,4 +213,3 @@ public class TestGenericTypeLink extends JavadocTester {
</dl>""");
}
}

View File

@ -95,8 +95,8 @@ public class TestInheritance extends JavadocTester {
<div class="inheritance">pkg.B&lt;O,<wbr>P&gt;</div>""");
checkOrder("pkg/C.html", """
<div class="inheritance" title="Inheritance Tree">java.lang.Object
<div class="inheritance"><a href="A.html" title="class in pkg">pkg.A</a>&lt;java.lang.String,<wbr>Q&gt;
<div class="inheritance"><a href="B.html" title="class in pkg">pkg.B</a>&lt;java.lang.String,<wbr>Q&gt;
<div class="inheritance"><a href="A.html" title="class in pkg">pkg.A</a>&lt;java.lang.String, Q&gt;
<div class="inheritance"><a href="B.html" title="class in pkg">pkg.B</a>&lt;java.lang.String, Q&gt;
<div class="inheritance">pkg.C&lt;Q&gt;</div>""");
checkOrder("pkg/D.html", """
<div class="inheritance" title="Inheritance Tree">java.lang.Object

View File

@ -212,9 +212,9 @@ public class TestInterface extends JavadocTester {
ator.OfInt</a>&lt;<a href="Spliterator.OfInt.html#type-param-Integer" title="type parameter in Spli\
terator.OfInt">Integer</a>&gt;, <a href="Spliterator.OfPrimitive.html" title="in\
terface in pkg2">Spliterator.OfPrimitive</a>&lt;<a href="Spliterator.OfPrimitive\
.html#type-param-T" title="type parameter in Spliterator.OfPrimitive">T</a>,<wbr><a href="Spl\
.html#type-param-T" title="type parameter in Spliterator.OfPrimitive">T</a>, <a href="Spl\
iterator.OfPrimitive.html#type-param-T_CONS" title="type parameter in Spliterator.OfPrimitive">T_C\
ONS</a>,<wbr><a href="Spliterator.OfPrimitive.html#type-param-T_SPLITR" title="type parameter in Spl\
ONS</a>, <a href="Spliterator.OfPrimitive.html#type-param-T_SPLITR" title="type parameter in Spl\
iterator.OfPrimitive">T_SPLITR</a> extends <a href="Spliterator.OfPrimitive.html\
" title="interface in pkg2">Spliterator.OfPrimitive</a>&lt;<a href="Spliterator.\
OfPrimitive.html#type-param-T" title="type parameter in Spliterator.OfPrimitive">T</a>,<wbr><\
@ -243,8 +243,8 @@ public class TestInterface extends JavadocTester {
<div class="col-second even-row-color"><code><a href="Spliterator.OfPrimitive.ht\
ml" class="type-name-link" title="interface in pkg2">Spliterator.OfPrimitive</a>\
&lt;<a href="Spliterator.OfPrimitive.html#type-param-T" title="type parameter in Spliterator.\
OfPrimitive">T</a>,<wbr><a href="Spliterator.OfPrimitive.html#type-param-T_CONS" title="type param\
eter in Spliterator.OfPrimitive">T_CONS</a>,<wbr><a href="Spliterator.OfPrimitiv\
OfPrimitive">T</a>, <a href="Spliterator.OfPrimitive.html#type-param-T_CONS" title="type param\
eter in Spliterator.OfPrimitive">T_CONS</a>, <a href="Spliterator.OfPrimitiv\
e.html#type-param-T_SPLITR" title="type parameter in Spliterator.OfPrimitive">T_SPLITR</a> extends <\
a href="Spliterator.OfPrimitive.html" title="interface in pkg2">Spliterator.OfPr\
imitive</a>&lt;<a href="Spliterator.OfPrimitive.html#type-param-T" title="type parameter in S\

View File

@ -72,13 +72,13 @@ public class TestMethodSignature extends JavadocTester {
"""
<div class="member-signature"><span class="modifiers">public static</span>&nbsp;\
<span class="type-parameters-long">&lt;T1 extends java.lang.AutoCloseable,<wbr>
T2 extends java.lang.AutoCloseable,<wbr>
T3 extends java.lang.AutoCloseable,<wbr>
T4 extends java.lang.AutoCloseable,<wbr>
T5 extends java.lang.AutoCloseable,<wbr>
T6 extends java.lang.AutoCloseable,<wbr>
T7 extends java.lang.AutoCloseable,<wbr>
<span class="type-parameters">&lt;T1 extends java.lang.AutoCloseable, \
T2 extends java.lang.AutoCloseable, \
T3 extends java.lang.AutoCloseable, \
T4 extends java.lang.AutoCloseable, \
T5 extends java.lang.AutoCloseable, \
T6 extends java.lang.AutoCloseable, \
T7 extends java.lang.AutoCloseable, \
T8 extends java.lang.AutoCloseable&gt;</span>
<span class="return-type"><a href="C.With8Types.html" title="class in pkg">C.Wit\
h8Types</a>&lt;T1,<wbr>T2,<wbr>T3,<wbr>T4,<wbr>T5,<wbr>T6,<wbr>T7,<wbr>T8&gt;</s\
@ -100,13 +100,13 @@ public class TestMethodSignature extends JavadocTester {
date="a date",
comments="some comment about the method below")
</span><span class="modifiers">public static</span>&nbsp;<span class="type-param\
eters-long">&lt;T1 extends java.lang.AutoCloseable,<wbr>
T2 extends java.lang.AutoCloseable,<wbr>
T3 extends java.lang.AutoCloseable,<wbr>
T4 extends java.lang.AutoCloseable,<wbr>
T5 extends java.lang.AutoCloseable,<wbr>
T6 extends java.lang.AutoCloseable,<wbr>
T7 extends java.lang.AutoCloseable,<wbr>
eters">&lt;T1 extends java.lang.AutoCloseable, \
T2 extends java.lang.AutoCloseable, \
T3 extends java.lang.AutoCloseable, \
T4 extends java.lang.AutoCloseable, \
T5 extends java.lang.AutoCloseable, \
T6 extends java.lang.AutoCloseable, \
T7 extends java.lang.AutoCloseable, \
T8 extends java.lang.AutoCloseable&gt;</span>
<span class="return-type"><a href="C.With8Types.html" title="class in pkg">C.Wit\
h8Types</a>&lt;T1,<wbr>T2,<wbr>T3,<wbr>T4,<wbr>T5,<wbr>T6,<wbr>T7,<wbr>T8&gt;</s\

View File

@ -141,7 +141,7 @@ public class TestNewLanguageFeatures extends JavadocTester {
// Signature of method with type parameters
"""
<div class="member-signature"><span class="modifiers">public</span>&nbsp;<span c\
lass="type-parameters">&lt;T extends java.util.List,<wbr>
lass="type-parameters">&lt;T extends java.util.List, \
V&gt;</span>
<span class="return-type">java.lang.String[]</span>&nbsp;<span class="element-name">meth\
odThatHasTypeParameters</span><wbr><span class="parameters">(T&nbsp;param1,

View File

@ -94,7 +94,7 @@ public class TestTypeAnnotations extends JavadocTester {
"""
<div class="type-signature"><span class="modifiers">class </span><span class="el\
ement-name type-name-label">TwoBounds&lt;K extends <a href="ClassParamA.html" ti\
tle="annotation interface in typeannos">@ClassParamA</a> java.lang.String,<wbr>V\
tle="annotation interface in typeannos">@ClassParamA</a> java.lang.String, V\
extends <a href="ClassParamB.html" title="annotation interface in typeannos">@C\
lassParamB</a> java.lang.String&gt;</span>""");
@ -122,7 +122,7 @@ public class TestTypeAnnotations extends JavadocTester {
"""
<div class="member-signature"><span class="return-type"><a href="Parameterized.h\
tml" title="class in typeannos">Parameterized</a>&lt;<a href="FldA.html" title="\
annotation interface in typeannos">@FldA</a> java.lang.String,<wbr><a href="FldB\
annotation interface in typeannos">@FldA</a> java.lang.String, <a href="FldB\
.html" title="annotation interface in typeannos">@FldB</a> java.lang.String&gt;<\
/span>&nbsp;<span class="element-name">bothTypeArgs</span></div>""",
@ -163,8 +163,8 @@ public class TestTypeAnnotations extends JavadocTester {
>Parameterized</a>&lt;<a href="FldA.html" title="annotation interface in typeann\
os">@FldA</a> <a href="Parameterized.html" title="class in typeannos">Parameteri\
zed</a>&lt;<a href="FldA.html" title="annotation interface in typeannos">@FldA</\
a> java.lang.String,<wbr><a href="FldB.html" title="annotation interface in type\
annos">@FldB</a> java.lang.String&gt;,<wbr><a href="FldB.html" title="annotation\
a> java.lang.String, <a href="FldB.html" title="annotation interface in type\
annos">@FldB</a> java.lang.String&gt;, <a href="FldB.html" title="annotation\
interface in typeannos">@FldB</a> java.lang.String&gt;</span>&nbsp;<span class=\
"element-name">nestedParameterized</span></div>""",
@ -212,8 +212,8 @@ public class TestTypeAnnotations extends JavadocTester {
os">MtdParameterized</a>&lt;<a href="MRtnA.html" title="annotation interface in \
typeannos">@MRtnA</a> <a href="MtdParameterized.html" title="class in typeannos"\
>MtdParameterized</a>&lt;<a href="MRtnA.html" title="annotation interface in typ\
eannos">@MRtnA</a> java.lang.String,<wbr><a href="MRtnB.html" title="annotation \
interface in typeannos">@MRtnB</a> java.lang.String&gt;,<wbr><a href="MRtnB.html\
eannos">@MRtnA</a> java.lang.String, <a href="MRtnB.html" title="annotation \
interface in typeannos">@MRtnB</a> java.lang.String&gt;, <a href="MRtnB.html\
" title="annotation interface in typeannos">@MRtnB</a> java.lang.String&gt;</spa\
n>&nbsp;<span class="element-name">nestedMtdParameterized</span>()</div>""");
@ -226,7 +226,7 @@ public class TestTypeAnnotations extends JavadocTester {
ass="element-name">methodExtends</span>()</div>""",
"""
<div class="member-signature"><span class="type-parameters-long">&lt;K extends <\
<div class="member-signature"><span class="type-parameters">&lt;K extends <\
a href="MTyParamA.html" title="annotation interface in typeannos">@MTyParamA</a>\
<a href="MtdTyParameterized.html" title="class in typeannos">MtdTyParameterized\
</a>&lt;<a href="MTyParamB.html" title="annotation interface in typeannos">@MTyP\
@ -242,8 +242,8 @@ public class TestTypeAnnotations extends JavadocTester {
"""
<div class="member-signature"><span class="modifiers">public final</span>&nbsp;<\
span class="type-parameters-long">&lt;K extends <a href="MTyParamA.html" title="\
annotation interface in typeannos">@MTyParamA</a> java.lang.String,<wbr>
span class="type-parameters">&lt;K extends <a href="MTyParamA.html" title="\
annotation interface in typeannos">@MTyParamA</a> java.lang.String, \
V extends <a href="MTyParamA.html" title="annotation interface in typeannos">@MT\
yParamA</a> <a href="MtdTyParameterized.html" title="class in typeannos">MtdTyPa\
rameterized</a>&lt;<a href="MTyParamB.html" title="annotation interface in typea\
@ -256,7 +256,7 @@ public class TestTypeAnnotations extends JavadocTester {
<div class="member-signature"><span class="return-type">void</span>&nbsp;<span c\
lass="element-name">unannotated</span><wbr><span class="parameters">(<a href="Pa\
raParameterized.html" title="class in typeannos">ParaParameterized</a>&lt;java.l\
ang.String,<wbr>java.lang.String&gt;&nbsp;a)</span></div>""",
ang.String, java.lang.String&gt;&nbsp;a)</span></div>""",
"""
<div class="member-signature"><span class="return-type">void</span>&nbsp;<span c\
@ -265,8 +265,8 @@ public class TestTypeAnnotations extends JavadocTester {
a>&lt;<a href="ParamA.html" title="annotation interface in typeannos">@ParamA</a\
> <a href="ParaParameterized.html" title="class in typeannos">ParaParameterized<\
/a>&lt;<a href="ParamA.html" title="annotation interface in typeannos">@ParamA</\
a> java.lang.String,<wbr><a href="ParamB.html" title="annotation interface in ty\
peannos">@ParamB</a> java.lang.String&gt;,<wbr><a href="ParamB.html" title="anno\
a> java.lang.String, <a href="ParamB.html" title="annotation interface in ty\
peannos">@ParamB</a> java.lang.String&gt;, <a href="ParamB.html" title="anno\
tation interface in typeannos">@ParamB</a> java.lang.String&gt;&nbsp;a)</span></\
div>""",
@ -339,7 +339,7 @@ public class TestTypeAnnotations extends JavadocTester {
// Test for type annotations on type parameters (TypeParameters.java).
checkOutput("typeannos/TestMethods.html", true,
"""
<div class="member-signature"><span class="type-parameters">&lt;K,<wbr>
<div class="member-signature"><span class="type-parameters">&lt;K, \
<a href="TyParaA.html" title="annotation interface in typeannos">@TyParaA</a> V \
extends <a href="TyParaA.html" title="annotation interface in typeannos">@TyPara\
A</a> java.lang.String&gt;</span>

View File

@ -56,8 +56,8 @@ public class TestTypeParameters extends JavadocTester {
checkOutput("pkg/C.html", true,
"""
<div class="col-first odd-row-color method-summary-table method-summary-table-ta\
b2 method-summary-table-tab4"><code>&lt;W extends java.lang.String,<wbr>
<div class="col-first odd-row-color method-summary-table method-summary-tab\
le-tab2 method-summary-table-tab4"><code>&lt;W extends java.lang.String, \
V extends java.util.List&gt;<br>java.lang.Object</code></div>""",
"<code>&lt;T&gt;&nbsp;java.lang.Object</code>");