1use is_macro::Is;
2use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, SyntaxContext, DUMMY_SP};
3
4use crate::{
5 decl::{Decl, VarDecl},
6 expr::Expr,
7 pat::Pat,
8 Ident, Lit, Str, UsingDecl,
9};
10
11#[ast_node("BlockStatement")]
13#[derive(Eq, Hash, EqIgnoreSpan, Default)]
14#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
15#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
16pub struct BlockStmt {
17 pub span: Span,
19
20 pub ctxt: SyntaxContext,
21
22 pub stmts: Vec<Stmt>,
23}
24
25impl Take for BlockStmt {
26 fn dummy() -> Self {
27 BlockStmt {
28 span: DUMMY_SP,
29 stmts: Vec::new(),
30 ctxt: Default::default(),
31 }
32 }
33}
34
35#[ast_node(no_clone)]
36#[derive(Eq, Hash, Is, EqIgnoreSpan)]
37#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
38#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
39pub enum Stmt {
40 #[tag("BlockStatement")]
41 Block(BlockStmt),
42
43 #[tag("EmptyStatement")]
44 Empty(EmptyStmt),
45
46 #[tag("DebuggerStatement")]
47 Debugger(DebuggerStmt),
48
49 #[tag("WithStatement")]
50 With(WithStmt),
51
52 #[tag("ReturnStatement")]
53 #[is(name = "return_stmt")]
54 Return(ReturnStmt),
55
56 #[tag("LabeledStatement")]
57 Labeled(LabeledStmt),
58
59 #[tag("BreakStatement")]
60 #[is(name = "break_stmt")]
61 Break(BreakStmt),
62
63 #[tag("ContinueStatement")]
64 #[is(name = "continue_stmt")]
65 Continue(ContinueStmt),
66
67 #[tag("IfStatement")]
68 #[is(name = "if_stmt")]
69 If(IfStmt),
70
71 #[tag("SwitchStatement")]
72 Switch(SwitchStmt),
73
74 #[tag("ThrowStatement")]
75 Throw(ThrowStmt),
76
77 #[tag("TryStatement")]
79 #[is(name = "try_stmt")]
80 Try(Box<TryStmt>),
81
82 #[tag("WhileStatement")]
83 #[is(name = "while_stmt")]
84 While(WhileStmt),
85
86 #[tag("DoWhileStatement")]
87 DoWhile(DoWhileStmt),
88
89 #[tag("ForStatement")]
90 #[is(name = "for_stmt")]
91 For(ForStmt),
92
93 #[tag("ForInStatement")]
94 ForIn(ForInStmt),
95
96 #[tag("ForOfStatement")]
97 ForOf(ForOfStmt),
98
99 #[tag("ClassDeclaration")]
100 #[tag("FunctionDeclaration")]
101 #[tag("VariableDeclaration")]
102 #[tag("TsInterfaceDeclaration")]
103 #[tag("TsTypeAliasDeclaration")]
104 #[tag("TsEnumDeclaration")]
105 #[tag("TsModuleDeclaration")]
106 #[tag("UsingDeclaration")]
107 Decl(Decl),
108
109 #[tag("ExpressionStatement")]
110 Expr(ExprStmt),
111}
112
113boxed!(Stmt, [TryStmt]);
114
115macro_rules! stmt_from {
116 ($($varant_ty:ty),*) => {
117 $(
118 bridge_from!(Box<crate::Stmt>, crate::Stmt, $varant_ty);
119 bridge_from!(crate::ModuleItem, crate::Stmt, $varant_ty);
120 )*
121 };
122}
123
124stmt_from!(
125 ExprStmt,
126 BlockStmt,
127 EmptyStmt,
128 DebuggerStmt,
129 WithStmt,
130 ReturnStmt,
131 LabeledStmt,
132 BreakStmt,
133 ContinueStmt,
134 IfStmt,
135 SwitchStmt,
136 ThrowStmt,
137 TryStmt,
138 WhileStmt,
139 DoWhileStmt,
140 ForStmt,
141 ForInStmt,
142 ForOfStmt,
143 Decl
144);
145
146impl Stmt {
147 pub fn is_use_strict(&self) -> bool {
148 match self {
149 Stmt::Expr(expr) => match *expr.expr {
150 Expr::Lit(Lit::Str(Str { ref raw, .. })) => {
151 matches!(raw, Some(value) if value == "\"use strict\"" || value == "'use strict'")
152 }
153 _ => false,
154 },
155 _ => false,
156 }
157 }
158
159 pub fn can_precede_directive(&self) -> bool {
162 match self {
163 Stmt::Expr(expr) => matches!(*expr.expr, Expr::Lit(Lit::Str(_))),
164 _ => false,
165 }
166 }
167}
168
169impl Clone for Stmt {
176 fn clone(&self) -> Self {
177 use Stmt::*;
178 match self {
179 #[cfg(all(swc_ast_unknown, feature = "encoding-impl"))]
180 Unknown(tag, v) => Unknown(*tag, v.clone()),
181 Block(s) => Block(s.clone()),
182 Empty(s) => Empty(s.clone()),
183 Debugger(s) => Debugger(s.clone()),
184 With(s) => With(s.clone()),
185 Return(s) => Return(s.clone()),
186 Labeled(s) => Labeled(s.clone()),
187 Break(s) => Break(s.clone()),
188 Continue(s) => Continue(s.clone()),
189 If(s) => If(s.clone()),
190 Switch(s) => Switch(s.clone()),
191 Throw(s) => Throw(s.clone()),
192 Try(s) => Try(s.clone()),
193 While(s) => While(s.clone()),
194 DoWhile(s) => DoWhile(s.clone()),
195 For(s) => For(s.clone()),
196 ForIn(s) => ForIn(s.clone()),
197 ForOf(s) => ForOf(s.clone()),
198 Decl(s) => Decl(s.clone()),
199 Expr(s) => Expr(s.clone()),
200 }
201 }
202}
203
204impl Default for Stmt {
205 fn default() -> Self {
206 Self::Empty(EmptyStmt { span: DUMMY_SP })
207 }
208}
209
210impl Take for Stmt {
211 fn dummy() -> Self {
212 Default::default()
213 }
214}
215
216#[ast_node("ExpressionStatement")]
217#[derive(Eq, Hash, EqIgnoreSpan, Default)]
218#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
219#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
220pub struct ExprStmt {
221 pub span: Span,
222 #[cfg_attr(feature = "serde-impl", serde(rename = "expression"))]
223 pub expr: Box<Expr>,
224}
225
226#[ast_node("EmptyStatement")]
227#[derive(Eq, Hash, Copy, EqIgnoreSpan)]
228#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
229#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
230pub struct EmptyStmt {
231 pub span: Span,
233}
234
235#[ast_node("DebuggerStatement")]
236#[derive(Eq, Hash, Copy, EqIgnoreSpan)]
237#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
238#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
239pub struct DebuggerStmt {
240 pub span: Span,
241}
242
243#[ast_node("WithStatement")]
244#[derive(Eq, Hash, EqIgnoreSpan, Default)]
245#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
246#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
247pub struct WithStmt {
248 pub span: Span,
249 #[cfg_attr(feature = "serde-impl", serde(rename = "object"))]
250 pub obj: Box<Expr>,
251 pub body: Box<Stmt>,
252}
253
254#[ast_node("ReturnStatement")]
255#[derive(Eq, Hash, EqIgnoreSpan, Default)]
256#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
257#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
258pub struct ReturnStmt {
259 pub span: Span,
260 #[cfg_attr(feature = "serde-impl", serde(default, rename = "argument"))]
261 #[cfg_attr(
262 feature = "encoding-impl",
263 encoding(with = "cbor4ii::core::types::Maybe")
264 )]
265 pub arg: Option<Box<Expr>>,
266}
267
268#[ast_node("LabeledStatement")]
269#[derive(Eq, Hash, EqIgnoreSpan, Default)]
270#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
271#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
272pub struct LabeledStmt {
273 pub span: Span,
274 pub label: Ident,
275 pub body: Box<Stmt>,
276}
277
278#[ast_node("BreakStatement")]
279#[derive(Eq, Hash, EqIgnoreSpan, Default)]
280#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
281#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
282pub struct BreakStmt {
283 pub span: Span,
284 #[cfg_attr(feature = "serde-impl", serde(default))]
285 #[cfg_attr(
286 feature = "encoding-impl",
287 encoding(with = "cbor4ii::core::types::Maybe")
288 )]
289 pub label: Option<Ident>,
290}
291
292#[ast_node("ContinueStatement")]
293#[derive(Eq, Hash, EqIgnoreSpan, Default)]
294#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
295#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
296pub struct ContinueStmt {
297 pub span: Span,
298 #[cfg_attr(feature = "serde-impl", serde(default))]
299 #[cfg_attr(
300 feature = "encoding-impl",
301 encoding(with = "cbor4ii::core::types::Maybe")
302 )]
303 pub label: Option<Ident>,
304}
305
306#[ast_node("IfStatement")]
307#[derive(Eq, Hash, EqIgnoreSpan, Default)]
308#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
309#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
310pub struct IfStmt {
311 pub span: Span,
312 pub test: Box<Expr>,
313
314 #[cfg_attr(feature = "serde-impl", serde(rename = "consequent"))]
315 pub cons: Box<Stmt>,
316
317 #[cfg_attr(feature = "serde-impl", serde(default, rename = "alternate"))]
318 #[cfg_attr(
319 feature = "encoding-impl",
320 encoding(with = "cbor4ii::core::types::Maybe")
321 )]
322 pub alt: Option<Box<Stmt>>,
323}
324
325#[ast_node("SwitchStatement")]
326#[derive(Eq, Hash, EqIgnoreSpan, Default)]
327#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
328#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
329pub struct SwitchStmt {
330 pub span: Span,
331 pub body_ctxt: SyntaxContext,
332 pub discriminant: Box<Expr>,
333 pub cases: Vec<SwitchCase>,
334}
335
336#[ast_node("ThrowStatement")]
337#[derive(Eq, Hash, EqIgnoreSpan, Default)]
338#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
339#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
340pub struct ThrowStmt {
341 pub span: Span,
342 #[cfg_attr(feature = "serde-impl", serde(rename = "argument"))]
343 pub arg: Box<Expr>,
344}
345
346#[ast_node("TryStatement")]
347#[derive(Eq, Hash, EqIgnoreSpan, Default)]
348#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
349#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
350pub struct TryStmt {
351 pub span: Span,
352
353 pub block: BlockStmt,
354
355 #[cfg_attr(feature = "serde-impl", serde(default))]
356 #[cfg_attr(
357 feature = "encoding-impl",
358 encoding(with = "cbor4ii::core::types::Maybe")
359 )]
360 pub handler: Option<CatchClause>,
361
362 #[cfg_attr(feature = "serde-impl", serde(default))]
363 #[cfg_attr(
364 feature = "encoding-impl",
365 encoding(with = "cbor4ii::core::types::Maybe")
366 )]
367 pub finalizer: Option<BlockStmt>,
368}
369
370#[ast_node("WhileStatement")]
371#[derive(Eq, Hash, EqIgnoreSpan, Default)]
372#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
373#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
374pub struct WhileStmt {
375 pub span: Span,
376 pub test: Box<Expr>,
377 pub body: Box<Stmt>,
378}
379
380#[ast_node("DoWhileStatement")]
381#[derive(Eq, Hash, EqIgnoreSpan, Default)]
382#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
383#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
384pub struct DoWhileStmt {
385 pub span: Span,
386 pub test: Box<Expr>,
387 pub body: Box<Stmt>,
388}
389
390#[ast_node("ForStatement")]
391#[derive(Eq, Hash, EqIgnoreSpan, Default)]
392#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
393#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
394pub struct ForStmt {
395 pub span: Span,
396
397 #[cfg_attr(feature = "serde-impl", serde(default))]
398 #[cfg_attr(
399 feature = "encoding-impl",
400 encoding(with = "cbor4ii::core::types::Maybe")
401 )]
402 pub init: Option<VarDeclOrExpr>,
403
404 #[cfg_attr(feature = "serde-impl", serde(default))]
405 #[cfg_attr(
406 feature = "encoding-impl",
407 encoding(with = "cbor4ii::core::types::Maybe")
408 )]
409 pub test: Option<Box<Expr>>,
410
411 #[cfg_attr(feature = "serde-impl", serde(default))]
412 #[cfg_attr(
413 feature = "encoding-impl",
414 encoding(with = "cbor4ii::core::types::Maybe")
415 )]
416 pub update: Option<Box<Expr>>,
417
418 pub body: Box<Stmt>,
419}
420
421#[ast_node("ForInStatement")]
422#[derive(Eq, Hash, EqIgnoreSpan, Default)]
423#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
424#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
425pub struct ForInStmt {
426 pub span: Span,
427 pub left: ForHead,
428 pub right: Box<Expr>,
429 pub body: Box<Stmt>,
430}
431
432#[ast_node("ForOfStatement")]
433#[derive(Eq, Hash, EqIgnoreSpan, Default)]
434#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
435#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
436pub struct ForOfStmt {
437 pub span: Span,
438 #[cfg_attr(feature = "serde-impl", serde(default, rename = "await"))]
444 pub is_await: bool,
445 pub left: ForHead,
446 pub right: Box<Expr>,
447 pub body: Box<Stmt>,
448}
449
450impl Take for ForOfStmt {
451 fn dummy() -> Self {
452 Default::default()
453 }
454}
455
456#[ast_node("SwitchCase")]
457#[derive(Eq, Hash, EqIgnoreSpan, Default)]
458#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
459#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
460pub struct SwitchCase {
461 pub span: Span,
462
463 #[cfg_attr(feature = "serde-impl", serde(default))]
465 #[cfg_attr(
466 feature = "encoding-impl",
467 encoding(with = "cbor4ii::core::types::Maybe")
468 )]
469 pub test: Option<Box<Expr>>,
470
471 #[cfg_attr(feature = "serde-impl", serde(rename = "consequent"))]
472 pub cons: Vec<Stmt>,
473}
474
475impl Take for SwitchCase {
476 fn dummy() -> Self {
477 Self {
478 span: DUMMY_SP,
479 test: None,
480 cons: Vec::new(),
481 }
482 }
483}
484
485#[ast_node("CatchClause")]
486#[derive(Eq, Hash, EqIgnoreSpan, Default)]
487#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
488#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
489pub struct CatchClause {
490 pub span: Span,
491 #[cfg_attr(feature = "serde-impl", serde(default))]
496 #[cfg_attr(
497 feature = "encoding-impl",
498 encoding(with = "cbor4ii::core::types::Maybe")
499 )]
500 pub param: Option<Pat>,
501
502 pub body: BlockStmt,
503}
504
505#[ast_node]
507#[derive(Eq, Hash, Is, EqIgnoreSpan)]
508#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
509#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
510pub enum ForHead {
511 #[tag("VariableDeclaration")]
512 VarDecl(Box<VarDecl>),
513
514 #[tag("UsingDeclaration")]
515 UsingDecl(Box<UsingDecl>),
516
517 #[tag("*")]
518 Pat(Box<Pat>),
519}
520
521bridge_from!(ForHead, Box<VarDecl>, VarDecl);
522bridge_from!(ForHead, Box<Pat>, Pat);
523
524impl Take for ForHead {
525 fn dummy() -> Self {
526 Default::default()
527 }
528}
529
530impl Default for ForHead {
531 fn default() -> Self {
532 ForHead::Pat(Take::dummy())
533 }
534}
535
536#[ast_node]
537#[derive(Eq, Hash, Is, EqIgnoreSpan)]
538#[allow(variant_size_differences)]
539#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
540#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
541pub enum VarDeclOrExpr {
542 #[tag("VariableDeclaration")]
543 VarDecl(Box<VarDecl>),
544
545 #[tag("*")]
546 Expr(Box<Expr>),
547}
548
549bridge_from!(VarDeclOrExpr, Box<VarDecl>, VarDecl);
550bridge_from!(VarDeclOrExpr, Box<Expr>, Expr);
551
552impl Take for VarDeclOrExpr {
553 fn dummy() -> Self {
554 VarDeclOrExpr::Expr(Take::dummy())
555 }
556}