mod.rs 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438
  1. //! This code mostly comes from idanarye/rust-typed-builder
  2. //!
  3. //! However, it has been adopted to fit the Dioxus Props builder pattern.
  4. //!
  5. //! For Dioxus, we make a few changes:
  6. //! - [ ] Automatically implement Into<Option> on the setters (IE the strip setter option)
  7. //! - [ ] Automatically implement a default of none for optional fields (those explicitly wrapped with Option<T>)
  8. use proc_macro2::TokenStream;
  9. use syn::parse::Error;
  10. use syn::spanned::Spanned;
  11. use quote::quote;
  12. pub fn impl_my_derive(ast: &syn::DeriveInput) -> Result<TokenStream, Error> {
  13. let data = match &ast.data {
  14. syn::Data::Struct(data) => match &data.fields {
  15. syn::Fields::Named(fields) => {
  16. let struct_info = struct_info::StructInfo::new(ast, fields.named.iter())?;
  17. let builder_creation = struct_info.builder_creation_impl()?;
  18. let conversion_helper = struct_info.conversion_helper_impl()?;
  19. let fields = struct_info
  20. .included_fields()
  21. .map(|f| struct_info.field_impl(f))
  22. .collect::<Result<Vec<_>, _>>()?;
  23. let extends = struct_info
  24. .extend_fields()
  25. .map(|f| struct_info.extends_impl(f))
  26. .collect::<Result<Vec<_>, _>>()?;
  27. let fields = quote!(#(#fields)*).into_iter();
  28. let required_fields = struct_info
  29. .included_fields()
  30. .filter(|f| f.builder_attr.default.is_none())
  31. .map(|f| struct_info.required_field_impl(f))
  32. .collect::<Result<Vec<_>, _>>()?;
  33. let build_method = struct_info.build_method_impl();
  34. quote! {
  35. #builder_creation
  36. #conversion_helper
  37. #( #fields )*
  38. #( #extends )*
  39. #( #required_fields )*
  40. #build_method
  41. }
  42. }
  43. syn::Fields::Unnamed(_) => {
  44. return Err(Error::new(
  45. ast.span(),
  46. "Props is not supported for tuple structs",
  47. ))
  48. }
  49. syn::Fields::Unit => {
  50. return Err(Error::new(
  51. ast.span(),
  52. "Props is not supported for unit structs",
  53. ))
  54. }
  55. },
  56. syn::Data::Enum(_) => {
  57. return Err(Error::new(ast.span(), "Props is not supported for enums"))
  58. }
  59. syn::Data::Union(_) => {
  60. return Err(Error::new(ast.span(), "Props is not supported for unions"))
  61. }
  62. };
  63. Ok(data)
  64. }
  65. mod util {
  66. use quote::ToTokens;
  67. pub fn path_to_single_string(path: &syn::Path) -> Option<String> {
  68. if path.leading_colon.is_some() {
  69. return None;
  70. }
  71. let mut it = path.segments.iter();
  72. let segment = it.next()?;
  73. if it.next().is_some() {
  74. // Multipart path
  75. return None;
  76. }
  77. if segment.arguments != syn::PathArguments::None {
  78. return None;
  79. }
  80. Some(segment.ident.to_string())
  81. }
  82. pub fn expr_to_single_string(expr: &syn::Expr) -> Option<String> {
  83. if let syn::Expr::Path(path) = expr {
  84. path_to_single_string(&path.path)
  85. } else {
  86. None
  87. }
  88. }
  89. pub fn ident_to_type(ident: syn::Ident) -> syn::Type {
  90. let mut path = syn::Path {
  91. leading_colon: None,
  92. segments: Default::default(),
  93. };
  94. path.segments.push(syn::PathSegment {
  95. ident,
  96. arguments: Default::default(),
  97. });
  98. syn::Type::Path(syn::TypePath { qself: None, path })
  99. }
  100. pub fn empty_type() -> syn::Type {
  101. syn::TypeTuple {
  102. paren_token: Default::default(),
  103. elems: Default::default(),
  104. }
  105. .into()
  106. }
  107. pub fn type_tuple(elems: impl Iterator<Item = syn::Type>) -> syn::TypeTuple {
  108. let mut result = syn::TypeTuple {
  109. paren_token: Default::default(),
  110. elems: elems.collect(),
  111. };
  112. if !result.elems.empty_or_trailing() {
  113. result.elems.push_punct(Default::default());
  114. }
  115. result
  116. }
  117. pub fn empty_type_tuple() -> syn::TypeTuple {
  118. syn::TypeTuple {
  119. paren_token: Default::default(),
  120. elems: Default::default(),
  121. }
  122. }
  123. pub fn make_punctuated_single<T, P: Default>(value: T) -> syn::punctuated::Punctuated<T, P> {
  124. let mut punctuated = syn::punctuated::Punctuated::new();
  125. punctuated.push(value);
  126. punctuated
  127. }
  128. pub fn modify_types_generics_hack<F>(
  129. ty_generics: &syn::TypeGenerics,
  130. mut mutator: F,
  131. ) -> syn::AngleBracketedGenericArguments
  132. where
  133. F: FnMut(&mut syn::punctuated::Punctuated<syn::GenericArgument, syn::token::Comma>),
  134. {
  135. let mut abga: syn::AngleBracketedGenericArguments =
  136. syn::parse(ty_generics.clone().into_token_stream().into()).unwrap_or_else(|_| {
  137. syn::AngleBracketedGenericArguments {
  138. colon2_token: None,
  139. lt_token: Default::default(),
  140. args: Default::default(),
  141. gt_token: Default::default(),
  142. }
  143. });
  144. mutator(&mut abga.args);
  145. abga
  146. }
  147. pub fn strip_raw_ident_prefix(mut name: String) -> String {
  148. if name.starts_with("r#") {
  149. name.replace_range(0..2, "");
  150. }
  151. name
  152. }
  153. }
  154. mod field_info {
  155. use crate::props::type_from_inside_option;
  156. use proc_macro2::TokenStream;
  157. use quote::quote;
  158. use syn::spanned::Spanned;
  159. use syn::{parse::Error, punctuated::Punctuated};
  160. use syn::{Expr, Path};
  161. use super::util::{
  162. expr_to_single_string, ident_to_type, path_to_single_string, strip_raw_ident_prefix,
  163. };
  164. #[derive(Debug)]
  165. pub struct FieldInfo<'a> {
  166. pub ordinal: usize,
  167. pub name: &'a syn::Ident,
  168. pub generic_ident: syn::Ident,
  169. pub ty: &'a syn::Type,
  170. pub builder_attr: FieldBuilderAttr,
  171. }
  172. impl<'a> FieldInfo<'a> {
  173. pub fn new(
  174. ordinal: usize,
  175. field: &syn::Field,
  176. field_defaults: FieldBuilderAttr,
  177. ) -> Result<FieldInfo, Error> {
  178. if let Some(ref name) = field.ident {
  179. let mut builder_attr = field_defaults.with(&field.attrs)?;
  180. // children field is automatically defaulted to None
  181. if name == "children" {
  182. builder_attr.default = Some(
  183. syn::parse(quote!(::core::default::Default::default()).into()).unwrap(),
  184. );
  185. }
  186. // extended field is automatically empty
  187. if !builder_attr.extends.is_empty() {
  188. builder_attr.default = Some(
  189. syn::parse(quote!(::core::default::Default::default()).into()).unwrap(),
  190. );
  191. }
  192. // auto detect optional
  193. let strip_option_auto = builder_attr.strip_option
  194. || !builder_attr.ignore_option
  195. && type_from_inside_option(&field.ty, true).is_some();
  196. if !builder_attr.strip_option && strip_option_auto {
  197. builder_attr.strip_option = true;
  198. builder_attr.default = Some(
  199. syn::parse(quote!(::core::default::Default::default()).into()).unwrap(),
  200. );
  201. }
  202. Ok(FieldInfo {
  203. ordinal,
  204. name,
  205. generic_ident: syn::Ident::new(
  206. &format!("__{}", strip_raw_ident_prefix(name.to_string())),
  207. name.span(),
  208. ),
  209. ty: &field.ty,
  210. builder_attr,
  211. })
  212. } else {
  213. Err(Error::new(field.span(), "Nameless field in struct"))
  214. }
  215. }
  216. pub fn generic_ty_param(&self) -> syn::GenericParam {
  217. syn::GenericParam::Type(self.generic_ident.clone().into())
  218. }
  219. pub fn type_ident(&self) -> syn::Type {
  220. ident_to_type(self.generic_ident.clone())
  221. }
  222. pub fn tuplized_type_ty_param(&self) -> syn::Type {
  223. let mut types = syn::punctuated::Punctuated::default();
  224. types.push(self.ty.clone());
  225. types.push_punct(Default::default());
  226. syn::TypeTuple {
  227. paren_token: Default::default(),
  228. elems: types,
  229. }
  230. .into()
  231. }
  232. pub fn type_from_inside_option(&self, check_option_name: bool) -> Option<&syn::Type> {
  233. type_from_inside_option(self.ty, check_option_name)
  234. }
  235. }
  236. #[derive(Debug, Default, Clone)]
  237. pub struct FieldBuilderAttr {
  238. pub default: Option<syn::Expr>,
  239. pub doc: Option<syn::Expr>,
  240. pub skip: bool,
  241. pub auto_into: bool,
  242. pub strip_option: bool,
  243. pub ignore_option: bool,
  244. pub extends: Vec<Path>,
  245. }
  246. impl FieldBuilderAttr {
  247. pub fn with(mut self, attrs: &[syn::Attribute]) -> Result<Self, Error> {
  248. let mut skip_tokens = None;
  249. for attr in attrs {
  250. if path_to_single_string(attr.path()).as_deref() != Some("props") {
  251. continue;
  252. }
  253. match &attr.meta {
  254. syn::Meta::List(list) => {
  255. if list.tokens.is_empty() {
  256. continue;
  257. }
  258. }
  259. _ => {
  260. continue;
  261. }
  262. }
  263. let as_expr = attr.parse_args_with(
  264. Punctuated::<Expr, syn::Token![,]>::parse_separated_nonempty,
  265. )?;
  266. for expr in as_expr.into_iter() {
  267. self.apply_meta(expr)?;
  268. }
  269. // Stash its span for later (we don’t yet know if it’ll be an error)
  270. if self.skip && skip_tokens.is_none() {
  271. skip_tokens = Some(attr.meta.clone());
  272. }
  273. }
  274. if self.skip && self.default.is_none() {
  275. return Err(Error::new_spanned(
  276. skip_tokens.unwrap(),
  277. "#[props(skip)] must be accompanied by default or default_code",
  278. ));
  279. }
  280. Ok(self)
  281. }
  282. pub fn apply_meta(&mut self, expr: syn::Expr) -> Result<(), Error> {
  283. match expr {
  284. // #[props(default = "...")]
  285. syn::Expr::Assign(assign) => {
  286. let name = expr_to_single_string(&assign.left)
  287. .ok_or_else(|| Error::new_spanned(&assign.left, "Expected identifier"))?;
  288. match name.as_str() {
  289. "extends" => {
  290. if let syn::Expr::Path(path) = *assign.right {
  291. self.extends.push(path.path);
  292. Ok(())
  293. } else {
  294. Err(Error::new_spanned(
  295. assign.right,
  296. "Expected simple identifier",
  297. ))
  298. }
  299. }
  300. "default" => {
  301. self.default = Some(*assign.right);
  302. Ok(())
  303. }
  304. "doc" => {
  305. self.doc = Some(*assign.right);
  306. Ok(())
  307. }
  308. "default_code" => {
  309. if let syn::Expr::Lit(syn::ExprLit {
  310. lit: syn::Lit::Str(code),
  311. ..
  312. }) = *assign.right
  313. {
  314. use std::str::FromStr;
  315. let tokenized_code = TokenStream::from_str(&code.value())?;
  316. self.default = Some(
  317. syn::parse(tokenized_code.into())
  318. .map_err(|e| Error::new_spanned(code, format!("{e}")))?,
  319. );
  320. } else {
  321. return Err(Error::new_spanned(assign.right, "Expected string"));
  322. }
  323. Ok(())
  324. }
  325. _ => Err(Error::new_spanned(
  326. &assign,
  327. format!("Unknown parameter {name:?}"),
  328. )),
  329. }
  330. }
  331. // #[props(default)]
  332. syn::Expr::Path(path) => {
  333. let name = path_to_single_string(&path.path)
  334. .ok_or_else(|| Error::new_spanned(&path, "Expected identifier"))?;
  335. match name.as_str() {
  336. "default" => {
  337. self.default = Some(
  338. syn::parse(quote!(::core::default::Default::default()).into())
  339. .unwrap(),
  340. );
  341. Ok(())
  342. }
  343. "optional" => {
  344. self.default = Some(
  345. syn::parse(quote!(::core::default::Default::default()).into())
  346. .unwrap(),
  347. );
  348. self.strip_option = true;
  349. Ok(())
  350. }
  351. "extend" => {
  352. self.extends.push(path.path);
  353. Ok(())
  354. }
  355. _ => {
  356. macro_rules! handle_fields {
  357. ( $( $flag:expr, $field:ident, $already:expr; )* ) => {
  358. match name.as_str() {
  359. $(
  360. $flag => {
  361. if self.$field {
  362. Err(Error::new(path.span(), concat!("Illegal setting - field is already ", $already)))
  363. } else {
  364. self.$field = true;
  365. Ok(())
  366. }
  367. }
  368. )*
  369. _ => Err(Error::new_spanned(
  370. &path,
  371. format!("Unknown setter parameter {:?}", name),
  372. ))
  373. }
  374. }
  375. }
  376. handle_fields!(
  377. "skip", skip, "skipped";
  378. "into", auto_into, "calling into() on the argument";
  379. "strip_option", strip_option, "putting the argument in Some(...)";
  380. )
  381. }
  382. }
  383. }
  384. syn::Expr::Unary(syn::ExprUnary {
  385. op: syn::UnOp::Not(_),
  386. expr,
  387. ..
  388. }) => {
  389. if let syn::Expr::Path(path) = *expr {
  390. let name = path_to_single_string(&path.path)
  391. .ok_or_else(|| Error::new_spanned(&path, "Expected identifier"))?;
  392. match name.as_str() {
  393. "default" => {
  394. self.default = None;
  395. Ok(())
  396. }
  397. "doc" => {
  398. self.doc = None;
  399. Ok(())
  400. }
  401. "skip" => {
  402. self.skip = false;
  403. Ok(())
  404. }
  405. "auto_into" => {
  406. self.auto_into = false;
  407. Ok(())
  408. }
  409. "optional" => {
  410. self.strip_option = false;
  411. self.ignore_option = true;
  412. Ok(())
  413. }
  414. _ => Err(Error::new_spanned(path, "Unknown setting".to_owned())),
  415. }
  416. } else {
  417. Err(Error::new_spanned(
  418. expr,
  419. "Expected simple identifier".to_owned(),
  420. ))
  421. }
  422. }
  423. _ => Err(Error::new_spanned(expr, "Expected (<...>=<...>)")),
  424. }
  425. }
  426. }
  427. }
  428. fn type_from_inside_option(ty: &syn::Type, check_option_name: bool) -> Option<&syn::Type> {
  429. let path = if let syn::Type::Path(type_path) = ty {
  430. if type_path.qself.is_some() {
  431. return None;
  432. } else {
  433. &type_path.path
  434. }
  435. } else {
  436. return None;
  437. };
  438. let segment = path.segments.last()?;
  439. if check_option_name && segment.ident != "Option" {
  440. return None;
  441. }
  442. let generic_params =
  443. if let syn::PathArguments::AngleBracketed(generic_params) = &segment.arguments {
  444. generic_params
  445. } else {
  446. return None;
  447. };
  448. if let syn::GenericArgument::Type(ty) = generic_params.args.first()? {
  449. Some(ty)
  450. } else {
  451. None
  452. }
  453. }
  454. mod struct_info {
  455. use convert_case::{Case, Casing};
  456. use proc_macro2::TokenStream;
  457. use quote::quote;
  458. use syn::parse::Error;
  459. use syn::punctuated::Punctuated;
  460. use syn::spanned::Spanned;
  461. use syn::visit::Visit;
  462. use syn::{parse_quote, Expr, Ident};
  463. use super::field_info::{FieldBuilderAttr, FieldInfo};
  464. use super::util::{
  465. empty_type, empty_type_tuple, expr_to_single_string, make_punctuated_single,
  466. modify_types_generics_hack, path_to_single_string, strip_raw_ident_prefix, type_tuple,
  467. };
  468. #[derive(Debug)]
  469. pub struct StructInfo<'a> {
  470. pub vis: &'a syn::Visibility,
  471. pub name: &'a syn::Ident,
  472. pub generics: &'a syn::Generics,
  473. pub fields: Vec<FieldInfo<'a>>,
  474. pub builder_attr: TypeBuilderAttr,
  475. pub builder_name: syn::Ident,
  476. pub conversion_helper_trait_name: syn::Ident,
  477. pub core: syn::Ident,
  478. }
  479. impl<'a> StructInfo<'a> {
  480. pub fn included_fields(&self) -> impl Iterator<Item = &FieldInfo<'a>> {
  481. self.fields
  482. .iter()
  483. .filter(|f| !f.builder_attr.skip && f.builder_attr.extends.is_empty())
  484. }
  485. pub fn extend_fields(&self) -> impl Iterator<Item = &FieldInfo<'a>> {
  486. self.fields
  487. .iter()
  488. .filter(|f| !f.builder_attr.extends.is_empty())
  489. }
  490. fn extend_lifetime(&self) -> syn::Result<Option<syn::Lifetime>> {
  491. let first_extend = self.extend_fields().next();
  492. match first_extend {
  493. Some(f) => {
  494. struct VisitFirstLifetime(Option<syn::Lifetime>);
  495. impl Visit<'_> for VisitFirstLifetime {
  496. fn visit_lifetime(&mut self, lifetime: &'_ syn::Lifetime) {
  497. if self.0.is_none() {
  498. self.0 = Some(lifetime.clone());
  499. }
  500. }
  501. }
  502. let name = f.name;
  503. let mut visitor = VisitFirstLifetime(None);
  504. visitor.visit_type(&f.ty);
  505. visitor.0.ok_or_else(|| {
  506. syn::Error::new_spanned(
  507. name,
  508. "Unable to find lifetime for extended field. Please specify it manually",
  509. )
  510. }).map(Some)
  511. }
  512. None => Ok(None),
  513. }
  514. }
  515. pub fn new(
  516. ast: &'a syn::DeriveInput,
  517. fields: impl Iterator<Item = &'a syn::Field>,
  518. ) -> Result<StructInfo<'a>, Error> {
  519. let builder_attr = TypeBuilderAttr::new(&ast.attrs)?;
  520. let builder_name = strip_raw_ident_prefix(format!("{}Builder", ast.ident));
  521. Ok(StructInfo {
  522. vis: &ast.vis,
  523. name: &ast.ident,
  524. generics: &ast.generics,
  525. fields: fields
  526. .enumerate()
  527. .map(|(i, f)| FieldInfo::new(i, f, builder_attr.field_defaults.clone()))
  528. .collect::<Result<_, _>>()?,
  529. builder_attr,
  530. builder_name: syn::Ident::new(&builder_name, ast.ident.span()),
  531. conversion_helper_trait_name: syn::Ident::new(
  532. &format!("{builder_name}_Optional"),
  533. ast.ident.span(),
  534. ),
  535. core: syn::Ident::new(&format!("{builder_name}_core"), ast.ident.span()),
  536. })
  537. }
  538. fn modify_generics<F: FnMut(&mut syn::Generics)>(&self, mut mutator: F) -> syn::Generics {
  539. let mut generics = self.generics.clone();
  540. mutator(&mut generics);
  541. generics
  542. }
  543. pub fn builder_creation_impl(&self) -> Result<TokenStream, Error> {
  544. let StructInfo {
  545. ref vis,
  546. ref name,
  547. ref builder_name,
  548. ..
  549. } = *self;
  550. // we're generating stuff that goes into unsafe code here
  551. // we use the heuristic: are there *any* generic parameters?
  552. // If so, then they might have non-static lifetimes and we can't compare two generic things that *might borrow*
  553. // Therefore, we will generate code that shortcircuits the "comparison" in memoization
  554. let are_there_generics = !self.generics.params.is_empty();
  555. let extend_lifetime = self.extend_lifetime()?;
  556. let generics = self.generics.clone();
  557. let (_, ty_generics, where_clause) = generics.split_for_impl();
  558. let impl_generics = self.modify_generics(|g| {
  559. if extend_lifetime.is_none() {
  560. g.params.insert(0, parse_quote!('__bump));
  561. }
  562. });
  563. let (impl_generics, _, _) = impl_generics.split_for_impl();
  564. let (_, b_initial_generics, _) = self.generics.split_for_impl();
  565. let all_fields_param = syn::GenericParam::Type(
  566. syn::Ident::new("TypedBuilderFields", proc_macro2::Span::call_site()).into(),
  567. );
  568. let b_generics = self.modify_generics(|g| {
  569. g.params.insert(0, all_fields_param.clone());
  570. });
  571. let empties_tuple = type_tuple(self.included_fields().map(|_| empty_type()));
  572. let generics_with_empty = modify_types_generics_hack(&b_initial_generics, |args| {
  573. args.insert(0, syn::GenericArgument::Type(empties_tuple.clone().into()));
  574. });
  575. let phantom_generics = self.generics.params.iter().map(|param| match param {
  576. syn::GenericParam::Lifetime(lifetime) => {
  577. let lifetime = &lifetime.lifetime;
  578. quote!(::core::marker::PhantomData<&#lifetime ()>)
  579. }
  580. syn::GenericParam::Type(ty) => {
  581. let ty = &ty.ident;
  582. quote!(::core::marker::PhantomData<#ty>)
  583. }
  584. syn::GenericParam::Const(_cnst) => {
  585. quote!()
  586. }
  587. });
  588. let builder_method_doc = match self.builder_attr.builder_method_doc {
  589. Some(ref doc) => quote!(#doc),
  590. None => {
  591. let doc = format!(
  592. "
  593. Create a builder for building `{name}`.
  594. On the builder, call {setters} to set the values of the fields.
  595. Finally, call `.build()` to create the instance of `{name}`.
  596. ",
  597. name = self.name,
  598. setters = {
  599. let mut result = String::new();
  600. let mut is_first = true;
  601. for field in self.included_fields() {
  602. use std::fmt::Write;
  603. if is_first {
  604. is_first = false;
  605. } else {
  606. write!(&mut result, ", ").unwrap();
  607. }
  608. write!(&mut result, "`.{}(...)`", field.name).unwrap();
  609. if field.builder_attr.default.is_some() {
  610. write!(&mut result, "(optional)").unwrap();
  611. }
  612. }
  613. result
  614. }
  615. );
  616. quote!(#doc)
  617. }
  618. };
  619. let builder_type_doc = if self.builder_attr.doc {
  620. match self.builder_attr.builder_type_doc {
  621. Some(ref doc) => quote!(#[doc = #doc]),
  622. None => {
  623. let doc = format!(
  624. "Builder for [`{name}`] instances.\n\nSee [`{name}::builder()`] for more info.",
  625. );
  626. quote!(#[doc = #doc])
  627. }
  628. }
  629. } else {
  630. quote!(#[doc(hidden)])
  631. };
  632. let (_, _, b_generics_where_extras_predicates) = b_generics.split_for_impl();
  633. let mut b_generics_where: syn::WhereClause = syn::parse2(quote! {
  634. where TypedBuilderFields: Clone
  635. })?;
  636. if let Some(predicates) = b_generics_where_extras_predicates {
  637. b_generics_where
  638. .predicates
  639. .extend(predicates.predicates.clone());
  640. }
  641. let can_memoize = match are_there_generics {
  642. true => quote! { false },
  643. false => quote! { self == other },
  644. };
  645. let is_static = match are_there_generics {
  646. true => quote! { false },
  647. false => quote! { true },
  648. };
  649. let extend_fields = self.extend_fields().map(|f| {
  650. let name = f.name;
  651. let ty = f.ty;
  652. quote!(#name: #ty)
  653. });
  654. let extend_fields_value = self.extend_fields().map(|f| {
  655. let name = f.name;
  656. quote!(#name: Vec::new())
  657. });
  658. let has_extend_fields = self.extend_fields().next().is_some();
  659. let take_bump = if has_extend_fields {
  660. quote!(bump: _cx.bump(),)
  661. } else {
  662. quote!()
  663. };
  664. let bump_field = if has_extend_fields {
  665. quote!(bump: & #extend_lifetime ::dioxus::core::exports::bumpalo::Bump,)
  666. } else {
  667. quote!()
  668. };
  669. let extend_lifetime = extend_lifetime.unwrap_or(syn::Lifetime::new(
  670. "'__bump",
  671. proc_macro2::Span::call_site(),
  672. ));
  673. Ok(quote! {
  674. impl #impl_generics #name #ty_generics #where_clause {
  675. #[doc = #builder_method_doc]
  676. #[allow(dead_code)]
  677. #vis fn builder(_cx: & #extend_lifetime ::dioxus::prelude::ScopeState) -> #builder_name #generics_with_empty {
  678. #builder_name {
  679. #(#extend_fields_value,)*
  680. #take_bump
  681. fields: #empties_tuple,
  682. _phantom: ::core::default::Default::default(),
  683. }
  684. }
  685. }
  686. #[must_use]
  687. #builder_type_doc
  688. #[allow(dead_code, non_camel_case_types, non_snake_case)]
  689. #vis struct #builder_name #b_generics {
  690. #(#extend_fields,)*
  691. #bump_field
  692. fields: #all_fields_param,
  693. _phantom: (#( #phantom_generics ),*),
  694. }
  695. impl #impl_generics ::dioxus::prelude::Properties<#extend_lifetime> for #name #ty_generics
  696. #b_generics_where_extras_predicates
  697. {
  698. type Builder = #builder_name #generics_with_empty;
  699. const IS_STATIC: bool = #is_static;
  700. fn builder(_cx: &#extend_lifetime ::dioxus::prelude::ScopeState) -> Self::Builder {
  701. #name::builder(_cx)
  702. }
  703. unsafe fn memoize(&self, other: &Self) -> bool {
  704. #can_memoize
  705. }
  706. }
  707. })
  708. }
  709. // TODO: once the proc-macro crate limitation is lifted, make this an util trait of this
  710. // crate.
  711. pub fn conversion_helper_impl(&self) -> Result<TokenStream, Error> {
  712. let trait_name = &self.conversion_helper_trait_name;
  713. Ok(quote! {
  714. #[doc(hidden)]
  715. #[allow(dead_code, non_camel_case_types, non_snake_case)]
  716. pub trait #trait_name<T> {
  717. fn into_value<F: FnOnce() -> T>(self, default: F) -> T;
  718. }
  719. impl<T> #trait_name<T> for () {
  720. fn into_value<F: FnOnce() -> T>(self, default: F) -> T {
  721. default()
  722. }
  723. }
  724. impl<T> #trait_name<T> for (T,) {
  725. fn into_value<F: FnOnce() -> T>(self, _: F) -> T {
  726. self.0
  727. }
  728. }
  729. })
  730. }
  731. pub fn extends_impl(&self, field: &FieldInfo) -> Result<TokenStream, Error> {
  732. let StructInfo {
  733. ref builder_name, ..
  734. } = *self;
  735. let field_name = field.name;
  736. let descructuring = self.included_fields().map(|f| {
  737. if f.ordinal == field.ordinal {
  738. quote!(_)
  739. } else {
  740. let name = f.name;
  741. quote!(#name)
  742. }
  743. });
  744. let reconstructing = self.included_fields().map(|f| f.name);
  745. // Add the bump lifetime to the generics
  746. let mut ty_generics: Vec<syn::GenericArgument> = self
  747. .generics
  748. .params
  749. .iter()
  750. .map(|generic_param| match generic_param {
  751. syn::GenericParam::Type(type_param) => {
  752. let ident = type_param.ident.clone();
  753. syn::parse(quote!(#ident).into()).unwrap()
  754. }
  755. syn::GenericParam::Lifetime(lifetime_def) => {
  756. syn::GenericArgument::Lifetime(lifetime_def.lifetime.clone())
  757. }
  758. syn::GenericParam::Const(const_param) => {
  759. let ident = const_param.ident.clone();
  760. syn::parse(quote!(#ident).into()).unwrap()
  761. }
  762. })
  763. .collect();
  764. let mut target_generics_tuple = empty_type_tuple();
  765. let mut ty_generics_tuple = empty_type_tuple();
  766. let generics = self.modify_generics(|g| {
  767. let index_after_lifetime_in_generics = g
  768. .params
  769. .iter()
  770. .filter(|arg| matches!(arg, syn::GenericParam::Lifetime(_)))
  771. .count();
  772. for f in self.included_fields() {
  773. if f.ordinal == field.ordinal {
  774. ty_generics_tuple.elems.push_value(empty_type());
  775. target_generics_tuple
  776. .elems
  777. .push_value(f.tuplized_type_ty_param());
  778. } else {
  779. g.params
  780. .insert(index_after_lifetime_in_generics, f.generic_ty_param());
  781. let generic_argument: syn::Type = f.type_ident();
  782. ty_generics_tuple.elems.push_value(generic_argument.clone());
  783. target_generics_tuple.elems.push_value(generic_argument);
  784. }
  785. ty_generics_tuple.elems.push_punct(Default::default());
  786. target_generics_tuple.elems.push_punct(Default::default());
  787. }
  788. });
  789. let mut target_generics = ty_generics.clone();
  790. let index_after_lifetime_in_generics = target_generics
  791. .iter()
  792. .filter(|arg| matches!(arg, syn::GenericArgument::Lifetime(_)))
  793. .count();
  794. target_generics.insert(
  795. index_after_lifetime_in_generics,
  796. syn::GenericArgument::Type(target_generics_tuple.into()),
  797. );
  798. ty_generics.insert(
  799. index_after_lifetime_in_generics,
  800. syn::GenericArgument::Type(ty_generics_tuple.into()),
  801. );
  802. let (impl_generics, _, where_clause) = generics.split_for_impl();
  803. let forward_extended_fields = self.extend_fields().map(|f| {
  804. let name = f.name;
  805. quote!(#name: self.#name)
  806. });
  807. let extend_lifetime = self.extend_lifetime()?.ok_or(Error::new_spanned(
  808. field_name,
  809. "Unable to find lifetime for extended field. Please specify it manually",
  810. ))?;
  811. let extends_impl = field.builder_attr.extends.iter().map(|path| {
  812. let name_str = path_to_single_string(path).unwrap();
  813. let camel_name = name_str.to_case(Case::UpperCamel);
  814. let marker_name = Ident::new(
  815. format!("{}Extension", &camel_name).as_str(),
  816. path.span(),
  817. );
  818. quote! {
  819. impl #impl_generics dioxus_elements::extensions::#marker_name < #extend_lifetime > for #builder_name < #( #ty_generics ),* > #where_clause {}
  820. }
  821. });
  822. Ok(quote! {
  823. impl #impl_generics ::dioxus::prelude::HasAttributesBox<#extend_lifetime> for #builder_name < #( #ty_generics ),* > #where_clause {
  824. fn push_attribute(
  825. mut self,
  826. name: &#extend_lifetime str,
  827. ns: Option<&'static str>,
  828. attr: impl ::dioxus::prelude::IntoAttributeValue<#extend_lifetime>,
  829. volatile: bool
  830. ) -> Self {
  831. let ( #(#descructuring,)* ) = self.fields;
  832. self.#field_name.push(
  833. ::dioxus::core::Attribute::new(
  834. name,
  835. {
  836. use ::dioxus::prelude::IntoAttributeValue;
  837. attr.into_value(self.bump)
  838. },
  839. ns,
  840. volatile,
  841. )
  842. );
  843. #builder_name {
  844. #(#forward_extended_fields,)*
  845. bump: self.bump,
  846. fields: ( #(#reconstructing,)* ),
  847. _phantom: self._phantom,
  848. }
  849. }
  850. }
  851. #(#extends_impl)*
  852. })
  853. }
  854. pub fn field_impl(&self, field: &FieldInfo) -> Result<TokenStream, Error> {
  855. let StructInfo {
  856. ref builder_name, ..
  857. } = *self;
  858. let descructuring = self.included_fields().map(|f| {
  859. if f.ordinal == field.ordinal {
  860. quote!(_)
  861. } else {
  862. let name = f.name;
  863. quote!(#name)
  864. }
  865. });
  866. let reconstructing = self.included_fields().map(|f| f.name);
  867. let FieldInfo {
  868. name: field_name,
  869. ty: field_type,
  870. ..
  871. } = field;
  872. // Add the bump lifetime to the generics
  873. let mut ty_generics: Vec<syn::GenericArgument> = self
  874. .generics
  875. .params
  876. .iter()
  877. .map(|generic_param| match generic_param {
  878. syn::GenericParam::Type(type_param) => {
  879. let ident = type_param.ident.clone();
  880. syn::parse(quote!(#ident).into()).unwrap()
  881. }
  882. syn::GenericParam::Lifetime(lifetime_def) => {
  883. syn::GenericArgument::Lifetime(lifetime_def.lifetime.clone())
  884. }
  885. syn::GenericParam::Const(const_param) => {
  886. let ident = const_param.ident.clone();
  887. syn::parse(quote!(#ident).into()).unwrap()
  888. }
  889. })
  890. .collect();
  891. let mut target_generics_tuple = empty_type_tuple();
  892. let mut ty_generics_tuple = empty_type_tuple();
  893. let generics = self.modify_generics(|g| {
  894. let index_after_lifetime_in_generics = g
  895. .params
  896. .iter()
  897. .filter(|arg| matches!(arg, syn::GenericParam::Lifetime(_)))
  898. .count();
  899. for f in self.included_fields() {
  900. if f.ordinal == field.ordinal {
  901. ty_generics_tuple.elems.push_value(empty_type());
  902. target_generics_tuple
  903. .elems
  904. .push_value(f.tuplized_type_ty_param());
  905. } else {
  906. g.params
  907. .insert(index_after_lifetime_in_generics, f.generic_ty_param());
  908. let generic_argument: syn::Type = f.type_ident();
  909. ty_generics_tuple.elems.push_value(generic_argument.clone());
  910. target_generics_tuple.elems.push_value(generic_argument);
  911. }
  912. ty_generics_tuple.elems.push_punct(Default::default());
  913. target_generics_tuple.elems.push_punct(Default::default());
  914. }
  915. });
  916. let mut target_generics = ty_generics.clone();
  917. let index_after_lifetime_in_generics = target_generics
  918. .iter()
  919. .filter(|arg| matches!(arg, syn::GenericArgument::Lifetime(_)))
  920. .count();
  921. target_generics.insert(
  922. index_after_lifetime_in_generics,
  923. syn::GenericArgument::Type(target_generics_tuple.into()),
  924. );
  925. ty_generics.insert(
  926. index_after_lifetime_in_generics,
  927. syn::GenericArgument::Type(ty_generics_tuple.into()),
  928. );
  929. let (impl_generics, _, where_clause) = generics.split_for_impl();
  930. let doc = match field.builder_attr.doc {
  931. Some(ref doc) => quote!(#[doc = #doc]),
  932. None => quote!(),
  933. };
  934. // NOTE: both auto_into and strip_option affect `arg_type` and `arg_expr`, but the order of
  935. // nesting is different so we have to do this little dance.
  936. let arg_type = if field.builder_attr.strip_option {
  937. field.type_from_inside_option(false).ok_or_else(|| {
  938. Error::new_spanned(
  939. field_type,
  940. "can't `strip_option` - field is not `Option<...>`",
  941. )
  942. })?
  943. } else {
  944. field_type
  945. };
  946. let (arg_type, arg_expr) = if field.builder_attr.auto_into {
  947. (
  948. quote!(impl ::core::convert::Into<#arg_type>),
  949. quote!(#field_name.into()),
  950. )
  951. } else {
  952. (quote!(#arg_type), quote!(#field_name))
  953. };
  954. let arg_expr = if field.builder_attr.strip_option {
  955. quote!(Some(#arg_expr))
  956. } else {
  957. arg_expr
  958. };
  959. let repeated_fields_error_type_name = syn::Ident::new(
  960. &format!(
  961. "{}_Error_Repeated_field_{}",
  962. builder_name,
  963. strip_raw_ident_prefix(field_name.to_string())
  964. ),
  965. builder_name.span(),
  966. );
  967. let repeated_fields_error_message = format!("Repeated field {field_name}");
  968. let forward_extended_fields = self.extend_fields().map(|f| {
  969. let name = f.name;
  970. quote!(#name: self.#name)
  971. });
  972. let forward_bump = if self.extend_fields().next().is_some() {
  973. quote!(bump: self.bump,)
  974. } else {
  975. quote!()
  976. };
  977. Ok(quote! {
  978. #[allow(dead_code, non_camel_case_types, missing_docs)]
  979. impl #impl_generics #builder_name < #( #ty_generics ),* > #where_clause {
  980. #doc
  981. pub fn #field_name (self, #field_name: #arg_type) -> #builder_name < #( #target_generics ),* > {
  982. let #field_name = (#arg_expr,);
  983. let ( #(#descructuring,)* ) = self.fields;
  984. #builder_name {
  985. #(#forward_extended_fields,)*
  986. #forward_bump
  987. fields: ( #(#reconstructing,)* ),
  988. _phantom: self._phantom,
  989. }
  990. }
  991. }
  992. #[doc(hidden)]
  993. #[allow(dead_code, non_camel_case_types, non_snake_case)]
  994. pub enum #repeated_fields_error_type_name {}
  995. #[doc(hidden)]
  996. #[allow(dead_code, non_camel_case_types, missing_docs)]
  997. impl #impl_generics #builder_name < #( #target_generics ),* > #where_clause {
  998. #[deprecated(
  999. note = #repeated_fields_error_message
  1000. )]
  1001. pub fn #field_name (self, _: #repeated_fields_error_type_name) -> #builder_name < #( #target_generics ),* > {
  1002. self
  1003. }
  1004. }
  1005. })
  1006. }
  1007. pub fn required_field_impl(&self, field: &FieldInfo) -> Result<TokenStream, Error> {
  1008. let StructInfo {
  1009. ref name,
  1010. ref builder_name,
  1011. ..
  1012. } = self;
  1013. let FieldInfo {
  1014. name: ref field_name,
  1015. ..
  1016. } = field;
  1017. // Add a bump lifetime to the generics
  1018. let mut builder_generics: Vec<syn::GenericArgument> = self
  1019. .generics
  1020. .params
  1021. .iter()
  1022. .map(|generic_param| match generic_param {
  1023. syn::GenericParam::Type(type_param) => {
  1024. let ident = &type_param.ident;
  1025. syn::parse(quote!(#ident).into()).unwrap()
  1026. }
  1027. syn::GenericParam::Lifetime(lifetime_def) => {
  1028. syn::GenericArgument::Lifetime(lifetime_def.lifetime.clone())
  1029. }
  1030. syn::GenericParam::Const(const_param) => {
  1031. let ident = &const_param.ident;
  1032. syn::parse(quote!(#ident).into()).unwrap()
  1033. }
  1034. })
  1035. .collect();
  1036. let mut builder_generics_tuple = empty_type_tuple();
  1037. let generics = self.modify_generics(|g| {
  1038. let index_after_lifetime_in_generics = g
  1039. .params
  1040. .iter()
  1041. .filter(|arg| matches!(arg, syn::GenericParam::Lifetime(_)))
  1042. .count();
  1043. for f in self.included_fields() {
  1044. if f.builder_attr.default.is_some() {
  1045. // `f` is not mandatory - it does not have it's own fake `build` method, so `field` will need
  1046. // to warn about missing `field` whether or not `f` is set.
  1047. assert!(
  1048. f.ordinal != field.ordinal,
  1049. "`required_field_impl` called for optional field {}",
  1050. field.name
  1051. );
  1052. g.params
  1053. .insert(index_after_lifetime_in_generics, f.generic_ty_param());
  1054. builder_generics_tuple.elems.push_value(f.type_ident());
  1055. } else if f.ordinal < field.ordinal {
  1056. // Only add a `build` method that warns about missing `field` if `f` is set. If `f` is not set,
  1057. // `f`'s `build` method will warn, since it appears earlier in the argument list.
  1058. builder_generics_tuple
  1059. .elems
  1060. .push_value(f.tuplized_type_ty_param());
  1061. } else if f.ordinal == field.ordinal {
  1062. builder_generics_tuple.elems.push_value(empty_type());
  1063. } else {
  1064. // `f` appears later in the argument list after `field`, so if they are both missing we will
  1065. // show a warning for `field` and not for `f` - which means this warning should appear whether
  1066. // or not `f` is set.
  1067. g.params
  1068. .insert(index_after_lifetime_in_generics, f.generic_ty_param());
  1069. builder_generics_tuple.elems.push_value(f.type_ident());
  1070. }
  1071. builder_generics_tuple.elems.push_punct(Default::default());
  1072. }
  1073. });
  1074. let index_after_lifetime_in_generics = builder_generics
  1075. .iter()
  1076. .filter(|arg| matches!(arg, syn::GenericArgument::Lifetime(_)))
  1077. .count();
  1078. builder_generics.insert(
  1079. index_after_lifetime_in_generics,
  1080. syn::GenericArgument::Type(builder_generics_tuple.into()),
  1081. );
  1082. let (impl_generics, _, where_clause) = generics.split_for_impl();
  1083. let (_, ty_generics, _) = self.generics.split_for_impl();
  1084. let early_build_error_type_name = syn::Ident::new(
  1085. &format!(
  1086. "{}_Error_Missing_required_field_{}",
  1087. builder_name,
  1088. strip_raw_ident_prefix(field_name.to_string())
  1089. ),
  1090. builder_name.span(),
  1091. );
  1092. let early_build_error_message = format!("Missing required field {field_name}");
  1093. Ok(quote! {
  1094. #[doc(hidden)]
  1095. #[allow(dead_code, non_camel_case_types, non_snake_case)]
  1096. pub enum #early_build_error_type_name {}
  1097. #[doc(hidden)]
  1098. #[allow(dead_code, non_camel_case_types, missing_docs, clippy::panic)]
  1099. impl #impl_generics #builder_name < #( #builder_generics ),* > #where_clause {
  1100. #[deprecated(
  1101. note = #early_build_error_message
  1102. )]
  1103. pub fn build(self, _: #early_build_error_type_name) -> #name #ty_generics {
  1104. panic!();
  1105. }
  1106. }
  1107. })
  1108. }
  1109. pub fn build_method_impl(&self) -> TokenStream {
  1110. let StructInfo {
  1111. ref name,
  1112. ref builder_name,
  1113. ..
  1114. } = *self;
  1115. let generics = self.modify_generics(|g| {
  1116. let index_after_lifetime_in_generics = g
  1117. .params
  1118. .iter()
  1119. .filter(|arg| matches!(arg, syn::GenericParam::Lifetime(_)))
  1120. .count();
  1121. for field in self.included_fields() {
  1122. if field.builder_attr.default.is_some() {
  1123. let trait_ref = syn::TraitBound {
  1124. paren_token: None,
  1125. lifetimes: None,
  1126. modifier: syn::TraitBoundModifier::None,
  1127. path: syn::PathSegment {
  1128. ident: self.conversion_helper_trait_name.clone(),
  1129. arguments: syn::PathArguments::AngleBracketed(
  1130. syn::AngleBracketedGenericArguments {
  1131. colon2_token: None,
  1132. lt_token: Default::default(),
  1133. args: make_punctuated_single(syn::GenericArgument::Type(
  1134. field.ty.clone(),
  1135. )),
  1136. gt_token: Default::default(),
  1137. },
  1138. ),
  1139. }
  1140. .into(),
  1141. };
  1142. let mut generic_param: syn::TypeParam = field.generic_ident.clone().into();
  1143. generic_param.bounds.push(trait_ref.into());
  1144. g.params
  1145. .insert(index_after_lifetime_in_generics, generic_param.into());
  1146. }
  1147. }
  1148. });
  1149. let (impl_generics, _, _) = generics.split_for_impl();
  1150. let (_, ty_generics, where_clause) = self.generics.split_for_impl();
  1151. let modified_ty_generics = modify_types_generics_hack(&ty_generics, |args| {
  1152. args.insert(
  1153. 0,
  1154. syn::GenericArgument::Type(
  1155. type_tuple(self.included_fields().map(|field| {
  1156. if field.builder_attr.default.is_some() {
  1157. field.type_ident()
  1158. } else {
  1159. field.tuplized_type_ty_param()
  1160. }
  1161. }))
  1162. .into(),
  1163. ),
  1164. );
  1165. });
  1166. let descructuring = self.included_fields().map(|f| f.name);
  1167. let helper_trait_name = &self.conversion_helper_trait_name;
  1168. // The default of a field can refer to earlier-defined fields, which we handle by
  1169. // writing out a bunch of `let` statements first, which can each refer to earlier ones.
  1170. // This means that field ordering may actually be significant, which isn’t ideal. We could
  1171. // relax that restriction by calculating a DAG of field default dependencies and
  1172. // reordering based on that, but for now this much simpler thing is a reasonable approach.
  1173. let assignments = self.fields.iter().map(|field| {
  1174. let name = &field.name;
  1175. if !field.builder_attr.extends.is_empty() {
  1176. quote!(let #name = self.#name;)
  1177. } else if let Some(ref default) = field.builder_attr.default {
  1178. if field.builder_attr.skip {
  1179. quote!(let #name = #default;)
  1180. } else {
  1181. quote!(let #name = #helper_trait_name::into_value(#name, || #default);)
  1182. }
  1183. } else {
  1184. quote!(let #name = #name.0;)
  1185. }
  1186. });
  1187. let field_names = self.fields.iter().map(|field| field.name);
  1188. let doc = if self.builder_attr.doc {
  1189. match self.builder_attr.build_method_doc {
  1190. Some(ref doc) => quote!(#[doc = #doc]),
  1191. None => {
  1192. // I’d prefer “a” or “an” to “its”, but determining which is grammatically
  1193. // correct is roughly impossible.
  1194. let doc =
  1195. format!("Finalise the builder and create its [`{name}`] instance");
  1196. quote!(#[doc = #doc])
  1197. }
  1198. }
  1199. } else {
  1200. quote!()
  1201. };
  1202. quote!(
  1203. #[allow(dead_code, non_camel_case_types, missing_docs)]
  1204. impl #impl_generics #builder_name #modified_ty_generics #where_clause {
  1205. #doc
  1206. pub fn build(self) -> #name #ty_generics {
  1207. let ( #(#descructuring,)* ) = self.fields;
  1208. #( #assignments )*
  1209. #name {
  1210. #( #field_names ),*
  1211. }
  1212. }
  1213. }
  1214. )
  1215. }
  1216. }
  1217. #[derive(Debug, Default)]
  1218. pub struct TypeBuilderAttr {
  1219. /// Whether to show docs for the `TypeBuilder` type (rather than hiding them).
  1220. pub doc: bool,
  1221. /// Docs on the `Type::builder()` method.
  1222. pub builder_method_doc: Option<syn::Expr>,
  1223. /// Docs on the `TypeBuilder` type. Specifying this implies `doc`, but you can just specify
  1224. /// `doc` instead and a default value will be filled in here.
  1225. pub builder_type_doc: Option<syn::Expr>,
  1226. /// Docs on the `TypeBuilder.build()` method. Specifying this implies `doc`, but you can just
  1227. /// specify `doc` instead and a default value will be filled in here.
  1228. pub build_method_doc: Option<syn::Expr>,
  1229. pub field_defaults: FieldBuilderAttr,
  1230. }
  1231. impl TypeBuilderAttr {
  1232. pub fn new(attrs: &[syn::Attribute]) -> Result<TypeBuilderAttr, Error> {
  1233. let mut result = TypeBuilderAttr::default();
  1234. for attr in attrs {
  1235. if path_to_single_string(attr.path()).as_deref() != Some("builder") {
  1236. continue;
  1237. }
  1238. match &attr.meta {
  1239. syn::Meta::List(list) => {
  1240. if list.tokens.is_empty() {
  1241. continue;
  1242. }
  1243. }
  1244. _ => {
  1245. continue;
  1246. }
  1247. }
  1248. let as_expr = attr.parse_args_with(
  1249. Punctuated::<Expr, syn::Token![,]>::parse_separated_nonempty,
  1250. )?;
  1251. for expr in as_expr.into_iter() {
  1252. result.apply_meta(expr)?;
  1253. }
  1254. }
  1255. Ok(result)
  1256. }
  1257. fn apply_meta(&mut self, expr: syn::Expr) -> Result<(), Error> {
  1258. match expr {
  1259. syn::Expr::Assign(assign) => {
  1260. let name = expr_to_single_string(&assign.left)
  1261. .ok_or_else(|| Error::new_spanned(&assign.left, "Expected identifier"))?;
  1262. match name.as_str() {
  1263. "builder_method_doc" => {
  1264. self.builder_method_doc = Some(*assign.right);
  1265. Ok(())
  1266. }
  1267. "builder_type_doc" => {
  1268. self.builder_type_doc = Some(*assign.right);
  1269. self.doc = true;
  1270. Ok(())
  1271. }
  1272. "build_method_doc" => {
  1273. self.build_method_doc = Some(*assign.right);
  1274. self.doc = true;
  1275. Ok(())
  1276. }
  1277. _ => Err(Error::new_spanned(
  1278. &assign,
  1279. format!("Unknown parameter {name:?}"),
  1280. )),
  1281. }
  1282. }
  1283. syn::Expr::Path(path) => {
  1284. let name = path_to_single_string(&path.path)
  1285. .ok_or_else(|| Error::new_spanned(&path, "Expected identifier"))?;
  1286. match name.as_str() {
  1287. "doc" => {
  1288. self.doc = true;
  1289. Ok(())
  1290. }
  1291. _ => Err(Error::new_spanned(
  1292. &path,
  1293. format!("Unknown parameter {name:?}"),
  1294. )),
  1295. }
  1296. }
  1297. syn::Expr::Call(call) => {
  1298. let subsetting_name = if let syn::Expr::Path(path) = &*call.func {
  1299. path_to_single_string(&path.path)
  1300. } else {
  1301. None
  1302. }
  1303. .ok_or_else(|| {
  1304. let call_func = &call.func;
  1305. let call_func = quote!(#call_func);
  1306. Error::new_spanned(
  1307. &call.func,
  1308. format!("Illegal builder setting group {call_func}"),
  1309. )
  1310. })?;
  1311. match subsetting_name.as_str() {
  1312. "field_defaults" => {
  1313. for arg in call.args {
  1314. self.field_defaults.apply_meta(arg)?;
  1315. }
  1316. Ok(())
  1317. }
  1318. _ => Err(Error::new_spanned(
  1319. &call.func,
  1320. format!("Illegal builder setting group name {subsetting_name}"),
  1321. )),
  1322. }
  1323. }
  1324. _ => Err(Error::new_spanned(expr, "Expected (<...>=<...>)")),
  1325. }
  1326. }
  1327. }
  1328. }