From 99738ef41233211d6e26de520c3817d395492d37 Mon Sep 17 00:00:00 2001 From: Austaras Date: Sun, 18 Aug 2024 21:27:20 +0800 Subject: [PATCH] fix(es/decorators): Fix metadata for accessors (#9444) **Related issue:** - Closes https://github.com/swc-project/swc/issues/9435 --- .changeset/four-onions-wash.md | 6 ++ .../legacy-metadata/issues/9435/input.ts | 44 ++++++++++++ .../legacy-metadata/issues/9435/output.ts | 69 +++++++++++++++++++ .../src/decorators/legacy/metadata.rs | 25 ++++++- 4 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 .changeset/four-onions-wash.md create mode 100644 crates/swc_ecma_transforms/tests/fixture/legacy-metadata/issues/9435/input.ts create mode 100644 crates/swc_ecma_transforms/tests/fixture/legacy-metadata/issues/9435/output.ts diff --git a/.changeset/four-onions-wash.md b/.changeset/four-onions-wash.md new file mode 100644 index 00000000000..176d2253ff8 --- /dev/null +++ b/.changeset/four-onions-wash.md @@ -0,0 +1,6 @@ +--- +swc_ecma_transforms_proposal: patch +swc_core: patch +--- + +fix(es/proposal): Metadata for accessor diff --git a/crates/swc_ecma_transforms/tests/fixture/legacy-metadata/issues/9435/input.ts b/crates/swc_ecma_transforms/tests/fixture/legacy-metadata/issues/9435/input.ts new file mode 100644 index 00000000000..52eba9ab7a5 --- /dev/null +++ b/crates/swc_ecma_transforms/tests/fixture/legacy-metadata/issues/9435/input.ts @@ -0,0 +1,44 @@ +import { Entity, Column } from "typeorm"; +import { Field, ObjectType, registerEnumType } from "type-graphql"; +import { Enum1, Enum2 } from "./enum.js"; + +export enum Enum3 { + A = "A", + B = "B", + C = "C", + D = "D", +} + +registerEnumType(Enum3, { name: "Enum3" }); + +@Entity("user", { schema: "public" }) +@ObjectType("User") +export class User { + @Column({ name: "first_name" }) + @Field({ nullable: true }) + firstName?: string; + + @Column({ name: "last_name" }) + @Field({ nullable: true }) + lastName?: string; + + @Field() + get fullName(): string { + if (!this.firstName && !this.lastName) { + return ""; + } + return `${this.firstName} ${this.lastName}`.trim(); + } + + @Column() + @Field(() => Enum1) + enum1: Enum1; + + @Column() + @Field(() => Enum2) + enum2: Enum2; + + @Column() + @Field(() => Enum3) + enum3: Enum3; +} diff --git a/crates/swc_ecma_transforms/tests/fixture/legacy-metadata/issues/9435/output.ts b/crates/swc_ecma_transforms/tests/fixture/legacy-metadata/issues/9435/output.ts new file mode 100644 index 00000000000..d39f0832291 --- /dev/null +++ b/crates/swc_ecma_transforms/tests/fixture/legacy-metadata/issues/9435/output.ts @@ -0,0 +1,69 @@ +import { Entity, Column } from "typeorm"; +import { Field, ObjectType, registerEnumType } from "type-graphql"; +import { Enum1, Enum2 } from "./enum.js"; +export enum Enum3 { + A = "A", + B = "B", + C = "C", + D = "D" +} +registerEnumType(Enum3, { + name: "Enum3" +}); +export class User { + firstName?: string; + lastName?: string; + get fullName(): string { + if (!this.firstName && !this.lastName) { + return ""; + } + return `${this.firstName} ${this.lastName}`.trim(); + } + enum1: Enum1; + enum2: Enum2; + enum3: Enum3; +} +_ts_decorate([ + Column({ + name: "first_name" + }), + Field({ + nullable: true + }), + _ts_metadata("design:type", String) +], User.prototype, "firstName", void 0); +_ts_decorate([ + Column({ + name: "last_name" + }), + Field({ + nullable: true + }), + _ts_metadata("design:type", String) +], User.prototype, "lastName", void 0); +_ts_decorate([ + Field(), + _ts_metadata("design:type", String), + _ts_metadata("design:paramtypes", []) +], User.prototype, "fullName", null); +_ts_decorate([ + Column(), + Field(()=>Enum1), + _ts_metadata("design:type", typeof Enum1 === "undefined" ? Object : Enum1) +], User.prototype, "enum1", void 0); +_ts_decorate([ + Column(), + Field(()=>Enum2), + _ts_metadata("design:type", typeof Enum2 === "undefined" ? Object : Enum2) +], User.prototype, "enum2", void 0); +_ts_decorate([ + Column(), + Field(()=>Enum3), + _ts_metadata("design:type", String) +], User.prototype, "enum3", void 0); +User = _ts_decorate([ + Entity("user", { + schema: "public" + }), + ObjectType("User") +], User); diff --git a/crates/swc_ecma_transforms_proposal/src/decorators/legacy/metadata.rs b/crates/swc_ecma_transforms_proposal/src/decorators/legacy/metadata.rs index b0b1c9fdc46..cff47ac53c7 100644 --- a/crates/swc_ecma_transforms_proposal/src/decorators/legacy/metadata.rs +++ b/crates/swc_ecma_transforms_proposal/src/decorators/legacy/metadata.rs @@ -192,8 +192,25 @@ impl VisitMut for Metadata<'_> { } { - let dec = self - .create_metadata_design_decorator("design:type", quote_ident!("Function").as_arg()); + let type_arg = match m.kind { + MethodKind::Method => quote_ident!("Function").as_arg(), + MethodKind::Getter => { + let return_type = m.function.return_type.as_deref(); + + if let Some(kind) = self.enums.get_kind_as_str(return_type) { + quote_ident!(kind).as_arg() + } else { + serialize_type(self.class_name, return_type).as_arg() + } + } + MethodKind::Setter => serialize_type( + self.class_name, + get_type_ann_of_pat(&m.function.params[0].pat), + ) + .as_arg(), + }; + + let dec = self.create_metadata_design_decorator("design:type", type_arg); m.function.decorators.push(dec); } { @@ -217,7 +234,9 @@ impl VisitMut for Metadata<'_> { ); m.function.decorators.push(dec); } - { + + // https://github.com/microsoft/TypeScript/blob/2a8865e6ba95c9bdcdb9e2c9c08f10c5f5c75391/src/compiler/transformers/ts.ts#L1180 + if m.kind == MethodKind::Method { // Copy tsc behaviour // https://github.com/microsoft/TypeScript/blob/5e8c261b6ab746213f19ee3501eb8c48a6215dd7/src/compiler/transformers/typeSerializer.ts#L242 let dec = self.create_metadata_design_decorator(