seaography_derive/
lib.rs

1use quote::ToTokens;
2use syn::DeriveInput;
3
4mod enumeration;
5mod error;
6mod filter;
7mod relation;
8mod root_query;
9
10#[proc_macro_derive(Filter, attributes(sea_orm))]
11pub fn derive_filter_fn(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
12    let DeriveInput {
13        ident, data, attrs, ..
14    } = syn::parse_macro_input!(input as syn::DeriveInput);
15
16    let item = match data {
17        syn::Data::Struct(item) => item,
18        _ => {
19            return quote::quote! {
20                compile_error!("Input not structure")
21            }
22            .into()
23        }
24    };
25
26    if ident.ne("Model") {
27        return quote::quote! {
28            compile_error!("Struct must be SeaOrm Model structure")
29        }
30        .into();
31    }
32
33    let attrs = filter::SeaOrm::from_attributes(&attrs).unwrap();
34
35    filter::filter_fn(item, attrs)
36        .unwrap_or_else(|err| {
37            let error = format!("{:?}", err);
38
39            quote::quote! {
40                compile_error!(#error)
41            }
42        })
43        .into()
44}
45
46// TODO use attrs to skip relations
47#[proc_macro_derive(RelationsCompact, attributes(sea_orm))]
48pub fn derive_relations_compact_fn(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
49    let DeriveInput { ident, data, .. } = syn::parse_macro_input!(input as syn::DeriveInput);
50
51    let item = match data {
52        syn::Data::Enum(item) => item,
53        _ => return quote::quote! { compile_error!("Input not enumeration") }.into(),
54    };
55
56    if ident.ne("Relation") {
57        return quote::quote! {
58            compile_error!("Struct must be SeaOrm Relation enumeration")
59        }
60        .into();
61    }
62
63    let res = relation::compact_relation_fn(&item).unwrap_or_else(|err| {
64        let error = format!("{:?}", err);
65
66        quote::quote! {
67            compile_error!(#error)
68        }
69    });
70
71    res.into()
72}
73
74#[proc_macro_attribute]
75pub fn relation(
76    _attrs: proc_macro::TokenStream,
77    input: proc_macro::TokenStream,
78) -> proc_macro::TokenStream {
79    let implementation = syn::parse_macro_input!(input as syn::Item);
80
81    if !implementation
82        .to_token_stream()
83        .to_string()
84        .starts_with("impl RelationTrait")
85    {
86        return quote::quote! {
87            compile_error!("Macro should be applied on the implementation of RelationTrait trait")
88        }
89        .into();
90    }
91
92    let item = match implementation {
93        syn::Item::Impl(implementation) => implementation,
94        _ => return quote::quote! {
95            compile_error!("Macro should be applied on the implementation of RelationTrait trait")
96        }
97        .into(),
98    };
99
100    let res = relation::expanded_relation_fn(&item).unwrap_or_else(|err| {
101        let error = format!("{:?}", err);
102
103        quote::quote! {
104            compile_error!(#error)
105        }
106    });
107
108    res.into()
109}
110
111#[proc_macro_derive(QueryRoot, attributes(seaography))]
112pub fn derive_root_query_fn(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
113    let DeriveInput {
114        ident, data, attrs, ..
115    } = syn::parse_macro_input!(input as syn::DeriveInput);
116
117    match data {
118        syn::Data::Struct(_) => (),
119        _ => return quote::quote! { compile_error!("Input not structure") }.into(),
120    };
121
122    let attrs: Vec<root_query::Seaography> = attrs
123        .into_iter()
124        .map(|attribute| root_query::Seaography::from_attributes(&[attribute]).unwrap())
125        .collect();
126
127    let res = root_query::root_query_fn(&ident, &attrs).unwrap_or_else(|err| {
128        let error = format!("{:?}", err);
129
130        quote::quote! {
131            compile_error!(#error)
132        }
133    });
134
135    res.into()
136}
137
138#[proc_macro_derive(EnumFilter, attributes())]
139pub fn derive_enum_filter_fn(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
140    let DeriveInput { ident, data, .. } = syn::parse_macro_input!(input as syn::DeriveInput);
141
142    let _ = match data {
143        syn::Data::Enum(enumeration) => enumeration,
144        _ => return quote::quote! { compile_error!("Input not enumeration") }.into(),
145    };
146
147    enumeration::enum_filter_fn(ident).into()
148}