@player-tools/typescript-expression-plugin 0.2.2--canary.20.519 → 0.4.0-next.2
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/dist/index.cjs.js +67 -51
- package/dist/index.esm.js +68 -52
- package/package.json +5 -5
- package/src/service.ts +63 -89
- package/src/transforms.ts +44 -0
package/dist/index.cjs.js
CHANGED
|
@@ -91,6 +91,47 @@ function convertExprToJSONNode(exprNode) {
|
|
|
91
91
|
return jsoncParser.parseTree(JSON.stringify(val));
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
var __defProp$1 = Object.defineProperty;
|
|
95
|
+
var __defProps$1 = Object.defineProperties;
|
|
96
|
+
var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors;
|
|
97
|
+
var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
|
|
98
|
+
var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
|
|
99
|
+
var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
|
|
100
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
101
|
+
var __spreadValues$1 = (a, b) => {
|
|
102
|
+
for (var prop in b || (b = {}))
|
|
103
|
+
if (__hasOwnProp$1.call(b, prop))
|
|
104
|
+
__defNormalProp$1(a, prop, b[prop]);
|
|
105
|
+
if (__getOwnPropSymbols$1)
|
|
106
|
+
for (var prop of __getOwnPropSymbols$1(b)) {
|
|
107
|
+
if (__propIsEnum$1.call(b, prop))
|
|
108
|
+
__defNormalProp$1(a, prop, b[prop]);
|
|
109
|
+
}
|
|
110
|
+
return a;
|
|
111
|
+
};
|
|
112
|
+
var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
|
|
113
|
+
const toFunction = xlrSdk.simpleTransformGenerator("ref", "Expressions", (exp) => {
|
|
114
|
+
if (!exp.genericArguments || exp.ref !== "ExpressionHandler") {
|
|
115
|
+
return exp;
|
|
116
|
+
}
|
|
117
|
+
const [args, returnType] = exp.genericArguments;
|
|
118
|
+
const parameters = (args.type === "tuple" ? args.elementTypes : []).map((elementType, index) => {
|
|
119
|
+
var _a, _b, _c, _d, _e, _f;
|
|
120
|
+
return {
|
|
121
|
+
name: (_c = (_b = (_a = elementType.name) != null ? _a : elementType.type.name) != null ? _b : elementType.type.title) != null ? _c : `arg_${index}`,
|
|
122
|
+
type: __spreadValues$1({
|
|
123
|
+
name: (_f = (_e = (_d = elementType.name) != null ? _d : elementType.type.name) != null ? _e : elementType.type.title) != null ? _f : `arg_${index}`
|
|
124
|
+
}, elementType.type),
|
|
125
|
+
optional: elementType.optional === true ? elementType.optional : void 0
|
|
126
|
+
};
|
|
127
|
+
});
|
|
128
|
+
return __spreadProps$1(__spreadValues$1({}, exp), {
|
|
129
|
+
type: "function",
|
|
130
|
+
parameters,
|
|
131
|
+
returnType
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
94
135
|
var __defProp = Object.defineProperty;
|
|
95
136
|
var __defProps = Object.defineProperties;
|
|
96
137
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
@@ -110,66 +151,41 @@ var __spreadValues = (a, b) => {
|
|
|
110
151
|
return a;
|
|
111
152
|
};
|
|
112
153
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
113
|
-
function reduceExpression(plugins) {
|
|
114
|
-
const expressions = new Map();
|
|
115
|
-
plugins.forEach((plugin) => {
|
|
116
|
-
var _a;
|
|
117
|
-
const { capabilities } = plugin;
|
|
118
|
-
const registeredExpressions = (_a = capabilities == null ? void 0 : capabilities.Expressions) != null ? _a : [];
|
|
119
|
-
registeredExpressions.forEach((exp) => {
|
|
120
|
-
var _a2;
|
|
121
|
-
if (exp.type !== "ref" || !exp.genericArguments) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
const expName = exp.name;
|
|
125
|
-
const [args, returnType] = exp.genericArguments;
|
|
126
|
-
const parameters = (args.type === "tuple" ? args.elementTypes : []).map((elementType, index) => {
|
|
127
|
-
var _a3, _b, _c, _d, _e, _f;
|
|
128
|
-
return {
|
|
129
|
-
name: (_c = (_b = (_a3 = elementType.name) != null ? _a3 : elementType.type.name) != null ? _b : elementType.type.title) != null ? _c : `arg_${index}`,
|
|
130
|
-
type: __spreadValues({
|
|
131
|
-
name: (_f = (_e = (_d = elementType.name) != null ? _d : elementType.type.name) != null ? _e : elementType.type.title) != null ? _f : `arg_${index}`
|
|
132
|
-
}, elementType.type),
|
|
133
|
-
optional: elementType.optional === true ? elementType.optional : void 0
|
|
134
|
-
};
|
|
135
|
-
});
|
|
136
|
-
const entry = {
|
|
137
|
-
name: expName,
|
|
138
|
-
description: (_a2 = exp.description) != null ? _a2 : "",
|
|
139
|
-
source: plugin,
|
|
140
|
-
type: __spreadProps(__spreadValues({}, exp), {
|
|
141
|
-
type: "function",
|
|
142
|
-
parameters,
|
|
143
|
-
returnType
|
|
144
|
-
})
|
|
145
|
-
};
|
|
146
|
-
expressions.set(expName, entry);
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
const expList = {
|
|
150
|
-
entries: expressions
|
|
151
|
-
};
|
|
152
|
-
return expList;
|
|
153
|
-
}
|
|
154
154
|
class ExpressionLanguageService {
|
|
155
155
|
constructor(options) {
|
|
156
156
|
this._plugins = [];
|
|
157
157
|
var _a;
|
|
158
158
|
this.logger = options == null ? void 0 : options.logger;
|
|
159
159
|
this._plugins = (_a = options == null ? void 0 : options.plugins) != null ? _a : [];
|
|
160
|
-
this._expressions = reduceExpression(this._plugins);
|
|
161
160
|
this.xlr = new xlrSdk.XLRSDK();
|
|
162
161
|
this._plugins.forEach((p) => {
|
|
163
|
-
this.xlr.loadDefinitionsFromModule(p);
|
|
162
|
+
this.xlr.loadDefinitionsFromModule(p, void 0, [toFunction]);
|
|
164
163
|
});
|
|
164
|
+
this._expressions = this.reduceExpression();
|
|
165
165
|
}
|
|
166
166
|
setConfig(config) {
|
|
167
167
|
this._plugins = config.plugins;
|
|
168
|
-
this._expressions = reduceExpression(this._plugins);
|
|
169
168
|
this.xlr = new xlrSdk.XLRSDK();
|
|
170
169
|
this._plugins.forEach((p) => {
|
|
171
|
-
this.xlr.loadDefinitionsFromModule(p);
|
|
170
|
+
this.xlr.loadDefinitionsFromModule(p, void 0, [toFunction]);
|
|
171
|
+
});
|
|
172
|
+
this._expressions = this.reduceExpression();
|
|
173
|
+
}
|
|
174
|
+
reduceExpression() {
|
|
175
|
+
const expressions = new Map();
|
|
176
|
+
this.xlr.listTypes().forEach((type) => {
|
|
177
|
+
const typeInfo = this.xlr.getTypeInfo(type.name);
|
|
178
|
+
const source = this._plugins.find((value) => value.pluginName === (typeInfo == null ? void 0 : typeInfo.plugin));
|
|
179
|
+
if (type.type === "function" && (typeInfo == null ? void 0 : typeInfo.capability) === "Expressions" && source) {
|
|
180
|
+
expressions.set(type.name, {
|
|
181
|
+
name: type.name,
|
|
182
|
+
description: type.description,
|
|
183
|
+
type,
|
|
184
|
+
source
|
|
185
|
+
});
|
|
186
|
+
}
|
|
172
187
|
});
|
|
188
|
+
return expressions;
|
|
173
189
|
}
|
|
174
190
|
getCompletionsAtPosition(context, position) {
|
|
175
191
|
var _a, _b;
|
|
@@ -180,7 +196,7 @@ class ExpressionLanguageService {
|
|
|
180
196
|
entries: []
|
|
181
197
|
};
|
|
182
198
|
if (context.text.length === 0) {
|
|
183
|
-
this._expressions.
|
|
199
|
+
this._expressions.forEach((exp) => {
|
|
184
200
|
completionInfo.entries.push({
|
|
185
201
|
name: exp.name,
|
|
186
202
|
kind: ts__namespace.ScriptElementKind.functionElement,
|
|
@@ -195,7 +211,7 @@ class ExpressionLanguageService {
|
|
|
195
211
|
const parsed = player.parseExpression(line, { strict: false });
|
|
196
212
|
const token = getTokenAtPosition(parsed, position);
|
|
197
213
|
if ((token == null ? void 0 : token.type) === "Compound" && token.error) {
|
|
198
|
-
this._expressions.
|
|
214
|
+
this._expressions.forEach((exp) => {
|
|
199
215
|
completionInfo.entries.push({
|
|
200
216
|
name: exp.name,
|
|
201
217
|
kind: ts__namespace.ScriptElementKind.functionElement,
|
|
@@ -209,7 +225,7 @@ class ExpressionLanguageService {
|
|
|
209
225
|
if ((token == null ? void 0 : token.type) === "Identifier") {
|
|
210
226
|
const start = (_b = (_a = token.location) == null ? void 0 : _a.start) != null ? _b : { character: 0 };
|
|
211
227
|
const wordFromStart = line.slice(start.character, position.character);
|
|
212
|
-
const allCompletions = Array.from(this._expressions.
|
|
228
|
+
const allCompletions = Array.from(this._expressions.keys()).filter((key) => key.startsWith(wordFromStart));
|
|
213
229
|
allCompletions.forEach((c) => {
|
|
214
230
|
completionInfo.entries.push({
|
|
215
231
|
name: c,
|
|
@@ -224,7 +240,7 @@ class ExpressionLanguageService {
|
|
|
224
240
|
}
|
|
225
241
|
getCompletionEntryDetails(context, position, name) {
|
|
226
242
|
var _a;
|
|
227
|
-
const expression = this._expressions.
|
|
243
|
+
const expression = this._expressions.get(name);
|
|
228
244
|
const completionDetails = {
|
|
229
245
|
name,
|
|
230
246
|
kind: ts__namespace.ScriptElementKind.functionElement,
|
|
@@ -243,7 +259,7 @@ class ExpressionLanguageService {
|
|
|
243
259
|
const parsed = player.parseExpression(context.text, { strict: false });
|
|
244
260
|
const token = getTokenAtPosition(parsed, position);
|
|
245
261
|
if ((token == null ? void 0 : token.type) === "Identifier") {
|
|
246
|
-
const expression = this._expressions.
|
|
262
|
+
const expression = this._expressions.get(token.name);
|
|
247
263
|
if (expression) {
|
|
248
264
|
const completionDetails = this.getCompletionEntryDetails(context, position, expression.name);
|
|
249
265
|
return __spreadProps(__spreadValues({}, completionDetails), {
|
|
@@ -279,7 +295,7 @@ class ExpressionLanguageService {
|
|
|
279
295
|
}
|
|
280
296
|
if (node.type === "CallExpression") {
|
|
281
297
|
const exprName = node.callTarget.name;
|
|
282
|
-
const expression = this._expressions.
|
|
298
|
+
const expression = this._expressions.get(exprName);
|
|
283
299
|
node.args.forEach((n) => {
|
|
284
300
|
diags.push(...this.getDiagnosticsForNode(context, n));
|
|
285
301
|
});
|
package/dist/index.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { decorateWithTemplateLanguageService } from 'typescript-template-language-service-decorator';
|
|
2
2
|
import * as ts from 'typescript/lib/tsserverlibrary';
|
|
3
3
|
import { createTSDocString } from '@player-tools/xlr-utils';
|
|
4
|
-
import { XLRSDK } from '@player-tools/xlr-sdk';
|
|
4
|
+
import { simpleTransformGenerator, XLRSDK } from '@player-tools/xlr-sdk';
|
|
5
5
|
import { parseExpression } from '@player-ui/player';
|
|
6
6
|
import { parseTree } from 'jsonc-parser';
|
|
7
7
|
|
|
@@ -69,6 +69,47 @@ function convertExprToJSONNode(exprNode) {
|
|
|
69
69
|
return parseTree(JSON.stringify(val));
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
var __defProp$1 = Object.defineProperty;
|
|
73
|
+
var __defProps$1 = Object.defineProperties;
|
|
74
|
+
var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors;
|
|
75
|
+
var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
|
|
76
|
+
var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
|
|
77
|
+
var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
|
|
78
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
79
|
+
var __spreadValues$1 = (a, b) => {
|
|
80
|
+
for (var prop in b || (b = {}))
|
|
81
|
+
if (__hasOwnProp$1.call(b, prop))
|
|
82
|
+
__defNormalProp$1(a, prop, b[prop]);
|
|
83
|
+
if (__getOwnPropSymbols$1)
|
|
84
|
+
for (var prop of __getOwnPropSymbols$1(b)) {
|
|
85
|
+
if (__propIsEnum$1.call(b, prop))
|
|
86
|
+
__defNormalProp$1(a, prop, b[prop]);
|
|
87
|
+
}
|
|
88
|
+
return a;
|
|
89
|
+
};
|
|
90
|
+
var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
|
|
91
|
+
const toFunction = simpleTransformGenerator("ref", "Expressions", (exp) => {
|
|
92
|
+
if (!exp.genericArguments || exp.ref !== "ExpressionHandler") {
|
|
93
|
+
return exp;
|
|
94
|
+
}
|
|
95
|
+
const [args, returnType] = exp.genericArguments;
|
|
96
|
+
const parameters = (args.type === "tuple" ? args.elementTypes : []).map((elementType, index) => {
|
|
97
|
+
var _a, _b, _c, _d, _e, _f;
|
|
98
|
+
return {
|
|
99
|
+
name: (_c = (_b = (_a = elementType.name) != null ? _a : elementType.type.name) != null ? _b : elementType.type.title) != null ? _c : `arg_${index}`,
|
|
100
|
+
type: __spreadValues$1({
|
|
101
|
+
name: (_f = (_e = (_d = elementType.name) != null ? _d : elementType.type.name) != null ? _e : elementType.type.title) != null ? _f : `arg_${index}`
|
|
102
|
+
}, elementType.type),
|
|
103
|
+
optional: elementType.optional === true ? elementType.optional : void 0
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
return __spreadProps$1(__spreadValues$1({}, exp), {
|
|
107
|
+
type: "function",
|
|
108
|
+
parameters,
|
|
109
|
+
returnType
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
72
113
|
var __defProp = Object.defineProperty;
|
|
73
114
|
var __defProps = Object.defineProperties;
|
|
74
115
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
@@ -88,66 +129,41 @@ var __spreadValues = (a, b) => {
|
|
|
88
129
|
return a;
|
|
89
130
|
};
|
|
90
131
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
91
|
-
function reduceExpression(plugins) {
|
|
92
|
-
const expressions = new Map();
|
|
93
|
-
plugins.forEach((plugin) => {
|
|
94
|
-
var _a;
|
|
95
|
-
const { capabilities } = plugin;
|
|
96
|
-
const registeredExpressions = (_a = capabilities == null ? void 0 : capabilities.Expressions) != null ? _a : [];
|
|
97
|
-
registeredExpressions.forEach((exp) => {
|
|
98
|
-
var _a2;
|
|
99
|
-
if (exp.type !== "ref" || !exp.genericArguments) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
const expName = exp.name;
|
|
103
|
-
const [args, returnType] = exp.genericArguments;
|
|
104
|
-
const parameters = (args.type === "tuple" ? args.elementTypes : []).map((elementType, index) => {
|
|
105
|
-
var _a3, _b, _c, _d, _e, _f;
|
|
106
|
-
return {
|
|
107
|
-
name: (_c = (_b = (_a3 = elementType.name) != null ? _a3 : elementType.type.name) != null ? _b : elementType.type.title) != null ? _c : `arg_${index}`,
|
|
108
|
-
type: __spreadValues({
|
|
109
|
-
name: (_f = (_e = (_d = elementType.name) != null ? _d : elementType.type.name) != null ? _e : elementType.type.title) != null ? _f : `arg_${index}`
|
|
110
|
-
}, elementType.type),
|
|
111
|
-
optional: elementType.optional === true ? elementType.optional : void 0
|
|
112
|
-
};
|
|
113
|
-
});
|
|
114
|
-
const entry = {
|
|
115
|
-
name: expName,
|
|
116
|
-
description: (_a2 = exp.description) != null ? _a2 : "",
|
|
117
|
-
source: plugin,
|
|
118
|
-
type: __spreadProps(__spreadValues({}, exp), {
|
|
119
|
-
type: "function",
|
|
120
|
-
parameters,
|
|
121
|
-
returnType
|
|
122
|
-
})
|
|
123
|
-
};
|
|
124
|
-
expressions.set(expName, entry);
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
const expList = {
|
|
128
|
-
entries: expressions
|
|
129
|
-
};
|
|
130
|
-
return expList;
|
|
131
|
-
}
|
|
132
132
|
class ExpressionLanguageService {
|
|
133
133
|
constructor(options) {
|
|
134
134
|
this._plugins = [];
|
|
135
135
|
var _a;
|
|
136
136
|
this.logger = options == null ? void 0 : options.logger;
|
|
137
137
|
this._plugins = (_a = options == null ? void 0 : options.plugins) != null ? _a : [];
|
|
138
|
-
this._expressions = reduceExpression(this._plugins);
|
|
139
138
|
this.xlr = new XLRSDK();
|
|
140
139
|
this._plugins.forEach((p) => {
|
|
141
|
-
this.xlr.loadDefinitionsFromModule(p);
|
|
140
|
+
this.xlr.loadDefinitionsFromModule(p, void 0, [toFunction]);
|
|
142
141
|
});
|
|
142
|
+
this._expressions = this.reduceExpression();
|
|
143
143
|
}
|
|
144
144
|
setConfig(config) {
|
|
145
145
|
this._plugins = config.plugins;
|
|
146
|
-
this._expressions = reduceExpression(this._plugins);
|
|
147
146
|
this.xlr = new XLRSDK();
|
|
148
147
|
this._plugins.forEach((p) => {
|
|
149
|
-
this.xlr.loadDefinitionsFromModule(p);
|
|
148
|
+
this.xlr.loadDefinitionsFromModule(p, void 0, [toFunction]);
|
|
149
|
+
});
|
|
150
|
+
this._expressions = this.reduceExpression();
|
|
151
|
+
}
|
|
152
|
+
reduceExpression() {
|
|
153
|
+
const expressions = new Map();
|
|
154
|
+
this.xlr.listTypes().forEach((type) => {
|
|
155
|
+
const typeInfo = this.xlr.getTypeInfo(type.name);
|
|
156
|
+
const source = this._plugins.find((value) => value.pluginName === (typeInfo == null ? void 0 : typeInfo.plugin));
|
|
157
|
+
if (type.type === "function" && (typeInfo == null ? void 0 : typeInfo.capability) === "Expressions" && source) {
|
|
158
|
+
expressions.set(type.name, {
|
|
159
|
+
name: type.name,
|
|
160
|
+
description: type.description,
|
|
161
|
+
type,
|
|
162
|
+
source
|
|
163
|
+
});
|
|
164
|
+
}
|
|
150
165
|
});
|
|
166
|
+
return expressions;
|
|
151
167
|
}
|
|
152
168
|
getCompletionsAtPosition(context, position) {
|
|
153
169
|
var _a, _b;
|
|
@@ -158,7 +174,7 @@ class ExpressionLanguageService {
|
|
|
158
174
|
entries: []
|
|
159
175
|
};
|
|
160
176
|
if (context.text.length === 0) {
|
|
161
|
-
this._expressions.
|
|
177
|
+
this._expressions.forEach((exp) => {
|
|
162
178
|
completionInfo.entries.push({
|
|
163
179
|
name: exp.name,
|
|
164
180
|
kind: ts.ScriptElementKind.functionElement,
|
|
@@ -173,7 +189,7 @@ class ExpressionLanguageService {
|
|
|
173
189
|
const parsed = parseExpression(line, { strict: false });
|
|
174
190
|
const token = getTokenAtPosition(parsed, position);
|
|
175
191
|
if ((token == null ? void 0 : token.type) === "Compound" && token.error) {
|
|
176
|
-
this._expressions.
|
|
192
|
+
this._expressions.forEach((exp) => {
|
|
177
193
|
completionInfo.entries.push({
|
|
178
194
|
name: exp.name,
|
|
179
195
|
kind: ts.ScriptElementKind.functionElement,
|
|
@@ -187,7 +203,7 @@ class ExpressionLanguageService {
|
|
|
187
203
|
if ((token == null ? void 0 : token.type) === "Identifier") {
|
|
188
204
|
const start = (_b = (_a = token.location) == null ? void 0 : _a.start) != null ? _b : { character: 0 };
|
|
189
205
|
const wordFromStart = line.slice(start.character, position.character);
|
|
190
|
-
const allCompletions = Array.from(this._expressions.
|
|
206
|
+
const allCompletions = Array.from(this._expressions.keys()).filter((key) => key.startsWith(wordFromStart));
|
|
191
207
|
allCompletions.forEach((c) => {
|
|
192
208
|
completionInfo.entries.push({
|
|
193
209
|
name: c,
|
|
@@ -202,7 +218,7 @@ class ExpressionLanguageService {
|
|
|
202
218
|
}
|
|
203
219
|
getCompletionEntryDetails(context, position, name) {
|
|
204
220
|
var _a;
|
|
205
|
-
const expression = this._expressions.
|
|
221
|
+
const expression = this._expressions.get(name);
|
|
206
222
|
const completionDetails = {
|
|
207
223
|
name,
|
|
208
224
|
kind: ts.ScriptElementKind.functionElement,
|
|
@@ -221,7 +237,7 @@ class ExpressionLanguageService {
|
|
|
221
237
|
const parsed = parseExpression(context.text, { strict: false });
|
|
222
238
|
const token = getTokenAtPosition(parsed, position);
|
|
223
239
|
if ((token == null ? void 0 : token.type) === "Identifier") {
|
|
224
|
-
const expression = this._expressions.
|
|
240
|
+
const expression = this._expressions.get(token.name);
|
|
225
241
|
if (expression) {
|
|
226
242
|
const completionDetails = this.getCompletionEntryDetails(context, position, expression.name);
|
|
227
243
|
return __spreadProps(__spreadValues({}, completionDetails), {
|
|
@@ -257,7 +273,7 @@ class ExpressionLanguageService {
|
|
|
257
273
|
}
|
|
258
274
|
if (node.type === "CallExpression") {
|
|
259
275
|
const exprName = node.callTarget.name;
|
|
260
|
-
const expression = this._expressions.
|
|
276
|
+
const expression = this._expressions.get(exprName);
|
|
261
277
|
node.args.forEach((n) => {
|
|
262
278
|
diags.push(...this.getDiagnosticsForNode(context, n));
|
|
263
279
|
});
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@player-tools/typescript-expression-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-next.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org"
|
|
7
7
|
},
|
|
8
8
|
"peerDependencies": {},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@player-tools/xlr": "0.
|
|
11
|
-
"@player-tools/xlr-sdk": "0.
|
|
12
|
-
"@player-tools/xlr-utils": "0.
|
|
13
|
-
"@player-ui/player": "0.
|
|
10
|
+
"@player-tools/xlr": "0.4.0-next.2",
|
|
11
|
+
"@player-tools/xlr-sdk": "0.4.0-next.2",
|
|
12
|
+
"@player-tools/xlr-utils": "0.4.0-next.2",
|
|
13
|
+
"@player-ui/player": "0.4.0-next.7",
|
|
14
14
|
"jsonc-parser": "^2.3.1",
|
|
15
15
|
"typescript-template-language-service-decorator": "^2.3.1",
|
|
16
16
|
"@babel/runtime": "7.15.4"
|
package/src/service.ts
CHANGED
|
@@ -4,12 +4,7 @@ import type {
|
|
|
4
4
|
TemplateContext,
|
|
5
5
|
Logger,
|
|
6
6
|
} from 'typescript-template-language-service-decorator';
|
|
7
|
-
import type {
|
|
8
|
-
FunctionType,
|
|
9
|
-
TSManifest,
|
|
10
|
-
FunctionTypeParameters,
|
|
11
|
-
NodeType,
|
|
12
|
-
} from '@player-tools/xlr';
|
|
7
|
+
import type { FunctionType, TSManifest, NodeType } from '@player-tools/xlr';
|
|
13
8
|
import { createTSDocString } from '@player-tools/xlr-utils';
|
|
14
9
|
import { XLRSDK } from '@player-tools/xlr-sdk';
|
|
15
10
|
import type { ExpressionNode } from '@player-ui/player';
|
|
@@ -19,90 +14,41 @@ import {
|
|
|
19
14
|
toTSLocation,
|
|
20
15
|
convertExprToJSONNode,
|
|
21
16
|
} from './utils';
|
|
17
|
+
import { toFunction } from './transforms';
|
|
22
18
|
|
|
23
|
-
interface
|
|
19
|
+
interface ExpressionEntry {
|
|
20
|
+
/**
|
|
21
|
+
* The name of the expression
|
|
22
|
+
*/
|
|
24
23
|
name: string;
|
|
25
|
-
|
|
24
|
+
/**
|
|
25
|
+
* The description of the expression
|
|
26
|
+
*/
|
|
27
|
+
description?: string;
|
|
28
|
+
/**
|
|
29
|
+
* The XLR type of the expression
|
|
30
|
+
*/
|
|
26
31
|
type: FunctionType;
|
|
32
|
+
/**
|
|
33
|
+
* The XLR enabled plugin the expression was sourced from
|
|
34
|
+
*/
|
|
27
35
|
source: TSManifest;
|
|
28
36
|
}
|
|
29
37
|
|
|
30
|
-
interface ExpressionList {
|
|
31
|
-
entries: Map<string, ExpEntry>;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
38
|
export interface ExpressionLanguageServiceConfig {
|
|
39
|
+
/**
|
|
40
|
+
* The list of XLR enabled plugins to load
|
|
41
|
+
*/
|
|
35
42
|
plugins: Array<TSManifest>;
|
|
36
43
|
}
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
// So use a map to ensure no duplicates
|
|
42
|
-
const expressions = new Map<string, ExpEntry>();
|
|
43
|
-
|
|
44
|
-
plugins.forEach((plugin) => {
|
|
45
|
-
const { capabilities } = plugin;
|
|
46
|
-
const registeredExpressions = capabilities?.Expressions ?? [];
|
|
47
|
-
|
|
48
|
-
registeredExpressions.forEach((exp) => {
|
|
49
|
-
if (exp.type !== 'ref' || !exp.genericArguments) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const expName = exp.name;
|
|
54
|
-
const [args, returnType] = exp.genericArguments;
|
|
55
|
-
|
|
56
|
-
const parameters: Array<FunctionTypeParameters> = (
|
|
57
|
-
args.type === 'tuple' ? args.elementTypes : []
|
|
58
|
-
).map((elementType, index) => {
|
|
59
|
-
return {
|
|
60
|
-
name:
|
|
61
|
-
elementType.name ??
|
|
62
|
-
elementType.type.name ??
|
|
63
|
-
elementType.type.title ??
|
|
64
|
-
`arg_${index}`,
|
|
65
|
-
|
|
66
|
-
type: {
|
|
67
|
-
name:
|
|
68
|
-
elementType.name ??
|
|
69
|
-
elementType.type.name ??
|
|
70
|
-
elementType.type.title ??
|
|
71
|
-
`arg_${index}`,
|
|
72
|
-
...elementType.type,
|
|
73
|
-
},
|
|
74
|
-
optional:
|
|
75
|
-
elementType.optional === true ? elementType.optional : undefined,
|
|
76
|
-
};
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
const entry: ExpEntry = {
|
|
80
|
-
name: expName,
|
|
81
|
-
description: exp.description ?? '',
|
|
82
|
-
source: plugin,
|
|
83
|
-
type: {
|
|
84
|
-
...exp,
|
|
85
|
-
type: 'function',
|
|
86
|
-
parameters,
|
|
87
|
-
returnType,
|
|
88
|
-
},
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
expressions.set(expName, entry);
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
const expList: ExpressionList = {
|
|
96
|
-
entries: expressions,
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
return expList;
|
|
100
|
-
}
|
|
101
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Language server to check Player expression syntax and usage
|
|
47
|
+
*/
|
|
102
48
|
export class ExpressionLanguageService implements TemplateLanguageService {
|
|
103
49
|
private logger?: Logger;
|
|
104
50
|
private _plugins: Array<TSManifest> = [];
|
|
105
|
-
private _expressions:
|
|
51
|
+
private _expressions: Map<string, ExpressionEntry>;
|
|
106
52
|
private xlr: XLRSDK;
|
|
107
53
|
|
|
108
54
|
constructor(
|
|
@@ -110,22 +56,50 @@ export class ExpressionLanguageService implements TemplateLanguageService {
|
|
|
110
56
|
) {
|
|
111
57
|
this.logger = options?.logger;
|
|
112
58
|
this._plugins = options?.plugins ?? [];
|
|
113
|
-
this._expressions = reduceExpression(this._plugins);
|
|
114
59
|
this.xlr = new XLRSDK();
|
|
115
60
|
|
|
116
61
|
this._plugins.forEach((p) => {
|
|
117
|
-
this.xlr.loadDefinitionsFromModule(p);
|
|
62
|
+
this.xlr.loadDefinitionsFromModule(p, undefined, [toFunction]);
|
|
118
63
|
});
|
|
64
|
+
this._expressions = this.reduceExpression();
|
|
119
65
|
}
|
|
120
66
|
|
|
121
67
|
setConfig(config: ExpressionLanguageServiceConfig) {
|
|
122
68
|
this._plugins = config.plugins;
|
|
123
|
-
this._expressions = reduceExpression(this._plugins);
|
|
124
69
|
this.xlr = new XLRSDK();
|
|
125
70
|
|
|
126
71
|
this._plugins.forEach((p) => {
|
|
127
|
-
this.xlr.loadDefinitionsFromModule(p);
|
|
72
|
+
this.xlr.loadDefinitionsFromModule(p, undefined, [toFunction]);
|
|
128
73
|
});
|
|
74
|
+
this._expressions = this.reduceExpression();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private reduceExpression(): Map<string, ExpressionEntry> {
|
|
78
|
+
// Overlaps in names will be resolved by the last plugin to be loaded
|
|
79
|
+
// So use a map to ensure no duplicates
|
|
80
|
+
const expressions = new Map<string, ExpressionEntry>();
|
|
81
|
+
|
|
82
|
+
this.xlr.listTypes().forEach((type) => {
|
|
83
|
+
const typeInfo = this.xlr.getTypeInfo(type.name);
|
|
84
|
+
const source = this._plugins.find(
|
|
85
|
+
(value) => value.pluginName === typeInfo?.plugin
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
if (
|
|
89
|
+
type.type === 'function' &&
|
|
90
|
+
typeInfo?.capability === 'Expressions' &&
|
|
91
|
+
source
|
|
92
|
+
) {
|
|
93
|
+
expressions.set(type.name, {
|
|
94
|
+
name: type.name,
|
|
95
|
+
description: type.description,
|
|
96
|
+
type: type as FunctionType,
|
|
97
|
+
source,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return expressions;
|
|
129
103
|
}
|
|
130
104
|
|
|
131
105
|
getCompletionsAtPosition(
|
|
@@ -143,7 +117,7 @@ export class ExpressionLanguageService implements TemplateLanguageService {
|
|
|
143
117
|
// This happens for the start of an expression (e``)
|
|
144
118
|
// Provide all the completions in this case
|
|
145
119
|
|
|
146
|
-
this._expressions.
|
|
120
|
+
this._expressions.forEach((exp) => {
|
|
147
121
|
completionInfo.entries.push({
|
|
148
122
|
name: exp.name,
|
|
149
123
|
kind: ts.ScriptElementKind.functionElement,
|
|
@@ -163,7 +137,7 @@ export class ExpressionLanguageService implements TemplateLanguageService {
|
|
|
163
137
|
if (token?.type === 'Compound' && token.error) {
|
|
164
138
|
// We hit the end of the expression, and it's expecting more
|
|
165
139
|
// so provide all the completions
|
|
166
|
-
this._expressions.
|
|
140
|
+
this._expressions.forEach((exp) => {
|
|
167
141
|
completionInfo.entries.push({
|
|
168
142
|
name: exp.name,
|
|
169
143
|
kind: ts.ScriptElementKind.functionElement,
|
|
@@ -180,9 +154,9 @@ export class ExpressionLanguageService implements TemplateLanguageService {
|
|
|
180
154
|
// get the relevant start of the identifier
|
|
181
155
|
const start = token.location?.start ?? { character: 0 };
|
|
182
156
|
const wordFromStart = line.slice(start.character, position.character);
|
|
183
|
-
const allCompletions = Array.from(
|
|
184
|
-
|
|
185
|
-
)
|
|
157
|
+
const allCompletions = Array.from(this._expressions.keys()).filter(
|
|
158
|
+
(key) => key.startsWith(wordFromStart)
|
|
159
|
+
);
|
|
186
160
|
|
|
187
161
|
allCompletions.forEach((c) => {
|
|
188
162
|
completionInfo.entries.push({
|
|
@@ -203,7 +177,7 @@ export class ExpressionLanguageService implements TemplateLanguageService {
|
|
|
203
177
|
position: ts.LineAndCharacter,
|
|
204
178
|
name: string
|
|
205
179
|
): ts.CompletionEntryDetails {
|
|
206
|
-
const expression = this._expressions.
|
|
180
|
+
const expression = this._expressions.get(name);
|
|
207
181
|
|
|
208
182
|
const completionDetails: ts.CompletionEntryDetails = {
|
|
209
183
|
name,
|
|
@@ -230,7 +204,7 @@ export class ExpressionLanguageService implements TemplateLanguageService {
|
|
|
230
204
|
const token = getTokenAtPosition(parsed, position);
|
|
231
205
|
|
|
232
206
|
if (token?.type === 'Identifier') {
|
|
233
|
-
const expression = this._expressions.
|
|
207
|
+
const expression = this._expressions.get(token.name);
|
|
234
208
|
|
|
235
209
|
if (expression) {
|
|
236
210
|
const completionDetails = this.getCompletionEntryDetails(
|
|
@@ -289,7 +263,7 @@ export class ExpressionLanguageService implements TemplateLanguageService {
|
|
|
289
263
|
if (node.type === 'CallExpression') {
|
|
290
264
|
// Check that the expression is valid
|
|
291
265
|
const exprName = node.callTarget.name;
|
|
292
|
-
const expression = this._expressions.
|
|
266
|
+
const expression = this._expressions.get(exprName);
|
|
293
267
|
|
|
294
268
|
node.args.forEach((n) => {
|
|
295
269
|
diags.push(...this.getDiagnosticsForNode(context, n));
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { FunctionType, FunctionTypeParameters } from '@player-tools/xlr';
|
|
2
|
+
import { simpleTransformGenerator } from '@player-tools/xlr-sdk';
|
|
3
|
+
|
|
4
|
+
export const toFunction = simpleTransformGenerator(
|
|
5
|
+
'ref',
|
|
6
|
+
'Expressions',
|
|
7
|
+
(exp) => {
|
|
8
|
+
if (!exp.genericArguments || exp.ref !== 'ExpressionHandler') {
|
|
9
|
+
return exp;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const [args, returnType] = exp.genericArguments;
|
|
13
|
+
|
|
14
|
+
const parameters: Array<FunctionTypeParameters> = (
|
|
15
|
+
args.type === 'tuple' ? args.elementTypes : []
|
|
16
|
+
).map((elementType, index) => {
|
|
17
|
+
return {
|
|
18
|
+
name:
|
|
19
|
+
elementType.name ??
|
|
20
|
+
elementType.type.name ??
|
|
21
|
+
elementType.type.title ??
|
|
22
|
+
`arg_${index}`,
|
|
23
|
+
|
|
24
|
+
type: {
|
|
25
|
+
name:
|
|
26
|
+
elementType.name ??
|
|
27
|
+
elementType.type.name ??
|
|
28
|
+
elementType.type.title ??
|
|
29
|
+
`arg_${index}`,
|
|
30
|
+
...elementType.type,
|
|
31
|
+
},
|
|
32
|
+
optional:
|
|
33
|
+
elementType.optional === true ? elementType.optional : undefined,
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
...exp,
|
|
39
|
+
type: 'function',
|
|
40
|
+
parameters,
|
|
41
|
+
returnType,
|
|
42
|
+
} as FunctionType as any;
|
|
43
|
+
}
|
|
44
|
+
);
|