@valtzu/codemirror-lang-el 0.6.2 → 0.8.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 +13 -0
- package/README.md +1 -29
- package/dist/complete.cjs +54 -20
- package/dist/complete.js +54 -20
- package/dist/index.cjs +116 -41
- package/dist/index.d.cts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +117 -42
- package/dist/linter.cjs +72 -13
- package/dist/linter.js +72 -13
- package/dist/tooltip.cjs +44 -23
- package/dist/tooltip.d.cts +4 -3
- package/dist/tooltip.d.ts +4 -3
- package/dist/tooltip.js +46 -24
- package/dist/utils.cjs +150 -0
- package/dist/utils.d.cts +53 -0
- package/dist/utils.d.ts +53 -0
- package/dist/utils.js +141 -0
- package/package.json +1 -1
package/dist/tooltip.cjs
CHANGED
|
@@ -6,6 +6,20 @@ var state = require('@codemirror/state');
|
|
|
6
6
|
var view = require('@codemirror/view');
|
|
7
7
|
var language = require('@codemirror/language');
|
|
8
8
|
|
|
9
|
+
var ELScalar;
|
|
10
|
+
(function (ELScalar) {
|
|
11
|
+
ELScalar["Bool"] = "bool";
|
|
12
|
+
ELScalar["Number"] = "number";
|
|
13
|
+
ELScalar["String"] = "string";
|
|
14
|
+
ELScalar["Null"] = "null";
|
|
15
|
+
ELScalar["Any"] = "any";
|
|
16
|
+
})(ELScalar || (ELScalar = {}));
|
|
17
|
+
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
const t = {
|
|
20
|
+
deserialize: (str) => str,
|
|
21
|
+
};
|
|
22
|
+
|
|
9
23
|
const createInfoElement = (html) => {
|
|
10
24
|
const dom = document.createElement("div");
|
|
11
25
|
dom.innerHTML = html;
|
|
@@ -42,12 +56,16 @@ const resolveIdentifier = (nodeName, identifier, config) => {
|
|
|
42
56
|
}
|
|
43
57
|
};
|
|
44
58
|
function resolveTypes(state, node, config, matchExact) {
|
|
45
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
59
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
46
60
|
let types = new Set();
|
|
47
61
|
if (!node) {
|
|
48
62
|
return types;
|
|
49
63
|
}
|
|
50
|
-
|
|
64
|
+
let type;
|
|
65
|
+
if (typeof (type = node.type.prop(t)) !== "undefined") {
|
|
66
|
+
types.add(type);
|
|
67
|
+
}
|
|
68
|
+
else if (node.name === 'Call' && node.firstChild && node.lastChild) {
|
|
51
69
|
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
52
70
|
}
|
|
53
71
|
else if (node.name === 'Variable') {
|
|
@@ -83,17 +101,32 @@ function resolveTypes(state, node, config, matchExact) {
|
|
|
83
101
|
resolveTypes(state, node.firstChild.nextSibling, config).forEach(x => types.add(x));
|
|
84
102
|
resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
|
|
85
103
|
}
|
|
86
|
-
else if (node.name === 'BinaryExpression' && ((
|
|
104
|
+
else if (node.name === 'BinaryExpression' && ((_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) && ((_l = (_k = node.firstChild) === null || _k === void 0 ? void 0 : _k.nextSibling) === null || _l === void 0 ? void 0 : _l.nextSibling)) {
|
|
87
105
|
const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
|
|
88
|
-
if (operator == '?:' || operator == '??') {
|
|
89
|
-
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
90
|
-
}
|
|
91
106
|
if (operator == '?:' || operator == '??' || operator == '?') {
|
|
92
|
-
|
|
107
|
+
if (operator == '?:' || operator == '??') {
|
|
108
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
109
|
+
}
|
|
110
|
+
resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
|
|
111
|
+
}
|
|
112
|
+
else if (['||', '&&', '==', '!=', '===', '!==', '>=', '<=', '>', '<'].includes(operator) || keywords.find(x => x.name == operator)) {
|
|
113
|
+
types.add(ELScalar.Bool);
|
|
114
|
+
}
|
|
115
|
+
else if (['**', '|', '^', '&', '<<', '>>', '+', '-', '*', '/', '%'].includes(operator)) {
|
|
116
|
+
types.add(ELScalar.Number);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else if (node.name === 'UnaryExpression' && node.firstChild) {
|
|
120
|
+
const operator = state.sliceDoc(node.firstChild.from, node.firstChild.to);
|
|
121
|
+
if (['not', '!'].includes(operator)) {
|
|
122
|
+
types.add(ELScalar.Bool);
|
|
123
|
+
}
|
|
124
|
+
else if (['+', '-'].includes(operator)) {
|
|
125
|
+
types.add(ELScalar.Number);
|
|
93
126
|
}
|
|
94
127
|
}
|
|
95
128
|
if (types.size === 0) {
|
|
96
|
-
types.add(
|
|
129
|
+
types.add(ELScalar.Any);
|
|
97
130
|
}
|
|
98
131
|
return types;
|
|
99
132
|
}
|
|
@@ -110,6 +143,7 @@ const keywords = [
|
|
|
110
143
|
{ name: 'not' },
|
|
111
144
|
{ name: 'or' },
|
|
112
145
|
{ name: 'and' },
|
|
146
|
+
{ name: 'xor' },
|
|
113
147
|
];
|
|
114
148
|
|
|
115
149
|
function getNodeOrdinal(node) {
|
|
@@ -132,7 +166,7 @@ function getCursorTooltips(state) {
|
|
|
132
166
|
return state.selection.ranges
|
|
133
167
|
.filter(range => range.empty)
|
|
134
168
|
.map(range => {
|
|
135
|
-
var _a;
|
|
169
|
+
var _a, _b;
|
|
136
170
|
const tree = language.syntaxTree(state);
|
|
137
171
|
const node = tree.resolveInner(range.from, 0);
|
|
138
172
|
const args = resolveArguments(node);
|
|
@@ -144,7 +178,7 @@ function getCursorTooltips(state) {
|
|
|
144
178
|
return null;
|
|
145
179
|
}
|
|
146
180
|
const n = args.childAfter(range.from - 1);
|
|
147
|
-
const argName = (_a = fn.args) === null || _a === void 0 ? void 0 : _a[n ? getNodeOrdinal(n) : 0];
|
|
181
|
+
const argName = (_b = (_a = fn.args) === null || _a === void 0 ? void 0 : _a[n ? getNodeOrdinal(n) : 0]) === null || _b === void 0 ? void 0 : _b.name;
|
|
148
182
|
if (n && n.from !== range.from || !argName) {
|
|
149
183
|
return null;
|
|
150
184
|
}
|
|
@@ -219,19 +253,6 @@ const keywordTooltip = view.hoverTooltip((view, pos, side) => {
|
|
|
219
253
|
create: () => ({ dom: createInfoElement(info) }),
|
|
220
254
|
};
|
|
221
255
|
});
|
|
222
|
-
const cursorTooltipBaseTheme = view.EditorView.baseTheme({
|
|
223
|
-
".cm-tooltip.cm-tooltip-cursor": {
|
|
224
|
-
boxShadow: 'rgba(0, 0, 0, .15) 0 1px 2px',
|
|
225
|
-
border: "1px solid rgba(127, 127, 127, .2)",
|
|
226
|
-
padding: "2px 7px",
|
|
227
|
-
borderRadius: "4px",
|
|
228
|
-
"& .cm-tooltip-arrow:before": {},
|
|
229
|
-
"& .cm-tooltip-arrow:after": {
|
|
230
|
-
borderTopColor: "transparent"
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
256
|
|
|
235
|
-
exports.cursorTooltipBaseTheme = cursorTooltipBaseTheme;
|
|
236
257
|
exports.cursorTooltipField = cursorTooltipField;
|
|
237
258
|
exports.keywordTooltip = keywordTooltip;
|
package/dist/tooltip.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { StateField } from "@codemirror/state";
|
|
2
2
|
import { Tooltip } from "@codemirror/view";
|
|
3
3
|
declare const cursorTooltipField: StateField<readonly Tooltip[]>;
|
|
4
|
-
declare const keywordTooltip: import("@codemirror/state").Extension
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
declare const keywordTooltip: import("@codemirror/state").Extension & {
|
|
5
|
+
active: StateField<readonly Tooltip[]>;
|
|
6
|
+
};
|
|
7
|
+
export { cursorTooltipField, keywordTooltip };
|
package/dist/tooltip.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { StateField } from "@codemirror/state";
|
|
2
2
|
import { Tooltip } from "@codemirror/view";
|
|
3
3
|
declare const cursorTooltipField: StateField<readonly Tooltip[]>;
|
|
4
|
-
declare const keywordTooltip: import("@codemirror/state").Extension
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
declare const keywordTooltip: import("@codemirror/state").Extension & {
|
|
5
|
+
active: StateField<readonly Tooltip[]>;
|
|
6
|
+
};
|
|
7
|
+
export { cursorTooltipField, keywordTooltip };
|
package/dist/tooltip.js
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
import { StateField } from '@codemirror/state';
|
|
2
|
-
import { showTooltip, hoverTooltip
|
|
2
|
+
import { showTooltip, hoverTooltip } from '@codemirror/view';
|
|
3
3
|
import { syntaxTree } from '@codemirror/language';
|
|
4
4
|
|
|
5
|
+
var ELScalar;
|
|
6
|
+
(function (ELScalar) {
|
|
7
|
+
ELScalar["Bool"] = "bool";
|
|
8
|
+
ELScalar["Number"] = "number";
|
|
9
|
+
ELScalar["String"] = "string";
|
|
10
|
+
ELScalar["Null"] = "null";
|
|
11
|
+
ELScalar["Any"] = "any";
|
|
12
|
+
})(ELScalar || (ELScalar = {}));
|
|
13
|
+
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
const t = {
|
|
16
|
+
deserialize: (str) => str,
|
|
17
|
+
};
|
|
18
|
+
|
|
5
19
|
const createInfoElement = (html) => {
|
|
6
20
|
const dom = document.createElement("div");
|
|
7
21
|
dom.innerHTML = html;
|
|
@@ -38,12 +52,16 @@ const resolveIdentifier = (nodeName, identifier, config) => {
|
|
|
38
52
|
}
|
|
39
53
|
};
|
|
40
54
|
function resolveTypes(state, node, config, matchExact) {
|
|
41
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
55
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
42
56
|
let types = new Set();
|
|
43
57
|
if (!node) {
|
|
44
58
|
return types;
|
|
45
59
|
}
|
|
46
|
-
|
|
60
|
+
let type;
|
|
61
|
+
if (typeof (type = node.type.prop(t)) !== "undefined") {
|
|
62
|
+
types.add(type);
|
|
63
|
+
}
|
|
64
|
+
else if (node.name === 'Call' && node.firstChild && node.lastChild) {
|
|
47
65
|
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
48
66
|
}
|
|
49
67
|
else if (node.name === 'Variable') {
|
|
@@ -79,17 +97,32 @@ function resolveTypes(state, node, config, matchExact) {
|
|
|
79
97
|
resolveTypes(state, node.firstChild.nextSibling, config).forEach(x => types.add(x));
|
|
80
98
|
resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
|
|
81
99
|
}
|
|
82
|
-
else if (node.name === 'BinaryExpression' && ((
|
|
100
|
+
else if (node.name === 'BinaryExpression' && ((_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) && ((_l = (_k = node.firstChild) === null || _k === void 0 ? void 0 : _k.nextSibling) === null || _l === void 0 ? void 0 : _l.nextSibling)) {
|
|
83
101
|
const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
|
|
84
|
-
if (operator == '?:' || operator == '??') {
|
|
85
|
-
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
86
|
-
}
|
|
87
102
|
if (operator == '?:' || operator == '??' || operator == '?') {
|
|
88
|
-
|
|
103
|
+
if (operator == '?:' || operator == '??') {
|
|
104
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
105
|
+
}
|
|
106
|
+
resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
|
|
107
|
+
}
|
|
108
|
+
else if (['||', '&&', '==', '!=', '===', '!==', '>=', '<=', '>', '<'].includes(operator) || keywords.find(x => x.name == operator)) {
|
|
109
|
+
types.add(ELScalar.Bool);
|
|
110
|
+
}
|
|
111
|
+
else if (['**', '|', '^', '&', '<<', '>>', '+', '-', '*', '/', '%'].includes(operator)) {
|
|
112
|
+
types.add(ELScalar.Number);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else if (node.name === 'UnaryExpression' && node.firstChild) {
|
|
116
|
+
const operator = state.sliceDoc(node.firstChild.from, node.firstChild.to);
|
|
117
|
+
if (['not', '!'].includes(operator)) {
|
|
118
|
+
types.add(ELScalar.Bool);
|
|
119
|
+
}
|
|
120
|
+
else if (['+', '-'].includes(operator)) {
|
|
121
|
+
types.add(ELScalar.Number);
|
|
89
122
|
}
|
|
90
123
|
}
|
|
91
124
|
if (types.size === 0) {
|
|
92
|
-
types.add(
|
|
125
|
+
types.add(ELScalar.Any);
|
|
93
126
|
}
|
|
94
127
|
return types;
|
|
95
128
|
}
|
|
@@ -106,6 +139,7 @@ const keywords = [
|
|
|
106
139
|
{ name: 'not' },
|
|
107
140
|
{ name: 'or' },
|
|
108
141
|
{ name: 'and' },
|
|
142
|
+
{ name: 'xor' },
|
|
109
143
|
];
|
|
110
144
|
|
|
111
145
|
function getNodeOrdinal(node) {
|
|
@@ -128,7 +162,7 @@ function getCursorTooltips(state) {
|
|
|
128
162
|
return state.selection.ranges
|
|
129
163
|
.filter(range => range.empty)
|
|
130
164
|
.map(range => {
|
|
131
|
-
var _a;
|
|
165
|
+
var _a, _b;
|
|
132
166
|
const tree = syntaxTree(state);
|
|
133
167
|
const node = tree.resolveInner(range.from, 0);
|
|
134
168
|
const args = resolveArguments(node);
|
|
@@ -140,7 +174,7 @@ function getCursorTooltips(state) {
|
|
|
140
174
|
return null;
|
|
141
175
|
}
|
|
142
176
|
const n = args.childAfter(range.from - 1);
|
|
143
|
-
const argName = (_a = fn.args) === null || _a === void 0 ? void 0 : _a[n ? getNodeOrdinal(n) : 0];
|
|
177
|
+
const argName = (_b = (_a = fn.args) === null || _a === void 0 ? void 0 : _a[n ? getNodeOrdinal(n) : 0]) === null || _b === void 0 ? void 0 : _b.name;
|
|
144
178
|
if (n && n.from !== range.from || !argName) {
|
|
145
179
|
return null;
|
|
146
180
|
}
|
|
@@ -215,17 +249,5 @@ const keywordTooltip = hoverTooltip((view, pos, side) => {
|
|
|
215
249
|
create: () => ({ dom: createInfoElement(info) }),
|
|
216
250
|
};
|
|
217
251
|
});
|
|
218
|
-
const cursorTooltipBaseTheme = EditorView.baseTheme({
|
|
219
|
-
".cm-tooltip.cm-tooltip-cursor": {
|
|
220
|
-
boxShadow: 'rgba(0, 0, 0, .15) 0 1px 2px',
|
|
221
|
-
border: "1px solid rgba(127, 127, 127, .2)",
|
|
222
|
-
padding: "2px 7px",
|
|
223
|
-
borderRadius: "4px",
|
|
224
|
-
"& .cm-tooltip-arrow:before": {},
|
|
225
|
-
"& .cm-tooltip-arrow:after": {
|
|
226
|
-
borderTopColor: "transparent"
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
252
|
|
|
231
|
-
export {
|
|
253
|
+
export { cursorTooltipField, keywordTooltip };
|
package/dist/utils.cjs
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var ELScalar;
|
|
6
|
+
(function (ELScalar) {
|
|
7
|
+
ELScalar["Bool"] = "bool";
|
|
8
|
+
ELScalar["Number"] = "number";
|
|
9
|
+
ELScalar["String"] = "string";
|
|
10
|
+
ELScalar["Null"] = "null";
|
|
11
|
+
ELScalar["Any"] = "any";
|
|
12
|
+
})(ELScalar || (ELScalar = {}));
|
|
13
|
+
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
const t = {
|
|
16
|
+
deserialize: (str) => str,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const createInfoElement = (html) => {
|
|
20
|
+
const dom = document.createElement("div");
|
|
21
|
+
dom.innerHTML = html;
|
|
22
|
+
dom.className = 'cm-diagnostic';
|
|
23
|
+
return dom;
|
|
24
|
+
};
|
|
25
|
+
function resolveFunctionDefinition(node, state, config) {
|
|
26
|
+
var _a;
|
|
27
|
+
if (!node) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
let identifier;
|
|
31
|
+
if (node.name === 'ObjectAccess' && node.lastChild) {
|
|
32
|
+
const leftArgument = (_a = node.firstChild) === null || _a === void 0 ? void 0 : _a.node;
|
|
33
|
+
const types = Array.from(resolveTypes(state, leftArgument, config));
|
|
34
|
+
identifier = state.sliceDoc(node.lastChild.from, node.lastChild.to);
|
|
35
|
+
return types.map(type => { var _a; return resolveCallable(identifier, (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]); }).find(x => x);
|
|
36
|
+
}
|
|
37
|
+
else if (node.name === 'Function') {
|
|
38
|
+
identifier = state.sliceDoc(node.from, node.node.firstChild ? node.node.firstChild.from - 1 : node.to);
|
|
39
|
+
return resolveCallable(identifier, config);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
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); };
|
|
43
|
+
const resolveIdentifier = (nodeName, identifier, config) => {
|
|
44
|
+
var _a;
|
|
45
|
+
switch (nodeName) {
|
|
46
|
+
case 'Method':
|
|
47
|
+
case 'Function':
|
|
48
|
+
return resolveCallable(identifier, config);
|
|
49
|
+
case 'Property':
|
|
50
|
+
case 'Variable':
|
|
51
|
+
return (_a = config === null || config === void 0 ? void 0 : config.identifiers) === null || _a === void 0 ? void 0 : _a.find(x => x.name === identifier);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
function resolveTypes(state, node, config, matchExact) {
|
|
55
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
56
|
+
let types = new Set();
|
|
57
|
+
if (!node) {
|
|
58
|
+
return types;
|
|
59
|
+
}
|
|
60
|
+
let type;
|
|
61
|
+
if (typeof (type = node.type.prop(t)) !== "undefined") {
|
|
62
|
+
types.add(type);
|
|
63
|
+
}
|
|
64
|
+
else if (node.name === 'Call' && node.firstChild && node.lastChild) {
|
|
65
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
66
|
+
}
|
|
67
|
+
else if (node.name === 'Variable') {
|
|
68
|
+
const varName = state.sliceDoc(node.from, node.to) || '';
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
(_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));
|
|
71
|
+
}
|
|
72
|
+
else if (node.name === 'Function') {
|
|
73
|
+
const varName = state.sliceDoc(node.from, node.to) || '';
|
|
74
|
+
// @ts-ignore
|
|
75
|
+
(_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));
|
|
76
|
+
}
|
|
77
|
+
else if (node.name === 'ObjectAccess' && node.firstChild && ((_e = node.lastChild) === null || _e === void 0 ? void 0 : _e.name) === 'Property') {
|
|
78
|
+
const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
|
|
79
|
+
(_f = resolveTypes(state, node.firstChild, config)) === null || _f === void 0 ? void 0 : _f.forEach(baseType => {
|
|
80
|
+
var _a, _b, _c, _d;
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
(_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));
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
else if (node.name === 'ObjectAccess' && node.firstChild && ((_g = node.lastChild) === null || _g === void 0 ? void 0 : _g.name) === 'Method') {
|
|
86
|
+
const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
|
|
87
|
+
(_h = resolveTypes(state, node.firstChild, config)) === null || _h === void 0 ? void 0 : _h.forEach(baseType => {
|
|
88
|
+
var _a, _b, _c, _d;
|
|
89
|
+
// @ts-ignore
|
|
90
|
+
(_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));
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
else if (node.name === 'Application' && node.firstChild) {
|
|
94
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
95
|
+
}
|
|
96
|
+
else if (node.name === 'TernaryExpression' && node.firstChild && node.firstChild.nextSibling && node.firstChild.nextSibling.nextSibling) {
|
|
97
|
+
resolveTypes(state, node.firstChild.nextSibling, config).forEach(x => types.add(x));
|
|
98
|
+
resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
|
|
99
|
+
}
|
|
100
|
+
else if (node.name === 'BinaryExpression' && ((_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) && ((_l = (_k = node.firstChild) === null || _k === void 0 ? void 0 : _k.nextSibling) === null || _l === void 0 ? void 0 : _l.nextSibling)) {
|
|
101
|
+
const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
|
|
102
|
+
if (operator == '?:' || operator == '??' || operator == '?') {
|
|
103
|
+
if (operator == '?:' || operator == '??') {
|
|
104
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
105
|
+
}
|
|
106
|
+
resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
|
|
107
|
+
}
|
|
108
|
+
else if (['||', '&&', '==', '!=', '===', '!==', '>=', '<=', '>', '<'].includes(operator) || keywords.find(x => x.name == operator)) {
|
|
109
|
+
types.add(ELScalar.Bool);
|
|
110
|
+
}
|
|
111
|
+
else if (['**', '|', '^', '&', '<<', '>>', '+', '-', '*', '/', '%'].includes(operator)) {
|
|
112
|
+
types.add(ELScalar.Number);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else if (node.name === 'UnaryExpression' && node.firstChild) {
|
|
116
|
+
const operator = state.sliceDoc(node.firstChild.from, node.firstChild.to);
|
|
117
|
+
if (['not', '!'].includes(operator)) {
|
|
118
|
+
types.add(ELScalar.Bool);
|
|
119
|
+
}
|
|
120
|
+
else if (['+', '-'].includes(operator)) {
|
|
121
|
+
types.add(ELScalar.Number);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (types.size === 0) {
|
|
125
|
+
types.add(ELScalar.Any);
|
|
126
|
+
}
|
|
127
|
+
return types;
|
|
128
|
+
}
|
|
129
|
+
function getExpressionLanguageConfig(state) {
|
|
130
|
+
return state.languageDataAt('expressionLanguageConfig', 0)[0];
|
|
131
|
+
}
|
|
132
|
+
const keywords = [
|
|
133
|
+
{ name: 'starts with', info: 'Check if a string starts with a specific string' },
|
|
134
|
+
{ name: 'ends with', info: 'Check if a string ends with a specific string' },
|
|
135
|
+
{ name: 'contains', info: 'Check if a string is not included in another string' },
|
|
136
|
+
{ name: 'matches', info: 'Check if a string matches a regex pattern' },
|
|
137
|
+
{ name: 'not in', info: 'Check if a value is not included in an array' },
|
|
138
|
+
{ name: 'in', info: 'Check if a value is included in an array' },
|
|
139
|
+
{ name: 'not' },
|
|
140
|
+
{ name: 'or' },
|
|
141
|
+
{ name: 'and' },
|
|
142
|
+
{ name: 'xor' },
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
exports.createInfoElement = createInfoElement;
|
|
146
|
+
exports.getExpressionLanguageConfig = getExpressionLanguageConfig;
|
|
147
|
+
exports.keywords = keywords;
|
|
148
|
+
exports.resolveFunctionDefinition = resolveFunctionDefinition;
|
|
149
|
+
exports.resolveIdentifier = resolveIdentifier;
|
|
150
|
+
exports.resolveTypes = resolveTypes;
|
package/dist/utils.d.cts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { SyntaxNode } from "@lezer/common";
|
|
2
|
+
import { EditorState } from "@codemirror/state";
|
|
3
|
+
/**
|
|
4
|
+
* Represents a variable or a property of an object
|
|
5
|
+
*/
|
|
6
|
+
interface ELIdentifier {
|
|
7
|
+
name: string;
|
|
8
|
+
detail?: string;
|
|
9
|
+
info?: string;
|
|
10
|
+
type?: string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Represents a function or a method of an object
|
|
14
|
+
*/
|
|
15
|
+
interface ELFunction {
|
|
16
|
+
name: string;
|
|
17
|
+
args: ELParameter[];
|
|
18
|
+
info?: string;
|
|
19
|
+
returnType?: string[];
|
|
20
|
+
}
|
|
21
|
+
interface ELParameter {
|
|
22
|
+
name: string;
|
|
23
|
+
type?: string[];
|
|
24
|
+
info?: string;
|
|
25
|
+
optional?: boolean;
|
|
26
|
+
}
|
|
27
|
+
interface ELType {
|
|
28
|
+
identifiers?: ELIdentifier[];
|
|
29
|
+
functions?: ELFunction[];
|
|
30
|
+
info?: string;
|
|
31
|
+
}
|
|
32
|
+
interface ExpressionLanguageConfig {
|
|
33
|
+
types?: {
|
|
34
|
+
[key: string]: ELType;
|
|
35
|
+
};
|
|
36
|
+
identifiers?: ELIdentifier[];
|
|
37
|
+
functions?: ELFunction[];
|
|
38
|
+
}
|
|
39
|
+
interface ELKeyword {
|
|
40
|
+
name: string;
|
|
41
|
+
detail?: string;
|
|
42
|
+
info?: string;
|
|
43
|
+
}
|
|
44
|
+
declare const createInfoElement: (html: string) => HTMLDivElement;
|
|
45
|
+
declare function resolveFunctionDefinition(node: SyntaxNode | null, state: EditorState, config: ExpressionLanguageConfig): ELFunction | undefined;
|
|
46
|
+
declare const resolveIdentifier: (nodeName: 'Method' | 'Property' | 'Function' | 'Variable', identifier?: string, config?: {
|
|
47
|
+
identifiers?: ELIdentifier[];
|
|
48
|
+
functions?: ELFunction[];
|
|
49
|
+
}) => ELIdentifier | ELFunction | undefined;
|
|
50
|
+
declare function resolveTypes(state: EditorState, node: SyntaxNode | undefined, config: ExpressionLanguageConfig, matchExact: boolean): Set<string>;
|
|
51
|
+
declare function getExpressionLanguageConfig(state: EditorState): ExpressionLanguageConfig;
|
|
52
|
+
declare const keywords: ELKeyword[];
|
|
53
|
+
export { createInfoElement, resolveFunctionDefinition, resolveIdentifier, resolveTypes, getExpressionLanguageConfig, keywords };
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { SyntaxNode } from "@lezer/common";
|
|
2
|
+
import { EditorState } from "@codemirror/state";
|
|
3
|
+
/**
|
|
4
|
+
* Represents a variable or a property of an object
|
|
5
|
+
*/
|
|
6
|
+
interface ELIdentifier {
|
|
7
|
+
name: string;
|
|
8
|
+
detail?: string;
|
|
9
|
+
info?: string;
|
|
10
|
+
type?: string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Represents a function or a method of an object
|
|
14
|
+
*/
|
|
15
|
+
interface ELFunction {
|
|
16
|
+
name: string;
|
|
17
|
+
args: ELParameter[];
|
|
18
|
+
info?: string;
|
|
19
|
+
returnType?: string[];
|
|
20
|
+
}
|
|
21
|
+
interface ELParameter {
|
|
22
|
+
name: string;
|
|
23
|
+
type?: string[];
|
|
24
|
+
info?: string;
|
|
25
|
+
optional?: boolean;
|
|
26
|
+
}
|
|
27
|
+
interface ELType {
|
|
28
|
+
identifiers?: ELIdentifier[];
|
|
29
|
+
functions?: ELFunction[];
|
|
30
|
+
info?: string;
|
|
31
|
+
}
|
|
32
|
+
interface ExpressionLanguageConfig {
|
|
33
|
+
types?: {
|
|
34
|
+
[key: string]: ELType;
|
|
35
|
+
};
|
|
36
|
+
identifiers?: ELIdentifier[];
|
|
37
|
+
functions?: ELFunction[];
|
|
38
|
+
}
|
|
39
|
+
interface ELKeyword {
|
|
40
|
+
name: string;
|
|
41
|
+
detail?: string;
|
|
42
|
+
info?: string;
|
|
43
|
+
}
|
|
44
|
+
declare const createInfoElement: (html: string) => HTMLDivElement;
|
|
45
|
+
declare function resolveFunctionDefinition(node: SyntaxNode | null, state: EditorState, config: ExpressionLanguageConfig): ELFunction | undefined;
|
|
46
|
+
declare const resolveIdentifier: (nodeName: 'Method' | 'Property' | 'Function' | 'Variable', identifier?: string, config?: {
|
|
47
|
+
identifiers?: ELIdentifier[];
|
|
48
|
+
functions?: ELFunction[];
|
|
49
|
+
}) => ELIdentifier | ELFunction | undefined;
|
|
50
|
+
declare function resolveTypes(state: EditorState, node: SyntaxNode | undefined, config: ExpressionLanguageConfig, matchExact: boolean): Set<string>;
|
|
51
|
+
declare function getExpressionLanguageConfig(state: EditorState): ExpressionLanguageConfig;
|
|
52
|
+
declare const keywords: ELKeyword[];
|
|
53
|
+
export { createInfoElement, resolveFunctionDefinition, resolveIdentifier, resolveTypes, getExpressionLanguageConfig, keywords };
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
var ELScalar;
|
|
2
|
+
(function (ELScalar) {
|
|
3
|
+
ELScalar["Bool"] = "bool";
|
|
4
|
+
ELScalar["Number"] = "number";
|
|
5
|
+
ELScalar["String"] = "string";
|
|
6
|
+
ELScalar["Null"] = "null";
|
|
7
|
+
ELScalar["Any"] = "any";
|
|
8
|
+
})(ELScalar || (ELScalar = {}));
|
|
9
|
+
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
const t = {
|
|
12
|
+
deserialize: (str) => str,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const createInfoElement = (html) => {
|
|
16
|
+
const dom = document.createElement("div");
|
|
17
|
+
dom.innerHTML = html;
|
|
18
|
+
dom.className = 'cm-diagnostic';
|
|
19
|
+
return dom;
|
|
20
|
+
};
|
|
21
|
+
function resolveFunctionDefinition(node, state, config) {
|
|
22
|
+
var _a;
|
|
23
|
+
if (!node) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
let identifier;
|
|
27
|
+
if (node.name === 'ObjectAccess' && node.lastChild) {
|
|
28
|
+
const leftArgument = (_a = node.firstChild) === null || _a === void 0 ? void 0 : _a.node;
|
|
29
|
+
const types = Array.from(resolveTypes(state, leftArgument, config));
|
|
30
|
+
identifier = state.sliceDoc(node.lastChild.from, node.lastChild.to);
|
|
31
|
+
return types.map(type => { var _a; return resolveCallable(identifier, (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]); }).find(x => x);
|
|
32
|
+
}
|
|
33
|
+
else if (node.name === 'Function') {
|
|
34
|
+
identifier = state.sliceDoc(node.from, node.node.firstChild ? node.node.firstChild.from - 1 : node.to);
|
|
35
|
+
return resolveCallable(identifier, config);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
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); };
|
|
39
|
+
const resolveIdentifier = (nodeName, identifier, config) => {
|
|
40
|
+
var _a;
|
|
41
|
+
switch (nodeName) {
|
|
42
|
+
case 'Method':
|
|
43
|
+
case 'Function':
|
|
44
|
+
return resolveCallable(identifier, config);
|
|
45
|
+
case 'Property':
|
|
46
|
+
case 'Variable':
|
|
47
|
+
return (_a = config === null || config === void 0 ? void 0 : config.identifiers) === null || _a === void 0 ? void 0 : _a.find(x => x.name === identifier);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
function resolveTypes(state, node, config, matchExact) {
|
|
51
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
52
|
+
let types = new Set();
|
|
53
|
+
if (!node) {
|
|
54
|
+
return types;
|
|
55
|
+
}
|
|
56
|
+
let type;
|
|
57
|
+
if (typeof (type = node.type.prop(t)) !== "undefined") {
|
|
58
|
+
types.add(type);
|
|
59
|
+
}
|
|
60
|
+
else if (node.name === 'Call' && node.firstChild && node.lastChild) {
|
|
61
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
62
|
+
}
|
|
63
|
+
else if (node.name === 'Variable') {
|
|
64
|
+
const varName = state.sliceDoc(node.from, node.to) || '';
|
|
65
|
+
// @ts-ignore
|
|
66
|
+
(_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));
|
|
67
|
+
}
|
|
68
|
+
else if (node.name === 'Function') {
|
|
69
|
+
const varName = state.sliceDoc(node.from, node.to) || '';
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
(_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));
|
|
72
|
+
}
|
|
73
|
+
else if (node.name === 'ObjectAccess' && node.firstChild && ((_e = node.lastChild) === null || _e === void 0 ? void 0 : _e.name) === 'Property') {
|
|
74
|
+
const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
|
|
75
|
+
(_f = resolveTypes(state, node.firstChild, config)) === null || _f === void 0 ? void 0 : _f.forEach(baseType => {
|
|
76
|
+
var _a, _b, _c, _d;
|
|
77
|
+
// @ts-ignore
|
|
78
|
+
(_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));
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
else if (node.name === 'ObjectAccess' && node.firstChild && ((_g = node.lastChild) === null || _g === void 0 ? void 0 : _g.name) === 'Method') {
|
|
82
|
+
const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
|
|
83
|
+
(_h = resolveTypes(state, node.firstChild, config)) === null || _h === void 0 ? void 0 : _h.forEach(baseType => {
|
|
84
|
+
var _a, _b, _c, _d;
|
|
85
|
+
// @ts-ignore
|
|
86
|
+
(_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));
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
else if (node.name === 'Application' && node.firstChild) {
|
|
90
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
91
|
+
}
|
|
92
|
+
else if (node.name === 'TernaryExpression' && node.firstChild && node.firstChild.nextSibling && node.firstChild.nextSibling.nextSibling) {
|
|
93
|
+
resolveTypes(state, node.firstChild.nextSibling, config).forEach(x => types.add(x));
|
|
94
|
+
resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
|
|
95
|
+
}
|
|
96
|
+
else if (node.name === 'BinaryExpression' && ((_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) && ((_l = (_k = node.firstChild) === null || _k === void 0 ? void 0 : _k.nextSibling) === null || _l === void 0 ? void 0 : _l.nextSibling)) {
|
|
97
|
+
const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
|
|
98
|
+
if (operator == '?:' || operator == '??' || operator == '?') {
|
|
99
|
+
if (operator == '?:' || operator == '??') {
|
|
100
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
101
|
+
}
|
|
102
|
+
resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
|
|
103
|
+
}
|
|
104
|
+
else if (['||', '&&', '==', '!=', '===', '!==', '>=', '<=', '>', '<'].includes(operator) || keywords.find(x => x.name == operator)) {
|
|
105
|
+
types.add(ELScalar.Bool);
|
|
106
|
+
}
|
|
107
|
+
else if (['**', '|', '^', '&', '<<', '>>', '+', '-', '*', '/', '%'].includes(operator)) {
|
|
108
|
+
types.add(ELScalar.Number);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else if (node.name === 'UnaryExpression' && node.firstChild) {
|
|
112
|
+
const operator = state.sliceDoc(node.firstChild.from, node.firstChild.to);
|
|
113
|
+
if (['not', '!'].includes(operator)) {
|
|
114
|
+
types.add(ELScalar.Bool);
|
|
115
|
+
}
|
|
116
|
+
else if (['+', '-'].includes(operator)) {
|
|
117
|
+
types.add(ELScalar.Number);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (types.size === 0) {
|
|
121
|
+
types.add(ELScalar.Any);
|
|
122
|
+
}
|
|
123
|
+
return types;
|
|
124
|
+
}
|
|
125
|
+
function getExpressionLanguageConfig(state) {
|
|
126
|
+
return state.languageDataAt('expressionLanguageConfig', 0)[0];
|
|
127
|
+
}
|
|
128
|
+
const keywords = [
|
|
129
|
+
{ name: 'starts with', info: 'Check if a string starts with a specific string' },
|
|
130
|
+
{ name: 'ends with', info: 'Check if a string ends with a specific string' },
|
|
131
|
+
{ name: 'contains', info: 'Check if a string is not included in another string' },
|
|
132
|
+
{ name: 'matches', info: 'Check if a string matches a regex pattern' },
|
|
133
|
+
{ name: 'not in', info: 'Check if a value is not included in an array' },
|
|
134
|
+
{ name: 'in', info: 'Check if a value is included in an array' },
|
|
135
|
+
{ name: 'not' },
|
|
136
|
+
{ name: 'or' },
|
|
137
|
+
{ name: 'and' },
|
|
138
|
+
{ name: 'xor' },
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
export { createInfoElement, getExpressionLanguageConfig, keywords, resolveFunctionDefinition, resolveIdentifier, resolveTypes };
|