@spyglassmc/mcdoc 0.3.7 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/binder/index.js +122 -191
- package/lib/index.d.ts +1 -0
- package/lib/index.js +4 -4
- package/lib/node/index.d.ts +9 -4
- package/lib/node/index.js +77 -131
- package/lib/parser/index.d.ts +13 -1
- package/lib/parser/index.js +112 -190
- package/lib/runtime/attribute/builtin.d.ts +3 -0
- package/lib/runtime/attribute/builtin.js +130 -0
- package/lib/runtime/attribute/index.d.ts +22 -0
- package/lib/runtime/attribute/index.js +22 -0
- package/lib/runtime/attribute/validator.d.ts +16 -0
- package/lib/runtime/attribute/validator.js +85 -0
- package/lib/runtime/checker/context.d.ts +34 -0
- package/lib/runtime/checker/context.js +17 -0
- package/lib/runtime/checker/error.d.ts +70 -0
- package/lib/runtime/checker/error.js +352 -0
- package/lib/runtime/checker/index.d.ts +80 -0
- package/lib/runtime/checker/index.js +914 -0
- package/lib/runtime/completer/index.d.ts +20 -0
- package/lib/runtime/completer/index.js +123 -0
- package/lib/runtime/index.d.ts +5 -0
- package/lib/runtime/index.js +5 -0
- package/lib/type/index.d.ts +73 -92
- package/lib/type/index.js +341 -422
- package/lib/uri_processors.js +2 -8
- package/package.json +3 -3
package/lib/binder/index.js
CHANGED
|
@@ -4,18 +4,18 @@ import { AttributeNode, AttributeTreeNamedValuesNode, AttributeTreeNode, Attribu
|
|
|
4
4
|
var ModuleSymbolData;
|
|
5
5
|
(function (ModuleSymbolData) {
|
|
6
6
|
function is(data) {
|
|
7
|
-
return (!!data
|
|
8
|
-
typeof data === 'object'
|
|
9
|
-
typeof data.nextAnonymousIndex === 'number');
|
|
7
|
+
return (!!data
|
|
8
|
+
&& typeof data === 'object'
|
|
9
|
+
&& typeof data.nextAnonymousIndex === 'number');
|
|
10
10
|
}
|
|
11
11
|
ModuleSymbolData.is = is;
|
|
12
12
|
})(ModuleSymbolData || (ModuleSymbolData = {}));
|
|
13
13
|
export var TypeDefSymbolData;
|
|
14
14
|
(function (TypeDefSymbolData) {
|
|
15
15
|
function is(data) {
|
|
16
|
-
return (!!data
|
|
17
|
-
typeof data === 'object'
|
|
18
|
-
typeof data.typeDef === 'object');
|
|
16
|
+
return (!!data
|
|
17
|
+
&& typeof data === 'object'
|
|
18
|
+
&& typeof data.typeDef === 'object');
|
|
19
19
|
}
|
|
20
20
|
TypeDefSymbolData.is = is;
|
|
21
21
|
})(TypeDefSymbolData || (TypeDefSymbolData = {}));
|
|
@@ -25,17 +25,14 @@ export const fileModule = AsyncBinder.create(async (node, ctx) => {
|
|
|
25
25
|
ctx.err.report(localize('mcdoc.binder.out-of-root', localeQuote(ctx.doc.uri)), Range.Beginning, 0 /* ErrorSeverity.Hint */);
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
|
-
const mcdocCtx = {
|
|
29
|
-
...ctx,
|
|
30
|
-
moduleIdentifier,
|
|
31
|
-
};
|
|
28
|
+
const mcdocCtx = { ...ctx, moduleIdentifier };
|
|
32
29
|
return module_(node, mcdocCtx);
|
|
33
30
|
});
|
|
34
31
|
export async function module_(node, ctx) {
|
|
35
32
|
const data = { nextAnonymousIndex: 0 };
|
|
36
|
-
ctx.symbols
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
ctx.symbols.query({ doc: ctx.doc, node }, 'mcdoc', ctx.moduleIdentifier).amend({
|
|
34
|
+
data: { data },
|
|
35
|
+
});
|
|
39
36
|
hoist(node, ctx);
|
|
40
37
|
for (const child of node.children) {
|
|
41
38
|
switch (child.type) {
|
|
@@ -81,14 +78,10 @@ function hoist(node, ctx) {
|
|
|
81
78
|
}
|
|
82
79
|
});
|
|
83
80
|
function hoistEnum(node) {
|
|
84
|
-
hoistFor('enum', node, EnumNode.destruct, (n) => ({
|
|
85
|
-
typeDef: convertEnum(n, ctx),
|
|
86
|
-
}));
|
|
81
|
+
hoistFor('enum', node, EnumNode.destruct, (n) => ({ typeDef: convertEnum(n, ctx) }));
|
|
87
82
|
}
|
|
88
83
|
function hoistStruct(node) {
|
|
89
|
-
hoistFor('struct', node, StructNode.destruct, (n) => ({
|
|
90
|
-
typeDef: convertStruct(n, ctx),
|
|
91
|
-
}));
|
|
84
|
+
hoistFor('struct', node, StructNode.destruct, (n) => ({ typeDef: convertStruct(n, ctx) }));
|
|
92
85
|
}
|
|
93
86
|
function hoistTypeAlias(node) {
|
|
94
87
|
hoistFor('type_alias', node, TypeAliasNode.destruct, (n) => {
|
|
@@ -100,7 +93,7 @@ function hoist(node, ctx) {
|
|
|
100
93
|
if (typeParams) {
|
|
101
94
|
bindTypeParamBlock(node, typeParams, ans, ctx);
|
|
102
95
|
}
|
|
103
|
-
|
|
96
|
+
appendAttributes(ans.typeDef, attributes, ctx);
|
|
104
97
|
return ans;
|
|
105
98
|
});
|
|
106
99
|
}
|
|
@@ -115,16 +108,15 @@ function hoist(node, ctx) {
|
|
|
115
108
|
return;
|
|
116
109
|
}
|
|
117
110
|
// hoistUseStatement associates the AST node with the binding definition in the file symbol table,
|
|
118
|
-
// which
|
|
111
|
+
// which will get overridden by bindUseStatement in the later stage as an reference to the imported symbol in the global symbol table.
|
|
119
112
|
// This way when the user tries to go to definition on the path in the use statement,
|
|
120
113
|
// they will go to the definition in the imported file.
|
|
121
|
-
ctx
|
|
122
|
-
|
|
123
|
-
.ifDeclared((symbol) => reportDuplicatedDeclaration(ctx, symbol, identifier))
|
|
124
|
-
.elseEnter({
|
|
114
|
+
const target = resolvePath(path, ctx);
|
|
115
|
+
ctx.symbols.query({ doc: ctx.doc, node }, 'mcdoc', `${ctx.moduleIdentifier}::${identifier.value}`).ifDeclared((symbol) => reportDuplicatedDeclaration(ctx, symbol, identifier)).elseEnter({
|
|
125
116
|
data: {
|
|
126
117
|
subcategory: 'use_statement_binding',
|
|
127
118
|
visibility: 1 /* SymbolVisibility.File */,
|
|
119
|
+
data: target ? { target } : undefined,
|
|
128
120
|
},
|
|
129
121
|
usage: { type: 'definition', node: identifier, fullRange: node },
|
|
130
122
|
});
|
|
@@ -132,15 +124,10 @@ function hoist(node, ctx) {
|
|
|
132
124
|
function hoistFor(subcategory, node, destructor, getData) {
|
|
133
125
|
const { docComments, identifier, keyword } = destructor(node);
|
|
134
126
|
const name = identifier?.value ?? nextAnonymousIdentifier(node, ctx);
|
|
135
|
-
ctx.symbols
|
|
136
|
-
.query({ doc: ctx.doc, node }, 'mcdoc', `${ctx.moduleIdentifier}::${name}`)
|
|
127
|
+
ctx.symbols.query({ doc: ctx.doc, node }, 'mcdoc', `${ctx.moduleIdentifier}::${name}`)
|
|
137
128
|
.ifDeclared((symbol) => reportDuplicatedDeclaration(ctx, symbol, identifier ?? node))
|
|
138
129
|
.elseEnter({
|
|
139
|
-
data: {
|
|
140
|
-
data: getData(node),
|
|
141
|
-
desc: DocCommentsNode.asText(docComments),
|
|
142
|
-
subcategory,
|
|
143
|
-
},
|
|
130
|
+
data: { data: getData(node), desc: DocCommentsNode.asText(docComments), subcategory },
|
|
144
131
|
// If the current syntax structure is named, then the identifier node is entered as a definition;
|
|
145
132
|
// otherwise, an anonymous identifier is generated for the symbol and the keyword node is entered as a definition.
|
|
146
133
|
usage: {
|
|
@@ -151,9 +138,7 @@ function hoist(node, ctx) {
|
|
|
151
138
|
});
|
|
152
139
|
}
|
|
153
140
|
function nextAnonymousIndex(node, ctx) {
|
|
154
|
-
const data = ctx.symbols
|
|
155
|
-
.query({ doc: ctx.doc, node }, 'mcdoc', ctx.moduleIdentifier)
|
|
156
|
-
.getData(ModuleSymbolData.is);
|
|
141
|
+
const data = ctx.symbols.query({ doc: ctx.doc, node }, 'mcdoc', ctx.moduleIdentifier).getData(ModuleSymbolData.is);
|
|
157
142
|
if (!data) {
|
|
158
143
|
throw new Error(`No symbol data for module '${ctx.moduleIdentifier}'`);
|
|
159
144
|
}
|
|
@@ -171,27 +156,16 @@ function bindTypeParamBlock(node, typeParams, data, ctx) {
|
|
|
171
156
|
// Thus we create a new local scope on the type alias statement node first.
|
|
172
157
|
node.locals = Object.create(null);
|
|
173
158
|
// They are also added to the type definition.
|
|
174
|
-
data.typeDef = {
|
|
175
|
-
kind: 'template',
|
|
176
|
-
child: data.typeDef,
|
|
177
|
-
typeParams: [],
|
|
178
|
-
};
|
|
159
|
+
data.typeDef = { kind: 'template', child: data.typeDef, typeParams: [] };
|
|
179
160
|
const { params } = TypeParamBlockNode.destruct(typeParams);
|
|
180
161
|
for (const param of params) {
|
|
181
162
|
const { identifier: paramIdentifier } = TypeParamNode.destruct(param);
|
|
182
163
|
if (paramIdentifier.value) {
|
|
183
164
|
// Add the type parameter as a local symbol.
|
|
184
165
|
const paramPath = `${ctx.moduleIdentifier}::${paramIdentifier.value}`;
|
|
185
|
-
ctx.symbols
|
|
186
|
-
.query({ doc: ctx.doc, node }, 'mcdoc', paramPath)
|
|
187
|
-
.ifDeclared((symbol) => reportDuplicatedDeclaration(ctx, symbol, paramIdentifier))
|
|
188
|
-
.elseEnter({
|
|
166
|
+
ctx.symbols.query({ doc: ctx.doc, node }, 'mcdoc', paramPath).ifDeclared((symbol) => reportDuplicatedDeclaration(ctx, symbol, paramIdentifier)).elseEnter({
|
|
189
167
|
data: { visibility: 0 /* SymbolVisibility.Block */ },
|
|
190
|
-
usage: {
|
|
191
|
-
type: 'declaration',
|
|
192
|
-
node: paramIdentifier,
|
|
193
|
-
fullRange: param,
|
|
194
|
-
},
|
|
168
|
+
usage: { type: 'declaration', node: paramIdentifier, fullRange: param },
|
|
195
169
|
});
|
|
196
170
|
// Also add it to the type definition.
|
|
197
171
|
data.typeDef.typeParams.push({ path: paramPath });
|
|
@@ -212,27 +186,19 @@ async function bindDispatchStatement(node, ctx) {
|
|
|
212
186
|
});
|
|
213
187
|
const { parallelIndices } = IndexBodyNode.destruct(index);
|
|
214
188
|
if (parallelIndices.length) {
|
|
215
|
-
const data = {
|
|
216
|
-
typeDef: convertType(target, ctx),
|
|
217
|
-
};
|
|
189
|
+
const data = { typeDef: convertType(target, ctx) };
|
|
218
190
|
if (typeParams) {
|
|
219
191
|
bindTypeParamBlock(node, typeParams, data, ctx);
|
|
220
192
|
}
|
|
221
|
-
|
|
193
|
+
appendAttributes(data.typeDef, attributes, ctx);
|
|
222
194
|
for (const key of parallelIndices) {
|
|
223
195
|
if (DynamicIndexNode.is(key)) {
|
|
224
196
|
// Ignore dynamic indices in dispatch statements.
|
|
225
197
|
continue;
|
|
226
198
|
}
|
|
227
|
-
ctx.symbols
|
|
228
|
-
.query(ctx.doc, 'mcdoc/dispatcher', locationStr, asString(key))
|
|
229
|
-
.ifDeclared((symbol) => reportDuplicatedDeclaration(ctx, symbol, key, {
|
|
199
|
+
ctx.symbols.query(ctx.doc, 'mcdoc/dispatcher', locationStr, asString(key)).ifDeclared((symbol) => reportDuplicatedDeclaration(ctx, symbol, key, {
|
|
230
200
|
localeString: 'mcdoc.binder.dispatcher-statement.duplicated-key',
|
|
231
|
-
}))
|
|
232
|
-
.elseEnter({
|
|
233
|
-
data: { data },
|
|
234
|
-
usage: { type: 'definition', node: key, fullRange: node },
|
|
235
|
-
});
|
|
201
|
+
})).elseEnter({ data: { data }, usage: { type: 'definition', node: key, fullRange: node } });
|
|
236
202
|
}
|
|
237
203
|
}
|
|
238
204
|
await bindType(target, ctx);
|
|
@@ -280,9 +246,9 @@ async function bindType(node, ctx) {
|
|
|
280
246
|
async function bindDispatcherType(node, ctx) {
|
|
281
247
|
const { index, location } = DispatcherTypeNode.destruct(node);
|
|
282
248
|
const locationStr = ResourceLocationNode.toString(location, 'full');
|
|
283
|
-
ctx.symbols
|
|
284
|
-
|
|
285
|
-
|
|
249
|
+
ctx.symbols.query(ctx.doc, 'mcdoc/dispatcher', locationStr).enter({
|
|
250
|
+
usage: { type: 'reference', node: location, fullRange: node },
|
|
251
|
+
});
|
|
286
252
|
const { parallelIndices } = IndexBodyNode.destruct(index);
|
|
287
253
|
for (const key of parallelIndices) {
|
|
288
254
|
if (DynamicIndexNode.is(key)) {
|
|
@@ -290,13 +256,15 @@ async function bindDispatcherType(node, ctx) {
|
|
|
290
256
|
// of struct keys, it is rather complicated to do so. We will ignore them for now.
|
|
291
257
|
continue;
|
|
292
258
|
}
|
|
293
|
-
ctx.symbols
|
|
294
|
-
|
|
295
|
-
|
|
259
|
+
ctx.symbols.query(ctx.doc, 'mcdoc/dispatcher', locationStr, asString(key)).enter({
|
|
260
|
+
usage: { type: 'reference', node: key, fullRange: node },
|
|
261
|
+
});
|
|
296
262
|
}
|
|
297
263
|
}
|
|
298
264
|
async function bindPath(node, ctx) {
|
|
299
|
-
for (const { identifiers, node: identNode, indexRight } of resolvePathByStep(node, ctx, {
|
|
265
|
+
for (const { identifiers, node: identNode, indexRight } of resolvePathByStep(node, ctx, {
|
|
266
|
+
reportErrors: true,
|
|
267
|
+
})) {
|
|
300
268
|
if (!identifiers?.length) {
|
|
301
269
|
continue;
|
|
302
270
|
}
|
|
@@ -310,8 +278,7 @@ async function bindPath(node, ctx) {
|
|
|
310
278
|
}
|
|
311
279
|
await ctx.ensureBindingStarted(referencedModuleUri);
|
|
312
280
|
}
|
|
313
|
-
ctx.symbols
|
|
314
|
-
.query({ doc: ctx.doc, node: identNode }, 'mcdoc', pathArrayToString(identifiers))
|
|
281
|
+
ctx.symbols.query({ doc: ctx.doc, node: identNode }, 'mcdoc', pathArrayToString(identifiers))
|
|
315
282
|
.ifDeclared((_, query) => query.enter({
|
|
316
283
|
usage: {
|
|
317
284
|
type: 'reference',
|
|
@@ -319,8 +286,7 @@ async function bindPath(node, ctx) {
|
|
|
319
286
|
fullRange: node,
|
|
320
287
|
skipRenaming: LiteralNode.is(identNode),
|
|
321
288
|
},
|
|
322
|
-
}))
|
|
323
|
-
.else(() => {
|
|
289
|
+
})).else(() => {
|
|
324
290
|
if (indexRight === 0) {
|
|
325
291
|
ctx.err.report(localize('mcdoc.binder.path.unknown-identifier', localeQuote(atArray(identifiers, -1)), localeQuote(pathArrayToString(identifiers.slice(0, -1)))), node, 2 /* ErrorSeverity.Warning */);
|
|
326
292
|
}
|
|
@@ -341,15 +307,8 @@ function bindEnumBlock(node, ctx, query, options = {}) {
|
|
|
341
307
|
const { fields } = EnumBlockNode.destruct(node);
|
|
342
308
|
for (const field of fields) {
|
|
343
309
|
const { identifier } = EnumFieldNode.destruct(field);
|
|
344
|
-
query.member(identifier.value, (fieldQuery) => fieldQuery
|
|
345
|
-
.
|
|
346
|
-
.elseEnter({
|
|
347
|
-
usage: {
|
|
348
|
-
type: 'definition',
|
|
349
|
-
node: identifier,
|
|
350
|
-
fullRange: field,
|
|
351
|
-
},
|
|
352
|
-
}));
|
|
310
|
+
query.member(identifier.value, (fieldQuery) => fieldQuery.ifDeclared((symbol) => reportDuplicatedDeclaration(ctx, symbol, identifier))
|
|
311
|
+
.elseEnter({ usage: { type: 'definition', node: identifier, fullRange: field } }));
|
|
353
312
|
}
|
|
354
313
|
}
|
|
355
314
|
async function bindInjection(node, ctx) {
|
|
@@ -376,11 +335,8 @@ async function bindStructBlock(node, ctx, query, options = {}) {
|
|
|
376
335
|
if (StructPairFieldNode.is(field)) {
|
|
377
336
|
const { key, type } = StructPairFieldNode.destruct(field);
|
|
378
337
|
if (!StructMapKeyNode.is(key)) {
|
|
379
|
-
query.member(key.value, (fieldQuery) => fieldQuery
|
|
380
|
-
.
|
|
381
|
-
.elseEnter({
|
|
382
|
-
usage: { type: 'definition', node: key, fullRange: field },
|
|
383
|
-
}));
|
|
338
|
+
query.member(key.value, (fieldQuery) => fieldQuery.ifDeclared((symbol) => reportDuplicatedDeclaration(ctx, symbol, key))
|
|
339
|
+
.elseEnter({ usage: { type: 'definition', node: key, fullRange: field } }));
|
|
384
340
|
}
|
|
385
341
|
await bindType(type, ctx);
|
|
386
342
|
}
|
|
@@ -411,23 +367,34 @@ export function registerMcdocBinders(meta) {
|
|
|
411
367
|
}
|
|
412
368
|
function reportDuplicatedDeclaration(ctx, symbol, range, options = { localeString: 'mcdoc.binder.duplicated-declaration' }) {
|
|
413
369
|
ctx.err.report(localize(options.localeString, localeQuote(symbol.identifier)), range, 2 /* ErrorSeverity.Warning */, {
|
|
414
|
-
related: [
|
|
415
|
-
{
|
|
370
|
+
related: [{
|
|
416
371
|
location: SymbolUtil.getDeclaredLocation(symbol),
|
|
417
372
|
message: localize(`${options.localeString}.related`, localeQuote(symbol.identifier)),
|
|
418
|
-
},
|
|
419
|
-
],
|
|
373
|
+
}],
|
|
420
374
|
});
|
|
421
375
|
}
|
|
422
376
|
function* resolvePathByStep(path, ctx, options = {}) {
|
|
423
377
|
const { children, isAbsolute } = PathNode.destruct(path);
|
|
424
|
-
|
|
425
|
-
? []
|
|
426
|
-
: ctx.moduleIdentifier.slice(2).split('::');
|
|
378
|
+
let identifiers = isAbsolute ? [] : pathStringToArray(ctx.moduleIdentifier);
|
|
427
379
|
for (const [i, child] of children.entries()) {
|
|
380
|
+
const indexRight = children.length - 1 - i;
|
|
428
381
|
switch (child.type) {
|
|
429
382
|
case 'mcdoc:identifier':
|
|
383
|
+
// For a path node with `n` children, the first `n-1` child nodes specify
|
|
384
|
+
// the path of the module that contains the symbol. They will be pushed
|
|
385
|
+
// to the `identifiers` array and yielded as-is. The last node, however,
|
|
386
|
+
// may be created by a use statement and points to a global symbol
|
|
387
|
+
// in a different file. We will query the symbol table and rewrite
|
|
388
|
+
// the `identifiers` array to be the target path if needed.
|
|
430
389
|
identifiers.push(child.value);
|
|
390
|
+
if (indexRight === 0) {
|
|
391
|
+
ctx.symbols.query({ doc: ctx.doc, node: child }, 'mcdoc', pathArrayToString(identifiers)).ifDeclared((symbol) => {
|
|
392
|
+
const data = symbol.data;
|
|
393
|
+
if (data?.target) {
|
|
394
|
+
identifiers = [...data.target];
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
}
|
|
431
398
|
break;
|
|
432
399
|
case 'mcdoc:literal':
|
|
433
400
|
// super
|
|
@@ -442,12 +409,7 @@ function* resolvePathByStep(path, ctx, options = {}) {
|
|
|
442
409
|
default:
|
|
443
410
|
Dev.assertNever(child);
|
|
444
411
|
}
|
|
445
|
-
yield {
|
|
446
|
-
identifiers,
|
|
447
|
-
node: child,
|
|
448
|
-
index: i,
|
|
449
|
-
indexRight: children.length - 1 - i,
|
|
450
|
-
};
|
|
412
|
+
yield { identifiers, node: child, index: i, indexRight };
|
|
451
413
|
}
|
|
452
414
|
}
|
|
453
415
|
function resolvePath(path, ctx, options = {}) {
|
|
@@ -458,13 +420,18 @@ function identifierToUri(module, ctx) {
|
|
|
458
420
|
}
|
|
459
421
|
function uriToIdentifier(uri, ctx) {
|
|
460
422
|
return Object.values(ctx.symbols.global.mcdoc ?? {}).find((symbol) => {
|
|
461
|
-
return (symbol.subcategory === 'module' &&
|
|
462
|
-
symbol.definition?.some((loc) => loc.uri === uri));
|
|
423
|
+
return (symbol.subcategory === 'module' && symbol.definition?.some((loc) => loc.uri === uri));
|
|
463
424
|
})?.identifier;
|
|
464
425
|
}
|
|
465
426
|
function pathArrayToString(path) {
|
|
466
427
|
return path ? `::${path.join('::')}` : undefined;
|
|
467
428
|
}
|
|
429
|
+
function pathStringToArray(path) {
|
|
430
|
+
if (!path.startsWith('::')) {
|
|
431
|
+
throw new Error('Only absolute paths are supported');
|
|
432
|
+
}
|
|
433
|
+
return path.slice(2).split('::');
|
|
434
|
+
}
|
|
468
435
|
function convertType(node, ctx) {
|
|
469
436
|
switch (node.type) {
|
|
470
437
|
case 'mcdoc:enum':
|
|
@@ -506,32 +473,25 @@ function wrapType(node, type, ctx, options = {}) {
|
|
|
506
473
|
options.skipFirstIndexBody = false;
|
|
507
474
|
continue;
|
|
508
475
|
}
|
|
509
|
-
ans = {
|
|
510
|
-
kind: 'indexed',
|
|
511
|
-
child: ans,
|
|
512
|
-
parallelIndices: convertIndexBody(appendix, ctx),
|
|
513
|
-
};
|
|
476
|
+
ans = { kind: 'indexed', child: ans, parallelIndices: convertIndexBody(appendix, ctx) };
|
|
514
477
|
}
|
|
515
478
|
else {
|
|
516
|
-
ans = {
|
|
517
|
-
kind: 'concrete',
|
|
518
|
-
child: ans,
|
|
519
|
-
typeArgs: convertTypeArgBlock(appendix, ctx),
|
|
520
|
-
};
|
|
479
|
+
ans = { kind: 'concrete', child: ans, typeArgs: convertTypeArgBlock(appendix, ctx) };
|
|
521
480
|
}
|
|
522
481
|
}
|
|
523
|
-
ans =
|
|
482
|
+
ans.attributes = convertAttributes(attributes, ctx);
|
|
524
483
|
return ans;
|
|
525
484
|
}
|
|
526
|
-
function
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
485
|
+
function appendAttributes(typeDef, attributes, ctx) {
|
|
486
|
+
const convertedAttributes = convertAttributes(attributes, ctx);
|
|
487
|
+
if (convertedAttributes) {
|
|
488
|
+
if (typeDef.attributes) {
|
|
489
|
+
typeDef.attributes = [...typeDef.attributes, ...convertedAttributes];
|
|
490
|
+
}
|
|
491
|
+
else {
|
|
492
|
+
typeDef.attributes = convertedAttributes;
|
|
493
|
+
}
|
|
533
494
|
}
|
|
534
|
-
return type;
|
|
535
495
|
}
|
|
536
496
|
function convertAttributes(nodes, ctx) {
|
|
537
497
|
return undefineEmptyArray(nodes.map((n) => convertAttribute(n, ctx)));
|
|
@@ -541,17 +501,11 @@ function undefineEmptyArray(array) {
|
|
|
541
501
|
}
|
|
542
502
|
function convertAttribute(node, ctx) {
|
|
543
503
|
const { name, value } = AttributeNode.destruct(node);
|
|
544
|
-
return {
|
|
545
|
-
name: name.value,
|
|
546
|
-
value: value && convertAttributeValue(value, ctx),
|
|
547
|
-
};
|
|
504
|
+
return { name: name.value, value: value && convertAttributeValue(value, ctx) };
|
|
548
505
|
}
|
|
549
506
|
function convertAttributeValue(node, ctx) {
|
|
550
507
|
if (node.type === 'mcdoc:attribute/tree') {
|
|
551
|
-
return {
|
|
552
|
-
kind: 'tree',
|
|
553
|
-
values: convertAttributeTree(node, ctx),
|
|
554
|
-
};
|
|
508
|
+
return { kind: 'tree', values: convertAttributeTree(node, ctx) };
|
|
555
509
|
}
|
|
556
510
|
else {
|
|
557
511
|
return convertType(node, ctx);
|
|
@@ -582,21 +536,21 @@ function convertIndexBody(node, ctx) {
|
|
|
582
536
|
return parallelIndices.map((n) => convertIndex(n, ctx));
|
|
583
537
|
}
|
|
584
538
|
function convertIndex(node, ctx) {
|
|
585
|
-
return StaticIndexNode.is(node)
|
|
586
|
-
? convertStaticIndex(node, ctx)
|
|
587
|
-
: convertDynamicIndex(node, ctx);
|
|
539
|
+
return StaticIndexNode.is(node) ? convertStaticIndex(node, ctx) : convertDynamicIndex(node, ctx);
|
|
588
540
|
}
|
|
589
541
|
function convertStaticIndex(node, ctx) {
|
|
590
|
-
return {
|
|
591
|
-
kind: 'static',
|
|
592
|
-
value: asString(node),
|
|
593
|
-
};
|
|
542
|
+
return { kind: 'static', value: asString(node) };
|
|
594
543
|
}
|
|
595
544
|
function convertDynamicIndex(node, ctx) {
|
|
596
545
|
const { keys } = DynamicIndexNode.destruct(node);
|
|
597
546
|
return {
|
|
598
547
|
kind: 'dynamic',
|
|
599
|
-
accessor: keys.map(
|
|
548
|
+
accessor: keys.map(key => {
|
|
549
|
+
if (LiteralNode.is(key) && key.value.startsWith('%')) {
|
|
550
|
+
return { keyword: key.value.slice(1) };
|
|
551
|
+
}
|
|
552
|
+
return asString(key);
|
|
553
|
+
}),
|
|
600
554
|
};
|
|
601
555
|
}
|
|
602
556
|
function convertTypeArgBlock(node, ctx) {
|
|
@@ -607,16 +561,10 @@ function convertEnum(node, ctx) {
|
|
|
607
561
|
const { block, enumKind, identifier } = EnumNode.destruct(node);
|
|
608
562
|
// Shortcut if the typeDef has been added to the enum symbol.
|
|
609
563
|
const symbol = identifier?.symbol ?? node.symbol;
|
|
610
|
-
if (symbol &&
|
|
611
|
-
TypeDefSymbolData.is(symbol.data) &&
|
|
612
|
-
symbol.data.typeDef.kind === 'enum') {
|
|
564
|
+
if (symbol && TypeDefSymbolData.is(symbol.data) && symbol.data.typeDef.kind === 'enum') {
|
|
613
565
|
return symbol.data.typeDef;
|
|
614
566
|
}
|
|
615
|
-
return wrapType(node, {
|
|
616
|
-
kind: 'enum',
|
|
617
|
-
enumKind,
|
|
618
|
-
values: convertEnumBlock(block, ctx),
|
|
619
|
-
}, ctx);
|
|
567
|
+
return wrapType(node, { kind: 'enum', enumKind, values: convertEnumBlock(block, ctx) }, ctx);
|
|
620
568
|
}
|
|
621
569
|
function convertEnumBlock(node, ctx) {
|
|
622
570
|
const { fields } = EnumBlockNode.destruct(node);
|
|
@@ -641,15 +589,10 @@ function convertStruct(node, ctx) {
|
|
|
641
589
|
const { block, identifier } = StructNode.destruct(node);
|
|
642
590
|
// Shortcut if the typeDef has been added to the struct symbol.
|
|
643
591
|
const symbol = identifier?.symbol ?? node.symbol;
|
|
644
|
-
if (symbol &&
|
|
645
|
-
TypeDefSymbolData.is(symbol.data) &&
|
|
646
|
-
symbol.data.typeDef.kind === 'struct') {
|
|
592
|
+
if (symbol && TypeDefSymbolData.is(symbol.data) && symbol.data.typeDef.kind === 'struct') {
|
|
647
593
|
return symbol.data.typeDef;
|
|
648
594
|
}
|
|
649
|
-
return wrapType(node, {
|
|
650
|
-
kind: 'struct',
|
|
651
|
-
fields: convertStructBlock(block, ctx),
|
|
652
|
-
}, ctx);
|
|
595
|
+
return wrapType(node, { kind: 'struct', fields: convertStructBlock(block, ctx) }, ctx);
|
|
653
596
|
}
|
|
654
597
|
function convertStructBlock(node, ctx) {
|
|
655
598
|
const { fields } = StructBlockNode.destruct(node);
|
|
@@ -661,10 +604,11 @@ function convertStructField(node, ctx) {
|
|
|
661
604
|
: convertStructSpreadField(node, ctx);
|
|
662
605
|
}
|
|
663
606
|
function convertStructPairField(node, ctx) {
|
|
664
|
-
const { attributes, key, type, isOptional } = StructPairFieldNode.destruct(node);
|
|
607
|
+
const { attributes, docComments, key, type, isOptional } = StructPairFieldNode.destruct(node);
|
|
665
608
|
return {
|
|
666
609
|
kind: 'pair',
|
|
667
610
|
attributes: convertAttributes(attributes, ctx),
|
|
611
|
+
desc: DocCommentsNode.asText(docComments),
|
|
668
612
|
key: convertStructKey(key, ctx),
|
|
669
613
|
type: convertType(type, ctx),
|
|
670
614
|
optional: isOptional,
|
|
@@ -688,14 +632,10 @@ function convertStructSpreadField(node, ctx) {
|
|
|
688
632
|
};
|
|
689
633
|
}
|
|
690
634
|
function convertAny(node, ctx) {
|
|
691
|
-
return wrapType(node, {
|
|
692
|
-
kind: 'any',
|
|
693
|
-
}, ctx);
|
|
635
|
+
return wrapType(node, { kind: 'any' }, ctx);
|
|
694
636
|
}
|
|
695
637
|
function convertBoolean(node, ctx) {
|
|
696
|
-
return wrapType(node, {
|
|
697
|
-
kind: 'boolean',
|
|
698
|
-
}, ctx);
|
|
638
|
+
return wrapType(node, { kind: 'boolean' }, ctx);
|
|
699
639
|
}
|
|
700
640
|
function convertDispatcher(node, ctx) {
|
|
701
641
|
const { index, location } = DispatcherTypeNode.destruct(node);
|
|
@@ -724,36 +664,40 @@ function convertRange(node, ctx) {
|
|
|
724
664
|
}
|
|
725
665
|
function convertLiteral(node, ctx) {
|
|
726
666
|
const { value } = LiteralTypeNode.destruct(node);
|
|
727
|
-
return wrapType(node, {
|
|
728
|
-
kind: 'literal',
|
|
729
|
-
value: convertLiteralValue(value, ctx),
|
|
730
|
-
}, ctx);
|
|
667
|
+
return wrapType(node, { kind: 'literal', value: convertLiteralValue(value, ctx) }, ctx);
|
|
731
668
|
}
|
|
732
669
|
function convertLiteralValue(node, ctx) {
|
|
733
670
|
if (LiteralNode.is(node)) {
|
|
734
|
-
return {
|
|
735
|
-
kind: 'boolean',
|
|
736
|
-
value: node.value === 'true',
|
|
737
|
-
};
|
|
671
|
+
return { kind: 'boolean', value: node.value === 'true' };
|
|
738
672
|
}
|
|
739
673
|
else if (TypedNumberNode.is(node)) {
|
|
740
674
|
const { suffix, value } = TypedNumberNode.destruct(node);
|
|
741
675
|
return {
|
|
742
|
-
kind:
|
|
676
|
+
kind: convertLiteralNumberSuffix(suffix, ctx)
|
|
677
|
+
?? (value.type === 'integer' ? 'int' : 'double'),
|
|
743
678
|
value: value.value,
|
|
744
|
-
suffix: convertLiteralNumberSuffix(suffix, ctx),
|
|
745
679
|
};
|
|
746
680
|
}
|
|
747
681
|
else {
|
|
748
|
-
return {
|
|
749
|
-
kind: 'string',
|
|
750
|
-
value: node.value,
|
|
751
|
-
};
|
|
682
|
+
return { kind: 'string', value: node.value };
|
|
752
683
|
}
|
|
753
684
|
}
|
|
754
685
|
function convertLiteralNumberSuffix(node, ctx) {
|
|
755
686
|
const suffix = node?.value;
|
|
756
|
-
|
|
687
|
+
switch (suffix?.toLowerCase()) {
|
|
688
|
+
case 'b':
|
|
689
|
+
return 'byte';
|
|
690
|
+
case 's':
|
|
691
|
+
return 'short';
|
|
692
|
+
case 'l':
|
|
693
|
+
return 'long';
|
|
694
|
+
case 'f':
|
|
695
|
+
return 'float';
|
|
696
|
+
case 'd':
|
|
697
|
+
return 'double';
|
|
698
|
+
default:
|
|
699
|
+
return undefined;
|
|
700
|
+
}
|
|
757
701
|
}
|
|
758
702
|
function convertNumericType(node, ctx) {
|
|
759
703
|
const { numericKind, valueRange } = NumericTypeNode.destruct(node);
|
|
@@ -763,8 +707,7 @@ function convertNumericType(node, ctx) {
|
|
|
763
707
|
}, ctx);
|
|
764
708
|
}
|
|
765
709
|
function convertPrimitiveArray(node, ctx) {
|
|
766
|
-
const { arrayKind, lengthRange, valueRange } = PrimitiveArrayTypeNode
|
|
767
|
-
.destruct(node);
|
|
710
|
+
const { arrayKind, lengthRange, valueRange } = PrimitiveArrayTypeNode.destruct(node);
|
|
768
711
|
return wrapType(node, {
|
|
769
712
|
kind: `${arrayKind.value}_array`,
|
|
770
713
|
lengthRange: convertRange(lengthRange, ctx),
|
|
@@ -773,31 +716,19 @@ function convertPrimitiveArray(node, ctx) {
|
|
|
773
716
|
}
|
|
774
717
|
function convertString(node, ctx) {
|
|
775
718
|
const { lengthRange } = StringTypeNode.destruct(node);
|
|
776
|
-
return wrapType(node, {
|
|
777
|
-
kind: 'string',
|
|
778
|
-
lengthRange: convertRange(lengthRange, ctx),
|
|
779
|
-
}, ctx);
|
|
719
|
+
return wrapType(node, { kind: 'string', lengthRange: convertRange(lengthRange, ctx) }, ctx);
|
|
780
720
|
}
|
|
781
721
|
function convertReference(node, ctx) {
|
|
782
722
|
const { path } = ReferenceTypeNode.destruct(node);
|
|
783
|
-
return wrapType(node, {
|
|
784
|
-
kind: 'reference',
|
|
785
|
-
path: pathArrayToString(resolvePath(path, ctx)),
|
|
786
|
-
}, ctx);
|
|
723
|
+
return wrapType(node, { kind: 'reference', path: pathArrayToString(resolvePath(path, ctx)) }, ctx);
|
|
787
724
|
}
|
|
788
725
|
function convertTuple(node, ctx) {
|
|
789
726
|
const { items } = TupleTypeNode.destruct(node);
|
|
790
|
-
return wrapType(node, {
|
|
791
|
-
kind: 'tuple',
|
|
792
|
-
items: items.map((n) => convertType(n, ctx)),
|
|
793
|
-
}, ctx);
|
|
727
|
+
return wrapType(node, { kind: 'tuple', items: items.map((n) => convertType(n, ctx)) }, ctx);
|
|
794
728
|
}
|
|
795
729
|
function convertUnion(node, ctx) {
|
|
796
730
|
const { members } = UnionTypeNode.destruct(node);
|
|
797
|
-
return wrapType(node, {
|
|
798
|
-
kind: 'union',
|
|
799
|
-
members: members.map((n) => convertType(n, ctx)),
|
|
800
|
-
}, ctx);
|
|
731
|
+
return wrapType(node, { kind: 'union', members: members.map((n) => convertType(n, ctx)) }, ctx);
|
|
801
732
|
}
|
|
802
733
|
function asString(node) {
|
|
803
734
|
if (ResourceLocationNode.is(node)) {
|
package/lib/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * as binder from './binder/index.js';
|
|
|
3
3
|
export * as colorizer from './colorizer/index.js';
|
|
4
4
|
export * from './node/index.js';
|
|
5
5
|
export * from './parser/index.js';
|
|
6
|
+
export * as runtime from './runtime/index.js';
|
|
6
7
|
export * from './type/index.js';
|
|
7
8
|
export * from './uri_processors.js';
|
|
8
9
|
export declare const initialize: ({ meta }: {
|
package/lib/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import * as binder from './binder/index.js';
|
|
2
2
|
import * as colorizer from './colorizer/index.js';
|
|
3
3
|
import * as parser from './parser/index.js';
|
|
4
|
+
import { registerBuiltinAttributes } from './runtime/attribute/builtin.js';
|
|
4
5
|
import * as uri_professors from './uri_processors.js';
|
|
5
6
|
export * as binder from './binder/index.js';
|
|
6
7
|
export * as colorizer from './colorizer/index.js';
|
|
7
8
|
export * from './node/index.js';
|
|
8
9
|
export * from './parser/index.js';
|
|
10
|
+
export * as runtime from './runtime/index.js';
|
|
9
11
|
export * from './type/index.js';
|
|
10
12
|
export * from './uri_processors.js';
|
|
11
13
|
/* istanbul ignore next */
|
|
12
14
|
export const initialize = ({ meta }) => {
|
|
13
|
-
meta.registerLanguage('mcdoc', {
|
|
14
|
-
|
|
15
|
-
parser: parser.module_,
|
|
16
|
-
});
|
|
15
|
+
meta.registerLanguage('mcdoc', { extensions: ['.mcdoc'], parser: parser.module_ });
|
|
16
|
+
registerBuiltinAttributes(meta);
|
|
17
17
|
meta.registerUriBinder(uri_professors.uriBinder);
|
|
18
18
|
meta.setUriSorter(uri_professors.uriSorter);
|
|
19
19
|
binder.registerMcdocBinders(meta);
|
package/lib/node/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AstNode, ColorTokenType,
|
|
2
|
-
import { CommentNode, FloatNode, ResourceLocationNode, StringNode } from '@spyglassmc/core';
|
|
1
|
+
import type { AstNode, ColorTokenType, SymbolBaseNode } from '@spyglassmc/core';
|
|
2
|
+
import { CommentNode, FloatNode, IntegerNode, ResourceLocationNode, StringNode } from '@spyglassmc/core';
|
|
3
3
|
export interface ModuleNode extends AstNode {
|
|
4
4
|
type: 'mcdoc:module';
|
|
5
5
|
children: TopLevelNode[];
|
|
@@ -185,11 +185,11 @@ export declare namespace LiteralTypeValueNode {
|
|
|
185
185
|
}
|
|
186
186
|
export interface TypedNumberNode extends AstNode {
|
|
187
187
|
type: 'mcdoc:typed_number';
|
|
188
|
-
children: (FloatNode | LiteralNode)[];
|
|
188
|
+
children: (FloatNode | IntegerNode | LiteralNode)[];
|
|
189
189
|
}
|
|
190
190
|
export declare namespace TypedNumberNode {
|
|
191
191
|
function destruct(node: TypedNumberNode): {
|
|
192
|
-
value: FloatNode;
|
|
192
|
+
value: FloatNode | IntegerNode;
|
|
193
193
|
suffix?: LiteralNode;
|
|
194
194
|
};
|
|
195
195
|
function is(node: AstNode | undefined): node is TypedNumberNode;
|
|
@@ -211,6 +211,10 @@ export declare const RangeExclusiveChar = "<";
|
|
|
211
211
|
* The bit is turned on if the range is exclusive on that end.
|
|
212
212
|
*/
|
|
213
213
|
export type RangeKind = 0b00 | 0b01 | 0b10 | 0b11;
|
|
214
|
+
export declare namespace RangeKind {
|
|
215
|
+
function isLeftExclusive(rangeKind: RangeKind): boolean;
|
|
216
|
+
function isRightExclusive(rangeKind: RangeKind): boolean;
|
|
217
|
+
}
|
|
214
218
|
export declare function getRangeDelimiter(kind: RangeKind): string;
|
|
215
219
|
export interface FloatRangeNode extends AstNode {
|
|
216
220
|
type: 'mcdoc:float_range';
|
|
@@ -395,6 +399,7 @@ export interface StructPairFieldNode extends AstNode {
|
|
|
395
399
|
export declare namespace StructPairFieldNode {
|
|
396
400
|
function destruct(node: StructPairFieldNode): {
|
|
397
401
|
attributes: AttributeNode[];
|
|
402
|
+
docComments?: DocCommentsNode;
|
|
398
403
|
key: StructKeyNode;
|
|
399
404
|
type: TypeNode;
|
|
400
405
|
isOptional?: boolean;
|