@valtzu/codemirror-lang-el 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -29
- package/dist/index.cjs +42 -17
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +42 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,37 +8,48 @@
|
|
|
8
8
|
```html
|
|
9
9
|
<div id="editor"></div>
|
|
10
10
|
<script type="importmap">
|
|
11
|
-
{
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
{
|
|
12
|
+
"imports": {
|
|
13
|
+
"codemirror": "https://esm.sh/*codemirror@6.0.1",
|
|
14
|
+
"@codemirror/state": "https://esm.sh/*@codemirror/state@6.4.1",
|
|
15
|
+
"@codemirror/search": "https://esm.sh/*@codemirror/search@6.5.6",
|
|
16
|
+
"@codemirror/autocomplete": "https://esm.sh/*@codemirror/autocomplete@6.9.0",
|
|
17
|
+
"@codemirror/view": "https://esm.sh/*@codemirror/view@6.17.1",
|
|
18
|
+
"@codemirror/commands": "https://esm.sh/*@codemirror/commands@6.2.5",
|
|
19
|
+
"@codemirror/language": "https://esm.sh/*@codemirror/language@6.9.0",
|
|
20
|
+
"@codemirror/lint": "https://esm.sh/*@codemirror/lint@6.4.1",
|
|
21
|
+
"@lezer/lr": "https://esm.sh/*@lezer/lr@1.3.9",
|
|
22
|
+
"@lezer/highlight": "https://esm.sh/*@lezer/highlight@1.1.6",
|
|
23
|
+
"@lezer/common": "https://esm.sh/*@lezer/common@1.2.1",
|
|
24
|
+
"style-mod": "https://esm.sh/*style-mod@4.1.2",
|
|
25
|
+
"w3c-keyname": "https://esm.sh/*w3c-keyname@2.2.8",
|
|
26
|
+
"crelt": "https://esm.sh/*crelt@1.0.6",
|
|
27
|
+
"@valtzu/codemirror-lang-el": "https://esm.sh/*@valtzu/codemirror-lang-el@0.2.3"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
19
30
|
</script>
|
|
20
31
|
<script type="module">
|
|
21
|
-
import {EditorView, basicSetup} from "codemirror";
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
32
|
+
import { EditorView, basicSetup } from "codemirror";
|
|
33
|
+
import { acceptCompletion } from "@codemirror/autocomplete";
|
|
34
|
+
import { keymap } from "@codemirror/view";
|
|
35
|
+
import { expressionlanguage } from "@valtzu/codemirror-lang-el";
|
|
25
36
|
|
|
26
|
-
let editor = new EditorView({
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
});
|
|
37
|
+
let editor = new EditorView({
|
|
38
|
+
extensions: [
|
|
39
|
+
basicSetup,
|
|
40
|
+
keymap.of([{key: "Tab", run: acceptCompletion}]),
|
|
41
|
+
expressionlanguage({
|
|
42
|
+
identifiers: [
|
|
43
|
+
{ name: 'foo', info: 'Foo is a variable' },
|
|
44
|
+
{ name: 'bar' }
|
|
45
|
+
],
|
|
46
|
+
functions: [
|
|
47
|
+
{ name: 'smh' },
|
|
48
|
+
{ name: 'smash_my_head', args: ['object'], info: 'This is a function' },
|
|
49
|
+
],
|
|
50
|
+
})
|
|
51
|
+
],
|
|
52
|
+
parent: document.getElementById('editor'),
|
|
53
|
+
});
|
|
43
54
|
</script>
|
|
44
55
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -11,7 +11,7 @@ var view = require('@codemirror/view');
|
|
|
11
11
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
12
12
|
const parser = lr.LRParser.deserialize({
|
|
13
13
|
version: 14,
|
|
14
|
-
states: "$nQVQPOOO!QQQO'#ChO!VQPO'#CjO!^QPO'#CmOOQO'#Cs'#CsOOQO'#Cn'#CnQVQPOOO!eQQO,59SOOQO,59U,59UO!
|
|
14
|
+
states: "$nQVQPOOO!QQQO'#ChO!VQPO'#CjO!^QPO'#CmOOQO'#Cs'#CsOOQO'#Cn'#CnQVQPOOO!eQQO,59SOOQO,59U,59UO!jQQO,59UOOQO,59X,59XO!rQPO,59XOOQO-E6l-E6lOVQPO1G.nOVQPO'#CoO!yQQO1G.pOOQO1G.p1G.pOOQO1G.s1G.sO#RQQO7+$YOOQO,59Z,59ZOOQO-E6m-E6mOOQO7+$[7+$[OOQO<<Gt<<GtO#ZQQO<<GtO#`QQOAN=`OVQPOG22zO#eQPOLD(fOOQO!$'LQ!$'LQ",
|
|
15
15
|
stateData: "#r~OfOS~OQSORSOSSOTSOUSOVSOWSOXSOYSOZSO`ROiPOmQO~O]VO~OlWO~PVO_YO~PVOj]O~Ok^Ol`O~O_aO~PVOk^OleO~OhfOkgO~O]hO~OjiO~OhkO~OQUTXWRW~",
|
|
16
16
|
goto: "!ghPPPPPPPPPPPPiPiPPis}PPP!TaSOQRUZ]^iQUOQZRT[UZQ_XRd_WTORUZQXQQb]Qc^Rji",
|
|
17
17
|
nodeNames: "⚠ Program Number Identifier String Boolean Null Operator OperatorKeyword Punctuation NullSafe NullCoalescing Object ObjectKey Array ClosingBracket OpeningBracket Application",
|
|
@@ -22,7 +22,7 @@ const parser = lr.LRParser.deserialize({
|
|
|
22
22
|
],
|
|
23
23
|
skippedNodes: [0],
|
|
24
24
|
repeatNodeCount: 2,
|
|
25
|
-
tokenData: "
|
|
25
|
+
tokenData: "B{~R!QXY$XYZ$X]^$Xpq$Xqr$jrs%Puv$zvw&{wx'Txy(xyz(}z{)S{|$z|})[}!O$z!O!P)c!P!Q$z!Q![*t![!],T!^!_$r!_!`,[!`!a$r!a!b,b!c!},w!}#O-[#P#Q-a#Q#R$z#R#S,w#T#U-f#U#V,w#V#W/P#W#X,w#X#Y2s#Y#Z5g#Z#],w#]#^8R#^#a,w#a#b8l#b#c;[#c#d>u#d#g,w#g#h?`#h#iAe#i#o,w#o#pBi#p#qBn#q#rBv#r#s$z~$^Sf~XY$XYZ$X]^$Xpq$X~$oPV~!_!`$r~$wPV~!_!`$z~%POV~R%SXOr%Prs%os#O%P#O#P%v#P;'S%P;'S;=`&u<%l~%P~O%P~~%oR%vO]QSPR%yRO;'S%P;'S;=`&S;=`O%PR&VYOr%Prs%os#O%P#O#P%v#P;'S%P;'S;=`&u;=`<%l%P<%l~%P~O%P~~%oR&xP;=`<%l%P~'QPV~vw$zR'WXOw'Twx%ox#O'T#O#P's#P;'S'T;'S;=`(r<%l~'T~O'T~~%oR'vRO;'S'T;'S;=`(P;=`O'TR(SYOw'Twx%ox#O'T#O#P's#P;'S'T;'S;=`(r;=`<%l'T<%l~'T~O'T~~%oR(uP;=`<%l'T~(}O`~~)SO_~~)XPV~z{$zR)cOkQXP~)hQXP!O!P$z!Q![)n~)sSQ~!Q![)n!g!h*P#R#S*n#X#Y*P~*SR{|*]}!O*]!Q![*c~*`P!Q![*c~*hQQ~!Q![*c#R#S*]~*qP!Q![)n~*yTQ~!O!P+Y!Q![*t!g!h*P#R#S+}#X#Y*P~+]SO!O+i!P;'S+i;'S;=`+w<%lO+i~+nRQ~!Q![)n!g!h*P#X#Y*P~+zP;=`<%l+i~,QP!Q![*tR,[OjQXP~,_P!_!`$r~,gQXP!O!P,m!a!b,r~,rOY~~,wOZ~R-OS]QRP!Q![,w!c!},w#R#S,w#T#o,w~-aOm~~-fOl~R-mU]QRP!Q![,w!c!},w#R#S,w#T#b,w#b#c.P#c#o,wR.WU]QRP!Q![,w!c!},w#R#S,w#T#W,w#W#X.j#X#o,wR.sS]QWPRP!Q![,w!c!},w#R#S,w#T#o,wR/WU]QRP!Q![,w!c!},w#R#S,w#T#c,w#c#d/j#d#o,wR/qU]QRP!Q![,w!c!},w#R#S,w#T#b,w#b#c0T#c#o,wR0[U]QRP!Q![,w!c!},w#R#S,w#T#h,w#h#i0n#i#o,wR0uT]QRP!Q![,w!c!},w#R#S,w#T#U1U#U#o,wR1]U]QRP!Q![,w!c!},w#R#S,w#T#],w#]#^1o#^#o,wR1vU]QRP!Q![,w!c!},w#R#S,w#T#b,w#b#c2Y#c#o,wR2aU]QRP!Q![,w!c!},w#R#S,w#T#g,w#g#h.j#h#o,wR2zU]QRP!Q![,w!c!},w#R#S,w#T#b,w#b#c3^#c#o,wR3eU]QRP!Q![,w!c!},w#R#S,w#T#W,w#W#X3w#X#o,wR4OU]QRP!Q![,w!c!},w#R#S,w#T#g,w#g#h4b#h#o,wR4iT]QRPpq4x!Q![,w!c!},w#R#S,w#T#o,wP4{P#k#l5OP5RP#]#^5UP5XP#h#i5[P5_P#[#]5bP5gOWPR5nT]QRP!Q![,w!c!},w#R#S,w#T#U5}#U#o,wR6UU]QRP!Q![,w!c!},w#R#S,w#T#`,w#`#a6h#a#o,wR6oU]QRP!Q![,w!c!},w#R#S,w#T#g,w#g#h7R#h#o,wR7YU]QRP!Q![,w!c!},w#R#S,w#T#X,w#X#Y7l#Y#o,wR7uS]QTPRP!Q![,w!c!},w#R#S,w#T#o,wR8YU]QRP!Q![,w!c!},w#R#S,w#T#b,w#b#c.j#c#o,wR8sT]QRP!Q![,w!c!},w#R#S,w#T#U9S#U#o,wR9ZU]QRP!Q![,w!c!},w#R#S,w#T#h,w#h#i9m#i#o,wR9tU]QRP!Q![,w!c!},w#R#S,w#T#V,w#V#W:W#W#o,wR:_U]QRP!Q![,w!c!},w#R#S,w#T#[,w#[#]:q#]#o,wR:xU]QRP!Q![,w!c!},w#R#S,w#T#X,w#X#Y2Y#Y#o,wR;cW]QRP!Q![,w!c!},w#R#S,w#T#c,w#c#d;{#d#i,w#i#j=[#j#o,wR<SU]QRP!Q![,w!c!},w#R#S,w#T#h,w#h#i<f#i#o,wR<oT]QWPRPpq=O!Q![,w!c!},w#R#S,w#T#o,wP=RP#]#^=UP=XP#b#c5bR=cU]QRP!Q![,w!c!},w#R#S,w#T#`,w#`#a=u#a#o,wR=|U]QRP!Q![,w!c!},w#R#S,w#T#`,w#`#a>`#a#o,wR>iS]QUPRP!Q![,w!c!},w#R#S,w#T#o,wR>|U]QRP!Q![,w!c!},w#R#S,w#T#f,w#f#g.j#g#o,wR?gU]QRP!Q![,w!c!},w#R#S,w#T#h,w#h#i?y#i#o,wR@QT]QRP!Q![,w!c!},w#R#S,w#T#U@a#U#o,wR@hU]QRP!Q![,w!c!},w#R#S,w#T#f,w#f#g@z#g#o,wRARU]QRP!Q![,w!c!},w#R#S,w#T#h,w#h#i3w#i#o,wRAlU]QRP!Q![,w!c!},w#R#S,w#T#f,w#f#gBO#g#o,wRBVU]QRP!Q![,w!c!},w#R#S,w#T#i,w#i#j7R#j#o,w~BnOi~~BsPV~#p#q$z~B{Oh~",
|
|
26
26
|
tokenizers: [0, 1],
|
|
27
27
|
topRules: {"Program":[0,1]},
|
|
28
28
|
tokenPrec: 118
|
|
@@ -33,8 +33,18 @@ const isFunction = (identifier, config) => { var _a; return (_a = config.functio
|
|
|
33
33
|
const isVariable = (identifier, config) => { var _a; return (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.find(variable => variable.name === identifier); };
|
|
34
34
|
const expressionLanguageLinter = (config) => lint.linter(view => {
|
|
35
35
|
let diagnostics = [];
|
|
36
|
+
let previousNode = null;
|
|
36
37
|
language.syntaxTree(view.state).cursor().iterate(node => {
|
|
38
|
+
var _a;
|
|
37
39
|
if (node.name == "Identifier") {
|
|
40
|
+
if ((previousNode === null || previousNode === void 0 ? void 0 : previousNode.name) == "Identifier" && ((_a = node.node.parent) === null || _a === void 0 ? void 0 : _a.name) != 'Array') {
|
|
41
|
+
diagnostics.push({
|
|
42
|
+
from: node.from,
|
|
43
|
+
to: node.to,
|
|
44
|
+
severity: 'error',
|
|
45
|
+
message: `Unexpected identifier after another identifier`,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
38
48
|
const identifier = view.state.sliceDoc(node.from, node.to);
|
|
39
49
|
if (!isFunction(identifier, config) && !isVariable(identifier, config)) {
|
|
40
50
|
diagnostics.push({
|
|
@@ -45,6 +55,7 @@ const expressionLanguageLinter = (config) => lint.linter(view => {
|
|
|
45
55
|
});
|
|
46
56
|
}
|
|
47
57
|
}
|
|
58
|
+
previousNode = node.node;
|
|
48
59
|
});
|
|
49
60
|
return diagnostics;
|
|
50
61
|
});
|
|
@@ -104,48 +115,62 @@ const ELLanguage = language.LRLanguage.define({
|
|
|
104
115
|
}),
|
|
105
116
|
languageData: {}
|
|
106
117
|
});
|
|
107
|
-
function completeOperatorKeyword(state, config, tree, from, to) {
|
|
118
|
+
function completeOperatorKeyword(state, config, tree, from, to, explicit) {
|
|
108
119
|
var _a, _b;
|
|
109
120
|
const text = state.sliceDoc(from, to);
|
|
110
121
|
return {
|
|
111
122
|
from,
|
|
112
123
|
to,
|
|
113
|
-
options: (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.filter(
|
|
114
|
-
validFor: (text) => { var _a, _b; return (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.some(
|
|
124
|
+
options: (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.filter(({ name }) => explicit || name.startsWith(text)).map(({ name, info, detail }) => ({ label: name, apply: `${name} `, info, detail, type: "keyword" }))) !== null && _b !== void 0 ? _b : [],
|
|
125
|
+
validFor: (text) => { var _a, _b; return (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.some(({ name }) => explicit || name.startsWith(text))) !== null && _b !== void 0 ? _b : false; },
|
|
115
126
|
};
|
|
116
127
|
}
|
|
117
|
-
function completeIdentifier(state, config, tree, from, to) {
|
|
118
|
-
var _a, _b, _c, _d, _e, _f;
|
|
128
|
+
function completeIdentifier(state, config, tree, from, to, explicit) {
|
|
129
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
119
130
|
const text = state.sliceDoc(from, to);
|
|
120
|
-
const identifiers = (_b = (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.filter(({ name }) => name.startsWith(text))) !== null && _b !== void 0 ? _b : [];
|
|
121
|
-
const functions = (_d = (_c = config.functions) === null || _c === void 0 ? void 0 : _c.filter(({ name }) => name.startsWith(text))) !== null && _d !== void 0 ? _d : [];
|
|
131
|
+
const identifiers = (_b = (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.filter(({ name }) => explicit || name.startsWith(text))) !== null && _b !== void 0 ? _b : [];
|
|
132
|
+
const functions = (_d = (_c = config.functions) === null || _c === void 0 ? void 0 : _c.filter(({ name }) => explicit || name.startsWith(text))) !== null && _d !== void 0 ? _d : [];
|
|
133
|
+
const prevName = (_e = tree.prevSibling) === null || _e === void 0 ? void 0 : _e.name;
|
|
134
|
+
const apply = (name) => !prevName || !['OpeningBracket', 'Operator', 'OperatorKeyword', 'Punctuation'].includes(prevName) ? `${name} ` : name;
|
|
122
135
|
return {
|
|
123
136
|
from,
|
|
124
137
|
to,
|
|
125
138
|
options: [
|
|
126
|
-
...((
|
|
127
|
-
...((
|
|
139
|
+
...((_f = identifiers.map(({ name, info, detail }) => ({ label: name, apply: apply(name), info, detail, type: 'variable' }))) !== null && _f !== void 0 ? _f : []),
|
|
140
|
+
...((_g = functions.map(({ name, args = [], info }) => ({ label: name, detail: `(${args.join(',')})`, apply: `${name}(${args.length == 0 ? ')' : ''}`, info, type: "function" }))) !== null && _g !== void 0 ? _g : []),
|
|
128
141
|
],
|
|
129
142
|
validFor: identifier,
|
|
130
143
|
};
|
|
131
144
|
}
|
|
132
145
|
function expressionLanguageCompletionFor(config, context) {
|
|
133
|
-
let { state, pos } = context;
|
|
146
|
+
let { state, pos, explicit } = context;
|
|
134
147
|
let tree = language.syntaxTree(state).resolveInner(pos, -1);
|
|
148
|
+
const isOperator = (node) => ['Operator', 'OperatorKeyword', 'Punctuation', 'NullSafe', 'NullCoalescing', 'OpeningBracket'].includes(node.name);
|
|
149
|
+
const isIdentifier = (node) => node.name === 'Identifier';
|
|
135
150
|
if (tree.name == 'String') {
|
|
136
151
|
return null;
|
|
137
152
|
}
|
|
138
|
-
if (tree.prevSibling && !
|
|
139
|
-
return completeOperatorKeyword(state, config, tree, tree.from, pos);
|
|
153
|
+
if (tree.prevSibling && !isOperator(tree.prevSibling) && (!explicit || !isOperator(tree.node))) {
|
|
154
|
+
return completeOperatorKeyword(state, config, tree, tree.from, pos, explicit);
|
|
140
155
|
}
|
|
141
|
-
if (tree.
|
|
142
|
-
return completeIdentifier(state, config, tree, tree.from, pos);
|
|
156
|
+
if ((!tree.prevSibling || !isIdentifier(tree.prevSibling) || isOperator(tree.node)) && (explicit || isIdentifier(tree.node))) {
|
|
157
|
+
return completeIdentifier(state, config, tree, isIdentifier(tree.node) ? tree.from : pos, pos, explicit);
|
|
143
158
|
}
|
|
144
159
|
return null;
|
|
145
160
|
}
|
|
146
161
|
function expressionLanguageCompletionSourceWith(config) {
|
|
147
162
|
var _a;
|
|
148
|
-
(_a = config.operatorKeywords) !== null && _a !== void 0 ? _a : (config.operatorKeywords = [
|
|
163
|
+
(_a = config.operatorKeywords) !== null && _a !== void 0 ? _a : (config.operatorKeywords = [
|
|
164
|
+
{ name: 'starts with' },
|
|
165
|
+
{ name: 'ends with' },
|
|
166
|
+
{ name: 'contains' },
|
|
167
|
+
{ name: 'matches' },
|
|
168
|
+
{ name: 'not in' },
|
|
169
|
+
{ name: 'in' },
|
|
170
|
+
{ name: 'not' },
|
|
171
|
+
{ name: 'or' },
|
|
172
|
+
{ name: 'and' },
|
|
173
|
+
]);
|
|
149
174
|
return (context) => expressionLanguageCompletionFor(config, context);
|
|
150
175
|
}
|
|
151
176
|
function expressionlanguage(config = {}, extensions = []) {
|
package/dist/index.d.cts
CHANGED
|
@@ -10,7 +10,11 @@ interface ExpressionLanguageConfig {
|
|
|
10
10
|
args: string[];
|
|
11
11
|
info?: string;
|
|
12
12
|
}[];
|
|
13
|
-
operatorKeywords?: readonly
|
|
13
|
+
operatorKeywords?: readonly {
|
|
14
|
+
name: string;
|
|
15
|
+
detail?: string;
|
|
16
|
+
info?: string;
|
|
17
|
+
}[];
|
|
14
18
|
}
|
|
15
19
|
declare const keywordTooltip: (config: ExpressionLanguageConfig) => import("@codemirror/state").Extension;
|
|
16
20
|
declare const ELLanguage: LRLanguage;
|
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,11 @@ interface ExpressionLanguageConfig {
|
|
|
10
10
|
args: string[];
|
|
11
11
|
info?: string;
|
|
12
12
|
}[];
|
|
13
|
-
operatorKeywords?: readonly
|
|
13
|
+
operatorKeywords?: readonly {
|
|
14
|
+
name: string;
|
|
15
|
+
detail?: string;
|
|
16
|
+
info?: string;
|
|
17
|
+
}[];
|
|
14
18
|
}
|
|
15
19
|
declare const keywordTooltip: (config: ExpressionLanguageConfig) => import("@codemirror/state").Extension;
|
|
16
20
|
declare const ELLanguage: LRLanguage;
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { hoverTooltip } from '@codemirror/view';
|
|
|
7
7
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
8
8
|
const parser = LRParser.deserialize({
|
|
9
9
|
version: 14,
|
|
10
|
-
states: "$nQVQPOOO!QQQO'#ChO!VQPO'#CjO!^QPO'#CmOOQO'#Cs'#CsOOQO'#Cn'#CnQVQPOOO!eQQO,59SOOQO,59U,59UO!
|
|
10
|
+
states: "$nQVQPOOO!QQQO'#ChO!VQPO'#CjO!^QPO'#CmOOQO'#Cs'#CsOOQO'#Cn'#CnQVQPOOO!eQQO,59SOOQO,59U,59UO!jQQO,59UOOQO,59X,59XO!rQPO,59XOOQO-E6l-E6lOVQPO1G.nOVQPO'#CoO!yQQO1G.pOOQO1G.p1G.pOOQO1G.s1G.sO#RQQO7+$YOOQO,59Z,59ZOOQO-E6m-E6mOOQO7+$[7+$[OOQO<<Gt<<GtO#ZQQO<<GtO#`QQOAN=`OVQPOG22zO#eQPOLD(fOOQO!$'LQ!$'LQ",
|
|
11
11
|
stateData: "#r~OfOS~OQSORSOSSOTSOUSOVSOWSOXSOYSOZSO`ROiPOmQO~O]VO~OlWO~PVO_YO~PVOj]O~Ok^Ol`O~O_aO~PVOk^OleO~OhfOkgO~O]hO~OjiO~OhkO~OQUTXWRW~",
|
|
12
12
|
goto: "!ghPPPPPPPPPPPPiPiPPis}PPP!TaSOQRUZ]^iQUOQZRT[UZQ_XRd_WTORUZQXQQb]Qc^Rji",
|
|
13
13
|
nodeNames: "⚠ Program Number Identifier String Boolean Null Operator OperatorKeyword Punctuation NullSafe NullCoalescing Object ObjectKey Array ClosingBracket OpeningBracket Application",
|
|
@@ -18,7 +18,7 @@ const parser = LRParser.deserialize({
|
|
|
18
18
|
],
|
|
19
19
|
skippedNodes: [0],
|
|
20
20
|
repeatNodeCount: 2,
|
|
21
|
-
tokenData: "
|
|
21
|
+
tokenData: "B{~R!QXY$XYZ$X]^$Xpq$Xqr$jrs%Puv$zvw&{wx'Txy(xyz(}z{)S{|$z|})[}!O$z!O!P)c!P!Q$z!Q![*t![!],T!^!_$r!_!`,[!`!a$r!a!b,b!c!},w!}#O-[#P#Q-a#Q#R$z#R#S,w#T#U-f#U#V,w#V#W/P#W#X,w#X#Y2s#Y#Z5g#Z#],w#]#^8R#^#a,w#a#b8l#b#c;[#c#d>u#d#g,w#g#h?`#h#iAe#i#o,w#o#pBi#p#qBn#q#rBv#r#s$z~$^Sf~XY$XYZ$X]^$Xpq$X~$oPV~!_!`$r~$wPV~!_!`$z~%POV~R%SXOr%Prs%os#O%P#O#P%v#P;'S%P;'S;=`&u<%l~%P~O%P~~%oR%vO]QSPR%yRO;'S%P;'S;=`&S;=`O%PR&VYOr%Prs%os#O%P#O#P%v#P;'S%P;'S;=`&u;=`<%l%P<%l~%P~O%P~~%oR&xP;=`<%l%P~'QPV~vw$zR'WXOw'Twx%ox#O'T#O#P's#P;'S'T;'S;=`(r<%l~'T~O'T~~%oR'vRO;'S'T;'S;=`(P;=`O'TR(SYOw'Twx%ox#O'T#O#P's#P;'S'T;'S;=`(r;=`<%l'T<%l~'T~O'T~~%oR(uP;=`<%l'T~(}O`~~)SO_~~)XPV~z{$zR)cOkQXP~)hQXP!O!P$z!Q![)n~)sSQ~!Q![)n!g!h*P#R#S*n#X#Y*P~*SR{|*]}!O*]!Q![*c~*`P!Q![*c~*hQQ~!Q![*c#R#S*]~*qP!Q![)n~*yTQ~!O!P+Y!Q![*t!g!h*P#R#S+}#X#Y*P~+]SO!O+i!P;'S+i;'S;=`+w<%lO+i~+nRQ~!Q![)n!g!h*P#X#Y*P~+zP;=`<%l+i~,QP!Q![*tR,[OjQXP~,_P!_!`$r~,gQXP!O!P,m!a!b,r~,rOY~~,wOZ~R-OS]QRP!Q![,w!c!},w#R#S,w#T#o,w~-aOm~~-fOl~R-mU]QRP!Q![,w!c!},w#R#S,w#T#b,w#b#c.P#c#o,wR.WU]QRP!Q![,w!c!},w#R#S,w#T#W,w#W#X.j#X#o,wR.sS]QWPRP!Q![,w!c!},w#R#S,w#T#o,wR/WU]QRP!Q![,w!c!},w#R#S,w#T#c,w#c#d/j#d#o,wR/qU]QRP!Q![,w!c!},w#R#S,w#T#b,w#b#c0T#c#o,wR0[U]QRP!Q![,w!c!},w#R#S,w#T#h,w#h#i0n#i#o,wR0uT]QRP!Q![,w!c!},w#R#S,w#T#U1U#U#o,wR1]U]QRP!Q![,w!c!},w#R#S,w#T#],w#]#^1o#^#o,wR1vU]QRP!Q![,w!c!},w#R#S,w#T#b,w#b#c2Y#c#o,wR2aU]QRP!Q![,w!c!},w#R#S,w#T#g,w#g#h.j#h#o,wR2zU]QRP!Q![,w!c!},w#R#S,w#T#b,w#b#c3^#c#o,wR3eU]QRP!Q![,w!c!},w#R#S,w#T#W,w#W#X3w#X#o,wR4OU]QRP!Q![,w!c!},w#R#S,w#T#g,w#g#h4b#h#o,wR4iT]QRPpq4x!Q![,w!c!},w#R#S,w#T#o,wP4{P#k#l5OP5RP#]#^5UP5XP#h#i5[P5_P#[#]5bP5gOWPR5nT]QRP!Q![,w!c!},w#R#S,w#T#U5}#U#o,wR6UU]QRP!Q![,w!c!},w#R#S,w#T#`,w#`#a6h#a#o,wR6oU]QRP!Q![,w!c!},w#R#S,w#T#g,w#g#h7R#h#o,wR7YU]QRP!Q![,w!c!},w#R#S,w#T#X,w#X#Y7l#Y#o,wR7uS]QTPRP!Q![,w!c!},w#R#S,w#T#o,wR8YU]QRP!Q![,w!c!},w#R#S,w#T#b,w#b#c.j#c#o,wR8sT]QRP!Q![,w!c!},w#R#S,w#T#U9S#U#o,wR9ZU]QRP!Q![,w!c!},w#R#S,w#T#h,w#h#i9m#i#o,wR9tU]QRP!Q![,w!c!},w#R#S,w#T#V,w#V#W:W#W#o,wR:_U]QRP!Q![,w!c!},w#R#S,w#T#[,w#[#]:q#]#o,wR:xU]QRP!Q![,w!c!},w#R#S,w#T#X,w#X#Y2Y#Y#o,wR;cW]QRP!Q![,w!c!},w#R#S,w#T#c,w#c#d;{#d#i,w#i#j=[#j#o,wR<SU]QRP!Q![,w!c!},w#R#S,w#T#h,w#h#i<f#i#o,wR<oT]QWPRPpq=O!Q![,w!c!},w#R#S,w#T#o,wP=RP#]#^=UP=XP#b#c5bR=cU]QRP!Q![,w!c!},w#R#S,w#T#`,w#`#a=u#a#o,wR=|U]QRP!Q![,w!c!},w#R#S,w#T#`,w#`#a>`#a#o,wR>iS]QUPRP!Q![,w!c!},w#R#S,w#T#o,wR>|U]QRP!Q![,w!c!},w#R#S,w#T#f,w#f#g.j#g#o,wR?gU]QRP!Q![,w!c!},w#R#S,w#T#h,w#h#i?y#i#o,wR@QT]QRP!Q![,w!c!},w#R#S,w#T#U@a#U#o,wR@hU]QRP!Q![,w!c!},w#R#S,w#T#f,w#f#g@z#g#o,wRARU]QRP!Q![,w!c!},w#R#S,w#T#h,w#h#i3w#i#o,wRAlU]QRP!Q![,w!c!},w#R#S,w#T#f,w#f#gBO#g#o,wRBVU]QRP!Q![,w!c!},w#R#S,w#T#i,w#i#j7R#j#o,w~BnOi~~BsPV~#p#q$z~B{Oh~",
|
|
22
22
|
tokenizers: [0, 1],
|
|
23
23
|
topRules: {"Program":[0,1]},
|
|
24
24
|
tokenPrec: 118
|
|
@@ -29,8 +29,18 @@ const isFunction = (identifier, config) => { var _a; return (_a = config.functio
|
|
|
29
29
|
const isVariable = (identifier, config) => { var _a; return (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.find(variable => variable.name === identifier); };
|
|
30
30
|
const expressionLanguageLinter = (config) => linter(view => {
|
|
31
31
|
let diagnostics = [];
|
|
32
|
+
let previousNode = null;
|
|
32
33
|
syntaxTree(view.state).cursor().iterate(node => {
|
|
34
|
+
var _a;
|
|
33
35
|
if (node.name == "Identifier") {
|
|
36
|
+
if ((previousNode === null || previousNode === void 0 ? void 0 : previousNode.name) == "Identifier" && ((_a = node.node.parent) === null || _a === void 0 ? void 0 : _a.name) != 'Array') {
|
|
37
|
+
diagnostics.push({
|
|
38
|
+
from: node.from,
|
|
39
|
+
to: node.to,
|
|
40
|
+
severity: 'error',
|
|
41
|
+
message: `Unexpected identifier after another identifier`,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
34
44
|
const identifier = view.state.sliceDoc(node.from, node.to);
|
|
35
45
|
if (!isFunction(identifier, config) && !isVariable(identifier, config)) {
|
|
36
46
|
diagnostics.push({
|
|
@@ -41,6 +51,7 @@ const expressionLanguageLinter = (config) => linter(view => {
|
|
|
41
51
|
});
|
|
42
52
|
}
|
|
43
53
|
}
|
|
54
|
+
previousNode = node.node;
|
|
44
55
|
});
|
|
45
56
|
return diagnostics;
|
|
46
57
|
});
|
|
@@ -100,48 +111,62 @@ const ELLanguage = LRLanguage.define({
|
|
|
100
111
|
}),
|
|
101
112
|
languageData: {}
|
|
102
113
|
});
|
|
103
|
-
function completeOperatorKeyword(state, config, tree, from, to) {
|
|
114
|
+
function completeOperatorKeyword(state, config, tree, from, to, explicit) {
|
|
104
115
|
var _a, _b;
|
|
105
116
|
const text = state.sliceDoc(from, to);
|
|
106
117
|
return {
|
|
107
118
|
from,
|
|
108
119
|
to,
|
|
109
|
-
options: (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.filter(
|
|
110
|
-
validFor: (text) => { var _a, _b; return (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.some(
|
|
120
|
+
options: (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.filter(({ name }) => explicit || name.startsWith(text)).map(({ name, info, detail }) => ({ label: name, apply: `${name} `, info, detail, type: "keyword" }))) !== null && _b !== void 0 ? _b : [],
|
|
121
|
+
validFor: (text) => { var _a, _b; return (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.some(({ name }) => explicit || name.startsWith(text))) !== null && _b !== void 0 ? _b : false; },
|
|
111
122
|
};
|
|
112
123
|
}
|
|
113
|
-
function completeIdentifier(state, config, tree, from, to) {
|
|
114
|
-
var _a, _b, _c, _d, _e, _f;
|
|
124
|
+
function completeIdentifier(state, config, tree, from, to, explicit) {
|
|
125
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
115
126
|
const text = state.sliceDoc(from, to);
|
|
116
|
-
const identifiers = (_b = (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.filter(({ name }) => name.startsWith(text))) !== null && _b !== void 0 ? _b : [];
|
|
117
|
-
const functions = (_d = (_c = config.functions) === null || _c === void 0 ? void 0 : _c.filter(({ name }) => name.startsWith(text))) !== null && _d !== void 0 ? _d : [];
|
|
127
|
+
const identifiers = (_b = (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.filter(({ name }) => explicit || name.startsWith(text))) !== null && _b !== void 0 ? _b : [];
|
|
128
|
+
const functions = (_d = (_c = config.functions) === null || _c === void 0 ? void 0 : _c.filter(({ name }) => explicit || name.startsWith(text))) !== null && _d !== void 0 ? _d : [];
|
|
129
|
+
const prevName = (_e = tree.prevSibling) === null || _e === void 0 ? void 0 : _e.name;
|
|
130
|
+
const apply = (name) => !prevName || !['OpeningBracket', 'Operator', 'OperatorKeyword', 'Punctuation'].includes(prevName) ? `${name} ` : name;
|
|
118
131
|
return {
|
|
119
132
|
from,
|
|
120
133
|
to,
|
|
121
134
|
options: [
|
|
122
|
-
...((
|
|
123
|
-
...((
|
|
135
|
+
...((_f = identifiers.map(({ name, info, detail }) => ({ label: name, apply: apply(name), info, detail, type: 'variable' }))) !== null && _f !== void 0 ? _f : []),
|
|
136
|
+
...((_g = functions.map(({ name, args = [], info }) => ({ label: name, detail: `(${args.join(',')})`, apply: `${name}(${args.length == 0 ? ')' : ''}`, info, type: "function" }))) !== null && _g !== void 0 ? _g : []),
|
|
124
137
|
],
|
|
125
138
|
validFor: identifier,
|
|
126
139
|
};
|
|
127
140
|
}
|
|
128
141
|
function expressionLanguageCompletionFor(config, context) {
|
|
129
|
-
let { state, pos } = context;
|
|
142
|
+
let { state, pos, explicit } = context;
|
|
130
143
|
let tree = syntaxTree(state).resolveInner(pos, -1);
|
|
144
|
+
const isOperator = (node) => ['Operator', 'OperatorKeyword', 'Punctuation', 'NullSafe', 'NullCoalescing', 'OpeningBracket'].includes(node.name);
|
|
145
|
+
const isIdentifier = (node) => node.name === 'Identifier';
|
|
131
146
|
if (tree.name == 'String') {
|
|
132
147
|
return null;
|
|
133
148
|
}
|
|
134
|
-
if (tree.prevSibling && !
|
|
135
|
-
return completeOperatorKeyword(state, config, tree, tree.from, pos);
|
|
149
|
+
if (tree.prevSibling && !isOperator(tree.prevSibling) && (!explicit || !isOperator(tree.node))) {
|
|
150
|
+
return completeOperatorKeyword(state, config, tree, tree.from, pos, explicit);
|
|
136
151
|
}
|
|
137
|
-
if (tree.
|
|
138
|
-
return completeIdentifier(state, config, tree, tree.from, pos);
|
|
152
|
+
if ((!tree.prevSibling || !isIdentifier(tree.prevSibling) || isOperator(tree.node)) && (explicit || isIdentifier(tree.node))) {
|
|
153
|
+
return completeIdentifier(state, config, tree, isIdentifier(tree.node) ? tree.from : pos, pos, explicit);
|
|
139
154
|
}
|
|
140
155
|
return null;
|
|
141
156
|
}
|
|
142
157
|
function expressionLanguageCompletionSourceWith(config) {
|
|
143
158
|
var _a;
|
|
144
|
-
(_a = config.operatorKeywords) !== null && _a !== void 0 ? _a : (config.operatorKeywords = [
|
|
159
|
+
(_a = config.operatorKeywords) !== null && _a !== void 0 ? _a : (config.operatorKeywords = [
|
|
160
|
+
{ name: 'starts with' },
|
|
161
|
+
{ name: 'ends with' },
|
|
162
|
+
{ name: 'contains' },
|
|
163
|
+
{ name: 'matches' },
|
|
164
|
+
{ name: 'not in' },
|
|
165
|
+
{ name: 'in' },
|
|
166
|
+
{ name: 'not' },
|
|
167
|
+
{ name: 'or' },
|
|
168
|
+
{ name: 'and' },
|
|
169
|
+
]);
|
|
145
170
|
return (context) => expressionLanguageCompletionFor(config, context);
|
|
146
171
|
}
|
|
147
172
|
function expressionlanguage(config = {}, extensions = []) {
|
package/package.json
CHANGED