pub mod abi;
pub mod config;
pub mod derive;
pub mod errors;
pub mod import_registry;
pub mod lower;
pub mod parse;
pub mod quote_helpers;
pub mod stream;
pub use abi::*;
pub use derive::*;
pub use errors::*;
pub use import_registry::{
ImportRegistry, clear_registry, install_registry, take_registry, with_registry,
with_registry_mut,
};
pub use lower::*;
pub use stream::*;
#[cfg(feature = "swc")]
pub use swc_core::quote;
#[cfg(feature = "swc")]
pub use swc_core;
#[cfg(feature = "swc")]
pub use swc_core::common as swc_common;
#[cfg(feature = "swc")]
pub use swc_core::ecma::ast as swc_ecma_ast;
#[cfg(feature = "swc")]
pub trait ToTsExpr {
fn to_ts_expr(self) -> swc_core::ecma::ast::Expr;
}
#[cfg(feature = "swc")]
impl ToTsExpr for swc_core::ecma::ast::Expr {
fn to_ts_expr(self) -> swc_core::ecma::ast::Expr {
self
}
}
#[cfg(feature = "swc")]
impl ToTsExpr for Box<swc_core::ecma::ast::Expr> {
fn to_ts_expr(self) -> swc_core::ecma::ast::Expr {
*self
}
}
#[cfg(feature = "swc")]
impl ToTsExpr for &swc_core::ecma::ast::Expr {
fn to_ts_expr(self) -> swc_core::ecma::ast::Expr {
self.clone()
}
}
#[cfg(feature = "swc")]
impl ToTsExpr for swc_core::ecma::ast::Ident {
fn to_ts_expr(self) -> swc_core::ecma::ast::Expr {
swc_core::ecma::ast::Expr::Ident(self)
}
}
#[cfg(feature = "swc")]
impl ToTsExpr for &swc_core::ecma::ast::Ident {
fn to_ts_expr(self) -> swc_core::ecma::ast::Expr {
swc_core::ecma::ast::Expr::Ident(self.clone())
}
}
#[cfg(feature = "swc")]
impl ToTsExpr for String {
fn to_ts_expr(self) -> swc_core::ecma::ast::Expr {
swc_core::ecma::ast::Expr::Lit(swc_core::ecma::ast::Lit::Str(swc_core::ecma::ast::Str {
span: swc_core::common::DUMMY_SP,
value: self.into(),
raw: None,
}))
}
}
#[cfg(feature = "swc")]
impl ToTsExpr for &String {
fn to_ts_expr(self) -> swc_core::ecma::ast::Expr {
self.clone().to_ts_expr()
}
}
#[cfg(feature = "swc")]
impl ToTsExpr for &str {
fn to_ts_expr(self) -> swc_core::ecma::ast::Expr {
swc_core::ecma::ast::Expr::Lit(swc_core::ecma::ast::Lit::Str(swc_core::ecma::ast::Str {
span: swc_core::common::DUMMY_SP,
value: self.into(),
raw: None,
}))
}
}
#[cfg(feature = "swc")]
impl ToTsExpr for bool {
fn to_ts_expr(self) -> swc_core::ecma::ast::Expr {
swc_core::ecma::ast::Expr::Lit(swc_core::ecma::ast::Lit::Bool(swc_core::ecma::ast::Bool {
span: swc_core::common::DUMMY_SP,
value: self,
}))
}
}
#[cfg(feature = "swc")]
impl ToTsExpr for &bool {
fn to_ts_expr(self) -> swc_core::ecma::ast::Expr {
(*self).to_ts_expr()
}
}
#[cfg(feature = "swc")]
pub fn to_ts_expr<T: ToTsExpr>(value: T) -> swc_core::ecma::ast::Expr {
value.to_ts_expr()
}
#[cfg(feature = "swc")]
pub trait ToTsType {
fn to_ts_type(self) -> swc_core::ecma::ast::TsType;
}
#[cfg(feature = "swc")]
impl ToTsType for swc_core::ecma::ast::TsType {
fn to_ts_type(self) -> swc_core::ecma::ast::TsType {
self
}
}
#[cfg(feature = "swc")]
impl ToTsType for Box<swc_core::ecma::ast::TsType> {
fn to_ts_type(self) -> swc_core::ecma::ast::TsType {
*self
}
}
#[cfg(feature = "swc")]
impl ToTsType for &swc_core::ecma::ast::TsType {
fn to_ts_type(self) -> swc_core::ecma::ast::TsType {
self.clone()
}
}
#[cfg(feature = "swc")]
impl ToTsType for String {
fn to_ts_type(self) -> swc_core::ecma::ast::TsType {
swc_core::ecma::ast::TsType::TsTypeRef(swc_core::ecma::ast::TsTypeRef {
span: swc_core::common::DUMMY_SP,
type_name: swc_core::ecma::ast::TsEntityName::Ident(
swc_core::ecma::ast::Ident::new_no_ctxt(self.into(), swc_core::common::DUMMY_SP),
),
type_params: None,
})
}
}
#[cfg(feature = "swc")]
impl ToTsType for &String {
fn to_ts_type(self) -> swc_core::ecma::ast::TsType {
self.clone().to_ts_type()
}
}
#[cfg(feature = "swc")]
impl ToTsType for &str {
fn to_ts_type(self) -> swc_core::ecma::ast::TsType {
self.to_string().to_ts_type()
}
}
#[cfg(feature = "swc")]
impl ToTsType for swc_core::ecma::ast::Ident {
fn to_ts_type(self) -> swc_core::ecma::ast::TsType {
swc_core::ecma::ast::TsType::TsTypeRef(swc_core::ecma::ast::TsTypeRef {
span: swc_core::common::DUMMY_SP,
type_name: swc_core::ecma::ast::TsEntityName::Ident(self),
type_params: None,
})
}
}
#[cfg(feature = "swc")]
impl ToTsType for &swc_core::ecma::ast::Ident {
fn to_ts_type(self) -> swc_core::ecma::ast::TsType {
self.clone().to_ts_type()
}
}
#[cfg(feature = "swc")]
impl ToTsType for bool {
fn to_ts_type(self) -> swc_core::ecma::ast::TsType {
swc_core::ecma::ast::TsType::TsLitType(swc_core::ecma::ast::TsLitType {
span: swc_core::common::DUMMY_SP,
lit: swc_core::ecma::ast::TsLit::Bool(swc_core::ecma::ast::Bool {
span: swc_core::common::DUMMY_SP,
value: self,
}),
})
}
}
#[cfg(feature = "swc")]
impl ToTsType for &bool {
fn to_ts_type(self) -> swc_core::ecma::ast::TsType {
(*self).to_ts_type()
}
}
#[cfg(feature = "swc")]
impl ToTsType for swc_core::ecma::ast::Expr {
fn to_ts_type(self) -> swc_core::ecma::ast::TsType {
match self {
swc_core::ecma::ast::Expr::Ident(ident) => ident.to_ts_type(),
other => swc_core::ecma::ast::TsType::TsTypeQuery(swc_core::ecma::ast::TsTypeQuery {
span: swc_core::common::DUMMY_SP,
expr_name: swc_core::ecma::ast::TsTypeQueryExpr::TsEntityName(
swc_core::ecma::ast::TsEntityName::Ident(
swc_core::ecma::ast::Ident::new_no_ctxt(
format!("{:?}", other).into(),
swc_core::common::DUMMY_SP,
),
),
),
type_args: None,
}),
}
}
}
#[cfg(feature = "swc")]
impl ToTsType for &swc_core::ecma::ast::Expr {
fn to_ts_type(self) -> swc_core::ecma::ast::TsType {
self.clone().to_ts_type()
}
}
#[cfg(feature = "swc")]
pub fn to_ts_type<T: ToTsType>(value: T) -> swc_core::ecma::ast::TsType {
value.to_ts_type()
}
#[cfg(feature = "swc")]
pub trait ToTsIdent {
fn to_ts_ident(self) -> swc_core::ecma::ast::Ident;
}
#[cfg(feature = "swc")]
impl ToTsIdent for swc_core::ecma::ast::Ident {
fn to_ts_ident(self) -> swc_core::ecma::ast::Ident {
self
}
}
#[cfg(feature = "swc")]
impl ToTsIdent for &swc_core::ecma::ast::Ident {
fn to_ts_ident(self) -> swc_core::ecma::ast::Ident {
self.clone()
}
}
#[cfg(feature = "swc")]
impl ToTsIdent for String {
fn to_ts_ident(self) -> swc_core::ecma::ast::Ident {
swc_core::ecma::ast::Ident::new_no_ctxt(self.into(), swc_core::common::DUMMY_SP)
}
}
#[cfg(feature = "swc")]
impl ToTsIdent for &String {
fn to_ts_ident(self) -> swc_core::ecma::ast::Ident {
self.clone().to_ts_ident()
}
}
#[cfg(feature = "swc")]
impl ToTsIdent for &str {
fn to_ts_ident(self) -> swc_core::ecma::ast::Ident {
swc_core::ecma::ast::Ident::new_no_ctxt(self.into(), swc_core::common::DUMMY_SP)
}
}
#[cfg(feature = "swc")]
impl ToTsIdent for swc_core::ecma::ast::Expr {
fn to_ts_ident(self) -> swc_core::ecma::ast::Ident {
match self {
swc_core::ecma::ast::Expr::Ident(ident) => ident,
_ => swc_core::ecma::ast::Ident::new_no_ctxt(
"__expr__".into(),
swc_core::common::DUMMY_SP,
),
}
}
}
#[cfg(feature = "swc")]
impl ToTsIdent for &swc_core::ecma::ast::Expr {
fn to_ts_ident(self) -> swc_core::ecma::ast::Ident {
self.clone().to_ts_ident()
}
}
#[cfg(feature = "swc")]
impl ToTsIdent for swc_core::ecma::ast::TsType {
fn to_ts_ident(self) -> swc_core::ecma::ast::Ident {
match self {
swc_core::ecma::ast::TsType::TsTypeRef(swc_core::ecma::ast::TsTypeRef {
type_name: swc_core::ecma::ast::TsEntityName::Ident(ident),
..
}) => ident,
_ => swc_core::ecma::ast::Ident::new_no_ctxt(
"__type__".into(),
swc_core::common::DUMMY_SP,
),
}
}
}
#[cfg(feature = "swc")]
impl ToTsIdent for &swc_core::ecma::ast::TsType {
fn to_ts_ident(self) -> swc_core::ecma::ast::Ident {
self.clone().to_ts_ident()
}
}
#[cfg(feature = "swc")]
impl ToTsIdent for Box<swc_core::ecma::ast::TsType> {
fn to_ts_ident(self) -> swc_core::ecma::ast::Ident {
(*self).to_ts_ident()
}
}
#[cfg(feature = "swc")]
pub fn to_ts_ident<T: ToTsIdent>(value: T) -> swc_core::ecma::ast::Ident {
value.to_ts_ident()
}
#[cfg(feature = "swc")]
pub trait ToTsStmt {
fn to_ts_stmt(self) -> swc_core::ecma::ast::Stmt;
}
#[cfg(feature = "swc")]
impl ToTsStmt for swc_core::ecma::ast::Stmt {
fn to_ts_stmt(self) -> swc_core::ecma::ast::Stmt {
self
}
}
#[cfg(feature = "swc")]
impl ToTsStmt for Box<swc_core::ecma::ast::Stmt> {
fn to_ts_stmt(self) -> swc_core::ecma::ast::Stmt {
*self
}
}
#[cfg(feature = "swc")]
impl ToTsStmt for &swc_core::ecma::ast::Stmt {
fn to_ts_stmt(self) -> swc_core::ecma::ast::Stmt {
self.clone()
}
}
#[cfg(feature = "swc")]
impl ToTsStmt for swc_core::ecma::ast::Expr {
fn to_ts_stmt(self) -> swc_core::ecma::ast::Stmt {
swc_core::ecma::ast::Stmt::Expr(swc_core::ecma::ast::ExprStmt {
span: swc_core::common::DUMMY_SP,
expr: Box::new(self),
})
}
}
#[cfg(feature = "swc")]
impl ToTsStmt for Box<swc_core::ecma::ast::Expr> {
fn to_ts_stmt(self) -> swc_core::ecma::ast::Stmt {
swc_core::ecma::ast::Stmt::Expr(swc_core::ecma::ast::ExprStmt {
span: swc_core::common::DUMMY_SP,
expr: self,
})
}
}
#[cfg(feature = "swc")]
impl ToTsStmt for String {
fn to_ts_stmt(self) -> swc_core::ecma::ast::Stmt {
use swc_core::ecma::ast::{BlockStmt, EmptyStmt, ModuleItem, Stmt};
let mut stmts: Vec<Stmt> = parse_ts_to_module_items(&self)
.into_iter()
.filter_map(|item| match item {
ModuleItem::Stmt(stmt) => Some(stmt),
_ => None,
})
.collect();
match stmts.len() {
0 => Stmt::Empty(EmptyStmt {
span: swc_core::common::DUMMY_SP,
}),
1 => stmts.pop().expect("single statement missing"),
_ => Stmt::Block(BlockStmt {
span: swc_core::common::DUMMY_SP,
ctxt: swc_core::common::SyntaxContext::empty(),
stmts,
}),
}
}
}
#[cfg(feature = "swc")]
impl ToTsStmt for &String {
fn to_ts_stmt(self) -> swc_core::ecma::ast::Stmt {
self.as_str().to_ts_stmt()
}
}
#[cfg(feature = "swc")]
impl ToTsStmt for &str {
fn to_ts_stmt(self) -> swc_core::ecma::ast::Stmt {
self.to_string().to_ts_stmt()
}
}
#[cfg(feature = "swc")]
pub fn to_ts_stmt<T: ToTsStmt>(value: T) -> swc_core::ecma::ast::Stmt {
value.to_ts_stmt()
}
#[cfg(feature = "swc")]
pub trait ToTsTypeName {
fn to_ts_type_name(&self) -> String;
}
#[cfg(feature = "swc")]
impl ToTsTypeName for swc_core::ecma::ast::Ident {
fn to_ts_type_name(&self) -> String {
self.sym.to_string()
}
}
#[cfg(feature = "swc")]
impl ToTsTypeName for &swc_core::ecma::ast::Ident {
fn to_ts_type_name(&self) -> String {
self.sym.to_string()
}
}
#[cfg(feature = "swc")]
impl ToTsTypeName for String {
fn to_ts_type_name(&self) -> String {
self.clone()
}
}
#[cfg(feature = "swc")]
impl ToTsTypeName for &String {
fn to_ts_type_name(&self) -> String {
(*self).clone()
}
}
#[cfg(feature = "swc")]
impl ToTsTypeName for &str {
fn to_ts_type_name(&self) -> String {
(*self).to_string()
}
}
#[cfg(feature = "swc")]
#[macro_export]
macro_rules! ts_ident {
($name:expr) => {
$crate::swc_core::ecma::ast::Ident::new_no_ctxt(
AsRef::<str>::as_ref(&$name).into(),
$crate::swc_core::common::DUMMY_SP,
)
};
($fmt:expr, $($args:expr),+ $(,)?) => {
$crate::swc_core::ecma::ast::Ident::new_no_ctxt(format!($fmt, $($args),+).into(), $crate::swc_core::common::DUMMY_SP)
};
}
#[cfg(feature = "swc")]
#[macro_export]
macro_rules! ts_private_ident {
($name:expr) => {{
let mark = $crate::swc_core::common::Mark::fresh($crate::swc_core::common::Mark::root());
$crate::swc_core::ecma::ast::Ident::new(
$name.into(),
$crate::swc_core::common::DUMMY_SP,
$crate::swc_core::common::SyntaxContext::empty().apply_mark(mark),
)
}};
}
#[cfg(feature = "swc")]
#[macro_export]
macro_rules! stmt_block {
($stmts:expr) => {
$crate::swc_core::ecma::ast::Stmt::Block($crate::swc_core::ecma::ast::BlockStmt {
span: $crate::swc_core::common::DUMMY_SP,
ctxt: $crate::swc_core::common::SyntaxContext::empty(),
stmts: $stmts,
})
};
}
#[cfg(feature = "swc")]
pub struct StmtVec(pub Vec<swc_core::ecma::ast::Stmt>);
#[cfg(feature = "swc")]
#[macro_export]
macro_rules! stmt_vec {
($stmts:expr) => {
macroforge_ts_syn::StmtVec($stmts)
};
}
#[cfg(feature = "swc")]
#[macro_export]
macro_rules! stmt_block_from_vec {
($stmts:expr) => {
$crate::swc_core::ecma::ast::Stmt::Block($crate::swc_core::ecma::ast::BlockStmt {
span: $crate::swc_core::common::DUMMY_SP,
ctxt: $crate::swc_core::common::SyntaxContext::empty(),
stmts: $stmts,
})
};
}
#[cfg(feature = "swc")]
#[macro_export]
macro_rules! fn_expr {
($body_stmts:expr) => {
$crate::swc_core::ecma::ast::Expr::Fn($crate::swc_core::ecma::ast::FnExpr {
ident: None,
function: Box::new($crate::swc_core::ecma::ast::Function {
params: vec![],
decorators: vec![],
span: $crate::swc_core::common::DUMMY_SP,
ctxt: $crate::swc_core::common::SyntaxContext::empty(),
body: Some($crate::swc_core::ecma::ast::BlockStmt {
span: $crate::swc_core::common::DUMMY_SP,
ctxt: $crate::swc_core::common::SyntaxContext::empty(),
stmts: $body_stmts,
}),
is_generator: false,
is_async: false,
type_params: None,
return_type: None,
}),
})
};
($params:expr, $body_stmts:expr) => {
$crate::swc_core::ecma::ast::Expr::Fn($crate::swc_core::ecma::ast::FnExpr {
ident: None,
function: Box::new($crate::swc_core::ecma::ast::Function {
params: $params,
decorators: vec![],
span: $crate::swc_core::common::DUMMY_SP,
ctxt: $crate::swc_core::common::SyntaxContext::empty(),
body: Some($crate::swc_core::ecma::ast::BlockStmt {
span: $crate::swc_core::common::DUMMY_SP,
ctxt: $crate::swc_core::common::SyntaxContext::empty(),
stmts: $body_stmts,
}),
is_generator: false,
is_async: false,
type_params: None,
return_type: None,
}),
})
};
}
#[cfg(feature = "swc")]
#[macro_export]
macro_rules! member_expr {
($obj:expr, $prop:expr) => {
$crate::swc_core::ecma::ast::Expr::Member($crate::swc_core::ecma::ast::MemberExpr {
span: $crate::swc_core::common::DUMMY_SP,
obj: Box::new($obj),
prop: $crate::swc_core::ecma::ast::MemberProp::Ident(
$crate::swc_core::ecma::ast::IdentName {
span: $crate::swc_core::common::DUMMY_SP,
sym: $prop.into(),
},
),
})
};
}
#[cfg(feature = "swc")]
#[macro_export]
macro_rules! assign_stmt {
($lhs:expr, $rhs:expr) => {
$crate::swc_core::ecma::ast::Stmt::Expr($crate::swc_core::ecma::ast::ExprStmt {
span: $crate::swc_core::common::DUMMY_SP,
expr: Box::new($crate::swc_core::ecma::ast::Expr::Assign(
$crate::swc_core::ecma::ast::AssignExpr {
span: $crate::swc_core::common::DUMMY_SP,
op: $crate::swc_core::ecma::ast::AssignOp::Assign,
left: $lhs,
right: Box::new($rhs),
},
)),
})
};
}
#[cfg(feature = "swc")]
#[macro_export]
macro_rules! fn_assign {
($obj:expr, $prop:expr, $body_stmts:expr) => {{
use $crate::swc_core::common::{DUMMY_SP, SyntaxContext};
use $crate::swc_core::ecma::ast::*;
Stmt::Expr(ExprStmt {
span: DUMMY_SP,
expr: Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
op: AssignOp::Assign,
left: AssignTarget::Simple(SimpleAssignTarget::Member(MemberExpr {
span: DUMMY_SP,
obj: Box::new($obj),
prop: MemberProp::Ident(IdentName {
span: DUMMY_SP,
sym: $prop.into(),
}),
})),
right: Box::new(Expr::Fn(FnExpr {
ident: None,
function: Box::new(Function {
params: vec![],
decorators: vec![],
span: DUMMY_SP,
ctxt: SyntaxContext::empty(),
body: Some(BlockStmt {
span: DUMMY_SP,
ctxt: SyntaxContext::empty(),
stmts: $body_stmts,
}),
is_generator: false,
is_async: false,
type_params: None,
return_type: None,
}),
})),
})),
})
}};
($obj:expr, $prop:expr, $params:expr, $body_stmts:expr) => {{
use $crate::swc_core::common::{DUMMY_SP, SyntaxContext};
use $crate::swc_core::ecma::ast::*;
Stmt::Expr(ExprStmt {
span: DUMMY_SP,
expr: Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
op: AssignOp::Assign,
left: AssignTarget::Simple(SimpleAssignTarget::Member(MemberExpr {
span: DUMMY_SP,
obj: Box::new($obj),
prop: MemberProp::Ident(IdentName {
span: DUMMY_SP,
sym: $prop.into(),
}),
})),
right: Box::new(Expr::Fn(FnExpr {
ident: None,
function: Box::new(Function {
params: $params,
decorators: vec![],
span: DUMMY_SP,
ctxt: SyntaxContext::empty(),
body: Some(BlockStmt {
span: DUMMY_SP,
ctxt: SyntaxContext::empty(),
stmts: $body_stmts,
}),
is_generator: false,
is_async: false,
type_params: None,
return_type: None,
}),
})),
})),
})
}};
}
#[cfg(feature = "swc")]
pub fn expr_to_string(expr: &swc_core::ecma::ast::Expr) -> String {
use swc_core::common::sync::Lrc;
use swc_core::ecma::ast::{ExprStmt, Module, ModuleItem, Stmt};
use swc_core::ecma::codegen::{Config, Emitter, text_writer::JsWriter};
let module = Module {
span: swc_core::common::DUMMY_SP,
body: vec![ModuleItem::Stmt(Stmt::Expr(ExprStmt {
span: swc_core::common::DUMMY_SP,
expr: Box::new(expr.clone()),
}))],
shebang: None,
};
let cm = Lrc::new(swc_core::common::SourceMap::default());
let mut buf = Vec::new();
{
let mut emitter = Emitter {
cfg: Config::default(),
cm: cm.clone(),
comments: None,
wr: JsWriter::new(cm.clone(), "\n", &mut buf, None),
};
let _ = emitter.emit_module(&module);
}
let s = String::from_utf8(buf).unwrap_or_default();
s.trim_end().trim_end_matches(';').to_string()
}
#[cfg(feature = "swc")]
pub fn type_to_string(ty: &swc_core::ecma::ast::TsType) -> String {
use swc_core::common::sync::Lrc;
use swc_core::ecma::ast::*;
use swc_core::ecma::codegen::{Config, Emitter, text_writer::JsWriter};
let module = Module {
span: swc_core::common::DUMMY_SP,
body: vec![ModuleItem::Stmt(Stmt::Decl(Decl::TsTypeAlias(Box::new(
TsTypeAliasDecl {
span: swc_core::common::DUMMY_SP,
declare: false,
id: Ident::new_no_ctxt("__T".into(), swc_core::common::DUMMY_SP),
type_params: None,
type_ann: Box::new(ty.clone()),
},
))))],
shebang: None,
};
let cm = Lrc::new(swc_core::common::SourceMap::default());
let mut buf = Vec::new();
{
let mut emitter = Emitter {
cfg: Config::default(),
cm: cm.clone(),
comments: None,
wr: JsWriter::new(cm.clone(), "\n", &mut buf, None),
};
let _ = emitter.emit_module(&module);
}
let s = String::from_utf8(buf).unwrap_or_default();
if let Some(eq_pos) = s.find("= ") {
let after_eq = &s[eq_pos + 2..];
if let Some(semi_pos) = after_eq.rfind(';') {
return after_eq[..semi_pos].to_string();
}
}
s.trim().to_string()
}
#[cfg(feature = "swc")]
pub fn ident_to_string(ident: &swc_core::ecma::ast::Ident) -> String {
ident.sym.to_string()
}
#[cfg(feature = "swc")]
pub fn emit_module_items(
items: &[swc_core::ecma::ast::ModuleItem],
comments: &swc_core::common::comments::SingleThreadedComments,
) -> String {
use swc_core::common::sync::Lrc;
use swc_core::ecma::ast::Module;
use swc_core::ecma::codegen::{Config, Emitter, text_writer::JsWriter};
let module = Module {
span: swc_core::common::DUMMY_SP,
body: items.to_vec(),
shebang: None,
};
let cm = Lrc::new(swc_core::common::SourceMap::default());
let mut buf = Vec::new();
{
let mut emitter = Emitter {
cfg: Config::default().with_minify(false),
cm: cm.clone(),
comments: Some(comments),
wr: JsWriter::new(cm.clone(), "\n", &mut buf, None),
};
let _ = emitter.emit_module(&module);
}
String::from_utf8(buf).unwrap_or_default()
}
#[cfg(feature = "swc")]
pub fn emit_expr(expr: &swc_core::ecma::ast::Expr) -> String {
use swc_core::common::comments::SingleThreadedComments;
use swc_core::common::sync::Lrc;
use swc_core::ecma::ast::{ExprStmt, Module, ModuleItem, Stmt};
use swc_core::ecma::codegen::{Config, Emitter, text_writer::JsWriter};
let module = Module {
span: swc_core::common::DUMMY_SP,
body: vec![ModuleItem::Stmt(Stmt::Expr(ExprStmt {
span: swc_core::common::DUMMY_SP,
expr: Box::new(expr.clone()),
}))],
shebang: None,
};
let cm = Lrc::new(swc_core::common::SourceMap::default());
let comments = SingleThreadedComments::default();
let mut buf = Vec::new();
{
let mut emitter = Emitter {
cfg: Config::default().with_minify(false),
cm: cm.clone(),
comments: Some(&comments),
wr: JsWriter::new(cm.clone(), "\n", &mut buf, None),
};
let _ = emitter.emit_module(&module);
}
let s = String::from_utf8(buf).unwrap_or_default();
s.trim_end().trim_end_matches(';').to_string()
}
#[cfg(feature = "swc")]
pub fn emit_ts_type(ty: &swc_core::ecma::ast::TsType) -> String {
use swc_core::common::comments::SingleThreadedComments;
use swc_core::common::sync::Lrc;
use swc_core::ecma::ast::{Decl, Ident, Module, ModuleItem, Stmt, TsTypeAliasDecl};
use swc_core::ecma::codegen::{Config, Emitter, text_writer::JsWriter};
let module = Module {
span: swc_core::common::DUMMY_SP,
body: vec![ModuleItem::Stmt(Stmt::Decl(Decl::TsTypeAlias(Box::new(
TsTypeAliasDecl {
span: swc_core::common::DUMMY_SP,
declare: false,
id: Ident::new("__T".into(), swc_core::common::DUMMY_SP, Default::default()),
type_params: None,
type_ann: Box::new(ty.clone()),
},
))))],
shebang: None,
};
let cm = Lrc::new(swc_core::common::SourceMap::default());
let comments = SingleThreadedComments::default();
let mut buf = Vec::new();
{
let mut emitter = Emitter {
cfg: Config::default().with_minify(false),
cm: cm.clone(),
comments: Some(&comments),
wr: JsWriter::new(cm.clone(), "\n", &mut buf, None),
};
let _ = emitter.emit_module(&module);
}
let s = String::from_utf8(buf).unwrap_or_default();
if let Some(start) = s.find('=') {
let after_eq = &s[start + 1..];
after_eq.trim().trim_end_matches(';').to_string()
} else {
s
}
}
#[cfg(feature = "swc")]
pub fn emit_stmt(stmt: &swc_core::ecma::ast::Stmt) -> String {
use swc_core::common::comments::SingleThreadedComments;
use swc_core::common::sync::Lrc;
use swc_core::ecma::ast::{Module, ModuleItem};
use swc_core::ecma::codegen::{Config, Emitter, text_writer::JsWriter};
let module = Module {
span: swc_core::common::DUMMY_SP,
body: vec![ModuleItem::Stmt(stmt.clone())],
shebang: None,
};
let cm = Lrc::new(swc_core::common::SourceMap::default());
let comments = SingleThreadedComments::default();
let mut buf = Vec::new();
{
let mut emitter = Emitter {
cfg: Config::default().with_minify(false),
cm: cm.clone(),
comments: Some(&comments),
wr: JsWriter::new(cm.clone(), "\n", &mut buf, None),
};
let _ = emitter.emit_module(&module);
}
String::from_utf8(buf).unwrap_or_default()
}
pub trait ToTsString {
fn to_ts_string(&self) -> String;
}
impl ToTsString for String {
fn to_ts_string(&self) -> String {
self.clone()
}
}
impl ToTsString for str {
fn to_ts_string(&self) -> String {
self.to_owned()
}
}
impl ToTsString for bool {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for i8 {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for i16 {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for i32 {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for i64 {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for i128 {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for isize {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for u8 {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for u16 {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for u32 {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for u64 {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for u128 {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for usize {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for f32 {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for f64 {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
impl ToTsString for char {
fn to_ts_string(&self) -> String {
self.to_string()
}
}
#[cfg(feature = "swc")]
impl ToTsString for swc_core::ecma::ast::Expr {
fn to_ts_string(&self) -> String {
emit_expr(self)
}
}
#[cfg(feature = "swc")]
impl ToTsString for swc_core::ecma::ast::Ident {
fn to_ts_string(&self) -> String {
self.sym.to_string()
}
}
#[cfg(feature = "swc")]
impl ToTsString for swc_core::ecma::ast::TsType {
fn to_ts_string(&self) -> String {
emit_ts_type(self)
}
}
#[cfg(feature = "swc")]
impl ToTsString for swc_core::ecma::ast::Stmt {
fn to_ts_string(&self) -> String {
emit_stmt(self)
}
}
#[cfg(feature = "swc")]
impl ToTsString for crate::TsStream {
fn to_ts_string(&self) -> String {
self.source().to_string()
}
}
impl<T: ToTsString + ?Sized> ToTsString for &T {
fn to_ts_string(&self) -> String {
(*self).to_ts_string()
}
}
impl<T: ToTsString + ?Sized> ToTsString for &mut T {
fn to_ts_string(&self) -> String {
(**self).to_ts_string()
}
}
impl<T: ToTsString + ?Sized> ToTsString for Box<T> {
fn to_ts_string(&self) -> String {
(**self).to_ts_string()
}
}
impl<T: ToTsString + Clone> ToTsString for std::borrow::Cow<'_, T> {
fn to_ts_string(&self) -> String {
self.as_ref().to_ts_string()
}
}
impl<T: ToTsString> ToTsString for std::rc::Rc<T> {
fn to_ts_string(&self) -> String {
(**self).to_ts_string()
}
}
impl<T: ToTsString> ToTsString for std::sync::Arc<T> {
fn to_ts_string(&self) -> String {
(**self).to_ts_string()
}
}
#[cfg(feature = "swc")]
#[derive(Debug, Clone)]
pub struct TsExpr(pub swc_core::ecma::ast::Expr);
#[cfg(feature = "swc")]
impl std::fmt::Display for TsExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", emit_expr(&self.0))
}
}
#[cfg(feature = "swc")]
impl From<swc_core::ecma::ast::Expr> for TsExpr {
fn from(expr: swc_core::ecma::ast::Expr) -> Self {
TsExpr(expr)
}
}
#[cfg(feature = "swc")]
impl std::ops::Deref for TsExpr {
type Target = swc_core::ecma::ast::Expr;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg(feature = "swc")]
#[derive(Debug, Clone)]
pub struct TsIdent(pub swc_core::ecma::ast::Ident);
#[cfg(feature = "swc")]
impl std::fmt::Display for TsIdent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0.sym)
}
}
#[cfg(feature = "swc")]
impl From<swc_core::ecma::ast::Ident> for TsIdent {
fn from(ident: swc_core::ecma::ast::Ident) -> Self {
TsIdent(ident)
}
}
#[cfg(feature = "swc")]
impl std::ops::Deref for TsIdent {
type Target = swc_core::ecma::ast::Ident;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg(feature = "swc")]
#[derive(Debug, Clone)]
pub struct TsTypeWrapper(pub swc_core::ecma::ast::TsType);
#[cfg(feature = "swc")]
impl std::fmt::Display for TsTypeWrapper {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", emit_ts_type(&self.0))
}
}
#[cfg(feature = "swc")]
impl From<swc_core::ecma::ast::TsType> for TsTypeWrapper {
fn from(ty: swc_core::ecma::ast::TsType) -> Self {
TsTypeWrapper(ty)
}
}
#[cfg(feature = "swc")]
impl std::ops::Deref for TsTypeWrapper {
type Target = swc_core::ecma::ast::TsType;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg(feature = "swc")]
#[derive(Debug, Clone)]
pub struct TsStmt(pub swc_core::ecma::ast::Stmt);
#[cfg(feature = "swc")]
impl std::fmt::Display for TsStmt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", emit_stmt(&self.0))
}
}
#[cfg(feature = "swc")]
impl From<swc_core::ecma::ast::Stmt> for TsStmt {
fn from(stmt: swc_core::ecma::ast::Stmt) -> Self {
TsStmt(stmt)
}
}
#[cfg(feature = "swc")]
impl std::ops::Deref for TsStmt {
type Target = swc_core::ecma::ast::Stmt;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg(feature = "swc")]
pub mod __internal {
use std::collections::HashMap;
use swc_core::ecma::ast::*;
use swc_core::ecma::visit::{VisitMut, VisitMutWith};
#[derive(Debug, Clone)]
pub enum ContextCollector {
ObjectProps(Vec<PropOrSpread>),
ArrayElems(Vec<ExprOrSpread>),
ClassMembers(Vec<ClassMember>),
TypeProps(Vec<TsTypeElement>),
Stmts(Vec<Stmt>),
}
impl ContextCollector {
pub fn new(context_type: u8) -> Self {
match context_type {
0 => Self::ObjectProps(vec![]),
1 => Self::ArrayElems(vec![]),
2 => Self::ClassMembers(vec![]),
3 => Self::TypeProps(vec![]),
_ => Self::Stmts(vec![]),
}
}
pub fn for_object() -> Self {
Self::ObjectProps(vec![])
}
pub fn for_array() -> Self {
Self::ArrayElems(vec![])
}
pub fn for_class() -> Self {
Self::ClassMembers(vec![])
}
pub fn for_type_object() -> Self {
Self::TypeProps(vec![])
}
}
pub fn push_object_prop(collector: &mut ContextCollector, prop: PropOrSpread) {
match collector {
ContextCollector::ObjectProps(props) => props.push(prop),
_ => panic!("push_object_prop called on non-ObjectProps collector"),
}
}
pub fn push_array_elem(collector: &mut ContextCollector, elem: ExprOrSpread) {
match collector {
ContextCollector::ArrayElems(elems) => elems.push(elem),
_ => panic!("push_array_elem called on non-ArrayElems collector"),
}
}
pub fn push_class_member(collector: &mut ContextCollector, member: ClassMember) {
match collector {
ContextCollector::ClassMembers(members) => members.push(member),
_ => panic!("push_class_member called on non-ClassMembers collector"),
}
}
pub fn push_type_prop(collector: &mut ContextCollector, prop: TsTypeElement) {
match collector {
ContextCollector::TypeProps(props) => props.push(prop),
_ => panic!("push_type_prop called on non-TypeProps collector"),
}
}
pub fn extract_prop_from_wrapped_expr(expr: &Expr) -> Option<PropOrSpread> {
if let Expr::Paren(ParenExpr { expr: inner, .. }) = expr
&& let Expr::Object(ObjectLit { props, .. }) = inner.as_ref()
{
for prop in props {
match prop {
PropOrSpread::Prop(p) => {
if let Prop::KeyValue(KeyValueProp {
key: PropName::Ident(ident),
..
}) = p.as_ref()
&& ident.sym.as_ref() == "__mf_dummy"
{
continue;
}
return Some(prop.clone());
}
PropOrSpread::Spread(_) => return Some(prop.clone()),
}
}
}
None
}
pub fn extract_elem_from_wrapped_expr(expr: &Expr) -> Option<ExprOrSpread> {
if let Expr::Array(ArrayLit { elems, .. }) = expr
&& let Some(elem) = elems.iter().flatten().next()
{
return Some(elem.clone());
}
None
}
pub fn extract_class_members_from_wrapped(item: &ModuleItem) -> Vec<ClassMember> {
if let ModuleItem::Stmt(Stmt::Decl(Decl::Class(ClassDecl { class, .. }))) = item {
return class.body.clone();
}
vec![]
}
pub fn extract_type_elements_from_wrapped(item: &ModuleItem) -> Vec<TsTypeElement> {
if let ModuleItem::Stmt(Stmt::Decl(Decl::TsTypeAlias(type_alias))) = item
&& let TsType::TsTypeLit(type_lit) = type_alias.type_ann.as_ref()
{
return type_lit.members.clone();
}
vec![]
}
pub fn merge_object_props(item: &mut ModuleItem, props: Vec<PropOrSpread>) {
let mut merger = ObjectPropMerger {
props_to_add: props,
};
item.visit_mut_with(&mut merger);
}
pub fn merge_array_elems(item: &mut ModuleItem, elems: Vec<ExprOrSpread>) {
let mut merger = ArrayElemMerger {
elems_to_add: elems,
};
item.visit_mut_with(&mut merger);
}
pub fn merge_class_members(item: &mut ModuleItem, members: Vec<ClassMember>) {
let mut merger = ClassMemberMerger {
members_to_add: members,
};
item.visit_mut_with(&mut merger);
}
pub fn merge_type_props(item: &mut ModuleItem, props: Vec<TsTypeElement>) {
let mut merger = TypePropMerger {
props_to_add: props,
};
item.visit_mut_with(&mut merger);
}
struct ObjectPropMerger {
props_to_add: Vec<PropOrSpread>,
}
impl VisitMut for ObjectPropMerger {
fn visit_mut_object_lit(&mut self, obj: &mut ObjectLit) {
if !self.props_to_add.is_empty() {
obj.props.retain(|prop| {
if let PropOrSpread::Prop(p) = prop
&& let Prop::KeyValue(KeyValueProp {
key: PropName::Ident(ident),
..
}) = p.as_ref()
&& ident.sym.as_ref() == "__mf_dummy"
{
return false;
}
true
});
obj.props.extend(std::mem::take(&mut self.props_to_add));
}
}
}
struct ArrayElemMerger {
elems_to_add: Vec<ExprOrSpread>,
}
impl VisitMut for ArrayElemMerger {
fn visit_mut_array_lit(&mut self, arr: &mut ArrayLit) {
if !self.elems_to_add.is_empty() {
if let Some(Some(ExprOrSpread { expr, .. })) = arr.elems.first()
&& let Expr::Lit(Lit::Num(Number { value, .. })) = expr.as_ref()
&& *value == 0.0
{
arr.elems.remove(0);
}
for elem in std::mem::take(&mut self.elems_to_add) {
arr.elems.push(Some(elem));
}
}
}
}
struct ClassMemberMerger {
members_to_add: Vec<ClassMember>,
}
impl VisitMut for ClassMemberMerger {
fn visit_mut_class(&mut self, class: &mut Class) {
if !self.members_to_add.is_empty() {
class.body.extend(std::mem::take(&mut self.members_to_add));
}
}
}
struct TypePropMerger {
props_to_add: Vec<TsTypeElement>,
}
impl VisitMut for TypePropMerger {
fn visit_mut_ts_type_lit(&mut self, lit: &mut TsTypeLit) {
if !self.props_to_add.is_empty() {
lit.members.extend(std::mem::take(&mut self.props_to_add));
}
}
}
struct TypeReplacer {
replacements: HashMap<String, TsType>,
}
impl VisitMut for TypeReplacer {
fn visit_mut_ts_type(&mut self, ty: &mut TsType) {
if let TsType::TsTypeRef(TsTypeRef {
type_name: TsEntityName::Ident(ident),
type_params: None,
..
}) = ty
{
let name = ident.sym.to_string();
if let Some(replacement) = self.replacements.get(&name) {
*ty = replacement.clone();
return;
}
}
ty.visit_mut_children_with(self);
}
}
pub fn replace_type_markers(item: &mut ModuleItem, replacements: HashMap<String, TsType>) {
let mut replacer = TypeReplacer { replacements };
item.visit_mut_with(&mut replacer);
}
pub fn replace_type_markers_stmt(stmt: &mut Stmt, replacements: HashMap<String, TsType>) {
let mut replacer = TypeReplacer { replacements };
stmt.visit_mut_with(&mut replacer);
}
pub fn push_opener(item: ModuleItem, output: &mut Vec<ModuleItem>, _depth: usize) -> usize {
let idx = output.len();
output.push(item);
idx
}
pub fn finalize_closer(item: ModuleItem, output: &mut Vec<ModuleItem>, opener_idx: usize) {
let closer_stmts = extract_function_body_statements(&item);
let intermediate_items: Vec<ModuleItem> = output.drain((opener_idx + 1)..).collect();
let intermediate_stmts: Vec<Stmt> = intermediate_items
.into_iter()
.filter_map(|mi| match mi {
ModuleItem::Stmt(stmt) => Some(stmt),
_ => None, })
.collect();
if let Some(opener) = output.get_mut(opener_idx) {
let all_stmts: Vec<Stmt> = intermediate_stmts.into_iter().chain(closer_stmts).collect();
extend_item_body(opener, all_stmts);
}
}
pub fn push_middle(item: ModuleItem, output: &mut Vec<ModuleItem>, opener_idx: usize) {
let stmts = extract_function_body_statements(&item);
let intermediate_items: Vec<ModuleItem> = output.drain((opener_idx + 1)..).collect();
let intermediate_stmts: Vec<Stmt> = intermediate_items
.into_iter()
.filter_map(|mi| match mi {
ModuleItem::Stmt(stmt) => Some(stmt),
_ => None,
})
.collect();
if let Some(opener) = output.get_mut(opener_idx) {
let all_stmts: Vec<Stmt> = intermediate_stmts.into_iter().chain(stmts).collect();
extend_item_body(opener, all_stmts);
}
}
pub fn extract_function_body_statements(item: &ModuleItem) -> Vec<Stmt> {
match item {
ModuleItem::Stmt(Stmt::Decl(Decl::Fn(FnDecl { function, .. }))) => {
if let Some(body) = &function.body {
body.stmts.clone()
} else {
vec![]
}
}
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
decl: Decl::Fn(FnDecl { function, .. }),
..
})) => {
if let Some(body) = &function.body {
body.stmts.clone()
} else {
vec![]
}
}
_ => vec![],
}
}
fn extend_item_body(item: &mut ModuleItem, stmts: Vec<Stmt>) {
match item {
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
decl: Decl::Fn(FnDecl { function, .. }),
..
})) => {
if let Some(ref mut body) = function.body {
body.stmts.extend(stmts);
}
}
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(ExportDefaultDecl {
decl: DefaultDecl::Fn(FnExpr { function, .. }),
..
})) => {
if let Some(ref mut body) = function.body {
body.stmts.extend(stmts);
}
}
ModuleItem::Stmt(Stmt::Decl(Decl::Fn(FnDecl { function, .. }))) => {
if let Some(ref mut body) = function.body {
body.stmts.extend(stmts);
}
}
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
decl: Decl::Class(ClassDecl { class, .. }),
..
})) => {
for member in class.body.iter_mut().rev() {
match member {
ClassMember::Method(ClassMethod { function, .. }) => {
if let Some(ref mut body) = function.body {
body.stmts.extend(stmts);
return;
}
}
ClassMember::Constructor(Constructor {
body: Some(body), ..
}) => {
body.stmts.extend(stmts);
return;
}
_ => {}
}
}
}
ModuleItem::Stmt(Stmt::Decl(Decl::Class(ClassDecl { class, .. }))) => {
for member in class.body.iter_mut().rev() {
match member {
ClassMember::Method(ClassMethod { function, .. }) => {
if let Some(ref mut body) = function.body {
body.stmts.extend(stmts);
return;
}
}
ClassMember::Constructor(Constructor {
body: Some(body), ..
}) => {
body.stmts.extend(stmts);
return;
}
_ => {}
}
}
}
ModuleItem::Stmt(stmt) => {
extend_stmt_body(stmt, stmts);
}
_ => {
}
}
}
fn extend_stmt_body(stmt: &mut Stmt, stmts: Vec<Stmt>) {
match stmt {
Stmt::Block(block) => {
block.stmts.extend(stmts);
}
Stmt::If(if_stmt) => {
if let Some(alt) = if_stmt.alt.as_deref_mut() {
extend_stmt_body(alt, stmts);
} else {
extend_stmt_body(if_stmt.cons.as_mut(), stmts);
}
}
Stmt::For(for_stmt) => {
extend_stmt_body(for_stmt.body.as_mut(), stmts);
}
Stmt::ForIn(for_in_stmt) => {
extend_stmt_body(for_in_stmt.body.as_mut(), stmts);
}
Stmt::ForOf(for_of_stmt) => {
extend_stmt_body(for_of_stmt.body.as_mut(), stmts);
}
Stmt::While(while_stmt) => {
extend_stmt_body(while_stmt.body.as_mut(), stmts);
}
Stmt::DoWhile(do_while_stmt) => {
extend_stmt_body(do_while_stmt.body.as_mut(), stmts);
}
Stmt::Labeled(labeled_stmt) => {
extend_stmt_body(labeled_stmt.body.as_mut(), stmts);
}
Stmt::With(with_stmt) => {
extend_stmt_body(with_stmt.body.as_mut(), stmts);
}
Stmt::Try(try_stmt) => {
if let Some(finalizer) = &mut try_stmt.finalizer {
finalizer.stmts.extend(stmts);
} else if let Some(handler) = &mut try_stmt.handler {
handler.body.stmts.extend(stmts);
} else {
try_stmt.block.stmts.extend(stmts);
}
}
_ => {}
}
}
}
#[cfg(feature = "swc")]
pub fn stmt_to_string(stmt: &swc_core::ecma::ast::Stmt) -> String {
use swc_core::common::sync::Lrc;
use swc_core::ecma::ast::{Module, ModuleItem};
use swc_core::ecma::codegen::{Config, Emitter, text_writer::JsWriter};
let module = Module {
span: swc_core::common::DUMMY_SP,
body: vec![ModuleItem::Stmt(stmt.clone())],
shebang: None,
};
let cm = Lrc::new(swc_core::common::SourceMap::default());
let mut buf = Vec::new();
{
let mut emitter = Emitter {
cfg: Config::default(),
cm: cm.clone(),
comments: None,
wr: JsWriter::new(cm.clone(), "\n", &mut buf, None),
};
let _ = emitter.emit_module(&module);
}
String::from_utf8(buf)
.unwrap_or_default()
.trim()
.to_string()
}
#[cfg(feature = "swc")]
pub fn parse_ts_to_module_items(source: &str) -> Vec<swc_core::ecma::ast::ModuleItem> {
use swc_core::common::{FileName, SourceMap, sync::Lrc};
use swc_core::ecma::parser::{Parser, StringInput, Syntax, TsSyntax, lexer::Lexer};
let cm: Lrc<SourceMap> = Lrc::new(SourceMap::default());
let fm = cm.new_source_file(
FileName::Custom("template.ts".into()).into(),
source.to_string(),
);
let syntax = Syntax::Typescript(TsSyntax {
tsx: true,
decorators: true,
..Default::default()
});
let lexer = Lexer::new(
syntax,
swc_core::ecma::ast::EsVersion::latest(),
StringInput::from(&*fm),
None,
);
let mut parser = Parser::new_from(lexer);
match parser.parse_module() {
Ok(module) => module.body,
Err(_) => vec![],
}
}
#[cfg(feature = "swc")]
pub fn extend_module_item_body(
item: &mut swc_core::ecma::ast::ModuleItem,
stmts: Vec<swc_core::ecma::ast::Stmt>,
) {
use swc_core::ecma::ast::*;
match item {
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
decl: Decl::Fn(FnDecl { function, .. }),
..
})) => {
if let Some(ref mut body) = function.body {
body.stmts.extend(stmts);
}
}
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(ExportDefaultDecl {
decl: DefaultDecl::Fn(FnExpr { function, .. }),
..
})) => {
if let Some(ref mut body) = function.body {
body.stmts.extend(stmts);
}
}
ModuleItem::Stmt(Stmt::Decl(Decl::Fn(FnDecl { function, .. }))) => {
if let Some(ref mut body) = function.body {
body.stmts.extend(stmts);
}
}
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
decl: Decl::Class(ClassDecl { class, .. }),
..
})) => {
for member in class.body.iter_mut().rev() {
if let ClassMember::Method(ClassMethod { function, .. }) = member
&& let Some(ref mut body) = function.body
{
body.stmts.extend(stmts);
return;
}
}
}
ModuleItem::Stmt(Stmt::Decl(Decl::Class(ClassDecl { class, .. }))) => {
for member in class.body.iter_mut().rev() {
if let ClassMember::Method(ClassMethod { function, .. }) = member
&& let Some(ref mut body) = function.body
{
body.stmts.extend(stmts);
return;
}
}
}
_ => {
}
}
}