Skip to content

Commit

Permalink
fix(language-core): infer template ref's type of native elements with…
Browse files Browse the repository at this point in the history
… `v-for` correctly (#4933)
  • Loading branch information
KazariEX authored Oct 26, 2024
1 parent 06f6f02 commit e6e8ae5
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 9 deletions.
9 changes: 7 additions & 2 deletions packages/language-core/lib/codegen/template/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,8 @@ export function* generateElement(
ctx: TemplateCodegenContext,
node: CompilerDOM.ElementNode,
currentComponent: CompilerDOM.ElementNode | undefined,
componentCtxVar: string | undefined
componentCtxVar: string | undefined,
isVForChild: boolean
): Generator<Code> {
const startTagOffset = node.loc.start.offset + options.template.content.substring(node.loc.start.offset).indexOf(node.tag);
const endTagOffset = !node.isSelfClosing && options.template.lang === 'html'
Expand Down Expand Up @@ -350,7 +351,11 @@ export function* generateElement(

const [refName, offset] = yield* generateVScope(options, ctx, node, node.props);
if (refName) {
ctx.templateRefs.set(refName, [`__VLS_nativeElements['${node.tag}']`, offset!]);
let refValue = `__VLS_nativeElements['${node.tag}']`;
if (isVForChild) {
refValue = `[${refValue}]`;
}
ctx.templateRefs.set(refName, [refValue, offset!]);
}
if (ctx.singleRootNode === node) {
ctx.singleRootElType = `typeof __VLS_nativeElements['${node.tag}']`;
Expand Down
5 changes: 3 additions & 2 deletions packages/language-core/lib/codegen/template/templateChild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export function* generateTemplateChild(
node: CompilerDOM.RootNode | CompilerDOM.TemplateChildNode | CompilerDOM.SimpleExpressionNode,
currentComponent: CompilerDOM.ElementNode | undefined,
prevNode: CompilerDOM.TemplateChildNode | undefined,
componentCtxVar: string | undefined
componentCtxVar: string | undefined,
isVForChild: boolean = false
): Generator<Code> {
if (prevNode?.type === CompilerDOM.NodeTypes.COMMENT) {
const commentText = prevNode.content.trim().split(' ')[0];
Expand Down Expand Up @@ -82,7 +83,7 @@ export function* generateTemplateChild(
node.tagType === CompilerDOM.ElementTypes.ELEMENT
|| node.tagType === CompilerDOM.ElementTypes.TEMPLATE
) {
yield* generateElement(options, ctx, node, currentComponent, componentCtxVar);
yield* generateElement(options, ctx, node, currentComponent, componentCtxVar, isVForChild);
}
else {
yield* generateComponent(options, ctx, node, currentComponent);
Expand Down
2 changes: 1 addition & 1 deletion packages/language-core/lib/codegen/template/vFor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export function* generateVFor(
}
let prev: CompilerDOM.TemplateChildNode | undefined;
for (const childNode of node.children) {
yield* generateTemplateChild(options, ctx, childNode, currentComponent, prev, componentCtxVar);
yield* generateTemplateChild(options, ctx, childNode, currentComponent, prev, componentCtxVar, true);
prev = childNode;
}
for (const varName of forBlockVars) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,32 @@ if (comp1.value) {
exactType(comp1.value.foo, 1);
}
const comp2 = useTemplateRef('v-for');
const comp2 = useTemplateRef('v-for-generic');
if (comp2.value) {
exactType(comp2.value[0]?.foo, {} as number | undefined);
}
const comp3 = useTemplateRef('a');
const comp3 = useTemplateRef('native');
if (comp3.value) {
exactType(comp3.value.href, {} as string);
}
const comp4 = useTemplateRef('v-for-native');
if (comp4.value) {
exactType(comp4.value[0]?.href, {} as string | undefined);
}
</script>

<template>
<GenericGlobal ref="generic" :foo="1"/>
{{ exactType(comp1?.foo, {} as 1 | undefined) }}

<GenericGlobal v-for="i in 4" ref="v-for" :foo="i"/>
<GenericGlobal v-for="i in 4" ref="v-for-generic" :foo="i"/>
{{ exactType(comp2?.[0]?.foo, {} as number | undefined) }}

<a ref="a"></a>
<a ref="native"></a>
{{ exactType(comp3?.href, {} as string | undefined) }}

<a v-for="i in 3" ref="v-for-native" :key="i"></a>
{{ exactType(comp4?.[0]?.href, {} as string | undefined) }}
</template>

0 comments on commit e6e8ae5

Please sign in to comment.