SPEL syntax highlighting and validation
This commit is contained in:
@@ -23,8 +23,6 @@ public class Constants {
|
||||
|
||||
public static final String PREF_SCAN_JAVA_TEST_SOURCES = "boot-java.scan-java-test-sources";
|
||||
|
||||
public static final String PREF_VALIDATION_SPEL_EXPRESSIONS = "boot-java.validation.spel.on";
|
||||
|
||||
public static final String PREF_SUPPORT_SPRING_XML_CONFIGS = "boot-java.support-spring-xml-config.on";
|
||||
public static final String PREF_XML_CONFIGS_SCAN_FOLDERS = "boot-java.support-spring-xml-config.scan-folders-globs";
|
||||
public static final String PREF_XML_CONFIGS_HYPERLINKS = "boot-java.support-spring-xml-config.hyperlinks";
|
||||
|
||||
@@ -183,7 +183,6 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
|
||||
Map<String, Object> bootChangeDetection = new HashMap<>();
|
||||
Map<String, Object> scanTestJavaSources = new HashMap<>();
|
||||
Map<String, Object> validation = new HashMap<>();
|
||||
Map<String, Object> validationSpelExpressions = new HashMap<>();
|
||||
Map<String, Object> javaValidation = new HashMap<>();
|
||||
|
||||
IPreferenceStore preferenceStore = BootLanguageServerPlugin.getDefault().getPreferenceStore();
|
||||
@@ -202,8 +201,6 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
|
||||
scanTestJavaSources.put("on", preferenceStore.getBoolean(Constants.PREF_SCAN_JAVA_TEST_SOURCES));
|
||||
|
||||
javaValidation.put("reconcilers", preferenceStore.getBoolean(Constants.PREF_JAVA_RECONCILE));
|
||||
validationSpelExpressions.put("on", preferenceStore.getBoolean(Constants.PREF_VALIDATION_SPEL_EXPRESSIONS));
|
||||
validation.put("spel", validationSpelExpressions);
|
||||
validation.put("java", javaValidation);
|
||||
|
||||
bootJavaObj.put("jpql", preferenceStore.getBoolean(Constants.PREF_JPQL));
|
||||
|
||||
@@ -41,7 +41,6 @@ public class PrefsInitializer extends AbstractPreferenceInitializer {
|
||||
preferenceStore.setDefault(Constants.PREF_XML_CONFIGS_SCAN_FOLDERS, "src/main");
|
||||
|
||||
preferenceStore.setDefault(Constants.PREF_CHANGE_DETECTION, false);
|
||||
preferenceStore.setDefault(Constants.PREF_VALIDATION_SPEL_EXPRESSIONS, true);
|
||||
|
||||
preferenceStore.setDefault(Constants.PREF_SCAN_JAVA_TEST_SOURCES, false);
|
||||
|
||||
|
||||
4
headless-services/commons/jpql/.gitignore
vendored
4
headless-services/commons/jpql/.gitignore
vendored
@@ -11,4 +11,8 @@
|
||||
/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
|
||||
/src/main/java/org/springframework/ide/vscode/parser/spel/SpelParser.interp
|
||||
/src/main/java/org/springframework/ide/vscode/parser/spel/SpelParser.tokens
|
||||
/src/main/java/org/springframework/ide/vscode/parser/spel/SpelLexer.interp
|
||||
/src/main/java/org/springframework/ide/vscode/parser/spel/SpelLexer.tokens
|
||||
/target
|
||||
|
||||
@@ -9,4 +9,5 @@ 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 MySqlLexer.g4 MySqlParser.g4 -o ${workdir}/src/main/java/org/springframework/ide/vscode/parser/sql -package org.springframework.ide.vscode.parser.sql
|
||||
java -jar ${workdir}/antlr-${ANTLR_VERSION}.jar SpelLexer.g4 SpelParser.g4 -o ${workdir}/src/main/java/org/springframework/ide/vscode/parser/spel -package org.springframework.ide.vscode.parser.spel
|
||||
|
||||
|
||||
@@ -38,8 +38,6 @@ channels {
|
||||
ERRORCHANNEL
|
||||
}
|
||||
|
||||
SPEL : ('#')('{')(.)*?('}') ;
|
||||
|
||||
// SKIP
|
||||
|
||||
SPACE : [ \t\r\n]+ -> channel(HIDDEN);
|
||||
@@ -1251,6 +1249,8 @@ DOUBLE_QUOTE_SYMB : '"';
|
||||
REVERSE_QUOTE_SYMB : '`';
|
||||
COLON_SYMB : ':';
|
||||
|
||||
QUESTION_SYMB : '?';
|
||||
|
||||
fragment QUOTE_SYMB: SINGLE_QUOTE_SYMB | DOUBLE_QUOTE_SYMB | REVERSE_QUOTE_SYMB;
|
||||
|
||||
// Charsets
|
||||
@@ -1293,6 +1293,8 @@ HOST_IP_ADDRESS : (AT_SIGN IP_ADDRESS);
|
||||
LOCAL_ID : AT_SIGN ( STRING_LITERAL | [A-Z0-9._$\u0080-\uFFFF]+);
|
||||
GLOBAL_ID : AT_SIGN AT_SIGN ( [A-Z0-9._$\u0080-\uFFFF]+ | BQUOTA_STRING);
|
||||
|
||||
SPEL : ('#')('{')(.)*?('}') ;
|
||||
|
||||
// Fragments for Literal primitives
|
||||
|
||||
fragment CHARSET_NAME:
|
||||
|
||||
@@ -2544,7 +2544,8 @@ predicate
|
||||
|
||||
// Add in ASTVisitor nullNotnull in constant
|
||||
expressionAtom
|
||||
: constant # constantExpressionAtom
|
||||
: (QUESTION_SYMB | COLON_SYMB) SPEL # spelExpressionAtom
|
||||
| constant # constantExpressionAtom
|
||||
| fullColumnName # fullColumnNameExpressionAtom
|
||||
| functionCall # functionCallExpressionAtom
|
||||
| expressionAtom COLLATE collationName # collateExpressionAtom
|
||||
@@ -2552,7 +2553,6 @@ expressionAtom
|
||||
| unaryOperator expressionAtom # unaryExpressionAtom
|
||||
| BINARY expressionAtom # binaryExpressionAtom
|
||||
| LOCAL_ID VAR_ASSIGN expressionAtom # variableAssignExpressionAtom
|
||||
| SPEL # spelExpressionAtom
|
||||
| '(' expression (',' expression)* ')' # nestedExpressionAtom
|
||||
| ROW '(' expression (',' expression)+ ')' # nestedRowExpressionAtom
|
||||
| EXISTS '(' selectStatement ')' # existsExpressionAtom
|
||||
|
||||
193
headless-services/commons/jpql/grammars/SpelLexer.g4
Normal file
193
headless-services/commons/jpql/grammars/SpelLexer.g4
Normal file
@@ -0,0 +1,193 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
*******************************************************************************/
|
||||
|
||||
lexer grammar SpelLexer;
|
||||
|
||||
@header {
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
*******************************************************************************/
|
||||
}
|
||||
|
||||
@members {
|
||||
int nesting = 0;
|
||||
}
|
||||
|
||||
SEMICOLON: ';';
|
||||
|
||||
fragment NEWLINE
|
||||
: '\r\n'
|
||||
| [\r\n\u2028\u2029]
|
||||
;
|
||||
|
||||
WS
|
||||
: [ \t\r\n]+ -> channel(HIDDEN)
|
||||
;
|
||||
|
||||
// ========================== S P E L ====================================================
|
||||
|
||||
INC: '++';
|
||||
PLUS: '+';
|
||||
DEC: '--';
|
||||
MINUS: '-';
|
||||
COLON: ':';
|
||||
DOT: '.';
|
||||
COMMA: ',';
|
||||
STAR: '*';
|
||||
DIV: '/';
|
||||
MOD: '%';
|
||||
LPAREN: '(';
|
||||
RPAREN: ')';
|
||||
LSQUARE: '[';
|
||||
RSQUARE: ']';
|
||||
HASH: '#';
|
||||
BEAN_REF: '@';
|
||||
SELECT_FIRST: '^[';
|
||||
POWER: '^';
|
||||
NE: '!=';
|
||||
PROJECT: '![';
|
||||
NOT: '!';
|
||||
EQ: '==';
|
||||
ASSIGN: '=';
|
||||
SYMBOLIC_AND: '&&';
|
||||
FACTORY_BEAN_REF: '&';
|
||||
SYMBOLIC_OR: '||';
|
||||
SELECT: '?[';
|
||||
ELVIS: '?:';
|
||||
SAFE_NAVI: '?.';
|
||||
QMARK: '?';
|
||||
SELECT_LAST: '$[';
|
||||
GE: '>=';
|
||||
GT: '>';
|
||||
LE: '<=';
|
||||
LT: '<';
|
||||
|
||||
// Special treatment to support template literals
|
||||
LCURLY: '{' { nesting++; } -> pushMode(DEFAULT_MODE);
|
||||
|
||||
RCURLY: '}' {
|
||||
if (nesting > 0) {
|
||||
nesting--;
|
||||
}
|
||||
} -> popMode;
|
||||
|
||||
BACKTICK
|
||||
: '`' -> pushMode(IN_TEMPLATE_STRING)
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
OR: 'or';
|
||||
AND: 'and';
|
||||
|
||||
TRUE: 'true';
|
||||
FALSE: 'false';
|
||||
NEW: 'new';
|
||||
NULL: 'null';
|
||||
T: 'T';
|
||||
MATCHES: 'matches';
|
||||
GT_KEYWORD: 'gt';
|
||||
GE_KEYWORD: 'ge';
|
||||
LE_KEYWORD: 'le';
|
||||
LT_KEYWORD: 'lt';
|
||||
EQ_KEYWORD: 'eq';
|
||||
NE_KEYWORD: 'ne';
|
||||
|
||||
// IDENTIFIER appearing AFTER tokens like OR and AND make those lex as special tokens,
|
||||
// like SpEL's lexIdentifier() does
|
||||
IDENTIFIER
|
||||
: (ALPHABETIC | '_') (ALPHABETIC | DIGIT | '_' | '$')*
|
||||
;
|
||||
|
||||
NUMERIC_LITERAL
|
||||
: REAL_LITERAL
|
||||
| INTEGER_LITERAL
|
||||
;
|
||||
|
||||
|
||||
REAL_LITERAL
|
||||
: '.' DECIMAL_DIGIT+ EXPONENT_PART? REAL_TYPE_SUFFIX?
|
||||
| DECIMAL_DIGIT+ '.' DECIMAL_DIGIT+ EXPONENT_PART? REAL_TYPE_SUFFIX?
|
||||
| DECIMAL_DIGIT+ EXPONENT_PART REAL_TYPE_SUFFIX?
|
||||
| DECIMAL_DIGIT+ REAL_TYPE_SUFFIX
|
||||
;
|
||||
|
||||
INTEGER_LITERAL
|
||||
: DECIMAL_DIGIT+ INTEGER_TYPE_SUFFIX?
|
||||
;
|
||||
|
||||
STRING_LITERAL
|
||||
: SINGLE_QUOTED_STRING
|
||||
| DOUBLE_QUOTED_STRING
|
||||
;
|
||||
|
||||
SINGLE_QUOTED_STRING
|
||||
: '\'' ( '\'\'' | ~['\n] )* '\''
|
||||
;
|
||||
|
||||
DOUBLE_QUOTED_STRING
|
||||
: '"' ( '""' | ~["\n] )* '"'
|
||||
;
|
||||
|
||||
fragment INTEGER_TYPE_SUFFIX : ( 'L' | 'l' );
|
||||
fragment HEX_DIGIT : [0-9A-Fa-f];
|
||||
fragment DECIMAL_DIGIT: [0-9];
|
||||
fragment EXPONENT_PART
|
||||
: 'e' (SIGN)* (DECIMAL_DIGIT)+
|
||||
| 'E' (SIGN)* (DECIMAL_DIGIT)+
|
||||
;
|
||||
|
||||
fragment SIGN : '+' | '-' ;
|
||||
fragment REAL_TYPE_SUFFIX : 'F' | 'f' | 'D' | 'd';
|
||||
|
||||
|
||||
|
||||
fragment ALPHABETIC
|
||||
// See Character.isLetter()
|
||||
// and https://github.com/antlr/antlr4/blob/master/doc/lexer-rules.md#lexer-rule-elements
|
||||
// and https://github.com/spring-projects/spring-framework/commit/c8c8f5722bc58452894742534954c0935653771f
|
||||
: [\p{Lu}] // UPPERCASE_LETTER
|
||||
| [\p{Ll}] // LOWERCASE_LETTER
|
||||
| [\p{Lt}] // TITLECASE_LETTER
|
||||
| [\p{Lm}] // MODIFIER_LETTER
|
||||
| [\p{Lo}] // OTHER_LETTER
|
||||
;
|
||||
|
||||
fragment DIGIT
|
||||
: [0-9]
|
||||
;
|
||||
|
||||
|
||||
mode IN_TEMPLATE_STRING;
|
||||
|
||||
ESCAPED_BACKTICK
|
||||
: '``'
|
||||
;
|
||||
|
||||
SPEL_IN_TEMPLATE_STRING_OPEN: '#{' { nesting++; } -> pushMode(DEFAULT_MODE);
|
||||
|
||||
TEMPLATE_TEXT
|
||||
: ~[`\n]
|
||||
;
|
||||
|
||||
BACKTICK_IN_TEMPLATE
|
||||
: '`' -> type(BACKTICK), popMode
|
||||
;
|
||||
171
headless-services/commons/jpql/grammars/SpelParser.g4
Normal file
171
headless-services/commons/jpql/grammars/SpelParser.g4
Normal file
@@ -0,0 +1,171 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
*******************************************************************************/
|
||||
|
||||
parser grammar SpelParser;
|
||||
|
||||
@header {
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
*******************************************************************************/
|
||||
}
|
||||
|
||||
options {
|
||||
tokenVocab = SpelLexer;
|
||||
}
|
||||
|
||||
script
|
||||
: spelExpr EOF
|
||||
;
|
||||
|
||||
spelExpr
|
||||
: (PLUS | MINUS | NOT | INC | DEC) spelExpr // ~unaryspelExpr
|
||||
| spelExpr (INC | DEC) // ~incspelExpr
|
||||
| spelExpr POWER spelExpr // ~powerExpr
|
||||
| spelExpr (STAR | DIV | MOD) spelExpr // ~productspelExpr
|
||||
| spelExpr (PLUS | MINUS) spelExpr // ~sumspelExpr
|
||||
| spelExpr (GT | LT | LE | GE | EQ | NE | GT_KEYWORD | LT_KEYWORD | LE_KEYWORD | GE_KEYWORD | EQ_KEYWORD | NE_KEYWORD) spelExpr // ~relationalspelExpr
|
||||
| spelExpr (AND | SYMBOLIC_AND) spelExpr // ~logicalAndspelExpr
|
||||
| spelExpr (OR | SYMBOLIC_OR) spelExpr // ~logicalOrspelExpr
|
||||
| spelExpr MATCHES spelExpr // ~regexExpr
|
||||
// spelExpr
|
||||
| spelExpr ASSIGN spelExpr
|
||||
| spelExpr ELVIS spelExpr
|
||||
| spelExpr QMARK spelExpr COLON spelExpr
|
||||
// primaryspelExpr
|
||||
| startNode node*
|
||||
;
|
||||
|
||||
|
||||
node
|
||||
: dottedNode
|
||||
| nonDottedNode
|
||||
;
|
||||
|
||||
nonDottedNode
|
||||
: (LSQUARE spelExpr RSQUARE)
|
||||
;
|
||||
|
||||
dottedNode
|
||||
: (DOT | SAFE_NAVI) methodOrProperty
|
||||
| functionOrVar
|
||||
| projection
|
||||
| selection
|
||||
;
|
||||
|
||||
functionOrVar
|
||||
: HASH IDENTIFIER
|
||||
| HASH IDENTIFIER methodArgs
|
||||
;
|
||||
|
||||
methodArgs
|
||||
: LPAREN args RPAREN
|
||||
;
|
||||
|
||||
args
|
||||
: spelExpr? (COMMA spelExpr)*
|
||||
;
|
||||
|
||||
methodOrProperty
|
||||
: IDENTIFIER
|
||||
| IDENTIFIER methodArgs
|
||||
;
|
||||
|
||||
projection
|
||||
: PROJECT spelExpr RSQUARE
|
||||
;
|
||||
|
||||
selection
|
||||
: (SELECT | SELECT_FIRST | SELECT_LAST) spelExpr RSQUARE
|
||||
;
|
||||
|
||||
startNode
|
||||
: literal
|
||||
| parenspelExpr
|
||||
| typeReference
|
||||
| nullReference
|
||||
| constructorReference
|
||||
| methodOrProperty
|
||||
| functionOrVar
|
||||
| beanReference
|
||||
| projection
|
||||
| selection
|
||||
| inlineListOrMap
|
||||
;
|
||||
|
||||
|
||||
literal
|
||||
: NUMERIC_LITERAL
|
||||
| STRING_LITERAL
|
||||
| TRUE
|
||||
| FALSE
|
||||
;
|
||||
|
||||
|
||||
parenspelExpr
|
||||
: LPAREN spelExpr RPAREN
|
||||
;
|
||||
|
||||
typeReference
|
||||
: T LPAREN possiblyQualifiedId (LSQUARE RSQUARE)* RPAREN
|
||||
;
|
||||
|
||||
possiblyQualifiedId
|
||||
: IDENTIFIER (DOT IDENTIFIER)*
|
||||
;
|
||||
|
||||
nullReference
|
||||
: NULL
|
||||
;
|
||||
|
||||
constructorReference
|
||||
: NEW possiblyQualifiedId (LSQUARE spelExpr? RSQUARE)+ inlineListOrMap?
|
||||
| NEW possiblyQualifiedId constructorArgs
|
||||
;
|
||||
|
||||
constructorArgs
|
||||
: LPAREN args RPAREN
|
||||
;
|
||||
|
||||
inlineListOrMap
|
||||
: LCURLY RCURLY
|
||||
| LCURLY COLON RCURLY
|
||||
| LCURLY listBindings RCURLY
|
||||
| LCURLY mapBindings RCURLY
|
||||
;
|
||||
|
||||
listBindings
|
||||
: bindings+=listBinding (COMMA bindings+=listBinding)*
|
||||
;
|
||||
|
||||
listBinding
|
||||
: spelExpr
|
||||
;
|
||||
|
||||
mapBindings
|
||||
: bindings+=mapBinding (COMMA bindings+=mapBinding)*
|
||||
;
|
||||
|
||||
mapBinding
|
||||
: key=spelExpr COLON value=spelExpr
|
||||
;
|
||||
|
||||
beanReference
|
||||
: (BEAN_REF | FACTORY_BEAN_REF) (IDENTIFIER | STRING_LITERAL)
|
||||
;
|
||||
|
||||
|
||||
@@ -0,0 +1,672 @@
|
||||
// Generated from SpelLexer.g4 by ANTLR 4.13.1
|
||||
package org.springframework.ide.vscode.parser.spel;
|
||||
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
*******************************************************************************/
|
||||
|
||||
import org.antlr.v4.runtime.Lexer;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.TokenStream;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.atn.*;
|
||||
import org.antlr.v4.runtime.dfa.DFA;
|
||||
import org.antlr.v4.runtime.misc.*;
|
||||
|
||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue", "this-escape"})
|
||||
public class SpelLexer extends Lexer {
|
||||
static { RuntimeMetaData.checkVersion("4.13.1", RuntimeMetaData.VERSION); }
|
||||
|
||||
protected static final DFA[] _decisionToDFA;
|
||||
protected static final PredictionContextCache _sharedContextCache =
|
||||
new PredictionContextCache();
|
||||
public static final int
|
||||
SEMICOLON=1, WS=2, INC=3, PLUS=4, DEC=5, MINUS=6, COLON=7, DOT=8, COMMA=9,
|
||||
STAR=10, DIV=11, MOD=12, LPAREN=13, RPAREN=14, LSQUARE=15, RSQUARE=16,
|
||||
HASH=17, BEAN_REF=18, SELECT_FIRST=19, POWER=20, NE=21, PROJECT=22, NOT=23,
|
||||
EQ=24, ASSIGN=25, SYMBOLIC_AND=26, FACTORY_BEAN_REF=27, SYMBOLIC_OR=28,
|
||||
SELECT=29, ELVIS=30, SAFE_NAVI=31, QMARK=32, SELECT_LAST=33, GE=34, GT=35,
|
||||
LE=36, LT=37, LCURLY=38, RCURLY=39, BACKTICK=40, OR=41, AND=42, TRUE=43,
|
||||
FALSE=44, NEW=45, NULL=46, T=47, MATCHES=48, GT_KEYWORD=49, GE_KEYWORD=50,
|
||||
LE_KEYWORD=51, LT_KEYWORD=52, EQ_KEYWORD=53, NE_KEYWORD=54, IDENTIFIER=55,
|
||||
NUMERIC_LITERAL=56, REAL_LITERAL=57, INTEGER_LITERAL=58, STRING_LITERAL=59,
|
||||
SINGLE_QUOTED_STRING=60, DOUBLE_QUOTED_STRING=61, ESCAPED_BACKTICK=62,
|
||||
SPEL_IN_TEMPLATE_STRING_OPEN=63, TEMPLATE_TEXT=64;
|
||||
public static final int
|
||||
IN_TEMPLATE_STRING=1;
|
||||
public static String[] channelNames = {
|
||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
|
||||
};
|
||||
|
||||
public static String[] modeNames = {
|
||||
"DEFAULT_MODE", "IN_TEMPLATE_STRING"
|
||||
};
|
||||
|
||||
private static String[] makeRuleNames() {
|
||||
return new String[] {
|
||||
"SEMICOLON", "NEWLINE", "WS", "INC", "PLUS", "DEC", "MINUS", "COLON",
|
||||
"DOT", "COMMA", "STAR", "DIV", "MOD", "LPAREN", "RPAREN", "LSQUARE",
|
||||
"RSQUARE", "HASH", "BEAN_REF", "SELECT_FIRST", "POWER", "NE", "PROJECT",
|
||||
"NOT", "EQ", "ASSIGN", "SYMBOLIC_AND", "FACTORY_BEAN_REF", "SYMBOLIC_OR",
|
||||
"SELECT", "ELVIS", "SAFE_NAVI", "QMARK", "SELECT_LAST", "GE", "GT", "LE",
|
||||
"LT", "LCURLY", "RCURLY", "BACKTICK", "OR", "AND", "TRUE", "FALSE", "NEW",
|
||||
"NULL", "T", "MATCHES", "GT_KEYWORD", "GE_KEYWORD", "LE_KEYWORD", "LT_KEYWORD",
|
||||
"EQ_KEYWORD", "NE_KEYWORD", "IDENTIFIER", "NUMERIC_LITERAL", "REAL_LITERAL",
|
||||
"INTEGER_LITERAL", "STRING_LITERAL", "SINGLE_QUOTED_STRING", "DOUBLE_QUOTED_STRING",
|
||||
"INTEGER_TYPE_SUFFIX", "HEX_DIGIT", "DECIMAL_DIGIT", "EXPONENT_PART",
|
||||
"SIGN", "REAL_TYPE_SUFFIX", "ALPHABETIC", "DIGIT", "ESCAPED_BACKTICK",
|
||||
"SPEL_IN_TEMPLATE_STRING_OPEN", "TEMPLATE_TEXT", "BACKTICK_IN_TEMPLATE"
|
||||
};
|
||||
}
|
||||
public static final String[] ruleNames = makeRuleNames();
|
||||
|
||||
private static String[] makeLiteralNames() {
|
||||
return new String[] {
|
||||
null, "';'", null, "'++'", "'+'", "'--'", "'-'", "':'", "'.'", "','",
|
||||
"'*'", "'/'", "'%'", "'('", "')'", "'['", "']'", "'#'", "'@'", "'^['",
|
||||
"'^'", "'!='", "'!['", "'!'", "'=='", "'='", "'&&'", "'&'", "'||'", "'?['",
|
||||
"'?:'", "'?.'", "'?'", "'$['", "'>='", "'>'", "'<='", "'<'", null, null,
|
||||
null, "'or'", "'and'", "'true'", "'false'", "'new'", "'null'", "'T'",
|
||||
"'matches'", "'gt'", "'ge'", "'le'", "'lt'", "'eq'", "'ne'", null, null,
|
||||
null, null, null, null, null, "'``'"
|
||||
};
|
||||
}
|
||||
private static final String[] _LITERAL_NAMES = makeLiteralNames();
|
||||
private static String[] makeSymbolicNames() {
|
||||
return new String[] {
|
||||
null, "SEMICOLON", "WS", "INC", "PLUS", "DEC", "MINUS", "COLON", "DOT",
|
||||
"COMMA", "STAR", "DIV", "MOD", "LPAREN", "RPAREN", "LSQUARE", "RSQUARE",
|
||||
"HASH", "BEAN_REF", "SELECT_FIRST", "POWER", "NE", "PROJECT", "NOT",
|
||||
"EQ", "ASSIGN", "SYMBOLIC_AND", "FACTORY_BEAN_REF", "SYMBOLIC_OR", "SELECT",
|
||||
"ELVIS", "SAFE_NAVI", "QMARK", "SELECT_LAST", "GE", "GT", "LE", "LT",
|
||||
"LCURLY", "RCURLY", "BACKTICK", "OR", "AND", "TRUE", "FALSE", "NEW",
|
||||
"NULL", "T", "MATCHES", "GT_KEYWORD", "GE_KEYWORD", "LE_KEYWORD", "LT_KEYWORD",
|
||||
"EQ_KEYWORD", "NE_KEYWORD", "IDENTIFIER", "NUMERIC_LITERAL", "REAL_LITERAL",
|
||||
"INTEGER_LITERAL", "STRING_LITERAL", "SINGLE_QUOTED_STRING", "DOUBLE_QUOTED_STRING",
|
||||
"ESCAPED_BACKTICK", "SPEL_IN_TEMPLATE_STRING_OPEN", "TEMPLATE_TEXT"
|
||||
};
|
||||
}
|
||||
private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
|
||||
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #VOCABULARY} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String[] tokenNames;
|
||||
static {
|
||||
tokenNames = new String[_SYMBOLIC_NAMES.length];
|
||||
for (int i = 0; i < tokenNames.length; i++) {
|
||||
tokenNames[i] = VOCABULARY.getLiteralName(i);
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = VOCABULARY.getSymbolicName(i);
|
||||
}
|
||||
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = "<INVALID>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public String[] getTokenNames() {
|
||||
return tokenNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public Vocabulary getVocabulary() {
|
||||
return VOCABULARY;
|
||||
}
|
||||
|
||||
|
||||
int nesting = 0;
|
||||
|
||||
|
||||
public SpelLexer(CharStream input) {
|
||||
super(input);
|
||||
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGrammarFileName() { return "SpelLexer.g4"; }
|
||||
|
||||
@Override
|
||||
public String[] getRuleNames() { return ruleNames; }
|
||||
|
||||
@Override
|
||||
public String getSerializedATN() { return _serializedATN; }
|
||||
|
||||
@Override
|
||||
public String[] getChannelNames() { return channelNames; }
|
||||
|
||||
@Override
|
||||
public String[] getModeNames() { return modeNames; }
|
||||
|
||||
@Override
|
||||
public ATN getATN() { return _ATN; }
|
||||
|
||||
@Override
|
||||
public void action(RuleContext _localctx, int ruleIndex, int actionIndex) {
|
||||
switch (ruleIndex) {
|
||||
case 38:
|
||||
LCURLY_action((RuleContext)_localctx, actionIndex);
|
||||
break;
|
||||
case 39:
|
||||
RCURLY_action((RuleContext)_localctx, actionIndex);
|
||||
break;
|
||||
case 71:
|
||||
SPEL_IN_TEMPLATE_STRING_OPEN_action((RuleContext)_localctx, actionIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void LCURLY_action(RuleContext _localctx, int actionIndex) {
|
||||
switch (actionIndex) {
|
||||
case 0:
|
||||
nesting++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void RCURLY_action(RuleContext _localctx, int actionIndex) {
|
||||
switch (actionIndex) {
|
||||
case 1:
|
||||
|
||||
if (nesting > 0) {
|
||||
nesting--;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void SPEL_IN_TEMPLATE_STRING_OPEN_action(RuleContext _localctx, int actionIndex) {
|
||||
switch (actionIndex) {
|
||||
case 2:
|
||||
nesting++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static final String _serializedATN =
|
||||
"\u0004\u0000@\u01d8\u0006\uffff\uffff\u0006\uffff\uffff\u0002\u0000\u0007"+
|
||||
"\u0000\u0002\u0001\u0007\u0001\u0002\u0002\u0007\u0002\u0002\u0003\u0007"+
|
||||
"\u0003\u0002\u0004\u0007\u0004\u0002\u0005\u0007\u0005\u0002\u0006\u0007"+
|
||||
"\u0006\u0002\u0007\u0007\u0007\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n"+
|
||||
"\u0007\n\u0002\u000b\u0007\u000b\u0002\f\u0007\f\u0002\r\u0007\r\u0002"+
|
||||
"\u000e\u0007\u000e\u0002\u000f\u0007\u000f\u0002\u0010\u0007\u0010\u0002"+
|
||||
"\u0011\u0007\u0011\u0002\u0012\u0007\u0012\u0002\u0013\u0007\u0013\u0002"+
|
||||
"\u0014\u0007\u0014\u0002\u0015\u0007\u0015\u0002\u0016\u0007\u0016\u0002"+
|
||||
"\u0017\u0007\u0017\u0002\u0018\u0007\u0018\u0002\u0019\u0007\u0019\u0002"+
|
||||
"\u001a\u0007\u001a\u0002\u001b\u0007\u001b\u0002\u001c\u0007\u001c\u0002"+
|
||||
"\u001d\u0007\u001d\u0002\u001e\u0007\u001e\u0002\u001f\u0007\u001f\u0002"+
|
||||
" \u0007 \u0002!\u0007!\u0002\"\u0007\"\u0002#\u0007#\u0002$\u0007$\u0002"+
|
||||
"%\u0007%\u0002&\u0007&\u0002\'\u0007\'\u0002(\u0007(\u0002)\u0007)\u0002"+
|
||||
"*\u0007*\u0002+\u0007+\u0002,\u0007,\u0002-\u0007-\u0002.\u0007.\u0002"+
|
||||
"/\u0007/\u00020\u00070\u00021\u00071\u00022\u00072\u00023\u00073\u0002"+
|
||||
"4\u00074\u00025\u00075\u00026\u00076\u00027\u00077\u00028\u00078\u0002"+
|
||||
"9\u00079\u0002:\u0007:\u0002;\u0007;\u0002<\u0007<\u0002=\u0007=\u0002"+
|
||||
">\u0007>\u0002?\u0007?\u0002@\u0007@\u0002A\u0007A\u0002B\u0007B\u0002"+
|
||||
"C\u0007C\u0002D\u0007D\u0002E\u0007E\u0002F\u0007F\u0002G\u0007G\u0002"+
|
||||
"H\u0007H\u0002I\u0007I\u0001\u0000\u0001\u0000\u0001\u0001\u0001\u0001"+
|
||||
"\u0001\u0001\u0003\u0001\u009c\b\u0001\u0001\u0002\u0004\u0002\u009f\b"+
|
||||
"\u0002\u000b\u0002\f\u0002\u00a0\u0001\u0002\u0001\u0002\u0001\u0003\u0001"+
|
||||
"\u0003\u0001\u0003\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005\u0001"+
|
||||
"\u0005\u0001\u0006\u0001\u0006\u0001\u0007\u0001\u0007\u0001\b\u0001\b"+
|
||||
"\u0001\t\u0001\t\u0001\n\u0001\n\u0001\u000b\u0001\u000b\u0001\f\u0001"+
|
||||
"\f\u0001\r\u0001\r\u0001\u000e\u0001\u000e\u0001\u000f\u0001\u000f\u0001"+
|
||||
"\u0010\u0001\u0010\u0001\u0011\u0001\u0011\u0001\u0012\u0001\u0012\u0001"+
|
||||
"\u0013\u0001\u0013\u0001\u0013\u0001\u0014\u0001\u0014\u0001\u0015\u0001"+
|
||||
"\u0015\u0001\u0015\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0017\u0001"+
|
||||
"\u0017\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0019\u0001\u0019\u0001"+
|
||||
"\u001a\u0001\u001a\u0001\u001a\u0001\u001b\u0001\u001b\u0001\u001c\u0001"+
|
||||
"\u001c\u0001\u001c\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001e\u0001"+
|
||||
"\u001e\u0001\u001e\u0001\u001f\u0001\u001f\u0001\u001f\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,\u0001,\u0001,\u0001,\u0001-\u0001-\u0001-\u0001-\u0001.\u0001"+
|
||||
".\u0001.\u0001.\u0001.\u0001/\u0001/\u00010\u00010\u00010\u00010\u0001"+
|
||||
"0\u00010\u00010\u00010\u00011\u00011\u00011\u00012\u00012\u00012\u0001"+
|
||||
"3\u00013\u00013\u00014\u00014\u00014\u00015\u00015\u00015\u00016\u0001"+
|
||||
"6\u00016\u00017\u00017\u00037\u0140\b7\u00017\u00017\u00017\u00057\u0145"+
|
||||
"\b7\n7\f7\u0148\t7\u00018\u00018\u00038\u014c\b8\u00019\u00019\u00049"+
|
||||
"\u0150\b9\u000b9\f9\u0151\u00019\u00039\u0155\b9\u00019\u00039\u0158\b"+
|
||||
"9\u00019\u00049\u015b\b9\u000b9\f9\u015c\u00019\u00019\u00049\u0161\b"+
|
||||
"9\u000b9\f9\u0162\u00019\u00039\u0166\b9\u00019\u00039\u0169\b9\u0001"+
|
||||
"9\u00049\u016c\b9\u000b9\f9\u016d\u00019\u00019\u00039\u0172\b9\u0001"+
|
||||
"9\u00049\u0175\b9\u000b9\f9\u0176\u00019\u00019\u00039\u017b\b9\u0001"+
|
||||
":\u0004:\u017e\b:\u000b:\f:\u017f\u0001:\u0003:\u0183\b:\u0001;\u0001"+
|
||||
";\u0003;\u0187\b;\u0001<\u0001<\u0001<\u0001<\u0005<\u018d\b<\n<\f<\u0190"+
|
||||
"\t<\u0001<\u0001<\u0001=\u0001=\u0001=\u0001=\u0005=\u0198\b=\n=\f=\u019b"+
|
||||
"\t=\u0001=\u0001=\u0001>\u0001>\u0001?\u0001?\u0001@\u0001@\u0001A\u0001"+
|
||||
"A\u0005A\u01a7\bA\nA\fA\u01aa\tA\u0001A\u0004A\u01ad\bA\u000bA\fA\u01ae"+
|
||||
"\u0001A\u0001A\u0005A\u01b3\bA\nA\fA\u01b6\tA\u0001A\u0004A\u01b9\bA\u000b"+
|
||||
"A\fA\u01ba\u0003A\u01bd\bA\u0001B\u0001B\u0001C\u0001C\u0001D\u0003D\u01c4"+
|
||||
"\bD\u0001E\u0001E\u0001F\u0001F\u0001F\u0001G\u0001G\u0001G\u0001G\u0001"+
|
||||
"G\u0001G\u0001G\u0001H\u0001H\u0001I\u0001I\u0001I\u0001I\u0001I\u0000"+
|
||||
"\u0000J\u0002\u0001\u0004\u0000\u0006\u0002\b\u0003\n\u0004\f\u0005\u000e"+
|
||||
"\u0006\u0010\u0007\u0012\b\u0014\t\u0016\n\u0018\u000b\u001a\f\u001c\r"+
|
||||
"\u001e\u000e \u000f\"\u0010$\u0011&\u0012(\u0013*\u0014,\u0015.\u0016"+
|
||||
"0\u00172\u00184\u00196\u001a8\u001b:\u001c<\u001d>\u001e@\u001fB D!F\""+
|
||||
"H#J$L%N&P\'R(T)V*X+Z,\\-^.`/b0d1f2h3j4l5n6p7r8t9v:x;z<|=~\u0000\u0080"+
|
||||
"\u0000\u0082\u0000\u0084\u0000\u0086\u0000\u0088\u0000\u008a\u0000\u008c"+
|
||||
"\u0000\u008e>\u0090?\u0092@\u0094\u0000\u0002\u0000\u0001\f\u0003\u0000"+
|
||||
"\n\n\r\r\u2028\u2029\u0003\u0000\t\n\r\r \u0002\u0000$$__\u0002\u0000"+
|
||||
"\n\n\'\'\u0002\u0000\n\n\"\"\u0002\u0000LLll\u0003\u000009AFaf\u0001\u0000"+
|
||||
"09\u0002\u0000++--\u0004\u0000DDFFddff\u0293\u0000AZaz\u00aa\u00aa\u00b5"+
|
||||
"\u00b5\u00ba\u00ba\u00c0\u00d6\u00d8\u00f6\u00f8\u02c1\u02c6\u02d1\u02e0"+
|
||||
"\u02e4\u02ec\u02ec\u02ee\u02ee\u0370\u0374\u0376\u0377\u037a\u037d\u037f"+
|
||||
"\u037f\u0386\u0386\u0388\u038a\u038c\u038c\u038e\u03a1\u03a3\u03f5\u03f7"+
|
||||
"\u0481\u048a\u052f\u0531\u0556\u0559\u0559\u0560\u0588\u05d0\u05ea\u05ef"+
|
||||
"\u05f2\u0620\u064a\u066e\u066f\u0671\u06d3\u06d5\u06d5\u06e5\u06e6\u06ee"+
|
||||
"\u06ef\u06fa\u06fc\u06ff\u06ff\u0710\u0710\u0712\u072f\u074d\u07a5\u07b1"+
|
||||
"\u07b1\u07ca\u07ea\u07f4\u07f5\u07fa\u07fa\u0800\u0815\u081a\u081a\u0824"+
|
||||
"\u0824\u0828\u0828\u0840\u0858\u0860\u086a\u0870\u0887\u0889\u088e\u08a0"+
|
||||
"\u08c9\u0904\u0939\u093d\u093d\u0950\u0950\u0958\u0961\u0971\u0980\u0985"+
|
||||
"\u098c\u098f\u0990\u0993\u09a8\u09aa\u09b0\u09b2\u09b2\u09b6\u09b9\u09bd"+
|
||||
"\u09bd\u09ce\u09ce\u09dc\u09dd\u09df\u09e1\u09f0\u09f1\u09fc\u09fc\u0a05"+
|
||||
"\u0a0a\u0a0f\u0a10\u0a13\u0a28\u0a2a\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38"+
|
||||
"\u0a39\u0a59\u0a5c\u0a5e\u0a5e\u0a72\u0a74\u0a85\u0a8d\u0a8f\u0a91\u0a93"+
|
||||
"\u0aa8\u0aaa\u0ab0\u0ab2\u0ab3\u0ab5\u0ab9\u0abd\u0abd\u0ad0\u0ad0\u0ae0"+
|
||||
"\u0ae1\u0af9\u0af9\u0b05\u0b0c\u0b0f\u0b10\u0b13\u0b28\u0b2a\u0b30\u0b32"+
|
||||
"\u0b33\u0b35\u0b39\u0b3d\u0b3d\u0b5c\u0b5d\u0b5f\u0b61\u0b71\u0b71\u0b83"+
|
||||
"\u0b83\u0b85\u0b8a\u0b8e\u0b90\u0b92\u0b95\u0b99\u0b9a\u0b9c\u0b9c\u0b9e"+
|
||||
"\u0b9f\u0ba3\u0ba4\u0ba8\u0baa\u0bae\u0bb9\u0bd0\u0bd0\u0c05\u0c0c\u0c0e"+
|
||||
"\u0c10\u0c12\u0c28\u0c2a\u0c39\u0c3d\u0c3d\u0c58\u0c5a\u0c5d\u0c5d\u0c60"+
|
||||
"\u0c61\u0c80\u0c80\u0c85\u0c8c\u0c8e\u0c90\u0c92\u0ca8\u0caa\u0cb3\u0cb5"+
|
||||
"\u0cb9\u0cbd\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04\u0d0c\u0d0e"+
|
||||
"\u0d10\u0d12\u0d3a\u0d3d\u0d3d\u0d4e\u0d4e\u0d54\u0d56\u0d5f\u0d61\u0d7a"+
|
||||
"\u0d7f\u0d85\u0d96\u0d9a\u0db1\u0db3\u0dbb\u0dbd\u0dbd\u0dc0\u0dc6\u0e01"+
|
||||
"\u0e30\u0e32\u0e33\u0e40\u0e46\u0e81\u0e82\u0e84\u0e84\u0e86\u0e8a\u0e8c"+
|
||||
"\u0ea3\u0ea5\u0ea5\u0ea7\u0eb0\u0eb2\u0eb3\u0ebd\u0ebd\u0ec0\u0ec4\u0ec6"+
|
||||
"\u0ec6\u0edc\u0edf\u0f00\u0f00\u0f40\u0f47\u0f49\u0f6c\u0f88\u0f8c\u1000"+
|
||||
"\u102a\u103f\u103f\u1050\u1055\u105a\u105d\u1061\u1061\u1065\u1066\u106e"+
|
||||
"\u1070\u1075\u1081\u108e\u108e\u10a0\u10c5\u10c7\u10c7\u10cd\u10cd\u10d0"+
|
||||
"\u10fa\u10fc\u1248\u124a\u124d\u1250\u1256\u1258\u1258\u125a\u125d\u1260"+
|
||||
"\u1288\u128a\u128d\u1290\u12b0\u12b2\u12b5\u12b8\u12be\u12c0\u12c0\u12c2"+
|
||||
"\u12c5\u12c8\u12d6\u12d8\u1310\u1312\u1315\u1318\u135a\u1380\u138f\u13a0"+
|
||||
"\u13f5\u13f8\u13fd\u1401\u166c\u166f\u167f\u1681\u169a\u16a0\u16ea\u16f1"+
|
||||
"\u16f8\u1700\u1711\u171f\u1731\u1740\u1751\u1760\u176c\u176e\u1770\u1780"+
|
||||
"\u17b3\u17d7\u17d7\u17dc\u17dc\u1820\u1878\u1880\u1884\u1887\u18a8\u18aa"+
|
||||
"\u18aa\u18b0\u18f5\u1900\u191e\u1950\u196d\u1970\u1974\u1980\u19ab\u19b0"+
|
||||
"\u19c9\u1a00\u1a16\u1a20\u1a54\u1aa7\u1aa7\u1b05\u1b33\u1b45\u1b4c\u1b83"+
|
||||
"\u1ba0\u1bae\u1baf\u1bba\u1be5\u1c00\u1c23\u1c4d\u1c4f\u1c5a\u1c7d\u1c80"+
|
||||
"\u1c88\u1c90\u1cba\u1cbd\u1cbf\u1ce9\u1cec\u1cee\u1cf3\u1cf5\u1cf6\u1cfa"+
|
||||
"\u1cfa\u1d00\u1dbf\u1e00\u1f15\u1f18\u1f1d\u1f20\u1f45\u1f48\u1f4d\u1f50"+
|
||||
"\u1f57\u1f59\u1f59\u1f5b\u1f5b\u1f5d\u1f5d\u1f5f\u1f7d\u1f80\u1fb4\u1fb6"+
|
||||
"\u1fbc\u1fbe\u1fbe\u1fc2\u1fc4\u1fc6\u1fcc\u1fd0\u1fd3\u1fd6\u1fdb\u1fe0"+
|
||||
"\u1fec\u1ff2\u1ff4\u1ff6\u1ffc\u2071\u2071\u207f\u207f\u2090\u209c\u2102"+
|
||||
"\u2102\u2107\u2107\u210a\u2113\u2115\u2115\u2119\u211d\u2124\u2124\u2126"+
|
||||
"\u2126\u2128\u2128\u212a\u212d\u212f\u2139\u213c\u213f\u2145\u2149\u214e"+
|
||||
"\u214e\u2183\u2184\u2c00\u2ce4\u2ceb\u2cee\u2cf2\u2cf3\u2d00\u2d25\u2d27"+
|
||||
"\u2d27\u2d2d\u2d2d\u2d30\u2d67\u2d6f\u2d6f\u2d80\u2d96\u2da0\u2da6\u2da8"+
|
||||
"\u2dae\u2db0\u2db6\u2db8\u2dbe\u2dc0\u2dc6\u2dc8\u2dce\u2dd0\u2dd6\u2dd8"+
|
||||
"\u2dde\u2e2f\u2e2f\u3005\u3006\u3031\u3035\u303b\u303c\u3041\u3096\u309d"+
|
||||
"\u309f\u30a1\u30fa\u30fc\u30ff\u3105\u312f\u3131\u318e\u31a0\u31bf\u31f0"+
|
||||
"\u31ff\u3400\u4dbf\u4e00\u8000\ua48c\u8000\ua4d0\u8000\ua4fd\u8000\ua500"+
|
||||
"\u8000\ua60c\u8000\ua610\u8000\ua61f\u8000\ua62a\u8000\ua62b\u8000\ua640"+
|
||||
"\u8000\ua66e\u8000\ua67f\u8000\ua69d\u8000\ua6a0\u8000\ua6e5\u8000\ua717"+
|
||||
"\u8000\ua71f\u8000\ua722\u8000\ua788\u8000\ua78b\u8000\ua7ca\u8000\ua7d0"+
|
||||
"\u8000\ua7d1\u8000\ua7d3\u8000\ua7d3\u8000\ua7d5\u8000\ua7d9\u8000\ua7f2"+
|
||||
"\u8000\ua801\u8000\ua803\u8000\ua805\u8000\ua807\u8000\ua80a\u8000\ua80c"+
|
||||
"\u8000\ua822\u8000\ua840\u8000\ua873\u8000\ua882\u8000\ua8b3\u8000\ua8f2"+
|
||||
"\u8000\ua8f7\u8000\ua8fb\u8000\ua8fb\u8000\ua8fd\u8000\ua8fe\u8000\ua90a"+
|
||||
"\u8000\ua925\u8000\ua930\u8000\ua946\u8000\ua960\u8000\ua97c\u8000\ua984"+
|
||||
"\u8000\ua9b2\u8000\ua9cf\u8000\ua9cf\u8000\ua9e0\u8000\ua9e4\u8000\ua9e6"+
|
||||
"\u8000\ua9ef\u8000\ua9fa\u8000\ua9fe\u8000\uaa00\u8000\uaa28\u8000\uaa40"+
|
||||
"\u8000\uaa42\u8000\uaa44\u8000\uaa4b\u8000\uaa60\u8000\uaa76\u8000\uaa7a"+
|
||||
"\u8000\uaa7a\u8000\uaa7e\u8000\uaaaf\u8000\uaab1\u8000\uaab1\u8000\uaab5"+
|
||||
"\u8000\uaab6\u8000\uaab9\u8000\uaabd\u8000\uaac0\u8000\uaac0\u8000\uaac2"+
|
||||
"\u8000\uaac2\u8000\uaadb\u8000\uaadd\u8000\uaae0\u8000\uaaea\u8000\uaaf2"+
|
||||
"\u8000\uaaf4\u8000\uab01\u8000\uab06\u8000\uab09\u8000\uab0e\u8000\uab11"+
|
||||
"\u8000\uab16\u8000\uab20\u8000\uab26\u8000\uab28\u8000\uab2e\u8000\uab30"+
|
||||
"\u8000\uab5a\u8000\uab5c\u8000\uab69\u8000\uab70\u8000\uabe2\u8000\uac00"+
|
||||
"\u8000\ud7a3\u8000\ud7b0\u8000\ud7c6\u8000\ud7cb\u8000\ud7fb\u8000\uf900"+
|
||||
"\u8000\ufa6d\u8000\ufa70\u8000\ufad9\u8000\ufb00\u8000\ufb06\u8000\ufb13"+
|
||||
"\u8000\ufb17\u8000\ufb1d\u8000\ufb1d\u8000\ufb1f\u8000\ufb28\u8000\ufb2a"+
|
||||
"\u8000\ufb36\u8000\ufb38\u8000\ufb3c\u8000\ufb3e\u8000\ufb3e\u8000\ufb40"+
|
||||
"\u8000\ufb41\u8000\ufb43\u8000\ufb44\u8000\ufb46\u8000\ufbb1\u8000\ufbd3"+
|
||||
"\u8000\ufd3d\u8000\ufd50\u8000\ufd8f\u8000\ufd92\u8000\ufdc7\u8000\ufdf0"+
|
||||
"\u8000\ufdfb\u8000\ufe70\u8000\ufe74\u8000\ufe76\u8000\ufefc\u8000\uff21"+
|
||||
"\u8000\uff3a\u8000\uff41\u8000\uff5a\u8000\uff66\u8000\uffbe\u8000\uffc2"+
|
||||
"\u8000\uffc7\u8000\uffca\u8000\uffcf\u8000\uffd2\u8000\uffd7\u8000\uffda"+
|
||||
"\u8000\uffdc\u8001\u0000\u8001\u000b\u8001\r\u8001&\u8001(\u8001:\u8001"+
|
||||
"<\u8001=\u8001?\u8001M\u8001P\u8001]\u8001\u0080\u8001\u00fa\u8001\u0280"+
|
||||
"\u8001\u029c\u8001\u02a0\u8001\u02d0\u8001\u0300\u8001\u031f\u8001\u032d"+
|
||||
"\u8001\u0340\u8001\u0342\u8001\u0349\u8001\u0350\u8001\u0375\u8001\u0380"+
|
||||
"\u8001\u039d\u8001\u03a0\u8001\u03c3\u8001\u03c8\u8001\u03cf\u8001\u0400"+
|
||||
"\u8001\u049d\u8001\u04b0\u8001\u04d3\u8001\u04d8\u8001\u04fb\u8001\u0500"+
|
||||
"\u8001\u0527\u8001\u0530\u8001\u0563\u8001\u0570\u8001\u057a\u8001\u057c"+
|
||||
"\u8001\u058a\u8001\u058c\u8001\u0592\u8001\u0594\u8001\u0595\u8001\u0597"+
|
||||
"\u8001\u05a1\u8001\u05a3\u8001\u05b1\u8001\u05b3\u8001\u05b9\u8001\u05bb"+
|
||||
"\u8001\u05bc\u8001\u0600\u8001\u0736\u8001\u0740\u8001\u0755\u8001\u0760"+
|
||||
"\u8001\u0767\u8001\u0780\u8001\u0785\u8001\u0787\u8001\u07b0\u8001\u07b2"+
|
||||
"\u8001\u07ba\u8001\u0800\u8001\u0805\u8001\u0808\u8001\u0808\u8001\u080a"+
|
||||
"\u8001\u0835\u8001\u0837\u8001\u0838\u8001\u083c\u8001\u083c\u8001\u083f"+
|
||||
"\u8001\u0855\u8001\u0860\u8001\u0876\u8001\u0880\u8001\u089e\u8001\u08e0"+
|
||||
"\u8001\u08f2\u8001\u08f4\u8001\u08f5\u8001\u0900\u8001\u0915\u8001\u0920"+
|
||||
"\u8001\u0939\u8001\u0980\u8001\u09b7\u8001\u09be\u8001\u09bf\u8001\u0a00"+
|
||||
"\u8001\u0a00\u8001\u0a10\u8001\u0a13\u8001\u0a15\u8001\u0a17\u8001\u0a19"+
|
||||
"\u8001\u0a35\u8001\u0a60\u8001\u0a7c\u8001\u0a80\u8001\u0a9c\u8001\u0ac0"+
|
||||
"\u8001\u0ac7\u8001\u0ac9\u8001\u0ae4\u8001\u0b00\u8001\u0b35\u8001\u0b40"+
|
||||
"\u8001\u0b55\u8001\u0b60\u8001\u0b72\u8001\u0b80\u8001\u0b91\u8001\u0c00"+
|
||||
"\u8001\u0c48\u8001\u0c80\u8001\u0cb2\u8001\u0cc0\u8001\u0cf2\u8001\u0d00"+
|
||||
"\u8001\u0d23\u8001\u0e80\u8001\u0ea9\u8001\u0eb0\u8001\u0eb1\u8001\u0f00"+
|
||||
"\u8001\u0f1c\u8001\u0f27\u8001\u0f27\u8001\u0f30\u8001\u0f45\u8001\u0f70"+
|
||||
"\u8001\u0f81\u8001\u0fb0\u8001\u0fc4\u8001\u0fe0\u8001\u0ff6\u8001\u1003"+
|
||||
"\u8001\u1037\u8001\u1071\u8001\u1072\u8001\u1075\u8001\u1075\u8001\u1083"+
|
||||
"\u8001\u10af\u8001\u10d0\u8001\u10e8\u8001\u1103\u8001\u1126\u8001\u1144"+
|
||||
"\u8001\u1144\u8001\u1147\u8001\u1147\u8001\u1150\u8001\u1172\u8001\u1176"+
|
||||
"\u8001\u1176\u8001\u1183\u8001\u11b2\u8001\u11c1\u8001\u11c4\u8001\u11da"+
|
||||
"\u8001\u11da\u8001\u11dc\u8001\u11dc\u8001\u1200\u8001\u1211\u8001\u1213"+
|
||||
"\u8001\u122b\u8001\u123f\u8001\u1240\u8001\u1280\u8001\u1286\u8001\u1288"+
|
||||
"\u8001\u1288\u8001\u128a\u8001\u128d\u8001\u128f\u8001\u129d\u8001\u129f"+
|
||||
"\u8001\u12a8\u8001\u12b0\u8001\u12de\u8001\u1305\u8001\u130c\u8001\u130f"+
|
||||
"\u8001\u1310\u8001\u1313\u8001\u1328\u8001\u132a\u8001\u1330\u8001\u1332"+
|
||||
"\u8001\u1333\u8001\u1335\u8001\u1339\u8001\u133d\u8001\u133d\u8001\u1350"+
|
||||
"\u8001\u1350\u8001\u135d\u8001\u1361\u8001\u1400\u8001\u1434\u8001\u1447"+
|
||||
"\u8001\u144a\u8001\u145f\u8001\u1461\u8001\u1480\u8001\u14af\u8001\u14c4"+
|
||||
"\u8001\u14c5\u8001\u14c7\u8001\u14c7\u8001\u1580\u8001\u15ae\u8001\u15d8"+
|
||||
"\u8001\u15db\u8001\u1600\u8001\u162f\u8001\u1644\u8001\u1644\u8001\u1680"+
|
||||
"\u8001\u16aa\u8001\u16b8\u8001\u16b8\u8001\u1700\u8001\u171a\u8001\u1740"+
|
||||
"\u8001\u1746\u8001\u1800\u8001\u182b\u8001\u18a0\u8001\u18df\u8001\u18ff"+
|
||||
"\u8001\u1906\u8001\u1909\u8001\u1909\u8001\u190c\u8001\u1913\u8001\u1915"+
|
||||
"\u8001\u1916\u8001\u1918\u8001\u192f\u8001\u193f\u8001\u193f\u8001\u1941"+
|
||||
"\u8001\u1941\u8001\u19a0\u8001\u19a7\u8001\u19aa\u8001\u19d0\u8001\u19e1"+
|
||||
"\u8001\u19e1\u8001\u19e3\u8001\u19e3\u8001\u1a00\u8001\u1a00\u8001\u1a0b"+
|
||||
"\u8001\u1a32\u8001\u1a3a\u8001\u1a3a\u8001\u1a50\u8001\u1a50\u8001\u1a5c"+
|
||||
"\u8001\u1a89\u8001\u1a9d\u8001\u1a9d\u8001\u1ab0\u8001\u1af8\u8001\u1c00"+
|
||||
"\u8001\u1c08\u8001\u1c0a\u8001\u1c2e\u8001\u1c40\u8001\u1c40\u8001\u1c72"+
|
||||
"\u8001\u1c8f\u8001\u1d00\u8001\u1d06\u8001\u1d08\u8001\u1d09\u8001\u1d0b"+
|
||||
"\u8001\u1d30\u8001\u1d46\u8001\u1d46\u8001\u1d60\u8001\u1d65\u8001\u1d67"+
|
||||
"\u8001\u1d68\u8001\u1d6a\u8001\u1d89\u8001\u1d98\u8001\u1d98\u8001\u1ee0"+
|
||||
"\u8001\u1ef2\u8001\u1f02\u8001\u1f02\u8001\u1f04\u8001\u1f10\u8001\u1f12"+
|
||||
"\u8001\u1f33\u8001\u1fb0\u8001\u1fb0\u8001\u2000\u8001\u2399\u8001\u2480"+
|
||||
"\u8001\u2543\u8001\u2f90\u8001\u2ff0\u8001\u3000\u8001\u342f\u8001\u3441"+
|
||||
"\u8001\u3446\u8001\u4400\u8001\u4646\u8001\u6800\u8001\u6a38\u8001\u6a40"+
|
||||
"\u8001\u6a5e\u8001\u6a70\u8001\u6abe\u8001\u6ad0\u8001\u6aed\u8001\u6b00"+
|
||||
"\u8001\u6b2f\u8001\u6b40\u8001\u6b43\u8001\u6b63\u8001\u6b77\u8001\u6b7d"+
|
||||
"\u8001\u6b8f\u8001\u6e40\u8001\u6e7f\u8001\u6f00\u8001\u6f4a\u8001\u6f50"+
|
||||
"\u8001\u6f50\u8001\u6f93\u8001\u6f9f\u8001\u6fe0\u8001\u6fe1\u8001\u6fe3"+
|
||||
"\u8001\u6fe3\u8001\u7000\u8001\u87f7\u8001\u8800\u8001\u8cd5\u8001\u8d00"+
|
||||
"\u8001\u8d08\u8001\uaff0\u8001\uaff3\u8001\uaff5\u8001\uaffb\u8001\uaffd"+
|
||||
"\u8001\uaffe\u8001\ub000\u8001\ub122\u8001\ub132\u8001\ub132\u8001\ub150"+
|
||||
"\u8001\ub152\u8001\ub155\u8001\ub155\u8001\ub164\u8001\ub167\u8001\ub170"+
|
||||
"\u8001\ub2fb\u8001\ubc00\u8001\ubc6a\u8001\ubc70\u8001\ubc7c\u8001\ubc80"+
|
||||
"\u8001\ubc88\u8001\ubc90\u8001\ubc99\u8001\ud400\u8001\ud454\u8001\ud456"+
|
||||
"\u8001\ud49c\u8001\ud49e\u8001\ud49f\u8001\ud4a2\u8001\ud4a2\u8001\ud4a5"+
|
||||
"\u8001\ud4a6\u8001\ud4a9\u8001\ud4ac\u8001\ud4ae\u8001\ud4b9\u8001\ud4bb"+
|
||||
"\u8001\ud4bb\u8001\ud4bd\u8001\ud4c3\u8001\ud4c5\u8001\ud505\u8001\ud507"+
|
||||
"\u8001\ud50a\u8001\ud50d\u8001\ud514\u8001\ud516\u8001\ud51c\u8001\ud51e"+
|
||||
"\u8001\ud539\u8001\ud53b\u8001\ud53e\u8001\ud540\u8001\ud544\u8001\ud546"+
|
||||
"\u8001\ud546\u8001\ud54a\u8001\ud550\u8001\ud552\u8001\ud6a5\u8001\ud6a8"+
|
||||
"\u8001\ud6c0\u8001\ud6c2\u8001\ud6da\u8001\ud6dc\u8001\ud6fa\u8001\ud6fc"+
|
||||
"\u8001\ud714\u8001\ud716\u8001\ud734\u8001\ud736\u8001\ud74e\u8001\ud750"+
|
||||
"\u8001\ud76e\u8001\ud770\u8001\ud788\u8001\ud78a\u8001\ud7a8\u8001\ud7aa"+
|
||||
"\u8001\ud7c2\u8001\ud7c4\u8001\ud7cb\u8001\udf00\u8001\udf1e\u8001\udf25"+
|
||||
"\u8001\udf2a\u8001\ue030\u8001\ue06d\u8001\ue100\u8001\ue12c\u8001\ue137"+
|
||||
"\u8001\ue13d\u8001\ue14e\u8001\ue14e\u8001\ue290\u8001\ue2ad\u8001\ue2c0"+
|
||||
"\u8001\ue2eb\u8001\ue4d0\u8001\ue4eb\u8001\ue7e0\u8001\ue7e6\u8001\ue7e8"+
|
||||
"\u8001\ue7eb\u8001\ue7ed\u8001\ue7ee\u8001\ue7f0\u8001\ue7fe\u8001\ue800"+
|
||||
"\u8001\ue8c4\u8001\ue900\u8001\ue943\u8001\ue94b\u8001\ue94b\u8001\uee00"+
|
||||
"\u8001\uee03\u8001\uee05\u8001\uee1f\u8001\uee21\u8001\uee22\u8001\uee24"+
|
||||
"\u8001\uee24\u8001\uee27\u8001\uee27\u8001\uee29\u8001\uee32\u8001\uee34"+
|
||||
"\u8001\uee37\u8001\uee39\u8001\uee39\u8001\uee3b\u8001\uee3b\u8001\uee42"+
|
||||
"\u8001\uee42\u8001\uee47\u8001\uee47\u8001\uee49\u8001\uee49\u8001\uee4b"+
|
||||
"\u8001\uee4b\u8001\uee4d\u8001\uee4f\u8001\uee51\u8001\uee52\u8001\uee54"+
|
||||
"\u8001\uee54\u8001\uee57\u8001\uee57\u8001\uee59\u8001\uee59\u8001\uee5b"+
|
||||
"\u8001\uee5b\u8001\uee5d\u8001\uee5d\u8001\uee5f\u8001\uee5f\u8001\uee61"+
|
||||
"\u8001\uee62\u8001\uee64\u8001\uee64\u8001\uee67\u8001\uee6a\u8001\uee6c"+
|
||||
"\u8001\uee72\u8001\uee74\u8001\uee77\u8001\uee79\u8001\uee7c\u8001\uee7e"+
|
||||
"\u8001\uee7e\u8001\uee80\u8001\uee89\u8001\uee8b\u8001\uee9b\u8001\ueea1"+
|
||||
"\u8001\ueea3\u8001\ueea5\u8001\ueea9\u8001\ueeab\u8001\ueebb\u8002\u0000"+
|
||||
"\u8002\ua6df\u8002\ua700\u8002\ub739\u8002\ub740\u8002\ub81d\u8002\ub820"+
|
||||
"\u8002\ucea1\u8002\uceb0\u8002\uebe0\u8002\uf800\u8002\ufa1d\u8003\u0000"+
|
||||
"\u8003\u134a\u8003\u1350\u8003\u23af\u0002\u0000\n\n``\u01ed\u0000\u0002"+
|
||||
"\u0001\u0000\u0000\u0000\u0000\u0006\u0001\u0000\u0000\u0000\u0000\b\u0001"+
|
||||
"\u0000\u0000\u0000\u0000\n\u0001\u0000\u0000\u0000\u0000\f\u0001\u0000"+
|
||||
"\u0000\u0000\u0000\u000e\u0001\u0000\u0000\u0000\u0000\u0010\u0001\u0000"+
|
||||
"\u0000\u0000\u0000\u0012\u0001\u0000\u0000\u0000\u0000\u0014\u0001\u0000"+
|
||||
"\u0000\u0000\u0000\u0016\u0001\u0000\u0000\u0000\u0000\u0018\u0001\u0000"+
|
||||
"\u0000\u0000\u0000\u001a\u0001\u0000\u0000\u0000\u0000\u001c\u0001\u0000"+
|
||||
"\u0000\u0000\u0000\u001e\u0001\u0000\u0000\u0000\u0000 \u0001\u0000\u0000"+
|
||||
"\u0000\u0000\"\u0001\u0000\u0000\u0000\u0000$\u0001\u0000\u0000\u0000"+
|
||||
"\u0000&\u0001\u0000\u0000\u0000\u0000(\u0001\u0000\u0000\u0000\u0000*"+
|
||||
"\u0001\u0000\u0000\u0000\u0000,\u0001\u0000\u0000\u0000\u0000.\u0001\u0000"+
|
||||
"\u0000\u0000\u00000\u0001\u0000\u0000\u0000\u00002\u0001\u0000\u0000\u0000"+
|
||||
"\u00004\u0001\u0000\u0000\u0000\u00006\u0001\u0000\u0000\u0000\u00008"+
|
||||
"\u0001\u0000\u0000\u0000\u0000:\u0001\u0000\u0000\u0000\u0000<\u0001\u0000"+
|
||||
"\u0000\u0000\u0000>\u0001\u0000\u0000\u0000\u0000@\u0001\u0000\u0000\u0000"+
|
||||
"\u0000B\u0001\u0000\u0000\u0000\u0000D\u0001\u0000\u0000\u0000\u0000F"+
|
||||
"\u0001\u0000\u0000\u0000\u0000H\u0001\u0000\u0000\u0000\u0000J\u0001\u0000"+
|
||||
"\u0000\u0000\u0000L\u0001\u0000\u0000\u0000\u0000N\u0001\u0000\u0000\u0000"+
|
||||
"\u0000P\u0001\u0000\u0000\u0000\u0000R\u0001\u0000\u0000\u0000\u0000T"+
|
||||
"\u0001\u0000\u0000\u0000\u0000V\u0001\u0000\u0000\u0000\u0000X\u0001\u0000"+
|
||||
"\u0000\u0000\u0000Z\u0001\u0000\u0000\u0000\u0000\\\u0001\u0000\u0000"+
|
||||
"\u0000\u0000^\u0001\u0000\u0000\u0000\u0000`\u0001\u0000\u0000\u0000\u0000"+
|
||||
"b\u0001\u0000\u0000\u0000\u0000d\u0001\u0000\u0000\u0000\u0000f\u0001"+
|
||||
"\u0000\u0000\u0000\u0000h\u0001\u0000\u0000\u0000\u0000j\u0001\u0000\u0000"+
|
||||
"\u0000\u0000l\u0001\u0000\u0000\u0000\u0000n\u0001\u0000\u0000\u0000\u0000"+
|
||||
"p\u0001\u0000\u0000\u0000\u0000r\u0001\u0000\u0000\u0000\u0000t\u0001"+
|
||||
"\u0000\u0000\u0000\u0000v\u0001\u0000\u0000\u0000\u0000x\u0001\u0000\u0000"+
|
||||
"\u0000\u0000z\u0001\u0000\u0000\u0000\u0000|\u0001\u0000\u0000\u0000\u0001"+
|
||||
"\u008e\u0001\u0000\u0000\u0000\u0001\u0090\u0001\u0000\u0000\u0000\u0001"+
|
||||
"\u0092\u0001\u0000\u0000\u0000\u0001\u0094\u0001\u0000\u0000\u0000\u0002"+
|
||||
"\u0096\u0001\u0000\u0000\u0000\u0004\u009b\u0001\u0000\u0000\u0000\u0006"+
|
||||
"\u009e\u0001\u0000\u0000\u0000\b\u00a4\u0001\u0000\u0000\u0000\n\u00a7"+
|
||||
"\u0001\u0000\u0000\u0000\f\u00a9\u0001\u0000\u0000\u0000\u000e\u00ac\u0001"+
|
||||
"\u0000\u0000\u0000\u0010\u00ae\u0001\u0000\u0000\u0000\u0012\u00b0\u0001"+
|
||||
"\u0000\u0000\u0000\u0014\u00b2\u0001\u0000\u0000\u0000\u0016\u00b4\u0001"+
|
||||
"\u0000\u0000\u0000\u0018\u00b6\u0001\u0000\u0000\u0000\u001a\u00b8\u0001"+
|
||||
"\u0000\u0000\u0000\u001c\u00ba\u0001\u0000\u0000\u0000\u001e\u00bc\u0001"+
|
||||
"\u0000\u0000\u0000 \u00be\u0001\u0000\u0000\u0000\"\u00c0\u0001\u0000"+
|
||||
"\u0000\u0000$\u00c2\u0001\u0000\u0000\u0000&\u00c4\u0001\u0000\u0000\u0000"+
|
||||
"(\u00c6\u0001\u0000\u0000\u0000*\u00c9\u0001\u0000\u0000\u0000,\u00cb"+
|
||||
"\u0001\u0000\u0000\u0000.\u00ce\u0001\u0000\u0000\u00000\u00d1\u0001\u0000"+
|
||||
"\u0000\u00002\u00d3\u0001\u0000\u0000\u00004\u00d6\u0001\u0000\u0000\u0000"+
|
||||
"6\u00d8\u0001\u0000\u0000\u00008\u00db\u0001\u0000\u0000\u0000:\u00dd"+
|
||||
"\u0001\u0000\u0000\u0000<\u00e0\u0001\u0000\u0000\u0000>\u00e3\u0001\u0000"+
|
||||
"\u0000\u0000@\u00e6\u0001\u0000\u0000\u0000B\u00e9\u0001\u0000\u0000\u0000"+
|
||||
"D\u00eb\u0001\u0000\u0000\u0000F\u00ee\u0001\u0000\u0000\u0000H\u00f1"+
|
||||
"\u0001\u0000\u0000\u0000J\u00f3\u0001\u0000\u0000\u0000L\u00f6\u0001\u0000"+
|
||||
"\u0000\u0000N\u00f8\u0001\u0000\u0000\u0000P\u00fd\u0001\u0000\u0000\u0000"+
|
||||
"R\u0102\u0001\u0000\u0000\u0000T\u0106\u0001\u0000\u0000\u0000V\u0109"+
|
||||
"\u0001\u0000\u0000\u0000X\u010d\u0001\u0000\u0000\u0000Z\u0112\u0001\u0000"+
|
||||
"\u0000\u0000\\\u0118\u0001\u0000\u0000\u0000^\u011c\u0001\u0000\u0000"+
|
||||
"\u0000`\u0121\u0001\u0000\u0000\u0000b\u0123\u0001\u0000\u0000\u0000d"+
|
||||
"\u012b\u0001\u0000\u0000\u0000f\u012e\u0001\u0000\u0000\u0000h\u0131\u0001"+
|
||||
"\u0000\u0000\u0000j\u0134\u0001\u0000\u0000\u0000l\u0137\u0001\u0000\u0000"+
|
||||
"\u0000n\u013a\u0001\u0000\u0000\u0000p\u013f\u0001\u0000\u0000\u0000r"+
|
||||
"\u014b\u0001\u0000\u0000\u0000t\u017a\u0001\u0000\u0000\u0000v\u017d\u0001"+
|
||||
"\u0000\u0000\u0000x\u0186\u0001\u0000\u0000\u0000z\u0188\u0001\u0000\u0000"+
|
||||
"\u0000|\u0193\u0001\u0000\u0000\u0000~\u019e\u0001\u0000\u0000\u0000\u0080"+
|
||||
"\u01a0\u0001\u0000\u0000\u0000\u0082\u01a2\u0001\u0000\u0000\u0000\u0084"+
|
||||
"\u01bc\u0001\u0000\u0000\u0000\u0086\u01be\u0001\u0000\u0000\u0000\u0088"+
|
||||
"\u01c0\u0001\u0000\u0000\u0000\u008a\u01c3\u0001\u0000\u0000\u0000\u008c"+
|
||||
"\u01c5\u0001\u0000\u0000\u0000\u008e\u01c7\u0001\u0000\u0000\u0000\u0090"+
|
||||
"\u01ca\u0001\u0000\u0000\u0000\u0092\u01d1\u0001\u0000\u0000\u0000\u0094"+
|
||||
"\u01d3\u0001\u0000\u0000\u0000\u0096\u0097\u0005;\u0000\u0000\u0097\u0003"+
|
||||
"\u0001\u0000\u0000\u0000\u0098\u0099\u0005\r\u0000\u0000\u0099\u009c\u0005"+
|
||||
"\n\u0000\u0000\u009a\u009c\u0007\u0000\u0000\u0000\u009b\u0098\u0001\u0000"+
|
||||
"\u0000\u0000\u009b\u009a\u0001\u0000\u0000\u0000\u009c\u0005\u0001\u0000"+
|
||||
"\u0000\u0000\u009d\u009f\u0007\u0001\u0000\u0000\u009e\u009d\u0001\u0000"+
|
||||
"\u0000\u0000\u009f\u00a0\u0001\u0000\u0000\u0000\u00a0\u009e\u0001\u0000"+
|
||||
"\u0000\u0000\u00a0\u00a1\u0001\u0000\u0000\u0000\u00a1\u00a2\u0001\u0000"+
|
||||
"\u0000\u0000\u00a2\u00a3\u0006\u0002\u0000\u0000\u00a3\u0007\u0001\u0000"+
|
||||
"\u0000\u0000\u00a4\u00a5\u0005+\u0000\u0000\u00a5\u00a6\u0005+\u0000\u0000"+
|
||||
"\u00a6\t\u0001\u0000\u0000\u0000\u00a7\u00a8\u0005+\u0000\u0000\u00a8"+
|
||||
"\u000b\u0001\u0000\u0000\u0000\u00a9\u00aa\u0005-\u0000\u0000\u00aa\u00ab"+
|
||||
"\u0005-\u0000\u0000\u00ab\r\u0001\u0000\u0000\u0000\u00ac\u00ad\u0005"+
|
||||
"-\u0000\u0000\u00ad\u000f\u0001\u0000\u0000\u0000\u00ae\u00af\u0005:\u0000"+
|
||||
"\u0000\u00af\u0011\u0001\u0000\u0000\u0000\u00b0\u00b1\u0005.\u0000\u0000"+
|
||||
"\u00b1\u0013\u0001\u0000\u0000\u0000\u00b2\u00b3\u0005,\u0000\u0000\u00b3"+
|
||||
"\u0015\u0001\u0000\u0000\u0000\u00b4\u00b5\u0005*\u0000\u0000\u00b5\u0017"+
|
||||
"\u0001\u0000\u0000\u0000\u00b6\u00b7\u0005/\u0000\u0000\u00b7\u0019\u0001"+
|
||||
"\u0000\u0000\u0000\u00b8\u00b9\u0005%\u0000\u0000\u00b9\u001b\u0001\u0000"+
|
||||
"\u0000\u0000\u00ba\u00bb\u0005(\u0000\u0000\u00bb\u001d\u0001\u0000\u0000"+
|
||||
"\u0000\u00bc\u00bd\u0005)\u0000\u0000\u00bd\u001f\u0001\u0000\u0000\u0000"+
|
||||
"\u00be\u00bf\u0005[\u0000\u0000\u00bf!\u0001\u0000\u0000\u0000\u00c0\u00c1"+
|
||||
"\u0005]\u0000\u0000\u00c1#\u0001\u0000\u0000\u0000\u00c2\u00c3\u0005#"+
|
||||
"\u0000\u0000\u00c3%\u0001\u0000\u0000\u0000\u00c4\u00c5\u0005@\u0000\u0000"+
|
||||
"\u00c5\'\u0001\u0000\u0000\u0000\u00c6\u00c7\u0005^\u0000\u0000\u00c7"+
|
||||
"\u00c8\u0005[\u0000\u0000\u00c8)\u0001\u0000\u0000\u0000\u00c9\u00ca\u0005"+
|
||||
"^\u0000\u0000\u00ca+\u0001\u0000\u0000\u0000\u00cb\u00cc\u0005!\u0000"+
|
||||
"\u0000\u00cc\u00cd\u0005=\u0000\u0000\u00cd-\u0001\u0000\u0000\u0000\u00ce"+
|
||||
"\u00cf\u0005!\u0000\u0000\u00cf\u00d0\u0005[\u0000\u0000\u00d0/\u0001"+
|
||||
"\u0000\u0000\u0000\u00d1\u00d2\u0005!\u0000\u0000\u00d21\u0001\u0000\u0000"+
|
||||
"\u0000\u00d3\u00d4\u0005=\u0000\u0000\u00d4\u00d5\u0005=\u0000\u0000\u00d5"+
|
||||
"3\u0001\u0000\u0000\u0000\u00d6\u00d7\u0005=\u0000\u0000\u00d75\u0001"+
|
||||
"\u0000\u0000\u0000\u00d8\u00d9\u0005&\u0000\u0000\u00d9\u00da\u0005&\u0000"+
|
||||
"\u0000\u00da7\u0001\u0000\u0000\u0000\u00db\u00dc\u0005&\u0000\u0000\u00dc"+
|
||||
"9\u0001\u0000\u0000\u0000\u00dd\u00de\u0005|\u0000\u0000\u00de\u00df\u0005"+
|
||||
"|\u0000\u0000\u00df;\u0001\u0000\u0000\u0000\u00e0\u00e1\u0005?\u0000"+
|
||||
"\u0000\u00e1\u00e2\u0005[\u0000\u0000\u00e2=\u0001\u0000\u0000\u0000\u00e3"+
|
||||
"\u00e4\u0005?\u0000\u0000\u00e4\u00e5\u0005:\u0000\u0000\u00e5?\u0001"+
|
||||
"\u0000\u0000\u0000\u00e6\u00e7\u0005?\u0000\u0000\u00e7\u00e8\u0005.\u0000"+
|
||||
"\u0000\u00e8A\u0001\u0000\u0000\u0000\u00e9\u00ea\u0005?\u0000\u0000\u00ea"+
|
||||
"C\u0001\u0000\u0000\u0000\u00eb\u00ec\u0005$\u0000\u0000\u00ec\u00ed\u0005"+
|
||||
"[\u0000\u0000\u00edE\u0001\u0000\u0000\u0000\u00ee\u00ef\u0005>\u0000"+
|
||||
"\u0000\u00ef\u00f0\u0005=\u0000\u0000\u00f0G\u0001\u0000\u0000\u0000\u00f1"+
|
||||
"\u00f2\u0005>\u0000\u0000\u00f2I\u0001\u0000\u0000\u0000\u00f3\u00f4\u0005"+
|
||||
"<\u0000\u0000\u00f4\u00f5\u0005=\u0000\u0000\u00f5K\u0001\u0000\u0000"+
|
||||
"\u0000\u00f6\u00f7\u0005<\u0000\u0000\u00f7M\u0001\u0000\u0000\u0000\u00f8"+
|
||||
"\u00f9\u0005{\u0000\u0000\u00f9\u00fa\u0006&\u0001\u0000\u00fa\u00fb\u0001"+
|
||||
"\u0000\u0000\u0000\u00fb\u00fc\u0006&\u0002\u0000\u00fcO\u0001\u0000\u0000"+
|
||||
"\u0000\u00fd\u00fe\u0005}\u0000\u0000\u00fe\u00ff\u0006\'\u0003\u0000"+
|
||||
"\u00ff\u0100\u0001\u0000\u0000\u0000\u0100\u0101\u0006\'\u0004\u0000\u0101"+
|
||||
"Q\u0001\u0000\u0000\u0000\u0102\u0103\u0005`\u0000\u0000\u0103\u0104\u0001"+
|
||||
"\u0000\u0000\u0000\u0104\u0105\u0006(\u0005\u0000\u0105S\u0001\u0000\u0000"+
|
||||
"\u0000\u0106\u0107\u0005o\u0000\u0000\u0107\u0108\u0005r\u0000\u0000\u0108"+
|
||||
"U\u0001\u0000\u0000\u0000\u0109\u010a\u0005a\u0000\u0000\u010a\u010b\u0005"+
|
||||
"n\u0000\u0000\u010b\u010c\u0005d\u0000\u0000\u010cW\u0001\u0000\u0000"+
|
||||
"\u0000\u010d\u010e\u0005t\u0000\u0000\u010e\u010f\u0005r\u0000\u0000\u010f"+
|
||||
"\u0110\u0005u\u0000\u0000\u0110\u0111\u0005e\u0000\u0000\u0111Y\u0001"+
|
||||
"\u0000\u0000\u0000\u0112\u0113\u0005f\u0000\u0000\u0113\u0114\u0005a\u0000"+
|
||||
"\u0000\u0114\u0115\u0005l\u0000\u0000\u0115\u0116\u0005s\u0000\u0000\u0116"+
|
||||
"\u0117\u0005e\u0000\u0000\u0117[\u0001\u0000\u0000\u0000\u0118\u0119\u0005"+
|
||||
"n\u0000\u0000\u0119\u011a\u0005e\u0000\u0000\u011a\u011b\u0005w\u0000"+
|
||||
"\u0000\u011b]\u0001\u0000\u0000\u0000\u011c\u011d\u0005n\u0000\u0000\u011d"+
|
||||
"\u011e\u0005u\u0000\u0000\u011e\u011f\u0005l\u0000\u0000\u011f\u0120\u0005"+
|
||||
"l\u0000\u0000\u0120_\u0001\u0000\u0000\u0000\u0121\u0122\u0005T\u0000"+
|
||||
"\u0000\u0122a\u0001\u0000\u0000\u0000\u0123\u0124\u0005m\u0000\u0000\u0124"+
|
||||
"\u0125\u0005a\u0000\u0000\u0125\u0126\u0005t\u0000\u0000\u0126\u0127\u0005"+
|
||||
"c\u0000\u0000\u0127\u0128\u0005h\u0000\u0000\u0128\u0129\u0005e\u0000"+
|
||||
"\u0000\u0129\u012a\u0005s\u0000\u0000\u012ac\u0001\u0000\u0000\u0000\u012b"+
|
||||
"\u012c\u0005g\u0000\u0000\u012c\u012d\u0005t\u0000\u0000\u012de\u0001"+
|
||||
"\u0000\u0000\u0000\u012e\u012f\u0005g\u0000\u0000\u012f\u0130\u0005e\u0000"+
|
||||
"\u0000\u0130g\u0001\u0000\u0000\u0000\u0131\u0132\u0005l\u0000\u0000\u0132"+
|
||||
"\u0133\u0005e\u0000\u0000\u0133i\u0001\u0000\u0000\u0000\u0134\u0135\u0005"+
|
||||
"l\u0000\u0000\u0135\u0136\u0005t\u0000\u0000\u0136k\u0001\u0000\u0000"+
|
||||
"\u0000\u0137\u0138\u0005e\u0000\u0000\u0138\u0139\u0005q\u0000\u0000\u0139"+
|
||||
"m\u0001\u0000\u0000\u0000\u013a\u013b\u0005n\u0000\u0000\u013b\u013c\u0005"+
|
||||
"e\u0000\u0000\u013co\u0001\u0000\u0000\u0000\u013d\u0140\u0003\u008aD"+
|
||||
"\u0000\u013e\u0140\u0005_\u0000\u0000\u013f\u013d\u0001\u0000\u0000\u0000"+
|
||||
"\u013f\u013e\u0001\u0000\u0000\u0000\u0140\u0146\u0001\u0000\u0000\u0000"+
|
||||
"\u0141\u0145\u0003\u008aD\u0000\u0142\u0145\u0003\u008cE\u0000\u0143\u0145"+
|
||||
"\u0007\u0002\u0000\u0000\u0144\u0141\u0001\u0000\u0000\u0000\u0144\u0142"+
|
||||
"\u0001\u0000\u0000\u0000\u0144\u0143\u0001\u0000\u0000\u0000\u0145\u0148"+
|
||||
"\u0001\u0000\u0000\u0000\u0146\u0144\u0001\u0000\u0000\u0000\u0146\u0147"+
|
||||
"\u0001\u0000\u0000\u0000\u0147q\u0001\u0000\u0000\u0000\u0148\u0146\u0001"+
|
||||
"\u0000\u0000\u0000\u0149\u014c\u0003t9\u0000\u014a\u014c\u0003v:\u0000"+
|
||||
"\u014b\u0149\u0001\u0000\u0000\u0000\u014b\u014a\u0001\u0000\u0000\u0000"+
|
||||
"\u014cs\u0001\u0000\u0000\u0000\u014d\u014f\u0005.\u0000\u0000\u014e\u0150"+
|
||||
"\u0003\u0082@\u0000\u014f\u014e\u0001\u0000\u0000\u0000\u0150\u0151\u0001"+
|
||||
"\u0000\u0000\u0000\u0151\u014f\u0001\u0000\u0000\u0000\u0151\u0152\u0001"+
|
||||
"\u0000\u0000\u0000\u0152\u0154\u0001\u0000\u0000\u0000\u0153\u0155\u0003"+
|
||||
"\u0084A\u0000\u0154\u0153\u0001\u0000\u0000\u0000\u0154\u0155\u0001\u0000"+
|
||||
"\u0000\u0000\u0155\u0157\u0001\u0000\u0000\u0000\u0156\u0158\u0003\u0088"+
|
||||
"C\u0000\u0157\u0156\u0001\u0000\u0000\u0000\u0157\u0158\u0001\u0000\u0000"+
|
||||
"\u0000\u0158\u017b\u0001\u0000\u0000\u0000\u0159\u015b\u0003\u0082@\u0000"+
|
||||
"\u015a\u0159\u0001\u0000\u0000\u0000\u015b\u015c\u0001\u0000\u0000\u0000"+
|
||||
"\u015c\u015a\u0001\u0000\u0000\u0000\u015c\u015d\u0001\u0000\u0000\u0000"+
|
||||
"\u015d\u015e\u0001\u0000\u0000\u0000\u015e\u0160\u0005.\u0000\u0000\u015f"+
|
||||
"\u0161\u0003\u0082@\u0000\u0160\u015f\u0001\u0000\u0000\u0000\u0161\u0162"+
|
||||
"\u0001\u0000\u0000\u0000\u0162\u0160\u0001\u0000\u0000\u0000\u0162\u0163"+
|
||||
"\u0001\u0000\u0000\u0000\u0163\u0165\u0001\u0000\u0000\u0000\u0164\u0166"+
|
||||
"\u0003\u0084A\u0000\u0165\u0164\u0001\u0000\u0000\u0000\u0165\u0166\u0001"+
|
||||
"\u0000\u0000\u0000\u0166\u0168\u0001\u0000\u0000\u0000\u0167\u0169\u0003"+
|
||||
"\u0088C\u0000\u0168\u0167\u0001\u0000\u0000\u0000\u0168\u0169\u0001\u0000"+
|
||||
"\u0000\u0000\u0169\u017b\u0001\u0000\u0000\u0000\u016a\u016c\u0003\u0082"+
|
||||
"@\u0000\u016b\u016a\u0001\u0000\u0000\u0000\u016c\u016d\u0001\u0000\u0000"+
|
||||
"\u0000\u016d\u016b\u0001\u0000\u0000\u0000\u016d\u016e\u0001\u0000\u0000"+
|
||||
"\u0000\u016e\u016f\u0001\u0000\u0000\u0000\u016f\u0171\u0003\u0084A\u0000"+
|
||||
"\u0170\u0172\u0003\u0088C\u0000\u0171\u0170\u0001\u0000\u0000\u0000\u0171"+
|
||||
"\u0172\u0001\u0000\u0000\u0000\u0172\u017b\u0001\u0000\u0000\u0000\u0173"+
|
||||
"\u0175\u0003\u0082@\u0000\u0174\u0173\u0001\u0000\u0000\u0000\u0175\u0176"+
|
||||
"\u0001\u0000\u0000\u0000\u0176\u0174\u0001\u0000\u0000\u0000\u0176\u0177"+
|
||||
"\u0001\u0000\u0000\u0000\u0177\u0178\u0001\u0000\u0000\u0000\u0178\u0179"+
|
||||
"\u0003\u0088C\u0000\u0179\u017b\u0001\u0000\u0000\u0000\u017a\u014d\u0001"+
|
||||
"\u0000\u0000\u0000\u017a\u015a\u0001\u0000\u0000\u0000\u017a\u016b\u0001"+
|
||||
"\u0000\u0000\u0000\u017a\u0174\u0001\u0000\u0000\u0000\u017bu\u0001\u0000"+
|
||||
"\u0000\u0000\u017c\u017e\u0003\u0082@\u0000\u017d\u017c\u0001\u0000\u0000"+
|
||||
"\u0000\u017e\u017f\u0001\u0000\u0000\u0000\u017f\u017d\u0001\u0000\u0000"+
|
||||
"\u0000\u017f\u0180\u0001\u0000\u0000\u0000\u0180\u0182\u0001\u0000\u0000"+
|
||||
"\u0000\u0181\u0183\u0003~>\u0000\u0182\u0181\u0001\u0000\u0000\u0000\u0182"+
|
||||
"\u0183\u0001\u0000\u0000\u0000\u0183w\u0001\u0000\u0000\u0000\u0184\u0187"+
|
||||
"\u0003z<\u0000\u0185\u0187\u0003|=\u0000\u0186\u0184\u0001\u0000\u0000"+
|
||||
"\u0000\u0186\u0185\u0001\u0000\u0000\u0000\u0187y\u0001\u0000\u0000\u0000"+
|
||||
"\u0188\u018e\u0005\'\u0000\u0000\u0189\u018a\u0005\'\u0000\u0000\u018a"+
|
||||
"\u018d\u0005\'\u0000\u0000\u018b\u018d\b\u0003\u0000\u0000\u018c\u0189"+
|
||||
"\u0001\u0000\u0000\u0000\u018c\u018b\u0001\u0000\u0000\u0000\u018d\u0190"+
|
||||
"\u0001\u0000\u0000\u0000\u018e\u018c\u0001\u0000\u0000\u0000\u018e\u018f"+
|
||||
"\u0001\u0000\u0000\u0000\u018f\u0191\u0001\u0000\u0000\u0000\u0190\u018e"+
|
||||
"\u0001\u0000\u0000\u0000\u0191\u0192\u0005\'\u0000\u0000\u0192{\u0001"+
|
||||
"\u0000\u0000\u0000\u0193\u0199\u0005\"\u0000\u0000\u0194\u0195\u0005\""+
|
||||
"\u0000\u0000\u0195\u0198\u0005\"\u0000\u0000\u0196\u0198\b\u0004\u0000"+
|
||||
"\u0000\u0197\u0194\u0001\u0000\u0000\u0000\u0197\u0196\u0001\u0000\u0000"+
|
||||
"\u0000\u0198\u019b\u0001\u0000\u0000\u0000\u0199\u0197\u0001\u0000\u0000"+
|
||||
"\u0000\u0199\u019a\u0001\u0000\u0000\u0000\u019a\u019c\u0001\u0000\u0000"+
|
||||
"\u0000\u019b\u0199\u0001\u0000\u0000\u0000\u019c\u019d\u0005\"\u0000\u0000"+
|
||||
"\u019d}\u0001\u0000\u0000\u0000\u019e\u019f\u0007\u0005\u0000\u0000\u019f"+
|
||||
"\u007f\u0001\u0000\u0000\u0000\u01a0\u01a1\u0007\u0006\u0000\u0000\u01a1"+
|
||||
"\u0081\u0001\u0000\u0000\u0000\u01a2\u01a3\u0007\u0007\u0000\u0000\u01a3"+
|
||||
"\u0083\u0001\u0000\u0000\u0000\u01a4\u01a8\u0005e\u0000\u0000\u01a5\u01a7"+
|
||||
"\u0003\u0086B\u0000\u01a6\u01a5\u0001\u0000\u0000\u0000\u01a7\u01aa\u0001"+
|
||||
"\u0000\u0000\u0000\u01a8\u01a6\u0001\u0000\u0000\u0000\u01a8\u01a9\u0001"+
|
||||
"\u0000\u0000\u0000\u01a9\u01ac\u0001\u0000\u0000\u0000\u01aa\u01a8\u0001"+
|
||||
"\u0000\u0000\u0000\u01ab\u01ad\u0003\u0082@\u0000\u01ac\u01ab\u0001\u0000"+
|
||||
"\u0000\u0000\u01ad\u01ae\u0001\u0000\u0000\u0000\u01ae\u01ac\u0001\u0000"+
|
||||
"\u0000\u0000\u01ae\u01af\u0001\u0000\u0000\u0000\u01af\u01bd\u0001\u0000"+
|
||||
"\u0000\u0000\u01b0\u01b4\u0005E\u0000\u0000\u01b1\u01b3\u0003\u0086B\u0000"+
|
||||
"\u01b2\u01b1\u0001\u0000\u0000\u0000\u01b3\u01b6\u0001\u0000\u0000\u0000"+
|
||||
"\u01b4\u01b2\u0001\u0000\u0000\u0000\u01b4\u01b5\u0001\u0000\u0000\u0000"+
|
||||
"\u01b5\u01b8\u0001\u0000\u0000\u0000\u01b6\u01b4\u0001\u0000\u0000\u0000"+
|
||||
"\u01b7\u01b9\u0003\u0082@\u0000\u01b8\u01b7\u0001\u0000\u0000\u0000\u01b9"+
|
||||
"\u01ba\u0001\u0000\u0000\u0000\u01ba\u01b8\u0001\u0000\u0000\u0000\u01ba"+
|
||||
"\u01bb\u0001\u0000\u0000\u0000\u01bb\u01bd\u0001\u0000\u0000\u0000\u01bc"+
|
||||
"\u01a4\u0001\u0000\u0000\u0000\u01bc\u01b0\u0001\u0000\u0000\u0000\u01bd"+
|
||||
"\u0085\u0001\u0000\u0000\u0000\u01be\u01bf\u0007\b\u0000\u0000\u01bf\u0087"+
|
||||
"\u0001\u0000\u0000\u0000\u01c0\u01c1\u0007\t\u0000\u0000\u01c1\u0089\u0001"+
|
||||
"\u0000\u0000\u0000\u01c2\u01c4\u0007\n\u0000\u0000\u01c3\u01c2\u0001\u0000"+
|
||||
"\u0000\u0000\u01c4\u008b\u0001\u0000\u0000\u0000\u01c5\u01c6\u0007\u0007"+
|
||||
"\u0000\u0000\u01c6\u008d\u0001\u0000\u0000\u0000\u01c7\u01c8\u0005`\u0000"+
|
||||
"\u0000\u01c8\u01c9\u0005`\u0000\u0000\u01c9\u008f\u0001\u0000\u0000\u0000"+
|
||||
"\u01ca\u01cb\u0005#\u0000\u0000\u01cb\u01cc\u0005{\u0000\u0000\u01cc\u01cd"+
|
||||
"\u0001\u0000\u0000\u0000\u01cd\u01ce\u0006G\u0006\u0000\u01ce\u01cf\u0001"+
|
||||
"\u0000\u0000\u0000\u01cf\u01d0\u0006G\u0002\u0000\u01d0\u0091\u0001\u0000"+
|
||||
"\u0000\u0000\u01d1\u01d2\b\u000b\u0000\u0000\u01d2\u0093\u0001\u0000\u0000"+
|
||||
"\u0000\u01d3\u01d4\u0005`\u0000\u0000\u01d4\u01d5\u0001\u0000\u0000\u0000"+
|
||||
"\u01d5\u01d6\u0006I\u0007\u0000\u01d6\u01d7\u0006I\u0004\u0000\u01d7\u0095"+
|
||||
"\u0001\u0000\u0000\u0000 \u0000\u0001\u009b\u00a0\u013f\u0144\u0146\u014b"+
|
||||
"\u0151\u0154\u0157\u015c\u0162\u0165\u0168\u016d\u0171\u0176\u017a\u017f"+
|
||||
"\u0182\u0186\u018c\u018e\u0197\u0199\u01a8\u01ae\u01b4\u01ba\u01bc\u01c3"+
|
||||
"\b\u0000\u0001\u0000\u0001&\u0000\u0005\u0000\u0000\u0001\'\u0001\u0004"+
|
||||
"\u0000\u0000\u0005\u0001\u0000\u0001G\u0002\u0007(\u0000";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
|
||||
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
|
||||
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,352 @@
|
||||
// Generated from SpelParser.g4 by ANTLR 4.13.1
|
||||
package org.springframework.ide.vscode.parser.spel;
|
||||
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.antlr.v4.runtime.tree.ErrorNode;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
|
||||
/**
|
||||
* This class provides an empty implementation of {@link SpelParserListener},
|
||||
* which can be extended to create a listener which only needs to handle a subset
|
||||
* of the available methods.
|
||||
*/
|
||||
@SuppressWarnings("CheckReturnValue")
|
||||
public class SpelParserBaseListener implements SpelParserListener {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterScript(SpelParser.ScriptContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitScript(SpelParser.ScriptContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterSpelExpr(SpelParser.SpelExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitSpelExpr(SpelParser.SpelExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterNode(SpelParser.NodeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitNode(SpelParser.NodeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterNonDottedNode(SpelParser.NonDottedNodeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitNonDottedNode(SpelParser.NonDottedNodeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterDottedNode(SpelParser.DottedNodeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitDottedNode(SpelParser.DottedNodeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterFunctionOrVar(SpelParser.FunctionOrVarContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitFunctionOrVar(SpelParser.FunctionOrVarContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterMethodArgs(SpelParser.MethodArgsContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitMethodArgs(SpelParser.MethodArgsContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterArgs(SpelParser.ArgsContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitArgs(SpelParser.ArgsContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterMethodOrProperty(SpelParser.MethodOrPropertyContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitMethodOrProperty(SpelParser.MethodOrPropertyContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterProjection(SpelParser.ProjectionContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitProjection(SpelParser.ProjectionContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterSelection(SpelParser.SelectionContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitSelection(SpelParser.SelectionContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterStartNode(SpelParser.StartNodeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitStartNode(SpelParser.StartNodeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterLiteral(SpelParser.LiteralContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitLiteral(SpelParser.LiteralContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterParenspelExpr(SpelParser.ParenspelExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitParenspelExpr(SpelParser.ParenspelExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterTypeReference(SpelParser.TypeReferenceContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitTypeReference(SpelParser.TypeReferenceContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterPossiblyQualifiedId(SpelParser.PossiblyQualifiedIdContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitPossiblyQualifiedId(SpelParser.PossiblyQualifiedIdContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterNullReference(SpelParser.NullReferenceContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitNullReference(SpelParser.NullReferenceContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterConstructorReference(SpelParser.ConstructorReferenceContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitConstructorReference(SpelParser.ConstructorReferenceContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterConstructorArgs(SpelParser.ConstructorArgsContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitConstructorArgs(SpelParser.ConstructorArgsContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterInlineListOrMap(SpelParser.InlineListOrMapContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitInlineListOrMap(SpelParser.InlineListOrMapContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterListBindings(SpelParser.ListBindingsContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitListBindings(SpelParser.ListBindingsContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterListBinding(SpelParser.ListBindingContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitListBinding(SpelParser.ListBindingContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterMapBindings(SpelParser.MapBindingsContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitMapBindings(SpelParser.MapBindingsContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterMapBinding(SpelParser.MapBindingContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitMapBinding(SpelParser.MapBindingContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterBeanReference(SpelParser.BeanReferenceContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitBeanReference(SpelParser.BeanReferenceContext ctx) { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterEveryRule(ParserRuleContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitEveryRule(ParserRuleContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void visitTerminal(TerminalNode node) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void visitErrorNode(ErrorNode node) { }
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
// Generated from SpelParser.g4 by ANTLR 4.13.1
|
||||
package org.springframework.ide.vscode.parser.spel;
|
||||
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
*******************************************************************************/
|
||||
|
||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
||||
|
||||
/**
|
||||
* This interface defines a complete listener for a parse tree produced by
|
||||
* {@link SpelParser}.
|
||||
*/
|
||||
public interface SpelParserListener extends ParseTreeListener {
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#script}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterScript(SpelParser.ScriptContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#script}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitScript(SpelParser.ScriptContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#spelExpr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterSpelExpr(SpelParser.SpelExprContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#spelExpr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitSpelExpr(SpelParser.SpelExprContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#node}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterNode(SpelParser.NodeContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#node}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitNode(SpelParser.NodeContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#nonDottedNode}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterNonDottedNode(SpelParser.NonDottedNodeContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#nonDottedNode}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitNonDottedNode(SpelParser.NonDottedNodeContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#dottedNode}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterDottedNode(SpelParser.DottedNodeContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#dottedNode}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitDottedNode(SpelParser.DottedNodeContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#functionOrVar}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterFunctionOrVar(SpelParser.FunctionOrVarContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#functionOrVar}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitFunctionOrVar(SpelParser.FunctionOrVarContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#methodArgs}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterMethodArgs(SpelParser.MethodArgsContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#methodArgs}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitMethodArgs(SpelParser.MethodArgsContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#args}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterArgs(SpelParser.ArgsContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#args}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitArgs(SpelParser.ArgsContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#methodOrProperty}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterMethodOrProperty(SpelParser.MethodOrPropertyContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#methodOrProperty}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitMethodOrProperty(SpelParser.MethodOrPropertyContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#projection}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterProjection(SpelParser.ProjectionContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#projection}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitProjection(SpelParser.ProjectionContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#selection}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterSelection(SpelParser.SelectionContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#selection}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitSelection(SpelParser.SelectionContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#startNode}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterStartNode(SpelParser.StartNodeContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#startNode}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitStartNode(SpelParser.StartNodeContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#literal}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterLiteral(SpelParser.LiteralContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#literal}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitLiteral(SpelParser.LiteralContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#parenspelExpr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterParenspelExpr(SpelParser.ParenspelExprContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#parenspelExpr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitParenspelExpr(SpelParser.ParenspelExprContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#typeReference}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterTypeReference(SpelParser.TypeReferenceContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#typeReference}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitTypeReference(SpelParser.TypeReferenceContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#possiblyQualifiedId}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterPossiblyQualifiedId(SpelParser.PossiblyQualifiedIdContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#possiblyQualifiedId}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitPossiblyQualifiedId(SpelParser.PossiblyQualifiedIdContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#nullReference}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterNullReference(SpelParser.NullReferenceContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#nullReference}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitNullReference(SpelParser.NullReferenceContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#constructorReference}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterConstructorReference(SpelParser.ConstructorReferenceContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#constructorReference}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitConstructorReference(SpelParser.ConstructorReferenceContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#constructorArgs}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterConstructorArgs(SpelParser.ConstructorArgsContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#constructorArgs}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitConstructorArgs(SpelParser.ConstructorArgsContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#inlineListOrMap}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterInlineListOrMap(SpelParser.InlineListOrMapContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#inlineListOrMap}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitInlineListOrMap(SpelParser.InlineListOrMapContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#listBindings}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterListBindings(SpelParser.ListBindingsContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#listBindings}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitListBindings(SpelParser.ListBindingsContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#listBinding}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterListBinding(SpelParser.ListBindingContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#listBinding}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitListBinding(SpelParser.ListBindingContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#mapBindings}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterMapBindings(SpelParser.MapBindingsContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#mapBindings}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitMapBindings(SpelParser.MapBindingsContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#mapBinding}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterMapBinding(SpelParser.MapBindingContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#mapBinding}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitMapBinding(SpelParser.MapBindingContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SpelParser#beanReference}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterBeanReference(SpelParser.BeanReferenceContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SpelParser#beanReference}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitBeanReference(SpelParser.BeanReferenceContext ctx);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,7 @@ import org.springframework.ide.vscode.boot.java.data.jpa.queries.JpqlSupportStat
|
||||
import org.springframework.ide.vscode.boot.java.links.JavaElementLocationProvider;
|
||||
import org.springframework.ide.vscode.boot.java.links.SourceLinks;
|
||||
import org.springframework.ide.vscode.boot.java.livehover.v2.SpringProcessLiveDataProvider;
|
||||
import org.springframework.ide.vscode.boot.java.spel.SpelReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
|
||||
import org.springframework.ide.vscode.boot.maven.PomLanguageServerComponents;
|
||||
import org.springframework.ide.vscode.boot.metadata.ProjectBasedPropertyIndexProvider;
|
||||
@@ -126,7 +127,7 @@ public class BootLanguageServerInitializer implements InitializingBean {
|
||||
List<LanguageServerComponents> componentsList = List.of(
|
||||
new BootPropertiesLanguageServerComponents(server, params, javaElementLocationProvider, parser, yamlStructureProvider, yamlAssistContextProvider, sourceLinks),
|
||||
new BootJavaLanguageServerComponents(appContext),
|
||||
new SpringXMLLanguageServerComponents(server, springIndexer, params, config),
|
||||
new SpringXMLLanguageServerComponents(server, springIndexer, params, config, appContext.getBean(SpelReconciler.class)),
|
||||
new SpringFactoriesLanguageServerComponents(projectFinder, springIndexer, config),
|
||||
new PomLanguageServerComponents(server, projectFinder, params.projectObserver, appContext.getBean(SpringProjectsProvider.class)),
|
||||
new JpaQueryPropertiesLanguageServerComponents(server.getTextDocumentService(), projectFinder, appContext.getBean(JpqlSemanticTokens.class),
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.springframework.ide.vscode.boot.java.data.jpa.queries.QueryJdtAstReco
|
||||
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;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.AutowiredFieldIntoConstructorParameterReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.BeanMethodNotPublicReconciler;
|
||||
@@ -41,15 +40,15 @@ import org.springframework.ide.vscode.boot.java.reconcilers.UnnecessarySpringExt
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.WebSecurityConfigurerAdapterReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.semantictokens.EmbeddedLanguagesSemanticTokensSupport;
|
||||
import org.springframework.ide.vscode.boot.java.semantictokens.JavaSemanticTokensProvider;
|
||||
import org.springframework.ide.vscode.boot.java.spel.JdtSpelReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.spel.JdtSpelSemanticTokensProvider;
|
||||
import org.springframework.ide.vscode.boot.java.spel.SpelReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.spel.SpelSemanticTokens;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class JdtConfig {
|
||||
|
||||
@Bean AnnotationNodeReconciler annotationNodeReconciler(BootJavaConfig config) {
|
||||
return new AnnotationNodeReconciler(config);
|
||||
}
|
||||
|
||||
@Bean BeanMethodNotPublicReconciler beanMethodNotPublicReconciler(SimpleLanguageServer server) {
|
||||
return new BeanMethodNotPublicReconciler(server.getQuickfixRegistry());
|
||||
}
|
||||
@@ -129,9 +128,17 @@ public class JdtConfig {
|
||||
@Bean QueryJdtAstReconciler dataQueryReconciler(HqlReconciler hqlReconciler, JpqlReconciler jpqlReconciler, SqlReconciler sqlReconciler) {
|
||||
return new QueryJdtAstReconciler(hqlReconciler, jpqlReconciler, sqlReconciler);
|
||||
}
|
||||
|
||||
|
||||
@Bean EmbeddedLanguagesSemanticTokensSupport embbededLanguagesSyntaxHighlighting(SimpleLanguageServer server, BootJavaConfig config) {
|
||||
return new EmbeddedLanguagesSemanticTokensSupport(server, config);
|
||||
}
|
||||
|
||||
@Bean JdtSpelSemanticTokensProvider jdtSpelSemanticTokensProvider(SpelSemanticTokens spelSemanticTokens) {
|
||||
return new JdtSpelSemanticTokensProvider(spelSemanticTokens);
|
||||
}
|
||||
|
||||
@Bean JdtSpelReconciler jdtSpelReconciler(SpelReconciler spelReconciler) {
|
||||
return new JdtSpelReconciler(spelReconciler);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*******************************************************************************
|
||||
* 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.app;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.ide.vscode.boot.java.spel.SpelReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.spel.SpelSemanticTokens;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class SpelConfig {
|
||||
|
||||
@Bean SpelSemanticTokens spelSemanticTokens() {
|
||||
return new SpelSemanticTokens();
|
||||
}
|
||||
|
||||
@Bean SpelReconciler spelReconciler(BootJavaConfig config) {
|
||||
SpelReconciler reconciler = new SpelReconciler();
|
||||
config.addListener(v -> reconciler.setEnabled(config.isSpelExpressionValidationEnabled()));
|
||||
return reconciler;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,6 +10,8 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.app;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.ide.vscode.boot.java.data.jpa.queries.HqlReconciler;
|
||||
@@ -19,6 +21,8 @@ import org.springframework.ide.vscode.boot.java.data.jpa.queries.JpqlSemanticTok
|
||||
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.boot.java.spel.SpelReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.spel.SpelSemanticTokens;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
|
||||
@@ -26,33 +30,33 @@ import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguage
|
||||
public class SpringDataConfig {
|
||||
|
||||
@Bean
|
||||
JpqlSemanticTokens jpqlSemanticTokens() {
|
||||
return new JpqlSemanticTokens();
|
||||
JpqlSemanticTokens jpqlSemanticTokens(Optional<SpelSemanticTokens> optSpelTokensProvider) {
|
||||
return new JpqlSemanticTokens(optSpelTokensProvider);
|
||||
}
|
||||
|
||||
@Bean
|
||||
HqlSemanticTokens hqlSemanticTokens() {
|
||||
return new HqlSemanticTokens();
|
||||
HqlSemanticTokens hqlSemanticTokens(Optional<SpelSemanticTokens> optSpelTokensProvider) {
|
||||
return new HqlSemanticTokens(optSpelTokensProvider);
|
||||
}
|
||||
|
||||
@Bean
|
||||
SqlSemanticTokens sqlSemanticTokens() {
|
||||
return new SqlSemanticTokens();
|
||||
SqlSemanticTokens sqlSemanticTokens(Optional<SpelSemanticTokens> optSpelTokensProvider) {
|
||||
return new SqlSemanticTokens(optSpelTokensProvider);
|
||||
}
|
||||
|
||||
@Bean
|
||||
HqlReconciler hqlReconciler() {
|
||||
return new HqlReconciler();
|
||||
HqlReconciler hqlReconciler(Optional<SpelReconciler> spelReconciler) {
|
||||
return new HqlReconciler(spelReconciler);
|
||||
}
|
||||
|
||||
@Bean
|
||||
JpqlReconciler jpqlReconciler() {
|
||||
return new JpqlReconciler();
|
||||
JpqlReconciler jpqlReconciler(Optional<SpelReconciler> spelReconciler) {
|
||||
return new JpqlReconciler(spelReconciler);
|
||||
}
|
||||
|
||||
@Bean
|
||||
SqlReconciler sqlReconciler() {
|
||||
return new SqlReconciler();
|
||||
SqlReconciler sqlReconciler(Optional<SpelReconciler> spelReconciler) {
|
||||
return new SqlReconciler(spelReconciler);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
package org.springframework.ide.vscode.boot.java.data.jpa.queries;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.antlr.v4.runtime.ANTLRErrorListener;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
@@ -22,13 +23,24 @@ 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.boot.java.handlers.Reconciler;
|
||||
import org.springframework.ide.vscode.boot.java.spel.SpelReconciler;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
|
||||
import org.springframework.ide.vscode.parser.hql.HqlBaseListener;
|
||||
import org.springframework.ide.vscode.parser.hql.HqlLexer;
|
||||
import org.springframework.ide.vscode.parser.hql.HqlParser;
|
||||
import org.springframework.ide.vscode.parser.jpql.JpqlParser;
|
||||
|
||||
public class HqlReconciler implements Reconciler {
|
||||
|
||||
private final Optional<SpelReconciler> spelReconciler;
|
||||
|
||||
public HqlReconciler(Optional<SpelReconciler> spelReconiler) {
|
||||
this.spelReconciler = spelReconiler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconcile(String text, int startPosition, IProblemCollector problemCollector) {
|
||||
@@ -36,6 +48,7 @@ public class HqlReconciler implements Reconciler {
|
||||
CommonTokenStream antlrTokens = new CommonTokenStream(lexer);
|
||||
HqlParser parser = new HqlParser(antlrTokens);
|
||||
|
||||
lexer.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
parser.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
|
||||
parser.addErrorListener(new ANTLRErrorListener() {
|
||||
@@ -69,6 +82,27 @@ public class HqlReconciler implements Reconciler {
|
||||
}
|
||||
});
|
||||
|
||||
// Reconcile embedded SPEL
|
||||
parser.addParseListener(new HqlBaseListener() {
|
||||
|
||||
private void processTerminal(TerminalNode node) {
|
||||
if (node.getSymbol().getType() == JpqlParser.SPEL) {
|
||||
spelReconciler.ifPresent(r -> JpqlReconciler.reconcileEmbeddedSpelNode(node, startPosition, r, problemCollector));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTerminal(TerminalNode node) {
|
||||
processTerminal(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitErrorNode(ErrorNode node) {
|
||||
processTerminal(node);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
parser.ql_statement();
|
||||
|
||||
}
|
||||
|
||||
@@ -10,11 +10,13 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.data.jpa.queries;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
@@ -22,6 +24,7 @@ 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.boot.java.spel.SpelSemanticTokens;
|
||||
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.hql.HqlBaseListener;
|
||||
@@ -35,21 +38,36 @@ import org.springframework.ide.vscode.parser.hql.HqlParser.SimplePathElementCont
|
||||
public class HqlSemanticTokens implements SemanticTokensDataProvider {
|
||||
|
||||
private static List<String> TOKEN_TYPES = List.of("keyword", "type", "class", "string", "number", "operator",
|
||||
"variable", "method", "parameter", "regexp");
|
||||
"variable", "method", "parameter");
|
||||
|
||||
private Optional<SpelSemanticTokens> optSpelTokens;
|
||||
|
||||
public HqlSemanticTokens(Optional<SpelSemanticTokens> optSpelTokens) {
|
||||
this.optSpelTokens = optSpelTokens;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTokenTypes() {
|
||||
return TOKEN_TYPES;
|
||||
LinkedHashSet<String> tokenTypes = new LinkedHashSet<>(TOKEN_TYPES);
|
||||
tokenTypes.addAll(optSpelTokens.map(s -> s.getTokenTypes()).orElse(Collections.emptyList()));
|
||||
return tokenTypes.stream().toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypeModifiers() {
|
||||
return optSpelTokens.map(s -> s.getTypeModifiers()).orElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SemanticTokenData> computeTokens(String text, int initialOffset) {
|
||||
HqlLexer lexer = new HqlLexer(CharStreams.fromString(text));
|
||||
CommonTokenStream antlrTokens = new CommonTokenStream(lexer);
|
||||
HqlParser parser = new HqlParser(antlrTokens);
|
||||
|
||||
HqlParser parser = new HqlParser(antlrTokens);
|
||||
Map<Token, String> semantics = new HashMap<>();
|
||||
List<SemanticTokenData> tokens = new ArrayList<>();
|
||||
|
||||
lexer.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
parser.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
|
||||
parser.addParseListener(new HqlBaseListener() {
|
||||
@@ -76,7 +94,7 @@ public class HqlSemanticTokens implements SemanticTokensDataProvider {
|
||||
case HqlParser.WS:
|
||||
break;
|
||||
case HqlParser.SPEL:
|
||||
semantics.put(node.getSymbol(), "regexp");
|
||||
tokens.addAll(JpqlSemanticTokens.computeTokensFromSpelNode(node, initialOffset, optSpelTokens));
|
||||
break;
|
||||
default:
|
||||
if (HqlParser.WS < type && type <= HqlParser.YEAR) {
|
||||
@@ -120,11 +138,11 @@ public class HqlSemanticTokens implements SemanticTokensDataProvider {
|
||||
|
||||
parser.ql_statement();
|
||||
|
||||
List<SemanticTokenData> tokens = semantics.entrySet().stream()
|
||||
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());
|
||||
.forEach(tokens::add);
|
||||
|
||||
Collections.sort(tokens);
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
package org.springframework.ide.vscode.boot.java.data.jpa.queries;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.antlr.v4.runtime.ANTLRErrorListener;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
@@ -22,20 +23,31 @@ 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.boot.java.handlers.Reconciler;
|
||||
import org.springframework.ide.vscode.boot.java.spel.SpelReconciler;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
|
||||
import org.springframework.ide.vscode.parser.jpql.JpqlBaseListener;
|
||||
import org.springframework.ide.vscode.parser.jpql.JpqlLexer;
|
||||
import org.springframework.ide.vscode.parser.jpql.JpqlParser;
|
||||
|
||||
public class JpqlReconciler implements Reconciler {
|
||||
|
||||
private final Optional<SpelReconciler> spelReconciler;
|
||||
|
||||
public JpqlReconciler(Optional<SpelReconciler> spelReconciler) {
|
||||
this.spelReconciler = spelReconciler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconcile(String text, int startPosition, IProblemCollector problemCollector) {
|
||||
JpqlLexer lexer = new JpqlLexer(CharStreams.fromString(text));
|
||||
CommonTokenStream antlrTokens = new CommonTokenStream(lexer);
|
||||
JpqlParser parser = new JpqlParser(antlrTokens);
|
||||
|
||||
lexer.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
parser.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
|
||||
parser.addErrorListener(new ANTLRErrorListener() {
|
||||
@@ -69,8 +81,36 @@ public class JpqlReconciler implements Reconciler {
|
||||
}
|
||||
});
|
||||
|
||||
// Reconcile embedded SPEL
|
||||
parser.addParseListener(new JpqlBaseListener() {
|
||||
|
||||
private void processTerminal(TerminalNode node) {
|
||||
if (node.getSymbol().getType() == JpqlParser.SPEL) {
|
||||
spelReconciler.ifPresent(r -> reconcileEmbeddedSpelNode(node, startPosition, r, problemCollector));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTerminal(TerminalNode node) {
|
||||
processTerminal(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitErrorNode(ErrorNode node) {
|
||||
processTerminal(node);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
parser.ql_statement();
|
||||
|
||||
}
|
||||
|
||||
static void reconcileEmbeddedSpelNode(TerminalNode node, int initialOffset, SpelReconciler spelReconciler, IProblemCollector problemCollector) {
|
||||
int startPosition = initialOffset + node.getSymbol().getStartIndex();
|
||||
String spelContent = node.getSymbol().getText().substring(2, node.getSymbol().getText().length() - 1);
|
||||
spelReconciler.reconcile(spelContent, startPosition, problemCollector);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,11 +10,13 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.data.jpa.queries;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
@@ -22,6 +24,7 @@ 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.boot.java.spel.SpelSemanticTokens;
|
||||
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.jpql.JpqlBaseListener;
|
||||
@@ -39,19 +42,34 @@ public class JpqlSemanticTokens implements SemanticTokensDataProvider {
|
||||
|
||||
private static List<String> TOKEN_TYPES = List.of("keyword", "type", "class", "string", "number", "operator",
|
||||
"variable", "method", "regexp", "parameter");
|
||||
|
||||
final private Optional<SpelSemanticTokens> optSpelSemantictokens;
|
||||
|
||||
public JpqlSemanticTokens(Optional<SpelSemanticTokens> optSpelSemantictokens) {
|
||||
this.optSpelSemantictokens = optSpelSemantictokens;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTokenTypes() {
|
||||
return TOKEN_TYPES;
|
||||
LinkedHashSet<String> tokenTypes = new LinkedHashSet<>(TOKEN_TYPES);
|
||||
tokenTypes.addAll(optSpelSemantictokens.map(s -> s.getTokenTypes()).orElse(Collections.emptyList()));
|
||||
return tokenTypes.stream().toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypeModifiers() {
|
||||
return optSpelSemantictokens.map(s -> s.getTypeModifiers()).orElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SemanticTokenData> computeTokens(String text, int initialOffset) {
|
||||
JpqlLexer lexer = new JpqlLexer(CharStreams.fromString(text));
|
||||
CommonTokenStream antlrTokens = new CommonTokenStream(lexer);
|
||||
JpqlParser parser = new JpqlParser(antlrTokens);
|
||||
Map<Token, String> semantics = new HashMap<>();
|
||||
List<SemanticTokenData> tokens = new ArrayList<>();
|
||||
|
||||
lexer.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
parser.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
|
||||
parser.addParseListener(new JpqlBaseListener() {
|
||||
@@ -81,7 +99,7 @@ public class JpqlSemanticTokens implements SemanticTokensDataProvider {
|
||||
case JpqlParser.WS:
|
||||
break;
|
||||
case JpqlParser.SPEL:
|
||||
semantics.put(node.getSymbol(), "regexp");
|
||||
tokens.addAll(computeTokensFromSpelNode(node, initialOffset, optSpelSemantictokens));
|
||||
break;
|
||||
default:
|
||||
if (JpqlParser.WS < type && type <= JpqlParser.WHERE) {
|
||||
@@ -140,15 +158,35 @@ public class JpqlSemanticTokens implements SemanticTokensDataProvider {
|
||||
|
||||
parser.ql_statement();
|
||||
|
||||
List<SemanticTokenData> tokens = semantics.entrySet().stream()
|
||||
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());
|
||||
.forEach(tokens::add);
|
||||
|
||||
Collections.sort(tokens);
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
static List<SemanticTokenData> computeTokensFromSpelNode(TerminalNode node, int initialOffset, Optional<SpelSemanticTokens> optSpelTokens) {
|
||||
List<SemanticTokenData> spelTokens = new ArrayList<>();
|
||||
|
||||
int startPosition = initialOffset + node.getSymbol().getStartIndex();
|
||||
int spelStartPosition = startPosition + 2;
|
||||
int endPosition = startPosition + node.getText().length();
|
||||
int spelEndPosition = endPosition - 1;
|
||||
// '#{' operator
|
||||
spelTokens.add(new SemanticTokenData(startPosition, spelStartPosition, "operator", new String[0]));
|
||||
// SPEL contents
|
||||
optSpelTokens.ifPresentOrElse(
|
||||
spelTokenProvider -> spelTokens
|
||||
.addAll(spelTokenProvider.computeTokens(node.getText().substring(2, node.getText().length() - 1), spelStartPosition)),
|
||||
() -> spelTokens.add(new SemanticTokenData(spelStartPosition, spelEndPosition, "string", new String[0])));
|
||||
|
||||
// '}' operator
|
||||
spelTokens.add(new SemanticTokenData(spelEndPosition, endPosition, "operator", new String[0]));
|
||||
return spelTokens;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public class NamedQueryPropertiesReconcileEngine implements IReconcileEngine {
|
||||
try {
|
||||
Reconciler reconciler = projectFinder.find(new TextDocumentIdentifier(doc.getUri()))
|
||||
.map(p -> SpringProjectUtil.hasDependencyStartingWith(p, "spring-data-jpa", null) ? hqlReconciler : jpqlReconciler)
|
||||
.orElse(new JpqlReconciler());
|
||||
.orElse(jpqlReconciler);
|
||||
|
||||
AntlrParser parser = new AntlrParser();
|
||||
ParseResults parseResults = parser.parse(doc.get());
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
package org.springframework.ide.vscode.boot.java.data.jpa.queries;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.antlr.v4.runtime.ANTLRErrorListener;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
@@ -22,20 +23,31 @@ 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.boot.java.handlers.Reconciler;
|
||||
import org.springframework.ide.vscode.boot.java.spel.SpelReconciler;
|
||||
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;
|
||||
import org.springframework.ide.vscode.parser.sql.MySqlParserBaseListener;
|
||||
|
||||
public class SqlReconciler implements Reconciler {
|
||||
|
||||
private final Optional<SpelReconciler> spelReconciler;
|
||||
|
||||
public SqlReconciler(Optional<SpelReconciler> spelReconciler) {
|
||||
this.spelReconciler = spelReconciler;
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
lexer.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
parser.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
|
||||
parser.addErrorListener(new ANTLRErrorListener() {
|
||||
@@ -69,6 +81,28 @@ public class SqlReconciler implements Reconciler {
|
||||
}
|
||||
});
|
||||
|
||||
// Reconcile embedded SPEL
|
||||
parser.addParseListener(new MySqlParserBaseListener() {
|
||||
|
||||
private void processTerminal(TerminalNode node) {
|
||||
if (node.getSymbol().getType() == MySqlParser.SPEL) {
|
||||
spelReconciler.ifPresent(r -> JpqlReconciler.reconcileEmbeddedSpelNode(node, startPosition, r, problemCollector));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTerminal(TerminalNode node) {
|
||||
processTerminal(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitErrorNode(ErrorNode node) {
|
||||
processTerminal(node);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
parser.sqlStatements();
|
||||
|
||||
}
|
||||
|
||||
@@ -10,18 +10,28 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.data.jpa.queries;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Optional;
|
||||
|
||||
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.boot.java.spel.SpelSemanticTokens;
|
||||
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;
|
||||
@@ -33,11 +43,23 @@ 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;
|
||||
private Optional<SpelSemanticTokens> optSpelTokens;
|
||||
|
||||
public SqlSemanticTokens(Optional<SpelSemanticTokens> optSpelTokens) {
|
||||
this.optSpelTokens = optSpelTokens;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTokenTypes() {
|
||||
LinkedHashSet<String> tokenTypes = new LinkedHashSet<>(TOKEN_TYPES);
|
||||
tokenTypes.addAll(optSpelTokens.map(s -> s.getTokenTypes()).orElse(Collections.emptyList()));
|
||||
return tokenTypes.stream().toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTypeModifiers() {
|
||||
return optSpelTokens.map(s -> s.getTypeModifiers()).orElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SemanticTokenData> computeTokens(String text, int initialOffset) {
|
||||
@@ -47,6 +69,9 @@ public class SqlSemanticTokens implements SemanticTokensDataProvider {
|
||||
|
||||
Map<Token, String> semantics = new HashMap<>();
|
||||
|
||||
List<SemanticTokenData> tokens = new ArrayList<>();
|
||||
|
||||
lexer.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
parser.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
|
||||
parser.addParseListener(new MySqlParserBaseListener() {
|
||||
@@ -55,7 +80,7 @@ public class SqlSemanticTokens implements SemanticTokensDataProvider {
|
||||
int type = node.getSymbol().getType();
|
||||
switch (type) {
|
||||
case MySqlParser.SPEL:
|
||||
semantics.put(node.getSymbol(), "regexp");
|
||||
tokens.addAll(JpqlSemanticTokens.computeTokensFromSpelNode(node, initialOffset, optSpelTokens));
|
||||
break;
|
||||
case MySqlParser.ID:
|
||||
semantics.put(node.getSymbol(), "variable");
|
||||
@@ -162,13 +187,44 @@ public class SqlSemanticTokens implements SemanticTokensDataProvider {
|
||||
|
||||
});
|
||||
|
||||
parser.addErrorListener(new ANTLRErrorListener() {
|
||||
|
||||
@Override
|
||||
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
|
||||
String msg, RecognitionException e) {
|
||||
// TODO Auto-generated method stub
|
||||
msg.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportContextSensitivity(Parser recognizer, DFA dfa, int startIndex, int stopIndex, int prediction,
|
||||
ATNConfigSet configs) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportAttemptingFullContext(Parser recognizer, DFA dfa, int startIndex, int stopIndex,
|
||||
BitSet conflictingAlts, ATNConfigSet configs) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportAmbiguity(Parser recognizer, DFA dfa, int startIndex, int stopIndex, boolean exact,
|
||||
BitSet ambigAlts, ATNConfigSet configs) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
parser.sqlStatements();
|
||||
|
||||
List<SemanticTokenData> tokens = semantics.entrySet().stream()
|
||||
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());
|
||||
.forEach(tokens::add);
|
||||
|
||||
Collections.sort(tokens);
|
||||
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2023, 2024 VMware, 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:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.reconcilers;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor;
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MarkerAnnotation;
|
||||
import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
|
||||
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.SpelProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.SpelExpressionReconciler;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
|
||||
public class AnnotationNodeReconciler implements JdtAstReconciler {
|
||||
|
||||
public static final String SPRING_CACHEABLE = "org.springframework.cache.annotation.Cacheable";
|
||||
public static final String SPRING_CACHE_EVICT = "org.springframework.cache.annotation.CacheEvict";
|
||||
|
||||
public static final String SPRING_EVENT_LISTENER = "org.springframework.context.event.EventListener";
|
||||
|
||||
public static final String SPRING_PRE_AUTHORIZE = "org.springframework.security.access.prepost.PreAuthorize";
|
||||
public static final String SPRING_PRE_FILTER = "org.springframework.security.access.prepost.PreFilter";
|
||||
public static final String SPRING_POST_AUTHORIZE = "org.springframework.security.access.prepost.PostAuthorize";
|
||||
public static final String SPRING_POST_FILTER= "org.springframework.security.access.prepost.PostFilter";
|
||||
|
||||
public static final String SPRING_CONDITIONAL_ON_EXPRESSION = "org.springframework.boot.autoconfigure.condition.ConditionalOnExpression";
|
||||
|
||||
private final SpelExpressionReconciler spelExpressionReconciler;
|
||||
private final AnnotationReconciler[] reconcilers;
|
||||
|
||||
public AnnotationNodeReconciler(BootJavaConfig config) {
|
||||
this.spelExpressionReconciler = new SpelExpressionReconciler();
|
||||
this.reconcilers = new AnnotationReconciler[] {
|
||||
|
||||
new AnnotationParamReconciler(Annotations.VALUE, null, "#{", "}", spelExpressionReconciler),
|
||||
new AnnotationParamReconciler(Annotations.VALUE, "value", "#{", "}", spelExpressionReconciler),
|
||||
|
||||
new AnnotationParamReconciler(SPRING_CACHEABLE, "key", "", "", spelExpressionReconciler),
|
||||
new AnnotationParamReconciler(SPRING_CACHEABLE, "condition", "", "", spelExpressionReconciler),
|
||||
new AnnotationParamReconciler(SPRING_CACHEABLE, "unless", "", "", spelExpressionReconciler),
|
||||
|
||||
new AnnotationParamReconciler(SPRING_CACHE_EVICT, "key", "", "", spelExpressionReconciler),
|
||||
new AnnotationParamReconciler(SPRING_CACHE_EVICT, "condition", "", "", spelExpressionReconciler),
|
||||
|
||||
new AnnotationParamReconciler(SPRING_EVENT_LISTENER, "condition", "", "", spelExpressionReconciler),
|
||||
|
||||
new AnnotationParamReconciler(SPRING_PRE_AUTHORIZE, null, "", "", spelExpressionReconciler),
|
||||
new AnnotationParamReconciler(SPRING_PRE_AUTHORIZE, "value", "", "", spelExpressionReconciler),
|
||||
new AnnotationParamReconciler(SPRING_PRE_FILTER, null, "", "", spelExpressionReconciler),
|
||||
new AnnotationParamReconciler(SPRING_PRE_FILTER, "value", "", "", spelExpressionReconciler),
|
||||
new AnnotationParamReconciler(SPRING_POST_AUTHORIZE, null, "", "", spelExpressionReconciler),
|
||||
new AnnotationParamReconciler(SPRING_POST_AUTHORIZE, "value", "", "", spelExpressionReconciler),
|
||||
new AnnotationParamReconciler(SPRING_POST_FILTER, null, "", "", spelExpressionReconciler),
|
||||
new AnnotationParamReconciler(SPRING_POST_FILTER, "value", "", "", spelExpressionReconciler),
|
||||
|
||||
new AnnotationParamReconciler(SPRING_CONDITIONAL_ON_EXPRESSION, null, "", "", spelExpressionReconciler),
|
||||
new AnnotationParamReconciler(SPRING_CONDITIONAL_ON_EXPRESSION, "value", "", "", spelExpressionReconciler)
|
||||
|
||||
};
|
||||
config.addListener(evt -> this.spelExpressionReconciler.setEnabled(config.isSpelExpressionValidationEnabled()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(IJavaProject project) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemType getProblemType() {
|
||||
return SpelProblemType.JAVA_SPEL_EXPRESSION_SYNTAX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTVisitor createVisitor(IJavaProject project, URI docUri, CompilationUnit cu,
|
||||
IProblemCollector problemCollector, boolean isCompleteAst) {
|
||||
return new ASTVisitor() {
|
||||
|
||||
@Override
|
||||
public boolean visit(SingleMemberAnnotation node) {
|
||||
try {
|
||||
visitAnnotation(project, docUri, node, problemCollector);
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
return super.visit(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(NormalAnnotation node) {
|
||||
try {
|
||||
visitAnnotation(project, docUri, node, problemCollector);
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
return super.visit(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(MarkerAnnotation node) {
|
||||
try {
|
||||
visitAnnotation(project, docUri, node, problemCollector);
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
return super.visit(node);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private void visitAnnotation(IJavaProject project, URI docUri, Annotation node, IProblemCollector problemCollector) {
|
||||
ITypeBinding typeBinding = node.resolveTypeBinding();
|
||||
if (typeBinding != null) {
|
||||
for (int i = 0; i < reconcilers.length; i++) {
|
||||
reconcilers[i].visit(project, docUri, node, typeBinding, problemCollector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2020, 2022 Pivotal, 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:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.reconcilers;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.Expression;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MemberValuePair;
|
||||
import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
|
||||
import org.eclipse.jdt.core.dom.StringLiteral;
|
||||
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchies;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.Reconciler;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public class AnnotationParamReconciler implements AnnotationReconciler {
|
||||
|
||||
private final String annotationType;
|
||||
private final String paramName;
|
||||
private final String paramValuePrefix;
|
||||
private final String paramValuePostfix;
|
||||
private final Reconciler reconciler;
|
||||
|
||||
public AnnotationParamReconciler(String annotationType, String paramName,
|
||||
String paramValuePrefix, String paramValuePostfix, Reconciler reconciler) {
|
||||
this.annotationType = annotationType;
|
||||
this.paramName = paramName;
|
||||
this.paramValuePrefix = paramValuePrefix;
|
||||
this.paramValuePostfix = paramValuePostfix;
|
||||
this.reconciler = reconciler;
|
||||
}
|
||||
|
||||
public void visit(IJavaProject project, URI docUri, Annotation node, ITypeBinding typeBinding, IProblemCollector problemCollector) {
|
||||
if (node instanceof SingleMemberAnnotation) {
|
||||
visitSingleMemberAnnotation((SingleMemberAnnotation) node, typeBinding, problemCollector);
|
||||
} else if (node instanceof NormalAnnotation) {
|
||||
visitNormalAnnotation((NormalAnnotation) node, typeBinding, problemCollector);
|
||||
}
|
||||
}
|
||||
|
||||
protected void visitSingleMemberAnnotation(SingleMemberAnnotation node, ITypeBinding typeBinding, IProblemCollector problemCollector) {
|
||||
if (this.paramName != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AnnotationHierarchies.hasTransitiveSuperAnnotationType(typeBinding, this.annotationType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Expression valueExp = node.getValue();
|
||||
|
||||
if (valueExp instanceof StringLiteral) {
|
||||
reconcileStringLiteral((StringLiteral) valueExp, problemCollector);
|
||||
}
|
||||
}
|
||||
|
||||
protected void visitNormalAnnotation(NormalAnnotation node, ITypeBinding typeBinding, IProblemCollector problemCollector) {
|
||||
if (paramName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AnnotationHierarchies.hasTransitiveSuperAnnotationType(typeBinding, this.annotationType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<?> values = node.values();
|
||||
|
||||
for (Object value : values) {
|
||||
if (value instanceof MemberValuePair) {
|
||||
MemberValuePair pair = (MemberValuePair) value;
|
||||
String name = pair.getName().getFullyQualifiedName();
|
||||
if (name != null && name.equals(paramName)) {
|
||||
Expression expression = pair.getValue();
|
||||
if (expression instanceof StringLiteral) {
|
||||
reconcileStringLiteral((StringLiteral) expression, problemCollector);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void reconcileStringLiteral(StringLiteral valueExp, IProblemCollector problemCollector) {
|
||||
String value = valueExp.getLiteralValue();
|
||||
|
||||
if (value != null && value.startsWith(paramValuePrefix) && value.endsWith(paramValuePostfix)) {
|
||||
String valueToReconcile = value.substring(paramValuePrefix.length(), value.length() - paramValuePostfix.length());
|
||||
|
||||
reconciler.reconcile(valueToReconcile, valueExp.getStartPosition() + paramValuePrefix.length() + 1, problemCollector);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022 VMware, 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:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.reconcilers;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
|
||||
public interface AnnotationReconciler {
|
||||
|
||||
void visit(IJavaProject project, URI docUri, Annotation node, ITypeBinding typeBinding, IProblemCollector problemCollector);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*******************************************************************************
|
||||
* 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.spel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.core.dom.Expression;
|
||||
import org.eclipse.jdt.core.dom.MemberValuePair;
|
||||
import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
|
||||
import org.eclipse.jdt.core.dom.StringLiteral;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchies;
|
||||
|
||||
final class AnnotationParamSpelExtractor {
|
||||
|
||||
private static final String SPRING_CACHEABLE = "org.springframework.cache.annotation.Cacheable";
|
||||
private static final String SPRING_CACHE_EVICT = "org.springframework.cache.annotation.CacheEvict";
|
||||
|
||||
private static final String SPRING_EVENT_LISTENER = "org.springframework.context.event.EventListener";
|
||||
|
||||
private static final String SPRING_PRE_AUTHORIZE = "org.springframework.security.access.prepost.PreAuthorize";
|
||||
private static final String SPRING_PRE_FILTER = "org.springframework.security.access.prepost.PreFilter";
|
||||
private static final String SPRING_POST_AUTHORIZE = "org.springframework.security.access.prepost.PostAuthorize";
|
||||
private static final String SPRING_POST_FILTER= "org.springframework.security.access.prepost.PostFilter";
|
||||
|
||||
private static final String SPRING_CONDITIONAL_ON_EXPRESSION = "org.springframework.boot.autoconfigure.condition.ConditionalOnExpression";
|
||||
|
||||
final static AnnotationParamSpelExtractor[] SPEL_EXTRACTORS = new AnnotationParamSpelExtractor[] {
|
||||
new AnnotationParamSpelExtractor(Annotations.VALUE, null, "#{", "}"),
|
||||
new AnnotationParamSpelExtractor(Annotations.VALUE, "value", "#{", "}"),
|
||||
|
||||
new AnnotationParamSpelExtractor(SPRING_CACHEABLE, "key", "", ""),
|
||||
new AnnotationParamSpelExtractor(SPRING_CACHEABLE, "condition", "", ""),
|
||||
new AnnotationParamSpelExtractor(SPRING_CACHEABLE, "unless", "", ""),
|
||||
|
||||
new AnnotationParamSpelExtractor(SPRING_CACHE_EVICT, "key", "", ""),
|
||||
new AnnotationParamSpelExtractor(SPRING_CACHE_EVICT, "condition", "", ""),
|
||||
|
||||
new AnnotationParamSpelExtractor(SPRING_EVENT_LISTENER, "condition", "", ""),
|
||||
|
||||
new AnnotationParamSpelExtractor(SPRING_PRE_AUTHORIZE, null, "", ""),
|
||||
new AnnotationParamSpelExtractor(SPRING_PRE_AUTHORIZE, "value", "", ""),
|
||||
new AnnotationParamSpelExtractor(SPRING_PRE_FILTER, null, "", ""),
|
||||
new AnnotationParamSpelExtractor(SPRING_PRE_FILTER, "value", "", ""),
|
||||
new AnnotationParamSpelExtractor(SPRING_POST_AUTHORIZE, null, "", ""),
|
||||
new AnnotationParamSpelExtractor(SPRING_POST_AUTHORIZE, "value", "", ""),
|
||||
new AnnotationParamSpelExtractor(SPRING_POST_FILTER, null, "", ""),
|
||||
new AnnotationParamSpelExtractor(SPRING_POST_FILTER, "value", "", ""),
|
||||
|
||||
new AnnotationParamSpelExtractor(SPRING_CONDITIONAL_ON_EXPRESSION, null, "", ""),
|
||||
new AnnotationParamSpelExtractor(SPRING_CONDITIONAL_ON_EXPRESSION, "value", "", "")
|
||||
};
|
||||
|
||||
|
||||
record Snippet(String text, int offset) {}
|
||||
|
||||
private final String annotationType;
|
||||
private final String paramName;
|
||||
private final String paramValuePrefix;
|
||||
private final String paramValuePostfix;
|
||||
|
||||
public AnnotationParamSpelExtractor(String annotationType, String paramName, String paramValuePrefix,
|
||||
String paramValuePostfix) {
|
||||
this.annotationType = annotationType;
|
||||
this.paramName = paramName;
|
||||
this.paramValuePrefix = paramValuePrefix;
|
||||
this.paramValuePostfix = paramValuePostfix;
|
||||
}
|
||||
|
||||
Optional<Snippet> getSpelRegion(NormalAnnotation a) {
|
||||
if (paramName == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (!AnnotationHierarchies.hasTransitiveSuperAnnotationType(a.resolveTypeBinding(), this.annotationType)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
List<?> values = a.values();
|
||||
|
||||
for (Object value : values) {
|
||||
if (value instanceof MemberValuePair) {
|
||||
MemberValuePair pair = (MemberValuePair) value;
|
||||
String name = pair.getName().getFullyQualifiedName();
|
||||
if (name != null && name.equals(paramName)) {
|
||||
Expression expression = pair.getValue();
|
||||
if (expression instanceof StringLiteral) {
|
||||
return fromStringLiteral((StringLiteral) expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Optional<Snippet> getSpelRegion(SingleMemberAnnotation a) {
|
||||
if (this.paramName != null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (!AnnotationHierarchies.hasTransitiveSuperAnnotationType(a.resolveTypeBinding(), this.annotationType)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Expression valueExp = a.getValue();
|
||||
|
||||
if (valueExp instanceof StringLiteral) {
|
||||
return fromStringLiteral((StringLiteral) valueExp);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private Optional<Snippet> fromStringLiteral(StringLiteral valueExp) {
|
||||
String value = valueExp.getEscapedValue();
|
||||
value = value.substring(1, value.length() - 1);
|
||||
if (value != null && value.startsWith(paramValuePrefix) && value.endsWith(paramValuePostfix)) {
|
||||
String spelText = value.substring(paramValuePrefix.length(), value.length() - paramValuePostfix.length());
|
||||
int offset = valueExp.getStartPosition() + paramValuePrefix.length() + 1;
|
||||
return Optional.of(new Snippet(spelText, offset));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*******************************************************************************
|
||||
* 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.spel;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
|
||||
import org.springframework.ide.vscode.boot.java.SpelProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.JdtAstReconciler;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
|
||||
public class JdtSpelReconciler implements JdtAstReconciler {
|
||||
|
||||
final private AnnotationParamSpelExtractor[] spelExtractors = AnnotationParamSpelExtractor.SPEL_EXTRACTORS;
|
||||
final private SpelReconciler spelReconciler;
|
||||
|
||||
public JdtSpelReconciler(SpelReconciler spelReconciler) {
|
||||
this.spelReconciler = spelReconciler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(IJavaProject project) {
|
||||
return SpringProjectUtil.hasDependencyStartingWith(project, "spring-expression", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemType getProblemType() {
|
||||
return SpelProblemType.JAVA_SPEL_EXPRESSION_SYNTAX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTVisitor createVisitor(IJavaProject project, URI docURI, CompilationUnit cu,
|
||||
IProblemCollector problemCollector, boolean isCompleteAst) {
|
||||
return new ASTVisitor() {
|
||||
@Override
|
||||
public boolean visit(SingleMemberAnnotation node) {
|
||||
Arrays.stream(spelExtractors)
|
||||
.map(e -> e.getSpelRegion(node))
|
||||
.filter(o -> o.isPresent())
|
||||
.map(o -> o.get())
|
||||
.forEach(snippet -> spelReconciler.reconcile(snippet.text(), snippet.offset(), problemCollector));
|
||||
return super.visit(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(NormalAnnotation node) {
|
||||
Arrays.stream(spelExtractors)
|
||||
.map(e -> e.getSpelRegion(node))
|
||||
.filter(o -> o.isPresent())
|
||||
.map(o -> o.get())
|
||||
.forEach(snippet -> spelReconciler.reconcile(snippet.text(), snippet.offset(), problemCollector));
|
||||
return super.visit(node);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*******************************************************************************
|
||||
* 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.spel;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
|
||||
import org.springframework.ide.vscode.boot.java.JdtSemanticTokensProvider;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
|
||||
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData;
|
||||
import org.springframework.ide.vscode.commons.util.Collector;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
public class JdtSpelSemanticTokensProvider implements JdtSemanticTokensProvider {
|
||||
|
||||
final private AnnotationParamSpelExtractor[] spelExtractors = AnnotationParamSpelExtractor.SPEL_EXTRACTORS;
|
||||
|
||||
final private SpelSemanticTokens tokensProvider;
|
||||
|
||||
public JdtSpelSemanticTokensProvider(SpelSemanticTokens tokensProvider) {
|
||||
this.tokensProvider = tokensProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTokenTypes() {
|
||||
return tokensProvider.getTokenTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTokenModifiers() {
|
||||
return tokensProvider.getTypeModifiers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(IJavaProject project) {
|
||||
return SpringProjectUtil.hasDependencyStartingWith(project, "spring-expression", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTVisitor getTokensComputer(IJavaProject project, TextDocument doc, CompilationUnit cu,
|
||||
Collector<SemanticTokenData> collector) {
|
||||
return new ASTVisitor() {
|
||||
|
||||
@Override
|
||||
public boolean visit(SingleMemberAnnotation node) {
|
||||
Arrays.stream(spelExtractors)
|
||||
.map(e -> e.getSpelRegion(node))
|
||||
.filter(o -> o.isPresent())
|
||||
.map(o -> o.get())
|
||||
.forEach(snippet -> tokensProvider.computeTokens(snippet.text(), snippet.offset()).forEach(collector::accept));
|
||||
return super.visit(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(NormalAnnotation node) {
|
||||
Arrays.stream(spelExtractors)
|
||||
.map(e -> e.getSpelRegion(node))
|
||||
.filter(o -> o.isPresent())
|
||||
.map(o -> o.get())
|
||||
.forEach(snippet -> tokensProvider.computeTokens(snippet.text(), snippet.offset()).forEach(collector::accept));
|
||||
return super.visit(node);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*******************************************************************************
|
||||
* 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.spel;
|
||||
|
||||
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.SpelProblemType;
|
||||
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.spel.SpelLexer;
|
||||
import org.springframework.ide.vscode.parser.spel.SpelParser;
|
||||
|
||||
public class SpelReconciler implements Reconciler {
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
public void setEnabled(boolean spelExpressionValidationEnabled) {
|
||||
this.enabled = spelExpressionValidationEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconcile(String text, int startPosition, IProblemCollector problemCollector) {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
SpelLexer lexer = new SpelLexer(CharStreams.fromString(text));
|
||||
CommonTokenStream antlrTokens = new CommonTokenStream(lexer);
|
||||
SpelParser parser = new SpelParser(antlrTokens);
|
||||
|
||||
lexer.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
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(SpelProblemType.JAVA_SPEL_EXPRESSION_SYNTAX, "SPEL: " + 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.spelExpr();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/*******************************************************************************
|
||||
* 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.spel;
|
||||
|
||||
import static org.springframework.ide.vscode.parser.spel.SpelLexer.*;
|
||||
|
||||
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.spel.SpelLexer;
|
||||
import org.springframework.ide.vscode.parser.spel.SpelParser;
|
||||
import org.springframework.ide.vscode.parser.spel.SpelParser.BeanReferenceContext;
|
||||
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.MethodOrPropertyContext;
|
||||
import org.springframework.ide.vscode.parser.spel.SpelParser.PossiblyQualifiedIdContext;
|
||||
import org.springframework.ide.vscode.parser.spel.SpelParserBaseListener;
|
||||
|
||||
public class SpelSemanticTokens implements SemanticTokensDataProvider {
|
||||
|
||||
@Override
|
||||
public List<String> getTokenTypes() {
|
||||
return List.of("operator", "keyword", "type", "string", "number", "method", "property");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SemanticTokenData> computeTokens(String text, int initialOffset) {
|
||||
SpelLexer lexer = new SpelLexer(CharStreams.fromString(text));
|
||||
CommonTokenStream antlrTokens = new CommonTokenStream(lexer);
|
||||
SpelParser parser = new SpelParser(antlrTokens);
|
||||
|
||||
Map<Token, String> semantics = new HashMap<>();
|
||||
|
||||
lexer.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
parser.removeErrorListener(ConsoleErrorListener.INSTANCE);
|
||||
|
||||
parser.addParseListener(new SpelParserBaseListener() {
|
||||
|
||||
private void processTerminalNode(TerminalNode node) {
|
||||
int type = node.getSymbol().getType();
|
||||
switch (type) {
|
||||
case INC:
|
||||
case PLUS:
|
||||
case DEC:
|
||||
case MINUS:
|
||||
case DOT:
|
||||
case COMMA:
|
||||
case STAR:
|
||||
case DIV:
|
||||
case MOD:
|
||||
case LPAREN:
|
||||
case RPAREN:
|
||||
case LSQUARE:
|
||||
case RSQUARE:
|
||||
case POWER:
|
||||
case ELVIS:
|
||||
case NE:
|
||||
case NOT:
|
||||
case EQ:
|
||||
case ASSIGN:
|
||||
case SYMBOLIC_AND:
|
||||
case SYMBOLIC_OR:
|
||||
case GE:
|
||||
case LE:
|
||||
case GT:
|
||||
case LT:
|
||||
case QMARK:
|
||||
case RCURLY:
|
||||
case LCURLY:
|
||||
case SEMICOLON:
|
||||
case COLON:
|
||||
case SELECT_FIRST:
|
||||
case HASH:
|
||||
case BEAN_REF:
|
||||
case PROJECT:
|
||||
case FACTORY_BEAN_REF:
|
||||
case SELECT:
|
||||
case SAFE_NAVI:
|
||||
case SELECT_LAST:
|
||||
case BACKTICK:
|
||||
semantics.put(node.getSymbol(), "operator");
|
||||
break;
|
||||
case OR:
|
||||
case AND:
|
||||
case NEW:
|
||||
case NULL:
|
||||
case TRUE:
|
||||
case FALSE:
|
||||
case T:
|
||||
case MATCHES:
|
||||
case LE_KEYWORD:
|
||||
case LT_KEYWORD:
|
||||
case GE_KEYWORD:
|
||||
case GT_KEYWORD:
|
||||
case EQ_KEYWORD:
|
||||
case NE_KEYWORD:
|
||||
semantics.put(node.getSymbol(), "keyword");
|
||||
break;
|
||||
case IDENTIFIER:
|
||||
semantics.put(node.getSymbol(), "variable");
|
||||
break;
|
||||
case NUMERIC_LITERAL:
|
||||
case INTEGER_LITERAL:
|
||||
case REAL_LITERAL:
|
||||
semantics.put(node.getSymbol(), "number");
|
||||
break;
|
||||
case STRING_LITERAL:
|
||||
case SINGLE_QUOTED_STRING:
|
||||
case DOUBLE_QUOTED_STRING:
|
||||
semantics.put(node.getSymbol(), "string");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitBeanReference(BeanReferenceContext ctx) {
|
||||
if (ctx.IDENTIFIER() != null) {
|
||||
semantics.put(ctx.IDENTIFIER().getSymbol(), "type");
|
||||
}
|
||||
if (ctx.STRING_LITERAL() != null) {
|
||||
semantics.put(ctx.STRING_LITERAL().getSymbol(), "type");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitMethodOrProperty(MethodOrPropertyContext ctx) {
|
||||
if (ctx.methodArgs() != null) {
|
||||
semantics.put(ctx.IDENTIFIER().getSymbol(), "method");
|
||||
} else {
|
||||
if (ctx.parent instanceof DottedNodeContext) {
|
||||
semantics.put(ctx.IDENTIFIER().getSymbol(), "property");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitFunctionOrVar(FunctionOrVarContext ctx) {
|
||||
if (ctx.methodArgs() != null) {
|
||||
semantics.put(ctx.IDENTIFIER().getSymbol(), "method");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitConstructorReference(ConstructorReferenceContext ctx) {
|
||||
PossiblyQualifiedIdContext qualified = ctx.possiblyQualifiedId();
|
||||
if (qualified != null) {
|
||||
semantics.put(qualified.IDENTIFIER(qualified.IDENTIFIER().size() - 1).getSymbol(), "method");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitPossiblyQualifiedId(PossiblyQualifiedIdContext ctx) {
|
||||
if (ctx.IDENTIFIER() != null) {
|
||||
for (int i = 0; i < ctx.IDENTIFIER().size() - 1; i++) {
|
||||
semantics.put(ctx.IDENTIFIER(i).getSymbol(), "namespace");
|
||||
}
|
||||
semantics.put(ctx.IDENTIFIER(ctx.IDENTIFIER().size() - 1).getSymbol(), "type");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTerminal(TerminalNode node) {
|
||||
processTerminalNode(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitErrorNode(ErrorNode node) {
|
||||
processTerminalNode(node);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
parser.spelExpr();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import java.util.Set;
|
||||
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
|
||||
import org.springframework.ide.vscode.boot.app.BootLanguageServerParams;
|
||||
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
|
||||
import org.springframework.ide.vscode.boot.java.spel.SpelReconciler;
|
||||
import org.springframework.ide.vscode.commons.languageserver.composable.LanguageServerComponents;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
|
||||
@@ -41,7 +42,8 @@ public class SpringXMLLanguageServerComponents implements LanguageServerComponen
|
||||
SimpleLanguageServer server,
|
||||
SpringSymbolIndex springIndexer,
|
||||
BootLanguageServerParams serverParams,
|
||||
BootJavaConfig config) {
|
||||
BootJavaConfig config,
|
||||
SpelReconciler spelReconciler) {
|
||||
|
||||
this.projectFinder = serverParams.projectFinder;
|
||||
this.docSymbolProvider = params -> springIndexer.getSymbols(params.getTextDocument().getUri());
|
||||
@@ -49,12 +51,7 @@ public class SpringXMLLanguageServerComponents implements LanguageServerComponen
|
||||
server.doOnInitialized(this::initialized);
|
||||
server.onShutdown(this::shutdown);
|
||||
|
||||
this.reconcileEngine = new SpringXMLReconcileEngine(projectFinder, config);
|
||||
|
||||
config.addListener(ignore -> {
|
||||
reconcileEngine.setSpelExpressionSyntaxValidationEnabled(config.isSpelExpressionValidationEnabled() && config.isSpringXMLSupportEnabled());
|
||||
});
|
||||
|
||||
this.reconcileEngine = new SpringXMLReconcileEngine(projectFinder, config, spelReconciler);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.eclipse.lemminx.dom.DOMNode;
|
||||
import org.eclipse.lemminx.dom.DOMParser;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.SpelExpressionReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.spel.SpelReconciler;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
@@ -36,15 +36,15 @@ import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
public class SpringXMLReconcileEngine implements IReconcileEngine {
|
||||
|
||||
private final JavaProjectFinder projectFinder;
|
||||
private final SpelExpressionReconciler spelExpressionReconciler;
|
||||
private final SpelReconciler spelExpressionReconciler;
|
||||
private final XMLElementReconciler[] reconcilers;
|
||||
private final BootJavaConfig config;
|
||||
|
||||
public SpringXMLReconcileEngine(JavaProjectFinder projectFinder, BootJavaConfig config) {
|
||||
public SpringXMLReconcileEngine(JavaProjectFinder projectFinder, BootJavaConfig config, SpelReconciler spelReconciler) {
|
||||
this.projectFinder = projectFinder;
|
||||
this.config = config;
|
||||
|
||||
this.spelExpressionReconciler = new SpelExpressionReconciler();
|
||||
this.spelExpressionReconciler = spelReconciler;
|
||||
|
||||
this.reconcilers = new XMLElementReconciler[] {
|
||||
|
||||
|
||||
@@ -13,13 +13,21 @@ package org.springframework.ide.vscode.boot.java.data.jpa.queries;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ide.vscode.boot.java.spel.SpelSemanticTokens;
|
||||
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData;
|
||||
|
||||
public class HqlSemanticTokensTest {
|
||||
|
||||
private HqlSemanticTokens provider = new HqlSemanticTokens();
|
||||
private HqlSemanticTokens provider;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
provider = new HqlSemanticTokens(Optional.empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void simpleQuery_1() {
|
||||
@@ -108,9 +116,39 @@ public class HqlSemanticTokensTest {
|
||||
assertThat(tokens.get(14)).isEqualTo(new SemanticTokenData(69, 71, "method", new String[0])); // id
|
||||
assertThat(tokens.get(15)).isEqualTo(new SemanticTokenData(72, 73, "operator", new String[0])); // =
|
||||
assertThat(tokens.get(16)).isEqualTo(new SemanticTokenData(73, 74, "operator", new String[0])); // :
|
||||
assertThat(tokens.get(17)).isEqualTo(new SemanticTokenData(74, 79, "regexp", new String[0])); // #{id}
|
||||
assertThat(tokens.get(17)).isEqualTo(new SemanticTokenData(74, 76, "operator", new String[0])); // #{
|
||||
assertThat(tokens.get(18)).isEqualTo(new SemanticTokenData(76, 78, "string", new String[0])); // id
|
||||
assertThat(tokens.get(19)).isEqualTo(new SemanticTokenData(78, 79, "operator", new String[0])); // }
|
||||
|
||||
assertThat(tokens.size()).isEqualTo(18);
|
||||
assertThat(tokens.size()).isEqualTo(20);
|
||||
}
|
||||
|
||||
@Test
|
||||
void query_with_SPEL_Tokens() {
|
||||
provider = new HqlSemanticTokens(Optional.of(new SpelSemanticTokens()));
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:#{id}", 0);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 12, "variable", new String[0])); // owner
|
||||
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(13, 17, "keyword", new String[0])); // FROM
|
||||
assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(18, 23, "class", new String[0])); // Owner
|
||||
assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(24, 29, "variable", new String[0])); // owner
|
||||
assertThat(tokens.get(5)).isEqualTo(new SemanticTokenData(30, 34, "keyword", new String[0])); // left
|
||||
assertThat(tokens.get(6)).isEqualTo(new SemanticTokenData(35, 39, "keyword", new String[0])); // join
|
||||
assertThat(tokens.get(7)).isEqualTo(new SemanticTokenData(40, 45, "keyword", new String[0])); // fetch
|
||||
assertThat(tokens.get(8)).isEqualTo(new SemanticTokenData(46, 51, "variable", new String[0])); // owner
|
||||
assertThat(tokens.get(9)).isEqualTo(new SemanticTokenData(51, 52, "operator", new String[0])); // .
|
||||
assertThat(tokens.get(10)).isEqualTo(new SemanticTokenData(52, 56, "method", new String[0])); // pets
|
||||
assertThat(tokens.get(11)).isEqualTo(new SemanticTokenData(57, 62, "keyword", new String[0])); // WHERE
|
||||
assertThat(tokens.get(12)).isEqualTo(new SemanticTokenData(63, 68, "variable", new String[0])); // owner
|
||||
assertThat(tokens.get(13)).isEqualTo(new SemanticTokenData(68, 69, "operator", new String[0])); // .
|
||||
assertThat(tokens.get(14)).isEqualTo(new SemanticTokenData(69, 71, "method", new String[0])); // id
|
||||
assertThat(tokens.get(15)).isEqualTo(new SemanticTokenData(72, 73, "operator", new String[0])); // =
|
||||
assertThat(tokens.get(16)).isEqualTo(new SemanticTokenData(73, 74, "operator", new String[0])); // :
|
||||
assertThat(tokens.get(17)).isEqualTo(new SemanticTokenData(74, 76, "operator", new String[0])); // #{
|
||||
assertThat(tokens.get(18)).isEqualTo(new SemanticTokenData(76, 78, "variable", new String[0])); // id
|
||||
assertThat(tokens.get(19)).isEqualTo(new SemanticTokenData(78, 79, "operator", new String[0])); // }
|
||||
|
||||
assertThat(tokens.size()).isEqualTo(20);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -354,4 +355,78 @@ public class JdtDataQuerySemanticTokensProviderTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("Needs proper SPEL support in SQL grammar")
|
||||
void nativeQueryWithSpel() throws Exception {
|
||||
String source = """
|
||||
package my.package
|
||||
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
public interface OwnerRepository {
|
||||
|
||||
@Query(value = "SELECT * FROM USERS u WHERE u.status = ?#{status}", nativeQuery = true)
|
||||
void findByLastName();
|
||||
}
|
||||
""";
|
||||
|
||||
String uri = Paths.get(jp.getLocationUri()).resolve("src/main/resource/my/package/OwnerRepository.java").toUri().toASCIIString();
|
||||
CompilationUnit cu = CompilationUnitCache.parse2(source.toCharArray(), uri, "OwnerRepository.java", jp);
|
||||
|
||||
assertThat(cu).isNotNull();
|
||||
|
||||
List<SemanticTokenData> tokens = computeTokens(cu);
|
||||
|
||||
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("?");
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(167, 168, "operator", new String[0]));
|
||||
token = tokens.get(9);
|
||||
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo("#{");
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(168, 170, "operator", new String[0]));
|
||||
|
||||
token = tokens.get(10);
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo("status");
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(170, 176, "variable", new String[0]));
|
||||
|
||||
token = tokens.get(11);
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo("}");
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(176, 177, "operator", new String[0]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,21 @@ package org.springframework.ide.vscode.boot.java.data.jpa.queries;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ide.vscode.boot.java.spel.SpelSemanticTokens;
|
||||
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData;
|
||||
|
||||
public class JpqlSemanticTokensTest {
|
||||
|
||||
private JpqlSemanticTokens provider = new JpqlSemanticTokens();
|
||||
private JpqlSemanticTokens provider;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
provider = new JpqlSemanticTokens(Optional.empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void simpleQuery_1() {
|
||||
@@ -109,8 +117,39 @@ public class JpqlSemanticTokensTest {
|
||||
assertThat(tokens.get(14)).isEqualTo(new SemanticTokenData(69, 71, "method", new String[0])); // id
|
||||
assertThat(tokens.get(15)).isEqualTo(new SemanticTokenData(72, 73, "operator", new String[0])); // =
|
||||
assertThat(tokens.get(16)).isEqualTo(new SemanticTokenData(73, 74, "operator", new String[0])); // :
|
||||
assertThat(tokens.get(17)).isEqualTo(new SemanticTokenData(74, 79, "regexp", new String[0])); // #{id}
|
||||
assertThat(tokens.get(17)).isEqualTo(new SemanticTokenData(74, 76, "operator", new String[0])); // #{
|
||||
assertThat(tokens.get(18)).isEqualTo(new SemanticTokenData(76, 78, "string", new String[0])); // id
|
||||
assertThat(tokens.get(19)).isEqualTo(new SemanticTokenData(78, 79, "operator", new String[0])); // }
|
||||
|
||||
assertThat(tokens.size()).isEqualTo(18);
|
||||
assertThat(tokens.size()).isEqualTo(20);
|
||||
}
|
||||
|
||||
@Test
|
||||
void query_with_SPEL_Tokens() {
|
||||
provider = new JpqlSemanticTokens(Optional.of(new SpelSemanticTokens()));
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:#{id}", 0);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 12, "variable", new String[0])); // owner
|
||||
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(13, 17, "keyword", new String[0])); // FROM
|
||||
assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(18, 23, "class", new String[0])); // Owner
|
||||
assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(24, 29, "variable", new String[0])); // owner
|
||||
assertThat(tokens.get(5)).isEqualTo(new SemanticTokenData(30, 34, "keyword", new String[0])); // left
|
||||
assertThat(tokens.get(6)).isEqualTo(new SemanticTokenData(35, 39, "keyword", new String[0])); // join
|
||||
assertThat(tokens.get(7)).isEqualTo(new SemanticTokenData(40, 45, "keyword", new String[0])); // fetch
|
||||
assertThat(tokens.get(8)).isEqualTo(new SemanticTokenData(46, 51, "variable", new String[0])); // owner
|
||||
assertThat(tokens.get(9)).isEqualTo(new SemanticTokenData(51, 52, "operator", new String[0])); // .
|
||||
assertThat(tokens.get(10)).isEqualTo(new SemanticTokenData(52, 56, "method", new String[0])); // pets
|
||||
assertThat(tokens.get(11)).isEqualTo(new SemanticTokenData(57, 62, "keyword", new String[0])); // WHERE
|
||||
assertThat(tokens.get(12)).isEqualTo(new SemanticTokenData(63, 68, "variable", new String[0])); // owner
|
||||
assertThat(tokens.get(13)).isEqualTo(new SemanticTokenData(68, 69, "operator", new String[0])); // .
|
||||
assertThat(tokens.get(14)).isEqualTo(new SemanticTokenData(69, 71, "method", new String[0])); // id
|
||||
assertThat(tokens.get(15)).isEqualTo(new SemanticTokenData(72, 73, "operator", new String[0])); // =
|
||||
assertThat(tokens.get(16)).isEqualTo(new SemanticTokenData(73, 74, "operator", new String[0])); // :
|
||||
assertThat(tokens.get(17)).isEqualTo(new SemanticTokenData(74, 76, "operator", new String[0])); // #{
|
||||
assertThat(tokens.get(18)).isEqualTo(new SemanticTokenData(76, 78, "variable", new String[0])); // id
|
||||
assertThat(tokens.get(19)).isEqualTo(new SemanticTokenData(78, 79, "operator", new String[0])); // }
|
||||
|
||||
assertThat(tokens.size()).isEqualTo(20);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*******************************************************************************
|
||||
* 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.spel;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
|
||||
import org.springframework.ide.vscode.boot.bootiful.HoverTestConf;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.CompositeASTVisitor;
|
||||
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
|
||||
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData;
|
||||
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
|
||||
import org.springframework.ide.vscode.commons.util.Collector;
|
||||
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@BootLanguageServerTest
|
||||
@Import(HoverTestConf.class)
|
||||
public class JdtSpelSemanticTokensProviderTest {
|
||||
|
||||
@Autowired JdtSpelSemanticTokensProvider provider;
|
||||
|
||||
private ProjectsHarness projects = ProjectsHarness.INSTANCE;
|
||||
|
||||
private MavenJavaProject jp;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws Exception {
|
||||
jp = projects.mavenProject("spring-modulith-example-full");
|
||||
}
|
||||
|
||||
private List<SemanticTokenData> computeTokens(CompilationUnit cu) {
|
||||
Collector<SemanticTokenData> collector = new Collector<>();
|
||||
CompositeASTVisitor visitor = new CompositeASTVisitor();
|
||||
visitor.add(provider.getTokensComputer(jp, null, cu, collector));
|
||||
cu.accept(visitor);
|
||||
return collector.get();
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalAnnotation() throws Exception {
|
||||
String source = """
|
||||
package my.package
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
public class Owner {
|
||||
|
||||
@Value(value="#{new String('hello world').toUpperCase()}")
|
||||
String s;
|
||||
|
||||
}
|
||||
""";
|
||||
|
||||
String uri = Paths.get(jp.getLocationUri()).resolve("src/main/resource/my/package/OwnerRepository.java").toUri().toASCIIString();
|
||||
CompilationUnit cu = CompilationUnitCache.parse2(source.toCharArray(), uri, "OwnerRepository.java", jp);
|
||||
|
||||
assertThat(cu).isNotNull();
|
||||
|
||||
List<SemanticTokenData> tokens = computeTokens(cu);
|
||||
|
||||
assertThat(tokens.size()).isEqualTo(9);
|
||||
|
||||
SemanticTokenData token = tokens.get(0);
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(119, 122, "keyword", new String[0]));
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo("new");
|
||||
|
||||
token = tokens.get(1);
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(123, 129, "method", new String[0]));
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo("String");
|
||||
|
||||
token = tokens.get(2);
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(129, 130, "operator", new String[0]));
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo("(");
|
||||
|
||||
token = tokens.get(3);
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(130, 143, "string", new String[0]));
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo("'hello world'");
|
||||
|
||||
token = tokens.get(4);
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(143, 144, "operator", new String[0]));
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo(")");
|
||||
|
||||
token = tokens.get(5);
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(144, 145, "operator", new String[0]));
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo(".");
|
||||
|
||||
token = tokens.get(6);
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(145, 156, "method", new String[0]));
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo("toUpperCase");
|
||||
|
||||
token = tokens.get(7);
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(156, 157, "operator", new String[0]));
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo("(");
|
||||
|
||||
token = tokens.get(8);
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(157, 158, "operator", new String[0]));
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo(")");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void singleMemberAnnotation() throws Exception {
|
||||
String source = """
|
||||
package my.package
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
public class Owner {
|
||||
|
||||
@Value("#{'invalid alphabetic string #$1' matches '[a-zA-Z\\s]+' }")
|
||||
String s;
|
||||
|
||||
}
|
||||
""";
|
||||
|
||||
String uri = Paths.get(jp.getLocationUri()).resolve("src/main/resource/my/package/OwnerRepository.java").toUri().toASCIIString();
|
||||
CompilationUnit cu = CompilationUnitCache.parse2(source.toCharArray(), uri, "OwnerRepository.java", jp);
|
||||
|
||||
assertThat(cu).isNotNull();
|
||||
|
||||
List<SemanticTokenData> tokens = computeTokens(cu);
|
||||
|
||||
assertThat(tokens.size()).isEqualTo(3);
|
||||
|
||||
SemanticTokenData token = tokens.get(0);
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(113, 144, "string", new String[0]));
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo("'invalid alphabetic string #$1'");
|
||||
|
||||
token = tokens.get(1);
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(145, 152, "keyword", new String[0]));
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo("matches");
|
||||
|
||||
token = tokens.get(2);
|
||||
assertThat(token).isEqualTo(new SemanticTokenData(153, 166, "string", new String[0]));
|
||||
assertThat(source.substring(token.start(), token.end())).isEqualTo("'[a-zA-Z\\s]+'");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*******************************************************************************
|
||||
* 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.spel;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData;
|
||||
|
||||
public class SpelSemanticTokensTest {
|
||||
|
||||
private SpelSemanticTokens provider = new SpelSemanticTokens();
|
||||
|
||||
@Test
|
||||
void simpleCompare() {
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("1 >= 1", 0);
|
||||
assertThat(tokens.size()).isEqualTo(3);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0]));
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 4, "operator", new String[0]));
|
||||
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(5, 6, "number", new String[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
void simpleCompareWithOp() {
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("1 ge 1", 0);
|
||||
assertThat(tokens.size()).isEqualTo(3);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0]));
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 4, "keyword", new String[0]));
|
||||
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(5, 6, "number", new String[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
void logicalOperators() {
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("4 > 3 or 15 < 10", 0);
|
||||
assertThat(tokens.size()).isEqualTo(7);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0]));
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "operator", new String[0]));
|
||||
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(4, 5, "number", new String[0]));
|
||||
assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(6, 8, "keyword", new String[0]));
|
||||
assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(9, 11, "number", new String[0]));
|
||||
assertThat(tokens.get(5)).isEqualTo(new SemanticTokenData(12, 13, "operator", new String[0]));
|
||||
assertThat(tokens.get(6)).isEqualTo(new SemanticTokenData(14, 16, "number", new String[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
void conditionalOperators() {
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("someBean.someProperty != null ? someBean.someProperty : 'default'", 0);
|
||||
assertThat(tokens.size()).isEqualTo(11);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 8, "variable", new String[0]));
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(8, 9, "operator", new String[0]));
|
||||
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(9, 21, "property", new String[0]));
|
||||
assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(22, 24, "operator", new String[0]));
|
||||
assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(25, 29, "keyword", new String[0]));
|
||||
assertThat(tokens.get(5)).isEqualTo(new SemanticTokenData(30, 31, "operator", new String[0]));
|
||||
assertThat(tokens.get(6)).isEqualTo(new SemanticTokenData(32, 40, "variable", new String[0]));
|
||||
assertThat(tokens.get(7)).isEqualTo(new SemanticTokenData(40, 41, "operator", new String[0]));
|
||||
assertThat(tokens.get(8)).isEqualTo(new SemanticTokenData(41, 53, "property", new String[0]));
|
||||
assertThat(tokens.get(9)).isEqualTo(new SemanticTokenData(54, 55, "operator", new String[0]));
|
||||
assertThat(tokens.get(10)).isEqualTo(new SemanticTokenData(56, 65, "string", new String[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
void regex() {
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("'invalid alphabetic string #$1' matches '[a-zA-Z\\s]+' ", 0);
|
||||
assertThat(tokens.size()).isEqualTo(3);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 31, "string", new String[0]));
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(32, 39, "keyword", new String[0]));
|
||||
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(40, 53, "string", new String[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
void accessMapObj() {
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("carPark.carsByDriver['Driver1']", 0);
|
||||
assertThat(tokens.size()).isEqualTo(6);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 7, "variable", new String[0]));
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 8, "operator", new String[0]));
|
||||
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(8, 20, "property", new String[0]));
|
||||
assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(20, 21, "operator", new String[0]));
|
||||
assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(21, 30, "string", new String[0]));
|
||||
assertThat(tokens.get(5)).isEqualTo(new SemanticTokenData(30, 31, "operator", new String[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
void accessListItems() {
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("carPark.cars[0]", 0);
|
||||
assertThat(tokens.size()).isEqualTo(6);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 7, "variable", new String[0]));
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 8, "operator", new String[0]));
|
||||
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(8, 12, "property", new String[0]));
|
||||
assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(12, 13, "operator", new String[0]));
|
||||
assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(13, 14, "number", new String[0]));
|
||||
assertThat(tokens.get(5)).isEqualTo(new SemanticTokenData(14, 15, "operator", new String[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
void beanReference() {
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("@vetRepo", 0);
|
||||
assertThat(tokens.size()).isEqualTo(2);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "operator", new String[0]));
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(1, 8, "type", new String[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
void contructorAndMethod() {
|
||||
List<SemanticTokenData> tokens = provider.computeTokens("new String('hello world').toUpperCase()", 0);
|
||||
assertThat(tokens.size()).isEqualTo(9);
|
||||
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 3, "keyword", new String[0]));
|
||||
assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(4, 10, "method", new String[0]));
|
||||
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(10, 11, "operator", new String[0]));
|
||||
assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(11, 24, "string", new String[0]));
|
||||
assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(24, 25, "operator", new String[0]));
|
||||
assertThat(tokens.get(5)).isEqualTo(new SemanticTokenData(25, 26, "operator", new String[0]));
|
||||
assertThat(tokens.get(6)).isEqualTo(new SemanticTokenData(26, 37, "method", new String[0]));
|
||||
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]));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2020, 2023 Pivotal, Inc.
|
||||
* Copyright (c) 2020, 2024 Pivotal, 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
|
||||
@@ -15,6 +15,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -45,10 +46,10 @@ import org.springframework.ide.vscode.boot.index.cache.IndexCacheVoid;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.BootJavaReconcileEngine;
|
||||
import org.springframework.ide.vscode.boot.java.links.SourceLinkFactory;
|
||||
import org.springframework.ide.vscode.boot.java.links.SourceLinks;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.AnnotationNodeReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.JavaReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.JdtAstReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.JdtReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.spel.JdtSpelReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
|
||||
import org.springframework.ide.vscode.boot.java.utils.test.MockProjectObserver;
|
||||
import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry;
|
||||
@@ -79,11 +80,11 @@ import com.google.gson.JsonElement;
|
||||
public class ValueSpelExpressionValidationTest {
|
||||
|
||||
@Autowired private BootLanguageServerHarness harness;
|
||||
@Autowired private IJavaProject testProject;
|
||||
@Autowired private JavaProjectFinder projectFinder;
|
||||
@Autowired private CompilationUnitCache compilationUnitCache;
|
||||
@Autowired private SimpleLanguageServer server;
|
||||
@Autowired private BootJavaConfig config;
|
||||
@Autowired private JdtSpelReconciler jdtSpelReconciler;
|
||||
|
||||
private File directory;
|
||||
private String docUri;
|
||||
@@ -149,8 +150,20 @@ public class ValueSpelExpressionValidationTest {
|
||||
@BeforeEach
|
||||
public void setup() throws Exception {
|
||||
harness.intialize(null);
|
||||
|
||||
String changedSettings = "{\"boot-java\": {\"validation\": {\"java\": { \"reconcilers\": true}}}}";
|
||||
String changedSettings = """
|
||||
{
|
||||
"boot-java": {
|
||||
"validation": {
|
||||
"java": {
|
||||
"reconcilers": true
|
||||
},
|
||||
"spel": {
|
||||
"on": "ON"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
JsonElement settingsAsJson = new Gson().fromJson(changedSettings, JsonElement.class);
|
||||
harness.changeConfiguration(new Settings(settingsAsJson));
|
||||
|
||||
@@ -160,7 +173,7 @@ public class ValueSpelExpressionValidationTest {
|
||||
problemCollector = new TestProblemCollector();
|
||||
reconcileEngine = new BootJavaReconcileEngine(projectFinder, new JavaReconciler[] {
|
||||
new JdtReconciler(compilationUnitCache, config, new JdtAstReconciler[] {
|
||||
new AnnotationNodeReconciler(config)
|
||||
jdtSpelReconciler
|
||||
}, new MockProjectObserver())
|
||||
});
|
||||
}
|
||||
@@ -328,7 +341,7 @@ public class ValueSpelExpressionValidationTest {
|
||||
}
|
||||
|
||||
private TextDocument prepareDocument(String selectedAnnotation, String annotationStatementBeforeTest) throws Exception {
|
||||
String content = IOUtils.toString(new URI(docUri));
|
||||
String content = IOUtils.toString(new URI(docUri), StandardCharsets.UTF_8);
|
||||
|
||||
TextDocumentItem docItem = new TextDocumentItem(docUri, LanguageId.JAVA.toString(), 0, content);
|
||||
DidOpenTextDocumentParams openParams = new DidOpenTextDocumentParams(docItem);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2020, 2023 Pivotal, Inc.
|
||||
* Copyright (c) 2020, 2024 Pivotal, 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
|
||||
@@ -15,6 +15,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -35,6 +36,7 @@ import org.springframework.context.annotation.Import;
|
||||
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
|
||||
import org.springframework.ide.vscode.boot.app.BootLanguageServerBootApp;
|
||||
import org.springframework.ide.vscode.boot.bootiful.XmlBeansTestConf;
|
||||
import org.springframework.ide.vscode.boot.java.spel.SpelReconciler;
|
||||
import org.springframework.ide.vscode.boot.xml.SpringXMLReconcileEngine;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
@@ -67,6 +69,7 @@ public class XMLSpelExpressionValidationTest {
|
||||
@Autowired private SimpleLanguageServer server;
|
||||
@Autowired private JavaProjectFinder projectFinder;
|
||||
@Autowired private BootJavaConfig config;
|
||||
@Autowired private SpelReconciler spelReconciler;
|
||||
|
||||
private ProjectsHarness projects = ProjectsHarness.INSTANCE;
|
||||
private MavenJavaProject project;
|
||||
@@ -97,7 +100,7 @@ public class XMLSpelExpressionValidationTest {
|
||||
docUri = directory.toPath().resolve("src/main/webapp/WEB-INF/spring/root-context.xml").toUri().toASCIIString();
|
||||
|
||||
problemCollector = new TestProblemCollector();
|
||||
reconcileEngine = new SpringXMLReconcileEngine(projectFinder, config);
|
||||
reconcileEngine = new SpringXMLReconcileEngine(projectFinder, config, spelReconciler);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -142,7 +145,7 @@ public class XMLSpelExpressionValidationTest {
|
||||
}
|
||||
|
||||
private TextDocument prepareDocument(String selectedAnnotation, String annotationStatementBeforeTest) throws Exception {
|
||||
String content = IOUtils.toString(new URI(docUri));
|
||||
String content = IOUtils.toString(new URI(docUri), StandardCharsets.UTF_8);
|
||||
|
||||
TextDocumentItem docItem = new TextDocumentItem(docUri, LanguageId.XML.toString(), 0, content);
|
||||
DidOpenTextDocumentParams openParams = new DidOpenTextDocumentParams(docItem);
|
||||
|
||||
@@ -1195,4 +1195,4 @@
|
||||
"extensionDependencies": [
|
||||
"redhat.java"
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user