#![warn(missing_docs)]
mod build;
mod entry;
mod example;
mod font;
mod rebuild;
fn found_crate(krate: proc_macro_crate::FoundCrate, name: &str) -> syn::Path {
match krate {
proc_macro_crate::FoundCrate::Itself => {
let ident = proc_macro2::Ident::new(name, proc_macro2::Span::call_site());
syn::parse_quote!(::#ident)
}
proc_macro_crate::FoundCrate::Name(ref name) => {
let ident = proc_macro2::Ident::new(name, proc_macro2::Span::call_site());
syn::parse_quote!(::#ident)
}
}
}
fn find_core() -> syn::Path {
match proc_macro_crate::crate_name("ori-core") {
Ok(krate) => found_crate(krate, "ori_core"),
Err(_) => match proc_macro_crate::crate_name("ori") {
Ok(krate) => {
let ori = found_crate(krate, "ori");
syn::parse_quote!(#ori::core)
}
Err(_) => syn::parse_quote!(ori::core),
},
}
}
fn find_shell() -> syn::Path {
match proc_macro_crate::crate_name("ori-shell") {
Ok(krate) => found_crate(krate, "ori_shell"),
Err(_) => match proc_macro_crate::crate_name("ori") {
Ok(krate) => {
let ori = found_crate(krate, "ori");
syn::parse_quote!(#ori::shell)
}
Err(_) => syn::parse_quote!(ori::shell),
},
}
}
fn get_option_type(ty: &syn::Type) -> Option<&syn::Type> {
const ALLOWED: &[&str] = &[
"Option",
"option::Option",
"std::option::Option",
"core::option::Option",
];
let path = match ty {
syn::Type::Path(path) => path,
_ => return None,
};
let segments = &path.path.segments;
let mut path_allowed = false;
'outer: for allowed in ALLOWED {
let allowed = allowed.split("::").collect::<Vec<_>>();
if segments.len() != allowed.len() {
continue;
}
for (segment, allowed) in segments.iter().zip(&allowed) {
if segment.ident != allowed {
continue 'outer;
}
}
path_allowed = true;
}
if !path_allowed {
return None;
}
let args = &segments.last()?.arguments;
if let syn::PathArguments::AngleBracketed(args) = args {
let args = &args.args;
if args.len() != 1 {
return None;
}
if let syn::GenericArgument::Type(ty) = args.first()? {
return Some(ty);
}
}
None
}
#[doc(hidden)]
#[proc_macro]
pub fn lowercase_ident(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = proc_macro2::TokenStream::from(input);
let ident = syn::parse2::<syn::Ident>(input).unwrap();
let ident = ident.to_string().to_lowercase();
quote::quote!(#ident).into()
}
#[manyhow::manyhow]
#[proc_macro]
pub fn include_font(input: proc_macro::TokenStream) -> manyhow::Result<proc_macro::TokenStream> {
font::include_font(input)
}
#[manyhow::manyhow]
#[proc_macro_derive(Rebuild, attributes(style, rebuild))]
pub fn derive_rebuild(input: proc_macro::TokenStream) -> manyhow::Result<proc_macro::TokenStream> {
rebuild::derive_rebuild(input)
}
#[manyhow::manyhow]
#[proc_macro_derive(Build, attributes(build))]
pub fn derive_build(input: proc_macro::TokenStream) -> manyhow::Result<proc_macro::TokenStream> {
build::derive_build(input)
}
#[proc_macro_attribute]
pub fn desktop(
_args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let input = proc_macro2::TokenStream::from(input);
let expanded = quote::quote! {
#[cfg(any(
target_os = "windows",
target_os = "macos",
target_os = "linux",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "openbsd",
target_os = "netbsd",
))]
#input
};
expanded.into()
}
#[proc_macro_attribute]
pub fn mobile(
_args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let input = proc_macro2::TokenStream::from(input);
let expanded = quote::quote! {
#[cfg(any(
target_os = "android",
target_os = "ios",
))]
#input
};
expanded.into()
}
#[proc_macro_attribute]
pub fn web(
_args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let input = proc_macro2::TokenStream::from(input);
let expanded = quote::quote! {
#[cfg(target_arch = "wasm32")]
#input
};
expanded.into()
}
#[proc_macro]
pub fn is_desktop(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let expanded = quote::quote! {
::std::cfg!(any(
target_os = "windows",
target_os = "macos",
target_os = "linux",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "openbsd",
target_os = "netbsd",
))
};
expanded.into()
}
#[proc_macro]
pub fn is_mobile(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let expanded = quote::quote! {
::std::cfg!(any(
target_os = "android",
target_os = "ios",
))
};
expanded.into()
}
#[proc_macro]
pub fn is_web(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let expanded = quote::quote! {
::std::cfg!(target_arch = "wasm32")
};
expanded.into()
}
#[manyhow::manyhow]
#[proc_macro_attribute]
pub fn example(
args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> manyhow::Result<proc_macro::TokenStream> {
example::example(args, input)
}
#[manyhow::manyhow]
#[proc_macro_attribute]
pub fn main(
args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> manyhow::Result<proc_macro::TokenStream> {
entry::main(args, input)
}