@spyglassmc/mcdoc 0.3.10 → 0.3.11
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.d.ts +2 -0
- package/lib/runtime/attribute/builtin.js +76 -0
- package/lib/runtime/attribute/index.d.ts +3 -1
- package/lib/runtime/checker/context.d.ts +2 -0
- package/lib/runtime/checker/context.js +1 -0
- package/lib/runtime/checker/error.js +2 -2
- package/lib/runtime/checker/index.d.ts +6 -6
- package/lib/runtime/checker/index.js +207 -153
- package/lib/runtime/completer/index.d.ts +2 -0
- package/lib/runtime/completer/index.js +28 -0
- package/package.json +3 -3
package/lib/binder/index.d.ts
CHANGED
|
@@ -2,11 +2,13 @@ import type { BinderContext, MetaRegistry } from '@spyglassmc/core';
|
|
|
2
2
|
import { AsyncBinder } from '@spyglassmc/core';
|
|
3
3
|
import type { AdditionalContext } from '../common.js';
|
|
4
4
|
import type { ModuleNode } from '../node/index.js';
|
|
5
|
+
import type { SimplifiedMcdocType } from '../runtime/checker/index.js';
|
|
5
6
|
import type { McdocType } from '../type/index.js';
|
|
6
7
|
interface McdocBinderContext extends BinderContext, AdditionalContext {
|
|
7
8
|
}
|
|
8
9
|
export interface TypeDefSymbolData {
|
|
9
10
|
typeDef: McdocType;
|
|
11
|
+
simplifiedTypeDef?: SimplifiedMcdocType;
|
|
10
12
|
}
|
|
11
13
|
export declare namespace TypeDefSymbolData {
|
|
12
14
|
function is(data: unknown): data is TypeDefSymbolData;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import * as core from '@spyglassmc/core';
|
|
2
|
+
import { localeQuote, localize } from '@spyglassmc/locales';
|
|
2
3
|
import { registerAttribute, validator } from './index.js';
|
|
3
4
|
const idValidator = validator.alternatives(validator.map(validator.string, v => ({ registry: v })), validator.tree({
|
|
4
5
|
registry: validator.string,
|
|
5
6
|
tags: validator.optional(validator.options('allowed', 'implicit', 'required')),
|
|
6
7
|
definition: validator.optional(validator.boolean),
|
|
7
8
|
prefix: validator.optional(validator.options('!')),
|
|
9
|
+
empty: validator.optional(validator.options('allowed')),
|
|
8
10
|
}), () => ({}));
|
|
9
11
|
function getResourceLocationOptions({ registry, tags, definition }, requireCanonical, ctx, typeDef) {
|
|
10
12
|
if (!registry) {
|
|
@@ -45,6 +47,10 @@ function getResourceLocationOptions({ registry, tags, definition }, requireCanon
|
|
|
45
47
|
ctx.logger.warn(`[mcdoc id] Unhandled registry ${registry}`);
|
|
46
48
|
return undefined;
|
|
47
49
|
}
|
|
50
|
+
const integerValidator = validator.alternatives(validator.tree({
|
|
51
|
+
min: validator.optional(validator.number),
|
|
52
|
+
max: validator.optional(validator.number),
|
|
53
|
+
}), () => ({}));
|
|
48
54
|
export function registerBuiltinAttributes(meta) {
|
|
49
55
|
registerAttribute(meta, 'canonical', () => undefined, {
|
|
50
56
|
// Has hardcoded behavior in the runtime checker
|
|
@@ -108,6 +114,11 @@ export function registerBuiltinAttributes(meta) {
|
|
|
108
114
|
}
|
|
109
115
|
const resourceLocation = core.resourceLocation(options);
|
|
110
116
|
return (src, ctx) => {
|
|
117
|
+
if (config.empty && !src.canRead()) {
|
|
118
|
+
return core.string({
|
|
119
|
+
unquotable: { blockList: new Set(), allowEmpty: true },
|
|
120
|
+
})(src, ctx);
|
|
121
|
+
}
|
|
111
122
|
if (config.prefix) {
|
|
112
123
|
return core.prefixed({ prefix: config.prefix, child: resourceLocation })(src, ctx);
|
|
113
124
|
}
|
|
@@ -126,5 +137,70 @@ export function registerBuiltinAttributes(meta) {
|
|
|
126
137
|
return resourceLocation;
|
|
127
138
|
},
|
|
128
139
|
});
|
|
140
|
+
registerAttribute(meta, 'integer', integerValidator, {
|
|
141
|
+
stringParser: (config) => {
|
|
142
|
+
return core.integer({ pattern: /^-?\d+$/, min: config.min, max: config.max });
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
registerAttribute(meta, 'color', validator.string, {
|
|
146
|
+
checkInferred: (config, inferred, ctx) => {
|
|
147
|
+
if (config === 'hex_rgb' && inferred.kind === 'literal' && inferred.value.kind === 'string') {
|
|
148
|
+
return inferred.value.value.startsWith('#');
|
|
149
|
+
}
|
|
150
|
+
return true;
|
|
151
|
+
},
|
|
152
|
+
checker: (config, inferred) => {
|
|
153
|
+
return (node, ctx) => {
|
|
154
|
+
switch (config) {
|
|
155
|
+
case 'named':
|
|
156
|
+
if (inferred.kind !== 'literal' || inferred.value.kind !== 'string') {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
node.color = core.Color.fromNamed(inferred.value.value);
|
|
160
|
+
return;
|
|
161
|
+
case 'hex_rgb':
|
|
162
|
+
if (inferred.kind !== 'literal' || inferred.value.kind !== 'string') {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
let range = node.range;
|
|
166
|
+
if (core.StringBaseNode.is(node) && node.quote) {
|
|
167
|
+
range = core.Range.translate(range, 1, -1);
|
|
168
|
+
}
|
|
169
|
+
if (!inferred.value.value.startsWith('#')) {
|
|
170
|
+
ctx.err.report(localize('expected', localeQuote('#')), range, 2 /* core.ErrorSeverity.Warning */);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
node.color = {
|
|
174
|
+
value: core.Color.fromHexRGB(inferred.value.value),
|
|
175
|
+
format: [core.ColorFormat.HexRGB],
|
|
176
|
+
range,
|
|
177
|
+
};
|
|
178
|
+
return;
|
|
179
|
+
case 'composite_rgb':
|
|
180
|
+
if (inferred.kind !== 'literal' || typeof inferred.value.value !== 'number') {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
node.color = {
|
|
184
|
+
value: core.Color.fromCompositeRGB(inferred.value.value),
|
|
185
|
+
format: [core.ColorFormat.CompositeRGB],
|
|
186
|
+
range: node.range,
|
|
187
|
+
};
|
|
188
|
+
return;
|
|
189
|
+
case 'composite_argb':
|
|
190
|
+
if (inferred.kind !== 'literal' || typeof inferred.value.value !== 'number') {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
node.color = {
|
|
194
|
+
value: core.Color.fromCompositeARGB(inferred.value.value),
|
|
195
|
+
format: [core.ColorFormat.CompositeARGB],
|
|
196
|
+
range: node.range,
|
|
197
|
+
};
|
|
198
|
+
return;
|
|
199
|
+
default:
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
},
|
|
204
|
+
});
|
|
129
205
|
}
|
|
130
206
|
//# sourceMappingURL=builtin.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as core from '@spyglassmc/core';
|
|
2
|
-
import type { Attribute, StructTypePairField } from '../../type/index.js';
|
|
2
|
+
import type { Attribute, McdocType, StructTypePairField, UnionType } from '../../type/index.js';
|
|
3
3
|
import type { McdocCheckerContext, SimplifiedMcdocType, SimplifiedMcdocTypeNoUnion } from '../checker/index.js';
|
|
4
4
|
import type { McdocCompleterContext } from '../completer/index.js';
|
|
5
5
|
import type { McdocAttributeValidator } from './validator.js';
|
|
@@ -10,7 +10,9 @@ export interface McdocAttribute<C = unknown> {
|
|
|
10
10
|
mapField?: <T>(config: C, field: StructTypePairField, ctx: McdocCheckerContext<T>) => StructTypePairField;
|
|
11
11
|
filterElement?: (config: C, ctx: core.ContextBase) => boolean;
|
|
12
12
|
stringParser?: <T>(config: C, typeDef: SimplifiedMcdocTypeNoUnion, ctx: McdocCheckerContext<T>) => core.InfallibleParser<core.AstNode | undefined> | undefined;
|
|
13
|
+
checker?: <T>(config: C, inferred: Exclude<McdocType, UnionType>, ctx: McdocCheckerContext<T>) => core.SyncChecker<core.AstNode> | undefined;
|
|
13
14
|
stringMocker?: (config: C, typeDef: core.DeepReadonly<SimplifiedMcdocTypeNoUnion>, ctx: McdocCompleterContext) => core.AstNode | undefined;
|
|
15
|
+
numericCompleter?: (config: C, ctx: McdocCompleterContext) => core.CompletionItem[];
|
|
14
16
|
}
|
|
15
17
|
export declare function registerAttribute<C extends core.Returnable>(meta: core.MetaRegistry, name: string, validator: McdocAttributeValidator<C>, attribute: McdocAttribute<C>): void;
|
|
16
18
|
interface AttributeInfo {
|
|
@@ -14,6 +14,7 @@ export interface RuntimePair<T> {
|
|
|
14
14
|
}
|
|
15
15
|
export type NodeEquivalenceChecker = (inferredNode: Exclude<SimplifiedMcdocTypeNoUnion, LiteralType | EnumType>, definition: Exclude<SimplifiedMcdocTypeNoUnion, LiteralType | EnumType>) => boolean;
|
|
16
16
|
export type TypeInfoAttacher<T> = (node: T, definition: SimplifiedMcdocType, description?: string) => void;
|
|
17
|
+
export type NodeAttacher<T> = (node: T, attacher: (node: core.AstNode) => void) => void;
|
|
17
18
|
export type StringAttacher<T> = (node: T, attacher: (node: core.StringBaseNode) => void) => void;
|
|
18
19
|
export type ChildrenGetter<T> = (node: T, simplified: SimplifiedMcdocTypeNoUnion) => RuntimeUnion<T>[];
|
|
19
20
|
export type ErrorReporter<T> = (error: McdocRuntimeError<T>) => void;
|
|
@@ -24,6 +25,7 @@ export interface McdocCheckerContext<T> extends core.CheckerContext {
|
|
|
24
25
|
getChildren: ChildrenGetter<T>;
|
|
25
26
|
reportError: ErrorReporter<T>;
|
|
26
27
|
attachTypeInfo?: TypeInfoAttacher<T>;
|
|
28
|
+
nodeAttacher?: NodeAttacher<T>;
|
|
27
29
|
stringAttacher?: StringAttacher<T>;
|
|
28
30
|
}
|
|
29
31
|
type McdocCheckerContextOptions<T> = Partial<McdocCheckerContext<T>>;
|
|
@@ -9,6 +9,7 @@ export var McdocCheckerContext;
|
|
|
9
9
|
getChildren: options.getChildren ?? (() => []),
|
|
10
10
|
reportError: options.reportError ?? (() => { }),
|
|
11
11
|
attachTypeInfo: options.attachTypeInfo,
|
|
12
|
+
nodeAttacher: options.nodeAttacher,
|
|
12
13
|
stringAttacher: options.stringAttacher,
|
|
13
14
|
};
|
|
14
15
|
}
|
|
@@ -202,7 +202,7 @@ function condense(validDefinitions, is, equals, combineAlternatives) {
|
|
|
202
202
|
}, []);
|
|
203
203
|
const distinctErrors = distinctErrorsPerNode.flatMap(e => e.errors);
|
|
204
204
|
const commonErrors = distinctErrors
|
|
205
|
-
.filter(e => e.definitions.length
|
|
205
|
+
.filter(e => e.definitions.length === validDefinitions.length)
|
|
206
206
|
.map(e => e.error);
|
|
207
207
|
const definitionsWithUncommonErrors = distinctErrors
|
|
208
208
|
.filter(e => e.definitions.length < validDefinitions.length)
|
|
@@ -342,7 +342,7 @@ export function getDefaultErrorReporter(ctx, getErrorRange) {
|
|
|
342
342
|
localizedText = localize(`mcdoc.runtime.checker.${defaultTranslationKey}`);
|
|
343
343
|
break;
|
|
344
344
|
case 'internal':
|
|
345
|
-
|
|
345
|
+
return;
|
|
346
346
|
default:
|
|
347
347
|
localizedText = localize(defaultTranslationKey);
|
|
348
348
|
}
|
|
@@ -65,16 +65,16 @@ export interface SimplifyValueNode<T> {
|
|
|
65
65
|
export interface SimplifyContext<T> {
|
|
66
66
|
node: SimplifyValueNode<T>;
|
|
67
67
|
ctx: McdocCheckerContext<T>;
|
|
68
|
-
structFields?: {
|
|
69
|
-
literalFields: Map<string, StructTypePairField>;
|
|
70
|
-
complexFields: SimplifiedStructTypePairField[];
|
|
71
|
-
};
|
|
72
68
|
isMember?: boolean;
|
|
73
69
|
typeArgs?: SimplifiedMcdocType[];
|
|
74
70
|
typeMapping?: {
|
|
75
71
|
[path: string]: SimplifiedMcdocType;
|
|
76
72
|
};
|
|
77
73
|
}
|
|
78
|
-
export
|
|
79
|
-
|
|
74
|
+
export interface SimplifyResult<T extends SimplifiedMcdocType> {
|
|
75
|
+
typeDef: T;
|
|
76
|
+
dynamicData?: boolean;
|
|
77
|
+
}
|
|
78
|
+
export declare function simplify<T>(typeDef: Exclude<McdocType, UnionType>, context: SimplifyContext<T>): SimplifyResult<SimplifiedMcdocTypeNoUnion>;
|
|
79
|
+
export declare function simplify<T>(typeDef: McdocType, context: SimplifyContext<T>): SimplifyResult<SimplifiedMcdocType>;
|
|
80
80
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -88,7 +88,7 @@ export function typeDefinition(runtimeValues, typeDef, ctx) {
|
|
|
88
88
|
children: [],
|
|
89
89
|
}));
|
|
90
90
|
for (const value of rootNode.possibleValues) {
|
|
91
|
-
const simplifiedRoot = simplify(typeDef, { ctx, node: value });
|
|
91
|
+
const simplifiedRoot = simplify(typeDef, { ctx, node: value }).typeDef;
|
|
92
92
|
const validRootDefinitions = simplifiedRoot.kind === 'union'
|
|
93
93
|
? simplifiedRoot.members
|
|
94
94
|
: [simplifiedRoot];
|
|
@@ -110,7 +110,7 @@ export function typeDefinition(runtimeValues, typeDef, ctx) {
|
|
|
110
110
|
while (nodeQueue.length !== 0) {
|
|
111
111
|
const node = nodeQueue.shift();
|
|
112
112
|
for (const value of node.possibleValues) {
|
|
113
|
-
const inferredSimplified = simplify(value.node.inferredType, { ctx, node: value });
|
|
113
|
+
const inferredSimplified = simplify(value.node.inferredType, { ctx, node: value }).typeDef;
|
|
114
114
|
const children = ctx.getChildren(value.node.originalNode, inferredSimplified);
|
|
115
115
|
const childNodes = children.map(c => {
|
|
116
116
|
const ans = {
|
|
@@ -165,7 +165,7 @@ export function typeDefinition(runtimeValues, typeDef, ctx) {
|
|
|
165
165
|
// the same types again and just collect the errors of the lower depth.
|
|
166
166
|
// This will currently lead to a stack overflow error when e.g. comparing two
|
|
167
167
|
// text component definitions
|
|
168
|
-
const simplified = simplify(childDef.type, { ctx, node: childValue });
|
|
168
|
+
const simplified = simplify(childDef.type, { ctx, node: childValue }).typeDef;
|
|
169
169
|
const childDefinitionGroup = {
|
|
170
170
|
parents: [def],
|
|
171
171
|
runtimeNode: childValue,
|
|
@@ -212,10 +212,10 @@ function attachTypeInfo(node, ctx) {
|
|
|
212
212
|
if (definitions.length === 1) {
|
|
213
213
|
const { typeDef, groupNode } = definitions[0];
|
|
214
214
|
ctx.attachTypeInfo?.(node.node.originalNode, typeDef, groupNode.desc);
|
|
215
|
-
|
|
215
|
+
handleNodeAttachers(node.node, typeDef, ctx);
|
|
216
216
|
if (node.entryNode.runtimeKey && groupNode.keyDefinition) {
|
|
217
217
|
ctx.attachTypeInfo?.(node.entryNode.runtimeKey.originalNode, groupNode.keyDefinition, groupNode.desc);
|
|
218
|
-
|
|
218
|
+
handleNodeAttachers(node.entryNode.runtimeKey, groupNode.keyDefinition, ctx);
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
221
|
else if (definitions.length > 1) {
|
|
@@ -237,40 +237,46 @@ function attachTypeInfo(node, ctx) {
|
|
|
237
237
|
attachTypeInfo(child, ctx);
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
|
-
function
|
|
241
|
-
const { stringAttacher } = ctx;
|
|
242
|
-
if (!stringAttacher) {
|
|
240
|
+
function handleNodeAttachers(runtimeValue, typeDef, ctx) {
|
|
241
|
+
const { nodeAttacher, stringAttacher } = ctx;
|
|
242
|
+
if (!nodeAttacher && !stringAttacher) {
|
|
243
243
|
return;
|
|
244
244
|
}
|
|
245
245
|
handleAttributes(typeDef.attributes, ctx, (handler, config) => {
|
|
246
246
|
const parser = handler.stringParser?.(config, typeDef, ctx);
|
|
247
|
-
if (
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
|
|
247
|
+
if (parser && stringAttacher) {
|
|
248
|
+
stringAttacher(runtimeValue.originalNode, (node) => {
|
|
249
|
+
const src = new Source(node.value, node.valueMap);
|
|
250
|
+
const start = src.cursor;
|
|
251
|
+
const child = parser(src, ctx);
|
|
252
|
+
if (!child) {
|
|
253
|
+
ctx.err.report(localize('expected', localize('mcdoc.runtime.checker.value')), Range.create(start, src.skipRemaining()));
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
else if (src.canRead()) {
|
|
257
|
+
ctx.err.report(localize('mcdoc.runtime.checker.trailing'), Range.create(src.cursor, src.skipRemaining()));
|
|
258
|
+
}
|
|
259
|
+
node.children = [child];
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
const checker = handler.checker?.(config, runtimeValue.inferredType, ctx);
|
|
263
|
+
if (checker && nodeAttacher) {
|
|
264
|
+
nodeAttacher(runtimeValue.originalNode, (node) => {
|
|
265
|
+
checker(node, ctx);
|
|
266
|
+
});
|
|
267
|
+
}
|
|
263
268
|
});
|
|
264
269
|
}
|
|
265
270
|
function checkShallowly(runtimeNode, simplifiedInferred, children, typeDef, ctx) {
|
|
266
|
-
const typeDefValueType = getValueType(typeDef);
|
|
267
|
-
const runtimeValueType = getValueType(simplifiedInferred);
|
|
268
271
|
const childDefinitions = Array(children.length)
|
|
269
272
|
.fill(undefined);
|
|
270
|
-
if (
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
273
|
+
if (typeDef.kind === 'any' || typeDef.kind === 'unsafe' || simplifiedInferred.kind === 'unsafe') {
|
|
274
|
+
return { childDefinitions, errors: [] };
|
|
275
|
+
}
|
|
276
|
+
const typeDefValueType = getValueType(typeDef);
|
|
277
|
+
const runtimeValueType = getValueType(simplifiedInferred);
|
|
278
|
+
if (runtimeValueType.kind !== typeDefValueType.kind
|
|
279
|
+
&& !ctx.isEquivalent(runtimeValueType, typeDefValueType)) {
|
|
274
280
|
return {
|
|
275
281
|
childDefinitions,
|
|
276
282
|
errors: [{ kind: 'type_mismatch', node: runtimeNode, expected: [typeDef] }],
|
|
@@ -299,9 +305,6 @@ function checkShallowly(runtimeNode, simplifiedInferred, children, typeDef, ctx)
|
|
|
299
305
|
};
|
|
300
306
|
}
|
|
301
307
|
switch (typeDef.kind) {
|
|
302
|
-
case 'any':
|
|
303
|
-
case 'unsafe':
|
|
304
|
-
break;
|
|
305
308
|
case 'byte':
|
|
306
309
|
case 'short':
|
|
307
310
|
case 'int':
|
|
@@ -357,6 +360,7 @@ function checkShallowly(runtimeNode, simplifiedInferred, children, typeDef, ctx)
|
|
|
357
360
|
otherKvps.push({ value: child, index: i });
|
|
358
361
|
}
|
|
359
362
|
}
|
|
363
|
+
const missingKeys = new Set();
|
|
360
364
|
for (const pair of typeDef.fields) {
|
|
361
365
|
const otherKvpMatches = [];
|
|
362
366
|
let foundMatch = false;
|
|
@@ -368,17 +372,14 @@ function checkShallowly(runtimeNode, simplifiedInferred, children, typeDef, ctx)
|
|
|
368
372
|
}
|
|
369
373
|
}
|
|
370
374
|
if (!foundMatch) {
|
|
371
|
-
for (
|
|
372
|
-
const kvp = otherKvps[i];
|
|
375
|
+
for (const kvp of otherKvps) {
|
|
373
376
|
if (isAssignable(kvp.value.key.inferredType, pair.key, ctx, ctx.isEquivalent)) {
|
|
374
377
|
foundMatch = true;
|
|
375
|
-
otherKvps.splice(i, 1);
|
|
376
378
|
otherKvpMatches.push(kvp.index);
|
|
377
|
-
i--;
|
|
378
379
|
}
|
|
379
380
|
}
|
|
380
381
|
for (const kvp of literalKvps.entries()) {
|
|
381
|
-
if (!kvp[1].definition
|
|
382
|
+
if ((!kvp[1].definition || kvp[1].definition.keyType?.kind !== 'literal')
|
|
382
383
|
&& isAssignable({ kind: 'literal', value: { kind: 'string', value: kvp[0] } }, pair.key, ctx, ctx.isEquivalent)) {
|
|
383
384
|
foundMatch = true;
|
|
384
385
|
kvp[1].definition = { keyType: pair.key, type: pair.type, desc: pair.desc };
|
|
@@ -393,9 +394,14 @@ function checkShallowly(runtimeNode, simplifiedInferred, children, typeDef, ctx)
|
|
|
393
394
|
&& pair.key.kind === 'literal'
|
|
394
395
|
&& pair.key.value.kind === 'string'
|
|
395
396
|
&& pair.optional !== true) {
|
|
396
|
-
|
|
397
|
+
missingKeys.add(pair.key.value.value);
|
|
397
398
|
}
|
|
398
399
|
}
|
|
400
|
+
errors.push(...Array.from(missingKeys).map(key => ({
|
|
401
|
+
kind: 'missing_key',
|
|
402
|
+
node: runtimeNode,
|
|
403
|
+
keys: [key],
|
|
404
|
+
})));
|
|
399
405
|
for (const kvp of literalKvps.values()) {
|
|
400
406
|
for (const value of kvp.values) {
|
|
401
407
|
childDefinitions[value.index] = kvp.definition;
|
|
@@ -484,16 +490,16 @@ export function getPossibleTypes(typeDef) {
|
|
|
484
490
|
return typeDef.kind === 'union' ? typeDef.members.flatMap(m => getPossibleTypes(m)) : [typeDef];
|
|
485
491
|
}
|
|
486
492
|
export function simplify(typeDef, context) {
|
|
487
|
-
function wrap(
|
|
488
|
-
if (!typeDef.attributes?.length) {
|
|
489
|
-
return
|
|
493
|
+
function wrap(result) {
|
|
494
|
+
if (!result.typeDef.attributes?.length) {
|
|
495
|
+
return result;
|
|
490
496
|
}
|
|
491
497
|
handleAttributes(typeDef.attributes, context.ctx, (handler, config) => {
|
|
492
498
|
if (handler.mapType) {
|
|
493
|
-
typeDef = handler.mapType(config, typeDef, context.ctx);
|
|
499
|
+
result.typeDef = handler.mapType(config, result.typeDef, context.ctx);
|
|
494
500
|
}
|
|
495
501
|
});
|
|
496
|
-
return
|
|
502
|
+
return result;
|
|
497
503
|
}
|
|
498
504
|
switch (typeDef.kind) {
|
|
499
505
|
case 'reference':
|
|
@@ -519,53 +525,67 @@ export function simplify(typeDef, context) {
|
|
|
519
525
|
case 'mapped':
|
|
520
526
|
return wrap(simplifyMapped(typeDef, context));
|
|
521
527
|
default:
|
|
522
|
-
return wrap(typeDef);
|
|
528
|
+
return wrap({ typeDef });
|
|
523
529
|
}
|
|
524
530
|
}
|
|
525
531
|
function simplifyReference(typeDef, context) {
|
|
526
532
|
if (!typeDef.path) {
|
|
527
533
|
// TODO when does this happen?
|
|
528
534
|
context.ctx.logger.warn(`Tried to access empty reference`);
|
|
529
|
-
return { kind: 'union', members: [] };
|
|
535
|
+
return { typeDef: { kind: 'union', members: [] } };
|
|
530
536
|
}
|
|
531
537
|
const mapped = context.typeMapping?.[typeDef.path];
|
|
532
538
|
if (mapped) {
|
|
533
|
-
return mapped;
|
|
539
|
+
return { typeDef: mapped };
|
|
534
540
|
}
|
|
535
541
|
// TODO Probably need to keep original symbol around in some way to support "go to definition"
|
|
536
542
|
const symbol = context.ctx.symbols.query(context.ctx.doc, 'mcdoc', typeDef.path);
|
|
537
|
-
const
|
|
538
|
-
if (!
|
|
543
|
+
const data = symbol.getData(TypeDefSymbolData.is);
|
|
544
|
+
if (!data?.typeDef) {
|
|
539
545
|
context.ctx.logger.warn(`Tried to access unknown reference ${typeDef.path}`);
|
|
540
|
-
return { kind: 'union', members: [] };
|
|
546
|
+
return { typeDef: { kind: 'union', members: [] } };
|
|
547
|
+
}
|
|
548
|
+
if (data.simplifiedTypeDef) {
|
|
549
|
+
return { typeDef: data.simplifiedTypeDef };
|
|
541
550
|
}
|
|
542
|
-
const
|
|
551
|
+
const simplifiedResult = simplify(data.typeDef, context);
|
|
543
552
|
if (typeDef.attributes?.length) {
|
|
544
|
-
|
|
545
|
-
...
|
|
546
|
-
attributes: [...typeDef.attributes, ...
|
|
553
|
+
simplifiedResult.typeDef = {
|
|
554
|
+
...simplifiedResult.typeDef,
|
|
555
|
+
attributes: [...typeDef.attributes, ...simplifiedResult.typeDef.attributes ?? []],
|
|
547
556
|
};
|
|
548
557
|
}
|
|
549
|
-
|
|
558
|
+
if (!simplifiedResult.dynamicData) {
|
|
559
|
+
symbol.amend({
|
|
560
|
+
data: {
|
|
561
|
+
data: {
|
|
562
|
+
...data,
|
|
563
|
+
simplifiedTypeDef: simplifiedResult.typeDef,
|
|
564
|
+
},
|
|
565
|
+
},
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
return simplifiedResult;
|
|
550
569
|
}
|
|
551
570
|
function simplifyDispatcher(typeDef, context) {
|
|
552
|
-
const
|
|
553
|
-
|
|
571
|
+
const dispatcherQuery = context.ctx.symbols.query(context.ctx.doc, 'mcdoc/dispatcher', typeDef.registry);
|
|
572
|
+
const dispatcher = dispatcherQuery.symbol?.members;
|
|
554
573
|
if (!dispatcher) {
|
|
555
574
|
context.ctx.logger.warn(`Tried to access unknown dispatcher ${typeDef.registry}`);
|
|
556
|
-
return { kind: 'union', members: [] };
|
|
575
|
+
return { typeDef: { kind: 'union', members: [] } };
|
|
557
576
|
}
|
|
558
|
-
|
|
577
|
+
const result = resolveIndices(typeDef.parallelIndices, dispatcher, dispatcherQuery, context);
|
|
578
|
+
return result;
|
|
559
579
|
}
|
|
560
580
|
function simplifyIndexed(typeDef, context) {
|
|
561
|
-
const
|
|
581
|
+
const childResult = simplify(typeDef.child, {
|
|
562
582
|
...context,
|
|
563
583
|
typeArgs: [],
|
|
564
|
-
structFields: undefined,
|
|
565
584
|
});
|
|
585
|
+
const child = childResult.typeDef;
|
|
566
586
|
if (child.kind !== 'struct') {
|
|
567
587
|
context.ctx.logger.warn(`Tried to index un-indexable type ${child.kind}`);
|
|
568
|
-
return { kind: 'union', members: [] };
|
|
588
|
+
return { typeDef: { kind: 'union', members: [] }, dynamicData: childResult.dynamicData };
|
|
569
589
|
}
|
|
570
590
|
const symbolMap = {};
|
|
571
591
|
for (const field of child.fields) {
|
|
@@ -577,15 +597,44 @@ function simplifyIndexed(typeDef, context) {
|
|
|
577
597
|
};
|
|
578
598
|
}
|
|
579
599
|
}
|
|
580
|
-
|
|
600
|
+
const simplified = resolveIndices(typeDef.parallelIndices, symbolMap, undefined, context);
|
|
601
|
+
return { ...simplified, dynamicData: childResult.dynamicData ?? simplified.dynamicData };
|
|
581
602
|
}
|
|
582
|
-
function resolveIndices(parallelIndices, symbolMap, context) {
|
|
603
|
+
function resolveIndices(parallelIndices, symbolMap, symbolQuery, context) {
|
|
604
|
+
let dynamicData = false;
|
|
583
605
|
let values = [];
|
|
606
|
+
function pushValue(key, data) {
|
|
607
|
+
if (data.simplifiedTypeDef) {
|
|
608
|
+
if (data.simplifiedTypeDef.kind === 'union') {
|
|
609
|
+
values.push(...data.simplifiedTypeDef.members);
|
|
610
|
+
}
|
|
611
|
+
else {
|
|
612
|
+
values.push(data.simplifiedTypeDef);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
else {
|
|
616
|
+
const simplifiedResult = simplify(data.typeDef, context);
|
|
617
|
+
if (simplifiedResult.dynamicData) {
|
|
618
|
+
dynamicData = true;
|
|
619
|
+
}
|
|
620
|
+
else if (symbolQuery) {
|
|
621
|
+
symbolQuery.member(key, s => s.amend({
|
|
622
|
+
data: { data: { ...data, simplifiedTypeDef: simplifiedResult.typeDef } },
|
|
623
|
+
}));
|
|
624
|
+
}
|
|
625
|
+
if (simplifiedResult.typeDef.kind === 'union') {
|
|
626
|
+
values.push(...simplifiedResult.typeDef.members);
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
values.push(simplifiedResult.typeDef);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
584
633
|
let unkownTypeDef = false;
|
|
585
634
|
function getUnknownTypeDef() {
|
|
586
635
|
if (unkownTypeDef === false) {
|
|
587
636
|
const data = symbolMap['%unknown']?.data;
|
|
588
|
-
unkownTypeDef = TypeDefSymbolData.is(data) ? data
|
|
637
|
+
unkownTypeDef = TypeDefSymbolData.is(data) ? data : undefined;
|
|
589
638
|
}
|
|
590
639
|
return unkownTypeDef;
|
|
591
640
|
}
|
|
@@ -593,10 +642,12 @@ function resolveIndices(parallelIndices, symbolMap, context) {
|
|
|
593
642
|
let lookup = [];
|
|
594
643
|
if (index.kind === 'static') {
|
|
595
644
|
if (index.value === '%fallback') {
|
|
596
|
-
values =
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
645
|
+
values = [];
|
|
646
|
+
for (const [key, value] of Object.entries(symbolMap)) {
|
|
647
|
+
if (TypeDefSymbolData.is(value.data)) {
|
|
648
|
+
pushValue(key, value.data);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
600
651
|
break;
|
|
601
652
|
}
|
|
602
653
|
if (index.value.startsWith('minecraft:')) {
|
|
@@ -607,6 +658,7 @@ function resolveIndices(parallelIndices, symbolMap, context) {
|
|
|
607
658
|
}
|
|
608
659
|
}
|
|
609
660
|
else {
|
|
661
|
+
dynamicData = true;
|
|
610
662
|
let possibilities = context.isMember
|
|
611
663
|
? [{ value: context.node, key: context.node.entryNode.runtimeKey }]
|
|
612
664
|
: [{
|
|
@@ -633,7 +685,8 @@ function resolveIndices(parallelIndices, symbolMap, context) {
|
|
|
633
685
|
const newPossibilities = [];
|
|
634
686
|
for (const node of possibilities) {
|
|
635
687
|
const possibleChildren = node.value
|
|
636
|
-
? context.ctx.getChildren(node.value.node.originalNode, simplify(node.value.node.inferredType, { ...context, node: node.value })
|
|
688
|
+
? context.ctx.getChildren(node.value.node.originalNode, simplify(node.value.node.inferredType, { ...context, node: node.value })
|
|
689
|
+
.typeDef).filter(child => {
|
|
637
690
|
if (!Array.isArray(child)) {
|
|
638
691
|
return child.key.inferredType.kind === 'literal'
|
|
639
692
|
&& child.key.inferredType.value.kind === 'string'
|
|
@@ -680,23 +733,26 @@ function resolveIndices(parallelIndices, symbolMap, context) {
|
|
|
680
733
|
}
|
|
681
734
|
const currentValues = lookup.map(v => {
|
|
682
735
|
const data = symbolMap[v]?.data;
|
|
683
|
-
return TypeDefSymbolData.is(data) ? data
|
|
736
|
+
return { value: v, data: TypeDefSymbolData.is(data) ? data : getUnknownTypeDef() };
|
|
684
737
|
});
|
|
685
|
-
|
|
738
|
+
const missing = currentValues.find(v => !v.data);
|
|
739
|
+
if (missing) {
|
|
686
740
|
// fallback case
|
|
687
|
-
return { kind: 'any' };
|
|
741
|
+
return { typeDef: { kind: 'any' }, dynamicData };
|
|
688
742
|
}
|
|
689
743
|
else {
|
|
690
|
-
|
|
744
|
+
for (const entry of currentValues) {
|
|
745
|
+
pushValue(entry.value, entry.data);
|
|
746
|
+
}
|
|
691
747
|
}
|
|
692
748
|
}
|
|
693
749
|
if (values.length === 1) {
|
|
694
|
-
|
|
695
|
-
return simplify(values[0], context);
|
|
750
|
+
return { typeDef: values[0], dynamicData };
|
|
696
751
|
}
|
|
697
|
-
return
|
|
752
|
+
return { typeDef: { kind: 'union', members: values }, dynamicData };
|
|
698
753
|
}
|
|
699
754
|
function simplifyUnion(typeDef, context) {
|
|
755
|
+
let dynamicData = false;
|
|
700
756
|
const filterCanonical = context.ctx.requireCanonical
|
|
701
757
|
&& typeDef.members.some(m => m.attributes?.some(a => a.name === 'canonical'));
|
|
702
758
|
const validMembers = typeDef.members
|
|
@@ -716,46 +772,29 @@ function simplifyUnion(typeDef, context) {
|
|
|
716
772
|
return keep;
|
|
717
773
|
});
|
|
718
774
|
if (validMembers.length === 1) {
|
|
719
|
-
// Avoid needing to manually add struct fields to parent if we are in a spread operation
|
|
720
775
|
return simplify(validMembers[0], context);
|
|
721
776
|
}
|
|
722
777
|
const members = [];
|
|
723
778
|
for (const member of validMembers) {
|
|
724
|
-
const simplified = simplify(member,
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
}
|
|
779
|
+
const { typeDef: simplified, dynamicData: memberDynamid } = simplify(member, context);
|
|
780
|
+
if (memberDynamid) {
|
|
781
|
+
dynamicData = true;
|
|
782
|
+
}
|
|
728
783
|
if (simplified.kind === 'union') {
|
|
729
784
|
members.push(...simplified.members);
|
|
730
785
|
}
|
|
731
786
|
else {
|
|
732
787
|
members.push(simplified);
|
|
733
788
|
}
|
|
734
|
-
if (context.structFields && members.length > 1) {
|
|
735
|
-
return { kind: 'union', members: [] };
|
|
736
|
-
}
|
|
737
789
|
}
|
|
738
790
|
if (members.length === 1) {
|
|
739
|
-
|
|
740
|
-
// Apply struct fields to parent if we are inside a spread operation.
|
|
741
|
-
if (members[0].kind === 'struct' && context.structFields) {
|
|
742
|
-
for (const field of members[0].fields) {
|
|
743
|
-
if (field.key.kind === 'literal' && field.key.value.kind === 'string') {
|
|
744
|
-
context.structFields.literalFields.set(field.key.value.value, field);
|
|
745
|
-
}
|
|
746
|
-
else {
|
|
747
|
-
context.structFields.complexFields.push(field);
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
return members[0];
|
|
791
|
+
return { typeDef: members[0], dynamicData };
|
|
752
792
|
}
|
|
753
|
-
return {
|
|
793
|
+
return { typeDef: { kind: 'union', members }, dynamicData };
|
|
754
794
|
}
|
|
755
795
|
function simplifyStruct(typeDef, context) {
|
|
756
|
-
const
|
|
757
|
-
|
|
758
|
-
let complexFields = context.structFields?.complexFields ?? [];
|
|
796
|
+
const fields = [];
|
|
797
|
+
let dynamicData = false;
|
|
759
798
|
function addField(key, field) {
|
|
760
799
|
handleAttributes(field.attributes, context.ctx, (handler, config) => {
|
|
761
800
|
if (handler.mapField) {
|
|
@@ -763,20 +802,16 @@ function simplifyStruct(typeDef, context) {
|
|
|
763
802
|
}
|
|
764
803
|
});
|
|
765
804
|
if (typeof key === 'string') {
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
805
|
+
fields.push({
|
|
806
|
+
...field,
|
|
807
|
+
key: { kind: 'literal', value: { kind: 'string', value: key } },
|
|
808
|
+
});
|
|
770
809
|
}
|
|
771
810
|
else if (key.kind === 'union') {
|
|
772
811
|
key.members.forEach(m => addField(m, { ...field, optional: true }));
|
|
773
812
|
}
|
|
774
813
|
else {
|
|
775
|
-
|
|
776
|
-
complexFields = complexFields.filter(other => !McdocType.equals(key, typeof other.key === 'string'
|
|
777
|
-
? { kind: 'literal', value: { kind: 'string', value: other.key } }
|
|
778
|
-
: other.key));
|
|
779
|
-
complexFields.push({ ...field, key });
|
|
814
|
+
fields.push({ ...field, key });
|
|
780
815
|
}
|
|
781
816
|
}
|
|
782
817
|
for (const field of typeDef.fields) {
|
|
@@ -790,12 +825,24 @@ function simplifyStruct(typeDef, context) {
|
|
|
790
825
|
continue;
|
|
791
826
|
}
|
|
792
827
|
if (field.kind === 'pair') {
|
|
793
|
-
// Don't simplify the value here
|
|
794
|
-
//
|
|
795
|
-
//
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
828
|
+
// Don't simplify the value here, simplify is shallow and needs a runtime value to work
|
|
829
|
+
// properly, so the values should only be simplified once they were assigned to a
|
|
830
|
+
// runtime value.
|
|
831
|
+
let structKey;
|
|
832
|
+
if (typeof field.key === 'string') {
|
|
833
|
+
structKey = field.key;
|
|
834
|
+
}
|
|
835
|
+
else {
|
|
836
|
+
const simplifiedKeyResult = simplify(field.key, {
|
|
837
|
+
...context,
|
|
838
|
+
isMember: true,
|
|
839
|
+
typeArgs: [],
|
|
840
|
+
});
|
|
841
|
+
if (simplifiedKeyResult.dynamicData) {
|
|
842
|
+
dynamicData = true;
|
|
843
|
+
}
|
|
844
|
+
structKey = simplifiedKeyResult.typeDef;
|
|
845
|
+
}
|
|
799
846
|
const mappedField = context.typeMapping
|
|
800
847
|
? {
|
|
801
848
|
...field,
|
|
@@ -813,54 +860,47 @@ function simplifyStruct(typeDef, context) {
|
|
|
813
860
|
...context,
|
|
814
861
|
isMember: true,
|
|
815
862
|
typeArgs: [],
|
|
816
|
-
structFields: { literalFields, complexFields },
|
|
817
863
|
});
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
if (simplifiedSpread.kind === 'any') {
|
|
822
|
-
|
|
864
|
+
if (simplifiedSpread.dynamicData) {
|
|
865
|
+
dynamicData = true;
|
|
866
|
+
}
|
|
867
|
+
if (simplifiedSpread.typeDef.kind === 'any') {
|
|
868
|
+
fields.push({ kind: 'pair', key: { kind: 'any' }, type: { kind: 'any' } });
|
|
869
|
+
}
|
|
870
|
+
else if (simplifiedSpread.typeDef.kind === 'struct') {
|
|
871
|
+
fields.push(...simplifiedSpread.typeDef.fields);
|
|
823
872
|
}
|
|
824
873
|
}
|
|
825
874
|
}
|
|
826
|
-
if (context.structFields) {
|
|
827
|
-
// In this case we are spreading a struct and the fields have been added to the parent map
|
|
828
|
-
// from context now.
|
|
829
|
-
return { kind: 'struct', fields: [] };
|
|
830
|
-
}
|
|
831
|
-
// Literal fields may still be assignable to complex fields,
|
|
832
|
-
// however this is currently not seen as an issue
|
|
833
875
|
return {
|
|
834
|
-
kind: 'struct',
|
|
835
|
-
|
|
836
|
-
...complexFields,
|
|
837
|
-
...[...literalFields.entries()].map(([key, field]) => ({
|
|
838
|
-
...field,
|
|
839
|
-
key: { kind: 'literal', value: { kind: 'string', value: key } },
|
|
840
|
-
})),
|
|
841
|
-
],
|
|
876
|
+
typeDef: { kind: 'struct', fields },
|
|
877
|
+
dynamicData,
|
|
842
878
|
};
|
|
843
879
|
}
|
|
844
880
|
function simplifyList(typeDef, context) {
|
|
845
881
|
if (!context.typeMapping) {
|
|
846
|
-
return typeDef;
|
|
882
|
+
return { typeDef };
|
|
847
883
|
}
|
|
848
884
|
return {
|
|
849
|
-
|
|
850
|
-
|
|
885
|
+
typeDef: {
|
|
886
|
+
...typeDef,
|
|
887
|
+
item: { kind: 'mapped', child: typeDef.item, mapping: context.typeMapping },
|
|
888
|
+
},
|
|
851
889
|
};
|
|
852
890
|
}
|
|
853
891
|
function simplifyTuple(typeDef, context) {
|
|
854
892
|
if (!context.typeMapping) {
|
|
855
|
-
return typeDef;
|
|
893
|
+
return { typeDef };
|
|
856
894
|
}
|
|
857
895
|
return {
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
896
|
+
typeDef: {
|
|
897
|
+
...typeDef,
|
|
898
|
+
items: typeDef.items.map(item => ({
|
|
899
|
+
kind: 'mapped',
|
|
900
|
+
child: item,
|
|
901
|
+
mapping: context.typeMapping,
|
|
902
|
+
})),
|
|
903
|
+
},
|
|
864
904
|
};
|
|
865
905
|
}
|
|
866
906
|
function simplifyEnum(typeDef, context) {
|
|
@@ -876,11 +916,19 @@ function simplifyEnum(typeDef, context) {
|
|
|
876
916
|
});
|
|
877
917
|
return keep;
|
|
878
918
|
});
|
|
879
|
-
return { ...typeDef, enumKind: typeDef.enumKind ?? 'int', values: filteredValues };
|
|
919
|
+
return { typeDef: { ...typeDef, enumKind: typeDef.enumKind ?? 'int', values: filteredValues } };
|
|
880
920
|
}
|
|
881
921
|
function simplifyConcrete(typeDef, context) {
|
|
882
|
-
|
|
883
|
-
|
|
922
|
+
let dynamicData = false;
|
|
923
|
+
const simplifiedArgs = typeDef.typeArgs.map(arg => {
|
|
924
|
+
const ans = simplify(arg, context);
|
|
925
|
+
if (ans.dynamicData) {
|
|
926
|
+
dynamicData = true;
|
|
927
|
+
}
|
|
928
|
+
return ans.typeDef;
|
|
929
|
+
});
|
|
930
|
+
const result = simplify(typeDef.child, { ...context, typeArgs: simplifiedArgs });
|
|
931
|
+
return { typeDef: result.typeDef, dynamicData: dynamicData || result.dynamicData };
|
|
884
932
|
}
|
|
885
933
|
function simplifyTemplate(typeDef, context) {
|
|
886
934
|
if (context.typeArgs?.length !== typeDef.typeParams.length) {
|
|
@@ -893,13 +941,19 @@ function simplifyTemplate(typeDef, context) {
|
|
|
893
941
|
return simplify(typeDef.child, { ...context, typeArgs: [], typeMapping: mapping });
|
|
894
942
|
}
|
|
895
943
|
function simplifyMapped(typeDef, context) {
|
|
944
|
+
let dynamicData = false;
|
|
896
945
|
// Mapped types that were created in simplify are always simplified
|
|
897
946
|
// types already, in which case this will be a cheap operation, but
|
|
898
947
|
// this is necessary for type safety
|
|
899
948
|
const simplifiedMapping = Object.fromEntries(Object.entries(typeDef.mapping).map(([path, param]) => {
|
|
900
|
-
|
|
949
|
+
const ans = simplify(param, context);
|
|
950
|
+
if (ans.dynamicData) {
|
|
951
|
+
dynamicData = true;
|
|
952
|
+
}
|
|
953
|
+
return [path, ans.typeDef];
|
|
901
954
|
}));
|
|
902
|
-
|
|
955
|
+
const ans = simplify(typeDef.child, { ...context, typeMapping: simplifiedMapping });
|
|
956
|
+
return { typeDef: ans.typeDef, dynamicData: dynamicData || ans.dynamicData };
|
|
903
957
|
}
|
|
904
958
|
function getValueType(type) {
|
|
905
959
|
switch (type.kind) {
|
|
@@ -12,9 +12,11 @@ export declare function getFields(typeDef: core.DeepReadonly<SimplifiedMcdocType
|
|
|
12
12
|
export type SimpleCompletionValue = {
|
|
13
13
|
value: string;
|
|
14
14
|
detail?: string;
|
|
15
|
+
labelSuffix?: string;
|
|
15
16
|
kind?: McdocType['kind'];
|
|
16
17
|
completionKind?: core.CompletionKind;
|
|
17
18
|
insertText?: string;
|
|
19
|
+
sortText?: string;
|
|
18
20
|
};
|
|
19
21
|
export declare function getValues(typeDef: core.DeepReadonly<McdocType>, ctx: McdocCompleterContext): SimpleCompletionValue[];
|
|
20
22
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -95,6 +95,13 @@ export function getValues(typeDef, ctx) {
|
|
|
95
95
|
detail: v.identifier,
|
|
96
96
|
kind: typeDef.enumKind ?? 'string',
|
|
97
97
|
}));
|
|
98
|
+
case 'byte':
|
|
99
|
+
case 'short':
|
|
100
|
+
case 'int':
|
|
101
|
+
case 'long':
|
|
102
|
+
case 'float':
|
|
103
|
+
case 'double':
|
|
104
|
+
return getNumericCompletions(typeDef, ctx);
|
|
98
105
|
default:
|
|
99
106
|
return [];
|
|
100
107
|
}
|
|
@@ -110,9 +117,11 @@ function getStringCompletions(typeDef, ctx) {
|
|
|
110
117
|
ans.push(...items.map(item => ({
|
|
111
118
|
value: item.label,
|
|
112
119
|
kind: 'string',
|
|
120
|
+
labelSuffix: item.labelSuffix,
|
|
113
121
|
detail: item.detail,
|
|
114
122
|
completionKind: item.kind,
|
|
115
123
|
insertText: item.insertText,
|
|
124
|
+
sortText: item.sortText,
|
|
116
125
|
})));
|
|
117
126
|
});
|
|
118
127
|
if (ans.length === 0 && typeDef.kind === 'literal') {
|
|
@@ -120,4 +129,23 @@ function getStringCompletions(typeDef, ctx) {
|
|
|
120
129
|
}
|
|
121
130
|
return ans;
|
|
122
131
|
}
|
|
132
|
+
function getNumericCompletions(typeDef, ctx) {
|
|
133
|
+
const ans = [];
|
|
134
|
+
handleAttributes(typeDef.attributes, ctx, (handler, config) => {
|
|
135
|
+
const items = handler.numericCompleter?.(config, ctx);
|
|
136
|
+
if (!items) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
ans.push(...items.map(item => ({
|
|
140
|
+
value: item.label,
|
|
141
|
+
kind: typeDef.kind,
|
|
142
|
+
labelSuffix: item.labelSuffix,
|
|
143
|
+
detail: item.detail,
|
|
144
|
+
completionKind: item.kind,
|
|
145
|
+
insertText: item.insertText,
|
|
146
|
+
sortText: item.sortText,
|
|
147
|
+
})));
|
|
148
|
+
});
|
|
149
|
+
return ans;
|
|
150
|
+
}
|
|
123
151
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spyglassmc/mcdoc",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.11",
|
|
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.8",
|
|
29
|
+
"@spyglassmc/locales": "0.3.8"
|
|
30
30
|
}
|
|
31
31
|
}
|