diff --git a/packages/language-core/lib/codegen/script/scriptSetup.ts b/packages/language-core/lib/codegen/script/scriptSetup.ts index fb1dd9d151..5e4a8f684c 100644 --- a/packages/language-core/lib/codegen/script/scriptSetup.ts +++ b/packages/language-core/lib/codegen/script/scriptSetup.ts @@ -244,7 +244,15 @@ function* generateSetupFunction( } for (const { define } of scriptSetupRanges.templateRefs) { if (define?.arg) { - setupCodeModifies.push([[`<__VLS_Refs[${scriptSetup.content.slice(define.arg.start, define.arg.end)}], keyof __VLS_Refs>`], define.arg.start - 1, define.arg.start - 1]); + setupCodeModifies.push([ + [ + `<__VLS_Refs[`, + generateSfcBlockSection(scriptSetup, define.arg.start, define.arg.end, codeFeatures.navigation), + `], keyof __VLS_Refs>` + ], + define.arg.start - 1, + define.arg.start - 1 + ]); } } setupCodeModifies = setupCodeModifies.sort((a, b) => a[1] - b[1]); diff --git a/packages/language-core/lib/codegen/template/element.ts b/packages/language-core/lib/codegen/template/element.ts index 9670cbf4c6..7bae0f2b32 100644 --- a/packages/language-core/lib/codegen/template/element.ts +++ b/packages/language-core/lib/codegen/template/element.ts @@ -223,10 +223,10 @@ export function* generateComponent( yield endOfLine; } - const refName = yield* generateVScope(options, ctx, node, props); + const [refName, offset] = yield* generateVScope(options, ctx, node, props); if (refName) { const varName = ctx.getInternalVariable(); - options.templateRefNames.set(refName, varName); + options.templateRefNames.set(refName, [varName, offset!]); ctx.usedComponentCtxVars.add(var_defineComponentCtx); yield `// @ts-ignore${newLine}`; @@ -332,9 +332,9 @@ export function* generateElement( yield endOfLine; } - const refName = yield* generateVScope(options, ctx, node, node.props); + const [refName, offset] = yield* generateVScope(options, ctx, node, node.props); if (refName) { - options.templateRefNames.set(refName, `__VLS_intrinsicElements['${node.tag}']`); + options.templateRefNames.set(refName, [`__VLS_intrinsicElements['${node.tag}']`, offset!]); } const slotDir = node.props.find(p => p.type === CompilerDOM.NodeTypes.DIRECTIVE && p.name === 'slot') as CompilerDOM.DirectiveNode; @@ -361,7 +361,7 @@ function* generateVScope( ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, props: (CompilerDOM.AttributeNode | CompilerDOM.DirectiveNode)[] -): Generator { +): Generator { const vScope = props.find(prop => prop.type === CompilerDOM.NodeTypes.DIRECTIVE && (prop.name === 'scope' || prop.name === 'data')); let inScope = false; let originalConditionsNum = ctx.blockConditions.length; @@ -385,14 +385,14 @@ function* generateVScope( } yield* generateElementDirectives(options, ctx, node); - const refName = yield* generateReferencesForElements(options, ctx, node); // + const [refName, offset] = yield* generateReferencesForElements(options, ctx, node); // yield* generateReferencesForScopedCssClasses(options, ctx, node); if (inScope) { yield `}${newLine}`; ctx.blockConditions.length = originalConditionsNum; } - return refName; + return [refName, offset]; } export function getCanonicalComponentName(tagText: string) { @@ -541,7 +541,7 @@ function* generateReferencesForElements( options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode -): Generator { +): Generator { for (const prop of node.props) { if ( prop.type === CompilerDOM.NodeTypes.ATTRIBUTE @@ -566,9 +566,10 @@ function* generateReferencesForElements( ctx.accessExternalVariable(content, startOffset); } - return prop.value.content; + return [content, startOffset]; } } + return []; } function* generateReferencesForScopedCssClasses( diff --git a/packages/language-core/lib/codegen/template/index.ts b/packages/language-core/lib/codegen/template/index.ts index 643136d385..7b49c45017 100644 --- a/packages/language-core/lib/codegen/template/index.ts +++ b/packages/language-core/lib/codegen/template/index.ts @@ -5,6 +5,7 @@ import { endOfLine, newLine, wrapWith } from '../common'; import { TemplateCodegenContext, createTemplateCodegenContext } from './context'; import { getCanonicalComponentName, getPossibleOriginalComponentNames } from './element'; import { generateObjectProperty } from './objectProperty'; +import { generateStringLiteralKey } from './stringLiteralKey'; import { generateTemplateChild, getVForNode } from './templateChild'; import { generateStyleScopedClasses } from './styleScopedClasses'; @@ -16,7 +17,7 @@ export interface TemplateCodegenOptions { scriptSetupBindingNames: Set; scriptSetupImportComponentNames: Set; edited: boolean; - templateRefNames: Map; + templateRefNames: Map; hasDefineSlots?: boolean; slotsAssignName?: string; propsAssignName?: string; @@ -58,8 +59,13 @@ export function* generateTemplate(options: TemplateCodegenOptions): Generator { yield `const __VLS_refs = {${newLine}`; - for (const [name, varName] of options.templateRefNames) { - yield `'${name}': ${varName}!,${newLine}`; + for (const [name, [varName, offset]] of options.templateRefNames) { + yield* generateStringLiteralKey( + name, + offset, + ctx.codeFeatures.navigationAndCompletion + ) + yield `: ${varName}!,${newLine}`; } yield `}${endOfLine}`; yield `declare var $refs: typeof __VLS_refs${endOfLine}`; diff --git a/packages/language-server/tests/renaming.spec.ts b/packages/language-server/tests/renaming.spec.ts index f2b59688d1..203724c902 100644 --- a/packages/language-server/tests/renaming.spec.ts +++ b/packages/language-server/tests/renaming.spec.ts @@ -871,6 +871,54 @@ describe('Renaming', async () => { `); }); + it('Template Ref', async () => { + expect( + await requestRename('tsconfigProject/fixture.vue', 'vue', ` + + + + `, 'bar') + ).toMatchInlineSnapshot(` + { + "changes": { + "file://\${testWorkspacePath}/tsconfigProject/fixture.vue": [ + { + "newText": "bar", + "range": { + "end": { + "character": 16, + "line": 2, + }, + "start": { + "character": 13, + "line": 2, + }, + }, + }, + { + "newText": "bar", + "range": { + "end": { + "character": 34, + "line": 7, + }, + "start": { + "character": 31, + "line": 7, + }, + }, + }, + ], + }, + } + `); + }); + const openedDocuments: TextDocument[] = []; afterEach(async () => {