@spyglassmc/mcdoc 0.1.0 → 0.3.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/lib/node/index.js CHANGED
@@ -1,275 +1,588 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.UseStatementNode = exports.TypeAliasNode = exports.StructInjectionNode = exports.EnumInjectionNode = exports.InjectionNode = exports.UnionTypeNode = exports.DispatcherTypeNode = exports.StructSpreadFieldNode = exports.StructMapKeyNode = exports.StructKeyNode = exports.StructPairFieldNode = exports.StructFieldNode = exports.StructBlockNode = exports.PathNode = exports.TypeParamNode = exports.TypeParamBlockNode = exports.StructNode = exports.PrelimNode = exports.EnumValueNode = exports.EnumFieldNode = exports.EnumBlockNode = exports.DocCommentsNode = exports.EnumNode = exports.TupleTypeNode = exports.ListTypeNode = exports.PrimitiveArrayTypeNode = exports.FloatRangeNode = exports.NumericTypeNode = exports.TypedNumberNode = exports.LiteralTypeNode = exports.IntRangeNode = exports.StringTypeNode = exports.BooleanTypeNode = exports.AnyTypeNode = exports.AttributeTreeNamedValuesNode = exports.AttributeTreePosValuesNode = exports.AttributeTreeNode = exports.AttributeValueNode = exports.AttributeNode = exports.TypeNode = exports.AccessorKeyNode = exports.DynamicIndexNode = exports.IdentifierNode = exports.StaticIndexNode = exports.IndexNode = exports.IndexBodyNode = exports.LiteralNode = exports.DispatchStatementNode = exports.TopLevelNode = exports.ModuleNode = void 0;
4
- const core_1 = require("@spyglassmc/core");
5
- exports.ModuleNode = Object.freeze({
1
+ import { atArray, CommentNode, FloatNode, ResourceLocationNode, StringNode } from '@spyglassmc/core';
2
+ export const ModuleNode = Object.freeze({
6
3
  is(node) {
7
4
  return node?.type === 'mcdoc:module';
8
5
  },
9
6
  });
10
- exports.TopLevelNode = Object.freeze({
7
+ export const TopLevelNode = Object.freeze({
11
8
  is(node) {
12
- return (core_1.CommentNode.is(node) ||
13
- exports.DispatchStatementNode.is(node) ||
14
- exports.EnumNode.is(node) ||
15
- exports.InjectionNode.is(node) ||
16
- exports.StructNode.is(node) ||
17
- exports.TypeAliasNode.is(node) ||
18
- exports.UseStatementNode.is(node));
9
+ return (CommentNode.is(node) ||
10
+ DispatchStatementNode.is(node) ||
11
+ EnumNode.is(node) ||
12
+ InjectionNode.is(node) ||
13
+ StructNode.is(node) ||
14
+ TypeAliasNode.is(node) ||
15
+ UseStatementNode.is(node));
19
16
  },
20
17
  });
21
- exports.DispatchStatementNode = Object.freeze({
18
+ export const DispatchStatementNode = Object.freeze({
19
+ destruct(node) {
20
+ return {
21
+ attributes: node.children.filter(AttributeNode.is),
22
+ location: node.children.find(ResourceLocationNode.is),
23
+ index: node.children.find(IndexBodyNode.is),
24
+ target: node.children.find(TypeNode.is),
25
+ };
26
+ },
22
27
  is(node) {
23
28
  return node?.type === 'mcdoc:dispatch_statement';
24
29
  },
25
30
  });
26
- exports.LiteralNode = Object.freeze({
31
+ export const LiteralNode = Object.freeze({
27
32
  is(node) {
28
33
  return node?.type === 'mcdoc:literal';
29
34
  },
30
35
  });
31
- exports.IndexBodyNode = Object.freeze({
36
+ export const IndexBodyNode = Object.freeze({
37
+ destruct(node) {
38
+ return {
39
+ parallelIndices: node.children.filter(IndexNode.is),
40
+ };
41
+ },
32
42
  is(node) {
33
43
  return node?.type === 'mcdoc:index_body';
34
44
  },
35
45
  });
36
- exports.IndexNode = Object.freeze({
46
+ export const IndexNode = Object.freeze({
37
47
  is(node) {
38
- return exports.StaticIndexNode.is(node) || exports.DynamicIndexNode.is(node);
48
+ return StaticIndexNode.is(node) || DynamicIndexNode.is(node);
39
49
  },
40
50
  });
41
- exports.StaticIndexNode = Object.freeze({
51
+ export const StaticIndexNode = Object.freeze({
42
52
  is(node) {
43
- return exports.LiteralNode.is(node) || exports.IdentifierNode.is(node) || core_1.StringNode.is(node) || core_1.ResourceLocationNode.is(node);
53
+ return LiteralNode.is(node) || IdentifierNode.is(node) || StringNode.is(node) || ResourceLocationNode.is(node);
44
54
  },
45
55
  });
46
- exports.IdentifierNode = Object.freeze({
56
+ export const IdentifierNode = Object.freeze({
47
57
  is(node) {
48
58
  return node?.type === 'mcdoc:identifier';
49
59
  },
50
60
  });
51
- exports.DynamicIndexNode = Object.freeze({
61
+ export const DynamicIndexNode = Object.freeze({
62
+ destruct(node) {
63
+ return {
64
+ keys: node.children.filter(AccessorKeyNode.is),
65
+ };
66
+ },
52
67
  is(node) {
53
68
  return node?.type === 'mcdoc:dynamic_index';
54
69
  },
55
70
  });
56
- exports.AccessorKeyNode = Object.freeze({
71
+ export const AccessorKeyNode = Object.freeze({
57
72
  is(node) {
58
- return exports.LiteralNode.is(node) || exports.IdentifierNode.is(node) || core_1.StringNode.is(node);
73
+ return LiteralNode.is(node) || IdentifierNode.is(node) || StringNode.is(node);
59
74
  },
60
75
  });
61
- exports.TypeNode = Object.freeze({
76
+ export const TypeNode = Object.freeze({
62
77
  is(node) {
63
- return (exports.AnyTypeNode.is(node) ||
64
- exports.BooleanTypeNode.is(node) ||
65
- exports.StringTypeNode.is(node) ||
66
- exports.LiteralTypeNode.is(node) ||
67
- exports.NumericTypeNode.is(node) ||
68
- exports.PrimitiveArrayTypeNode.is(node) ||
69
- exports.ListTypeNode.is(node) ||
70
- exports.TupleTypeNode.is(node) ||
71
- exports.EnumNode.is(node) ||
72
- exports.StructNode.is(node) ||
73
- exports.PathNode.is(node) ||
74
- exports.DispatcherTypeNode.is(node) ||
75
- exports.UnionTypeNode.is(node));
78
+ return (AnyTypeNode.is(node) ||
79
+ BooleanTypeNode.is(node) ||
80
+ StringTypeNode.is(node) ||
81
+ LiteralTypeNode.is(node) ||
82
+ NumericTypeNode.is(node) ||
83
+ PrimitiveArrayTypeNode.is(node) ||
84
+ ListTypeNode.is(node) ||
85
+ TupleTypeNode.is(node) ||
86
+ EnumNode.is(node) ||
87
+ StructNode.is(node) ||
88
+ ReferenceTypeNode.is(node) ||
89
+ DispatcherTypeNode.is(node) ||
90
+ UnionTypeNode.is(node));
76
91
  },
77
- asType(node) {
78
- throw '// TODO';
92
+ });
93
+ export const TypeBaseNode = Object.freeze({
94
+ destruct(node) {
95
+ return {
96
+ attributes: node.children.filter(AttributeNode.is),
97
+ indices: node.children.filter(IndexBodyNode.is),
98
+ };
79
99
  },
80
100
  });
81
- exports.AttributeNode = Object.freeze({
101
+ export const AttributeNode = Object.freeze({
102
+ destruct(node) {
103
+ return {
104
+ name: node.children.find(IdentifierNode.is),
105
+ value: node.children.find(AttributeValueNode.is),
106
+ };
107
+ },
82
108
  is(node) {
83
109
  return node?.type === 'mcdoc:attribute';
84
110
  },
85
111
  });
86
- exports.AttributeValueNode = Object.freeze({
112
+ export const AttributeValueNode = Object.freeze({
87
113
  is(node) {
88
- return exports.TypeNode.is(node) || exports.AttributeTreeNode.is(node);
114
+ return TypeNode.is(node) || AttributeTreeNode.is(node);
89
115
  },
90
116
  });
91
- exports.AttributeTreeNode = Object.freeze({
117
+ export const AttributeTreeNode = Object.freeze({
118
+ destruct(node) {
119
+ return {
120
+ positional: node.children.find(AttributeTreePosValuesNode.is),
121
+ named: node.children.find(AttributeTreeNamedValuesNode.is),
122
+ };
123
+ },
92
124
  is(node) {
93
125
  return node?.type === 'mcdoc:attribute/tree';
94
126
  },
95
127
  });
96
- exports.AttributeTreePosValuesNode = Object.freeze({
128
+ export const AttributeTreePosValuesNode = Object.freeze({
129
+ destruct(node) {
130
+ return {
131
+ values: node.children.filter(AttributeValueNode.is),
132
+ };
133
+ },
97
134
  is(node) {
98
135
  return node?.type === 'mcdoc:attribute/tree/pos';
99
136
  },
100
137
  });
101
- exports.AttributeTreeNamedValuesNode = Object.freeze({
138
+ export const AttributeTreeNamedValuesNode = Object.freeze({
139
+ destruct(node) {
140
+ const ans = {
141
+ values: [],
142
+ };
143
+ let key;
144
+ for (const child of node.children) {
145
+ if (CommentNode.is(child)) {
146
+ continue;
147
+ }
148
+ if (IdentifierNode.is(child) || StringNode.is(child)) {
149
+ key = child;
150
+ }
151
+ else if (key) {
152
+ ans.values.push({ key, value: child });
153
+ key = undefined;
154
+ }
155
+ }
156
+ return ans;
157
+ },
102
158
  is(node) {
103
159
  return node?.type === 'mcdoc:attribute/tree/named';
104
160
  },
105
161
  });
106
- exports.AnyTypeNode = Object.freeze({
162
+ export const AnyTypeNode = Object.freeze({
107
163
  is(node) {
108
164
  return node?.type === 'mcdoc:type/any';
109
165
  },
110
166
  });
111
- exports.BooleanTypeNode = Object.freeze({
167
+ export const BooleanTypeNode = Object.freeze({
112
168
  is(node) {
113
169
  return node?.type === 'mcdoc:type/boolean';
114
170
  },
115
171
  });
116
- exports.StringTypeNode = Object.freeze({
117
- is(node) {
118
- return node?.type === 'mcdoc:type/string';
172
+ export const IntRangeNode = Object.freeze({
173
+ destruct(node) {
174
+ return destructRangeNode(node);
119
175
  },
120
- });
121
- exports.IntRangeNode = Object.freeze({
122
176
  is(node) {
123
177
  return node?.type === 'mcdoc:int_range';
124
178
  },
125
179
  });
126
- exports.LiteralTypeNode = Object.freeze({
180
+ export const LiteralTypeNode = Object.freeze({
181
+ destruct(node) {
182
+ return {
183
+ value: node.children.find(LiteralTypeValueNode.is),
184
+ };
185
+ },
127
186
  is(node) {
128
187
  return node?.type === 'mcdoc:type/literal';
129
188
  },
130
189
  });
131
- exports.TypedNumberNode = Object.freeze({
190
+ export const LiteralTypeValueNode = Object.freeze({
191
+ is(node) {
192
+ return LiteralNode.is(node) || TypedNumberNode.is(node) || StringNode.is(node);
193
+ },
194
+ });
195
+ export const TypedNumberNode = Object.freeze({
196
+ destruct(node) {
197
+ return {
198
+ value: node.children.find(FloatNode.is),
199
+ suffix: node.children.find(LiteralNode.is),
200
+ };
201
+ },
132
202
  is(node) {
133
203
  return node?.type === 'mcdoc:typed_number';
134
204
  },
135
205
  });
136
- exports.NumericTypeNode = Object.freeze({
206
+ export const NumericTypeNode = Object.freeze({
207
+ destruct(node) {
208
+ return {
209
+ numericKind: node.children.find(LiteralNode.is),
210
+ valueRange: node.children.find(FloatRangeNode.is) || node.children.find(IntRangeNode.is),
211
+ };
212
+ },
137
213
  is(node) {
138
214
  return node?.type === 'mcdoc:type/numeric_type';
139
215
  },
140
216
  });
141
- exports.FloatRangeNode = Object.freeze({
217
+ export const RangeExclusiveChar = '<';
218
+ export function getRangeDelimiter(kind) {
219
+ const prefix = kind & 0b10 ? RangeExclusiveChar : '';
220
+ const suffix = kind & 0b01 ? RangeExclusiveChar : '';
221
+ return `${prefix}..${suffix}`;
222
+ }
223
+ function destructRangeNode(node) {
224
+ let kind;
225
+ let min;
226
+ let max;
227
+ if (node.children.length === 1) {
228
+ // a
229
+ kind = 0b00;
230
+ min = max = node.children[0];
231
+ }
232
+ else if (node.children.length === 3) {
233
+ // a..b
234
+ kind = getKind(node.children[1]);
235
+ min = node.children[0];
236
+ max = node.children[2];
237
+ }
238
+ else if (LiteralNode.is(node.children[0])) {
239
+ // ..b
240
+ kind = getKind(node.children[0]);
241
+ max = node.children[1];
242
+ }
243
+ else {
244
+ // a..
245
+ kind = getKind(node.children[1]);
246
+ min = node.children[0];
247
+ }
248
+ return {
249
+ kind,
250
+ min,
251
+ max,
252
+ };
253
+ function getKind(delimiter) {
254
+ let ans = 0b00;
255
+ if (delimiter.value.startsWith(RangeExclusiveChar)) {
256
+ ans |= 0b10;
257
+ }
258
+ if (delimiter.value.endsWith(RangeExclusiveChar)) {
259
+ ans |= 0b01;
260
+ }
261
+ return ans;
262
+ }
263
+ }
264
+ export const FloatRangeNode = Object.freeze({
265
+ destruct(node) {
266
+ return destructRangeNode(node);
267
+ },
142
268
  is(node) {
143
269
  return node?.type === 'mcdoc:float_range';
144
270
  },
145
271
  });
146
- exports.PrimitiveArrayTypeNode = Object.freeze({
272
+ export const PrimitiveArrayTypeNode = Object.freeze({
273
+ destruct(node) {
274
+ let lengthRange;
275
+ let valueRange;
276
+ let afterBrackets = false;
277
+ for (const child of node.children) {
278
+ if (LiteralNode.is(child) && child.value === '[]') {
279
+ afterBrackets = true;
280
+ }
281
+ else if (IntRangeNode.is(child)) {
282
+ if (afterBrackets) {
283
+ lengthRange = child;
284
+ }
285
+ else {
286
+ valueRange = child;
287
+ }
288
+ }
289
+ }
290
+ return {
291
+ arrayKind: node.children.find(LiteralNode.is),
292
+ lengthRange,
293
+ valueRange,
294
+ };
295
+ },
147
296
  is(node) {
148
297
  return node?.type === 'mcdoc:type/primitive_array';
149
298
  },
150
299
  });
151
- exports.ListTypeNode = Object.freeze({
300
+ export const ListTypeNode = Object.freeze({
301
+ destruct(node) {
302
+ return {
303
+ item: node.children.find(TypeNode.is),
304
+ lengthRange: node.children.find(IntRangeNode.is),
305
+ };
306
+ },
152
307
  is(node) {
153
308
  return node?.type === 'mcdoc:type/list';
154
309
  },
155
310
  });
156
- exports.TupleTypeNode = Object.freeze({
311
+ export const StringTypeNode = Object.freeze({
312
+ destruct(node) {
313
+ return {
314
+ lengthRange: node.children.find(IntRangeNode.is),
315
+ };
316
+ },
317
+ is(node) {
318
+ return node?.type === 'mcdoc:type/string';
319
+ },
320
+ });
321
+ export const TupleTypeNode = Object.freeze({
322
+ destruct(node) {
323
+ return {
324
+ items: node.children.filter(TypeNode.is),
325
+ };
326
+ },
157
327
  is(node) {
158
328
  return node?.type === 'mcdoc:type/tuple';
159
329
  },
160
330
  });
161
- exports.EnumNode = Object.freeze({
331
+ const EnumKinds = new Set(['byte', 'short', 'int', 'long', 'float', 'double', 'string']);
332
+ export const EnumNode = Object.freeze({
333
+ kinds: EnumKinds,
334
+ destruct(node) {
335
+ return {
336
+ block: node.children.find(EnumBlockNode.is),
337
+ docComments: node.children.find(DocCommentsNode.is),
338
+ enumKind: getEnumKind(node),
339
+ identifier: node.children.find(IdentifierNode.is),
340
+ };
341
+ function getEnumKind(node) {
342
+ for (const literal of node.children.filter(LiteralNode.is)) {
343
+ if (EnumKinds.has(literal.value)) {
344
+ return literal.value;
345
+ }
346
+ }
347
+ return undefined;
348
+ }
349
+ },
162
350
  is(node) {
163
351
  return node?.type === 'mcdoc:enum';
164
352
  },
165
- kinds: new Set(['byte', 'short', 'int', 'long', 'float', 'double', 'string']),
166
353
  });
167
- exports.DocCommentsNode = Object.freeze({
354
+ export const DocCommentsNode = Object.freeze({
355
+ /**
356
+ * @returns The text content of this doc comment block.
357
+ */
358
+ asText(node) {
359
+ if (!node) {
360
+ return undefined;
361
+ }
362
+ let comments = node.children.map(doc => doc.comment);
363
+ // If every comment contains a leading space or is empty, stripe the leading spaces off.
364
+ // e.g. /// This is an example doc comment.
365
+ // ///
366
+ // /// Another line.
367
+ // should be converted to "This is an example doc comment.\n\nAnother line."
368
+ if (comments.every(s => s.length === 0 || s.startsWith(' '))) {
369
+ comments = comments.map(s => s.slice(1));
370
+ }
371
+ return comments.join('\n');
372
+ },
168
373
  is(node) {
169
374
  return node?.type === 'mcdoc:doc_comments';
170
375
  },
171
376
  });
172
- exports.EnumBlockNode = Object.freeze({
377
+ export const EnumBlockNode = Object.freeze({
378
+ destruct(node) {
379
+ return {
380
+ fields: node.children.filter(EnumFieldNode.is),
381
+ };
382
+ },
173
383
  is(node) {
174
384
  return node?.type === 'mcdoc:enum/block';
175
385
  },
176
386
  });
177
- exports.EnumFieldNode = Object.freeze({
387
+ export const EnumFieldNode = Object.freeze({
388
+ destruct(node) {
389
+ return {
390
+ attributes: node.children.filter(AttributeNode.is),
391
+ identifier: node.children.find(IdentifierNode.is),
392
+ value: node.children.find(EnumValueNode.is),
393
+ };
394
+ },
178
395
  is(node) {
179
396
  return node?.type === 'mcdoc:enum/field';
180
397
  },
181
398
  });
182
- exports.EnumValueNode = Object.freeze({
399
+ export const EnumValueNode = Object.freeze({
183
400
  is(node) {
184
- return exports.TypedNumberNode.is(node) || core_1.StringNode.is(node);
401
+ return TypedNumberNode.is(node) || StringNode.is(node);
185
402
  },
186
403
  });
187
- exports.PrelimNode = Object.freeze({
404
+ export const PrelimNode = Object.freeze({
188
405
  is(node) {
189
- return exports.AttributeNode.is(node) || exports.DocCommentsNode.is(node);
406
+ return AttributeNode.is(node) || DocCommentsNode.is(node);
190
407
  },
191
408
  });
192
- exports.StructNode = Object.freeze({
409
+ export const StructNode = Object.freeze({
410
+ destruct(node) {
411
+ return {
412
+ block: node.children.find(StructBlockNode.is),
413
+ docComments: node.children.find(DocCommentsNode.is),
414
+ identifier: node.children.find(IdentifierNode.is),
415
+ };
416
+ },
193
417
  is(node) {
194
418
  return node?.type === 'mcdoc:struct';
195
419
  },
196
420
  });
197
- exports.TypeParamBlockNode = Object.freeze({
421
+ export const ReferenceTypeNode = Object.freeze({
422
+ destruct(node) {
423
+ return {
424
+ path: node.children.find(PathNode.is),
425
+ typeParameters: node.children.filter(TypeNode.is),
426
+ };
427
+ },
428
+ is(node) {
429
+ return node?.type === 'mcdoc:type/reference';
430
+ },
431
+ });
432
+ export const TypeParamBlockNode = Object.freeze({
433
+ destruct(node) {
434
+ return {
435
+ params: node.children.filter(TypeParamNode.is),
436
+ };
437
+ },
198
438
  is(node) {
199
439
  return node?.type === 'mcdoc:type_param_block';
200
440
  },
201
441
  });
202
- exports.TypeParamNode = Object.freeze({
442
+ export const TypeParamNode = Object.freeze({
443
+ destruct(node) {
444
+ return {
445
+ // constraint: node.children.find(TypeNode.is),
446
+ identifier: node.children.find(IdentifierNode.is),
447
+ };
448
+ },
203
449
  is(node) {
204
450
  return node?.type === 'mcdoc:type_param';
205
451
  },
206
452
  });
207
- exports.PathNode = Object.freeze({
453
+ export const PathNode = Object.freeze({
454
+ destruct(node) {
455
+ const lastChild = atArray(node?.children, -1);
456
+ return {
457
+ children: node?.children ?? [],
458
+ isAbsolute: node?.isAbsolute,
459
+ lastIdentifier: IdentifierNode.is(lastChild) ? lastChild : undefined,
460
+ };
461
+ },
208
462
  is(node) {
209
463
  return node?.type === 'mcdoc:path';
210
464
  },
211
465
  });
212
- exports.StructBlockNode = Object.freeze({
466
+ export const StructBlockNode = Object.freeze({
467
+ destruct(node) {
468
+ return {
469
+ fields: node.children.filter(StructFieldNode.is),
470
+ };
471
+ },
213
472
  is(node) {
214
473
  return node?.type === 'mcdoc:struct/block';
215
474
  },
216
475
  });
217
- exports.StructFieldNode = Object.freeze({
476
+ export const StructFieldNode = Object.freeze({
218
477
  is(node) {
219
- return exports.StructPairFieldNode.is(node) || exports.StructSpreadFieldNode.is(node);
478
+ return StructPairFieldNode.is(node) || StructSpreadFieldNode.is(node);
220
479
  },
221
480
  });
222
- exports.StructPairFieldNode = Object.freeze({
481
+ export const StructPairFieldNode = Object.freeze({
482
+ destruct(node) {
483
+ return {
484
+ attributes: node.children.filter(AttributeNode.is),
485
+ key: node.children.find(StructKeyNode.is),
486
+ type: node.children.find(TypeNode.is),
487
+ isOptional: node.isOptional,
488
+ };
489
+ },
223
490
  is(node) {
224
491
  return node?.type === 'mcdoc:struct/field/pair';
225
492
  },
226
493
  });
227
- exports.StructKeyNode = Object.freeze({
494
+ export const StructKeyNode = Object.freeze({
228
495
  is(node) {
229
- return core_1.StringNode.is(node) || exports.IdentifierNode.is(node) || exports.StructMapKeyNode.is(node);
496
+ return StringNode.is(node) || IdentifierNode.is(node) || StructMapKeyNode.is(node);
230
497
  },
231
498
  });
232
- exports.StructMapKeyNode = Object.freeze({
499
+ export const StructMapKeyNode = Object.freeze({
500
+ destruct(node) {
501
+ return {
502
+ type: node.children.find(TypeNode.is),
503
+ };
504
+ },
233
505
  is(node) {
234
506
  return node?.type === 'mcdoc:struct/map_key';
235
507
  },
236
508
  });
237
- exports.StructSpreadFieldNode = Object.freeze({
509
+ export const StructSpreadFieldNode = Object.freeze({
510
+ destruct(node) {
511
+ return {
512
+ attributes: node.children.filter(AttributeNode.is),
513
+ type: node.children.find(TypeNode.is),
514
+ };
515
+ },
238
516
  is(node) {
239
517
  return node?.type === 'mcdoc:struct/field/spread';
240
518
  },
241
519
  });
242
- exports.DispatcherTypeNode = Object.freeze({
520
+ export const DispatcherTypeNode = Object.freeze({
521
+ destruct(node) {
522
+ return {
523
+ location: node.children.find(ResourceLocationNode.is),
524
+ index: node.children.find(IndexBodyNode.is),
525
+ };
526
+ },
243
527
  is(node) {
244
528
  return node?.type === 'mcdoc:type/dispatcher';
245
529
  },
246
530
  });
247
- exports.UnionTypeNode = Object.freeze({
531
+ export const UnionTypeNode = Object.freeze({
532
+ destruct(node) {
533
+ return {
534
+ members: node.children.filter(TypeNode.is),
535
+ };
536
+ },
248
537
  is(node) {
249
538
  return node?.type === 'mcdoc:type/union';
250
539
  },
251
540
  });
252
- exports.InjectionNode = Object.freeze({
541
+ export const InjectionNode = Object.freeze({
542
+ destruct(node) {
543
+ return {
544
+ injection: node.children.find(InjectionContentNode.is),
545
+ };
546
+ },
253
547
  is(node) {
254
548
  return node?.type === 'mcdoc:injection';
255
549
  },
256
550
  });
257
- exports.EnumInjectionNode = Object.freeze({
551
+ export const InjectionContentNode = Object.freeze({
552
+ is(node) {
553
+ return EnumInjectionNode.is(node) || StructInjectionNode.is(node);
554
+ },
555
+ });
556
+ export const EnumInjectionNode = Object.freeze({
258
557
  is(node) {
259
558
  return node?.type === 'mcdoc:injection/enum';
260
559
  },
261
560
  });
262
- exports.StructInjectionNode = Object.freeze({
561
+ export const StructInjectionNode = Object.freeze({
263
562
  is(node) {
264
563
  return node?.type === 'mcdoc:injection/struct';
265
564
  },
266
565
  });
267
- exports.TypeAliasNode = Object.freeze({
566
+ export const TypeAliasNode = Object.freeze({
567
+ destruct(node) {
568
+ return {
569
+ docComments: node.children.find(DocCommentsNode.is),
570
+ identifier: node.children.find(IdentifierNode.is),
571
+ typeParams: node.children.find(TypeParamBlockNode.is),
572
+ rhs: node.children.find(TypeNode.is),
573
+ };
574
+ },
268
575
  is(node) {
269
576
  return node?.type === 'mcdoc:type_alias';
270
577
  },
271
578
  });
272
- exports.UseStatementNode = Object.freeze({
579
+ export const UseStatementNode = Object.freeze({
580
+ destruct(node) {
581
+ return {
582
+ binding: node.children.find(IdentifierNode.is),
583
+ path: node.children.find(PathNode.is),
584
+ };
585
+ },
273
586
  is(node) {
274
587
  return node?.type === 'mcdoc:use_statement';
275
588
  },