@valtzu/codemirror-lang-el 0.9.0 → 1.0.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 CHANGED
@@ -1,6 +1,18 @@
1
1
  CHANGELOG
2
2
  =========
3
3
 
4
+ 1.0
5
+ ---
6
+
7
+ * Render completion info as HTML
8
+ * Bump to stable
9
+
10
+ 0.10
11
+ ---
12
+
13
+ * Exclude optional arguments when linting argument count
14
+ * Lint minimum argument count
15
+
4
16
  0.9
5
17
  ---
6
18
 
@@ -0,0 +1,108 @@
1
+
2
+ ## Enum
3
+
4
+ - [ELScalar](#elscalar)
5
+
6
+ ### ELScalar
7
+
8
+
9
+
10
+ | Property | Type | Description |
11
+ | ---------- | ---------- | ---------- |
12
+ | `Bool` | `'bool'` | Equivalent to PHP `bool` |
13
+ | `Number` | `'number'` | Equivalent to PHP `int` or `float` |
14
+ | `String` | `'string'` | Equivalent to PHP `string` |
15
+ | `Null` | `'null'` | Equivalent to PHP `null` |
16
+ | `Any` | `'any'` | Equivalent to PHP `mixed` |
17
+
18
+
19
+ ## Interfaces
20
+
21
+ - [ExpressionLanguageConfig](#expressionlanguageconfig)
22
+ - [ELType](#eltype)
23
+ - [ELIdentifier](#elidentifier)
24
+ - [ELFunction](#elfunction)
25
+ - [ELParameter](#elparameter)
26
+ - [ELKeyword](#elkeyword)
27
+
28
+ ### ExpressionLanguageConfig
29
+
30
+ The configuration object that is passed to `expressionlanguage` function
31
+
32
+ | Property | Type | Description |
33
+ | ---------- | ---------- | ---------- |
34
+ | `types` | `{ [key: string]: ELType; } or undefined` | Type definitions used in `identifiers` and `functions` |
35
+ | `identifiers` | `ELIdentifier[] or undefined` | Top-level variables |
36
+ | `functions` | `ELFunction[] or undefined` | Top-level functions |
37
+
38
+
39
+ ### ELType
40
+
41
+
42
+
43
+ | Property | Type | Description |
44
+ | ---------- | ---------- | ---------- |
45
+ | `identifiers` | `ELIdentifier[] or undefined` | Properties of the object |
46
+ | `functions` | `ELFunction[] or undefined` | Methods of the object |
47
+ | `info` | `string or undefined` | |
48
+
49
+
50
+ ### ELIdentifier
51
+
52
+ Represents a variable or a property of an object
53
+
54
+ | Property | Type | Description |
55
+ | ---------- | ---------- | ---------- |
56
+ | `name` | `string` | |
57
+ | `detail` | `string or undefined` | If set, this is shown instead of `type` |
58
+ | `info` | `string or undefined` | Text to show in hover tooltip, autocomplete etc. |
59
+ | `type` | `string[] or undefined` | All possible types for this identifier |
60
+
61
+
62
+ ### ELFunction
63
+
64
+ Represents a function or a method of an object
65
+
66
+ | Property | Type | Description |
67
+ | ---------- | ---------- | ---------- |
68
+ | `name` | `string` | |
69
+ | `args` | `ELParameter[] or undefined` | |
70
+ | `info` | `string or undefined` | |
71
+ | `returnType` | `string[] or undefined` | |
72
+
73
+
74
+ ### ELParameter
75
+
76
+
77
+
78
+ | Property | Type | Description |
79
+ | ---------- | ---------- | ---------- |
80
+ | `name` | `string` | |
81
+ | `type` | `string[] or undefined` | |
82
+ | `info` | `string or undefined` | |
83
+ | `optional` | `boolean or undefined` | |
84
+
85
+
86
+ ### ELKeyword
87
+
88
+
89
+
90
+ | Property | Type | Description |
91
+ | ---------- | ---------- | ---------- |
92
+ | `name` | `string` | |
93
+ | `detail` | `string or undefined` | |
94
+ | `info` | `string or undefined` | |
95
+
96
+
97
+ ## Types
98
+
99
+ - [ELTypeName](#eltypename)
100
+
101
+ ### ELTypeName
102
+
103
+ One of predefined types (`ELScalar`) or a custom type from `ExpressionLanguageConfig.types`
104
+
105
+ | Type | Type |
106
+ | ---------- | ---------- |
107
+ | `ELTypeName` | `ELScalar or string` |
108
+
package/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  ## Symfony Expression Language support for CodeMirror 6
2
2
 
3
- > :warning: **This is unstable**: Expect breaking changes until v1 is out.
4
-
5
3
  ### Features
6
4
 
7
5
  #### Linting
@@ -10,7 +8,7 @@
10
8
 
11
9
  1. Lint variable & function names
12
10
  1. Lint object properties & methods, even on expression result
13
- 1. Lint argument count (only max. count checked for now)
11
+ 1. Lint argument count
14
12
  1. Lint argument types
15
13
 
16
14
  #### Autocompletion
@@ -58,6 +56,10 @@ yarn add @valtzu/codemirror-lang-el
58
56
 
59
57
  ---
60
58
 
59
+ ### Configuration
60
+
61
+ See [CONFIGURATION.md](CONFIGURATION.md)
62
+
61
63
  ### Example
62
64
 
63
65
  [Live demo](https://jsfiddle.net/turse2xq/)
package/dist/index.cjs CHANGED
@@ -35,12 +35,18 @@ const parser = lr.LRParser.deserialize({
35
35
  tokenPrec: 532
36
36
  });
37
37
 
38
+ // generate CONFIGURATION.md from this file by running "tsdoc --src=src/types.ts --dest=CONFIGURATION.md --noemoji --types"
38
39
  exports.ELScalar = void 0;
39
40
  (function (ELScalar) {
41
+ /** Equivalent to PHP `bool` */
40
42
  ELScalar["Bool"] = "bool";
43
+ /** Equivalent to PHP `int` or `float` */
41
44
  ELScalar["Number"] = "number";
45
+ /** Equivalent to PHP `string` */
42
46
  ELScalar["String"] = "string";
47
+ /** Equivalent to PHP `null` */
43
48
  ELScalar["Null"] = "null";
49
+ /** Equivalent to PHP `mixed` */
44
50
  ELScalar["Any"] = "any";
45
51
  })(exports.ELScalar || (exports.ELScalar = {}));
46
52
 
@@ -70,6 +76,11 @@ const createInfoElement = (html) => {
70
76
  dom.className = 'cm-diagnostic';
71
77
  return dom;
72
78
  };
79
+ const createCompletionInfoElement = (html) => {
80
+ const dom = document.createElement("div");
81
+ dom.innerHTML = html;
82
+ return dom;
83
+ };
73
84
  function resolveFunctionDefinition(node, state, config) {
74
85
  var _a;
75
86
  if (!node) {
@@ -77,17 +88,17 @@ function resolveFunctionDefinition(node, state, config) {
77
88
  }
78
89
  let identifier;
79
90
  if ((node.type.is(PropertyAccess) || node.type.is(MethodAccess)) && node.lastChild) {
80
- const leftArgument = (_a = node.firstChild) === null || _a === undefined ? undefined : _a.node;
91
+ const leftArgument = (_a = node.firstChild) === null || _a === void 0 ? void 0 : _a.node;
81
92
  const types = Array.from(resolveTypes(state, leftArgument, config));
82
93
  identifier = state.sliceDoc(node.lastChild.from, node.lastChild.to);
83
- return types.map(type => { var _a; return resolveCallable(identifier, (_a = config.types) === null || _a === undefined ? undefined : _a[type]); }).find(x => x);
94
+ return types.map(type => { var _a; return resolveCallable(identifier, (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]); }).find(x => x);
84
95
  }
85
96
  else if (node.type.is(Function)) {
86
97
  identifier = state.sliceDoc(node.from, node.node.firstChild ? node.node.firstChild.from - 1 : node.to);
87
98
  return resolveCallable(identifier, config);
88
99
  }
89
100
  }
90
- const resolveCallable = (identifier, config) => { var _a; return (_a = config === null || config === undefined ? undefined : config.functions) === null || _a === undefined ? undefined : _a.find(x => x.name === identifier); };
101
+ 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); };
91
102
  const resolveIdentifier = (nodeTypeId, identifier, config) => {
92
103
  var _a;
93
104
  switch (nodeTypeId) {
@@ -96,7 +107,7 @@ const resolveIdentifier = (nodeTypeId, identifier, config) => {
96
107
  return resolveCallable(identifier, config);
97
108
  case Property:
98
109
  case Variable:
99
- return (_a = config === null || config === undefined ? undefined : config.identifiers) === null || _a === undefined ? undefined : _a.find(x => x.name === identifier);
110
+ return (_a = config === null || config === void 0 ? void 0 : config.identifiers) === null || _a === void 0 ? void 0 : _a.find(x => x.name === identifier);
100
111
  }
101
112
  };
102
113
  function resolveTypes(state, node, config) {
@@ -115,27 +126,27 @@ function resolveTypes(state, node, config) {
115
126
  else if (node.type.is(Variable)) {
116
127
  const varName = state.sliceDoc(node.from, node.to) || '';
117
128
  // @ts-ignore
118
- (_b = (_a = resolveIdentifier(node.type.id, varName, config)) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.forEach((x) => types.add(x));
129
+ (_b = (_a = resolveIdentifier(node.type.id, varName, config)) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.forEach((x) => types.add(x));
119
130
  }
120
131
  else if (node.type.is(Function)) {
121
132
  const varName = state.sliceDoc(node.from, node.to) || '';
122
133
  // @ts-ignore
123
- (_d = (_c = resolveIdentifier(node.type.id, varName, config)) === null || _c === undefined ? undefined : _c.returnType) === null || _d === undefined ? undefined : _d.forEach((x) => types.add(x));
134
+ (_d = (_c = resolveIdentifier(node.type.id, varName, config)) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
124
135
  }
125
- else if (node.type.is(PropertyAccess) && node.firstChild && ((_e = node.lastChild) === null || _e === undefined ? undefined : _e.type.is(Property))) {
136
+ else if (node.type.is(PropertyAccess) && node.firstChild && ((_e = node.lastChild) === null || _e === void 0 ? void 0 : _e.type.is(Property))) {
126
137
  const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
127
- (_f = resolveTypes(state, node.firstChild, config)) === null || _f === undefined ? undefined : _f.forEach(baseType => {
138
+ (_f = resolveTypes(state, node.firstChild, config)) === null || _f === void 0 ? void 0 : _f.forEach(baseType => {
128
139
  var _a, _b, _c, _d;
129
140
  // @ts-ignore
130
- (_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === undefined ? undefined : _a.type.id, varName, (_b = config.types) === null || _b === undefined ? undefined : _b[baseType])) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.forEach((x) => types.add(x));
141
+ (_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.type.id, varName, (_b = config.types) === null || _b === void 0 ? void 0 : _b[baseType])) === null || _c === void 0 ? void 0 : _c.type) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
131
142
  });
132
143
  }
133
- else if (node.type.is(MethodAccess) && node.firstChild && ((_g = node.lastChild) === null || _g === undefined ? undefined : _g.type.is(Method))) {
144
+ else if (node.type.is(MethodAccess) && node.firstChild && ((_g = node.lastChild) === null || _g === void 0 ? void 0 : _g.type.is(Method))) {
134
145
  const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
135
- (_h = resolveTypes(state, node.firstChild, config)) === null || _h === undefined ? undefined : _h.forEach(baseType => {
146
+ (_h = resolveTypes(state, node.firstChild, config)) === null || _h === void 0 ? void 0 : _h.forEach(baseType => {
136
147
  var _a, _b, _c, _d;
137
148
  // @ts-ignore
138
- (_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === undefined ? undefined : _a.type.id, varName, (_b = config.types) === null || _b === undefined ? undefined : _b[baseType])) === null || _c === undefined ? undefined : _c.returnType) === null || _d === undefined ? undefined : _d.forEach((x) => types.add(x));
149
+ (_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.type.id, varName, (_b = config.types) === null || _b === void 0 ? void 0 : _b[baseType])) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
139
150
  });
140
151
  }
141
152
  else if (node.type.is(Application) && node.firstChild) {
@@ -145,7 +156,7 @@ function resolveTypes(state, node, config) {
145
156
  resolveTypes(state, node.firstChild.nextSibling, config).forEach(x => types.add(x));
146
157
  resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
147
158
  }
148
- else if (node.type.is(BinaryExpression) && ((_j = node.firstChild) === null || _j === undefined ? undefined : _j.nextSibling) && ((_l = (_k = node.firstChild) === null || _k === undefined ? undefined : _k.nextSibling) === null || _l === undefined ? undefined : _l.nextSibling)) {
159
+ else if (node.type.is(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)) {
149
160
  const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
150
161
  if (operator == '?:' || operator == '??' || operator == '?') {
151
162
  if (operator == '?:' || operator == '??') {
@@ -192,6 +203,7 @@ const keywords = [
192
203
 
193
204
  var utils = /*#__PURE__*/Object.freeze({
194
205
  __proto__: null,
206
+ createCompletionInfoElement: createCompletionInfoElement,
195
207
  createInfoElement: createInfoElement,
196
208
  getExpressionLanguageConfig: getExpressionLanguageConfig,
197
209
  keywords: keywords,
@@ -218,7 +230,7 @@ const expressionLanguageLinterSource = (state) => {
218
230
  }
219
231
  identifier = state.sliceDoc(from, to);
220
232
  if (identifier.length === 0) {
221
- diagnostics.push({ from, to: (_c = (_b = (_a = node.node.parent) === null || _a === undefined ? undefined : _a.parent) === null || _b === undefined ? undefined : _b.to) !== null && _c !== undefined ? _c : to, severity: 'error', message: `Expression expected` });
233
+ diagnostics.push({ from, to: (_c = (_b = (_a = node.node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.to) !== null && _c !== void 0 ? _c : to, severity: 'error', message: `Expression expected` });
222
234
  }
223
235
  else {
224
236
  const type = /^[a-zA-Z_]+[a-zA-Z_0-9]*$/.test(identifier) ? 'identifier' : 'operator';
@@ -227,16 +239,20 @@ const expressionLanguageLinterSource = (state) => {
227
239
  return;
228
240
  case Arguments:
229
241
  const fn = resolveFunctionDefinition(node.node.prevSibling, state, config);
230
- const args = fn === null || fn === undefined ? undefined : fn.args;
242
+ const args = fn === null || fn === void 0 ? void 0 : fn.args;
231
243
  if (!args) {
232
244
  return;
233
245
  }
234
- for (let n = node.node.firstChild, i = 0; n != null; n = n.nextSibling) {
246
+ const argCountMin = args.reduce((count, arg) => count + Number(!arg.optional), 0);
247
+ const argCountMax = args.length;
248
+ const argumentCountHintFn = () => `<code>${fn.name}</code> takes ${argCountMin == argCountMax ? `exactly ${argCountMax}` : `${argCountMin}–${argCountMax}`} argument${argCountMax == 1 ? '' : 's'}`;
249
+ let i = 0;
250
+ for (let n = node.node.firstChild; n != null; n = n.nextSibling) {
235
251
  if (n.type.is(BlockComment)) {
236
252
  continue;
237
253
  }
238
- if (i > args.length - 1) {
239
- diagnostics.push({ from: n.from, to: n.to, severity: 'warning', message: `Unexpected argument – <code>${fn.name}</code> takes ${args.length} argument${args.length == 1 ? '' : 's'}` });
254
+ if (i > argCountMax - 1) {
255
+ diagnostics.push({ from: n.from, to: n.to, severity: 'warning', message: `Unexpected argument – ${argumentCountHintFn()}` });
240
256
  continue;
241
257
  }
242
258
  const typesUsed = Array.from(resolveTypes(state, n, config));
@@ -246,13 +262,16 @@ const expressionLanguageLinterSource = (state) => {
246
262
  }
247
263
  i++;
248
264
  }
265
+ if (i < argCountMin) {
266
+ diagnostics.push({ from: node.from, to: node.to, severity: 'error', message: `Too few arguments – ${argumentCountHintFn()}` });
267
+ }
249
268
  break;
250
269
  case Property:
251
270
  case Method:
252
- const leftArgument = (_e = (_d = node.node.parent) === null || _d === undefined ? undefined : _d.firstChild) === null || _e === undefined ? undefined : _e.node;
271
+ const leftArgument = (_e = (_d = node.node.parent) === null || _d === void 0 ? void 0 : _d.firstChild) === null || _e === void 0 ? void 0 : _e.node;
253
272
  const types = Array.from(resolveTypes(state, leftArgument, config));
254
273
  identifier = state.sliceDoc(from, to);
255
- if (!types.find(type => { var _a; return resolveIdentifier(id, identifier, (_a = config.types) === null || _a === undefined ? undefined : _a[type]); })) {
274
+ if (!types.find(type => { var _a; return resolveIdentifier(id, identifier, (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]); })) {
256
275
  diagnostics.push({ from, to, severity: 'error', message: `${node.name} <code>${identifier}</code> not found in <code>${types.join('|')}</code>` });
257
276
  }
258
277
  break;
@@ -264,7 +283,7 @@ const expressionLanguageLinterSource = (state) => {
264
283
  }
265
284
  break;
266
285
  }
267
- if (identifier && ((_f = node.node.parent) === null || _f === undefined ? undefined : _f.type.isError)) {
286
+ if (identifier && ((_f = node.node.parent) === null || _f === void 0 ? void 0 : _f.type.isError)) {
268
287
  diagnostics.push({ from, to, severity: 'error', message: `Unexpected identifier <code>${identifier}</code>` });
269
288
  }
270
289
  });
@@ -288,13 +307,13 @@ var linter = /*#__PURE__*/Object.freeze({
288
307
  const autocompleteFunction = (x) => {
289
308
  var _a, _b, _c;
290
309
  return ({
291
- label: `${x.name}(${((_b = (_a = x.args) === null || _a === undefined ? undefined : _a.map(x => x.name)) === null || _b === undefined ? undefined : _b.join(',')) || ''})`,
310
+ 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(',')) || ''})`,
292
311
  apply: (view, completion, from, to) => {
293
312
  var _a, _b;
294
- view.dispatch(Object.assign(Object.assign({}, autocomplete.insertCompletionText(view.state, `${x.name}()`, from, to)), { selection: { anchor: from + x.name.length + (((_b = (_a = x.args) === null || _a === undefined ? undefined : _a.length) !== null && _b !== undefined ? _b : 0) > 0 ? 1 : 2) } }));
313
+ view.dispatch(Object.assign(Object.assign({}, autocomplete.insertCompletionText(view.state, `${x.name}()`, from, to)), { selection: { anchor: from + x.name.length + (((_b = (_a = x.args) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0 ? 1 : 2) } }));
295
314
  },
296
- detail: (_c = x.returnType) === null || _c === undefined ? undefined : _c.join('|'),
297
- info: x.info,
315
+ detail: (_c = x.returnType) === null || _c === void 0 ? void 0 : _c.join('|'),
316
+ info: () => ({ dom: createCompletionInfoElement(x.info) }),
298
317
  type: "function",
299
318
  });
300
319
  };
@@ -303,8 +322,8 @@ const autocompleteIdentifier = (x) => {
303
322
  return ({
304
323
  label: x.name,
305
324
  apply: x.name,
306
- info: x.info,
307
- detail: x.detail || ((_a = x.type) === null || _a === undefined ? undefined : _a.join('|')),
325
+ info: () => ({ dom: createCompletionInfoElement(x.info) }),
326
+ detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')),
308
327
  type: 'variable',
309
328
  });
310
329
  };
@@ -316,17 +335,17 @@ function completeOperatorKeyword(state, config, tree, from, to, explicit) {
316
335
  options: (_a = keywords.map(({ name, info, detail }) => ({
317
336
  label: name,
318
337
  apply: `${name} `,
319
- info: info,
338
+ info: () => ({ dom: createCompletionInfoElement(info) }),
320
339
  detail,
321
340
  type: "keyword"
322
- }))) !== null && _a !== undefined ? _a : [],
323
- validFor: (text) => { var _a; return (_a = keywords.some(({ name }) => explicit || name.includes(text))) !== null && _a !== undefined ? _a : false; },
341
+ }))) !== null && _a !== void 0 ? _a : [],
342
+ validFor: (text) => { var _a; return (_a = keywords.some(({ name }) => explicit || name.includes(text))) !== null && _a !== void 0 ? _a : false; },
324
343
  };
325
344
  }
326
345
  function completeIdentifier(state, config, tree, from, to) {
327
346
  var _a, _b;
328
- const identifiers = (_a = config.identifiers) !== null && _a !== undefined ? _a : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
329
- const functions = (_b = config.functions) !== null && _b !== undefined ? _b : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
347
+ const identifiers = (_a = config.identifiers) !== null && _a !== void 0 ? _a : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
348
+ const functions = (_b = config.functions) !== null && _b !== void 0 ? _b : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
330
349
  return {
331
350
  from,
332
351
  to,
@@ -336,17 +355,17 @@ function completeIdentifier(state, config, tree, from, to) {
336
355
  }
337
356
  function completeMember(state, config, tree, from, to, explicit) {
338
357
  var _a, _b, _c, _d, _e, _f;
339
- if (!(((_a = tree.parent) === null || _a === undefined ? undefined : _a.type.is(PropertyAccess)) || ((_b = tree.parent) === null || _b === undefined ? undefined : _b.type.is(MethodAccess))) || !((_c = tree.parent) === null || _c === undefined ? undefined : _c.firstChild)) {
358
+ if (!(((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.type.is(PropertyAccess)) || ((_b = tree.parent) === null || _b === void 0 ? void 0 : _b.type.is(MethodAccess))) || !((_c = tree.parent) === null || _c === void 0 ? void 0 : _c.firstChild)) {
340
359
  return null;
341
360
  }
342
361
  const types = resolveTypes(state, tree.parent.firstChild.node, config);
343
- if (!(types === null || types === undefined ? undefined : types.size)) {
362
+ if (!(types === null || types === void 0 ? void 0 : types.size)) {
344
363
  return null;
345
364
  }
346
365
  let options = [];
347
366
  for (const type of types) {
348
- const typeDeclaration = (_d = config.types) === null || _d === undefined ? undefined : _d[type];
349
- options.push(...(((_e = typeDeclaration === null || typeDeclaration === undefined ? undefined : typeDeclaration.identifiers) === null || _e === undefined ? undefined : _e.map(autocompleteIdentifier)) || []), ...(((_f = typeDeclaration === null || typeDeclaration === undefined ? undefined : typeDeclaration.functions) === null || _f === undefined ? undefined : _f.map(autocompleteFunction)) || []));
367
+ const typeDeclaration = (_d = config.types) === null || _d === void 0 ? void 0 : _d[type];
368
+ options.push(...(((_e = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.identifiers) === null || _e === void 0 ? void 0 : _e.map(autocompleteIdentifier)) || []), ...(((_f = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.functions) === null || _f === void 0 ? void 0 : _f.map(autocompleteFunction)) || []));
350
369
  }
351
370
  return {
352
371
  from,
@@ -362,22 +381,22 @@ function expressionLanguageCompletion(context) {
362
381
  const lastChar = state.sliceDoc(pos - 1, pos);
363
382
  const prevNode = tree.resolveInner(pos, lastChar === ')' ? 0 : -1);
364
383
  const config = getExpressionLanguageConfig(state);
365
- const isIdentifier = (node) => (node === null || node === undefined ? undefined : node.type.is(Variable)) || (node === null || node === undefined ? undefined : node.type.is(Function));
366
- const isMember = (node) => (node === null || node === undefined ? undefined : node.type.is(Property)) || (node === null || node === undefined ? undefined : node.type.is(Method));
384
+ const isIdentifier = (node) => (node === null || node === void 0 ? void 0 : node.type.is(Variable)) || (node === null || node === void 0 ? void 0 : node.type.is(Function));
385
+ const isMember = (node) => (node === null || node === void 0 ? void 0 : node.type.is(Property)) || (node === null || node === void 0 ? void 0 : node.type.is(Method));
367
386
  if (prevNode.type.is(String) || prevNode.type.is(BlockComment)) {
368
387
  return null;
369
388
  }
370
- if ((((_a = prevNode.parent) === null || _a === undefined ? undefined : _a.type.is(PropertyAccess)) || ((_b = prevNode.parent) === null || _b === undefined ? undefined : _b.type.is(MethodAccess))) && [PropertyAccess, MethodAccess, ArrayAccess, Variable, Call, Application].includes((_c = prevNode.parent.firstChild) === null || _c === undefined ? undefined : _c.type.id)) {
389
+ if ((((_a = prevNode.parent) === null || _a === void 0 ? void 0 : _a.type.is(PropertyAccess)) || ((_b = prevNode.parent) === null || _b === void 0 ? void 0 : _b.type.is(MethodAccess))) && [PropertyAccess, MethodAccess, ArrayAccess, Variable, Call, Application].includes((_c = prevNode.parent.firstChild) === null || _c === void 0 ? void 0 : _c.type.id)) {
371
390
  return completeMember(state, config, prevNode, isIdentifier(prevNode) || isMember(prevNode) ? prevNode.from : pos, pos);
372
391
  }
373
- if (/^[\sa-z]*$/.test(lastChar) && ([Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes(prevNode.type.id) && prevNode.lastChild && !((_d = prevNode.lastChild) === null || _d === undefined ? undefined : _d.type.isError)
374
- || [Arguments, Array$1].includes(prevNode.type.id) && prevNode.lastChild && !((_e = prevNode.lastChild) === null || _e === undefined ? undefined : _e.type.isError)
375
- || [Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes((_f = prevNode.parent) === null || _f === undefined ? undefined : _f.type.id) && prevNode.type.isError
376
- || [Variable, Function].includes((_g = prevNode.parent) === null || _g === undefined ? undefined : _g.type.id) && prevNode.type.isError)) {
392
+ if (/^[\sa-z]*$/.test(lastChar) && ([Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes(prevNode.type.id) && prevNode.lastChild && !((_d = prevNode.lastChild) === null || _d === void 0 ? void 0 : _d.type.isError)
393
+ || [Arguments, Array$1].includes(prevNode.type.id) && prevNode.lastChild && !((_e = prevNode.lastChild) === null || _e === void 0 ? void 0 : _e.type.isError)
394
+ || [Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes((_f = prevNode.parent) === null || _f === void 0 ? void 0 : _f.type.id) && prevNode.type.isError
395
+ || [Variable, Function].includes((_g = prevNode.parent) === null || _g === void 0 ? void 0 : _g.type.id) && prevNode.type.isError)) {
377
396
  return completeOperatorKeyword(state, config, prevNode, ![Expression, UnaryExpression, BinaryExpression, TernaryExpression, Arguments].includes(prevNode.type.id) ? prevNode.from : pos, pos, explicit);
378
397
  }
379
- if (!/[0-9]/.test(lastChar) && !prevNode.type.is(OperatorKeyword) && ([Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes(prevNode.type.id) && ((_h = prevNode.lastChild) === null || _h === undefined ? undefined : _h.type.isError)
380
- || [Expression, UnaryExpression, BinaryExpression, TernaryExpression, Arguments].includes((_k = (_j = prevNode.parent) === null || _j === undefined ? undefined : _j.type.id) !== null && _k !== undefined ? _k : -1) && !prevNode.type.isError
398
+ if (!/[0-9]/.test(lastChar) && !prevNode.type.is(OperatorKeyword) && ([Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes(prevNode.type.id) && ((_h = prevNode.lastChild) === null || _h === void 0 ? void 0 : _h.type.isError)
399
+ || [Expression, UnaryExpression, BinaryExpression, TernaryExpression, Arguments].includes((_k = (_j = prevNode.parent) === null || _j === void 0 ? void 0 : _j.type.id) !== null && _k !== void 0 ? _k : -1) && !prevNode.type.isError
381
400
  || prevNode.type.is(Arguments) || prevNode.type.is(Array$1))) {
382
401
  return completeIdentifier(state, config, prevNode, isIdentifier(prevNode) ? prevNode.from : pos, pos);
383
402
  }
@@ -421,7 +440,7 @@ function getCursorTooltips(state) {
421
440
  return null;
422
441
  }
423
442
  const n = args.childAfter(range.from - 1);
424
- const argName = (_b = (_a = fn.args) === null || _a === undefined ? undefined : _a[n ? getNodeOrdinal(n) : 0]) === null || _b === undefined ? undefined : _b.name;
443
+ 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;
425
444
  if (n && n.from !== range.from || !argName) {
426
445
  return null;
427
446
  }
@@ -455,7 +474,7 @@ const keywordTooltip = view.hoverTooltip((view, pos, side) => {
455
474
  const tree = language.syntaxTree(view.state).resolveInner(pos, side);
456
475
  if (tree.type.is(OperatorKeyword)) {
457
476
  const name = view.state.sliceDoc(tree.from, tree.to);
458
- const info = (_a = keywords.find(x => x.name === name)) === null || _a === undefined ? undefined : _a.info;
477
+ const info = (_a = keywords.find(x => x.name === name)) === null || _a === void 0 ? void 0 : _a.info;
459
478
  if (info) {
460
479
  return {
461
480
  pos: tree.from,
@@ -470,20 +489,20 @@ const keywordTooltip = view.hoverTooltip((view, pos, side) => {
470
489
  }
471
490
  const skipEmpty = (x) => x;
472
491
  let info;
473
- if (((_b = tree.parent) === null || _b === undefined ? undefined : _b.firstChild) && (((_c = tree.parent) === null || _c === undefined ? undefined : _c.type.is(PropertyAccess)) || ((_d = tree.parent) === null || _d === undefined ? undefined : _d.type.is(MethodAccess))) && tree.prevSibling) {
492
+ if (((_b = tree.parent) === null || _b === void 0 ? void 0 : _b.firstChild) && (((_c = tree.parent) === null || _c === void 0 ? void 0 : _c.type.is(PropertyAccess)) || ((_d = tree.parent) === null || _d === void 0 ? void 0 : _d.type.is(MethodAccess))) && tree.prevSibling) {
474
493
  const node = tree.parent.firstChild;
475
494
  const types = Array.from(resolveTypes(view.state, node, config));
476
495
  const name = view.state.sliceDoc(tree.from, tree.to);
477
496
  info = [
478
- ...types.map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === undefined ? undefined : _a[type]) === null || _b === undefined ? undefined : _b.identifiers) === null || _c === undefined ? undefined : _c.find(x => x.name === name)) === null || _d === undefined ? undefined : _d.info; }).filter(skipEmpty),
479
- ...types.map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === undefined ? undefined : _a[type]) === null || _b === undefined ? undefined : _b.functions) === null || _c === undefined ? undefined : _c.find(x => x.name === name)) === null || _d === undefined ? undefined : _d.info; }).filter(skipEmpty),
497
+ ...types.map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.identifiers) === null || _c === void 0 ? void 0 : _c.find(x => x.name === name)) === null || _d === void 0 ? void 0 : _d.info; }).filter(skipEmpty),
498
+ ...types.map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.functions) === null || _c === void 0 ? void 0 : _c.find(x => x.name === name)) === null || _d === void 0 ? void 0 : _d.info; }).filter(skipEmpty),
480
499
  ].join('\n');
481
500
  }
482
501
  else {
483
502
  const name = view.state.sliceDoc(tree.from, tree.to);
484
503
  info = [
485
- ...[(_f = (_e = config.identifiers) === null || _e === undefined ? undefined : _e.find(x => x.name === name)) === null || _f === undefined ? undefined : _f.info].filter(skipEmpty),
486
- ...[(_h = (_g = config.functions) === null || _g === undefined ? undefined : _g.find(x => x.name === name)) === null || _h === undefined ? undefined : _h.info].filter(skipEmpty),
504
+ ...[(_f = (_e = config.identifiers) === null || _e === void 0 ? void 0 : _e.find(x => x.name === name)) === null || _f === void 0 ? void 0 : _f.info].filter(skipEmpty),
505
+ ...[(_h = (_g = config.functions) === null || _g === void 0 ? void 0 : _g.find(x => x.name === name)) === null || _h === void 0 ? void 0 : _h.info].filter(skipEmpty),
487
506
  ].join('\n');
488
507
  }
489
508
  if (!info) {
@@ -529,6 +548,9 @@ const baseTheme = view.EditorView.baseTheme({
529
548
  fontSize: ".8em",
530
549
  fontStyle: "monospace",
531
550
  backgroundColor: "rgba(127, 127, 127, .3)",
551
+ display: 'inline-block',
552
+ padding: '2px 4px',
553
+ borderRadius: '3px',
532
554
  },
533
555
  });
534
556
 
package/dist/index.d.cts CHANGED
@@ -5,14 +5,37 @@ import { CompletionContext, CompletionResult } from '@codemirror/autocomplete';
5
5
  import { SyntaxNode } from '@lezer/common';
6
6
  import { Tooltip } from '@codemirror/view';
7
7
 
8
+ /**
9
+ * The configuration object that is passed to `expressionlanguage` function
10
+ */
11
+ interface ExpressionLanguageConfig {
12
+ /** Type definitions used in `identifiers` & `functions` */
13
+ types?: {
14
+ [key: string]: ELType;
15
+ };
16
+ /** Top-level variables */
17
+ identifiers?: ELIdentifier[];
18
+ /** Top-level functions */
19
+ functions?: ELFunction[];
20
+ }
21
+ interface ELType {
22
+ /** Properties of the object */
23
+ identifiers?: ELIdentifier[];
24
+ /** Methods of the object */
25
+ functions?: ELFunction[];
26
+ info?: string;
27
+ }
8
28
  /**
9
29
  * Represents a variable or a property of an object
10
30
  */
11
31
  interface ELIdentifier {
12
32
  name: string;
33
+ /** If set, this is shown instead of `type` */
13
34
  detail?: string;
35
+ /** Text to show in hover tooltip, autocomplete etc. */
14
36
  info?: string;
15
- type?: string[];
37
+ /** All possible types for this identifier */
38
+ type?: ELTypeName[];
16
39
  }
17
40
  /**
18
41
  * Represents a function or a method of an object
@@ -21,38 +44,35 @@ interface ELFunction {
21
44
  name: string;
22
45
  args?: ELParameter[];
23
46
  info?: string;
24
- returnType?: string[];
47
+ returnType?: ELTypeName[];
25
48
  }
26
49
  interface ELParameter {
27
50
  name: string;
28
- type?: string[];
51
+ type?: ELTypeName[];
29
52
  info?: string;
30
53
  optional?: boolean;
31
54
  }
32
- interface ELType {
33
- identifiers?: ELIdentifier[];
34
- functions?: ELFunction[];
35
- info?: string;
36
- }
37
- interface ExpressionLanguageConfig {
38
- types?: {
39
- [key: string]: ELType;
40
- };
41
- identifiers?: ELIdentifier[];
42
- functions?: ELFunction[];
43
- }
44
55
  interface ELKeyword {
45
56
  name: string;
46
57
  detail?: string;
47
58
  info?: string;
48
59
  }
49
60
  declare enum ELScalar {
61
+ /** Equivalent to PHP `bool` */
50
62
  Bool = "bool",
63
+ /** Equivalent to PHP `int` or `float` */
51
64
  Number = "number",
65
+ /** Equivalent to PHP `string` */
52
66
  String = "string",
67
+ /** Equivalent to PHP `null` */
53
68
  Null = "null",
69
+ /** Equivalent to PHP `mixed` */
54
70
  Any = "any"
55
71
  }
72
+ /**
73
+ * One of predefined types (`ELScalar`) or a custom type from `ExpressionLanguageConfig.types`
74
+ */
75
+ type ELTypeName = ELScalar | string;
56
76
 
57
77
  declare function expressionLanguageCompletion(context: CompletionContext): CompletionResult | null;
58
78
 
@@ -74,6 +94,7 @@ declare const Property: number;
74
94
  declare const Variable: number;
75
95
 
76
96
  declare const createInfoElement: (html: string) => HTMLDivElement;
97
+ declare const createCompletionInfoElement: (html: string) => HTMLDivElement;
77
98
  declare function resolveFunctionDefinition(node: SyntaxNode | null, state: EditorState, config: ExpressionLanguageConfig): ELFunction | undefined;
78
99
  declare const resolveIdentifier: (nodeTypeId: typeof Method | typeof Property | typeof Function | typeof Variable, identifier?: string, config?: {
79
100
  identifiers?: ELIdentifier[];
@@ -83,6 +104,7 @@ declare function resolveTypes(state: EditorState, node: SyntaxNode | undefined |
83
104
  declare function getExpressionLanguageConfig(state: EditorState): ExpressionLanguageConfig;
84
105
  declare const keywords: ELKeyword[];
85
106
 
107
+ declare const utils_d_createCompletionInfoElement: typeof createCompletionInfoElement;
86
108
  declare const utils_d_createInfoElement: typeof createInfoElement;
87
109
  declare const utils_d_getExpressionLanguageConfig: typeof getExpressionLanguageConfig;
88
110
  declare const utils_d_keywords: typeof keywords;
@@ -90,7 +112,7 @@ declare const utils_d_resolveFunctionDefinition: typeof resolveFunctionDefinitio
90
112
  declare const utils_d_resolveIdentifier: typeof resolveIdentifier;
91
113
  declare const utils_d_resolveTypes: typeof resolveTypes;
92
114
  declare namespace utils_d {
93
- export { utils_d_createInfoElement as createInfoElement, utils_d_getExpressionLanguageConfig as getExpressionLanguageConfig, utils_d_keywords as keywords, utils_d_resolveFunctionDefinition as resolveFunctionDefinition, utils_d_resolveIdentifier as resolveIdentifier, utils_d_resolveTypes as resolveTypes };
115
+ export { utils_d_createCompletionInfoElement as createCompletionInfoElement, utils_d_createInfoElement as createInfoElement, utils_d_getExpressionLanguageConfig as getExpressionLanguageConfig, utils_d_keywords as keywords, utils_d_resolveFunctionDefinition as resolveFunctionDefinition, utils_d_resolveIdentifier as resolveIdentifier, utils_d_resolveTypes as resolveTypes };
94
116
  }
95
117
 
96
118
  declare const cursorTooltipField: StateField<readonly Tooltip[]>;
@@ -107,4 +129,4 @@ declare namespace tooltip_d {
107
129
  declare const ELLanguage: LRLanguage;
108
130
  declare function expressionlanguage(config?: ExpressionLanguageConfig, extensions?: Extension[]): LanguageSupport;
109
131
 
110
- export { type ELFunction, type ELIdentifier, type ELKeyword, ELLanguage, type ELParameter, ELScalar, type ELType, type ExpressionLanguageConfig, complete_d as _complete, linter_d as _linter, tooltip_d as _tooltip, utils_d as _utils, expressionlanguage };
132
+ export { type ELFunction, type ELIdentifier, type ELKeyword, ELLanguage, type ELParameter, ELScalar, type ELType, type ELTypeName, type ExpressionLanguageConfig, complete_d as _complete, linter_d as _linter, tooltip_d as _tooltip, utils_d as _utils, expressionlanguage };
package/dist/index.d.ts CHANGED
@@ -5,14 +5,37 @@ import { CompletionContext, CompletionResult } from '@codemirror/autocomplete';
5
5
  import { SyntaxNode } from '@lezer/common';
6
6
  import { Tooltip } from '@codemirror/view';
7
7
 
8
+ /**
9
+ * The configuration object that is passed to `expressionlanguage` function
10
+ */
11
+ interface ExpressionLanguageConfig {
12
+ /** Type definitions used in `identifiers` & `functions` */
13
+ types?: {
14
+ [key: string]: ELType;
15
+ };
16
+ /** Top-level variables */
17
+ identifiers?: ELIdentifier[];
18
+ /** Top-level functions */
19
+ functions?: ELFunction[];
20
+ }
21
+ interface ELType {
22
+ /** Properties of the object */
23
+ identifiers?: ELIdentifier[];
24
+ /** Methods of the object */
25
+ functions?: ELFunction[];
26
+ info?: string;
27
+ }
8
28
  /**
9
29
  * Represents a variable or a property of an object
10
30
  */
11
31
  interface ELIdentifier {
12
32
  name: string;
33
+ /** If set, this is shown instead of `type` */
13
34
  detail?: string;
35
+ /** Text to show in hover tooltip, autocomplete etc. */
14
36
  info?: string;
15
- type?: string[];
37
+ /** All possible types for this identifier */
38
+ type?: ELTypeName[];
16
39
  }
17
40
  /**
18
41
  * Represents a function or a method of an object
@@ -21,38 +44,35 @@ interface ELFunction {
21
44
  name: string;
22
45
  args?: ELParameter[];
23
46
  info?: string;
24
- returnType?: string[];
47
+ returnType?: ELTypeName[];
25
48
  }
26
49
  interface ELParameter {
27
50
  name: string;
28
- type?: string[];
51
+ type?: ELTypeName[];
29
52
  info?: string;
30
53
  optional?: boolean;
31
54
  }
32
- interface ELType {
33
- identifiers?: ELIdentifier[];
34
- functions?: ELFunction[];
35
- info?: string;
36
- }
37
- interface ExpressionLanguageConfig {
38
- types?: {
39
- [key: string]: ELType;
40
- };
41
- identifiers?: ELIdentifier[];
42
- functions?: ELFunction[];
43
- }
44
55
  interface ELKeyword {
45
56
  name: string;
46
57
  detail?: string;
47
58
  info?: string;
48
59
  }
49
60
  declare enum ELScalar {
61
+ /** Equivalent to PHP `bool` */
50
62
  Bool = "bool",
63
+ /** Equivalent to PHP `int` or `float` */
51
64
  Number = "number",
65
+ /** Equivalent to PHP `string` */
52
66
  String = "string",
67
+ /** Equivalent to PHP `null` */
53
68
  Null = "null",
69
+ /** Equivalent to PHP `mixed` */
54
70
  Any = "any"
55
71
  }
72
+ /**
73
+ * One of predefined types (`ELScalar`) or a custom type from `ExpressionLanguageConfig.types`
74
+ */
75
+ type ELTypeName = ELScalar | string;
56
76
 
57
77
  declare function expressionLanguageCompletion(context: CompletionContext): CompletionResult | null;
58
78
 
@@ -74,6 +94,7 @@ declare const Property: number;
74
94
  declare const Variable: number;
75
95
 
76
96
  declare const createInfoElement: (html: string) => HTMLDivElement;
97
+ declare const createCompletionInfoElement: (html: string) => HTMLDivElement;
77
98
  declare function resolveFunctionDefinition(node: SyntaxNode | null, state: EditorState, config: ExpressionLanguageConfig): ELFunction | undefined;
78
99
  declare const resolveIdentifier: (nodeTypeId: typeof Method | typeof Property | typeof Function | typeof Variable, identifier?: string, config?: {
79
100
  identifiers?: ELIdentifier[];
@@ -83,6 +104,7 @@ declare function resolveTypes(state: EditorState, node: SyntaxNode | undefined |
83
104
  declare function getExpressionLanguageConfig(state: EditorState): ExpressionLanguageConfig;
84
105
  declare const keywords: ELKeyword[];
85
106
 
107
+ declare const utils_d_createCompletionInfoElement: typeof createCompletionInfoElement;
86
108
  declare const utils_d_createInfoElement: typeof createInfoElement;
87
109
  declare const utils_d_getExpressionLanguageConfig: typeof getExpressionLanguageConfig;
88
110
  declare const utils_d_keywords: typeof keywords;
@@ -90,7 +112,7 @@ declare const utils_d_resolveFunctionDefinition: typeof resolveFunctionDefinitio
90
112
  declare const utils_d_resolveIdentifier: typeof resolveIdentifier;
91
113
  declare const utils_d_resolveTypes: typeof resolveTypes;
92
114
  declare namespace utils_d {
93
- export { utils_d_createInfoElement as createInfoElement, utils_d_getExpressionLanguageConfig as getExpressionLanguageConfig, utils_d_keywords as keywords, utils_d_resolveFunctionDefinition as resolveFunctionDefinition, utils_d_resolveIdentifier as resolveIdentifier, utils_d_resolveTypes as resolveTypes };
115
+ export { utils_d_createCompletionInfoElement as createCompletionInfoElement, utils_d_createInfoElement as createInfoElement, utils_d_getExpressionLanguageConfig as getExpressionLanguageConfig, utils_d_keywords as keywords, utils_d_resolveFunctionDefinition as resolveFunctionDefinition, utils_d_resolveIdentifier as resolveIdentifier, utils_d_resolveTypes as resolveTypes };
94
116
  }
95
117
 
96
118
  declare const cursorTooltipField: StateField<readonly Tooltip[]>;
@@ -107,4 +129,4 @@ declare namespace tooltip_d {
107
129
  declare const ELLanguage: LRLanguage;
108
130
  declare function expressionlanguage(config?: ExpressionLanguageConfig, extensions?: Extension[]): LanguageSupport;
109
131
 
110
- export { type ELFunction, type ELIdentifier, type ELKeyword, ELLanguage, type ELParameter, ELScalar, type ELType, type ExpressionLanguageConfig, complete_d as _complete, linter_d as _linter, tooltip_d as _tooltip, utils_d as _utils, expressionlanguage };
132
+ export { type ELFunction, type ELIdentifier, type ELKeyword, ELLanguage, type ELParameter, ELScalar, type ELType, type ELTypeName, type ExpressionLanguageConfig, complete_d as _complete, linter_d as _linter, tooltip_d as _tooltip, utils_d as _utils, expressionlanguage };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { LRParser, LocalTokenGroup } from '@lezer/lr';
2
- import { syntaxTree, LRLanguage, indentNodeProp, delimitedIndent, foldNodeProp, LanguageSupport } from '@codemirror/language';
2
+ import { syntaxTree, LRLanguage, indentNodeProp, foldNodeProp, delimitedIndent, LanguageSupport } from '@codemirror/language';
3
3
  import { styleTags, tags } from '@lezer/highlight';
4
4
  import { linter as linter$1 } from '@codemirror/lint';
5
5
  import { insertCompletionText } from '@codemirror/autocomplete';
@@ -33,11 +33,17 @@ const parser = /*@__PURE__*/LRParser.deserialize({
33
33
  tokenPrec: 532
34
34
  });
35
35
 
36
+ // generate CONFIGURATION.md from this file by running "tsdoc --src=src/types.ts --dest=CONFIGURATION.md --noemoji --types"
36
37
  var ELScalar = /*@__PURE__*/(function (ELScalar) {
38
+ /** Equivalent to PHP `bool` */
37
39
  ELScalar["Bool"] = "bool";
40
+ /** Equivalent to PHP `int` or `float` */
38
41
  ELScalar["Number"] = "number";
42
+ /** Equivalent to PHP `string` */
39
43
  ELScalar["String"] = "string";
44
+ /** Equivalent to PHP `null` */
40
45
  ELScalar["Null"] = "null";
46
+ /** Equivalent to PHP `mixed` */
41
47
  ELScalar["Any"] = "any";
42
48
  return ELScalar})(ELScalar || (ELScalar = {}));
43
49
 
@@ -67,6 +73,11 @@ const createInfoElement = (html) => {
67
73
  dom.className = 'cm-diagnostic';
68
74
  return dom;
69
75
  };
76
+ const createCompletionInfoElement = (html) => {
77
+ const dom = document.createElement("div");
78
+ dom.innerHTML = html;
79
+ return dom;
80
+ };
70
81
  function resolveFunctionDefinition(node, state, config) {
71
82
  var _a;
72
83
  if (!node) {
@@ -74,17 +85,17 @@ function resolveFunctionDefinition(node, state, config) {
74
85
  }
75
86
  let identifier;
76
87
  if ((node.type.is(PropertyAccess) || node.type.is(MethodAccess)) && node.lastChild) {
77
- const leftArgument = (_a = node.firstChild) === null || _a === undefined ? undefined : _a.node;
88
+ const leftArgument = (_a = node.firstChild) === null || _a === void 0 ? void 0 : _a.node;
78
89
  const types = Array.from(resolveTypes(state, leftArgument, config));
79
90
  identifier = state.sliceDoc(node.lastChild.from, node.lastChild.to);
80
- return types.map(type => { var _a; return resolveCallable(identifier, (_a = config.types) === null || _a === undefined ? undefined : _a[type]); }).find(x => x);
91
+ return types.map(type => { var _a; return resolveCallable(identifier, (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]); }).find(x => x);
81
92
  }
82
93
  else if (node.type.is(Function)) {
83
94
  identifier = state.sliceDoc(node.from, node.node.firstChild ? node.node.firstChild.from - 1 : node.to);
84
95
  return resolveCallable(identifier, config);
85
96
  }
86
97
  }
87
- const resolveCallable = (identifier, config) => { var _a; return (_a = config === null || config === undefined ? undefined : config.functions) === null || _a === undefined ? undefined : _a.find(x => x.name === identifier); };
98
+ 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); };
88
99
  const resolveIdentifier = (nodeTypeId, identifier, config) => {
89
100
  var _a;
90
101
  switch (nodeTypeId) {
@@ -93,7 +104,7 @@ const resolveIdentifier = (nodeTypeId, identifier, config) => {
93
104
  return resolveCallable(identifier, config);
94
105
  case Property:
95
106
  case Variable:
96
- return (_a = config === null || config === undefined ? undefined : config.identifiers) === null || _a === undefined ? undefined : _a.find(x => x.name === identifier);
107
+ return (_a = config === null || config === void 0 ? void 0 : config.identifiers) === null || _a === void 0 ? void 0 : _a.find(x => x.name === identifier);
97
108
  }
98
109
  };
99
110
  function resolveTypes(state, node, config) {
@@ -112,27 +123,27 @@ function resolveTypes(state, node, config) {
112
123
  else if (node.type.is(Variable)) {
113
124
  const varName = state.sliceDoc(node.from, node.to) || '';
114
125
  // @ts-ignore
115
- (_b = (_a = resolveIdentifier(node.type.id, varName, config)) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.forEach((x) => types.add(x));
126
+ (_b = (_a = resolveIdentifier(node.type.id, varName, config)) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.forEach((x) => types.add(x));
116
127
  }
117
128
  else if (node.type.is(Function)) {
118
129
  const varName = state.sliceDoc(node.from, node.to) || '';
119
130
  // @ts-ignore
120
- (_d = (_c = resolveIdentifier(node.type.id, varName, config)) === null || _c === undefined ? undefined : _c.returnType) === null || _d === undefined ? undefined : _d.forEach((x) => types.add(x));
131
+ (_d = (_c = resolveIdentifier(node.type.id, varName, config)) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
121
132
  }
122
- else if (node.type.is(PropertyAccess) && node.firstChild && ((_e = node.lastChild) === null || _e === undefined ? undefined : _e.type.is(Property))) {
133
+ else if (node.type.is(PropertyAccess) && node.firstChild && ((_e = node.lastChild) === null || _e === void 0 ? void 0 : _e.type.is(Property))) {
123
134
  const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
124
- (_f = resolveTypes(state, node.firstChild, config)) === null || _f === undefined ? undefined : _f.forEach(baseType => {
135
+ (_f = resolveTypes(state, node.firstChild, config)) === null || _f === void 0 ? void 0 : _f.forEach(baseType => {
125
136
  var _a, _b, _c, _d;
126
137
  // @ts-ignore
127
- (_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === undefined ? undefined : _a.type.id, varName, (_b = config.types) === null || _b === undefined ? undefined : _b[baseType])) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.forEach((x) => types.add(x));
138
+ (_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.type.id, varName, (_b = config.types) === null || _b === void 0 ? void 0 : _b[baseType])) === null || _c === void 0 ? void 0 : _c.type) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
128
139
  });
129
140
  }
130
- else if (node.type.is(MethodAccess) && node.firstChild && ((_g = node.lastChild) === null || _g === undefined ? undefined : _g.type.is(Method))) {
141
+ else if (node.type.is(MethodAccess) && node.firstChild && ((_g = node.lastChild) === null || _g === void 0 ? void 0 : _g.type.is(Method))) {
131
142
  const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
132
- (_h = resolveTypes(state, node.firstChild, config)) === null || _h === undefined ? undefined : _h.forEach(baseType => {
143
+ (_h = resolveTypes(state, node.firstChild, config)) === null || _h === void 0 ? void 0 : _h.forEach(baseType => {
133
144
  var _a, _b, _c, _d;
134
145
  // @ts-ignore
135
- (_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === undefined ? undefined : _a.type.id, varName, (_b = config.types) === null || _b === undefined ? undefined : _b[baseType])) === null || _c === undefined ? undefined : _c.returnType) === null || _d === undefined ? undefined : _d.forEach((x) => types.add(x));
146
+ (_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.type.id, varName, (_b = config.types) === null || _b === void 0 ? void 0 : _b[baseType])) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
136
147
  });
137
148
  }
138
149
  else if (node.type.is(Application) && node.firstChild) {
@@ -142,7 +153,7 @@ function resolveTypes(state, node, config) {
142
153
  resolveTypes(state, node.firstChild.nextSibling, config).forEach(x => types.add(x));
143
154
  resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
144
155
  }
145
- else if (node.type.is(BinaryExpression) && ((_j = node.firstChild) === null || _j === undefined ? undefined : _j.nextSibling) && ((_l = (_k = node.firstChild) === null || _k === undefined ? undefined : _k.nextSibling) === null || _l === undefined ? undefined : _l.nextSibling)) {
156
+ else if (node.type.is(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)) {
146
157
  const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
147
158
  if (operator == '?:' || operator == '??' || operator == '?') {
148
159
  if (operator == '?:' || operator == '??') {
@@ -189,6 +200,7 @@ const keywords = [
189
200
 
190
201
  var utils = /*#__PURE__*//*@__PURE__*/Object.freeze({
191
202
  __proto__: null,
203
+ createCompletionInfoElement: createCompletionInfoElement,
192
204
  createInfoElement: createInfoElement,
193
205
  getExpressionLanguageConfig: getExpressionLanguageConfig,
194
206
  keywords: keywords,
@@ -215,7 +227,7 @@ const expressionLanguageLinterSource = (state) => {
215
227
  }
216
228
  identifier = state.sliceDoc(from, to);
217
229
  if (identifier.length === 0) {
218
- diagnostics.push({ from, to: (_c = (_b = (_a = node.node.parent) === null || _a === undefined ? undefined : _a.parent) === null || _b === undefined ? undefined : _b.to) !== null && _c !== undefined ? _c : to, severity: 'error', message: `Expression expected` });
230
+ diagnostics.push({ from, to: (_c = (_b = (_a = node.node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.to) !== null && _c !== void 0 ? _c : to, severity: 'error', message: `Expression expected` });
219
231
  }
220
232
  else {
221
233
  const type = /^[a-zA-Z_]+[a-zA-Z_0-9]*$/.test(identifier) ? 'identifier' : 'operator';
@@ -224,16 +236,20 @@ const expressionLanguageLinterSource = (state) => {
224
236
  return;
225
237
  case Arguments:
226
238
  const fn = resolveFunctionDefinition(node.node.prevSibling, state, config);
227
- const args = fn === null || fn === undefined ? undefined : fn.args;
239
+ const args = fn === null || fn === void 0 ? void 0 : fn.args;
228
240
  if (!args) {
229
241
  return;
230
242
  }
231
- for (let n = node.node.firstChild, i = 0; n != null; n = n.nextSibling) {
243
+ const argCountMin = args.reduce((count, arg) => count + Number(!arg.optional), 0);
244
+ const argCountMax = args.length;
245
+ const argumentCountHintFn = () => `<code>${fn.name}</code> takes ${argCountMin == argCountMax ? `exactly ${argCountMax}` : `${argCountMin}–${argCountMax}`} argument${argCountMax == 1 ? '' : 's'}`;
246
+ let i = 0;
247
+ for (let n = node.node.firstChild; n != null; n = n.nextSibling) {
232
248
  if (n.type.is(BlockComment)) {
233
249
  continue;
234
250
  }
235
- if (i > args.length - 1) {
236
- diagnostics.push({ from: n.from, to: n.to, severity: 'warning', message: `Unexpected argument – <code>${fn.name}</code> takes ${args.length} argument${args.length == 1 ? '' : 's'}` });
251
+ if (i > argCountMax - 1) {
252
+ diagnostics.push({ from: n.from, to: n.to, severity: 'warning', message: `Unexpected argument – ${argumentCountHintFn()}` });
237
253
  continue;
238
254
  }
239
255
  const typesUsed = Array.from(resolveTypes(state, n, config));
@@ -243,13 +259,16 @@ const expressionLanguageLinterSource = (state) => {
243
259
  }
244
260
  i++;
245
261
  }
262
+ if (i < argCountMin) {
263
+ diagnostics.push({ from: node.from, to: node.to, severity: 'error', message: `Too few arguments – ${argumentCountHintFn()}` });
264
+ }
246
265
  break;
247
266
  case Property:
248
267
  case Method:
249
- const leftArgument = (_e = (_d = node.node.parent) === null || _d === undefined ? undefined : _d.firstChild) === null || _e === undefined ? undefined : _e.node;
268
+ const leftArgument = (_e = (_d = node.node.parent) === null || _d === void 0 ? void 0 : _d.firstChild) === null || _e === void 0 ? void 0 : _e.node;
250
269
  const types = Array.from(resolveTypes(state, leftArgument, config));
251
270
  identifier = state.sliceDoc(from, to);
252
- if (!types.find(type => { var _a; return resolveIdentifier(id, identifier, (_a = config.types) === null || _a === undefined ? undefined : _a[type]); })) {
271
+ if (!types.find(type => { var _a; return resolveIdentifier(id, identifier, (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]); })) {
253
272
  diagnostics.push({ from, to, severity: 'error', message: `${node.name} <code>${identifier}</code> not found in <code>${types.join('|')}</code>` });
254
273
  }
255
274
  break;
@@ -261,7 +280,7 @@ const expressionLanguageLinterSource = (state) => {
261
280
  }
262
281
  break;
263
282
  }
264
- if (identifier && ((_f = node.node.parent) === null || _f === undefined ? undefined : _f.type.isError)) {
283
+ if (identifier && ((_f = node.node.parent) === null || _f === void 0 ? void 0 : _f.type.isError)) {
265
284
  diagnostics.push({ from, to, severity: 'error', message: `Unexpected identifier <code>${identifier}</code>` });
266
285
  }
267
286
  });
@@ -285,13 +304,13 @@ var linter = /*#__PURE__*//*@__PURE__*/Object.freeze({
285
304
  const autocompleteFunction = (x) => {
286
305
  var _a, _b, _c;
287
306
  return ({
288
- label: `${x.name}(${((_b = (_a = x.args) === null || _a === undefined ? undefined : _a.map(x => x.name)) === null || _b === undefined ? undefined : _b.join(',')) || ''})`,
307
+ 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(',')) || ''})`,
289
308
  apply: (view, completion, from, to) => {
290
309
  var _a, _b;
291
- view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, `${x.name}()`, from, to)), { selection: { anchor: from + x.name.length + (((_b = (_a = x.args) === null || _a === undefined ? undefined : _a.length) !== null && _b !== undefined ? _b : 0) > 0 ? 1 : 2) } }));
310
+ view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, `${x.name}()`, from, to)), { selection: { anchor: from + x.name.length + (((_b = (_a = x.args) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0 ? 1 : 2) } }));
292
311
  },
293
- detail: (_c = x.returnType) === null || _c === undefined ? undefined : _c.join('|'),
294
- info: x.info,
312
+ detail: (_c = x.returnType) === null || _c === void 0 ? void 0 : _c.join('|'),
313
+ info: () => ({ dom: createCompletionInfoElement(x.info) }),
295
314
  type: "function",
296
315
  });
297
316
  };
@@ -300,8 +319,8 @@ const autocompleteIdentifier = (x) => {
300
319
  return ({
301
320
  label: x.name,
302
321
  apply: x.name,
303
- info: x.info,
304
- detail: x.detail || ((_a = x.type) === null || _a === undefined ? undefined : _a.join('|')),
322
+ info: () => ({ dom: createCompletionInfoElement(x.info) }),
323
+ detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')),
305
324
  type: 'variable',
306
325
  });
307
326
  };
@@ -313,17 +332,17 @@ function completeOperatorKeyword(state, config, tree, from, to, explicit) {
313
332
  options: (_a = keywords.map(({ name, info, detail }) => ({
314
333
  label: name,
315
334
  apply: `${name} `,
316
- info: info,
335
+ info: () => ({ dom: createCompletionInfoElement(info) }),
317
336
  detail,
318
337
  type: "keyword"
319
- }))) !== null && _a !== undefined ? _a : [],
320
- validFor: (text) => { var _a; return (_a = keywords.some(({ name }) => explicit || name.includes(text))) !== null && _a !== undefined ? _a : false; },
338
+ }))) !== null && _a !== void 0 ? _a : [],
339
+ validFor: (text) => { var _a; return (_a = keywords.some(({ name }) => explicit || name.includes(text))) !== null && _a !== void 0 ? _a : false; },
321
340
  };
322
341
  }
323
342
  function completeIdentifier(state, config, tree, from, to) {
324
343
  var _a, _b;
325
- const identifiers = (_a = config.identifiers) !== null && _a !== undefined ? _a : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
326
- const functions = (_b = config.functions) !== null && _b !== undefined ? _b : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
344
+ const identifiers = (_a = config.identifiers) !== null && _a !== void 0 ? _a : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
345
+ const functions = (_b = config.functions) !== null && _b !== void 0 ? _b : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
327
346
  return {
328
347
  from,
329
348
  to,
@@ -333,17 +352,17 @@ function completeIdentifier(state, config, tree, from, to) {
333
352
  }
334
353
  function completeMember(state, config, tree, from, to, explicit) {
335
354
  var _a, _b, _c, _d, _e, _f;
336
- if (!(((_a = tree.parent) === null || _a === undefined ? undefined : _a.type.is(PropertyAccess)) || ((_b = tree.parent) === null || _b === undefined ? undefined : _b.type.is(MethodAccess))) || !((_c = tree.parent) === null || _c === undefined ? undefined : _c.firstChild)) {
355
+ if (!(((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.type.is(PropertyAccess)) || ((_b = tree.parent) === null || _b === void 0 ? void 0 : _b.type.is(MethodAccess))) || !((_c = tree.parent) === null || _c === void 0 ? void 0 : _c.firstChild)) {
337
356
  return null;
338
357
  }
339
358
  const types = resolveTypes(state, tree.parent.firstChild.node, config);
340
- if (!(types === null || types === undefined ? undefined : types.size)) {
359
+ if (!(types === null || types === void 0 ? void 0 : types.size)) {
341
360
  return null;
342
361
  }
343
362
  let options = [];
344
363
  for (const type of types) {
345
- const typeDeclaration = (_d = config.types) === null || _d === undefined ? undefined : _d[type];
346
- options.push(...(((_e = typeDeclaration === null || typeDeclaration === undefined ? undefined : typeDeclaration.identifiers) === null || _e === undefined ? undefined : _e.map(autocompleteIdentifier)) || []), ...(((_f = typeDeclaration === null || typeDeclaration === undefined ? undefined : typeDeclaration.functions) === null || _f === undefined ? undefined : _f.map(autocompleteFunction)) || []));
364
+ const typeDeclaration = (_d = config.types) === null || _d === void 0 ? void 0 : _d[type];
365
+ options.push(...(((_e = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.identifiers) === null || _e === void 0 ? void 0 : _e.map(autocompleteIdentifier)) || []), ...(((_f = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.functions) === null || _f === void 0 ? void 0 : _f.map(autocompleteFunction)) || []));
347
366
  }
348
367
  return {
349
368
  from,
@@ -359,22 +378,22 @@ function expressionLanguageCompletion(context) {
359
378
  const lastChar = state.sliceDoc(pos - 1, pos);
360
379
  const prevNode = tree.resolveInner(pos, lastChar === ')' ? 0 : -1);
361
380
  const config = getExpressionLanguageConfig(state);
362
- const isIdentifier = (node) => (node === null || node === undefined ? undefined : node.type.is(Variable)) || (node === null || node === undefined ? undefined : node.type.is(Function));
363
- const isMember = (node) => (node === null || node === undefined ? undefined : node.type.is(Property)) || (node === null || node === undefined ? undefined : node.type.is(Method));
381
+ const isIdentifier = (node) => (node === null || node === void 0 ? void 0 : node.type.is(Variable)) || (node === null || node === void 0 ? void 0 : node.type.is(Function));
382
+ const isMember = (node) => (node === null || node === void 0 ? void 0 : node.type.is(Property)) || (node === null || node === void 0 ? void 0 : node.type.is(Method));
364
383
  if (prevNode.type.is(String) || prevNode.type.is(BlockComment)) {
365
384
  return null;
366
385
  }
367
- if ((((_a = prevNode.parent) === null || _a === undefined ? undefined : _a.type.is(PropertyAccess)) || ((_b = prevNode.parent) === null || _b === undefined ? undefined : _b.type.is(MethodAccess))) && [PropertyAccess, MethodAccess, ArrayAccess, Variable, Call, Application].includes((_c = prevNode.parent.firstChild) === null || _c === undefined ? undefined : _c.type.id)) {
386
+ if ((((_a = prevNode.parent) === null || _a === void 0 ? void 0 : _a.type.is(PropertyAccess)) || ((_b = prevNode.parent) === null || _b === void 0 ? void 0 : _b.type.is(MethodAccess))) && [PropertyAccess, MethodAccess, ArrayAccess, Variable, Call, Application].includes((_c = prevNode.parent.firstChild) === null || _c === void 0 ? void 0 : _c.type.id)) {
368
387
  return completeMember(state, config, prevNode, isIdentifier(prevNode) || isMember(prevNode) ? prevNode.from : pos, pos);
369
388
  }
370
- if (/^[\sa-z]*$/.test(lastChar) && ([Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes(prevNode.type.id) && prevNode.lastChild && !((_d = prevNode.lastChild) === null || _d === undefined ? undefined : _d.type.isError)
371
- || [Arguments, Array$1].includes(prevNode.type.id) && prevNode.lastChild && !((_e = prevNode.lastChild) === null || _e === undefined ? undefined : _e.type.isError)
372
- || [Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes((_f = prevNode.parent) === null || _f === undefined ? undefined : _f.type.id) && prevNode.type.isError
373
- || [Variable, Function].includes((_g = prevNode.parent) === null || _g === undefined ? undefined : _g.type.id) && prevNode.type.isError)) {
389
+ if (/^[\sa-z]*$/.test(lastChar) && ([Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes(prevNode.type.id) && prevNode.lastChild && !((_d = prevNode.lastChild) === null || _d === void 0 ? void 0 : _d.type.isError)
390
+ || [Arguments, Array$1].includes(prevNode.type.id) && prevNode.lastChild && !((_e = prevNode.lastChild) === null || _e === void 0 ? void 0 : _e.type.isError)
391
+ || [Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes((_f = prevNode.parent) === null || _f === void 0 ? void 0 : _f.type.id) && prevNode.type.isError
392
+ || [Variable, Function].includes((_g = prevNode.parent) === null || _g === void 0 ? void 0 : _g.type.id) && prevNode.type.isError)) {
374
393
  return completeOperatorKeyword(state, config, prevNode, ![Expression, UnaryExpression, BinaryExpression, TernaryExpression, Arguments].includes(prevNode.type.id) ? prevNode.from : pos, pos, explicit);
375
394
  }
376
- if (!/[0-9]/.test(lastChar) && !prevNode.type.is(OperatorKeyword) && ([Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes(prevNode.type.id) && ((_h = prevNode.lastChild) === null || _h === undefined ? undefined : _h.type.isError)
377
- || [Expression, UnaryExpression, BinaryExpression, TernaryExpression, Arguments].includes((_k = (_j = prevNode.parent) === null || _j === undefined ? undefined : _j.type.id) !== null && _k !== undefined ? _k : -1) && !prevNode.type.isError
395
+ if (!/[0-9]/.test(lastChar) && !prevNode.type.is(OperatorKeyword) && ([Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes(prevNode.type.id) && ((_h = prevNode.lastChild) === null || _h === void 0 ? void 0 : _h.type.isError)
396
+ || [Expression, UnaryExpression, BinaryExpression, TernaryExpression, Arguments].includes((_k = (_j = prevNode.parent) === null || _j === void 0 ? void 0 : _j.type.id) !== null && _k !== void 0 ? _k : -1) && !prevNode.type.isError
378
397
  || prevNode.type.is(Arguments) || prevNode.type.is(Array$1))) {
379
398
  return completeIdentifier(state, config, prevNode, isIdentifier(prevNode) ? prevNode.from : pos, pos);
380
399
  }
@@ -418,7 +437,7 @@ function getCursorTooltips(state) {
418
437
  return null;
419
438
  }
420
439
  const n = args.childAfter(range.from - 1);
421
- const argName = (_b = (_a = fn.args) === null || _a === undefined ? undefined : _a[n ? getNodeOrdinal(n) : 0]) === null || _b === undefined ? undefined : _b.name;
440
+ 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;
422
441
  if (n && n.from !== range.from || !argName) {
423
442
  return null;
424
443
  }
@@ -452,7 +471,7 @@ const keywordTooltip = /*@__PURE__*/hoverTooltip((view, pos, side) => {
452
471
  const tree = syntaxTree(view.state).resolveInner(pos, side);
453
472
  if (tree.type.is(OperatorKeyword)) {
454
473
  const name = view.state.sliceDoc(tree.from, tree.to);
455
- const info = (_a = keywords.find(x => x.name === name)) === null || _a === undefined ? undefined : _a.info;
474
+ const info = (_a = keywords.find(x => x.name === name)) === null || _a === void 0 ? void 0 : _a.info;
456
475
  if (info) {
457
476
  return {
458
477
  pos: tree.from,
@@ -467,20 +486,20 @@ const keywordTooltip = /*@__PURE__*/hoverTooltip((view, pos, side) => {
467
486
  }
468
487
  const skipEmpty = (x) => x;
469
488
  let info;
470
- if (((_b = tree.parent) === null || _b === undefined ? undefined : _b.firstChild) && (((_c = tree.parent) === null || _c === undefined ? undefined : _c.type.is(PropertyAccess)) || ((_d = tree.parent) === null || _d === undefined ? undefined : _d.type.is(MethodAccess))) && tree.prevSibling) {
489
+ if (((_b = tree.parent) === null || _b === void 0 ? void 0 : _b.firstChild) && (((_c = tree.parent) === null || _c === void 0 ? void 0 : _c.type.is(PropertyAccess)) || ((_d = tree.parent) === null || _d === void 0 ? void 0 : _d.type.is(MethodAccess))) && tree.prevSibling) {
471
490
  const node = tree.parent.firstChild;
472
491
  const types = Array.from(resolveTypes(view.state, node, config));
473
492
  const name = view.state.sliceDoc(tree.from, tree.to);
474
493
  info = [
475
- ...types.map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === undefined ? undefined : _a[type]) === null || _b === undefined ? undefined : _b.identifiers) === null || _c === undefined ? undefined : _c.find(x => x.name === name)) === null || _d === undefined ? undefined : _d.info; }).filter(skipEmpty),
476
- ...types.map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === undefined ? undefined : _a[type]) === null || _b === undefined ? undefined : _b.functions) === null || _c === undefined ? undefined : _c.find(x => x.name === name)) === null || _d === undefined ? undefined : _d.info; }).filter(skipEmpty),
494
+ ...types.map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.identifiers) === null || _c === void 0 ? void 0 : _c.find(x => x.name === name)) === null || _d === void 0 ? void 0 : _d.info; }).filter(skipEmpty),
495
+ ...types.map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.functions) === null || _c === void 0 ? void 0 : _c.find(x => x.name === name)) === null || _d === void 0 ? void 0 : _d.info; }).filter(skipEmpty),
477
496
  ].join('\n');
478
497
  }
479
498
  else {
480
499
  const name = view.state.sliceDoc(tree.from, tree.to);
481
500
  info = [
482
- ...[(_f = (_e = config.identifiers) === null || _e === undefined ? undefined : _e.find(x => x.name === name)) === null || _f === undefined ? undefined : _f.info].filter(skipEmpty),
483
- ...[(_h = (_g = config.functions) === null || _g === undefined ? undefined : _g.find(x => x.name === name)) === null || _h === undefined ? undefined : _h.info].filter(skipEmpty),
501
+ ...[(_f = (_e = config.identifiers) === null || _e === void 0 ? void 0 : _e.find(x => x.name === name)) === null || _f === void 0 ? void 0 : _f.info].filter(skipEmpty),
502
+ ...[(_h = (_g = config.functions) === null || _g === void 0 ? void 0 : _g.find(x => x.name === name)) === null || _h === void 0 ? void 0 : _h.info].filter(skipEmpty),
484
503
  ].join('\n');
485
504
  }
486
505
  if (!info) {
@@ -526,6 +545,9 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
526
545
  fontSize: ".8em",
527
546
  fontStyle: "monospace",
528
547
  backgroundColor: "rgba(127, 127, 127, .3)",
548
+ display: 'inline-block',
549
+ padding: '2px 4px',
550
+ borderRadius: '3px',
529
551
  },
530
552
  });
531
553
 
package/package.json CHANGED
@@ -27,7 +27,8 @@
27
27
  "devDependencies": {
28
28
  "@codemirror/buildhelper": "^1.0.0",
29
29
  "@types/mocha": "^10.0.10",
30
- "@types/node": "^22.10.5"
30
+ "@types/node": "^22.10.5",
31
+ "tsdoc-markdown": "^1.1.1"
31
32
  },
32
33
  "license": "MIT",
33
34
  "repository": {
@@ -38,5 +39,5 @@
38
39
  "access": "public",
39
40
  "registry": "https://registry.npmjs.org/"
40
41
  },
41
- "version": "0.9.0"
42
+ "version": "1.0.0"
42
43
  }