@seljs/checker 1.0.0 → 1.0.1
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/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/checker/checker.cjs +482 -0
- package/dist/checker/checker.d.cts +176 -0
- package/dist/checker/checker.d.mts +176 -0
- package/dist/checker/checker.mjs +481 -0
- package/dist/checker/diagnostics.cjs +66 -0
- package/dist/checker/diagnostics.mjs +66 -0
- package/dist/checker/index.cjs +2 -0
- package/dist/checker/index.d.mts +2 -0
- package/dist/checker/index.mjs +3 -0
- package/dist/checker/type-compatibility.cjs +70 -0
- package/dist/checker/type-compatibility.d.cts +8 -0
- package/dist/checker/type-compatibility.d.mts +8 -0
- package/dist/checker/type-compatibility.mjs +69 -0
- package/dist/constants.cjs +14 -0
- package/dist/constants.d.cts +7 -0
- package/dist/constants.d.mts +7 -0
- package/dist/constants.mjs +13 -0
- package/dist/debug.cjs +7 -0
- package/dist/debug.mjs +5 -0
- package/dist/environment/codec-registry.cjs +109 -0
- package/dist/environment/codec-registry.d.cts +45 -0
- package/dist/environment/codec-registry.d.mts +45 -0
- package/dist/environment/codec-registry.mjs +108 -0
- package/dist/environment/hydrate.cjs +163 -0
- package/dist/environment/hydrate.d.cts +52 -0
- package/dist/environment/hydrate.d.mts +52 -0
- package/dist/environment/hydrate.mjs +160 -0
- package/dist/environment/index.cjs +4 -0
- package/dist/environment/index.d.mts +4 -0
- package/dist/environment/index.mjs +5 -0
- package/dist/environment/register-types.cjs +107 -0
- package/dist/environment/register-types.d.cts +15 -0
- package/dist/environment/register-types.d.mts +15 -0
- package/dist/environment/register-types.mjs +106 -0
- package/dist/environment/value-wrappers.cjs +44 -0
- package/dist/environment/value-wrappers.d.cts +20 -0
- package/dist/environment/value-wrappers.d.mts +20 -0
- package/dist/environment/value-wrappers.mjs +41 -0
- package/dist/index.cjs +27 -0
- package/dist/index.d.cts +11 -0
- package/dist/index.d.mts +11 -0
- package/dist/index.mjs +13 -0
- package/dist/rules/defaults/deferred-call.cjs +107 -0
- package/dist/rules/defaults/deferred-call.mjs +106 -0
- package/dist/rules/defaults/index.cjs +6 -0
- package/dist/rules/defaults/index.mjs +7 -0
- package/dist/rules/defaults/no-constant-condition.cjs +31 -0
- package/dist/rules/defaults/no-constant-condition.mjs +31 -0
- package/dist/rules/defaults/no-mixed-operators.cjs +39 -0
- package/dist/rules/defaults/no-mixed-operators.mjs +39 -0
- package/dist/rules/defaults/no-redundant-bool.cjs +26 -0
- package/dist/rules/defaults/no-redundant-bool.mjs +26 -0
- package/dist/rules/defaults/no-self-comparison.cjs +44 -0
- package/dist/rules/defaults/no-self-comparison.mjs +43 -0
- package/dist/rules/defaults/require-type.cjs +18 -0
- package/dist/rules/defaults/require-type.mjs +18 -0
- package/dist/rules/facade.cjs +31 -0
- package/dist/rules/facade.d.cts +20 -0
- package/dist/rules/facade.d.mts +20 -0
- package/dist/rules/facade.mjs +31 -0
- package/dist/rules/index.cjs +2 -0
- package/dist/rules/index.d.mts +3 -0
- package/dist/rules/index.mjs +3 -0
- package/dist/rules/runner.cjs +40 -0
- package/dist/rules/runner.d.cts +27 -0
- package/dist/rules/runner.d.mts +27 -0
- package/dist/rules/runner.mjs +40 -0
- package/dist/rules/types.d.cts +77 -0
- package/dist/rules/types.d.mts +77 -0
- package/dist/utils/ast-utils.cjs +164 -0
- package/dist/utils/ast-utils.mjs +162 -0
- package/package.json +24 -17
- package/dist/checker/checker.d.ts +0 -173
- package/dist/checker/checker.js +0 -567
- package/dist/checker/diagnostics.d.ts +0 -10
- package/dist/checker/diagnostics.js +0 -80
- package/dist/checker/index.d.ts +0 -2
- package/dist/checker/index.js +0 -2
- package/dist/checker/type-compatibility.d.ts +0 -16
- package/dist/checker/type-compatibility.js +0 -59
- package/dist/constants.d.ts +0 -4
- package/dist/constants.js +0 -10
- package/dist/debug.d.ts +0 -2
- package/dist/debug.js +0 -2
- package/dist/environment/codec-registry.d.ts +0 -42
- package/dist/environment/codec-registry.js +0 -146
- package/dist/environment/hydrate.d.ts +0 -48
- package/dist/environment/hydrate.js +0 -198
- package/dist/environment/index.d.ts +0 -4
- package/dist/environment/index.js +0 -4
- package/dist/environment/register-types.d.ts +0 -14
- package/dist/environment/register-types.js +0 -154
- package/dist/environment/value-wrappers.d.ts +0 -17
- package/dist/environment/value-wrappers.js +0 -65
- package/dist/index.d.ts +0 -4
- package/dist/index.js +0 -4
- package/dist/rules/defaults/deferred-call.d.ts +0 -13
- package/dist/rules/defaults/deferred-call.js +0 -162
- package/dist/rules/defaults/index.d.ts +0 -6
- package/dist/rules/defaults/index.js +0 -6
- package/dist/rules/defaults/no-constant-condition.d.ts +0 -7
- package/dist/rules/defaults/no-constant-condition.js +0 -36
- package/dist/rules/defaults/no-mixed-operators.d.ts +0 -9
- package/dist/rules/defaults/no-mixed-operators.js +0 -44
- package/dist/rules/defaults/no-redundant-bool.d.ts +0 -5
- package/dist/rules/defaults/no-redundant-bool.js +0 -27
- package/dist/rules/defaults/no-self-comparison.d.ts +0 -9
- package/dist/rules/defaults/no-self-comparison.js +0 -31
- package/dist/rules/defaults/require-type.d.ts +0 -7
- package/dist/rules/defaults/require-type.js +0 -19
- package/dist/rules/facade.d.ts +0 -22
- package/dist/rules/facade.js +0 -29
- package/dist/rules/index.d.ts +0 -3
- package/dist/rules/index.js +0 -3
- package/dist/rules/runner.d.ts +0 -16
- package/dist/rules/runner.js +0 -30
- package/dist/rules/types.d.ts +0 -73
- package/dist/rules/types.js +0 -1
- package/dist/utils/ast-utils.d.ts +0 -55
- package/dist/utils/ast-utils.js +0 -255
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -1
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
//#region src/utils/ast-utils.ts
|
|
2
|
+
const BINARY_OPS = new Set([
|
|
3
|
+
"==",
|
|
4
|
+
"!=",
|
|
5
|
+
"<",
|
|
6
|
+
"<=",
|
|
7
|
+
">",
|
|
8
|
+
">=",
|
|
9
|
+
"+",
|
|
10
|
+
"-",
|
|
11
|
+
"*",
|
|
12
|
+
"/",
|
|
13
|
+
"%",
|
|
14
|
+
"in",
|
|
15
|
+
"||",
|
|
16
|
+
"&&",
|
|
17
|
+
"[]",
|
|
18
|
+
"[?]"
|
|
19
|
+
]);
|
|
20
|
+
/**
|
|
21
|
+
* Compute the source span {from, to} of an AST node.
|
|
22
|
+
*
|
|
23
|
+
* Uses the AST structure and `node.input` (original source) to calculate
|
|
24
|
+
* positions. Does NOT use `serialize()` which normalizes whitespace,
|
|
25
|
+
* quotes, and parentheses.
|
|
26
|
+
*
|
|
27
|
+
* Note: for binary operators, `node.pos` points to the operator token,
|
|
28
|
+
* not the start of the expression. We compute `from` by finding the
|
|
29
|
+
* leftmost descendant leaf position instead.
|
|
30
|
+
*/
|
|
31
|
+
const nodeSpan = (node) => {
|
|
32
|
+
const src = node.input;
|
|
33
|
+
if (node.op === "id") return {
|
|
34
|
+
from: node.pos,
|
|
35
|
+
to: node.pos + node.args.length
|
|
36
|
+
};
|
|
37
|
+
if (node.op === "value") return valueSpan(src, node.pos);
|
|
38
|
+
const children = collectChildren(node);
|
|
39
|
+
let minFrom = node.pos;
|
|
40
|
+
let maxTo = node.pos;
|
|
41
|
+
for (const child of children) {
|
|
42
|
+
const s = nodeSpan(child);
|
|
43
|
+
if (s.from < minFrom) minFrom = s.from;
|
|
44
|
+
if (s.to > maxTo) maxTo = s.to;
|
|
45
|
+
}
|
|
46
|
+
if (node.op === "!_" || node.op === "-_") minFrom = node.pos;
|
|
47
|
+
if (node.op === "." || node.op === ".?") {
|
|
48
|
+
const fieldName = node.args[1];
|
|
49
|
+
let i = maxTo;
|
|
50
|
+
while (i < src.length && src[i] !== ".") i++;
|
|
51
|
+
i++;
|
|
52
|
+
if (node.op === ".?" && i < src.length && src[i] === "?") i++;
|
|
53
|
+
i += fieldName.length;
|
|
54
|
+
return {
|
|
55
|
+
from: minFrom,
|
|
56
|
+
to: Math.min(i, src.length)
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (node.op === "call" || node.op === "rcall") return {
|
|
60
|
+
from: minFrom,
|
|
61
|
+
to: scanTo(src, maxTo, ")")
|
|
62
|
+
};
|
|
63
|
+
if (node.op === "list" || node.op === "[]" || node.op === "[?]") return {
|
|
64
|
+
from: minFrom,
|
|
65
|
+
to: scanTo(src, maxTo, "]")
|
|
66
|
+
};
|
|
67
|
+
if (node.op === "map") return {
|
|
68
|
+
from: minFrom,
|
|
69
|
+
to: scanTo(src, maxTo, "}")
|
|
70
|
+
};
|
|
71
|
+
return {
|
|
72
|
+
from: minFrom,
|
|
73
|
+
to: maxTo
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Depth-first walk of the AST, calling visitor on every node.
|
|
78
|
+
*/
|
|
79
|
+
const walkAST = (node, visitor, parent = null) => {
|
|
80
|
+
visitor(node, parent);
|
|
81
|
+
for (const child of collectChildren(node)) walkAST(child, visitor, node);
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Collect all ASTNode children of a node, regardless of op shape.
|
|
85
|
+
*/
|
|
86
|
+
const collectChildren = (node) => {
|
|
87
|
+
if (node.op === "value" || node.op === "id") return [];
|
|
88
|
+
if (node.op === "!_" || node.op === "-_") return [node.args];
|
|
89
|
+
if (BINARY_OPS.has(node.op)) {
|
|
90
|
+
const [left, right] = node.args;
|
|
91
|
+
return [left, right];
|
|
92
|
+
}
|
|
93
|
+
switch (node.op) {
|
|
94
|
+
case ".":
|
|
95
|
+
case ".?": {
|
|
96
|
+
const [receiver] = node.args;
|
|
97
|
+
return [receiver];
|
|
98
|
+
}
|
|
99
|
+
case "call": {
|
|
100
|
+
const [, callArgs] = node.args;
|
|
101
|
+
return callArgs;
|
|
102
|
+
}
|
|
103
|
+
case "rcall": {
|
|
104
|
+
const [, receiver, callArgs] = node.args;
|
|
105
|
+
return [receiver, ...callArgs];
|
|
106
|
+
}
|
|
107
|
+
case "list": return node.args;
|
|
108
|
+
case "map": return node.args.flat();
|
|
109
|
+
case "?:": {
|
|
110
|
+
const [cond, then, els] = node.args;
|
|
111
|
+
return [
|
|
112
|
+
cond,
|
|
113
|
+
then,
|
|
114
|
+
els
|
|
115
|
+
];
|
|
116
|
+
}
|
|
117
|
+
default: return [];
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
const valueSpan = (src, from) => {
|
|
121
|
+
const ch = src[from];
|
|
122
|
+
if (ch === "\"" || ch === "'") {
|
|
123
|
+
let i = from + 1;
|
|
124
|
+
while (i < src.length && src[i] !== ch) {
|
|
125
|
+
if (src[i] === "\\") i++;
|
|
126
|
+
i++;
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
from,
|
|
130
|
+
to: i < src.length ? i + 1 : i
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
let i = from;
|
|
134
|
+
while (i < src.length && /[\w.]/.test(src[i] ?? "")) i++;
|
|
135
|
+
return {
|
|
136
|
+
from,
|
|
137
|
+
to: i
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
const scanTo = (src, from, ch) => {
|
|
141
|
+
let i = from;
|
|
142
|
+
while (i < src.length && src[i] !== ch) i++;
|
|
143
|
+
return i < src.length ? i + 1 : from;
|
|
144
|
+
};
|
|
145
|
+
const findNodeWithParentAt = (root, offset, parent = null) => {
|
|
146
|
+
const rootSpan = nodeSpan(root);
|
|
147
|
+
if (offset < rootSpan.from || offset >= rootSpan.to) return;
|
|
148
|
+
const children = collectChildren(root);
|
|
149
|
+
for (const child of children) {
|
|
150
|
+
const childSpan = nodeSpan(child);
|
|
151
|
+
if (offset >= childSpan.from && offset < childSpan.to) return findNodeWithParentAt(child, offset, root) ?? {
|
|
152
|
+
node: child,
|
|
153
|
+
parent: root
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
node: root,
|
|
158
|
+
parent
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
//#endregion
|
|
162
|
+
exports.findNodeWithParentAt = findNodeWithParentAt;
|
|
163
|
+
exports.nodeSpan = nodeSpan;
|
|
164
|
+
exports.walkAST = walkAST;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
//#region src/utils/ast-utils.ts
|
|
2
|
+
const BINARY_OPS = new Set([
|
|
3
|
+
"==",
|
|
4
|
+
"!=",
|
|
5
|
+
"<",
|
|
6
|
+
"<=",
|
|
7
|
+
">",
|
|
8
|
+
">=",
|
|
9
|
+
"+",
|
|
10
|
+
"-",
|
|
11
|
+
"*",
|
|
12
|
+
"/",
|
|
13
|
+
"%",
|
|
14
|
+
"in",
|
|
15
|
+
"||",
|
|
16
|
+
"&&",
|
|
17
|
+
"[]",
|
|
18
|
+
"[?]"
|
|
19
|
+
]);
|
|
20
|
+
/**
|
|
21
|
+
* Compute the source span {from, to} of an AST node.
|
|
22
|
+
*
|
|
23
|
+
* Uses the AST structure and `node.input` (original source) to calculate
|
|
24
|
+
* positions. Does NOT use `serialize()` which normalizes whitespace,
|
|
25
|
+
* quotes, and parentheses.
|
|
26
|
+
*
|
|
27
|
+
* Note: for binary operators, `node.pos` points to the operator token,
|
|
28
|
+
* not the start of the expression. We compute `from` by finding the
|
|
29
|
+
* leftmost descendant leaf position instead.
|
|
30
|
+
*/
|
|
31
|
+
const nodeSpan = (node) => {
|
|
32
|
+
const src = node.input;
|
|
33
|
+
if (node.op === "id") return {
|
|
34
|
+
from: node.pos,
|
|
35
|
+
to: node.pos + node.args.length
|
|
36
|
+
};
|
|
37
|
+
if (node.op === "value") return valueSpan(src, node.pos);
|
|
38
|
+
const children = collectChildren(node);
|
|
39
|
+
let minFrom = node.pos;
|
|
40
|
+
let maxTo = node.pos;
|
|
41
|
+
for (const child of children) {
|
|
42
|
+
const s = nodeSpan(child);
|
|
43
|
+
if (s.from < minFrom) minFrom = s.from;
|
|
44
|
+
if (s.to > maxTo) maxTo = s.to;
|
|
45
|
+
}
|
|
46
|
+
if (node.op === "!_" || node.op === "-_") minFrom = node.pos;
|
|
47
|
+
if (node.op === "." || node.op === ".?") {
|
|
48
|
+
const fieldName = node.args[1];
|
|
49
|
+
let i = maxTo;
|
|
50
|
+
while (i < src.length && src[i] !== ".") i++;
|
|
51
|
+
i++;
|
|
52
|
+
if (node.op === ".?" && i < src.length && src[i] === "?") i++;
|
|
53
|
+
i += fieldName.length;
|
|
54
|
+
return {
|
|
55
|
+
from: minFrom,
|
|
56
|
+
to: Math.min(i, src.length)
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (node.op === "call" || node.op === "rcall") return {
|
|
60
|
+
from: minFrom,
|
|
61
|
+
to: scanTo(src, maxTo, ")")
|
|
62
|
+
};
|
|
63
|
+
if (node.op === "list" || node.op === "[]" || node.op === "[?]") return {
|
|
64
|
+
from: minFrom,
|
|
65
|
+
to: scanTo(src, maxTo, "]")
|
|
66
|
+
};
|
|
67
|
+
if (node.op === "map") return {
|
|
68
|
+
from: minFrom,
|
|
69
|
+
to: scanTo(src, maxTo, "}")
|
|
70
|
+
};
|
|
71
|
+
return {
|
|
72
|
+
from: minFrom,
|
|
73
|
+
to: maxTo
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Depth-first walk of the AST, calling visitor on every node.
|
|
78
|
+
*/
|
|
79
|
+
const walkAST = (node, visitor, parent = null) => {
|
|
80
|
+
visitor(node, parent);
|
|
81
|
+
for (const child of collectChildren(node)) walkAST(child, visitor, node);
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Collect all ASTNode children of a node, regardless of op shape.
|
|
85
|
+
*/
|
|
86
|
+
const collectChildren = (node) => {
|
|
87
|
+
if (node.op === "value" || node.op === "id") return [];
|
|
88
|
+
if (node.op === "!_" || node.op === "-_") return [node.args];
|
|
89
|
+
if (BINARY_OPS.has(node.op)) {
|
|
90
|
+
const [left, right] = node.args;
|
|
91
|
+
return [left, right];
|
|
92
|
+
}
|
|
93
|
+
switch (node.op) {
|
|
94
|
+
case ".":
|
|
95
|
+
case ".?": {
|
|
96
|
+
const [receiver] = node.args;
|
|
97
|
+
return [receiver];
|
|
98
|
+
}
|
|
99
|
+
case "call": {
|
|
100
|
+
const [, callArgs] = node.args;
|
|
101
|
+
return callArgs;
|
|
102
|
+
}
|
|
103
|
+
case "rcall": {
|
|
104
|
+
const [, receiver, callArgs] = node.args;
|
|
105
|
+
return [receiver, ...callArgs];
|
|
106
|
+
}
|
|
107
|
+
case "list": return node.args;
|
|
108
|
+
case "map": return node.args.flat();
|
|
109
|
+
case "?:": {
|
|
110
|
+
const [cond, then, els] = node.args;
|
|
111
|
+
return [
|
|
112
|
+
cond,
|
|
113
|
+
then,
|
|
114
|
+
els
|
|
115
|
+
];
|
|
116
|
+
}
|
|
117
|
+
default: return [];
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
const valueSpan = (src, from) => {
|
|
121
|
+
const ch = src[from];
|
|
122
|
+
if (ch === "\"" || ch === "'") {
|
|
123
|
+
let i = from + 1;
|
|
124
|
+
while (i < src.length && src[i] !== ch) {
|
|
125
|
+
if (src[i] === "\\") i++;
|
|
126
|
+
i++;
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
from,
|
|
130
|
+
to: i < src.length ? i + 1 : i
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
let i = from;
|
|
134
|
+
while (i < src.length && /[\w.]/.test(src[i] ?? "")) i++;
|
|
135
|
+
return {
|
|
136
|
+
from,
|
|
137
|
+
to: i
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
const scanTo = (src, from, ch) => {
|
|
141
|
+
let i = from;
|
|
142
|
+
while (i < src.length && src[i] !== ch) i++;
|
|
143
|
+
return i < src.length ? i + 1 : from;
|
|
144
|
+
};
|
|
145
|
+
const findNodeWithParentAt = (root, offset, parent = null) => {
|
|
146
|
+
const rootSpan = nodeSpan(root);
|
|
147
|
+
if (offset < rootSpan.from || offset >= rootSpan.to) return;
|
|
148
|
+
const children = collectChildren(root);
|
|
149
|
+
for (const child of children) {
|
|
150
|
+
const childSpan = nodeSpan(child);
|
|
151
|
+
if (offset >= childSpan.from && offset < childSpan.to) return findNodeWithParentAt(child, offset, root) ?? {
|
|
152
|
+
node: child,
|
|
153
|
+
parent: root
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
node: root,
|
|
158
|
+
parent
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
//#endregion
|
|
162
|
+
export { findNodeWithParentAt, nodeSpan, walkAST };
|
package/package.json
CHANGED
|
@@ -1,30 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seljs/checker",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"repository": {
|
|
5
|
+
"url": "https://github.com/abinnovision/seljs"
|
|
6
|
+
},
|
|
5
7
|
"license": "Apache-2.0",
|
|
6
8
|
"author": {
|
|
7
9
|
"name": "abi group GmbH",
|
|
8
10
|
"email": "info@abigroup.io",
|
|
9
11
|
"url": "https://abigroup.io/"
|
|
10
12
|
},
|
|
11
|
-
"
|
|
12
|
-
"url": "https://github.com/abinnovision/seljs"
|
|
13
|
-
},
|
|
13
|
+
"type": "module",
|
|
14
14
|
"exports": {
|
|
15
15
|
".": {
|
|
16
|
-
"import":
|
|
17
|
-
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./dist/index.d.mts",
|
|
18
|
+
"default": "./dist/index.mjs"
|
|
19
|
+
},
|
|
20
|
+
"require": {
|
|
21
|
+
"types": "./dist/index.d.cts",
|
|
22
|
+
"default": "./dist/index.cjs"
|
|
23
|
+
}
|
|
18
24
|
}
|
|
19
25
|
},
|
|
20
|
-
"main": "./dist/index.
|
|
21
|
-
"types": "./dist/index.d.
|
|
26
|
+
"main": "./dist/index.cjs",
|
|
27
|
+
"types": "./dist/index.d.cts",
|
|
22
28
|
"files": [
|
|
23
29
|
"dist",
|
|
24
30
|
"LICENSE.md"
|
|
25
31
|
],
|
|
26
32
|
"scripts": {
|
|
27
|
-
"build": "
|
|
33
|
+
"build": "tsdown",
|
|
28
34
|
"format:check": "prettier --check '{{src,test}/**/*,*}.{{t,j}s{,x},json{,5},md,y{,a}ml}'",
|
|
29
35
|
"format:fix": "prettier --write '{{src,test}/**/*,*}.{{t,j}s{,x},json{,5},md,y{,a}ml}'",
|
|
30
36
|
"lint:check": "eslint '{{src,test}/**/*,*}.{t,j}s{,x}'",
|
|
@@ -43,15 +49,12 @@
|
|
|
43
49
|
]
|
|
44
50
|
},
|
|
45
51
|
"dependencies": {
|
|
46
|
-
"@marcbachmann/cel-js": "^7.5.
|
|
47
|
-
"@seljs/common": "1.0.
|
|
48
|
-
"@seljs/schema": "1.0.
|
|
49
|
-
"@seljs/types": "1.0.
|
|
52
|
+
"@marcbachmann/cel-js": "^7.5.3",
|
|
53
|
+
"@seljs/common": "1.0.1",
|
|
54
|
+
"@seljs/schema": "1.0.1",
|
|
55
|
+
"@seljs/types": "1.0.1",
|
|
50
56
|
"debug": "^4.4.3"
|
|
51
57
|
},
|
|
52
|
-
"peerDependencies": {
|
|
53
|
-
"zod": "^4.0.0"
|
|
54
|
-
},
|
|
55
58
|
"devDependencies": {
|
|
56
59
|
"@abinnovision/eslint-config-base": "^3.2.0",
|
|
57
60
|
"@abinnovision/prettier-config": "^2.1.5",
|
|
@@ -59,10 +62,14 @@
|
|
|
59
62
|
"@types/debug": "^4.1.12",
|
|
60
63
|
"eslint": "^9.39.4",
|
|
61
64
|
"prettier": "^3.8.1",
|
|
65
|
+
"tsdown": "^0.21.3",
|
|
62
66
|
"typescript": "^5.9.3",
|
|
63
67
|
"vitest": "^4.0.18",
|
|
64
68
|
"zod": "^4.3.6"
|
|
65
69
|
},
|
|
70
|
+
"peerDependencies": {
|
|
71
|
+
"zod": "^4.0.0"
|
|
72
|
+
},
|
|
66
73
|
"publishConfig": {
|
|
67
74
|
"npm": true,
|
|
68
75
|
"npmAccess": "public"
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import type { SELRule } from "../rules/index.js";
|
|
2
|
-
import type { SELSchema } from "@seljs/schema";
|
|
3
|
-
interface SELCheckResult {
|
|
4
|
-
valid: boolean;
|
|
5
|
-
type?: string;
|
|
6
|
-
diagnostics: SELDiagnostic[];
|
|
7
|
-
}
|
|
8
|
-
interface TypeAtResult {
|
|
9
|
-
type: string;
|
|
10
|
-
from: number;
|
|
11
|
-
to: number;
|
|
12
|
-
}
|
|
13
|
-
interface ExpectedTypeInfo {
|
|
14
|
-
/**
|
|
15
|
-
* The CEL type expected at this position.
|
|
16
|
-
*/
|
|
17
|
-
expectedType: string;
|
|
18
|
-
/**
|
|
19
|
-
* How the expectation was inferred.
|
|
20
|
-
*/
|
|
21
|
-
context: "operator" | "function-argument";
|
|
22
|
-
/**
|
|
23
|
-
* For function args: which parameter index.
|
|
24
|
-
*/
|
|
25
|
-
paramIndex?: number;
|
|
26
|
-
/**
|
|
27
|
-
* For function args: the function/method name.
|
|
28
|
-
*/
|
|
29
|
-
functionName?: string;
|
|
30
|
-
}
|
|
31
|
-
interface CompletionInfo {
|
|
32
|
-
kind: "top-level" | "dot-access" | "explicit";
|
|
33
|
-
receiverType?: string;
|
|
34
|
-
items: CompletionItem[];
|
|
35
|
-
/**
|
|
36
|
-
* Inferred expected type at cursor, if determinable.
|
|
37
|
-
*/
|
|
38
|
-
expectedType?: string;
|
|
39
|
-
}
|
|
40
|
-
export interface CompletionItem {
|
|
41
|
-
label: string;
|
|
42
|
-
type: string;
|
|
43
|
-
detail?: string;
|
|
44
|
-
description?: string;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* A diagnostic message with optional position info. Used for both parse/type errors
|
|
48
|
-
* and rule violations. Positions are optional because some errors (e.g. from cel-js)
|
|
49
|
-
* may not include reliable spans, and rules may choose to report non-positional issues.
|
|
50
|
-
*/
|
|
51
|
-
export interface SELDiagnostic {
|
|
52
|
-
message: string;
|
|
53
|
-
severity: "error" | "warning" | "info";
|
|
54
|
-
from?: number;
|
|
55
|
-
to?: number;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Options for configuring the SELChecker.
|
|
59
|
-
*/
|
|
60
|
-
export interface SELCheckerOptions {
|
|
61
|
-
/**
|
|
62
|
-
* Lint rules to enable. Defaults to none (backward compatible).
|
|
63
|
-
*/
|
|
64
|
-
rules?: readonly SELRule[];
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* SEL expression checker.
|
|
68
|
-
*
|
|
69
|
-
* Wraps a hydrated cel-js Environment built from a SELSchema and exposes
|
|
70
|
-
* parse/type-check, type inference, cursor-position type lookups, and
|
|
71
|
-
* type-aware completions.
|
|
72
|
-
*/
|
|
73
|
-
export declare class SELChecker {
|
|
74
|
-
private readonly rules;
|
|
75
|
-
private env;
|
|
76
|
-
private schema;
|
|
77
|
-
private structTypeMap;
|
|
78
|
-
constructor(schema: SELSchema, options?: SELCheckerOptions);
|
|
79
|
-
/**
|
|
80
|
-
* Parse and type-check an expression, returning position-aware diagnostics.
|
|
81
|
-
*
|
|
82
|
-
* Uses a single `env.parse()` call, then `.check()` on the result
|
|
83
|
-
* to avoid double-parsing. Rules run against the AST from the same parse:
|
|
84
|
-
* - Structural rules run after successful parse (even if type-check fails)
|
|
85
|
-
* - Type-aware rules run only after both parse and type-check succeed
|
|
86
|
-
*/
|
|
87
|
-
check(expression: string): SELCheckResult;
|
|
88
|
-
/**
|
|
89
|
-
* Get the inferred CEL type of the full expression.
|
|
90
|
-
* Returns undefined if the expression is invalid.
|
|
91
|
-
*/
|
|
92
|
-
typeOf(expression: string): string | undefined;
|
|
93
|
-
/**
|
|
94
|
-
* Get the inferred type at a cursor position (for hover info).
|
|
95
|
-
*
|
|
96
|
-
* Attempts to identify the sub-expression under the cursor and infer its
|
|
97
|
-
* type. Falls back to the full expression type when sub-expression
|
|
98
|
-
* isolation is not possible.
|
|
99
|
-
*/
|
|
100
|
-
typeAt(expression: string, offset: number): TypeAtResult | undefined;
|
|
101
|
-
/**
|
|
102
|
-
* Get type-aware completions for a cursor context.
|
|
103
|
-
*
|
|
104
|
-
* Supports:
|
|
105
|
-
* - **dot-access**: after `contract.` — lists methods of that contract
|
|
106
|
-
* - **top-level**: at the start or after operators — lists variables,
|
|
107
|
-
* contracts, and functions
|
|
108
|
-
*/
|
|
109
|
-
completionsAt(expression: string, offset: number): CompletionInfo;
|
|
110
|
-
/**
|
|
111
|
-
* Infer the expected type at a cursor position from surrounding context.
|
|
112
|
-
*
|
|
113
|
-
* Supports two contexts:
|
|
114
|
-
* - **Operator**: `expr > |` — infers the left operand type and derives the
|
|
115
|
-
* expected right operand type from the operator.
|
|
116
|
-
* - **Function argument**: `contract.method(arg, |)` — looks up the
|
|
117
|
-
* parameter type from the schema.
|
|
118
|
-
*
|
|
119
|
-
* Returns undefined when context cannot be determined, signaling that
|
|
120
|
-
* no narrowing should occur (safe fallback).
|
|
121
|
-
*/
|
|
122
|
-
expectedTypeAt(expression: string, offset: number): ExpectedTypeInfo | undefined;
|
|
123
|
-
/**
|
|
124
|
-
* Resolve type and available members for a dot-access receiver expression.
|
|
125
|
-
*/
|
|
126
|
-
dotCompletions(receiverExpression: string): CompletionInfo;
|
|
127
|
-
/**
|
|
128
|
-
* Resolve expected type from a structured context.
|
|
129
|
-
*/
|
|
130
|
-
expectedTypeFor(context: {
|
|
131
|
-
kind: "operator";
|
|
132
|
-
leftExpression: string;
|
|
133
|
-
operator: string;
|
|
134
|
-
} | {
|
|
135
|
-
kind: "function-arg";
|
|
136
|
-
receiverName?: string;
|
|
137
|
-
functionName: string;
|
|
138
|
-
paramIndex: number;
|
|
139
|
-
}): string | undefined;
|
|
140
|
-
/**
|
|
141
|
-
* Rebuild the internal environment from an updated schema.
|
|
142
|
-
*/
|
|
143
|
-
updateSchema(schema: SELSchema): void;
|
|
144
|
-
private buildStructTypeMap;
|
|
145
|
-
private structFieldsFor;
|
|
146
|
-
/**
|
|
147
|
-
* Scan backwards from a dot position to extract the receiver expression.
|
|
148
|
-
* Handles balanced parentheses so that `foo(erc20.name().` correctly
|
|
149
|
-
* identifies `erc20.name()` as the receiver, not `foo(erc20.name()`.
|
|
150
|
-
*/
|
|
151
|
-
private extractReceiverBefore;
|
|
152
|
-
/**
|
|
153
|
-
* Find the largest call/dot-access chain node that contains the offset.
|
|
154
|
-
*/
|
|
155
|
-
private findContainingChain;
|
|
156
|
-
/**
|
|
157
|
-
* Scan backwards from the end of text to find a trailing binary operator.
|
|
158
|
-
* Tries multi-character operators first (==, !=, etc.) to avoid partial matches.
|
|
159
|
-
*/
|
|
160
|
-
private findTrailingOperator;
|
|
161
|
-
/**
|
|
162
|
-
* Find the enclosing function/method call around the cursor by scanning
|
|
163
|
-
* backwards for an unclosed `(`, then extracting the function name and
|
|
164
|
-
* counting commas to determine the parameter index.
|
|
165
|
-
*/
|
|
166
|
-
private findEnclosingCall;
|
|
167
|
-
/**
|
|
168
|
-
* Look up the expected parameter type from the schema for a function or
|
|
169
|
-
* method call at the given parameter index.
|
|
170
|
-
*/
|
|
171
|
-
private resolveRawParamType;
|
|
172
|
-
}
|
|
173
|
-
export {};
|