derive_builder_core_fork_arti/
builder_field.rs1use std::borrow::Cow;
2
3use proc_macro2::TokenStream;
4use quote::{ToTokens, TokenStreamExt};
5use syn;
6
7#[derive(Debug, Clone)]
33pub struct BuilderField<'a> {
34 pub field_ident: &'a syn::Ident,
36 pub field_type: BuilderFieldType<'a>,
38 pub field_visibility: Cow<'a, syn::Visibility>,
40 pub attrs: &'a [syn::Attribute],
42}
43
44impl<'a> ToTokens for BuilderField<'a> {
45 fn to_tokens(&self, tokens: &mut TokenStream) {
46 let ident = self.field_ident;
47 let vis = &self.field_visibility;
48 let ty = &self.field_type;
49 let attrs = self.attrs;
50 tokens.append_all(quote!(
51 #(#attrs)* #vis #ident: #ty,
52 ));
53 }
54}
55
56impl<'a> BuilderField<'a> {
57 pub fn default_initializer_tokens(&self) -> TokenStream {
59 let ident = self.field_ident;
60 quote! { #ident : ::derive_builder::export::core::default::Default::default(), }
61 }
62}
63
64#[derive(Debug, Clone)]
66pub enum BuilderFieldType<'a> {
67 Optional(&'a syn::Type),
69 Precise(&'a syn::Type),
71 Phantom(&'a syn::Type),
81}
82
83impl<'a> BuilderFieldType<'a> {
84 pub fn setter_type_info(&'a self) -> (&'a syn::Type, bool) {
91 match self {
92 BuilderFieldType::Optional(ty) => (ty, true),
93 BuilderFieldType::Precise(ty) => (ty, false),
94 BuilderFieldType::Phantom(_ty) => panic!("phantom fields should never have setters"),
95 }
96 }
97}
98
99impl<'a> ToTokens for BuilderFieldType<'a> {
100 fn to_tokens(&self, tokens: &mut TokenStream) {
101 match self {
102 BuilderFieldType::Optional(ty) => tokens.append_all(quote!(
103 ::derive_builder::export::core::option::Option<#ty>
104 )),
105 BuilderFieldType::Precise(ty) => ty.to_tokens(tokens),
106 BuilderFieldType::Phantom(ty) => tokens.append_all(quote!(
107 ::derive_builder::export::core::marker::PhantomData<#ty>
108 )),
109 }
110 }
111}
112
113#[cfg(test)] #[doc(hidden)]
117#[macro_export]
118macro_rules! default_builder_field {
119 () => {{
120 BuilderField {
121 field_ident: &syn::Ident::new("foo", ::proc_macro2::Span::call_site()),
122 field_type: BuilderFieldType::Optional(Box::leak(Box::new(parse_quote!(String)))),
123 field_visibility: ::std::borrow::Cow::Owned(parse_quote!(pub)),
124 attrs: &[parse_quote!(#[some_attr])],
125 }
126 }};
127}
128
129#[cfg(test)]
130mod tests {
131 #[allow(unused_imports)]
132 use super::*;
133
134 #[test]
135 fn setter_enabled() {
136 let field = default_builder_field!();
137
138 assert_eq!(
139 quote!(#field).to_string(),
140 quote!(
141 #[some_attr] pub foo: ::derive_builder::export::core::option::Option<String>,
142 )
143 .to_string()
144 );
145 }
146
147 #[test]
148 fn setter_disabled() {
149 let mut field = default_builder_field!();
150 field.field_visibility = Cow::Owned(syn::Visibility::Inherited);
151 field.field_type = match field.field_type {
152 BuilderFieldType::Optional(ty) => BuilderFieldType::Phantom(ty),
153 _ => panic!(),
154 };
155
156 assert_eq!(
157 quote!(#field).to_string(),
158 quote!(
159 #[some_attr]
160 foo: ::derive_builder::export::core::marker::PhantomData<String>,
161 )
162 .to_string()
163 );
164 }
165
166 #[test]
167 fn private_field() {
168 let private = Cow::Owned(syn::Visibility::Inherited);
169 let mut field = default_builder_field!();
170 field.field_visibility = private;
171
172 assert_eq!(
173 quote!(#field).to_string(),
174 quote!(
175 #[some_attr]
176 foo: ::derive_builder::export::core::option::Option<String>,
177 )
178 .to_string()
179 );
180 }
181}