@valtzu/codemirror-lang-el 1.3.0 → 1.4.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/CHANGELOG.md +7 -0
- package/dist/index.cjs +100 -32
- package/dist/index.js +100 -32
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -14,25 +14,25 @@ const t = {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
17
|
-
const spec_word = {__proto__:null,true:
|
|
18
|
-
const spec_Operator = {__proto__:null,"?":
|
|
17
|
+
const spec_word = {__proto__:null,true:92, TRUE:94, false:96, FALSE:98, null:100, NULL:102, starts:114, with:116, ends:118, contains:120, matches:122, not:124, in:126, and:128, or:130, xor:132};
|
|
18
|
+
const spec_Operator = {__proto__:null,"?":113, "!":135, "~":137, "+":139, "-":141};
|
|
19
19
|
const parser = lr.LRParser.deserialize({
|
|
20
20
|
version: 14,
|
|
21
|
-
states: ")YOYQPOOP!aOPOOQ!
|
|
22
|
-
stateData: ",
|
|
23
|
-
goto: "%
|
|
24
|
-
nodeNames: "⚠ BlockComment Expression PropertyAccess MemberOf NullSafeMemberOf Property ArrayAccess Call Function Arguments MethodAccess Method Number String Boolean Null Object Array Variable TernaryExpression Operator BinaryExpression OperatorKeyword UnaryExpression UnaryOperator Application",
|
|
25
|
-
maxTerm:
|
|
21
|
+
states: ")YOYQPOOP!aOPOOQ!fQQOOO#gQQO'#CgO$}QPO'#CoO%UQPO'#CpOYQPO'#CvOYQPO'#CxOOQO'#DT'#DTO%]QPO'#CfOOQO'#Cm'#CmOOQO'#Cn'#CnOOQO'#Cw'#CwP%bOSO'#C]POOO)C>s)C>sO%mQPO,58yOYQPO,58}OYQPO,59`OYQPO,59^O%rQPO'#CuOOQO'#Cu'#CuO%wQPO'#CuO'RQQO,59ZOOQO,59Z,59ZO'YQQO'#DYO'gQPO,59[O'lQQO,59bO(SQQO,59dO(ZQPO'#ChOOQO,59Q,59QPOOO'#Cy'#CyP(bOSO,58wPOOO,58w,58wO(mQQO'#CbOOQO1G.e1G.eOOQO1G.o1G.oO*TQQO1G.iO*[QQO1G.zO*rQQO1G.xOOQO,59a,59aOYQPO1G.uOYQPO'#CzO*yQPO,59tOOQO1G.v1G.vOOQO1G/O1G/OO+UQPO,59SPOOO-E6w-E6wPOOO1G.c1G.cOOQO7+$T7+$TOYQPO7+$dO+ZQQO7+$aO+eQQO,59fOOQO-E6x-E6xOOQO1G.n1G.nO+rQQO<<HOOYQPO'#C{O,YQPO<<G{OOQO<<G{<<G{O,bQQO,59gOOQO-E6y-E6yOOQOAN=gAN=gOYQPO1G/RO,iQQO7+$m",
|
|
22
|
+
stateData: ",{~OrOSsPQ~O_WO`WOxRO{VO!OYO!PYO!QYO!RYO!SZO!TZO!VSO!XTO!`[O!e[O!f[O!g[O!h[O~Os]O~OS_OT_OW`OX`OgaO!YbO!ZcO!]cO!^dO!_dO!`eO!adO!bdO!cdO!ddO~OSeXTeXWeXXeXgeXpeX{ZX!YeX!ZeX!]eX!^eX!_eX!`eX!aeX!beX!ceX!deX!WeXyeX}eXzeX!UeX~O!UgO~PYOy|P~PYO{lO~OtnOunOvpO~OxqO~O![wO~O!awO_iX`iXxiX{iX!OiX!PiX!QiX!RiX!SiX!TiX!ViX!XiX!`iX!eiX!fiX!giX!hiX~O!WxO~P!fO}yOy|Xz|X~P!fOy{O~Opja!Wjayja}jazja!Uja~P!fOz|O~P!fOz|P~PYOtnOunOv!PO~OSUXTUXWUXXUXgUXpUX{^X!YUX!ZUX!]UX!^UX!_UX!`UX!aUX!bUX!cUX!dUX!WUXyUX}UXzUX!UUX~Oy!QO~P!fOphi!Whiyhi}hizhi!Uhi~P!fO!W!RO~P!fO}yOy|az|a~Oz!VO~O}!XO!U!ZO~P!fOyna}nazna~P!fOpfy!Wfyyfy}fyzfy!Ufy~P!fO}!XO!U!^O~O!W!_O~P!fO}oq!Uoq~P!fO`TgS_xS~",
|
|
23
|
+
goto: "%P}P!OP!RPP!c!RPP!R!f!v!f!yPP!R!R!R!R!R!RP!R!|!R#]!R#m#s#yPPPPPPP$PPPPP$yR^PmWOSTUV`ablxy!R!X!_Rr_mXOSTUV`ablxy!R!X!_RmXRs_kaQfhjktuv!S!T!W![!`mUOSTUV`ablxy!R!X!_Qo]R!OoQzhR!UzQ!Y!SR!]!YQQOQfSShTlQjUQkVQt`QuaQvbQ!SxQ!TyQ!W!RQ![!XR!`!_QiTR}l",
|
|
24
|
+
nodeNames: "⚠ BlockComment Expression PropertyAccess MemberOf NullSafeMemberOf Property ArrayAccess ArrayAccessor NullSafeArrayAccessor Call Function Arguments MethodAccess Method Number String Boolean Null Object Array Variable TernaryExpression Operator BinaryExpression OperatorKeyword UnaryExpression UnaryOperator Application",
|
|
25
|
+
maxTerm: 70,
|
|
26
26
|
nodeProps: [
|
|
27
|
-
[t,
|
|
27
|
+
[t, 15,"number",16,"string",17,"bool",18,"null",19,"object",20,"array"]
|
|
28
28
|
],
|
|
29
|
-
skippedNodes: [0,1,
|
|
29
|
+
skippedNodes: [0,1,29],
|
|
30
30
|
repeatNodeCount: 3,
|
|
31
|
-
tokenData: "-
|
|
32
|
-
tokenizers: [1, new lr.LocalTokenGroup("j~RQYZXz{^~^
|
|
31
|
+
tokenData: "-k~RqXY#YYZ#Y]^#Ypq#Yqr#krs$Quv#{vw%zwx&Sxy'wyz'|z{(R{|#{|}(Z}!O#{!O!P(`!P!Q(h!Q![(u![!]+[!^!_+a!_!`+l!`!a+r!a!b+}!c!},j!}#O,{#P#Q-S#Q#R#{#R#S,j#T#o,j#o#p-X#p#q-^#q#r-f#r#s#{~#_Sr~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~'|O{~~(ROz~~(WPg~z{#{~(`O}~~(ePS~!O!P#{~(mPg~z{(p~(uOs~~(zT_~!O!P)Z!Q![(u!g!h*Z#R#S+U#X#Y*Z~)^SO!O)j!P;'S)j;'S;=`+O<%lO)j~)oR_~!Q![)x!g!h*Z#X#Y*Z~)}S_~!Q![)x!g!h*Z#R#S*x#X#Y*Z~*^R{|*g}!O*g!Q![*m~*jP!Q![*m~*rQ_~!Q![*m#R#S*g~*{P!Q![)x~+RP;=`<%l)j~+XP!Q![(u~+aO!W~~+fQg~!^!_#{!_!`#{~+oP!_!`#s~+wQg~!_!`#{!`!a#{~,SRg~!O!P,]![!]#{!a!b#{~,bPT~!}#O,e~,jOX~~,oSx~!Q![,j!c!},j#R#S,j#T#o,jU-SO!XQWS~-XOy~~-^O!V~~-cPg~#p#q#{~-kO!U~",
|
|
32
|
+
tokenizers: [1, 2, new lr.LocalTokenGroup("j~RQYZXz{^~^Ou~~aP!P!Qd~iOv~~", 25, 36)],
|
|
33
33
|
topRules: {"Expression":[0,2]},
|
|
34
|
-
specialized: [{term:
|
|
35
|
-
tokenPrec:
|
|
34
|
+
specialized: [{term: 40, get: (value) => spec_word[value] || -1},{term: 23, get: (value) => spec_Operator[value] || -1}],
|
|
35
|
+
tokenPrec: 541
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
// generate CONFIGURATION.md from this file by running "tsdoc --src=src/types.ts --dest=CONFIGURATION.md --noemoji --types"
|
|
@@ -56,21 +56,23 @@ exports.ELScalar = void 0;
|
|
|
56
56
|
const BlockComment = 1,
|
|
57
57
|
Expression = 2,
|
|
58
58
|
PropertyAccess = 3,
|
|
59
|
+
NullSafeMemberOf = 5,
|
|
59
60
|
Property = 6,
|
|
60
61
|
ArrayAccess = 7,
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
62
|
+
NullSafeArrayAccessor = 9,
|
|
63
|
+
Call = 10,
|
|
64
|
+
Function = 11,
|
|
65
|
+
Arguments = 12,
|
|
66
|
+
MethodAccess = 13,
|
|
67
|
+
Method = 14,
|
|
68
|
+
String = 16,
|
|
69
|
+
Array$1 = 20,
|
|
70
|
+
Variable = 21,
|
|
71
|
+
TernaryExpression = 22,
|
|
72
|
+
BinaryExpression = 24,
|
|
73
|
+
OperatorKeyword = 25,
|
|
74
|
+
UnaryExpression = 26,
|
|
75
|
+
Application = 28;
|
|
74
76
|
|
|
75
77
|
const createInfoElement = (html) => {
|
|
76
78
|
const dom = document.createElement("div");
|
|
@@ -94,7 +96,7 @@ function resolveFunctionDefinition(node, state, config) {
|
|
|
94
96
|
let identifier;
|
|
95
97
|
if ((node.type.is(PropertyAccess) || node.type.is(MethodAccess)) && node.lastChild) {
|
|
96
98
|
const leftArgument = (_a = node.firstChild) === null || _a === void 0 ? void 0 : _a.node;
|
|
97
|
-
const types = Array.from(resolveTypes(state, leftArgument, config));
|
|
99
|
+
const types = window.Array.from(resolveTypes(state, leftArgument, config));
|
|
98
100
|
identifier = state.sliceDoc(node.lastChild.from, node.lastChild.to);
|
|
99
101
|
return types.map(type => { var _a; return resolveCallable(identifier, (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]); }).find(x => x);
|
|
100
102
|
}
|
|
@@ -123,7 +125,29 @@ function resolveTypes(state, node, config) {
|
|
|
123
125
|
}
|
|
124
126
|
let type;
|
|
125
127
|
if (typeof (type = node.type.prop(t)) !== "undefined") {
|
|
126
|
-
|
|
128
|
+
if (type === exports.ELScalar.Array) {
|
|
129
|
+
// For array literals, infer element types from array contents
|
|
130
|
+
const elementTypes = new Set();
|
|
131
|
+
for (let child = node.firstChild; child; child = child.nextSibling) {
|
|
132
|
+
if (!child.type.isError) {
|
|
133
|
+
resolveTypes(state, child, config).forEach(elementType => {
|
|
134
|
+
elementTypes.add(elementType);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (elementTypes.size > 0) {
|
|
139
|
+
// Build typed array notation (e.g., "string[]")
|
|
140
|
+
elementTypes.forEach(elementType => {
|
|
141
|
+
types.add(`${elementType}[]`);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
types.add(type);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
types.add(type);
|
|
150
|
+
}
|
|
127
151
|
}
|
|
128
152
|
else if (node.type.is(Call) && node.firstChild && node.lastChild) {
|
|
129
153
|
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
@@ -145,6 +169,9 @@ function resolveTypes(state, node, config) {
|
|
|
145
169
|
// @ts-expect-error TS2339
|
|
146
170
|
(_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.type.id, 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));
|
|
147
171
|
});
|
|
172
|
+
if (node.getChild(NullSafeMemberOf)) {
|
|
173
|
+
types.add(exports.ELScalar.Null);
|
|
174
|
+
}
|
|
148
175
|
}
|
|
149
176
|
else if (node.type.is(MethodAccess) && node.firstChild && ((_g = node.lastChild) === null || _g === void 0 ? void 0 : _g.type.is(Method))) {
|
|
150
177
|
const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
|
|
@@ -153,6 +180,9 @@ function resolveTypes(state, node, config) {
|
|
|
153
180
|
// @ts-expect-error TS2339
|
|
154
181
|
(_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.type.id, 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));
|
|
155
182
|
});
|
|
183
|
+
if (node.getChild(NullSafeMemberOf)) {
|
|
184
|
+
types.add(exports.ELScalar.Null);
|
|
185
|
+
}
|
|
156
186
|
}
|
|
157
187
|
// Array indexing: for typed arrays (e.g. Foo[]) return element type, for generic arrays return any
|
|
158
188
|
else if (node.type.is(ArrayAccess) && node.firstChild) {
|
|
@@ -165,6 +195,9 @@ function resolveTypes(state, node, config) {
|
|
|
165
195
|
types.add(exports.ELScalar.Any);
|
|
166
196
|
}
|
|
167
197
|
});
|
|
198
|
+
if (node.getChild(NullSafeArrayAccessor)) {
|
|
199
|
+
types.add(exports.ELScalar.Null);
|
|
200
|
+
}
|
|
168
201
|
}
|
|
169
202
|
else if (node.type.is(Application) && node.firstChild) {
|
|
170
203
|
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
@@ -236,7 +269,7 @@ const expressionLanguageLinterSource = (state) => {
|
|
|
236
269
|
const config = getExpressionLanguageConfig(state);
|
|
237
270
|
const diagnostics = [];
|
|
238
271
|
language.syntaxTree(state).cursor().iterate(node => {
|
|
239
|
-
var _a, _b, _c, _d, _e, _f;
|
|
272
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
240
273
|
const { from, to, type: { id } } = node;
|
|
241
274
|
let identifier;
|
|
242
275
|
switch (id) {
|
|
@@ -292,7 +325,19 @@ const expressionLanguageLinterSource = (state) => {
|
|
|
292
325
|
}
|
|
293
326
|
case Property:
|
|
294
327
|
case Method: {
|
|
295
|
-
const
|
|
328
|
+
const parent = node.node.parent;
|
|
329
|
+
const isPropertyAccess = parent === null || parent === void 0 ? void 0 : parent.type.is(PropertyAccess);
|
|
330
|
+
const isMethodAccess = parent === null || parent === void 0 ? void 0 : parent.type.is(MethodAccess);
|
|
331
|
+
// Skip validation if this is part of a PropertyAccess/MethodAccess on array type
|
|
332
|
+
// (the PropertyAccess/MethodAccess case will handle the error)
|
|
333
|
+
if ((isPropertyAccess || isMethodAccess) && (parent === null || parent === void 0 ? void 0 : parent.firstChild)) {
|
|
334
|
+
const types = Array.from(resolveTypes(state, parent.firstChild.node, config));
|
|
335
|
+
const hasArrayType = types.includes(exports.ELScalar.Array) || types.some(x => x.endsWith('[]'));
|
|
336
|
+
if (hasArrayType && !types.includes(exports.ELScalar.Any)) {
|
|
337
|
+
break; // Skip property validation, error will be reported by PropertyAccess/MethodAccess case
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const leftArgument = (_d = parent === null || parent === void 0 ? void 0 : parent.firstChild) === null || _d === void 0 ? void 0 : _d.node;
|
|
296
341
|
const types = Array.from(resolveTypes(state, leftArgument, config));
|
|
297
342
|
identifier = state.sliceDoc(from, to);
|
|
298
343
|
if (!types.find(type => { var _a; return resolveIdentifier(id, identifier, (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]); })) {
|
|
@@ -300,6 +345,29 @@ const expressionLanguageLinterSource = (state) => {
|
|
|
300
345
|
}
|
|
301
346
|
break;
|
|
302
347
|
}
|
|
348
|
+
case PropertyAccess:
|
|
349
|
+
case MethodAccess: {
|
|
350
|
+
const leftArgument = (_e = node.node.firstChild) === null || _e === void 0 ? void 0 : _e.node;
|
|
351
|
+
const types = Array.from(resolveTypes(state, leftArgument, config));
|
|
352
|
+
const hasArrayType = types.includes(exports.ELScalar.Array) || types.some(x => x.endsWith('[]'));
|
|
353
|
+
if (hasArrayType && !types.includes(exports.ELScalar.Any)) {
|
|
354
|
+
const propertyOrMethod = node.node.lastChild;
|
|
355
|
+
const errorFrom = (_f = propertyOrMethod === null || propertyOrMethod === void 0 ? void 0 : propertyOrMethod.from) !== null && _f !== void 0 ? _f : from;
|
|
356
|
+
const errorTo = (_g = propertyOrMethod === null || propertyOrMethod === void 0 ? void 0 : propertyOrMethod.to) !== null && _g !== void 0 ? _g : to;
|
|
357
|
+
diagnostics.push({ from: errorFrom, to: errorTo, severity: 'error', message: `Unexpected object access on <code>${types.join('|')}</code>` });
|
|
358
|
+
}
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
case ArrayAccess: {
|
|
362
|
+
const leftArgument = (_h = node.node.firstChild) === null || _h === void 0 ? void 0 : _h.node;
|
|
363
|
+
const arrayAccessor = leftArgument.nextSibling;
|
|
364
|
+
const types = Array.from(resolveTypes(state, leftArgument, config));
|
|
365
|
+
const allowsAny = types.includes(exports.ELScalar.Array) || types.includes(exports.ELScalar.Any);
|
|
366
|
+
if (!allowsAny && ![...types].some(x => x.endsWith('[]'))) {
|
|
367
|
+
diagnostics.push({ from: arrayAccessor.from, to, severity: 'error', message: `Unexpected array access on <code>${types.join('|')}</code>` });
|
|
368
|
+
}
|
|
369
|
+
break;
|
|
370
|
+
}
|
|
303
371
|
case Variable:
|
|
304
372
|
case Function: {
|
|
305
373
|
identifier = state.sliceDoc(from, node.node.firstChild ? node.node.firstChild.from - 1 : to);
|
|
@@ -340,7 +408,7 @@ const expressionLanguageLinterSource = (state) => {
|
|
|
340
408
|
break;
|
|
341
409
|
}
|
|
342
410
|
}
|
|
343
|
-
if (identifier && ((
|
|
411
|
+
if (identifier && ((_j = node.node.parent) === null || _j === void 0 ? void 0 : _j.type.isError)) {
|
|
344
412
|
diagnostics.push({ from, to, severity: 'error', message: `Unexpected identifier <code>${identifier}</code>` });
|
|
345
413
|
}
|
|
346
414
|
});
|
|
@@ -436,7 +504,7 @@ function expressionLanguageCompletion(context) {
|
|
|
436
504
|
const { state, pos, explicit } = context;
|
|
437
505
|
const tree = language.syntaxTree(state);
|
|
438
506
|
const lastChar = state.sliceDoc(pos - 1, pos);
|
|
439
|
-
const prevNode = tree.resolveInner(pos, lastChar === ')' ? 0 : -1);
|
|
507
|
+
const prevNode = tree.resolveInner(pos, (lastChar === ')' || lastChar === ']') ? 0 : -1);
|
|
440
508
|
const config = getExpressionLanguageConfig(state);
|
|
441
509
|
const isIdentifier = (node) => (node === null || node === void 0 ? void 0 : node.type.is(Variable)) || (node === null || node === void 0 ? void 0 : node.type.is(Function));
|
|
442
510
|
const isMember = (node) => (node === null || node === void 0 ? void 0 : node.type.is(Property)) || (node === null || node === void 0 ? void 0 : node.type.is(Method));
|
package/dist/index.js
CHANGED
|
@@ -12,25 +12,25 @@ const t = {
|
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
15
|
-
const spec_word = {__proto__:null,true:
|
|
16
|
-
const spec_Operator = {__proto__:null,"?":
|
|
15
|
+
const spec_word = {__proto__:null,true:92, TRUE:94, false:96, FALSE:98, null:100, NULL:102, starts:114, with:116, ends:118, contains:120, matches:122, not:124, in:126, and:128, or:130, xor:132};
|
|
16
|
+
const spec_Operator = {__proto__:null,"?":113, "!":135, "~":137, "+":139, "-":141};
|
|
17
17
|
const parser = /*@__PURE__*/LRParser.deserialize({
|
|
18
18
|
version: 14,
|
|
19
|
-
states: ")YOYQPOOP!aOPOOQ!
|
|
20
|
-
stateData: ",
|
|
21
|
-
goto: "%
|
|
22
|
-
nodeNames: "⚠ BlockComment Expression PropertyAccess MemberOf NullSafeMemberOf Property ArrayAccess Call Function Arguments MethodAccess Method Number String Boolean Null Object Array Variable TernaryExpression Operator BinaryExpression OperatorKeyword UnaryExpression UnaryOperator Application",
|
|
23
|
-
maxTerm:
|
|
19
|
+
states: ")YOYQPOOP!aOPOOQ!fQQOOO#gQQO'#CgO$}QPO'#CoO%UQPO'#CpOYQPO'#CvOYQPO'#CxOOQO'#DT'#DTO%]QPO'#CfOOQO'#Cm'#CmOOQO'#Cn'#CnOOQO'#Cw'#CwP%bOSO'#C]POOO)C>s)C>sO%mQPO,58yOYQPO,58}OYQPO,59`OYQPO,59^O%rQPO'#CuOOQO'#Cu'#CuO%wQPO'#CuO'RQQO,59ZOOQO,59Z,59ZO'YQQO'#DYO'gQPO,59[O'lQQO,59bO(SQQO,59dO(ZQPO'#ChOOQO,59Q,59QPOOO'#Cy'#CyP(bOSO,58wPOOO,58w,58wO(mQQO'#CbOOQO1G.e1G.eOOQO1G.o1G.oO*TQQO1G.iO*[QQO1G.zO*rQQO1G.xOOQO,59a,59aOYQPO1G.uOYQPO'#CzO*yQPO,59tOOQO1G.v1G.vOOQO1G/O1G/OO+UQPO,59SPOOO-E6w-E6wPOOO1G.c1G.cOOQO7+$T7+$TOYQPO7+$dO+ZQQO7+$aO+eQQO,59fOOQO-E6x-E6xOOQO1G.n1G.nO+rQQO<<HOOYQPO'#C{O,YQPO<<G{OOQO<<G{<<G{O,bQQO,59gOOQO-E6y-E6yOOQOAN=gAN=gOYQPO1G/RO,iQQO7+$m",
|
|
20
|
+
stateData: ",{~OrOSsPQ~O_WO`WOxRO{VO!OYO!PYO!QYO!RYO!SZO!TZO!VSO!XTO!`[O!e[O!f[O!g[O!h[O~Os]O~OS_OT_OW`OX`OgaO!YbO!ZcO!]cO!^dO!_dO!`eO!adO!bdO!cdO!ddO~OSeXTeXWeXXeXgeXpeX{ZX!YeX!ZeX!]eX!^eX!_eX!`eX!aeX!beX!ceX!deX!WeXyeX}eXzeX!UeX~O!UgO~PYOy|P~PYO{lO~OtnOunOvpO~OxqO~O![wO~O!awO_iX`iXxiX{iX!OiX!PiX!QiX!RiX!SiX!TiX!ViX!XiX!`iX!eiX!fiX!giX!hiX~O!WxO~P!fO}yOy|Xz|X~P!fOy{O~Opja!Wjayja}jazja!Uja~P!fOz|O~P!fOz|P~PYOtnOunOv!PO~OSUXTUXWUXXUXgUXpUX{^X!YUX!ZUX!]UX!^UX!_UX!`UX!aUX!bUX!cUX!dUX!WUXyUX}UXzUX!UUX~Oy!QO~P!fOphi!Whiyhi}hizhi!Uhi~P!fO!W!RO~P!fO}yOy|az|a~Oz!VO~O}!XO!U!ZO~P!fOyna}nazna~P!fOpfy!Wfyyfy}fyzfy!Ufy~P!fO}!XO!U!^O~O!W!_O~P!fO}oq!Uoq~P!fO`TgS_xS~",
|
|
21
|
+
goto: "%P}P!OP!RPP!c!RPP!R!f!v!f!yPP!R!R!R!R!R!RP!R!|!R#]!R#m#s#yPPPPPPP$PPPPP$yR^PmWOSTUV`ablxy!R!X!_Rr_mXOSTUV`ablxy!R!X!_RmXRs_kaQfhjktuv!S!T!W![!`mUOSTUV`ablxy!R!X!_Qo]R!OoQzhR!UzQ!Y!SR!]!YQQOQfSShTlQjUQkVQt`QuaQvbQ!SxQ!TyQ!W!RQ![!XR!`!_QiTR}l",
|
|
22
|
+
nodeNames: "⚠ BlockComment Expression PropertyAccess MemberOf NullSafeMemberOf Property ArrayAccess ArrayAccessor NullSafeArrayAccessor Call Function Arguments MethodAccess Method Number String Boolean Null Object Array Variable TernaryExpression Operator BinaryExpression OperatorKeyword UnaryExpression UnaryOperator Application",
|
|
23
|
+
maxTerm: 70,
|
|
24
24
|
nodeProps: [
|
|
25
|
-
[t,
|
|
25
|
+
[t, 15,"number",16,"string",17,"bool",18,"null",19,"object",20,"array"]
|
|
26
26
|
],
|
|
27
|
-
skippedNodes: [0,1,
|
|
27
|
+
skippedNodes: [0,1,29],
|
|
28
28
|
repeatNodeCount: 3,
|
|
29
|
-
tokenData: "-
|
|
30
|
-
tokenizers: [1, /*@__PURE__*/new LocalTokenGroup("j~RQYZXz{^~^
|
|
29
|
+
tokenData: "-k~RqXY#YYZ#Y]^#Ypq#Yqr#krs$Quv#{vw%zwx&Sxy'wyz'|z{(R{|#{|}(Z}!O#{!O!P(`!P!Q(h!Q![(u![!]+[!^!_+a!_!`+l!`!a+r!a!b+}!c!},j!}#O,{#P#Q-S#Q#R#{#R#S,j#T#o,j#o#p-X#p#q-^#q#r-f#r#s#{~#_Sr~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~'|O{~~(ROz~~(WPg~z{#{~(`O}~~(ePS~!O!P#{~(mPg~z{(p~(uOs~~(zT_~!O!P)Z!Q![(u!g!h*Z#R#S+U#X#Y*Z~)^SO!O)j!P;'S)j;'S;=`+O<%lO)j~)oR_~!Q![)x!g!h*Z#X#Y*Z~)}S_~!Q![)x!g!h*Z#R#S*x#X#Y*Z~*^R{|*g}!O*g!Q![*m~*jP!Q![*m~*rQ_~!Q![*m#R#S*g~*{P!Q![)x~+RP;=`<%l)j~+XP!Q![(u~+aO!W~~+fQg~!^!_#{!_!`#{~+oP!_!`#s~+wQg~!_!`#{!`!a#{~,SRg~!O!P,]![!]#{!a!b#{~,bPT~!}#O,e~,jOX~~,oSx~!Q![,j!c!},j#R#S,j#T#o,jU-SO!XQWS~-XOy~~-^O!V~~-cPg~#p#q#{~-kO!U~",
|
|
30
|
+
tokenizers: [1, 2, /*@__PURE__*/new LocalTokenGroup("j~RQYZXz{^~^Ou~~aP!P!Qd~iOv~~", 25, 36)],
|
|
31
31
|
topRules: {"Expression":[0,2]},
|
|
32
|
-
specialized: [{term:
|
|
33
|
-
tokenPrec:
|
|
32
|
+
specialized: [{term: 40, get: (value) => spec_word[value] || -1},{term: 23, get: (value) => spec_Operator[value] || -1}],
|
|
33
|
+
tokenPrec: 541
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
// generate CONFIGURATION.md from this file by running "tsdoc --src=src/types.ts --dest=CONFIGURATION.md --noemoji --types"
|
|
@@ -53,21 +53,23 @@ return ELScalar})(ELScalar || (ELScalar = {}));
|
|
|
53
53
|
const BlockComment = 1,
|
|
54
54
|
Expression = 2,
|
|
55
55
|
PropertyAccess = 3,
|
|
56
|
+
NullSafeMemberOf = 5,
|
|
56
57
|
Property = 6,
|
|
57
58
|
ArrayAccess = 7,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
59
|
+
NullSafeArrayAccessor = 9,
|
|
60
|
+
Call = 10,
|
|
61
|
+
Function = 11,
|
|
62
|
+
Arguments = 12,
|
|
63
|
+
MethodAccess = 13,
|
|
64
|
+
Method = 14,
|
|
65
|
+
String = 16,
|
|
66
|
+
Array$1 = 20,
|
|
67
|
+
Variable = 21,
|
|
68
|
+
TernaryExpression = 22,
|
|
69
|
+
BinaryExpression = 24,
|
|
70
|
+
OperatorKeyword = 25,
|
|
71
|
+
UnaryExpression = 26,
|
|
72
|
+
Application = 28;
|
|
71
73
|
|
|
72
74
|
const createInfoElement = (html) => {
|
|
73
75
|
const dom = document.createElement("div");
|
|
@@ -91,7 +93,7 @@ function resolveFunctionDefinition(node, state, config) {
|
|
|
91
93
|
let identifier;
|
|
92
94
|
if ((node.type.is(PropertyAccess) || node.type.is(MethodAccess)) && node.lastChild) {
|
|
93
95
|
const leftArgument = (_a = node.firstChild) === null || _a === void 0 ? void 0 : _a.node;
|
|
94
|
-
const types = Array.from(resolveTypes(state, leftArgument, config));
|
|
96
|
+
const types = window.Array.from(resolveTypes(state, leftArgument, config));
|
|
95
97
|
identifier = state.sliceDoc(node.lastChild.from, node.lastChild.to);
|
|
96
98
|
return types.map(type => { var _a; return resolveCallable(identifier, (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]); }).find(x => x);
|
|
97
99
|
}
|
|
@@ -120,7 +122,29 @@ function resolveTypes(state, node, config) {
|
|
|
120
122
|
}
|
|
121
123
|
let type;
|
|
122
124
|
if (typeof (type = node.type.prop(t)) !== "undefined") {
|
|
123
|
-
|
|
125
|
+
if (type === ELScalar.Array) {
|
|
126
|
+
// For array literals, infer element types from array contents
|
|
127
|
+
const elementTypes = new Set();
|
|
128
|
+
for (let child = node.firstChild; child; child = child.nextSibling) {
|
|
129
|
+
if (!child.type.isError) {
|
|
130
|
+
resolveTypes(state, child, config).forEach(elementType => {
|
|
131
|
+
elementTypes.add(elementType);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (elementTypes.size > 0) {
|
|
136
|
+
// Build typed array notation (e.g., "string[]")
|
|
137
|
+
elementTypes.forEach(elementType => {
|
|
138
|
+
types.add(`${elementType}[]`);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
types.add(type);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
types.add(type);
|
|
147
|
+
}
|
|
124
148
|
}
|
|
125
149
|
else if (node.type.is(Call) && node.firstChild && node.lastChild) {
|
|
126
150
|
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
@@ -142,6 +166,9 @@ function resolveTypes(state, node, config) {
|
|
|
142
166
|
// @ts-expect-error TS2339
|
|
143
167
|
(_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.type.id, 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));
|
|
144
168
|
});
|
|
169
|
+
if (node.getChild(NullSafeMemberOf)) {
|
|
170
|
+
types.add(ELScalar.Null);
|
|
171
|
+
}
|
|
145
172
|
}
|
|
146
173
|
else if (node.type.is(MethodAccess) && node.firstChild && ((_g = node.lastChild) === null || _g === void 0 ? void 0 : _g.type.is(Method))) {
|
|
147
174
|
const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
|
|
@@ -150,6 +177,9 @@ function resolveTypes(state, node, config) {
|
|
|
150
177
|
// @ts-expect-error TS2339
|
|
151
178
|
(_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.type.id, 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));
|
|
152
179
|
});
|
|
180
|
+
if (node.getChild(NullSafeMemberOf)) {
|
|
181
|
+
types.add(ELScalar.Null);
|
|
182
|
+
}
|
|
153
183
|
}
|
|
154
184
|
// Array indexing: for typed arrays (e.g. Foo[]) return element type, for generic arrays return any
|
|
155
185
|
else if (node.type.is(ArrayAccess) && node.firstChild) {
|
|
@@ -162,6 +192,9 @@ function resolveTypes(state, node, config) {
|
|
|
162
192
|
types.add(ELScalar.Any);
|
|
163
193
|
}
|
|
164
194
|
});
|
|
195
|
+
if (node.getChild(NullSafeArrayAccessor)) {
|
|
196
|
+
types.add(ELScalar.Null);
|
|
197
|
+
}
|
|
165
198
|
}
|
|
166
199
|
else if (node.type.is(Application) && node.firstChild) {
|
|
167
200
|
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
@@ -233,7 +266,7 @@ const expressionLanguageLinterSource = (state) => {
|
|
|
233
266
|
const config = getExpressionLanguageConfig(state);
|
|
234
267
|
const diagnostics = [];
|
|
235
268
|
syntaxTree(state).cursor().iterate(node => {
|
|
236
|
-
var _a, _b, _c, _d, _e, _f;
|
|
269
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
237
270
|
const { from, to, type: { id } } = node;
|
|
238
271
|
let identifier;
|
|
239
272
|
switch (id) {
|
|
@@ -289,7 +322,19 @@ const expressionLanguageLinterSource = (state) => {
|
|
|
289
322
|
}
|
|
290
323
|
case Property:
|
|
291
324
|
case Method: {
|
|
292
|
-
const
|
|
325
|
+
const parent = node.node.parent;
|
|
326
|
+
const isPropertyAccess = parent === null || parent === void 0 ? void 0 : parent.type.is(PropertyAccess);
|
|
327
|
+
const isMethodAccess = parent === null || parent === void 0 ? void 0 : parent.type.is(MethodAccess);
|
|
328
|
+
// Skip validation if this is part of a PropertyAccess/MethodAccess on array type
|
|
329
|
+
// (the PropertyAccess/MethodAccess case will handle the error)
|
|
330
|
+
if ((isPropertyAccess || isMethodAccess) && (parent === null || parent === void 0 ? void 0 : parent.firstChild)) {
|
|
331
|
+
const types = Array.from(resolveTypes(state, parent.firstChild.node, config));
|
|
332
|
+
const hasArrayType = types.includes(ELScalar.Array) || types.some(x => x.endsWith('[]'));
|
|
333
|
+
if (hasArrayType && !types.includes(ELScalar.Any)) {
|
|
334
|
+
break; // Skip property validation, error will be reported by PropertyAccess/MethodAccess case
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const leftArgument = (_d = parent === null || parent === void 0 ? void 0 : parent.firstChild) === null || _d === void 0 ? void 0 : _d.node;
|
|
293
338
|
const types = Array.from(resolveTypes(state, leftArgument, config));
|
|
294
339
|
identifier = state.sliceDoc(from, to);
|
|
295
340
|
if (!types.find(type => { var _a; return resolveIdentifier(id, identifier, (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]); })) {
|
|
@@ -297,6 +342,29 @@ const expressionLanguageLinterSource = (state) => {
|
|
|
297
342
|
}
|
|
298
343
|
break;
|
|
299
344
|
}
|
|
345
|
+
case PropertyAccess:
|
|
346
|
+
case MethodAccess: {
|
|
347
|
+
const leftArgument = (_e = node.node.firstChild) === null || _e === void 0 ? void 0 : _e.node;
|
|
348
|
+
const types = Array.from(resolveTypes(state, leftArgument, config));
|
|
349
|
+
const hasArrayType = types.includes(ELScalar.Array) || types.some(x => x.endsWith('[]'));
|
|
350
|
+
if (hasArrayType && !types.includes(ELScalar.Any)) {
|
|
351
|
+
const propertyOrMethod = node.node.lastChild;
|
|
352
|
+
const errorFrom = (_f = propertyOrMethod === null || propertyOrMethod === void 0 ? void 0 : propertyOrMethod.from) !== null && _f !== void 0 ? _f : from;
|
|
353
|
+
const errorTo = (_g = propertyOrMethod === null || propertyOrMethod === void 0 ? void 0 : propertyOrMethod.to) !== null && _g !== void 0 ? _g : to;
|
|
354
|
+
diagnostics.push({ from: errorFrom, to: errorTo, severity: 'error', message: `Unexpected object access on <code>${types.join('|')}</code>` });
|
|
355
|
+
}
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
case ArrayAccess: {
|
|
359
|
+
const leftArgument = (_h = node.node.firstChild) === null || _h === void 0 ? void 0 : _h.node;
|
|
360
|
+
const arrayAccessor = leftArgument.nextSibling;
|
|
361
|
+
const types = Array.from(resolveTypes(state, leftArgument, config));
|
|
362
|
+
const allowsAny = types.includes(ELScalar.Array) || types.includes(ELScalar.Any);
|
|
363
|
+
if (!allowsAny && ![...types].some(x => x.endsWith('[]'))) {
|
|
364
|
+
diagnostics.push({ from: arrayAccessor.from, to, severity: 'error', message: `Unexpected array access on <code>${types.join('|')}</code>` });
|
|
365
|
+
}
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
300
368
|
case Variable:
|
|
301
369
|
case Function: {
|
|
302
370
|
identifier = state.sliceDoc(from, node.node.firstChild ? node.node.firstChild.from - 1 : to);
|
|
@@ -337,7 +405,7 @@ const expressionLanguageLinterSource = (state) => {
|
|
|
337
405
|
break;
|
|
338
406
|
}
|
|
339
407
|
}
|
|
340
|
-
if (identifier && ((
|
|
408
|
+
if (identifier && ((_j = node.node.parent) === null || _j === void 0 ? void 0 : _j.type.isError)) {
|
|
341
409
|
diagnostics.push({ from, to, severity: 'error', message: `Unexpected identifier <code>${identifier}</code>` });
|
|
342
410
|
}
|
|
343
411
|
});
|
|
@@ -433,7 +501,7 @@ function expressionLanguageCompletion(context) {
|
|
|
433
501
|
const { state, pos, explicit } = context;
|
|
434
502
|
const tree = syntaxTree(state);
|
|
435
503
|
const lastChar = state.sliceDoc(pos - 1, pos);
|
|
436
|
-
const prevNode = tree.resolveInner(pos, lastChar === ')' ? 0 : -1);
|
|
504
|
+
const prevNode = tree.resolveInner(pos, (lastChar === ')' || lastChar === ']') ? 0 : -1);
|
|
437
505
|
const config = getExpressionLanguageConfig(state);
|
|
438
506
|
const isIdentifier = (node) => (node === null || node === void 0 ? void 0 : node.type.is(Variable)) || (node === null || node === void 0 ? void 0 : node.type.is(Function));
|
|
439
507
|
const isMember = (node) => (node === null || node === void 0 ? void 0 : node.type.is(Property)) || (node === null || node === void 0 ? void 0 : node.type.is(Method));
|
package/package.json
CHANGED