Skip to content

Commit 638b949

Browse files
authored
feat(language-core): support navigation of events with v-on syntax (#5275)
1 parent c2dfd86 commit 638b949

File tree

4 files changed

+40
-14
lines changed

4 files changed

+40
-14
lines changed

packages/language-core/lib/codegen/globalTypes.ts

+11-5
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,13 @@ export function generateGlobalTypes({
7979
: true
8080
: false
8181
: false;
82-
type __VLS_NormalizeComponentEvent<Props, Events, onEvent extends keyof Props, Event extends keyof Events, CamelizedEvent extends keyof Events> = (
82+
type __VLS_NormalizeComponentEvent<Props, Emits, onEvent extends keyof Props, Event extends keyof Emits, CamelizedEvent extends keyof Emits> = (
8383
__VLS_IsFunction<Props, onEvent> extends true
8484
? Props
85-
: __VLS_IsFunction<Events, Event> extends true
86-
? { [K in onEvent]?: Events[Event] }
87-
: __VLS_IsFunction<Events, CamelizedEvent> extends true
88-
? { [K in onEvent]?: Events[CamelizedEvent] }
85+
: __VLS_IsFunction<Emits, Event> extends true
86+
? { [K in onEvent]?: Emits[Event] }
87+
: __VLS_IsFunction<Emits, CamelizedEvent> extends true
88+
? { [K in onEvent]?: Emits[CamelizedEvent] }
8989
: Props
9090
)${checkUnknownEvents ? '' : ' & Record<string, unknown>'};
9191
// fix https://github.com/vuejs/language-tools/issues/926
@@ -111,6 +111,12 @@ export function generateGlobalTypes({
111111
}
112112
>
113113
>;
114+
type __VLS_ResolveEmits<
115+
Comp,
116+
Emits,
117+
TypeEmits = ${target >= 3.6 ? `Comp extends { __typeEmits?: infer T } ? unknown extends T ? {} : import('${lib}').ShortEmitsToObject<T> : {}` : `{}`},
118+
NormalizedEmits = __VLS_NormalizeEmits<Emits> extends infer E ? string extends keyof E ? {} : E : never,
119+
> = __VLS_SpreadMerge<NormalizedEmits, TypeEmits>;
114120
type __VLS_PrettifyGlobal<T> = { [K in keyof T]: T[K]; } & {};
115121
type __VLS_PickFunctionalComponentCtx<T, K> = NonNullable<__VLS_PickNotAny<
116122
'__ctx' extends keyof __VLS_PickNotAny<K, {}> ? K extends { __ctx?: infer Ctx } ? Ctx : never : any

packages/language-core/lib/codegen/template/element.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ export function* generateComponent(
245245
yield `, ...__VLS_functionalComponentArgsRest(${componentFunctionalVar}))${endOfLine}`;
246246

247247
yield* generateFailedPropExps(options, ctx, failedPropExps);
248-
yield* generateElementEvents(options, ctx, node, componentFunctionalVar, componentVNodeVar, componentCtxVar);
248+
yield* generateElementEvents(options, ctx, node, componentOriginalVar, componentFunctionalVar, componentVNodeVar, componentCtxVar);
249249
yield* generateElementDirectives(options, ctx, node);
250250

251251
const [refName, offset] = yield* generateElementReference(options, ctx, node);

packages/language-core/lib/codegen/template/elementEvents.ts

+16-8
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,18 @@ import { wrapWith } from '../utils/wrapWith';
88
import type { TemplateCodegenContext } from './context';
99
import type { TemplateCodegenOptions } from './index';
1010
import { generateInterpolation } from './interpolation';
11+
import { generatePropertyAccess } from './propertyAccess';
1112

1213
export function* generateElementEvents(
1314
options: TemplateCodegenOptions,
1415
ctx: TemplateCodegenContext,
1516
node: CompilerDOM.ElementNode,
17+
componentOriginalVar: string,
1618
componentFunctionalVar: string,
1719
componentVNodeVar: string,
1820
componentCtxVar: string
1921
): Generator<Code> {
20-
let emitVar: string | undefined;
21-
let eventsVar: string | undefined;
22+
let emitsVar: string | undefined;
2223
let propsVar: string | undefined;
2324

2425
for (const prop of node.props) {
@@ -33,12 +34,10 @@ export function* generateElementEvents(
3334
)
3435
) {
3536
ctx.currentComponent!.used = true;
36-
if (!emitVar) {
37-
emitVar = ctx.getInternalVariable();
38-
eventsVar = ctx.getInternalVariable();
37+
if (!emitsVar) {
38+
emitsVar = ctx.getInternalVariable();
3939
propsVar = ctx.getInternalVariable();
40-
yield `let ${emitVar}!: typeof ${componentCtxVar}.emit${endOfLine}`;
41-
yield `let ${eventsVar}!: __VLS_NormalizeEmits<typeof ${emitVar}>${endOfLine}`;
40+
yield `let ${emitsVar}!: __VLS_ResolveEmits<typeof ${componentOriginalVar}, typeof ${componentCtxVar}.emit>${endOfLine}`;
4241
yield `let ${propsVar}!: __VLS_FunctionalComponentProps<typeof ${componentFunctionalVar}, typeof ${componentVNodeVar}>${endOfLine}`;
4342
}
4443
let source = prop.arg?.loc.source ?? 'model-value';
@@ -55,7 +54,16 @@ export function* generateElementEvents(
5554
propPrefix = 'onVnode-';
5655
emitPrefix = 'vnode-';
5756
}
58-
yield `(): __VLS_NormalizeComponentEvent<typeof ${propsVar}, typeof ${eventsVar}, '${camelize(propPrefix + source)}', '${emitPrefix + source}', '${camelize(emitPrefix + source)}'> => ({${newLine}`;
57+
yield `(): __VLS_NormalizeComponentEvent<typeof ${propsVar}, typeof ${emitsVar}, '${camelize(propPrefix + source)}', '${emitPrefix + source}', '${camelize(emitPrefix + source)}'> => (`;
58+
yield emitsVar;
59+
yield* generatePropertyAccess(
60+
options,
61+
ctx,
62+
emitPrefix + source,
63+
start,
64+
ctx.codeFeatures.navigation
65+
);
66+
yield `, {${newLine}`;
5967
if (prop.name === 'on') {
6068
yield* generateEventArg(ctx, source, start!, propPrefix.slice(0, -1));
6169
yield `: `;

packages/typescript-plugin/lib/common.ts

+12
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,18 @@ function getDefinitionAndBoundSpan<T>(
185185
const definitions = new Set<ts.DefinitionInfo>(result.definitions);
186186
const skippedDefinitions: ts.DefinitionInfo[] = [];
187187

188+
// #5275
189+
if (result.definitions.length >= 2) {
190+
for (const definition of result.definitions) {
191+
if (
192+
root.sfc.content[definition.textSpan.start - 1] === '@'
193+
|| root.sfc.content.slice(definition.textSpan.start - 5, definition.textSpan.start) === 'v-on:'
194+
) {
195+
skippedDefinitions.push(definition);
196+
}
197+
}
198+
}
199+
188200
for (const definition of result.definitions) {
189201
if (vueOptions.extensions.some(ext => definition.fileName.endsWith(ext))) {
190202
continue;

0 commit comments

Comments
 (0)