0a58cffe88
8329296: Update Elements for '///' documentation comments Co-authored-by: Jim Laskey <jlaskey@openjdk.org> Reviewed-by: prappo, darcy, hannesw
524 lines
12 KiB
Java
524 lines
12 KiB
Java
/*
|
|
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/*
|
|
* @test
|
|
* @bug 8298405
|
|
* @summary Proper lexing of comments, especially /// comments
|
|
* @library /tools/lib
|
|
* @modules jdk.compiler/com.sun.tools.javac.parser
|
|
* jdk.compiler/com.sun.tools.javac.util
|
|
* @build toolbox.TestRunner
|
|
* @run main CommentTest
|
|
*/
|
|
|
|
import java.util.Objects;
|
|
|
|
import com.sun.tools.javac.parser.ScannerFactory;
|
|
import com.sun.tools.javac.parser.Tokens;
|
|
import com.sun.tools.javac.util.Context;
|
|
|
|
import toolbox.TestRunner;
|
|
|
|
public class CommentTest extends TestRunner {
|
|
public static void main(String... args) throws Exception {
|
|
new CommentTest().runTests();
|
|
}
|
|
|
|
CommentTest() {
|
|
super(System.err);
|
|
}
|
|
|
|
/**
|
|
* Control: a simple comment with no blank lines or incidental whitespace.
|
|
*/
|
|
@Test
|
|
public void testControl() {
|
|
test("""
|
|
[
|
|
|
|
///abc
|
|
///def
|
|
///ghi
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
def
|
|
ghi""");
|
|
}
|
|
|
|
/**
|
|
* Whitespace before the comment is completely ignored.
|
|
*/
|
|
@Test
|
|
public void testRaggedInitialIndent() {
|
|
test("""
|
|
[
|
|
|
|
///abc
|
|
///def
|
|
///ghi
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
def
|
|
ghi""");
|
|
}
|
|
|
|
/**
|
|
* Leading blank lines are preserved.
|
|
*/
|
|
@Test
|
|
public void testLeadingBlankLine_1() {
|
|
test("""
|
|
[
|
|
|
|
///
|
|
///abc
|
|
///def
|
|
///ghi
|
|
|
|
]
|
|
""", """
|
|
|
|
abc
|
|
def
|
|
ghi""");
|
|
}
|
|
|
|
/**
|
|
* Leading blank lines do not affect the amount of incidental whitespace.
|
|
*/
|
|
@Test
|
|
public void testLeadingBlankLine_2() {
|
|
test("""
|
|
[
|
|
|
|
///
|
|
/// abc
|
|
/// def
|
|
/// ghi
|
|
|
|
]
|
|
""", """
|
|
|
|
abc
|
|
def
|
|
ghi""");
|
|
}
|
|
|
|
/**
|
|
* Inner blank lines are preserved.
|
|
*/
|
|
@Test
|
|
public void testInnerBlankLine_1() {
|
|
test("""
|
|
[
|
|
|
|
///abc
|
|
///
|
|
///def
|
|
///ghi
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
|
|
def
|
|
ghi""");
|
|
}
|
|
|
|
/**
|
|
* Inner blank lines do not affect the amount of incidental whitespace.
|
|
*/
|
|
@Test
|
|
public void testInnerBlankLine_2() {
|
|
test("""
|
|
[
|
|
|
|
/// abc
|
|
///
|
|
/// def
|
|
/// ghi
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
|
|
def
|
|
ghi""");
|
|
}
|
|
|
|
/**
|
|
* Inner blank lines do not affect the amount of incidental whitespace,
|
|
* but may have whitespace removed, perhaps resulting in an empty line.
|
|
*/
|
|
@Test
|
|
public void testInnerBlankLine_3() {
|
|
test("""
|
|
[
|
|
|
|
/// abc
|
|
/// \s
|
|
/// def
|
|
/// ghi
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
|
|
def
|
|
ghi""");
|
|
}
|
|
|
|
/**
|
|
* Inner blank lines do not affect the amount of incidental whitespace,
|
|
* but may have whitespace removed.
|
|
*/
|
|
@Test
|
|
public void testInnerBlankLine_4() {
|
|
test("""
|
|
[
|
|
|
|
/// abc
|
|
/// \s
|
|
/// def
|
|
/// ghi
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
\s
|
|
def
|
|
ghi""");
|
|
}
|
|
|
|
/**
|
|
* Trailing blank lines are preserved.
|
|
*/
|
|
@Test
|
|
public void testTrailingBlankLine_1() {
|
|
test("""
|
|
[
|
|
|
|
///abc
|
|
///def
|
|
///ghi
|
|
///
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
def
|
|
ghi
|
|
""");
|
|
}
|
|
|
|
/**
|
|
* Trailing blank lines do not affect the amount of incidental whitespace.
|
|
*/
|
|
@Test
|
|
public void testTrailingBlankLine_2() {
|
|
test("""
|
|
[
|
|
|
|
/// abc
|
|
/// def
|
|
/// ghi
|
|
///
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
def
|
|
ghi
|
|
""");
|
|
}
|
|
|
|
/**
|
|
* Small amounts of incidental whitespace are removed.
|
|
*/
|
|
@Test
|
|
public void testIncidental_small() {
|
|
test("""
|
|
[
|
|
|
|
/// abc
|
|
/// def
|
|
/// ghi
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
def
|
|
ghi""");
|
|
}
|
|
|
|
/**
|
|
* Large amounts of incidental whitespace are removed.
|
|
*/
|
|
@Test
|
|
public void testIncidental_large() {
|
|
test("""
|
|
[
|
|
|
|
/// abc
|
|
/// def
|
|
/// ghi
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
def
|
|
ghi""");
|
|
}
|
|
|
|
/**
|
|
* Additional leading whitespace may remain after incidental whitespace is removed.
|
|
*/
|
|
@Test
|
|
public void testIncidental_mixed() {
|
|
test("""
|
|
[
|
|
|
|
/// abc
|
|
/// def
|
|
/// ghi
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
def
|
|
ghi""");
|
|
}
|
|
|
|
/**
|
|
* Tabs and spaces are treated equally, as whitespace characters.
|
|
*/
|
|
@Test
|
|
public void testIncidental_withTabs() {
|
|
test("""
|
|
[
|
|
|
|
/// abc
|
|
///\t def
|
|
///\t\t ghi
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
def
|
|
ghi""");
|
|
}
|
|
|
|
/**
|
|
* Leading tabs may remain after incidental whitespace is removed.
|
|
*/
|
|
@Test
|
|
public void testTabAfterIncidental() {
|
|
test("""
|
|
[
|
|
|
|
/// abc
|
|
/// \tdef
|
|
/// ghi
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
\tdef
|
|
ghi""");
|
|
}
|
|
|
|
/**
|
|
* Trailing spaces are never removed.
|
|
*/
|
|
@Test
|
|
public void testTrailingSpaces() {
|
|
test("""
|
|
[
|
|
|
|
///abc
|
|
///def \s
|
|
///ghi
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
def \s
|
|
ghi""");
|
|
|
|
}
|
|
|
|
/**
|
|
* Trailing tabs are never removed.
|
|
*/
|
|
@Test
|
|
public void testTrailingTabs() {
|
|
test("""
|
|
[
|
|
|
|
///abc
|
|
///def \t
|
|
///ghi
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
def \t
|
|
ghi""");
|
|
|
|
}
|
|
|
|
/**
|
|
* Tabs may appear in incidental whitespace, and may remain in the leading
|
|
* whitespace after incidental whitespace is removed.
|
|
*/
|
|
@Test
|
|
public void testMixedTabs() {
|
|
test("""
|
|
[
|
|
|
|
///\t \t abc
|
|
///\t \t \tdef
|
|
///\t \t ghi
|
|
|
|
]
|
|
""", """
|
|
abc
|
|
\tdef
|
|
ghi""");
|
|
|
|
}
|
|
|
|
/**
|
|
* A blank line between two /// comments is significant, and separates the two comments.
|
|
*/
|
|
@Test
|
|
public void testMultipleComments() {
|
|
// When there is more than one comment, the most recent comment is first in the list
|
|
// stored in the token.
|
|
//
|
|
// (For JavaDoc, only the most recent comment is used; any preceding comments are ignored.)
|
|
test("""
|
|
[
|
|
|
|
///abc
|
|
|
|
///ghi
|
|
|
|
]
|
|
""", """
|
|
ghi""", """
|
|
abc""");
|
|
|
|
}
|
|
|
|
/**
|
|
* An example of pseudo-typical Markdown, containing various Markdown constructs,
|
|
* like lists and code blocks.
|
|
*/
|
|
@Test
|
|
public void testSampleMarkdown() {
|
|
test("""
|
|
[
|
|
|
|
/// Lorem ipsum dolor sit amet,
|
|
/// consectetur adipiscing elit.
|
|
///
|
|
/// * item 1
|
|
/// * item 2
|
|
///
|
|
/// ```
|
|
/// fenced code block
|
|
/// ```
|
|
///
|
|
/// Ut enim ad minim veniam, quis nostrud
|
|
/// exercitation ullamco laboris nisi ut
|
|
/// aliquip ex ea commodo consequat.
|
|
///
|
|
/// indented code block
|
|
/// ...
|
|
///
|
|
/// Duis aute irure dolor in reprehenderit
|
|
/// in voluptate velit esse cillum dolore
|
|
/// eu fugiat nulla pariatur.
|
|
]
|
|
""", """
|
|
Lorem ipsum dolor sit amet,
|
|
consectetur adipiscing elit.
|
|
|
|
* item 1
|
|
* item 2
|
|
|
|
```
|
|
fenced code block
|
|
```
|
|
|
|
Ut enim ad minim veniam, quis nostrud
|
|
exercitation ullamco laboris nisi ut
|
|
aliquip ex ea commodo consequat.
|
|
|
|
indented code block
|
|
...
|
|
|
|
Duis aute irure dolor in reprehenderit
|
|
in voluptate velit esse cillum dolore
|
|
eu fugiat nulla pariatur.""");
|
|
|
|
}
|
|
|
|
private void test(String input, String... expect) {
|
|
var ctx = new Context();
|
|
var sf = ScannerFactory.instance(ctx);
|
|
var s = sf.newScanner(input, true);
|
|
s. nextToken();
|
|
var skipToken = s.token();
|
|
checkEqual(skipToken.kind, Tokens.TokenKind.LBRACKET);
|
|
|
|
s.nextToken();
|
|
var t = s.token();
|
|
var comments = t.comments;
|
|
if (comments == null) {
|
|
error("no comments");
|
|
} else if (comments.size() == expect.length) {
|
|
for (var i = 0; i < comments.size(); i++) {
|
|
checkEqual(comments.get(i).getText(), expect[i]);
|
|
}
|
|
} else {
|
|
error("Unexpected comments: " + comments);
|
|
out.println(" expected " + expect.length + " comments");
|
|
out.println(" found " + comments.size() + " comments");
|
|
}
|
|
}
|
|
|
|
private void checkEqual(Object found, Object expect) {
|
|
if (!Objects.equals(found, expect)) {
|
|
error("mismatch");
|
|
out.println(" expect: " + String.valueOf(expect).replace("\n", "|"));
|
|
out.println(" found: " + String.valueOf(found).replace("\n", "|"));
|
|
}
|
|
}
|
|
} |