Skip to content

Commit

Permalink
feat(language-core): unwrap __VLS_template & type support of `useAt…
Browse files Browse the repository at this point in the history
…trs` (vuejs#5106)
  • Loading branch information
KazariEX authored Jan 17, 2025
1 parent 2f98264 commit 47946f1
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 117 deletions.
6 changes: 3 additions & 3 deletions packages/language-core/lib/codegen/script/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 `})`;
}
Expand Down Expand Up @@ -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}\`>`;
}
Expand Down
2 changes: 0 additions & 2 deletions packages/language-core/lib/codegen/script/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,7 @@ export function* generateScript(options: ScriptCodegenOptions): Generator<Code,
}

if (!ctx.generatedTemplate) {
yield `function __VLS_template() {${newLine}`;
const templateCodegenCtx = yield* generateTemplate(options, ctx);
yield `}${endOfLine}`;
yield* generateComponentSelf(options, ctx, templateCodegenCtx);
}

Expand Down
36 changes: 16 additions & 20 deletions packages/language-core/lib/codegen/script/scriptSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ export function* generateScriptSetup(
}

yield `return {} as {${newLine}`
+ ` props: ${ctx.localTypes.PrettifyLocal}<__VLS_OwnProps & __VLS_PublicProps & __VLS_TemplateResult['attrs']> & __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 () => {
Expand Down Expand Up @@ -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<string, unknown>)`],
// callExp.end,
// callExp.end
// ]);
// }
for (const { callExp } of scriptSetupRanges.useAttrs) {
setupCodeModifies.push([
[`(`],
callExp.start,
callExp.start
], [
[` as typeof __VLS_special.$attrs)`],
callExp.end,
callExp.end
]);
}
for (const { callExp, exp, arg } of scriptSetupRanges.useCssModule) {
setupCodeModifies.push([
[`(`],
Expand Down Expand Up @@ -216,7 +215,7 @@ function* generateSetupFunction(
callExp.start,
callExp.start
], [
[` as __VLS_TemplateResult['slots'])`],
[` as typeof __VLS_special.$slots)`],
callExp.end,
callExp.end
]);
Expand All @@ -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),
`]`
]
Expand Down Expand Up @@ -294,19 +293,16 @@ 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<typeof __VLS_template>${endOfLine}`;

if (syntax) {
if (!options.vueCompilerOptions.skipTemplateCodegen && (options.templateCodegen?.hasSlot || scriptSetupRanges.defineSlots)) {
yield `const __VLS_component = `;
yield* generateComponent(options, ctx, scriptSetup, scriptSetupRanges);
yield endOfLine;
yield `${syntax} `;
yield `{} as ${ctx.localTypes.WithTemplateSlots}<typeof __VLS_component, __VLS_TemplateResult['slots']>${endOfLine}`;
yield `{} as ${ctx.localTypes.WithTemplateSlots}<typeof __VLS_component, __VLS_TemplateSlots>${endOfLine}`;
}
else {
yield `${syntax} `;
Expand Down
10 changes: 4 additions & 6 deletions packages/language-core/lib/codegen/script/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,10 @@ function* generateTemplateBody(
yield `const __VLS_rootEl = {} as any${endOfLine}`;
}

yield `return {${newLine}`;
yield ` attrs: {} as Partial<typeof __VLS_inheritedAttrs>,${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<typeof __VLS_inheritedAttrs>${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(
Expand Down
5 changes: 3 additions & 2 deletions packages/language-core/lib/codegen/template/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function* generateTemplate(options: TemplateCodegenOptions): Generator<Co
yield* generateStyleScopedClassReferences(ctx);
const speicalTypes = [
[slotsPropertyName, yield* generateSlots(options, ctx)],
['$attrs', yield* generateInheritedAttrs(ctx)],
['$attrs', yield* generateInheritedAttrs(options, ctx)],
['$refs', yield* generateRefs(ctx)],
['$el', yield* generateRootEl(ctx)]
];
Expand Down Expand Up @@ -102,6 +102,7 @@ function* generateSlots(
}

function* generateInheritedAttrs(
options: TemplateCodegenOptions,
ctx: TemplateCodegenContext
): Generator<Code> {
yield 'let __VLS_inheritedAttrs!: {}';
Expand All @@ -124,7 +125,7 @@ function* generateInheritedAttrs(
}
yield `]${endOfLine}`;
}
return `typeof __VLS_ctx.$attrs & Partial<typeof __VLS_inheritedAttrs>`;
return `import('${options.vueCompilerOptions.lib}').ComponentPublicInstance['$attrs'] & Partial<typeof __VLS_inheritedAttrs>`;
}

function* generateRefs(
Expand Down
156 changes: 72 additions & 84 deletions packages/tsc/tests/__snapshots__/dts.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -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<typeof __VLS_template>;
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<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateSlots>;
export default _default;
type __VLS_WithTemplateSlots<T, S> = T & {
new (): {
Expand All @@ -649,39 +648,34 @@ type __VLS_WithTemplateSlots<T, S> = 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<typeof __VLS_template>;
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<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateSlots>;
export default _default;
type __VLS_WithTemplateSlots<T, S> = T & {
new (): {
Expand All @@ -692,23 +686,18 @@ type __VLS_WithTemplateSlots<T, S> = 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<typeof __VLS_template>;
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<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateSlots>;
export default _default;
type __VLS_WithTemplateSlots<T, S> = T & {
new (): {
Expand All @@ -719,27 +708,26 @@ type __VLS_WithTemplateSlots<T, S> = 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<typeof __VLS_template>;
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<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateSlots>;
export default _default;
type __VLS_WithTemplateSlots<T, S> = T & {
new (): {
Expand Down
21 changes: 21 additions & 0 deletions test-workspace/tsc/passedFixtures/#5106/main.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script setup lang="ts">
import { useAttrs } from 'vue';
import { exactType } from '../shared';
declare module 'vue' {
interface ComponentCustomProperties {
$attrs: {
class: string
};
}
}
type AttrsExact = Record<string, unknown> & { class: string } & Partial<{}>;
const attrs = useAttrs();
exactType(attrs, {} as AttrsExact);
</script>

<template>
{{ exactType($attrs, {} as AttrsExact) }}
</template>
4 changes: 4 additions & 0 deletions test-workspace/tsc/passedFixtures/#5106/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "../../../tsconfig.base.json",
"include": [ "**/*" ]
}

0 comments on commit 47946f1

Please sign in to comment.