Skip to main content

swc_ecma_ast/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![deny(unreachable_patterns)]
3#![deny(missing_copy_implementations)]
4#![deny(trivial_casts)]
5#![deny(trivial_numeric_casts)]
6#![deny(unreachable_pub)]
7#![deny(clippy::all)]
8#![allow(clippy::enum_variant_names)]
9#![allow(clippy::clone_on_copy)]
10#![recursion_limit = "1024"]
11
12pub use num_bigint::BigInt as BigIntValue;
13#[cfg(feature = "serde")]
14use serde::{Deserialize, Serialize};
15use swc_common::{ast_node, pass::Either, util::take::Take, EqIgnoreSpan, Span};
16
17pub use self::{
18    class::{
19        AutoAccessor, Class, ClassMember, ClassMethod, ClassProp, Constructor, Decorator, Key,
20        MethodKind, PrivateMethod, PrivateProp, StaticBlock,
21    },
22    decl::{ClassDecl, Decl, FnDecl, UsingDecl, VarDecl, VarDeclKind, VarDeclarator},
23    expr::*,
24    function::{Function, FunctionBody, Param, ParamOrTsParamProp},
25    ident::{
26        unsafe_id, unsafe_id_from_ident, BindingIdent, EsReserved, Id, Ident, IdentName,
27        PrivateName, UnsafeId,
28    },
29    jsx::{
30        JSXAttr, JSXAttrName, JSXAttrOrSpread, JSXAttrValue, JSXClosingElement, JSXClosingFragment,
31        JSXElement, JSXElementChild, JSXElementName, JSXEmptyExpr, JSXExpr, JSXExprContainer,
32        JSXFragment, JSXMemberExpr, JSXNamespacedName, JSXObject, JSXOpeningElement,
33        JSXOpeningFragment, JSXSpreadChild, JSXText,
34    },
35    list::ListFormat,
36    lit::{BigInt, Bool, Lit, Null, Number, Regex, Str},
37    module::{Module, ModuleItem, Program, Script},
38    module_decl::{
39        DefaultDecl, ExportAll, ExportDecl, ExportDefaultDecl, ExportDefaultExpr,
40        ExportDefaultSpecifier, ExportNamedSpecifier, ExportNamespaceSpecifier, ExportSpecifier,
41        ImportDecl, ImportDefaultSpecifier, ImportNamedSpecifier, ImportPhase, ImportSpecifier,
42        ImportStarAsSpecifier, ModuleDecl, ModuleExportName, NamedExport,
43    },
44    operators::{AssignOp, BinaryOp, UnaryOp, UpdateOp},
45    pat::{
46        ArrayPat, AssignPat, AssignPatProp, KeyValuePatProp, ObjectPat, ObjectPatProp, Pat, RestPat,
47    },
48    prop::{
49        AssignProp, ComputedPropName, GetterProp, KeyValueProp, MethodProp, Prop, PropName,
50        SetterProp,
51    },
52    source_map::{SourceMapperExt, SpanExt},
53    stmt::{
54        BlockStmt, BreakStmt, CatchClause, ContinueStmt, DebuggerStmt, DoWhileStmt, EmptyStmt,
55        ExprStmt, ForHead, ForInStmt, ForOfStmt, ForStmt, IfStmt, LabeledStmt, ReturnStmt, Stmt,
56        SwitchCase, SwitchStmt, ThrowStmt, TryStmt, VarDeclOrExpr, WhileStmt, WithStmt,
57    },
58    typescript::{
59        Accessibility, TruePlusMinus, TsArrayType, TsAsExpr, TsCallSignatureDecl,
60        TsConditionalType, TsConstAssertion, TsConstructSignatureDecl, TsConstructorType,
61        TsEntityName, TsEnumDecl, TsEnumMember, TsEnumMemberId, TsExportAssignment,
62        TsExprWithTypeArgs, TsExternalModuleRef, TsFnOrConstructorType, TsFnParam, TsFnType,
63        TsGetterSignature, TsImportCallOptions, TsImportEqualsDecl, TsImportType, TsIndexSignature,
64        TsIndexedAccessType, TsInferType, TsInstantiation, TsInterfaceBody, TsInterfaceDecl,
65        TsIntersectionType, TsKeywordType, TsKeywordTypeKind, TsLit, TsLitType, TsMappedType,
66        TsMethodSignature, TsModuleBlock, TsModuleDecl, TsModuleName, TsModuleRef, TsNamespaceBody,
67        TsNamespaceDecl, TsNamespaceExportDecl, TsNonNullExpr, TsOptionalType, TsParamProp,
68        TsParamPropParam, TsParenthesizedType, TsPropertySignature, TsQualifiedName, TsRestType,
69        TsSatisfiesExpr, TsSetterSignature, TsThisParam, TsThisType, TsThisTypeOrIdent,
70        TsTplLitType, TsTupleElement, TsTupleType, TsType, TsTypeAliasDecl, TsTypeAnn,
71        TsTypeAssertion, TsTypeElement, TsTypeLit, TsTypeOperator, TsTypeOperatorOp, TsTypeParam,
72        TsTypeParamDecl, TsTypeParamInstantiation, TsTypePredicate, TsTypeQuery, TsTypeQueryExpr,
73        TsTypeRef, TsUnionOrIntersectionType, TsUnionType,
74    },
75};
76
77#[macro_use]
78mod macros;
79mod class;
80mod decl;
81mod expr;
82mod function;
83mod ident;
84mod jsx;
85mod list;
86mod lit;
87mod module;
88mod module_decl;
89mod operators;
90mod pat;
91mod prop;
92mod source_map;
93mod stmt;
94mod typescript;
95
96/// A map from the [Program] to the [Program].
97///
98/// This trait is used to implement transformations. The implementor may decide
99/// to implement [Fold] or [VisitMut] if the transform is fine to start from an
100/// arbitrary node.
101///
102/// Tuple of [Pass] implementations also implements [Pass], but it's limited to
103/// 12 items for fast compile time. If you have more passes, nest it like `(a,
104/// (b, c), (d, e))`
105pub trait Pass {
106    fn process(&mut self, program: &mut Program);
107}
108
109/// Optional pass implementation.
110impl<P> Pass for Option<P>
111where
112    P: Pass,
113{
114    #[inline(always)]
115    fn process(&mut self, program: &mut Program) {
116        if let Some(pass) = self {
117            pass.process(program);
118        }
119    }
120}
121
122impl<P: ?Sized> Pass for Box<P>
123where
124    P: Pass,
125{
126    #[inline(always)]
127    fn process(&mut self, program: &mut Program) {
128        (**self).process(program);
129    }
130}
131
132impl<P: ?Sized> Pass for &'_ mut P
133where
134    P: Pass,
135{
136    #[inline(always)]
137    fn process(&mut self, program: &mut Program) {
138        (**self).process(program);
139    }
140}
141
142impl<L, R> Pass for Either<L, R>
143where
144    L: Pass,
145    R: Pass,
146{
147    #[inline]
148    fn process(&mut self, program: &mut Program) {
149        match self {
150            Either::Left(l) => l.process(program),
151            Either::Right(r) => r.process(program),
152        }
153    }
154}
155
156impl<P> Pass for swc_visit::Optional<P>
157where
158    P: Pass,
159{
160    #[inline]
161    fn process(&mut self, program: &mut Program) {
162        if self.enabled {
163            self.visitor.process(program);
164        }
165    }
166}
167
168impl<P> Pass for swc_visit::Repeat<P>
169where
170    P: Pass + swc_visit::Repeated,
171{
172    #[inline]
173    fn process(&mut self, program: &mut Program) {
174        loop {
175            self.pass.reset();
176            self.pass.process(program);
177
178            if !self.pass.changed() {
179                break;
180            }
181        }
182    }
183}
184
185impl Program {
186    #[inline(always)]
187    pub fn mutate<P>(&mut self, mut pass: P)
188    where
189        P: Pass,
190    {
191        pass.process(self);
192    }
193
194    #[inline(always)]
195    pub fn apply<P>(mut self, mut pass: P) -> Self
196    where
197        P: Pass,
198    {
199        pass.process(&mut self);
200        self
201    }
202}
203
204macro_rules! impl_pass_for_tuple {
205    (
206        [$idx:tt, $name:ident], $([$idx_rest:tt, $name_rest:ident]),*
207    ) => {
208        impl<$name, $($name_rest),*> Pass for ($name, $($name_rest),*)
209        where
210            $name: Pass,
211            $($name_rest: Pass),*
212        {
213            #[inline]
214            fn process(&mut self, program: &mut Program) {
215                self.$idx.process(program);
216
217                $(
218                    self.$idx_rest.process(program);
219                )*
220
221            }
222        }
223    };
224}
225
226impl_pass_for_tuple!([0, A], [1, B]);
227impl_pass_for_tuple!([0, A], [1, B], [2, C]);
228impl_pass_for_tuple!([0, A], [1, B], [2, C], [3, D]);
229impl_pass_for_tuple!([0, A], [1, B], [2, C], [3, D], [4, E]);
230impl_pass_for_tuple!([0, A], [1, B], [2, C], [3, D], [4, E], [5, F]);
231impl_pass_for_tuple!([0, A], [1, B], [2, C], [3, D], [4, E], [5, F], [6, G]);
232impl_pass_for_tuple!(
233    [0, A],
234    [1, B],
235    [2, C],
236    [3, D],
237    [4, E],
238    [5, F],
239    [6, G],
240    [7, H]
241);
242impl_pass_for_tuple!(
243    [0, A],
244    [1, B],
245    [2, C],
246    [3, D],
247    [4, E],
248    [5, F],
249    [6, G],
250    [7, H],
251    [8, I]
252);
253impl_pass_for_tuple!(
254    [0, A],
255    [1, B],
256    [2, C],
257    [3, D],
258    [4, E],
259    [5, F],
260    [6, G],
261    [7, H],
262    [8, I],
263    [9, J]
264);
265impl_pass_for_tuple!(
266    [0, A],
267    [1, B],
268    [2, C],
269    [3, D],
270    [4, E],
271    [5, F],
272    [6, G],
273    [7, H],
274    [8, I],
275    [9, J],
276    [10, K]
277);
278impl_pass_for_tuple!(
279    [0, A],
280    [1, B],
281    [2, C],
282    [3, D],
283    [4, E],
284    [5, F],
285    [6, G],
286    [7, H],
287    [8, I],
288    [9, J],
289    [10, K],
290    [11, L]
291);
292impl_pass_for_tuple!(
293    [0, A],
294    [1, B],
295    [2, C],
296    [3, D],
297    [4, E],
298    [5, F],
299    [6, G],
300    [7, H],
301    [8, I],
302    [9, J],
303    [10, K],
304    [11, L],
305    [12, M]
306);
307
308#[inline(always)]
309pub fn noop_pass() -> impl Pass {
310    fn noop(_: &mut Program) {}
311
312    fn_pass(noop)
313}
314
315#[inline(always)]
316pub fn fn_pass(f: impl FnMut(&mut Program)) -> impl Pass {
317    FnPass { f }
318}
319
320struct FnPass<F> {
321    f: F,
322}
323
324impl<F> Pass for FnPass<F>
325where
326    F: FnMut(&mut Program),
327{
328    fn process(&mut self, program: &mut Program) {
329        (self.f)(program);
330    }
331}
332
333/// Represents a invalid node.
334#[ast_node("Invalid")]
335#[derive(Eq, Default, Hash, Copy, EqIgnoreSpan)]
336#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
337#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
338pub struct Invalid {
339    pub span: Span,
340}
341
342impl Take for Invalid {
343    fn dummy() -> Self {
344        Invalid::default()
345    }
346}
347
348/// Note: This type implements `Serailize` and `Deserialize` if `serde` is
349/// enabled, instead of requiring `serde-impl` feature.
350#[derive(Debug, Default, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
351#[cfg_attr(feature = "serde", derive(Serialize))]
352#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
353pub enum EsVersion {
354    Es3,
355    #[default]
356    Es5,
357    Es2015,
358    Es2016,
359    Es2017,
360    Es2018,
361    Es2019,
362    Es2020,
363    Es2021,
364    Es2022,
365    Es2023,
366    Es2024,
367    EsNext,
368}
369
370#[cfg(feature = "serde")]
371impl<'de> Deserialize<'de> for EsVersion {
372    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
373    where
374        D: serde::Deserializer<'de>,
375    {
376        use serde::de::Error;
377
378        let s = String::deserialize(deserializer)?;
379        match s.to_lowercase().as_str() {
380            "es3" => Ok(EsVersion::Es3),
381            "es5" => Ok(EsVersion::Es5),
382            "es2015" | "es6" => Ok(EsVersion::Es2015),
383            "es2016" => Ok(EsVersion::Es2016),
384            "es2017" => Ok(EsVersion::Es2017),
385            "es2018" => Ok(EsVersion::Es2018),
386            "es2019" => Ok(EsVersion::Es2019),
387            "es2020" => Ok(EsVersion::Es2020),
388            "es2021" => Ok(EsVersion::Es2021),
389            "es2022" => Ok(EsVersion::Es2022),
390            "es2023" => Ok(EsVersion::Es2023),
391            "es2024" => Ok(EsVersion::Es2024),
392            "esnext" => Ok(EsVersion::EsNext),
393            _ => Err(D::Error::custom(format!("Unknown ES version: {s}"))),
394        }
395    }
396}
397
398impl EsVersion {
399    pub const fn latest() -> Self {
400        EsVersion::EsNext
401    }
402}