Replace PostgreSQL grammar to support COLLATE
This commit is contained in:
@@ -37,16 +37,16 @@ import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.Sem
|
||||
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokensDataProvider;
|
||||
import org.springframework.ide.vscode.parser.postgresql.PostgreSqlLexer;
|
||||
import org.springframework.ide.vscode.parser.postgresql.PostgreSqlParser;
|
||||
import org.springframework.ide.vscode.parser.postgresql.PostgreSqlParser.Data_typeContext;
|
||||
import org.springframework.ide.vscode.parser.postgresql.PostgreSqlParser.Attr_nameContext;
|
||||
import org.springframework.ide.vscode.parser.postgresql.PostgreSqlParser.Func_nameContext;
|
||||
import org.springframework.ide.vscode.parser.postgresql.PostgreSqlParser.IdentifierContext;
|
||||
import org.springframework.ide.vscode.parser.postgresql.PostgreSqlParser.ParameterContext;
|
||||
import org.springframework.ide.vscode.parser.postgresql.PostgreSqlParser.TypenameContext;
|
||||
import org.springframework.ide.vscode.parser.postgresql.PostgreSqlParserBaseListener;
|
||||
|
||||
public class PostgreSqlSemanticTokens implements SemanticTokensDataProvider {
|
||||
|
||||
private static List<String> TOKEN_TYPES = List.of("keyword", "type", "string", "number", "operator",
|
||||
"variable", "regexp", "comment", "parameter", "method");
|
||||
"variable", "comment", "parameter", "method");
|
||||
|
||||
private Optional<SpelSemanticTokens> optSpelTokens;
|
||||
private Optional<Consumer<RecognitionException>> parseErrorHandler;
|
||||
@@ -90,24 +90,23 @@ public class PostgreSqlSemanticTokens implements SemanticTokensDataProvider {
|
||||
private void processTerminalNode(TerminalNode node) {
|
||||
Token token = node.getSymbol();
|
||||
int type = token.getType();
|
||||
if (type >= PostgreSqlLexer.A_ && type <= PostgreSqlLexer.OWNED) {
|
||||
if (type >= PostgreSqlLexer.ALL && type <= PostgreSqlLexer.TOP) {
|
||||
semantics.put(token, "keyword");
|
||||
} else if (type >= PostgreSqlLexer.ABSTIME && type <= PostgreSqlLexer.XML) {
|
||||
semantics.put(token, "type");
|
||||
} else if ((type >= PostgreSqlLexer.AMP && type <= PostgreSqlLexer.SEMI)
|
||||
} else if (type >= PostgreSqlLexer.ABS && type <= PostgreSqlLexer.TO_NUMBER) {
|
||||
semantics.put(token, "method");
|
||||
} else if ((type >= PostgreSqlLexer.Dollar && type <= PostgreSqlLexer.Operator)
|
||||
|| (type >= PostgreSqlLexer.COMMA && type <= PostgreSqlLexer.CLOSE_BRACKET)
|
||||
|| type == PostgreSqlLexer.DOT) {
|
||||
semantics.put(token, "operator");
|
||||
} else if (type == PostgreSqlLexer.REGEX_STRING) {
|
||||
semantics.put(token, "regexp");
|
||||
} else if (type >= PostgreSqlLexer.SINGLEQ_STRING_LITERAL && type <= PostgreSqlLexer.DOUBLEQ_STRING_LITERAL) {
|
||||
} else if (type >= PostgreSqlLexer.StringConstant && type <= PostgreSqlLexer.BeginDollarStringConstant) {
|
||||
semantics.put(token, "string");
|
||||
} else if ((type >= PostgreSqlLexer.NUMERIC_LITERAL && type <= PostgreSqlLexer.HEX_INTEGER_LITERAL)
|
||||
|| type == PostgreSqlLexer.DOLLAR_DEC || type == PostgreSqlLexer.BIT_STRING) {
|
||||
} else if ((type >= PostgreSqlLexer.Integral && type <= PostgreSqlLexer.Numeric)
|
||||
|| (type >= PostgreSqlLexer.BinaryStringConstant && type <= PostgreSqlLexer.InvalidUnterminatedHexadecimalStringConstant)) {
|
||||
semantics.put(token, "number");
|
||||
} else if (type == PostgreSqlLexer.IDENTIFIER) {
|
||||
} else if ((type >= PostgreSqlLexer.Identifier && type <= PostgreSqlLexer.InvalidUnterminatedHexadecimalStringConstant)
|
||||
|| type == PostgreSqlLexer.PLSQLIDENTIFIER) {
|
||||
semantics.put(token, "variable");
|
||||
} else if (type >= PostgreSqlLexer.BLOCK_COMMENT && type <= PostgreSqlLexer.LINE_COMMENT) {
|
||||
} else if (type >= PostgreSqlLexer.LineComment && type <= PostgreSqlLexer.UnterminatedBlockComment) {
|
||||
semantics.put(token, "comment");
|
||||
} else if (type == PostgreSqlLexer.SPEL) {
|
||||
tokens.addAll(JpqlSemanticTokens.computeTokensFromSpelNode(node, initialOffset, optSpelTokens));
|
||||
@@ -124,40 +123,30 @@ public class PostgreSqlSemanticTokens implements SemanticTokensDataProvider {
|
||||
processTerminalNode(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitIdentifier(IdentifierContext ctx) {
|
||||
if (ctx.identifier() != null) {
|
||||
for (int i = 1; i < ctx.identifier().size(); i++) {
|
||||
IdentifierContext identifier = ctx.identifier(i);
|
||||
if (identifier.IDENTIFIER() != null) {
|
||||
semantics.put(identifier.IDENTIFIER().getSymbol(), "property");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitFunc_name(Func_nameContext funcName) {
|
||||
if (funcName.identifier() != null && funcName.identifier().IDENTIFIER() != null) {
|
||||
semantics.put(funcName.identifier().IDENTIFIER().getSymbol(), "method");
|
||||
}
|
||||
AntlrUtils.getAllLeafs(funcName).filter(t -> t.getType() != PostgreSqlLexer.DOT)
|
||||
.forEach(t -> semantics.put(t, "method"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitData_type(Data_typeContext dataType) {
|
||||
if (dataType.identifier() != null) {
|
||||
AntlrUtils.getAllLeafs(dataType.identifier())
|
||||
.filter(t -> t.getType() == PostgreSqlLexer.IDENTIFIER)
|
||||
public void exitAttr_name(Attr_nameContext ctx) {
|
||||
AntlrUtils.getAllLeafs(ctx)
|
||||
.forEach(t -> semantics.put(t, "proeprty"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitTypename(TypenameContext ctx) {
|
||||
AntlrUtils.getAllLeafs(ctx).filter(t -> t.getType() != PostgreSqlLexer.DOT)
|
||||
.forEach(t -> semantics.put(t, "type"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitParameter(ParameterContext param) {
|
||||
if (param.identifier() != null) {
|
||||
AntlrUtils.getAllLeafs(param.identifier()).forEach(t -> semantics.put(t, "parameter"));
|
||||
} else if (param.INTEGER_LITERAL() != null) {
|
||||
semantics.put(param.INTEGER_LITERAL().getSymbol(), "parameter");
|
||||
if (param.colid() != null) {
|
||||
AntlrUtils.getAllLeafs(param.colid()).forEach(t -> semantics.put(t, "parameter"));
|
||||
} else if (param.Integral() != null) {
|
||||
semantics.put(param.Integral().getSymbol(), "parameter");
|
||||
} else if (param.reserved_keyword() != null) {
|
||||
AntlrUtils.getAllLeafs(param.reserved_keyword()).forEach(t -> semantics.put(t, "parameter"));
|
||||
}
|
||||
|
||||
@@ -58,10 +58,10 @@ public class PostgreSqlSemanticTokensTest {
|
||||
assertThat(tokens.get(26)).isEqualTo(new SemanticTokenData(154, 155, "parameter", new String[0])); // 1 from ?1
|
||||
assertThat(tokens.get(28)).isEqualTo(new SemanticTokenData(161, 177, "method", new String[0])); // json_path_exists
|
||||
assertThat(tokens.get(33)).isEqualTo(new SemanticTokenData(194, 196, "operator", new String[0])); // ::
|
||||
assertThat(tokens.get(34)).isEqualTo(new SemanticTokenData(196, 201, "type", new String[0])); // ::
|
||||
assertThat(tokens.get(34)).isEqualTo(new SemanticTokenData(196, 201, "type", new String[0])); // jsonb
|
||||
assertThat(tokens.get(37)).isEqualTo(new SemanticTokenData(204, 281, "string", new String[0])); // 'strict $.content.**.id ? (@ == "\\' || representation.targetobjectid || \\'")'
|
||||
assertThat(tokens.get(39)).isEqualTo(new SemanticTokenData(282, 284, "operator", new String[0])); // ::
|
||||
assertThat(tokens.get(40)).isEqualTo(new SemanticTokenData(284, 292, "type", new String[0])); // ::
|
||||
assertThat(tokens.get(40)).isEqualTo(new SemanticTokenData(284, 292, "type", new String[0])); // jsonpath
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -85,7 +85,7 @@ public class PostgreSqlSemanticTokensTest {
|
||||
void semiColonAtEnd() {
|
||||
List<SemanticTokenData> tokens = provider.computeTokens(" select count(*) from anecdote where anecdote_id=:anecdote ; ", 0);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(1, 7, "keyword", new String[0])); // select
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(8, 13, "keyword", new String[0])); // count
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(8, 13, "method", new String[0])); // count
|
||||
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(13, 14, "operator", new String[0])); // (
|
||||
assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(14, 15, "operator", new String[0])); // *
|
||||
assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(15, 16, "operator", new String[0])); // )
|
||||
@@ -103,7 +103,7 @@ public class PostgreSqlSemanticTokensTest {
|
||||
|
||||
@Test
|
||||
void parameterInLimitClause_1() {
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("SELECT * FROM cards ORDER BY random() LIMIT :2", 0);
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("SELECT * FROM cards ORDER BY random() LIMIT ?2", 0);
|
||||
assertThat(tokens.size()).isEqualTo(12);
|
||||
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0]));
|
||||
@@ -203,7 +203,7 @@ public class PostgreSqlSemanticTokensTest {
|
||||
assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(15, 19, "keyword", new String[0]));
|
||||
assertThat(tokens.get(5)).isEqualTo(new SemanticTokenData(20, 32, "variable", new String[0]));
|
||||
assertThat(tokens.get(6)).isEqualTo(new SemanticTokenData(33, 38, "keyword", new String[0]));
|
||||
assertThat(tokens.get(7)).isEqualTo(new SemanticTokenData(39, 50, "keyword", new String[0]));
|
||||
assertThat(tokens.get(7)).isEqualTo(new SemanticTokenData(39, 50, "variable", new String[0]));
|
||||
assertThat(tokens.get(8)).isEqualTo(new SemanticTokenData(51, 52, "operator", new String[0]));
|
||||
assertThat(tokens.get(9)).isEqualTo(new SemanticTokenData(53, 54, "operator", new String[0]));
|
||||
assertThat(tokens.get(10)).isEqualTo(new SemanticTokenData(54, 55, "parameter", new String[0]));
|
||||
@@ -285,4 +285,36 @@ public class PostgreSqlSemanticTokensTest {
|
||||
""", 0);
|
||||
assertThat(tokens.size()).isEqualTo(74);
|
||||
}
|
||||
|
||||
@Test
|
||||
void collate_1() {
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("""
|
||||
SELECT DISTINCT test COLLATE "numeric" FROM Test
|
||||
""", 0);
|
||||
assertThat(tokens.size()).isEqualTo(7);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 15, "keyword", new String[0])); // DISTICT
|
||||
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(16, 20, "variable", new String[0])); // test
|
||||
assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(21, 28, "keyword", new String[0])); // COLLATE
|
||||
assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(29, 38, "variable", new String[0])); // "numeric"
|
||||
assertThat(tokens.get(5)).isEqualTo(new SemanticTokenData(39, 43, "keyword", new String[0])); // FROM
|
||||
assertThat(tokens.get(6)).isEqualTo(new SemanticTokenData(44, 48, "variable", new String[0])); // Test
|
||||
}
|
||||
|
||||
@Test
|
||||
void collate_2() {
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("""
|
||||
SELECT a COLLATE "de_DE" < b FROM test1
|
||||
""", 0);
|
||||
assertThat(tokens.size()).isEqualTo(8);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 8, "variable", new String[0])); // a
|
||||
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(9, 16, "keyword", new String[0])); // COLLATE
|
||||
assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(17, 24, "variable", new String[0])); // "de_DE"
|
||||
assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(25, 26, "operator", new String[0])); // <
|
||||
assertThat(tokens.get(5)).isEqualTo(new SemanticTokenData(27, 28, "variable", new String[0])); // b
|
||||
assertThat(tokens.get(6)).isEqualTo(new SemanticTokenData(29, 33, "keyword", new String[0])); // FROM
|
||||
assertThat(tokens.get(7)).isEqualTo(new SemanticTokenData(34, 39, "variable", new String[0])); // test1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ public class QueryReconcilerTest {
|
||||
String docUri = directory.toPath().resolve("src/main/java/example/demo/OwnerRepository.java").toUri()
|
||||
.toString();
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA, source, docUri);
|
||||
editor.assertProblems("ptype|PostgreSQL: no viable alternative at input 'SELECTXptype'");
|
||||
editor.assertProblems("SELECTX|PostgreSQL: mismatched input 'SELECTX'");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user