diff --git a/__snapshots__/packages/mcdoc/test-out/__fixture__/dispatcher/random_number_generator.spec.js b/__snapshots__/packages/mcdoc/test-out/__fixture__/dispatcher/random_number_generator.spec.js index e94ebc9ac..2ebb3d3af 100644 --- a/__snapshots__/packages/mcdoc/test-out/__fixture__/dispatcher/random_number_generator.spec.js +++ b/__snapshots__/packages/mcdoc/test-out/__fixture__/dispatcher/random_number_generator.spec.js @@ -734,48 +734,8 @@ exports['mcdoc __fixture__ dispatcher/random number generator 1'] = { "rng": { "data": { "typeDef": { - "kind": "struct", - "fields": [ - { - "kind": "pair", - "key": "type", - "type": { - "kind": "union", - "members": [ - { - "kind": "literal", - "value": { - "kind": "string", - "value": "uniform" - } - }, - { - "kind": "literal", - "value": { - "kind": "string", - "value": "binomial" - } - } - ] - }, - "optional": true - }, - { - "kind": "spread", - "type": { - "kind": "dispatcher", - "parallelIndices": [ - { - "kind": "dynamic", - "accessor": [ - "type" - ] - } - ], - "registry": "minecraft:rng" - } - } - ] + "kind": "reference", + "path": "::test::RNG" } }, "definition": [ diff --git a/packages/json/src/completer/index.ts b/packages/json/src/completer/index.ts index 67654d5b1..027a30fbd 100644 --- a/packages/json/src/completer/index.ts +++ b/packages/json/src/completer/index.ts @@ -39,6 +39,7 @@ const object = core.completer.record({ core.CompletionItem.create(key, pair?.key ?? range, { kind: core.CompletionKind.Field, detail: mcdoc.McdocType.toString(field.type as core.Mutable), + documentation: field.desc, deprecated: field.deprecated, sortText: field.optional ? '$b' : '$a', // sort above hardcoded $schema filterText: `"${key}"`, @@ -83,11 +84,14 @@ function getValues( ctx: core.CompleterContext, ): core.CompletionItem[] { return mcdoc.runtime.completer.getValues(typeDef, ctx) - .map(({ value, labelSuffix, detail, kind, completionKind, insertText, sortText }) => + .map(( + { value, labelSuffix, detail, documentation, kind, completionKind, insertText, sortText }, + ) => core.CompletionItem.create(value, range, { kind: completionKind ?? core.CompletionKind.Value, labelSuffix, detail, + documentation, filterText: kind === 'string' ? `"${value}"` : value, insertText: kind === 'string' ? `"${insertText ?? value}"` : insertText ?? value, sortText, diff --git a/packages/language-server/src/util/toLS.ts b/packages/language-server/src/util/toLS.ts index 76d9bea8b..a913fad98 100644 --- a/packages/language-server/src/util/toLS.ts +++ b/packages/language-server/src/util/toLS.ts @@ -197,7 +197,7 @@ export function completionItem( kind: completion.kind, ...(completion.labelSuffix ? { labelDetails: { detail: completion.labelSuffix } } : {}), detail: completion.detail, - documentation: completion.documentation, + documentation: completion.documentation ? markupContent(completion.documentation) : undefined, filterText: completion.filterText, sortText: completion.sortText, textEdit, diff --git a/packages/mcdoc-cli/src/commands/locale.ts b/packages/mcdoc-cli/src/commands/locale.ts index 9f87a432f..1a71906ab 100644 --- a/packages/mcdoc-cli/src/commands/locale.ts +++ b/packages/mcdoc-cli/src/commands/locale.ts @@ -48,11 +48,11 @@ export async function localeCommand(args: Args) { collect(name, member) }) } else if (type.kind === 'enum') { - // for (const field of type.values) { - // if (field.desc) { - // add(`${name}.${field.identifier}`, field.desc) - // } - // } + for (const field of type.values) { + if (field.desc) { + add(`${name}.${field.identifier}`, field.desc) + } + } } else if (type.kind === 'list') { collect(name, type.item) } else if (type.kind === 'tuple') { diff --git a/packages/mcdoc/src/binder/index.ts b/packages/mcdoc/src/binder/index.ts index a98f438be..80c6bd41f 100644 --- a/packages/mcdoc/src/binder/index.ts +++ b/packages/mcdoc/src/binder/index.ts @@ -21,7 +21,6 @@ import { traversePreOrder, } from '@spyglassmc/core' import { localeQuote, localize } from '@spyglassmc/locales' -import type { AdditionalContext } from '../common.js' import type { AnyTypeNode, AttributeValueNode, @@ -96,10 +95,12 @@ import type { StructTypeField, StructTypePairField, StructTypeSpreadField, - UseStatementBindingData, } from '../type/index.js' -interface McdocBinderContext extends BinderContext, AdditionalContext {} +interface McdocBinderContext extends BinderContext { + moduleIdentifier: string + isHoisting?: boolean +} interface ModuleSymbolData { nextAnonymousIndex: number @@ -124,6 +125,10 @@ export namespace TypeDefSymbolData { } } +interface UseStatementBindingData { + target: readonly string[] +} + export const fileModule = AsyncBinder.create(async (node, ctx) => { const moduleIdentifier = uriToIdentifier(ctx.doc.uri, ctx) if (!moduleIdentifier) { @@ -145,7 +150,7 @@ export async function module_(node: ModuleNode, ctx: McdocBinderContext): Promis data: { data }, }) - hoist(node, ctx) + hoist(node, { ...ctx, isHoisting: true }) for (const child of node.children) { switch (child.type) { @@ -847,6 +852,11 @@ function convertTypeArgBlock(node: TypeArgBlockNode, ctx: McdocBinderContext): M function convertEnum(node: EnumNode, ctx: McdocBinderContext): McdocType { const { block, enumKind, identifier } = EnumNode.destruct(node) + // Return reference if the enum has been hoisted + if (identifier && !ctx.isHoisting) { + return { kind: 'reference', path: `${ctx.moduleIdentifier}::${identifier.value}` } + } + // Shortcut if the typeDef has been added to the enum symbol. const symbol = identifier?.symbol ?? node.symbol if (symbol && TypeDefSymbolData.is(symbol.data) && symbol.data.typeDef.kind === 'enum') { @@ -862,9 +872,10 @@ function convertEnumBlock(node: EnumBlockNode, ctx: McdocBinderContext): EnumTyp } function convertEnumField(node: EnumFieldNode, ctx: McdocBinderContext): EnumTypeField { - const { attributes, identifier, value } = EnumFieldNode.destruct(node) + const { attributes, docComments, identifier, value } = EnumFieldNode.destruct(node) return { attributes: convertAttributes(attributes, ctx), + desc: DocCommentsNode.asText(docComments), identifier: identifier.value, value: convertEnumValue(value, ctx), } @@ -881,6 +892,11 @@ function convertEnumValue(node: EnumValueNode, ctx: McdocBinderContext): string function convertStruct(node: StructNode, ctx: McdocBinderContext): McdocType { const { block, identifier } = StructNode.destruct(node) + // Return reference if the struct has been hoisted + if (identifier && !ctx.isHoisting) { + return { kind: 'reference', path: `${ctx.moduleIdentifier}::${identifier.value}` } + } + // Shortcut if the typeDef has been added to the struct symbol. const symbol = identifier?.symbol ?? node.symbol if (symbol && TypeDefSymbolData.is(symbol.data) && symbol.data.typeDef.kind === 'struct') { diff --git a/packages/mcdoc/src/common.ts b/packages/mcdoc/src/common.ts index 9755b5a51..ae1d0e0dd 100644 --- a/packages/mcdoc/src/common.ts +++ b/packages/mcdoc/src/common.ts @@ -13,7 +13,3 @@ export function identifierToSeg(identifier: string): Segments { export function segToIdentifier(seg: Segments): string { return `::${seg.join('::')}` } - -export interface AdditionalContext { - moduleIdentifier: string -} diff --git a/packages/mcdoc/src/node/index.ts b/packages/mcdoc/src/node/index.ts index 57f6fc0ed..ffbe00e2e 100644 --- a/packages/mcdoc/src/node/index.ts +++ b/packages/mcdoc/src/node/index.ts @@ -622,9 +622,15 @@ export interface EnumFieldNode extends AstNode { export namespace EnumFieldNode { export function destruct( node: EnumFieldNode, - ): { attributes: AttributeNode[]; identifier: IdentifierNode; value: EnumValueNode } { + ): { + attributes: AttributeNode[] + docComments?: DocCommentsNode + identifier: IdentifierNode + value: EnumValueNode + } { return { attributes: node.children.filter(AttributeNode.is), + docComments: node.children.find(DocCommentsNode.is), identifier: node.children.find(IdentifierNode.is)!, value: node.children.find(EnumValueNode.is)!, } diff --git a/packages/mcdoc/src/runtime/completer/index.ts b/packages/mcdoc/src/runtime/completer/index.ts index ac17091c5..02414c1b9 100644 --- a/packages/mcdoc/src/runtime/completer/index.ts +++ b/packages/mcdoc/src/runtime/completer/index.ts @@ -61,6 +61,7 @@ export function getFields( export type SimpleCompletionValue = { value: string detail?: string + documentation?: string labelSuffix?: string kind?: McdocType['kind'] completionKind?: core.CompletionKind @@ -131,6 +132,7 @@ export function getValues( value: `${v.value}`, detail: v.identifier, kind: typeDef.enumKind ?? 'string', + documentation: v.desc, })) case 'byte': case 'short': diff --git a/packages/mcdoc/src/type/index.ts b/packages/mcdoc/src/type/index.ts index 1f78f4a6b..3375adb3f 100644 --- a/packages/mcdoc/src/type/index.ts +++ b/packages/mcdoc/src/type/index.ts @@ -217,6 +217,7 @@ export interface EnumType extends McdocBaseType { export interface EnumTypeField extends McdocBaseType { identifier: string value: string | number + desc?: string } export interface ReferenceType extends McdocBaseType { @@ -611,7 +612,3 @@ export namespace McdocType { return attributesString + typeString } } - -export interface UseStatementBindingData { - target: readonly string[] -} diff --git a/packages/nbt/src/completer/index.ts b/packages/nbt/src/completer/index.ts index 9b2d19780..f9f30c0f3 100644 --- a/packages/nbt/src/completer/index.ts +++ b/packages/nbt/src/completer/index.ts @@ -44,6 +44,7 @@ const compound = core.completer.record( core.CompletionItem.create(key, pair?.key ?? range, { kind: core.CompletionKind.Field, detail: mcdoc.McdocType.toString(field.type as core.Mutable), + documentation: field.desc, deprecated: field.deprecated, sortText: field.optional ? '$b' : '$a', // sort above hardcoded $schema filterText: formatKey(key, pair?.key?.quote), @@ -126,6 +127,7 @@ function getPathKeys( core.CompletionItem.create(key, range, { kind: core.CompletionKind.Field, detail: mcdoc.McdocType.toString(field.type as core.Mutable), + documentation: field.desc, deprecated: field.deprecated, sortText: field.optional ? '$b' : '$a', // sort above hardcoded $schema filterText: formatKey(key, quote), @@ -140,11 +142,14 @@ function getValues( ctx: mcdoc.runtime.completer.McdocCompleterContext, ): core.CompletionItem[] { return mcdoc.runtime.completer.getValues(typeDef, ctx) - .map(({ value, labelSuffix, detail, kind, completionKind, insertText, sortText }) => + .map(( + { value, labelSuffix, detail, documentation, kind, completionKind, insertText, sortText }, + ) => core.CompletionItem.create(value, range, { kind: completionKind ?? core.CompletionKind.Value, labelSuffix, detail, + documentation, filterText: formatValue(value, kind), insertText: formatValue(insertText ?? value, kind), sortText,