bon_macros/parsing/
bon_crate_path.rs1use 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}