darling-0.10.2/.gitignore010064400027200000024000000001261355634016400134200ustar0000000000000000/target **/target **/*.rs.bk Cargo.lock .vscode .rls.toml .DS_STORE [._]*.sw? [._]sw? darling-0.10.2/CHANGELOG.md010064400027200000024000000126001355634035000132360ustar0000000000000000# Changelog ## v0.10.2 (October 30, 2019) - Bump syn dependency to 1.0.1 [#83](https://github.com/TedDriggs/darling/pull/83) ## v0.10.1 (September 25, 2019) - Fix test compilation errors [#81](https://github.com/TedDriggs/darling/pull/81) ## v0.10.0 (August 15, 2019) - Bump syn and quote to 1.0 [#79](https://github.com/TedDriggs/darling/pull/79) - Increase rust version to 1.31 ## v0.9.0 (March 20, 2019) - Enable "did you mean" suggestions by default - Make `darling_core::{codegen, options}` private [#58](https://github.com/TedDriggs/darling/issues/58) - Fix `Override::as_mut`: [#66](https://github.com/TedDriggs/darling/issues/66) ## v0.8.6 (March 18, 2019) - Added "did you mean" suggestions for unknown fields behind the `suggestions` flag [#60](https://github.com/TedDriggs/issues/60) - Added `Error::unknown_field_with_alts` to support the suggestion use-case. - Added `ast::Fields::len` and `ast::Fields::is_empty` methods. ## v0.8.5 (February 4, 2019) - Accept unquoted positive numeric literals [#52](https://github.com/TedDriggs/issues/52) - Add `FromMeta` to the `syn::Lit` enum and its variants - Improve error message for unexpected literal formats to not say "other" ## v0.8.4 (February 4, 2019) - Use `syn::Error` to provide precise errors before `proc_macro::Diagnostic` is available - Add `diagnostics` feature flag to toggle between stable and unstable error backends - Attach error information in more contexts - Add `allow_unknown_fields` to support parsing the same attribute multiple times for different macros [#51](https://github.com/darling/issues/51) - Proc-macro authors will now see better errors in `darling` attributes ## v0.8.3 (January 21, 2019) - Attach spans to errors in generated trait impls [#37](https://github.com/darling/issues/37) - Attach spans to errors for types with provided bespoke implementations - Deprecate `set_span` from 0.8.2, as spans should never be broadened after being initially set ## v0.8.2 (January 17, 2019) - Add spans to errors to make quality warnings and errors easy in darling. This is blocked on diagnostics stabilizing. - Add `darling::util::SpannedValue` so proc-macro authors can remember position information alongside parsed values. ## v0.8.0 - Update dependency on `syn` to 0.15 [#44](https://github.com/darling/pull/44). Thanks to @hcpl ## v0.7.0 (July 24, 2018) - Update dependencies on `syn` and `proc-macro2` - Add `util::IdentString`, which acts as an Ident or its string equivalent ## v0.6.3 (May 22, 2018) - Add support for `Uses*` traits in where predicates ## v0.6.2 (May 22, 2018) - Add `usage` module for tracking type param and lifetime usage in generic declarations - Add `UsesTypeParams` and `CollectsTypeParams` traits [#37](https://github.com/darling/issues/37) - Add `UsesLifetimes` and `CollectLifetimes` traits [#41](https://github.com/darling/pull/41) - Don't add `FromMeta` bounds to type parameters only used by skipped fields [#40](https://github.com/darling/pull/40) ## v0.6.1 (May 17, 2018) - Fix an issue where the `syn` update broke shape validation [#36](https://github.com/TedDriggs/darling/issues/36) ## v0.6.0 (May 15, 2018) ### Breaking Changes - Renamed `FromMetaItem` to `FromMeta`, and renamed `from_meta_item` method to `from_meta` - Added dedicated `derive(FromMetaItem)` which panics and redirects users to `FromMeta` ## v0.5.0 (May 10, 2018) - Add `ast::Generics` and `ast::GenericParam` to work with generics in a manner similar to `ast::Data` - Add `ast::GenericParamExt` to support alternate representations of generic parameters - Add `util::WithOriginal` to get a parsed representation and syn's own struct for a syntax block - Add `FromGenerics` and `FromGenericParam` traits (without derive support) - Change generated code for `generics` magic field to invoke `FromGenerics` trait during parsing - Add `FromTypeParam` trait [#30](https://github.com/TedDriggs/darling/pull/30). Thanks to @upsuper ## v0.4.0 (April 5, 2018) - Update dependencies on `proc-macro`, `quote`, and `syn` [#26](https://github.com/TedDriggs/darling/pull/26). Thanks to @hcpl ## v0.3.3 (April 2, 2018) **YANKED** ## v0.3.2 (March 13, 2018) - Derive `Default` on `darling::Ignored` (fixes [#25](https://github.com/TedDriggs/darling/issues/25)). ## v0.3.1 (March 7, 2018) - Support proc-macro2/nightly [#24](https://github.com/TedDriggs/darling/pull/24). Thanks to @kdy1 ## v0.3.0 (January 26, 2018) ### Breaking Changes - Update `syn` to 0.12 [#20](https://github.com/TedDriggs/darling/pull/20). Thanks to @Eijebong - Update `quote` to 0.4 [#20](https://github.com/TedDriggs/darling/pull/20). Thanks to @Eijebong - Rename magic field `body` in derived `FromDeriveInput` structs to `data` to stay in sync with `syn` - Rename magic field `data` in derived `FromVariant` structs to `fields` to stay in sync with `syn` ## v0.2.2 (December 5, 2017) - Update `lazy_static` to 1.0 [#15](https://github.com/TedDriggs/darling/pull/16). Thanks to @Eijebong ## v0.2.1 (November 28, 2017) - Add `impl FromMetaItem` for integer types [#15](https://github.com/TedDriggs/darling/pull/15) ## v0.2.0 (June 18, 2017) - Added support for returning multiple errors from parsing [#5](https://github.com/TedDriggs/darling/pull/5) - Derived impls no longer return on first error [#5](https://github.com/TedDriggs/darling/pull/5) - Removed default types for `V` and `F` from `ast::Body` - Enum variants are automatically converted to snake_case [#12](https://github.com/TedDriggs/darling/pull/12) darling-0.10.2/Cargo.toml.orig010064400027200000024000000015171355634035000143210ustar0000000000000000[package] name = "darling" version = "0.10.2" authors = ["Ted Driggs "] repository = "https://github.com/TedDriggs/darling" documentation = "https://docs.rs/darling/0.10.2" description = """ A proc-macro library for reading attributes into structs when implementing custom derives. """ license = "MIT" readme = "README.md" exclude = ["/.travis.yml", "/publish.sh"] [badges] travis-ci = { repository = "TedDriggs/darling" } maintenance = { status = "actively-developed" } [dependencies] darling_core = { version = "=0.10.2", path = "core" } darling_macro = { version = "=0.10.2", path = "macro" } [dev-dependencies] proc-macro2 = "1" quote = "1" syn = "1" [features] default = ["suggestions"] diagnostics = ["darling_core/diagnostics"] suggestions = ["darling_core/suggestions"] [workspace] members = ["macro", "core"] darling-0.10.2/Cargo.toml0000644000000025200000000000000105700ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "darling" version = "0.10.2" authors = ["Ted Driggs "] exclude = ["/.travis.yml", "/publish.sh"] description = "A proc-macro library for reading attributes into structs when\nimplementing custom derives.\n" documentation = "https://docs.rs/darling/0.10.2" readme = "README.md" license = "MIT" repository = "https://github.com/TedDriggs/darling" [dependencies.darling_core] version = "=0.10.2" [dependencies.darling_macro] version = "=0.10.2" [dev-dependencies.proc-macro2] version = "1" [dev-dependencies.quote] version = "1" [dev-dependencies.syn] version = "1" [features] default = ["suggestions"] diagnostics = ["darling_core/diagnostics"] suggestions = ["darling_core/suggestions"] [badges.maintenance] status = "actively-developed" [badges.travis-ci] repository = "TedDriggs/darling" darling-0.10.2/LICENSE010064400027200000024000000020531320461243200124240ustar0000000000000000MIT License Copyright (c) 2017 Ted Driggs 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. darling-0.10.2/README.md010064400027200000024000000132111352533635700127130ustar0000000000000000Darling ======= [![Build Status](https://travis-ci.org/TedDriggs/darling.svg?branch=master)](https://travis-ci.org/TedDriggs/darling) [![Latest Version](https://img.shields.io/crates/v/darling.svg)](https://crates.io/crates/darling) [![Rustc Version 1.31+](https://img.shields.io/badge/rustc-1.31+-lightgray.svg)](https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html) `darling` is a crate for proc macro authors, which enables parsing attributes into structs. It is heavily inspired by `serde` both in its internals and in its API. # Benefits * Easy and declarative parsing of macro input - make your proc-macros highly controllable with minimal time investment. * Great validation and errors, no work required. When users of your proc-macro make a mistake, `darling` makes sure they get error markers at the right place in their source, and provides "did you mean" suggestions for misspelled fields. # Usage `darling` provides a set of traits which can be derived or manually implemented. 1. `FromMeta` is used to extract values from a meta-item in an attribute. Implementations are likely reusable for many libraries, much like `FromStr` or `serde::Deserialize`. Trait implementations are provided for primitives, some std types, and some `syn` types. 2. `FromDeriveInput` is implemented or derived by each proc-macro crate which depends on `darling`. This is the root for input parsing; it gets access to the identity, generics, and visibility of the target type, and can specify which attribute names should be parsed or forwarded from the input AST. 3. `FromField` is implemented or derived by each proc-macro crate which depends on `darling`. Structs deriving this trait will get access to the identity (if it exists), type, and visibility of the field. 4. `FromVariant` is implemented or derived by each proc-macro crate which depends on `darling`. Structs deriving this trait will get access to the identity and contents of the variant, which can be transformed the same as any other `darling` input. ## Additional Modules * `darling::ast` provides generic types for representing the AST. * `darling::usage` provides traits and functions for determining where type parameters and lifetimes are used in a struct or enum. * `darling::util` provides helper types with special `FromMeta` implementations, such as `IdentList`. # Example ```rust,ignore #[macro_use] extern crate darling; extern crate syn; #[derive(Default, FromMeta)] #[darling(default)] pub struct Lorem { #[darling(rename = "sit")] ipsum: bool, dolor: Option, } #[derive(FromDeriveInput)] #[darling(from_ident, attributes(my_crate), forward_attrs(allow, doc, cfg))] pub struct MyTraitOpts { ident: syn::Ident, attrs: Vec, lorem: Lorem, } ``` The above code will then be able to parse this input: ```rust,ignore /// A doc comment which will be available in `MyTraitOpts::attrs`. #[derive(MyTrait)] #[my_crate(lorem(dolor = "Hello", ipsum))] pub struct ConsumingType; ``` # Attribute Macros Non-derive attribute macros are supported. To parse arguments for attribute macros, derive `FromMeta` on the argument receiver type, then pass `&syn::AttributeArgs` to the `from_list` method. This will produce a normal `darling::Result` that can be used the same as a result from parsing a `DeriveInput`. ## Macro Code ```rust,ignore use darling::FromMeta; use syn::{AttributeArgs, ItemFn}; use proc_macro::TokenStream; #[derive(Debug, FromMeta)] pub struct MacroArgs { #[darling(default)] timeout_ms: Option, path: String, } #[proc_macro_attribute] fn your_attr(args: TokenStream, input: TokenStream) -> TokenStream { let attr_args = parse_macro_input!(args as AttributeArgs); let _input = parse_macro_input!(input as ItemFn); let _args = match MacroArgs::from_list(&attr_args) { Ok(v) => v, Err(e) => { return e.write_errors(); } }; // do things with `args` unimplemented!() } ``` ## Consuming Code ```rust,ignore use your_crate::your_attr; #[your_attr(path = "hello", timeout_ms = 15)] fn do_stuff() { println!("Hello"); } ``` # Features Darling's features are built to work well for real-world projects. * **Defaults**: Supports struct- and field-level defaults, using the same path syntax as `serde`. * **Field Renaming**: Fields can have different names in usage vs. the backing code. * **Auto-populated fields**: Structs deriving `FromDeriveInput` and `FromField` can declare properties named `ident`, `vis`, `ty`, `attrs`, and `generics` to automatically get copies of the matching values from the input AST. `FromDeriveInput` additionally exposes `data` to get access to the body of the deriving type, and `FromVariant` exposes `fields`. * **Mapping function**: Use `#[darling(map="path")]` to specify a function that runs on the result of parsing a meta-item field. This can change the return type, which enables you to parse to an intermediate form and convert that to the type you need in your struct. * **Skip fields**: Use `#[darling(skip)]` to mark a field that shouldn't be read from attribute meta-items. * **Multiple-occurrence fields**: Use `#[darling(multiple)]` on a `Vec` field to allow that field to appear multiple times in the meta-item. Each occurrence will be pushed into the `Vec`. * **Span access**: Use `darling::util::SpannedValue` in a struct to get access to that meta item's source code span. This can be used to emit warnings that point at a specific field from your proc macro. In addition, you can use `darling::Error::write_errors` to automatically get precise error location details in most cases. * **"Did you mean" suggestions**: Compile errors from derived darling trait impls include suggestions for misspelled fields.darling-0.10.2/examples/automatic_bounds.rs010064400027200000024000000033571352533544000171620ustar0000000000000000#[macro_use] extern crate darling; extern crate syn; use darling::FromDeriveInput; #[derive(FromMeta, PartialEq, Eq, Debug)] enum Volume { Whisper, Talk, Shout, } /// A more complex example showing the ability to skip at a field or struct /// level while still tracking which type parameters need to be bounded. /// This can be seen by expanding this example using `cargo expand`. #[derive(FromMeta)] #[allow(dead_code)] enum Emphasis { Constant(Volume), Variable(darling::util::PathList), #[darling(skip)] PerPhoneme(Option), Strided { #[darling(skip)] step: Vec, #[darling(multiple)] volume: Vec, }, } #[derive(FromDeriveInput)] #[darling(attributes(speak))] struct SpeakingOptions { max_volume: U, #[darling(skip, default)] additional_data: Vec, } #[derive(Default)] struct Phoneme { #[allow(dead_code)] first: String, } // This is probably the holy grail for `darling`'s own internal use-case: // Auto-apply `Default` bound to skipped *field* types in `where` clause. impl Default for SpeakingOptions where Vec: Default, U: Default, { fn default() -> Self { Self { max_volume: Default::default(), additional_data: Default::default(), } } } fn main() { let derive_input = syn::parse_str( r#" #[derive(Speak)] #[speak(max_volume = "shout")] enum HtmlElement { Div(String) } "#, ) .unwrap(); let parsed: SpeakingOptions = FromDeriveInput::from_derive_input(&derive_input).unwrap(); assert_eq!(parsed.max_volume, Volume::Shout); assert_eq!(parsed.additional_data.len(), 0); } darling-0.10.2/examples/consume_fields.rs010064400027200000024000000120041342024242700166020ustar0000000000000000//! This example shows how to do struct and field parsing using darling. #[macro_use] extern crate darling; extern crate proc_macro2; #[macro_use] extern crate quote; extern crate syn; use darling::ast; use darling::FromDeriveInput; use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse_str; /// A speaking volume. Deriving `FromMeta` will cause this to be usable /// as a string value for a meta-item key. #[derive(Debug, Clone, Copy, FromMeta)] #[darling(default)] enum Volume { Normal, Whisper, Shout, } impl Default for Volume { fn default() -> Self { Volume::Normal } } /// Support parsing from a full derive input. Unlike FromMeta, this isn't /// composable; each darling-dependent crate should have its own struct to handle /// when its trait is derived. #[derive(Debug, FromDeriveInput)] // This line says that we want to process all attributes declared with `my_trait`, // and that darling should panic if this receiver is given an enum. #[darling(attributes(my_trait), supports(struct_any))] struct MyInputReceiver { /// The struct ident. ident: syn::Ident, /// The type's generics. You'll need these any time your trait is expected /// to work with types that declare generics. generics: syn::Generics, /// Receives the body of the struct or enum. We don't care about /// struct fields because we previously told darling we only accept structs. data: ast::Data<(), MyFieldReceiver>, /// The Input Receiver demands a volume, so use `Volume::Normal` if the /// caller doesn't provide one. #[darling(default)] volume: Volume, } impl ToTokens for MyInputReceiver { fn to_tokens(&self, tokens: &mut TokenStream) { let MyInputReceiver { ref ident, ref generics, ref data, volume, } = *self; let (imp, ty, wher) = generics.split_for_impl(); let fields = data .as_ref() .take_struct() .expect("Should never be enum") .fields; // Generate the format string which shows each field and its name let fmt_string = fields .iter() .enumerate() .map(|(i, f)| { // We have to preformat the ident in this case so we can fall back // to the field index for unnamed fields. It's not easy to read, // unfortunately. format!( "{} = {{}}", f.ident .as_ref() .map(|v| format!("{}", v)) .unwrap_or_else(|| format!("{}", i)) ) }) .collect::>() .join(", "); // Generate the actual values to fill the format string. let field_list = fields .into_iter() .enumerate() .map(|(i, f)| { let field_volume = f.volume.unwrap_or(volume); // This works with named or indexed fields, so we'll fall back to the index so we can // write the output as a key-value pair. let field_ident = f.ident .as_ref() .map(|v| quote!(#v)) .unwrap_or_else(|| quote!(#i)); match field_volume { Volume::Normal => quote!(self.#field_ident), Volume::Shout => { quote!(::std::string::ToString::to_string(&self.#field_ident).to_uppercase()) } Volume::Whisper => { quote!(::std::string::ToString::to_string(&self.#field_ident).to_lowercase()) } } }) .collect::>(); tokens.extend(quote! { impl #imp Speak for #ident #ty #wher { fn speak(&self, writer: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { write!(#fmt_string, #(#field_list),*) } } }); } } #[derive(Debug, FromField)] #[darling(attributes(my_trait))] struct MyFieldReceiver { /// Get the ident of the field. For fields in tuple or newtype structs or /// enum bodies, this can be `None`. ident: Option, /// This magic field name pulls the type from the input. ty: syn::Type, /// We declare this as an `Option` so that during tokenization we can write /// `field.volume.unwrap_or(derive_input.volume)` to facilitate field-level /// overrides of struct-level settings. #[darling(default)] volume: Option, } fn main() { let input = r#"#[derive(MyTrait)] #[my_trait(volume = "shout")] pub struct Foo { #[my_trait(volume = "whisper")] bar: bool, baz: i64, }"#; let parsed = parse_str(input).unwrap(); let receiver = MyInputReceiver::from_derive_input(&parsed).unwrap(); let tokens = quote!(#receiver); println!( r#" INPUT: {} PARSED AS: {:?} EMITS: {} "#, input, receiver, tokens ); } darling-0.10.2/examples/fallible_read.rs010064400027200000024000000051121344444330400163550ustar0000000000000000//! This example demonstrates techniques for performing custom error handling //! in a derive-input receiver. //! //! 1. Using `darling::Result` as a carrier to preserve the error for later display //! 1. Using `Result` to attempt a recovery in imperative code //! 1. Using the `map` darling meta-item to post-process the receiver before returning. #[macro_use] extern crate darling; extern crate syn; use darling::{FromDeriveInput, FromMeta}; use syn::parse_str; #[derive(Debug, FromDeriveInput)] #[darling(attributes(my_trait), map = "MyInputReceiver::autocorrect")] pub struct MyInputReceiver { /// This field must be present and a string or else parsing will panic. name: String, /// If this field fails to parse, the struct can still be built; the field /// will contain the error. The consuming struct can then decide if this /// blocks code generation. If so, panic. Otherwise, recover and proceed. frequency: darling::Result, /// If this field fails to parse, the struct can still be built; the field /// will contain an `Err` with the original `syn::Meta`. This can be used /// for alternate parsing attempts before panicking. amplitude: Result, } impl MyInputReceiver { /// This function will be called by `darling` _after_ it's finished parsing the /// input but before returning to the caller. This is a good place to initialize /// skipped fields or to perform corrections that don't lend themselves to being /// done elsewhere. fn autocorrect(self) -> Self { let Self { name, frequency, amplitude, } = self; // Amplitude doesn't have a sign, so if we received a negative number then // we'll go ahead and make it positive. let amplitude = match amplitude { Ok(amp) => amp, Err(mi) => { let val: i64 = if let Ok(v) = FromMeta::from_meta(&mi) { v } else { panic!(format!("amplitude should have been an integer")) }; val.abs() as u64 } }; Self { name, frequency, amplitude: Ok(amplitude), } } } fn main() { let input = r#"#[derive(MyTrait)] #[my_trait(name="Jon", amplitude = "-1", frequency = "1")] pub struct Foo;"#; let parsed = parse_str(input).unwrap(); let receiver = MyInputReceiver::from_derive_input(&parsed).unwrap(); println!( r#" INPUT: {} PARSED AS: {:?} "#, input, receiver ); } darling-0.10.2/examples/supports_struct.rs010064400027200000024000000021311342024377000171100ustar0000000000000000#[macro_use] extern crate darling; extern crate syn; use darling::{ast, util, FromDeriveInput}; use syn::{Ident, Type}; #[derive(Debug, FromField)] #[darling(attributes(lorem))] pub struct LoremField { ident: Option, ty: Type, #[darling(default)] skip: bool, } #[derive(Debug, FromDeriveInput)] #[darling(attributes(lorem), supports(struct_named))] pub struct Lorem { ident: Ident, data: ast::Data, } fn main() { let good_input = r#"#[derive(Lorem)] pub struct Foo { #[lorem(skip)] bar: bool, baz: i64, }"#; let bad_input = r#"#[derive(Lorem)] pub struct BadFoo(String, u32);"#; let parsed = syn::parse_str(good_input).unwrap(); let receiver = Lorem::from_derive_input(&parsed).unwrap(); let wrong_shape_parsed = syn::parse_str(bad_input).unwrap(); let wrong_shape = Lorem::from_derive_input(&wrong_shape_parsed).expect_err("Shape was wrong"); println!( r#" INPUT: {} PARSED AS: {:?} BAD INPUT: {} PRODUCED ERROR: {} "#, good_input, receiver, bad_input, wrong_shape ); } darling-0.10.2/src/lib.rs010064400027200000024000000112261335453366700133460ustar0000000000000000//! # Darling //! Darling is a tool for declarative attribute parsing in proc macro implementations. //! //! //! ## Design //! Darling takes considerable design inspiration from [`serde`]. A data structure that can be //! read from any attribute implements `FromMeta` (or has an implementation automatically //! generated using `derive`). Any crate can provide `FromMeta` implementations, even one not //! specifically geared towards proc-macro authors. //! //! Proc-macro crates should provide their own structs which implement or derive `FromDeriveInput`, //! `FromField`, `FromVariant`, `FromGenerics`, _et alia_ to gather settings relevant to their operation. //! //! ## Attributes //! There are a number of attributes that `darling` exposes to enable finer-grained control over the code //! it generates. //! //! * **Field renaming**: You can use `#[darling(rename="new_name")]` on a field to change the name Darling looks for. //! You can also use `#[darling(rename_all="...")]` at the struct or enum level to apply a casing rule to all fields or variants. //! * **Map function**: You can use `#[darling(map="path::to::function")]` to run code on a field before its stored in the struct. //! * **Default values**: You can use `#[darling(default)]` at the type or field level to use that type's default value to fill //! in values not specified by the caller. //! * **Skipped fields**: You can skip a variant or field using `#[darling(skip)]`. Fields marked with this will fall back to //! `Default::default()` for their value, but you can override that with an explicit default or a value from the type-level default. //! //! ## Forwarded Fields //! All derivable traits except `FromMeta` support forwarding some fields from the input AST to the derived struct. //! These fields are matched up by identifier **before** `rename` attribute values are considered, //! allowing you to use their names for your own properties. //! The deriving struct is responsible for making sure the types of fields it chooses to declare are compatible with this table. //! //! A deriving struct is free to include or exclude any of the fields below. //! //! ### `FromDeriveInput` //! |Field name|Type|Meaning| //! |---|---|---| //! |`ident`|`syn::Ident`|The identifier of the passed-in type| //! |`vis`|`syn::Visibility`|The visibility of the passed-in type| //! |`generics`|`T: darling::FromGenerics`|The generics of the passed-in type. This can be `syn::Generics`, `darling::ast::Generics`, or any compatible type.| //! |`data`|`darling::ast::Data`|The body of the passed-in type| //! |`attrs`|`Vec`|The forwarded attributes from the passed in type. These are controlled using the `forward_attrs` attribute.| //! //! ### `FromField` //! |Field name|Type|Meaning| //! |---|---|---| //! |`ident`|`syn::Ident`|The identifier of the passed-in field| //! |`vis`|`syn::Visibility`|The visibility of the passed-in field| //! |`ty`|`syn::Type`|The type of the passed-in field| //! |`attrs`|`Vec`|The forwarded attributes from the passed in field. These are controlled using the `forward_attrs` attribute.| //! //! ### `FromTypeParam` //! |Field name|Type|Meaning| //! |---|---|---| //! |`ident`|`syn::Ident`|The identifier of the passed-in type param| //! |`bounds`|`Vec`|The bounds applied to the type param| //! |`default`|`Option`|The default type of the parameter, if one exists| //! |`attrs`|`Vec`|The forwarded attributes from the passed in type param. These are controlled using the `forward_attrs` attribute.| extern crate core; extern crate darling_core; #[allow(unused_imports)] #[macro_use] extern crate darling_macro; #[doc(hidden)] pub use darling_macro::*; #[doc(inline)] pub use darling_core::{FromDeriveInput, FromField, FromGenericParam, FromGenerics, FromMeta, FromTypeParam, FromVariant}; #[doc(inline)] pub use darling_core::{Error, Result}; #[doc(inline)] pub use darling_core::{ast, error, usage, util}; // XXX exported so that `ExtractAttribute::extractor` can convert a path into tokens. // This is likely to change in the future, so only generated code should depend on this export. #[doc(hidden)] pub use darling_core::ToTokens; /// Core/std trait re-exports. This should help produce generated code which doesn't /// depend on `std` unnecessarily, and avoids problems caused by aliasing `std` or any /// of the referenced types. #[doc(hidden)] pub mod export { pub use core::convert::From; pub use core::default::Default; pub use core::option::Option::{self, None, Some}; pub use core::result::Result::{self, Err, Ok}; pub use std::vec::Vec; pub use std::string::ToString; } #[macro_use] mod macros_public; darling-0.10.2/src/macros_public.rs010064400027200000024000000070221330106735100154010ustar0000000000000000//! Macros that should be exported from both `darling_core` and `darling`. //! Note that these are **sym-linked** into the main code, and so cannot declare on items that are exported differently //! in `darling_core` vs. `darling`. /// Generator for `UsesTypeParam` impls that unions the used type parameters of the selected fields. /// /// # Usage /// The macro takes the type implementing the trait as the first argument, then a comma-separated list of /// fields for the rest of its arguments. /// /// The type of each passed-in field must implement `UsesTypeParams`, or the resulting code won't compile. /// /// ```rust /// # extern crate syn; /// # /// # #[macro_use] /// # extern crate darling_core; /// # /// struct MyField { /// ty: syn::Type, /// } /// /// uses_type_params!(MyField, ty); /// /// fn main() { /// // no test run /// } /// ``` /// /// `darling` cannot derive this trait automatically, as it doesn't know which information extracted from /// proc-macro input is meant to constitute "using" the type parameter, but crate consumers should /// implement it by hand or using the macro. #[macro_export] macro_rules! uses_type_params { ($impl_type:ty, $accessor:ident) => { impl $crate::usage::UsesTypeParams for $impl_type { fn uses_type_params<'gen>( &self, options: &$crate::usage::Options, type_set: &'gen $crate::usage::IdentSet ) -> $crate::usage::IdentRefSet<'gen> { self.$accessor.uses_type_params(options, type_set) } } }; ($impl_type:ty, $first:ident, $($field:ident),+) => { impl $crate::usage::UsesTypeParams for $impl_type { fn uses_type_params<'gen>( &self, options: &$crate::usage::Options, type_set: &'gen $crate::usage::IdentSet ) -> $crate::usage::IdentRefSet<'gen> { let mut hits = self.$first.uses_type_params(options, type_set); $( hits.extend(self.$field.uses_type_params(options, type_set)); )* hits } } }; } /// Generator for `UsesLifetimes` impls that unions the used lifetimes of the selected fields. /// /// # Usage /// The macro takes the type implementing the trait as the first argument, then a comma-separated list of /// fields for the rest of its arguments. /// /// The type of each passed-in field must implement `UsesLifetimes`, or the resulting code won't compile. #[macro_export] macro_rules! uses_lifetimes { ($impl_type:ty, $accessor:ident) => { impl $crate::usage::UsesLifetimes for $impl_type { fn uses_lifetimes<'gen>( &self, options: &$crate::usage::Options, type_set: &'gen $crate::usage::LifetimeSet ) -> $crate::usage::LifetimeRefSet<'gen> { self.$accessor.uses_lifetimes(options, type_set) } } }; ($impl_type:ty, $first:ident, $($field:ident),+) => { impl $crate::usage::UsesLifetimes for $impl_type { fn uses_lifetimes<'gen>( &self, options: &$crate::usage::Options, type_set: &'gen $crate::usage::LifetimeSet ) -> $crate::usage::LifetimeRefSet<'gen> { let mut hits = self.$first.uses_lifetimes(options, type_set); $( hits.extend(self.$field.uses_lifetimes(options, type_set)); )* hits } } }; } darling-0.10.2/tests/accrue_errors.rs010064400027200000024000000045361342734324700160110ustar0000000000000000//! These tests verify that multiple errors will be collected up from throughout //! the parsing process and returned correctly to the caller. #[macro_use] extern crate darling; #[macro_use] extern crate syn; #[macro_use] extern crate quote; use darling::ast; use darling::FromDeriveInput; #[derive(Debug, FromDeriveInput)] #[darling(attributes(accrue))] struct Lorem { ipsum: String, dolor: Dolor, data: ast::Data<(), LoremField>, } #[derive(Debug, FromMeta)] struct Dolor { sit: bool, } #[derive(Debug, FromField)] #[darling(attributes(accrue))] struct LoremField { ident: Option, aliased_as: syn::Ident, } #[test] fn bad_type_and_missing_fields() { let input = parse_quote! { #[accrue(ipsum = true, dolor(amet = "Hi"))] pub struct NonConforming { foo: () } }; let s_result: ::darling::Error = Lorem::from_derive_input(&input).unwrap_err(); let err = s_result.flatten(); println!("{}", err); assert_eq!(3, err.len()); } #[test] fn body_only_issues() { let input = parse_quote! { #[accrue(ipsum = "Hello", dolor(sit))] pub struct NonConforming { foo: (), bar: bool, } }; let s_err = Lorem::from_derive_input(&input).unwrap_err(); println!("{:?}", s_err); assert_eq!(2, s_err.len()); } #[derive(Debug, FromMeta)] enum Week { Monday, Tuesday { morning: bool, afternoon: String }, Wednesday(Dolor), } #[derive(Debug, FromDeriveInput)] #[darling(attributes(accrue))] struct Month { schedule: Week, } #[test] fn error_in_enum_fields() { let input = parse_quote! { #[accrue(schedule(tuesday(morning = "yes")))] pub struct NonConforming { foo: (), bar: bool, } }; let s_err = Month::from_derive_input(&input).unwrap_err(); assert_eq!(2, s_err.len()); let err = s_err.flatten(); // TODO add tests to check location path is correct println!("{}", err); } #[test] fn error_in_newtype_variant() { let input = parse_quote! { #[accrue(schedule(wednesday(sit = "yes")))] pub struct NonConforming { foo: (), bar: bool, } }; let s_err = Month::from_derive_input(&input).unwrap_err(); assert_eq!(1, s_err.len()); println!("{}", s_err); println!("{}", s_err.flatten()); } darling-0.10.2/tests/computed_bound.rs010064400027200000024000000015671342733524300161600ustar0000000000000000#[macro_use] extern crate darling; extern crate syn; use darling::FromDeriveInput; fn parse(src: &str) -> T { let ast = syn::parse_str(src).unwrap(); FromDeriveInput::from_derive_input(&ast).unwrap() } #[derive(FromMeta, PartialEq, Eq, Debug)] enum Volume { Whisper, Talk, Shout, } #[derive(FromDeriveInput)] #[darling(attributes(speak))] struct SpeakingOptions { max_volume: U, #[darling(skip)] #[allow(dead_code)] additional_data: T, } #[derive(Default)] struct Phoneme { #[allow(dead_code)] first: String, } #[test] fn skipped_field() { let parsed: SpeakingOptions = parse( r#" #[derive(Speak)] #[speak(max_volume = "shout")] enum HtmlElement { Div(String) } "#, ); assert_eq!(parsed.max_volume, Volume::Shout); } darling-0.10.2/tests/custom_bound.rs010064400027200000024000000010221327667427600156520ustar0000000000000000#[macro_use] extern crate darling; extern crate syn; use std::ops::Add; #[derive(Debug, Clone, FromMeta)] #[darling(bound = "T: FromMeta + Add")] struct Wrapper(pub T); impl Add for Wrapper { type Output = Wrapper<::Output>; fn add(self, rhs: Self) -> Wrapper<::Output> { Wrapper(self.0 + rhs.0) } } #[derive(Debug, FromDeriveInput)] #[darling(attributes(hello), bound = "Wrapper: Add, T: FromMeta")] struct Foo { lorem: Wrapper, } #[test] fn expansion() {} darling-0.10.2/tests/defaults.rs010064400027200000024000000011661344444330400147500ustar0000000000000000#[macro_use] extern crate darling; #[macro_use] extern crate quote; #[macro_use] extern crate syn; use darling::FromDeriveInput; mod foo { pub mod bar { pub fn init() -> String { String::from("hello") } } } #[derive(FromDeriveInput)] #[darling(attributes(speak))] pub struct SpeakerOpts { #[darling(default="foo::bar::init")] first_word: String, } #[test] fn path_default() { let speaker: SpeakerOpts = FromDeriveInput::from_derive_input(&parse_quote! { struct Foo; }).expect("Unit struct with no attrs should parse"); assert_eq!(speaker.first_word, "hello"); }darling-0.10.2/tests/enums_newtype.rs010064400027200000024000000035401342734324700160470ustar0000000000000000#[macro_use] extern crate darling; #[macro_use] extern crate syn; #[macro_use] extern crate quote; use darling::FromDeriveInput; #[derive(Debug, Default, PartialEq, Eq, FromMeta)] #[darling(default)] pub struct Amet { hello: bool, world: String, } #[derive(Debug, PartialEq, Eq, FromMeta)] #[darling(rename_all = "snake_case")] pub enum Lorem { Ipsum(bool), Dolor(String), Sit(Amet), } #[derive(Debug, PartialEq, Eq, FromDeriveInput)] #[darling(attributes(hello))] pub struct Holder { lorem: Lorem, } impl PartialEq for Holder { fn eq(&self, other: &Lorem) -> bool { self.lorem == *other } } #[test] fn bool_word() { let di = parse_quote! { #[hello(lorem(ipsum))] pub struct Bar; }; let pr = Holder::from_derive_input(&di).unwrap(); assert_eq!(pr, Lorem::Ipsum(true)); } #[test] fn bool_literal() { let di = parse_quote! { #[hello(lorem(ipsum = false))] pub struct Bar; }; let pr = Holder::from_derive_input(&di).unwrap(); assert_eq!(pr, Lorem::Ipsum(false)); } #[test] fn string_literal() { let di = parse_quote! { #[hello(lorem(dolor = "Hello"))] pub struct Bar; }; let pr = Holder::from_derive_input(&di).unwrap(); assert_eq!(pr, Lorem::Dolor("Hello".to_string())); } #[test] fn struct_nested() { let di = parse_quote! { #[hello(lorem(sit(world = "Hello", hello = false)))] pub struct Bar; }; let pr = Holder::from_derive_input(&di).unwrap(); assert_eq!( pr, Lorem::Sit(Amet { hello: false, world: "Hello".to_string(), }) ); } #[test] #[should_panic] fn format_mismatch() { let di = parse_quote! { #[hello(lorem(dolor(world = "Hello", hello = false)))] pub struct Bar; }; Holder::from_derive_input(&di).unwrap(); } darling-0.10.2/tests/enums_struct.rs010064400027200000024000000004561327667427600157160ustar0000000000000000//! Test expansion of enums which have struct variants. #[macro_use] extern crate darling; extern crate syn; #[derive(Debug, FromMeta)] #[darling(rename_all = "snake_case")] enum Message { Hello { user: String, silent: bool }, Ping, Goodbye { user: String }, } #[test] fn expansion() {} darling-0.10.2/tests/enums_unit.rs010064400027200000024000000004161327667427600153450ustar0000000000000000//! Test expansion of enum variants which have no associated data. #[macro_use] extern crate darling; extern crate syn; #[derive(Debug, FromMeta)] #[darling(rename_all = "snake_case")] enum Pattern { Owned, Immutable, Mutable, } #[test] fn expansion() {} darling-0.10.2/tests/error.rs010064400027200000024000000021321342734324700142720ustar0000000000000000//! In case of bad input, parsing should fail. The error should have locations set in derived implementations. #[macro_use] extern crate darling; #[macro_use] extern crate syn; #[macro_use] extern crate quote; use darling::FromDeriveInput; #[derive(Debug, FromMeta)] struct Dolor { #[darling(rename = "amet")] sit: bool, world: bool, } #[derive(Debug, FromDeriveInput)] #[darling(from_ident, attributes(hello))] struct Lorem { ident: syn::Ident, ipsum: Dolor, } impl From for Lorem { fn from(ident: syn::Ident) -> Self { Lorem { ident, ipsum: Dolor { sit: false, world: true, }, } } } #[test] fn parsing_fail() { let di = parse_quote! { #[hello(ipsum(amet = "yes", world = false))] pub struct Foo; }; println!("{}", Lorem::from_derive_input(&di).unwrap_err()); } #[test] fn missing_field() { let di = parse_quote! { #[hello(ipsum(amet = true))] pub struct Foo; }; println!("{}", Lorem::from_derive_input(&di).unwrap_err()); } darling-0.10.2/tests/from_generics.rs010064400027200000024000000116511332564236600157720ustar0000000000000000//! Tests for `FromGenerics`, and - indirectly - `FromGenericParam`. //! These tests assume `FromTypeParam` is working and only look at whether the wrappers for magic //! fields are working as expected. #[macro_use] extern crate darling; extern crate syn; use darling::ast::{self, GenericParamExt}; use darling::util::{Ignored, WithOriginal}; use darling::{FromDeriveInput, Result}; #[derive(FromDeriveInput)] #[darling(attributes(lorem))] struct MyReceiver { pub ident: syn::Ident, pub generics: ast::Generics>, } #[derive(FromTypeParam)] #[darling(attributes(lorem))] struct MyTypeParam { pub ident: syn::Ident, #[darling(default)] pub foo: bool, #[darling(default)] pub bar: Option, } fn fdi(src: &str) -> Result { FromDeriveInput::from_derive_input(&syn::parse_str(src).expect("Source parses")) } /// Verify that `ast::Generics` is populated correctly when there is no generics declaration #[test] fn no_generics() { let rec: MyReceiver = fdi("struct Baz;").expect("Input is well-formed"); assert!(rec.generics.where_clause.is_none()); assert_eq!(rec.generics.params.len(), 0); } #[test] fn expand_some() { let rec: MyReceiver = fdi(r#" struct Baz< 'a, #[lorem(foo)] T, #[lorem(bar = "x")] U: Eq + ?Sized >(&'a T, U); "#) .expect("Input is well-formed"); assert!(rec.generics.where_clause.is_none()); // Make sure we've preserved the lifetime def, though we don't do anything with it. assert!(rec.generics.params[0].as_lifetime_def().is_some()); let mut ty_param_iter = rec.generics.type_params(); let first = ty_param_iter .next() .expect("type_params should not be empty"); assert!(first.bar.is_none()); assert!(first.foo); assert_eq!(first.ident, "T"); let second = ty_param_iter .next() .expect("type_params should have a second value"); assert_eq!( second .bar .as_ref() .expect("Second type param should set bar"), "x" ); assert_eq!(second.foo, false); assert_eq!(second.ident, "U"); } /// Verify ≤0.4.1 behavior - where `generics` had to be `syn::Generics` - keeps working. #[test] fn passthrough() { #[derive(FromDeriveInput)] struct PassthroughReceiver { pub generics: syn::Generics, } let rec: PassthroughReceiver = fdi(r#" struct Baz< 'a, #[lorem(foo)] T, #[lorem(bar = "x")] U: Eq + ?Sized >(&'a T, U); "#) .expect("Input is well-formed"); let mut type_param_iter = rec.generics.type_params(); assert!(type_param_iter.next().is_some()); } /// Verify that `where_clause` is passed through when it exists. /// As of 0.4.1, there is no `FromWhereClause` trait, so other types aren't supported /// for that field. #[test] fn where_clause() { let rec: MyReceiver = fdi(r#" struct Baz< 'a, #[lorem(foo)] T, #[lorem(bar = "x")] U: Eq + ?Sized >(&'a T, U) where T: Into; "#) .expect("Input is well-formed"); assert!(rec.generics.where_clause.is_some()); } /// Test that `WithOriginal` works for generics. #[test] fn with_original() { #[derive(FromDeriveInput)] struct WorigReceiver { generics: WithOriginal>, syn::Generics>, } let rec: WorigReceiver = fdi(r#" struct Baz< 'a, #[lorem(foo)] T, #[lorem(bar = "x")] U: Eq + ?Sized >(&'a T, U) where T: Into; "#) .expect("Input is well-formed"); // Make sure we haven't lost anything in the conversion assert_eq!(rec.generics.parsed.params.len(), 3); assert_eq!( rec.generics .original .params .iter() .collect::>() .len(), 3 ); let parsed_t: &MyTypeParam = rec.generics.parsed.params[1] .as_type_param() .expect("Second argument should be type param"); // Make sure the first type param in each case is T assert_eq!(parsed_t.ident, "T"); assert_eq!( rec.generics .original .type_params() .next() .expect("First type param should exist") .ident, "T" ); // Make sure we actually parsed the first type param assert!(parsed_t.foo); assert!(parsed_t.bar.is_none()); } /// Make sure generics can be ignored #[test] fn ignored() { #[derive(FromDeriveInput)] struct IgnoredReceiver { generics: Ignored, } let rec: IgnoredReceiver = fdi(r#" struct Baz< 'a, #[lorem(foo)] T, #[lorem(bar = "x")] U: Eq + ?Sized >(&'a T, U) where T: Into; "#) .expect("Input is well-formed"); assert_eq!(Ignored, rec.generics); } darling-0.10.2/tests/from_type_param.rs010064400027200000024000000027121344444330400163230ustar0000000000000000#[macro_use] extern crate darling; #[macro_use] extern crate syn; #[macro_use] extern crate quote; use darling::FromTypeParam; use syn::{DeriveInput, GenericParam, Ident, TypeParam}; #[darling(attributes(lorem), from_ident)] #[derive(FromTypeParam)] struct Lorem { ident: Ident, bounds: Vec, foo: bool, bar: Option, } impl From for Lorem { fn from(ident: Ident) -> Self { Lorem { ident, foo: false, bar: None, bounds: Default::default(), } } } fn extract_type(param: &GenericParam) -> &TypeParam { match *param { GenericParam::Type(ref ty) => ty, _ => unreachable!("Not a type param"), } } #[test] fn expand_many() { let di: DeriveInput = parse_quote! { struct Baz< #[lorem(foo)] T, #[lorem(bar = "x")] U: Eq + ?Sized >(T, U); }; let params = di.generics.params; { let ty = extract_type(¶ms[0]); let lorem = Lorem::from_type_param(ty).unwrap(); assert_eq!(lorem.ident, "T"); assert_eq!(lorem.foo, true); assert_eq!(lorem.bar, None); } { let ty = extract_type(¶ms[1]); let lorem = Lorem::from_type_param(ty).unwrap(); assert_eq!(lorem.ident, "U"); assert_eq!(lorem.foo, false); assert_eq!(lorem.bar, Some("x".to_string())); assert_eq!(lorem.bounds.len(), 2); } } darling-0.10.2/tests/from_type_param_default.rs010064400027200000024000000026511344444330400200310ustar0000000000000000#[macro_use] extern crate darling; #[macro_use] extern crate syn; #[macro_use] extern crate quote; use darling::FromTypeParam; use syn::{DeriveInput, GenericParam, TypeParam}; #[darling(attributes(lorem), default)] #[derive(Default, FromTypeParam)] struct Lorem { foo: bool, bar: Option, default: Option, } fn extract_type(param: &GenericParam) -> &TypeParam { match *param { GenericParam::Type(ref ty) => ty, _ => unreachable!("Not a type param"), } } #[test] fn expand_many() { let di: DeriveInput = parse_quote! { struct Baz< #[lorem(foo)] T, #[lorem(bar = "x")] U: Eq + ?Sized, #[lorem(foo = false)] V = (), >(T, U, V); }; let params = di.generics.params; { let ty = extract_type(¶ms[0]); let lorem = Lorem::from_type_param(ty).unwrap(); assert_eq!(lorem.foo, true); assert_eq!(lorem.bar, None); } { let ty = extract_type(¶ms[1]); let lorem = Lorem::from_type_param(ty).unwrap(); assert_eq!(lorem.foo, false); assert_eq!(lorem.bar, Some("x".to_string())); assert!(lorem.default.is_none()); } { let ty = extract_type(¶ms[2]); let lorem = Lorem::from_type_param(ty).unwrap(); assert_eq!(lorem.foo, false); assert_eq!(lorem.bar, None); assert!(lorem.default.is_some()); } } darling-0.10.2/tests/from_variant.rs010064400027200000024000000010621327506073100156240ustar0000000000000000#[macro_use] extern crate darling; extern crate syn; #[derive(FromVariant)] #[darling(from_ident, attributes(hello))] #[allow(dead_code)] pub struct Lorem { ident: syn::Ident, into: Option, skip: Option, fields: darling::ast::Fields, } impl From for Lorem { fn from(ident: syn::Ident) -> Self { Lorem { ident, into: Default::default(), skip: Default::default(), fields: darling::ast::Style::Unit.into(), } } } #[test] fn expansion() {} darling-0.10.2/tests/generics.rs010064400027200000024000000007271342734324700147500ustar0000000000000000#[macro_use] extern crate darling; #[macro_use] extern crate syn; #[macro_use] extern crate quote; use darling::FromDeriveInput; #[derive(Debug, Clone, FromMeta)] struct Wrapper(pub T); #[derive(Debug, FromDeriveInput)] #[darling(attributes(hello))] struct Foo { lorem: Wrapper, } #[test] fn expansion() { let di = parse_quote! { #[hello(lorem = "Hello")] pub struct Foo; }; Foo::::from_derive_input(&di).unwrap(); } darling-0.10.2/tests/happy_path.rs010064400027200000024000000030161342734324700153000ustar0000000000000000#[macro_use] extern crate darling; #[macro_use] extern crate syn; #[macro_use] extern crate quote; use darling::FromDeriveInput; #[derive(Default, FromMeta, PartialEq, Debug)] #[darling(default)] struct Lorem { ipsum: bool, dolor: Option, } #[derive(FromDeriveInput, PartialEq, Debug)] #[darling(attributes(darling_demo))] struct Core { ident: syn::Ident, vis: syn::Visibility, generics: syn::Generics, lorem: Lorem, } #[derive(FromDeriveInput, PartialEq, Debug)] #[darling(attributes(darling_demo))] struct TraitCore { ident: syn::Ident, generics: syn::Generics, lorem: Lorem, } #[test] fn simple() { let di = parse_quote! { #[derive(Foo)] #[darling_demo(lorem(ipsum))] pub struct Bar; }; assert_eq!( Core::from_derive_input(&di).unwrap(), Core { ident: parse_quote!(Bar), vis: parse_quote!(pub), generics: Default::default(), lorem: Lorem { ipsum: true, dolor: None, }, } ); } #[test] fn trait_type() { let di = parse_quote! { #[derive(Foo)] #[darling_demo(lorem(dolor = "hello"))] pub struct Bar; }; assert_eq!( TraitCore::from_derive_input(&di).unwrap(), TraitCore { ident: parse_quote!(Bar), generics: Default::default(), lorem: Lorem { ipsum: false, dolor: Some("hello".to_owned()), } } ); } darling-0.10.2/tests/multiple.rs010064400027200000024000000012351342734324700147770ustar0000000000000000#[macro_use] extern crate darling; #[macro_use] extern crate syn; #[macro_use] extern crate quote; use darling::FromDeriveInput; #[derive(FromDeriveInput)] #[darling(attributes(hello))] #[allow(dead_code)] struct Lorem { ident: syn::Ident, ipsum: Ipsum, } #[derive(FromMeta)] struct Ipsum { #[darling(multiple)] dolor: Vec, } #[test] fn expand_many() { let di = parse_quote! { #[hello(ipsum(dolor = "Hello", dolor = "World"))] pub struct Baz; }; let lorem: Lorem = Lorem::from_derive_input(&di).unwrap(); assert_eq!( lorem.ipsum.dolor, vec!["Hello".to_string(), "World".to_string()] ); } darling-0.10.2/tests/newtype.rs010064400027200000024000000011731342734324700146400ustar0000000000000000//! A newtype struct should be able to derive `FromMeta` if its member implements it. #[macro_use] extern crate darling; #[macro_use] extern crate syn; #[macro_use] extern crate quote; use darling::FromDeriveInput; #[derive(Debug, FromMeta, PartialEq, Eq)] struct Lorem(bool); #[derive(Debug, FromDeriveInput)] #[darling(attributes(newtype))] struct DemoContainer { lorem: Lorem, } #[test] fn generated() { let di = parse_quote! { #[derive(Baz)] #[newtype(lorem = false)] pub struct Foo; }; let c = DemoContainer::from_derive_input(&di).unwrap(); assert_eq!(c.lorem, Lorem(false)); } darling-0.10.2/tests/skip.rs010064400027200000024000000016731342734324700141200ustar0000000000000000//! Test that skipped fields are not read into structs when they appear in input. #[macro_use] extern crate darling; #[macro_use] extern crate syn; #[macro_use] extern crate quote; use darling::FromDeriveInput; #[derive(Debug, PartialEq, Eq, FromDeriveInput)] #[darling(attributes(skip_test))] pub struct Lorem { ipsum: String, #[darling(skip)] dolor: u8, } /// Verify variant-level and field-level skip work correctly for enums. #[derive(Debug, FromMeta)] pub enum Sit { Amet(bool), #[darling(skip)] Foo { hello: bool, }, Bar { hello: bool, #[darling(skip)] world: u8, }, } #[test] fn verify_skipped_field_not_required() { let di = parse_quote! { #[skip_test(ipsum = "Hello")] struct Baz; }; assert_eq!( Lorem::from_derive_input(&di).unwrap(), Lorem { ipsum: "Hello".to_string(), dolor: 0, } ); } darling-0.10.2/tests/split_declaration.rs010064400027200000024000000033601344444330400166370ustar0000000000000000//! When input is split across multiple attributes on one element, //! darling should collapse that into one struct. #[macro_use] extern crate darling; #[macro_use] extern crate syn; #[macro_use] extern crate quote; use std::string::ToString; use darling::{Error, FromDeriveInput}; #[derive(Debug, FromDeriveInput, PartialEq, Eq)] #[darling(attributes(split))] struct Lorem { foo: String, bar: bool, } #[test] fn split_attributes_accrue_to_instance() { let di = parse_quote! { #[split(foo = "Hello")] #[split(bar)] pub struct Foo; }; let parsed = Lorem::from_derive_input(&di).unwrap(); assert_eq!( parsed, Lorem { foo: "Hello".to_string(), bar: true, } ); } #[test] fn duplicates_across_split_attrs_error() { let di = parse_quote! { #[split(foo = "Hello")] #[split(foo = "World", bar)] pub struct Foo; }; let pr = Lorem::from_derive_input(&di).unwrap_err(); assert!(pr.has_span()); assert_eq!( pr.to_string(), Error::duplicate_field("foo").to_string() ); } #[test] fn multiple_errors_accrue_to_instance() { let di = parse_quote! { #[split(foo = "Hello")] #[split(foo = "World")] pub struct Foo; }; let pr = Lorem::from_derive_input(&di); let err: Error = pr.unwrap_err(); assert_eq!(2, err.len()); let mut errs = err.into_iter().peekable(); assert_eq!( errs.peek().unwrap().to_string(), Error::duplicate_field("foo").to_string() ); assert!(errs.next().unwrap().has_span()); assert_eq!( errs.next().unwrap().to_string(), Error::missing_field("bar").to_string() ); assert!(errs.next().is_none()); } darling-0.10.2/tests/suggestions.rs010064400027200000024000000012311342740556200155110ustar0000000000000000#![cfg(feature = "suggestions")] #[macro_use] extern crate darling; #[macro_use] extern crate syn; #[macro_use] extern crate quote; use darling::FromDeriveInput; #[derive(Debug, FromDeriveInput)] #[darling(attributes(suggest))] struct Lorem { ipsum: String, dolor: Dolor, } #[derive(Debug, FromMeta)] struct Dolor { sit: bool, } #[test] fn suggest_dolor() { let input: syn::DeriveInput = parse_quote! { #[suggest(ipsum = "Hello", dolorr(sit))] pub struct Foo; }; let result = Lorem::from_derive_input(&input).unwrap_err(); assert_eq!(2, result.len()); assert!(format!("{}", result).contains("Did you mean")); } darling-0.10.2/tests/supports.rs010064400027200000024000000037571344445143000150470ustar0000000000000000#[macro_use] extern crate darling; #[macro_use] extern crate syn; #[macro_use] extern crate quote; use darling::ast; use darling::FromDeriveInput; #[derive(Debug, FromDeriveInput)] #[darling(attributes(from_variants), supports(enum_any))] pub struct Container { data: ast::Data, } #[derive(Default, Debug, FromVariant)] #[darling(default, attributes(from_variants), supports(newtype, unit))] pub struct Variant { into: Option, skip: Option, } #[derive(Debug, FromDeriveInput)] #[darling(attributes(from_struct), supports(struct_named))] pub struct StructContainer { data: ast::Data<(), syn::Field>, } mod source { use syn::DeriveInput; pub fn newtype_enum() -> DeriveInput { parse_quote!{ enum Hello { World(bool), String(String), } } } pub fn named_field_enum() -> DeriveInput { parse_quote! { enum Hello { Foo(u16), World { name: String }, } } } pub fn named_struct() -> DeriveInput { parse_quote! { struct Hello { world: bool, } } } pub fn tuple_struct() -> DeriveInput { parse_quote! { struct Hello(String, bool); } } } #[test] fn enum_newtype_or_unit() { // Should pass Container::from_derive_input(&source::newtype_enum()).unwrap(); // Should error Container::from_derive_input(&source::named_field_enum()).unwrap_err(); Container::from_derive_input(&source::named_struct()).unwrap_err(); } #[test] fn struct_named() { // Should pass StructContainer::from_derive_input(&source::named_struct()).unwrap(); // Should fail StructContainer::from_derive_input(&source::tuple_struct()).unwrap_err(); StructContainer::from_derive_input(&source::named_field_enum()).unwrap_err(); StructContainer::from_derive_input(&source::newtype_enum()).unwrap_err(); } darling-0.10.2/.cargo_vcs_info.json0000644000000001120000000000000125650ustar00{ "git": { "sha1": "c0e0cfdd75964ec355b1df0e71421c32281fa8a8" } } darling-0.10.2/Cargo.lock0000644000000077650000000000000105650ustar00# This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] name = "darling" version = "0.10.2" dependencies = [ "darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "darling_macro 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "darling_core" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "darling_macro" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "fnv" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ident_case" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "quote" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "strsim" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-xid" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" "checksum darling_macro 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9826188e666f2ed92071d2dadef6edc430b11b158b5b2b3f4babbcc891eaaa" "checksum proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "19f287c234c9b2d0308d692dee5c449c1a171167a6f8150f7cf2a49d8fd96967" "checksum quote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ab938ebe6f1c82426b5fb82eaf10c3e3028c53deaa3fbe38f5904b37cf4d767" "checksum strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "032c03039aae92b350aad2e3779c352e104d919cb192ba2fabbd7b831ce4f0f6" "checksum syn 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "863ecbce06044c8380458360b4146d7372edadfedd77f120ba8c193da427b708" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"