diff --git a/derive_builder/CHANGELOG.md b/derive_builder/CHANGELOG.md index 050e9850..6faa7800 100644 --- a/derive_builder/CHANGELOG.md +++ b/derive_builder/CHANGELOG.md @@ -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 diff --git a/derive_builder/tests/forward_allow_attr.rs b/derive_builder/tests/forward_allow_attr.rs new file mode 100644 index 00000000..76826945 --- /dev/null +++ b/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" + ); +} diff --git a/derive_builder_core/src/builder.rs b/derive_builder_core/src/builder.rs index c52b7ef3..bed2ee02 100644 --- a/derive_builder_core/src/builder.rs +++ b/derive_builder_core/src/builder.rs @@ -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. @@ -168,6 +170,8 @@ 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(); @@ -175,6 +179,7 @@ impl<'a> ToTokens for Builder<'a> { 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 { @@ -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)* @@ -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, diff --git a/derive_builder_core/src/macro_options/darling_opts.rs b/derive_builder_core/src/macro_options/darling_opts.rs index 7e1d540a..e18e2d76 100644 --- a/derive_builder_core/src/macro_options/darling_opts.rs +++ b/derive_builder_core/src/macro_options/darling_opts.rs @@ -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, + attrs: Vec, + vis: Visibility, generics: Generics, @@ -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