Skip to content

Commit cc85abc

Browse files
committed
8326332: Unclosed inline tags cause misalignment in summary tables
Reviewed-by: rschmelter Backport-of: a6dc4bc2b83c7240e573ac43f9b7a10191c58ed3
1 parent bba56e0 commit cc85abc

File tree

3 files changed

+47
-13
lines changed

3 files changed

+47
-13
lines changed

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
import static com.sun.source.doctree.DocTree.Kind.LINK;
118118
import static com.sun.source.doctree.DocTree.Kind.LINK_PLAIN;
119119
import static com.sun.source.doctree.DocTree.Kind.SEE;
120+
import static com.sun.source.doctree.DocTree.Kind.START_ELEMENT;
120121
import static com.sun.source.doctree.DocTree.Kind.TEXT;
121122

122123

@@ -1133,21 +1134,37 @@ private void addCommentTags(Element element, List<? extends DocTree> tags, boole
11331134
}
11341135
}
11351136

1136-
boolean ignoreNonInlineTag(DocTree dtree) {
1137+
// helper methods because jdk21 functionality is not allowed
1138+
private static Name getLastHelper(List<Name> l) {
1139+
return l.get(l.size() - 1);
1140+
}
1141+
1142+
private static Name removeLastHelper(List<Name> l) {
1143+
return l.remove(l.size() - 1);
1144+
}
1145+
1146+
boolean ignoreNonInlineTag(DocTree dtree, List<Name> openTags) {
11371147
Name name = null;
1138-
if (dtree.getKind() == Kind.START_ELEMENT) {
1139-
StartElementTree setree = (StartElementTree)dtree;
1140-
name = setree.getName();
1141-
} else if (dtree.getKind() == Kind.END_ELEMENT) {
1142-
EndElementTree eetree = (EndElementTree)dtree;
1143-
name = eetree.getName();
1148+
Kind kind = dtree.getKind();
1149+
if (kind == Kind.START_ELEMENT) {
1150+
name = ((StartElementTree)dtree).getName();
1151+
} else if (kind == Kind.END_ELEMENT) {
1152+
name = ((EndElementTree)dtree).getName();
11441153
}
11451154

11461155
if (name != null) {
11471156
HtmlTag htmlTag = HtmlTag.get(name);
1148-
if (htmlTag != null &&
1149-
htmlTag.blockType != jdk.javadoc.internal.doclint.HtmlTag.BlockType.INLINE) {
1150-
return true;
1157+
if (htmlTag != null) {
1158+
if (htmlTag.blockType != HtmlTag.BlockType.INLINE) {
1159+
return true;
1160+
}
1161+
// Keep track of open inline tags that need to be closed, see 8326332
1162+
if (kind == START_ELEMENT && htmlTag.endKind == HtmlTag.EndKind.REQUIRED) {
1163+
openTags.add(name);
1164+
} else if (kind == Kind.END_ELEMENT && !openTags.isEmpty()
1165+
&& getLastHelper(openTags).equals(name)) {
1166+
removeLastHelper(openTags);
1167+
}
11511168
}
11521169
}
11531170
return false;
@@ -1219,6 +1236,7 @@ public ContentBuilder add(CharSequence text) {
12191236
CommentHelper ch = utils.getCommentHelper(element);
12201237
configuration.tagletManager.checkTags(element, trees);
12211238
commentRemoved = false;
1239+
List<Name> openTags = new ArrayList<>();
12221240

12231241
for (ListIterator<? extends DocTree> iterator = trees.listIterator(); iterator.hasNext();) {
12241242
boolean isFirstNode = !iterator.hasPrevious();
@@ -1227,14 +1245,16 @@ public ContentBuilder add(CharSequence text) {
12271245

12281246
if (context.isFirstSentence) {
12291247
// Ignore block tags
1230-
if (ignoreNonInlineTag(tag))
1248+
if (ignoreNonInlineTag(tag, openTags)) {
12311249
continue;
1250+
}
12321251

12331252
// Ignore any trailing whitespace OR whitespace after removed html comment
12341253
if ((isLastNode || commentRemoved)
12351254
&& tag.getKind() == TEXT
1236-
&& ((tag instanceof TextTree tt) && tt.getBody().isBlank()))
1255+
&& ((tag instanceof TextTree tt) && tt.getBody().isBlank())) {
12371256
continue;
1257+
}
12381258

12391259
// Ignore any leading html comments
12401260
if ((isFirstNode || commentRemoved) && tag.getKind() == COMMENT) {
@@ -1485,6 +1505,10 @@ protected Boolean defaultAction(DocTree node, Content content) {
14851505
if (allDone)
14861506
break;
14871507
}
1508+
// Close any open inline tags
1509+
while (!openTags.isEmpty()) {
1510+
result.add(RawHtml.endElement(removeLastHelper(openTags)));
1511+
}
14881512
return result;
14891513
}
14901514

test/langtools/jdk/javadoc/doclet/testBreakIterator/TestBreakIterator.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 4165985
26+
* @bug 4165985 8326332
2727
* @summary Determine the end of the first sentence using BreakIterator.
2828
* If the first sentence of "method" is parsed correctly, the test passes.
2929
* Correct Answer: "This is a class (i.e. it is indeed a class)."
@@ -76,5 +76,10 @@ public void test() {
7676
"""
7777
<div class="block">A constant indicating that the keyLocation is indeterminate
7878
or not relevant.</div>""");
79+
80+
checkOutput("pkg/BreakIteratorTest.html", true,
81+
"""
82+
<div class="block">Inline tags <i><a href="../index-all.html">extending
83+
beyond the first sentence.</a></i></div>""");
7984
}
8085
}

test/langtools/jdk/javadoc/doclet/testBreakIterator/pkg/BreakIteratorTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,9 @@ public void foobar(){}
5656
*/
5757
public void fe(){}
5858

59+
/**
60+
* Inline tags <i><a href="{@docRoot}/index-all.html">extending
61+
* beyond the first sentence. Tags are closed here.</a></i>
62+
*/
63+
public void meh(){}
5964
}

0 commit comments

Comments
 (0)