diff --git a/vue-language-tools/vue-language-core/schemas/vue-tsconfig.schema.json b/vue-language-tools/vue-language-core/schemas/vue-tsconfig.schema.json index 36c79eddc..a6514b758 100644 --- a/vue-language-tools/vue-language-core/schemas/vue-tsconfig.schema.json +++ b/vue-language-tools/vue-language-core/schemas/vue-tsconfig.schema.json @@ -90,6 +90,11 @@ "never" ], "markdownDescription": "https://github.com/johnsoncodehk/volar/issues/1038, https://github.com/johnsoncodehk/volar/issues/1121" + }, + "experimentalRfc436": { + "type": "boolean", + "default": false, + "markdownDescription": "https://github.com/vuejs/rfcs/discussions/436" } } } diff --git a/vue-language-tools/vue-language-core/src/generators/script.ts b/vue-language-tools/vue-language-core/src/generators/script.ts index 4978cf7b7..fac9d7af3 100644 --- a/vue-language-tools/vue-language-core/src/generators/script.ts +++ b/vue-language-tools/vue-language-core/src/generators/script.ts @@ -245,7 +245,11 @@ export function generate( 0, { diagnostic: true }, ]); - codeGen.push('export default await (async () => {\n'); + codeGen.push('export default await (async '); + if (vueCompilerOptions.experimentalRfc436 && sfc.scriptSetup.generic) { + codeGen.push(`<${sfc.scriptSetup.generic}>`); + } + codeGen.push('() => {\n'); } codeGen.push('const __VLS_setup = async () => {\n'); @@ -377,12 +381,25 @@ export function generate( writeTemplate(); + codeGen.push(`return {} as typeof __VLS_Component`); if (htmlGen?.slotsNum) { - codeGen.push(`return {} as typeof __VLS_Component & (new () => { ${getSlotsPropertyName(vueVersion)}: ReturnType });\n`); + codeGen.push(` & (new () => { ${getSlotsPropertyName(vueVersion)}: ReturnType })`); } - else { - codeGen.push(`return {} as typeof __VLS_Component;\n`); + if (vueCompilerOptions.experimentalRfc436 && sfc.scriptSetup.generic) { + codeGen.push(` & (new <${sfc.scriptSetup.generic}>() => {\n`); + if (scriptSetupRanges.propsTypeArg) { + codeGen.push(`$props: `); + addVirtualCode('scriptSetup', scriptSetupRanges.propsTypeArg.start, scriptSetupRanges.propsTypeArg.end); + codeGen.push(`,\n`); + } + if (scriptSetupRanges.emitsTypeArg) { + codeGen.push(`$emit: `); + addVirtualCode('scriptSetup', scriptSetupRanges.emitsTypeArg.start, scriptSetupRanges.emitsTypeArg.end); + codeGen.push(`,\n`); + } + codeGen.push(`})`); } + codeGen.push(`;\n`); codeGen.push(`};\n`); codeGen.push(`return await __VLS_setup();\n`); diff --git a/vue-language-tools/vue-language-core/src/sourceFile.ts b/vue-language-tools/vue-language-core/src/sourceFile.ts index cf4f8552f..5b7ff7280 100644 --- a/vue-language-tools/vue-language-core/src/sourceFile.ts +++ b/vue-language-tools/vue-language-core/src/sourceFile.ts @@ -440,6 +440,7 @@ export class VueSourceFile implements SourceFile { endTagStart: block.loc.end.offset, content: block.content, lang: block.lang ?? 'js', + generic: typeof block.attrs.generic === 'string' ? block.attrs.generic : undefined, } : null; if (self.sfc.scriptSetup && newData) { diff --git a/vue-language-tools/vue-language-core/src/types.ts b/vue-language-tools/vue-language-core/src/types.ts index 321355bed..bd6b6aec1 100644 --- a/vue-language-tools/vue-language-core/src/types.ts +++ b/vue-language-tools/vue-language-core/src/types.ts @@ -30,6 +30,7 @@ export interface ResolvedVueCompilerOptions { experimentalTemplateCompilerOptions: any; experimentalTemplateCompilerOptionsRequirePath: string | undefined; experimentalResolveStyleCssClasses: 'scoped' | 'always' | 'never'; + experimentalRfc436: boolean; } export type VueLanguagePlugin = (ctx: { @@ -66,7 +67,10 @@ export interface Sfc { script: (SfcBlock & { src: string | undefined; }) | null; - scriptSetup: SfcBlock | null; + scriptSetup: SfcBlock & { + // https://github.com/vuejs/rfcs/discussions/436 + generic: string | undefined; + } | null; styles: (SfcBlock & { module: string | undefined; scoped: boolean; diff --git a/vue-language-tools/vue-language-core/src/utils/ts.ts b/vue-language-tools/vue-language-core/src/utils/ts.ts index a12e90900..1408c4f9b 100644 --- a/vue-language-tools/vue-language-core/src/utils/ts.ts +++ b/vue-language-tools/vue-language-core/src/utils/ts.ts @@ -98,6 +98,7 @@ export function resolveVueCompilerOptions(vueOptions: VueCompilerOptions): Resol experimentalTemplateCompilerOptions: vueOptions.experimentalTemplateCompilerOptions ?? {}, experimentalTemplateCompilerOptionsRequirePath: vueOptions.experimentalTemplateCompilerOptionsRequirePath ?? undefined, experimentalResolveStyleCssClasses: vueOptions.experimentalResolveStyleCssClasses ?? 'scoped', + experimentalRfc436: vueOptions.experimentalRfc436 ?? false, }; }