diff --git a/packages/language-core/lib/codegen/script/scriptSetup.ts b/packages/language-core/lib/codegen/script/scriptSetup.ts index d8235fd792..8b21666f86 100644 --- a/packages/language-core/lib/codegen/script/scriptSetup.ts +++ b/packages/language-core/lib/codegen/script/scriptSetup.ts @@ -211,7 +211,7 @@ function* generateSetupFunction( [` as __VLS_TemplateResult['attrs'] & Record)`], callExp.end, callExp.end - ]) + ]); } for (const { callExp, exp, arg } of scriptSetupRanges.useCssModule) { setupCodeModifies.push([ @@ -234,6 +234,17 @@ function* generateSetupFunction( callExp.end ]); } + for (const { callExp } of scriptSetupRanges.useSlots) { + setupCodeModifies.push([ + [`(`], + callExp.start, + callExp.start + ], [ + [` as __VLS_TemplateResult['slots'])`], + callExp.end, + callExp.end + ]); + } const isTs = options.lang !== 'js' && options.lang !== 'jsx'; for (const { callExp, exp, arg } of scriptSetupRanges.useTemplateRef) { const templateRefType = arg ? [ diff --git a/packages/language-core/lib/codegen/script/template.ts b/packages/language-core/lib/codegen/script/template.ts index ad493af3b3..348e1f0dd5 100644 --- a/packages/language-core/lib/codegen/script/template.ts +++ b/packages/language-core/lib/codegen/script/template.ts @@ -62,7 +62,7 @@ function* generateTemplateComponents(options: ScriptCodegenOptions): Generator { ` + getSlotsPropertyName(options.vueCompilerOptions.target) - + ` : typeof ${options.scriptSetupRanges?.defineSlots?.name ?? `__VLS_slots`} }) }` + + `: typeof ${options.scriptSetupRanges?.defineSlots?.name ?? `__VLS_slots`} }) }` ); } diff --git a/packages/language-core/lib/codegen/template/index.ts b/packages/language-core/lib/codegen/template/index.ts index 17ddef19d8..4818b253e1 100644 --- a/packages/language-core/lib/codegen/template/index.ts +++ b/packages/language-core/lib/codegen/template/index.ts @@ -1,6 +1,7 @@ import * as CompilerDOM from '@vue/compiler-dom'; import type * as ts from 'typescript'; import type { Code, Sfc, VueCompilerOptions } from '../../types'; +import { getSlotsPropertyName } from '../../utils/shared'; import { endOfLine, newLine, wrapWith } from '../utils'; import { generateStringLiteralKey } from '../utils/stringLiteralKey'; import { TemplateCodegenContext, createTemplateCodegenContext } from './context'; @@ -34,9 +35,10 @@ export function* generateTemplate(options: TemplateCodegenOptions): Generator { - for (const { expVar, varName } of ctx.dynamicSlots) { - ctx.hasSlot = true; - yield `Partial, (_: typeof ${varName}) => any>> &${newLine}`; - } - yield `{${newLine}`; - for (const slot of ctx.slots) { - ctx.hasSlot = true; - if (slot.name && slot.loc !== undefined) { - yield* generateObjectProperty( - options, - ctx, - slot.name, - slot.loc, - ctx.codeFeatures.withoutHighlightAndCompletion, - slot.nodeLoc - ); +function* generateSlots(options: TemplateCodegenOptions, ctx: TemplateCodegenContext): Generator { + if (!options.hasDefineSlots) { + yield `var __VLS_slots!: `; + for (const { expVar, varName } of ctx.dynamicSlots) { + ctx.hasSlot = true; + yield `Partial, (_: typeof ${varName}) => any>> &${newLine}`; } - else { - yield* wrapWith( - slot.tagRange[0], - slot.tagRange[1], - ctx.codeFeatures.withoutHighlightAndCompletion, - `default` - ); + yield `{${newLine}`; + for (const slot of ctx.slots) { + ctx.hasSlot = true; + if (slot.name && slot.loc !== undefined) { + yield* generateObjectProperty( + options, + ctx, + slot.name, + slot.loc, + ctx.codeFeatures.withoutHighlightAndCompletion, + slot.nodeLoc + ); + } + else { + yield* wrapWith( + slot.tagRange[0], + slot.tagRange[1], + ctx.codeFeatures.withoutHighlightAndCompletion, + `default` + ); + } + yield `?(_: typeof ${slot.varName}): any,${newLine}`; } - yield `?(_: typeof ${slot.varName}): any,${newLine}`; + yield `}${endOfLine}`; } - yield `}`; + const name = getSlotsPropertyName(options.vueCompilerOptions.target); + yield `var ${name}!: typeof ${options.slotsAssignName ?? '__VLS_slots'}${endOfLine}`; } function* generateInheritedAttrs(ctx: TemplateCodegenContext): Generator { diff --git a/packages/language-core/lib/parsers/scriptSetupRanges.ts b/packages/language-core/lib/parsers/scriptSetupRanges.ts index 5866612611..7c1b40bd14 100644 --- a/packages/language-core/lib/parsers/scriptSetupRanges.ts +++ b/packages/language-core/lib/parsers/scriptSetupRanges.ts @@ -54,6 +54,8 @@ type UseAttrs = CallExpressionRange; type UseCssModule = CallExpressionRange; +type UseSlots = CallExpressionRange; + type UseTemplateRef = CallExpressionRange & { name?: string; } @@ -74,6 +76,7 @@ export function parseScriptSetupRanges( let defineOptions: DefineOptions | undefined; const useAttrs: UseAttrs[] = []; const useCssModule: UseCssModule[] = []; + const useSlots: UseSlots[] = []; const useTemplateRef: UseTemplateRef[] = []; const definePropProposalA = vueCompilerOptions.experimentalDefinePropProposal === 'kevinEdition' || ast.text.trimStart().startsWith('// @experimentalDefinePropProposal=kevinEdition'); const definePropProposalB = vueCompilerOptions.experimentalDefinePropProposal === 'johnsonEdition' || ast.text.trimStart().startsWith('// @experimentalDefinePropProposal=johnsonEdition'); @@ -145,6 +148,7 @@ export function parseScriptSetupRanges( defineOptions, useAttrs, useCssModule, + useSlots, useTemplateRef, }; @@ -390,6 +394,9 @@ export function parseScriptSetupRanges( else if (vueCompilerOptions.composables.useCssModule.includes(callText)) { useCssModule.push(parseCallExpression(node)); } + else if (vueCompilerOptions.composables.useSlots.includes(callText)) { + useSlots.push(parseCallExpression(node)); + } else if ( vueCompilerOptions.composables.useTemplateRef.includes(callText) && !node.typeArguments?.length diff --git a/packages/language-core/lib/types.ts b/packages/language-core/lib/types.ts index 46c91ba83c..bcee20d441 100644 --- a/packages/language-core/lib/types.ts +++ b/packages/language-core/lib/types.ts @@ -46,6 +46,7 @@ export interface VueCompilerOptions { composables: { useAttrs: string[]; useCssModule: string[]; + useSlots: string[]; useTemplateRef: string[]; }; plugins: VueLanguagePlugin[]; diff --git a/packages/language-core/lib/utils/ts.ts b/packages/language-core/lib/utils/ts.ts index 1b308acfc9..e3607ba6bb 100644 --- a/packages/language-core/lib/utils/ts.ts +++ b/packages/language-core/lib/utils/ts.ts @@ -254,6 +254,7 @@ export function resolveVueCompilerOptions(vueOptions: Partial - @@ -38,8 +37,15 @@ declare const Comp: new (props: { value: T; }) => {