mirror of
https://github.com/swc-project/swc.git
synced 2024-11-27 13:38:33 +03:00
fix(es/decorators): Resolve enum for design:returntype
(#8320)
This commit is contained in:
parent
c9c3e7d189
commit
91ef7c9415
@ -6,6 +6,24 @@ function decorator(target: any, key: string | symbol, descriptor: PropertyDescri
|
||||
returnType = Reflect.getMetadata('design:returntype', target, key);
|
||||
}
|
||||
|
||||
enum NumericEnum {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
enum StringEnum {
|
||||
A = "A",
|
||||
B = "B",
|
||||
C = "C",
|
||||
}
|
||||
|
||||
enum ObjectEnum {
|
||||
A = "A",
|
||||
B = 2,
|
||||
C = "C",
|
||||
}
|
||||
|
||||
class Foo {
|
||||
@decorator
|
||||
public foo(x: string): string {
|
||||
@ -31,4 +49,34 @@ class Foo {
|
||||
public async quux() {
|
||||
return 'quux';
|
||||
}
|
||||
|
||||
@decorator
|
||||
public numeric_array(): number[] {
|
||||
return [1, 2, 3];
|
||||
}
|
||||
|
||||
@decorator
|
||||
public string_array(): string[] {
|
||||
return ['first', 'second', 'third'];
|
||||
}
|
||||
|
||||
@decorator
|
||||
public numeric_enum(): NumericEnum {
|
||||
return NumericEnum.A;
|
||||
}
|
||||
|
||||
@decorator
|
||||
public string_enum(): StringEnum {
|
||||
return StringEnum.A;
|
||||
}
|
||||
|
||||
@decorator
|
||||
public object_enum(): ObjectEnum {
|
||||
return ObjectEnum.A;
|
||||
}
|
||||
|
||||
@decorator
|
||||
public array_enum(): StringEnum[] {
|
||||
return [StringEnum.A, StringEnum.B, StringEnum.C];
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,23 @@ function decorator(target: any, key: string | symbol, descriptor: PropertyDescri
|
||||
returnType = Reflect.getMetadata('design:returntype', target, key);
|
||||
}
|
||||
|
||||
enum NumericEnum {
|
||||
A,
|
||||
B,
|
||||
C
|
||||
}
|
||||
enum StringEnum {
|
||||
A = "A",
|
||||
B = "B",
|
||||
C = "C"
|
||||
}
|
||||
|
||||
enum ObjectEnum {
|
||||
A = "A",
|
||||
B = 2,
|
||||
C = "C"
|
||||
}
|
||||
|
||||
class Foo {
|
||||
public foo(x: string): string {
|
||||
return 'foo';
|
||||
@ -22,6 +39,24 @@ class Foo {
|
||||
public async quux() {
|
||||
return 'quux';
|
||||
}
|
||||
public numeric_array(): number[] {
|
||||
return [1, 2, 3];
|
||||
}
|
||||
public string_array(): string[] {
|
||||
return ['first', 'second', 'third'];
|
||||
}
|
||||
public numeric_enum(): NumericEnum {
|
||||
return NumericEnum.A;
|
||||
}
|
||||
public string_enum(): StringEnum {
|
||||
return StringEnum.A;
|
||||
}
|
||||
public object_enum(): ObjectEnum {
|
||||
return ObjectEnum.A;
|
||||
}
|
||||
public array_enum(): StringEnum[] {
|
||||
return [StringEnum.A, StringEnum.B, StringEnum.C];
|
||||
}
|
||||
}
|
||||
_ts_decorate([
|
||||
decorator,
|
||||
@ -53,3 +88,39 @@ _ts_decorate([
|
||||
_ts_metadata("design:paramtypes", []),
|
||||
_ts_metadata("design:returntype", Promise)
|
||||
], Foo.prototype, "quux", null);
|
||||
_ts_decorate([
|
||||
decorator,
|
||||
_ts_metadata("design:type", Function),
|
||||
_ts_metadata("design:paramtypes", []),
|
||||
_ts_metadata("design:returntype", Array)
|
||||
], Foo.prototype, "numeric_array", null);
|
||||
_ts_decorate([
|
||||
decorator,
|
||||
_ts_metadata("design:type", Function),
|
||||
_ts_metadata("design:paramtypes", []),
|
||||
_ts_metadata("design:returntype", Array)
|
||||
], Foo.prototype, "string_array", null);
|
||||
_ts_decorate([
|
||||
decorator,
|
||||
_ts_metadata("design:type", Function),
|
||||
_ts_metadata("design:paramtypes", []),
|
||||
_ts_metadata("design:returntype", Number)
|
||||
], Foo.prototype, "numeric_enum", null);
|
||||
_ts_decorate([
|
||||
decorator,
|
||||
_ts_metadata("design:type", Function),
|
||||
_ts_metadata("design:paramtypes", []),
|
||||
_ts_metadata("design:returntype", String)
|
||||
], Foo.prototype, "string_enum", null);
|
||||
_ts_decorate([
|
||||
decorator,
|
||||
_ts_metadata("design:type", Function),
|
||||
_ts_metadata("design:paramtypes", []),
|
||||
_ts_metadata("design:returntype", Object)
|
||||
], Foo.prototype, "object_enum", null);
|
||||
_ts_decorate([
|
||||
decorator,
|
||||
_ts_metadata("design:type", Function),
|
||||
_ts_metadata("design:paramtypes", []),
|
||||
_ts_metadata("design:returntype", Array)
|
||||
], Foo.prototype, "array_enum", null);
|
||||
|
@ -1,3 +1,5 @@
|
||||
use std::ops::Deref;
|
||||
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::{
|
||||
collections::AHashMap,
|
||||
@ -71,9 +73,35 @@ impl ParamMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
type EnumMapType = AHashMap<JsWord, EnumKind>;
|
||||
|
||||
pub(super) struct EnumMap<'a>(&'a EnumMapType);
|
||||
|
||||
impl Deref for EnumMap<'_> {
|
||||
type Target = EnumMapType;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl EnumMap<'_> {
|
||||
fn get_kind_as_str(&self, param: Option<&TsTypeAnn>) -> Option<&'static str> {
|
||||
param
|
||||
.and_then(|t| t.type_ann.as_ts_type_ref())
|
||||
.and_then(|t| t.type_name.as_ident())
|
||||
.and_then(|t| self.get(&t.sym))
|
||||
.map(|kind| match kind {
|
||||
EnumKind::Mixed => "Object",
|
||||
EnumKind::Str => "String",
|
||||
EnumKind::Num => "Number",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata/blob/master/src/metadata/metadataVisitor.ts
|
||||
pub(super) struct Metadata<'a> {
|
||||
pub(super) enums: &'a AHashMap<JsWord, EnumKind>,
|
||||
pub(super) enums: EnumMap<'a>,
|
||||
|
||||
pub(super) class_name: Option<&'a Ident>,
|
||||
}
|
||||
@ -169,7 +197,13 @@ impl VisitMut for Metadata<'_> {
|
||||
if m.function.is_async {
|
||||
quote_ident!("Promise").as_arg()
|
||||
} else {
|
||||
serialize_type(self.class_name, m.function.return_type.as_deref()).as_arg()
|
||||
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()
|
||||
}
|
||||
},
|
||||
);
|
||||
m.function.decorators.push(dec);
|
||||
@ -177,49 +211,31 @@ impl VisitMut for Metadata<'_> {
|
||||
}
|
||||
|
||||
fn visit_mut_class_prop(&mut self, p: &mut ClassProp) {
|
||||
if p.decorators.is_empty() {
|
||||
if p.decorators.is_empty() || p.type_ann.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
if p.type_ann.is_none() {
|
||||
return;
|
||||
}
|
||||
if let Some(name) = p
|
||||
.type_ann
|
||||
.as_ref()
|
||||
.map(|ty| &ty.type_ann)
|
||||
.and_then(|type_ann| match &**type_ann {
|
||||
TsType::TsTypeRef(r) => Some(r),
|
||||
_ => None,
|
||||
})
|
||||
.and_then(|r| match &r.type_name {
|
||||
TsEntityName::TsQualifiedName(_) => None,
|
||||
TsEntityName::Ident(i) => Some(i),
|
||||
})
|
||||
{
|
||||
if let Some(kind) = self.enums.get(&name.sym) {
|
||||
let dec = self.create_metadata_design_decorator(
|
||||
"design:type",
|
||||
match kind {
|
||||
EnumKind::Mixed => quote_ident!("Object").as_arg(),
|
||||
EnumKind::Str => quote_ident!("String").as_arg(),
|
||||
EnumKind::Num => quote_ident!("Number").as_arg(),
|
||||
},
|
||||
);
|
||||
p.decorators.push(dec);
|
||||
return;
|
||||
let dec = self.create_metadata_design_decorator("design:type", {
|
||||
let prop_type = p.type_ann.as_deref();
|
||||
|
||||
if let Some(kind) = self.enums.get_kind_as_str(prop_type) {
|
||||
quote_ident!(kind).as_arg()
|
||||
} else {
|
||||
serialize_type(self.class_name, prop_type).as_arg()
|
||||
}
|
||||
}
|
||||
|
||||
let dec = self.create_metadata_design_decorator(
|
||||
"design:type",
|
||||
serialize_type(self.class_name, p.type_ann.as_deref()).as_arg(),
|
||||
);
|
||||
});
|
||||
p.decorators.push(dec);
|
||||
}
|
||||
}
|
||||
|
||||
impl Metadata<'_> {
|
||||
impl<'a> Metadata<'a> {
|
||||
pub(super) fn new(enums: &'a EnumMapType, class_name: Option<&'a Ident>) -> Self {
|
||||
Self {
|
||||
enums: EnumMap(enums),
|
||||
class_name,
|
||||
}
|
||||
}
|
||||
|
||||
fn create_metadata_design_decorator(&self, design: &str, type_arg: ExprOrSpread) -> Decorator {
|
||||
Decorator {
|
||||
span: DUMMY_SP,
|
||||
|
@ -224,10 +224,7 @@ impl VisitMut for TscDecorator {
|
||||
if self.metadata {
|
||||
let i = self.class_name.clone();
|
||||
|
||||
n.visit_mut_with(&mut Metadata {
|
||||
enums: &self.enums,
|
||||
class_name: i.as_ref(),
|
||||
});
|
||||
n.visit_mut_with(&mut Metadata::new(&self.enums, i.as_ref()));
|
||||
}
|
||||
|
||||
n.visit_mut_children_with(self);
|
||||
|
Loading…
Reference in New Issue
Block a user