Embedded SQL syntax highlighting and syntax validation
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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]));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user