bon_macros/builder/builder_gen/input_fn/
validation.rs1use crate::util::prelude::*;
2use syn::visit::Visit;
3
4impl super::FnInputCtx<'_> {
5 pub(super) fn validate(&self) -> Result {
6 if self.impl_ctx.is_none() {
7 let explanation = "\
8 which likely means the builder attribute was used inside of an \
9 impl block; the impl block needs to be annotated with the #[bon] \
10 attribute and the builder attribute must be spelled as #[builder] \
11 without any additional path prefix, since it's used as a simple \
12 inert config attribute for #[bon] in impl blocks; more info on \
13 inert vs active attributes: \
14 https://doc.rust-lang.org/reference/attributes.html#active-and-inert-attributes";
15
16 if let Some(receiver) = &self.fn_item.orig.sig.receiver() {
17 bail!(
18 &receiver.self_token,
19 "this function contains a `self` parameter {explanation}"
20 );
21 }
22
23 let mut ctx = FindSelfReference::default();
24 ctx.visit_item_fn(&self.fn_item.orig);
25 if let Some(self_span) = ctx.self_span {
26 bail!(
27 &self_span,
28 "this function contains a `Self` type reference {explanation}"
29 );
30 }
31 }
32
33 if let Some(const_) = &self.config.const_ {
34 if self.fn_item.orig.sig.constness.is_none() {
35 bail!(
36 &const_,
37 "#[builder(const)] requires the underlying function to be \
38 marked as `const fn`"
39 );
40 }
41 }
42
43 Ok(())
44 }
45
46 pub(crate) fn warnings(&self) -> TokenStream {
47 let _ = self;
52
53 TokenStream::new()
54 }
55}
56
57#[derive(Default)]
58struct FindSelfReference {
59 self_span: Option<Span>,
60}
61
62impl Visit<'_> for FindSelfReference {
63 fn visit_item(&mut self, _: &syn::Item) {
64 }
67
68 fn visit_path(&mut self, path: &syn::Path) {
69 if self.self_span.is_some() {
70 return;
71 }
72 syn::visit::visit_path(self, path);
73
74 let first_segment = match path.segments.first() {
75 Some(first_segment) => first_segment,
76 _ => return,
77 };
78
79 if first_segment.ident == "Self" {
80 self.self_span = Some(first_segment.ident.span());
81 }
82 }
83}