From d39ad4fe37fd88e9897c42a260921140e62ba700 Mon Sep 17 00:00:00 2001 From: edison1105 Date: Thu, 1 Jun 2023 20:57:18 +0800 Subject: [PATCH 1/8] fix(compiler-sfc): support resolve enum value for defineEmits --- .../__snapshots__/defineEmits.spec.ts.snap | 20 +++++++++ .../compileScript/defineEmits.spec.ts | 14 ++++++ .../compiler-sfc/src/script/defineEmits.ts | 6 +++ .../compiler-sfc/src/script/resolveType.ts | 44 ++++++++++++------- 4 files changed, 69 insertions(+), 15 deletions(-) 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 a8bd930fbbc..ca433de60eb 100644 --- a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap +++ b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap @@ -30,6 +30,26 @@ return { emit } })" `; +exports[`defineEmits > w/ type (enum) 1`] = ` +"import { defineComponent as _defineComponent } from 'vue' +enum Foo { BAR = 'bar' } + interface Emits { + (e: Foo.BAR, value: string): void; + } + +export default /*#__PURE__*/_defineComponent({ + emits: [\\"bar\\"], + setup(__props, { expose: __expose, emit }) { + __expose(); + + + +return { Foo, emit } +} + +})" +`; + exports[`defineEmits > w/ type (exported interface) 1`] = ` "import { defineComponent as _defineComponent } from 'vue' export interface Emits { (e: 'foo' | 'bar'): void } diff --git a/packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts b/packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts index c5d2900a4e7..d7e0fff63da 100644 --- a/packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts +++ b/packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts @@ -89,6 +89,20 @@ const emit = defineEmits(['a', 'b']) expect(content).toMatch(`emits: ["foo", "bar"]`) }) + test('w/ enum value', () => { + const { content } = compile(` + + `) + assertCode(content) + expect(content).toMatch(`emits: ["bar"]`) + }) + test('w/ type from normal script', () => { 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 719b1db5dd5..aca8c7c6829 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 8d67ab9686a..afce63c6a3b 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 From e6b33ab69c0d0bf2a1988a3eb6ce7add6d5206cf Mon Sep 17 00:00:00 2001 From: edison1105 Date: Sat, 3 Jun 2023 11:58:58 +0800 Subject: [PATCH 4/8] chore: support nested enum member --- .../__snapshots__/defineEmits.spec.ts.snap | 16 ++++--- .../compileScript/defineEmits.spec.ts | 14 +++--- .../compiler-sfc/src/script/defineEmits.ts | 48 ++++++++----------- .../compiler-sfc/src/script/resolveType.ts | 46 +++++++++++++++++- 4 files changed, 81 insertions(+), 43 deletions(-) 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 16566fdbcf6..8c3952bccf3 100644 --- a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap +++ b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap @@ -14,23 +14,25 @@ return { myEmit } }" `; -exports[`defineEmits > w/ enum value 1`] = ` +exports[`defineEmits > w/ enum member 1`] = ` "import { defineComponent as _defineComponent } from 'vue' -enum Foo { BAR = 'bar', BAZ = 'baz', QUX = 'qux' } - type BAZ = Foo.BAZ +enum Foo { Foo = 'foo', Bar = 'bar', Qux = 'qux' } + export type FooRef = Bar.Foo + interface Emits { - (e: Foo.BAR, value: string): void; - (e: BAZ, value: string): void; + (e: FooRef, value: string): void; + (e: Foo.Bar, value: string): void; } export default /*#__PURE__*/_defineComponent({ - emits: [\\"bar\\", \\"baz\\"], + emits: [\\"foo\\", \\"bar\\"], setup(__props, { expose: __expose, emit }) { __expose(); + enum Bar { Foo = Foo.Foo } -return { Foo, emit } +return { Foo, Bar, emit } } })" diff --git a/packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts b/packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts index 81dbba941b9..2fd5b0f95eb 100644 --- a/packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts +++ b/packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts @@ -89,20 +89,22 @@ const emit = defineEmits(['a', 'b']) expect(content).toMatch(`emits: ["foo", "bar"]`) }) - test('w/ enum value', () => { + test('w/ enum member', () => { const { content } = compile(` `) assertCode(content) - expect(content).toMatch(`emits: ["bar", "baz"]`) + expect(content).toMatch(`emits: ["foo", "bar"]`) }) 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 aca8c7c6829..1c80d1c863e 100644 --- a/packages/compiler-sfc/src/script/defineEmits.ts +++ b/packages/compiler-sfc/src/script/defineEmits.ts @@ -1,16 +1,11 @@ -import { - Identifier, - LVal, - Node, - RestElement, - TSEnumDeclaration -} from '@babel/types' +import { Identifier, LVal, Node, RestElement } from '@babel/types' import { isCallOf } from './utils' import { ScriptCompileContext } from './context' import { resolveTypeElements, resolveUnionType, - resolveTypeReference + resolveTypeReference, + resolveEnumMemberValue } from './resolveType' export const DEFINE_EMITS = 'defineEmits' @@ -124,10 +119,16 @@ function extractEventNames( emits.add(String(type.literal.value)) } } else if (type.type === 'TSEnumDeclaration') { - if (typeNode.type === 'TSTypeReference') { - if (typeNode.typeName.type === 'TSQualifiedName') { - extractEnumValue(type, typeNode.typeName.right.name, emits) - } + if ( + typeNode.type === 'TSTypeReference' && + typeNode.typeName.type === 'TSQualifiedName' + ) { + const memberValue = resolveEnumMemberValue( + ctx, + type, + typeNode.typeName.right.name + ) + if (memberValue) emits.add(memberValue) } } else if (type.type === 'TSTypeReference') { if ( @@ -141,26 +142,15 @@ function extractEventNames( type.typeName.left.name ) if (resolved && resolved.type === 'TSEnumDeclaration') { - extractEnumValue(resolved, type.typeName.right.name, emits) + const memberValue = resolveEnumMemberValue( + ctx, + resolved, + type.typeName.right.name + ) + if (memberValue) emits.add(memberValue) } } } } } } -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 afce63c6a3b..87aedfef81a 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -592,6 +592,7 @@ type ReferenceTypes = | TSExpressionWithTypeArguments | TSImportType | TSTypeQuery + | Identifier export function resolveTypeReference( ctx: TypeResolveContext, @@ -692,7 +693,9 @@ function getReferenceName(node: ReferenceTypes): string | string[] { ? node.expression : node.type === 'TSImportType' ? node.qualifier - : node.exprName + : node.type === 'TSTypeQuery' + ? node.exprName + : node if (ref?.type === 'Identifier') { return ref.name } else if (ref?.type === 'TSQualifiedName') { @@ -1687,3 +1690,44 @@ export function resolveUnionType( return types } + +export function resolveEnumMemberValue( + ctx: TypeResolveContext, + node: Node & MaybeWithScope & { _resolvedElements?: ResolvedElements }, + typeName: string, + scope?: TypeScope +): string | undefined { + if (node.type === 'TSTypeReference') { + const resolved = resolveTypeReference(ctx, node, scope, typeName) + if (resolved) node = resolved + } + + if (node.type === 'Identifier') { + const resolved = resolveTypeReference(ctx, node, scope, node.name) + if (resolved) node = resolved + } + + if (node.type === 'TSEnumDeclaration') { + for (const m of node.members) { + if (m.id.type === 'Identifier' && m.id.name === typeName) { + if (m.initializer) { + if (m.initializer.type === 'StringLiteral') { + return m.initializer.value + } else if (m.initializer.type === 'MemberExpression') { + if ( + m.initializer.object.type === 'Identifier' && + m.initializer.property.type === 'Identifier' + ) { + return resolveEnumMemberValue( + ctx, + m.initializer.object, + m.initializer.property.name, + scope + ) + } + } + } + } + } + } +} From e5609b6c13fee52f5888de24c8f8a39d40d0e199 Mon Sep 17 00:00:00 2001 From: daiwei Date: Fri, 20 Oct 2023 17:46:47 +0800 Subject: [PATCH 5/8] test: update snap --- .../compileScript/__snapshots__/defineEmits.spec.ts.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 27f28a36c49..b9dcfdcb2ae 100644 --- a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap +++ b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap @@ -26,11 +26,11 @@ enum Foo { Foo = 'foo', Bar = 'bar', Qux = 'qux' } export default /*#__PURE__*/_defineComponent({ emits: [\\"foo\\", \\"bar\\"], - setup(__props, { expose: __expose, emit }) { + setup(__props, { expose: __expose, emit: __emit }) { __expose(); enum Bar { Foo = Foo.Foo } - + const emit = __emit return { Foo, Bar, emit } } From ee222232ad5c4c77696040851d57b34c2f2ea81c Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 01:09:32 +0000 Subject: [PATCH 6/8] [autofix.ci] apply automated fixes --- packages/compiler-sfc/src/script/resolveType.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index 143c0973380..ed6c40e72f3 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -757,9 +757,9 @@ function getReferenceName(node: ReferenceTypes): string | string[] { node.type === 'TSTypeReference' ? node.typeName : node.type === 'TSExpressionWithTypeArguments' - ? node.expression + ? node.expression : node.type === 'TSImportType' - ? node.qualifier + ? node.qualifier : node.type === 'TSTypeQuery' ? node.exprName : node From e51c358f73a691bebc3189c9323e98f43ff88c46 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 10 Oct 2024 08:57:35 +0000 Subject: [PATCH 7/8] [autofix.ci] apply automated fixes --- packages/compiler-sfc/src/script/defineEmits.ts | 10 +++++----- packages/compiler-sfc/src/script/resolveType.ts | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/compiler-sfc/src/script/defineEmits.ts b/packages/compiler-sfc/src/script/defineEmits.ts index c48c7e560b7..f684d548202 100644 --- a/packages/compiler-sfc/src/script/defineEmits.ts +++ b/packages/compiler-sfc/src/script/defineEmits.ts @@ -10,10 +10,10 @@ import { isCallOf } from './utils' import type { ScriptCompileContext } from './context' import { type TypeResolveContext, + resolveEnumMemberValue, resolveTypeElements, - resolveUnionType, resolveTypeReference, - resolveEnumMemberValue, + resolveUnionType, } from './resolveType' export const DEFINE_EMITS = 'defineEmits' @@ -133,7 +133,7 @@ function extractEventNames( const memberValue = resolveEnumMemberValue( ctx, type, - typeNode.typeName.right.name + typeNode.typeName.right.name, ) if (memberValue) emits.add(memberValue) } @@ -146,13 +146,13 @@ function extractEventNames( ctx, type, undefined, - type.typeName.left.name + type.typeName.left.name, ) if (resolved && resolved.type === 'TSEnumDeclaration') { const memberValue = resolveEnumMemberValue( ctx, resolved, - type.typeName.right.name + type.typeName.right.name, ) if (memberValue) emits.add(memberValue) } diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index f77247079b6..3a4b50d535b 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -765,7 +765,7 @@ function innerResolveTypeReference( scope, name[0], node, - onlyExported + onlyExported, ) if (resolved) { if (resolved.type === 'TSEnumDeclaration') { @@ -779,14 +779,14 @@ function innerResolveTypeReference( const childScope = moduleDeclToScope( ctx, resolved, - resolved._ownerScope || scope + resolved._ownerScope || scope, ) return innerResolveTypeReference( ctx, childScope, name.length > 2 ? name.slice(1) : name[name.length - 1], node, - !resolved.declare + !resolved.declare, ) } } @@ -1963,7 +1963,7 @@ export function resolveEnumMemberValue( ctx: TypeResolveContext, node: Node & MaybeWithScope & { _resolvedElements?: ResolvedElements }, typeName: string, - scope?: TypeScope + scope?: TypeScope, ): string | undefined { if (node.type === 'TSTypeReference') { const resolved = resolveTypeReference(ctx, node, scope, typeName) @@ -1990,7 +1990,7 @@ export function resolveEnumMemberValue( ctx, m.initializer.object, m.initializer.property.name, - scope + scope, ) } } From 60f79ea44012c0820853e2ea7993597b90155098 Mon Sep 17 00:00:00 2001 From: daiwei Date: Thu, 10 Oct 2024 17:00:19 +0800 Subject: [PATCH 8/8] chore: update test --- .../compileScript/__snapshots__/defineEmits.spec.ts.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 b2a69d77794..9ce23d7eed7 100644 --- a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap +++ b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap @@ -25,8 +25,8 @@ enum Foo { Foo = 'foo', Bar = 'bar', Qux = 'qux' } (e: Foo.Bar, value: string): void; } -export default /*#__PURE__*/_defineComponent({ - emits: [\\"foo\\", \\"bar\\"], +export default /*@__PURE__*/_defineComponent({ + emits: ["foo", "bar"], setup(__props, { expose: __expose, emit: __emit }) { __expose();