bon_macros/parsing/
bon_crate_path.rs

1use crate::util::prelude::*;
2use darling::FromMeta;
3
4#[derive(Debug, Clone)]
5pub(crate) enum BonCratePath {
6    Default,
7    Explicit(syn::Path),
8}
9
10impl Default for BonCratePath {
11    fn default() -> Self {
12        Self::Default
13    }
14}
15
16impl FromMeta for BonCratePath {
17    fn from_meta(meta: &syn::Meta) -> Result<Self> {
18        let path = super::parse_path_mod_style(meta)?;
19
20        let prefix = &path
21            .segments
22            .first()
23            .ok_or_else(|| err!(&path, "path must have at least one segment"))?
24            .ident;
25
26        let is_absolute = path.leading_colon.is_some() || prefix == "crate" || prefix == "$crate";
27
28        if is_absolute {
29            return Ok(Self::Explicit(path));
30        }
31
32        if prefix == "super" || prefix == "self" {
33            bail!(
34                &path,
35                "path must not be relative; specify the path that starts with `crate::` \
36                instead; if you want to refer to a reexport from an external crate then \
37                use leading colons like `::crate_name::reexport::path::bon`"
38            )
39        }
40
41        let path_str = darling::util::path_to_string(&path);
42
43        bail!(
44            &path,
45            "path must be absolute; if you want to refer to a reexport from an external \
46            crate then add leading colons like `::{path_str}`; if the path leads to a module \
47            in the current crate, then specify the absolute path with `crate` like \
48            `crate::reexport::path::bon` or `$crate::reexport::path::bon` (if within a macro)"
49        );
50    }
51}
52
53impl ToTokens for BonCratePath {
54    fn to_tokens(&self, tokens: &mut TokenStream) {
55        match self {
56            Self::Default => tokens.extend(quote!(::bon)),
57            Self::Explicit(path) => path.to_tokens(tokens),
58        }
59    }
60}