mod.rs 48 KB

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