Skip to content

Commit

Permalink
Forward allow and cfg attrs to builder
Browse files Browse the repository at this point in the history
If a struct is conditionally present, its builder should only be present in the same conditions.

If a struct disables lints, its builder should disable the same lints.

Fixes #222
  • Loading branch information
TedDriggs committed Mar 16, 2022
1 parent f7e6c71 commit faf0dbf
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 9 deletions.
3 changes: 3 additions & 0 deletions derive_builder/CHANGELOG.md
Expand Up @@ -2,6 +2,9 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
- Forward `allow` and `cfg` attributes from the deriving struct to the builder and its impl block #222

## [0.11.0] - 2022-03-15
- Support shorthand and long-form collection setters; `#[builder(setter(each = "..."))]` and `#[builder(setter(each(name = "...")))]` #234
- Allow collection setters to be generic over `Into` using `#[builder(setter(each(name = "...", into)))] #234 and #214
Expand Down
24 changes: 24 additions & 0 deletions derive_builder/tests/forward_allow_attr.rs
@@ -0,0 +1,24 @@
#![deny(non_snake_case)]

#[macro_use]
extern crate derive_builder;

#[derive(Builder)]
// If this attribute is not forwarded to both the struct and the impl block, there would
// be a compile error on either the field or the setter method name. Therefore, forwarding
// is working as-expected if this test compiles.
#[allow(non_snake_case)]
pub struct Example {
aPascalName: &'static str,
}

fn main() {
assert_eq!(
ExampleBuilder::default()
.aPascalName("hello")
.build()
.unwrap()
.aPascalName,
"hello"
);
}
7 changes: 7 additions & 0 deletions derive_builder_core/src/builder.rs
Expand Up @@ -92,6 +92,8 @@ pub struct Builder<'a> {
pub pattern: BuilderPattern,
/// Traits to automatically derive on the builder type.
pub derives: &'a [Path],
/// Attributes to include on the builder `struct` declaration and its inherent `impl`.
pub attrs: &'a [syn::Attribute],
/// When true, generate `impl Default for #ident` which calls the `create_empty` inherent method.
///
/// Note that the name of `create_empty` can be overridden; see the `create_empty` field for more.
Expand Down Expand Up @@ -168,13 +170,16 @@ impl<'a> ToTokens for Builder<'a> {
}
};

let attrs = self.attrs;

let builder_doc_comment = &self.doc_comment;
let deprecation_notes = &self.deprecation_notes.as_item();

#[cfg(not(feature = "clippy"))]
tokens.append_all(quote!(#[allow(clippy::all)]));

tokens.append_all(quote!(
#(#attrs)*
#derive_attr
#builder_doc_comment
#builder_vis struct #builder_ident #struct_generics #where_clause {
Expand All @@ -186,6 +191,7 @@ impl<'a> ToTokens for Builder<'a> {
tokens.append_all(quote!(#[allow(clippy::all)]));

tokens.append_all(quote!(
#(#attrs)*
#[allow(dead_code)]
impl #impl_generics #builder_ident #ty_generics #where_clause {
#(#functions)*
Expand Down Expand Up @@ -324,6 +330,7 @@ macro_rules! default_builder {
ident: syn::Ident::new("FooBuilder", ::proc_macro2::Span::call_site()),
pattern: Default::default(),
derives: &vec![],
attrs: &vec![],
impl_default: true,
create_empty: syn::Ident::new("create_empty", ::proc_macro2::Span::call_site()),
generics: None,
Expand Down
13 changes: 4 additions & 9 deletions derive_builder_core/src/macro_options/darling_opts.rs
Expand Up @@ -345,18 +345,12 @@ fn default_create_empty() -> Ident {
}

#[derive(Debug, Clone, FromDeriveInput)]
#[darling(
attributes(builder),
forward_attrs(doc, cfg, allow),
supports(struct_named)
)]
#[darling(attributes(builder), forward_attrs(cfg, allow), supports(struct_named))]
pub struct Options {
ident: Ident,

// These are currently unused, but that means the generated builder cannot have
// inherited the cfg or allow attributes from the base struct.
// see https://github.com/colin-kiegel/rust-derive-builder/issues/222
// attrs: Vec<Attribute>,
attrs: Vec<Attribute>,

vis: Visibility,

generics: Generics,
Expand Down Expand Up @@ -493,6 +487,7 @@ impl Options {
ident: self.builder_ident(),
pattern: self.pattern,
derives: &self.derive,
attrs: &self.attrs,
impl_default: {
let custom_constructor: bool = self.custom_constructor.into();
!custom_constructor
Expand Down

0 comments on commit faf0dbf

Please sign in to comment.