macroforge_ts_syn/
lib.rs

1pub mod abi;
2pub mod derive;
3pub mod errors;
4pub mod lower;
5pub mod parse;
6pub mod quote_helpers;
7pub mod stream;
8
9pub use abi::*;
10pub use derive::*;
11pub use errors::*;
12pub use lower::*;
13pub use stream::*;
14#[cfg(feature = "swc")]
15pub use swc_core::quote;
16
17// Re-export swc_core for convenience
18#[cfg(feature = "swc")]
19pub use swc_core;
20
21// Re-export common swc modules at top level for ergonomics
22#[cfg(feature = "swc")]
23pub use swc_core::common as swc_common;
24#[cfg(feature = "swc")]
25pub use swc_core::ecma::ast as swc_ecma_ast;
26
27// Helper macros for creating AST nodes
28#[cfg(feature = "swc")]
29#[macro_export]
30macro_rules! ident {
31    // Single argument - direct string
32    ($name:expr) => {
33        swc_core::ecma::ast::Ident::new_no_ctxt($name.into(), swc_core::common::DUMMY_SP)
34    };
35    // Format string with arguments
36    ($fmt:expr, $($args:expr),+ $(,)?) => {
37        swc_core::ecma::ast::Ident::new_no_ctxt(format!($fmt, $($args),+).into(), swc_core::common::DUMMY_SP)
38    };
39}
40
41#[cfg(feature = "swc")]
42#[macro_export]
43macro_rules! private_ident {
44    ($name:expr) => {{
45        let mark = swc_core::common::Mark::fresh(swc_core::common::Mark::root());
46        swc_core::ecma::ast::Ident::new(
47            $name.into(),
48            swc_core::common::DUMMY_SP,
49            swc_core::common::SyntaxContext::empty().apply_mark(mark),
50        )
51    }};
52}
53
54/// Create a block statement from a Vec<Stmt>
55#[cfg(feature = "swc")]
56#[macro_export]
57macro_rules! stmt_block {
58    ($stmts:expr) => {
59        swc_core::ecma::ast::Stmt::Block(swc_core::ecma::ast::BlockStmt {
60            span: swc_core::common::DUMMY_SP,
61            ctxt: swc_core::common::SyntaxContext::empty(),
62            stmts: $stmts,
63        })
64    };
65}
66
67/// Helper to pass Vec<Stmt> to be used inline in function bodies
68/// This is a marker type that ts_quote! can detect and handle specially
69#[cfg(feature = "swc")]
70pub struct StmtVec(pub Vec<swc_core::ecma::ast::Stmt>);
71
72#[cfg(feature = "swc")]
73#[macro_export]
74macro_rules! stmt_vec {
75    ($stmts:expr) => {
76        macroforge_ts_syn::StmtVec($stmts)
77    };
78}
79
80/// Convert a Vec<Stmt> into a single block statement that can be used in ts_quote!
81/// This allows you to interpolate multiple statements where a single statement is expected.
82#[cfg(feature = "swc")]
83#[macro_export]
84macro_rules! stmt_block_from_vec {
85    ($stmts:expr) => {
86        swc_core::ecma::ast::Stmt::Block(swc_core::ecma::ast::BlockStmt {
87            span: swc_core::common::DUMMY_SP,
88            ctxt: swc_core::common::SyntaxContext::empty(),
89            stmts: $stmts,
90        })
91    };
92}
93
94/// Create a function expression with the given body statements
95#[cfg(feature = "swc")]
96#[macro_export]
97macro_rules! fn_expr {
98    ($body_stmts:expr) => {
99        swc_core::ecma::ast::Expr::Fn(swc_core::ecma::ast::FnExpr {
100            ident: None,
101            function: Box::new(swc_core::ecma::ast::Function {
102                params: vec![],
103                decorators: vec![],
104                span: swc_core::common::DUMMY_SP,
105                ctxt: swc_core::common::SyntaxContext::empty(),
106                body: Some(swc_core::ecma::ast::BlockStmt {
107                    span: swc_core::common::DUMMY_SP,
108                    ctxt: swc_core::common::SyntaxContext::empty(),
109                    stmts: $body_stmts,
110                }),
111                is_generator: false,
112                is_async: false,
113                type_params: None,
114                return_type: None,
115            }),
116        })
117    };
118    ($params:expr, $body_stmts:expr) => {
119        swc_core::ecma::ast::Expr::Fn(swc_core::ecma::ast::FnExpr {
120            ident: None,
121            function: Box::new(swc_core::ecma::ast::Function {
122                params: $params,
123                decorators: vec![],
124                span: swc_core::common::DUMMY_SP,
125                ctxt: swc_core::common::SyntaxContext::empty(),
126                body: Some(swc_core::ecma::ast::BlockStmt {
127                    span: swc_core::common::DUMMY_SP,
128                    ctxt: swc_core::common::SyntaxContext::empty(),
129                    stmts: $body_stmts,
130                }),
131                is_generator: false,
132                is_async: false,
133                type_params: None,
134                return_type: None,
135            }),
136        })
137    };
138}
139
140/// Create a member expression: obj.prop
141#[cfg(feature = "swc")]
142#[macro_export]
143macro_rules! member_expr {
144    ($obj:expr, $prop:expr) => {
145        swc_core::ecma::ast::Expr::Member(swc_core::ecma::ast::MemberExpr {
146            span: swc_core::common::DUMMY_SP,
147            obj: Box::new($obj),
148            prop: swc_core::ecma::ast::MemberProp::Ident(swc_core::ecma::ast::IdentName {
149                span: swc_core::common::DUMMY_SP,
150                sym: $prop.into(),
151            }),
152        })
153    };
154}
155
156/// Create an assignment expression statement: lhs = rhs;
157#[cfg(feature = "swc")]
158#[macro_export]
159macro_rules! assign_stmt {
160    ($lhs:expr, $rhs:expr) => {
161        swc_core::ecma::ast::Stmt::Expr(swc_core::ecma::ast::ExprStmt {
162            span: swc_core::common::DUMMY_SP,
163            expr: Box::new(swc_core::ecma::ast::Expr::Assign(
164                swc_core::ecma::ast::AssignExpr {
165                    span: swc_core::common::DUMMY_SP,
166                    op: swc_core::ecma::ast::AssignOp::Assign,
167                    left: $lhs,
168                    right: Box::new($rhs),
169                },
170            )),
171        })
172    };
173}
174
175/// Create a function assignment: obj.prop = function(params) { body };
176/// Usage: fn_assign!(ClassName.prototype.methodName, params, body_stmts)
177/// Or: fn_assign!(ClassName.prototype.methodName, body_stmts) for no params
178#[cfg(feature = "swc")]
179#[macro_export]
180macro_rules! fn_assign {
181    ($obj:expr, $prop:expr, $body_stmts:expr) => {{
182        use swc_core::common::{DUMMY_SP, SyntaxContext};
183        use swc_core::ecma::ast::*;
184
185        Stmt::Expr(ExprStmt {
186            span: DUMMY_SP,
187            expr: Box::new(Expr::Assign(AssignExpr {
188                span: DUMMY_SP,
189                op: AssignOp::Assign,
190                left: AssignTarget::Simple(SimpleAssignTarget::Member(MemberExpr {
191                    span: DUMMY_SP,
192                    obj: Box::new($obj),
193                    prop: MemberProp::Ident(IdentName {
194                        span: DUMMY_SP,
195                        sym: $prop.into(),
196                    }),
197                })),
198                right: Box::new(Expr::Fn(FnExpr {
199                    ident: None,
200                    function: Box::new(Function {
201                        params: vec![],
202                        decorators: vec![],
203                        span: DUMMY_SP,
204                        ctxt: SyntaxContext::empty(),
205                        body: Some(BlockStmt {
206                            span: DUMMY_SP,
207                            ctxt: SyntaxContext::empty(),
208                            stmts: $body_stmts,
209                        }),
210                        is_generator: false,
211                        is_async: false,
212                        type_params: None,
213                        return_type: None,
214                    }),
215                })),
216            })),
217        })
218    }};
219    ($obj:expr, $prop:expr, $params:expr, $body_stmts:expr) => {{
220        use swc_core::common::{DUMMY_SP, SyntaxContext};
221        use swc_core::ecma::ast::*;
222
223        Stmt::Expr(ExprStmt {
224            span: DUMMY_SP,
225            expr: Box::new(Expr::Assign(AssignExpr {
226                span: DUMMY_SP,
227                op: AssignOp::Assign,
228                left: AssignTarget::Simple(SimpleAssignTarget::Member(MemberExpr {
229                    span: DUMMY_SP,
230                    obj: Box::new($obj),
231                    prop: MemberProp::Ident(IdentName {
232                        span: DUMMY_SP,
233                        sym: $prop.into(),
234                    }),
235                })),
236                right: Box::new(Expr::Fn(FnExpr {
237                    ident: None,
238                    function: Box::new(Function {
239                        params: $params,
240                        decorators: vec![],
241                        span: DUMMY_SP,
242                        ctxt: SyntaxContext::empty(),
243                        body: Some(BlockStmt {
244                            span: DUMMY_SP,
245                            ctxt: SyntaxContext::empty(),
246                            stmts: $body_stmts,
247                        }),
248                        is_generator: false,
249                        is_async: false,
250                        type_params: None,
251                        return_type: None,
252                    }),
253                })),
254            })),
255        })
256    }};
257}