@valtzu/codemirror-lang-el 0.4.2 → 0.5.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/dist/index.cjs +258 -110
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +259 -112
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -4,99 +4,217 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var lr = require('@lezer/lr');
|
|
6
6
|
var language = require('@codemirror/language');
|
|
7
|
+
var autocomplete = require('@codemirror/autocomplete');
|
|
8
|
+
var view = require('@codemirror/view');
|
|
7
9
|
var highlight = require('@lezer/highlight');
|
|
10
|
+
var state = require('@codemirror/state');
|
|
8
11
|
var lint = require('@codemirror/lint');
|
|
9
|
-
var view = require('@codemirror/view');
|
|
10
12
|
|
|
11
13
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
14
|
+
const spec_word = {__proto__:null,true:80, false:82, null:84, starts:94, with:96, ends:98, contains:100, matches:102, not:104, in:106, and:108, or:110};
|
|
15
|
+
const spec_Operator = {__proto__:null,"!":113, "+":115, "-":117};
|
|
12
16
|
const parser = lr.LRParser.deserialize({
|
|
13
17
|
version: 14,
|
|
14
|
-
states: "'
|
|
15
|
-
stateData: "
|
|
16
|
-
goto: "#
|
|
17
|
-
nodeNames: "⚠ Expression ObjectAccess NullSafeMemberOf
|
|
18
|
-
maxTerm:
|
|
18
|
+
states: "(pOVQPOOQ!QQPOOO!{QPO'#CdO$]QPO'#CmO$dQPO'#CnOVQPO'#CtOVQPO'#CvOOQO'#C|'#C|O$kQPO'#CcO$pQPO'#CcOOQO'#Ck'#CkOOQO'#Cl'#ClOOQO'#Cu'#CuO$uQPO,58xOVQPO,58|OVQPO,59[OVQPO,59]O$zQPO'#CrOOQO'#Cr'#CrO%PQPO'#CrO%}QPO,59XOOQO,59X,59XO&UQPO'#DSO&cQPO,59YO&hQPO,59`O'OQPO,59bO'VQPO'#CeOOQO,58},58}O'VQPO'#ChO'^QPO'#CaOOQO1G.d1G.dOOQO1G.l1G.lO(nQPO1G.hO(uQPO1G.vO(|QPO1G.wOOQO,59^,59^OVQPO1G.sOVQPO'#CwO)dQPO,59nOOQO1G.t1G.tOOQO1G.|1G.|O)oQPO,59PO)tQPO,59SOOQO7+$S7+$SOVQPO7+$bO)yQPO7+$_O*TQPO,59cOOQO-E6u-E6uOOQO1G.k1G.kOOQO1G.n1G.nO*bQPO<<G|OVQPO'#CxO*xQPO<<GyOOQO<<Gy<<GyO+QQPO,59dOOQO-E6v-E6vOOQOAN=eAN=eOVQPO1G/OO+XQPO7+$j",
|
|
19
|
+
stateData: "+k~OoOS~O]VO^VOqQOsSOuUOxYOyYOzZO|RO!U[O!Y[O!Z[O![[O~OR]OS]Og`Os^O!O_O!PaO!RaO!SbO!TbO!UcO!VbO!WbO!XbO~ORcXScXgcXmcXscXuWX!OcX!PcX!RcX!ScX!TcX!UcX!VcX!WcX!XcX}cXrcXwcXtcX{cX~O{eO~PVOrvP~PVOujO~OulO~OqmO~O!QsO~O!VsO]fX^fXqfXsfXufXxfXyfXzfX|fX!UfX!YfX!ZfX![fX~O}tO~P!QOwuOrvXtvX~P!QOrwO~Omha}harhawhatha{ha~P!QOtxO~P!QOtvP~PVORTXSTXgTXmTXsTXuZX!OTX!PTX!RTX!STX!TTX!UTX!VTX!WTX!XTX}TXrTXwTXtTX{TX~Or{O~P!QO}|O~P!QOmei}eireiweitei{ei~P!QOwuOrvatva~Ot!QO~Ot!RO~Ow!TO{!VO~P!QOrkawkatka~P!QOmdy}dyrdywdytdy{dy~P!QOw!TO{!YO~O}!ZO~P!QOwlq{lq~P!QO^gRS]qS~",
|
|
20
|
+
goto: "%]wPPxPP!Zxx!^!o!r#T#WPPxxxxxxx#ZPx#jx#{$RPPP$XPPPPP%SoVORSTU^_`jltu|!T!ZRn]oWORSTU^_`jltu|!T!ZRkWoXORSTU^_`jltu|!T!ZRo]RkXk`Pdfhipqr}!O!S!W![oTORSTU^_`jltu|!T!ZQvfR!PvQ!U}R!X!UQPOQdRUfSjlQhTQiUQp^Qq_Qr`Q}tQ!OuQ!S|Q!W!TR![!ZQgSQyjRzl",
|
|
21
|
+
nodeNames: "⚠ Expression ObjectAccess MemberOf NullSafeMemberOf Property ArrayAccess Call Function Arguments ObjectAccess Method Arguments Number String Boolean Null Object Array Variable TernaryExpression BinaryExpression OperatorKeyword Operator UnaryExpression UnaryOperator Application",
|
|
22
|
+
maxTerm: 58,
|
|
19
23
|
skippedNodes: [0],
|
|
20
24
|
repeatNodeCount: 2,
|
|
21
|
-
tokenData: "
|
|
22
|
-
tokenizers: [0
|
|
25
|
+
tokenData: ",l~RqXY#YYZ#Y]^#Ypq#Yqr#krs$Quv#{vw%zwx&Sxy'wyz'|z{(R{|#{|}(Z}!O#{!O!P(`!P!Q#{!Q![(h![!]*}!^!_#s!_!`+S!`!a#s!a!b+Y!c!}+m!}#O,O#P#Q,T#Q#R#{#R#S+m#T#o+m#o#p,Y#p#q,_#q#r,g#r#s#{~#_So~XY#YYZ#Y]^#Ypq#Y~#pPg~!_!`#s~#xPg~!_!`#{~$QOg~~$TXOr$Qrs$ps#O$Q#O#P$u#P;'S$Q;'S;=`%t<%l~$Q~O$Q~~$p~$uO^~~$xRO;'S$Q;'S;=`%R;=`O$Q~%UYOr$Qrs$ps#O$Q#O#P$u#P;'S$Q;'S;=`%t;=`<%l$Q<%l~$Q~O$Q~~$p~%wP;=`<%l$Q~&PPg~vw#{~&VXOw&Swx$px#O&S#O#P&r#P;'S&S;'S;=`'q<%l~&S~O&S~~$p~&uRO;'S&S;'S;=`'O;=`O&S~'RYOw&Swx$px#O&S#O#P&r#P;'S&S;'S;=`'q;=`<%l&S<%l~&S~O&S~~$p~'tP;=`<%l&S~'|Ou~~(ROt~~(WPg~z{#{~(`Ow~~(ePR~!O!P#{~(mT]~!O!P(|!Q![(h!g!h)|#R#S*w#X#Y)|~)PSO!O)]!P;'S)];'S;=`*q<%lO)]~)bR]~!Q![)k!g!h)|#X#Y)|~)pS]~!Q![)k!g!h)|#R#S*k#X#Y)|~*PR{|*Y}!O*Y!Q![*`~*]P!Q![*`~*eQ]~!Q![*`#R#S*Y~*nP!Q![)k~*tP;=`<%l)]~*zP!Q![(h~+SO}~~+VP!_!`#s~+_R!O~!O!P+h![!]#{!a!b#{~+mOS~~+rSq~!Q![+m!c!}+m#R#S+m#T#o+m~,TOs~~,YOr~~,_O|~~,dPg~#p#q#{~,lO{~",
|
|
26
|
+
tokenizers: [0],
|
|
23
27
|
topRules: {"Expression":[0,1]},
|
|
24
|
-
|
|
28
|
+
specialized: [{term: 33, get: (value) => spec_word[value] || -1},{term: 23, get: (value) => spec_Operator[value] || -1}],
|
|
29
|
+
tokenPrec: 479
|
|
25
30
|
});
|
|
26
31
|
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
const autocompleteFunction = (x) => {
|
|
33
|
+
var _a, _b;
|
|
34
|
+
return ({
|
|
35
|
+
label: `${x.name}(${((_a = x.args) === null || _a === void 0 ? void 0 : _a.join(',')) || ''})`,
|
|
36
|
+
apply: (view, completion, from, to) => {
|
|
37
|
+
var _a;
|
|
38
|
+
view.dispatch(Object.assign(Object.assign({}, autocomplete.insertCompletionText(view.state, `${x.name}()`, from, to)), { selection: { anchor: from + x.name.length + (((_a = x.args) === null || _a === void 0 ? void 0 : _a.length) > 0 ? 1 : 2) } }));
|
|
39
|
+
},
|
|
40
|
+
detail: (_b = x.returnType) === null || _b === void 0 ? void 0 : _b.join('|'),
|
|
41
|
+
info: x.info, type: "function"
|
|
42
|
+
});
|
|
43
|
+
};
|
|
30
44
|
const autocompleteIdentifier = (x) => { var _a; return ({ label: x.name, apply: x.name, info: x.info, detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')), type: 'variable' }); };
|
|
31
|
-
const
|
|
45
|
+
const resolveCallable = (identifier, config) => { var _a; return (_a = config === null || config === void 0 ? void 0 : config.functions) === null || _a === void 0 ? void 0 : _a.find(x => x.name === identifier); };
|
|
46
|
+
const resolveIdentifier = (nodeName, identifier, config) => {
|
|
47
|
+
var _a;
|
|
48
|
+
switch (nodeName) {
|
|
49
|
+
case 'Method':
|
|
50
|
+
case 'Function':
|
|
51
|
+
return resolveCallable(identifier, config);
|
|
52
|
+
case 'Property':
|
|
53
|
+
case 'Variable':
|
|
54
|
+
return (_a = config === null || config === void 0 ? void 0 : config.identifiers) === null || _a === void 0 ? void 0 : _a.find(x => x.name === identifier);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
const cursorTooltipBaseTheme = view.EditorView.baseTheme({
|
|
58
|
+
".cm-tooltip.cm-tooltip-cursor": {
|
|
59
|
+
boxShadow: 'rgba(0, 0, 0, .15) 0 1px 2px',
|
|
60
|
+
border: "1px solid rgba(127, 127, 127, .2)",
|
|
61
|
+
padding: "2px 7px",
|
|
62
|
+
borderRadius: "4px",
|
|
63
|
+
"& .cm-tooltip-arrow:before": {},
|
|
64
|
+
"& .cm-tooltip-arrow:after": {
|
|
65
|
+
borderTopColor: "transparent"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
function getNodeOrdinal(node) {
|
|
70
|
+
let ordinal = -1;
|
|
71
|
+
for (let c = node; c; c = c.prevSibling, ordinal++)
|
|
72
|
+
;
|
|
73
|
+
return ordinal;
|
|
74
|
+
}
|
|
75
|
+
function resolveArguments(node) {
|
|
76
|
+
let c = node;
|
|
77
|
+
while (c && c.name !== 'Arguments') {
|
|
78
|
+
c = c.parent;
|
|
79
|
+
}
|
|
80
|
+
return c;
|
|
81
|
+
}
|
|
82
|
+
function resolveFunctionDefinition(node, state, config) {
|
|
83
|
+
var _a;
|
|
84
|
+
if (!node) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
let identifier;
|
|
88
|
+
if (node.name === 'ObjectAccess' && node.lastChild) {
|
|
89
|
+
const leftArgument = (_a = node.firstChild) === null || _a === void 0 ? void 0 : _a.node;
|
|
90
|
+
const types = Array.from(resolveTypes(state, leftArgument, config));
|
|
91
|
+
identifier = state.sliceDoc(node.lastChild.from, node.lastChild.to);
|
|
92
|
+
return types.map(type => { var _a; return resolveCallable(identifier, (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]); }).find(x => x);
|
|
93
|
+
}
|
|
94
|
+
else if (node.name === 'Function') {
|
|
95
|
+
identifier = state.sliceDoc(node.from, node.node.firstChild ? node.node.firstChild.from - 1 : node.to);
|
|
96
|
+
return resolveCallable(identifier, config);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function getCursorTooltips(state, config) {
|
|
100
|
+
// @ts-ignore
|
|
101
|
+
return state.selection.ranges
|
|
102
|
+
.filter(range => range.empty)
|
|
103
|
+
.map(range => {
|
|
104
|
+
var _a;
|
|
105
|
+
const tree = language.syntaxTree(state);
|
|
106
|
+
const node = tree.resolveInner(range.from, 0);
|
|
107
|
+
const args = resolveArguments(node);
|
|
108
|
+
if (!args || !args.prevSibling) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
const fn = resolveFunctionDefinition(args.prevSibling, state, config);
|
|
112
|
+
if (!fn) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
const n = args.childAfter(range.from - 1);
|
|
116
|
+
const argName = (_a = fn.args) === null || _a === void 0 ? void 0 : _a[n ? getNodeOrdinal(n) : 0];
|
|
117
|
+
if (n && n.from !== range.from || !argName) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
pos: range.head,
|
|
122
|
+
above: true,
|
|
123
|
+
strictSide: false,
|
|
124
|
+
arrow: true,
|
|
125
|
+
create: () => {
|
|
126
|
+
let dom = document.createElement("div");
|
|
127
|
+
dom.className = "cm-tooltip-cursor";
|
|
128
|
+
dom.textContent = `${argName}`;
|
|
129
|
+
return { dom };
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}).filter(x => x);
|
|
133
|
+
}
|
|
134
|
+
const cursorTooltipField = (config) => state.StateField.define({
|
|
135
|
+
create: (state) => getCursorTooltips(state, config),
|
|
136
|
+
update(tooltips, tr) {
|
|
137
|
+
if (!tr.docChanged && !tr.selection) {
|
|
138
|
+
return tooltips;
|
|
139
|
+
}
|
|
140
|
+
return getCursorTooltips(tr.state, config);
|
|
141
|
+
},
|
|
142
|
+
provide: f => view.showTooltip.computeN([f], state => state.field(f))
|
|
143
|
+
});
|
|
144
|
+
const expressionLanguageLinterSource = (config) => (state) => {
|
|
32
145
|
let diagnostics = [];
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
146
|
+
language.syntaxTree(state).cursor().iterate(node => {
|
|
147
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
148
|
+
const { from, to, name } = node;
|
|
149
|
+
let identifier;
|
|
150
|
+
switch (name) {
|
|
151
|
+
case '⚠':
|
|
152
|
+
if (state.doc.length === 0 || from === 0) {
|
|
153
|
+
// Don't show error on empty doc (even though it is an error)
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
identifier = state.sliceDoc(from, to);
|
|
157
|
+
if (identifier.length === 0) {
|
|
158
|
+
diagnostics.push({ from, to: (_c = (_b = (_a = node.node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.to) !== null && _c !== void 0 ? _c : to, severity: 'error', message: `Expression expected` });
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
const type = /^[a-zA-Z_]+[a-zA-Z_0-9]*$/.test(identifier) ? 'identifier' : 'operator';
|
|
162
|
+
diagnostics.push({ from, to, severity: 'error', message: `Unexpected ${type} '${identifier}'` });
|
|
48
163
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
to: node.to,
|
|
55
|
-
severity: 'warning',
|
|
56
|
-
message: `Property '${identifier}' not found in ${Array.from(types).join('|')}`,
|
|
57
|
-
});
|
|
164
|
+
return;
|
|
165
|
+
case 'Arguments':
|
|
166
|
+
const args = (_d = resolveFunctionDefinition(node.node.prevSibling, state, config)) === null || _d === void 0 ? void 0 : _d.args;
|
|
167
|
+
if (!args) {
|
|
168
|
+
return;
|
|
58
169
|
}
|
|
59
|
-
|
|
60
|
-
|
|
170
|
+
let i = 0;
|
|
171
|
+
let n = node.node.firstChild;
|
|
172
|
+
while (n) {
|
|
173
|
+
if (++i > args.length) {
|
|
174
|
+
diagnostics.push({ from: n.from, to: n.to, severity: 'error', message: `Unexpected argument` });
|
|
175
|
+
}
|
|
176
|
+
n = n.nextSibling;
|
|
177
|
+
}
|
|
178
|
+
break;
|
|
179
|
+
case 'Property':
|
|
180
|
+
case 'Method':
|
|
181
|
+
const leftArgument = (_f = (_e = node.node.parent) === null || _e === void 0 ? void 0 : _e.firstChild) === null || _f === void 0 ? void 0 : _f.node;
|
|
182
|
+
const types = Array.from(resolveTypes(state, leftArgument, config));
|
|
183
|
+
identifier = state.sliceDoc(from, to);
|
|
184
|
+
if (!types.find(type => { var _a; return resolveIdentifier(name, identifier, (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]); })) {
|
|
185
|
+
diagnostics.push({ from, to, severity: 'error', message: `${node.name} "${identifier}" not found in ${types.join('|')}` });
|
|
186
|
+
}
|
|
187
|
+
break;
|
|
188
|
+
case 'Variable':
|
|
189
|
+
case 'Function':
|
|
190
|
+
identifier = state.sliceDoc(from, node.node.firstChild ? node.node.firstChild.from - 1 : to);
|
|
191
|
+
if (!resolveIdentifier(name, identifier, config)) {
|
|
192
|
+
diagnostics.push({ from, to, severity: 'error', message: `${node.node.name} "${identifier}" not found` });
|
|
193
|
+
}
|
|
194
|
+
break;
|
|
61
195
|
}
|
|
62
|
-
if (node.
|
|
63
|
-
|
|
64
|
-
diagnostics.push({
|
|
65
|
-
from: node.from,
|
|
66
|
-
to: node.to,
|
|
67
|
-
severity: 'error',
|
|
68
|
-
message: `Unexpected identifier after another identifier`,
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
const identifier = view.state.sliceDoc(node.from, node.to);
|
|
72
|
-
if (!isFunction(identifier, config) && !isVariable(identifier, config)) {
|
|
73
|
-
diagnostics.push({
|
|
74
|
-
from: node.from,
|
|
75
|
-
to: node.to,
|
|
76
|
-
severity: 'error',
|
|
77
|
-
message: `Identifier "${identifier}" not found`,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
196
|
+
if (identifier && ((_g = node.node.parent) === null || _g === void 0 ? void 0 : _g.type.isError)) {
|
|
197
|
+
diagnostics.push({ from, to, severity: 'error', message: `Unexpected identifier "${identifier}"` });
|
|
80
198
|
}
|
|
81
|
-
previousNode = node.node;
|
|
82
199
|
});
|
|
83
200
|
return diagnostics;
|
|
84
|
-
}
|
|
201
|
+
};
|
|
202
|
+
const expressionLanguageLinter = (config) => lint.linter(view => expressionLanguageLinterSource(config)(view.state));
|
|
85
203
|
const keywordTooltip = (config) => view.hoverTooltip((view, pos, side) => {
|
|
86
204
|
var _a, _b, _c, _d, _e, _f;
|
|
87
205
|
const tree = language.syntaxTree(view.state).resolveInner(pos, side);
|
|
88
|
-
if (
|
|
206
|
+
if (!['Function', 'Variable', 'Method', 'Property'].includes(tree.name)) {
|
|
89
207
|
return null;
|
|
90
208
|
}
|
|
91
209
|
const skipEmpty = (x) => x;
|
|
92
210
|
let info;
|
|
93
211
|
if (((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.firstChild) && ((_b = tree.parent) === null || _b === void 0 ? void 0 : _b.name) === 'ObjectAccess' && tree.prevSibling) {
|
|
94
212
|
const node = tree.parent.firstChild;
|
|
95
|
-
const types = resolveTypes(view.state, node, config
|
|
213
|
+
const types = Array.from(resolveTypes(view.state, node, config));
|
|
96
214
|
const name = view.state.sliceDoc(tree.from, tree.to);
|
|
97
215
|
info = [
|
|
98
|
-
...
|
|
99
|
-
...
|
|
216
|
+
...types.map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.identifiers) === null || _c === void 0 ? void 0 : _c.find(x => x.name === name)) === null || _d === void 0 ? void 0 : _d.info; }).filter(skipEmpty),
|
|
217
|
+
...types.map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.functions) === null || _c === void 0 ? void 0 : _c.find(x => x.name === name)) === null || _d === void 0 ? void 0 : _d.info; }).filter(skipEmpty),
|
|
100
218
|
].join('\n');
|
|
101
219
|
}
|
|
102
220
|
else {
|
|
@@ -114,8 +232,8 @@ const keywordTooltip = (config) => view.hoverTooltip((view, pos, side) => {
|
|
|
114
232
|
end: tree.to,
|
|
115
233
|
above: true,
|
|
116
234
|
create(view) {
|
|
117
|
-
|
|
118
|
-
dom.textContent = info;
|
|
235
|
+
const dom = document.createElement("div");
|
|
236
|
+
dom[config.htmlTooltip ? 'innerHTML' : 'textContent'] = info;
|
|
119
237
|
dom.className = 'cm-diagnostic';
|
|
120
238
|
return { dom };
|
|
121
239
|
},
|
|
@@ -125,13 +243,20 @@ const ELLanguage = language.LRLanguage.define({
|
|
|
125
243
|
parser: parser.configure({
|
|
126
244
|
props: [
|
|
127
245
|
language.indentNodeProp.add({
|
|
128
|
-
Application: language.delimitedIndent({ closing: ")", align: false })
|
|
246
|
+
Application: language.delimitedIndent({ closing: ")", align: false }),
|
|
247
|
+
Arguments: language.delimitedIndent({ closing: ")", align: false }),
|
|
248
|
+
Object: language.delimitedIndent({ closing: "}", align: false }),
|
|
129
249
|
}),
|
|
130
250
|
language.foldNodeProp.add({
|
|
131
|
-
Application:
|
|
251
|
+
Application: ({ from, to }) => ({ from: from + 1, to: to - 1 }),
|
|
252
|
+
Arguments: ({ from, to }) => ({ from: from + 1, to: to - 1 }),
|
|
253
|
+
Object: ({ from, to }) => ({ from: from + 1, to: to - 1 }),
|
|
132
254
|
}),
|
|
133
255
|
highlight.styleTags({
|
|
134
|
-
|
|
256
|
+
Property: highlight.tags.propertyName,
|
|
257
|
+
Variable: highlight.tags.variableName,
|
|
258
|
+
Function: highlight.tags.function(highlight.tags.variableName),
|
|
259
|
+
Method: highlight.tags.function(highlight.tags.propertyName),
|
|
135
260
|
Boolean: highlight.tags.bool,
|
|
136
261
|
String: highlight.tags.string,
|
|
137
262
|
Number: highlight.tags.number,
|
|
@@ -139,10 +264,12 @@ const ELLanguage = language.LRLanguage.define({
|
|
|
139
264
|
')': highlight.tags.paren,
|
|
140
265
|
'[': highlight.tags.squareBracket,
|
|
141
266
|
']': highlight.tags.squareBracket,
|
|
267
|
+
',': highlight.tags.punctuation,
|
|
268
|
+
MemberOf: highlight.tags.punctuation,
|
|
269
|
+
NullSafeMemberOf: highlight.tags.punctuation,
|
|
142
270
|
OperatorKeyword: highlight.tags.operatorKeyword,
|
|
271
|
+
UnaryOperator: highlight.tags.operator,
|
|
143
272
|
Operator: highlight.tags.operator,
|
|
144
|
-
MemberOf: highlight.tags.operator,
|
|
145
|
-
NullSafeMemberOf: highlight.tags.operator,
|
|
146
273
|
})
|
|
147
274
|
]
|
|
148
275
|
}),
|
|
@@ -150,46 +277,61 @@ const ELLanguage = language.LRLanguage.define({
|
|
|
150
277
|
});
|
|
151
278
|
function completeOperatorKeyword(state, config, tree, from, to, explicit) {
|
|
152
279
|
var _a, _b;
|
|
153
|
-
const text = state.sliceDoc(from, to);
|
|
154
280
|
return {
|
|
155
281
|
from,
|
|
156
282
|
to,
|
|
157
|
-
options: (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.
|
|
158
|
-
validFor: (text) => { var _a, _b; return (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.some(({ name }) => explicit || name.
|
|
283
|
+
options: (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.map(({ name, info, detail }) => ({ label: name, apply: `${name} `, info, detail, type: "keyword" }))) !== null && _b !== void 0 ? _b : [],
|
|
284
|
+
validFor: (text) => { var _a, _b; return (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.some(({ name }) => explicit || name.includes(text))) !== null && _b !== void 0 ? _b : false; },
|
|
159
285
|
};
|
|
160
286
|
}
|
|
161
|
-
function completeIdentifier(state, config, tree, from, to
|
|
162
|
-
var _a, _b
|
|
163
|
-
const
|
|
164
|
-
const
|
|
165
|
-
const functions = (_d = (_c = config.functions) === null || _c === void 0 ? void 0 : _c.filter(({ name }) => explicit || name.toLowerCase().startsWith(text))) !== null && _d !== void 0 ? _d : [];
|
|
287
|
+
function completeIdentifier(state, config, tree, from, to) {
|
|
288
|
+
var _a, _b;
|
|
289
|
+
const identifiers = (_a = config.identifiers) !== null && _a !== void 0 ? _a : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
|
|
290
|
+
const functions = (_b = config.functions) !== null && _b !== void 0 ? _b : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
|
|
166
291
|
return {
|
|
167
292
|
from,
|
|
168
293
|
to,
|
|
169
294
|
options: [...(identifiers.map(autocompleteIdentifier)), ...(functions.map(autocompleteFunction))],
|
|
170
|
-
|
|
171
|
-
filter: false,
|
|
295
|
+
validFor: /^[a-zA-Z_]+[a-zA-Z_0-9]*$/,
|
|
172
296
|
};
|
|
173
297
|
}
|
|
174
298
|
function resolveTypes(state, node, config, matchExact) {
|
|
175
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
299
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
176
300
|
let types = new Set();
|
|
177
|
-
if (node
|
|
178
|
-
|
|
301
|
+
if (!node) {
|
|
302
|
+
return types;
|
|
303
|
+
}
|
|
304
|
+
if (node.name === 'Call' && node.firstChild && node.lastChild) {
|
|
305
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
306
|
+
}
|
|
307
|
+
else if (node.name === 'Variable') {
|
|
308
|
+
const varName = state.sliceDoc(node.from, node.to) || '';
|
|
309
|
+
// @ts-ignore
|
|
310
|
+
(_b = (_a = resolveIdentifier(node.name, varName, config)) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.forEach((x) => types.add(x));
|
|
179
311
|
}
|
|
180
|
-
else if (node.name === '
|
|
312
|
+
else if (node.name === 'Function') {
|
|
181
313
|
const varName = state.sliceDoc(node.from, node.to) || '';
|
|
182
|
-
|
|
183
|
-
(
|
|
314
|
+
// @ts-ignore
|
|
315
|
+
(_d = (_c = resolveIdentifier(node.name, varName, config)) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
|
|
184
316
|
}
|
|
185
|
-
else if (node.name === 'ObjectAccess' && node.firstChild && ((
|
|
186
|
-
const baseTypes = resolveTypes(state, node.firstChild, config, matchExact);
|
|
317
|
+
else if (node.name === 'ObjectAccess' && node.firstChild && ((_e = node.lastChild) === null || _e === void 0 ? void 0 : _e.name) === 'Property') {
|
|
187
318
|
const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
(
|
|
192
|
-
}
|
|
319
|
+
(_f = resolveTypes(state, node.firstChild, config)) === null || _f === void 0 ? void 0 : _f.forEach(baseType => {
|
|
320
|
+
var _a, _b, _c, _d;
|
|
321
|
+
// @ts-ignore
|
|
322
|
+
(_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.name, varName, (_b = config.types) === null || _b === void 0 ? void 0 : _b[baseType])) === null || _c === void 0 ? void 0 : _c.type) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
else if (node.name === 'ObjectAccess' && node.firstChild && ((_g = node.lastChild) === null || _g === void 0 ? void 0 : _g.name) === 'Method') {
|
|
326
|
+
const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
|
|
327
|
+
(_h = resolveTypes(state, node.firstChild, config)) === null || _h === void 0 ? void 0 : _h.forEach(baseType => {
|
|
328
|
+
var _a, _b, _c, _d;
|
|
329
|
+
// @ts-ignore
|
|
330
|
+
(_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.name, varName, (_b = config.types) === null || _b === void 0 ? void 0 : _b[baseType])) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
else if (node.name === 'Application' && node.firstChild) {
|
|
334
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
193
335
|
}
|
|
194
336
|
if (types.size === 0) {
|
|
195
337
|
types.add('any');
|
|
@@ -201,42 +343,46 @@ function completeMember(state, config, tree, from, to, explicit) {
|
|
|
201
343
|
if (((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.name) != 'ObjectAccess' || !tree.parent.firstChild) {
|
|
202
344
|
return null;
|
|
203
345
|
}
|
|
204
|
-
|
|
346
|
+
state.sliceDoc(from, to);
|
|
347
|
+
const types = resolveTypes(state, tree.parent.firstChild.node, config);
|
|
205
348
|
if (!(types === null || types === void 0 ? void 0 : types.size)) {
|
|
206
349
|
return null;
|
|
207
350
|
}
|
|
208
|
-
const varName = state.sliceDoc(from, to);
|
|
209
351
|
let options = [];
|
|
210
352
|
for (const type of types) {
|
|
211
353
|
const typeDeclaration = (_b = config.types) === null || _b === void 0 ? void 0 : _b[type];
|
|
212
|
-
options.push(...(((_c = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.identifiers) === null || _c === void 0 ? void 0 : _c.
|
|
354
|
+
options.push(...(((_c = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.identifiers) === null || _c === void 0 ? void 0 : _c.map(autocompleteIdentifier)) || []), ...(((_d = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.functions) === null || _d === void 0 ? void 0 : _d.map(autocompleteFunction)) || []));
|
|
213
355
|
}
|
|
214
356
|
return {
|
|
215
357
|
from,
|
|
216
358
|
to,
|
|
217
359
|
options,
|
|
218
|
-
|
|
360
|
+
validFor: /^[a-zA-Z_]+[a-zA-Z_0-9]*$/,
|
|
219
361
|
};
|
|
220
362
|
}
|
|
221
363
|
function expressionLanguageCompletionFor(config, context) {
|
|
222
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
364
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
223
365
|
const { state, pos, explicit } = context;
|
|
224
|
-
const tree = language.syntaxTree(state)
|
|
225
|
-
const
|
|
226
|
-
const isIdentifier = (node) => (node === null || node === void 0 ? void 0 : node.name)
|
|
227
|
-
const
|
|
228
|
-
if (
|
|
366
|
+
const tree = language.syntaxTree(state);
|
|
367
|
+
const prevNode = tree.resolveInner(pos, state.sliceDoc(pos - 1, pos) === ')' ? 0 : -1);
|
|
368
|
+
const isIdentifier = (node) => { var _a; return ['Variable', 'Function'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
|
|
369
|
+
const isMember = (node) => { var _a; return ['Property', 'Method'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
|
|
370
|
+
if (prevNode.name == 'String') {
|
|
229
371
|
return null;
|
|
230
372
|
}
|
|
231
|
-
if (((
|
|
232
|
-
return completeMember(state, config,
|
|
373
|
+
if (((_a = prevNode.parent) === null || _a === void 0 ? void 0 : _a.name) == 'ObjectAccess' && ['ObjectAccess', 'ArrayAccess', 'Variable', 'Call'].includes(((_b = prevNode.parent.firstChild) === null || _b === void 0 ? void 0 : _b.name) || '')) {
|
|
374
|
+
return completeMember(state, config, prevNode, isIdentifier(prevNode) || isMember(prevNode) ? prevNode.from : pos, pos);
|
|
233
375
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
376
|
+
if (['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes(prevNode.name) && prevNode.lastChild && !((_c = prevNode.lastChild) === null || _c === void 0 ? void 0 : _c.type.isError)
|
|
377
|
+
|| ['Arguments', 'Array'].includes(prevNode.name) && prevNode.lastChild && !((_d = prevNode.lastChild) === null || _d === void 0 ? void 0 : _d.type.isError)
|
|
378
|
+
|| ['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes((_f = (_e = prevNode.parent) === null || _e === void 0 ? void 0 : _e.name) !== null && _f !== void 0 ? _f : '') && prevNode.type.isError
|
|
379
|
+
|| ['Variable', 'Function'].includes((_h = (_g = prevNode.parent) === null || _g === void 0 ? void 0 : _g.name) !== null && _h !== void 0 ? _h : '') && prevNode.type.isError) {
|
|
380
|
+
return completeOperatorKeyword(state, config, prevNode, !['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression', 'Arguments'].includes(prevNode.name) ? prevNode.from : pos, pos, explicit);
|
|
237
381
|
}
|
|
238
|
-
if (
|
|
239
|
-
|
|
382
|
+
if (['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes(prevNode.name) && ((_j = prevNode.lastChild) === null || _j === void 0 ? void 0 : _j.type.isError)
|
|
383
|
+
|| ['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression', 'Arguments'].includes((_l = (_k = prevNode.parent) === null || _k === void 0 ? void 0 : _k.name) !== null && _l !== void 0 ? _l : '') && !prevNode.type.isError
|
|
384
|
+
|| ['Arguments', 'Array'].includes((_m = prevNode.name) !== null && _m !== void 0 ? _m : '')) {
|
|
385
|
+
return completeIdentifier(state, config, prevNode, isIdentifier(prevNode) ? prevNode.from : pos, pos);
|
|
240
386
|
}
|
|
241
387
|
return null;
|
|
242
388
|
}
|
|
@@ -261,9 +407,11 @@ function expressionlanguage(config = {}, extensions = []) {
|
|
|
261
407
|
expressionLanguageLinter(config),
|
|
262
408
|
keywordTooltip(config),
|
|
263
409
|
...extensions,
|
|
410
|
+
[cursorTooltipField(config), cursorTooltipBaseTheme],
|
|
264
411
|
]);
|
|
265
412
|
}
|
|
266
413
|
|
|
267
414
|
exports.ELLanguage = ELLanguage;
|
|
415
|
+
exports.expressionLanguageLinterSource = expressionLanguageLinterSource;
|
|
268
416
|
exports.expressionlanguage = expressionlanguage;
|
|
269
417
|
exports.keywordTooltip = keywordTooltip;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { LRLanguage, LanguageSupport } from "@codemirror/language";
|
|
2
|
+
import { EditorState } from "@codemirror/state";
|
|
3
|
+
import { Diagnostic } from "@codemirror/lint";
|
|
2
4
|
interface ELIdentifier {
|
|
3
5
|
name: string;
|
|
4
6
|
detail?: string;
|
|
@@ -27,8 +29,10 @@ interface ExpressionLanguageConfig {
|
|
|
27
29
|
detail?: string;
|
|
28
30
|
info?: string;
|
|
29
31
|
}[];
|
|
32
|
+
htmlTooltip?: boolean;
|
|
30
33
|
}
|
|
34
|
+
declare const expressionLanguageLinterSource: (config: ExpressionLanguageConfig) => (state: EditorState) => Diagnostic[];
|
|
31
35
|
declare const keywordTooltip: (config: ExpressionLanguageConfig) => import("@codemirror/state").Extension;
|
|
32
36
|
declare const ELLanguage: LRLanguage;
|
|
33
37
|
declare function expressionlanguage(config?: ExpressionLanguageConfig, extensions?: Array<any>): LanguageSupport;
|
|
34
|
-
export { ELIdentifier, ELFunction, ExpressionLanguageConfig, keywordTooltip, ELLanguage, expressionlanguage };
|
|
38
|
+
export { ELIdentifier, ELFunction, ExpressionLanguageConfig, expressionLanguageLinterSource, keywordTooltip, ELLanguage, expressionlanguage };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { LRLanguage, LanguageSupport } from "@codemirror/language";
|
|
2
|
+
import { EditorState } from "@codemirror/state";
|
|
3
|
+
import { Diagnostic } from "@codemirror/lint";
|
|
2
4
|
interface ELIdentifier {
|
|
3
5
|
name: string;
|
|
4
6
|
detail?: string;
|
|
@@ -27,8 +29,10 @@ interface ExpressionLanguageConfig {
|
|
|
27
29
|
detail?: string;
|
|
28
30
|
info?: string;
|
|
29
31
|
}[];
|
|
32
|
+
htmlTooltip?: boolean;
|
|
30
33
|
}
|
|
34
|
+
declare const expressionLanguageLinterSource: (config: ExpressionLanguageConfig) => (state: EditorState) => Diagnostic[];
|
|
31
35
|
declare const keywordTooltip: (config: ExpressionLanguageConfig) => import("@codemirror/state").Extension;
|
|
32
36
|
declare const ELLanguage: LRLanguage;
|
|
33
37
|
declare function expressionlanguage(config?: ExpressionLanguageConfig, extensions?: Array<any>): LanguageSupport;
|
|
34
|
-
export { ELIdentifier, ELFunction, ExpressionLanguageConfig, keywordTooltip, ELLanguage, expressionlanguage };
|
|
38
|
+
export { ELIdentifier, ELFunction, ExpressionLanguageConfig, expressionLanguageLinterSource, keywordTooltip, ELLanguage, expressionlanguage };
|
package/dist/index.js
CHANGED
|
@@ -1,98 +1,216 @@
|
|
|
1
1
|
import { LRParser } from '@lezer/lr';
|
|
2
|
-
import { LRLanguage, indentNodeProp, delimitedIndent, foldNodeProp,
|
|
2
|
+
import { LRLanguage, indentNodeProp, delimitedIndent, foldNodeProp, syntaxTree, LanguageSupport } from '@codemirror/language';
|
|
3
|
+
import { insertCompletionText } from '@codemirror/autocomplete';
|
|
4
|
+
import { EditorView, hoverTooltip, showTooltip } from '@codemirror/view';
|
|
3
5
|
import { styleTags, tags } from '@lezer/highlight';
|
|
6
|
+
import { StateField } from '@codemirror/state';
|
|
4
7
|
import { linter } from '@codemirror/lint';
|
|
5
|
-
import { hoverTooltip } from '@codemirror/view';
|
|
6
8
|
|
|
7
9
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
10
|
+
const spec_word = {__proto__:null,true:80, false:82, null:84, starts:94, with:96, ends:98, contains:100, matches:102, not:104, in:106, and:108, or:110};
|
|
11
|
+
const spec_Operator = {__proto__:null,"!":113, "+":115, "-":117};
|
|
8
12
|
const parser = LRParser.deserialize({
|
|
9
13
|
version: 14,
|
|
10
|
-
states: "'
|
|
11
|
-
stateData: "
|
|
12
|
-
goto: "#
|
|
13
|
-
nodeNames: "⚠ Expression ObjectAccess NullSafeMemberOf
|
|
14
|
-
maxTerm:
|
|
14
|
+
states: "(pOVQPOOQ!QQPOOO!{QPO'#CdO$]QPO'#CmO$dQPO'#CnOVQPO'#CtOVQPO'#CvOOQO'#C|'#C|O$kQPO'#CcO$pQPO'#CcOOQO'#Ck'#CkOOQO'#Cl'#ClOOQO'#Cu'#CuO$uQPO,58xOVQPO,58|OVQPO,59[OVQPO,59]O$zQPO'#CrOOQO'#Cr'#CrO%PQPO'#CrO%}QPO,59XOOQO,59X,59XO&UQPO'#DSO&cQPO,59YO&hQPO,59`O'OQPO,59bO'VQPO'#CeOOQO,58},58}O'VQPO'#ChO'^QPO'#CaOOQO1G.d1G.dOOQO1G.l1G.lO(nQPO1G.hO(uQPO1G.vO(|QPO1G.wOOQO,59^,59^OVQPO1G.sOVQPO'#CwO)dQPO,59nOOQO1G.t1G.tOOQO1G.|1G.|O)oQPO,59PO)tQPO,59SOOQO7+$S7+$SOVQPO7+$bO)yQPO7+$_O*TQPO,59cOOQO-E6u-E6uOOQO1G.k1G.kOOQO1G.n1G.nO*bQPO<<G|OVQPO'#CxO*xQPO<<GyOOQO<<Gy<<GyO+QQPO,59dOOQO-E6v-E6vOOQOAN=eAN=eOVQPO1G/OO+XQPO7+$j",
|
|
15
|
+
stateData: "+k~OoOS~O]VO^VOqQOsSOuUOxYOyYOzZO|RO!U[O!Y[O!Z[O![[O~OR]OS]Og`Os^O!O_O!PaO!RaO!SbO!TbO!UcO!VbO!WbO!XbO~ORcXScXgcXmcXscXuWX!OcX!PcX!RcX!ScX!TcX!UcX!VcX!WcX!XcX}cXrcXwcXtcX{cX~O{eO~PVOrvP~PVOujO~OulO~OqmO~O!QsO~O!VsO]fX^fXqfXsfXufXxfXyfXzfX|fX!UfX!YfX!ZfX![fX~O}tO~P!QOwuOrvXtvX~P!QOrwO~Omha}harhawhatha{ha~P!QOtxO~P!QOtvP~PVORTXSTXgTXmTXsTXuZX!OTX!PTX!RTX!STX!TTX!UTX!VTX!WTX!XTX}TXrTXwTXtTX{TX~Or{O~P!QO}|O~P!QOmei}eireiweitei{ei~P!QOwuOrvatva~Ot!QO~Ot!RO~Ow!TO{!VO~P!QOrkawkatka~P!QOmdy}dyrdywdytdy{dy~P!QOw!TO{!YO~O}!ZO~P!QOwlq{lq~P!QO^gRS]qS~",
|
|
16
|
+
goto: "%]wPPxPP!Zxx!^!o!r#T#WPPxxxxxxx#ZPx#jx#{$RPPP$XPPPPP%SoVORSTU^_`jltu|!T!ZRn]oWORSTU^_`jltu|!T!ZRkWoXORSTU^_`jltu|!T!ZRo]RkXk`Pdfhipqr}!O!S!W![oTORSTU^_`jltu|!T!ZQvfR!PvQ!U}R!X!UQPOQdRUfSjlQhTQiUQp^Qq_Qr`Q}tQ!OuQ!S|Q!W!TR![!ZQgSQyjRzl",
|
|
17
|
+
nodeNames: "⚠ Expression ObjectAccess MemberOf NullSafeMemberOf Property ArrayAccess Call Function Arguments ObjectAccess Method Arguments Number String Boolean Null Object Array Variable TernaryExpression BinaryExpression OperatorKeyword Operator UnaryExpression UnaryOperator Application",
|
|
18
|
+
maxTerm: 58,
|
|
15
19
|
skippedNodes: [0],
|
|
16
20
|
repeatNodeCount: 2,
|
|
17
|
-
tokenData: "
|
|
18
|
-
tokenizers: [0
|
|
21
|
+
tokenData: ",l~RqXY#YYZ#Y]^#Ypq#Yqr#krs$Quv#{vw%zwx&Sxy'wyz'|z{(R{|#{|}(Z}!O#{!O!P(`!P!Q#{!Q![(h![!]*}!^!_#s!_!`+S!`!a#s!a!b+Y!c!}+m!}#O,O#P#Q,T#Q#R#{#R#S+m#T#o+m#o#p,Y#p#q,_#q#r,g#r#s#{~#_So~XY#YYZ#Y]^#Ypq#Y~#pPg~!_!`#s~#xPg~!_!`#{~$QOg~~$TXOr$Qrs$ps#O$Q#O#P$u#P;'S$Q;'S;=`%t<%l~$Q~O$Q~~$p~$uO^~~$xRO;'S$Q;'S;=`%R;=`O$Q~%UYOr$Qrs$ps#O$Q#O#P$u#P;'S$Q;'S;=`%t;=`<%l$Q<%l~$Q~O$Q~~$p~%wP;=`<%l$Q~&PPg~vw#{~&VXOw&Swx$px#O&S#O#P&r#P;'S&S;'S;=`'q<%l~&S~O&S~~$p~&uRO;'S&S;'S;=`'O;=`O&S~'RYOw&Swx$px#O&S#O#P&r#P;'S&S;'S;=`'q;=`<%l&S<%l~&S~O&S~~$p~'tP;=`<%l&S~'|Ou~~(ROt~~(WPg~z{#{~(`Ow~~(ePR~!O!P#{~(mT]~!O!P(|!Q![(h!g!h)|#R#S*w#X#Y)|~)PSO!O)]!P;'S)];'S;=`*q<%lO)]~)bR]~!Q![)k!g!h)|#X#Y)|~)pS]~!Q![)k!g!h)|#R#S*k#X#Y)|~*PR{|*Y}!O*Y!Q![*`~*]P!Q![*`~*eQ]~!Q![*`#R#S*Y~*nP!Q![)k~*tP;=`<%l)]~*zP!Q![(h~+SO}~~+VP!_!`#s~+_R!O~!O!P+h![!]#{!a!b#{~+mOS~~+rSq~!Q![+m!c!}+m#R#S+m#T#o+m~,TOs~~,YOr~~,_O|~~,dPg~#p#q#{~,lO{~",
|
|
22
|
+
tokenizers: [0],
|
|
19
23
|
topRules: {"Expression":[0,1]},
|
|
20
|
-
|
|
24
|
+
specialized: [{term: 33, get: (value) => spec_word[value] || -1},{term: 23, get: (value) => spec_Operator[value] || -1}],
|
|
25
|
+
tokenPrec: 479
|
|
21
26
|
});
|
|
22
27
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
const autocompleteFunction = (x) => {
|
|
29
|
+
var _a, _b;
|
|
30
|
+
return ({
|
|
31
|
+
label: `${x.name}(${((_a = x.args) === null || _a === void 0 ? void 0 : _a.join(',')) || ''})`,
|
|
32
|
+
apply: (view, completion, from, to) => {
|
|
33
|
+
var _a;
|
|
34
|
+
view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, `${x.name}()`, from, to)), { selection: { anchor: from + x.name.length + (((_a = x.args) === null || _a === void 0 ? void 0 : _a.length) > 0 ? 1 : 2) } }));
|
|
35
|
+
},
|
|
36
|
+
detail: (_b = x.returnType) === null || _b === void 0 ? void 0 : _b.join('|'),
|
|
37
|
+
info: x.info, type: "function"
|
|
38
|
+
});
|
|
39
|
+
};
|
|
26
40
|
const autocompleteIdentifier = (x) => { var _a; return ({ label: x.name, apply: x.name, info: x.info, detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')), type: 'variable' }); };
|
|
27
|
-
const
|
|
41
|
+
const resolveCallable = (identifier, config) => { var _a; return (_a = config === null || config === void 0 ? void 0 : config.functions) === null || _a === void 0 ? void 0 : _a.find(x => x.name === identifier); };
|
|
42
|
+
const resolveIdentifier = (nodeName, identifier, config) => {
|
|
43
|
+
var _a;
|
|
44
|
+
switch (nodeName) {
|
|
45
|
+
case 'Method':
|
|
46
|
+
case 'Function':
|
|
47
|
+
return resolveCallable(identifier, config);
|
|
48
|
+
case 'Property':
|
|
49
|
+
case 'Variable':
|
|
50
|
+
return (_a = config === null || config === void 0 ? void 0 : config.identifiers) === null || _a === void 0 ? void 0 : _a.find(x => x.name === identifier);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const cursorTooltipBaseTheme = EditorView.baseTheme({
|
|
54
|
+
".cm-tooltip.cm-tooltip-cursor": {
|
|
55
|
+
boxShadow: 'rgba(0, 0, 0, .15) 0 1px 2px',
|
|
56
|
+
border: "1px solid rgba(127, 127, 127, .2)",
|
|
57
|
+
padding: "2px 7px",
|
|
58
|
+
borderRadius: "4px",
|
|
59
|
+
"& .cm-tooltip-arrow:before": {},
|
|
60
|
+
"& .cm-tooltip-arrow:after": {
|
|
61
|
+
borderTopColor: "transparent"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
function getNodeOrdinal(node) {
|
|
66
|
+
let ordinal = -1;
|
|
67
|
+
for (let c = node; c; c = c.prevSibling, ordinal++)
|
|
68
|
+
;
|
|
69
|
+
return ordinal;
|
|
70
|
+
}
|
|
71
|
+
function resolveArguments(node) {
|
|
72
|
+
let c = node;
|
|
73
|
+
while (c && c.name !== 'Arguments') {
|
|
74
|
+
c = c.parent;
|
|
75
|
+
}
|
|
76
|
+
return c;
|
|
77
|
+
}
|
|
78
|
+
function resolveFunctionDefinition(node, state, config) {
|
|
79
|
+
var _a;
|
|
80
|
+
if (!node) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
let identifier;
|
|
84
|
+
if (node.name === 'ObjectAccess' && node.lastChild) {
|
|
85
|
+
const leftArgument = (_a = node.firstChild) === null || _a === void 0 ? void 0 : _a.node;
|
|
86
|
+
const types = Array.from(resolveTypes(state, leftArgument, config));
|
|
87
|
+
identifier = state.sliceDoc(node.lastChild.from, node.lastChild.to);
|
|
88
|
+
return types.map(type => { var _a; return resolveCallable(identifier, (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]); }).find(x => x);
|
|
89
|
+
}
|
|
90
|
+
else if (node.name === 'Function') {
|
|
91
|
+
identifier = state.sliceDoc(node.from, node.node.firstChild ? node.node.firstChild.from - 1 : node.to);
|
|
92
|
+
return resolveCallable(identifier, config);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function getCursorTooltips(state, config) {
|
|
96
|
+
// @ts-ignore
|
|
97
|
+
return state.selection.ranges
|
|
98
|
+
.filter(range => range.empty)
|
|
99
|
+
.map(range => {
|
|
100
|
+
var _a;
|
|
101
|
+
const tree = syntaxTree(state);
|
|
102
|
+
const node = tree.resolveInner(range.from, 0);
|
|
103
|
+
const args = resolveArguments(node);
|
|
104
|
+
if (!args || !args.prevSibling) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
const fn = resolveFunctionDefinition(args.prevSibling, state, config);
|
|
108
|
+
if (!fn) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
const n = args.childAfter(range.from - 1);
|
|
112
|
+
const argName = (_a = fn.args) === null || _a === void 0 ? void 0 : _a[n ? getNodeOrdinal(n) : 0];
|
|
113
|
+
if (n && n.from !== range.from || !argName) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
pos: range.head,
|
|
118
|
+
above: true,
|
|
119
|
+
strictSide: false,
|
|
120
|
+
arrow: true,
|
|
121
|
+
create: () => {
|
|
122
|
+
let dom = document.createElement("div");
|
|
123
|
+
dom.className = "cm-tooltip-cursor";
|
|
124
|
+
dom.textContent = `${argName}`;
|
|
125
|
+
return { dom };
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}).filter(x => x);
|
|
129
|
+
}
|
|
130
|
+
const cursorTooltipField = (config) => StateField.define({
|
|
131
|
+
create: (state) => getCursorTooltips(state, config),
|
|
132
|
+
update(tooltips, tr) {
|
|
133
|
+
if (!tr.docChanged && !tr.selection) {
|
|
134
|
+
return tooltips;
|
|
135
|
+
}
|
|
136
|
+
return getCursorTooltips(tr.state, config);
|
|
137
|
+
},
|
|
138
|
+
provide: f => showTooltip.computeN([f], state => state.field(f))
|
|
139
|
+
});
|
|
140
|
+
const expressionLanguageLinterSource = (config) => (state) => {
|
|
28
141
|
let diagnostics = [];
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
142
|
+
syntaxTree(state).cursor().iterate(node => {
|
|
143
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
144
|
+
const { from, to, name } = node;
|
|
145
|
+
let identifier;
|
|
146
|
+
switch (name) {
|
|
147
|
+
case '⚠':
|
|
148
|
+
if (state.doc.length === 0 || from === 0) {
|
|
149
|
+
// Don't show error on empty doc (even though it is an error)
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
identifier = state.sliceDoc(from, to);
|
|
153
|
+
if (identifier.length === 0) {
|
|
154
|
+
diagnostics.push({ from, to: (_c = (_b = (_a = node.node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.to) !== null && _c !== void 0 ? _c : to, severity: 'error', message: `Expression expected` });
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
const type = /^[a-zA-Z_]+[a-zA-Z_0-9]*$/.test(identifier) ? 'identifier' : 'operator';
|
|
158
|
+
diagnostics.push({ from, to, severity: 'error', message: `Unexpected ${type} '${identifier}'` });
|
|
159
|
+
}
|
|
160
|
+
return;
|
|
161
|
+
case 'Arguments':
|
|
162
|
+
const args = (_d = resolveFunctionDefinition(node.node.prevSibling, state, config)) === null || _d === void 0 ? void 0 : _d.args;
|
|
163
|
+
if (!args) {
|
|
164
|
+
return;
|
|
44
165
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
from:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
message: `Property '${identifier}' not found in ${Array.from(types).join('|')}`,
|
|
53
|
-
});
|
|
166
|
+
let i = 0;
|
|
167
|
+
let n = node.node.firstChild;
|
|
168
|
+
while (n) {
|
|
169
|
+
if (++i > args.length) {
|
|
170
|
+
diagnostics.push({ from: n.from, to: n.to, severity: 'error', message: `Unexpected argument` });
|
|
171
|
+
}
|
|
172
|
+
n = n.nextSibling;
|
|
54
173
|
}
|
|
55
|
-
|
|
56
|
-
|
|
174
|
+
break;
|
|
175
|
+
case 'Property':
|
|
176
|
+
case 'Method':
|
|
177
|
+
const leftArgument = (_f = (_e = node.node.parent) === null || _e === void 0 ? void 0 : _e.firstChild) === null || _f === void 0 ? void 0 : _f.node;
|
|
178
|
+
const types = Array.from(resolveTypes(state, leftArgument, config));
|
|
179
|
+
identifier = state.sliceDoc(from, to);
|
|
180
|
+
if (!types.find(type => { var _a; return resolveIdentifier(name, identifier, (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]); })) {
|
|
181
|
+
diagnostics.push({ from, to, severity: 'error', message: `${node.name} "${identifier}" not found in ${types.join('|')}` });
|
|
182
|
+
}
|
|
183
|
+
break;
|
|
184
|
+
case 'Variable':
|
|
185
|
+
case 'Function':
|
|
186
|
+
identifier = state.sliceDoc(from, node.node.firstChild ? node.node.firstChild.from - 1 : to);
|
|
187
|
+
if (!resolveIdentifier(name, identifier, config)) {
|
|
188
|
+
diagnostics.push({ from, to, severity: 'error', message: `${node.node.name} "${identifier}" not found` });
|
|
189
|
+
}
|
|
190
|
+
break;
|
|
57
191
|
}
|
|
58
|
-
if (node.
|
|
59
|
-
|
|
60
|
-
diagnostics.push({
|
|
61
|
-
from: node.from,
|
|
62
|
-
to: node.to,
|
|
63
|
-
severity: 'error',
|
|
64
|
-
message: `Unexpected identifier after another identifier`,
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
const identifier = view.state.sliceDoc(node.from, node.to);
|
|
68
|
-
if (!isFunction(identifier, config) && !isVariable(identifier, config)) {
|
|
69
|
-
diagnostics.push({
|
|
70
|
-
from: node.from,
|
|
71
|
-
to: node.to,
|
|
72
|
-
severity: 'error',
|
|
73
|
-
message: `Identifier "${identifier}" not found`,
|
|
74
|
-
});
|
|
75
|
-
}
|
|
192
|
+
if (identifier && ((_g = node.node.parent) === null || _g === void 0 ? void 0 : _g.type.isError)) {
|
|
193
|
+
diagnostics.push({ from, to, severity: 'error', message: `Unexpected identifier "${identifier}"` });
|
|
76
194
|
}
|
|
77
|
-
previousNode = node.node;
|
|
78
195
|
});
|
|
79
196
|
return diagnostics;
|
|
80
|
-
}
|
|
197
|
+
};
|
|
198
|
+
const expressionLanguageLinter = (config) => linter(view => expressionLanguageLinterSource(config)(view.state));
|
|
81
199
|
const keywordTooltip = (config) => hoverTooltip((view, pos, side) => {
|
|
82
200
|
var _a, _b, _c, _d, _e, _f;
|
|
83
201
|
const tree = syntaxTree(view.state).resolveInner(pos, side);
|
|
84
|
-
if (
|
|
202
|
+
if (!['Function', 'Variable', 'Method', 'Property'].includes(tree.name)) {
|
|
85
203
|
return null;
|
|
86
204
|
}
|
|
87
205
|
const skipEmpty = (x) => x;
|
|
88
206
|
let info;
|
|
89
207
|
if (((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.firstChild) && ((_b = tree.parent) === null || _b === void 0 ? void 0 : _b.name) === 'ObjectAccess' && tree.prevSibling) {
|
|
90
208
|
const node = tree.parent.firstChild;
|
|
91
|
-
const types = resolveTypes(view.state, node, config
|
|
209
|
+
const types = Array.from(resolveTypes(view.state, node, config));
|
|
92
210
|
const name = view.state.sliceDoc(tree.from, tree.to);
|
|
93
211
|
info = [
|
|
94
|
-
...
|
|
95
|
-
...
|
|
212
|
+
...types.map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.identifiers) === null || _c === void 0 ? void 0 : _c.find(x => x.name === name)) === null || _d === void 0 ? void 0 : _d.info; }).filter(skipEmpty),
|
|
213
|
+
...types.map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.functions) === null || _c === void 0 ? void 0 : _c.find(x => x.name === name)) === null || _d === void 0 ? void 0 : _d.info; }).filter(skipEmpty),
|
|
96
214
|
].join('\n');
|
|
97
215
|
}
|
|
98
216
|
else {
|
|
@@ -110,8 +228,8 @@ const keywordTooltip = (config) => hoverTooltip((view, pos, side) => {
|
|
|
110
228
|
end: tree.to,
|
|
111
229
|
above: true,
|
|
112
230
|
create(view) {
|
|
113
|
-
|
|
114
|
-
dom.textContent = info;
|
|
231
|
+
const dom = document.createElement("div");
|
|
232
|
+
dom[config.htmlTooltip ? 'innerHTML' : 'textContent'] = info;
|
|
115
233
|
dom.className = 'cm-diagnostic';
|
|
116
234
|
return { dom };
|
|
117
235
|
},
|
|
@@ -121,13 +239,20 @@ const ELLanguage = LRLanguage.define({
|
|
|
121
239
|
parser: parser.configure({
|
|
122
240
|
props: [
|
|
123
241
|
indentNodeProp.add({
|
|
124
|
-
Application: delimitedIndent({ closing: ")", align: false })
|
|
242
|
+
Application: delimitedIndent({ closing: ")", align: false }),
|
|
243
|
+
Arguments: delimitedIndent({ closing: ")", align: false }),
|
|
244
|
+
Object: delimitedIndent({ closing: "}", align: false }),
|
|
125
245
|
}),
|
|
126
246
|
foldNodeProp.add({
|
|
127
|
-
Application:
|
|
247
|
+
Application: ({ from, to }) => ({ from: from + 1, to: to - 1 }),
|
|
248
|
+
Arguments: ({ from, to }) => ({ from: from + 1, to: to - 1 }),
|
|
249
|
+
Object: ({ from, to }) => ({ from: from + 1, to: to - 1 }),
|
|
128
250
|
}),
|
|
129
251
|
styleTags({
|
|
130
|
-
|
|
252
|
+
Property: tags.propertyName,
|
|
253
|
+
Variable: tags.variableName,
|
|
254
|
+
Function: tags.function(tags.variableName),
|
|
255
|
+
Method: tags.function(tags.propertyName),
|
|
131
256
|
Boolean: tags.bool,
|
|
132
257
|
String: tags.string,
|
|
133
258
|
Number: tags.number,
|
|
@@ -135,10 +260,12 @@ const ELLanguage = LRLanguage.define({
|
|
|
135
260
|
')': tags.paren,
|
|
136
261
|
'[': tags.squareBracket,
|
|
137
262
|
']': tags.squareBracket,
|
|
263
|
+
',': tags.punctuation,
|
|
264
|
+
MemberOf: tags.punctuation,
|
|
265
|
+
NullSafeMemberOf: tags.punctuation,
|
|
138
266
|
OperatorKeyword: tags.operatorKeyword,
|
|
267
|
+
UnaryOperator: tags.operator,
|
|
139
268
|
Operator: tags.operator,
|
|
140
|
-
MemberOf: tags.operator,
|
|
141
|
-
NullSafeMemberOf: tags.operator,
|
|
142
269
|
})
|
|
143
270
|
]
|
|
144
271
|
}),
|
|
@@ -146,46 +273,61 @@ const ELLanguage = LRLanguage.define({
|
|
|
146
273
|
});
|
|
147
274
|
function completeOperatorKeyword(state, config, tree, from, to, explicit) {
|
|
148
275
|
var _a, _b;
|
|
149
|
-
const text = state.sliceDoc(from, to);
|
|
150
276
|
return {
|
|
151
277
|
from,
|
|
152
278
|
to,
|
|
153
|
-
options: (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.
|
|
154
|
-
validFor: (text) => { var _a, _b; return (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.some(({ name }) => explicit || name.
|
|
279
|
+
options: (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.map(({ name, info, detail }) => ({ label: name, apply: `${name} `, info, detail, type: "keyword" }))) !== null && _b !== void 0 ? _b : [],
|
|
280
|
+
validFor: (text) => { var _a, _b; return (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.some(({ name }) => explicit || name.includes(text))) !== null && _b !== void 0 ? _b : false; },
|
|
155
281
|
};
|
|
156
282
|
}
|
|
157
|
-
function completeIdentifier(state, config, tree, from, to
|
|
158
|
-
var _a, _b
|
|
159
|
-
const
|
|
160
|
-
const
|
|
161
|
-
const functions = (_d = (_c = config.functions) === null || _c === void 0 ? void 0 : _c.filter(({ name }) => explicit || name.toLowerCase().startsWith(text))) !== null && _d !== void 0 ? _d : [];
|
|
283
|
+
function completeIdentifier(state, config, tree, from, to) {
|
|
284
|
+
var _a, _b;
|
|
285
|
+
const identifiers = (_a = config.identifiers) !== null && _a !== void 0 ? _a : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
|
|
286
|
+
const functions = (_b = config.functions) !== null && _b !== void 0 ? _b : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
|
|
162
287
|
return {
|
|
163
288
|
from,
|
|
164
289
|
to,
|
|
165
290
|
options: [...(identifiers.map(autocompleteIdentifier)), ...(functions.map(autocompleteFunction))],
|
|
166
|
-
|
|
167
|
-
filter: false,
|
|
291
|
+
validFor: /^[a-zA-Z_]+[a-zA-Z_0-9]*$/,
|
|
168
292
|
};
|
|
169
293
|
}
|
|
170
294
|
function resolveTypes(state, node, config, matchExact) {
|
|
171
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
295
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
172
296
|
let types = new Set();
|
|
173
|
-
if (node
|
|
174
|
-
|
|
297
|
+
if (!node) {
|
|
298
|
+
return types;
|
|
299
|
+
}
|
|
300
|
+
if (node.name === 'Call' && node.firstChild && node.lastChild) {
|
|
301
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
175
302
|
}
|
|
176
|
-
else if (node.name === '
|
|
303
|
+
else if (node.name === 'Variable') {
|
|
177
304
|
const varName = state.sliceDoc(node.from, node.to) || '';
|
|
178
|
-
|
|
179
|
-
(
|
|
305
|
+
// @ts-ignore
|
|
306
|
+
(_b = (_a = resolveIdentifier(node.name, varName, config)) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.forEach((x) => types.add(x));
|
|
180
307
|
}
|
|
181
|
-
else if (node.name === '
|
|
182
|
-
const
|
|
308
|
+
else if (node.name === 'Function') {
|
|
309
|
+
const varName = state.sliceDoc(node.from, node.to) || '';
|
|
310
|
+
// @ts-ignore
|
|
311
|
+
(_d = (_c = resolveIdentifier(node.name, varName, config)) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
|
|
312
|
+
}
|
|
313
|
+
else if (node.name === 'ObjectAccess' && node.firstChild && ((_e = node.lastChild) === null || _e === void 0 ? void 0 : _e.name) === 'Property') {
|
|
183
314
|
const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
(
|
|
188
|
-
}
|
|
315
|
+
(_f = resolveTypes(state, node.firstChild, config)) === null || _f === void 0 ? void 0 : _f.forEach(baseType => {
|
|
316
|
+
var _a, _b, _c, _d;
|
|
317
|
+
// @ts-ignore
|
|
318
|
+
(_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.name, varName, (_b = config.types) === null || _b === void 0 ? void 0 : _b[baseType])) === null || _c === void 0 ? void 0 : _c.type) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
else if (node.name === 'ObjectAccess' && node.firstChild && ((_g = node.lastChild) === null || _g === void 0 ? void 0 : _g.name) === 'Method') {
|
|
322
|
+
const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
|
|
323
|
+
(_h = resolveTypes(state, node.firstChild, config)) === null || _h === void 0 ? void 0 : _h.forEach(baseType => {
|
|
324
|
+
var _a, _b, _c, _d;
|
|
325
|
+
// @ts-ignore
|
|
326
|
+
(_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.name, varName, (_b = config.types) === null || _b === void 0 ? void 0 : _b[baseType])) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
else if (node.name === 'Application' && node.firstChild) {
|
|
330
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
189
331
|
}
|
|
190
332
|
if (types.size === 0) {
|
|
191
333
|
types.add('any');
|
|
@@ -197,42 +339,46 @@ function completeMember(state, config, tree, from, to, explicit) {
|
|
|
197
339
|
if (((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.name) != 'ObjectAccess' || !tree.parent.firstChild) {
|
|
198
340
|
return null;
|
|
199
341
|
}
|
|
200
|
-
|
|
342
|
+
state.sliceDoc(from, to);
|
|
343
|
+
const types = resolveTypes(state, tree.parent.firstChild.node, config);
|
|
201
344
|
if (!(types === null || types === void 0 ? void 0 : types.size)) {
|
|
202
345
|
return null;
|
|
203
346
|
}
|
|
204
|
-
const varName = state.sliceDoc(from, to);
|
|
205
347
|
let options = [];
|
|
206
348
|
for (const type of types) {
|
|
207
349
|
const typeDeclaration = (_b = config.types) === null || _b === void 0 ? void 0 : _b[type];
|
|
208
|
-
options.push(...(((_c = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.identifiers) === null || _c === void 0 ? void 0 : _c.
|
|
350
|
+
options.push(...(((_c = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.identifiers) === null || _c === void 0 ? void 0 : _c.map(autocompleteIdentifier)) || []), ...(((_d = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.functions) === null || _d === void 0 ? void 0 : _d.map(autocompleteFunction)) || []));
|
|
209
351
|
}
|
|
210
352
|
return {
|
|
211
353
|
from,
|
|
212
354
|
to,
|
|
213
355
|
options,
|
|
214
|
-
|
|
356
|
+
validFor: /^[a-zA-Z_]+[a-zA-Z_0-9]*$/,
|
|
215
357
|
};
|
|
216
358
|
}
|
|
217
359
|
function expressionLanguageCompletionFor(config, context) {
|
|
218
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
360
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
219
361
|
const { state, pos, explicit } = context;
|
|
220
|
-
const tree = syntaxTree(state)
|
|
221
|
-
const
|
|
222
|
-
const isIdentifier = (node) => (node === null || node === void 0 ? void 0 : node.name)
|
|
223
|
-
const
|
|
224
|
-
if (
|
|
362
|
+
const tree = syntaxTree(state);
|
|
363
|
+
const prevNode = tree.resolveInner(pos, state.sliceDoc(pos - 1, pos) === ')' ? 0 : -1);
|
|
364
|
+
const isIdentifier = (node) => { var _a; return ['Variable', 'Function'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
|
|
365
|
+
const isMember = (node) => { var _a; return ['Property', 'Method'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
|
|
366
|
+
if (prevNode.name == 'String') {
|
|
225
367
|
return null;
|
|
226
368
|
}
|
|
227
|
-
if (((
|
|
228
|
-
return completeMember(state, config,
|
|
369
|
+
if (((_a = prevNode.parent) === null || _a === void 0 ? void 0 : _a.name) == 'ObjectAccess' && ['ObjectAccess', 'ArrayAccess', 'Variable', 'Call'].includes(((_b = prevNode.parent.firstChild) === null || _b === void 0 ? void 0 : _b.name) || '')) {
|
|
370
|
+
return completeMember(state, config, prevNode, isIdentifier(prevNode) || isMember(prevNode) ? prevNode.from : pos, pos);
|
|
229
371
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
372
|
+
if (['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes(prevNode.name) && prevNode.lastChild && !((_c = prevNode.lastChild) === null || _c === void 0 ? void 0 : _c.type.isError)
|
|
373
|
+
|| ['Arguments', 'Array'].includes(prevNode.name) && prevNode.lastChild && !((_d = prevNode.lastChild) === null || _d === void 0 ? void 0 : _d.type.isError)
|
|
374
|
+
|| ['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes((_f = (_e = prevNode.parent) === null || _e === void 0 ? void 0 : _e.name) !== null && _f !== void 0 ? _f : '') && prevNode.type.isError
|
|
375
|
+
|| ['Variable', 'Function'].includes((_h = (_g = prevNode.parent) === null || _g === void 0 ? void 0 : _g.name) !== null && _h !== void 0 ? _h : '') && prevNode.type.isError) {
|
|
376
|
+
return completeOperatorKeyword(state, config, prevNode, !['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression', 'Arguments'].includes(prevNode.name) ? prevNode.from : pos, pos, explicit);
|
|
233
377
|
}
|
|
234
|
-
if (
|
|
235
|
-
|
|
378
|
+
if (['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes(prevNode.name) && ((_j = prevNode.lastChild) === null || _j === void 0 ? void 0 : _j.type.isError)
|
|
379
|
+
|| ['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression', 'Arguments'].includes((_l = (_k = prevNode.parent) === null || _k === void 0 ? void 0 : _k.name) !== null && _l !== void 0 ? _l : '') && !prevNode.type.isError
|
|
380
|
+
|| ['Arguments', 'Array'].includes((_m = prevNode.name) !== null && _m !== void 0 ? _m : '')) {
|
|
381
|
+
return completeIdentifier(state, config, prevNode, isIdentifier(prevNode) ? prevNode.from : pos, pos);
|
|
236
382
|
}
|
|
237
383
|
return null;
|
|
238
384
|
}
|
|
@@ -257,7 +403,8 @@ function expressionlanguage(config = {}, extensions = []) {
|
|
|
257
403
|
expressionLanguageLinter(config),
|
|
258
404
|
keywordTooltip(config),
|
|
259
405
|
...extensions,
|
|
406
|
+
[cursorTooltipField(config), cursorTooltipBaseTheme],
|
|
260
407
|
]);
|
|
261
408
|
}
|
|
262
409
|
|
|
263
|
-
export { ELLanguage, expressionlanguage, keywordTooltip };
|
|
410
|
+
export { ELLanguage, expressionLanguageLinterSource, expressionlanguage, keywordTooltip };
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@valtzu/codemirror-lang-el",
|
|
3
3
|
"description": "Symfony Expression Language language support for CodeMirror",
|
|
4
4
|
"scripts": {
|
|
5
|
-
"test": "mocha test
|
|
5
|
+
"test": "mocha test/*.js",
|
|
6
6
|
"dev": "rollup -c -w",
|
|
7
7
|
"prepare": "rollup -c"
|
|
8
8
|
},
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"access": "public",
|
|
43
43
|
"registry": "https://registry.npmjs.org/"
|
|
44
44
|
},
|
|
45
|
-
"version": "0.
|
|
45
|
+
"version": "0.5.0"
|
|
46
46
|
}
|