mod.rs 49 KB

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