Skip to content

Commit

Permalink
fix(language-core): support defineModel for generic component (#4345)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhiyuanzmj committed May 10, 2024
1 parent 635f4fe commit dd6c13e
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 25 deletions.
41 changes: 23 additions & 18 deletions packages/language-core/lib/codegen/script/scriptSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,19 @@ export function* generateScriptSetup(
+ ` __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>['expose'],${newLine}`
+ ` __VLS_setup = (async () => {${newLine}`;
yield* generateSetupFunction(options, ctx, scriptSetup, scriptSetupRanges, undefined, definePropMirrors);

const emitTypes = ['typeof __VLS_modelEmitsType'];

if (scriptSetupRanges.emits.define) {
emitTypes.unshift(`typeof ${scriptSetupRanges.emits.name ?? '__VLS_emit'}`);
}

yield ` return {} as {${newLine}`
+ ` props: ${ctx.helperTypes.Prettify.name}<typeof __VLS_functionalComponentProps & __VLS_PublicProps> & __VLS_BuiltInPublicProps,${newLine}`
+ ` expose(exposed: import('${options.vueCompilerOptions.lib}').ShallowUnwrapRef<${scriptSetupRanges.expose.define ? 'typeof __VLS_exposed' : '{}'}>): void,${newLine}`
+ ` attrs: any,${newLine}`
+ ` slots: ReturnType<typeof __VLS_template>,${newLine}`
+ ` emit: typeof ${scriptSetupRanges.emits.name ?? '__VLS_emit'} & typeof __VLS_modelEmitsType,${newLine}`
+ ` emit: ${emitTypes.join(' & ')},${newLine}`
+ ` }${endOfLine}`;
yield ` })(),${newLine}`; // __VLS_setup = (async () => {
yield `) => ({} as import('${options.vueCompilerOptions.lib}').VNode & { __ctx?: Awaited<typeof __VLS_setup> }))`;
Expand Down Expand Up @@ -263,27 +270,25 @@ function* generateComponentProps(
scriptSetupRanges: ScriptSetupRanges,
definePropMirrors: Map<string, number>,
): Generator<Code> {
if (scriptSetupRanges.props.define?.arg || scriptSetupRanges.emits.define) {
yield `const __VLS_fnComponent = `
+ `(await import('${options.vueCompilerOptions.lib}')).defineComponent({${newLine}`;
if (scriptSetupRanges.props.define?.arg) {
yield ` props: `;
yield generateSfcBlockSection(scriptSetup, scriptSetupRanges.props.define.arg.start, scriptSetupRanges.props.define.arg.end, codeFeatures.navigation);
yield `,${newLine}`;
}
yield `const __VLS_fnComponent = `
+ `(await import('${options.vueCompilerOptions.lib}')).defineComponent({${newLine}`;
if (scriptSetupRanges.props.define?.arg) {
yield ` props: `;
yield generateSfcBlockSection(scriptSetup, scriptSetupRanges.props.define.arg.start, scriptSetupRanges.props.define.arg.end, codeFeatures.navigation);
yield `,${newLine}`;
}
if (scriptSetupRanges.emits.define || scriptSetupRanges.defineProp.some(p => p.isModel)) {
yield ` emits: ({} as __VLS_NormalizeEmits<typeof __VLS_modelEmitsType`;
if (scriptSetupRanges.emits.define) {
yield ` emits: ({} as __VLS_NormalizeEmits<typeof `;
yield ` & typeof `;
yield scriptSetupRanges.emits.name ?? '__VLS_emit';
yield `>),${newLine}`;
}
yield `})${endOfLine}`;
yield `let __VLS_functionalComponentProps!: `;
yield `${ctx.helperTypes.OmitKeepDiscriminatedUnion.name}<InstanceType<typeof __VLS_fnComponent>['$props'], keyof __VLS_BuiltInPublicProps>`;
yield endOfLine;
}
else {
yield `let __VLS_functionalComponentProps!: {}${endOfLine}`;
yield `>),${newLine}`;
}
yield `})${endOfLine}`;
yield `let __VLS_functionalComponentProps!: `;
yield `${ctx.helperTypes.OmitKeepDiscriminatedUnion.name}<InstanceType<typeof __VLS_fnComponent>['$props'], keyof __VLS_BuiltInPublicProps>`;
yield endOfLine;

yield `type __VLS_BuiltInPublicProps =${newLine}`
+ ` import('${options.vueCompilerOptions.lib}').VNodeProps${newLine}`
Expand Down
30 changes: 24 additions & 6 deletions packages/tsc/tests/__snapshots__/dts.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ type __VLS_Prettify<T> = {
exports[`vue-tsc-dts > Input: generic/component.vue, Output: generic/component.vue.d.ts 1`] = `
"declare const _default: <T>(__VLS_props: {
"onUpdate:title"?: (title: string) => any;
onBar?: (data: number) => any;
title?: string;
foo: number;
} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, __VLS_ctx?: {
slots: Readonly<{
Expand All @@ -88,12 +90,14 @@ exports[`vue-tsc-dts > Input: generic/component.vue, Output: generic/component.v
}): any;
};
attrs: any;
emit: (e: 'bar', data: number) => void;
emit: ((e: 'bar', data: number) => void) & ((evt: "update:title", title: string) => void);
}, __VLS_expose?: (exposed: import("vue").ShallowUnwrapRef<{
baz: number;
}>) => void, __VLS_setup?: Promise<{
props: {
"onUpdate:title"?: (title: string) => any;
onBar?: (data: number) => any;
title?: string;
foo: number;
} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps;
expose(exposed: import("vue").ShallowUnwrapRef<{
Expand All @@ -109,13 +113,15 @@ exports[`vue-tsc-dts > Input: generic/component.vue, Output: generic/component.v
foo: number;
}): any;
};
emit: (e: 'bar', data: number) => void;
emit: ((e: 'bar', data: number) => void) & ((evt: "update:title", title: string) => void);
}>) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}> & {
__ctx?: {
props: {
"onUpdate:title"?: (title: string) => any;
onBar?: (data: number) => any;
title?: string;
foo: number;
} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps;
expose(exposed: import("vue").ShallowUnwrapRef<{
Expand All @@ -131,7 +137,7 @@ exports[`vue-tsc-dts > Input: generic/component.vue, Output: generic/component.v
foo: number;
}): any;
};
emit: (e: 'bar', data: number) => void;
emit: ((e: 'bar', data: number) => void) & ((evt: "update:title", title: string) => void);
};
};
export default _default;
Expand All @@ -143,7 +149,9 @@ type __VLS_Prettify<T> = {
exports[`vue-tsc-dts > Input: generic/custom-extension-component.cext, Output: generic/custom-extension-component.cext.d.ts 1`] = `
"declare const _default: <T>(__VLS_props: {
"onUpdate:title"?: (title: string) => any;
onBar?: (data: number) => any;
title?: string;
foo: number;
} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, __VLS_ctx?: {
slots: Readonly<{
Expand All @@ -156,12 +164,14 @@ exports[`vue-tsc-dts > Input: generic/custom-extension-component.cext, Output: g
}): any;
};
attrs: any;
emit: (e: 'bar', data: number) => void;
emit: ((e: 'bar', data: number) => void) & ((evt: "update:title", title: string) => void);
}, __VLS_expose?: (exposed: import("vue").ShallowUnwrapRef<{
baz: number;
}>) => void, __VLS_setup?: Promise<{
props: {
"onUpdate:title"?: (title: string) => any;
onBar?: (data: number) => any;
title?: string;
foo: number;
} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps;
expose(exposed: import("vue").ShallowUnwrapRef<{
Expand All @@ -177,13 +187,15 @@ exports[`vue-tsc-dts > Input: generic/custom-extension-component.cext, Output: g
foo: number;
}): any;
};
emit: (e: 'bar', data: number) => void;
emit: ((e: 'bar', data: number) => void) & ((evt: "update:title", title: string) => void);
}>) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}> & {
__ctx?: {
props: {
"onUpdate:title"?: (title: string) => any;
onBar?: (data: number) => any;
title?: string;
foo: number;
} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps;
expose(exposed: import("vue").ShallowUnwrapRef<{
Expand All @@ -199,7 +211,7 @@ exports[`vue-tsc-dts > Input: generic/custom-extension-component.cext, Output: g
foo: number;
}): any;
};
emit: (e: 'bar', data: number) => void;
emit: ((e: 'bar', data: number) => void) & ((evt: "update:title", title: string) => void);
};
};
export default _default;
Expand All @@ -209,6 +221,12 @@ type __VLS_Prettify<T> = {
"
`;
exports[`vue-tsc-dts > Input: generic/main.vue, Output: generic/main.vue.d.ts 1`] = `
"declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
export default _default;
"
`;
exports[`vue-tsc-dts > Input: non-component/component.ts, Output: non-component/component.d.ts 1`] = `
"declare const _default: {};
export default _default;
Expand Down
1 change: 1 addition & 0 deletions test-workspace/component-meta/generic/component.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ defineProps<{ foo: number }>();
defineEmits<{ (e: 'bar', data: number): void }>();
defineExpose({ baz: {} as number });
defineSlots<{ default?(data: { foo: number }): any }>();
defineModel<string>('title');
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ defineProps<{ foo: number }>();
defineEmits<{ (e: 'bar', data: number): void }>();
defineExpose({ baz: {} as number });
defineSlots<{ default?(data: { foo: number }): any }>();
defineModel<string>('title');
</script>
10 changes: 10 additions & 0 deletions test-workspace/component-meta/generic/main.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script setup lang="ts">
import { ref } from 'vue';
import Comp from './component.vue';
const title = ref('');
</script>

<template>
<Comp :foo="1" v-model:title="title" />
</template>
2 changes: 1 addition & 1 deletion test-workspace/tsc/vue3/defineProp_B/main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ declare const ScriptSetupGenericExact: <T, >(
} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps,
attrs: any,
slots: {},
emit: any,
emit: {},
expose(_exposed: {}): void,
}>
) => import('vue').VNode & { __ctx?: Awaited<typeof _setup>; };
Expand Down

0 comments on commit dd6c13e

Please sign in to comment.