From e0892e61d9b59f0b0fa3e6069b6cb80edbdd4835 Mon Sep 17 00:00:00 2001 From: KazariEX <1364035137@qq.com> Date: Thu, 2 Jan 2025 21:55:00 +0800 Subject: [PATCH 1/2] feat: unwrap `__VLS_template` & type support of `useAttrs` --- .../lib/codegen/script/component.ts | 6 +- .../language-core/lib/codegen/script/index.ts | 2 - .../lib/codegen/script/scriptSetup.ts | 36 ++-- .../lib/codegen/script/template.ts | 10 +- .../tsc/tests/__snapshots__/dts.spec.ts.snap | 156 ++++++++---------- 5 files changed, 95 insertions(+), 115 deletions(-) diff --git a/packages/language-core/lib/codegen/script/component.ts b/packages/language-core/lib/codegen/script/component.ts index 04707b9967..d4552a8466 100644 --- a/packages/language-core/lib/codegen/script/component.ts +++ b/packages/language-core/lib/codegen/script/component.ts @@ -41,10 +41,10 @@ export function* generateComponent( yield generateSfcBlockSection(options.sfc.script, args.start + 1, args.end - 1, codeFeatures.all); } if (options.vueCompilerOptions.target >= 3.5 && options.templateCodegen?.templateRefs.size) { - yield `__typeRefs: {} as __VLS_TemplateResult['refs'],${newLine}`; + yield `__typeRefs: {} as __VLS_TemplateRefs,${newLine}`; } if (options.vueCompilerOptions.target >= 3.5 && options.templateCodegen?.singleRootElType) { - yield `__typeEl: {} as __VLS_TemplateResult['rootEl'],${newLine}`; + yield `__typeEl: {} as __VLS_TemplateEl,${newLine}`; } yield `})`; } @@ -154,7 +154,7 @@ export function* generatePropsOption( }); } if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size) { - let attrsType = `__VLS_TemplateResult['attrs']`; + let attrsType = `__VLS_TemplateAttrs`; if (hasEmitsOption) { attrsType = `Omit<${attrsType}, \`on\${string}\`>`; } diff --git a/packages/language-core/lib/codegen/script/index.ts b/packages/language-core/lib/codegen/script/index.ts index 9c975f325d..fd93e9c639 100644 --- a/packages/language-core/lib/codegen/script/index.ts +++ b/packages/language-core/lib/codegen/script/index.ts @@ -151,9 +151,7 @@ export function* generateScript(options: ScriptCodegenOptions): Generator & __VLS_BuiltInPublicProps,${newLine}` + + ` props: ${ctx.localTypes.PrettifyLocal}<__VLS_OwnProps & __VLS_PublicProps & __VLS_TemplateAttrs> & __VLS_BuiltInPublicProps,${newLine}` + ` expose(exposed: import('${options.vueCompilerOptions.lib}').ShallowUnwrapRef<${scriptSetupRanges.defineExpose ? 'typeof __VLS_exposed' : '{}'}>): void,${newLine}` + ` attrs: any,${newLine}` - + ` slots: __VLS_TemplateResult['slots'],${newLine}` + + ` slots: __VLS_TemplateSlots,${newLine}` + ` emit: ${emitTypes.length ? emitTypes.join(' & ') : `{}`},${newLine}` + `}${endOfLine}`; yield `})(),${newLine}`; // __VLS_setup = (async () => { @@ -170,18 +170,17 @@ function* generateSetupFunction( ]); } } - // TODO: circular reference - // for (const { callExp } of scriptSetupRanges.useAttrs) { - // setupCodeModifies.push([ - // [`(`], - // callExp.start, - // callExp.start - // ], [ - // [` as __VLS_TemplateResult['attrs'] & Record)`], - // callExp.end, - // callExp.end - // ]); - // } + for (const { callExp } of scriptSetupRanges.useAttrs) { + setupCodeModifies.push([ + [`(`], + callExp.start, + callExp.start + ], [ + [` as __VLS_TemplateAttrs & Record)`], + callExp.end, + callExp.end + ]); + } for (const { callExp, exp, arg } of scriptSetupRanges.useCssModule) { setupCodeModifies.push([ [`(`], @@ -216,7 +215,7 @@ function* generateSetupFunction( callExp.start, callExp.start ], [ - [` as __VLS_TemplateResult['slots'])`], + [` as __VLS_TemplateSlots)`], callExp.end, callExp.end ]); @@ -225,7 +224,7 @@ function* generateSetupFunction( for (const { callExp, exp, arg } of scriptSetupRanges.useTemplateRef) { const templateRefType = arg ? [ - `__VLS_TemplateResult['refs'][`, + `__VLS_TemplateRefs[`, generateSfcBlockSection(scriptSetup, arg.start, arg.end, codeFeatures.all), `]` ] @@ -294,11 +293,8 @@ function* generateSetupFunction( yield* generateComponentProps(options, ctx, scriptSetup, scriptSetupRanges); yield* generateModelEmit(scriptSetup, scriptSetupRanges); - yield `function __VLS_template() {${newLine}`; const templateCodegenCtx = yield* generateTemplate(options, ctx); - yield `}${endOfLine}`; yield* generateComponentSelf(options, ctx, templateCodegenCtx); - yield `type __VLS_TemplateResult = ReturnType${endOfLine}`; if (syntax) { if (!options.vueCompilerOptions.skipTemplateCodegen && (options.templateCodegen?.hasSlot || scriptSetupRanges.defineSlots)) { @@ -306,7 +302,7 @@ function* generateSetupFunction( yield* generateComponent(options, ctx, scriptSetup, scriptSetupRanges); yield endOfLine; yield `${syntax} `; - yield `{} as ${ctx.localTypes.WithTemplateSlots}${endOfLine}`; + yield `{} as ${ctx.localTypes.WithTemplateSlots}${endOfLine}`; } else { yield `${syntax} `; diff --git a/packages/language-core/lib/codegen/script/template.ts b/packages/language-core/lib/codegen/script/template.ts index 92a49bf7ac..2e6a356e77 100644 --- a/packages/language-core/lib/codegen/script/template.ts +++ b/packages/language-core/lib/codegen/script/template.ts @@ -131,12 +131,10 @@ function* generateTemplateBody( yield `const __VLS_rootEl = {} as any${endOfLine}`; } - yield `return {${newLine}`; - yield ` attrs: {} as Partial,${newLine}`; - yield ` slots: ${options.scriptSetupRanges?.defineSlots?.name ?? '__VLS_slots'},${newLine}`; - yield ` refs: __VLS_refs,${newLine}`; - yield ` rootEl: __VLS_rootEl,${newLine}`; - yield `}${endOfLine}`; + yield `type __VLS_TemplateAttrs = Partial${endOfLine}`; + yield `type __VLS_TemplateSlots = typeof ${options.scriptSetupRanges?.defineSlots?.name ?? '__VLS_slots'}${endOfLine}`; + yield `type __VLS_TemplateRefs = typeof __VLS_refs${endOfLine}`; + yield `type __VLS_TemplateEl = typeof __VLS_rootEl${endOfLine}`; } function* generateStyleScopedClasses( diff --git a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap index 6959c4430d..67887bcab3 100644 --- a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap +++ b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap @@ -617,27 +617,26 @@ export {}; `; exports[`vue-tsc-dts > Input: template-slots/component.vue, Output: template-slots/component.vue.d.ts 1`] = ` -"declare function __VLS_template(): { - attrs: Partial<{}>; - slots: { - 'no-bind'?(_: {}): any; - default?(_: { - num: number; - }): any; - 'named-slot'?(_: { - str: string; - }): any; - vbind?(_: { - num: number; - str: string; - }): any; - }; - refs: {}; - rootEl: any; +"declare var __VLS_0: {}; +declare var __VLS_1: { + num: number; +}; +declare var __VLS_2: { + str: string; }; -type __VLS_TemplateResult = ReturnType; +declare var __VLS_3: { + num: number; + str: string; +}; +declare var __VLS_slots: { + 'no-bind'?(_: typeof __VLS_0): any; + default?(_: typeof __VLS_1): any; + 'named-slot'?(_: typeof __VLS_2): any; + vbind?(_: typeof __VLS_3): any; +}; +type __VLS_TemplateSlots = typeof __VLS_slots; declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; -declare const _default: __VLS_WithTemplateSlots; +declare const _default: __VLS_WithTemplateSlots; export default _default; type __VLS_WithTemplateSlots = T & { new (): { @@ -649,39 +648,34 @@ type __VLS_WithTemplateSlots = T & { exports[`vue-tsc-dts > Input: template-slots/component-define-slots.vue, Output: template-slots/component-define-slots.vue.d.ts 1`] = ` "import { VNode } from 'vue'; -declare function __VLS_template(): { - attrs: Partial<{}>; - slots: Readonly<{ - default: (props: { - num: number; - }) => VNode[]; - 'named-slot': (props: { - str: string; - }) => VNode[]; - vbind: (props: { - num: number; - str: string; - }) => VNode[]; - 'no-bind': () => VNode[]; - }> & { - default: (props: { - num: number; - }) => VNode[]; - 'named-slot': (props: { - str: string; - }) => VNode[]; - vbind: (props: { - num: number; - str: string; - }) => VNode[]; - 'no-bind': () => VNode[]; - }; - refs: {}; - rootEl: any; +declare const __VLS_slots: Readonly<{ + default: (props: { + num: number; + }) => VNode[]; + 'named-slot': (props: { + str: string; + }) => VNode[]; + vbind: (props: { + num: number; + str: string; + }) => VNode[]; + 'no-bind': () => VNode[]; +}> & { + default: (props: { + num: number; + }) => VNode[]; + 'named-slot': (props: { + str: string; + }) => VNode[]; + vbind: (props: { + num: number; + str: string; + }) => VNode[]; + 'no-bind': () => VNode[]; }; -type __VLS_TemplateResult = ReturnType; +type __VLS_TemplateSlots = typeof __VLS_slots; declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; -declare const _default: __VLS_WithTemplateSlots; +declare const _default: __VLS_WithTemplateSlots; export default _default; type __VLS_WithTemplateSlots = T & { new (): { @@ -692,23 +686,18 @@ type __VLS_WithTemplateSlots = T & { `; exports[`vue-tsc-dts > Input: template-slots/component-destructuring.vue, Output: template-slots/component-destructuring.vue.d.ts 1`] = ` -"declare function __VLS_template(): { - attrs: Partial<{}>; - slots: Readonly<{ - bottom: (props: { - num: number; - }) => any[]; - }> & { - bottom: (props: { - num: number; - }) => any[]; - }; - refs: {}; - rootEl: any; +"declare const __VLS_slots: Readonly<{ + bottom: (props: { + num: number; + }) => any[]; +}> & { + bottom: (props: { + num: number; + }) => any[]; }; -type __VLS_TemplateResult = ReturnType; +type __VLS_TemplateSlots = typeof __VLS_slots; declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; -declare const _default: __VLS_WithTemplateSlots; +declare const _default: __VLS_WithTemplateSlots; export default _default; type __VLS_WithTemplateSlots = T & { new (): { @@ -719,27 +708,26 @@ type __VLS_WithTemplateSlots = T & { `; exports[`vue-tsc-dts > Input: template-slots/component-no-script.vue, Output: template-slots/component-no-script.vue.d.ts 1`] = ` -"declare function __VLS_template(): { - attrs: Partial<{}>; - slots: { - 'no-bind'?(_: {}): any; - default?(_: { - num: number; - }): any; - 'named-slot'?(_: { - str: string; - }): any; - vbind?(_: { - num: number; - str: string; - }): any; - }; - refs: {}; - rootEl: any; +"declare var __VLS_0: {}; +declare var __VLS_1: { + num: number; +}; +declare var __VLS_2: { + str: string; +}; +declare var __VLS_3: { + num: number; + str: string; +}; +declare var __VLS_slots: { + 'no-bind'?(_: typeof __VLS_0): any; + default?(_: typeof __VLS_1): any; + 'named-slot'?(_: typeof __VLS_2): any; + vbind?(_: typeof __VLS_3): any; }; -type __VLS_TemplateResult = ReturnType; +type __VLS_TemplateSlots = typeof __VLS_slots; declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; -declare const _default: __VLS_WithTemplateSlots; +declare const _default: __VLS_WithTemplateSlots; export default _default; type __VLS_WithTemplateSlots = T & { new (): { From 1a4f46a50bc30ebfa314f4ba5e142529e81985db Mon Sep 17 00:00:00 2001 From: KazariEX <1364035137@qq.com> Date: Tue, 7 Jan 2025 23:58:43 +0800 Subject: [PATCH 2/2] fix: standardize the return type of `useAttrs` and `useSlots` --- packages/language-core/lib/codegen/script/scriptSetup.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/language-core/lib/codegen/script/scriptSetup.ts b/packages/language-core/lib/codegen/script/scriptSetup.ts index b8f128e6ec..81eac14a19 100644 --- a/packages/language-core/lib/codegen/script/scriptSetup.ts +++ b/packages/language-core/lib/codegen/script/scriptSetup.ts @@ -176,7 +176,7 @@ function* generateSetupFunction( callExp.start, callExp.start ], [ - [` as __VLS_TemplateAttrs & Record)`], + [` as typeof __VLS_special.$attrs)`], callExp.end, callExp.end ]); @@ -215,7 +215,7 @@ function* generateSetupFunction( callExp.start, callExp.start ], [ - [` as __VLS_TemplateSlots)`], + [` as typeof __VLS_special.$slots)`], callExp.end, callExp.end ]);