Embedded SQL syntax highlighting and syntax validation

This commit is contained in:
aboyko
2024-05-16 18:12:46 -04:00
parent 212dacff69
commit fe953bde5b
21 changed files with 102990 additions and 25 deletions

View File

@@ -7,4 +7,8 @@
/src/main/java/org/springframework/ide/vscode/parser/hql/Hql.tokens
/src/main/java/org/springframework/ide/vscode/parser/hql/HqlLexer.interp
/src/main/java/org/springframework/ide/vscode/parser/hql/HqlLexer.tokens
/src/main/java/org/springframework/ide/vscode/parser/sql/MySqlParser.interp
/src/main/java/org/springframework/ide/vscode/parser/sql/MySqlParser.tokens
/src/main/java/org/springframework/ide/vscode/parser/sql/MySqlLexer.interp
/src/main/java/org/springframework/ide/vscode/parser/sql/MySqlLexer.tokens
/target

View File

@@ -7,5 +7,6 @@ fi
workdir=$(pwd)
cd grammars
java -jar ${workdir}/antlr-${ANTLR_VERSION}.jar Jpql.g4 -o ${workdir}/src/main/java/org/springframework/ide/vscode/parser/jpql -package org.springframework.ide.vscode.parser.jpql
java -jar ${workdir}/antlr-${ANTLR_VERSION}.jar Hql.g4 -o ${workdir}/src/main/java/org/springframework/ide/vscode//parser/hql -package org.springframework.ide.vscode.parser.hql
java -jar ${workdir}/antlr-${ANTLR_VERSION}.jar Hql.g4 -o ${workdir}/src/main/java/org/springframework/ide/vscode/parser/hql -package org.springframework.ide.vscode.parser.hql
java -jar ${workdir}/antlr-${ANTLR_VERSION}.jar MySqlLexer.g4 MySqlParser.g4 -o ${workdir}/src/main/java/org/springframework/ide/vscode/parser/sql -package org.springframework.ide.vscode.parser.sql

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -25,8 +25,10 @@ import org.springframework.context.ApplicationContext;
import org.springframework.ide.vscode.boot.factories.SpringFactoriesLanguageServerComponents;
import org.springframework.ide.vscode.boot.index.cache.IndexCache;
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.HqlReconciler;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.HqlSemanticTokens;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.JpaQueryPropertiesLanguageServerComponents;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.JpqlReconciler;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.JpqlSemanticTokens;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.JpqlSupportState;
import org.springframework.ide.vscode.boot.java.links.JavaElementLocationProvider;
@@ -128,7 +130,7 @@ public class BootLanguageServerInitializer implements InitializingBean {
new SpringFactoriesLanguageServerComponents(projectFinder, springIndexer, config),
new PomLanguageServerComponents(server, projectFinder, params.projectObserver, appContext.getBean(SpringProjectsProvider.class)),
new JpaQueryPropertiesLanguageServerComponents(server.getTextDocumentService(), projectFinder, appContext.getBean(JpqlSemanticTokens.class),
appContext.getBean(HqlSemanticTokens.class), appContext.getBean(JpqlSupportState.class))
appContext.getBean(HqlSemanticTokens.class), appContext.getBean(JpqlSupportState.class), appContext.getBean(HqlReconciler.class), appContext.getBean(JpqlReconciler.class))
);
for (LanguageServerComponents c : componentsList) {

View File

@@ -12,11 +12,15 @@ package org.springframework.ide.vscode.boot.app;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.HqlReconciler;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.HqlSemanticTokens;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.JdtDataQuerySemanticTokensProvider;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.JpqlReconciler;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.JpqlSemanticTokens;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.JpqlSupportState;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.QueryJdtAstReconciler;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.SqlReconciler;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.SqlSemanticTokens;
import org.springframework.ide.vscode.boot.java.reconcilers.AddConfigurationIfBeansPresentReconciler;
import org.springframework.ide.vscode.boot.java.reconcilers.AnnotationNodeReconciler;
import org.springframework.ide.vscode.boot.java.reconcilers.AuthorizeHttpRequestsReconciler;
@@ -117,12 +121,12 @@ public class JdtConfig {
return new JavaSemanticTokensProvider();
}
@Bean JdtDataQuerySemanticTokensProvider jpqlJdtSemanticTokensProvider(JpqlSemanticTokens jpqlProvider, HqlSemanticTokens hqlProvider, JpqlSupportState supportState) {
return new JdtDataQuerySemanticTokensProvider(jpqlProvider, hqlProvider, supportState);
@Bean JdtDataQuerySemanticTokensProvider jpqlJdtSemanticTokensProvider(JpqlSemanticTokens jpqlProvider, HqlSemanticTokens hqlProvider, SqlSemanticTokens sqlSemanticTokens, JpqlSupportState supportState) {
return new JdtDataQuerySemanticTokensProvider(jpqlProvider, hqlProvider, sqlSemanticTokens, supportState);
}
@Bean QueryJdtAstReconciler dataQueryReconciler() {
return new QueryJdtAstReconciler();
@Bean QueryJdtAstReconciler dataQueryReconciler(HqlReconciler hqlReconciler, JpqlReconciler jpqlReconciler, SqlReconciler sqlReconciler) {
return new QueryJdtAstReconciler(hqlReconciler, jpqlReconciler, sqlReconciler);
}
}

View File

@@ -12,9 +12,13 @@ package org.springframework.ide.vscode.boot.app;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.HqlReconciler;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.HqlSemanticTokens;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.JpqlReconciler;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.JpqlSemanticTokens;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.JpqlSupportState;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.SqlReconciler;
import org.springframework.ide.vscode.boot.java.data.jpa.queries.SqlSemanticTokens;
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
@@ -30,6 +34,26 @@ public class SpringDataConfig {
HqlSemanticTokens hqlSemanticTokens() {
return new HqlSemanticTokens();
}
@Bean
SqlSemanticTokens sqlSemanticTokens() {
return new SqlSemanticTokens();
}
@Bean
HqlReconciler hqlReconciler() {
return new HqlReconciler();
}
@Bean
JpqlReconciler jpqlReconciler() {
return new JpqlReconciler();
}
@Bean
SqlReconciler sqlReconciler() {
return new SqlReconciler();
}
@Bean
JpqlSupportState jpqlSupportState(SimpleLanguageServer server, ProjectObserver projectObserver, BootJavaConfig config) {

View File

@@ -50,7 +50,7 @@ public class HqlReconciler implements Reconciler {
offset = token.getStartIndex() - token.getCharPositionInLine();
length = token.getCharPositionInLine() + 1;
}
problemCollector.accept(new ReconcileProblemImpl(QueryProblemType.EXPRESSION_SYNTAX, msg, startPosition + offset, length));
problemCollector.accept(new ReconcileProblemImpl(QueryProblemType.EXPRESSION_SYNTAX, "HQL: " + msg, startPosition + offset, length));
}
@Override

View File

@@ -40,11 +40,13 @@ public class JdtDataQuerySemanticTokensProvider implements JdtSemanticTokensProv
private final JpqlSemanticTokens jpqlProvider;
private final HqlSemanticTokens hqlProvider;
private final SqlSemanticTokens sqlProvider;
private final JpqlSupportState supportState;
public JdtDataQuerySemanticTokensProvider(JpqlSemanticTokens jpqlProvider, HqlSemanticTokens hqlProvider, JpqlSupportState supportState) {
public JdtDataQuerySemanticTokensProvider(JpqlSemanticTokens jpqlProvider, HqlSemanticTokens hqlProvider, SqlSemanticTokens sqlSemanticTokens, JpqlSupportState supportState) {
this.jpqlProvider = jpqlProvider;
this.hqlProvider = hqlProvider;
this.sqlProvider = sqlSemanticTokens;
this.supportState = supportState;
}
@@ -94,7 +96,7 @@ public class JdtDataQuerySemanticTokensProvider implements JdtSemanticTokensProv
if (queryExpression != null) {
if (isNative) {
//TODO: SQL semantic tokens
computeTokensForQueryExpression(sqlProvider, queryExpression).forEach(tokensData::accept);
} else {
computeTokensForQueryExpression(provider, queryExpression).forEach(tokensData::accept);
}

View File

@@ -26,9 +26,10 @@ public class JpaQueryPropertiesLanguageServerComponents implements LanguageServe
private final NamedQueryPropertiesReconcileEngine reconcileEngine;
public JpaQueryPropertiesLanguageServerComponents(SimpleTextDocumentService documents, JavaProjectFinder projectsFinder,
JpqlSemanticTokens jpqlSemanticTokensProvider, HqlSemanticTokens hqlSematicTokensProvider, JpqlSupportState supportState) {
JpqlSemanticTokens jpqlSemanticTokensProvider, HqlSemanticTokens hqlSematicTokensProvider, JpqlSupportState supportState,
HqlReconciler hqlReconciler, JpqlReconciler jpqlReconciler) {
this.semanticTokensHandler = new QueryPropertiesSemanticTokensHandler(projectsFinder, jpqlSemanticTokensProvider, hqlSematicTokensProvider, supportState);
this.reconcileEngine = new NamedQueryPropertiesReconcileEngine(projectsFinder);
this.reconcileEngine = new NamedQueryPropertiesReconcileEngine(projectsFinder, hqlReconciler, jpqlReconciler);
}
@Override

View File

@@ -50,7 +50,7 @@ public class JpqlReconciler implements Reconciler {
offset = token.getStartIndex() - token.getCharPositionInLine();
length = token.getCharPositionInLine() + 1;
}
problemCollector.accept(new ReconcileProblemImpl(QueryProblemType.EXPRESSION_SYNTAX, msg, startPosition + offset, length));
problemCollector.accept(new ReconcileProblemImpl(QueryProblemType.EXPRESSION_SYNTAX, "JPQL: " + msg, startPosition + offset, length));
}
@Override

View File

@@ -25,16 +25,20 @@ import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.Value
public class NamedQueryPropertiesReconcileEngine implements IReconcileEngine {
private final JavaProjectFinder projectFinder;
private final HqlReconciler hqlReconciler;
private final JpqlReconciler jpqlReconciler;
public NamedQueryPropertiesReconcileEngine(JavaProjectFinder projectFinder) {
public NamedQueryPropertiesReconcileEngine(JavaProjectFinder projectFinder, HqlReconciler hqlReconciler, JpqlReconciler jpqlReconciler) {
this.projectFinder = projectFinder;
this.hqlReconciler = hqlReconciler;
this.jpqlReconciler = jpqlReconciler;
}
@Override
public void reconcile(IDocument doc, IProblemCollector problemCollector) {
try {
Reconciler reconciler = projectFinder.find(new TextDocumentIdentifier(doc.getUri()))
.map(p -> SpringProjectUtil.hasDependencyStartingWith(p, "spring-data-jpa", null) ? new HqlReconciler() : new JpqlReconciler())
.map(p -> SpringProjectUtil.hasDependencyStartingWith(p, "spring-data-jpa", null) ? hqlReconciler : jpqlReconciler)
.orElse(new JpqlReconciler());
AntlrParser parser = new AntlrParser();

View File

@@ -34,6 +34,18 @@ import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemC
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
public class QueryJdtAstReconciler implements JdtAstReconciler {
private final HqlReconciler hqlReconciler;
private final JpqlReconciler jpqlReconciler;
private final SqlReconciler sqlReconciler;
public QueryJdtAstReconciler(HqlReconciler hqlReconciler, JpqlReconciler jpqlReconciler,
SqlReconciler sqlReconciler) {
this.hqlReconciler = hqlReconciler;
this.jpqlReconciler = jpqlReconciler;
this.sqlReconciler = sqlReconciler;
}
@Override
public ASTVisitor createVisitor(IJavaProject project, URI docURI, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
@@ -75,7 +87,7 @@ public class QueryJdtAstReconciler implements JdtAstReconciler {
if (queryExpression != null) {
if (isNative) {
//TODO: SQL syntax validation
reconcileExpression(sqlReconciler, queryExpression, problemCollector);
} else {
reconcileExpression(getQueryReconciler(project), queryExpression, problemCollector);
}
@@ -113,8 +125,8 @@ public class QueryJdtAstReconciler implements JdtAstReconciler {
/*
* Gets either HQL or JPQL reconciler
*/
private static Reconciler getQueryReconciler(IJavaProject project) {
return SpringProjectUtil.hasDependencyStartingWith(project, "hibernate-core", null) ? new HqlReconciler() : new JpqlReconciler();
private Reconciler getQueryReconciler(IJavaProject project) {
return SpringProjectUtil.hasDependencyStartingWith(project, "hibernate-core", null) ? hqlReconciler : jpqlReconciler;
}
private void reconcileExpression(Reconciler reconciler, Expression valueExp, IProblemCollector problemCollector) {

View File

@@ -0,0 +1,76 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.data.jpa.queries;
import java.util.BitSet;
import org.antlr.v4.runtime.ANTLRErrorListener;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ConsoleErrorListener;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.atn.ATNConfigSet;
import org.antlr.v4.runtime.dfa.DFA;
import org.springframework.ide.vscode.boot.java.handlers.Reconciler;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
import org.springframework.ide.vscode.parser.sql.MySqlLexer;
import org.springframework.ide.vscode.parser.sql.MySqlParser;
public class SqlReconciler implements Reconciler {
@Override
public void reconcile(String text, int startPosition, IProblemCollector problemCollector) {
MySqlLexer lexer = new MySqlLexer(CharStreams.fromString(text));
CommonTokenStream antlrTokens = new CommonTokenStream(lexer);
MySqlParser parser = new MySqlParser(antlrTokens);
parser.removeErrorListener(ConsoleErrorListener.INSTANCE);
parser.addErrorListener(new ANTLRErrorListener() {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
String msg, RecognitionException e) {
Token token = (Token) offendingSymbol;
int offset = token.getStartIndex();
int length = token.getStopIndex() - token.getStartIndex() + 1;
if (token.getStartIndex() >= token.getStopIndex()) {
offset = token.getStartIndex() - token.getCharPositionInLine();
length = token.getCharPositionInLine() + 1;
}
problemCollector.accept(new ReconcileProblemImpl(QueryProblemType.EXPRESSION_SYNTAX, "SQL: " + msg, startPosition + offset, length));
}
@Override
public void reportContextSensitivity(Parser recognizer, DFA dfa, int startIndex, int stopIndex, int prediction,
ATNConfigSet configs) {
}
@Override
public void reportAttemptingFullContext(Parser recognizer, DFA dfa, int startIndex, int stopIndex,
BitSet conflictingAlts, ATNConfigSet configs) {
}
@Override
public void reportAmbiguity(Parser recognizer, DFA dfa, int startIndex, int stopIndex, boolean exact,
BitSet ambigAlts, ATNConfigSet configs) {
}
});
parser.sqlStatements();
}
}

View File

@@ -0,0 +1,179 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.data.jpa.queries;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ConsoleErrorListener;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData;
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokensDataProvider;
import org.springframework.ide.vscode.parser.sql.MySqlLexer;
import org.springframework.ide.vscode.parser.sql.MySqlParser;
import org.springframework.ide.vscode.parser.sql.MySqlParserBaseListener;
public class SqlSemanticTokens implements SemanticTokensDataProvider {
private static List<String> TOKEN_TYPES = List.of("keyword", "type", "string", "number", "operator",
"variable", "regexp", "comment");
@Override
public List<String> getTokenTypes() {
return TOKEN_TYPES;
}
@Override
public List<SemanticTokenData> computeTokens(String text, int initialOffset) {
MySqlLexer lexer = new MySqlLexer(CharStreams.fromString(text));
CommonTokenStream antlrTokens = new CommonTokenStream(lexer);
MySqlParser parser = new MySqlParser(antlrTokens);
Map<Token, String> semantics = new HashMap<>();
parser.removeErrorListener(ConsoleErrorListener.INSTANCE);
parser.addParseListener(new MySqlParserBaseListener() {
private void processTerminalNode(TerminalNode node) {
int type = node.getSymbol().getType();
switch (type) {
case MySqlParser.SPEL:
semantics.put(node.getSymbol(), "regexp");
break;
case MySqlParser.ID:
semantics.put(node.getSymbol(), "variable");
break;
case MySqlParser.DOT_ID:
semantics.put(node.getSymbol(), "variable");
break;
case MySqlParser.DOT:
semantics.put(node.getSymbol(), "operator");
break;
case MySqlParser.NULL_LITERAL:
semantics.put(node.getSymbol(), "number");
break;
case MySqlParser.FILESIZE_LITERAL:
semantics.put(node.getSymbol(), "number");
break;
case MySqlParser.ZERO_DECIMAL:
case MySqlParser.ONE_DECIMAL:
case MySqlParser.TWO_DECIMAL:
semantics.put(node.getSymbol(), "number");
break;
case MySqlParser.START_NATIONAL_STRING_LITERAL:
case MySqlParser.STRING_LITERAL:
semantics.put(node.getSymbol(), "string");
break;
case MySqlParser.STRING_CHARSET_NAME:
semantics.put(node.getSymbol(), "type");
break;
case MySqlParser.HOST_IP_ADDRESS:
case MySqlParser.LOCAL_ID:
case MySqlParser.GLOBAL_ID:
semantics.put(node.getSymbol(), "string");
break;
case MySqlParser.SPEC_MYSQL_COMMENT:
case MySqlParser.COMMENT_INPUT:
case MySqlParser.LINE_COMMENT:
semantics.put(node.getSymbol(), "comment");
break;
default:
if (MySqlParser.VAR_ASSIGN <= type && type <= MySqlParser.COLON_SYMB) {
semantics.put(node.getSymbol(), "operator");
} else if (MySqlParser.DECIMAL_LITERAL <= type && type <= MySqlParser.BIT_STRING) {
semantics.put(node.getSymbol(), "number");
} else if (MySqlParser.ABS <= type && type <= MySqlParser.X_FUNCTION) {
// Common function names
semantics.put(node.getSymbol(), "keyword");
} else if (MySqlParser.ADD <= type && type <= MySqlParser.ZEROFILL) {
// Keywords
// Common Keywords
semantics.put(node.getSymbol(), "keyword");
} else if (MySqlParser.TINYINT <= type && type <= MySqlParser.SERIAL) {
// DATA TYPE Keywords
semantics.put(node.getSymbol(), "type");
} else if (MySqlParser.YEAR_MONTH <= type && type <= MySqlParser.DAY_MICROSECOND) {
// Interval type Keywords
semantics.put(node.getSymbol(), "type");
} else if (MySqlParser.JSON_ARRAY <= type && type <= MySqlParser.PATH) {
// JSON keywords
semantics.put(node.getSymbol(), "keyword");
} else if (MySqlParser.JSON_ARRAY <= type && type <= MySqlParser.PATH) {
// Group function Keywords
semantics.put(node.getSymbol(), "keyword");
} else if (MySqlParser.CURRENT_DATE <= type && type <= MySqlParser.UTC_TIMESTAMP) {
// Common function Keywords
semantics.put(node.getSymbol(), "keyword");
} else if (MySqlParser.ACCOUNT <= type && type <= MySqlParser.YES) {
// Keywords, but can be ID
// Common Keywords, but can be ID
semantics.put(node.getSymbol(), "type");
} else if (MySqlParser.EUR <= type && type <= MySqlParser.INTERNAL) {
// Date format Keywords
semantics.put(node.getSymbol(), "type");
} else if (MySqlParser.QUARTER <= type && type <= MySqlParser.MICROSECOND) {
// Date format Keywords
semantics.put(node.getSymbol(), "type");
} else if (MySqlParser.ADMIN <= type && type <= MySqlParser.XA_RECOVER_ADMIN) {
// PRIVILEGES
semantics.put(node.getSymbol(), "type");
} else if (MySqlParser.ARMSCII8 <= type && type <= MySqlParser.UTF8MB4) {
// Charsets
semantics.put(node.getSymbol(), "type");
} else if (MySqlParser.ARCHIVE <= type && type <= MySqlParser.TOKUDB) {
// DB Engines
semantics.put(node.getSymbol(), "type");
} else if (MySqlParser.REPEATABLE <= type && type <= MySqlParser.SERIALIZABLE) {
// Transaction Levels
semantics.put(node.getSymbol(), "type");
} else if (MySqlParser.GEOMETRYCOLLECTION <= type && type <= MySqlParser.POLYGON) {
// Spatial data types
semantics.put(node.getSymbol(), "type");
}
}
}
@Override
public void visitTerminal(TerminalNode node) {
processTerminalNode(node);
}
@Override
public void visitErrorNode(ErrorNode node) {
processTerminalNode(node);
}
});
parser.sqlStatements();
List<SemanticTokenData> tokens = semantics.entrySet().stream()
.map(e -> new SemanticTokenData(e.getKey().getStartIndex() + initialOffset,
e.getKey().getStartIndex() + e.getKey().getText().length() + initialOffset, e.getValue(),
new String[0]))
.collect(Collectors.toList());
Collections.sort(tokens);
return tokens;
}
}

View File

@@ -300,7 +300,7 @@ public class JdtDataQuerySemanticTokensProviderTest {
public interface OwnerRepository {
@Query(value = "SELECT DISTINCT owner FROM Owner owner", nativeQuery = true)
@Query(value = "SELECT * FROM USERS u WHERE u.status = 1", nativeQuery = true)
void findByLastName();
}
""";
@@ -312,7 +312,45 @@ public class JdtDataQuerySemanticTokensProviderTest {
List<SemanticTokenData> tokens = computeTokens(cu);
assertThat(tokens.size()).isZero();
SemanticTokenData token = tokens.get(0);
assertThat(source.substring(token.start(), token.end())).isEqualTo("SELECT");
assertThat(token).isEqualTo(new SemanticTokenData(128, 134, "keyword", new String[0]));
token = tokens.get(1);
assertThat(source.substring(token.start(), token.end())).isEqualTo("*");
assertThat(token).isEqualTo(new SemanticTokenData(135, 136, "operator", new String[0]));
token = tokens.get(2);
assertThat(source.substring(token.start(), token.end())).isEqualTo("FROM");
assertThat(token).isEqualTo(new SemanticTokenData(137, 141, "keyword", new String[0]));
token = tokens.get(3);
assertThat(source.substring(token.start(), token.end())).isEqualTo("USERS");
assertThat(token).isEqualTo(new SemanticTokenData(142, 147, "variable", new String[0]));
token = tokens.get(4);
assertThat(source.substring(token.start(), token.end())).isEqualTo("u");
assertThat(token).isEqualTo(new SemanticTokenData(148, 149, "variable", new String[0]));
token = tokens.get(5);
assertThat(source.substring(token.start(), token.end())).isEqualTo("WHERE");
assertThat(token).isEqualTo(new SemanticTokenData(150, 155, "keyword", new String[0]));
token = tokens.get(6);
assertThat(source.substring(token.start(), token.end())).isEqualTo("u");
assertThat(token).isEqualTo(new SemanticTokenData(156, 157, "variable", new String[0]));
token = tokens.get(7);
assertThat(source.substring(token.start(), token.end())).isEqualTo(".status");
assertThat(token).isEqualTo(new SemanticTokenData(157, 164, "variable", new String[0]));
token = tokens.get(8);
assertThat(source.substring(token.start(), token.end())).isEqualTo("=");
assertThat(token).isEqualTo(new SemanticTokenData(165, 166, "operator", new String[0]));
token = tokens.get(9);
assertThat(source.substring(token.start(), token.end())).isEqualTo("1");
assertThat(token).isEqualTo(new SemanticTokenData(167, 168, "number", new String[0]));
}

View File

@@ -71,7 +71,7 @@ public class QueryReconcilerTest {
String docUri = directory.toPath().resolve("src/main/resources/jpa-named-queries.properties").toUri()
.toString();
Editor editor = harness.newEditor(LanguageId.JPA_QUERY_PROPERTIES, source, docUri);
editor.assertProblems("SELECTX|mismatched input 'SELECTX'");
editor.assertProblems("SELECTX|HQL: mismatched input 'SELECTX'");
}
@Test
@@ -99,7 +99,7 @@ public class QueryReconcilerTest {
String docUri = directory.toPath().resolve("src/main/resources/jpa-named-queries.properties").toUri()
.toString();
Editor editor = harness.newEditor(LanguageId.JPA_QUERY_PROPERTIES, source, docUri);
editor.assertProblems("WHERE|no viable alternative");
editor.assertProblems("WHERE|JPQL: no viable alternative");
}
@Test
@@ -141,7 +141,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("SELECTX|mismatched input 'SELECTX'");
editor.assertProblems("SELECTX|HQL: mismatched input 'SELECTX'");
}
@Test
@@ -164,7 +164,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("SELECTX|mismatched input 'SELECTX'");
editor.assertProblems("SELECTX|HQL: mismatched input 'SELECTX'");
}
@Test
@@ -185,7 +185,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("SELECTX|mismatched input 'SELECTX'");
editor.assertProblems("SELECTX|HQL: mismatched input 'SELECTX'");
}
@Test
@@ -206,7 +206,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();
editor.assertProblems("SELECTX|SQL: mismatched input 'SELECTX' expecting {'ALTER',");
}
@Test