Skip to content

Commit

Permalink
feat(language-core): navigation support for template-ref (#4726)
Browse files Browse the repository at this point in the history
  • Loading branch information
KazariEX authored Aug 31, 2024
1 parent 63fca0b commit 69be985
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 13 deletions.
10 changes: 9 additions & 1 deletion packages/language-core/lib/codegen/script/scriptSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down
19 changes: 10 additions & 9 deletions packages/language-core/lib/codegen/template/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`;
Expand Down Expand Up @@ -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;
Expand All @@ -361,7 +361,7 @@ function* generateVScope(
ctx: TemplateCodegenContext,
node: CompilerDOM.ElementNode,
props: (CompilerDOM.AttributeNode | CompilerDOM.DirectiveNode)[]
): Generator<Code> {
): Generator<Code, [refName?: string, offset?: number]> {
const vScope = props.find(prop => prop.type === CompilerDOM.NodeTypes.DIRECTIVE && (prop.name === 'scope' || prop.name === 'data'));
let inScope = false;
let originalConditionsNum = ctx.blockConditions.length;
Expand All @@ -385,14 +385,14 @@ function* generateVScope(
}

yield* generateElementDirectives(options, ctx, node);
const refName = yield* generateReferencesForElements(options, ctx, node); // <el ref="foo" />
const [refName, offset] = yield* generateReferencesForElements(options, ctx, node); // <el ref="foo" />
yield* generateReferencesForScopedCssClasses(options, ctx, node);

if (inScope) {
yield `}${newLine}`;
ctx.blockConditions.length = originalConditionsNum;
}
return refName;
return [refName, offset];
}

export function getCanonicalComponentName(tagText: string) {
Expand Down Expand Up @@ -541,7 +541,7 @@ function* generateReferencesForElements(
options: TemplateCodegenOptions,
ctx: TemplateCodegenContext,
node: CompilerDOM.ElementNode
): Generator<Code> {
): Generator<Code, [refName: string, offset: number] | []> {
for (const prop of node.props) {
if (
prop.type === CompilerDOM.NodeTypes.ATTRIBUTE
Expand All @@ -566,9 +566,10 @@ function* generateReferencesForElements(
ctx.accessExternalVariable(content, startOffset);
}

return prop.value.content;
return [content, startOffset];
}
}
return [];
}

function* generateReferencesForScopedCssClasses(
Expand Down
12 changes: 9 additions & 3 deletions packages/language-core/lib/codegen/template/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -16,7 +17,7 @@ export interface TemplateCodegenOptions {
scriptSetupBindingNames: Set<string>;
scriptSetupImportComponentNames: Set<string>;
edited: boolean;
templateRefNames: Map<string, string>;
templateRefNames: Map<string, [varName: string, offset: number]>;
hasDefineSlots?: boolean;
slotsAssignName?: string;
propsAssignName?: string;
Expand Down Expand Up @@ -58,8 +59,13 @@ export function* generateTemplate(options: TemplateCodegenOptions): Generator<Co

function* generateRefs(): Generator<Code> {
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}`;
Expand Down
48 changes: 48 additions & 0 deletions packages/language-server/tests/renaming.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,54 @@ describe('Renaming', async () => {
`);
});

it('Template Ref', async () => {
expect(
await requestRename('tsconfigProject/fixture.vue', 'vue', `
<template>
<a ref="foo"></a>
</template>
<script lang="ts" setup>
import { useTemplateRef } from 'vue';
const el = useTemplateRef('foo|');
</script>
`, '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 () => {
Expand Down

0 comments on commit 69be985

Please sign in to comment.