From 2a2aa73798793c897557a36d04d5bb45ddfc6686 Mon Sep 17 00:00:00 2001 From: Johnson Chu Date: Tue, 9 Dec 2025 08:27:28 +0800 Subject: [PATCH] perf(language-core): dedupe component options generation --- packages/language-core/lib/codegen/names.ts | 1 - .../language-core/lib/codegen/script/index.ts | 4 +-- .../language-core/lib/codegen/script/src.ts | 31 ++++++++++--------- .../lib/codegen/script/template.ts | 29 ++++++++++------- .../language-server/tests/renaming.spec.ts | 20 ++++++------ 5 files changed, 46 insertions(+), 39 deletions(-) diff --git a/packages/language-core/lib/codegen/names.ts b/packages/language-core/lib/codegen/names.ts index cdf316c90b..6fa67c4940 100644 --- a/packages/language-core/lib/codegen/names.ts +++ b/packages/language-core/lib/codegen/names.ts @@ -1,5 +1,4 @@ export const ctx = '__VLS_ctx'; -export const self = '__VLS_self'; export const dollars = '__VLS_dollars'; export const slots = '__VLS_slots'; export const props = '__VLS_props'; diff --git a/packages/language-core/lib/codegen/script/index.ts b/packages/language-core/lib/codegen/script/index.ts index f7c3495629..e92288c656 100644 --- a/packages/language-core/lib/codegen/script/index.ts +++ b/packages/language-core/lib/codegen/script/index.ts @@ -163,7 +163,7 @@ function* generateWorker( yield* generateSfcBlockSection(script, 0, expression.start, codeFeatures.all); yield exportExpression; yield endOfLine; - yield* generateTemplate(options, ctx); + yield* generateTemplate(options, ctx, names._export); yield* generateExportDeclareEqual(script); if (wrapLeft && wrapRight) { yield wrapLeft; @@ -179,7 +179,7 @@ function* generateWorker( yield* generateSfcBlockSection(script, 0, script.content.length, codeFeatures.all); yield* generateExportDeclareEqual(script); yield `(await import('${vueCompilerOptions.lib}')).defineComponent({})${endOfLine}`; - yield* generateTemplate(options, ctx); + yield* generateTemplate(options, ctx, names._export); yield `export default ${exportExpression}${endOfLine}`; } } diff --git a/packages/language-core/lib/codegen/script/src.ts b/packages/language-core/lib/codegen/script/src.ts index 7b632354b0..2f4a0fd216 100644 --- a/packages/language-core/lib/codegen/script/src.ts +++ b/packages/language-core/lib/codegen/script/src.ts @@ -8,20 +8,7 @@ export function* generateSrc(src: SfcBlockAttr): Generator { return; } let { text } = src; - - if (text.endsWith('.d.ts')) { - text = text.slice(0, -'.d.ts'.length); - } - else if (text.endsWith('.ts')) { - text = text.slice(0, -'.ts'.length); - } - else if (text.endsWith('.tsx')) { - text = text.slice(0, -'.tsx'.length) + '.jsx'; - } - - if (!text.endsWith('.js') && !text.endsWith('.jsx')) { - text = text + '.js'; - } + text = resolveSrcPath(text); yield `export * from `; const wrapCodeFeatures: VueCodeInformation = { @@ -37,3 +24,19 @@ export function* generateSrc(src: SfcBlockAttr): Generator { yield endOfLine; yield `export { default } from '${text}'${endOfLine}`; } + +export function resolveSrcPath(text: string): string { + if (text.endsWith('.d.ts')) { + text = text.slice(0, -'.d.ts'.length); + } + else if (text.endsWith('.ts')) { + text = text.slice(0, -'.ts'.length); + } + else if (text.endsWith('.tsx')) { + text = text.slice(0, -'.tsx'.length) + '.jsx'; + } + if (!text.endsWith('.js') && !text.endsWith('.jsx')) { + text = text + '.js'; + } + return text; +} diff --git a/packages/language-core/lib/codegen/script/template.ts b/packages/language-core/lib/codegen/script/template.ts index 1d0fa309ab..bc4498a787 100644 --- a/packages/language-core/lib/codegen/script/template.ts +++ b/packages/language-core/lib/codegen/script/template.ts @@ -1,4 +1,3 @@ -import * as path from 'path-browserify'; import type { Code } from '../../types'; import { codeFeatures } from '../codeFeatures'; import * as names from '../names'; @@ -6,14 +5,16 @@ import { endOfLine, generateSfcBlockSection, newLine } from '../utils'; import { generateSpreadMerge } from '../utils/merge'; import type { ScriptCodegenContext } from './context'; import type { ScriptCodegenOptions } from './index'; +import { resolveSrcPath } from './src'; export function* generateTemplate( options: ScriptCodegenOptions, ctx: ScriptCodegenContext, + selfType?: string, ): Generator { - yield* generateSelf(options); + selfType ??= yield* generateSelf(options); yield* generateSetupExposed(options, ctx); - yield* generateTemplateCtx(options, ctx); + yield* generateTemplateCtx(options, ctx, selfType); yield* generateTemplateComponents(options); yield* generateTemplateDirectives(options); @@ -25,27 +26,28 @@ export function* generateTemplate( } } -function* generateSelf({ script, scriptRanges, vueCompilerOptions, fileName }: ScriptCodegenOptions): Generator { +function* generateSelf({ script, scriptRanges, vueCompilerOptions }: ScriptCodegenOptions): Generator { + const varName = '__VLS_self'; if (script && scriptRanges?.componentOptions) { - yield `const ${names.self} = (await import('${vueCompilerOptions.lib}')).defineComponent(`; + yield `const ${varName} = (await import('${vueCompilerOptions.lib}')).defineComponent(`; const { args } = scriptRanges.componentOptions; yield* generateSfcBlockSection(script, args.start, args.end, codeFeatures.all); yield `)${endOfLine}`; + return varName; } else if (script && scriptRanges?.exportDefault) { - yield `const ${names.self} = `; + yield `const ${varName} = `; const { expression } = scriptRanges.exportDefault; yield* generateSfcBlockSection(script, expression.start, expression.end, codeFeatures.all); yield endOfLine; - } - else if (script?.src) { - yield `let ${names.self}!: typeof import('./${path.basename(fileName)}').default${endOfLine}`; + return varName; } } function* generateTemplateCtx( - { vueCompilerOptions, script, scriptRanges, styleCodegen, scriptSetupRanges, fileName }: ScriptCodegenOptions, + { vueCompilerOptions, script, styleCodegen, scriptSetupRanges, fileName }: ScriptCodegenOptions, ctx: ScriptCodegenContext, + selfType: string | undefined, ): Generator { const exps: Iterable[] = []; const emitTypes: string[] = []; @@ -54,8 +56,11 @@ function* generateTemplateCtx( if (vueCompilerOptions.petiteVueExtensions.some(ext => fileName.endsWith(ext))) { exps.push([`globalThis`]); } - if (script?.src || scriptRanges?.exportDefault) { - exps.push([`{} as InstanceType<__VLS_PickNotAny {}>>`]); + if (selfType) { + exps.push([`{} as InstanceType<__VLS_PickNotAny {}>>`]); + } + else if (typeof script?.src === 'object') { + exps.push([`{} as typeof import('${resolveSrcPath(script.src.text)}').default`]); } else { exps.push([`{} as import('${vueCompilerOptions.lib}').ComponentPublicInstance`]); diff --git a/packages/language-server/tests/renaming.spec.ts b/packages/language-server/tests/renaming.spec.ts index 5ce86de6b6..b524b3941a 100644 --- a/packages/language-server/tests/renaming.spec.ts +++ b/packages/language-server/tests/renaming.spec.ts @@ -693,16 +693,6 @@ test('Component returns', async () => { { "file": "\${testWorkspacePath}/tsconfigProject/fixture.vue", "locs": [ - { - "end": { - "line": 3, - "offset": 11, - }, - "start": { - "line": 3, - "offset": 8, - }, - }, { "contextEnd": { "line": 12, @@ -721,6 +711,16 @@ test('Component returns', async () => { "offset": 7, }, }, + { + "end": { + "line": 3, + "offset": 11, + }, + "start": { + "line": 3, + "offset": 8, + }, + }, ], }, ],