diff --git a/headless-services/commons/jpql/grammars/PostgreSqlParser.g4 b/headless-services/commons/jpql/grammars/PostgreSqlParser.g4 index f291e1e5f..997388eb5 100644 --- a/headless-services/commons/jpql/grammars/PostgreSqlParser.g4 +++ b/headless-services/commons/jpql/grammars/PostgreSqlParser.g4 @@ -26,7 +26,7 @@ options { tokenVocab=PostgreSqlLexer; } root - : stmt ((SEMI stmt)+ SEMI)? EOF + : stmt ((SEMI stmt)* SEMI)? EOF ; // Top Level Description diff --git a/headless-services/commons/jpql/src/main/java/org/springframework/ide/vscode/parser/postgresql/PostgreSqlParser.java b/headless-services/commons/jpql/src/main/java/org/springframework/ide/vscode/parser/postgresql/PostgreSqlParser.java index eac3e65cf..3d37a8193 100644 --- a/headless-services/commons/jpql/src/main/java/org/springframework/ide/vscode/parser/postgresql/PostgreSqlParser.java +++ b/headless-services/commons/jpql/src/main/java/org/springframework/ide/vscode/parser/postgresql/PostgreSqlParser.java @@ -640,12 +640,11 @@ public class PostgreSqlParser extends Parser { _la = _input.LA(1); if (_la==SEMI) { { - setState(535); + setState(537); _errHandler.sync(this); - _alt = 1; - do { - switch (_alt) { - case 1: + _alt = getInterpreter().adaptivePredict(_input,0,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { { { setState(533); @@ -653,16 +652,13 @@ public class PostgreSqlParser extends Parser { setState(534); stmt(); } - } - break; - default: - throw new NoViableAltException(this); + } } - setState(537); + setState(539); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,0,_ctx); - } while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ); - setState(539); + } + setState(540); match(SEMI); } } @@ -46413,8 +46409,8 @@ public class PostgreSqlParser extends Parser { "\u0101\u0002\u0102\u0007\u0102\u0002\u0103\u0007\u0103\u0002\u0104\u0007"+ "\u0104\u0002\u0105\u0007\u0105\u0002\u0106\u0007\u0106\u0002\u0107\u0007"+ "\u0107\u0002\u0108\u0007\u0108\u0002\u0109\u0007\u0109\u0001\u0000\u0001"+ - "\u0000\u0001\u0000\u0004\u0000\u0218\b\u0000\u000b\u0000\f\u0000\u0219"+ - "\u0001\u0000\u0001\u0000\u0003\u0000\u021e\b\u0000\u0001\u0000\u0001\u0000"+ + "\u0000\u0001\u0000\u0005\u0000\u0218\b\u0000\n\u0000\f\u0000\u021b\t\u0000"+ + "\u0001\u0000\u0003\u0000\u021e\b\u0000\u0001\u0000\u0001\u0000\u0001\u0001"+ "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ @@ -46423,49 +46419,49 @@ public class PostgreSqlParser extends Parser { "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ - "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0001\u0256\b\u0001"+ - "\u0001\u0002\u0001\u0002\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ + "\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0001\u0256\b\u0001\u0001\u0002"+ + "\u0001\u0002\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ - "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ - "\u0003\u0003\u0282\b\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+ + "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0003\u0003"+ + "\u0282\b\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+ "\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+ "\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+ "\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+ "\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+ - "\u0001\u0004\u0001\u0004\u0003\u0004\u02a2\b\u0004\u0001\u0005\u0001\u0005"+ + "\u0001\u0004\u0003\u0004\u02a2\b\u0004\u0001\u0005\u0001\u0005\u0001\u0005"+ "\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005"+ "\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005"+ "\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005"+ "\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005"+ - "\u0001\u0005\u0003\u0005\u02bf\b\u0005\u0001\u0006\u0001\u0006\u0001\u0006"+ + "\u0003\u0005\u02bf\b\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006"+ "\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006"+ "\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006"+ - "\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006"+ - "\u0003\u0006\u02d6\b\u0006\u0001\u0007\u0001\u0007\u0001\b\u0001\b\u0001"+ - "\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0003\t\u02e4"+ - "\b\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+ - "\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0003\t\u02f4\b\t\u0001\t\u0001"+ - "\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0003\t\u02fd\b\t\u0001\t\u0001"+ - "\t\u0003\t\u0301\b\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+ + "\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0003\u0006"+ + "\u02d6\b\u0006\u0001\u0007\u0001\u0007\u0001\b\u0001\b\u0001\t\u0001\t"+ + "\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0003\t\u02e4\b\t\u0001"+ + "\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+ + "\t\u0001\t\u0001\t\u0001\t\u0001\t\u0003\t\u02f4\b\t\u0001\t\u0001\t\u0001"+ + "\t\u0001\t\u0001\t\u0001\t\u0001\t\u0003\t\u02fd\b\t\u0001\t\u0001\t\u0003"+ + "\t\u0301\b\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+ "\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+ "\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+ "\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+ - "\t\u0001\t\u0001\t\u0001\t\u0003\t\u0328\b\t\u0001\n\u0001\n\u0001\n\u0001"+ - "\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0003"+ - "\n\u0336\b\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001"+ - "\n\u0001\n\u0003\n\u0341\b\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001"+ - "\n\u0001\n\u0001\n\u0003\n\u034b\b\n\u0001\u000b\u0001\u000b\u0001\u000b"+ - "\u0001\u000b\u0001\u000b\u0001\u000b\u0003\u000b\u0353\b\u000b\u0001\u000b"+ - "\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b"+ - "\u0003\u000b\u035c\b\u000b\u0001\f\u0001\f\u0001\r\u0001\r\u0003\r\u0362"+ - "\b\r\u0001\r\u0001\r\u0001\r\u0001\r\u0003\r\u0368\b\r\u0001\r\u0003\r"+ - "\u036b\b\r\u0001\r\u0001\r\u0003\r\u036f\b\r\u0001\r\u0001\r\u0003\r\u0373"+ - "\b\r\u0001\r\u0001\r\u0003\r\u0377\b\r\u0001\r\u0001\r\u0003\r\u037b\b"+ - "\r\u0001\r\u0001\r\u0001\r\u0003\r\u0380\b\r\u0001\r\u0001\r\u0001\r\u0001"+ + "\t\u0001\t\u0001\t\u0003\t\u0328\b\t\u0001\n\u0001\n\u0001\n\u0001\n\u0001"+ + "\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0003\n\u0336"+ + "\b\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001"+ + "\n\u0003\n\u0341\b\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001"+ + "\n\u0001\n\u0003\n\u034b\b\n\u0001\u000b\u0001\u000b\u0001\u000b\u0001"+ + "\u000b\u0001\u000b\u0001\u000b\u0003\u000b\u0353\b\u000b\u0001\u000b\u0001"+ + "\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0003"+ + "\u000b\u035c\b\u000b\u0001\f\u0001\f\u0001\r\u0001\r\u0003\r\u0362\b\r"+ + "\u0001\r\u0001\r\u0001\r\u0001\r\u0003\r\u0368\b\r\u0001\r\u0003\r\u036b"+ + "\b\r\u0001\r\u0001\r\u0003\r\u036f\b\r\u0001\r\u0001\r\u0003\r\u0373\b"+ + "\r\u0001\r\u0001\r\u0003\r\u0377\b\r\u0001\r\u0001\r\u0003\r\u037b\b\r"+ + "\u0001\r\u0001\r\u0001\r\u0003\r\u0380\b\r\u0001\r\u0001\r\u0001\r\u0001"+ "\r\u0003\r\u0386\b\r\u0001\r\u0001\r\u0003\r\u038a\b\r\u0001\r\u0001\r"+ "\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0003\r\u0393\b\r\u0001\r\u0001"+ "\r\u0001\r\u0001\r\u0001\r\u0001\r\u0003\r\u039b\b\r\u0001\r\u0001\r\u0001"+ @@ -47332,10 +47328,10 @@ public class PostgreSqlParser extends Parser { "\u0210\u160b\u0001\u0000\u0000\u0000\u0212\u160d\u0001\u0000\u0000\u0000"+ "\u0214\u021d\u0003\u0002\u0001\u0000\u0215\u0216\u0005\u0343\u0000\u0000"+ "\u0216\u0218\u0003\u0002\u0001\u0000\u0217\u0215\u0001\u0000\u0000\u0000"+ - "\u0218\u0219\u0001\u0000\u0000\u0000\u0219\u0217\u0001\u0000\u0000\u0000"+ - "\u0219\u021a\u0001\u0000\u0000\u0000\u021a\u021b\u0001\u0000\u0000\u0000"+ - "\u021b\u021c\u0005\u0343\u0000\u0000\u021c\u021e\u0001\u0000\u0000\u0000"+ - "\u021d\u0217\u0001\u0000\u0000\u0000\u021d\u021e\u0001\u0000\u0000\u0000"+ + "\u0218\u021b\u0001\u0000\u0000\u0000\u0219\u0217\u0001\u0000\u0000\u0000"+ + "\u0219\u021a\u0001\u0000\u0000\u0000\u021a\u021c\u0001\u0000\u0000\u0000"+ + "\u021b\u0219\u0001\u0000\u0000\u0000\u021c\u021e\u0005\u0343\u0000\u0000"+ + "\u021d\u0219\u0001\u0000\u0000\u0000\u021d\u021e\u0001\u0000\u0000\u0000"+ "\u021e\u021f\u0001\u0000\u0000\u0000\u021f\u0220\u0005\u0000\u0000\u0001"+ "\u0220\u0001\u0001\u0000\u0000\u0000\u0221\u0256\u0003\u0004\u0002\u0000"+ "\u0222\u0256\u0003\u0006\u0003\u0000\u0223\u0256\u0003`0\u0000\u0224\u0256"+ diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/PostgreSqlSemanticTokensTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/PostgreSqlSemanticTokensTest.java index efdf1aa8d..31896f107 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/PostgreSqlSemanticTokensTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/PostgreSqlSemanticTokensTest.java @@ -80,5 +80,25 @@ public class PostgreSqlSemanticTokensTest { assertThat(tokens.size()).isEqualTo(10); } + + @Test + void semiColonAtEnd() { + List 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(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])); // ) + assertThat(tokens.get(5)).isEqualTo(new SemanticTokenData(17, 21, "keyword", new String[0])); // from + assertThat(tokens.get(6)).isEqualTo(new SemanticTokenData(22, 30, "variable", new String[0])); // anecdote + assertThat(tokens.get(7)).isEqualTo(new SemanticTokenData(31, 36, "keyword", new String[0])); // where + assertThat(tokens.get(8)).isEqualTo(new SemanticTokenData(37, 48, "variable", new String[0])); // anecdote_id + assertThat(tokens.get(9)).isEqualTo(new SemanticTokenData(48, 49, "operator", new String[0])); // = + assertThat(tokens.get(10)).isEqualTo(new SemanticTokenData(49, 50, "operator", new String[0])); // : + assertThat(tokens.get(11)).isEqualTo(new SemanticTokenData(50, 58, "parameter", new String[0])); // anecdote + assertThat(tokens.get(12)).isEqualTo(new SemanticTokenData(59, 60, "operator", new String[0])); // ; + + assertThat(tokens.size()).isEqualTo(13); + } }