@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 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: ["subject", "object"], info: 'Check if subject has permission to the object', returnType: ['bool'] },
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
- const createInfoElement = (html) => {
9
- const dom = document.createElement("div");
10
- dom.innerHTML = html;
11
- dom.className = 'cm-diagnostic';
12
- return dom;
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
- if (node.name === 'Call' && node.firstChild && node.lastChild) {
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' && ((_k = (_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) === null || _k === void 0 ? void 0 : _k.name) == 'Operator' && node.lastChild) {
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
- resolveTypes(state, node.lastChild, config).forEach(x => types.add(x));
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('any');
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: (_b = x.returnType) === null || _b === void 0 ? void 0 : _b.join('|'),
106
- info: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
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: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
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 }) => ({ label: name, apply: `${name} `, info, detail, type: "keyword" }))) !== null && _a !== void 0 ? _a : [],
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
- const createInfoElement = (html) => {
5
- const dom = document.createElement("div");
6
- dom.innerHTML = html;
7
- dom.className = 'cm-diagnostic';
8
- return dom;
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
- if (node.name === 'Call' && node.firstChild && node.lastChild) {
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' && ((_k = (_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) === null || _k === void 0 ? void 0 : _k.name) == 'Operator' && node.lastChild) {
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
- resolveTypes(state, node.lastChild, config).forEach(x => types.add(x));
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('any');
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: (_b = x.returnType) === null || _b === void 0 ? void 0 : _b.join('|'),
102
- info: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
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: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
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 }) => ({ label: name, apply: `${name} `, info, detail, type: "keyword" }))) !== null && _a !== void 0 ? _a : [],
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:80, false:82, null:84, starts:94, with:96, ends:98, contains:100, matches:102, not:104, in:106, and:108, or:110};
15
- const spec_Operator = {__proto__:null,"?":93, "!":113, "+":115, "-":117};
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: "(pOVQPOOQ!QQPOOO!{QPO'#CdO$]QPO'#CmO$dQPO'#CnOVQPO'#CtOVQPO'#CvOOQO'#C|'#C|O$kQPO'#CcO$pQPO'#CcOOQO'#Ck'#CkOOQO'#Cl'#ClOOQO'#Cu'#CuO$uQPO,58xOVQPO,58|OVQPO,59^OVQPO,59[O$zQPO'#CsOOQO'#Cs'#CsO%PQPO'#CsO%}QPO,59XOOQO,59X,59XO&UQPO'#DSO&cQPO,59YO&hQPO,59`O'OQPO,59bO'VQPO'#CeOOQO,58},58}O'VQPO'#ChO'^QPO'#CaOOQO1G.d1G.dOOQO1G.l1G.lO(nQPO1G.hO(uQPO1G.xO)]QPO1G.vOOQO,59_,59_OVQPO1G.sOVQPO'#CwO)dQPO,59nOOQO1G.t1G.tOOQO1G.|1G.|O)oQPO,59PO)tQPO,59SOOQO7+$S7+$SOVQPO7+$bO)yQPO7+$_O*TQPO,59cOOQO-E6u-E6uOOQO1G.k1G.kOOQO1G.n1G.nO*bQPO<<G|OVQPO'#CxO*xQPO<<GyOOQO<<Gy<<GyO+QQPO,59dOOQO-E6v-E6vOOQOAN=eAN=eOVQPO1G/OO+XQPO7+$j",
19
- stateData: "+k~OoOS~O]VO^VOqQOsSOuUOxYOyYOzZO|RO!U[O!Y[O!Z[O![[O~OR]OS]Oe_Os^O!O`O!PaO!RaO!SbO!TbO!UcO!VbO!WbO!XbO~ORcXScXecXmcXscXuWX!OcX!PcX!RcX!ScX!TcX!UcX!VcX!WcX!XcX}cXrcXwcXtcX{cX~O{eO~PVOrvP~PVOujO~OulO~OqmO~O!QsO~O!VsO]gX^gXqgXsgXugXxgXygXzgX|gX!UgX!YgX!ZgX![gX~O}tO~P!QOwuOrvXtvX~P!QOrwO~Omha}harhawhatha{ha~P!QOtxO~P!QOtvP~PVORTXSTXeTXmTXsTXuZX!OTX!PTX!RTX!STX!TTX!UTX!VTX!WTX!XTX}TXrTXwTXtTX{TX~Or{O~P!QOmfi}firfiwfitfi{fi~P!QO}|O~P!QOwuOrvatva~Ot!QO~Ot!RO~Ow!TO{!VO~P!QOrkawkatka~P!QOmdy}dyrdywdytdy{dy~P!QOw!TO{!YO~O}!ZO~P!QOwlq{lq~P!QO^SeR]qR~",
20
- goto: "%]wPPxPP!Zxx!^!o!r#T#WPPxxxxxxPx#Zx#jx#{$RPPP$XPPPPP%SoVORSTU^_`jltu|!T!ZRn]oWORSTU^_`jltu|!T!ZRkWoXORSTU^_`jltu|!T!ZRo]RkXk_Pdfhipqr}!O!S!W![oTORSTU^_`jltu|!T!ZQvfR!PvQ!U}R!X!UQPOQdRUfSjlQhTQiUQp^Qq_Qr`Q}tQ!OuQ!S|Q!W!TR![!ZQgSQyjRzl",
21
- nodeNames: "⚠ Expression ObjectAccess MemberOf NullSafeMemberOf Property ArrayAccess Call Function Arguments ObjectAccess Method Arguments Number String Boolean Null Object Array Variable TernaryExpression Operator BinaryExpression OperatorKeyword UnaryExpression UnaryOperator Application",
22
- maxTerm: 58,
23
- skippedNodes: [0],
24
- repeatNodeCount: 2,
25
- tokenData: ",l~RqXY#YYZ#Y]^#Ypq#Yqr#krs$Quv#{vw%zwx&Sxy'wyz'|z{(R{|#{|}(Z}!O#{!O!P(`!P!Q#{!Q![(h![!]*}!^!_#s!_!`+S!`!a#s!a!b+Y!c!}+m!}#O,O#P#Q,T#Q#R#{#R#S+m#T#o+m#o#p,Y#p#q,_#q#r,g#r#s#{~#_So~XY#YYZ#Y]^#Ypq#Y~#pPe~!_!`#s~#xPe~!_!`#{~$QOe~~$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~&PPe~vw#{~&VXOw&Swx$px#O&S#O#P&r#P;'S&S;'S;=`'q<%l~&S~O&S~~$p~&uRO;'S&S;'S;=`'O;=`O&S~'RYOw&Swx$px#O&S#O#P&r#P;'S&S;'S;=`'q;=`<%l&S<%l~&S~O&S~~$p~'tP;=`<%l&S~'|Ou~~(ROt~~(WPe~z{#{~(`Ow~~(ePR~!O!P#{~(mT]~!O!P(|!Q![(h!g!h)|#R#S*w#X#Y)|~)PSO!O)]!P;'S)];'S;=`*q<%lO)]~)bR]~!Q![)k!g!h)|#X#Y)|~)pS]~!Q![)k!g!h)|#R#S*k#X#Y)|~*PR{|*Y}!O*Y!Q![*`~*]P!Q![*`~*eQ]~!Q![*`#R#S*Y~*nP!Q![)k~*tP;=`<%l)]~*zP!Q![(h~+SO}~~+VP!_!`#s~+_Re~!O!P+h![!]#{!a!b#{~+mOS~~+rSq~!Q![+m!c!}+m#R#S+m#T#o+m~,TOs~~,YOr~~,_O|~~,dPe~#p#q#{~,lO{~",
26
- tokenizers: [0],
27
- topRules: {"Expression":[0,1]},
28
- specialized: [{term: 33, get: (value) => spec_word[value] || -1},{term: 21, get: (value) => spec_Operator[value] || -1}],
29
- tokenPrec: 479
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
- if (node.name === 'Call' && node.firstChild && node.lastChild) {
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' && ((_k = (_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) === null || _k === void 0 ? void 0 : _k.name) == 'Operator' && node.lastChild) {
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
- resolveTypes(state, node.lastChild, config).forEach(x => types.add(x));
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('any');
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
- let n = node.node.firstChild;
170
- while (n) {
171
- if (++i > args.length) {
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
- n = n.nextSibling;
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: (_b = x.returnType) === null || _b === void 0 ? void 0 : _b.join('|'),
211
- info: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
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: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
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 }) => ({ label: name, apply: `${name} `, info, detail, type: "keyword" }))) !== null && _a !== void 0 ? _a : [],
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
- const cursorTooltipBaseTheme = view.EditorView.baseTheme({
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
- padding: "2px 7px",
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
- cursorTooltipBaseTheme,
535
+ baseTheme,
461
536
  ...extensions,
462
537
  ]);
463
538
  }