derive_builder_core-0.9.0/CHANGELOG.md010066400037200003720000000024721356110163200155510ustar0000000000000000# Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## 0.3.0 - 2018-10-22 - Updated all dependencies #138 ## 0.2.0 - 2017-12-16 ### Fixed - `unused_mut` lint (variable does not need to be mutable) #104 ## 0.1.7 - 2017-04-29 ### Fixed - for generic structs, apply the `T: Clone` type bound in builder impl instead of struct definition #91 - only emit the `T: Clone` type bound when it is actually needed, i.e. mutable/immutable pattern, but not owned pattern. ## 0.1.6 - 2017-04-26 ### Added - pre-build validation ## 0.1.5 - 2017-04-25 ### Added - derive traits on builder struct ## 0.1.4 - 2017-04-12 ### Added - try_setters ## 0.1.3 - 2017-04-11 ### Fixed - `setter(skip)` honors struct-inherited and explicit defaults #68 ## 0.1.2 - 2017-04-10 ### Added - Bindings to abstract over libstd/libcore ### Changed - Use `bindings: Bindings` instead of `no_std: bool` ### Fixed - support generic references in structs #55 - no_std support #63 ## 0.1.1 - 2017-04-08 ### Added - struct default ## 0.1 - 2017-03-25 ### Added - helper crate `derive_builder_core`: Allow `derive_builder` to use its own code generation technique. - helper structs implementing `quote::ToTokens`: Allow unit tests on code generation items. derive_builder_core-0.9.0/Cargo.toml.orig010066400037200003720000000014661356110163200166310ustar0000000000000000[package] name = "derive_builder_core" version = "0.9.0" authors = ["Colin Kiegel ", "Pascal Hertleif ", "Jan-Erik Rediger ", "Ted Driggs "] description = "Internal helper library for the derive_builder crate." repository = "https://github.com/colin-kiegel/rust-derive-builder" documentation = "https://docs.rs/derive_builder_core" license = "MIT/Apache-2.0" readme = "README.md" [features] logging = [ "log" ] [badges] travis-ci = { repository = "colin-kiegel/rust-derive-builder" } [dependencies] darling = "0.10.2" proc-macro2 = "1.0" quote = "1.0" syn = { version = "1.0", features = ["full", "extra-traits"] } log = { version = "0.4", optional = true } [dev-dependencies] pretty_assertions = "0.6" derive_builder_core-0.9.0/Cargo.toml0000644000000025471356110203400131350ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "derive_builder_core" version = "0.9.0" authors = ["Colin Kiegel ", "Pascal Hertleif ", "Jan-Erik Rediger ", "Ted Driggs "] description = "Internal helper library for the derive_builder crate." documentation = "https://docs.rs/derive_builder_core" readme = "README.md" license = "MIT/Apache-2.0" repository = "https://github.com/colin-kiegel/rust-derive-builder" [dependencies.darling] version = "0.10.2" [dependencies.log] version = "0.4" optional = true [dependencies.proc-macro2] version = "1.0" [dependencies.quote] version = "1.0" [dependencies.syn] version = "1.0" features = ["full", "extra-traits"] [dev-dependencies.pretty_assertions] version = "0.6" [features] logging = ["log"] [badges.travis-ci] repository = "colin-kiegel/rust-derive-builder" derive_builder_core-0.9.0/LICENSE-APACHE010066400037200003720000000261361356110163200156670ustar0000000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. derive_builder_core-0.9.0/LICENSE-MIT010066400037200003720000000021131356110163200153640ustar0000000000000000The MIT License (MIT) Copyright (c) 2016 rust-derive-builder contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. derive_builder_core-0.9.0/README.md010066400037200003720000000042621356110163200152160ustar0000000000000000[![Build status](https://travis-ci.org/colin-kiegel/rust-derive-builder.svg?branch=master)](https://travis-ci.org/colin-kiegel/rust-derive-builder) [![Documentation](https://docs.rs/derive_builder_core/badge.svg)](https://docs.rs/derive_builder_core) [![Latest version](https://img.shields.io/crates/v/derive_builder_core.svg)](https://crates.io/crates/derive_builder_core) [![All downloads](https://img.shields.io/crates/d/derive_builder_core.svg)](https://crates.io/crates/derive_builder_core) [![Downloads of latest version](https://img.shields.io/crates/dv/derive_builder_core.svg)](https://crates.io/crates/derive_builder_core) # Crate [`derive_builder_core`] **Important Note**: * You are probably looking for the [`derive_builder`] crate, which wraps this crate and is much more ergonomic to use. * The API of this crate might **change frequently** in the near future. The [`derive_builder`] crate also provides a much more stable API. ## Purpose This is an internal helper library of [`derive_builder`]. Its purpose is to allow [`derive_builder`] to use its own code generation technique, if needed. [`derive_builder_core`] might also be used in crates that [`derive_builder`] depends on - to break a dependency cycle. If [`derive_builder`] does not itself depend on _your_ crate, then you should consider using [`derive_builder`] instead of [`derive_builder_core`]. [`derive_builder`]: https://crates.io/crates/derive_builder [`derive_builder_core`]: https://crates.io/crates/derive_builder_core ## Documentation Please refer to [docs.rs/derive_builder_core](https://docs.rs/derive_builder_core) for the documentation of all published versions. ## [Changelog](CHANGELOG.md) Yes, we keep a changelog. ## License Licensed under either of - Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or ) - MIT license ([LICENSE-MIT](LICENSE-MIT) or ) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. derive_builder_core-0.9.0/src/bindings.rs010066400037200003720000000041151356110163200166660ustar0000000000000000use syn::{self, Path}; /// Bindings to be used by the generated code. #[derive(Debug, Clone, Copy, Default)] pub struct Bindings { /// Whether the generated code should comply with `#![no_std]`. pub no_std: bool, } impl Bindings { /// String type. pub fn string_ty(&self) -> Path { syn::parse_str(if self.no_std { "::alloc::string::String" } else { "::std::string::String" }) .unwrap() } /// Result type. pub fn result_ty(&self) -> Path { syn::parse_str(if self.no_std { "::core::result::Result" } else { "::std::result::Result" }) .unwrap() } /// Option type. pub fn option_ty(&self) -> Path { syn::parse_str(if self.no_std { "::core::option::Option" } else { "::std::option::Option" }) .unwrap() } /// PhantomData type. pub fn phantom_data_ty(&self) -> Path { syn::parse_str(if self.no_std { "::core::marker::PhantomData" } else { "::std::marker::PhantomData" }) .unwrap() } /// Default trait. pub fn default_trait(&self) -> Path { syn::parse_str(if self.no_std { "::core::default::Default" } else { "::std::default::Default" }) .unwrap() } /// Clone trait. pub fn clone_trait(&self) -> Path { syn::parse_str(if self.no_std { "::core::clone::Clone" } else { "::std::clone::Clone" }) .unwrap() } /// Into trait. #[allow(clippy::wrong_self_convention)] pub fn into_trait(&self) -> Path { syn::parse_str(if self.no_std { "::core::convert::Into" } else { "::std::convert::Into" }) .unwrap() } /// TryInto trait. pub fn try_into_trait(&self) -> Path { syn::parse_str(if self.no_std { "::core::convert::TryInto" } else { "::std::convert::TryInto" }) .unwrap() } } derive_builder_core-0.9.0/src/block.rs010066400037200003720000000045021356110163200161630ustar0000000000000000use std::str::FromStr; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt}; use syn; /// A permissive wrapper for expressions/blocks, implementing `quote::ToTokens`. /// /// - **full access** to variables environment. /// - **full access** to control-flow of the environment via `return`, `?` etc. /// /// # Examples /// /// Will expand to something like the following (depending on settings): /// /// ```rust /// # #[macro_use] /// # extern crate quote; /// # extern crate derive_builder_core; /// # use std::str::FromStr; /// # use derive_builder_core::Block; /// # fn main() { /// # let expr = Block::from_str("x+1").unwrap(); /// # assert_eq!(quote!(#expr).to_string(), quote!( /// { x + 1 } /// # ).to_string()); /// # } /// ``` #[derive(Debug, Clone)] pub struct Block(Vec); impl Default for Block { fn default() -> Self { "".parse().unwrap() } } impl ToTokens for Block { fn to_tokens(&self, tokens: &mut TokenStream) { let inner = &self.0; tokens.append_all(quote!( { #( #inner )* } )); } } impl FromStr for Block { type Err = String; /// Parses a string `s` to return a `Block`. /// /// # Errors /// /// When `expr` cannot be parsed as `Vec`. E.g. unbalanced /// opening/closing delimiters like `{`, `(` and `[` will be _rejected_ as /// parsing error. fn from_str(expr: &str) -> Result { let b: syn::Block = syn::parse_str(&format!("{{{}}}", expr)).map_err(|e| format!("{}", e))?; Ok(Self(b.stmts)) } } #[cfg(test)] mod test { #[allow(unused_imports)] use super::*; #[test] #[should_panic(expected = r#"LexError"#)] fn block_invalid_token_trees() { Block::from_str("let x = 2; { x+1").unwrap(); } #[test] fn block_delimited_token_tree() { let expr = Block::from_str("let x = 2; { x+1 }").unwrap(); assert_eq!( quote!(#expr).to_string(), quote!({ let x = 2; { x + 1 } }) .to_string() ); } #[test] fn block_single_token_tree() { let expr = Block::from_str("42").unwrap(); assert_eq!(quote!(#expr).to_string(), quote!({ 42 }).to_string()); } } derive_builder_core-0.9.0/src/build_method.rs010066400037200003720000000177171356110163200175440ustar0000000000000000use doc_comment::doc_comment_from; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt}; use syn; use Bindings; use Block; use BuilderPattern; use Initializer; use DEFAULT_STRUCT_NAME; /// Initializer for the struct fields in the build method, implementing /// `quote::ToTokens`. /// /// # Examples /// /// Will expand to something like the following (depending on settings): /// /// ```rust /// # extern crate proc_macro2; /// # #[macro_use] /// # extern crate quote; /// # extern crate syn; /// # #[macro_use(default_build_method)] /// # extern crate derive_builder_core; /// # use derive_builder_core::{BuildMethod, BuilderPattern}; /// # fn main() { /// # let build_method = default_build_method!(); /// # /// # assert_eq!(quote!(#build_method).to_string(), quote!( /// pub fn build(&self) -> ::std::result::Result { /// Ok(Foo { /// foo: self.foo, /// }) /// } /// # ).to_string()); /// # } /// ``` #[derive(Debug)] pub struct BuildMethod<'a> { /// Enables code generation for this build method. pub enabled: bool, /// Name of this build fn. pub ident: &'a syn::Ident, /// Visibility of the build method, e.g. `syn::Visibility::Public`. pub visibility: syn::Visibility, /// How the build method takes and returns `self` (e.g. mutably). pub pattern: BuilderPattern, /// Type of the target field. /// /// The corresonding builder field will be `Option`. pub target_ty: &'a syn::Ident, /// Type parameters and lifetimes attached to this builder struct. pub target_ty_generics: Option>, /// Field initializers for the target type. pub initializers: Vec, /// Doc-comment of the builder struct. pub doc_comment: Option, /// Bindings to libstd or libcore. pub bindings: Bindings, /// Default value for the whole struct. /// /// This will be in scope for all initializers as `__default`. pub default_struct: Option, /// Validation function with signature `&FooBuilder -> Result<(), String>` /// to call before the macro-provided struct buildout. pub validate_fn: Option<&'a syn::Path>, } impl<'a> ToTokens for BuildMethod<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let ident = &self.ident; let vis = &self.visibility; let target_ty = &self.target_ty; let target_ty_generics = &self.target_ty_generics; let initializers = &self.initializers; let self_param = match self.pattern { BuilderPattern::Owned => quote!(self), BuilderPattern::Mutable | BuilderPattern::Immutable => quote!(&self), }; let doc_comment = &self.doc_comment; let default_struct = self.default_struct.as_ref().map(|default_expr| { let ident = syn::Ident::new(DEFAULT_STRUCT_NAME, Span::call_site()); quote!(let #ident: #target_ty #target_ty_generics = #default_expr;) }); let validate_fn = self.validate_fn.as_ref().map(|vfn| quote!(#vfn(&self)?;)); let result = self.bindings.result_ty(); let string = self.bindings.string_ty(); if self.enabled { trace!("Deriving build method `{}`.", self.ident); tokens.append_all(quote!( #doc_comment #vis fn #ident(#self_param) -> #result<#target_ty #target_ty_generics, #string> { #validate_fn #default_struct Ok(#target_ty { #(#initializers)* }) } )) } else { trace!("Skipping build method."); } } } impl<'a> BuildMethod<'a> { /// Set a doc-comment for this item. pub fn doc_comment(&mut self, s: String) -> &mut Self { self.doc_comment = Some(doc_comment_from(s)); self } /// Populate the `BuildMethod` with appropriate initializers of the /// underlying struct. /// /// For each struct field this must be called with the appropriate /// initializer. pub fn push_initializer(&mut self, init: Initializer) -> &mut Self { self.initializers.push(quote!(#init)); self } } /// Helper macro for unit tests. This is _only_ public in order to be accessible /// from doc-tests too. #[doc(hidden)] #[macro_export] macro_rules! default_build_method { () => { BuildMethod { enabled: true, ident: &syn::Ident::new("build", ::proc_macro2::Span::call_site()), visibility: syn::parse_str("pub").unwrap(), pattern: BuilderPattern::Mutable, target_ty: &syn::Ident::new("Foo", ::proc_macro2::Span::call_site()), target_ty_generics: None, initializers: vec![quote!(foo: self.foo,)], doc_comment: None, bindings: Default::default(), default_struct: None, validate_fn: None, } }; } #[cfg(test)] mod tests { #[allow(unused_imports)] use super::*; #[test] fn std() { let build_method = default_build_method!(); assert_eq!( quote!(#build_method).to_string(), quote!( pub fn build(&self) -> ::std::result::Result { Ok(Foo { foo: self.foo, }) } ) .to_string() ); } #[test] fn no_std() { let mut build_method = default_build_method!(); build_method.bindings.no_std = true; assert_eq!( quote!(#build_method).to_string(), quote!( pub fn build(&self) -> ::core::result::Result { Ok(Foo { foo: self.foo, }) } ) .to_string() ); } #[test] fn default_struct() { let mut build_method = default_build_method!(); build_method.default_struct = Some("Default::default()".parse().unwrap()); assert_eq!( quote!(#build_method).to_string(), quote!( pub fn build(&self) -> ::std::result::Result { let __default: Foo = {Default::default()}; Ok(Foo { foo: self.foo, }) } ) .to_string() ); } #[test] fn skip() { let mut build_method = default_build_method!(); build_method.enabled = false; build_method.enabled = false; assert_eq!(quote!(#build_method).to_string(), quote!().to_string()); } #[test] fn rename() { let ident = syn::Ident::new("finish", Span::call_site()); let mut build_method: BuildMethod = default_build_method!(); build_method.ident = &ident; assert_eq!( quote!(#build_method).to_string(), quote!( pub fn finish(&self) -> ::std::result::Result { Ok(Foo { foo: self.foo, }) } ) .to_string() ) } #[test] fn validation() { let validate_path: syn::Path = syn::parse_str("IpsumBuilder::validate") .expect("Statically-entered path should be valid"); let mut build_method: BuildMethod = default_build_method!(); build_method.validate_fn = Some(&validate_path); assert_eq!( quote!(#build_method).to_string(), quote!( pub fn build(&self) -> ::std::result::Result { IpsumBuilder::validate(&self)?; Ok(Foo { foo: self.foo, }) } ) .to_string() ); } } derive_builder_core-0.9.0/src/builder.rs010066400037200003720000000264451356110163200165310ustar0000000000000000use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt}; use syn::punctuated::Punctuated; use syn::{self, Path, TraitBound, TraitBoundModifier, TypeParamBound}; use doc_comment::doc_comment_from; use Bindings; use BuildMethod; use BuilderField; use BuilderPattern; use DeprecationNotes; use Setter; /// Builder, implementing `quote::ToTokens`. /// /// # Examples /// /// Will expand to something like the following (depending on settings): /// /// ```rust /// # extern crate proc_macro2; /// # #[macro_use] /// # extern crate quote; /// # extern crate syn; /// # #[macro_use] /// # extern crate derive_builder_core; /// # use derive_builder_core::{Builder, DeprecationNotes}; /// # fn main() { /// # let builder = default_builder!(); /// # /// # assert_eq!(quote!(#builder).to_string(), quote!( /// #[derive(Default, Clone)] /// pub struct FooBuilder { /// foo: u32, /// } /// /// #[allow(dead_code)] /// impl FooBuilder { /// fn bar () -> { /// unimplemented!() /// } /// } /// # ).to_string()); /// # } /// ``` #[derive(Debug)] pub struct Builder<'a> { /// Enables code generation for this builder struct. pub enabled: bool, /// Name of this builder struct. pub ident: syn::Ident, /// Pattern of this builder struct. pub pattern: BuilderPattern, /// Traits to automatically derive on the builder type. pub derives: &'a [Path], /// Type parameters and lifetimes attached to this builder's struct /// definition. pub generics: Option<&'a syn::Generics>, /// Visibility of the builder struct, e.g. `syn::Visibility::Public`. pub visibility: syn::Visibility, /// Fields of the builder struct, e.g. `foo: u32,` /// /// Expects each entry to be terminated by a comma. pub fields: Vec, /// Functions of the builder struct, e.g. `fn bar() -> { unimplemented!() }` pub functions: Vec, /// Whether this builder must derive `Clone`. /// /// This is true even for a builder using the `owned` pattern if there is a field whose setter /// uses a different pattern. pub must_derive_clone: bool, /// Doc-comment of the builder struct. pub doc_comment: Option, /// Emit deprecation notes to the user. pub deprecation_notes: DeprecationNotes, /// Library bindings to use in emitted builder. pub bindings: Bindings, } impl<'a> ToTokens for Builder<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { if self.enabled { trace!("Deriving builder `{}`.", self.ident); let builder_vis = &self.visibility; let builder_ident = &self.ident; let bounded_generics = self.compute_impl_bounds(); let (impl_generics, _, _) = bounded_generics.split_for_impl(); let (struct_generics, ty_generics, where_clause) = self .generics .map(syn::Generics::split_for_impl) .map(|(i, t, w)| (Some(i), Some(t), Some(w))) .unwrap_or((None, None, None)); let builder_fields = &self.fields; let functions = &self.functions; // Create the comma-separated set of derived traits for the builder let derived_traits = { let default_trait: Path = parse_quote!(Default); let clone_trait: Path = parse_quote!(Clone); let mut traits: Punctuated<&Path, Token![,]> = Default::default(); traits.push(&default_trait); if self.must_derive_clone { traits.push(&clone_trait); } traits.extend(self.derives); quote!(#traits) }; let builder_doc_comment = &self.doc_comment; let deprecation_notes = &self.deprecation_notes.as_item(); debug!( "ty_generics={:?}, where_clause={:?}, struct_generics={:?}", ty_generics, where_clause, struct_generics ); tokens.append_all(quote!( #[derive(#derived_traits)] #builder_doc_comment #builder_vis struct #builder_ident #struct_generics #where_clause { #(#builder_fields)* } #[allow(dead_code)] impl #impl_generics #builder_ident #ty_generics #where_clause { #(#functions)* #deprecation_notes } )); } else { trace!("Skipping builder `{}`.", self.ident); } } } impl<'a> Builder<'a> { /// Set a doc-comment for this item. pub fn doc_comment(&mut self, s: String) -> &mut Self { self.doc_comment = Some(doc_comment_from(s)); self } /// Add a field to the builder pub fn push_field(&mut self, f: BuilderField) -> &mut Self { self.fields.push(quote!(#f)); self } /// Add a setter function to the builder pub fn push_setter_fn(&mut self, f: Setter) -> &mut Self { self.functions.push(quote!(#f)); self } /// Add final build function to the builder pub fn push_build_fn(&mut self, f: BuildMethod) -> &mut Self { self.functions.push(quote!(#f)); self } /// Add `Clone` trait bound to generic types for non-owned builders. /// This enables target types to declare generics without requiring a /// `Clone` impl. This is the same as how the built-in derives for /// `Clone`, `Default`, `PartialEq`, and other traits work. fn compute_impl_bounds(&self) -> syn::Generics { if let Some(type_gen) = self.generics { let mut generics = type_gen.clone(); if !self.pattern.requires_clone() || type_gen.type_params().next().is_none() { return generics; } let clone_bound = TypeParamBound::Trait(TraitBound { paren_token: None, modifier: TraitBoundModifier::None, lifetimes: None, path: self.bindings.clone_trait(), }); for typ in generics.type_params_mut() { typ.bounds.push(clone_bound.clone()); } generics } else { Default::default() } } } /// Helper macro for unit tests. This is _only_ public in order to be accessible /// from doc-tests too. #[doc(hidden)] #[macro_export] macro_rules! default_builder { () => { Builder { enabled: true, ident: syn::Ident::new("FooBuilder", ::proc_macro2::Span::call_site()), pattern: Default::default(), derives: &vec![], generics: None, visibility: syn::parse_str("pub").unwrap(), fields: vec![quote!(foo: u32,)], functions: vec![quote!(fn bar() -> { unimplemented!() })], must_derive_clone: true, doc_comment: None, deprecation_notes: DeprecationNotes::default(), bindings: Default::default(), } }; } #[cfg(test)] mod tests { #[allow(unused_imports)] use super::*; #[test] fn simple() { let builder = default_builder!(); assert_eq!( quote!(#builder).to_string(), quote!( #[derive(Default, Clone)] pub struct FooBuilder { foo: u32, } #[allow(dead_code)] impl FooBuilder { fn bar () -> { unimplemented!() } } ) .to_string() ); } // This test depends on the exact formatting of the `stringify`'d code, // so we don't automatically format the test #[rustfmt::skip] #[test] fn generic() { let ast: syn::DeriveInput = syn::parse_str(stringify!( struct Lorem<'a, T: Debug> where T: PartialEq { } )).expect("Couldn't parse item"); let generics = ast.generics; let mut builder = default_builder!(); builder.generics = Some(&generics); assert_eq!( quote!(#builder).to_string(), quote!( #[derive(Default, Clone)] pub struct FooBuilder<'a, T: Debug> where T: PartialEq { foo: u32, } #[allow(dead_code)] impl<'a, T: Debug + ::std::clone::Clone> FooBuilder<'a, T> where T: PartialEq { fn bar() -> { unimplemented!() } } ).to_string() ); } // This test depends on the exact formatting of the `stringify`'d code, // so we don't automatically format the test #[rustfmt::skip] #[test] fn generic_reference() { let ast: syn::DeriveInput = syn::parse_str(stringify!( struct Lorem<'a, T: 'a + Default> where T: PartialEq{ } )).expect("Couldn't parse item"); let generics = ast.generics; let mut builder = default_builder!(); builder.generics = Some(&generics); assert_eq!( quote!(#builder).to_string(), quote!( #[derive(Default, Clone)] pub struct FooBuilder<'a, T: 'a + Default> where T: PartialEq { foo: u32, } #[allow(dead_code)] impl<'a, T: 'a + Default + ::std::clone::Clone> FooBuilder<'a, T> where T: PartialEq { fn bar() -> { unimplemented!() } } ).to_string() ); } // This test depends on the exact formatting of the `stringify`'d code, // so we don't automatically format the test #[rustfmt::skip] #[test] fn owned_generic() { let ast: syn::DeriveInput = syn::parse_str(stringify!( struct Lorem<'a, T: Debug> where T: PartialEq { } )).expect("Couldn't parse item"); let generics = ast.generics; let mut builder = default_builder!(); builder.generics = Some(&generics); builder.pattern = BuilderPattern::Owned; builder.must_derive_clone = false; assert_eq!( quote!(#builder).to_string(), quote!( #[derive(Default)] pub struct FooBuilder<'a, T: Debug> where T: PartialEq { foo: u32, } #[allow(dead_code)] impl<'a, T: Debug> FooBuilder<'a, T> where T: PartialEq { fn bar() -> { unimplemented!() } } ).to_string() ); } #[test] fn disabled() { let mut builder = default_builder!(); builder.enabled = false; assert_eq!(quote!(#builder).to_string(), quote!().to_string()); } #[test] fn add_derives() { let derives = vec![syn::parse_str("Serialize").unwrap()]; let mut builder = default_builder!(); builder.derives = &derives; assert_eq!( quote!(#builder).to_string(), quote!( #[derive(Default, Clone, Serialize)] pub struct FooBuilder { foo: u32, } #[allow(dead_code)] impl FooBuilder { fn bar () -> { unimplemented!() } } ) .to_string() ); } } derive_builder_core-0.9.0/src/builder_field.rs010066400037200003720000000117331356110163200176660ustar0000000000000000use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt}; use syn; use Bindings; /// Field for the builder struct, implementing `quote::ToTokens`. /// /// # Examples /// /// Will expand to something like the following (depending on settings): /// /// ```rust /// # extern crate proc_macro2; /// # #[macro_use] /// # extern crate quote; /// # #[macro_use] /// # extern crate syn; /// # #[macro_use] /// # extern crate derive_builder_core; /// # use derive_builder_core::{BuilderField, BuilderPattern}; /// # fn main() { /// # let attrs = vec![parse_quote!(#[some_attr])]; /// # let mut field = default_builder_field!(); /// # field.attrs = attrs.as_slice(); /// # /// # assert_eq!(quote!(#field).to_string(), quote!( /// #[some_attr] pub foo: ::std::option::Option, /// # ).to_string()); /// # } /// ``` #[derive(Debug, Clone)] pub struct BuilderField<'a> { /// Name of the target field. pub field_ident: &'a syn::Ident, /// Type of the target field. /// /// The corresonding builder field will be `Option`. pub field_type: &'a syn::Type, /// Whether the builder implements a setter for this field. /// /// Note: We will fallback to `PhantomData` if the setter is disabled /// to hack around issues with unused generic type parameters - at /// least for now. pub field_enabled: bool, /// Visibility of this builder field, e.g. `syn::Visibility::Public`. pub field_visibility: syn::Visibility, /// Attributes which will be attached to this builder field. pub attrs: &'a [syn::Attribute], /// Bindings to libstd or libcore. pub bindings: Bindings, } impl<'a> ToTokens for BuilderField<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { if self.field_enabled { trace!("Deriving builder field for `{}`.", self.field_ident); let vis = &self.field_visibility; let ident = self.field_ident; let ty = self.field_type; let attrs = self.attrs; let option = self.bindings.option_ty(); tokens.append_all(quote!( #(#attrs)* #vis #ident: #option<#ty>, )); } else { trace!( "Skipping builder field for `{}`, fallback to PhantomData.", self.field_ident ); let ident = self.field_ident; let ty = self.field_type; let attrs = self.attrs; let phantom_data = self.bindings.phantom_data_ty(); tokens.append_all(quote!( #(#attrs)* #ident: #phantom_data<#ty>, )); } } } /// Helper macro for unit tests. This is _only_ public in order to be accessible /// from doc-tests too. #[doc(hidden)] #[macro_export] macro_rules! default_builder_field { () => {{ BuilderField { field_ident: &syn::Ident::new("foo", ::proc_macro2::Span::call_site()), field_type: &syn::parse_str("String").unwrap(), field_enabled: true, field_visibility: syn::parse_str("pub").unwrap(), attrs: &[parse_quote!(#[some_attr])], bindings: Default::default(), } }}; } #[cfg(test)] mod tests { #[allow(unused_imports)] use super::*; #[test] fn setter_enabled() { let field = default_builder_field!(); assert_eq!( quote!(#field).to_string(), quote!( #[some_attr] pub foo: ::std::option::Option, ) .to_string() ); } #[test] fn setter_disabled() { let mut field = default_builder_field!(); field.field_enabled = false; assert_eq!( quote!(#field).to_string(), quote!( #[some_attr] foo: ::std::marker::PhantomData, ) .to_string() ); } #[test] fn no_std_setter_enabled() { let mut field = default_builder_field!(); field.bindings.no_std = true; assert_eq!( quote!(#field).to_string(), quote!( #[some_attr] pub foo: ::core::option::Option, ) .to_string() ); } #[test] fn no_std_setter_disabled() { let mut field = default_builder_field!(); field.bindings.no_std = true; field.field_enabled = false; assert_eq!( quote!(#field).to_string(), quote!( #[some_attr] foo: ::core::marker::PhantomData, ) .to_string() ); } #[test] fn private_field() { let private = syn::Visibility::Inherited; let mut field = default_builder_field!(); field.field_visibility = private; assert_eq!( quote!(#field).to_string(), quote!( #[some_attr] foo: ::std::option::Option, ) .to_string() ); } } derive_builder_core-0.9.0/src/deprecation_notes.rs010066400037200003720000000062431356110163200206020ustar0000000000000000use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt}; use syn; /// Deprecation notes we want to emit to the user, implementing /// `quote::ToTokens`. /// /// Can be expanded at every place that accepts statements and item definitions /// (e.g. function bodys). /// /// # Examples /// /// Will expand to something like the following (depending on settings): /// /// ```rust /// # #[macro_use] /// # extern crate quote; /// # extern crate derive_builder_core; /// # use derive_builder_core::DeprecationNotes; /// # fn main() { /// # let mut note = DeprecationNotes::default(); /// # note.push("Some Warning".to_string()); /// # assert_eq!(quote!(#note).to_string(), quote!( /// { /// #[deprecated(note = "Some Warning")] /// fn derive_builder_core_deprecation_note() { } /// derive_builder_core_deprecation_note(); /// } /// # ).to_string()); /// # } /// ``` /// /// This will emit a deprecation warning in the downstream crate. Cool stuff. ^^ /// /// Proof of concept: /// - https://play.rust-lang.org/?gist=8394141c07d1f6d75d314818389eb4d8 #[derive(Debug, Default, Clone)] pub struct DeprecationNotes(Vec); impl ToTokens for DeprecationNotes { fn to_tokens(&self, tokens: &mut TokenStream) { for note in &self.0 { let fn_ident = syn::Ident::new("derive_builder_core_deprecation_note", Span::call_site()); tokens.append_all(quote!( { #[deprecated(note=#note)] fn #fn_ident() { } #fn_ident(); } )); } } } impl DeprecationNotes { /// Appends a note to the collection. pub fn push(&mut self, note: String) { self.0.push(note) } /// Extend this collection with all values from another collection. pub fn extend(&mut self, other: &Self) { for x in &other.0 { self.0.push(x.to_owned()) } } /// Create a view of these deprecation notes that can annotate a struct. pub const fn as_item(&self) -> DeprecationNotesAsItem { DeprecationNotesAsItem(self) } } /// A view of `DeprecationNotes` that can be used in any context that accept /// items. /// /// Expands to a function `__deprecation_notes` which emits the notes. #[derive(Debug)] pub struct DeprecationNotesAsItem<'a>(&'a DeprecationNotes); impl<'a> ToTokens for DeprecationNotesAsItem<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let deprecation_notes = self.0; if !deprecation_notes.0.is_empty() { tokens.append_all(quote!( #[doc(hidden)] fn derive_builder_core_deprecation_note() { #deprecation_notes } )) } } } #[test] fn deprecation_note() { let mut note = DeprecationNotes::default(); note.push("Some Warning".to_string()); assert_eq!( quote!(#note).to_string(), quote!({ #[deprecated(note = "Some Warning")] fn derive_builder_core_deprecation_note() {} derive_builder_core_deprecation_note(); }) .to_string() ); } derive_builder_core-0.9.0/src/doc_comment.rs010066400037200003720000000011711356110163200173570ustar0000000000000000use syn::Attribute; /// Doc-comment, implementing `quote::ToTokens`. /// /// # Examples /// /// Will expand to something like the following (depending on inner value): /// /// ```rust /// # #[macro_use] /// # extern crate quote; /// # extern crate syn; /// # extern crate derive_builder_core; /// # use derive_builder_core::doc_comment_from; /// # fn main() { /// # let doc_comment = doc_comment_from("foo".to_string()); /// # /// # assert_eq!(quote!(#doc_comment).to_string(), quote!( /// #[doc = "foo"] /// # ).to_string()); /// # } /// ``` pub fn doc_comment_from(s: String) -> Attribute { parse_quote!(#[doc=#s]) } derive_builder_core-0.9.0/src/initializer.rs010066400037200003720000000247631356110163200174270ustar0000000000000000use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt}; use syn; use Bindings; use Block; use BuilderPattern; use DEFAULT_STRUCT_NAME; /// Initializer for the target struct fields, implementing `quote::ToTokens`. /// /// Lives in the body of `BuildMethod`. /// /// # Examples /// /// Will expand to something like the following (depending on settings): /// /// ```rust /// # extern crate proc_macro2; /// # #[macro_use] /// # extern crate quote; /// # extern crate syn; /// # #[macro_use] /// # extern crate derive_builder_core; /// # use derive_builder_core::{DeprecationNotes, Initializer, BuilderPattern}; /// # fn main() { /// # let mut initializer = default_initializer!(); /// # initializer.default_value = Some("42".parse().unwrap()); /// # initializer.builder_pattern = BuilderPattern::Owned; /// # /// # assert_eq!(quote!(#initializer).to_string(), quote!( /// foo: match self.foo { /// Some(value) => value, /// None => { 42 }, /// }, /// # ).to_string()); /// # } /// ``` #[derive(Debug, Clone)] pub struct Initializer<'a> { /// Name of the target field. pub field_ident: &'a syn::Ident, /// Whether the builder implements a setter for this field. pub field_enabled: bool, /// How the build method takes and returns `self` (e.g. mutably). pub builder_pattern: BuilderPattern, /// Default value for the target field. /// /// This takes precedence over a default struct identifier. pub default_value: Option, /// Whether the build_method defines a default struct. pub use_default_struct: bool, /// Bindings to libstd or libcore. pub bindings: Bindings, } impl<'a> ToTokens for Initializer<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { trace!("Deriving initializer for `{}`.", self.field_ident); let struct_field = &self.field_ident; if self.field_enabled { let match_some = self.match_some(); let match_none = self.match_none(); let builder_field = &*struct_field; tokens.append_all(quote!( #struct_field: match self.#builder_field { #match_some, #match_none, }, )); } else { let default = self.default(); tokens.append_all(quote!( #struct_field: #default, )); } } } impl<'a> Initializer<'a> { /// To be used inside of `#struct_field: match self.#builder_field { ... }` fn match_some(&'a self) -> MatchSome { match self.builder_pattern { BuilderPattern::Owned => MatchSome::Move, BuilderPattern::Mutable | BuilderPattern::Immutable => { if self.bindings.no_std { MatchSome::CloneNoStd } else { MatchSome::Clone } } } } /// To be used inside of `#struct_field: match self.#builder_field { ... }` fn match_none(&'a self) -> MatchNone<'a> { match self.default_value { Some(ref expr) => MatchNone::DefaultTo(expr), None => { if self.use_default_struct { MatchNone::UseDefaultStructField(self.field_ident) } else if self.bindings.no_std { MatchNone::ReturnErrorNoStd(format!( "`{}` must be initialized", self.field_ident )) } else { MatchNone::ReturnError(format!("`{}` must be initialized", self.field_ident)) } } } } fn default(&'a self) -> TokenStream { match self.default_value { Some(ref expr) => quote!(#expr), None if self.use_default_struct => { let struct_ident = syn::Ident::new(DEFAULT_STRUCT_NAME, Span::call_site()); let field_ident = self.field_ident; quote!(#struct_ident.#field_ident) } None => { let default = self.bindings.default_trait(); quote!(#default::default()) } } } } /// To be used inside of `#struct_field: match self.#builder_field { ... }` enum MatchNone<'a> { /// Inner value must be a valid Rust expression DefaultTo(&'a Block), /// Inner value must be the field identifier /// /// The default struct must be in scope in the build_method. UseDefaultStructField(&'a syn::Ident), /// Inner value must be the field name ReturnError(String), /// Inner value must be the field name ReturnErrorNoStd(String), } impl<'a> ToTokens for MatchNone<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { match *self { MatchNone::DefaultTo(expr) => tokens.append_all(quote!( None => #expr )), MatchNone::UseDefaultStructField(field_ident) => { let struct_ident = syn::Ident::new(DEFAULT_STRUCT_NAME, Span::call_site()); tokens.append_all(quote!( None => #struct_ident.#field_ident )) } MatchNone::ReturnError(ref err) => tokens.append_all(quote!( None => return ::std::result::Result::Err(::std::string::String::from(#err)) )), MatchNone::ReturnErrorNoStd(ref err) => tokens.append_all(quote!( None => return ::core::result::Result::Err( ::alloc::string::String::from(#err)) )), } } } /// To be used inside of `#struct_field: match self.#builder_field { ... }` enum MatchSome { Move, Clone, CloneNoStd, } impl<'a> ToTokens for MatchSome { fn to_tokens(&self, tokens: &mut TokenStream) { match *self { Self::Move => tokens.append_all(quote!( Some(value) => value )), Self::Clone => tokens.append_all(quote!( Some(ref value) => ::std::clone::Clone::clone(value) )), Self::CloneNoStd => tokens.append_all(quote!( Some(ref value) => ::core::clone::Clone::clone(value) )), } } } /// Helper macro for unit tests. This is _only_ public in order to be accessible /// from doc-tests too. #[doc(hidden)] #[macro_export] macro_rules! default_initializer { () => { Initializer { field_ident: &syn::Ident::new("foo", ::proc_macro2::Span::call_site()), field_enabled: true, builder_pattern: BuilderPattern::Mutable, default_value: None, use_default_struct: false, bindings: Default::default(), } }; } #[cfg(test)] mod tests { #[allow(unused_imports)] use super::*; #[test] fn immutable() { let mut initializer = default_initializer!(); initializer.builder_pattern = BuilderPattern::Immutable; assert_eq!( quote!(#initializer).to_string(), quote!( foo: match self.foo { Some(ref value) => ::std::clone::Clone::clone(value), None => return ::std::result::Result::Err(::std::string::String::from( "`foo` must be initialized" )), }, ) .to_string() ); } #[test] fn mutable() { let mut initializer = default_initializer!(); initializer.builder_pattern = BuilderPattern::Mutable; assert_eq!( quote!(#initializer).to_string(), quote!( foo: match self.foo { Some(ref value) => ::std::clone::Clone::clone(value), None => return ::std::result::Result::Err(::std::string::String::from( "`foo` must be initialized" )), }, ) .to_string() ); } #[test] fn owned() { let mut initializer = default_initializer!(); initializer.builder_pattern = BuilderPattern::Owned; assert_eq!( quote!(#initializer).to_string(), quote!( foo: match self.foo { Some(value) => value, None => return ::std::result::Result::Err(::std::string::String::from( "`foo` must be initialized" )), }, ) .to_string() ); } #[test] fn default_value() { let mut initializer = default_initializer!(); initializer.default_value = Some("42".parse().unwrap()); assert_eq!( quote!(#initializer).to_string(), quote!( foo: match self.foo { Some(ref value) => ::std::clone::Clone::clone(value), None => { 42 }, }, ) .to_string() ); } #[test] fn default_struct() { let mut initializer = default_initializer!(); initializer.use_default_struct = true; assert_eq!( quote!(#initializer).to_string(), quote!( foo: match self.foo { Some(ref value) => ::std::clone::Clone::clone(value), None => __default.foo, }, ) .to_string() ); } #[test] fn setter_disabled() { let mut initializer = default_initializer!(); initializer.field_enabled = false; assert_eq!( quote!(#initializer).to_string(), quote!(foo: ::std::default::Default::default(),).to_string() ); } #[test] fn no_std() { let mut initializer = default_initializer!(); initializer.bindings.no_std = true; assert_eq!( quote!(#initializer).to_string(), quote!( foo: match self.foo { Some(ref value) => ::core::clone::Clone::clone(value), None => return ::core::result::Result::Err(::alloc::string::String::from( "`foo` must be initialized" )), }, ) .to_string() ); } #[test] fn no_std_setter_disabled() { let mut initializer = default_initializer!(); initializer.bindings.no_std = true; initializer.field_enabled = false; assert_eq!( quote!(#initializer).to_string(), quote!(foo: ::core::default::Default::default(),).to_string() ); } } derive_builder_core-0.9.0/src/lib.rs010066400037200003720000000036251356110163200156440ustar0000000000000000//! Internal helper library for the `derive_builder` crate. //! //! **Important Note**: //! //! * You are probably looking for the [`derive_builder`] crate, //! which wraps this crate and is much more ergonomic to use. //! * The API of this crate might **change frequently** in the near future. //! The [`derive_builder`] crate also provides a much more stable API. //! //! ## Purpose //! //! This is an internal helper library of [`derive_builder`]. Its purpose is to //! allow [`derive_builder`] to use its own code generation technique, if //! needed. //! //! [`derive_builder_core`] might also be used in crates that //! [`derive_builder`] depends on - again to break a dependency cycle. //! //! If [`derive_builder`] does not itself depend on _your_ crate, then you //! should consider using [`derive_builder`] instead of [`derive_builder_core`]. //! //! [`derive_builder`]: https://!crates.io/crates/derive_builder //! [`derive_builder_core`]: https://!crates.io/crates/derive_builder_core #![deny(warnings, missing_docs)] #![cfg_attr(test, recursion_limit = "100")] #[macro_use] extern crate darling; extern crate proc_macro; extern crate proc_macro2; #[macro_use] extern crate syn; #[macro_use] extern crate quote; #[cfg(feature = "logging")] #[macro_use] extern crate log; #[cfg(test)] #[macro_use] extern crate pretty_assertions; #[cfg(not(feature = "logging"))] #[macro_use] mod log_disabled; mod bindings; mod block; mod build_method; mod builder; mod builder_field; mod deprecation_notes; mod doc_comment; mod initializer; mod options; mod setter; pub use bindings::Bindings; pub use block::Block; pub use build_method::BuildMethod; pub use builder::Builder; pub use builder_field::BuilderField; pub use deprecation_notes::DeprecationNotes; pub use doc_comment::doc_comment_from; pub use initializer::Initializer; pub use options::BuilderPattern; pub use setter::Setter; const DEFAULT_STRUCT_NAME: &str = "__default"; derive_builder_core-0.9.0/src/log_disabled.rs010066400037200003720000000020311356110163200174740ustar0000000000000000/// Overrides for https://docs.rs/log/#macros /// /// Source shared by `derive_builder_core` and `derive_builder` via symlink. #[allow(unknown_lints, unused_macros)] macro_rules! log_enabled { ($($x:tt)*) => { false }; } // delegate to format_args and throw away the result to avoid `unused variable` // lints. // The compiler should be able to optimize this away. #[allow(unknown_lints, unused_macros)] macro_rules! debug { ($( $x:tt )*) => { format_args!($( $x )*); } } #[allow(unknown_lints, unused_macros)] macro_rules! error { ($( $x:tt )*) => { format_args!($( $x )*); } } #[allow(unknown_lints, unused_macros)] macro_rules! info { ($( $x:tt )*) => { format_args!($( $x )*); } } #[allow(unknown_lints, unused_macros)] macro_rules! log { ($( $x:tt )*) => { format_args!($( $x )*); } } #[allow(unknown_lints, unused_macros)] macro_rules! trace { ($( $x:tt )*) => { format_args!($( $x )*); } } #[allow(unknown_lints, unused_macros)] macro_rules! warn { ($( $x:tt )*) => { format_args!($( $x )*); } } derive_builder_core-0.9.0/src/options.rs010066400037200003720000000021661356110163200165700ustar0000000000000000/// Controls the signature of a setter method, /// more specifically how `self` is passed and returned. /// /// It can also be generalized to methods with different parameter sets and /// return types, e.g. the `build()` method. #[derive(PartialEq, Eq, Debug, Clone, Copy, FromMeta)] pub enum BuilderPattern { /// E.g. `fn bar(self, bar: Bar) -> Self`. Owned, /// E.g. `fn bar(&mut self, bar: Bar) -> &mut Self`. Mutable, /// E.g. `fn bar(&self, bar: Bar) -> Self`. /// /// Note: /// - Needs to `clone` in order to return an _updated_ instance of `Self`. /// - There is a great chance that the Rust compiler (LLVM) will /// optimize chained `clone` calls away in release mode. /// Therefore this turns out not to be as bad as it sounds. Immutable, } impl BuilderPattern { /// Returns true if this style of builder needs to be able to clone its /// fields during the `build` method. pub fn requires_clone(&self) -> bool { *self != Self::Owned } } /// Defaults to `Mutable`. impl Default for BuilderPattern { fn default() -> Self { Self::Mutable } } derive_builder_core-0.9.0/src/setter.rs010066400037200003720000000414501356110163200164020ustar0000000000000000#![allow(clippy::useless_let_if_seq)] use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt}; use syn; use Bindings; use BuilderPattern; use DeprecationNotes; /// Setter for the struct fields in the build method, implementing /// `quote::ToTokens`. /// /// # Examples /// /// Will expand to something like the following (depending on settings): /// /// ```rust /// # extern crate proc_macro2; /// # #[macro_use] /// # extern crate quote; /// # extern crate syn; /// # #[macro_use] /// # extern crate derive_builder_core; /// # use derive_builder_core::{Setter, BuilderPattern}; /// # fn main() { /// # let mut setter = default_setter!(); /// # setter.pattern = BuilderPattern::Mutable; /// # /// # assert_eq!(quote!(#setter).to_string(), quote!( /// # #[allow(unused_mut)] /// pub fn foo(&mut self, value: Foo) -> &mut Self { /// let mut new = self; /// new.foo = ::std::option::Option::Some(value); /// new /// } /// # ).to_string()); /// # } /// ``` #[derive(Debug, Clone)] pub struct Setter<'a> { /// Enables code generation for this setter fn. pub setter_enabled: bool, /// Enables code generation for the `try_` variant of this setter fn. pub try_setter: bool, /// Visibility of the setter, e.g. `syn::Visibility::Public`. pub visibility: syn::Visibility, /// How the setter method takes and returns `self` (e.g. mutably). pub pattern: BuilderPattern, /// Attributes which will be attached to this setter fn. pub attrs: &'a [syn::Attribute], /// Name of this setter fn. pub ident: syn::Ident, /// Name of the target field. pub field_ident: &'a syn::Ident, /// Type of the target field. /// /// The corresonding builder field will be `Option`. pub field_type: &'a syn::Type, /// Make the setter generic over `Into`, where `T` is the field type. pub generic_into: bool, /// Make the setter remove the Option wrapper from the setter, remove the need to call Some(...). /// when combined with into, the into is used on the content Type of the Option. pub strip_option: bool, /// Emit deprecation notes to the user. pub deprecation_notes: &'a DeprecationNotes, /// Bindings to libstd or libcore. pub bindings: Bindings, } impl<'a> ToTokens for Setter<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { if self.setter_enabled { trace!("Deriving setter for `{}`.", self.field_ident); let field_type = self.field_type; let pattern = self.pattern; let vis = &self.visibility; let field_ident = self.field_ident; let ident = &self.ident; let attrs = self.attrs; let deprecation_notes = self.deprecation_notes; let clone = self.bindings.clone_trait(); let option = self.bindings.option_ty(); let into = self.bindings.into_trait(); let (ty, stripped_option) = { if self.strip_option { match extract_type_from_option(field_type) { Some(ty) => (ty, true), None => (field_type, false), } } else { (field_type, false) } }; let self_param: TokenStream; let return_ty: TokenStream; let self_into_return_ty: TokenStream; match pattern { BuilderPattern::Owned => { self_param = quote!(self); return_ty = quote!(Self); self_into_return_ty = quote!(self); } BuilderPattern::Mutable => { self_param = quote!(&mut self); return_ty = quote!(&mut Self); self_into_return_ty = quote!(self); } BuilderPattern::Immutable => { self_param = quote!(&self); return_ty = quote!(Self); self_into_return_ty = quote!(#clone::clone(self)); } }; let ty_params: TokenStream; let param_ty: TokenStream; let mut into_value: TokenStream; if self.generic_into { ty_params = quote!(>); param_ty = quote!(VALUE); into_value = quote!(value.into()); } else { ty_params = quote!(); param_ty = quote!(#ty); into_value = quote!(value); } if stripped_option { into_value = quote!(#option::Some(#into_value)); } tokens.append_all(quote!( #(#attrs)* #[allow(unused_mut)] #vis fn #ident #ty_params (#self_param, value: #param_ty) -> #return_ty { #deprecation_notes let mut new = #self_into_return_ty; new.#field_ident = #option::Some(#into_value); new })); if self.try_setter { let try_into = self.bindings.try_into_trait(); let try_ty_params = quote!(>); let try_ident = syn::Ident::new(&format!("try_{}", ident), Span::call_site()); let result = self.bindings.result_ty(); tokens.append_all(quote!( #(#attrs)* #vis fn #try_ident #try_ty_params (#self_param, value: VALUE) -> #result<#return_ty, VALUE::Error> { let converted : #ty = value.try_into()?; let mut new = #self_into_return_ty; new.#field_ident = #option::Some(converted); Ok(new) })); } else { trace!("Skipping try_setter for `{}`.", self.field_ident); } } else { trace!("Skipping setter for `{}`.", self.field_ident); } } } // adapted from https://stackoverflow.com/a/55277337/469066 // Note that since syn is a parser, it works with tokens. // We cannot know for sure that this is an Option. // The user could, for example, `type MaybeString = std::option::Option` // We cannot handle those arbitrary names. fn extract_type_from_option(ty: &syn::Type) -> Option<&syn::Type> { use syn::punctuated::Pair; use syn::token::Colon2; use syn::{GenericArgument, Path, PathArguments, PathSegment}; fn extract_type_path(ty: &syn::Type) -> Option<&Path> { match *ty { syn::Type::Path(ref typepath) if typepath.qself.is_none() => Some(&typepath.path), _ => None, } } // TODO store (with lazy static) precomputed parsing of Option when support of rust 1.18 will be removed (incompatible with lazy_static) // TODO maybe optimization, reverse the order of segments fn extract_option_segment(path: &Path) -> Option> { let idents_of_path = path.segments.iter().fold(String::new(), |mut acc, v| { acc.push_str(&v.ident.to_string()); acc.push('|'); acc }); vec!["Option|", "std|option|Option|", "core|option|Option|"] .into_iter() .find(|s| idents_of_path == *s) .and_then(|_| path.segments.last().map(Pair::End)) } extract_type_path(ty) .and_then(|path| extract_option_segment(path)) .and_then(|pair_path_segment| { let type_params = &pair_path_segment.into_value().arguments; // It should have only on angle-bracketed param (""): match *type_params { PathArguments::AngleBracketed(ref params) => params.args.first(), _ => None, } }) .and_then(|generic_arg| match *generic_arg { GenericArgument::Type(ref ty) => Some(ty), _ => None, }) } /// Helper macro for unit tests. This is _only_ public in order to be accessible /// from doc-tests too. #[doc(hidden)] #[macro_export] macro_rules! default_setter { () => { Setter { setter_enabled: true, try_setter: false, visibility: syn::parse_str("pub").unwrap(), pattern: BuilderPattern::Mutable, attrs: &vec![], ident: syn::Ident::new("foo", ::proc_macro2::Span::call_site()), field_ident: &syn::Ident::new("foo", ::proc_macro2::Span::call_site()), field_type: &syn::parse_str("Foo").unwrap(), generic_into: false, strip_option: false, deprecation_notes: &Default::default(), bindings: Default::default(), }; }; } #[cfg(test)] mod tests { #[allow(unused_imports)] use super::*; #[test] fn immutable() { let mut setter = default_setter!(); setter.pattern = BuilderPattern::Immutable; assert_eq!( quote!(#setter).to_string(), quote!( #[allow(unused_mut)] pub fn foo(&self, value: Foo) -> Self { let mut new = ::std::clone::Clone::clone(self); new.foo = ::std::option::Option::Some(value); new } ) .to_string() ); } #[test] fn mutable() { let mut setter = default_setter!(); setter.pattern = BuilderPattern::Mutable; assert_eq!( quote!(#setter).to_string(), quote!( #[allow(unused_mut)] pub fn foo(&mut self, value: Foo) -> &mut Self { let mut new = self; new.foo = ::std::option::Option::Some(value); new } ) .to_string() ); } #[test] fn owned() { let mut setter = default_setter!(); setter.pattern = BuilderPattern::Owned; assert_eq!( quote!(#setter).to_string(), quote!( #[allow(unused_mut)] pub fn foo(self, value: Foo) -> Self { let mut new = self; new.foo = ::std::option::Option::Some(value); new } ) .to_string() ); } #[test] fn private() { let vis = syn::Visibility::Inherited; let mut setter = default_setter!(); setter.visibility = vis; assert_eq!( quote!(#setter).to_string(), quote!( #[allow(unused_mut)] fn foo(&mut self, value: Foo) -> &mut Self { let mut new = self; new.foo = ::std::option::Option::Some(value); new } ) .to_string() ); } #[test] fn generic() { let mut setter = default_setter!(); setter.generic_into = true; assert_eq!( quote!(#setter).to_string(), quote!( #[allow(unused_mut)] pub fn foo >(&mut self, value: VALUE) -> &mut Self { let mut new = self; new.foo = ::std::option::Option::Some(value.into()); new } ).to_string() ); } #[test] fn strip_option() { let ty = syn::parse_str("Option").unwrap(); let mut setter = default_setter!(); setter.strip_option = true; setter.field_type = &ty; assert_eq!( quote!(#setter).to_string(), quote!( #[allow(unused_mut)] pub fn foo(&mut self, value: Foo) -> &mut Self { let mut new = self; new.foo = ::std::option::Option::Some(::std::option::Option::Some(value)); new } ) .to_string() ); } #[test] fn strip_option_into() { let ty = syn::parse_str("Option").unwrap(); let mut setter = default_setter!(); setter.strip_option = true; setter.generic_into = true; setter.field_type = &ty; assert_eq!( quote!(#setter).to_string(), quote!( #[allow(unused_mut)] pub fn foo>(&mut self, value: VALUE) -> &mut Self { let mut new = self; new.foo = ::std::option::Option::Some(::std::option::Option::Some(value.into())); new } ) .to_string() ); } // including try_setter #[test] fn full() { //named!(outer_attrs -> Vec, many0!(syn::Attribute::parse_outer)); //let attrs = outer_attrs.parse_str("#[some_attr]").unwrap(); let attrs: Vec = vec![parse_quote!(#[some_attr])]; let mut deprecated = DeprecationNotes::default(); deprecated.push("Some example.".to_string()); let mut setter = default_setter!(); setter.attrs = attrs.as_slice(); setter.generic_into = true; setter.deprecation_notes = &deprecated; setter.try_setter = true; assert_eq!( quote!(#setter).to_string(), quote!( #[some_attr] #[allow(unused_mut)] pub fn foo >(&mut self, value: VALUE) -> &mut Self { #deprecated let mut new = self; new.foo = ::std::option::Option::Some(value.into()); new } #[some_attr] pub fn try_foo>(&mut self, value: VALUE) -> ::std::result::Result<&mut Self, VALUE::Error> { let converted : Foo = value.try_into()?; let mut new = self; new.foo = ::std::option::Option::Some(converted); Ok(new) } ).to_string() ); } #[test] fn no_std() { let mut setter = default_setter!(); setter.bindings.no_std = true; setter.pattern = BuilderPattern::Immutable; assert_eq!( quote!(#setter).to_string(), quote!( #[allow(unused_mut)] pub fn foo(&self, value: Foo) -> Self { let mut new = ::core::clone::Clone::clone(self); new.foo = ::core::option::Option::Some(value); new } ) .to_string() ); } #[test] fn no_std_generic() { let mut setter = default_setter!(); setter.bindings.no_std = true; setter.generic_into = true; assert_eq!( quote!(#setter).to_string(), quote!( #[allow(unused_mut)] pub fn foo >(&mut self, value: VALUE) -> &mut Self { let mut new = self; new.foo = ::core::option::Option::Some(value.into()); new } ).to_string() ); } #[test] fn setter_disabled() { let mut setter = default_setter!(); setter.setter_enabled = false; assert_eq!(quote!(#setter).to_string(), quote!().to_string()); } #[test] fn try_setter() { let mut setter: Setter = default_setter!(); setter.pattern = BuilderPattern::Mutable; setter.try_setter = true; assert_eq!( quote!(#setter).to_string(), quote!( #[allow(unused_mut)] pub fn foo(&mut self, value: Foo) -> &mut Self { let mut new = self; new.foo = ::std::option::Option::Some(value); new } pub fn try_foo>(&mut self, value: VALUE) -> ::std::result::Result<&mut Self, VALUE::Error> { let converted : Foo = value.try_into()?; let mut new = self; new.foo = ::std::option::Option::Some(converted); Ok(new) } ) .to_string() ); } #[test] fn extract_type_from_option_on_simple_type() { let ty_foo = syn::parse_str("Foo").unwrap(); assert_eq!(extract_type_from_option(&ty_foo), None); for s in vec![ "Option", "std::option::Option", "::std::option::Option", "core::option::Option", "::core::option::Option", ] { let ty_foo_opt = syn::parse_str(s).unwrap(); assert_eq!(extract_type_from_option(&ty_foo_opt), Some(&ty_foo)); } } } derive_builder_core-0.9.0/.cargo_vcs_info.json0000644000000001121356110203400151210ustar00{ "git": { "sha1": "7c093c1cb3a2c20bbd14d1ea94c05d8a8fdb7c52" } }