Skip to content

Commit 6ac9299

Browse files
committed
8352249: Remove incidental whitespace in traditional doc comments
Reviewed-by: liach
1 parent 19e818b commit 6ac9299

File tree

64 files changed

+1385
-1170
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1385
-1170
lines changed

src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -1070,6 +1070,11 @@ public String getText() {
10701070
return "";
10711071
}
10721072

1073+
@Override
1074+
public Comment stripIndent() {
1075+
return this;
1076+
}
1077+
10731078
@Override
10741079
public JCDiagnostic.DiagnosticPosition getPos() {
10751080
return null;

src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -158,7 +158,7 @@ public DocCommentParser(ParserFactory fac, DiagnosticSource diagSource,
158158
this.fac = fac;
159159
this.diags = fac.log.diags;
160160
this.diagSource = diagSource;
161-
this.comment = comment;
161+
this.comment = comment.stripIndent();
162162
names = fac.names;
163163
this.isHtmlFile = isHtmlFile;
164164
textKind = isHtmlFile ? DocTree.Kind.TEXT : getTextKind(comment);

src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java

+15
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,21 @@ public String getText() {
12651265
return null;
12661266
}
12671267

1268+
/**
1269+
* Return a version of this comment with incidental whitespace removed,
1270+
* or this comment if the operation is not supported.
1271+
*
1272+
* @return comment with removed whitespace or this comment
1273+
*/
1274+
public Comment stripIndent() {
1275+
return this;
1276+
}
1277+
1278+
/**
1279+
* Return the diagnostic position of this comment.
1280+
*
1281+
* @return diagnostic position
1282+
*/
12681283
public DiagnosticPosition getPos() {
12691284
return pos;
12701285
}

src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java

+158-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -27,11 +27,11 @@
2727

2828
import com.sun.tools.javac.parser.Tokens.Comment;
2929
import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
30-
import com.sun.tools.javac.util.*;
30+
import com.sun.tools.javac.util.JCDiagnostic;
31+
import com.sun.tools.javac.util.Position;
3132

3233
import java.nio.CharBuffer;
3334
import java.util.Arrays;
34-
import java.util.regex.Pattern;
3535

3636
/**
3737
* An extension to the base lexical analyzer (JavaTokenizer) that
@@ -170,6 +170,11 @@ protected void scanDocComment() {
170170
offsetMap.trim();
171171
}
172172
}
173+
174+
@Override
175+
public Comment stripIndent() {
176+
return StrippedComment.of(this);
177+
}
173178
}
174179

175180
/**
@@ -354,4 +359,154 @@ int getSourcePos(int pos) {
354359
return map[startScaled + POS_OFFSET] + (pos - map[startScaled + SB_OFFSET]);
355360
}
356361
}
362+
363+
/**
364+
* A Comment derived from a JavadocComment with leading whitespace removed from all lines.
365+
* A new OffsetMap is used in combination with the OffsetMap of the original comment to
366+
* translate comment locations to positions in the source file.
367+
*
368+
* Note: This class assumes new lines are encoded as {@code '\n'}, which is the case
369+
* for comments created by {@code JavadocTokenizer}.
370+
*/
371+
static class StrippedComment implements Comment {
372+
String text;
373+
final OffsetMap strippedMap;
374+
final OffsetMap sourceMap;
375+
// Copy these fields to not hold a reference to the original comment with its text
376+
final JCDiagnostic.DiagnosticPosition diagPos;
377+
final CommentStyle style;
378+
final boolean deprecated;
379+
380+
/**
381+
* Returns a stripped version of the comment, or the comment itself if there is no
382+
* whitespace that can be stripped.
383+
*
384+
* @param comment the original comment
385+
* @return stripped or original comment
386+
*/
387+
static Comment of(JavadocComment comment) {
388+
if (comment.getStyle() != CommentStyle.JAVADOC_BLOCK) {
389+
return comment;
390+
}
391+
int indent = getIndent(comment);
392+
return indent > 0 ? new StrippedComment(comment, indent) : comment;
393+
}
394+
395+
private StrippedComment(JavadocComment comment, int indent) {
396+
this.diagPos = comment.getPos();
397+
this.style = comment.getStyle();
398+
this.deprecated = comment.isDeprecated();
399+
this.strippedMap = new OffsetMap();
400+
this.sourceMap = comment.offsetMap;
401+
stripComment(comment, indent);
402+
}
403+
404+
/**
405+
* Determines the number of leading whitespace characters that can be removed from
406+
* all non-blank lines of the original comment.
407+
*
408+
* @param comment the original comment
409+
* @return number of leading whitespace characters that can be reomved
410+
*/
411+
static int getIndent(Comment comment) {
412+
String txt = comment.getText();
413+
int len = txt.length();
414+
int indent = Integer.MAX_VALUE;
415+
416+
for (int i = 0; i < len; ) {
417+
int next;
418+
boolean inIndent = true;
419+
for (next = i; next < len && txt.charAt(next) != '\n'; next++) {
420+
if (inIndent && !Character.isWhitespace(txt.charAt(next))) {
421+
indent = Math.min(indent, next - i);
422+
inIndent = false;
423+
}
424+
}
425+
i = next + 1;
426+
}
427+
428+
return indent == Integer.MAX_VALUE ? 0 : indent;
429+
}
430+
431+
/**
432+
* Strips {@code indent} whitespace characters from every line of the original comment
433+
* and initializes an OffsetMap to translate positions to the original comment's OffsetMap.
434+
* This method does not distinguish between blank and non-blank lines except for the fact
435+
* that blank lines are not required to contain the number of leading whitespace indicated
436+
* by {@indent}.
437+
*
438+
* @param comment the original comment
439+
* @param indent number of whitespace characters to remove from each non-blank line
440+
*/
441+
private void stripComment(JavadocComment comment, int indent) {
442+
String txt = comment.getText();
443+
int len = txt.length();
444+
StringBuilder sb = new StringBuilder(len);
445+
446+
for (int i = 0; i < len; ) {
447+
int startOfLine = i;
448+
// Advance till start of stripped line, or \n if line is blank
449+
while (startOfLine < len
450+
&& startOfLine < i + indent
451+
&& txt.charAt(startOfLine) != '\n') {
452+
assert(Character.isWhitespace(txt.charAt(startOfLine)));
453+
startOfLine++;
454+
}
455+
if (startOfLine == len) {
456+
break;
457+
}
458+
459+
// Copy stripped line (terminated by \n or end of input)
460+
i = startOfLine + 1;
461+
while (i < len && txt.charAt(i - 1) != '\n') {
462+
i++;
463+
}
464+
// Add new offset if necessary
465+
strippedMap.add(sb.length(), startOfLine);
466+
sb.append(txt, startOfLine, i);
467+
}
468+
469+
text = sb.toString();
470+
strippedMap.trim();
471+
}
472+
473+
@Override
474+
public String getText() {
475+
return text;
476+
}
477+
478+
@Override
479+
public Comment stripIndent() {
480+
return this;
481+
}
482+
483+
@Override
484+
public int getSourcePos(int pos) {
485+
if (pos == Position.NOPOS) {
486+
return Position.NOPOS;
487+
}
488+
489+
if (pos < 0 || pos > text.length()) {
490+
throw new StringIndexOutOfBoundsException(String.valueOf(pos));
491+
}
492+
493+
return sourceMap.getSourcePos(strippedMap.getSourcePos(pos));
494+
}
495+
496+
@Override
497+
public JCDiagnostic.DiagnosticPosition getPos() {
498+
return diagPos;
499+
}
500+
501+
@Override
502+
public CommentStyle getStyle() {
503+
return style;
504+
}
505+
506+
@Override
507+
public boolean isDeprecated() {
508+
return deprecated;
509+
}
510+
}
511+
357512
}

src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Tokens.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -281,6 +281,7 @@ enum CommentStyle {
281281
}
282282

283283
String getText();
284+
Comment stripIndent();
284285
JCDiagnostic.DiagnosticPosition getPos();
285286
int getSourcePos(int index);
286287
CommentStyle getStyle();

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocPretty.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ public Void visitLiteral(LiteralTree node, Void p) {
345345
print('{');
346346
printTagName(node);
347347
String body = node.getBody().getBody();
348-
if (!body.isEmpty() && !Character.isWhitespace(body.charAt(0))) {
348+
if (!body.isEmpty() && body.charAt(0) != '\n') {
349349
print(' ');
350350
}
351351
print(node.getBody());

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -236,6 +236,9 @@ public String getText() {
236236
throw new UnsupportedOperationException(getClass() + ".getText");
237237
}
238238

239+
@Override
240+
public Comment stripIndent() { return this; }
241+
239242
@Override
240243
public CommentStyle getStyle() {
241244
throw new UnsupportedOperationException(getClass() + ".getStyle");

test/langtools/jdk/javadoc/doclet/testAutoHeaderId/TestAutoHeaderId.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ private void checkIds() {
133133
""",
134134
"""
135135
<h2 id="3-0-multi-line-heading-with-extra-whitespace-heading"> 3.0 Multi-line
136-
heading with extra
137-
whitespace</h2>""");
136+
heading with extra
137+
whitespace</h2>""");
138138
}
139139

140140
private void checkSearchIndex() {

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -70,16 +70,16 @@ public void test() {
7070
checkOutput("pkg/BreakIteratorTest.html", true,
7171
"""
7272
<div class="block">with an anchor for the
73-
<a href="../index-all.html">top level index</a>.</div>""");
73+
<a href="../index-all.html">top level index</a>.</div>""");
7474

7575
checkOutput("pkg/BreakIteratorTest.html", true,
7676
"""
7777
<div class="block">A constant indicating that the keyLocation is indeterminate
78-
or not relevant.</div>""");
78+
or not relevant.</div>""");
7979

8080
checkOutput("pkg/BreakIteratorTest.html", true,
8181
"""
8282
<div class="block">Inline tags <i><a href="../index-all.html">extending
83-
beyond the first sentence.</a></i></div>""");
83+
beyond the first sentence.</a></i></div>""");
8484
}
8585
}

test/langtools/jdk/javadoc/doclet/testCRLineSeparator/TestCRLineSeparator.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,7 @@ public void test() throws IOException {
5353

5454
checkOutput("pkg/MyClass.html", true,
5555
"Line 1\n"
56-
+ " Line 2");
56+
+ "Line 2");
5757
}
5858

5959
// recursively copy files from fromDir to toDir, replacing newlines

test/langtools/jdk/javadoc/doclet/testDirectedInheritance/TestDirectedInheritance.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -220,8 +220,8 @@ public interface E1 extends I1, I2 {
220220
checkExit(Exit.OK);
221221
new OutputChecker("x/E1.html").check("""
222222
<div class="block">E1: main description
223-
I2: main description
224-
I1: main description</div>""", """
223+
I2: main description
224+
I1: main description</div>""", """
225225
<dt>Throws:</dt>
226226
<dd><code>F</code> - E1: description of an exception</dd>
227227
<dd><code>F</code> - I2: first description of an exception</dd>

test/langtools/jdk/javadoc/doclet/testDocRootLink/TestDocRootLink.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -59,10 +59,10 @@ public void test1() {
5959
Refer <a href="../../technotes/guides/index.html">Here</a>""",
6060
"""
6161
This <a href="../pkg2/C2.html">Here</a> should not be replaced
62-
with an absolute link.""",
62+
with an absolute link.""",
6363
"""
6464
Testing <a href="../technotes/guides/index.html">Link 1</a> and
65-
<a href="../pkg2/C2.html">Link 2</a>.""");
65+
<a href="../pkg2/C2.html">Link 2</a>.""");
6666

6767
checkOutput("pkg1/package-summary.html", true,
6868
"""
@@ -102,10 +102,10 @@ public void test2() {
102102
Refer <a href="http://download.oracle.com/javase/7/docs/technotes/guides/index.html">Here</a>""",
103103
"""
104104
This <a href="../pkg1/C1.html">Here</a> should not be replaced
105-
with an absolute link.""",
105+
with an absolute link.""",
106106
"""
107107
Testing <a href="../technotes/guides/index.html">Link 1</a> and
108-
<a href="../pkg1/C1.html">Link 2</a>.""");
108+
<a href="../pkg1/C1.html">Link 2</a>.""");
109109

110110
checkOutput("pkg2/package-summary.html", true,
111111
"""

0 commit comments

Comments
 (0)