swc_estree_compat/babelify/
decl.rs

1use copyless::BoxHelper;
2use swc_ecma_ast::{ClassDecl, Decl, FnDecl, UsingDecl, VarDecl, VarDeclKind, VarDeclarator};
3use swc_estree_ast::{
4    ClassBody, ClassDeclaration, Declaration, FunctionDeclaration, UsingDeclaration,
5    VariableDeclaration, VariableDeclarationKind, VariableDeclarator,
6};
7
8use crate::babelify::{extract_class_body_span, Babelify, Context};
9
10impl Babelify for Decl {
11    type Output = Declaration;
12
13    fn babelify(self, ctx: &Context) -> Self::Output {
14        match self {
15            Decl::Class(d) => Declaration::ClassDecl(d.babelify(ctx)),
16            Decl::Fn(d) => Declaration::FuncDecl(d.babelify(ctx)),
17            Decl::Var(d) => Declaration::VarDecl(d.babelify(ctx)),
18            Decl::Using(d) => Declaration::UsingDecl(d.babelify(ctx)),
19            Decl::TsInterface(d) => Declaration::TSInterfaceDecl(d.babelify(ctx)),
20            Decl::TsTypeAlias(d) => Declaration::TSTypeAliasDecl(d.babelify(ctx)),
21            Decl::TsEnum(d) => Declaration::TSEnumDecl(d.babelify(ctx)),
22            Decl::TsModule(d) => Declaration::TSModuleDecl(d.babelify(ctx)),
23            #[cfg(swc_ast_unknown)]
24            _ => panic!("unable to access unknown nodes"),
25        }
26    }
27}
28
29impl Babelify for FnDecl {
30    type Output = FunctionDeclaration;
31
32    fn babelify(self, ctx: &Context) -> Self::Output {
33        let func = self.function.babelify(ctx);
34        FunctionDeclaration {
35            base: func.base,
36            id: Some(self.ident.babelify(ctx)),
37            params: func.params,
38            body: func.body,
39            generator: func.generator,
40            is_async: func.is_async,
41            expression: false,
42            return_type: func.return_type,
43            type_parameters: func.type_parameters,
44        }
45    }
46}
47
48impl Babelify for ClassDecl {
49    type Output = ClassDeclaration;
50
51    fn babelify(self, ctx: &Context) -> Self::Output {
52        let is_abstract = self.class.is_abstract;
53        // NOTE: The body field needs a bit of special handling because babel
54        // represents the body as a node, whereas swc represents it as a vector of
55        // statements. This means that swc does not have a span corresponding the
56        // class body base node for babel. To solve this, we generate a new span
57        // starting from the end of the identifier to the end of the body.
58        // For example,
59        //
60        // babel ClassBody node starts here
61        //                  v
62        //     class MyClass {
63        //         a = 0;
64        //     }
65        //     ^
66        // and ends here
67        //
68        // TODO: Verify that this implementation of class body span is correct.
69        // It may need to be modified to take into account implements, super classes,
70        // etc.
71        let body_span = extract_class_body_span(&self.class, ctx);
72        let class = self.class.babelify(ctx);
73        ClassDeclaration {
74            base: class.base,
75            id: self.ident.babelify(ctx),
76            super_class: class.super_class.map(|s| Box::alloc().init(*s)),
77            body: ClassBody {
78                base: ctx.base(body_span),
79                ..class.body
80            },
81            decorators: class.decorators,
82            is_abstract: Some(is_abstract),
83            declare: Some(self.declare),
84            implements: class.implements,
85            mixins: class.mixins,
86            super_type_parameters: class.super_type_parameters,
87            type_parameters: class.type_parameters,
88        }
89    }
90}
91
92impl Babelify for VarDecl {
93    type Output = VariableDeclaration;
94
95    fn babelify(self, ctx: &Context) -> Self::Output {
96        VariableDeclaration {
97            base: ctx.base(self.span),
98            kind: self.kind.babelify(ctx),
99            declare: Some(self.declare),
100            declarations: self.decls.babelify(ctx),
101        }
102    }
103}
104
105impl Babelify for VarDeclKind {
106    type Output = VariableDeclarationKind;
107
108    fn babelify(self, _ctx: &Context) -> Self::Output {
109        match self {
110            VarDeclKind::Var => VariableDeclarationKind::Var,
111            VarDeclKind::Let => VariableDeclarationKind::Let,
112            VarDeclKind::Const => VariableDeclarationKind::Const,
113            #[cfg(swc_ast_unknown)]
114            _ => panic!("unable to access unknown nodes"),
115        }
116    }
117}
118
119impl Babelify for VarDeclarator {
120    type Output = VariableDeclarator;
121
122    fn babelify(self, ctx: &Context) -> Self::Output {
123        VariableDeclarator {
124            base: ctx.base(self.span),
125            id: self.name.babelify(ctx).into(),
126            init: self.init.map(|i| Box::alloc().init(i.babelify(ctx).into())),
127            definite: Some(self.definite),
128        }
129    }
130}
131
132impl Babelify for UsingDecl {
133    type Output = UsingDeclaration;
134
135    fn babelify(self, ctx: &Context) -> Self::Output {
136        UsingDeclaration {
137            base: ctx.base(self.span),
138            declarations: self.decls.babelify(ctx),
139        }
140    }
141}