From 968c00fe5dbba91698be6b479802402e110b5dd5 Mon Sep 17 00:00:00 2001 From: KazariEX Date: Sat, 2 Aug 2025 01:55:26 +0800 Subject: [PATCH 01/13] refactor(language-service): remove redundant `isGlobal` checks for models and special props --- .../language-service/lib/plugins/vue-template.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/language-service/lib/plugins/vue-template.ts b/packages/language-service/lib/plugins/vue-template.ts index 8bdf03bd34..0e330be4ed 100644 --- a/packages/language-service/lib/plugins/vue-template.ts +++ b/packages/language-service/lib/plugins/vue-template.ts @@ -236,7 +236,6 @@ export function create( prop = { name, kind: 'prop', - isGlobal: true, }; } } @@ -247,7 +246,7 @@ export function create( const { isEvent, propName } = getPropName(prop.name, prop.kind === 'event'); if (prop.kind === 'prop') { - if (!prop.isGlobal || specialProps.has(propName)) { + if (!prop.isGlobal) { item.kind = 5 satisfies typeof CompletionItemKind.Field; } } @@ -258,7 +257,7 @@ export function create( } } - if (!prop.isGlobal || specialProps.has(propName)) { + if (!prop.isGlobal) { tokens.push('\u0000'); if (item.label.startsWith(':')) { @@ -573,7 +572,7 @@ export function create( }); } - const models: [boolean, string][] = []; + const models: string[] = []; for ( const prop of [ @@ -582,31 +581,28 @@ export function create( ] ) { if (prop.name.startsWith('onUpdate:')) { - const isGlobal = !propNameSet.has(prop.name); - models.push([isGlobal, prop.name.slice('onUpdate:'.length)]); + models.push(prop.name.slice('onUpdate:'.length)); } } for (const event of events) { if (event.startsWith('update:')) { - models.push([false, event.slice('update:'.length)]); + models.push(event.slice('update:'.length)); } } - for (const [isGlobal, model] of models) { + for (const model of models) { const name = casing.attr === AttrNameCasing.Camel ? model : hyphenateAttr(model); attributes.push({ name: 'v-model:' + name }); propMap.set('v-model:' + name, { name, kind: 'prop', - isGlobal, }); if (model === 'modelValue') { propMap.set('v-model', { name, kind: 'prop', - isGlobal, }); } } From 112f65b6377638817f57078bb23269c8c15802e6 Mon Sep 17 00:00:00 2001 From: KazariEX Date: Sat, 2 Aug 2025 03:50:34 +0800 Subject: [PATCH 02/13] refactor(language-core): wrap `__VLS_InheritedAttrs` with `Partial` at definition --- .../language-core/lib/codegen/script/component.ts | 2 +- .../language-core/lib/codegen/script/scriptSetup.ts | 2 +- packages/language-core/lib/codegen/template/index.ts | 11 ++++++----- packages/tsc/tests/__snapshots__/dts.spec.ts.snap | 4 ++-- test-workspace/tsc/passedFixtures/#5106/main.vue | 2 +- test-workspace/tsc/passedFixtures/vue3/attrs/main.vue | 1 + 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/language-core/lib/codegen/script/component.ts b/packages/language-core/lib/codegen/script/component.ts index f891b4ae8a..6ae1ec3172 100644 --- a/packages/language-core/lib/codegen/script/component.ts +++ b/packages/language-core/lib/codegen/script/component.ts @@ -132,7 +132,7 @@ export function* generatePropsOption( const typeOptionCodes: Code[] = []; if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size) { - let attrsType = `Partial<__VLS_InheritedAttrs>`; + let attrsType = `__VLS_InheritedAttrs`; if (hasEmitsOption) { attrsType = `Omit<${attrsType}, \`on\${string}\`>`; } diff --git a/packages/language-core/lib/codegen/script/scriptSetup.ts b/packages/language-core/lib/codegen/script/scriptSetup.ts index aa889d3cc3..58397c4c2d 100644 --- a/packages/language-core/lib/codegen/script/scriptSetup.ts +++ b/packages/language-core/lib/codegen/script/scriptSetup.ts @@ -69,7 +69,7 @@ export function* generateScriptSetup( } yield `return {} as {${newLine}` - + ` props: ${ctx.localTypes.PrettifyLocal}<__VLS_OwnProps & __VLS_PublicProps & Partial<__VLS_InheritedAttrs>> & __VLS_BuiltInPublicProps,${newLine}` + + ` props: ${ctx.localTypes.PrettifyLocal}<__VLS_OwnProps & __VLS_PublicProps & __VLS_InheritedAttrs> & __VLS_BuiltInPublicProps,${newLine}` + ` expose(exposed: import('${options.vueCompilerOptions.lib}').ShallowUnwrapRef<${ scriptSetupRanges.defineExpose ? 'typeof __VLS_exposed' : '{}' }>): void,${newLine}` diff --git a/packages/language-core/lib/codegen/template/index.ts b/packages/language-core/lib/codegen/template/index.ts index e21ae2f952..f623349b67 100644 --- a/packages/language-core/lib/codegen/template/index.ts +++ b/packages/language-core/lib/codegen/template/index.ts @@ -113,10 +113,11 @@ function* generateInheritedAttrs( options: TemplateCodegenOptions, ctx: TemplateCodegenContext, ): Generator { - yield `type __VLS_InheritedAttrs = {}`; - for (const varName of ctx.inheritedAttrVars) { - yield ` & typeof ${varName}`; - } + yield `type __VLS_InheritedAttrs = ${ + ctx.inheritedAttrVars.size + ? `Partial<${[...ctx.inheritedAttrVars].map(name => `typeof ${name}`).join(` & `)}>` + : `{}` + }`; yield endOfLine; if (ctx.bindingAttrLocs.length) { @@ -133,7 +134,7 @@ function* generateInheritedAttrs( } yield `]${endOfLine}`; } - return `import('${options.vueCompilerOptions.lib}').ComponentPublicInstance['$attrs'] & Partial<__VLS_InheritedAttrs>`; + return `import('${options.vueCompilerOptions.lib}').ComponentPublicInstance['$attrs'] & __VLS_InheritedAttrs`; } function* generateTemplateRefs( diff --git a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap index 5a4791ef21..3916ac1441 100644 --- a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap +++ b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap @@ -61,7 +61,7 @@ exports[`vue-tsc-dts > Input: generic/component.vue, Output: generic/component.v foo: number; } & { title?: string; - }) & Partial<{}>> & import("vue").PublicProps; + }) & {}> & import("vue").PublicProps; expose(exposed: import("vue").ShallowUnwrapRef<{ baz: number; }>): void; @@ -91,7 +91,7 @@ exports[`vue-tsc-dts > Input: generic/custom-extension-component.cext, Output: g foo: number; } & { title?: string; - }) & Partial<{}>> & import("vue").PublicProps; + }) & {}> & import("vue").PublicProps; expose(exposed: import("vue").ShallowUnwrapRef<{ baz: number; }>): void; diff --git a/test-workspace/tsc/passedFixtures/#5106/main.vue b/test-workspace/tsc/passedFixtures/#5106/main.vue index 492156fe51..5d9caab3c3 100644 --- a/test-workspace/tsc/passedFixtures/#5106/main.vue +++ b/test-workspace/tsc/passedFixtures/#5106/main.vue @@ -12,7 +12,7 @@ declare module 'vue' { } } -type AttrsExact = Record & { class: string } & Partial<{}>; +type AttrsExact = Record & { class: string }; const attrs = useAttrs(); exactType(attrs, {} as AttrsExact); diff --git a/test-workspace/tsc/passedFixtures/vue3/attrs/main.vue b/test-workspace/tsc/passedFixtures/vue3/attrs/main.vue index 63a42d4a88..60ca99480f 100644 --- a/test-workspace/tsc/passedFixtures/vue3/attrs/main.vue +++ b/test-workspace/tsc/passedFixtures/vue3/attrs/main.vue @@ -1,3 +1,4 @@ +