1use super::member::Member;
2use super::top_level_config::{DerivesConfig, OnConfig};
3use crate::normalization::GenericsNamespace;
4use crate::parsing::{ItemSigConfig, SpannedKey};
5use crate::util::prelude::*;
6use std::borrow::Cow;
78pub(super) trait FinishFnBody {
9/// Generate the `finish` function body from the ready-made variables.
10 /// The generated function body may assume that there are variables
11 /// named the same as the members in scope.
12fn generate(&self, ctx: &BuilderGenCtx) -> TokenStream;
13}
1415pub(super) struct AssocMethodReceiverCtx {
16pub(super) with_self_keyword: syn::Receiver,
17pub(super) without_self_keyword: Box<syn::Type>,
18}
1920pub(super) struct AssocMethodCtx {
21/// The `Self` type of the impl block. It doesn't contain any nested
22 /// `Self` keywords in it. This is prohibited by Rust's syntax itself.
23pub(super) self_ty: Box<syn::Type>,
2425/// Present only if the method has a receiver, i.e. `self` or `&self` or
26 /// `&mut self` or `self: ExplicitType`.
27pub(super) receiver: Option<AssocMethodReceiverCtx>,
28}
2930pub(super) struct FinishFn {
31pub(super) ident: syn::Ident,
3233/// Visibility override specified by the user
34pub(super) vis: syn::Visibility,
3536/// Additional attributes to apply to the item
37pub(super) attrs: Vec<syn::Attribute>,
3839pub(super) unsafety: Option<syn::Token![unsafe]>,
40pub(super) asyncness: Option<syn::Token![async]>,
41/// <https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute>
42pub(super) must_use: Option<syn::Attribute>,
43pub(super) body: Box<dyn FinishFnBody>,
44pub(super) output: syn::ReturnType,
45}
4647pub(super) struct FinishFnParams {
48pub(super) ident: syn::Ident,
4950/// Visibility override specified by the user
51pub(super) vis: Option<syn::Visibility>,
5253pub(super) attrs: Vec<syn::Attribute>,
54pub(super) unsafety: Option<syn::Token![unsafe]>,
55pub(super) asyncness: Option<syn::Token![async]>,
56pub(super) must_use: Option<syn::Attribute>,
57pub(super) body: Box<dyn FinishFnBody>,
58pub(super) output: syn::ReturnType,
59}
6061pub(super) struct StartFn {
62pub(super) ident: syn::Ident,
63pub(super) vis: syn::Visibility,
6465pub(super) docs: Vec<syn::Attribute>,
6667/// Overrides the default generics
68pub(super) generics: Option<Generics>,
69}
7071pub(super) struct StartFnParams {
72pub(super) ident: syn::Ident,
7374/// If present overrides the default visibility derived from the builder's type.
75pub(super) vis: Option<syn::Visibility>,
7677pub(super) docs: Vec<syn::Attribute>,
7879/// Overrides the default generics
80pub(super) generics: Option<Generics>,
81}
8283pub(super) struct BuilderType {
84pub(super) ident: syn::Ident,
8586/// Visibility of the builder module itself.
87pub(super) vis: syn::Visibility,
8889pub(super) derives: DerivesConfig,
90pub(super) docs: Vec<syn::Attribute>,
91}
9293pub(super) struct BuilderTypeParams {
94pub(super) ident: syn::Ident,
95pub(super) vis: Option<syn::Visibility>,
96pub(super) derives: DerivesConfig,
97pub(super) docs: Option<Vec<syn::Attribute>>,
98}
99100pub(super) struct StateMod {
101pub(super) ident: syn::Ident,
102103/// Visibility of the builder module itself.
104pub(super) vis: syn::Visibility,
105106/// Visibility equivalent to the [`Self::vis`], but for items
107 /// generated inside the builder child module.
108pub(super) vis_child: syn::Visibility,
109110/// Visibility equivalent to the [`Self::vis_child`], but for items
111 /// generated inside one more level of nesting in the builder child module.
112pub(super) vis_child_child: syn::Visibility,
113114pub(super) docs: Vec<syn::Attribute>,
115}
116117pub(super) struct Generics {
118pub(super) where_clause: Option<syn::WhereClause>,
119120/// Original generics that may contain default values in them. This is only
121 /// suitable for use in places where default values for generic parameters
122 /// are allowed.
123pub(super) decl_with_defaults: Vec<syn::GenericParam>,
124125/// Generic parameters without default values in them. This is suitable for
126 /// use as generics in function signatures or impl blocks.
127pub(super) decl_without_defaults: Vec<syn::GenericParam>,
128129/// Mirrors the `decl` representing how generic params should be represented
130 /// when these parameters are passed through as arguments in a turbofish.
131pub(super) args: Vec<syn::GenericArgument>,
132}
133134pub(crate) struct BuilderGenCtx {
135/// Path to the `bon` crate.
136pub(super) bon: syn::Path,
137138/// Name of the generic variable that holds the builder's state.
139pub(super) state_var: syn::Ident,
140141pub(super) members: Vec<Member>,
142143/// Lint suppressions from the original item that will be inherited by all items
144 /// generated by the macro. If the original syntax used `#[expect(...)]`,
145 /// then it must be represented as `#[allow(...)]` here.
146pub(super) allow_attrs: Vec<syn::Attribute>,
147pub(super) on: Vec<OnConfig>,
148149pub(super) generics: Generics,
150151pub(super) assoc_method_ctx: Option<AssocMethodCtx>,
152153pub(super) builder_type: BuilderType,
154pub(super) state_mod: StateMod,
155pub(super) start_fn: StartFn,
156pub(super) finish_fn: FinishFn,
157}
158159pub(super) struct BuilderGenCtxParams<'a> {
160pub(crate) bon: Option<syn::Path>,
161pub(super) namespace: Cow<'a, GenericsNamespace>,
162pub(super) members: Vec<Member>,
163164pub(super) allow_attrs: Vec<syn::Attribute>,
165pub(super) on: Vec<OnConfig>,
166167/// This is the visibility of the original item that the builder is generated for.
168 /// For example, the `struct` or `fn` item visibility that the `#[builder]` or
169 /// `#[derive(Builder)]` attribute is applied to.
170 ///
171 /// It is used as the default visibility for all the generated items unless
172 /// explicitly overridden at a more specific level.
173pub(super) orig_item_vis: syn::Visibility,
174175/// Generics to apply to the builder type.
176pub(super) generics: Generics,
177178pub(super) assoc_method_ctx: Option<AssocMethodCtx>,
179180pub(super) builder_type: BuilderTypeParams,
181pub(super) state_mod: ItemSigConfig,
182pub(super) start_fn: StartFnParams,
183pub(super) finish_fn: FinishFnParams,
184}
185186impl BuilderGenCtx {
187pub(super) fn new(params: BuilderGenCtxParams<'_>) -> Result<Self> {
188let BuilderGenCtxParams {
189 bon,
190 namespace,
191 members,
192 allow_attrs,
193 on,
194 generics,
195 orig_item_vis,
196 assoc_method_ctx,
197 builder_type,
198 state_mod,
199 start_fn,
200 finish_fn,
201 } = params;
202203let builder_type = BuilderType {
204 ident: builder_type.ident,
205 vis: builder_type.vis.unwrap_or(orig_item_vis),
206 derives: builder_type.derives,
207 docs: builder_type.docs.unwrap_or_else(|| {
208let doc = format!(
209"Use builder syntax to set the inputs and finish with [`{0}()`](Self::{0}()).",
210 finish_fn.ident
211 );
212213vec![syn::parse_quote! {
214#[doc = #doc]
215}]
216 }),
217 };
218219let state_mod = {
220let is_ident_overridden = state_mod.name.is_some();
221let ident = state_mod
222 .name
223 .map(SpannedKey::into_value)
224 .unwrap_or_else(|| builder_type.ident.pascal_to_snake_case());
225226if builder_type.ident == ident {
227if is_ident_overridden {
228bail!(
229&ident,
230"the builder module name must be different from the builder type name"
231)
232 }
233234bail!(
235&builder_type.ident,
236"couldn't infer the builder module name that doesn't conflict with \
237 the builder type name; by default, the builder module name is set \
238 to a snake_case equivalent of the builder type name; the snake_case \
239 conversion doesn't produce a different name for this builder type \
240 name; consider using PascalCase for the builder type name or specify \
241 a separate name for the builder module explicitly via \
242 `#[builder(state_mod = {{new_name}})]`"
243);
244 }
245246// The builder module is private by default, meaning all symbols under
247 // that module can't be accessed from outside the module where the builder
248 // is defined. This makes the builder type signature unnamable from outside
249 // the module where we output the builder. The users need to explicitly
250 // opt-in to make the builder module public.
251let vis = state_mod
252 .vis
253 .map(SpannedKey::into_value)
254 .unwrap_or_else(|| syn::Visibility::Inherited);
255256// The visibility for child items is based on the visibility of the
257 // builder type itself, because the types and traits from this module
258 // are part of the builder's generic type state parameter signature.
259let vis_child = builder_type.vis.clone().into_equivalent_in_child_module()?;
260let vis_child_child = vis_child.clone().into_equivalent_in_child_module()?;
261262 StateMod {
263 vis,
264 vis_child,
265 vis_child_child,
266267 ident,
268269 docs: state_mod
270 .docs
271 .map(SpannedKey::into_value)
272 .unwrap_or_else(|| {
273let docs = format!(
274"Tools for manipulating the type state of [`{}`].\n\
275 \n\
276 See the [detailed guide](https://bon-rs.com/guide/typestate-api) \
277 that describes how all the pieces here fit together.",
278 builder_type.ident
279 );
280281vec![syn::parse_quote!(#[doc = #docs])]
282 }),
283 }
284 };
285286let start_fn = StartFn {
287 ident: start_fn.ident,
288 vis: start_fn.vis.unwrap_or_else(|| builder_type.vis.clone()),
289 docs: start_fn.docs,
290 generics: start_fn.generics,
291 };
292293let finish_fn = FinishFn {
294 ident: finish_fn.ident,
295 vis: finish_fn.vis.unwrap_or_else(|| builder_type.vis.clone()),
296 attrs: finish_fn.attrs,
297 unsafety: finish_fn.unsafety,
298 asyncness: finish_fn.asyncness,
299 must_use: finish_fn.must_use,
300 body: finish_fn.body,
301 output: finish_fn.output,
302 };
303304let state_var = {
305let possible_names = ["S", "State", "BuilderState"];
306 possible_names
307 .iter()
308 .find(|&&candidate| !namespace.idents.contains(candidate))
309 .map(|&name| syn::Ident::new(name, Span::call_site()))
310 .unwrap_or_else(|| namespace.unique_ident(format!("{}_", possible_names[0])))
311 };
312313Ok(Self {
314 bon: bon.unwrap_or_else(|| syn::parse_quote!(::bon)),
315 state_var,
316 members,
317 allow_attrs,
318 on,
319 generics,
320 assoc_method_ctx,
321 builder_type,
322 state_mod,
323 start_fn,
324 finish_fn,
325 })
326 }
327}
328329impl Generics {
330pub(super) fn new(
331 decl_with_defaults: Vec<syn::GenericParam>,
332 where_clause: Option<syn::WhereClause>,
333 ) -> Self {
334let decl_without_defaults = decl_with_defaults
335 .iter()
336 .cloned()
337 .map(|mut param| {
338match &mut param {
339 syn::GenericParam::Type(param) => {
340 param.default = None;
341 }
342 syn::GenericParam::Const(param) => {
343 param.default = None;
344 }
345 syn::GenericParam::Lifetime(_) => {}
346 }
347 param
348 })
349 .collect();
350351let args = decl_with_defaults
352 .iter()
353 .map(syn::GenericParam::to_generic_argument)
354 .collect();
355356Self {
357 where_clause,
358 decl_with_defaults,
359 decl_without_defaults,
360 args,
361 }
362 }
363364pub(super) fn where_clause_predicates(&self) -> impl Iterator<Item = &syn::WherePredicate> {
365self.where_clause
366 .as_ref()
367 .into_iter()
368 .flat_map(|clause| &clause.predicates)
369 }
370}