diff --git a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap index b876743fe..16566fdbc 100644 --- a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap +++ b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap @@ -16,13 +16,15 @@ return { myEmit } exports[`defineEmits > w/ enum value 1`] = ` "import { defineComponent as _defineComponent } from 'vue' -enum Foo { BAR = 'bar' } +enum Foo { BAR = 'bar', BAZ = 'baz', QUX = 'qux' } + type BAZ = Foo.BAZ interface Emits { (e: Foo.BAR, value: string): void; + (e: BAZ, value: string): void; } export default /*#__PURE__*/_defineComponent({ - emits: [\\"bar\\"], + emits: [\\"bar\\", \\"baz\\"], setup(__props, { expose: __expose, emit }) { __expose(); diff --git a/packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts b/packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts index d7e0fff63..81dbba941 100644 --- a/packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts +++ b/packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts @@ -92,15 +92,17 @@ const emit = defineEmits(['a', 'b']) test('w/ enum value', () => { const { content } = compile(` `) assertCode(content) - expect(content).toMatch(`emits: ["bar"]`) + expect(content).toMatch(`emits: ["bar", "baz"]`) }) test('w/ type from normal script', () => { diff --git a/packages/compiler-sfc/src/script/defineEmits.ts b/packages/compiler-sfc/src/script/defineEmits.ts index 719b1db5d..aca8c7c68 100644 --- a/packages/compiler-sfc/src/script/defineEmits.ts +++ b/packages/compiler-sfc/src/script/defineEmits.ts @@ -1,7 +1,17 @@ -import { Identifier, LVal, Node, RestElement } from '@babel/types' +import { + Identifier, + LVal, + Node, + RestElement, + TSEnumDeclaration +} from '@babel/types' import { isCallOf } from './utils' import { ScriptCompileContext } from './context' -import { resolveTypeElements, resolveUnionType } from './resolveType' +import { + resolveTypeElements, + resolveUnionType, + resolveTypeReference +} from './resolveType' export const DEFINE_EMITS = 'defineEmits' @@ -102,7 +112,8 @@ function extractEventNames( eventName.typeAnnotation && eventName.typeAnnotation.type === 'TSTypeAnnotation' ) { - const types = resolveUnionType(ctx, eventName.typeAnnotation.typeAnnotation) + const typeNode = eventName.typeAnnotation.typeAnnotation + const types = resolveUnionType(ctx, typeNode) for (const type of types) { if (type.type === 'TSLiteralType') { @@ -113,12 +124,43 @@ function extractEventNames( emits.add(String(type.literal.value)) } } else if (type.type === 'TSEnumDeclaration') { - for (const m of type.members) { - if (m.initializer && m.initializer.type === 'StringLiteral') { - emits.add(String(m.initializer.value)) + if (typeNode.type === 'TSTypeReference') { + if (typeNode.typeName.type === 'TSQualifiedName') { + extractEnumValue(type, typeNode.typeName.right.name, emits) + } + } + } else if (type.type === 'TSTypeReference') { + if ( + type.typeName.type === 'TSQualifiedName' && + type.typeName.left.type === 'Identifier' + ) { + const resolved = resolveTypeReference( + ctx, + type, + undefined, + type.typeName.left.name + ) + if (resolved && resolved.type === 'TSEnumDeclaration') { + extractEnumValue(resolved, type.typeName.right.name, emits) } } } } } } +function extractEnumValue( + typeNode: TSEnumDeclaration, + typeName: string, + emits: Set +) { + for (const m of typeNode.members) { + if ( + m.id.type === 'Identifier' && + m.id.name === typeName && + m.initializer && + m.initializer.type === 'StringLiteral' + ) { + emits.add(String(m.initializer.value)) + } + } +} diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index 8d67ab968..afce63c6a 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -593,7 +593,7 @@ type ReferenceTypes = | TSImportType | TSTypeQuery -function resolveTypeReference( +export function resolveTypeReference( ctx: TypeResolveContext, node: ReferenceTypes & { _resolvedReference?: ScopeTypeNode