macroscope_macro/
lib.rs

1use derive_syn_parse::Parse;
2use macroscope_utils::find_macroscope;
3use proc_macro2::Span;
4use quote::quote;
5use syn::{
6    parse::ParseStream, parse_macro_input, punctuated::Punctuated, Ident, LitStr, Path, Token,
7};
8
9#[derive(Debug, Parse)]
10struct UsingArgs {
11    crate_name: CrateName,
12    #[peek(Token![|])]
13    extra: Option<UsingArgsExtra>,
14}
15
16#[derive(Debug, Parse)]
17enum CrateName {
18    #[peek_with(is_lit_str, name = "Literal")]
19    Literal(LitStr),
20    #[peek_with(is_path, name = "Path")]
21    Path(Path),
22}
23
24impl CrateName {
25    fn path(self) -> proc_macro2::TokenStream {
26        match self {
27            CrateName::Literal(literal) => {
28                let id = Ident::new(&normalize(&literal.value()), Span::call_site());
29                quote!(#id)
30            }
31            CrateName::Path(path) => quote!(#path),
32        }
33    }
34}
35
36fn is_lit_str(token: ParseStream) -> bool {
37    token.peek(LitStr)
38}
39
40fn is_path(token: ParseStream) -> bool {
41    token.peek(syn::Token![::]) || token.peek(Ident)
42}
43
44#[derive(Debug, Parse)]
45struct UsingArgsExtra {
46    pipe: Token![|],
47    #[parse_terminated(parse_str)]
48    crates: Punctuated<LitStr, Token![|]>,
49}
50
51fn parse_str(input: ParseStream<'_>) -> syn::parse::Result<LitStr> {
52    input.parse()
53}
54
55#[proc_macro]
56pub fn build_using(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
57    let UsingArgs {
58        crate_name,
59        extra: _,
60    } = parse_macro_input!(input as UsingArgs);
61
62    let macroscope = find_macroscope();
63    let crate_name = crate_name.path();
64
65    // let extra = extra
66    //     .into_iter()
67    //     .flat_map(|UsingArgsExtra { crates, .. }| crates.into_pairs().map(|p| p.into_value()));
68
69    // let found = #macroscope::find_crate(#crate_name, #extra);
70    // let found = #macroscope::quote_crate(found);
71
72    (quote! {
73        macro_rules! using {
74            ($($path:tt)*) => {{
75                #macroscope::quote! { ::#crate_name::macros::crates::$($path)* }
76            }}
77        }
78    })
79    .into()
80
81    // let using_fn = quote! {
82    //     let found = #macroscope::found_crate!($crate_name)
83    //         $(
84    //             .or_else(|_| crate_name($crates))
85    //         )*
86    //         .unwrap_or_else(|err| {
87    //             #macroscope::couldnt_find!(err, $crate_name $($crates)*)
88    //         });
89
90    //     let prefix = #macroscope::found_crate_prefix(found);
91
92    //     proc_macro2::TokenStream::from(quote! { #prefix :: macros :: crates :: #quoted })
93    // };
94}
95
96fn normalize(name: &str) -> String {
97    name.replace("-", "_")
98}