#![cfg_attr(feature = "nightly", feature(proc_macro_span))]
extern crate proc_macro;
mod declare_derive;
mod lerp_derive;
mod util;
use proc_macro::TokenStream;
use quote::quote;
use symbol_process::DollarRefsCtx;
use syn::{parse_macro_input, DeriveInput};
mod child_template;
mod fn_widget_macro;
mod pipe_macro;
mod rdl_macro;
mod simple_declare_attr;
pub(crate) mod variable_names;
mod watch_macro;
pub(crate) use rdl_macro::*;
pub(crate) mod declare_obj;
pub(crate) mod error;
pub(crate) mod symbol_process;
macro_rules! ok {
($e:expr) => {
match $e {
Ok(ok) => ok,
Err(err) => return err.into(),
}
};
}
pub(crate) use ok;
#[proc_macro_derive(SingleChild)]
pub fn single_child_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let name = input.ident;
quote! {
impl #impl_generics SingleChild for #name #ty_generics #where_clause {}
}
.into()
}
#[proc_macro_derive(MultiChild)]
pub fn multi_child_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let name = input.ident;
quote! {
impl #impl_generics MultiChild for #name #ty_generics #where_clause {}
}
.into()
}
#[proc_macro_derive(PairChild)]
pub fn pair_compose_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let name = input.ident;
quote! {
impl #impl_generics PairChild for #name #ty_generics #where_clause {}
}
.into()
}
#[proc_macro_derive(Lerp)]
pub fn lerp_derive(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
lerp_derive::lerp_derive(&mut input)
.unwrap_or_else(|e| e.into_compile_error())
.into()
}
#[proc_macro_derive(Declare, attributes(declare))]
pub fn declare_trait_macro_derive(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
declare_derive::declare_derive(&mut input)
.unwrap_or_else(|e| e.into_compile_error())
.into()
}
#[proc_macro_attribute]
pub fn simple_declare(_attr: TokenStream, item: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(item as syn::ItemStruct);
simple_declare_attr::simple_declarer_attr(&mut input)
.unwrap_or_else(|e| e.into_compile_error())
.into()
}
#[proc_macro_derive(Template, attributes(template))]
pub fn child_template_trait_derive(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
child_template::derive_child_template(&mut input)
.unwrap_or_else(|e| e.into_compile_error())
.into()
}
#[proc_macro]
pub fn rdl(input: TokenStream) -> TokenStream {
let mut refs = DollarRefsCtx::top_level();
refs.new_dollar_scope(false);
RdlMacro::gen_code(input.into(), &mut refs)
}
#[proc_macro]
pub fn fn_widget(input: TokenStream) -> TokenStream {
fn_widget_macro::gen_code(input.into(), &mut DollarRefsCtx::top_level())
}
#[proc_macro]
pub fn ribir_expanded_ಠ_ಠ(input: TokenStream) -> TokenStream { input }
#[proc_macro]
pub fn ctx(input: TokenStream) -> TokenStream {
let tokens = if !input.is_empty() {
quote!(compile_error!("ctx! macro does not accept any argument"))
} else {
quote! { _ctx_ಠ_ಠ }
};
tokens.into()
}
#[proc_macro]
pub fn pipe(input: TokenStream) -> TokenStream {
pipe_macro::gen_code(input.into(), &mut DollarRefsCtx::top_level())
}
#[proc_macro]
pub fn watch(input: TokenStream) -> TokenStream {
watch_macro::gen_code(input.into(), &mut DollarRefsCtx::top_level())
}
#[proc_macro]
pub fn include_crate_svg(input: TokenStream) -> TokenStream {
let file = parse_macro_input! { input as syn::LitStr };
let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let path = std::path::Path::new(&dir).join(file.value());
include_svg_from_path(path)
}
#[cfg(feature = "nightly")]
#[proc_macro]
pub fn include_svg(input: TokenStream) -> TokenStream {
let rf = parse_macro_input! { input as syn::LitStr };
let mut span = proc_macro::Span::call_site();
while let Some(p) = span.parent() {
span = p;
}
let mut file = span.source_file().path();
file.pop();
file.push(rf.value());
include_svg_from_path(file)
}
fn include_svg_from_path(path: std::path::PathBuf) -> TokenStream {
let encoded_bytes =
ribir_painter::Svg::open(path.as_path()).and_then(|reader| reader.serialize());
match encoded_bytes {
Ok(data) => quote! {
Svg::deserialize(#data).unwrap()
}
.into(),
Err(err) => {
let err = format!("{err}({:?})", &path);
quote! { compile_error!(#err) }.into()
}
}
}