@valtzu/codemirror-lang-el 0.6.1 → 0.7.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
@@ -57,7 +57,7 @@ yarn add @valtzu/codemirror-lang-el
57
57
  "@codemirror/state": "https://esm.sh/*@codemirror/state@6.4.1",
58
58
  "@codemirror/search": "https://esm.sh/*@codemirror/search@6.5.6",
59
59
  "@codemirror/autocomplete": "https://esm.sh/*@codemirror/autocomplete@6.9.0",
60
- "@codemirror/view": "https://esm.sh/*@codemirror/view@6.17.1",
60
+ "@codemirror/view": "https://esm.sh/*@codemirror/view@6.26.3",
61
61
  "@codemirror/commands": "https://esm.sh/*@codemirror/commands@6.2.5",
62
62
  "@codemirror/language": "https://esm.sh/*@codemirror/language@6.9.0",
63
63
  "@codemirror/lint": "https://esm.sh/*@codemirror/lint@6.4.1",
@@ -67,7 +67,7 @@ yarn add @valtzu/codemirror-lang-el
67
67
  "style-mod": "https://esm.sh/*style-mod@4.1.2",
68
68
  "w3c-keyname": "https://esm.sh/*w3c-keyname@2.2.8",
69
69
  "crelt": "https://esm.sh/*crelt@1.0.6",
70
- "@valtzu/codemirror-lang-el": "https://esm.sh/*@valtzu/codemirror-lang-el@0.4.2"
70
+ "@valtzu/codemirror-lang-el": "https://esm.sh/*@valtzu/codemirror-lang-el@0.6.3"
71
71
  }
72
72
  }
73
73
  </script>
@@ -111,13 +111,6 @@ yarn add @valtzu/codemirror-lang-el
111
111
  doc: 'is_granted(user, user.self.getGroup())',
112
112
  });
113
113
  </script>
114
- <style>
115
- .cm-completionDetail {
116
- float: right;
117
- opacity: 0.5;
118
- font-style: inherit !important;
119
- }
120
- </style>
121
114
  ```
122
115
 
123
116
  ### 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;
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,8 +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
  }
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)) {
81
+ const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
82
+ if (operator == '?:' || operator == '??' || operator == '?') {
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);
102
+ }
103
+ }
68
104
  if (types.size === 0) {
69
- types.add('any');
105
+ types.add(ELScalar.Any);
70
106
  }
71
107
  return types;
72
108
  }
@@ -83,18 +119,19 @@ const keywords = [
83
119
  { name: 'not' },
84
120
  { name: 'or' },
85
121
  { name: 'and' },
122
+ { name: 'xor' },
86
123
  ];
87
124
 
88
125
  const autocompleteFunction = (x) => {
89
- var _a, _b;
126
+ var _a, _b, _c;
90
127
  return ({
91
- 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(',')) || ''})`,
92
129
  apply: (view, completion, from, to) => {
93
130
  var _a;
94
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) } }));
95
132
  },
96
- detail: (_b = x.returnType) === null || _b === void 0 ? void 0 : _b.join('|'),
97
- 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,
98
135
  type: "function",
99
136
  });
100
137
  };
@@ -103,7 +140,7 @@ const autocompleteIdentifier = (x) => {
103
140
  return ({
104
141
  label: x.name,
105
142
  apply: x.name,
106
- info: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
143
+ info: x.info,
107
144
  detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')),
108
145
  type: 'variable',
109
146
  });
@@ -113,7 +150,13 @@ function completeOperatorKeyword(state, config, tree, from, to, explicit) {
113
150
  return {
114
151
  from,
115
152
  to,
116
- 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 : [],
117
160
  validFor: (text) => { var _a; return (_a = keywords.some(({ name }) => explicit || name.includes(text))) !== null && _a !== void 0 ? _a : false; },
118
161
  };
119
162
  }
@@ -158,7 +201,7 @@ function expressionLanguageCompletion(context) {
158
201
  const config = getExpressionLanguageConfig(state);
159
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 : ''); };
160
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 : ''); };
161
- if (prevNode.name == 'String') {
204
+ if (prevNode.name == 'String' || prevNode.name == 'BlockComment') {
162
205
  return null;
163
206
  }
164
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;
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,8 +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
  }
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)) {
77
+ const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
78
+ if (operator == '?:' || operator == '??' || operator == '?') {
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);
98
+ }
99
+ }
64
100
  if (types.size === 0) {
65
- types.add('any');
101
+ types.add(ELScalar.Any);
66
102
  }
67
103
  return types;
68
104
  }
@@ -79,18 +115,19 @@ const keywords = [
79
115
  { name: 'not' },
80
116
  { name: 'or' },
81
117
  { name: 'and' },
118
+ { name: 'xor' },
82
119
  ];
83
120
 
84
121
  const autocompleteFunction = (x) => {
85
- var _a, _b;
122
+ var _a, _b, _c;
86
123
  return ({
87
- 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(',')) || ''})`,
88
125
  apply: (view, completion, from, to) => {
89
126
  var _a;
90
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) } }));
91
128
  },
92
- detail: (_b = x.returnType) === null || _b === void 0 ? void 0 : _b.join('|'),
93
- 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,
94
131
  type: "function",
95
132
  });
96
133
  };
@@ -99,7 +136,7 @@ const autocompleteIdentifier = (x) => {
99
136
  return ({
100
137
  label: x.name,
101
138
  apply: x.name,
102
- info: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
139
+ info: x.info,
103
140
  detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')),
104
141
  type: 'variable',
105
142
  });
@@ -109,7 +146,13 @@ function completeOperatorKeyword(state, config, tree, from, to, explicit) {
109
146
  return {
110
147
  from,
111
148
  to,
112
- 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 : [],
113
156
  validFor: (text) => { var _a; return (_a = keywords.some(({ name }) => explicit || name.includes(text))) !== null && _a !== void 0 ? _a : false; },
114
157
  };
115
158
  }
@@ -154,7 +197,7 @@ function expressionLanguageCompletion(context) {
154
197
  const config = getExpressionLanguageConfig(state);
155
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 : ''); };
156
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 : ''); };
157
- if (prevNode.name == 'String') {
200
+ if (prevNode.name == 'String' || prevNode.name == 'BlockComment') {
158
201
  return null;
159
202
  }
160
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,"!":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};
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'#CrOOQO'#Cr'#CrO%PQPO'#CrO%}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.vO(|QPO1G.wOOQO,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]Og`Os^O!O_O!PaO!RaO!SbO!TbO!UcO!VbO!WbO!XbO~ORcXScXgcXmcXscXuWX!OcX!PcX!RcX!ScX!TcX!UcX!VcX!WcX!XcX}cXrcXwcXtcX{cX~O{eO~PVOrvP~PVOujO~OulO~OqmO~O!QsO~O!VsO]fX^fXqfXsfXufXxfXyfXzfX|fX!UfX!YfX!ZfX![fX~O}tO~P!QOwuOrvXtvX~P!QOrwO~Omha}harhawhatha{ha~P!QOtxO~P!QOtvP~PVORTXSTXgTXmTXsTXuZX!OTX!PTX!RTX!STX!TTX!UTX!VTX!WTX!XTX}TXrTXwTXtTX{TX~Or{O~P!QO}|O~P!QOmei}eireiweitei{ei~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^gRS]qS~",
20
- goto: "%]wPPxPP!Zxx!^!o!r#T#WPPxxxxxxx#ZPx#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 BinaryExpression OperatorKeyword Operator 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~#pPg~!_!`#s~#xPg~!_!`#{~$QOg~~$TXOr$Qrs$ps#O$Q#O#P$u#P;'S$Q;'S;=`%t<%l~$Q~O$Q~~$p~$uO^~~$xRO;'S$Q;'S;=`%R;=`O$Q~%UYOr$Qrs$ps#O$Q#O#P$u#P;'S$Q;'S;=`%t;=`<%l$Q<%l~$Q~O$Q~~$p~%wP;=`<%l$Q~&PPg~vw#{~&VXOw&Swx$px#O&S#O#P&r#P;'S&S;'S;=`'q<%l~&S~O&S~~$p~&uRO;'S&S;'S;=`'O;=`O&S~'RYOw&Swx$px#O&S#O#P&r#P;'S&S;'S;=`'q;=`<%l&S<%l~&S~O&S~~$p~'tP;=`<%l&S~'|Ou~~(ROt~~(WPg~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~+_R!O~!O!P+h![!]#{!a!b#{~+mOS~~+rSq~!Q![+m!c!}+m#R#S+m#T#o+m~,TOs~~,YOr~~,_O|~~,dPg~#p#q#{~,lO{~",
26
- tokenizers: [0],
27
- topRules: {"Expression":[0,1]},
28
- specialized: [{term: 33, get: (value) => spec_word[value] || -1},{term: 23, get: (value) => spec_Operator[value] || -1}],
29
- tokenPrec: 479
23
+ states: ")rOYQPOOP!^OPOOQ!cQPOOO#aQPO'#CeO$tQPO'#CnO${QPO'#CoOYQPO'#CuOYQPO'#CwOOQO'#DS'#DSO%SQPO'#CdO%XQPO'#CdOOQO'#Cl'#ClOOQO'#Cm'#CmOOQO'#Cv'#CvP%^OQO'#C]POOO)C>r)C>rO%iQPO,58yOYQPO,58}OYQPO,59_OYQPO,59]O%nQPO'#CtOOQO'#Ct'#CtO%sQPO'#CtO&zQPO,59YOOQO,59Y,59YO'RQPO'#DYO'`QPO,59ZO'eQPO,59aO'{QPO,59cO(SQPO'#CfOOQO,59O,59OO(SQPO'#CiPOOO'#Cx'#CxP(ZOQO,58wPOOO,58w,58wO(fQPO'#CbOOQO1G.e1G.eOOQO1G.m1G.mO)yQPO1G.iO*QQPO1G.yO*hQPO1G.wOOQO,59`,59`OYQPO1G.tOYQPO'#CyO*oQPO,59tOOQO1G.u1G.uOOQO1G.}1G.}O*zQPO,59QO+PQPO,59TPOOO-E6v-E6vPOOO1G.c1G.cOOQO7+$T7+$TOYQPO7+$cO+UQPO7+$`O+`QPO,59eOOQO-E6w-E6wOOQO1G.l1G.lOOQO1G.o1G.oO+mQPO<<G}OYQPO'#CzO,TQPO<<GzOOQO<<Gz<<GzO,]QPO,59fOOQO-E6x-E6xOOQOAN=fAN=fOYQPO1G/QO,dQPO7+$l",
24
+ stateData: ",v~OqOSrPQ~O^WO_WOwROyTO{VO!OZO!PZO!QZO!RZO!S[O!T[O!VSO!_]O!d]O!e]O!f]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~O!WzO~P!cO}{Ox|Xz|X~P!cOx}O~Ooia!Wiaxia}iazia!Uia~P!cOz!OO~P!cOz|P~PYOspOtpOu!SO~OSUXTUXfUXoUXyUX{[X!XUX!YUX![UX!]UX!^UX!_UX!`UX!aUX!bUX!cUX!WUXxUX}UXzUX!UUX~Ox!TO~P!cOogi!Wgixgi}gizgi!Ugi~P!cO!W!UO~P!cO}{Ox|az|a~Oz!YO~Oz!ZO~O}!]O!U!_O~P!cOxma}mazma~P!cOoey!Weyxey}eyzey!Uey~P!cO}!]O!U!bO~O!W!cO~P!cO}nq!Unq~P!cO_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: 68,
28
+ nodeProps: [
29
+ [t, 14,"number",15,"string",16,"bool",17,"null"]
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: 536
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;
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,8 +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
  }
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)) {
131
+ const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
132
+ if (operator == '?:' || operator == '??' || operator == '?') {
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);
152
+ }
153
+ }
109
154
  if (types.size === 0) {
110
- types.add('any');
155
+ types.add(ELScalar.Any);
111
156
  }
112
157
  return types;
113
158
  }
@@ -124,6 +169,7 @@ const keywords = [
124
169
  { name: 'not' },
125
170
  { name: 'or' },
126
171
  { name: 'and' },
172
+ { name: 'xor' },
127
173
  ];
128
174
 
129
175
  /**
@@ -159,7 +205,7 @@ const expressionLanguageLinterSource = (state) => {
159
205
  let i = 0;
160
206
  let n = node.node.firstChild;
161
207
  while (n) {
162
- if (++i > args.length) {
208
+ if (n.name !== 'BlockComment' && ++i > args.length) {
163
209
  diagnostics.push({ from: n.from, to: n.to, severity: 'error', message: `Unexpected argument` });
164
210
  }
165
211
  n = n.nextSibling;
@@ -191,15 +237,15 @@ const expressionLanguageLinterSource = (state) => {
191
237
  const expressionLanguageLinter = lint.linter(view => expressionLanguageLinterSource(view.state));
192
238
 
193
239
  const autocompleteFunction = (x) => {
194
- var _a, _b;
240
+ var _a, _b, _c;
195
241
  return ({
196
- label: `${x.name}(${((_a = x.args) === null || _a === void 0 ? void 0 : _a.join(',')) || ''})`,
242
+ 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(',')) || ''})`,
197
243
  apply: (view, completion, from, to) => {
198
244
  var _a;
199
245
  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) } }));
200
246
  },
201
- detail: (_b = x.returnType) === null || _b === void 0 ? void 0 : _b.join('|'),
202
- info: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
247
+ detail: (_c = x.returnType) === null || _c === void 0 ? void 0 : _c.join('|'),
248
+ info: x.info,
203
249
  type: "function",
204
250
  });
205
251
  };
@@ -208,7 +254,7 @@ const autocompleteIdentifier = (x) => {
208
254
  return ({
209
255
  label: x.name,
210
256
  apply: x.name,
211
- info: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
257
+ info: x.info,
212
258
  detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')),
213
259
  type: 'variable',
214
260
  });
@@ -218,7 +264,13 @@ function completeOperatorKeyword(state, config, tree, from, to, explicit) {
218
264
  return {
219
265
  from,
220
266
  to,
221
- options: (_a = keywords.map(({ name, info, detail }) => ({ label: name, apply: `${name} `, info, detail, type: "keyword" }))) !== null && _a !== void 0 ? _a : [],
267
+ options: (_a = keywords.map(({ name, info, detail }) => ({
268
+ label: name,
269
+ apply: `${name} `,
270
+ info: info,
271
+ detail,
272
+ type: "keyword"
273
+ }))) !== null && _a !== void 0 ? _a : [],
222
274
  validFor: (text) => { var _a; return (_a = keywords.some(({ name }) => explicit || name.includes(text))) !== null && _a !== void 0 ? _a : false; },
223
275
  };
224
276
  }
@@ -263,7 +315,7 @@ function expressionLanguageCompletion(context) {
263
315
  const config = getExpressionLanguageConfig(state);
264
316
  const isIdentifier = (node) => { var _a; return ['Variable', 'Function'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
265
317
  const isMember = (node) => { var _a; return ['Property', 'Method'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
266
- if (prevNode.name == 'String') {
318
+ if (prevNode.name == 'String' || prevNode.name == 'BlockComment') {
267
319
  return null;
268
320
  }
269
321
  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) || '')) {
@@ -303,7 +355,7 @@ function getCursorTooltips(state) {
303
355
  return state.selection.ranges
304
356
  .filter(range => range.empty)
305
357
  .map(range => {
306
- var _a;
358
+ var _a, _b;
307
359
  const tree = language.syntaxTree(state);
308
360
  const node = tree.resolveInner(range.from, 0);
309
361
  const args = resolveArguments(node);
@@ -315,7 +367,7 @@ function getCursorTooltips(state) {
315
367
  return null;
316
368
  }
317
369
  const n = args.childAfter(range.from - 1);
318
- const argName = (_a = fn.args) === null || _a === void 0 ? void 0 : _a[n ? getNodeOrdinal(n) : 0];
370
+ 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;
319
371
  if (n && n.from !== range.from || !argName) {
320
372
  return null;
321
373
  }
@@ -390,17 +442,29 @@ const keywordTooltip = view.hoverTooltip((view, pos, side) => {
390
442
  create: () => ({ dom: createInfoElement(info) }),
391
443
  };
392
444
  });
393
- const cursorTooltipBaseTheme = view.EditorView.baseTheme({
445
+
446
+ const baseTheme = view.EditorView.baseTheme({
394
447
  ".cm-tooltip.cm-tooltip-cursor": {
395
448
  boxShadow: 'rgba(0, 0, 0, .15) 0 1px 2px',
396
449
  border: "1px solid rgba(127, 127, 127, .2)",
397
- padding: "2px 7px",
450
+ fontSize: ".85rem",
451
+ padding: ".4rem .5rem",
398
452
  borderRadius: "4px",
399
453
  "& .cm-tooltip-arrow:before": {},
400
454
  "& .cm-tooltip-arrow:after": {
401
455
  borderTopColor: "transparent"
402
- }
403
- }
456
+ },
457
+ },
458
+ ".cm-tooltip.cm-completionInfo, .cm-diagnostic": {
459
+ boxShadow: "rgba(0, 0, 0, .15) 0 2px 5px",
460
+ fontSize: ".85rem",
461
+ padding: ".8rem !important", // Couldn't figure out other means to override https://github.com/codemirror/autocomplete/blob/6.18.1/src/theme.ts#L65
462
+ },
463
+ ".cm-completionDetail": {
464
+ float: "right",
465
+ opacity: 0.5,
466
+ fontStyle: "inherit !important",
467
+ },
404
468
  });
405
469
 
406
470
  const ELLanguage = language.LRLanguage.define({
@@ -434,6 +498,7 @@ const ELLanguage = language.LRLanguage.define({
434
498
  OperatorKeyword: highlight.tags.operatorKeyword,
435
499
  UnaryOperator: highlight.tags.operator,
436
500
  Operator: highlight.tags.operator,
501
+ BlockComment: highlight.tags.comment,
437
502
  })
438
503
  ]
439
504
  }),
@@ -448,7 +513,7 @@ function expressionlanguage(config = {}, extensions = []) {
448
513
  expressionLanguageLinter,
449
514
  keywordTooltip,
450
515
  cursorTooltipField,
451
- cursorTooltipBaseTheme,
516
+ baseTheme,
452
517
  ...extensions,
453
518
  ]);
454
519
  }
package/dist/index.d.cts CHANGED
@@ -14,10 +14,16 @@ interface ELIdentifier {
14
14
  */
15
15
  interface ELFunction {
16
16
  name: string;
17
- args: string[]; // maybe these could be ELIdentifier[] ?
17
+ args: ELParameter[];
18
18
  info?: string;
19
19
  returnType?: string[];
20
20
  }
21
+ interface ELParameter {
22
+ name: string;
23
+ type?: string[];
24
+ info?: string;
25
+ optional?: boolean;
26
+ }
21
27
  interface ELType {
22
28
  identifiers?: ELIdentifier[];
23
29
  functions?: ELFunction[];
package/dist/index.d.ts CHANGED
@@ -14,10 +14,16 @@ interface ELIdentifier {
14
14
  */
15
15
  interface ELFunction {
16
16
  name: string;
17
- args: string[]; // maybe these could be ELIdentifier[] ?
17
+ args: ELParameter[];
18
18
  info?: string;
19
19
  returnType?: string[];
20
20
  }
21
+ interface ELParameter {
22
+ name: string;
23
+ type?: string[];
24
+ info?: string;
25
+ optional?: boolean;
26
+ }
21
27
  interface ELType {
22
28
  identifiers?: ELIdentifier[];
23
29
  functions?: ELFunction[];