@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.
- package/lib/binder/index.js +3 -3
- package/lib/node/index.d.ts +1 -1
- package/lib/node/index.js +2 -2
- package/lib/runtime/checker/context.d.ts +2 -2
- package/lib/runtime/checker/context.js +1 -1
- package/lib/runtime/checker/index.d.ts +2 -2
- package/lib/runtime/checker/index.js +31 -10
- package/lib/type/index.d.ts +3 -0
- package/lib/type/index.js +40 -0
- package/package.json +3 -3
package/lib/binder/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AsyncBinder,
|
|
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(
|
|
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
|
|
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;
|
package/lib/node/index.d.ts
CHANGED
|
@@ -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<"
|
|
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 {
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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 [[{
|
|
36
|
+
return [[{
|
|
37
|
+
originalNode: { kind: 'byte' },
|
|
38
|
+
inferredType: { kind: 'byte' },
|
|
39
|
+
}]];
|
|
37
40
|
case 'int_array':
|
|
38
|
-
return [[{
|
|
41
|
+
return [[{
|
|
42
|
+
originalNode: { kind: 'int' },
|
|
43
|
+
inferredType: { kind: 'int' },
|
|
44
|
+
}]];
|
|
39
45
|
case 'long_array':
|
|
40
|
-
return [[{
|
|
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
|
-
|
|
282
|
-
if (runtimeValueType.kind !== typeDefValueType.kind
|
|
283
|
-
|
|
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,
|
|
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
|
-
&&
|
|
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
|
}
|
package/lib/type/index.d.ts
CHANGED
|
@@ -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.
|
|
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.
|
|
29
|
-
"@spyglassmc/locales": "0.3.
|
|
28
|
+
"@spyglassmc/core": "0.4.48",
|
|
29
|
+
"@spyglassmc/locales": "0.3.25"
|
|
30
30
|
}
|
|
31
31
|
}
|