Skip to main content

sabry_procmacro_impl/impls/
usey.rs

1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::{parse::Parse, punctuated::Punctuated, Macro, Token};
4
5/// Syntax:
6/// `#(pub? #macro,)*`
7pub fn usey_macro_impl(input: TokenStream) -> TokenStream {
8    let MacroSyntax { stylecalls } = match syn::parse2(input) {
9        Ok(ms) => ms,
10        Err(e) => return e.to_compile_error(),
11    };
12
13    let stylecall_pairs = stylecalls
14        .iter()
15        .map(|c| c.to_contract_pair("__sabry_pub_module"));
16
17    quote! {
18        vec![
19            #(#stylecall_pairs,)*
20        ]
21    }
22}
23
24#[derive(Clone)]
25pub struct StyleCall {
26    vis_pub: bool,
27    call: Macro,
28}
29
30impl StyleCall {
31    pub fn to_contract_pair(&self, pub_module: &str) -> TokenStream {
32        let call_code = &self.call;
33        let call_path = &self.call.path;
34        let call_bang = &self.call.bang_token;
35        // the following calls are expected by macro genereted by `scssy!`
36        let call_syntax = quote! {#call_path #call_bang (syntax)};
37
38        let module_name = call_path
39            .segments
40            .last()
41            .map(|l| l.ident.to_string())
42            .expect("BUG: failed to get identifier for macro call");
43
44        if self.vis_pub {
45            quote! {
46                (format!("{}.{}", #pub_module, #call_syntax), #call_code .to_string())
47            }
48        } else {
49            quote! {
50                (format!("{}.{}", #module_name, #call_syntax), #call_code .to_string())
51            }
52        }
53    }
54}
55
56impl Parse for StyleCall {
57    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
58        let vis_pub = input.parse::<Token![pub]>().is_ok();
59        let call = input.parse::<Macro>()?;
60
61        Ok(Self { vis_pub, call })
62    }
63}
64
65pub struct MacroSyntax {
66    stylecalls: Vec<StyleCall>,
67}
68
69impl Parse for MacroSyntax {
70    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
71        let calls = Punctuated::<StyleCall, Token![,]>::parse_separated_nonempty(input)?;
72
73        let stylecalls = calls.iter().cloned().collect();
74        Ok(Self { stylecalls })
75    }
76}