Skip to content

Commit 91ef7c9

Browse files
authoredNov 22, 2023
fix(es/decorators): Resolve enum for design:returntype (#8320)
1 parent c9c3e7d commit 91ef7c9

File tree

4 files changed

+173
-41
lines changed

4 files changed

+173
-41
lines changed
 

‎crates/swc_ecma_transforms/tests/fixture/legacy-metadata/issues/3319/input.ts

+48
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,24 @@ function decorator(target: any, key: string | symbol, descriptor: PropertyDescri
66
returnType = Reflect.getMetadata('design:returntype', target, key);
77
}
88

9+
enum NumericEnum {
10+
A,
11+
B,
12+
C,
13+
}
14+
15+
enum StringEnum {
16+
A = "A",
17+
B = "B",
18+
C = "C",
19+
}
20+
21+
enum ObjectEnum {
22+
A = "A",
23+
B = 2,
24+
C = "C",
25+
}
26+
927
class Foo {
1028
@decorator
1129
public foo(x: string): string {
@@ -31,4 +49,34 @@ class Foo {
3149
public async quux() {
3250
return 'quux';
3351
}
52+
53+
@decorator
54+
public numeric_array(): number[] {
55+
return [1, 2, 3];
56+
}
57+
58+
@decorator
59+
public string_array(): string[] {
60+
return ['first', 'second', 'third'];
61+
}
62+
63+
@decorator
64+
public numeric_enum(): NumericEnum {
65+
return NumericEnum.A;
66+
}
67+
68+
@decorator
69+
public string_enum(): StringEnum {
70+
return StringEnum.A;
71+
}
72+
73+
@decorator
74+
public object_enum(): ObjectEnum {
75+
return ObjectEnum.A;
76+
}
77+
78+
@decorator
79+
public array_enum(): StringEnum[] {
80+
return [StringEnum.A, StringEnum.B, StringEnum.C];
81+
}
3482
}

‎crates/swc_ecma_transforms/tests/fixture/legacy-metadata/issues/3319/output.ts

+71
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,23 @@ function decorator(target: any, key: string | symbol, descriptor: PropertyDescri
66
returnType = Reflect.getMetadata('design:returntype', target, key);
77
}
88

9+
enum NumericEnum {
10+
A,
11+
B,
12+
C
13+
}
14+
enum StringEnum {
15+
A = "A",
16+
B = "B",
17+
C = "C"
18+
}
19+
20+
enum ObjectEnum {
21+
A = "A",
22+
B = 2,
23+
C = "C"
24+
}
25+
926
class Foo {
1027
public foo(x: string): string {
1128
return 'foo';
@@ -22,6 +39,24 @@ class Foo {
2239
public async quux() {
2340
return 'quux';
2441
}
42+
public numeric_array(): number[] {
43+
return [1, 2, 3];
44+
}
45+
public string_array(): string[] {
46+
return ['first', 'second', 'third'];
47+
}
48+
public numeric_enum(): NumericEnum {
49+
return NumericEnum.A;
50+
}
51+
public string_enum(): StringEnum {
52+
return StringEnum.A;
53+
}
54+
public object_enum(): ObjectEnum {
55+
return ObjectEnum.A;
56+
}
57+
public array_enum(): StringEnum[] {
58+
return [StringEnum.A, StringEnum.B, StringEnum.C];
59+
}
2560
}
2661
_ts_decorate([
2762
decorator,
@@ -53,3 +88,39 @@ _ts_decorate([
5388
_ts_metadata("design:paramtypes", []),
5489
_ts_metadata("design:returntype", Promise)
5590
], Foo.prototype, "quux", null);
91+
_ts_decorate([
92+
decorator,
93+
_ts_metadata("design:type", Function),
94+
_ts_metadata("design:paramtypes", []),
95+
_ts_metadata("design:returntype", Array)
96+
], Foo.prototype, "numeric_array", null);
97+
_ts_decorate([
98+
decorator,
99+
_ts_metadata("design:type", Function),
100+
_ts_metadata("design:paramtypes", []),
101+
_ts_metadata("design:returntype", Array)
102+
], Foo.prototype, "string_array", null);
103+
_ts_decorate([
104+
decorator,
105+
_ts_metadata("design:type", Function),
106+
_ts_metadata("design:paramtypes", []),
107+
_ts_metadata("design:returntype", Number)
108+
], Foo.prototype, "numeric_enum", null);
109+
_ts_decorate([
110+
decorator,
111+
_ts_metadata("design:type", Function),
112+
_ts_metadata("design:paramtypes", []),
113+
_ts_metadata("design:returntype", String)
114+
], Foo.prototype, "string_enum", null);
115+
_ts_decorate([
116+
decorator,
117+
_ts_metadata("design:type", Function),
118+
_ts_metadata("design:paramtypes", []),
119+
_ts_metadata("design:returntype", Object)
120+
], Foo.prototype, "object_enum", null);
121+
_ts_decorate([
122+
decorator,
123+
_ts_metadata("design:type", Function),
124+
_ts_metadata("design:paramtypes", []),
125+
_ts_metadata("design:returntype", Array)
126+
], Foo.prototype, "array_enum", null);

‎crates/swc_ecma_transforms_proposal/src/decorators/legacy/metadata.rs

+53-37
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::ops::Deref;
2+
13
use swc_atoms::JsWord;
24
use swc_common::{
35
collections::AHashMap,
@@ -71,9 +73,35 @@ impl ParamMetadata {
7173
}
7274
}
7375

76+
type EnumMapType = AHashMap<JsWord, EnumKind>;
77+
78+
pub(super) struct EnumMap<'a>(&'a EnumMapType);
79+
80+
impl Deref for EnumMap<'_> {
81+
type Target = EnumMapType;
82+
83+
fn deref(&self) -> &Self::Target {
84+
self.0
85+
}
86+
}
87+
88+
impl EnumMap<'_> {
89+
fn get_kind_as_str(&self, param: Option<&TsTypeAnn>) -> Option<&'static str> {
90+
param
91+
.and_then(|t| t.type_ann.as_ts_type_ref())
92+
.and_then(|t| t.type_name.as_ident())
93+
.and_then(|t| self.get(&t.sym))
94+
.map(|kind| match kind {
95+
EnumKind::Mixed => "Object",
96+
EnumKind::Str => "String",
97+
EnumKind::Num => "Number",
98+
})
99+
}
100+
}
101+
74102
/// https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata/blob/master/src/metadata/metadataVisitor.ts
75103
pub(super) struct Metadata<'a> {
76-
pub(super) enums: &'a AHashMap<JsWord, EnumKind>,
104+
pub(super) enums: EnumMap<'a>,
77105

78106
pub(super) class_name: Option<&'a Ident>,
79107
}
@@ -169,57 +197,45 @@ impl VisitMut for Metadata<'_> {
169197
if m.function.is_async {
170198
quote_ident!("Promise").as_arg()
171199
} else {
172-
serialize_type(self.class_name, m.function.return_type.as_deref()).as_arg()
200+
let return_type = m.function.return_type.as_deref();
201+
202+
if let Some(kind) = self.enums.get_kind_as_str(return_type) {
203+
quote_ident!(kind).as_arg()
204+
} else {
205+
serialize_type(self.class_name, return_type).as_arg()
206+
}
173207
},
174208
);
175209
m.function.decorators.push(dec);
176210
}
177211
}
178212

179213
fn visit_mut_class_prop(&mut self, p: &mut ClassProp) {
180-
if p.decorators.is_empty() {
214+
if p.decorators.is_empty() || p.type_ann.is_none() {
181215
return;
182216
}
183217

184-
if p.type_ann.is_none() {
185-
return;
186-
}
187-
if let Some(name) = p
188-
.type_ann
189-
.as_ref()
190-
.map(|ty| &ty.type_ann)
191-
.and_then(|type_ann| match &**type_ann {
192-
TsType::TsTypeRef(r) => Some(r),
193-
_ => None,
194-
})
195-
.and_then(|r| match &r.type_name {
196-
TsEntityName::TsQualifiedName(_) => None,
197-
TsEntityName::Ident(i) => Some(i),
198-
})
199-
{
200-
if let Some(kind) = self.enums.get(&name.sym) {
201-
let dec = self.create_metadata_design_decorator(
202-
"design:type",
203-
match kind {
204-
EnumKind::Mixed => quote_ident!("Object").as_arg(),
205-
EnumKind::Str => quote_ident!("String").as_arg(),
206-
EnumKind::Num => quote_ident!("Number").as_arg(),
207-
},
208-
);
209-
p.decorators.push(dec);
210-
return;
211-
}
212-
}
218+
let dec = self.create_metadata_design_decorator("design:type", {
219+
let prop_type = p.type_ann.as_deref();
213220

214-
let dec = self.create_metadata_design_decorator(
215-
"design:type",
216-
serialize_type(self.class_name, p.type_ann.as_deref()).as_arg(),
217-
);
221+
if let Some(kind) = self.enums.get_kind_as_str(prop_type) {
222+
quote_ident!(kind).as_arg()
223+
} else {
224+
serialize_type(self.class_name, prop_type).as_arg()
225+
}
226+
});
218227
p.decorators.push(dec);
219228
}
220229
}
221230

222-
impl Metadata<'_> {
231+
impl<'a> Metadata<'a> {
232+
pub(super) fn new(enums: &'a EnumMapType, class_name: Option<&'a Ident>) -> Self {
233+
Self {
234+
enums: EnumMap(enums),
235+
class_name,
236+
}
237+
}
238+
223239
fn create_metadata_design_decorator(&self, design: &str, type_arg: ExprOrSpread) -> Decorator {
224240
Decorator {
225241
span: DUMMY_SP,

‎crates/swc_ecma_transforms_proposal/src/decorators/legacy/mod.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,7 @@ impl VisitMut for TscDecorator {
224224
if self.metadata {
225225
let i = self.class_name.clone();
226226

227-
n.visit_mut_with(&mut Metadata {
228-
enums: &self.enums,
229-
class_name: i.as_ref(),
230-
});
227+
n.visit_mut_with(&mut Metadata::new(&self.enums, i.as_ref()));
231228
}
232229

233230
n.visit_mut_children_with(self);

0 commit comments

Comments
 (0)
Please sign in to comment.