@valtzu/codemirror-lang-el 0.5.3 → 0.6.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.
@@ -22,7 +22,7 @@ jobs:
22
22
  uses: svenstaro/upload-release-action@v2
23
23
  with:
24
24
  repo_token: ${{ secrets.GITHUB_TOKEN }}
25
- file: dist/*
25
+ file: dist/index.*
26
26
  tag: ${{ github.ref_name }}
27
27
  overwrite: true
28
28
  file_glob: true
@@ -0,0 +1,16 @@
1
+ name: Run tests
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+ types: [opened, synchronize, reopened]
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v3
12
+ - uses: actions/setup-node@v3
13
+ with:
14
+ node-version: '20.x'
15
+ - run: npm install
16
+ - run: npm run test
package/README.md CHANGED
@@ -1,14 +1,50 @@
1
- ### Symfony Expression Language support for CodeMirror
1
+ ## Symfony Expression Language support for CodeMirror 6
2
2
 
3
- #### Features
3
+ > :warning: **This is unstable**: Expect breaking changes until v1 is out.
4
4
 
5
- 1. Autocompletion for variables, functions, operator keywords – with (some) type resolving
6
- 2. Hover tooltip
7
- 3. Linting
5
+ ### Features
8
6
 
9
- #### Example
7
+ #### Linting
10
8
 
11
- ![image](https://github.com/valtzu/codemirror-lang-el/assets/652734/c139cc50-077e-4f58-87e4-7ce404a445f4)
9
+ ![image](https://github.com/valtzu/codemirror-lang-el/assets/652734/dd221b7d-7cc6-494f-9823-dae8a55eca03)
10
+
11
+ #### Autocompletion
12
+
13
+ ![image](https://github.com/valtzu/codemirror-lang-el/assets/652734/a5a7bfdc-2869-4cbb-98f6-0abe361d55ba)
14
+
15
+ #### Hover tooltip
16
+
17
+ ![image](https://github.com/valtzu/codemirror-lang-el/assets/652734/3cfd7a49-4503-491c-972d-26d209ea26f3)
18
+
19
+ #### Function argument hints
20
+
21
+ ![image](https://github.com/valtzu/codemirror-lang-el/assets/652734/129eb510-a2aa-479e-b1de-dd0232b33299)
22
+
23
+ ---
24
+
25
+ ### Installation
26
+
27
+ #### Symfony AssetMapper
28
+
29
+ ```
30
+ bin/console importmap:require @valtzu/codemirror-lang-el
31
+ ```
32
+
33
+ #### npm
34
+
35
+ ```
36
+ npm install @valtzu/codemirror-lang-el
37
+ ```
38
+
39
+ #### Yarn
40
+
41
+ ```
42
+ yarn add @valtzu/codemirror-lang-el
43
+ ```
44
+
45
+ ---
46
+
47
+ ### Example
12
48
 
13
49
  [Live demo](https://jsfiddle.net/9xhezam4/)
14
50
 
@@ -84,3 +120,7 @@
84
120
  }
85
121
  </style>
86
122
  ```
123
+
124
+ ### Contributing
125
+
126
+ Contributions are accepted.
@@ -0,0 +1,177 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var autocomplete = require('@codemirror/autocomplete');
6
+ var language = require('@codemirror/language');
7
+
8
+ const createInfoElement = (html) => {
9
+ const dom = document.createElement("div");
10
+ dom.innerHTML = html;
11
+ dom.className = 'cm-diagnostic';
12
+ return dom;
13
+ };
14
+ 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
+ const resolveIdentifier = (nodeName, identifier, config) => {
16
+ var _a;
17
+ switch (nodeName) {
18
+ case 'Method':
19
+ case 'Function':
20
+ return resolveCallable(identifier, config);
21
+ case 'Property':
22
+ case 'Variable':
23
+ return (_a = config === null || config === void 0 ? void 0 : config.identifiers) === null || _a === void 0 ? void 0 : _a.find(x => x.name === identifier);
24
+ }
25
+ };
26
+ function resolveTypes(state, node, config, matchExact) {
27
+ var _a, _b, _c, _d, _e, _f, _g, _h;
28
+ let types = new Set();
29
+ if (!node) {
30
+ return types;
31
+ }
32
+ if (node.name === 'Call' && node.firstChild && node.lastChild) {
33
+ resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
34
+ }
35
+ else if (node.name === 'Variable') {
36
+ const varName = state.sliceDoc(node.from, node.to) || '';
37
+ // @ts-ignore
38
+ (_b = (_a = resolveIdentifier(node.name, varName, config)) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.forEach((x) => types.add(x));
39
+ }
40
+ else if (node.name === 'Function') {
41
+ const varName = state.sliceDoc(node.from, node.to) || '';
42
+ // @ts-ignore
43
+ (_d = (_c = resolveIdentifier(node.name, varName, config)) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
44
+ }
45
+ else if (node.name === 'ObjectAccess' && node.firstChild && ((_e = node.lastChild) === null || _e === void 0 ? void 0 : _e.name) === 'Property') {
46
+ const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
47
+ (_f = resolveTypes(state, node.firstChild, config)) === null || _f === void 0 ? void 0 : _f.forEach(baseType => {
48
+ var _a, _b, _c, _d;
49
+ // @ts-ignore
50
+ (_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.name, varName, (_b = config.types) === null || _b === void 0 ? void 0 : _b[baseType])) === null || _c === void 0 ? void 0 : _c.type) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
51
+ });
52
+ }
53
+ else if (node.name === 'ObjectAccess' && node.firstChild && ((_g = node.lastChild) === null || _g === void 0 ? void 0 : _g.name) === 'Method') {
54
+ const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
55
+ (_h = resolveTypes(state, node.firstChild, config)) === null || _h === void 0 ? void 0 : _h.forEach(baseType => {
56
+ var _a, _b, _c, _d;
57
+ // @ts-ignore
58
+ (_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.name, varName, (_b = config.types) === null || _b === void 0 ? void 0 : _b[baseType])) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
59
+ });
60
+ }
61
+ else if (node.name === 'Application' && node.firstChild) {
62
+ resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
63
+ }
64
+ if (types.size === 0) {
65
+ types.add('any');
66
+ }
67
+ return types;
68
+ }
69
+ function getExpressionLanguageConfig(state) {
70
+ return state.languageDataAt('expressionLanguageConfig', 0)[0];
71
+ }
72
+ const keywords = [
73
+ { name: 'starts with', info: 'Check if a string starts with a specific string' },
74
+ { name: 'ends with', info: 'Check if a string ends with a specific string' },
75
+ { name: 'contains', info: 'Check if a string is not included in another string' },
76
+ { name: 'matches', info: 'Check if a string matches a regex pattern' },
77
+ { name: 'not in', info: 'Check if a value is not included in an array' },
78
+ { name: 'in', info: 'Check if a value is included in an array' },
79
+ { name: 'not' },
80
+ { name: 'or' },
81
+ { name: 'and' },
82
+ ];
83
+
84
+ const autocompleteFunction = (x) => {
85
+ var _a, _b;
86
+ return ({
87
+ label: `${x.name}(${((_a = x.args) === null || _a === void 0 ? void 0 : _a.join(',')) || ''})`,
88
+ apply: (view, completion, from, to) => {
89
+ var _a;
90
+ 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) } }));
91
+ },
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 : ''); },
94
+ type: "function",
95
+ });
96
+ };
97
+ const autocompleteIdentifier = (x) => {
98
+ var _a;
99
+ return ({
100
+ label: x.name,
101
+ apply: x.name,
102
+ info: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
103
+ detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')),
104
+ type: 'variable',
105
+ });
106
+ };
107
+ function completeOperatorKeyword(state, config, tree, from, to, explicit) {
108
+ var _a;
109
+ return {
110
+ from,
111
+ to,
112
+ options: (_a = keywords.map(({ name, info, detail }) => ({ label: name, apply: `${name} `, info, detail, type: "keyword" }))) !== null && _a !== void 0 ? _a : [],
113
+ validFor: (text) => { var _a; return (_a = keywords.some(({ name }) => explicit || name.includes(text))) !== null && _a !== void 0 ? _a : false; },
114
+ };
115
+ }
116
+ function completeIdentifier(state, config, tree, from, to) {
117
+ var _a, _b;
118
+ const identifiers = (_a = config.identifiers) !== null && _a !== void 0 ? _a : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
119
+ const functions = (_b = config.functions) !== null && _b !== void 0 ? _b : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
120
+ return {
121
+ from,
122
+ to,
123
+ options: [...(identifiers.map(autocompleteIdentifier)), ...(functions.map(autocompleteFunction))],
124
+ validFor: /^[a-zA-Z_]+[a-zA-Z_0-9]*$/,
125
+ };
126
+ }
127
+ function completeMember(state, config, tree, from, to, explicit) {
128
+ var _a, _b, _c, _d;
129
+ if (((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.name) != 'ObjectAccess' || !tree.parent.firstChild) {
130
+ return null;
131
+ }
132
+ const types = resolveTypes(state, tree.parent.firstChild.node, config);
133
+ if (!(types === null || types === void 0 ? void 0 : types.size)) {
134
+ return null;
135
+ }
136
+ let options = [];
137
+ for (const type of types) {
138
+ const typeDeclaration = (_b = config.types) === null || _b === void 0 ? void 0 : _b[type];
139
+ options.push(...(((_c = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.identifiers) === null || _c === void 0 ? void 0 : _c.map(autocompleteIdentifier)) || []), ...(((_d = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.functions) === null || _d === void 0 ? void 0 : _d.map(autocompleteFunction)) || []));
140
+ }
141
+ return {
142
+ from,
143
+ to,
144
+ options,
145
+ validFor: /^[a-zA-Z_]+[a-zA-Z_0-9]*$/,
146
+ };
147
+ }
148
+ function expressionLanguageCompletion(context) {
149
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
150
+ const { state, pos, explicit } = context;
151
+ const tree = language.syntaxTree(state);
152
+ const lastChar = state.sliceDoc(pos - 1, pos);
153
+ const prevNode = tree.resolveInner(pos, lastChar === ')' ? 0 : -1);
154
+ const config = getExpressionLanguageConfig(state);
155
+ 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
+ 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') {
158
+ return null;
159
+ }
160
+ if (((_a = prevNode.parent) === null || _a === void 0 ? void 0 : _a.name) == 'ObjectAccess' && ['ObjectAccess', 'ArrayAccess', 'Variable', 'Call'].includes(((_b = prevNode.parent.firstChild) === null || _b === void 0 ? void 0 : _b.name) || '')) {
161
+ return completeMember(state, config, prevNode, isIdentifier(prevNode) || isMember(prevNode) ? prevNode.from : pos, pos);
162
+ }
163
+ if (['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes(prevNode.name) && prevNode.lastChild && !((_c = prevNode.lastChild) === null || _c === void 0 ? void 0 : _c.type.isError)
164
+ || ['Arguments', 'Array'].includes(prevNode.name) && prevNode.lastChild && !((_d = prevNode.lastChild) === null || _d === void 0 ? void 0 : _d.type.isError)
165
+ || ['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes((_f = (_e = prevNode.parent) === null || _e === void 0 ? void 0 : _e.name) !== null && _f !== void 0 ? _f : '') && prevNode.type.isError
166
+ || ['Variable', 'Function'].includes((_h = (_g = prevNode.parent) === null || _g === void 0 ? void 0 : _g.name) !== null && _h !== void 0 ? _h : '') && prevNode.type.isError) {
167
+ return completeOperatorKeyword(state, config, prevNode, !['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression', 'Arguments'].includes(prevNode.name) ? prevNode.from : pos, pos, explicit);
168
+ }
169
+ if (!/[0-9]/.test(lastChar) && !['OperatorKeyword'].includes((_j = prevNode.name) !== null && _j !== void 0 ? _j : '') && (['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes(prevNode.name) && ((_k = prevNode.lastChild) === null || _k === void 0 ? void 0 : _k.type.isError)
170
+ || ['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression', 'Arguments'].includes((_m = (_l = prevNode.parent) === null || _l === void 0 ? void 0 : _l.name) !== null && _m !== void 0 ? _m : '') && !prevNode.type.isError
171
+ || ['Arguments', 'Array'].includes((_o = prevNode.name) !== null && _o !== void 0 ? _o : ''))) {
172
+ return completeIdentifier(state, config, prevNode, isIdentifier(prevNode) ? prevNode.from : pos, pos);
173
+ }
174
+ return null;
175
+ }
176
+
177
+ exports.expressionLanguageCompletion = expressionLanguageCompletion;
@@ -0,0 +1,3 @@
1
+ import { CompletionContext, CompletionResult } from "@codemirror/autocomplete";
2
+ declare function expressionLanguageCompletion(context: CompletionContext): CompletionResult | null;
3
+ export { expressionLanguageCompletion };
@@ -0,0 +1,3 @@
1
+ import { CompletionContext, CompletionResult } from "@codemirror/autocomplete";
2
+ declare function expressionLanguageCompletion(context: CompletionContext): CompletionResult | null;
3
+ export { expressionLanguageCompletion };
@@ -0,0 +1,173 @@
1
+ import { insertCompletionText } from '@codemirror/autocomplete';
2
+ import { syntaxTree } from '@codemirror/language';
3
+
4
+ const createInfoElement = (html) => {
5
+ const dom = document.createElement("div");
6
+ dom.innerHTML = html;
7
+ dom.className = 'cm-diagnostic';
8
+ return dom;
9
+ };
10
+ 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
+ const resolveIdentifier = (nodeName, identifier, config) => {
12
+ var _a;
13
+ switch (nodeName) {
14
+ case 'Method':
15
+ case 'Function':
16
+ return resolveCallable(identifier, config);
17
+ case 'Property':
18
+ case 'Variable':
19
+ return (_a = config === null || config === void 0 ? void 0 : config.identifiers) === null || _a === void 0 ? void 0 : _a.find(x => x.name === identifier);
20
+ }
21
+ };
22
+ function resolveTypes(state, node, config, matchExact) {
23
+ var _a, _b, _c, _d, _e, _f, _g, _h;
24
+ let types = new Set();
25
+ if (!node) {
26
+ return types;
27
+ }
28
+ if (node.name === 'Call' && node.firstChild && node.lastChild) {
29
+ resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
30
+ }
31
+ else if (node.name === 'Variable') {
32
+ const varName = state.sliceDoc(node.from, node.to) || '';
33
+ // @ts-ignore
34
+ (_b = (_a = resolveIdentifier(node.name, varName, config)) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.forEach((x) => types.add(x));
35
+ }
36
+ else if (node.name === 'Function') {
37
+ const varName = state.sliceDoc(node.from, node.to) || '';
38
+ // @ts-ignore
39
+ (_d = (_c = resolveIdentifier(node.name, varName, config)) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
40
+ }
41
+ else if (node.name === 'ObjectAccess' && node.firstChild && ((_e = node.lastChild) === null || _e === void 0 ? void 0 : _e.name) === 'Property') {
42
+ const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
43
+ (_f = resolveTypes(state, node.firstChild, config)) === null || _f === void 0 ? void 0 : _f.forEach(baseType => {
44
+ var _a, _b, _c, _d;
45
+ // @ts-ignore
46
+ (_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.name, varName, (_b = config.types) === null || _b === void 0 ? void 0 : _b[baseType])) === null || _c === void 0 ? void 0 : _c.type) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
47
+ });
48
+ }
49
+ else if (node.name === 'ObjectAccess' && node.firstChild && ((_g = node.lastChild) === null || _g === void 0 ? void 0 : _g.name) === 'Method') {
50
+ const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
51
+ (_h = resolveTypes(state, node.firstChild, config)) === null || _h === void 0 ? void 0 : _h.forEach(baseType => {
52
+ var _a, _b, _c, _d;
53
+ // @ts-ignore
54
+ (_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.name, varName, (_b = config.types) === null || _b === void 0 ? void 0 : _b[baseType])) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
55
+ });
56
+ }
57
+ else if (node.name === 'Application' && node.firstChild) {
58
+ resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
59
+ }
60
+ if (types.size === 0) {
61
+ types.add('any');
62
+ }
63
+ return types;
64
+ }
65
+ function getExpressionLanguageConfig(state) {
66
+ return state.languageDataAt('expressionLanguageConfig', 0)[0];
67
+ }
68
+ const keywords = [
69
+ { name: 'starts with', info: 'Check if a string starts with a specific string' },
70
+ { name: 'ends with', info: 'Check if a string ends with a specific string' },
71
+ { name: 'contains', info: 'Check if a string is not included in another string' },
72
+ { name: 'matches', info: 'Check if a string matches a regex pattern' },
73
+ { name: 'not in', info: 'Check if a value is not included in an array' },
74
+ { name: 'in', info: 'Check if a value is included in an array' },
75
+ { name: 'not' },
76
+ { name: 'or' },
77
+ { name: 'and' },
78
+ ];
79
+
80
+ const autocompleteFunction = (x) => {
81
+ var _a, _b;
82
+ return ({
83
+ label: `${x.name}(${((_a = x.args) === null || _a === void 0 ? void 0 : _a.join(',')) || ''})`,
84
+ apply: (view, completion, from, to) => {
85
+ var _a;
86
+ 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) } }));
87
+ },
88
+ detail: (_b = x.returnType) === null || _b === void 0 ? void 0 : _b.join('|'),
89
+ info: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
90
+ type: "function",
91
+ });
92
+ };
93
+ const autocompleteIdentifier = (x) => {
94
+ var _a;
95
+ return ({
96
+ label: x.name,
97
+ apply: x.name,
98
+ info: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
99
+ detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')),
100
+ type: 'variable',
101
+ });
102
+ };
103
+ function completeOperatorKeyword(state, config, tree, from, to, explicit) {
104
+ var _a;
105
+ return {
106
+ from,
107
+ to,
108
+ options: (_a = keywords.map(({ name, info, detail }) => ({ label: name, apply: `${name} `, info, detail, type: "keyword" }))) !== null && _a !== void 0 ? _a : [],
109
+ validFor: (text) => { var _a; return (_a = keywords.some(({ name }) => explicit || name.includes(text))) !== null && _a !== void 0 ? _a : false; },
110
+ };
111
+ }
112
+ function completeIdentifier(state, config, tree, from, to) {
113
+ var _a, _b;
114
+ const identifiers = (_a = config.identifiers) !== null && _a !== void 0 ? _a : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
115
+ const functions = (_b = config.functions) !== null && _b !== void 0 ? _b : []; //?.filter(({ name }) => explicit || name.toLowerCase().startsWith(text)) ?? [];
116
+ return {
117
+ from,
118
+ to,
119
+ options: [...(identifiers.map(autocompleteIdentifier)), ...(functions.map(autocompleteFunction))],
120
+ validFor: /^[a-zA-Z_]+[a-zA-Z_0-9]*$/,
121
+ };
122
+ }
123
+ function completeMember(state, config, tree, from, to, explicit) {
124
+ var _a, _b, _c, _d;
125
+ if (((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.name) != 'ObjectAccess' || !tree.parent.firstChild) {
126
+ return null;
127
+ }
128
+ const types = resolveTypes(state, tree.parent.firstChild.node, config);
129
+ if (!(types === null || types === void 0 ? void 0 : types.size)) {
130
+ return null;
131
+ }
132
+ let options = [];
133
+ for (const type of types) {
134
+ const typeDeclaration = (_b = config.types) === null || _b === void 0 ? void 0 : _b[type];
135
+ options.push(...(((_c = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.identifiers) === null || _c === void 0 ? void 0 : _c.map(autocompleteIdentifier)) || []), ...(((_d = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.functions) === null || _d === void 0 ? void 0 : _d.map(autocompleteFunction)) || []));
136
+ }
137
+ return {
138
+ from,
139
+ to,
140
+ options,
141
+ validFor: /^[a-zA-Z_]+[a-zA-Z_0-9]*$/,
142
+ };
143
+ }
144
+ function expressionLanguageCompletion(context) {
145
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
146
+ const { state, pos, explicit } = context;
147
+ const tree = syntaxTree(state);
148
+ const lastChar = state.sliceDoc(pos - 1, pos);
149
+ const prevNode = tree.resolveInner(pos, lastChar === ')' ? 0 : -1);
150
+ const config = getExpressionLanguageConfig(state);
151
+ const isIdentifier = (node) => { var _a; return ['Variable', 'Function'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
152
+ const isMember = (node) => { var _a; return ['Property', 'Method'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
153
+ if (prevNode.name == 'String') {
154
+ return null;
155
+ }
156
+ if (((_a = prevNode.parent) === null || _a === void 0 ? void 0 : _a.name) == 'ObjectAccess' && ['ObjectAccess', 'ArrayAccess', 'Variable', 'Call'].includes(((_b = prevNode.parent.firstChild) === null || _b === void 0 ? void 0 : _b.name) || '')) {
157
+ return completeMember(state, config, prevNode, isIdentifier(prevNode) || isMember(prevNode) ? prevNode.from : pos, pos);
158
+ }
159
+ if (['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes(prevNode.name) && prevNode.lastChild && !((_c = prevNode.lastChild) === null || _c === void 0 ? void 0 : _c.type.isError)
160
+ || ['Arguments', 'Array'].includes(prevNode.name) && prevNode.lastChild && !((_d = prevNode.lastChild) === null || _d === void 0 ? void 0 : _d.type.isError)
161
+ || ['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes((_f = (_e = prevNode.parent) === null || _e === void 0 ? void 0 : _e.name) !== null && _f !== void 0 ? _f : '') && prevNode.type.isError
162
+ || ['Variable', 'Function'].includes((_h = (_g = prevNode.parent) === null || _g === void 0 ? void 0 : _g.name) !== null && _h !== void 0 ? _h : '') && prevNode.type.isError) {
163
+ return completeOperatorKeyword(state, config, prevNode, !['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression', 'Arguments'].includes(prevNode.name) ? prevNode.from : pos, pos, explicit);
164
+ }
165
+ if (!/[0-9]/.test(lastChar) && !['OperatorKeyword'].includes((_j = prevNode.name) !== null && _j !== void 0 ? _j : '') && (['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes(prevNode.name) && ((_k = prevNode.lastChild) === null || _k === void 0 ? void 0 : _k.type.isError)
166
+ || ['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression', 'Arguments'].includes((_m = (_l = prevNode.parent) === null || _l === void 0 ? void 0 : _l.name) !== null && _m !== void 0 ? _m : '') && !prevNode.type.isError
167
+ || ['Arguments', 'Array'].includes((_o = prevNode.name) !== null && _o !== void 0 ? _o : ''))) {
168
+ return completeIdentifier(state, config, prevNode, isIdentifier(prevNode) ? prevNode.from : pos, pos);
169
+ }
170
+ return null;
171
+ }
172
+
173
+ export { expressionLanguageCompletion };