1mod attributes;
2mod generate;
3mod helpers;
4mod utils;
5
6use attributes::{ATTRIBUTE_MODULE_PREFIX, ATTRIBUTE_PATH, ATTRIBUTE_REMOTE_TYPE};
7use proc_macro2::TokenStream;
8use syn::{parse_macro_input, parse_quote, DeriveInput, Expr, Path};
9
10#[proc_macro_derive(IntoPath, attributes(into_path))]
11pub fn derive_into_path(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
12 let input = parse_macro_input!(input as DeriveInput);
13 let mut prefix = None;
14 const INTO_PATH: &str = "into_path";
15 const PREFIX: &str = "prefix";
16 input.attrs.iter().for_each(|attr| {
17 if attr.path().is_ident(INTO_PATH) {
18 if let Ok(syn::ExprAssign { left, right, .. }) = attr.parse_args() {
19 if let (Expr::Path(left), Expr::Path(right)) = (&*left, &*right) {
20 if left.path.is_ident(PREFIX) {
21 prefix = Some(right.path.clone());
22 }
23 }
24 }
25 }
26 });
27 match helpers::into_path(
28 input,
29 prefix.unwrap_or_else(|| parse_quote!(::x_bow::__private_macro_only)),
30 ) {
31 Ok(r) => r,
32 Err(e) => e.to_compile_error(),
33 }
34 .into()
35}
36
37#[proc_macro_derive(Trackable, attributes(x_bow, track))]
38pub fn derive_trackable(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
39 let input = parse_macro_input!(input as DeriveInput);
40 match derive(input) {
41 Ok(r) => r,
42 Err(e) => e.to_compile_error(),
43 }
44 .into()
45}
46fn derive(ast: DeriveInput) -> syn::Result<TokenStream> {
47 let mut remote_path = None;
48 let mut prefix_path = None;
49 ast.attrs.iter().for_each(|attr| {
50 if attr.path().is_ident(ATTRIBUTE_PATH) {
51 if let Ok(syn::ExprAssign { left, right, .. }) = attr.parse_args() {
52 if let (Expr::Path(left), Expr::Path(right)) = (&*left, &*right) {
53 if left.path.is_ident(ATTRIBUTE_MODULE_PREFIX) {
54 prefix_path = Some(right.path.clone());
55 }
56 if left.path.is_ident(ATTRIBUTE_REMOTE_TYPE) {
57 remote_path = Some(right.path.clone());
58 }
59 }
60 }
61 }
62 });
63 let remote_path = remote_path.unwrap_or_else(|| Path::from(ast.ident.clone()));
64 let prefix_path = prefix_path.unwrap_or_else(|| parse_quote!(::x_bow::__private_macro_only));
65 generate::generate(&ast, &remote_path, &prefix_path)
66}