diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
commit | c23a457e72abe608715ac76f076f47dc42af07a5 (patch) | |
tree | 2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /vendor/derive_builder_core | |
parent | Releasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip |
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/derive_builder_core')
23 files changed, 4048 insertions, 0 deletions
diff --git a/vendor/derive_builder_core/.cargo-checksum.json b/vendor/derive_builder_core/.cargo-checksum.json new file mode 100644 index 000000000..d59632bfe --- /dev/null +++ b/vendor/derive_builder_core/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"85e8674412cdf7bd55e211eef4ce89acc765904b390868831a552ffa1b55e05d","Cargo.toml":"0b34edf7c141b6d66f3ac6c176f844499af65601ce52d5bc908a0c16db136eb1","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"8c9612877aacfa1b42f5e80b679e6c3c93a7ba2bb99dfaf6e87e200dca4b4e6c","README.md":"3527c7ed45f590c715500167fc784c1357bc02af1d4b3d361dd1195faea986ea","src/block.rs":"7e53655b9165c0484f28aae9d1a60478e7ccf8b9293de5ebadb35edfe690c0c9","src/build_method.rs":"ee07c2711dc126c3896339bb72b12c2f7602a9f974569210a1814c244f0337b0","src/builder.rs":"b282dbb13075585455359556d3075386a8c8144a9283c66d4372e37383672f3f","src/builder_field.rs":"861161e98ef6c8dba72be86446514127d59f046a2060b8b5e32e17dd4ffeaed0","src/change_span.rs":"ca77c13950a64bf8975ee4cef4af22129d84536409668a290f6a49ee9f6c8433","src/default_expression.rs":"1e702664533c0a151865dd8108e6d9e4b2b405d71c2af7cb82850a461e26b792","src/deprecation_notes.rs":"94e3a9d40016008fc1f8470d90ef6413ffe544055457ff3c99545a8f08082465","src/doc_comment.rs":"0d3b7ae4790564e47bdde3592c4bd6882cada859a5f1a3288226a7c740606179","src/doc_tpl/builder_method.md":"2e0e690c13b28f36b98be2ab63f0b4237a29ef034d112ebab45b0a8a0859c487","src/doc_tpl/builder_struct.md":"3694e0eb1aa481ec1728269cb39ab01b5c151c21f83e7f72cadf8daf1e481104","src/doc_tpl/mod.rs":"221631f07f31489c7653d418bca32bf864770af6d9d9ec225c86eb0f1c414229","src/initializer.rs":"8d5eb14dc01ab66ee3736189e3997fb1222f4b74ffba974f05edc1101f298fad","src/lib.rs":"b96b54bc0b8b4218bed451b890993c2bfa7c433a936ba27e711d70035b7e6096","src/macro_options/darling_opts.rs":"bf2f0928ee6bea289567d09b0bb279ecd48b95d2c432c6a1c8f27290cc031072","src/macro_options/mod.rs":"fbe1fa4a604cd565dd55a00089e5912a9c9dbc5217cd36651737366a6387da65","src/options.rs":"5c7eaa563606851b54775911b2f8b4a22edda29c9086f8df69ac1c0f341d09ea","src/setter.rs":"95cdf6dcf32f989c277b50a04768c2e71bbe0f27c6025732b784dc77b6aecc36"},"package":"c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f"}
\ No newline at end of file diff --git a/vendor/derive_builder_core/CHANGELOG.md b/vendor/derive_builder_core/CHANGELOG.md new file mode 100644 index 000000000..6cb2f2dac --- /dev/null +++ b/vendor/derive_builder_core/CHANGELOG.md @@ -0,0 +1,62 @@ +# 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. diff --git a/vendor/derive_builder_core/Cargo.toml b/vendor/derive_builder_core/Cargo.toml new file mode 100644 index 000000000..fe58c9645 --- /dev/null +++ b/vendor/derive_builder_core/Cargo.toml @@ -0,0 +1,47 @@ +# 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 are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +name = "derive_builder_core" +version = "0.12.0" +authors = [ + "Colin Kiegel <kiegel@gmx.de>", + "Pascal Hertleif <killercup@gmail.com>", + "Jan-Erik Rediger <janerik@fnordig.de>", + "Ted Driggs <ted.driggs@outlook.com>", +] +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.14.0" + +[dependencies.proc-macro2] +version = "1.0.37" + +[dependencies.quote] +version = "1.0.18" + +[dependencies.syn] +version = "1.0.91" +features = [ + "full", + "extra-traits", +] + +[dev-dependencies.pretty_assertions] +version = "0.6.1" + +[features] +clippy = [] diff --git a/vendor/derive_builder_core/LICENSE-APACHE b/vendor/derive_builder_core/LICENSE-APACHE new file mode 100644 index 000000000..8f71f43fe --- /dev/null +++ b/vendor/derive_builder_core/LICENSE-APACHE @@ -0,0 +1,202 @@ + 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. + diff --git a/vendor/derive_builder_core/LICENSE-MIT b/vendor/derive_builder_core/LICENSE-MIT new file mode 100644 index 000000000..48b7653f4 --- /dev/null +++ b/vendor/derive_builder_core/LICENSE-MIT @@ -0,0 +1,21 @@ +The 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. diff --git a/vendor/derive_builder_core/README.md b/vendor/derive_builder_core/README.md new file mode 100644 index 000000000..4565ad4ab --- /dev/null +++ b/vendor/derive_builder_core/README.md @@ -0,0 +1,54 @@ +![Build](https://github.com/colin-kiegel/rust-derive-builder/workflows/Build/badge.svg?branch=master) +[![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 <http://www.apache.org/licenses/LICENSE-2.0>) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>) + +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. diff --git a/vendor/derive_builder_core/src/block.rs b/vendor/derive_builder_core/src/block.rs new file mode 100644 index 000000000..d412f9010 --- /dev/null +++ b/vendor/derive_builder_core/src/block.rs @@ -0,0 +1,99 @@ +use std::convert::TryFrom; + +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::{self, spanned::Spanned, Block, LitStr}; + +/// A wrapper for expressions/blocks which automatically adds the start and end +/// braces. +/// +/// - **full access** to variables environment. +/// - **full access** to control-flow of the environment via `return`, `?` etc. +#[derive(Debug, Clone)] +pub struct BlockContents(Block); + +impl BlockContents { + pub fn is_empty(&self) -> bool { + self.0.stmts.is_empty() + } +} + +impl ToTokens for BlockContents { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.0.to_tokens(tokens) + } +} + +impl TryFrom<&'_ LitStr> for BlockContents { + type Error = syn::Error; + + fn try_from(s: &LitStr) -> Result<Self, Self::Error> { + let mut block_str = s.value(); + block_str.insert(0, '{'); + block_str.push('}'); + LitStr::new(&block_str, s.span()).parse().map(Self) + } +} + +impl From<syn::Expr> for BlockContents { + fn from(v: syn::Expr) -> Self { + Self(Block { + brace_token: syn::token::Brace(v.span()), + stmts: vec![syn::Stmt::Expr(v)], + }) + } +} + +impl darling::FromMeta for BlockContents { + fn from_value(value: &syn::Lit) -> darling::Result<Self> { + if let syn::Lit::Str(s) = value { + let contents = BlockContents::try_from(s)?; + if contents.is_empty() { + Err(darling::Error::unknown_value("").with_span(s)) + } else { + Ok(contents) + } + } else { + Err(darling::Error::unexpected_lit_type(value)) + } + } +} + +#[cfg(test)] +mod test { + use std::convert::TryInto; + + use super::*; + use proc_macro2::Span; + + fn parse(s: &str) -> Result<BlockContents, syn::Error> { + (&LitStr::new(s, Span::call_site())).try_into() + } + + #[test] + #[should_panic(expected = r#"lex error"#)] + fn block_invalid_token_trees() { + parse("let x = 2; { x+1").unwrap(); + } + + #[test] + fn block_delimited_token_tree() { + let expr = parse("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 = parse("42").unwrap(); + assert_eq!(quote!(#expr).to_string(), quote!({ 42 }).to_string()); + } +} diff --git a/vendor/derive_builder_core/src/build_method.rs b/vendor/derive_builder_core/src/build_method.rs new file mode 100644 index 000000000..514fb6ab0 --- /dev/null +++ b/vendor/derive_builder_core/src/build_method.rs @@ -0,0 +1,259 @@ +use std::borrow::Cow; + +use doc_comment_from; +use proc_macro2::{Span, TokenStream}; +use quote::{ToTokens, TokenStreamExt}; +use syn; +use syn::spanned::Spanned; +use BuilderPattern; +use Initializer; +use DEFAULT_STRUCT_NAME; + +use crate::DefaultExpression; + +/// Initializer for the struct fields in the build method, implementing +/// `quote::ToTokens`. +/// +/// # Examples +/// +/// Will expand to something like the following (depending on settings): +/// +/// ```rust,ignore +/// # 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) -> ::derive_builder::export::core::result::Result<Foo, FooBuilderError> { +/// Ok(Foo { +/// foo: self.foo, +/// }) +/// } +/// # ).to_string()); +/// # } +/// ``` +#[derive(Debug)] +pub struct BuildMethod<'a> { + /// Path to the root of the derive_builder crate. + pub crate_root: &'a syn::Path, + /// 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: Cow<'a, 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<field_type>`. + pub target_ty: &'a syn::Ident, + /// Type parameters and lifetimes attached to this builder struct. + pub target_ty_generics: Option<syn::TypeGenerics<'a>>, + /// Type of error. + pub error_ty: syn::Path, + /// Field initializers for the target type. + pub initializers: Vec<TokenStream>, + /// Doc-comment of the builder struct. + pub doc_comment: Option<syn::Attribute>, + /// Default value for the whole struct. + /// + /// This will be in scope for all initializers as `__default`. + pub default_struct: Option<&'a DefaultExpression>, + /// 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 default_expr = default_expr.with_crate_root(self.crate_root); + 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_spanned!(vfn.span() => #vfn(&self)?;)); + let error_ty = &self.error_ty; + + if self.enabled { + let crate_root = &self.crate_root; + tokens.append_all(quote!( + #doc_comment + #vis fn #ident(#self_param) + -> #crate_root::export::core::result::Result<#target_ty #target_ty_generics, #error_ty> + { + #validate_fn + #default_struct + Ok(#target_ty { + #(#initializers)* + }) + } + )) + } + } +} + +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 + } +} + +// pub struct BuildMethodError { +// is_generated: bool, +// ident: syn::Ident, +// } + +/// 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 { + // Deliberately don't use the default value here - make sure + // that all test cases are passing crate_root through properly. + crate_root: &parse_quote!(::db), + enabled: true, + ident: &syn::Ident::new("build", ::proc_macro2::Span::call_site()), + visibility: ::std::borrow::Cow::Owned(syn::parse_quote!(pub)), + pattern: BuilderPattern::Mutable, + target_ty: &syn::Ident::new("Foo", ::proc_macro2::Span::call_site()), + target_ty_generics: None, + error_ty: syn::parse_quote!(FooBuilderError), + initializers: vec![quote!(foo: self.foo,)], + doc_comment: None, + default_struct: None, + validate_fn: None, + } + }; +} + +#[cfg(test)] +mod tests { + #[allow(unused_imports)] + use super::*; + + #[test] + fn std() { + let build_method = default_build_method!(); + + #[rustfmt::skip] + assert_eq!( + quote!(#build_method).to_string(), + quote!( + pub fn build(&self) -> ::db::export::core::result::Result<Foo, FooBuilderError> { + Ok(Foo { + foo: self.foo, + }) + } + ) + .to_string() + ); + } + + #[test] + fn default_struct() { + let mut build_method = default_build_method!(); + let alt_default = + DefaultExpression::explicit::<syn::Expr>(parse_quote!(Default::default())); + build_method.default_struct = Some(&alt_default); + + #[rustfmt::skip] + assert_eq!( + quote!(#build_method).to_string(), + quote!( + pub fn build(&self) -> ::db::export::core::result::Result<Foo, FooBuilderError> { + 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; + + #[rustfmt::skip] + assert_eq!( + quote!(#build_method).to_string(), + quote!( + pub fn finish(&self) -> ::db::export::core::result::Result<Foo, FooBuilderError> { + Ok(Foo { + foo: self.foo, + }) + } + ) + .to_string() + ); + } + + #[test] + fn validation() { + let validate_path: syn::Path = parse_quote!(IpsumBuilder::validate); + + let mut build_method: BuildMethod = default_build_method!(); + build_method.validate_fn = Some(&validate_path); + + #[rustfmt::skip] + assert_eq!( + quote!(#build_method).to_string(), + quote!( + pub fn build(&self) -> ::db::export::core::result::Result<Foo, FooBuilderError> { + IpsumBuilder::validate(&self)?; + + Ok(Foo { + foo: self.foo, + }) + } + ) + .to_string() + ); + } +} diff --git a/vendor/derive_builder_core/src/builder.rs b/vendor/derive_builder_core/src/builder.rs new file mode 100644 index 000000000..e0ae21b99 --- /dev/null +++ b/vendor/derive_builder_core/src/builder.rs @@ -0,0 +1,760 @@ +use std::borrow::Cow; + +use proc_macro2::TokenStream; +use quote::{format_ident, ToTokens, TokenStreamExt}; +use syn::punctuated::Punctuated; +use syn::{self, Path, TraitBound, TraitBoundModifier, TypeParamBound}; + +use doc_comment_from; +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,ignore +/// # extern crate proc_macro2; +/// # #[macro_use] +/// # extern crate quote; +/// # extern crate syn; +/// # #[macro_use] +/// # extern crate derive_builder_core; +/// # use quote::TokenStreamExt; +/// # use derive_builder_core::{Builder, DeprecationNotes}; +/// # fn main() { +/// # let builder = default_builder!(); +/// # +/// # assert_eq!( +/// # quote!(#builder).to_string(), +/// # { +/// # let mut result = quote!(); +/// # #[cfg(not(feature = "clippy"))] +/// # result.append_all(quote!(#[allow(clippy::all)])); +/// # +/// # result.append_all(quote!( +/// #[derive(Clone)] +/// pub struct FooBuilder { +/// foo: u32, +/// } +/// +/// #[doc="Error type for FooBuilder"] +/// #[derive(Debug)] +/// #[non_exhaustive] +/// pub enum FooBuilderError { +/// /// Uninitialized field +/// UninitializedField(&'static str), +/// /// Custom validation error +/// ValidationError(::derive_builder::export::core::string::String), +/// } +/// +/// impl ::derive_builder::export::core::convert::From<... various ...> for FooBuilderError {} +/// +/// #[cfg(not(no_std))] +/// impl std::error::Error for FooBuilderError {} +/// # )); +/// # #[cfg(not(feature = "clippy"))] +/// # result.append_all(quote!(#[allow(clippy::all)])); +/// # +/// # result.append_all(quote!( +/// +/// #[allow(dead_code)] +/// impl FooBuilder { +/// fn bar () -> { +/// unimplemented!() +/// } +/// } +/// +/// impl ::derive_builder::export::core::default::Default for FooBuilder { +/// fn default() -> Self { +/// Self { +/// foo: ::derive_builder::export::core::default::Default::default(), +/// } +/// } +/// } +/// +/// # )); +/// # result +/// # }.to_string() +/// # ); +/// # } +/// ``` +#[derive(Debug)] +pub struct Builder<'a> { + /// Path to the root of the derive_builder crate. + pub crate_root: &'a Path, + /// 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], + /// Attributes to include on the builder `struct` declaration. + pub struct_attrs: &'a [syn::Attribute], + /// Attributes to include on the builder's inherent `impl` block. + pub impl_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. + pub impl_default: bool, + /// The identifier of the inherent method that creates a builder with all fields set to + /// `None` or `PhantomData`. + /// + /// This method will be invoked by `impl Default` for the builder, but it is also accessible + /// to `impl` blocks on the builder that expose custom constructors. + pub create_empty: syn::Ident, + /// 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: Cow<'a, syn::Visibility>, + /// Fields of the builder struct, e.g. `foo: u32,` + /// + /// Expects each entry to be terminated by a comma. + pub fields: Vec<TokenStream>, + /// Builder field initializers, e.g. `foo: Default::default(),` + /// + /// Expects each entry to be terminated by a comma. + pub field_initializers: Vec<TokenStream>, + /// Functions of the builder struct, e.g. `fn bar() -> { unimplemented!() }` + pub functions: Vec<TokenStream>, + /// Whether or not a generated error type is required. + /// + /// This would be `false` in the case where an already-existing error is to be used. + pub generate_error: bool, + /// 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<syn::Attribute>, + /// Emit deprecation notes to the user. + pub deprecation_notes: DeprecationNotes, + /// Whether or not a libstd is used. + pub std: bool, +} + +impl<'a> ToTokens for Builder<'a> { + fn to_tokens(&self, tokens: &mut TokenStream) { + if self.enabled { + let crate_root = self.crate_root; + 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 builder_field_initializers = &self.field_initializers; + let create_empty = &self.create_empty; + let functions = &self.functions; + + // Create the comma-separated set of derived traits for the builder + let derive_attr = { + let clone_trait: Path = parse_quote!(Clone); + + let mut traits: Punctuated<&Path, Token![,]> = Default::default(); + if self.must_derive_clone { + traits.push(&clone_trait); + } + traits.extend(self.derives); + + if traits.is_empty() { + quote!() + } else { + quote!(#[derive(#traits)]) + } + }; + + let struct_attrs = self.struct_attrs; + let impl_attrs = self.impl_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)])); + + // struct_attrs MUST come after derive_attr, otherwise attributes for a derived + // trait will appear before its derivation. As of rustc 1.59.0 this is a compiler + // warning; see https://github.com/rust-lang/rust/issues/79202 + tokens.append_all(quote!( + #derive_attr + #(#struct_attrs)* + #builder_doc_comment + #builder_vis struct #builder_ident #struct_generics #where_clause { + #(#builder_fields)* + } + )); + + #[cfg(not(feature = "clippy"))] + tokens.append_all(quote!(#[allow(clippy::all)])); + + tokens.append_all(quote!( + #(#impl_attrs)* + #[allow(dead_code)] + impl #impl_generics #builder_ident #ty_generics #where_clause { + #(#functions)* + #deprecation_notes + + /// Create an empty builder, with all fields set to `None` or `PhantomData`. + fn #create_empty() -> Self { + Self { + #(#builder_field_initializers)* + } + } + } + )); + + if self.impl_default { + tokens.append_all(quote!( + impl #impl_generics #crate_root::export::core::default::Default for #builder_ident #ty_generics #where_clause { + fn default() -> Self { + Self::#create_empty() + } + } + )); + } + + if self.generate_error { + let builder_error_ident = format_ident!("{}Error", builder_ident); + let builder_error_doc = format!("Error type for {}", builder_ident); + + tokens.append_all(quote!( + #[doc=#builder_error_doc] + #[derive(Debug)] + #[non_exhaustive] + #builder_vis enum #builder_error_ident { + /// Uninitialized field + UninitializedField(&'static str), + /// Custom validation error + ValidationError(#crate_root::export::core::string::String), + } + + impl #crate_root::export::core::convert::From<#crate_root::UninitializedFieldError> for #builder_error_ident { + fn from(s: #crate_root::UninitializedFieldError) -> Self { + Self::UninitializedField(s.field_name()) + } + } + + impl #crate_root::export::core::convert::From<#crate_root::export::core::string::String> for #builder_error_ident { + fn from(s: #crate_root::export::core::string::String) -> Self { + Self::ValidationError(s) + } + } + + impl #crate_root::export::core::fmt::Display for #builder_error_ident { + fn fmt(&self, f: &mut #crate_root::export::core::fmt::Formatter) -> #crate_root::export::core::fmt::Result { + match self { + Self::UninitializedField(ref field) => write!(f, "`{}` must be initialized", field), + Self::ValidationError(ref error) => write!(f, "{}", error), + } + } + } + )); + + if self.std { + tokens.append_all(quote!( + impl std::error::Error for #builder_error_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.field_initializers.push(f.default_initializer_tokens()); + 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 crate_root = self.crate_root; + + let clone_bound = TypeParamBound::Trait(TraitBound { + paren_token: None, + modifier: TraitBoundModifier::None, + lifetimes: None, + path: syn::parse_quote!(#crate_root::export::core::clone::Clone), + }); + + 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 { + // Deliberately don't use the default value here - make sure + // that all test cases are passing crate_root through properly. + crate_root: &parse_quote!(::db), + enabled: true, + ident: syn::Ident::new("FooBuilder", ::proc_macro2::Span::call_site()), + pattern: Default::default(), + derives: &vec![], + struct_attrs: &vec![], + impl_attrs: &vec![], + impl_default: true, + create_empty: syn::Ident::new("create_empty", ::proc_macro2::Span::call_site()), + generics: None, + visibility: ::std::borrow::Cow::Owned(parse_quote!(pub)), + fields: vec![quote!(foo: u32,)], + field_initializers: vec![quote!(foo: ::db::export::core::default::Default::default(), )], + functions: vec![quote!(fn bar() -> { unimplemented!() })], + generate_error: true, + must_derive_clone: true, + doc_comment: None, + deprecation_notes: DeprecationNotes::default(), + std: true, + } + }; +} + +#[cfg(test)] +mod tests { + #[allow(unused_imports)] + use super::*; + use proc_macro2::TokenStream; + use syn::Ident; + + fn add_generated_error(result: &mut TokenStream) { + result.append_all(quote!( + #[doc="Error type for FooBuilder"] + #[derive(Debug)] + #[non_exhaustive] + pub enum FooBuilderError { + /// Uninitialized field + UninitializedField(&'static str), + /// Custom validation error + ValidationError(::db::export::core::string::String), + } + + impl ::db::export::core::convert::From<::db::UninitializedFieldError> for FooBuilderError { + fn from(s: ::db::UninitializedFieldError) -> Self { + Self::UninitializedField(s.field_name()) + } + } + + impl ::db::export::core::convert::From<::db::export::core::string::String> for FooBuilderError { + fn from(s: ::db::export::core::string::String) -> Self { + Self::ValidationError(s) + } + } + + impl ::db::export::core::fmt::Display for FooBuilderError { + fn fmt(&self, f: &mut ::db::export::core::fmt::Formatter) -> ::db::export::core::fmt::Result { + match self { + Self::UninitializedField(ref field) => write!(f, "`{}` must be initialized", field), + Self::ValidationError(ref error) => write!(f, "{}", error), + } + } + } + + impl std::error::Error for FooBuilderError {} + )); + } + + #[test] + fn simple() { + let builder = default_builder!(); + + assert_eq!( + quote!(#builder).to_string(), + { + let mut result = quote!(); + + #[cfg(not(feature = "clippy"))] + result.append_all(quote!(#[allow(clippy::all)])); + + result.append_all(quote!( + #[derive(Clone)] + pub struct FooBuilder { + foo: u32, + } + )); + + #[cfg(not(feature = "clippy"))] + result.append_all(quote!(#[allow(clippy::all)])); + + result.append_all(quote!( + #[allow(dead_code)] + impl FooBuilder { + fn bar () -> { + unimplemented!() + } + + /// Create an empty builder, with all fields set to `None` or `PhantomData`. + fn create_empty() -> Self { + Self { + foo: ::db::export::core::default::Default::default(), + } + } + } + + impl ::db::export::core::default::Default for FooBuilder { + fn default() -> Self { + Self::create_empty() + } + } + )); + + add_generated_error(&mut result); + + result + } + .to_string() + ); + } + + #[test] + fn rename_create_empty() { + let mut builder = default_builder!(); + builder.create_empty = Ident::new("empty", proc_macro2::Span::call_site()); + + assert_eq!( + quote!(#builder).to_string(), + { + let mut result = quote!(); + + #[cfg(not(feature = "clippy"))] + result.append_all(quote!(#[allow(clippy::all)])); + + result.append_all(quote!( + #[derive(Clone)] + pub struct FooBuilder { + foo: u32, + } + )); + + #[cfg(not(feature = "clippy"))] + result.append_all(quote!(#[allow(clippy::all)])); + + result.append_all(quote!( + #[allow(dead_code)] + impl FooBuilder { + fn bar () -> { + unimplemented!() + } + + /// Create an empty builder, with all fields set to `None` or `PhantomData`. + fn empty() -> Self { + Self { + foo: ::db::export::core::default::Default::default(), + } + } + } + + impl ::db::export::core::default::Default for FooBuilder { + fn default() -> Self { + Self::empty() + } + } + )); + + add_generated_error(&mut result); + + result + } + .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 = parse_quote! { + struct Lorem<'a, T: Debug> where T: PartialEq { } + }; + let generics = ast.generics; + let mut builder = default_builder!(); + builder.generics = Some(&generics); + + assert_eq!( + quote!(#builder).to_string(), + { + let mut result = quote!(); + + #[cfg(not(feature = "clippy"))] + result.append_all(quote!(#[allow(clippy::all)])); + + result.append_all(quote!( + #[derive(Clone)] + pub struct FooBuilder<'a, T: Debug> where T: PartialEq { + foo: u32, + } + )); + + #[cfg(not(feature = "clippy"))] + result.append_all(quote!(#[allow(clippy::all)])); + + result.append_all(quote!( + #[allow(dead_code)] + impl<'a, T: Debug + ::db::export::core::clone::Clone> FooBuilder<'a, T> where T: PartialEq { + fn bar() -> { + unimplemented!() + } + + /// Create an empty builder, with all fields set to `None` or `PhantomData`. + fn create_empty() -> Self { + Self { + foo: ::db::export::core::default::Default::default(), + } + } + } + + impl<'a, T: Debug + ::db::export::core::clone::Clone> ::db::export::core::default::Default for FooBuilder<'a, T> where T: PartialEq { + fn default() -> Self { + Self::create_empty() + } + } + )); + + add_generated_error(&mut result); + + result + }.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 = parse_quote! { + struct Lorem<'a, T: 'a + Default> where T: PartialEq{ } + }; + + let generics = ast.generics; + let mut builder = default_builder!(); + builder.generics = Some(&generics); + + assert_eq!( + quote!(#builder).to_string(), + { + let mut result = quote!(); + + #[cfg(not(feature = "clippy"))] + result.append_all(quote!(#[allow(clippy::all)])); + + result.append_all(quote!( + #[derive(Clone)] + pub struct FooBuilder<'a, T: 'a + Default> where T: PartialEq { + foo: u32, + } + )); + + #[cfg(not(feature = "clippy"))] + result.append_all(quote!(#[allow(clippy::all)])); + + result.append_all(quote!( + #[allow(dead_code)] + impl<'a, T: 'a + Default + ::db::export::core::clone::Clone> FooBuilder<'a, T> + where + T: PartialEq + { + fn bar() -> { + unimplemented!() + } + + /// Create an empty builder, with all fields set to `None` or `PhantomData`. + fn create_empty() -> Self { + Self { + foo: ::db::export::core::default::Default::default(), + } + } + } + + impl<'a, T: 'a + Default + ::db::export::core::clone::Clone> ::db::export::core::default::Default for FooBuilder<'a, T> where T: PartialEq { + fn default() -> Self { + Self::create_empty() + } + } + )); + + add_generated_error(&mut result); + + result + }.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 = parse_quote! { + struct Lorem<'a, T: Debug> where T: PartialEq { } + }; + 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(), + { + let mut result = quote!(); + + #[cfg(not(feature = "clippy"))] + result.append_all(quote!(#[allow(clippy::all)])); + + result.append_all(quote!( + pub struct FooBuilder<'a, T: Debug> where T: PartialEq { + foo: u32, + } + )); + + #[cfg(not(feature = "clippy"))] + result.append_all(quote!(#[allow(clippy::all)])); + + result.append_all(quote!( + #[allow(dead_code)] + impl<'a, T: Debug> FooBuilder<'a, T> where T: PartialEq { + fn bar() -> { + unimplemented!() + } + + /// Create an empty builder, with all fields set to `None` or `PhantomData`. + fn create_empty() -> Self { + Self { + foo: ::db::export::core::default::Default::default(), + } + } + } + + impl<'a, T: Debug> ::db::export::core::default::Default for FooBuilder<'a, T> + where T: PartialEq { + fn default() -> Self { + Self::create_empty() + } + } + )); + + add_generated_error(&mut result); + + result + }.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![parse_quote!(Serialize)]; + let mut builder = default_builder!(); + builder.derives = &derives; + + assert_eq!( + quote!(#builder).to_string(), + { + let mut result = quote!(); + + #[cfg(not(feature = "clippy"))] + result.append_all(quote!(#[allow(clippy::all)])); + + result.append_all(quote!( + #[derive(Clone, Serialize)] + pub struct FooBuilder { + foo: u32, + } + )); + + #[cfg(not(feature = "clippy"))] + result.append_all(quote!(#[allow(clippy::all)])); + + result.append_all(quote!( + #[allow(dead_code)] + impl FooBuilder { + fn bar () -> { + unimplemented!() + } + + /// Create an empty builder, with all fields set to `None` or `PhantomData`. + fn create_empty() -> Self { + Self { + foo: ::db::export::core::default::Default::default(), + } + } + } + + impl ::db::export::core::default::Default for FooBuilder { + fn default() -> Self { + Self::create_empty() + } + } + )); + + add_generated_error(&mut result); + + result + } + .to_string() + ); + } +} diff --git a/vendor/derive_builder_core/src/builder_field.rs b/vendor/derive_builder_core/src/builder_field.rs new file mode 100644 index 000000000..089f75236 --- /dev/null +++ b/vendor/derive_builder_core/src/builder_field.rs @@ -0,0 +1,200 @@ +use std::borrow::Cow; + +use proc_macro2::TokenStream; +use quote::{ToTokens, TokenStreamExt}; +use syn; + +/// Field for the builder struct, implementing `quote::ToTokens`. +/// +/// # Examples +/// +/// Will expand to something like the following (depending on settings): +/// +/// ```rust,ignore +/// # 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: ::derive_builder::export::core::option::Option<String>, +/// # ).to_string()); +/// # } +/// ``` +#[derive(Debug, Clone)] +pub struct BuilderField<'a> { + /// Path to the root of the derive_builder crate. + pub crate_root: &'a syn::Path, + /// Name of the target field. + pub field_ident: &'a syn::Ident, + /// Type of the builder field. + pub field_type: BuilderFieldType<'a>, + /// Visibility of this builder field, e.g. `syn::Visibility::Public`. + pub field_visibility: Cow<'a, syn::Visibility>, + /// Attributes which will be attached to this builder field. + pub attrs: &'a [syn::Attribute], +} + +impl<'a> ToTokens for BuilderField<'a> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let ident = self.field_ident; + let vis = &self.field_visibility; + let ty = &self.field_type.with_crate_root(self.crate_root); + let attrs = self.attrs; + tokens.append_all(quote!( + #(#attrs)* #vis #ident: #ty, + )); + } +} + +impl<'a> BuilderField<'a> { + /// Emits a struct field initializer that initializes the field to `Default::default`. + pub fn default_initializer_tokens(&self) -> TokenStream { + let ident = self.field_ident; + let crate_root = self.crate_root; + quote! { #ident : #crate_root::export::core::default::Default::default(), } + } +} + +/// The type of a field in the builder struct +#[derive(Debug, Clone)] +pub enum BuilderFieldType<'a> { + /// The corresonding builder field will be `Option<field_type>`. + Optional(&'a syn::Type), + /// The corresponding builder field will be just this type + Precise(&'a syn::Type), + /// The corresponding builder field will be a PhantomData + /// + /// We do this if if the field is disabled. We mustn't just completely omit the field from the builder: + /// if we did that, the builder might have unused generic parameters (since we copy the generics from + /// the target struct). Using a PhantomData of the original field type provides the right generic usage + /// (and the right variance). The alternative would be to give the user a way to separately control + /// the generics of the builder struct, which would be very awkward to use and complex to document. + /// We could just include the field anyway, as `Option<T>`, but this is wasteful of space, and it + /// seems good to explicitly suppress the existence of a variable that won't be set or read. + Phantom(&'a syn::Type), +} + +impl<'a> BuilderFieldType<'a> { + /// Obtain type information for the builder field setter + /// + /// Return value: + /// * `.0`: type of the argument to the setter function + /// (before application of `strip_option`, `into`) + /// * `.1`: whether the builder field is `Option<type>` rather than just `type` + pub fn setter_type_info(&'a self) -> (&'a syn::Type, bool) { + match self { + BuilderFieldType::Optional(ty) => (ty, true), + BuilderFieldType::Precise(ty) => (ty, false), + BuilderFieldType::Phantom(_ty) => panic!("phantom fields should never have setters"), + } + } + + fn with_crate_root(&'a self, crate_root: &'a syn::Path) -> BuilderFieldTypeWithCrateRoot<'a> { + BuilderFieldTypeWithCrateRoot { + crate_root, + field_type: self, + } + } +} + +struct BuilderFieldTypeWithCrateRoot<'a> { + crate_root: &'a syn::Path, + field_type: &'a BuilderFieldType<'a>, +} + +impl<'a> ToTokens for BuilderFieldTypeWithCrateRoot<'a> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let crate_root = self.crate_root; + match self.field_type { + BuilderFieldType::Optional(ty) => tokens.append_all(quote!( + #crate_root::export::core::option::Option<#ty> + )), + BuilderFieldType::Precise(ty) => ty.to_tokens(tokens), + BuilderFieldType::Phantom(ty) => tokens.append_all(quote!( + #crate_root::export::core::marker::PhantomData<#ty> + )), + } + } +} + +/// Helper macro for unit tests. This is _only_ public in order to be accessible +/// from doc-tests too. +#[cfg(test)] // This contains a Box::leak, so is suitable only for tests +#[doc(hidden)] +#[macro_export] +macro_rules! default_builder_field { + () => {{ + BuilderField { + // Deliberately don't use the default value here - make sure + // that all test cases are passing crate_root through properly. + crate_root: &parse_quote!(::db), + field_ident: &syn::Ident::new("foo", ::proc_macro2::Span::call_site()), + field_type: BuilderFieldType::Optional(Box::leak(Box::new(parse_quote!(String)))), + field_visibility: ::std::borrow::Cow::Owned(parse_quote!(pub)), + attrs: &[parse_quote!(#[some_attr])], + } + }}; +} + +#[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: ::db::export::core::option::Option<String>, + ) + .to_string() + ); + } + + #[test] + fn setter_disabled() { + let mut field = default_builder_field!(); + field.field_visibility = Cow::Owned(syn::Visibility::Inherited); + field.field_type = match field.field_type { + BuilderFieldType::Optional(ty) => BuilderFieldType::Phantom(ty), + _ => panic!(), + }; + + assert_eq!( + quote!(#field).to_string(), + quote!( + #[some_attr] + foo: ::db::export::core::marker::PhantomData<String>, + ) + .to_string() + ); + } + + #[test] + fn private_field() { + let private = Cow::Owned(syn::Visibility::Inherited); + let mut field = default_builder_field!(); + field.field_visibility = private; + + assert_eq!( + quote!(#field).to_string(), + quote!( + #[some_attr] + foo: ::db::export::core::option::Option<String>, + ) + .to_string() + ); + } +} diff --git a/vendor/derive_builder_core/src/change_span.rs b/vendor/derive_builder_core/src/change_span.rs new file mode 100644 index 000000000..96a73a36e --- /dev/null +++ b/vendor/derive_builder_core/src/change_span.rs @@ -0,0 +1,29 @@ +use std::iter::FromIterator; + +use proc_macro2::{Group, Span, TokenStream, TokenTree}; + +/// Deeply change the span of some tokens, ensuring that the output only references `span`. +/// +/// Macros such as `quote_spanned` preserve the spans of interpolated tokens, which is useful. +/// However, in some very specific scenarios it is desirable to suppress the original span +/// information in favor of a different one. +/// +/// For more information, see [dtolnay/syn#309](https://github.com/dtolnay/syn/issues/309). +pub(crate) fn change_span(tokens: TokenStream, span: Span) -> TokenStream { + let mut result = vec![]; + for mut token in tokens { + match token { + TokenTree::Group(group) => { + let mut new_group = + Group::new(group.delimiter(), change_span(group.stream(), span)); + new_group.set_span(span); + result.push(TokenTree::Group(new_group)); + } + _ => { + token.set_span(span); + result.push(token); + } + } + } + FromIterator::from_iter(result.into_iter()) +} diff --git a/vendor/derive_builder_core/src/default_expression.rs b/vendor/derive_builder_core/src/default_expression.rs new file mode 100644 index 000000000..27e62faf5 --- /dev/null +++ b/vendor/derive_builder_core/src/default_expression.rs @@ -0,0 +1,68 @@ +use crate::BlockContents; +use proc_macro2::Span; +use quote::ToTokens; + +/// A `DefaultExpression` can be either explicit or refer to the canonical trait. +#[derive(Debug, Clone)] +pub enum DefaultExpression { + Explicit(BlockContents), + Trait, +} + +impl DefaultExpression { + /// Add the crate root path so the default expression can be emitted + /// to a `TokenStream`. + /// + /// This function is needed because the crate root is inherited from the container, so it cannot + /// be provided at parse time to [`darling::FromMeta::from_word`] when reading, and [`ToTokens`] does not + /// accept any additional parameters, so it annot be provided at emit time. + pub fn with_crate_root<'a>(&'a self, crate_root: &'a syn::Path) -> impl 'a + ToTokens { + DefaultExpressionWithCrateRoot { + crate_root, + expr: self, + } + } + + #[cfg(test)] + pub fn explicit<I: Into<BlockContents>>(content: I) -> Self { + DefaultExpression::Explicit(content.into()) + } +} + +impl darling::FromMeta for DefaultExpression { + fn from_word() -> darling::Result<Self> { + Ok(DefaultExpression::Trait) + } + + fn from_value(value: &syn::Lit) -> darling::Result<Self> { + Ok(Self::Explicit(BlockContents::from_value(value)?)) + } +} + +impl syn::spanned::Spanned for DefaultExpression { + fn span(&self) -> Span { + match self { + DefaultExpression::Explicit(block) => block.span(), + DefaultExpression::Trait => Span::call_site(), + } + } +} + +/// Wrapper for `DefaultExpression` +struct DefaultExpressionWithCrateRoot<'a> { + crate_root: &'a syn::Path, + expr: &'a DefaultExpression, +} + +impl<'a> ToTokens for DefaultExpressionWithCrateRoot<'a> { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let crate_root = self.crate_root; + match self.expr { + DefaultExpression::Explicit(ref block) => block.to_tokens(tokens), + DefaultExpression::Trait => quote!( + #crate_root::export::core::default::Default::default() + ) + .to_tokens(tokens), + } + } +} diff --git a/vendor/derive_builder_core/src/deprecation_notes.rs b/vendor/derive_builder_core/src/deprecation_notes.rs new file mode 100644 index 000000000..92a20a40c --- /dev/null +++ b/vendor/derive_builder_core/src/deprecation_notes.rs @@ -0,0 +1,104 @@ +use 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,ignore +/// # #[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<String>); + +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. + #[cfg(test)] + pub fn push(&mut self, note: String) { + self.0.push(note) + } + + /// 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() + ); +} diff --git a/vendor/derive_builder_core/src/doc_comment.rs b/vendor/derive_builder_core/src/doc_comment.rs new file mode 100644 index 000000000..b23ad8ce4 --- /dev/null +++ b/vendor/derive_builder_core/src/doc_comment.rs @@ -0,0 +1,25 @@ +use syn::Attribute; + +/// Doc-comment, implementing `quote::ToTokens`. +/// +/// # Examples +/// +/// Will expand to something like the following (depending on inner value): +/// +/// ```rust,ignore +/// # #[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]) +} diff --git a/vendor/derive_builder_core/src/doc_tpl/builder_method.md b/vendor/derive_builder_core/src/doc_tpl/builder_method.md new file mode 100644 index 000000000..ef69ecd40 --- /dev/null +++ b/vendor/derive_builder_core/src/doc_tpl/builder_method.md @@ -0,0 +1,5 @@ +Builds a new `{struct_name}`. + +# Errors + +If a required field has not been initialized. diff --git a/vendor/derive_builder_core/src/doc_tpl/builder_struct.md b/vendor/derive_builder_core/src/doc_tpl/builder_struct.md new file mode 100644 index 000000000..6a9b21853 --- /dev/null +++ b/vendor/derive_builder_core/src/doc_tpl/builder_struct.md @@ -0,0 +1 @@ +Builder for [`{struct_name}`](struct.{struct_name}.html). diff --git a/vendor/derive_builder_core/src/doc_tpl/mod.rs b/vendor/derive_builder_core/src/doc_tpl/mod.rs new file mode 100644 index 000000000..ccce3d4d8 --- /dev/null +++ b/vendor/derive_builder_core/src/doc_tpl/mod.rs @@ -0,0 +1,17 @@ +//! This module is organizes chunks of documentation templates +//! for the generated code. +//! +//! Documentation templates may contain the following placeholders +//! - {struct_name} +//! - {builder_name} +//! - {field_name} +//! +//! Templates are used like this: +//! +//! ```rust,ignore +//! let builder_struct_doc = format!( +//! include_str!("doc_tpl/builder_struct.md"), +//! struct_name = /*..*/, +//! builder_name = /*..*/), +//! field_name = /*..*/); +//! ``` diff --git a/vendor/derive_builder_core/src/initializer.rs b/vendor/derive_builder_core/src/initializer.rs new file mode 100644 index 000000000..21ad7f6bb --- /dev/null +++ b/vendor/derive_builder_core/src/initializer.rs @@ -0,0 +1,385 @@ +use proc_macro2::{Span, TokenStream}; +use quote::{ToTokens, TokenStreamExt}; +use syn; +use BuilderPattern; +use DEFAULT_STRUCT_NAME; + +use crate::{change_span, BlockContents, DefaultExpression}; + +/// 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,ignore +/// # 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> { + /// Path to the root of the derive_builder crate. + pub crate_root: &'a syn::Path, + /// 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<&'a DefaultExpression>, + /// Whether the build_method defines a default struct. + pub use_default_struct: bool, + /// Span where the macro was told to use a preexisting error type, instead of creating one, + /// to represent failures of the `build` method. + /// + /// An initializer can force early-return if a field has no set value and no default is + /// defined. In these cases, it will convert from `derive_builder::UninitializedFieldError` + /// into the return type of its enclosing `build` method. That conversion is guaranteed to + /// work for generated error types, but if the caller specified an error type to use instead + /// they may have forgotten the conversion from `UninitializedFieldError` into their specified + /// error type. + pub custom_error_type_span: Option<Span>, + /// Method to use to to convert the builder's field to the target field + /// + /// For sub-builder fields, this will be `build` (or similar) + pub conversion: FieldConversion<'a>, +} + +impl<'a> ToTokens for Initializer<'a> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let struct_field = &self.field_ident; + let builder_field = struct_field; + + // This structure prevents accidental failure to add the trailing `,` due to incautious `return` + let append_rhs = |tokens: &mut TokenStream| { + if !self.field_enabled { + let default = self.default(); + tokens.append_all(quote!( + #default + )); + } else { + match &self.conversion { + FieldConversion::Block(conv) => { + conv.to_tokens(tokens); + } + FieldConversion::Move => tokens.append_all(quote!( self.#builder_field )), + FieldConversion::OptionOrDefault => { + let match_some = self.match_some(); + let match_none = self.match_none(); + tokens.append_all(quote!( + match self.#builder_field { + #match_some, + #match_none, + } + )); + } + } + } + }; + + tokens.append_all(quote!(#struct_field:)); + append_rhs(tokens); + tokens.append_all(quote!(,)); + } +} + +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 => MatchSome::Clone { + crate_root: self.crate_root, + }, + } + } + + /// To be used inside of `#struct_field: match self.#builder_field { ... }` + fn match_none(&'a self) -> MatchNone<'a> { + match self.default_value { + Some(expr) => MatchNone::DefaultTo { + expr, + crate_root: self.crate_root, + }, + None => { + if self.use_default_struct { + MatchNone::UseDefaultStructField(self.field_ident) + } else { + MatchNone::ReturnError { + crate_root: self.crate_root, + field_name: self.field_ident.to_string(), + span: self.custom_error_type_span, + } + } + } + } + } + + fn default(&'a self) -> TokenStream { + let crate_root = self.crate_root; + match self.default_value { + Some(expr) => expr.with_crate_root(crate_root).into_token_stream(), + 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 => { + quote!(#crate_root::export::core::default::Default::default()) + } + } + } +} + +#[derive(Debug, Clone)] +pub enum FieldConversion<'a> { + /// Usual conversion: unwrap the Option from the builder, or (hope to) use a default value + OptionOrDefault, + /// Custom conversion is a block contents expression + Block(&'a BlockContents), + /// Custom conversion is just to move the field from the builder + Move, +} + +/// To be used inside of `#struct_field: match self.#builder_field { ... }` +enum MatchNone<'a> { + /// Inner value must be a valid Rust expression + DefaultTo { + expr: &'a DefaultExpression, + crate_root: &'a syn::Path, + }, + /// 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 { + crate_root: &'a syn::Path, + field_name: String, + span: Option<Span>, + }, +} + +impl<'a> ToTokens for MatchNone<'a> { + fn to_tokens(&self, tokens: &mut TokenStream) { + match *self { + MatchNone::DefaultTo { expr, crate_root } => { + let expr = expr.with_crate_root(crate_root); + 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 field_name, + ref span, + crate_root, + } => { + let conv_span = span.unwrap_or_else(Span::call_site); + // If the conversion fails, the compiler error should point to the error declaration + // rather than the crate root declaration, but the compiler will see the span of #crate_root + // and produce an undesired behavior (possibly because that's the first span in the bad expression?). + // Creating a copy with deeply-rewritten spans preserves the desired error behavior. + let crate_root = change_span(crate_root.into_token_stream(), conv_span); + let err_conv = quote_spanned!(conv_span => #crate_root::export::core::convert::Into::into( + #crate_root::UninitializedFieldError::from(#field_name) + )); + tokens.append_all(quote!( + None => return #crate_root::export::core::result::Result::Err(#err_conv) + )); + } + } + } +} + +/// To be used inside of `#struct_field: match self.#builder_field { ... }` +enum MatchSome<'a> { + Move, + Clone { crate_root: &'a syn::Path }, +} + +impl ToTokens for MatchSome<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + match *self { + Self::Move => tokens.append_all(quote!( + Some(value) => value + )), + Self::Clone { crate_root } => tokens.append_all(quote!( + Some(ref value) => #crate_root::export::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 { + // Deliberately don't use the default value here - make sure + // that all test cases are passing crate_root through properly. + crate_root: &parse_quote!(::db), + 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, + conversion: FieldConversion::OptionOrDefault, + custom_error_type_span: None, + } + }; +} + +#[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) => ::db::export::core::clone::Clone::clone(value), + None => return ::db::export::core::result::Result::Err(::db::export::core::convert::Into::into( + ::db::UninitializedFieldError::from("foo") + )), + }, + ) + .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) => ::db::export::core::clone::Clone::clone(value), + None => return ::db::export::core::result::Result::Err(::db::export::core::convert::Into::into( + ::db::UninitializedFieldError::from("foo") + )), + }, + ) + .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 ::db::export::core::result::Result::Err(::db::export::core::convert::Into::into( + ::db::UninitializedFieldError::from("foo") + )), + }, + ) + .to_string() + ); + } + + #[test] + fn default_value() { + let mut initializer = default_initializer!(); + let default_value = DefaultExpression::explicit::<syn::Expr>(parse_quote!(42)); + initializer.default_value = Some(&default_value); + + assert_eq!( + quote!(#initializer).to_string(), + quote!( + foo: match self.foo { + Some(ref value) => ::db::export::core::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) => ::db::export::core::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: ::db::export::core::default::Default::default(),).to_string() + ); + } + + #[test] + fn no_std() { + let initializer = default_initializer!(); + + assert_eq!( + quote!(#initializer).to_string(), + quote!( + foo: match self.foo { + Some(ref value) => ::db::export::core::clone::Clone::clone(value), + None => return ::db::export::core::result::Result::Err(::db::export::core::convert::Into::into( + ::db::UninitializedFieldError::from("foo") + )), + }, + ) + .to_string() + ); + } +} diff --git a/vendor/derive_builder_core/src/lib.rs b/vendor/derive_builder_core/src/lib.rs new file mode 100644 index 000000000..da5737d03 --- /dev/null +++ b/vendor/derive_builder_core/src/lib.rs @@ -0,0 +1,92 @@ +//! 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. +//! +//! ## Purpose +//! +//! This is an internal helper library of [`derive_builder`], which allows for +//! all the logic of builder creation to be decoupled from the proc-macro entry +//! point. +//! +//! +//! [`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(test)] +#[macro_use] +extern crate pretty_assertions; + +mod block; +mod build_method; +mod builder; +mod builder_field; +mod change_span; +mod default_expression; +mod deprecation_notes; +mod doc_comment; +mod initializer; +mod macro_options; +mod options; +mod setter; + +pub(crate) use block::BlockContents; +pub(crate) use build_method::BuildMethod; +pub(crate) use builder::Builder; +pub(crate) use builder_field::{BuilderField, BuilderFieldType}; +pub(crate) use change_span::change_span; +use darling::FromDeriveInput; +pub(crate) use default_expression::DefaultExpression; +pub(crate) use deprecation_notes::DeprecationNotes; +pub(crate) use doc_comment::doc_comment_from; +pub(crate) use initializer::{FieldConversion, Initializer}; +pub(crate) use options::{BuilderPattern, Each}; +pub(crate) use setter::Setter; + +const DEFAULT_STRUCT_NAME: &str = "__default"; + +/// Derive a builder for a struct +pub fn builder_for_struct(ast: syn::DeriveInput) -> proc_macro2::TokenStream { + let opts = match macro_options::Options::from_derive_input(&ast) { + Ok(val) => val, + Err(err) => { + return err.write_errors(); + } + }; + + let mut builder = opts.as_builder(); + let mut build_fn = opts.as_build_method(); + + builder.doc_comment(format!( + include_str!("doc_tpl/builder_struct.md"), + struct_name = ast.ident + )); + build_fn.doc_comment(format!( + include_str!("doc_tpl/builder_method.md"), + struct_name = ast.ident + )); + + for field in opts.fields() { + builder.push_field(field.as_builder_field()); + builder.push_setter_fn(field.as_setter()); + build_fn.push_initializer(field.as_initializer()); + } + + builder.push_build_fn(build_fn); + + quote!(#builder) +} diff --git a/vendor/derive_builder_core/src/macro_options/darling_opts.rs b/vendor/derive_builder_core/src/macro_options/darling_opts.rs new file mode 100644 index 000000000..0781330f9 --- /dev/null +++ b/vendor/derive_builder_core/src/macro_options/darling_opts.rs @@ -0,0 +1,950 @@ +use std::{borrow::Cow, vec::IntoIter}; + +use crate::BuildMethod; + +use darling::util::{Flag, PathList}; +use darling::{self, Error, FromMeta}; +use proc_macro2::{Span, TokenStream}; +use syn::parse::{ParseStream, Parser}; +use syn::Meta; +use syn::{self, spanned::Spanned, Attribute, Generics, Ident, Path}; + +use crate::{ + BlockContents, Builder, BuilderField, BuilderFieldType, BuilderPattern, DefaultExpression, + DeprecationNotes, Each, FieldConversion, Initializer, Setter, +}; + +/// `derive_builder` uses separate sibling keywords to represent +/// mutually-exclusive visibility states. This trait requires implementers to +/// expose those property values and provides a method to compute any explicit visibility +/// bounds. +trait Visibility { + fn public(&self) -> &Flag; + fn private(&self) -> &Flag; + fn explicit(&self) -> Option<&syn::Visibility>; + + /// Get the explicitly-expressed visibility preference from the attribute. + /// This returns `None` if the input didn't include either keyword. + /// + /// # Panics + /// This method panics if the input specifies both `public` and `private`. + fn as_expressed_vis(&self) -> Option<Cow<syn::Visibility>> { + let declares_public = self.public().is_present(); + let declares_private = self.private().is_present(); + let declares_explicit = self.explicit().is_some(); + + if declares_private { + assert!(!declares_public && !declares_explicit); + Some(Cow::Owned(syn::Visibility::Inherited)) + } else if let Some(vis) = self.explicit() { + assert!(!declares_public); + Some(Cow::Borrowed(vis)) + } else if declares_public { + Some(Cow::Owned(syn::parse_quote!(pub))) + } else { + None + } + } +} + +fn no_visibility_conflict<T: Visibility>(v: &T) -> darling::Result<()> { + let declares_public = v.public().is_present(); + let declares_private = v.private().is_present(); + if let Some(vis) = v.explicit() { + if declares_public || declares_private { + Err( + Error::custom(r#"`vis="..."` cannot be used with `public` or `private`"#) + .with_span(vis), + ) + } else { + Ok(()) + } + } else if declares_public && declares_private { + Err( + Error::custom(r#"`public` and `private` cannot be used together"#) + .with_span(v.public()), + ) + } else { + Ok(()) + } +} + +/// Options for the `build_fn` property in struct-level builder options. +/// There is no inheritance for these settings from struct-level to field-level, +/// so we don't bother using `Option` for values in this struct. +#[derive(Debug, Clone, FromMeta)] +#[darling(default)] +pub struct BuildFn { + skip: bool, + name: Ident, + validate: Option<Path>, + public: Flag, + private: Flag, + vis: Option<syn::Visibility>, + /// The path to an existing error type that the build method should return. + /// + /// Setting this will prevent `derive_builder` from generating an error type for the build + /// method. + /// + /// # Type Bounds + /// This type's bounds depend on other settings of the builder. + /// + /// * If uninitialized fields cause `build()` to fail, then this type + /// must `impl From<UninitializedFieldError>`. Uninitialized fields do not cause errors + /// when default values are provided for every field or at the struct level. + /// * If `validate` is specified, then this type must provide a conversion from the specified + /// function's error type. + error: Option<Path>, +} + +impl Default for BuildFn { + fn default() -> Self { + BuildFn { + skip: false, + name: Ident::new("build", Span::call_site()), + validate: None, + public: Default::default(), + private: Default::default(), + vis: None, + error: None, + } + } +} + +impl Visibility for BuildFn { + fn public(&self) -> &Flag { + &self.public + } + + fn private(&self) -> &Flag { + &self.private + } + + fn explicit(&self) -> Option<&syn::Visibility> { + self.vis.as_ref() + } +} + +/// Contents of the `field` meta in `builder` attributes at the struct level. +#[derive(Debug, Clone, Default, FromMeta)] +pub struct StructLevelFieldMeta { + public: Flag, + private: Flag, + vis: Option<syn::Visibility>, +} + +impl Visibility for StructLevelFieldMeta { + fn public(&self) -> &Flag { + &self.public + } + + fn private(&self) -> &Flag { + &self.private + } + + fn explicit(&self) -> Option<&syn::Visibility> { + self.vis.as_ref() + } +} + +/// Contents of the `field` meta in `builder` attributes at the field level. +// +// This is a superset of the attributes permitted in `field` at the struct level. +// Perhaps in the future we will be able to use `#[darling(flatten)]`, but +// that does not exist right now: https://github.com/TedDriggs/darling/issues/146 +#[derive(Debug, Clone, Default, FromMeta)] +pub struct FieldLevelFieldMeta { + public: Flag, + private: Flag, + vis: Option<syn::Visibility>, + /// Custom builder field type + #[darling(rename = "type")] + builder_type: Option<syn::Type>, + /// Custom builder field method, for making target struct field value + build: Option<BlockContents>, +} + +impl Visibility for FieldLevelFieldMeta { + fn public(&self) -> &Flag { + &self.public + } + + fn private(&self) -> &Flag { + &self.private + } + + fn explicit(&self) -> Option<&syn::Visibility> { + self.vis.as_ref() + } +} + +#[derive(Debug, Clone, Default, FromMeta)] +pub struct StructLevelSetter { + prefix: Option<Ident>, + into: Option<bool>, + strip_option: Option<bool>, + skip: Option<bool>, +} + +impl StructLevelSetter { + /// Check if setters are explicitly enabled or disabled at + /// the struct level. + pub fn enabled(&self) -> Option<bool> { + self.skip.map(|x| !x) + } +} + +/// Create `Each` from an attribute's `Meta`. +/// +/// Two formats are supported: +/// +/// * `each = "..."`, which provides the name of the `each` setter and otherwise uses default values +/// * `each(name = "...")`, which allows setting additional options on the `each` setter +fn parse_each(meta: &Meta) -> darling::Result<Option<Each>> { + if let Meta::NameValue(mnv) = meta { + if let syn::Lit::Str(v) = &mnv.lit { + v.parse::<Ident>() + .map(Each::from) + .map(Some) + .map_err(|_| darling::Error::unknown_value(&v.value()).with_span(v)) + } else { + Err(darling::Error::unexpected_lit_type(&mnv.lit)) + } + } else { + Each::from_meta(meta).map(Some) + } +} + +/// The `setter` meta item on fields in the input type. +/// Unlike the `setter` meta item at the struct level, this allows specific +/// name overrides. +#[derive(Debug, Clone, Default, FromMeta)] +pub struct FieldLevelSetter { + prefix: Option<Ident>, + name: Option<Ident>, + into: Option<bool>, + strip_option: Option<bool>, + skip: Option<bool>, + custom: Option<bool>, + #[darling(with = "parse_each")] + each: Option<Each>, +} + +impl FieldLevelSetter { + /// Get whether the setter should be emitted. The rules are the same as + /// for `field_enabled`, except we only skip the setter if `setter(custom)` is present. + pub fn setter_enabled(&self) -> Option<bool> { + if self.custom.is_some() { + return self.custom.map(|x| !x); + } + + self.field_enabled() + } + + /// Get whether or not this field-level setter indicates a setter and + /// field should be emitted. The setter shorthand rules are that the + /// presence of a `setter` with _any_ properties set forces the setter + /// to be emitted. + pub fn field_enabled(&self) -> Option<bool> { + if self.skip.is_some() { + return self.skip.map(|x| !x); + } + + if self.prefix.is_some() + || self.name.is_some() + || self.into.is_some() + || self.strip_option.is_some() + || self.each.is_some() + { + return Some(true); + } + + None + } +} + +/// `derive_builder` allows the calling code to use `setter` as a word to enable +/// setters when they've been disabled at the struct level. +fn field_setter(meta: &Meta) -> darling::Result<FieldLevelSetter> { + // it doesn't matter what the path is; the fact that this function + // has been called means that a valueless path is the shorthand case. + if let Meta::Path(_) = meta { + Ok(FieldLevelSetter { + skip: Some(false), + ..Default::default() + }) + } else { + FieldLevelSetter::from_meta(meta) + } +} + +/// Data extracted from the fields of the input struct. +#[derive(Debug, Clone, FromField)] +#[darling( + attributes(builder), + forward_attrs(doc, cfg, allow, builder_field_attr, builder_setter_attr), + and_then = "Self::resolve" +)] +pub struct Field { + ident: Option<Ident>, + /// Raw input attributes, for consumption by Field::unnest_attrs. Do not use elsewhere. + attrs: Vec<syn::Attribute>, + ty: syn::Type, + /// Field-level override for builder pattern. + /// Note that setting this may force the builder to derive `Clone`. + pattern: Option<BuilderPattern>, + public: Flag, + private: Flag, + /// Declared visibility for the field in the builder, e.g. `#[builder(vis = "...")]`. + /// + /// This cannot be named `vis` or `darling` would put the deriving field's visibility into the + /// field instead. + #[darling(rename = "vis")] + visibility: Option<syn::Visibility>, + // See the documentation for `FieldSetterMeta` to understand how `darling` + // is interpreting this field. + #[darling(default, with = "field_setter")] + setter: FieldLevelSetter, + /// The value for this field if the setter is never invoked. + /// + /// A field can get its default one of three ways: + /// + /// 1. An explicit `default = "..."` expression + /// 2. An explicit `default` word, in which case the field type's `Default::default()` + /// value is used + /// 3. Inherited from the field's value in the struct's `default` value. + /// + /// This property only captures the first two, the third is computed in `FieldWithDefaults`. + default: Option<DefaultExpression>, + try_setter: Flag, + #[darling(default)] + field: FieldLevelFieldMeta, + #[darling(skip)] + field_attrs: Vec<Attribute>, + #[darling(skip)] + setter_attrs: Vec<Attribute>, +} + +impl Field { + fn no_visibility_conflicts(&self) -> darling::Result<()> { + let mut errors = Error::accumulator(); + errors.handle(no_visibility_conflict(&self.field)); + errors.handle(no_visibility_conflict(self)); + errors.finish() + } + + /// Resolve and check (post-parsing) options which come from multiple darling options + /// + /// * Check that we don't have a custom field type or builder *and* a default value + /// * Populate `self.field_attrs` and `self.setter_attrs` by draining `self.attrs` + fn resolve(mut self) -> darling::Result<Self> { + let mut errors = darling::Error::accumulator(); + + // `default` can be preempted by properties in `field`. Silently ignoring a + // `default` could cause the direct user of `derive_builder` to see unexpected + // behavior from the builder, so instead we require that the deriving struct + // not pass any ignored instructions. + if let Field { + default: Some(field_default), + .. + } = &self + { + // `field.build` is stronger than `default`, as it contains both instructions on how to + // deal with a missing value and conversions to do on the value during target type + // construction. + if self.field.build.is_some() { + errors.push( + darling::Error::custom( + r#"#[builder(default)] and #[builder(field(build="..."))] cannot be used together"#, + ) + .with_span(field_default), + ); + } + + // `field.type` being set means `default` will not be used, since we don't know how + // to check a custom field type for the absence of a value and therefore we'll never + // know that we should use the `default` value. + if self.field.builder_type.is_some() { + errors.push( + darling::Error::custom( + r#"#[builder(default)] and #[builder(field(type="..."))] cannot be used together"#, + ) + .with_span(field_default) + ) + } + }; + + errors.handle(distribute_and_unnest_attrs( + &mut self.attrs, + &mut [ + ("builder_field_attr", &mut self.field_attrs), + ("builder_setter_attr", &mut self.setter_attrs), + ], + )); + + errors.finish_with(self) + } +} + +/// Divide a list of attributes into multiple partially-overlapping output lists. +/// +/// Some attributes from the macro input will be added to the output in multiple places; +/// for example, a `cfg` attribute must be replicated to both the struct and its impl block or +/// the resulting code will not compile. +/// +/// Other attributes are scoped to a specific output by their path, e.g. `builder_field_attr`. +/// These attributes will only appear in one output list, but need that outer path removed. +/// +/// For performance reasons, we want to do this in one pass through the list instead of +/// first distributing and then iterating through each of the output lists. +/// +/// Each item in `outputs` contains the attribute name unique to that output, and the `Vec` where all attributes for that output should be inserted. +/// Attributes whose path matches any value in `outputs` will be added only to the first matching one, and will be "unnested". +/// Other attributes are not unnested, and simply copied for each decoratee. +fn distribute_and_unnest_attrs( + input: &mut Vec<Attribute>, + outputs: &mut [(&'static str, &mut Vec<Attribute>)], +) -> darling::Result<()> { + let mut errors = vec![]; + + for (name, list) in &*outputs { + assert!(list.is_empty(), "Output Vec for '{}' was not empty", name); + } + + for attr in input.drain(..) { + let destination = outputs + .iter_mut() + .find(|(ptattr, _)| attr.path.is_ident(ptattr)); + + if let Some((_, destination)) = destination { + match unnest_from_one_attribute(attr) { + Ok(n) => destination.push(n), + Err(e) => errors.push(e), + } + } else { + for (_, output) in outputs.iter_mut() { + output.push(attr.clone()); + } + } + } + + if !errors.is_empty() { + return Err(darling::Error::multiple(errors)); + } + + Ok(()) +} + +fn unnest_from_one_attribute(attr: syn::Attribute) -> darling::Result<Attribute> { + match &attr.style { + syn::AttrStyle::Outer => (), + syn::AttrStyle::Inner(bang) => { + return Err(darling::Error::unsupported_format(&format!( + "{} must be an outer attribute", + attr.path + .get_ident() + .map(Ident::to_string) + .unwrap_or_else(|| "Attribute".to_string()) + )) + .with_span(bang)); + } + }; + + #[derive(Debug)] + struct ContainedAttribute(syn::Attribute); + impl syn::parse::Parse for ContainedAttribute { + fn parse(input: ParseStream) -> syn::Result<Self> { + // Strip parentheses, and save the span of the parenthesis token + let content; + let paren_token = parenthesized!(content in input); + let wrap_span = paren_token.span; + + // Wrap up in #[ ] instead. + let pound = Token![#](wrap_span); // We can't write a literal # inside quote + let content: TokenStream = content.parse()?; + let content = quote_spanned!(wrap_span=> #pound [ #content ]); + + let parser = syn::Attribute::parse_outer; + let mut attrs = parser.parse2(content)?.into_iter(); + // TryFrom for Array not available in Rust 1.40 + // We think this error can never actually happen, since `#[...]` ought to make just one Attribute + let attr = match (attrs.next(), attrs.next()) { + (Some(attr), None) => attr, + _ => return Err(input.error("expected exactly one attribute")), + }; + Ok(Self(attr)) + } + } + + let ContainedAttribute(attr) = syn::parse2(attr.tokens)?; + Ok(attr) +} + +impl Visibility for Field { + fn public(&self) -> &Flag { + &self.public + } + + fn private(&self) -> &Flag { + &self.private + } + + fn explicit(&self) -> Option<&syn::Visibility> { + self.visibility.as_ref() + } +} + +fn default_crate_root() -> Path { + parse_quote!(::derive_builder) +} + +fn default_create_empty() -> Ident { + Ident::new("create_empty", Span::call_site()) +} + +#[derive(Debug, Clone, FromDeriveInput)] +#[darling( + attributes(builder), + forward_attrs(cfg, allow, builder_struct_attr, builder_impl_attr), + supports(struct_named), + and_then = "Self::unnest_attrs" +)] +pub struct Options { + ident: Ident, + + /// DO NOT USE. + /// + /// Initial receiver for forwarded attributes from the struct; these are split + /// into `Options::struct_attrs` and `Options::impl_attrs` before `FromDeriveInput` + /// returns. + attrs: Vec<Attribute>, + + #[darling(skip)] + struct_attrs: Vec<Attribute>, + + #[darling(skip)] + impl_attrs: Vec<Attribute>, + + /// The visibility of the deriving struct. Do not confuse this with `#[builder(vis = "...")]`, + /// which is received by `Options::visibility`. + vis: syn::Visibility, + + generics: Generics, + + /// The name of the generated builder. Defaults to `#{ident}Builder`. + name: Option<Ident>, + + /// The path to the root of the derive_builder crate used in generated + /// code. + #[darling(rename = "crate", default = "default_crate_root")] + crate_root: Path, + + #[darling(default)] + pattern: BuilderPattern, + + #[darling(default)] + build_fn: BuildFn, + + /// Additional traits to derive on the builder. + #[darling(default)] + derive: PathList, + + custom_constructor: Flag, + + /// The ident of the inherent method which takes no arguments and returns + /// an instance of the builder with all fields empty. + #[darling(default = "default_create_empty")] + create_empty: Ident, + + /// Setter options applied to all field setters in the struct. + #[darling(default)] + setter: StructLevelSetter, + + /// Struct-level value to use in place of any unfilled fields + default: Option<DefaultExpression>, + + public: Flag, + + private: Flag, + + /// Desired visibility of the builder struct. + /// + /// Do not confuse this with `Options::vis`, which is the visibility of the deriving struct. + #[darling(rename = "vis")] + visibility: Option<syn::Visibility>, + + /// The parsed body of the derived struct. + data: darling::ast::Data<darling::util::Ignored, Field>, + + no_std: Flag, + + /// When present, emit additional fallible setters alongside each regular + /// setter. + try_setter: Flag, + + #[darling(default)] + field: StructLevelFieldMeta, + + #[darling(skip, default)] + deprecation_notes: DeprecationNotes, +} + +impl Visibility for Options { + fn public(&self) -> &Flag { + &self.public + } + + fn private(&self) -> &Flag { + &self.private + } + + fn explicit(&self) -> Option<&syn::Visibility> { + self.visibility.as_ref() + } +} + +impl Options { + /// Populate `self.struct_attrs` and `self.impl_attrs` by draining `self.attrs` + fn unnest_attrs(mut self) -> darling::Result<Self> { + let mut errors = Error::accumulator(); + + errors.handle(distribute_and_unnest_attrs( + &mut self.attrs, + &mut [ + ("builder_struct_attr", &mut self.struct_attrs), + ("builder_impl_attr", &mut self.impl_attrs), + ], + )); + + // Check for conflicting visibility declarations. These cannot be pushed + // down into `FieldMeta` et al because of the call to `no_visibility_conflict(&self)`, + // as all sub-fields must be valid for this `Options` function to run. + errors.handle(no_visibility_conflict(&self.field)); + errors.handle(no_visibility_conflict(&self.build_fn)); + self.data + .as_ref() + .map_struct_fields(|f| errors.handle(f.no_visibility_conflicts())); + errors.handle(no_visibility_conflict(&self)); + + errors.finish_with(self) + } +} + +/// Accessors for parsed properties. +impl Options { + pub fn builder_ident(&self) -> Ident { + if let Some(ref custom) = self.name { + return custom.clone(); + } + + format_ident!("{}Builder", self.ident) + } + + pub fn builder_error_ident(&self) -> Path { + if let Some(existing) = self.build_fn.error.as_ref() { + existing.clone() + } else if let Some(ref custom) = self.name { + format_ident!("{}Error", custom).into() + } else { + format_ident!("{}BuilderError", self.ident).into() + } + } + + /// The visibility of the builder struct. + /// If a visibility was declared in attributes, that will be used; + /// otherwise the struct's own visibility will be used. + pub fn builder_vis(&self) -> Cow<syn::Visibility> { + self.as_expressed_vis().unwrap_or(Cow::Borrowed(&self.vis)) + } + + /// Get the visibility of the emitted `build` method. + /// This defaults to the visibility of the parent builder, but can be overridden. + pub fn build_method_vis(&self) -> Cow<syn::Visibility> { + self.build_fn + .as_expressed_vis() + .unwrap_or_else(|| self.builder_vis()) + } + + pub fn raw_fields(&self) -> Vec<&Field> { + self.data + .as_ref() + .take_struct() + .expect("Only structs supported") + .fields + } + + /// A builder requires `Clone` to be derived if its build method or any of its setters + /// use the mutable or immutable pattern. + pub fn requires_clone(&self) -> bool { + self.pattern.requires_clone() || self.fields().any(|f| f.pattern().requires_clone()) + } + + /// Get an iterator over the input struct's fields which pulls fallback + /// values from struct-level settings. + pub fn fields(&self) -> FieldIter { + FieldIter(self, self.raw_fields().into_iter()) + } + + pub fn field_count(&self) -> usize { + self.raw_fields().len() + } +} + +/// Converters to codegen structs +impl Options { + pub fn as_builder(&self) -> Builder { + Builder { + crate_root: &self.crate_root, + enabled: true, + ident: self.builder_ident(), + pattern: self.pattern, + derives: &self.derive, + struct_attrs: &self.struct_attrs, + impl_attrs: &self.impl_attrs, + impl_default: !self.custom_constructor.is_present(), + create_empty: self.create_empty.clone(), + generics: Some(&self.generics), + visibility: self.builder_vis(), + fields: Vec::with_capacity(self.field_count()), + field_initializers: Vec::with_capacity(self.field_count()), + functions: Vec::with_capacity(self.field_count()), + generate_error: self.build_fn.error.is_none(), + must_derive_clone: self.requires_clone(), + doc_comment: None, + deprecation_notes: Default::default(), + std: !self.no_std.is_present(), + } + } + + pub fn as_build_method(&self) -> BuildMethod { + let (_, ty_generics, _) = self.generics.split_for_impl(); + BuildMethod { + crate_root: &self.crate_root, + enabled: !self.build_fn.skip, + ident: &self.build_fn.name, + visibility: self.build_method_vis(), + pattern: self.pattern, + target_ty: &self.ident, + target_ty_generics: Some(ty_generics), + error_ty: self.builder_error_ident(), + initializers: Vec::with_capacity(self.field_count()), + doc_comment: None, + default_struct: self.default.as_ref(), + validate_fn: self.build_fn.validate.as_ref(), + } + } +} + +/// Accessor for field data which can pull through options from the parent +/// struct. +pub struct FieldWithDefaults<'a> { + parent: &'a Options, + field: &'a Field, +} + +/// Accessors for parsed properties, with transparent pull-through from the +/// parent struct's configuration. +impl<'a> FieldWithDefaults<'a> { + /// Check if this field should emit a setter. + pub fn setter_enabled(&self) -> bool { + self.field + .setter + .setter_enabled() + .or_else(|| self.parent.setter.enabled()) + .unwrap_or(true) + } + + pub fn field_enabled(&self) -> bool { + self.field + .setter + .field_enabled() + .or_else(|| self.parent.setter.enabled()) + .unwrap_or(true) + } + + /// Check if this field should emit a fallible setter. + /// This depends on the `TryFrom` trait, which hasn't yet stabilized. + pub fn try_setter(&self) -> bool { + self.field.try_setter.is_present() || self.parent.try_setter.is_present() + } + + /// Get the prefix that should be applied to the field name to produce + /// the setter ident, if any. + pub fn setter_prefix(&self) -> Option<&Ident> { + self.field + .setter + .prefix + .as_ref() + .or(self.parent.setter.prefix.as_ref()) + } + + /// Get the ident of the emitted setter method + pub fn setter_ident(&self) -> syn::Ident { + if let Some(ref custom) = self.field.setter.name { + return custom.clone(); + } + + let ident = &self.field.ident; + + if let Some(ref prefix) = self.setter_prefix() { + return format_ident!("{}_{}", prefix, ident.as_ref().unwrap()); + } + + ident.clone().unwrap() + } + + /// Checks if the emitted setter should be generic over types that impl + /// `Into<FieldType>`. + pub fn setter_into(&self) -> bool { + self.field + .setter + .into + .or(self.parent.setter.into) + .unwrap_or_default() + } + + /// Checks if the emitted setter should strip the wrapper Option over types that impl + /// `Option<FieldType>`. + pub fn setter_strip_option(&self) -> bool { + self.field + .setter + .strip_option + .or(self.parent.setter.strip_option) + .unwrap_or_default() + } + + /// Get the visibility of the emitted setter, if there will be one. + pub fn setter_vis(&self) -> Cow<syn::Visibility> { + self.field + .as_expressed_vis() + .or_else(|| self.parent.as_expressed_vis()) + .unwrap_or_else(|| Cow::Owned(syn::parse_quote!(pub))) + } + + /// Get the ident of the input field. This is also used as the ident of the + /// emitted field. + pub fn field_ident(&self) -> &syn::Ident { + self.field + .ident + .as_ref() + .expect("Tuple structs are not supported") + } + + pub fn field_vis(&self) -> Cow<syn::Visibility> { + self.field + .field + .as_expressed_vis() + .or_else( + // Disabled fields become a PhantomData in the builder. We make that field + // non-public, even if the rest of the builder is public, since this field is just + // there to make sure the struct's generics are properly handled. + || { + if self.field_enabled() { + None + } else { + Some(Cow::Owned(syn::Visibility::Inherited)) + } + }, + ) + .or_else(|| self.parent.field.as_expressed_vis()) + .unwrap_or(Cow::Owned(syn::Visibility::Inherited)) + } + + pub fn field_type(&'a self) -> BuilderFieldType<'a> { + if !self.field_enabled() { + BuilderFieldType::Phantom(&self.field.ty) + } else if let Some(custom_ty) = self.field.field.builder_type.as_ref() { + BuilderFieldType::Precise(custom_ty) + } else { + BuilderFieldType::Optional(&self.field.ty) + } + } + + pub fn conversion(&'a self) -> FieldConversion<'a> { + match (&self.field.field.builder_type, &self.field.field.build) { + (_, Some(block)) => FieldConversion::Block(block), + (Some(_), None) => FieldConversion::Move, + (None, None) => FieldConversion::OptionOrDefault, + } + } + + pub fn pattern(&self) -> BuilderPattern { + self.field.pattern.unwrap_or(self.parent.pattern) + } + + pub fn use_parent_default(&self) -> bool { + self.field.default.is_none() && self.parent.default.is_some() + } + + pub fn deprecation_notes(&self) -> &DeprecationNotes { + &self.parent.deprecation_notes + } +} + +/// Converters to codegen structs +impl<'a> FieldWithDefaults<'a> { + /// Returns a `Setter` according to the options. + pub fn as_setter(&'a self) -> Setter<'a> { + Setter { + crate_root: &self.parent.crate_root, + setter_enabled: self.setter_enabled(), + try_setter: self.try_setter(), + visibility: self.setter_vis(), + pattern: self.pattern(), + attrs: &self.field.setter_attrs, + ident: self.setter_ident(), + field_ident: self.field_ident(), + field_type: self.field_type(), + generic_into: self.setter_into(), + strip_option: self.setter_strip_option(), + deprecation_notes: self.deprecation_notes(), + each: self.field.setter.each.as_ref(), + } + } + + /// Returns an `Initializer` according to the options. + /// + /// # Panics + /// + /// if `default_expression` can not be parsed as `Block`. + pub fn as_initializer(&'a self) -> Initializer<'a> { + Initializer { + crate_root: &self.parent.crate_root, + field_enabled: self.field_enabled(), + field_ident: self.field_ident(), + builder_pattern: self.pattern(), + default_value: self.field.default.as_ref(), + use_default_struct: self.use_parent_default(), + conversion: self.conversion(), + custom_error_type_span: self + .parent + .build_fn + .error + .as_ref() + .map(|err_ty| err_ty.span()), + } + } + + pub fn as_builder_field(&'a self) -> BuilderField<'a> { + BuilderField { + crate_root: &self.parent.crate_root, + field_ident: self.field_ident(), + field_type: self.field_type(), + field_visibility: self.field_vis(), + attrs: &self.field.field_attrs, + } + } +} + +pub struct FieldIter<'a>(&'a Options, IntoIter<&'a Field>); + +impl<'a> Iterator for FieldIter<'a> { + type Item = FieldWithDefaults<'a>; + + fn next(&mut self) -> Option<Self::Item> { + self.1.next().map(|field| FieldWithDefaults { + parent: self.0, + field, + }) + } +} diff --git a/vendor/derive_builder_core/src/macro_options/mod.rs b/vendor/derive_builder_core/src/macro_options/mod.rs new file mode 100644 index 000000000..84e091caa --- /dev/null +++ b/vendor/derive_builder_core/src/macro_options/mod.rs @@ -0,0 +1,16 @@ +//! Types and functions for parsing attribute options. +//! +//! Attribute parsing occurs in multiple stages: +//! +//! 1. Builder options on the struct are parsed into `OptionsBuilder<StructMode>`. +//! 1. The `OptionsBuilder<StructMode>` instance is converted into a starting point for the +//! per-field options (`OptionsBuilder<FieldMode>`) and the finished struct-level config, +//! called `StructOptions`. +//! 1. Each struct field is parsed, with discovered attributes overriding or augmenting the +//! options specified at the struct level. This creates one `OptionsBuilder<FieldMode>` per +//! struct field on the input/target type. Once complete, these get converted into +//! `FieldOptions` instances. + +mod darling_opts; + +pub use self::darling_opts::Options; diff --git a/vendor/derive_builder_core/src/options.rs b/vendor/derive_builder_core/src/options.rs new file mode 100644 index 000000000..c4d3ba9fd --- /dev/null +++ b/vendor/derive_builder_core/src/options.rs @@ -0,0 +1,48 @@ +/// 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(Debug, Clone, FromMeta)] +pub struct Each { + pub name: syn::Ident, + #[darling(default)] + pub into: bool, +} + +impl From<syn::Ident> for Each { + fn from(name: syn::Ident) -> Self { + Self { name, into: false } + } +} diff --git a/vendor/derive_builder_core/src/setter.rs b/vendor/derive_builder_core/src/setter.rs new file mode 100644 index 000000000..f8c8ad203 --- /dev/null +++ b/vendor/derive_builder_core/src/setter.rs @@ -0,0 +1,603 @@ +#![allow(clippy::useless_let_if_seq)] +use std::borrow::Cow; + +use proc_macro2::{Span, TokenStream}; +use quote::{ToTokens, TokenStreamExt}; +use syn; + +use BuilderFieldType; +use BuilderPattern; +use DeprecationNotes; +use Each; + +/// Setter for the struct fields in the build method, implementing +/// `quote::ToTokens`. +/// +/// # Examples +/// +/// Will expand to something like the following (depending on settings): +/// +/// ```rust,ignore +/// # 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 = ::derive_builder::export::core::option::Option::Some(value); +/// new +/// } +/// # ).to_string()); +/// # } +/// ``` +#[derive(Debug, Clone)] +pub struct Setter<'a> { + /// Path to the root of the derive_builder crate. + pub crate_root: &'a syn::Path, + /// 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: Cow<'a, 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 builder field. + /// + /// The corresonding builder field will be `Option<field_type>`. + pub field_type: BuilderFieldType<'a>, + /// Make the setter generic over `Into<T>`, 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, + /// Emit extend method. + pub each: Option<&'a Each>, +} + +impl<'a> ToTokens for Setter<'a> { + fn to_tokens(&self, tokens: &mut TokenStream) { + if self.setter_enabled { + let crate_root = self.crate_root; + 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 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!(#crate_root::export::core::clone::Clone::clone(self)); + } + }; + + let ty_params: TokenStream; + let param_ty: TokenStream; + let mut into_value: TokenStream; + + let (field_type, builder_field_is_option) = self.field_type.setter_type_info(); + + 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) + } + }; + + if self.generic_into { + ty_params = quote!(<VALUE: #crate_root::export::core::convert::Into<#ty>>); + param_ty = quote!(VALUE); + into_value = quote!(value.into()); + } else { + ty_params = quote!(); + param_ty = quote!(#ty); + into_value = quote!(value); + } + // If both `stripped_option` and `builder_field_is_option`, the target field is `Option<field_type>`, + // the builder field is `Option<Option<field_type>>`, and the setter takes `file_type`, so we must wrap it twice. + if stripped_option { + into_value = wrap_expression_in_some(crate_root, into_value); + } + if builder_field_is_option { + into_value = wrap_expression_in_some(crate_root, 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 = #into_value; + new + } + )); + + if self.try_setter { + let try_ty_params = + quote!(<VALUE: #crate_root::export::core::convert::TryInto<#ty>>); + let try_ident = syn::Ident::new(&format!("try_{}", ident), Span::call_site()); + + let mut converted = quote! {converted}; + if builder_field_is_option { + converted = wrap_expression_in_some(crate_root, converted); + } + + tokens.append_all(quote!( + #(#attrs)* + #vis fn #try_ident #try_ty_params (#self_param, value: VALUE) + -> #crate_root::export::core::result::Result<#return_ty, VALUE::Error> + { + let converted : #ty = value.try_into()?; + let mut new = #self_into_return_ty; + new.#field_ident = #converted; + Ok(new) + } + )); + } + + if let Some(each) = self.each { + let ident_each = &each.name; + + // Access the collection to extend, initialising with default value if necessary. + let get_initialized_collection = if stripped_option { + // Outer (builder) Option -> Inner (field) Option -> collection. + quote!(get_or_insert_with(|| Some( + #crate_root::export::core::default::Default::default() + )) + .get_or_insert_with(#crate_root::export::core::default::Default::default)) + } else { + // Outer (builder) Option -> collection. + quote!(get_or_insert_with( + #crate_root::export::core::default::Default::default + )) + }; + + let ty_params: TokenStream; + let param_ty: TokenStream; + let into_item: TokenStream; + + if each.into { + ty_params = quote!(<VALUE, FROM_VALUE: #crate_root::export::core::convert::Into<VALUE>>); + param_ty = quote!(FROM_VALUE); + into_item = quote!(#crate_root::export::core::convert::Into::into(item)); + } else { + ty_params = quote!(<VALUE>); + param_ty = quote!(VALUE); + into_item = quote!(item); + } + + tokens.append_all(quote!( + #(#attrs)* + #[allow(unused_mut)] + #vis fn #ident_each #ty_params(#self_param, item: #param_ty) -> #return_ty + where + #ty: #crate_root::export::core::default::Default + #crate_root::export::core::iter::Extend<VALUE>, + { + #deprecation_notes + let mut new = #self_into_return_ty; + new.#field_ident + .#get_initialized_collection + .extend(#crate_root::export::core::option::Option::Some(#into_item)); + new + } + )); + } + } + } +} + +/// Returns expression wrapping `bare_value` in `Some` +fn wrap_expression_in_some(crate_root: &syn::Path, bare_value: impl ToTokens) -> TokenStream { + quote!( #crate_root::export::core::option::Option::Some(#bare_value) ) +} + +// 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<String>` +// 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<Pair<&PathSegment, &Colon2>> { + 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(extract_option_segment) + .and_then(|pair_path_segment| { + let type_params = &pair_path_segment.into_value().arguments; + // It should have only on angle-bracketed param ("<String>"): + 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 { + // Deliberately don't use the default value here - make sure + // that all test cases are passing crate_root through properly. + crate_root: &parse_quote!(::db), + setter_enabled: true, + try_setter: false, + visibility: ::std::borrow::Cow::Owned(parse_quote!(pub)), + 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: BuilderFieldType::Optional(Box::leak(Box::new(parse_quote!(Foo)))), + generic_into: false, + strip_option: false, + deprecation_notes: &Default::default(), + each: None, + } + }; +} + +#[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 = ::db::export::core::clone::Clone::clone(self); + new.foo = ::db::export::core::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 = ::db::export::core::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 = ::db::export::core::option::Option::Some(value); + new + } + ) + .to_string() + ); + } + + #[test] + fn private() { + let vis = Cow::Owned(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 = ::db::export::core::option::Option::Some(value); + new + } + ) + .to_string() + ); + } + + #[test] + fn generic() { + let mut setter = default_setter!(); + setter.generic_into = true; + + #[rustfmt::skip] + assert_eq!( + quote!(#setter).to_string(), + quote!( + #[allow(unused_mut)] + pub fn foo<VALUE: ::db::export::core::convert::Into<Foo>>( + &mut self, + value: VALUE + ) -> &mut Self { + let mut new = self; + new.foo = ::db::export::core::option::Option::Some(value.into()); + new + } + ) + .to_string() + ); + } + + #[test] + fn strip_option() { + let ty = parse_quote!(Option<Foo>); + let mut setter = default_setter!(); + setter.strip_option = true; + setter.field_type = BuilderFieldType::Optional(&ty); + + #[rustfmt::skip] + 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 = ::db::export::core::option::Option::Some( + ::db::export::core::option::Option::Some(value) + ); + new + } + ) + .to_string() + ); + } + + #[test] + fn strip_option_into() { + let ty = parse_quote!(Option<Foo>); + let mut setter = default_setter!(); + setter.strip_option = true; + setter.generic_into = true; + setter.field_type = BuilderFieldType::Optional(&ty); + + #[rustfmt::skip] + assert_eq!( + quote!(#setter).to_string(), + quote!( + #[allow(unused_mut)] + pub fn foo<VALUE: ::db::export::core::convert::Into<Foo>>( + &mut self, + value: VALUE + ) -> &mut Self { + let mut new = self; + new.foo = ::db::export::core::option::Option::Some( + ::db::export::core::option::Option::Some(value.into()) + ); + new + } + ) + .to_string() + ); + } + + // including try_setter + #[test] + fn full() { + //named!(outer_attrs -> Vec<syn::Attribute>, many0!(syn::Attribute::parse_outer)); + //let attrs = outer_attrs.parse_str("#[some_attr]").unwrap(); + let attrs: Vec<syn::Attribute> = 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 <VALUE: ::db::export::core::convert::Into<Foo>>(&mut self, value: VALUE) -> &mut Self { + #deprecated + let mut new = self; + new.foo = ::db::export::core::option::Option::Some(value.into()); + new + } + + #[some_attr] + pub fn try_foo<VALUE: ::db::export::core::convert::TryInto<Foo>>(&mut self, value: VALUE) + -> ::db::export::core::result::Result<&mut Self, VALUE::Error> { + let converted : Foo = value.try_into()?; + let mut new = self; + new.foo = ::db::export::core::option::Option::Some(converted); + Ok(new) + } + ).to_string() + ); + } + + #[test] + fn no_std() { + 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 = ::db::export::core::clone::Clone::clone(self); + new.foo = ::db::export::core::option::Option::Some(value); + new + } + ) + .to_string() + ); + } + + #[test] + fn no_std_generic() { + let mut setter = default_setter!(); + setter.generic_into = true; + + #[rustfmt::skip] + assert_eq!( + quote!(#setter).to_string(), + quote!( + #[allow(unused_mut)] + pub fn foo<VALUE: ::db::export::core::convert::Into<Foo>>( + &mut self, + value: VALUE + ) -> &mut Self { + let mut new = self; + new.foo = ::db::export::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; + + #[rustfmt::skip] + 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 = ::db::export::core::option::Option::Some(value); + new + } + + pub fn try_foo<VALUE: ::db::export::core::convert::TryInto<Foo>>( + &mut self, + value: VALUE + ) -> ::db::export::core::result::Result<&mut Self, VALUE::Error> { + let converted: Foo = value.try_into()?; + let mut new = self; + new.foo = ::db::export::core::option::Option::Some(converted); + Ok(new) + } + ) + .to_string() + ); + } + + #[test] + fn extract_type_from_option_on_simple_type() { + let ty_foo = parse_quote!(Foo); + assert_eq!(extract_type_from_option(&ty_foo), None); + + for s in vec![ + parse_quote!(Option<Foo>), + parse_quote!(std::option::Option<Foo>), + parse_quote!(::std::option::Option<Foo>), + parse_quote!(core::option::Option<Foo>), + parse_quote!(::core::option::Option<Foo>), + ] { + assert_eq!(extract_type_from_option(&s), Some(&ty_foo)); + } + } +} |