Skip to content

Commit 0998415

Browse files
committed
feat(parser): expose leading comments via getLeadingComments()
Downstream SQL rewriters currently recover statement-leading comments from the JavaCC special-token chain via getASTNode(), whose erasure changed within 5.x and broke compiled downstream adapters. Signed-off-by: 付典 <fudianchn@gmail.com>
1 parent 066f581 commit 0998415

2 files changed

Lines changed: 94 additions & 0 deletions

File tree

‎src/main/java/net/sf/jsqlparser/parser/ASTNodeAccessImpl.java‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
*/
1010
package net.sf.jsqlparser.parser;
1111

12+
import java.util.ArrayList;
13+
import java.util.Collections;
14+
import java.util.List;
1215
import java.util.Set;
1316
import java.util.TreeSet;
1417

@@ -26,6 +29,26 @@ public void setASTNode(Node node) {
2629
this.node = node;
2730
}
2831

32+
/**
33+
* The comments preceding this node's first token, in source order, with the original token
34+
* images (line comments keep their line terminator). Empty for nodes built programmatically,
35+
* which carry no AST.
36+
*/
37+
public List<String> getLeadingComments() {
38+
Node node = getASTNode();
39+
if (node == null) {
40+
return new ArrayList<>();
41+
}
42+
List<String> comments = new ArrayList<>();
43+
for (Token specialToken =
44+
node.jjtGetFirstToken().specialToken; specialToken != null; specialToken =
45+
specialToken.specialToken) {
46+
comments.add(specialToken.image);
47+
}
48+
Collections.reverse(comments);
49+
return comments;
50+
}
51+
2952
public StringBuilder appendTo(StringBuilder builder) {
3053
// don't add spaces around the following punctuation
3154
final Set<String> punctuation = new TreeSet<>(Set.of(".", "[", "]"));
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2019 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.parser;
11+
12+
import static org.junit.jupiter.api.Assertions.assertEquals;
13+
import static org.junit.jupiter.api.Assertions.assertFalse;
14+
import static org.junit.jupiter.api.Assertions.assertTrue;
15+
16+
import java.util.List;
17+
import net.sf.jsqlparser.JSQLParserException;
18+
import net.sf.jsqlparser.statement.Statements;
19+
import net.sf.jsqlparser.statement.select.PlainSelect;
20+
import net.sf.jsqlparser.statement.select.Select;
21+
import org.junit.jupiter.api.Test;
22+
23+
public class LeadingCommentsTest {
24+
25+
@Test
26+
public void blockCommentsBeforeStatementInSourceOrder() throws JSQLParserException {
27+
Select select = (Select) CCJSqlParserUtil
28+
.parse("/* keep orderby */ /*+ FULL(t) */ SELECT * FROM mytable");
29+
assertEquals(List.of("/* keep orderby */", "/*+ FULL(t) */"), select.getLeadingComments());
30+
}
31+
32+
@Test
33+
public void lineCommentBeforeStatement() throws JSQLParserException {
34+
Select select = (Select) CCJSqlParserUtil.parse("-- paging hint\nSELECT 1");
35+
List<String> comments = select.getLeadingComments();
36+
assertEquals(1, comments.size());
37+
assertTrue(comments.get(0).startsWith("-- paging hint"));
38+
}
39+
40+
@Test
41+
public void commentInsideStatementIsNotLeading() throws JSQLParserException {
42+
Select select = (Select) CCJSqlParserUtil.parse("SELECT /* mid comment */ 1");
43+
assertEquals(List.of(), select.getLeadingComments());
44+
}
45+
46+
@Test
47+
public void statementWithoutComments() throws JSQLParserException {
48+
Select select = (Select) CCJSqlParserUtil.parse("SELECT * FROM mytable");
49+
assertEquals(List.of(), select.getLeadingComments());
50+
}
51+
52+
@Test
53+
public void programmaticStatementHasNoLeadingComments() {
54+
assertEquals(List.of(), new PlainSelect().getLeadingComments());
55+
}
56+
57+
@Test
58+
public void toStringDropsLeadingCommentsAsBefore() throws JSQLParserException {
59+
Select select = (Select) CCJSqlParserUtil
60+
.parse("/* keep orderby */ SELECT * FROM mytable");
61+
assertFalse(select.toString().contains("/*"));
62+
}
63+
64+
@Test
65+
public void commentsSplitPerStatement() throws JSQLParserException {
66+
Statements statements = CCJSqlParserUtil
67+
.parseStatements("/* first */ SELECT 1; /* second */ SELECT 2");
68+
assertEquals(List.of("/* first */"), ((Select) statements.get(0)).getLeadingComments());
69+
assertEquals(List.of("/* second */"), ((Select) statements.get(1)).getLeadingComments());
70+
}
71+
}

0 commit comments

Comments
 (0)