bon_macros/parsing/
docs.rs1use super::SpannedKey;
2use crate::util::prelude::*;
3
4pub(crate) fn parse_docs_without_self_mentions(
5 context: &'static str,
6 meta: &syn::Meta,
7) -> Result<SpannedKey<Vec<syn::Attribute>>> {
8 let docs = parse_docs(meta)?;
9 reject_self_mentions_in_docs(context, &docs)?;
10 Ok(docs)
11}
12
13pub(crate) fn parse_docs(meta: &syn::Meta) -> Result<SpannedKey<Vec<syn::Attribute>>> {
14 let meta = meta.require_list()?;
15
16 meta.require_curly_braces_delim()?;
17
18 let attrs = meta.parse_args_with(syn::Attribute::parse_outer)?;
19
20 for attr in &attrs {
21 if !attr.is_doc_expr() {
22 bail!(attr, "expected a doc comment");
23 }
24 }
25
26 SpannedKey::new(&meta.path, attrs)
27}
28
29pub(crate) fn reject_self_mentions_in_docs(
34 context: &'static str,
35 attrs: &[syn::Attribute],
36) -> Result {
37 for attr in attrs {
38 let doc = match attr.as_doc_expr() {
39 Some(doc) => doc,
40 _ => continue,
41 };
42
43 let doc = match &doc {
44 syn::Expr::Lit(doc) => doc,
45 _ => continue,
46 };
47
48 let doc = match &doc.lit {
49 syn::Lit::Str(doc) => doc,
50 _ => continue,
51 };
52
53 let self_references = ["[`Self`]", "[Self]"];
54
55 if self_references
56 .iter()
57 .any(|self_ref| doc.value().contains(self_ref))
58 {
59 bail!(
60 &doc.span(),
61 "the documentation should not reference `Self` because it will \
62 be moved to the {context} where `Self` changes meaning, which \
63 may confuse the reader of this code; use explicit type names instead.",
64 );
65 }
66 }
67
68 Ok(())
69}