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