masterror_derive/
lib.rs

1// SPDX-FileCopyrightText: 2025 RAprogramm <andrey.rozanov.vl@gmail.com>
2//
3// SPDX-License-Identifier: MIT
4
5//! Derive macro for `masterror::Error`.
6//!
7//! This crate is not intended to be used directly. Re-exported as
8//! `masterror::Error`.
9
10mod app_error_impl;
11mod display;
12mod error_trait;
13mod from_impl;
14mod input;
15mod lint;
16mod masterror_impl;
17mod span;
18mod template_support;
19
20use proc_macro::TokenStream;
21use quote::quote;
22use syn::{DeriveInput, Error, parse_macro_input};
23
24#[proc_macro_derive(Error, attributes(error, source, from, backtrace, app_error, provide))]
25pub fn derive_error(tokens: TokenStream) -> TokenStream {
26    let input = parse_macro_input!(tokens as DeriveInput);
27    match expand(input) {
28        Ok(stream) => stream.into(),
29        Err(err) => err.to_compile_error().into()
30    }
31}
32
33#[proc_macro_derive(
34    Masterror,
35    attributes(error, source, from, backtrace, masterror, provide)
36)]
37pub fn derive_masterror(tokens: TokenStream) -> TokenStream {
38    let input = parse_macro_input!(tokens as DeriveInput);
39    match expand_masterror(input) {
40        Ok(stream) => stream.into(),
41        Err(err) => err.to_compile_error().into()
42    }
43}
44
45fn expand(input: DeriveInput) -> Result<proc_macro2::TokenStream, Error> {
46    let parsed = input::parse_input(input)?;
47    let display_impl = display::expand(&parsed)?;
48    let error_impl = error_trait::expand(&parsed)?;
49    let from_impls = from_impl::expand(&parsed)?;
50    let app_error_impls = app_error_impl::expand(&parsed)?;
51    Ok(quote! {
52        #display_impl
53        #error_impl
54        #(#from_impls)*
55        #(#app_error_impls)*
56    })
57}
58
59fn expand_masterror(input: DeriveInput) -> Result<proc_macro2::TokenStream, Error> {
60    let parsed = input::parse_input(input)?;
61    let display_impl = display::expand(&parsed)?;
62    let error_impl = error_trait::expand(&parsed)?;
63    let from_impls = from_impl::expand(&parsed)?;
64    let masterror_impl = masterror_impl::expand(&parsed)?;
65    Ok(quote! {
66        #display_impl
67        #error_impl
68        #(#from_impls)*
69        #masterror_impl
70    })
71}