swc_estree_compat/babelify/
decl.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use copyless::BoxHelper;
use swc_ecma_ast::{ClassDecl, Decl, FnDecl, UsingDecl, VarDecl, VarDeclKind, VarDeclarator};
use swc_estree_ast::{
    ClassBody, ClassDeclaration, Declaration, FunctionDeclaration, UsingDeclaration,
    VariableDeclaration, VariableDeclarationKind, VariableDeclarator,
};

use crate::babelify::{extract_class_body_span, Babelify, Context};

impl Babelify for Decl {
    type Output = Declaration;

    fn babelify(self, ctx: &Context) -> Self::Output {
        match self {
            Decl::Class(d) => Declaration::ClassDecl(d.babelify(ctx)),
            Decl::Fn(d) => Declaration::FuncDecl(d.babelify(ctx)),
            Decl::Var(d) => Declaration::VarDecl(d.babelify(ctx)),
            Decl::Using(d) => Declaration::UsingDecl(d.babelify(ctx)),
            Decl::TsInterface(d) => Declaration::TSInterfaceDecl(d.babelify(ctx)),
            Decl::TsTypeAlias(d) => Declaration::TSTypeAliasDecl(d.babelify(ctx)),
            Decl::TsEnum(d) => Declaration::TSEnumDecl(d.babelify(ctx)),
            Decl::TsModule(d) => Declaration::TSModuleDecl(d.babelify(ctx)),
        }
    }
}

impl Babelify for FnDecl {
    type Output = FunctionDeclaration;

    fn babelify(self, ctx: &Context) -> Self::Output {
        let func = self.function.babelify(ctx);
        FunctionDeclaration {
            base: func.base,
            id: Some(self.ident.babelify(ctx)),
            params: func.params,
            body: func.body,
            generator: func.generator,
            is_async: func.is_async,
            expression: false,
            return_type: func.return_type,
            type_parameters: func.type_parameters,
        }
    }
}

impl Babelify for ClassDecl {
    type Output = ClassDeclaration;

    fn babelify(self, ctx: &Context) -> Self::Output {
        let is_abstract = self.class.is_abstract;
        // NOTE: The body field needs a bit of special handling because babel
        // represents the body as a node, whereas swc represents it as a vector of
        // statements. This means that swc does not have a span corresponding the
        // class body base node for babel. To solve this, we generate a new span
        // starting from the end of the identifier to the end of the body.
        // For example,
        //
        // babel ClassBody node starts here
        //                  v
        //     class MyClass {
        //         a = 0;
        //     }
        //     ^
        // and ends here
        //
        // TODO: Verify that this implementation of class body span is correct.
        // It may need to be modified to take into account implements, super classes,
        // etc.
        let body_span = extract_class_body_span(&self.class, ctx);
        let class = self.class.babelify(ctx);
        ClassDeclaration {
            base: class.base,
            id: self.ident.babelify(ctx),
            super_class: class.super_class.map(|s| Box::alloc().init(*s)),
            body: ClassBody {
                base: ctx.base(body_span),
                ..class.body
            },
            decorators: class.decorators,
            is_abstract: Some(is_abstract),
            declare: Some(self.declare),
            implements: class.implements,
            mixins: class.mixins,
            super_type_parameters: class.super_type_parameters,
            type_parameters: class.type_parameters,
        }
    }
}

impl Babelify for VarDecl {
    type Output = VariableDeclaration;

    fn babelify(self, ctx: &Context) -> Self::Output {
        VariableDeclaration {
            base: ctx.base(self.span),
            kind: self.kind.babelify(ctx),
            declare: Some(self.declare),
            declarations: self.decls.babelify(ctx),
        }
    }
}

impl Babelify for VarDeclKind {
    type Output = VariableDeclarationKind;

    fn babelify(self, _ctx: &Context) -> Self::Output {
        match self {
            VarDeclKind::Var => VariableDeclarationKind::Var,
            VarDeclKind::Let => VariableDeclarationKind::Let,
            VarDeclKind::Const => VariableDeclarationKind::Const,
        }
    }
}

impl Babelify for VarDeclarator {
    type Output = VariableDeclarator;

    fn babelify(self, ctx: &Context) -> Self::Output {
        VariableDeclarator {
            base: ctx.base(self.span),
            id: self.name.babelify(ctx).into(),
            init: self.init.map(|i| Box::alloc().init(i.babelify(ctx).into())),
            definite: Some(self.definite),
        }
    }
}

impl Babelify for UsingDecl {
    type Output = UsingDeclaration;

    fn babelify(self, ctx: &Context) -> Self::Output {
        UsingDeclaration {
            base: ctx.base(self.span),
            declarations: self.decls.babelify(ctx),
        }
    }
}