Input parameters for SPEL grammar
This commit is contained in:
@@ -12,16 +12,26 @@ package org.springframework.ide.vscode.boot.java.spel;
|
||||
|
||||
import static org.springframework.ide.vscode.parser.spel.SpelLexer.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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.antlr.v4.runtime.tree.ErrorNode;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData;
|
||||
@@ -32,15 +42,26 @@ import org.springframework.ide.vscode.parser.spel.SpelParser.BeanReferenceContex
|
||||
import org.springframework.ide.vscode.parser.spel.SpelParser.ConstructorReferenceContext;
|
||||
import org.springframework.ide.vscode.parser.spel.SpelParser.DottedNodeContext;
|
||||
import org.springframework.ide.vscode.parser.spel.SpelParser.FunctionOrVarContext;
|
||||
import org.springframework.ide.vscode.parser.spel.SpelParser.InputParameterContext;
|
||||
import org.springframework.ide.vscode.parser.spel.SpelParser.MethodOrPropertyContext;
|
||||
import org.springframework.ide.vscode.parser.spel.SpelParser.PossiblyQualifiedIdContext;
|
||||
import org.springframework.ide.vscode.parser.spel.SpelParserBaseListener;
|
||||
|
||||
public class SpelSemanticTokens implements SemanticTokensDataProvider {
|
||||
|
||||
private final Optional<Consumer<RecognitionException>> parseErrorHandler;
|
||||
|
||||
public SpelSemanticTokens(Optional<Consumer<RecognitionException>> parseErrorHandler) {
|
||||
this.parseErrorHandler = parseErrorHandler;
|
||||
}
|
||||
|
||||
public SpelSemanticTokens() {
|
||||
this(Optional.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTokenTypes() {
|
||||
return List.of("operator", "keyword", "type", "string", "number", "method", "property");
|
||||
return List.of("operator", "keyword", "type", "string", "number", "method", "property", "parameter");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,6 +75,8 @@ public class SpelSemanticTokens implements SemanticTokensDataProvider {
|
||||
lexer.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
parser.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
|
||||
List<SemanticTokenData> tokens = new ArrayList<>();
|
||||
|
||||
parser.addParseListener(new SpelParserBaseListener() {
|
||||
|
||||
private void processTerminalNode(TerminalNode node) {
|
||||
@@ -119,7 +142,6 @@ public class SpelSemanticTokens implements SemanticTokensDataProvider {
|
||||
case IDENTIFIER:
|
||||
semantics.put(node.getSymbol(), "variable");
|
||||
break;
|
||||
case NUMERIC_LITERAL:
|
||||
case INTEGER_LITERAL:
|
||||
case REAL_LITERAL:
|
||||
semantics.put(node.getSymbol(), "number");
|
||||
@@ -178,6 +200,17 @@ public class SpelSemanticTokens implements SemanticTokensDataProvider {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitInputParameter(InputParameterContext ctx) {
|
||||
semantics.remove(ctx.LSQUARE().getSymbol());
|
||||
semantics.remove(ctx.INTEGER_LITERAL().getSymbol());
|
||||
semantics.remove(ctx.RSQUARE().getSymbol());
|
||||
|
||||
int start = ctx.getStart().getStartIndex() + initialOffset;
|
||||
int end = start + ctx.getText().length();
|
||||
tokens.add(new SemanticTokenData(start, end, "parameter", new String[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTerminal(TerminalNode node) {
|
||||
processTerminalNode(node);
|
||||
@@ -190,13 +223,38 @@ public class SpelSemanticTokens implements SemanticTokensDataProvider {
|
||||
|
||||
});
|
||||
|
||||
parser.addErrorListener(new ANTLRErrorListener() {
|
||||
|
||||
@Override
|
||||
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
|
||||
String msg, RecognitionException e) {
|
||||
parseErrorHandler.ifPresent(h -> h.accept(e));
|
||||
}
|
||||
|
||||
@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.spelExpr();
|
||||
|
||||
List<SemanticTokenData> tokens = semantics.entrySet().stream()
|
||||
tokens.addAll(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());
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
Collections.sort(tokens);
|
||||
|
||||
|
||||
@@ -13,13 +13,15 @@ package org.springframework.ide.vscode.boot.java.spel;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData;
|
||||
|
||||
public class SpelSemanticTokensTest {
|
||||
|
||||
private SpelSemanticTokens provider = new SpelSemanticTokens();
|
||||
private SpelSemanticTokens provider = new SpelSemanticTokens(Optional.of(Assertions::fail));
|
||||
|
||||
@Test
|
||||
void simpleCompare() {
|
||||
@@ -124,5 +126,22 @@ public class SpelSemanticTokensTest {
|
||||
assertThat(tokens.get(7)).isEqualTo(new SemanticTokenData(37, 38, "operator", new String[0]));
|
||||
assertThat(tokens.get(8)).isEqualTo(new SemanticTokenData(38, 39, "operator", new String[0]));
|
||||
}
|
||||
|
||||
//https://github.com/spring-projects/sts4/issues/1320
|
||||
@Test
|
||||
void inputParameter() {
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("[1].size().longValue()", 0);
|
||||
assertThat(tokens.size()).isEqualTo(9);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 3, "parameter", new String[0])); // [1]
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(3, 4, "operator", new String[0])); // .
|
||||
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(4, 8, "method", new String[0])); // size
|
||||
assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(8, 9, "operator", new String[0])); // (
|
||||
assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(9, 10, "operator", new String[0])); // )
|
||||
assertThat(tokens.get(5)).isEqualTo(new SemanticTokenData(10, 11, "operator", new String[0])); // .
|
||||
assertThat(tokens.get(6)).isEqualTo(new SemanticTokenData(11, 20, "method", new String[0])); // longValue
|
||||
assertThat(tokens.get(7)).isEqualTo(new SemanticTokenData(20, 21, "operator", new String[0])); // (
|
||||
assertThat(tokens.get(8)).isEqualTo(new SemanticTokenData(21, 22, "operator", new String[0])); // )
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user