@spyglassmc/mcdoc 0.3.7 → 0.3.9

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/type/index.js CHANGED
@@ -1,66 +1,298 @@
1
1
  import { Arrayable, Dev } from '@spyglassmc/core';
2
- import { localeQuote, localize } from '@spyglassmc/locales';
3
- import { getRangeDelimiter } from '../node/index.js';
4
- export const StaticIndexKeywords = Object.freeze([
5
- 'fallback',
6
- 'none',
7
- 'unknown',
8
- 'spawnitem',
9
- 'blockitem',
10
- ]);
11
- export const EmptyUnion = Object.freeze({
12
- kind: 'union',
13
- members: [],
14
- });
2
+ import { getRangeDelimiter, RangeKind } from '../node/index.js';
3
+ export var Attributes;
4
+ (function (Attributes) {
5
+ function equals(a, b) {
6
+ if (a?.length !== b?.length) {
7
+ return false;
8
+ }
9
+ if (!a || !b) {
10
+ return true;
11
+ }
12
+ for (let i = 0; i < a.length; i++) {
13
+ if (!Attribute.equals(a[i], b[i])) {
14
+ return false;
15
+ }
16
+ }
17
+ return true;
18
+ }
19
+ Attributes.equals = equals;
20
+ })(Attributes || (Attributes = {}));
21
+ export var Attribute;
22
+ (function (Attribute) {
23
+ function equals(a, b) {
24
+ if (a.name !== b.name) {
25
+ return false;
26
+ }
27
+ if (a.value && b.value) {
28
+ return AttributeValue.equals(a.value, b.value);
29
+ }
30
+ return a.value === b.value;
31
+ }
32
+ Attribute.equals = equals;
33
+ })(Attribute || (Attribute = {}));
34
+ export var AttributeValue;
35
+ (function (AttributeValue) {
36
+ function equals(a, b) {
37
+ if (a.kind !== b.kind) {
38
+ return false;
39
+ }
40
+ if (a.kind === 'tree') {
41
+ if (Object.keys(a.values).length !== Object.keys(b.values).length) {
42
+ return false;
43
+ }
44
+ for (const kvp of Object.entries(a.values)) {
45
+ const other = b.values[kvp[0]];
46
+ if (!other) {
47
+ return false;
48
+ }
49
+ if (!equals(kvp[1], other)) {
50
+ return false;
51
+ }
52
+ }
53
+ return true;
54
+ }
55
+ else {
56
+ return McdocType.equals(a, b);
57
+ }
58
+ }
59
+ AttributeValue.equals = equals;
60
+ })(AttributeValue || (AttributeValue = {}));
61
+ export var NumericRange;
62
+ (function (NumericRange) {
63
+ function isInRange(range, val) {
64
+ const { min = -Infinity, max = Infinity } = range;
65
+ if (RangeKind.isLeftExclusive(range.kind) ? val <= min : val < min) {
66
+ return false;
67
+ }
68
+ if (RangeKind.isRightExclusive(range.kind) ? val >= max : val > max) {
69
+ return false;
70
+ }
71
+ return true;
72
+ }
73
+ NumericRange.isInRange = isInRange;
74
+ function equals(a, b) {
75
+ return a.kind === b.kind
76
+ && a.min === b.min
77
+ && a.max === b.max;
78
+ }
79
+ NumericRange.equals = equals;
80
+ function intersect(a, b) {
81
+ const min = a.min !== undefined && b.min !== undefined
82
+ ? Math.max(a.min, b.min)
83
+ : a.min !== undefined
84
+ ? a.min
85
+ : b.min;
86
+ const max = a.max !== undefined && b.max !== undefined
87
+ ? Math.min(a.max, b.max)
88
+ : a.max !== undefined
89
+ ? a.max
90
+ : b.max;
91
+ let kind = 0b00;
92
+ if (min === a.min && RangeKind.isLeftExclusive(a.kind)) {
93
+ kind |= 0b10;
94
+ }
95
+ else if (min === b.min && RangeKind.isLeftExclusive(b.kind)) {
96
+ kind |= 0b10;
97
+ }
98
+ if (max === a.max && RangeKind.isRightExclusive(a.kind)) {
99
+ kind |= 0b01;
100
+ }
101
+ else if (max === b.max && RangeKind.isRightExclusive(b.kind)) {
102
+ kind |= 0b01;
103
+ }
104
+ return { kind: kind, min, max };
105
+ }
106
+ NumericRange.intersect = intersect;
107
+ function toString({ kind, min, max }) {
108
+ return min === max && kind === 0b00
109
+ ? min !== undefined ? `${min}` : getRangeDelimiter(kind)
110
+ : `${min ?? ''}${getRangeDelimiter(kind)}${max ?? ''}`;
111
+ }
112
+ NumericRange.toString = toString;
113
+ })(NumericRange || (NumericRange = {}));
114
+ export const StaticIndexKeywords = Object.freeze(['fallback', 'none', 'unknown', 'spawnitem', 'blockitem']);
115
+ export var ParallelIndices;
116
+ (function (ParallelIndices) {
117
+ function equals(a, b) {
118
+ if (a.length !== b.length) {
119
+ return false;
120
+ }
121
+ for (let i = 0; i < a.length; i++) {
122
+ const first = a[i];
123
+ const second = b[i];
124
+ if (first.kind !== second.kind) {
125
+ return false;
126
+ }
127
+ if (first.kind === 'static') {
128
+ return first.value !== second.value;
129
+ }
130
+ if (first.accessor.length !== second.accessor.length) {
131
+ return false;
132
+ }
133
+ for (let j = 0; j < first.accessor.length; j++) {
134
+ const firstAcc = first.accessor[j];
135
+ const secondAcc = second.accessor[j];
136
+ if (typeof firstAcc === 'string' || typeof secondAcc === 'string') {
137
+ if (firstAcc !== secondAcc) {
138
+ return false;
139
+ }
140
+ }
141
+ else if (firstAcc.keyword !== secondAcc.keyword) {
142
+ return false;
143
+ }
144
+ }
145
+ }
146
+ return true;
147
+ }
148
+ ParallelIndices.equals = equals;
149
+ })(ParallelIndices || (ParallelIndices = {}));
150
+ export const EmptyUnion = Object.freeze({ kind: 'union', members: [] });
15
151
  export function createEmptyUnion(attributes) {
16
152
  return {
17
153
  ...EmptyUnion,
18
154
  // attributes,
19
155
  };
20
156
  }
21
- export const LiteralNumberSuffixes = Object.freeze([
22
- 'b',
23
- 's',
24
- 'l',
25
- 'f',
26
- 'd',
27
- ]);
28
- export const LiteralNumberCaseInsensitiveSuffixes = Object.freeze([
29
- ...LiteralNumberSuffixes,
30
- 'B',
31
- 'S',
32
- 'L',
33
- 'F',
34
- 'D',
35
- ]);
36
- export const NumericTypeIntKinds = Object.freeze([
37
- 'byte',
38
- 'short',
39
- 'int',
40
- 'long',
41
- ]);
157
+ export const NumericTypeIntKinds = Object.freeze(['byte', 'short', 'int', 'long']);
42
158
  export const NumericTypeFloatKinds = Object.freeze(['float', 'double']);
43
- export const NumericTypeKinds = Object.freeze([
44
- ...NumericTypeIntKinds,
45
- ...NumericTypeFloatKinds,
46
- ]);
47
- export const PrimitiveArrayValueKinds = Object.freeze([
48
- 'byte',
49
- 'int',
50
- 'long',
51
- ]);
159
+ export const NumericTypeKinds = Object.freeze([...NumericTypeIntKinds, ...NumericTypeFloatKinds]);
160
+ export const PrimitiveArrayValueKinds = Object.freeze(['byte', 'int', 'long']);
52
161
  export const PrimitiveArrayKinds = Object.freeze(PrimitiveArrayValueKinds.map((kind) => `${kind}_array`));
53
162
  export var McdocType;
54
163
  (function (McdocType) {
164
+ function equals(a, b) {
165
+ if (a.kind !== b.kind) {
166
+ return false;
167
+ }
168
+ if (!Attributes.equals(a.attributes, b.attributes)) {
169
+ return false;
170
+ }
171
+ switch (a.kind) {
172
+ case 'literal':
173
+ return a.value.kind === b.value.kind
174
+ && a.value.value === b.value.value;
175
+ case 'byte':
176
+ case 'short':
177
+ case 'int':
178
+ case 'long':
179
+ case 'float':
180
+ case 'double':
181
+ return a.valueRange === b.valueRange;
182
+ case 'string':
183
+ return a.lengthRange === b.lengthRange;
184
+ case 'byte_array':
185
+ case 'int_array':
186
+ case 'long_array':
187
+ return a.lengthRange === b.lengthRange
188
+ && a.valueRange === b.valueRange;
189
+ case 'list':
190
+ return a.lengthRange === b.lengthRange
191
+ && equals(a.item, b.item);
192
+ case 'tuple':
193
+ if (a.items.length !== b.items.length) {
194
+ return false;
195
+ }
196
+ for (let i = 0; i < a.items.length; i++) {
197
+ if (!equals(a.items[i], b.items[i])) {
198
+ return false;
199
+ }
200
+ }
201
+ return true;
202
+ case 'struct':
203
+ return a.fields.length === b.fields.length && !a.fields.some(f => {
204
+ if (f.kind === 'pair') {
205
+ return !b.fields.some(of => of.kind === 'pair'
206
+ && f.optional === of.optional
207
+ && f.deprecated === of.deprecated
208
+ && Attributes.equals(f.attributes, of.attributes)
209
+ && (typeof f.key === 'string' || typeof of.key === 'string'
210
+ ? f.key === of.key
211
+ : equals(f.key, of.key))
212
+ && equals(f.type, of.type));
213
+ }
214
+ return !b.fields.some(of => of.kind === 'spread'
215
+ && Attributes.equals(f.attributes, of.attributes)
216
+ && equals(f.type, of.type));
217
+ });
218
+ case 'union':
219
+ if (a.members.length !== b.members.length) {
220
+ return false;
221
+ }
222
+ for (let i = 0; i < a.members.length; i++) {
223
+ if (!equals(a.members[i], b.members[i])) {
224
+ return false;
225
+ }
226
+ }
227
+ return true;
228
+ case 'enum':
229
+ if (a.enumKind !== b.enumKind
230
+ || a.values.length !== b.values.length) {
231
+ return false;
232
+ }
233
+ for (let i = 0; i < a.values.length; i++) {
234
+ const first = a.values[i];
235
+ const second = b.values[i];
236
+ if (first.identifier !== second.identifier || first.value !== second.value
237
+ || !Attributes.equals(first.attributes, second.attributes)) {
238
+ return false;
239
+ }
240
+ }
241
+ return true;
242
+ case 'reference':
243
+ return a.path === b.path;
244
+ case 'template':
245
+ if (a.typeParams.length !== b.typeParams.length) {
246
+ return false;
247
+ }
248
+ for (let i = 0; i < a.typeParams.length; i++) {
249
+ if (a.typeParams[i].path !== b.typeParams[i].path) {
250
+ return false;
251
+ }
252
+ }
253
+ return equals(a.child, b.child);
254
+ case 'concrete':
255
+ if (a.typeArgs.length !== b.typeArgs.length) {
256
+ return false;
257
+ }
258
+ for (let i = 0; i < a.typeArgs.length; i++) {
259
+ if (!equals(a.typeArgs[i], b.typeArgs[i])) {
260
+ return false;
261
+ }
262
+ }
263
+ return equals(a.child, b.child);
264
+ case 'indexed':
265
+ if (ParallelIndices.equals(a.parallelIndices, b.parallelIndices)) {
266
+ return false;
267
+ }
268
+ return equals(a.child, b.child);
269
+ case 'dispatcher':
270
+ if (a.registry !== b.registry) {
271
+ return false;
272
+ }
273
+ return ParallelIndices.equals(a.parallelIndices, b.parallelIndices);
274
+ case 'mapped':
275
+ if (Object.keys(a.mapping).length !== Object.keys(b.mapping).length) {
276
+ return false;
277
+ }
278
+ for (const kvp of Object.entries(a.mapping)) {
279
+ const other = b.mapping[kvp[0]];
280
+ if (!other) {
281
+ return false;
282
+ }
283
+ if (!equals(kvp[1], other)) {
284
+ return false;
285
+ }
286
+ }
287
+ return equals(a.child, b.child);
288
+ default:
289
+ return true;
290
+ }
291
+ }
292
+ McdocType.equals = equals;
55
293
  function toString(type) {
56
294
  const rangeToString = (range) => {
57
- if (!range) {
58
- return '';
59
- }
60
- const { kind, min, max } = range;
61
- return min === max
62
- ? ` @ ${min}`
63
- : ` @ ${min ?? ''}${getRangeDelimiter(kind)}${max ?? ''}`;
295
+ return range ? ` @ ${NumericRange.toString(range)}` : '';
64
296
  };
65
297
  const indicesToString = (indices) => {
66
298
  const strings = [];
@@ -71,9 +303,7 @@ export var McdocType;
71
303
  else {
72
304
  strings.push(index.kind === 'static'
73
305
  ? `[${index.value}]`
74
- : `[[${index.accessor
75
- .map((v) => (typeof v === 'string' ? v : v.keyword))
76
- .join('.')}]]`);
306
+ : `[[${index.accessor.map((v) => (typeof v === 'string' ? v : v.keyword)).join('.')}]]`);
77
307
  }
78
308
  }
79
309
  return `[${strings.join(', ')}]`;
@@ -81,405 +311,94 @@ export var McdocType;
81
311
  if (type === undefined) {
82
312
  return '<unknown>';
83
313
  }
314
+ let attributesString = '';
315
+ if (type.attributes?.length) {
316
+ for (const attribute of type.attributes) {
317
+ attributesString += `#[${attribute.name}${attribute.value ? '=<value ...>' : ''}] `;
318
+ }
319
+ }
320
+ let typeString;
84
321
  switch (type.kind) {
85
322
  case 'any':
86
323
  case 'boolean':
87
- return type.kind;
88
- case 'attributed':
89
- return `#[${type.attribute.name}${type.attribute.value ? '=<value ...>' : ''}] ${toString(type.child)}`;
324
+ typeString = type.kind;
325
+ break;
90
326
  case 'byte':
91
- return `byte${rangeToString(type.valueRange)}`;
327
+ typeString = `byte${rangeToString(type.valueRange)}`;
328
+ break;
92
329
  case 'byte_array':
93
- return `byte${rangeToString(type.valueRange)}[]${rangeToString(type.lengthRange)}`;
330
+ typeString = `byte${rangeToString(type.valueRange)}[]${rangeToString(type.lengthRange)}`;
331
+ break;
94
332
  case 'concrete':
95
- return `${toString(type.child)}${type.typeArgs.length
96
- ? `<${type.typeArgs.map(toString).join(', ')}>`
97
- : ''}`;
333
+ typeString = `${toString(type.child)}${type.typeArgs.length ? `<${type.typeArgs.map(toString).join(', ')}>` : ''}`;
334
+ break;
98
335
  case 'dispatcher':
99
- return `${type.registry ?? 'spyglass:unknown'}[${indicesToString(type.parallelIndices)}]`;
336
+ typeString = `${type.registry ?? 'spyglass:unknown'}[${indicesToString(type.parallelIndices)}]`;
337
+ break;
100
338
  case 'double':
101
- return `double${rangeToString(type.valueRange)}`;
339
+ typeString = `double${rangeToString(type.valueRange)}`;
340
+ break;
102
341
  case 'enum':
103
- return '<enum ...>';
342
+ typeString = '<enum ...>';
343
+ break;
104
344
  case 'float':
105
- return `float${rangeToString(type.valueRange)}`;
345
+ typeString = `float${rangeToString(type.valueRange)}`;
346
+ break;
106
347
  case 'indexed':
107
- return `${toString(type.child)}${indicesToString(type.parallelIndices)}`;
348
+ typeString = `${toString(type.child)}${indicesToString(type.parallelIndices)}`;
349
+ break;
108
350
  case 'int':
109
- return `int${rangeToString(type.valueRange)}`;
351
+ typeString = `int${rangeToString(type.valueRange)}`;
352
+ break;
110
353
  case 'int_array':
111
- return `int${rangeToString(type.valueRange)}[]${rangeToString(type.lengthRange)}`;
354
+ typeString = `int${rangeToString(type.valueRange)}[]${rangeToString(type.lengthRange)}`;
355
+ break;
112
356
  case 'list':
113
- return `[${toString(type.item)}]${rangeToString(type.lengthRange)}`;
357
+ typeString = `[${toString(type.item)}]${rangeToString(type.lengthRange)}`;
358
+ break;
114
359
  case 'literal':
115
- return `${type.value}`;
360
+ typeString = `${type.value.value}`;
361
+ break;
116
362
  case 'long':
117
- return `long${rangeToString(type.valueRange)}`;
363
+ typeString = `long${rangeToString(type.valueRange)}`;
364
+ break;
118
365
  case 'long_array':
119
- return `long${rangeToString(type.valueRange)}[]${rangeToString(type.lengthRange)}`;
366
+ typeString = `long${rangeToString(type.valueRange)}[]${rangeToString(type.lengthRange)}`;
367
+ break;
368
+ case 'mapped':
369
+ typeString = toString(type.child);
370
+ break;
120
371
  case 'reference':
121
- return type.path ?? '<unknown_reference>';
372
+ typeString = type.path ?? '<unknown_reference>';
373
+ break;
122
374
  case 'short':
123
- return `short${rangeToString(type.valueRange)}`;
375
+ typeString = `short${rangeToString(type.valueRange)}`;
376
+ break;
124
377
  case 'string':
125
- return `string${rangeToString(type.lengthRange)}`;
378
+ typeString = `string${rangeToString(type.lengthRange)}`;
379
+ break;
126
380
  case 'struct':
127
- return '<struct ...>';
381
+ typeString = '<struct ...>';
382
+ break;
128
383
  case 'template':
129
- return `${toString(type.child)}${type.typeParams.length
384
+ typeString = `${toString(type.child)}${type.typeParams.length
130
385
  ? `<${type.typeParams.map((v) => `?${v.path}`).join(', ')}>`
131
386
  : ''}`;
387
+ break;
132
388
  case 'tuple':
133
- return `[${type.items.map((v) => toString(v)).join(',')}${type.items.length === 1 ? ',' : ''}]`;
389
+ typeString = `[${type.items.map((v) => toString(v)).join(',')}${type.items.length === 1 ? ',' : ''}]`;
390
+ break;
134
391
  case 'union':
135
- return `(${type.members.map(toString).join(' | ')})`;
392
+ typeString = `(${type.members.map(toString).join(' | ')})`;
393
+ break;
136
394
  case 'unsafe':
137
- return 'unsafe';
395
+ typeString = 'unsafe';
396
+ break;
138
397
  default:
139
- return Dev.assertNever(type);
398
+ Dev.assertNever(type);
140
399
  }
400
+ return attributesString + typeString;
141
401
  }
142
402
  McdocType.toString = toString;
143
403
  })(McdocType || (McdocType = {}));
144
- var CheckResult;
145
- (function (CheckResult) {
146
- CheckResult[CheckResult["Nah"] = 0] = "Nah";
147
- CheckResult[CheckResult["Assignable"] = 1] = "Assignable";
148
- CheckResult[CheckResult["StrictlyAssignable"] = 3] = "StrictlyAssignable";
149
- })(CheckResult || (CheckResult = {}));
150
- const areRangesMatch = (s, t) => {
151
- if (!t) {
152
- return true;
153
- }
154
- if (!s) {
155
- return false;
156
- }
157
- const { min: sMin, max: sMax } = s;
158
- const { min: tMin, max: tMax } = t;
159
- return ((tMin === undefined || (sMin !== undefined && sMin >= tMin)) &&
160
- (tMax === undefined || (sMax !== undefined && sMax <= tMax)));
161
- };
162
- export const flattenUnionType = (union) => {
163
- const set = new Set();
164
- const add = (data) => {
165
- for (const existingMember of set) {
166
- if ((check(data, existingMember) & CheckResult.StrictlyAssignable) ===
167
- CheckResult.StrictlyAssignable) {
168
- return;
169
- }
170
- if ((check(existingMember, data) & CheckResult.StrictlyAssignable) ===
171
- CheckResult.StrictlyAssignable) {
172
- set.delete(existingMember);
173
- }
174
- }
175
- set.add(data);
176
- };
177
- for (const member of union.members) {
178
- if (member.kind === 'union') {
179
- flattenUnionType(member).members.forEach(add);
180
- }
181
- else {
182
- add(member);
183
- }
184
- }
185
- return {
186
- kind: 'union',
187
- members: [...set],
188
- };
189
- };
190
- export const unionTypes = (a, b) => {
191
- if ((check(a, b) & CheckResult.StrictlyAssignable) ===
192
- CheckResult.StrictlyAssignable) {
193
- return b;
194
- }
195
- if ((check(b, a) & CheckResult.StrictlyAssignable) ===
196
- CheckResult.StrictlyAssignable) {
197
- return a;
198
- }
199
- const ans = {
200
- kind: 'union',
201
- members: [
202
- ...(a.kind === 'union' ? a.members : [a]),
203
- ...(b.kind === 'union' ? b.members : [b]),
204
- ],
205
- };
206
- return ans;
207
- };
208
- export const simplifyUnionType = (union) => {
209
- union = flattenUnionType(union);
210
- if (union.members.length === 1) {
211
- return union.members[0];
212
- }
213
- return union;
214
- };
215
- export const simplifyListType = (list) => ({
216
- kind: 'list',
217
- item: simplifyType(list.item),
218
- ...(list.lengthRange ? { lengthRange: { ...list.lengthRange } } : {}),
219
- });
220
- export const simplifyType = (data) => {
221
- if (data.kind === 'union') {
222
- data = simplifyUnionType(data);
223
- }
224
- else if (data.kind === 'list') {
225
- data = simplifyListType(data);
226
- }
227
- return data;
228
- };
229
- const check = (s, t, errors = []) => {
230
- const strictlyAssignableIfTrue = (value) => value ? CheckResult.StrictlyAssignable : CheckResult.Nah;
231
- const assignableIfTrue = (value) => value ? CheckResult.Assignable : CheckResult.Nah;
232
- let ans;
233
- s = simplifyType(s);
234
- t = simplifyType(t);
235
- if (s.kind === 'any' || s.kind === 'reference' || t.kind === 'reference') {
236
- // Reference types are treated as any for now.
237
- ans = CheckResult.Assignable;
238
- }
239
- else if (t.kind === 'any') {
240
- ans = CheckResult.StrictlyAssignable;
241
- }
242
- else if (s.kind === 'union') {
243
- ans = assignableIfTrue(s.members.every((v) => check(v, t, errors)));
244
- }
245
- else if (t.kind === 'union') {
246
- ans = assignableIfTrue(t.members.some((v) => check(s, v)));
247
- }
248
- else if (s.kind === 'boolean') {
249
- ans = strictlyAssignableIfTrue(t.kind === 'boolean' || t.kind === 'byte');
250
- }
251
- else if (s.kind === 'byte') {
252
- if (t.kind === 'boolean') {
253
- ans = check(s, { kind: 'byte', valueRange: { kind: 0b00, min: 0, max: 1 } }, errors);
254
- }
255
- else if (t.kind === 'byte') {
256
- ans = strictlyAssignableIfTrue(areRangesMatch(s.valueRange, t.valueRange));
257
- }
258
- else if (t.kind === 'enum') {
259
- ans = assignableIfTrue(!t.enumKind || t.enumKind === 'byte');
260
- }
261
- else {
262
- ans = CheckResult.Nah;
263
- }
264
- }
265
- else if (s.kind === 'byte_array' ||
266
- s.kind === 'int_array' ||
267
- s.kind === 'long_array') {
268
- ans = strictlyAssignableIfTrue(t.kind === s.kind &&
269
- areRangesMatch(s.lengthRange, t.lengthRange) &&
270
- areRangesMatch(s.valueRange, t.valueRange));
271
- }
272
- else if (s.kind === 'struct' || s.kind === 'dispatcher') {
273
- ans = assignableIfTrue(t.kind === 'struct' || t.kind === 'dispatcher');
274
- }
275
- else if (s.kind === 'enum') {
276
- ans = assignableIfTrue((t.kind === 'byte' ||
277
- t.kind === 'float' ||
278
- t.kind === 'double' ||
279
- t.kind === 'int' ||
280
- t.kind === 'long' ||
281
- t.kind === 'short' ||
282
- t.kind === 'string') &&
283
- (!s.enumKind || s.enumKind === t.kind));
284
- }
285
- else if (s.kind === 'float' ||
286
- s.kind === 'double' ||
287
- s.kind === 'int' ||
288
- s.kind === 'long' ||
289
- s.kind === 'short') {
290
- if (t.kind === s.kind) {
291
- ans = strictlyAssignableIfTrue(areRangesMatch(s.valueRange, t.valueRange));
292
- }
293
- else if (t.kind === 'enum') {
294
- ans = assignableIfTrue(!t.enumKind || t.enumKind === s.kind);
295
- }
296
- else {
297
- ans = CheckResult.Nah;
298
- }
299
- }
300
- else if (s.kind === 'list') {
301
- if (t.kind === 'list' && areRangesMatch(s.lengthRange, t.lengthRange)) {
302
- ans = check(s.item, t.item, errors);
303
- }
304
- else {
305
- ans = CheckResult.Nah;
306
- }
307
- }
308
- else if (s.kind === 'string') {
309
- if (t.kind === 'string') {
310
- ans = CheckResult.StrictlyAssignable;
311
- }
312
- else {
313
- ans = assignableIfTrue(t.kind === 'enum' && (!t.enumKind || t.enumKind === 'string'));
314
- }
315
- }
316
- else {
317
- ans = CheckResult.Nah;
318
- }
319
- if (!ans) {
320
- errors.push(localize('mcdoc.checker.type-not-assignable', localeQuote(McdocType.toString(s)), localeQuote(McdocType.toString(t))));
321
- }
322
- return ans;
323
- };
324
- export const checkAssignability = ({ source, target, }) => {
325
- if (source === undefined || target === undefined) {
326
- return { isAssignable: true };
327
- }
328
- const errors = [];
329
- check(source, target, errors);
330
- return {
331
- isAssignable: errors.length === 0,
332
- ...(errors.length
333
- ? {
334
- errorMessage: errors
335
- .reverse()
336
- .map((m, i) => `${' '.repeat(i)}${m}`)
337
- .join('\n'),
338
- }
339
- : {}),
340
- };
341
- };
342
- export function resolveType(inputType, ctx, value) {
343
- const type = getTangibleType(inputType, ctx, value);
344
- const ans = (() => {
345
- if (type.kind === 'union') {
346
- return {
347
- kind: 'union',
348
- members: type.members.map((t) => resolveType(t, ctx, value)),
349
- // attributes: type.attributes,
350
- };
351
- }
352
- else {
353
- return {
354
- ...type,
355
- indices: undefined,
356
- };
357
- }
358
- })();
359
- // for (const parallelIndices of type.indices ?? []) {
360
- // ans = navigateParallelIndices(ans, parallelIndices, ctx, value)
361
- // }
362
- return ans;
363
- }
364
- function dispatchType(type, ctx) {
365
- throw '// TODO';
366
- }
367
- function dereferenceType(type, ctx) {
368
- throw '// TODO';
369
- }
370
- function getTangibleType(type, ctx, value) {
371
- let ans;
372
- if (type.kind === 'dispatcher') {
373
- const dispatchedType = dispatchType(type, ctx);
374
- return getTangibleType(dispatchedType, ctx, value);
375
- }
376
- else if (type.kind === 'reference') {
377
- const dereferencedType = dereferenceType(type, ctx);
378
- return getTangibleType(dereferencedType, ctx, value);
379
- }
380
- else if (type.kind === 'union') {
381
- ans = mapUnion(type, (t) => getTangibleType(t, ctx, value));
382
- }
383
- else {
384
- ans = type;
385
- }
386
- return ans;
387
- }
388
- function navigateParallelIndices(type, indices, ctx, value) {
389
- if (indices.length === 1) {
390
- return navigateIndex(type, indices[0], ctx, value);
391
- }
392
- else {
393
- return {
394
- kind: 'union',
395
- members: indices.map((i) => navigateIndex(type, i, ctx, value)),
396
- // attributes: type.attributes,
397
- };
398
- }
399
- }
400
- function navigateIndex(type, index, ctx, value) {
401
- if (type.kind === 'struct') {
402
- const key = index.kind === 'static'
403
- ? typeof index.value === 'string'
404
- ? index.value
405
- : undefined // Special static indices have no meaning on structs.
406
- : resolveDynamicIndex(index, value);
407
- if (key === undefined) {
408
- // return createEmptyUnion(type.attributes)
409
- return createEmptyUnion();
410
- }
411
- const flatStruct = flattenStruct(type, ctx, value);
412
- return resolveType(flatStruct.fields[key], ctx, value);
413
- }
414
- else if (type.kind === 'union') {
415
- return mapUnion(type, (t) => navigateIndex(t, index, ctx, value));
416
- }
417
- else {
418
- // return createEmptyUnion(type.attributes)
419
- return createEmptyUnion();
420
- }
421
- }
422
- function resolveDynamicIndex(index, value) {
423
- for (const key of index.accessor) {
424
- if (value === undefined) {
425
- break;
426
- }
427
- if (typeof key === 'string') {
428
- value = value.getValue(key);
429
- }
430
- else if (key.keyword === 'key') {
431
- value = value.getKeyOnParent();
432
- }
433
- else if (key.keyword === 'parent') {
434
- value = value.getParent();
435
- }
436
- }
437
- return value?.asString();
438
- }
439
- function mapUnion(type, mapper) {
440
- const ans = {
441
- kind: 'union',
442
- members: type.members.map(mapper),
443
- // attributes: type.attributes,
444
- // indices: type.indices,
445
- };
446
- return ans;
447
- }
448
- function flattenStruct(type, ctx, value) {
449
- const ans = {
450
- kind: 'flat_struct',
451
- fields: Object.create(null),
452
- // attributes: type.attributes,
453
- // indices: type.indices,
454
- };
455
- for (const field of type.fields) {
456
- if (field.kind === 'spread') {
457
- const target = resolveType(field.type, ctx, value);
458
- // addAttributes(ans, ...target.attributes ?? [])
459
- if (target.kind === 'struct') {
460
- const flatTarget = flattenStruct(target, ctx, value);
461
- for (const [key, value] of Object.entries(flatTarget)) {
462
- ans.fields[key] = value;
463
- }
464
- }
465
- }
466
- else {
467
- if (typeof field.key === 'string') {
468
- ans.fields[field.key] = field.type;
469
- }
470
- else {
471
- // TODO: Handle map keys
472
- }
473
- }
474
- }
475
- return ans;
476
- }
477
- function addAttributes(type, ...attributes) {
478
- for (const attr of attributes) {
479
- // type.attributes ??= []
480
- // if (!type.attributes.some(a => a.name === attr.name)) {
481
- // type.attributes.push(attr)
482
- // }
483
- }
484
- }
485
404
  //# sourceMappingURL=index.js.map