Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions extensions/vscode/syntaxes/vue.tmLanguage.json
Original file line number Diff line number Diff line change
Expand Up @@ -977,10 +977,10 @@
"include": "#vue-directives-style-attr"
},
{
"include": "#vue-directives-original"
"include": "#vue-directives-generic-attr"
},
{
"include": "#vue-directives-generic-attr"
"include": "#vue-directives-original"
}
]
},
Expand Down Expand Up @@ -1199,7 +1199,7 @@
]
},
"vue-directives-generic-attr": {
"begin": "\\b(generic)\\s*(=)",
"begin": "\\b((?:v-)?generic)\\s*(=)",
"captures": {
"1": {
"name": "entity.other.attribute-name.html.vue"
Expand Down
29 changes: 28 additions & 1 deletion packages/language-core/lib/codegen/template/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,9 @@ export function* generateComponent(
yield* generateElementProps(options, ctx, node, props, false);
yield `}))${endOfLine}`;

yield `const ${var_componentInstance} = ${var_functionalComponent}(`;
yield `const ${var_componentInstance} = ${var_functionalComponent}`;
yield* generateComponentGeneric(ctx, props);
yield `(`;
yield* wrapWith(
startTagOffset,
startTagOffset + node.tag.length,
Expand Down Expand Up @@ -452,6 +454,31 @@ function* generateCanonicalComponentName(tagText: string, offset: number, featur
}
}

function* generateComponentGeneric(
ctx: TemplateCodegenContext,
props: (CompilerDOM.AttributeNode | CompilerDOM.DirectiveNode)[]
): Generator<Code> {
for (const prop of props) {
if (prop.type !== CompilerDOM.NodeTypes.DIRECTIVE || prop.name !== 'generic' || !prop.exp) {
continue;
}
yield* wrapWith(
prop.exp.loc.start.offset,
prop.exp.loc.end.offset,
ctx.codeFeatures.verification,
`<`,
[
prop.exp.loc.source,
'template',
prop.exp.loc.start.offset,
ctx.codeFeatures.all
],
`>`
);
break;
}
}

function* generateComponentSlot(
options: TemplateCodegenOptions,
ctx: TemplateCodegenContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export function* generateElementDirectives(
|| prop.name === 'bind'
|| prop.name === 'scope'
|| prop.name === 'data'
|| prop.name === 'generic'
) {
continue;
}
Expand Down
1 change: 1 addition & 0 deletions test-workspace/tsc/passedFixtures/vue2/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@
"../vue3/slots",
"../vue3/templateRef",
"../vue3/templateRef_native",
"../vue3/v-generic"
]
}
5 changes: 5 additions & 0 deletions test-workspace/tsc/passedFixtures/vue3/v-generic/comp.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script setup lang="ts" generic="T extends string | number">
defineEmits<{
foo: [val: T]
}>();
</script>
11 changes: 11 additions & 0 deletions test-workspace/tsc/passedFixtures/vue3/v-generic/main.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
import { exactType } from '../../shared';
import Comp from './comp.vue';
</script>

<template>
<Comp v-generic="number" @foo="(val) => exactType(val, {} as number)"/>
<Comp v-generic="string" @foo="(val) => exactType(val, {} as string)"/>
<!-- @vue-expect-error -->
<Comp v-generic="boolean" />
</template>