mod.rs 58 KB

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