jdk-24/test/langtools/tools/javac/lexer/CommentTest.java
Jonathan Gibbons 0a58cffe88 8298405: Implement JEP 467: Markdown Documentation Comments
8329296: Update Elements for '///' documentation comments

Co-authored-by: Jim Laskey <jlaskey@openjdk.org>
Reviewed-by: prappo, darcy, hannesw
2024-05-17 17:42:46 +00:00

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", "|"));
}
}
}