use proc_macro::TokenStream;
use quote::ToTokens;
use syn::{Block, ExprBlock};
use self::{
ctxt::{Ctx, prepare_vars},
input::QuoteInput,
};
#[cfg(feature = "oxc")]
use self::oxc_ret_type::parse_input_type;
#[cfg(all(feature = "swc", not(feature = "oxc")))]
use self::swc_ret_type::parse_input_type;
#[cfg(all(feature = "swc", not(feature = "oxc")))]
mod swc_ast;
#[cfg(all(feature = "swc", not(feature = "oxc")))]
mod swc_builder;
#[cfg(all(feature = "swc", not(feature = "oxc")))]
mod swc_ret_type;
#[cfg(feature = "oxc")]
mod oxc_ret_type;
#[cfg(feature = "compiler")]
mod compiler;
mod ctxt;
mod input;
mod template;
#[cfg(test)]
mod test;
#[proc_macro]
pub fn ts_quote(input: TokenStream) -> TokenStream {
#[cfg(feature = "oxc")]
{
match ts_quote_impl(input.into()) {
Ok(tokens) => tokens.into(),
Err(err) => err.to_compile_error().into(),
}
}
#[cfg(all(not(feature = "oxc"), feature = "swc"))]
{
match ts_quote_impl(input.into()) {
Ok(tokens) => tokens.into(),
Err(err) => err.to_compile_error().into(),
}
}
#[cfg(all(not(feature = "swc"), not(feature = "oxc")))]
{
syn::Error::new(
proc_macro2::Span::call_site(),
"Either 'swc' or 'oxc' feature must be enabled for macroforge_ts_quote",
)
.to_compile_error()
.into()
}
}
pub(crate) trait ToCode {
fn to_code(&self, cx: &Ctx) -> syn::Expr;
}
#[cfg(any(feature = "swc", feature = "oxc"))]
fn ts_quote_impl(input: proc_macro2::TokenStream) -> syn::Result<proc_macro2::TokenStream> {
use std::iter::once;
let QuoteInput {
src,
as_token: _,
output_type,
vars,
} = syn::parse2::<QuoteInput>(input)?;
let ret_type = parse_input_type(&src.value(), &output_type).map_err(|err| {
syn::Error::new_spanned(&src, format!("failed to parse TypeScript: {err}"))
})?;
let vars = vars.map(|v| v.1);
let (stmts, vars) = if let Some(vars) = vars {
prepare_vars(&ret_type, vars)?
} else {
Default::default()
};
let cx = Ctx { vars };
let expr_for_ast_creation = ret_type.to_code(&cx);
Ok(syn::Expr::Block(ExprBlock {
attrs: Default::default(),
label: Default::default(),
block: Block {
brace_token: Default::default(),
stmts: stmts
.into_iter()
.chain(once(syn::Stmt::Expr(expr_for_ast_creation, None)))
.collect(),
},
})
.to_token_stream())
}
#[proc_macro]
pub fn ts_template(input: TokenStream) -> TokenStream {
#[cfg(feature = "compiler")]
{
match compiler::compile_template_tokens(input.into()) {
Ok(tokens) => tokens.into(),
Err(err) => err.to_compile_error().into(),
}
}
#[cfg(not(feature = "compiler"))]
{
match template::compile_template(input.into()) {
Ok(tokens) => tokens.into(),
Err(err) => err.to_compile_error().into(),
}
}
}