diff --git a/packages/language-core/lib/codegen/script/component.ts b/packages/language-core/lib/codegen/script/component.ts index bf5ded4eea..f891b4ae8a 100644 --- a/packages/language-core/lib/codegen/script/component.ts +++ b/packages/language-core/lib/codegen/script/component.ts @@ -2,6 +2,7 @@ import type { ScriptSetupRanges } from '../../parsers/scriptSetupRanges'; import type { Code, Sfc } from '../../types'; import { codeFeatures } from '../codeFeatures'; import { endOfLine, generateSfcBlockSection, newLine } from '../utils'; +import { generateIntersectMerge, generateSpreadMerge } from '../utils/merge'; import type { ScriptCodegenContext } from './context'; import type { ScriptCodegenOptions } from './index'; @@ -29,15 +30,23 @@ export function* generateComponent( } yield `setup() {${newLine}`; - yield `return {${newLine}`; + const returns: Code[] = []; if (ctx.bypassDefineComponent) { + yield* `const __VLS_returns = {${newLine}`; yield* generateComponentSetupReturns(scriptSetupRanges); + yield `}${endOfLine}`; + returns.push(`typeof __VLS_returns`); } if (scriptSetupRanges.defineExpose) { - yield `...__VLS_exposed,${newLine}`; + returns.push(`typeof __VLS_exposed`); + } + if (returns.length) { + yield `return {} as `; + yield* generateIntersectMerge(returns); + yield endOfLine; } - yield `}${endOfLine}`; yield `},${newLine}`; + if (!ctx.bypassDefineComponent) { const emitOptionCodes = [...generateEmitsOption(options, scriptSetupRanges)]; yield* emitOptionCodes; @@ -100,10 +109,14 @@ export function* generateEmitsOption( } if (options.vueCompilerOptions.target >= 3.5 && typeOptionCodes.length) { - yield* generateIntersectMerge('__typeEmits', typeOptionCodes); + yield `__typeEmits: {} as `; + yield* generateIntersectMerge(typeOptionCodes); + yield `,${newLine}`; } else if (optionCodes.length) { - yield* generateSpreadMerge('emits', optionCodes); + yield `emits: `; + yield* generateSpreadMerge(optionCodes); + yield `,${newLine}`; } } @@ -159,36 +172,13 @@ export function* generatePropsOption( ) { yield `__defaults: __VLS_withDefaultsArg,${newLine}`; } - yield* generateSpreadMerge('__typeProps', typeOptionCodes); + yield `__typeProps: `; + yield* generateSpreadMerge(typeOptionCodes); + yield `,${newLine}`; } if (useOption) { - yield* generateSpreadMerge('props', getOptionCodes.map(fn => fn())); - } -} - -function* generateIntersectMerge(key: string, codes: Code[]): Generator { - yield `${key}: {} as `; - yield codes[0]; - for (let i = 1; i < codes.length; i++) { - yield ` & `; - yield codes[i]; - } - yield `,${newLine}`; -} - -function* generateSpreadMerge(key: string, codes: Code[]): Generator { - yield `${key}: `; - if (codes.length === 1) { - yield codes[0]; - } - else { - yield `{${newLine}`; - for (const code of codes) { - yield `...`; - yield code; - yield `,${newLine}`; - } - yield `}`; + yield `props: `; + yield* generateSpreadMerge(getOptionCodes.map(fn => fn())); + yield `,${newLine}`; } - yield `,${newLine}`; } diff --git a/packages/language-core/lib/codegen/script/template.ts b/packages/language-core/lib/codegen/script/template.ts index 85a2271301..7e443b7ffa 100644 --- a/packages/language-core/lib/codegen/script/template.ts +++ b/packages/language-core/lib/codegen/script/template.ts @@ -7,6 +7,7 @@ import { createTemplateCodegenContext, type TemplateCodegenContext } from '../te import { generateInterpolation } from '../template/interpolation'; import { generateStyleScopedClassReferences } from '../template/styleScopedClasses'; import { endOfLine, newLine } from '../utils'; +import { generateIntersectMerge, generateSpreadMerge } from '../utils/merge'; import type { ScriptCodegenContext } from './context'; import type { ScriptCodegenOptions } from './index'; @@ -40,19 +41,8 @@ function* generateTemplateCtx(options: ScriptCodegenOptions): Generator { } yield `const __VLS_ctx = `; - if (exps.length === 1) { - yield exps[0]; - yield `${endOfLine}`; - } - else { - yield `{${newLine}`; - for (const exp of exps) { - yield `...`; - yield exp; - yield `,${newLine}`; - } - yield `}${endOfLine}`; - } + yield* generateSpreadMerge(exps); + yield endOfLine; } function* generateTemplateElements(): Generator { @@ -76,10 +66,7 @@ function* generateTemplateComponents(options: ScriptCodegenOptions): Generator { + yield codes[0]; + for (let i = 1; i < codes.length; i++) { + yield ` & `; + yield codes[i]; + } +} + +export function* generateSpreadMerge(codes: Code[]): Generator { + if (codes.length === 1) { + yield codes[0]; + } + else { + yield `{${newLine}`; + for (const code of codes) { + yield `...`; + yield code; + yield `,${newLine}`; + } + yield `}`; + } +} diff --git a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap index ba514de5f4..26ac39b893 100644 --- a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap +++ b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap @@ -29,7 +29,7 @@ type __VLS_PrettifyLocal = { exports[`vue-tsc-dts > Input: empty-component/component.vue, Output: empty-component/component.vue.d.ts 1`] = ` "declare const _default: import("vue").DefineComponent2<{ - setup(): {}; + setup(): void; data(): {}; props: {}; computed: {}; @@ -55,7 +55,7 @@ export default _default; exports[`vue-tsc-dts > Input: empty-component/custom-extension-component.cext, Output: empty-component/custom-extension-component.cext.d.ts 1`] = ` "declare const _default: import("vue").DefineComponent2<{ - setup(): {}; + setup(): void; data(): {}; props: {}; computed: {}; @@ -141,7 +141,7 @@ type __VLS_PrettifyLocal = { exports[`vue-tsc-dts > Input: generic/main.vue, Output: generic/main.vue.d.ts 1`] = ` "declare const _default: import("vue").DefineComponent2<{ - setup(): {}; + setup(): void; data(): {}; props: {}; computed: {}; @@ -243,7 +243,7 @@ export default _default; exports[`vue-tsc-dts > Input: reference-type-events/component.vue, Output: reference-type-events/component.vue.d.ts 1`] = ` "import type { MyEvents } from './my-events'; declare const _default: import("vue").DefineComponent2<{ - setup(): {}; + setup(): void; data(): {}; props: {}; computed: {}; @@ -339,7 +339,7 @@ type __VLS_ModelEmit = { 'update:bar': [value: string | undefined]; }; declare const _default: import("vue").DefineComponent2<{ - setup(): {}; + setup(): void; data(): {}; props: {}; computed: {}; @@ -366,7 +366,7 @@ export default _default; exports[`vue-tsc-dts > Input: reference-type-props/component.vue, Output: reference-type-props/component.vue.d.ts 1`] = ` "import { MyProps } from './my-props'; declare const _default: import("vue").DefineComponent2<{ - setup(): {}; + setup(): void; data(): {}; props: {}; computed: {}; @@ -398,7 +398,7 @@ exports[`vue-tsc-dts > Input: reference-type-props/component-destructure.vue, Ou text: string; }; declare const _default: import("vue").DefineComponent2<{ - setup(): {}; + setup(): void; data(): {}; props: {}; computed: {}; @@ -473,7 +473,7 @@ export default _default; exports[`vue-tsc-dts > Input: reference-type-props/component-js-setup.vue, Output: reference-type-props/component-js-setup.vue.d.ts 1`] = ` "declare const _default: import("vue").DefineComponent2<{ - setup(): {}; + setup(): void; data(): {}; props: { foo: { @@ -667,7 +667,7 @@ type __VLS_Slots = {} & { vbind?: (props: typeof __VLS_7) => any; }; declare const __VLS_component: import("vue").DefineComponent2<{ - setup(): {}; + setup(): void; data(): {}; props: {}; computed: {}; @@ -713,7 +713,7 @@ type __VLS_Slots = { 'no-bind': () => VNode[]; }; declare const __VLS_component: import("vue").DefineComponent2<{ - setup(): {}; + setup(): void; data(): {}; props: {}; computed: {}; @@ -762,7 +762,7 @@ type __VLS_Slots = {} & { vbind?: (props: typeof __VLS_7) => any; }; declare const __VLS_component: import("vue").DefineComponent2<{ - setup(): {}; + setup(): void; data(): {}; props: {}; computed: {}; diff --git a/test-workspace/tsc/passedFixtures/vue3.4/components/main.vue b/test-workspace/tsc/passedFixtures/vue3.4/components/main.vue index e5248bedcb..d5b3764356 100644 --- a/test-workspace/tsc/passedFixtures/vue3.4/components/main.vue +++ b/test-workspace/tsc/passedFixtures/vue3.4/components/main.vue @@ -16,9 +16,7 @@ const ScriptSetupExact = defineComponent({ change(..._payload: any[]) { }, delete(..._payload: any[]) { }, }, - setup() { - return {}; - }, + setup() {}, }); // https://vuejs.org/api/sfc-script-setup.html#defineexpose const ScriptSetupExposeExact = defineComponent({ @@ -44,9 +42,7 @@ const ScriptSetupTypeOnlyExact = defineComponent({ change(_id: number) { }, update(_value: string) { }, }, - setup() { - return {}; - }, + setup() {}, }); // https://vuejs.org/api/sfc-script-setup.html#default-props-values-when-using-type-declaration const ScriptSetupDefaultPropsExact = defineComponent({ @@ -60,9 +56,7 @@ const ScriptSetupDefaultPropsExact = defineComponent({ default: () => ['one', 'two'] }, }, - setup() { - return {}; - }, + setup() {}, }); // vue 3.3 generic declare const ScriptSetupGenericExact: ( diff --git a/test-workspace/tsc/passedFixtures/vue3.4/defineModel/main.vue b/test-workspace/tsc/passedFixtures/vue3.4/defineModel/main.vue index a1b3d02e34..b24f82cbaa 100644 --- a/test-workspace/tsc/passedFixtures/vue3.4/defineModel/main.vue +++ b/test-workspace/tsc/passedFixtures/vue3.4/defineModel/main.vue @@ -20,9 +20,7 @@ const ScriptSetupExact = defineComponent({ "update:f": (_: string) => void "update:g": (_: string | undefined) => void }, - setup() { - return {}; - }, + setup() {}, }); exactType(ScriptSetup, ScriptSetupExact); diff --git a/test-workspace/tsc/passedFixtures/vue3/components/main.vue b/test-workspace/tsc/passedFixtures/vue3/components/main.vue index dd53d4f7cf..fe7dd1fca7 100644 --- a/test-workspace/tsc/passedFixtures/vue3/components/main.vue +++ b/test-workspace/tsc/passedFixtures/vue3/components/main.vue @@ -16,9 +16,7 @@ const ScriptSetupExact = defineComponent({ change(..._payload: any[]) { }, delete(..._payload: any[]) { }, }, - setup() { - return {}; - }, + setup() {}, }); // https://vuejs.org/api/sfc-script-setup.html#defineexpose const ScriptSetupExposeExact = defineComponent({ @@ -41,9 +39,7 @@ const ScriptSetupTypeOnlyExact = defineComponent({ (e: 'change', id: number): void; (e: 'update', value: string): void; }, - setup() { - return {}; - }, + setup() {}, }); // https://vuejs.org/api/sfc-script-setup.html#default-props-values-when-using-type-declaration const ScriptSetupDefaultPropsExact = defineComponent({ @@ -55,9 +51,7 @@ const ScriptSetupDefaultPropsExact = defineComponent({ msg: 'hello', labels: () => ['one', 'two'] }, - setup() { - return {}; - }, + setup() {}, }); // vue 3.3 generic declare const ScriptSetupGenericExact: ( diff --git a/test-workspace/tsc/passedFixtures/vue3/defineModel/main.vue b/test-workspace/tsc/passedFixtures/vue3/defineModel/main.vue index bb25b68577..2918f17455 100644 --- a/test-workspace/tsc/passedFixtures/vue3/defineModel/main.vue +++ b/test-workspace/tsc/passedFixtures/vue3/defineModel/main.vue @@ -20,9 +20,7 @@ const ScriptSetupExact = defineComponent({ 'update:f': [f: string | undefined]; 'update:gG': [g: string | undefined]; }, - setup() { - return {}; - }, + setup() {}, }); exactType(ScriptSetup, ScriptSetupExact);