@spyglassmc/mcdoc 0.3.50 → 0.3.52

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.
@@ -1,4 +1,4 @@
1
- import { AsyncBinder, atArray, Dev, ErrorSeverity, FloatNode, IntegerNode, LongNode, Range, ResourceLocationNode, StringNode, SymbolUtil, traversePreOrder, } from '@spyglassmc/core';
1
+ import { AsyncBinder, Dev, ErrorSeverity, FloatNode, IntegerNode, LongNode, Range, ResourceLocationNode, StringNode, SymbolUtil, traversePreOrder, } from '@spyglassmc/core';
2
2
  import { localeQuote, localize } from '@spyglassmc/locales';
3
3
  import { AttributeNode, AttributeTreeNamedValuesNode, AttributeTreeNode, AttributeTreePosValuesNode, DispatcherTypeNode, DispatchStatementNode, DocCommentsNode, DynamicIndexNode, EnumBlockNode, EnumFieldNode, EnumInjectionNode, EnumNode, FloatRangeNode, IndexBodyNode, InjectionNode, IntRangeNode, ListTypeNode, LiteralNode, LiteralTypeNode, LongRangeNode, NumericTypeNode, PathNode, PrimitiveArrayTypeNode, ReferenceTypeNode, StaticIndexNode, StringTypeNode, StructBlockNode, StructMapKeyNode, StructNode, StructPairFieldNode, StructSpreadFieldNode, TopLevelNode, TupleTypeNode, TypeAliasNode, TypeArgBlockNode, TypeBaseNode, TypedNumberNode, TypeParamBlockNode, TypeParamNode, UnionTypeNode, UseStatementNode, } from '../node/index.js';
4
4
  var ModuleSymbolData;
@@ -288,7 +288,7 @@ async function bindPath(node, ctx) {
288
288
  },
289
289
  })).else(() => {
290
290
  if (indexRight === 0) {
291
- ctx.err.report(localize('mcdoc.binder.path.unknown-identifier', localeQuote(atArray(identifiers, -1)), localeQuote(pathArrayToString(identifiers.slice(0, -1)))), node, ErrorSeverity.Warning);
291
+ ctx.err.report(localize('mcdoc.binder.path.unknown-identifier', localeQuote(identifiers.at(-1)), localeQuote(pathArrayToString(identifiers.slice(0, -1)))), node, ErrorSeverity.Warning);
292
292
  }
293
293
  });
294
294
  }
@@ -413,7 +413,7 @@ function* resolvePathByStep(path, ctx, options = {}) {
413
413
  }
414
414
  }
415
415
  function resolvePath(path, ctx, options = {}) {
416
- return atArray([...resolvePathByStep(path, ctx, options)], -1)?.identifiers;
416
+ return [...resolvePathByStep(path, ctx, options)].at(-1)?.identifiers;
417
417
  }
418
418
  function identifierToUri(module, ctx) {
419
419
  return ctx.symbols.global.mcdoc?.[module]?.definition?.[0]?.uri;
@@ -284,7 +284,7 @@ export interface EnumNode extends TypeBaseNode<DocCommentsNode | LiteralNode | I
284
284
  }
285
285
  export type EnumKind = typeof EnumNode.Kinds extends Set<infer V> ? V : never;
286
286
  export declare namespace EnumNode {
287
- const Kinds: Set<"string" | "long" | "float" | "byte" | "short" | "int" | "double">;
287
+ const Kinds: Set<"byte" | "double" | "float" | "int" | "long" | "short" | "string">;
288
288
  function destruct(node: EnumNode): {
289
289
  block: EnumBlockNode;
290
290
  docComments?: DocCommentsNode;
package/lib/node/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { atArray, CommentNode, FloatNode, IntegerNode, LongNode, ResourceLocationNode, StringNode, } from '@spyglassmc/core';
1
+ import { CommentNode, FloatNode, IntegerNode, LongNode, ResourceLocationNode, StringNode, } from '@spyglassmc/core';
2
2
  export var ModuleNode;
3
3
  (function (ModuleNode) {
4
4
  function is(node) {
@@ -581,7 +581,7 @@ export var TypeParamNode;
581
581
  export var PathNode;
582
582
  (function (PathNode) {
583
583
  function destruct(node) {
584
- const lastChild = atArray(node?.children, -1);
584
+ const lastChild = node?.children.at(-1);
585
585
  return {
586
586
  children: node?.children ?? [],
587
587
  isAbsolute: node?.isAbsolute,
@@ -12,7 +12,7 @@ export interface RuntimePair<T> {
12
12
  key: RuntimeNode<T>;
13
13
  possibleValues: RuntimeNode<T>[];
14
14
  }
15
- export type NodeEquivalenceChecker = (inferredNode: Exclude<SimplifiedMcdocTypeNoUnion, LiteralType | EnumType>, definition: Exclude<SimplifiedMcdocTypeNoUnion, LiteralType | EnumType>) => boolean;
15
+ export type TypeConverter<T> = (node: T, definition: Exclude<SimplifiedMcdocTypeNoUnion, LiteralType | EnumType>) => SimplifiedMcdocTypeNoUnion | undefined;
16
16
  export type TypeInfoAttacher<T> = (node: T, definition: SimplifiedMcdocType, description?: string) => void;
17
17
  export type NodeAttacher<T> = (node: T, attacher: (node: core.AstNode) => void) => void;
18
18
  export type StringAttacher<T> = (node: T, attacher: (node: core.StringBaseNode) => void) => void;
@@ -21,7 +21,7 @@ export type ErrorReporter<T> = (error: McdocRuntimeError<T>) => void;
21
21
  export interface McdocCheckerContext<T> extends core.CheckerContext {
22
22
  allowMissingKeys: boolean;
23
23
  requireCanonical: boolean;
24
- isEquivalent: NodeEquivalenceChecker;
24
+ tryConvertTo: TypeConverter<T>;
25
25
  getChildren: ChildrenGetter<T>;
26
26
  reportError: ErrorReporter<T>;
27
27
  attachTypeInfo?: TypeInfoAttacher<T>;
@@ -5,7 +5,7 @@ export var McdocCheckerContext;
5
5
  ...ctx,
6
6
  allowMissingKeys: options.allowMissingKeys ?? false,
7
7
  requireCanonical: options.requireCanonical ?? false,
8
- isEquivalent: options.isEquivalent ?? (() => false),
8
+ tryConvertTo: options.tryConvertTo ?? (() => undefined),
9
9
  getChildren: options.getChildren ?? (() => []),
10
10
  reportError: options.reportError ?? (() => { }),
11
11
  attachTypeInfo: options.attachTypeInfo,
@@ -1,7 +1,7 @@
1
1
  import type { CheckerContext, FullResourceLocation } from '@spyglassmc/core';
2
2
  import type { EnumType, Index, KeywordType, ListType, LiteralType, LongType, NumericType, ParallelIndices, PrimitiveArrayType, StringType, StructType, StructTypePairField, TupleType, UnionType } from '../../type/index.js';
3
3
  import { McdocType } from '../../type/index.js';
4
- import type { NodeEquivalenceChecker, RuntimeNode } from './context.js';
4
+ import type { RuntimeNode, TypeConverter } from './context.js';
5
5
  import { McdocCheckerContext } from './context.js';
6
6
  import type { McdocRuntimeError } from './error.js';
7
7
  export * from './context.js';
@@ -16,7 +16,7 @@ export interface SimplifiedStructTypePairField extends StructTypePairField {
16
16
  }
17
17
  export declare function reference<T>(node: RuntimeNode<T>[], path: string, ctx: McdocCheckerContext<T>): void;
18
18
  export declare function dispatcher<T>(node: RuntimeNode<T>[], registry: FullResourceLocation, index: string | Index | ParallelIndices, ctx: McdocCheckerContext<T>): void;
19
- export declare function isAssignable(assignValue: McdocType, typeDef: McdocType, ctx: CheckerContext, isEquivalent?: NodeEquivalenceChecker): boolean;
19
+ export declare function isAssignable(assignValue: McdocType, typeDef: McdocType, ctx: CheckerContext, convert?: TypeConverter<McdocType>): boolean;
20
20
  export interface CheckerTreeNode<T> {
21
21
  parent: CheckerTreeRuntimeNode<T> | undefined;
22
22
  runtimeKey: RuntimeNode<T> | undefined;
@@ -18,7 +18,7 @@ export function dispatcher(node, registry, index, ctx) {
18
18
  : [index];
19
19
  typeDefinition(node, { kind: 'dispatcher', registry, parallelIndices }, ctx);
20
20
  }
21
- export function isAssignable(assignValue, typeDef, ctx, isEquivalent) {
21
+ export function isAssignable(assignValue, typeDef, ctx, convert) {
22
22
  if (assignValue.kind === 'literal' && typeDef.kind === 'literal'
23
23
  && assignValue.value.kind === typeDef.value.kind
24
24
  && !assignValue.attributes && !typeDef.attributes) {
@@ -26,18 +26,27 @@ export function isAssignable(assignValue, typeDef, ctx, isEquivalent) {
26
26
  }
27
27
  let ans = true;
28
28
  const newCtx = McdocCheckerContext.create(ctx, {
29
- isEquivalent,
29
+ tryConvertTo: convert,
30
30
  getChildren: (_, d) => {
31
31
  switch (d.kind) {
32
32
  case 'list':
33
33
  const vals = getPossibleTypes(d.item);
34
34
  return [vals.map(v => ({ originalNode: v, inferredType: v }))];
35
35
  case 'byte_array':
36
- return [[{ originalNode: { kind: 'byte' }, inferredType: { kind: 'byte' } }]];
36
+ return [[{
37
+ originalNode: { kind: 'byte' },
38
+ inferredType: { kind: 'byte' },
39
+ }]];
37
40
  case 'int_array':
38
- return [[{ originalNode: { kind: 'int' }, inferredType: { kind: 'int' } }]];
41
+ return [[{
42
+ originalNode: { kind: 'int' },
43
+ inferredType: { kind: 'int' },
44
+ }]];
39
45
  case 'long_array':
40
- return [[{ originalNode: { kind: 'long' }, inferredType: { kind: 'long' } }]];
46
+ return [[{
47
+ originalNode: { kind: 'long' },
48
+ inferredType: { kind: 'long' },
49
+ }]];
41
50
  case 'struct':
42
51
  return d.fields.map(f => {
43
52
  const vals = getPossibleTypes(f.type);
@@ -278,9 +287,13 @@ function checkShallowly(runtimeNode, simplifiedInferred, children, typeDef, ctx)
278
287
  return { childDefinitions, errors: [] };
279
288
  }
280
289
  const typeDefValueType = getValueType(typeDef);
281
- const runtimeValueType = getValueType(simplifiedInferred);
282
- if (runtimeValueType.kind !== typeDefValueType.kind
283
- && !ctx.isEquivalent(runtimeValueType, typeDefValueType)) {
290
+ let runtimeValueType = getValueType(simplifiedInferred);
291
+ if (runtimeValueType.kind !== typeDefValueType.kind) {
292
+ simplifiedInferred = ctx.tryConvertTo(runtimeNode.originalNode, typeDefValueType)
293
+ ?? simplifiedInferred;
294
+ runtimeValueType = getValueType(simplifiedInferred);
295
+ }
296
+ if (runtimeValueType.kind !== typeDefValueType.kind) {
284
297
  return {
285
298
  childDefinitions,
286
299
  errors: [{ kind: 'type_mismatch', node: runtimeNode, expected: [typeDef] }],
@@ -378,14 +391,22 @@ function checkShallowly(runtimeNode, simplifiedInferred, children, typeDef, ctx)
378
391
  }
379
392
  if (!foundMatch) {
380
393
  for (const kvp of otherKvps) {
381
- if (isAssignable(kvp.value.key.inferredType, pair.key, ctx, ctx.isEquivalent)) {
394
+ if (isAssignable(kvp.value.key.inferredType, pair.key, ctx, (type, target) => type === kvp.value.key.inferredType
395
+ ? ctx.tryConvertTo(kvp.value.key.originalNode, target)
396
+ : undefined)) {
382
397
  foundMatch = true;
383
398
  otherKvpMatches.push(kvp.index);
384
399
  }
385
400
  }
386
401
  for (const kvp of literalKvps.entries()) {
402
+ const literalType = {
403
+ kind: 'literal',
404
+ value: { kind: 'string', value: kvp[0] },
405
+ };
387
406
  if ((!kvp[1].definition || kvp[1].definition.keyType?.kind !== 'literal')
388
- && isAssignable({ kind: 'literal', value: { kind: 'string', value: kvp[0] } }, pair.key, ctx, ctx.isEquivalent)) {
407
+ && kvp[1].values.some(v => isAssignable(literalType, pair.key, ctx, (type, target) => type === literalType
408
+ ? ctx.tryConvertTo(v.pair.key.originalNode, target)
409
+ : undefined))) {
389
410
  foundMatch = true;
390
411
  kvp[1].definition = { keyType: pair.key, type: pair.type, desc: pair.desc };
391
412
  }
@@ -160,6 +160,9 @@ export interface LiteralLongNumberValue {
160
160
  kind: 'long';
161
161
  value: bigint;
162
162
  }
163
+ export declare namespace LiteralNumericValue {
164
+ function makeIfValid(kind: string, value: number | bigint, allowInt?: boolean, allowFloat?: boolean): LiteralNumericValue | LiteralLongNumberValue | undefined;
165
+ }
163
166
  export interface LiteralType extends McdocBaseType {
164
167
  kind: 'literal';
165
168
  value: LiteralValue;
package/lib/type/index.js CHANGED
@@ -150,6 +150,46 @@ export function createEmptyUnion(attributes) {
150
150
  // attributes,
151
151
  };
152
152
  }
153
+ export var LiteralNumericValue;
154
+ (function (LiteralNumericValue) {
155
+ function makeIfValid(kind, value, allowInt = true, allowFloat = true) {
156
+ value = Number(value);
157
+ switch (kind) {
158
+ case 'byte':
159
+ if (allowInt && value >= -128 && value < 128) {
160
+ return { kind: 'byte', value };
161
+ }
162
+ break;
163
+ case 'short':
164
+ if (allowInt && value >= -32768 && value < 32768) {
165
+ return { kind: 'short', value };
166
+ }
167
+ break;
168
+ case 'int':
169
+ if (allowInt && value >= -2147483648 && value < 2147483648) {
170
+ return { kind: 'int', value };
171
+ }
172
+ break;
173
+ case 'long':
174
+ if (allowInt && value >= -9223372036854775808n && value < 9223372036854775808n) {
175
+ return { kind: 'long', value: BigInt(value) };
176
+ }
177
+ break;
178
+ case 'float':
179
+ if (allowFloat) {
180
+ return { kind: 'float', value };
181
+ }
182
+ break;
183
+ case 'double':
184
+ if (allowFloat) {
185
+ return { kind: 'double', value };
186
+ }
187
+ break;
188
+ }
189
+ return undefined;
190
+ }
191
+ LiteralNumericValue.makeIfValid = makeIfValid;
192
+ })(LiteralNumericValue || (LiteralNumericValue = {}));
153
193
  export const NumericTypeIntKinds = Object.freeze(['byte', 'short', 'int', 'long']);
154
194
  export const NumericTypeFloatKinds = Object.freeze(['float', 'double']);
155
195
  export const NumericTypeKinds = Object.freeze([...NumericTypeIntKinds, ...NumericTypeFloatKinds]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spyglassmc/mcdoc",
3
- "version": "0.3.50",
3
+ "version": "0.3.52",
4
4
  "type": "module",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -25,7 +25,7 @@
25
25
  "url": "https://github.com/SpyglassMC/Spyglass/issues"
26
26
  },
27
27
  "dependencies": {
28
- "@spyglassmc/core": "0.4.46",
29
- "@spyglassmc/locales": "0.3.24"
28
+ "@spyglassmc/core": "0.4.48",
29
+ "@spyglassmc/locales": "0.3.25"
30
30
  }
31
31
  }