@valtzu/codemirror-lang-el 0.1.13 → 0.2.2
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 +33 -7
- package/dist/index.cjs +36 -15
- package/dist/index.d.cts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +36 -15
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,18 +1,44 @@
|
|
|
1
1
|
# Symfony Expression Language support for CodeMirror
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
### Example
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
```html
|
|
9
|
+
<div id="editor"></div>
|
|
10
|
+
<script type="importmap">
|
|
11
|
+
{
|
|
12
|
+
"imports": {
|
|
13
|
+
"codemirror": "https://esm.sh/codemirror@6.0.1",
|
|
14
|
+
"@codemirror/autocomplete": "https://esm.sh/@codemirror/autocomplete@6.9.0",
|
|
15
|
+
"@codemirror/view": "https://esm.sh/@codemirror/view@6.17.1",
|
|
16
|
+
"@valtzu/codemirror-lang-el": "https://esm.sh/@valtzu/codemirror-lang-el@0.2.1"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
</script>
|
|
20
|
+
<script type="module">
|
|
4
21
|
import {EditorView, basicSetup} from "codemirror";
|
|
5
22
|
import { expressionlanguage } from "@valtzu/codemirror-lang-el";
|
|
6
23
|
import {acceptCompletion} from "@codemirror/autocomplete";
|
|
7
|
-
import {keymap} from "@codemirror/view"
|
|
24
|
+
import {keymap} from "@codemirror/view";
|
|
8
25
|
|
|
9
26
|
let editor = new EditorView({
|
|
10
27
|
extensions: [
|
|
11
|
-
keymap.of([{key: "Tab", run: acceptCompletion}]),
|
|
12
28
|
basicSetup,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
29
|
+
keymap.of([{key: "Tab", run: acceptCompletion}]),
|
|
30
|
+
expressionlanguage({
|
|
31
|
+
identifiers: [
|
|
32
|
+
{ name: 'foo' },
|
|
33
|
+
{ name: 'bar' }
|
|
34
|
+
],
|
|
35
|
+
functions: [
|
|
36
|
+
{name: 'smh'},
|
|
37
|
+
{name: 'smash_my_head', args: ['object']},
|
|
38
|
+
],
|
|
39
|
+
})
|
|
40
|
+
],
|
|
41
|
+
parent: document.getElementById('editor'),
|
|
16
42
|
});
|
|
17
|
-
|
|
43
|
+
</script>
|
|
18
44
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var lr = require('@lezer/lr');
|
|
6
6
|
var language = require('@codemirror/language');
|
|
7
7
|
var highlight = require('@lezer/highlight');
|
|
8
|
+
var lint = require('@codemirror/lint');
|
|
8
9
|
|
|
9
10
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
10
11
|
const parser = lr.LRParser.deserialize({
|
|
@@ -20,13 +21,33 @@ const parser = lr.LRParser.deserialize({
|
|
|
20
21
|
],
|
|
21
22
|
skippedNodes: [0],
|
|
22
23
|
repeatNodeCount: 2,
|
|
23
|
-
tokenData: "
|
|
24
|
+
tokenData: "By~R!QXY$XYZ$X]^$Xpq$Xqr$jrs%Puv$zvw&{wx'Txy(xyz(}z{)S{|$z|})[}!O$z!O!P)a!P!Q$z!Q![*r![!],R!^!_$r!_!`,Y!`!a$r!a!b,`!c!},u!}#O-Y#P#Q-_#Q#R$z#R#S,u#T#U-d#U#V,u#V#W.}#W#X,u#X#Y2q#Y#Z5e#Z#],u#]#^8P#^#a,u#a#b8j#b#c;Y#c#d>s#d#g,u#g#h?^#h#iAc#i#o,u#o#pBg#p#qBl#q#rBt#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{$z~)aOk~~)fQXP!O!P$z!Q![)l~)qSQ~!Q![)l!g!h)}#R#S*l#X#Y)}~*QR{|*Z}!O*Z!Q![*a~*^P!Q![*a~*fQQ~!Q![*a#R#S*Z~*oP!Q![)l~*wTQ~!O!P+W!Q![*r!g!h)}#R#S+{#X#Y)}~+ZSO!O+g!P;'S+g;'S;=`+u<%lO+g~+lRQ~!Q![)l!g!h)}#X#Y)}~+xP;=`<%l+g~,OP!Q![*rR,YOjQXP~,]P!_!`$r~,eQXP!O!P,k!a!b,p~,pOY~~,uOZ~R,|S]QRP!Q![,u!c!},u#R#S,u#T#o,u~-_Om~~-dOl~R-kU]QRP!Q![,u!c!},u#R#S,u#T#b,u#b#c-}#c#o,uR.UU]QRP!Q![,u!c!},u#R#S,u#T#W,u#W#X.h#X#o,uR.qS]QWPRP!Q![,u!c!},u#R#S,u#T#o,uR/UU]QRP!Q![,u!c!},u#R#S,u#T#c,u#c#d/h#d#o,uR/oU]QRP!Q![,u!c!},u#R#S,u#T#b,u#b#c0R#c#o,uR0YU]QRP!Q![,u!c!},u#R#S,u#T#h,u#h#i0l#i#o,uR0sT]QRP!Q![,u!c!},u#R#S,u#T#U1S#U#o,uR1ZU]QRP!Q![,u!c!},u#R#S,u#T#],u#]#^1m#^#o,uR1tU]QRP!Q![,u!c!},u#R#S,u#T#b,u#b#c2W#c#o,uR2_U]QRP!Q![,u!c!},u#R#S,u#T#g,u#g#h.h#h#o,uR2xU]QRP!Q![,u!c!},u#R#S,u#T#b,u#b#c3[#c#o,uR3cU]QRP!Q![,u!c!},u#R#S,u#T#W,u#W#X3u#X#o,uR3|U]QRP!Q![,u!c!},u#R#S,u#T#g,u#g#h4`#h#o,uR4gT]QRPpq4v!Q![,u!c!},u#R#S,u#T#o,uP4yP#k#l4|P5PP#]#^5SP5VP#h#i5YP5]P#[#]5`P5eOWPR5lT]QRP!Q![,u!c!},u#R#S,u#T#U5{#U#o,uR6SU]QRP!Q![,u!c!},u#R#S,u#T#`,u#`#a6f#a#o,uR6mU]QRP!Q![,u!c!},u#R#S,u#T#g,u#g#h7P#h#o,uR7WU]QRP!Q![,u!c!},u#R#S,u#T#X,u#X#Y7j#Y#o,uR7sS]QTPRP!Q![,u!c!},u#R#S,u#T#o,uR8WU]QRP!Q![,u!c!},u#R#S,u#T#b,u#b#c.h#c#o,uR8qT]QRP!Q![,u!c!},u#R#S,u#T#U9Q#U#o,uR9XU]QRP!Q![,u!c!},u#R#S,u#T#h,u#h#i9k#i#o,uR9rU]QRP!Q![,u!c!},u#R#S,u#T#V,u#V#W:U#W#o,uR:]U]QRP!Q![,u!c!},u#R#S,u#T#[,u#[#]:o#]#o,uR:vU]QRP!Q![,u!c!},u#R#S,u#T#X,u#X#Y2W#Y#o,uR;aW]QRP!Q![,u!c!},u#R#S,u#T#c,u#c#d;y#d#i,u#i#j=Y#j#o,uR<QU]QRP!Q![,u!c!},u#R#S,u#T#h,u#h#i<d#i#o,uR<mT]QWPRPpq<|!Q![,u!c!},u#R#S,u#T#o,uP=PP#]#^=SP=VP#b#c5`R=aU]QRP!Q![,u!c!},u#R#S,u#T#`,u#`#a=s#a#o,uR=zU]QRP!Q![,u!c!},u#R#S,u#T#`,u#`#a>^#a#o,uR>gS]QUPRP!Q![,u!c!},u#R#S,u#T#o,uR>zU]QRP!Q![,u!c!},u#R#S,u#T#f,u#f#g.h#g#o,uR?eU]QRP!Q![,u!c!},u#R#S,u#T#h,u#h#i?w#i#o,uR@OT]QRP!Q![,u!c!},u#R#S,u#T#U@_#U#o,uR@fU]QRP!Q![,u!c!},u#R#S,u#T#f,u#f#g@x#g#o,uRAPU]QRP!Q![,u!c!},u#R#S,u#T#h,u#h#i3u#i#o,uRAjU]QRP!Q![,u!c!},u#R#S,u#T#f,u#f#gA|#g#o,uRBTU]QRP!Q![,u!c!},u#R#S,u#T#i,u#i#j7P#j#o,u~BlOi~~BqPV~#p#q$z~ByOh~",
|
|
24
25
|
tokenizers: [0, 1],
|
|
25
26
|
topRules: {"Program":[0,1]},
|
|
26
27
|
tokenPrec: 118
|
|
27
28
|
});
|
|
28
29
|
|
|
29
30
|
const identifier = /^[a-zA-Z_]+[a-zA-Z_0-9]*$/;
|
|
31
|
+
const expressionLanguageLinter = (config) => lint.linter(view => {
|
|
32
|
+
let diagnostics = [];
|
|
33
|
+
language.syntaxTree(view.state).cursor().iterate(node => {
|
|
34
|
+
var _a, _b;
|
|
35
|
+
if (node.name == "Identifier") {
|
|
36
|
+
const identifier = view.state.sliceDoc(node.from, node.to);
|
|
37
|
+
const isFunction = (_a = config.functions) === null || _a === void 0 ? void 0 : _a.find(fn => fn.name === identifier);
|
|
38
|
+
const isVariable = (_b = config.identifiers) === null || _b === void 0 ? void 0 : _b.filter(variable => variable.name === identifier);
|
|
39
|
+
if (!isFunction && !isVariable) {
|
|
40
|
+
diagnostics.push({
|
|
41
|
+
from: node.from,
|
|
42
|
+
to: node.to,
|
|
43
|
+
severity: 'warning',
|
|
44
|
+
message: `Identifier "${identifier}" not found`,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
return diagnostics;
|
|
50
|
+
});
|
|
30
51
|
const ELLanguage = language.LRLanguage.define({
|
|
31
52
|
parser: parser.configure({
|
|
32
53
|
props: [
|
|
@@ -66,16 +87,16 @@ function completeOperatorKeyword(state, config, tree, from, to) {
|
|
|
66
87
|
};
|
|
67
88
|
}
|
|
68
89
|
function completeIdentifier(state, config, tree, from, to) {
|
|
69
|
-
var _a, _b, _c, _d, _e;
|
|
90
|
+
var _a, _b, _c, _d, _e, _f;
|
|
70
91
|
const text = state.sliceDoc(from, to);
|
|
71
|
-
const identifiers = (_b = (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.filter(
|
|
72
|
-
const functions =
|
|
92
|
+
const identifiers = (_b = (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.filter(({ name }) => name.startsWith(text))) !== null && _b !== void 0 ? _b : [];
|
|
93
|
+
const functions = (_d = (_c = config.functions) === null || _c === void 0 ? void 0 : _c.filter(({ name }) => name.startsWith(text))) !== null && _d !== void 0 ? _d : [];
|
|
73
94
|
return {
|
|
74
95
|
from,
|
|
75
96
|
to,
|
|
76
97
|
options: [
|
|
77
|
-
...((
|
|
78
|
-
...((
|
|
98
|
+
...((_e = identifiers.map(({ name, info, detail }) => ({ label: name, info, detail, type: 'variable' }))) !== null && _e !== void 0 ? _e : []),
|
|
99
|
+
...((_f = functions.map(({ name, args = [], info }) => ({ label: name, detail: `(${args.join(',')})`, apply: `${name}(${args.length == 0 ? ')' : ''}`, info, type: "function" }))) !== null && _f !== void 0 ? _f : []),
|
|
79
100
|
],
|
|
80
101
|
validFor: identifier,
|
|
81
102
|
};
|
|
@@ -83,14 +104,10 @@ function completeIdentifier(state, config, tree, from, to) {
|
|
|
83
104
|
function expressionLanguageCompletionFor(config, context) {
|
|
84
105
|
let { state, pos } = context;
|
|
85
106
|
let tree = language.syntaxTree(state).resolveInner(pos, -1);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
// around = tree = before;
|
|
91
|
-
// scan = last.from;
|
|
92
|
-
// }
|
|
93
|
-
if (tree.prevSibling && !['Operator', 'OperatorKeyword', 'Punctuation', 'NullSafe', 'NullCoalescing'].includes(tree.prevSibling.name)) {
|
|
107
|
+
if (tree.name == 'String') {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
if (tree.prevSibling && !['Operator', 'OperatorKeyword', 'Punctuation', 'NullSafe', 'NullCoalescing', 'OpeningBracket'].includes(tree.prevSibling.name)) {
|
|
94
111
|
return completeOperatorKeyword(state, config, tree, tree.from, pos);
|
|
95
112
|
}
|
|
96
113
|
if (tree.name == "Identifier") {
|
|
@@ -104,7 +121,11 @@ function expressionLanguageCompletionSourceWith(config) {
|
|
|
104
121
|
return (context) => expressionLanguageCompletionFor(config, context);
|
|
105
122
|
}
|
|
106
123
|
function expressionlanguage(config = {}, extensions = []) {
|
|
107
|
-
return new language.LanguageSupport(ELLanguage, [
|
|
124
|
+
return new language.LanguageSupport(ELLanguage, [
|
|
125
|
+
ELLanguage.data.of({ autocomplete: expressionLanguageCompletionSourceWith(config) }),
|
|
126
|
+
expressionLanguageLinter(config),
|
|
127
|
+
...extensions,
|
|
128
|
+
]);
|
|
108
129
|
}
|
|
109
130
|
|
|
110
131
|
exports.ELLanguage = ELLanguage;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { LRLanguage, LanguageSupport } from "@codemirror/language";
|
|
2
2
|
interface ExpressionLanguageConfig {
|
|
3
|
-
identifiers?: readonly
|
|
4
|
-
|
|
3
|
+
identifiers?: readonly {
|
|
4
|
+
name: string;
|
|
5
|
+
detail?: string;
|
|
6
|
+
info?: string;
|
|
7
|
+
}[];
|
|
8
|
+
functions?: readonly {
|
|
9
|
+
name: string;
|
|
10
|
+
args: string[];
|
|
11
|
+
info?: string;
|
|
12
|
+
}[];
|
|
5
13
|
operatorKeywords?: readonly string[];
|
|
6
14
|
}
|
|
7
15
|
declare const ELLanguage: LRLanguage;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { LRLanguage, LanguageSupport } from "@codemirror/language";
|
|
2
2
|
interface ExpressionLanguageConfig {
|
|
3
|
-
identifiers?: readonly
|
|
4
|
-
|
|
3
|
+
identifiers?: readonly {
|
|
4
|
+
name: string;
|
|
5
|
+
detail?: string;
|
|
6
|
+
info?: string;
|
|
7
|
+
}[];
|
|
8
|
+
functions?: readonly {
|
|
9
|
+
name: string;
|
|
10
|
+
args: string[];
|
|
11
|
+
info?: string;
|
|
12
|
+
}[];
|
|
5
13
|
operatorKeywords?: readonly string[];
|
|
6
14
|
}
|
|
7
15
|
declare const ELLanguage: LRLanguage;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LRParser } from '@lezer/lr';
|
|
2
2
|
import { LRLanguage, indentNodeProp, delimitedIndent, foldNodeProp, foldInside, LanguageSupport, syntaxTree } from '@codemirror/language';
|
|
3
3
|
import { styleTags, tags } from '@lezer/highlight';
|
|
4
|
+
import { linter } from '@codemirror/lint';
|
|
4
5
|
|
|
5
6
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
6
7
|
const parser = LRParser.deserialize({
|
|
@@ -16,13 +17,33 @@ const parser = LRParser.deserialize({
|
|
|
16
17
|
],
|
|
17
18
|
skippedNodes: [0],
|
|
18
19
|
repeatNodeCount: 2,
|
|
19
|
-
tokenData: "
|
|
20
|
+
tokenData: "By~R!QXY$XYZ$X]^$Xpq$Xqr$jrs%Puv$zvw&{wx'Txy(xyz(}z{)S{|$z|})[}!O$z!O!P)a!P!Q$z!Q![*r![!],R!^!_$r!_!`,Y!`!a$r!a!b,`!c!},u!}#O-Y#P#Q-_#Q#R$z#R#S,u#T#U-d#U#V,u#V#W.}#W#X,u#X#Y2q#Y#Z5e#Z#],u#]#^8P#^#a,u#a#b8j#b#c;Y#c#d>s#d#g,u#g#h?^#h#iAc#i#o,u#o#pBg#p#qBl#q#rBt#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{$z~)aOk~~)fQXP!O!P$z!Q![)l~)qSQ~!Q![)l!g!h)}#R#S*l#X#Y)}~*QR{|*Z}!O*Z!Q![*a~*^P!Q![*a~*fQQ~!Q![*a#R#S*Z~*oP!Q![)l~*wTQ~!O!P+W!Q![*r!g!h)}#R#S+{#X#Y)}~+ZSO!O+g!P;'S+g;'S;=`+u<%lO+g~+lRQ~!Q![)l!g!h)}#X#Y)}~+xP;=`<%l+g~,OP!Q![*rR,YOjQXP~,]P!_!`$r~,eQXP!O!P,k!a!b,p~,pOY~~,uOZ~R,|S]QRP!Q![,u!c!},u#R#S,u#T#o,u~-_Om~~-dOl~R-kU]QRP!Q![,u!c!},u#R#S,u#T#b,u#b#c-}#c#o,uR.UU]QRP!Q![,u!c!},u#R#S,u#T#W,u#W#X.h#X#o,uR.qS]QWPRP!Q![,u!c!},u#R#S,u#T#o,uR/UU]QRP!Q![,u!c!},u#R#S,u#T#c,u#c#d/h#d#o,uR/oU]QRP!Q![,u!c!},u#R#S,u#T#b,u#b#c0R#c#o,uR0YU]QRP!Q![,u!c!},u#R#S,u#T#h,u#h#i0l#i#o,uR0sT]QRP!Q![,u!c!},u#R#S,u#T#U1S#U#o,uR1ZU]QRP!Q![,u!c!},u#R#S,u#T#],u#]#^1m#^#o,uR1tU]QRP!Q![,u!c!},u#R#S,u#T#b,u#b#c2W#c#o,uR2_U]QRP!Q![,u!c!},u#R#S,u#T#g,u#g#h.h#h#o,uR2xU]QRP!Q![,u!c!},u#R#S,u#T#b,u#b#c3[#c#o,uR3cU]QRP!Q![,u!c!},u#R#S,u#T#W,u#W#X3u#X#o,uR3|U]QRP!Q![,u!c!},u#R#S,u#T#g,u#g#h4`#h#o,uR4gT]QRPpq4v!Q![,u!c!},u#R#S,u#T#o,uP4yP#k#l4|P5PP#]#^5SP5VP#h#i5YP5]P#[#]5`P5eOWPR5lT]QRP!Q![,u!c!},u#R#S,u#T#U5{#U#o,uR6SU]QRP!Q![,u!c!},u#R#S,u#T#`,u#`#a6f#a#o,uR6mU]QRP!Q![,u!c!},u#R#S,u#T#g,u#g#h7P#h#o,uR7WU]QRP!Q![,u!c!},u#R#S,u#T#X,u#X#Y7j#Y#o,uR7sS]QTPRP!Q![,u!c!},u#R#S,u#T#o,uR8WU]QRP!Q![,u!c!},u#R#S,u#T#b,u#b#c.h#c#o,uR8qT]QRP!Q![,u!c!},u#R#S,u#T#U9Q#U#o,uR9XU]QRP!Q![,u!c!},u#R#S,u#T#h,u#h#i9k#i#o,uR9rU]QRP!Q![,u!c!},u#R#S,u#T#V,u#V#W:U#W#o,uR:]U]QRP!Q![,u!c!},u#R#S,u#T#[,u#[#]:o#]#o,uR:vU]QRP!Q![,u!c!},u#R#S,u#T#X,u#X#Y2W#Y#o,uR;aW]QRP!Q![,u!c!},u#R#S,u#T#c,u#c#d;y#d#i,u#i#j=Y#j#o,uR<QU]QRP!Q![,u!c!},u#R#S,u#T#h,u#h#i<d#i#o,uR<mT]QWPRPpq<|!Q![,u!c!},u#R#S,u#T#o,uP=PP#]#^=SP=VP#b#c5`R=aU]QRP!Q![,u!c!},u#R#S,u#T#`,u#`#a=s#a#o,uR=zU]QRP!Q![,u!c!},u#R#S,u#T#`,u#`#a>^#a#o,uR>gS]QUPRP!Q![,u!c!},u#R#S,u#T#o,uR>zU]QRP!Q![,u!c!},u#R#S,u#T#f,u#f#g.h#g#o,uR?eU]QRP!Q![,u!c!},u#R#S,u#T#h,u#h#i?w#i#o,uR@OT]QRP!Q![,u!c!},u#R#S,u#T#U@_#U#o,uR@fU]QRP!Q![,u!c!},u#R#S,u#T#f,u#f#g@x#g#o,uRAPU]QRP!Q![,u!c!},u#R#S,u#T#h,u#h#i3u#i#o,uRAjU]QRP!Q![,u!c!},u#R#S,u#T#f,u#f#gA|#g#o,uRBTU]QRP!Q![,u!c!},u#R#S,u#T#i,u#i#j7P#j#o,u~BlOi~~BqPV~#p#q$z~ByOh~",
|
|
20
21
|
tokenizers: [0, 1],
|
|
21
22
|
topRules: {"Program":[0,1]},
|
|
22
23
|
tokenPrec: 118
|
|
23
24
|
});
|
|
24
25
|
|
|
25
26
|
const identifier = /^[a-zA-Z_]+[a-zA-Z_0-9]*$/;
|
|
27
|
+
const expressionLanguageLinter = (config) => linter(view => {
|
|
28
|
+
let diagnostics = [];
|
|
29
|
+
syntaxTree(view.state).cursor().iterate(node => {
|
|
30
|
+
var _a, _b;
|
|
31
|
+
if (node.name == "Identifier") {
|
|
32
|
+
const identifier = view.state.sliceDoc(node.from, node.to);
|
|
33
|
+
const isFunction = (_a = config.functions) === null || _a === void 0 ? void 0 : _a.find(fn => fn.name === identifier);
|
|
34
|
+
const isVariable = (_b = config.identifiers) === null || _b === void 0 ? void 0 : _b.filter(variable => variable.name === identifier);
|
|
35
|
+
if (!isFunction && !isVariable) {
|
|
36
|
+
diagnostics.push({
|
|
37
|
+
from: node.from,
|
|
38
|
+
to: node.to,
|
|
39
|
+
severity: 'warning',
|
|
40
|
+
message: `Identifier "${identifier}" not found`,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return diagnostics;
|
|
46
|
+
});
|
|
26
47
|
const ELLanguage = LRLanguage.define({
|
|
27
48
|
parser: parser.configure({
|
|
28
49
|
props: [
|
|
@@ -62,16 +83,16 @@ function completeOperatorKeyword(state, config, tree, from, to) {
|
|
|
62
83
|
};
|
|
63
84
|
}
|
|
64
85
|
function completeIdentifier(state, config, tree, from, to) {
|
|
65
|
-
var _a, _b, _c, _d, _e;
|
|
86
|
+
var _a, _b, _c, _d, _e, _f;
|
|
66
87
|
const text = state.sliceDoc(from, to);
|
|
67
|
-
const identifiers = (_b = (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.filter(
|
|
68
|
-
const functions =
|
|
88
|
+
const identifiers = (_b = (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.filter(({ name }) => name.startsWith(text))) !== null && _b !== void 0 ? _b : [];
|
|
89
|
+
const functions = (_d = (_c = config.functions) === null || _c === void 0 ? void 0 : _c.filter(({ name }) => name.startsWith(text))) !== null && _d !== void 0 ? _d : [];
|
|
69
90
|
return {
|
|
70
91
|
from,
|
|
71
92
|
to,
|
|
72
93
|
options: [
|
|
73
|
-
...((
|
|
74
|
-
...((
|
|
94
|
+
...((_e = identifiers.map(({ name, info, detail }) => ({ label: name, info, detail, type: 'variable' }))) !== null && _e !== void 0 ? _e : []),
|
|
95
|
+
...((_f = functions.map(({ name, args = [], info }) => ({ label: name, detail: `(${args.join(',')})`, apply: `${name}(${args.length == 0 ? ')' : ''}`, info, type: "function" }))) !== null && _f !== void 0 ? _f : []),
|
|
75
96
|
],
|
|
76
97
|
validFor: identifier,
|
|
77
98
|
};
|
|
@@ -79,14 +100,10 @@ function completeIdentifier(state, config, tree, from, to) {
|
|
|
79
100
|
function expressionLanguageCompletionFor(config, context) {
|
|
80
101
|
let { state, pos } = context;
|
|
81
102
|
let tree = syntaxTree(state).resolveInner(pos, -1);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// around = tree = before;
|
|
87
|
-
// scan = last.from;
|
|
88
|
-
// }
|
|
89
|
-
if (tree.prevSibling && !['Operator', 'OperatorKeyword', 'Punctuation', 'NullSafe', 'NullCoalescing'].includes(tree.prevSibling.name)) {
|
|
103
|
+
if (tree.name == 'String') {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
if (tree.prevSibling && !['Operator', 'OperatorKeyword', 'Punctuation', 'NullSafe', 'NullCoalescing', 'OpeningBracket'].includes(tree.prevSibling.name)) {
|
|
90
107
|
return completeOperatorKeyword(state, config, tree, tree.from, pos);
|
|
91
108
|
}
|
|
92
109
|
if (tree.name == "Identifier") {
|
|
@@ -100,7 +117,11 @@ function expressionLanguageCompletionSourceWith(config) {
|
|
|
100
117
|
return (context) => expressionLanguageCompletionFor(config, context);
|
|
101
118
|
}
|
|
102
119
|
function expressionlanguage(config = {}, extensions = []) {
|
|
103
|
-
return new LanguageSupport(ELLanguage, [
|
|
120
|
+
return new LanguageSupport(ELLanguage, [
|
|
121
|
+
ELLanguage.data.of({ autocomplete: expressionLanguageCompletionSourceWith(config) }),
|
|
122
|
+
expressionLanguageLinter(config),
|
|
123
|
+
...extensions,
|
|
124
|
+
]);
|
|
104
125
|
}
|
|
105
126
|
|
|
106
127
|
export { ELLanguage, expressionlanguage };
|
package/package.json
CHANGED
|
@@ -17,10 +17,12 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@codemirror/autocomplete": "^6.9.0",
|
|
19
19
|
"@codemirror/language": "^6.0.0",
|
|
20
|
+
"@codemirror/lint": "^6.4.2",
|
|
20
21
|
"@lezer/highlight": "^1.0.0",
|
|
21
22
|
"@lezer/lr": "^1.0.0"
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
25
|
+
"@codemirror/state": "^6.2.1",
|
|
24
26
|
"@lezer/generator": "^1.0.0",
|
|
25
27
|
"@types/mocha": "^10.0.1",
|
|
26
28
|
"ist": "^1.1.7",
|
|
@@ -39,5 +41,5 @@
|
|
|
39
41
|
"access": "public",
|
|
40
42
|
"registry": "https://registry.npmjs.org/"
|
|
41
43
|
},
|
|
42
|
-
"version": "0.
|
|
44
|
+
"version": "0.2.2"
|
|
43
45
|
}
|