@player-lang/json-language-service 0.0.2-next.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/dist/cjs/index.cjs +2314 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/index.legacy-esm.js +2249 -0
- package/dist/index.mjs +2249 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +40 -0
- package/src/__tests__/__snapshots__/service.test.ts.snap +213 -0
- package/src/__tests__/service.test.ts +298 -0
- package/src/constants.ts +38 -0
- package/src/index.ts +490 -0
- package/src/parser/__tests__/parse.test.ts +18 -0
- package/src/parser/document.ts +456 -0
- package/src/parser/edits.ts +31 -0
- package/src/parser/index.ts +38 -0
- package/src/parser/jsonParseErrors.ts +69 -0
- package/src/parser/types.ts +314 -0
- package/src/parser/utils.ts +94 -0
- package/src/plugins/__tests__/asset-wrapper-array-plugin.test.ts +112 -0
- package/src/plugins/__tests__/binding-schema-plugin.test.ts +62 -0
- package/src/plugins/__tests__/duplicate-id-plugin.test.ts +195 -0
- package/src/plugins/__tests__/missing-asset-wrapper-plugin.test.ts +190 -0
- package/src/plugins/__tests__/nav-state-plugin.test.ts +136 -0
- package/src/plugins/__tests__/view-node-plugin.test.ts +154 -0
- package/src/plugins/asset-wrapper-array-plugin.ts +123 -0
- package/src/plugins/binding-schema-plugin.ts +289 -0
- package/src/plugins/duplicate-id-plugin.ts +158 -0
- package/src/plugins/missing-asset-wrapper-plugin.ts +96 -0
- package/src/plugins/nav-state-plugin.ts +139 -0
- package/src/plugins/view-node-plugin.ts +225 -0
- package/src/plugins/xlr-plugin.ts +371 -0
- package/src/types.ts +119 -0
- package/src/utils.ts +143 -0
- package/src/xlr/__tests__/__snapshots__/transform.test.ts.snap +390 -0
- package/src/xlr/__tests__/transform.test.ts +108 -0
- package/src/xlr/index.ts +3 -0
- package/src/xlr/registry.ts +99 -0
- package/src/xlr/service.ts +190 -0
- package/src/xlr/transforms.ts +169 -0
- package/types/constants.d.ts +7 -0
- package/types/index.d.ts +69 -0
- package/types/parser/document.d.ts +25 -0
- package/types/parser/edits.d.ts +10 -0
- package/types/parser/index.d.ts +16 -0
- package/types/parser/jsonParseErrors.d.ts +27 -0
- package/types/parser/types.d.ts +188 -0
- package/types/parser/utils.d.ts +26 -0
- package/types/plugins/asset-wrapper-array-plugin.d.ts +9 -0
- package/types/plugins/binding-schema-plugin.d.ts +15 -0
- package/types/plugins/duplicate-id-plugin.d.ts +7 -0
- package/types/plugins/missing-asset-wrapper-plugin.d.ts +9 -0
- package/types/plugins/nav-state-plugin.d.ts +9 -0
- package/types/plugins/view-node-plugin.d.ts +9 -0
- package/types/plugins/xlr-plugin.d.ts +7 -0
- package/types/types.d.ts +81 -0
- package/types/utils.d.ts +24 -0
- package/types/xlr/index.d.ts +4 -0
- package/types/xlr/registry.d.ts +17 -0
- package/types/xlr/service.d.ts +22 -0
- package/types/xlr/transforms.d.ts +18 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
// https://github.com/microsoft/vscode-json-languageservice/blob/master/src/jsonLanguageTypes.ts
|
|
2
|
+
import type { Node } from "jsonc-parser";
|
|
3
|
+
|
|
4
|
+
export type ASTNode =
|
|
5
|
+
| StringASTNode
|
|
6
|
+
| NumberASTNode
|
|
7
|
+
| BooleanASTNode
|
|
8
|
+
| ArrayASTNode
|
|
9
|
+
| NullASTNode
|
|
10
|
+
| PropertyASTNode
|
|
11
|
+
| ObjectASTNode
|
|
12
|
+
| AssetASTNode
|
|
13
|
+
| ViewASTNode
|
|
14
|
+
| ContentASTNode
|
|
15
|
+
| NavigationASTNode
|
|
16
|
+
| FlowASTNode
|
|
17
|
+
| EmptyASTNode
|
|
18
|
+
| FlowStateASTNode;
|
|
19
|
+
|
|
20
|
+
export interface BaseASTNode<T extends string> {
|
|
21
|
+
/** The base type of the node */
|
|
22
|
+
readonly type: T;
|
|
23
|
+
|
|
24
|
+
/** an optional parent */
|
|
25
|
+
readonly parent?: ASTNode;
|
|
26
|
+
|
|
27
|
+
/** the underlying json node */
|
|
28
|
+
readonly jsonNode: Node;
|
|
29
|
+
|
|
30
|
+
/** any children of the node */
|
|
31
|
+
readonly children?: ASTNode[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Base JSON types
|
|
35
|
+
export interface StringASTNode extends BaseASTNode<"string"> {
|
|
36
|
+
/** the raw value */
|
|
37
|
+
readonly value: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface NumberASTNode extends BaseASTNode<"number"> {
|
|
41
|
+
/** the raw value */
|
|
42
|
+
readonly value: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface BooleanASTNode extends BaseASTNode<"boolean"> {
|
|
46
|
+
/** the raw value */
|
|
47
|
+
readonly value: boolean;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface ArrayASTNode extends BaseASTNode<"array"> {
|
|
51
|
+
/** the array items */
|
|
52
|
+
readonly children: Array<ASTNode>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface NullASTNode extends BaseASTNode<"null"> {
|
|
56
|
+
/** the raw value */
|
|
57
|
+
readonly value: null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface EmptyASTNode extends BaseASTNode<"empty"> {
|
|
61
|
+
/** the raw value */
|
|
62
|
+
readonly value: undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface PropertyASTNode<
|
|
66
|
+
T extends ASTNode = ASTNode,
|
|
67
|
+
> extends BaseASTNode<"property"> {
|
|
68
|
+
/** the key of the property */
|
|
69
|
+
readonly keyNode: StringASTNode;
|
|
70
|
+
|
|
71
|
+
/** the value of the property */
|
|
72
|
+
readonly valueNode?: T;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Object like things
|
|
76
|
+
export interface ObjectASTNode<
|
|
77
|
+
T extends string = "object",
|
|
78
|
+
> extends BaseASTNode<T> {
|
|
79
|
+
/** an array of properties of this object */
|
|
80
|
+
properties: Array<PropertyASTNode>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Player Semantic Nodes
|
|
84
|
+
export interface AssetASTNode extends ObjectASTNode<"asset"> {
|
|
85
|
+
/** The id property for this asset */
|
|
86
|
+
readonly id?: PropertyASTNode<StringASTNode>;
|
|
87
|
+
|
|
88
|
+
/** The type property for this asset */
|
|
89
|
+
readonly assetType?: PropertyASTNode<StringASTNode>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface ViewASTNode extends ObjectASTNode<"view"> {
|
|
93
|
+
/** the id property for this view */
|
|
94
|
+
readonly id?: PropertyASTNode<StringASTNode>;
|
|
95
|
+
|
|
96
|
+
/** the type of the view */
|
|
97
|
+
readonly viewType?: PropertyASTNode<StringASTNode>;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface ContentASTNode extends ObjectASTNode<"content"> {
|
|
101
|
+
/** the views prop of the flow */
|
|
102
|
+
readonly views?: PropertyASTNode<ArrayASTNode>;
|
|
103
|
+
|
|
104
|
+
/** the nav prop of the flow */
|
|
105
|
+
readonly navigation?: PropertyASTNode<NavigationASTNode>;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface NavigationASTNode extends ObjectASTNode<"navigation"> {
|
|
109
|
+
/** the begin prop of the navigation node */
|
|
110
|
+
readonly begin?: PropertyASTNode;
|
|
111
|
+
|
|
112
|
+
/** the flows of the navigation node */
|
|
113
|
+
readonly flows: Array<PropertyASTNode<FlowASTNode>>;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface FlowASTNode extends ObjectASTNode<"flow"> {
|
|
117
|
+
/** the start prop of the node */
|
|
118
|
+
readonly start?: PropertyASTNode<StringASTNode>;
|
|
119
|
+
|
|
120
|
+
/** the defined states */
|
|
121
|
+
readonly states: Array<PropertyASTNode<FlowStateASTNode>>;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface FlowStateASTNode extends ObjectASTNode<"state"> {
|
|
125
|
+
/** the type of the flow state */
|
|
126
|
+
readonly stateType?: PropertyASTNode<StringASTNode>;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** The base class for any node implementation */
|
|
130
|
+
export abstract class ASTNodeImpl {
|
|
131
|
+
public readonly parent: ASTNode | undefined;
|
|
132
|
+
public readonly jsonNode: Node;
|
|
133
|
+
|
|
134
|
+
constructor(jsonNode: Node, parent: ASTNode | undefined) {
|
|
135
|
+
this.jsonNode = jsonNode;
|
|
136
|
+
this.parent = parent;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** An implementation of a string node */
|
|
141
|
+
export class StringASTNodeImpl extends ASTNodeImpl implements StringASTNode {
|
|
142
|
+
public type = "string" as const;
|
|
143
|
+
public value: string;
|
|
144
|
+
|
|
145
|
+
constructor(jsonNode: Node, parent?: ASTNode) {
|
|
146
|
+
super(jsonNode, parent);
|
|
147
|
+
this.value = jsonNode.value;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** An implementation of the number node */
|
|
152
|
+
export class NumberASTNodeImpl extends ASTNodeImpl implements NumberASTNode {
|
|
153
|
+
public type = "number" as const;
|
|
154
|
+
public value: number;
|
|
155
|
+
|
|
156
|
+
constructor(jsonNode: Node, parent?: ASTNode) {
|
|
157
|
+
super(jsonNode, parent);
|
|
158
|
+
this.value = jsonNode.value;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** An implementation of a boolean node */
|
|
163
|
+
export class BooleanASTNodeImpl extends ASTNodeImpl implements BooleanASTNode {
|
|
164
|
+
public type = "boolean" as const;
|
|
165
|
+
public value: boolean;
|
|
166
|
+
|
|
167
|
+
constructor(jsonNode: Node, parent?: ASTNode) {
|
|
168
|
+
super(jsonNode, parent);
|
|
169
|
+
this.value = jsonNode.value;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** An implementation of a null node */
|
|
174
|
+
export class NullASTNodeImpl extends ASTNodeImpl implements NullASTNode {
|
|
175
|
+
public type = "null" as const;
|
|
176
|
+
public value = null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** An implementation of a property node */
|
|
180
|
+
export class PropertyASTNodeImpl
|
|
181
|
+
extends ASTNodeImpl
|
|
182
|
+
implements PropertyASTNode
|
|
183
|
+
{
|
|
184
|
+
public type = "property" as const;
|
|
185
|
+
public keyNode: StringASTNode;
|
|
186
|
+
public valueNode?: ASTNode;
|
|
187
|
+
|
|
188
|
+
constructor(
|
|
189
|
+
jsonNode: Node,
|
|
190
|
+
parent: ASTNode | undefined,
|
|
191
|
+
keyNode: StringASTNode,
|
|
192
|
+
) {
|
|
193
|
+
super(jsonNode, parent);
|
|
194
|
+
this.keyNode = keyNode;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
public get children() {
|
|
198
|
+
return this.valueNode ? [this.keyNode, this.valueNode] : [this.keyNode];
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** An implementation of a view node */
|
|
203
|
+
export class ViewASTNodeImpl extends ASTNodeImpl implements ViewASTNode {
|
|
204
|
+
public type = "view" as const;
|
|
205
|
+
public properties: PropertyASTNode[] = [];
|
|
206
|
+
public id?: PropertyASTNode<StringASTNode> = undefined;
|
|
207
|
+
public viewType?: PropertyASTNode<StringASTNode> = undefined;
|
|
208
|
+
|
|
209
|
+
public get children() {
|
|
210
|
+
return this.properties;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** An implementation of a top flow node */
|
|
215
|
+
export class ContentASTNodeImpl extends ASTNodeImpl implements ContentASTNode {
|
|
216
|
+
public type = "content" as const;
|
|
217
|
+
public properties: PropertyASTNode[] = [];
|
|
218
|
+
public views?: PropertyASTNode<ArrayASTNode> = undefined;
|
|
219
|
+
public navigation?: PropertyASTNode<NavigationASTNode> = undefined;
|
|
220
|
+
|
|
221
|
+
public get children() {
|
|
222
|
+
return this.properties;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** An implementation of a navigation node */
|
|
227
|
+
export class NavigationASTNodeImpl
|
|
228
|
+
extends ASTNodeImpl
|
|
229
|
+
implements NavigationASTNode
|
|
230
|
+
{
|
|
231
|
+
public type = "navigation" as const;
|
|
232
|
+
public properties: PropertyASTNode[] = [];
|
|
233
|
+
public begin?: PropertyASTNode<StringASTNode> = undefined;
|
|
234
|
+
public flows: Array<PropertyASTNode<FlowASTNode>> = [];
|
|
235
|
+
|
|
236
|
+
public get children() {
|
|
237
|
+
return this.properties;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** An implementation of a flow node */
|
|
242
|
+
export class FlowASTNodeImpl extends ASTNodeImpl implements FlowASTNode {
|
|
243
|
+
public type = "flow" as const;
|
|
244
|
+
public properties: PropertyASTNode[] = [];
|
|
245
|
+
public start?: PropertyASTNode<StringASTNode> = undefined;
|
|
246
|
+
public states: Array<PropertyASTNode<FlowStateASTNode>> = [];
|
|
247
|
+
|
|
248
|
+
public get children() {
|
|
249
|
+
return this.properties;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** An implementation of a flow-state node */
|
|
254
|
+
export class FlowStateASTNodeImpl
|
|
255
|
+
extends ASTNodeImpl
|
|
256
|
+
implements FlowStateASTNode
|
|
257
|
+
{
|
|
258
|
+
public type = "state" as const;
|
|
259
|
+
public properties: PropertyASTNode[] = [];
|
|
260
|
+
public stateType?: PropertyASTNode<StringASTNode> = undefined;
|
|
261
|
+
|
|
262
|
+
public get children() {
|
|
263
|
+
return this.properties;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** An implementation of an asset node */
|
|
268
|
+
export class AssetASTNodeImpl extends ASTNodeImpl implements AssetASTNode {
|
|
269
|
+
public type = "asset" as const;
|
|
270
|
+
public properties: PropertyASTNode[] = [];
|
|
271
|
+
public id?: PropertyASTNode<StringASTNode> = undefined;
|
|
272
|
+
public assetType?: PropertyASTNode<StringASTNode> = undefined;
|
|
273
|
+
|
|
274
|
+
public get children() {
|
|
275
|
+
return this.properties;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** An implementation of a array node */
|
|
280
|
+
export class ArrayASTNodeImpl extends ASTNodeImpl implements ArrayASTNode {
|
|
281
|
+
public type = "array" as const;
|
|
282
|
+
public items: ASTNode[] = [];
|
|
283
|
+
|
|
284
|
+
public get children() {
|
|
285
|
+
return this.items;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** An implementation of an object node */
|
|
290
|
+
export class ObjectASTNodeImpl extends ASTNodeImpl implements ObjectASTNode {
|
|
291
|
+
public type = "object" as const;
|
|
292
|
+
public properties: PropertyASTNode[] = [];
|
|
293
|
+
|
|
294
|
+
public get children() {
|
|
295
|
+
return this.properties;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Edits
|
|
300
|
+
|
|
301
|
+
export type NodeEdit = ReplaceEdit;
|
|
302
|
+
|
|
303
|
+
export interface BaseNodeEdit<T extends string> {
|
|
304
|
+
/** The type of node edit */
|
|
305
|
+
type: T;
|
|
306
|
+
|
|
307
|
+
/** the node to edit */
|
|
308
|
+
node: ASTNode;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export interface ReplaceEdit extends BaseNodeEdit<"replace"> {
|
|
312
|
+
/** the new value to replace with */
|
|
313
|
+
value: any;
|
|
314
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ASTNode,
|
|
3
|
+
PropertyASTNode,
|
|
4
|
+
StringASTNode,
|
|
5
|
+
ViewASTNode,
|
|
6
|
+
ContentASTNode,
|
|
7
|
+
FlowStateASTNode,
|
|
8
|
+
ObjectASTNode,
|
|
9
|
+
FlowASTNode,
|
|
10
|
+
NavigationASTNode,
|
|
11
|
+
AssetASTNode,
|
|
12
|
+
} from "./types";
|
|
13
|
+
|
|
14
|
+
/** check if the node is a property */
|
|
15
|
+
export function isPropertyNode(node?: ASTNode): node is PropertyASTNode {
|
|
16
|
+
return node?.type === "property";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** check if the node is an object ast */
|
|
20
|
+
export function isObjectNode(node?: ASTNode): node is ObjectASTNode {
|
|
21
|
+
return node?.type === "object";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** check if the node is a key */
|
|
25
|
+
export function isKeyNode(node?: ASTNode): node is StringASTNode {
|
|
26
|
+
return isPropertyNode(node?.parent) && node?.parent.keyNode === node;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** check if the node is a value */
|
|
30
|
+
export function isValueNode(node?: ASTNode): boolean {
|
|
31
|
+
return isPropertyNode(node?.parent) && node?.parent.valueNode === node;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** check if the node is a view */
|
|
35
|
+
export function isViewNode(node?: ASTNode): node is ViewASTNode {
|
|
36
|
+
return node?.type === "view";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** check if the node is a state */
|
|
40
|
+
export function isStateNode(node?: ASTNode): node is FlowStateASTNode {
|
|
41
|
+
return node?.type === "state";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** check if the node is a flow */
|
|
45
|
+
export function isFlowNode(node?: ASTNode): node is FlowASTNode {
|
|
46
|
+
return node?.type === "flow";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** check if the node is a nav */
|
|
50
|
+
export function isNavigationNode(node?: ASTNode): node is NavigationASTNode {
|
|
51
|
+
return node?.type === "navigation";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** get the value for a given key in the object */
|
|
55
|
+
export function getValForKey<T extends ObjectASTNode<any>>(
|
|
56
|
+
node: T,
|
|
57
|
+
key: string,
|
|
58
|
+
): any {
|
|
59
|
+
const prop = node.properties.find((k) => k.keyNode.value === key);
|
|
60
|
+
return prop?.valueNode?.jsonNode.value;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** get the key for the given value node */
|
|
64
|
+
export function getPropForValNode(node?: ASTNode): string | undefined {
|
|
65
|
+
if (isValueNode(node) && isPropertyNode(node?.parent)) {
|
|
66
|
+
return node?.parent.keyNode.value;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** find the view node */
|
|
71
|
+
export function getViewNode(
|
|
72
|
+
node: ASTNode,
|
|
73
|
+
): ViewASTNode | AssetASTNode | undefined {
|
|
74
|
+
if (node.parent) {
|
|
75
|
+
if (node.parent.type === "view") {
|
|
76
|
+
return node.parent;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return getViewNode(node.parent);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (node.type === "asset") {
|
|
83
|
+
return node;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** traverse up until we find the root content node */
|
|
88
|
+
export function getContentNode(node: ASTNode): ContentASTNode | undefined {
|
|
89
|
+
if (node.type === "content") {
|
|
90
|
+
return node;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return node.parent ? getContentNode(node.parent) : undefined;
|
|
94
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { test, expect, describe, beforeEach } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
ReferenceAssetsWebPluginManifest,
|
|
4
|
+
Types,
|
|
5
|
+
} from "@player-lang/static-xlrs";
|
|
6
|
+
import { PlayerLanguageService } from "../..";
|
|
7
|
+
import { toTextDocument } from "../../utils";
|
|
8
|
+
|
|
9
|
+
describe("asset-wrapper-array-plugin", () => {
|
|
10
|
+
let service: PlayerLanguageService;
|
|
11
|
+
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
service = new PlayerLanguageService();
|
|
14
|
+
await service.setAssetTypesFromModule([
|
|
15
|
+
Types,
|
|
16
|
+
ReferenceAssetsWebPluginManifest,
|
|
17
|
+
]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("finds arrays that should be asset wrappers", async () => {
|
|
21
|
+
const textDocument = toTextDocument(
|
|
22
|
+
JSON.stringify(
|
|
23
|
+
{
|
|
24
|
+
id: "foo",
|
|
25
|
+
navigation: {
|
|
26
|
+
BEGIN: "FLOW_1",
|
|
27
|
+
FLOW_1: {
|
|
28
|
+
startState: "VIEW_1",
|
|
29
|
+
VIEW_1: {
|
|
30
|
+
state_type: "VIEW",
|
|
31
|
+
ref: "bar",
|
|
32
|
+
transitions: {},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
views: [
|
|
37
|
+
{
|
|
38
|
+
id: "bar",
|
|
39
|
+
type: "info",
|
|
40
|
+
primaryInfo: [
|
|
41
|
+
{
|
|
42
|
+
id: "asset-1",
|
|
43
|
+
type: "text",
|
|
44
|
+
value: "Foo",
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
null,
|
|
51
|
+
2,
|
|
52
|
+
),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const diags = await service.validateTextDocument(textDocument);
|
|
56
|
+
|
|
57
|
+
expect(diags?.map((d) => d.message)).toMatchInlineSnapshot(`
|
|
58
|
+
[
|
|
59
|
+
"View Validation Error - value: Does not match any of the expected types for type: 'AssetWrapperOrSwitch'",
|
|
60
|
+
"Expected: AssetWrapper & object literal | StaticSwitch & object literal | DynamicSwitch & object literal",
|
|
61
|
+
"Implicit Array -> "collection" assets is not supported.",
|
|
62
|
+
]
|
|
63
|
+
`);
|
|
64
|
+
|
|
65
|
+
expect(diags).toMatchInlineSnapshot(`
|
|
66
|
+
[
|
|
67
|
+
{
|
|
68
|
+
"message": "View Validation Error - value: Does not match any of the expected types for type: 'AssetWrapperOrSwitch'",
|
|
69
|
+
"range": {
|
|
70
|
+
"end": {
|
|
71
|
+
"character": 7,
|
|
72
|
+
"line": 23,
|
|
73
|
+
},
|
|
74
|
+
"start": {
|
|
75
|
+
"character": 21,
|
|
76
|
+
"line": 17,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
"severity": 1,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"message": "Expected: AssetWrapper & object literal | StaticSwitch & object literal | DynamicSwitch & object literal",
|
|
83
|
+
"range": {
|
|
84
|
+
"end": {
|
|
85
|
+
"character": 7,
|
|
86
|
+
"line": 23,
|
|
87
|
+
},
|
|
88
|
+
"start": {
|
|
89
|
+
"character": 21,
|
|
90
|
+
"line": 17,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
"severity": 3,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"message": "Implicit Array -> "collection" assets is not supported.",
|
|
97
|
+
"range": {
|
|
98
|
+
"end": {
|
|
99
|
+
"character": 19,
|
|
100
|
+
"line": 17,
|
|
101
|
+
},
|
|
102
|
+
"start": {
|
|
103
|
+
"character": 6,
|
|
104
|
+
"line": 17,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
"severity": 1,
|
|
108
|
+
},
|
|
109
|
+
]
|
|
110
|
+
`);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { test, expect, describe, beforeEach } from "vitest";
|
|
2
|
+
import { Position } from "vscode-languageserver-types";
|
|
3
|
+
import {
|
|
4
|
+
ReferenceAssetsWebPluginManifest,
|
|
5
|
+
Types,
|
|
6
|
+
} from "@player-lang/static-xlrs";
|
|
7
|
+
import { PlayerLanguageService } from "../..";
|
|
8
|
+
import { toTextDocument } from "../../utils";
|
|
9
|
+
|
|
10
|
+
describe("binding-plugin", () => {
|
|
11
|
+
let service: PlayerLanguageService;
|
|
12
|
+
|
|
13
|
+
beforeEach(async () => {
|
|
14
|
+
service = new PlayerLanguageService();
|
|
15
|
+
await service.setAssetTypesFromModule([
|
|
16
|
+
Types,
|
|
17
|
+
ReferenceAssetsWebPluginManifest,
|
|
18
|
+
]);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("auto completes bindings", async () => {
|
|
22
|
+
const testDocument = toTextDocument(
|
|
23
|
+
JSON.stringify(
|
|
24
|
+
{
|
|
25
|
+
views: [
|
|
26
|
+
{
|
|
27
|
+
id: "bar",
|
|
28
|
+
type: "input",
|
|
29
|
+
binding: "",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
schema: {
|
|
33
|
+
ROOT: {
|
|
34
|
+
foo: {
|
|
35
|
+
type: "FooType",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
FooType: {
|
|
39
|
+
bar: {
|
|
40
|
+
type: "StringType",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
null,
|
|
46
|
+
2,
|
|
47
|
+
),
|
|
48
|
+
);
|
|
49
|
+
const completions = await service.getCompletionsAtPosition(
|
|
50
|
+
testDocument,
|
|
51
|
+
Position.create(5, 18),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
expect(completions.items).toHaveLength(2);
|
|
55
|
+
expect(completions.items.map((c) => c.label)).toMatchInlineSnapshot(`
|
|
56
|
+
[
|
|
57
|
+
"foo",
|
|
58
|
+
"foo.bar",
|
|
59
|
+
]
|
|
60
|
+
`);
|
|
61
|
+
});
|
|
62
|
+
});
|