mod.rs 50 KB

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