use darling::FromDeriveInput;
use syn::parse_macro_input;
use crate::attrs::{ContainerAttrs, extract_container_attr_spans};
use crate::config::MacroConfig;
use crate::context::MacroContext;
mod attrs;
mod build_schema;
pub(crate) mod codegen_ir_adapter;
pub(crate) mod config;
pub(crate) mod context;
mod emit_ir_common;
mod from_eure;
mod into_eure;
mod ir;
mod ir_spans;
mod must_be_text;
mod object_key;
#[proc_macro_derive(IntoEure, attributes(eure))]
pub fn into_eure_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as syn::DeriveInput);
match create_context(input) {
Ok(context) => into_eure::derive(context).into(),
Err(err) => err.to_compile_error().into(),
}
}
#[proc_macro_derive(FromEure, attributes(eure))]
pub fn from_eure_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as syn::DeriveInput);
match create_context(input) {
Ok(context) => from_eure::derive(context).into(),
Err(err) => err.to_compile_error().into(),
}
}
#[proc_macro_derive(ObjectKey, attributes(eure))]
pub fn object_key_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as syn::DeriveInput);
match create_context(input) {
Ok(context) => object_key::derive(context).into(),
Err(err) => err.to_compile_error().into(),
}
}
#[proc_macro_derive(BuildSchema, attributes(eure))]
pub fn build_schema_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as syn::DeriveInput);
match create_context(input) {
Ok(context) => build_schema::derive(context).into(),
Err(err) => err.to_compile_error().into(),
}
}
fn create_context(input: syn::DeriveInput) -> syn::Result<MacroContext> {
let attrs = ContainerAttrs::from_derive_input(&input).expect("Failed to parse eure attributes");
let attr_spans = extract_container_attr_spans(&input);
let mut config = MacroConfig::from_attrs(attrs, attr_spans)?;
if has_non_exhaustive_attr(&input.attrs) {
config.non_exhaustive = true;
}
Ok(MacroContext::new(config, input))
}
fn has_non_exhaustive_attr(attrs: &[syn::Attribute]) -> bool {
attrs
.iter()
.any(|attr| attr.path().is_ident("non_exhaustive"))
}
#[proc_macro]
#[allow(non_snake_case)]
pub fn MustBeText(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as must_be_text::MustBeTextInput);
must_be_text::expand(input).into()
}