@spyglassmc/mcdoc 0.3.8 → 0.3.10

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