@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/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
CHANGELOG
|
|
2
|
+
=========
|
|
3
|
+
|
|
4
|
+
0.7
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
* Add support for comments `/*` & `*/`
|
|
8
|
+
* Add support for `xor`
|
|
9
|
+
* Add support for uppercase `TRUE`/`FALSE`/`NULL`
|
|
10
|
+
* Add support for bitwise operators `<<` && `>>`
|
|
11
|
+
* Add some basic styles
|
|
12
|
+
* Resolve type on logical expressions
|
|
13
|
+
* **BC BREAK:** Function parameters are now passed in as objects (see [`ELParameter`](src/types.ts) for details)
|
package/README.md
CHANGED
|
@@ -50,27 +50,6 @@ yarn add @valtzu/codemirror-lang-el
|
|
|
50
50
|
|
|
51
51
|
```html
|
|
52
52
|
<div id="editor"></div>
|
|
53
|
-
<script type="importmap">
|
|
54
|
-
{
|
|
55
|
-
"imports": {
|
|
56
|
-
"codemirror": "https://esm.sh/*codemirror@6.0.1",
|
|
57
|
-
"@codemirror/state": "https://esm.sh/*@codemirror/state@6.4.1",
|
|
58
|
-
"@codemirror/search": "https://esm.sh/*@codemirror/search@6.5.6",
|
|
59
|
-
"@codemirror/autocomplete": "https://esm.sh/*@codemirror/autocomplete@6.9.0",
|
|
60
|
-
"@codemirror/view": "https://esm.sh/*@codemirror/view@6.17.1",
|
|
61
|
-
"@codemirror/commands": "https://esm.sh/*@codemirror/commands@6.2.5",
|
|
62
|
-
"@codemirror/language": "https://esm.sh/*@codemirror/language@6.9.0",
|
|
63
|
-
"@codemirror/lint": "https://esm.sh/*@codemirror/lint@6.4.1",
|
|
64
|
-
"@lezer/lr": "https://esm.sh/*@lezer/lr@1.3.9",
|
|
65
|
-
"@lezer/highlight": "https://esm.sh/*@lezer/highlight@1.1.6",
|
|
66
|
-
"@lezer/common": "https://esm.sh/*@lezer/common@1.2.1",
|
|
67
|
-
"style-mod": "https://esm.sh/*style-mod@4.1.2",
|
|
68
|
-
"w3c-keyname": "https://esm.sh/*w3c-keyname@2.2.8",
|
|
69
|
-
"crelt": "https://esm.sh/*crelt@1.0.6",
|
|
70
|
-
"@valtzu/codemirror-lang-el": "https://esm.sh/*@valtzu/codemirror-lang-el@0.4.2"
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
</script>
|
|
74
53
|
<script type="module">
|
|
75
54
|
import { EditorView, basicSetup } from "codemirror";
|
|
76
55
|
import { acceptCompletion } from "@codemirror/autocomplete";
|
|
@@ -103,7 +82,7 @@ yarn add @valtzu/codemirror-lang-el
|
|
|
103
82
|
{ name: "user", type: ["User"], info: 'This is the user' },
|
|
104
83
|
],
|
|
105
84
|
functions: [
|
|
106
|
-
{ name: "is_granted", args: ["
|
|
85
|
+
{ name: "is_granted", args: [{name: "attributes", type: ["string"]}, {name: "object", type: ["object"], optional: true}], info: 'Check if subject has permission to the object', returnType: ['bool'] },
|
|
107
86
|
],
|
|
108
87
|
})
|
|
109
88
|
],
|
|
@@ -111,13 +90,6 @@ yarn add @valtzu/codemirror-lang-el
|
|
|
111
90
|
doc: 'is_granted(user, user.self.getGroup())',
|
|
112
91
|
});
|
|
113
92
|
</script>
|
|
114
|
-
<style>
|
|
115
|
-
.cm-completionDetail {
|
|
116
|
-
float: right;
|
|
117
|
-
opacity: 0.5;
|
|
118
|
-
font-style: inherit !important;
|
|
119
|
-
}
|
|
120
|
-
</style>
|
|
121
93
|
```
|
|
122
94
|
|
|
123
95
|
### Contributing
|
package/dist/complete.cjs
CHANGED
|
@@ -5,12 +5,20 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var autocomplete = require('@codemirror/autocomplete');
|
|
6
6
|
var language = require('@codemirror/language');
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
var ELScalar;
|
|
9
|
+
(function (ELScalar) {
|
|
10
|
+
ELScalar["Bool"] = "bool";
|
|
11
|
+
ELScalar["Number"] = "number";
|
|
12
|
+
ELScalar["String"] = "string";
|
|
13
|
+
ELScalar["Null"] = "null";
|
|
14
|
+
ELScalar["Any"] = "any";
|
|
15
|
+
})(ELScalar || (ELScalar = {}));
|
|
16
|
+
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
const t = {
|
|
19
|
+
deserialize: (str) => str,
|
|
13
20
|
};
|
|
21
|
+
|
|
14
22
|
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); };
|
|
15
23
|
const resolveIdentifier = (nodeName, identifier, config) => {
|
|
16
24
|
var _a;
|
|
@@ -24,12 +32,16 @@ const resolveIdentifier = (nodeName, identifier, config) => {
|
|
|
24
32
|
}
|
|
25
33
|
};
|
|
26
34
|
function resolveTypes(state, node, config, matchExact) {
|
|
27
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
35
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
28
36
|
let types = new Set();
|
|
29
37
|
if (!node) {
|
|
30
38
|
return types;
|
|
31
39
|
}
|
|
32
|
-
|
|
40
|
+
let type;
|
|
41
|
+
if (typeof (type = node.type.prop(t)) !== "undefined") {
|
|
42
|
+
types.add(type);
|
|
43
|
+
}
|
|
44
|
+
else if (node.name === 'Call' && node.firstChild && node.lastChild) {
|
|
33
45
|
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
34
46
|
}
|
|
35
47
|
else if (node.name === 'Variable') {
|
|
@@ -65,17 +77,32 @@ function resolveTypes(state, node, config, matchExact) {
|
|
|
65
77
|
resolveTypes(state, node.firstChild.nextSibling, config).forEach(x => types.add(x));
|
|
66
78
|
resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
|
|
67
79
|
}
|
|
68
|
-
else if (node.name === 'BinaryExpression' && ((
|
|
80
|
+
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)) {
|
|
69
81
|
const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
|
|
70
|
-
if (operator == '?:' || operator == '??') {
|
|
71
|
-
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
72
|
-
}
|
|
73
82
|
if (operator == '?:' || operator == '??' || operator == '?') {
|
|
74
|
-
|
|
83
|
+
if (operator == '?:' || operator == '??') {
|
|
84
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
85
|
+
}
|
|
86
|
+
resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
|
|
87
|
+
}
|
|
88
|
+
else if (['||', '&&', '==', '!=', '===', '!==', '>=', '<=', '>', '<'].includes(operator) || keywords.find(x => x.name == operator)) {
|
|
89
|
+
types.add(ELScalar.Bool);
|
|
90
|
+
}
|
|
91
|
+
else if (['**', '|', '^', '&', '<<', '>>', '+', '-', '*', '/', '%'].includes(operator)) {
|
|
92
|
+
types.add(ELScalar.Number);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else if (node.name === 'UnaryExpression' && node.firstChild) {
|
|
96
|
+
const operator = state.sliceDoc(node.firstChild.from, node.firstChild.to);
|
|
97
|
+
if (['not', '!'].includes(operator)) {
|
|
98
|
+
types.add(ELScalar.Bool);
|
|
99
|
+
}
|
|
100
|
+
else if (['+', '-'].includes(operator)) {
|
|
101
|
+
types.add(ELScalar.Number);
|
|
75
102
|
}
|
|
76
103
|
}
|
|
77
104
|
if (types.size === 0) {
|
|
78
|
-
types.add(
|
|
105
|
+
types.add(ELScalar.Any);
|
|
79
106
|
}
|
|
80
107
|
return types;
|
|
81
108
|
}
|
|
@@ -92,18 +119,19 @@ const keywords = [
|
|
|
92
119
|
{ name: 'not' },
|
|
93
120
|
{ name: 'or' },
|
|
94
121
|
{ name: 'and' },
|
|
122
|
+
{ name: 'xor' },
|
|
95
123
|
];
|
|
96
124
|
|
|
97
125
|
const autocompleteFunction = (x) => {
|
|
98
|
-
var _a, _b;
|
|
126
|
+
var _a, _b, _c;
|
|
99
127
|
return ({
|
|
100
|
-
label: `${x.name}(${((_a = x.args) === null || _a === void 0 ? void 0 : _a.join(',')) || ''})`,
|
|
128
|
+
label: `${x.name}(${((_b = (_a = x.args) === null || _a === void 0 ? void 0 : _a.map(x => x.name)) === null || _b === void 0 ? void 0 : _b.join(',')) || ''})`,
|
|
101
129
|
apply: (view, completion, from, to) => {
|
|
102
130
|
var _a;
|
|
103
131
|
view.dispatch(Object.assign(Object.assign({}, autocomplete.insertCompletionText(view.state, `${x.name}()`, from, to)), { selection: { anchor: from + x.name.length + (((_a = x.args) === null || _a === void 0 ? void 0 : _a.length) > 0 ? 1 : 2) } }));
|
|
104
132
|
},
|
|
105
|
-
detail: (
|
|
106
|
-
info:
|
|
133
|
+
detail: (_c = x.returnType) === null || _c === void 0 ? void 0 : _c.join('|'),
|
|
134
|
+
info: x.info,
|
|
107
135
|
type: "function",
|
|
108
136
|
});
|
|
109
137
|
};
|
|
@@ -112,7 +140,7 @@ const autocompleteIdentifier = (x) => {
|
|
|
112
140
|
return ({
|
|
113
141
|
label: x.name,
|
|
114
142
|
apply: x.name,
|
|
115
|
-
info:
|
|
143
|
+
info: x.info,
|
|
116
144
|
detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')),
|
|
117
145
|
type: 'variable',
|
|
118
146
|
});
|
|
@@ -122,7 +150,13 @@ function completeOperatorKeyword(state, config, tree, from, to, explicit) {
|
|
|
122
150
|
return {
|
|
123
151
|
from,
|
|
124
152
|
to,
|
|
125
|
-
options: (_a = keywords.map(({ name, info, detail }) => ({
|
|
153
|
+
options: (_a = keywords.map(({ name, info, detail }) => ({
|
|
154
|
+
label: name,
|
|
155
|
+
apply: `${name} `,
|
|
156
|
+
info: info,
|
|
157
|
+
detail,
|
|
158
|
+
type: "keyword"
|
|
159
|
+
}))) !== null && _a !== void 0 ? _a : [],
|
|
126
160
|
validFor: (text) => { var _a; return (_a = keywords.some(({ name }) => explicit || name.includes(text))) !== null && _a !== void 0 ? _a : false; },
|
|
127
161
|
};
|
|
128
162
|
}
|
|
@@ -167,7 +201,7 @@ function expressionLanguageCompletion(context) {
|
|
|
167
201
|
const config = getExpressionLanguageConfig(state);
|
|
168
202
|
const isIdentifier = (node) => { var _a; return ['Variable', 'Function'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
|
|
169
203
|
const isMember = (node) => { var _a; return ['Property', 'Method'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
|
|
170
|
-
if (prevNode.name == 'String') {
|
|
204
|
+
if (prevNode.name == 'String' || prevNode.name == 'BlockComment') {
|
|
171
205
|
return null;
|
|
172
206
|
}
|
|
173
207
|
if (((_a = prevNode.parent) === null || _a === void 0 ? void 0 : _a.name) == 'ObjectAccess' && ['ObjectAccess', 'ArrayAccess', 'Variable', 'Call', 'Application'].includes(((_b = prevNode.parent.firstChild) === null || _b === void 0 ? void 0 : _b.name) || '')) {
|
package/dist/complete.js
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import { insertCompletionText } from '@codemirror/autocomplete';
|
|
2
2
|
import { syntaxTree } from '@codemirror/language';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
var ELScalar;
|
|
5
|
+
(function (ELScalar) {
|
|
6
|
+
ELScalar["Bool"] = "bool";
|
|
7
|
+
ELScalar["Number"] = "number";
|
|
8
|
+
ELScalar["String"] = "string";
|
|
9
|
+
ELScalar["Null"] = "null";
|
|
10
|
+
ELScalar["Any"] = "any";
|
|
11
|
+
})(ELScalar || (ELScalar = {}));
|
|
12
|
+
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
const t = {
|
|
15
|
+
deserialize: (str) => str,
|
|
9
16
|
};
|
|
17
|
+
|
|
10
18
|
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); };
|
|
11
19
|
const resolveIdentifier = (nodeName, identifier, config) => {
|
|
12
20
|
var _a;
|
|
@@ -20,12 +28,16 @@ const resolveIdentifier = (nodeName, identifier, config) => {
|
|
|
20
28
|
}
|
|
21
29
|
};
|
|
22
30
|
function resolveTypes(state, node, config, matchExact) {
|
|
23
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
31
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
24
32
|
let types = new Set();
|
|
25
33
|
if (!node) {
|
|
26
34
|
return types;
|
|
27
35
|
}
|
|
28
|
-
|
|
36
|
+
let type;
|
|
37
|
+
if (typeof (type = node.type.prop(t)) !== "undefined") {
|
|
38
|
+
types.add(type);
|
|
39
|
+
}
|
|
40
|
+
else if (node.name === 'Call' && node.firstChild && node.lastChild) {
|
|
29
41
|
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
30
42
|
}
|
|
31
43
|
else if (node.name === 'Variable') {
|
|
@@ -61,17 +73,32 @@ function resolveTypes(state, node, config, matchExact) {
|
|
|
61
73
|
resolveTypes(state, node.firstChild.nextSibling, config).forEach(x => types.add(x));
|
|
62
74
|
resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
|
|
63
75
|
}
|
|
64
|
-
else if (node.name === 'BinaryExpression' && ((
|
|
76
|
+
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)) {
|
|
65
77
|
const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
|
|
66
|
-
if (operator == '?:' || operator == '??') {
|
|
67
|
-
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
68
|
-
}
|
|
69
78
|
if (operator == '?:' || operator == '??' || operator == '?') {
|
|
70
|
-
|
|
79
|
+
if (operator == '?:' || operator == '??') {
|
|
80
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
81
|
+
}
|
|
82
|
+
resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
|
|
83
|
+
}
|
|
84
|
+
else if (['||', '&&', '==', '!=', '===', '!==', '>=', '<=', '>', '<'].includes(operator) || keywords.find(x => x.name == operator)) {
|
|
85
|
+
types.add(ELScalar.Bool);
|
|
86
|
+
}
|
|
87
|
+
else if (['**', '|', '^', '&', '<<', '>>', '+', '-', '*', '/', '%'].includes(operator)) {
|
|
88
|
+
types.add(ELScalar.Number);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else if (node.name === 'UnaryExpression' && node.firstChild) {
|
|
92
|
+
const operator = state.sliceDoc(node.firstChild.from, node.firstChild.to);
|
|
93
|
+
if (['not', '!'].includes(operator)) {
|
|
94
|
+
types.add(ELScalar.Bool);
|
|
95
|
+
}
|
|
96
|
+
else if (['+', '-'].includes(operator)) {
|
|
97
|
+
types.add(ELScalar.Number);
|
|
71
98
|
}
|
|
72
99
|
}
|
|
73
100
|
if (types.size === 0) {
|
|
74
|
-
types.add(
|
|
101
|
+
types.add(ELScalar.Any);
|
|
75
102
|
}
|
|
76
103
|
return types;
|
|
77
104
|
}
|
|
@@ -88,18 +115,19 @@ const keywords = [
|
|
|
88
115
|
{ name: 'not' },
|
|
89
116
|
{ name: 'or' },
|
|
90
117
|
{ name: 'and' },
|
|
118
|
+
{ name: 'xor' },
|
|
91
119
|
];
|
|
92
120
|
|
|
93
121
|
const autocompleteFunction = (x) => {
|
|
94
|
-
var _a, _b;
|
|
122
|
+
var _a, _b, _c;
|
|
95
123
|
return ({
|
|
96
|
-
label: `${x.name}(${((_a = x.args) === null || _a === void 0 ? void 0 : _a.join(',')) || ''})`,
|
|
124
|
+
label: `${x.name}(${((_b = (_a = x.args) === null || _a === void 0 ? void 0 : _a.map(x => x.name)) === null || _b === void 0 ? void 0 : _b.join(',')) || ''})`,
|
|
97
125
|
apply: (view, completion, from, to) => {
|
|
98
126
|
var _a;
|
|
99
127
|
view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, `${x.name}()`, from, to)), { selection: { anchor: from + x.name.length + (((_a = x.args) === null || _a === void 0 ? void 0 : _a.length) > 0 ? 1 : 2) } }));
|
|
100
128
|
},
|
|
101
|
-
detail: (
|
|
102
|
-
info:
|
|
129
|
+
detail: (_c = x.returnType) === null || _c === void 0 ? void 0 : _c.join('|'),
|
|
130
|
+
info: x.info,
|
|
103
131
|
type: "function",
|
|
104
132
|
});
|
|
105
133
|
};
|
|
@@ -108,7 +136,7 @@ const autocompleteIdentifier = (x) => {
|
|
|
108
136
|
return ({
|
|
109
137
|
label: x.name,
|
|
110
138
|
apply: x.name,
|
|
111
|
-
info:
|
|
139
|
+
info: x.info,
|
|
112
140
|
detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')),
|
|
113
141
|
type: 'variable',
|
|
114
142
|
});
|
|
@@ -118,7 +146,13 @@ function completeOperatorKeyword(state, config, tree, from, to, explicit) {
|
|
|
118
146
|
return {
|
|
119
147
|
from,
|
|
120
148
|
to,
|
|
121
|
-
options: (_a = keywords.map(({ name, info, detail }) => ({
|
|
149
|
+
options: (_a = keywords.map(({ name, info, detail }) => ({
|
|
150
|
+
label: name,
|
|
151
|
+
apply: `${name} `,
|
|
152
|
+
info: info,
|
|
153
|
+
detail,
|
|
154
|
+
type: "keyword"
|
|
155
|
+
}))) !== null && _a !== void 0 ? _a : [],
|
|
122
156
|
validFor: (text) => { var _a; return (_a = keywords.some(({ name }) => explicit || name.includes(text))) !== null && _a !== void 0 ? _a : false; },
|
|
123
157
|
};
|
|
124
158
|
}
|
|
@@ -163,7 +197,7 @@ function expressionLanguageCompletion(context) {
|
|
|
163
197
|
const config = getExpressionLanguageConfig(state);
|
|
164
198
|
const isIdentifier = (node) => { var _a; return ['Variable', 'Function'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
|
|
165
199
|
const isMember = (node) => { var _a; return ['Property', 'Method'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
|
|
166
|
-
if (prevNode.name == 'String') {
|
|
200
|
+
if (prevNode.name == 'String' || prevNode.name == 'BlockComment') {
|
|
167
201
|
return null;
|
|
168
202
|
}
|
|
169
203
|
if (((_a = prevNode.parent) === null || _a === void 0 ? void 0 : _a.name) == 'ObjectAccess' && ['ObjectAccess', 'ArrayAccess', 'Variable', 'Call', 'Application'].includes(((_b = prevNode.parent.firstChild) === null || _b === void 0 ? void 0 : _b.name) || '')) {
|
package/dist/index.cjs
CHANGED
|
@@ -10,25 +10,42 @@ var autocomplete = require('@codemirror/autocomplete');
|
|
|
10
10
|
var state = require('@codemirror/state');
|
|
11
11
|
var view = require('@codemirror/view');
|
|
12
12
|
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
const t = {
|
|
15
|
+
deserialize: (str) => str,
|
|
16
|
+
};
|
|
17
|
+
|
|
13
18
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
14
|
-
const spec_word = {__proto__:null,true:
|
|
15
|
-
const spec_Operator = {__proto__:null,"?":
|
|
19
|
+
const spec_word = {__proto__:null,true:92, TRUE:94, false:96, FALSE:98, null:100, NULL:102, starts:112, with:114, ends:116, contains:118, matches:120, not:122, in:124, and:126, or:128, xor:130};
|
|
20
|
+
const spec_Operator = {__proto__:null,"?":111, "!":133, "~":135, "+":137, "-":139};
|
|
16
21
|
const parser = lr.LRParser.deserialize({
|
|
17
22
|
version: 14,
|
|
18
|
-
states: "
|
|
19
|
-
stateData: "
|
|
20
|
-
goto: "%
|
|
21
|
-
nodeNames: "⚠ Expression ObjectAccess MemberOf NullSafeMemberOf Property ArrayAccess Call Function Arguments ObjectAccess Method Arguments Number String Boolean Null Object Array Variable TernaryExpression Operator BinaryExpression OperatorKeyword UnaryExpression UnaryOperator Application",
|
|
22
|
-
maxTerm:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
states: ")rOYQPOOP!aOPOOQ!fQPOOO#dQPO'#CeO$wQPO'#CnO%OQPO'#CoOYQPO'#CuOYQPO'#CwOOQO'#DS'#DSO%VQPO'#CdO%[QPO'#CdOOQO'#Cl'#ClOOQO'#Cm'#CmOOQO'#Cv'#CvP%aOQO'#C]POOO)C>r)C>rO%lQPO,58yOYQPO,58}OYQPO,59_OYQPO,59]O%qQPO'#CtOOQO'#Ct'#CtO%vQPO'#CtO'QQPO,59YOOQO,59Y,59YO'XQPO'#DYO'fQPO,59ZO'kQPO,59aO(RQPO,59cO(YQPO'#CfOOQO,59O,59OO(YQPO'#CiPOOO'#Cx'#CxP(aOQO,58wPOOO,58w,58wO(lQPO'#CbOOQO1G.e1G.eOOQO1G.m1G.mO*PQPO1G.iO*WQPO1G.yO*nQPO1G.wOOQO,59`,59`OYQPO1G.tOYQPO'#CyO*uQPO,59tOOQO1G.u1G.uOOQO1G.}1G.}O+QQPO,59QO+VQPO,59TPOOO-E6v-E6vPOOO1G.c1G.cOOQO7+$T7+$TOYQPO7+$cO+[QPO7+$`O+fQPO,59eOOQO-E6w-E6wOOQO1G.l1G.lOOQO1G.o1G.oO+sQPO<<G}OYQPO'#CzO,ZQPO<<GzOOQO<<Gz<<GzO,cQPO,59fOOQO-E6x-E6xOOQOAN=fAN=fOYQPO1G/QO,jQPO7+$l",
|
|
24
|
+
stateData: ",|~OqOSrPQ~O^WO_WOwROyTO{VO!OZO!PZO!QZO!RZO!S[O!T[O!VSO!_]O!d]O!e]O!f]O!g]O~Or^O~OS`OT`OfbOyaO!XcO!YdO![dO!]eO!^eO!_fO!`eO!aeO!beO!ceO~OSdXTdXfdXodXydX{XX!XdX!YdX![dX!]dX!^dX!_dX!`dX!adX!bdX!cdX!WdXxdX}dXzdX!UdX~O!UhO~PYOx|P~PYO{mO~O{oO~OspOtpOurO~OwsO~O!ZyO~O!`yO^hX_hXwhXyhX{hX!OhX!PhX!QhX!RhX!ShX!ThX!VhX!_hX!dhX!ehX!fhX!ghX~O!WzO~P!fO}{Ox|Xz|X~P!fOx}O~Ooia!Wiaxia}iazia!Uia~P!fOz!OO~P!fOz|P~PYOspOtpOu!SO~OSUXTUXfUXoUXyUX{[X!XUX!YUX![UX!]UX!^UX!_UX!`UX!aUX!bUX!cUX!WUXxUX}UXzUX!UUX~Ox!TO~P!fOogi!Wgixgi}gizgi!Ugi~P!fO!W!UO~P!fO}{Ox|az|a~Oz!YO~Oz!ZO~O}!]O!U!_O~P!fOxma}mazma~P!fOoey!Weyxey}eyzey!Uey~P!fO}!]O!U!bO~O!W!cO~P!fO}nq!Unq~P!fO_TfS^wS~",
|
|
25
|
+
goto: "%l}P!OP!RPP!d!R!R!g!x!{#^#aPP!R!R!R!R!R!RP!R#d!R#s!R$U$[$bPPPPPPP$hPPPPP%cR_PoWOSTUVabcmoz{!U!]!cRt`oXOSTUVabcmoz{!U!]!cRnXoYOSTUVabcmoz{!U!]!cRu`RnYkbQgiklvwx!V!W![!`!doUOSTUVabcmoz{!U!]!cQq^R!RqQ|iR!X|Q!^!VR!a!^QQOQgSUiTmoQkUQlVQvaQwbQxcQ!VzQ!W{Q![!UQ!`!]R!d!cQjTQ!PmR!Qo",
|
|
26
|
+
nodeNames: "⚠ BlockComment Expression ObjectAccess MemberOf NullSafeMemberOf Property ArrayAccess Call Function Arguments ObjectAccess Method Arguments Number String Boolean Null Object Array Variable TernaryExpression Operator BinaryExpression OperatorKeyword UnaryExpression UnaryOperator Application",
|
|
27
|
+
maxTerm: 69,
|
|
28
|
+
nodeProps: [
|
|
29
|
+
[t, 14,"number",15,"string",16,"bool",17,"null",18,"object",19,"array"]
|
|
30
|
+
],
|
|
31
|
+
skippedNodes: [0,1,28],
|
|
32
|
+
repeatNodeCount: 3,
|
|
33
|
+
tokenData: "-a~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!},b!}#O,s#P#Q,x#Q#R#{#R#S,b#T#o,b#o#p,}#p#q-S#q#r-[#r#s#{~#_Sq~XY#YYZ#Y]^#Ypq#Y~#pPf~!_!`#s~#xPf~!_!`#{~$QOf~~$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~&PPf~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~~(WPf~z{#{~(`O}~~(ePS~!O!P#{~(mPf~z{(p~(uOr~~(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~~+fQf~!^!_#{!_!`#{~+oP!_!`#s~+wQf~!_!`#{!`!a#{~,SRf~!O!P,]![!]#{!a!b#{~,bOT~~,gSw~!Q![,b!c!},b#R#S,b#T#o,b~,xOy~~,}Ox~~-SO!V~~-XPf~#p#q#{~-aO!U~",
|
|
34
|
+
tokenizers: [1, new lr.LocalTokenGroup("j~RQYZXz{^~^Ot~~aP!P!Qd~iOu~~", 25, 35)],
|
|
35
|
+
topRules: {"Expression":[0,2]},
|
|
36
|
+
specialized: [{term: 39, get: (value) => spec_word[value] || -1},{term: 22, get: (value) => spec_Operator[value] || -1}],
|
|
37
|
+
tokenPrec: 542
|
|
30
38
|
});
|
|
31
39
|
|
|
40
|
+
var ELScalar;
|
|
41
|
+
(function (ELScalar) {
|
|
42
|
+
ELScalar["Bool"] = "bool";
|
|
43
|
+
ELScalar["Number"] = "number";
|
|
44
|
+
ELScalar["String"] = "string";
|
|
45
|
+
ELScalar["Null"] = "null";
|
|
46
|
+
ELScalar["Any"] = "any";
|
|
47
|
+
})(ELScalar || (ELScalar = {}));
|
|
48
|
+
|
|
32
49
|
const createInfoElement = (html) => {
|
|
33
50
|
const dom = document.createElement("div");
|
|
34
51
|
dom.innerHTML = html;
|
|
@@ -65,12 +82,16 @@ const resolveIdentifier = (nodeName, identifier, config) => {
|
|
|
65
82
|
}
|
|
66
83
|
};
|
|
67
84
|
function resolveTypes(state, node, config, matchExact) {
|
|
68
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
85
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
69
86
|
let types = new Set();
|
|
70
87
|
if (!node) {
|
|
71
88
|
return types;
|
|
72
89
|
}
|
|
73
|
-
|
|
90
|
+
let type;
|
|
91
|
+
if (typeof (type = node.type.prop(t)) !== "undefined") {
|
|
92
|
+
types.add(type);
|
|
93
|
+
}
|
|
94
|
+
else if (node.name === 'Call' && node.firstChild && node.lastChild) {
|
|
74
95
|
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
75
96
|
}
|
|
76
97
|
else if (node.name === 'Variable') {
|
|
@@ -106,17 +127,32 @@ function resolveTypes(state, node, config, matchExact) {
|
|
|
106
127
|
resolveTypes(state, node.firstChild.nextSibling, config).forEach(x => types.add(x));
|
|
107
128
|
resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
|
|
108
129
|
}
|
|
109
|
-
else if (node.name === 'BinaryExpression' && ((
|
|
130
|
+
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)) {
|
|
110
131
|
const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
|
|
111
|
-
if (operator == '?:' || operator == '??') {
|
|
112
|
-
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
113
|
-
}
|
|
114
132
|
if (operator == '?:' || operator == '??' || operator == '?') {
|
|
115
|
-
|
|
133
|
+
if (operator == '?:' || operator == '??') {
|
|
134
|
+
resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
|
|
135
|
+
}
|
|
136
|
+
resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
|
|
137
|
+
}
|
|
138
|
+
else if (['||', '&&', '==', '!=', '===', '!==', '>=', '<=', '>', '<'].includes(operator) || keywords.find(x => x.name == operator)) {
|
|
139
|
+
types.add(ELScalar.Bool);
|
|
140
|
+
}
|
|
141
|
+
else if (['**', '|', '^', '&', '<<', '>>', '+', '-', '*', '/', '%'].includes(operator)) {
|
|
142
|
+
types.add(ELScalar.Number);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else if (node.name === 'UnaryExpression' && node.firstChild) {
|
|
146
|
+
const operator = state.sliceDoc(node.firstChild.from, node.firstChild.to);
|
|
147
|
+
if (['not', '!'].includes(operator)) {
|
|
148
|
+
types.add(ELScalar.Bool);
|
|
149
|
+
}
|
|
150
|
+
else if (['+', '-'].includes(operator)) {
|
|
151
|
+
types.add(ELScalar.Number);
|
|
116
152
|
}
|
|
117
153
|
}
|
|
118
154
|
if (types.size === 0) {
|
|
119
|
-
types.add(
|
|
155
|
+
types.add(ELScalar.Any);
|
|
120
156
|
}
|
|
121
157
|
return types;
|
|
122
158
|
}
|
|
@@ -133,6 +169,7 @@ const keywords = [
|
|
|
133
169
|
{ name: 'not' },
|
|
134
170
|
{ name: 'or' },
|
|
135
171
|
{ name: 'and' },
|
|
172
|
+
{ name: 'xor' },
|
|
136
173
|
];
|
|
137
174
|
|
|
138
175
|
/**
|
|
@@ -165,13 +202,20 @@ const expressionLanguageLinterSource = (state) => {
|
|
|
165
202
|
if (!args) {
|
|
166
203
|
return;
|
|
167
204
|
}
|
|
168
|
-
let i = 0;
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
205
|
+
for (let n = node.node.firstChild, i = 0; n != null; n = n.nextSibling) {
|
|
206
|
+
if (n.name === 'BlockComment') {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
if (i > args.length - 1) {
|
|
172
210
|
diagnostics.push({ from: n.from, to: n.to, severity: 'error', message: `Unexpected argument` });
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const typesUsed = Array.from(resolveTypes(state, n, config));
|
|
214
|
+
const typesExpected = args[i].type;
|
|
215
|
+
if (typesExpected && !typesExpected.includes(ELScalar.Any) && !typesUsed.some(x => typesExpected.includes(x))) {
|
|
216
|
+
diagnostics.push({ from: n.from, to: n.to, severity: 'error', message: `<code>${typesExpected.join('|')}</code> expected, got <code>${typesUsed.join('|')}</code>` });
|
|
173
217
|
}
|
|
174
|
-
|
|
218
|
+
i++;
|
|
175
219
|
}
|
|
176
220
|
break;
|
|
177
221
|
case 'Property':
|
|
@@ -195,20 +239,27 @@ const expressionLanguageLinterSource = (state) => {
|
|
|
195
239
|
diagnostics.push({ from, to, severity: 'error', message: `Unexpected identifier "${identifier}"` });
|
|
196
240
|
}
|
|
197
241
|
});
|
|
242
|
+
diagnostics.forEach(d => {
|
|
243
|
+
d.renderMessage = () => {
|
|
244
|
+
const span = document.createElement('span');
|
|
245
|
+
span.innerHTML = d.message;
|
|
246
|
+
return span;
|
|
247
|
+
};
|
|
248
|
+
});
|
|
198
249
|
return diagnostics;
|
|
199
250
|
};
|
|
200
251
|
const expressionLanguageLinter = lint.linter(view => expressionLanguageLinterSource(view.state));
|
|
201
252
|
|
|
202
253
|
const autocompleteFunction = (x) => {
|
|
203
|
-
var _a, _b;
|
|
254
|
+
var _a, _b, _c;
|
|
204
255
|
return ({
|
|
205
|
-
label: `${x.name}(${((_a = x.args) === null || _a === void 0 ? void 0 : _a.join(',')) || ''})`,
|
|
256
|
+
label: `${x.name}(${((_b = (_a = x.args) === null || _a === void 0 ? void 0 : _a.map(x => x.name)) === null || _b === void 0 ? void 0 : _b.join(',')) || ''})`,
|
|
206
257
|
apply: (view, completion, from, to) => {
|
|
207
258
|
var _a;
|
|
208
259
|
view.dispatch(Object.assign(Object.assign({}, autocomplete.insertCompletionText(view.state, `${x.name}()`, from, to)), { selection: { anchor: from + x.name.length + (((_a = x.args) === null || _a === void 0 ? void 0 : _a.length) > 0 ? 1 : 2) } }));
|
|
209
260
|
},
|
|
210
|
-
detail: (
|
|
211
|
-
info:
|
|
261
|
+
detail: (_c = x.returnType) === null || _c === void 0 ? void 0 : _c.join('|'),
|
|
262
|
+
info: x.info,
|
|
212
263
|
type: "function",
|
|
213
264
|
});
|
|
214
265
|
};
|
|
@@ -217,7 +268,7 @@ const autocompleteIdentifier = (x) => {
|
|
|
217
268
|
return ({
|
|
218
269
|
label: x.name,
|
|
219
270
|
apply: x.name,
|
|
220
|
-
info:
|
|
271
|
+
info: x.info,
|
|
221
272
|
detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')),
|
|
222
273
|
type: 'variable',
|
|
223
274
|
});
|
|
@@ -227,7 +278,13 @@ function completeOperatorKeyword(state, config, tree, from, to, explicit) {
|
|
|
227
278
|
return {
|
|
228
279
|
from,
|
|
229
280
|
to,
|
|
230
|
-
options: (_a = keywords.map(({ name, info, detail }) => ({
|
|
281
|
+
options: (_a = keywords.map(({ name, info, detail }) => ({
|
|
282
|
+
label: name,
|
|
283
|
+
apply: `${name} `,
|
|
284
|
+
info: info,
|
|
285
|
+
detail,
|
|
286
|
+
type: "keyword"
|
|
287
|
+
}))) !== null && _a !== void 0 ? _a : [],
|
|
231
288
|
validFor: (text) => { var _a; return (_a = keywords.some(({ name }) => explicit || name.includes(text))) !== null && _a !== void 0 ? _a : false; },
|
|
232
289
|
};
|
|
233
290
|
}
|
|
@@ -272,7 +329,7 @@ function expressionLanguageCompletion(context) {
|
|
|
272
329
|
const config = getExpressionLanguageConfig(state);
|
|
273
330
|
const isIdentifier = (node) => { var _a; return ['Variable', 'Function'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
|
|
274
331
|
const isMember = (node) => { var _a; return ['Property', 'Method'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
|
|
275
|
-
if (prevNode.name == 'String') {
|
|
332
|
+
if (prevNode.name == 'String' || prevNode.name == 'BlockComment') {
|
|
276
333
|
return null;
|
|
277
334
|
}
|
|
278
335
|
if (((_a = prevNode.parent) === null || _a === void 0 ? void 0 : _a.name) == 'ObjectAccess' && ['ObjectAccess', 'ArrayAccess', 'Variable', 'Call', 'Application'].includes(((_b = prevNode.parent.firstChild) === null || _b === void 0 ? void 0 : _b.name) || '')) {
|
|
@@ -312,7 +369,7 @@ function getCursorTooltips(state) {
|
|
|
312
369
|
return state.selection.ranges
|
|
313
370
|
.filter(range => range.empty)
|
|
314
371
|
.map(range => {
|
|
315
|
-
var _a;
|
|
372
|
+
var _a, _b;
|
|
316
373
|
const tree = language.syntaxTree(state);
|
|
317
374
|
const node = tree.resolveInner(range.from, 0);
|
|
318
375
|
const args = resolveArguments(node);
|
|
@@ -324,7 +381,7 @@ function getCursorTooltips(state) {
|
|
|
324
381
|
return null;
|
|
325
382
|
}
|
|
326
383
|
const n = args.childAfter(range.from - 1);
|
|
327
|
-
const argName = (_a = fn.args) === null || _a === void 0 ? void 0 : _a[n ? getNodeOrdinal(n) : 0];
|
|
384
|
+
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;
|
|
328
385
|
if (n && n.from !== range.from || !argName) {
|
|
329
386
|
return null;
|
|
330
387
|
}
|
|
@@ -399,17 +456,34 @@ const keywordTooltip = view.hoverTooltip((view, pos, side) => {
|
|
|
399
456
|
create: () => ({ dom: createInfoElement(info) }),
|
|
400
457
|
};
|
|
401
458
|
});
|
|
402
|
-
|
|
459
|
+
|
|
460
|
+
const baseTheme = view.EditorView.baseTheme({
|
|
403
461
|
".cm-tooltip.cm-tooltip-cursor": {
|
|
404
462
|
boxShadow: 'rgba(0, 0, 0, .15) 0 1px 2px',
|
|
405
463
|
border: "1px solid rgba(127, 127, 127, .2)",
|
|
406
|
-
|
|
464
|
+
fontSize: ".85rem",
|
|
465
|
+
padding: ".4rem .5rem",
|
|
407
466
|
borderRadius: "4px",
|
|
408
467
|
"& .cm-tooltip-arrow:before": {},
|
|
409
468
|
"& .cm-tooltip-arrow:after": {
|
|
410
469
|
borderTopColor: "transparent"
|
|
411
|
-
}
|
|
412
|
-
}
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
".cm-tooltip.cm-completionInfo, .cm-diagnostic": {
|
|
473
|
+
boxShadow: "rgba(0, 0, 0, .15) 0 2px 5px",
|
|
474
|
+
fontSize: ".85rem",
|
|
475
|
+
padding: ".8rem !important", // Couldn't figure out other means to override https://github.com/codemirror/autocomplete/blob/6.18.1/src/theme.ts#L65
|
|
476
|
+
},
|
|
477
|
+
".cm-completionDetail": {
|
|
478
|
+
float: "right",
|
|
479
|
+
opacity: 0.5,
|
|
480
|
+
fontStyle: "inherit !important",
|
|
481
|
+
},
|
|
482
|
+
"code": {
|
|
483
|
+
fontSize: ".8em",
|
|
484
|
+
fontStyle: "monospace",
|
|
485
|
+
backgroundColor: "rgba(127, 127, 127, .3)",
|
|
486
|
+
},
|
|
413
487
|
});
|
|
414
488
|
|
|
415
489
|
const ELLanguage = language.LRLanguage.define({
|
|
@@ -443,6 +517,7 @@ const ELLanguage = language.LRLanguage.define({
|
|
|
443
517
|
OperatorKeyword: highlight.tags.operatorKeyword,
|
|
444
518
|
UnaryOperator: highlight.tags.operator,
|
|
445
519
|
Operator: highlight.tags.operator,
|
|
520
|
+
BlockComment: highlight.tags.comment,
|
|
446
521
|
})
|
|
447
522
|
]
|
|
448
523
|
}),
|
|
@@ -457,7 +532,7 @@ function expressionlanguage(config = {}, extensions = []) {
|
|
|
457
532
|
expressionLanguageLinter,
|
|
458
533
|
keywordTooltip,
|
|
459
534
|
cursorTooltipField,
|
|
460
|
-
|
|
535
|
+
baseTheme,
|
|
461
536
|
...extensions,
|
|
462
537
|
]);
|
|
463
538
|
}
|