Bug 1513173 - Part 2: Revendor dependencies. r=emilio

This commit is contained in:
Bastien Orivel 2019-04-02 22:42:43 +02:00 коммит произвёл Emilio Cobos Álvarez
Родитель 5b0fd46634
Коммит 894fb2c90e
92 изменённых файлов: 3498 добавлений и 2391 удалений

Просмотреть файл

@ -1 +1 @@
{"files":{"CHANGELOG.md":"06091817afa317ff86efb9aee3fa8d165358150a92c6369e4ab2958765c14af8","Cargo.toml":"3ec79fcbc682939731504a261f9f7a10afecdbbf298af8a10a9748abcb79172a","LICENSE":"8ea93490d74a5a1b1af3ff71d786271b3f1e5f0bea79ac16e02ec533cef040d6","README.md":"f70d772dd28cd14fc817c71d343b07ec8bfbe02dfe8d3e999a0185c6ef8731ec","examples/automatic_bounds.rs":"2716da31a5beed954da77866779ef77600686688a8890fefa7e23db628358104","examples/consume_fields.rs":"abcdd6a919a95a5c295e8d362db0367ab171fe3c8a80b23d83701765cd902d2d","examples/fallible_read.rs":"e06d5c045d3a47c0e00d3c77ed3aa1a1d5173d2c3f462dc1967379db3094af4c","examples/supports_struct.rs":"f2d84a4377e555ed7535e563c9593bd6a398a63b42f7da72381eea2fccec229f","publish.sh":"42795a155247c69402f8c4c917c9874a06dfde5a7606c8b59fc4e9ccd34233dd","src/lib.rs":"07da20edb52c4aba30f2b680b28ca96cf995859566b0db3b1d2e0ee967249a18","src/macros_public.rs":"3ed7eb99f309d9cd600d3a09ff4dcf5cc5d787fb49e8e5ead6bb00e31e5e6793","tests/accrue_errors.rs":"f873acf2a13dba88f508c3eb118d14e36515bf94b7ee914ddec2ae1eb55e381f","tests/computed_bound.rs":"2313da96a250b5948ca06bf86cb7158b55a59eba75334aa8ba27a46b28ede6b5","tests/custom_bound.rs":"4dd3e8fd76734d8f262e857773f53a820229ad6e10fe6fbbbe1f636c7da9eab0","tests/defaults.rs":"b544be90d18be26305a757e8468bf8735356889b59c167294d118e32ee7f82ea","tests/enums_newtype.rs":"723c761eab356f577e804a5e07f5efa244f70fb7525d20fceb1bc3852c8d742e","tests/enums_struct.rs":"e0097d7f947cf9e4612c9450c55ea5075c7f6fcbbf8cac7176449d92eebc9343","tests/enums_unit.rs":"8c075d5897b60b58cb71d6306e7fdd80851f5a147ae3010ba70ea100007364a3","tests/error.rs":"f989a43fad47d61d75da2bc78af6c51bac549f39f14f87a804eea226308ece32","tests/from_generics.rs":"79230ad21e8482cf6e6ceb0c74303bc0cdf77fbb951f46a6ba1006ecf1248fd5","tests/from_type_param.rs":"4369737a9d4c21cfa8595a9159cd5d98d02af3445d8b4085654ad4ce8e8bba3f","tests/from_type_param_default.rs":"a5ee72f22540004e755445c37dd4c425ef12beef496896d608695bae964afe7f","tests/from_variant.rs":"2e804326302a62b979eae963e88f0a2cdb6a21ee9667407c361d178f8c0aadba","tests/generics.rs":"3c0f43b39a8f319b8318e409d3836c7235892ae4f50f5986ea80f69b80a4080b","tests/happy_path.rs":"13cf6cd5f87920d90762fd08e45d9f0bb378563e1c92cf5ffb3ba78decdc4969","tests/multiple.rs":"b76172c396a89414b1669eec2bf854c79a7215fd3b6977123b81591ac6761670","tests/newtype.rs":"c45842fd764174a6a8177851e15445d344ab93bf2124b5f77213780d1306adea","tests/skip.rs":"fd936a5eff92c0a49b0a900e6fcda6b7a10a83dd4096ae2000201ccb3f66a738","tests/split_declaration.rs":"b191ed446bf7b8fdf1d41059354adb4b155523507f37b0d36aed3347617a2492","tests/supports.rs":"acb53d4d810dcd3e46763db13234e4fb42e425cfde2516d9bf5d7b690be72dcc"},"package":"f593353cad5af2df6d54810de2b61aa8acba5b5fbc70b0d75e7cc5bdd80aca73"}
{"files":{"CHANGELOG.md":"111bee96e6baf82f8898ada5f5395888253832ed641fc6013ad803ac6afaeaf0","Cargo.toml":"66f4111240094e9fed78c1989fc56b30fb94a58f2465eb0eacbaf050cc027b81","LICENSE":"8ea93490d74a5a1b1af3ff71d786271b3f1e5f0bea79ac16e02ec533cef040d6","README.md":"05357355cb87aea0b5bda29ce9f6ef03331717cf351c6cf7554855f5d825756e","examples/automatic_bounds.rs":"dcac3391ed568475cea17ec64c324283f9771dce61adb0a0dd7b8a9ee0bf954d","examples/consume_fields.rs":"ebf4bd8baf4e54ccaa926f910957183d6a5b1decaa87ab5ebcca6c8d38b6c6b3","examples/fallible_read.rs":"aa9d1e0aaba8f3eb4580e94e133839f7eb77fca61beed254f3d5e0f6d6981f00","examples/supports_struct.rs":"d69124e09d3d6b8e04a3af07a6af96c5df7cbd3d6953a51657b39088cc2c2de7","src/lib.rs":"07da20edb52c4aba30f2b680b28ca96cf995859566b0db3b1d2e0ee967249a18","src/macros_public.rs":"3ed7eb99f309d9cd600d3a09ff4dcf5cc5d787fb49e8e5ead6bb00e31e5e6793","tests/accrue_errors.rs":"f5ac2d8cb0a12284a845d25b9472c4605aa5e8c1cd66a6dd6ad64f1c749b2caf","tests/computed_bound.rs":"2313da96a250b5948ca06bf86cb7158b55a59eba75334aa8ba27a46b28ede6b5","tests/custom_bound.rs":"4dd3e8fd76734d8f262e857773f53a820229ad6e10fe6fbbbe1f636c7da9eab0","tests/defaults.rs":"b544be90d18be26305a757e8468bf8735356889b59c167294d118e32ee7f82ea","tests/enums_newtype.rs":"a09af70072e566bee1f6cad91675f3553c47333e51a0e389ebb47ae82de776a8","tests/enums_struct.rs":"e0097d7f947cf9e4612c9450c55ea5075c7f6fcbbf8cac7176449d92eebc9343","tests/enums_unit.rs":"8c075d5897b60b58cb71d6306e7fdd80851f5a147ae3010ba70ea100007364a3","tests/error.rs":"465f7634fa23f0076c93a9c5fc16ccde16119b874d64c8dabaf275b6b7ae61f2","tests/from_generics.rs":"79230ad21e8482cf6e6ceb0c74303bc0cdf77fbb951f46a6ba1006ecf1248fd5","tests/from_type_param.rs":"7c97745cdcea18a2d6f51e4da7426055a078287bf9f2c93d487057195efa2b30","tests/from_type_param_default.rs":"80787ef6527e7f76c2aac93b1f35a006a9c5e0df8deed61698eaac1127278021","tests/from_variant.rs":"2e804326302a62b979eae963e88f0a2cdb6a21ee9667407c361d178f8c0aadba","tests/generics.rs":"e08aea8a8de8f03e3c243bde650e250defbe340cef3e4c06935b2b3e46d2a376","tests/happy_path.rs":"c32daa68e2becdc2d6204985a19b437cfb49d7f1680e890578f0760dc9749b77","tests/multiple.rs":"0391be49bab07771d7e37d35fe17f6d9bf1aa6dc57e2c0e5c0912ab8e043128f","tests/newtype.rs":"3f029724467abc7a33aaf7b6a1feb7b6898eba578576afff338e73deb9fd2b3b","tests/skip.rs":"604861aa4d1dfdc4e5f38f8261be19b7240c650eb493b64ce0178f54c24a8d2d","tests/split_declaration.rs":"f509390f88549164af9218f1e5b07564b169a4481a20b738432ffb03c517b599","tests/suggestions.rs":"0afb756949be876aaae76974f119be811c783fb134a54978ff0453c537ff3174","tests/supports.rs":"3b096c3d893bf8e76f70219bc276cbfe04529091e9e8652af140f0f1b3a91270"},"package":"9158d690bc62a3a57c3e45b85e4d50de2008b39345592c64efd79345c7e24be0"}

26
third_party/rust/darling/CHANGELOG.md поставляемый
Просмотреть файл

@ -1,5 +1,31 @@
# Changelog
## 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

15
third_party/rust/darling/Cargo.toml поставляемый
Просмотреть файл

@ -12,18 +12,19 @@
[package]
name = "darling"
version = "0.8.1"
version = "0.8.6"
authors = ["Ted Driggs <ted.driggs@outlook.com>"]
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.8.1"
documentation = "https://docs.rs/darling/0.8.6"
readme = "README.md"
license = "MIT"
repository = "https://github.com/TedDriggs/darling"
[dependencies.darling_core]
version = "=0.8.1"
version = "=0.8.6"
[dependencies.darling_macro]
version = "=0.8.1"
version = "=0.8.6"
[dev-dependencies.proc-macro2]
version = "0.4"
@ -31,6 +32,10 @@ version = "0.4"
version = "0.6"
[dev-dependencies.syn]
version = "0.15"
version = "0.15.26"
[features]
diagnostics = ["darling_core/diagnostics"]
suggestions = ["darling_core/suggestions"]
[badges.travis-ci]
repository = "TedDriggs/darling"

49
third_party/rust/darling/README.md поставляемый
Просмотреть файл

@ -10,8 +10,9 @@ Darling
`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.
1. `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.
1. `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.
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.
# Example
@ -46,6 +47,49 @@ The above code will then be able to parse this input:
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<T>` 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<u16>,
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.
@ -55,3 +99,4 @@ Darling's features are built to work well for real-world projects.
* **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.

Просмотреть файл

@ -68,7 +68,8 @@ fn main() {
Div(String)
}
"#,
).unwrap();
)
.unwrap();
let parsed: SpeakingOptions<Phoneme, Volume> =
FromDeriveInput::from_derive_input(&derive_input).unwrap();

Просмотреть файл

@ -64,7 +64,8 @@ impl ToTokens for MyInputReceiver {
} = *self;
let (imp, ty, wher) = generics.split_for_impl();
let fields = data.as_ref()
let fields = data
.as_ref()
.take_struct()
.expect("Should never be enum")
.fields;

Просмотреть файл

@ -4,7 +4,6 @@
//! 1. Using `darling::Result` as a carrier to preserve the error for later display
//! 1. Using `Result<T, syn::Meta>` 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;
@ -58,8 +57,8 @@ impl MyInputReceiver {
};
Self {
name: name,
frequency: frequency,
name,
frequency,
amplitude: Ok(amplitude),
}
}

Просмотреть файл

@ -37,8 +37,7 @@ pub struct Foo {
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");
let wrong_shape = Lorem::from_derive_input(&wrong_shape_parsed).expect_err("Shape was wrong");
println!(
r#"

3
third_party/rust/darling/publish.sh поставляемый
Просмотреть файл

@ -1,3 +0,0 @@
cargo publish --manifest-path core/Cargo.toml;
cargo publish --manifest-path macro/Cargo.toml;
cargo publish;

Просмотреть файл

@ -3,7 +3,10 @@
#[macro_use]
extern crate darling;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
use darling::ast;
use darling::FromDeriveInput;
@ -30,17 +33,14 @@ struct LoremField {
#[test]
fn bad_type_and_missing_fields() {
let input = syn::parse_str(
r#"
#[accrue(ipsum = true, dolor(amet = "Hi"))]
pub struct NonConforming {
foo: ()
}
"#,
).unwrap();
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();
//assert_eq!(3, s_result.len());
let err = s_result.flatten();
println!("{}", err);
assert_eq!(3, err.len());
@ -48,17 +48,15 @@ fn bad_type_and_missing_fields() {
#[test]
fn body_only_issues() {
let input = syn::parse_str(
r#"
#[accrue(ipsum = "Hello", dolor(sit))]
pub struct NonConforming {
foo: (),
bar: bool,
}
"#,
).unwrap();
let input = parse_quote! {
#[accrue(ipsum = "Hello", dolor(sit))]
pub struct NonConforming {
foo: (),
bar: bool,
}
};
let s_err: ::darling::Error = Lorem::from_derive_input(&input).unwrap_err();
let s_err = Lorem::from_derive_input(&input).unwrap_err();
println!("{:?}", s_err);
assert_eq!(2, s_err.len());
}
@ -78,17 +76,15 @@ struct Month {
#[test]
fn error_in_enum_fields() {
let input = syn::parse_str(
r#"
#[accrue(schedule(tuesday(morning = "yes")))]
pub struct NonConforming {
foo: (),
bar: bool,
}
"#,
).unwrap();
let input = parse_quote! {
#[accrue(schedule(tuesday(morning = "yes")))]
pub struct NonConforming {
foo: (),
bar: bool,
}
};
let s_err: ::darling::Error = Month::from_derive_input(&input).unwrap_err();
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
@ -97,17 +93,15 @@ fn error_in_enum_fields() {
#[test]
fn error_in_newtype_variant() {
let input = syn::parse_str(
r#"
#[accrue(schedule(wednesday(sit = "yes")))]
pub struct NonConforming {
foo: (),
bar: bool,
}
"#,
).unwrap();
let input = parse_quote! {
#[accrue(schedule(wednesday(sit = "yes")))]
pub struct NonConforming {
foo: (),
bar: bool,
}
};
let s_err: ::darling::Error = Month::from_derive_input(&input).unwrap_err();
let s_err = Month::from_derive_input(&input).unwrap_err();
assert_eq!(1, s_err.len());
println!("{}", s_err);
println!("{}", s_err.flatten());

Просмотреть файл

@ -1,10 +1,12 @@
#[macro_use]
extern crate darling;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
use darling::FromDeriveInput;
extern crate syn;
#[derive(Debug, Default, PartialEq, Eq, FromMeta)]
#[darling(default)]
pub struct Amet {
@ -34,12 +36,10 @@ impl PartialEq<Lorem> for Holder {
#[test]
fn bool_word() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[hello(lorem(ipsum))]
pub struct Bar;
"#,
).unwrap();
};
let pr = Holder::from_derive_input(&di).unwrap();
assert_eq!(pr, Lorem::Ipsum(true));
@ -47,12 +47,10 @@ fn bool_word() {
#[test]
fn bool_literal() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[hello(lorem(ipsum = false))]
pub struct Bar;
"#,
).unwrap();
};
let pr = Holder::from_derive_input(&di).unwrap();
assert_eq!(pr, Lorem::Ipsum(false));
@ -60,12 +58,10 @@ fn bool_literal() {
#[test]
fn string_literal() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[hello(lorem(dolor = "Hello"))]
pub struct Bar;
"#,
).unwrap();
};
let pr = Holder::from_derive_input(&di).unwrap();
assert_eq!(pr, Lorem::Dolor("Hello".to_string()));
@ -73,12 +69,10 @@ fn string_literal() {
#[test]
fn struct_nested() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[hello(lorem(sit(world = "Hello", hello = false)))]
pub struct Bar;
"#,
).unwrap();
};
let pr = Holder::from_derive_input(&di).unwrap();
assert_eq!(
@ -93,12 +87,10 @@ fn struct_nested() {
#[test]
#[should_panic]
fn format_mismatch() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[hello(lorem(dolor(world = "Hello", hello = false)))]
pub struct Bar;
"#,
).unwrap();
};
Holder::from_derive_input(&di).unwrap();
}

15
third_party/rust/darling/tests/error.rs поставляемый
Просмотреть файл

@ -1,7 +1,10 @@
//! 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;
@ -33,24 +36,20 @@ impl From<syn::Ident> for Lorem {
#[test]
fn parsing_fail() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[hello(ipsum(amet = "yes", world = false))]
pub struct Foo;
"#,
).unwrap();
};
println!("{}", Lorem::from_derive_input(&di).unwrap_err());
}
#[test]
fn missing_field() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[hello(ipsum(amet = true))]
pub struct Foo;
"#,
).unwrap();
};
println!("{}", Lorem::from_derive_input(&di).unwrap_err());
}

Просмотреть файл

@ -1,6 +1,9 @@
#[macro_use]
extern crate darling;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
use darling::FromTypeParam;
use syn::{DeriveInput, GenericParam, Ident, TypeParam};
@ -34,14 +37,13 @@ fn extract_type(param: &GenericParam) -> &TypeParam {
#[test]
fn expand_many() {
let di: DeriveInput = syn::parse_str(
r#"
let di: DeriveInput = parse_quote! {
struct Baz<
#[lorem(foo)] T,
#[lorem(bar = "x")] U: Eq + ?Sized
>(T, U);
"#,
).unwrap();
};
let params = di.generics.params;
{

Просмотреть файл

@ -1,6 +1,9 @@
#[macro_use]
extern crate darling;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
use darling::FromTypeParam;
use syn::{DeriveInput, GenericParam, TypeParam};
@ -22,15 +25,13 @@ fn extract_type(param: &GenericParam) -> &TypeParam {
#[test]
fn expand_many() {
let di: DeriveInput = syn::parse_str(
r#"
let di: DeriveInput = parse_quote! {
struct Baz<
#[lorem(foo)] T,
#[lorem(bar = "x")] U: Eq + ?Sized,
#[lorem(foo = false)] V = (),
>(T, U, V);
"#,
).unwrap();
};
let params = di.generics.params;
{

11
third_party/rust/darling/tests/generics.rs поставляемый
Просмотреть файл

@ -1,6 +1,9 @@
#[macro_use]
extern crate darling;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
use darling::FromDeriveInput;
@ -15,12 +18,10 @@ struct Foo<T> {
#[test]
fn expansion() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[hello(lorem = "Hello")]
pub struct Foo;
"#,
).unwrap();
};
let _parsed = Foo::<String>::from_derive_input(&di).unwrap();
Foo::<String>::from_derive_input(&di).unwrap();
}

13
third_party/rust/darling/tests/happy_path.rs поставляемый
Просмотреть файл

@ -1,6 +1,5 @@
#[macro_use]
extern crate darling;
#[macro_use]
extern crate syn;
#[macro_use]
@ -34,13 +33,11 @@ struct TraitCore {
#[test]
fn simple() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[derive(Foo)]
#[darling_demo(lorem(ipsum))]
pub struct Bar;
"#,
).unwrap();
};
assert_eq!(
Core::from_derive_input(&di).unwrap(),
@ -58,13 +55,11 @@ fn simple() {
#[test]
fn trait_type() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[derive(Foo)]
#[darling_demo(lorem(dolor = "hello"))]
pub struct Bar;
"#,
).unwrap();
};
assert_eq!(
TraitCore::from_derive_input(&di).unwrap(),

9
third_party/rust/darling/tests/multiple.rs поставляемый
Просмотреть файл

@ -1,6 +1,9 @@
#[macro_use]
extern crate darling;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
use darling::FromDeriveInput;
@ -20,12 +23,10 @@ struct Ipsum {
#[test]
fn expand_many() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[hello(ipsum(dolor = "Hello", dolor = "World"))]
pub struct Baz;
"#,
).unwrap();
};
let lorem: Lorem = Lorem::from_derive_input(&di).unwrap();
assert_eq!(

10
third_party/rust/darling/tests/newtype.rs поставляемый
Просмотреть файл

@ -2,8 +2,10 @@
#[macro_use]
extern crate darling;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
use darling::FromDeriveInput;
@ -18,13 +20,11 @@ struct DemoContainer {
#[test]
fn generated() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[derive(Baz)]
#[newtype(lorem = false)]
pub struct Foo;
"#,
).unwrap();
};
let c = DemoContainer::from_derive_input(&di).unwrap();

9
third_party/rust/darling/tests/skip.rs поставляемый
Просмотреть файл

@ -2,7 +2,10 @@
#[macro_use]
extern crate darling;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
use darling::FromDeriveInput;
@ -34,12 +37,10 @@ pub enum Sit {
#[test]
fn verify_skipped_field_not_required() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[skip_test(ipsum = "Hello")]
struct Baz;
"#,
).unwrap();
};
assert_eq!(
Lorem::from_derive_input(&di).unwrap(),

Просмотреть файл

@ -3,7 +3,10 @@
#[macro_use]
extern crate darling;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
use std::string::ToString;
@ -18,13 +21,11 @@ struct Lorem {
#[test]
fn split_attributes_accrue_to_instance() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[split(foo = "Hello")]
#[split(bar)]
pub struct Foo;
"#,
).unwrap();
};
let parsed = Lorem::from_derive_input(&di).unwrap();
assert_eq!(
@ -38,39 +39,37 @@ fn split_attributes_accrue_to_instance() {
#[test]
fn duplicates_across_split_attrs_error() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[split(foo = "Hello")]
#[split(foo = "World", bar)]
pub struct Foo;
"#,
).unwrap();
};
let pr = Lorem::from_derive_input(&di);
let pr = Lorem::from_derive_input(&di).unwrap_err();
assert!(pr.has_span());
assert_eq!(
pr.unwrap_err().to_string(),
pr.to_string(),
Error::duplicate_field("foo").to_string()
);
}
#[test]
fn multiple_errors_accrue_to_instance() {
let di = syn::parse_str(
r#"
let di = parse_quote! {
#[split(foo = "Hello")]
#[split(foo = "World")]
pub struct Foo;
"#,
).unwrap();
};
let pr = Lorem::from_derive_input(&di);
let err: Error = pr.unwrap_err();
assert_eq!(2, err.len());
let mut errs = err.into_iter();
let mut errs = err.into_iter().peekable();
assert_eq!(
errs.next().unwrap().to_string(),
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()

34
third_party/rust/darling/tests/suggestions.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,34 @@
#![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"));
}

43
third_party/rust/darling/tests/supports.rs поставляемый
Просмотреть файл

@ -1,6 +1,9 @@
#[macro_use]
extern crate darling;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
use darling::ast;
use darling::FromDeriveInput;
@ -28,41 +31,35 @@ mod source {
use syn::{self, DeriveInput};
pub fn newtype_enum() -> DeriveInput {
syn::parse_str(
r#"
enum Hello {
World(bool),
String(String),
parse_quote!{
enum Hello {
World(bool),
String(String),
}
}
"#,
).unwrap()
}
pub fn named_field_enum() -> DeriveInput {
syn::parse_str(
r#"
enum Hello {
Foo(u16),
World {
name: String
},
parse_quote! {
enum Hello {
Foo(u16),
World {
name: String
},
}
}
"#,
).unwrap()
}
pub fn named_struct() -> DeriveInput {
syn::parse_str(
r#"
struct Hello {
world: bool,
parse_quote! {
struct Hello {
world: bool,
}
}
"#,
).unwrap()
}
pub fn tuple_struct() -> DeriveInput {
syn::parse_str("struct Hello(String, bool);").unwrap()
parse_quote! { struct Hello(String, bool); }
}
}

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

12
third_party/rust/darling_core/Cargo.toml поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
[package]
name = "darling_core"
version = "0.8.1"
version = "0.8.6"
authors = ["Ted Driggs <ted.driggs@outlook.com>"]
description = "Helper crate for proc-macro library for reading attributes into structs when\nimplementing custom derives. Use https://crates.io/crates/darling in your code.\n"
license = "MIT"
@ -24,14 +24,20 @@ version = "1.0.6"
version = "1.0.0"
[dependencies.proc-macro2]
version = "0.4.2"
version = "0.4.26"
[dependencies.quote]
version = "0.6"
[dependencies.strsim]
version = "0.8.0"
optional = true
[dependencies.syn]
version = "0.15"
version = "0.15.26"
features = ["extra-traits"]
[features]
default = ["syn/full"]
diagnostics = []
suggestions = ["strsim"]

21
third_party/rust/darling_core/LICENSE поставляемый Normal file
Просмотреть файл

@ -0,0 +1,21 @@
MIT 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.

54
third_party/rust/darling_core/src/ast/data.rs поставляемый
Просмотреть файл

@ -1,4 +1,4 @@
use std::slice;
use std::{slice, vec};
use syn;
@ -16,7 +16,7 @@ pub enum Data<V, F> {
Struct(Fields<F>),
}
#[deprecated(since = "0.3", note = "this has been renamed to Data")]
#[deprecated(since = "0.3.0", note = "this has been renamed to Data")]
pub type Body<V, F> = Data<V, F>;
impl<V, F> Data<V, F> {
@ -32,7 +32,7 @@ impl<V, F> Data<V, F> {
/// Creates a new `Data<&'a V, &'a F>` instance from `Data<V, F>`.
pub fn as_ref<'a>(&'a self) -> Data<&'a V, &'a F> {
match *self {
Data::Enum(ref variants) => Data::Enum(variants.into_iter().collect()),
Data::Enum(ref variants) => Data::Enum(variants.iter().collect()),
Data::Struct(ref data) => Data::Struct(data.as_ref()),
}
}
@ -107,11 +107,7 @@ impl<V: FromVariant, F: FromField> Data<V, F> {
syn::Data::Enum(ref data) => {
let mut items = Vec::with_capacity(data.variants.len());
let mut errors = Vec::new();
for v_result in data.variants
.clone()
.into_iter()
.map(|v| FromVariant::from_variant(&v))
{
for v_result in data.variants.iter().map(FromVariant::from_variant) {
match v_result {
Ok(val) => items.push(val),
Err(err) => errors.push(err),
@ -156,13 +152,14 @@ impl<V: UsesLifetimes, F: UsesLifetimes> UsesLifetimes for Data<V, F> {
}
}
/// Equivalent to `syn::Fields`, but replaces the AST element with a generic.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Fields<T> {
pub style: Style,
pub fields: Vec<T>,
}
#[deprecated(since = "0.3", note = "this has been renamed to Fields")]
#[deprecated(since = "0.3.0", note = "this has been renamed to Fields")]
pub type VariantData<T> = Fields<T>;
impl<T> Fields<T> {
@ -181,7 +178,7 @@ impl<T> Fields<T> {
/// Returns true if this variant's data makes it a newtype.
pub fn is_newtype(&self) -> bool {
self.style == Style::Tuple && self.fields.len() == 1
self.style == Style::Tuple && self.len() == 1
}
pub fn is_unit(&self) -> bool {
@ -216,6 +213,16 @@ impl<T> Fields<T> {
pub fn iter(&self) -> slice::Iter<T> {
self.fields.iter()
}
/// Returns the number of fields in the structure.
pub fn len(&self) -> usize {
self.fields.len()
}
/// Returns `true` if the `Fields` contains no fields.
pub fn is_empty(&self) -> bool {
self.fields.is_empty()
}
}
impl<F: FromField> Fields<F> {
@ -226,8 +233,7 @@ impl<F: FromField> Fields<F> {
let mut errors = Vec::new();
for field in &fields.named {
let f_result = FromField::from_field(field);
match f_result {
match FromField::from_field(field) {
Ok(val) => items.push(val),
Err(err) => errors.push(if let Some(ref ident) = field.ident {
err.at(ident)
@ -244,8 +250,7 @@ impl<F: FromField> Fields<F> {
let mut errors = Vec::new();
for field in &fields.unnamed {
let f_result = FromField::from_field(field);
match f_result {
match FromField::from_field(field) {
Ok(val) => items.push(val),
Err(err) => errors.push(if let Some(ref ident) = field.ident {
err.at(ident)
@ -271,6 +276,15 @@ impl<F: FromField> Fields<F> {
}
}
impl<T> IntoIterator for Fields<T> {
type Item = T;
type IntoIter = vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.fields.into_iter()
}
}
impl<T> From<Style> for Fields<T> {
fn from(style: Style) -> Self {
Fields {
@ -314,16 +328,16 @@ pub enum Style {
}
impl Style {
pub fn is_unit(&self) -> bool {
*self == Style::Unit
pub fn is_unit(self) -> bool {
self == Style::Unit
}
pub fn is_tuple(&self) -> bool {
*self == Style::Tuple
pub fn is_tuple(self) -> bool {
self == Style::Tuple
}
pub fn is_struct(&self) -> bool {
*self == Style::Struct
pub fn is_struct(self) -> bool {
self == Style::Struct
}
/// Creates a new `Fields` of the specified style with the passed-in fields.

Просмотреть файл

@ -37,7 +37,8 @@ pub trait ExtractAttribute {
let declarations = self.declarations();
let will_parse_any = !self.attr_names().is_empty();
let will_fwd_any = self.forwarded_attrs()
let will_fwd_any = self
.forwarded_attrs()
.map(|fa| !fa.is_empty())
.unwrap_or_default();
@ -56,7 +57,7 @@ pub trait ExtractAttribute {
let core_loop = self.core_loop();
quote!(
#(#attr_names)|* => {
if let Some(::syn::Meta::List(ref __data)) = __attr.interpret_meta() {
if let ::darling::export::Some(::syn::Meta::List(ref __data)) = __attr.interpret_meta() {
let __items = &__data.nested;
#core_loop
@ -106,4 +107,4 @@ fn forwards_to_local(behavior: &ForwardAttrs) -> TokenStream {
)
}
}
}
}

Просмотреть файл

@ -2,38 +2,27 @@ use proc_macro2::TokenStream;
use quote::{TokenStreamExt, ToTokens};
/// Declares the local variable into which errors will be accumulated.
#[derive(Default)]
pub struct ErrorDeclaration {
__hidden: (),
}
impl ErrorDeclaration {
pub fn new() -> Self {
ErrorDeclaration { __hidden: () }
}
}
impl ToTokens for ErrorDeclaration {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(quote! {
let mut __errors = Vec::new();
let mut __errors = ::darling::export::Vec::new();
})
}
}
/// Returns early if attribute or body parsing has caused any errors.
#[derive(Default)]
pub struct ErrorCheck<'a> {
location: Option<&'a str>,
__hidden: (),
}
impl<'a> ErrorCheck<'a> {
pub fn new() -> Self {
ErrorCheck {
location: None,
__hidden: (),
}
}
pub fn with_location(location: &'a str) -> Self {
ErrorCheck {
location: Some(location),

Просмотреть файл

@ -1,5 +1,7 @@
use std::borrow::Cow;
use proc_macro2::TokenStream;
use quote::{TokenStreamExt, ToTokens};
use quote::{ToTokens, TokenStreamExt};
use syn::{Ident, Path, Type};
use codegen::DefaultExpression;
@ -11,7 +13,7 @@ use usage::{self, IdentRefSet, IdentSet, UsesTypeParams};
pub struct Field<'a> {
/// The name presented to the user of the library. This will appear
/// in error messages and will be looked when parsing names.
pub name_in_attr: String,
pub name_in_attr: Cow<'a, String>,
/// The name presented to the author of the library. This will appear
/// in the setters or temporary variables which contain the values.
@ -20,13 +22,17 @@ pub struct Field<'a> {
/// The type of the field in the input.
pub ty: &'a Type,
pub default_expression: Option<DefaultExpression<'a>>,
pub with_path: Path,
pub with_path: Cow<'a, Path>,
pub map: Option<&'a Path>,
pub skip: bool,
pub multiple: bool,
}
impl<'a> Field<'a> {
pub fn as_name(&'a self) -> &'a str {
&self.name_in_attr
}
pub fn as_declaration(&'a self) -> Declaration<'a> {
Declaration(self, !self.skip)
}
@ -104,7 +110,12 @@ impl<'a> ToTokens for MatchArm<'a> {
quote!(#name_str)
};
let mut extractor = quote!(#with_path(__inner).map_err(|e| e.at(#location)));
// Add the span immediately on extraction failure, so that it's as specific as possible.
// The behavior of `with_span` makes this safe to do; if the child applied an
// even-more-specific span, our attempt here will not overwrite that and will only cost
// us one `if` check.
let mut extractor =
quote!(#with_path(__inner).map_err(|e| e.with_span(&__inner).at(#location)));
if let Some(ref map) = field.map {
extractor = quote!(#extractor.map(#map))
}
@ -116,10 +127,10 @@ impl<'a> ToTokens for MatchArm<'a> {
// it for error reporting.
let __len = #ident.len();
match #extractor {
Ok(__val) => {
::darling::export::Ok(__val) => {
#ident.push(__val)
}
Err(__err) => {
::darling::export::Err(__err) => {
__errors.push(__err)
}
}
@ -130,16 +141,16 @@ impl<'a> ToTokens for MatchArm<'a> {
#name_str => {
if !#ident.0 {
match #extractor {
Ok(__val) => {
::darling::export::Ok(__val) => {
#ident = (true, ::darling::export::Some(__val));
}
Err(__err) => {
::darling::export::Err(__err) => {
#ident = (true, None);
__errors.push(__err);
}
}
} else {
__errors.push(::darling::Error::duplicate_field(#name_str));
__errors.push(::darling::Error::duplicate_field(#name_str).with_span(&__inner));
}
}
)
@ -165,15 +176,13 @@ impl<'a> ToTokens for Initializer<'a> {
} else {
quote!(#ident: #ident)
}
} else if let Some(ref expr) = field.default_expression {
quote!(#ident: match #ident.1 {
::darling::export::Some(__val) => __val,
::darling::export::None => #expr,
})
} else {
if let Some(ref expr) = field.default_expression {
quote!(#ident: match #ident.1 {
::darling::export::Some(__val) => __val,
::darling::export::None => #expr,
})
} else {
quote!(#ident: #ident.1.expect("Uninitialized fields without defaults were already checked"))
}
quote!(#ident: #ident.1.expect("Uninitialized fields without defaults were already checked"))
});
}
}

Просмотреть файл

@ -19,7 +19,7 @@ impl<'a> ToTokens for FromMetaImpl<'a> {
let ty_ident = base.ident;
quote!(
fn from_word() -> ::darling::Result<Self> {
Ok(#ty_ident)
::darling::export::Ok(#ty_ident)
}
)
}
@ -29,12 +29,13 @@ impl<'a> ToTokens for FromMetaImpl<'a> {
ref fields,
style: Style::Tuple,
..
}) if fields.len() == 1 =>
{
}) if fields.len() == 1 => {
let ty_ident = base.ident;
quote!(
fn from_meta(__item: &::syn::Meta) -> ::darling::Result<Self> {
Ok(#ty_ident(::darling::FromMeta::from_meta(__item)?))
::darling::FromMeta::from_meta(__item)
.map_err(|e| e.with_span(&__item))
.map(#ty_ident)
}
)
}
@ -79,6 +80,17 @@ impl<'a> ToTokens for FromMetaImpl<'a> {
let unit_arms = variants.iter().map(Variant::as_unit_match_arm);
let struct_arms = variants.iter().map(Variant::as_data_match_arm);
let unknown_variant_err = if !variants.is_empty() {
let names = variants.iter().map(Variant::as_name);
quote! {
unknown_field_with_alts(__other, &[#(#names),*])
}
} else {
quote! {
unknown_field(__other)
}
};
quote!(
fn from_list(__outer: &[::syn::NestedMeta]) -> ::darling::Result<Self> {
// An enum must have exactly one value inside the parentheses if it's not a unit
@ -89,7 +101,7 @@ impl<'a> ToTokens for FromMetaImpl<'a> {
if let ::syn::NestedMeta::Meta(ref __nested) = __outer[0] {
match __nested.name().to_string().as_ref() {
#(#struct_arms)*
__other => ::darling::export::Err(::darling::Error::unknown_value(__other))
__other => ::darling::export::Err(::darling::Error::#unknown_variant_err.with_span(__nested))
}
} else {
::darling::export::Err(::darling::Error::unsupported_format("literal"))

Просмотреть файл

@ -49,7 +49,7 @@ fn compute_impl_bounds(bound: Path, mut generics: Generics, applies_to: &IdentSe
});
for mut param in generics.params.iter_mut() {
if let &mut GenericParam::Type(ref mut typ) = param {
if let GenericParam::Type(ref mut typ) = *param {
if applies_to.contains(&typ.ident) {
typ.bounds.push(added_bound.clone());
}

Просмотреть файл

@ -15,6 +15,7 @@ pub struct TraitImpl<'a> {
pub default: Option<DefaultExpression<'a>>,
pub map: Option<&'a Path>,
pub bound: Option<&'a [WherePredicate]>,
pub allow_unknown_fields: bool,
}
impl<'a> TraitImpl<'a> {
@ -44,17 +45,18 @@ impl<'a> TraitImpl<'a> {
let declared = self.declared_type_params();
match self.data {
Data::Struct(ref v) => self.type_params_in_fields(v, &field_filter, &declared),
Data::Enum(ref v) => v.iter().filter(variant_filter).fold(
Default::default(),
|mut state, variant| {
state.extend(self.type_params_in_fields(
&variant.data,
&field_filter,
&declared,
));
state
},
),
Data::Enum(ref v) => {
v.iter()
.filter(variant_filter)
.fold(Default::default(), |mut state, variant| {
state.extend(self.type_params_in_fields(
&variant.data,
&field_filter,
&declared,
));
state
})
}
}
}
@ -78,12 +80,12 @@ impl<'a> TraitImpl<'a> {
impl<'a> TraitImpl<'a> {
/// Gets the `let` declaration for errors accumulated during parsing.
pub fn declare_errors(&self) -> ErrorDeclaration {
ErrorDeclaration::new()
ErrorDeclaration::default()
}
/// Gets the check which performs an early return if errors occurred during parsing.
pub fn check_errors(&self) -> ErrorCheck {
ErrorCheck::new()
ErrorCheck::default()
}
/// Generate local variable declarations for all fields.
@ -129,21 +131,18 @@ impl<'a> TraitImpl<'a> {
}
pub(in codegen) fn initializers(&self) -> TokenStream {
let foo = match self.data {
Data::Enum(_) => panic!("Core loop on enums isn't supported"),
Data::Struct(ref data) => FieldsGen(data),
};
foo.initializers()
self.make_field_ctx().initializers()
}
/// Generate the loop which walks meta items looking for property matches.
pub(in codegen) fn core_loop(&self) -> TokenStream {
let foo = match self.data {
Data::Enum(_) => panic!("Core loop on enums isn't supported"),
Data::Struct(ref data) => FieldsGen(data),
};
self.make_field_ctx().core_loop()
}
foo.core_loop()
fn make_field_ctx(&'a self) -> FieldsGen<'a> {
match self.data {
Data::Enum(_) => panic!("Core loop on enums isn't supported"),
Data::Struct(ref data) => FieldsGen::new(data, self.allow_unknown_fields),
}
}
}

Просмотреть файл

@ -1,5 +1,7 @@
use std::borrow::Cow;
use proc_macro2::TokenStream;
use quote::{TokenStreamExt, ToTokens};
use quote::{ToTokens, TokenStreamExt};
use syn::Ident;
use ast::Fields;
@ -7,11 +9,11 @@ use codegen::error::{ErrorCheck, ErrorDeclaration};
use codegen::{Field, FieldsGen};
use usage::{self, IdentRefSet, IdentSet, UsesTypeParams};
/// An enum variant.
/// A variant of the enum which is deriving `FromMeta`.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Variant<'a> {
/// The name which will appear in code passed to the `FromMeta` input.
pub name_in_attr: String,
pub name_in_attr: Cow<'a, String>,
/// The name of the variant which will be returned for a given `name_in_attr`.
pub variant_ident: &'a Ident,
@ -23,9 +25,15 @@ pub struct Variant<'a> {
/// Whether or not the variant should be skipped in the generated code.
pub skip: bool,
pub allow_unknown_fields: bool,
}
impl<'a> Variant<'a> {
pub fn as_name(&'a self) -> &'a str {
&self.name_in_attr
}
pub fn as_unit_match_arm(&'a self) -> UnitMatchArm<'a> {
UnitMatchArm(self)
}
@ -45,6 +53,9 @@ impl<'a> UsesTypeParams for Variant<'a> {
}
}
/// Code generator for an enum variant in a unit match position.
/// This is placed in generated `from_string` calls for the parent enum.
/// Value-carrying variants wrapped in this type will emit code to produce an "unsupported format" error.
pub struct UnitMatchArm<'a>(&'a Variant<'a>);
impl<'a> ToTokens for UnitMatchArm<'a> {
@ -72,6 +83,9 @@ impl<'a> ToTokens for UnitMatchArm<'a> {
}
}
/// Code generator for an enum variant in a data-carrying match position.
/// This is placed in generated `from_list` calls for the parent enum.
/// Unit variants wrapped in this type will emit code to produce an "unsupported format" error.
pub struct DataMatchArm<'a>(&'a Variant<'a>);
impl<'a> ToTokens for DataMatchArm<'a> {
@ -94,10 +108,10 @@ impl<'a> ToTokens for DataMatchArm<'a> {
return;
}
let vdg = FieldsGen(&val.data);
let vdg = FieldsGen::new(&val.data, val.allow_unknown_fields);
if val.data.is_struct() {
let declare_errors = ErrorDeclaration::new();
let declare_errors = ErrorDeclaration::default();
let check_errors = ErrorCheck::with_location(&name_in_attr);
let require_fields = vdg.require_fields();
let decls = vdg.declarations();

Просмотреть файл

@ -2,19 +2,29 @@ use proc_macro2::TokenStream;
use ast::Fields;
use ast::Style;
use codegen::field;
use codegen::Field;
pub struct FieldsGen<'a>(pub &'a Fields<Field<'a>>);
pub struct FieldsGen<'a> {
fields: &'a Fields<Field<'a>>,
allow_unknown_fields: bool,
}
impl<'a> FieldsGen<'a> {
pub fn new(fields: &'a Fields<Field<'a>>, allow_unknown_fields: bool) -> Self {
Self {
fields,
allow_unknown_fields,
}
}
/// Create declarations for all the fields in the struct.
pub(in codegen) fn declarations(&self) -> TokenStream {
match *self.0 {
match *self.fields {
Fields {
style: Style::Struct,
ref fields,
} => {
let vdr = fields.into_iter().map(Field::as_declaration);
let vdr = fields.iter().map(Field::as_declaration);
quote!(#(#vdr)*)
}
_ => panic!("FieldsGen doesn't support tuples yet"),
@ -23,7 +33,26 @@ impl<'a> FieldsGen<'a> {
/// Generate the loop which walks meta items looking for property matches.
pub(in codegen) fn core_loop(&self) -> TokenStream {
let arms: Vec<field::MatchArm> = self.0.as_ref().map(Field::as_match).fields;
let arms = self.fields.as_ref().map(Field::as_match);
// If we're allowing unknown fields, then handling one is a no-op.
// Otherwise, we're going to push a new spanned error pointing at the field.
let handle_unknown = if self.allow_unknown_fields {
quote!()
} else {
// We can't call `unknown_field_with_alts` with an empty slice, or else it fails to
// infer the type of the slice item.
let err_fn = if arms.is_empty() {
quote!(unknown_field(__other))
} else {
let names = self.fields.as_ref().map(Field::as_name);
quote!(unknown_field_with_alts(__other, &[#(#names),*]))
};
quote! {
__errors.push(::darling::Error::#err_fn.with_span(__inner));
}
};
quote!(
for __item in __items {
@ -31,7 +60,7 @@ impl<'a> FieldsGen<'a> {
let __name = __inner.name().to_string();
match __name.as_str() {
#(#arms)*
__other => { __errors.push(::darling::Error::unknown_field(__other)); }
__other => { #handle_unknown }
}
}
}
@ -39,12 +68,12 @@ impl<'a> FieldsGen<'a> {
}
pub fn require_fields(&self) -> TokenStream {
match *self.0 {
match *self.fields {
Fields {
style: Style::Struct,
ref fields,
} => {
let checks = fields.into_iter().map(Field::as_presence_check);
let checks = fields.iter().map(Field::as_presence_check);
quote!(#(#checks)*)
}
_ => panic!("FieldsGen doesn't support tuples for requirement checks"),
@ -52,7 +81,7 @@ impl<'a> FieldsGen<'a> {
}
pub(in codegen) fn initializers(&self) -> TokenStream {
let inits: Vec<_> = self.0.as_ref().map(Field::as_initializer).fields;
let inits = self.fields.as_ref().map(Field::as_initializer);
quote!(#(#inits),*)
}

54
third_party/rust/darling_core/src/derive.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,54 @@
//! Functions to derive `darling`'s traits from well-formed input, without directly depending
//! on `proc_macro`.
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::DeriveInput;
use options;
/// Run an expression which returns a `darling::Result`, then either return the tokenized
/// representation of the `Ok` value, or the tokens of the compiler errors in the `Err` case.
macro_rules! emit_impl_or_error {
($e:expr) => {
match $e {
Ok(val) => val.into_token_stream(),
Err(err) => err.write_errors(),
}
};
}
/// Create tokens for a `darling::FromMeta` impl from a `DeriveInput`. If
/// the input cannot produce a valid impl, the returned tokens will contain
/// compile errors instead.
pub fn from_meta(input: &DeriveInput) -> TokenStream {
emit_impl_or_error!(options::FromMetaOptions::new(input))
}
/// Create tokens for a `darling::FromDeriveInput` impl from a `DeriveInput`. If
/// the input cannot produce a valid impl, the returned tokens will contain
/// compile errors instead.
pub fn from_derive_input(input: &DeriveInput) -> TokenStream {
emit_impl_or_error!(options::FdiOptions::new(&input))
}
/// Create tokens for a `darling::FromField` impl from a `DeriveInput`. If
/// the input cannot produce a valid impl, the returned tokens will contain
/// compile errors instead.
pub fn from_field(input: &DeriveInput) -> TokenStream {
emit_impl_or_error!(options::FromFieldOptions::new(input))
}
/// Create tokens for a `darling::FromTypeParam` impl from a `DeriveInput`. If
/// the input cannot produce a valid impl, the returned tokens will contain
/// compile errors instead.
pub fn from_type_param(input: &DeriveInput) -> TokenStream {
emit_impl_or_error!(options::FromTypeParamOptions::new(input))
}
/// Create tokens for a `darling::FromVariant` impl from a `DeriveInput`. If
/// the input cannot produce a valid impl, the returned tokens will contain
/// compile errors instead.
pub fn from_variant(input: &DeriveInput) -> TokenStream {
emit_impl_or_error!(options::FromVariantOptions::new(input))
}

373
third_party/rust/darling_core/src/error.rs поставляемый
Просмотреть файл

@ -1,373 +0,0 @@
//! Types for working with darling errors and results.
use std::error::Error as StdError;
use std::fmt;
use std::iter::{self, Iterator};
use std::string::ToString;
use std::vec;
/// An alias of `Result` specific to attribute parsing.
pub type Result<T> = ::std::result::Result<T, Error>;
/// An error encountered during attribute parsing.
///
/// Given that most errors darling encounters represent code bugs in dependent crates,
/// the internal structure of the error is deliberately opaque.
#[derive(Debug)]
// Don't want to publicly commit to Error supporting equality yet, but
// not having it makes testing very difficult.
#[cfg_attr(test, derive(Clone, PartialEq, Eq))]
pub struct Error {
kind: ErrorKind,
locations: Vec<String>,
}
impl Error {
fn new(kind: ErrorKind) -> Self {
Error {
kind: kind,
locations: Vec::new(),
}
}
/// Creates a new error with a custom message.
pub fn custom<T: fmt::Display>(msg: T) -> Self {
Error::new(ErrorKind::Custom(msg.to_string()))
}
/// Creates a new error for a field that appears twice in the input.
pub fn duplicate_field(name: &str) -> Self {
Error::new(ErrorKind::DuplicateField(name.into()))
}
/// Creates a new error for a non-optional field that does not appear in the input.
pub fn missing_field(name: &str) -> Self {
Error::new(ErrorKind::MissingField(name.into()))
}
/// Creates a new error for a field name that appears in the input but does not correspond
/// to a known field.
pub fn unknown_field(name: &str) -> Self {
Error::new(ErrorKind::UnknownField(name.into()))
}
/// Creates a new error for a struct or variant that does not adhere to the supported shape.
pub fn unsupported_shape(shape: &str) -> Self {
Error::new(ErrorKind::UnsupportedShape(shape.into()))
}
pub fn unsupported_format(format: &str) -> Self {
Error::new(ErrorKind::UnexpectedFormat(format.into()))
}
/// Creates a new error for a field which has an unexpected literal type.
pub fn unexpected_type(ty: &str) -> Self {
Error::new(ErrorKind::UnexpectedType(ty.into()))
}
/// Creates a new error for a value which doesn't match a set of expected literals.
pub fn unknown_value(value: &str) -> Self {
Error::new(ErrorKind::UnknownValue(value.into()))
}
/// Creates a new error for a list which did not get enough items to proceed.
pub fn too_few_items(min: usize) -> Self {
Error::new(ErrorKind::TooFewItems(min))
}
/// Creates a new error when a list got more items than it supports. The `max` argument
/// is the largest number of items the receiver could accept.
pub fn too_many_items(max: usize) -> Self {
Error::new(ErrorKind::TooManyItems(max))
}
/// Bundle a set of multiple errors into a single `Error` instance.
///
/// # Panics
/// This function will panic if `errors.is_empty() == true`.
pub fn multiple(mut errors: Vec<Error>) -> Self {
if errors.len() > 1 {
Error::new(ErrorKind::Multiple(errors))
} else if errors.len() == 1 {
errors
.pop()
.expect("Error array of length 1 has a first item")
} else {
panic!("Can't deal with 0 errors")
}
}
/// Recursively converts a tree of errors to a flattened list.
pub fn flatten(self) -> Self {
Error::multiple(self.to_vec())
}
fn to_vec(self) -> Vec<Self> {
if let ErrorKind::Multiple(errors) = self.kind {
let mut flat = Vec::new();
for error in errors {
flat.extend(error.prepend_at(self.locations.clone()).to_vec());
}
flat
} else {
vec![self]
}
}
/// Adds a location to the error, such as a field or variant.
/// Locations must be added in reverse order of specificity.
pub fn at<T: fmt::Display>(mut self, location: T) -> Self {
self.locations.insert(0, location.to_string());
self
}
/// Gets the number of individual errors in this error.
///
/// This function should never return `0`, as it shouldn't be possible to construct
/// a multi-error from an empty `Vec`.
pub fn len(&self) -> usize {
self.kind.len()
}
/// Adds a location chain to the head of the error's existing locations.
fn prepend_at(mut self, mut locations: Vec<String>) -> Self {
if !locations.is_empty() {
locations.extend(self.locations);
self.locations = locations;
}
self
}
/// Gets the location slice.
#[cfg(test)]
pub(crate) fn location(&self) -> Vec<&str> {
self.locations.iter().map(|i| i.as_str()).collect()
}
}
impl StdError for Error {
fn description(&self) -> &str {
&self.kind.description()
}
fn cause(&self) -> Option<&StdError> {
None
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.kind)?;
if !self.locations.is_empty() {
write!(f, " at {}", self.locations.join("/"))?;
}
Ok(())
}
}
impl IntoIterator for Error {
type Item = Error;
type IntoIter = IntoIter;
fn into_iter(self) -> IntoIter {
if let ErrorKind::Multiple(errors) = self.kind {
IntoIter {
inner: IntoIterEnum::Multiple(errors.into_iter()),
}
} else {
IntoIter {
inner: IntoIterEnum::Single(iter::once(self)),
}
}
}
}
enum IntoIterEnum {
Single(iter::Once<Error>),
Multiple(vec::IntoIter<Error>),
}
impl Iterator for IntoIterEnum {
type Item = Error;
fn next(&mut self) -> Option<Self::Item> {
match *self {
IntoIterEnum::Single(ref mut content) => content.next(),
IntoIterEnum::Multiple(ref mut content) => content.next(),
}
}
}
/// An iterator that moves out of an `Error`.
pub struct IntoIter {
inner: IntoIterEnum,
}
impl Iterator for IntoIter {
type Item = Error;
fn next(&mut self) -> Option<Error> {
self.inner.next()
}
}
type DeriveInputShape = String;
type FieldName = String;
type MetaFormat = String;
#[derive(Debug)]
// Don't want to publicly commit to ErrorKind supporting equality yet, but
// not having it makes testing very difficult.
#[cfg_attr(test, derive(Clone, PartialEq, Eq))]
enum ErrorKind {
/// An arbitrary error message.
Custom(String),
DuplicateField(FieldName),
MissingField(FieldName),
UnsupportedShape(DeriveInputShape),
UnknownField(FieldName),
UnexpectedFormat(MetaFormat),
UnexpectedType(String),
UnknownValue(String),
TooFewItems(usize),
TooManyItems(usize),
/// A set of errors.
Multiple(Vec<Error>),
// TODO make this variant take `!` so it can't exist
#[doc(hidden)]
__NonExhaustive,
}
impl ErrorKind {
pub fn description(&self) -> &str {
use self::ErrorKind::*;
match *self {
Custom(ref s) => s,
DuplicateField(_) => "Duplicate field",
MissingField(_) => "Missing field",
UnknownField(_) => "Unexpected field",
UnsupportedShape(_) => "Unsupported shape",
UnexpectedFormat(_) => "Unexpected meta-item format",
UnexpectedType(_) => "Unexpected literal type",
UnknownValue(_) => "Unknown literal value",
TooFewItems(_) => "Too few items",
TooManyItems(_) => "Too many items",
Multiple(_) => "Multiple errors",
__NonExhaustive => unreachable!(),
}
}
/// Deeply counts the number of errors this item represents.
pub fn len(&self) -> usize {
if let ErrorKind::Multiple(ref items) = *self {
items.iter().map(Error::len).sum()
} else {
1
}
}
}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::ErrorKind::*;
match *self {
Custom(ref s) => s.fmt(f),
DuplicateField(ref field) => write!(f, "Duplicate field `{}`", field),
MissingField(ref field) => write!(f, "Missing field `{}`", field),
UnknownField(ref field) => write!(f, "Unexpected field `{}`", field),
UnsupportedShape(ref shape) => write!(f, "Unsupported shape `{}`", shape),
UnexpectedFormat(ref format) => write!(f, "Unexpected meta-item format `{}`", format),
UnexpectedType(ref ty) => write!(f, "Unexpected literal type `{}`", ty),
UnknownValue(ref val) => write!(f, "Unknown literal value `{}`", val),
TooFewItems(ref min) => write!(f, "Too few items: Expected at least {}", min),
TooManyItems(ref max) => write!(f, "Too many items: Expected no more than {}", max),
Multiple(ref items) if items.len() == 1 => items[0].fmt(f),
Multiple(ref items) => {
write!(f, "Multiple errors: (")?;
let mut first = true;
for item in items {
if !first {
write!(f, ", ")?;
} else {
first = false;
}
item.fmt(f)?;
}
write!(f, ")")
}
__NonExhaustive => unreachable!(),
}
}
}
#[cfg(test)]
mod tests {
use super::Error;
#[test]
fn flatten_noop() {
let err = Error::duplicate_field("hello").at("world");
assert_eq!(err.clone().flatten(), err);
}
#[test]
fn flatten_simple() {
let err = Error::multiple(vec![
Error::unknown_field("hello").at("world"),
Error::missing_field("hell_no").at("world"),
]).at("foo")
.flatten();
assert!(err.location().is_empty());
let mut err_iter = err.into_iter();
let first = err_iter.next();
assert!(first.is_some());
assert_eq!(first.unwrap().location(), vec!["foo", "world"]);
let second = err_iter.next();
assert!(second.is_some());
assert_eq!(second.unwrap().location(), vec!["foo", "world"]);
assert!(err_iter.next().is_none());
}
#[test]
fn len_single() {
let err = Error::duplicate_field("hello");
assert_eq!(1, err.len());
}
#[test]
fn len_multiple() {
let err = Error::multiple(vec![
Error::duplicate_field("hello"),
Error::missing_field("hell_no"),
]);
assert_eq!(2, err.len());
}
#[test]
fn len_nested() {
let err = Error::multiple(vec![
Error::duplicate_field("hello"),
Error::multiple(vec![
Error::duplicate_field("hi"),
Error::missing_field("bye"),
Error::multiple(vec![Error::duplicate_field("whatsup")]),
]),
]);
assert_eq!(4, err.len());
}
}

201
third_party/rust/darling_core/src/error/kind.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,201 @@
use std::fmt;
use error::Error;
type DeriveInputShape = String;
type FieldName = String;
type MetaFormat = String;
#[derive(Debug)]
// Don't want to publicly commit to ErrorKind supporting equality yet, but
// not having it makes testing very difficult.
#[cfg_attr(test, derive(Clone, PartialEq, Eq))]
pub(in error) enum ErrorKind {
/// An arbitrary error message.
Custom(String),
DuplicateField(FieldName),
MissingField(FieldName),
UnsupportedShape(DeriveInputShape),
UnknownField(ErrorUnknownField),
UnexpectedFormat(MetaFormat),
UnexpectedType(String),
UnknownValue(String),
TooFewItems(usize),
TooManyItems(usize),
/// A set of errors.
Multiple(Vec<Error>),
// TODO make this variant take `!` so it can't exist
#[doc(hidden)]
__NonExhaustive,
}
impl ErrorKind {
pub fn description(&self) -> &str {
use self::ErrorKind::*;
match *self {
Custom(ref s) => s,
DuplicateField(_) => "Duplicate field",
MissingField(_) => "Missing field",
UnknownField(_) => "Unexpected field",
UnsupportedShape(_) => "Unsupported shape",
UnexpectedFormat(_) => "Unexpected meta-item format",
UnexpectedType(_) => "Unexpected literal type",
UnknownValue(_) => "Unknown literal value",
TooFewItems(_) => "Too few items",
TooManyItems(_) => "Too many items",
Multiple(_) => "Multiple errors",
__NonExhaustive => unreachable!(),
}
}
/// Deeply counts the number of errors this item represents.
pub fn len(&self) -> usize {
if let ErrorKind::Multiple(ref items) = *self {
items.iter().map(Error::len).sum()
} else {
1
}
}
}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::ErrorKind::*;
match *self {
Custom(ref s) => s.fmt(f),
DuplicateField(ref field) => write!(f, "Duplicate field `{}`", field),
MissingField(ref field) => write!(f, "Missing field `{}`", field),
UnknownField(ref field) => field.fmt(f),
UnsupportedShape(ref shape) => write!(f, "Unsupported shape `{}`", shape),
UnexpectedFormat(ref format) => write!(f, "Unexpected meta-item format `{}`", format),
UnexpectedType(ref ty) => write!(f, "Unexpected literal type `{}`", ty),
UnknownValue(ref val) => write!(f, "Unknown literal value `{}`", val),
TooFewItems(ref min) => write!(f, "Too few items: Expected at least {}", min),
TooManyItems(ref max) => write!(f, "Too many items: Expected no more than {}", max),
Multiple(ref items) if items.len() == 1 => items[0].fmt(f),
Multiple(ref items) => {
write!(f, "Multiple errors: (")?;
let mut first = true;
for item in items {
if !first {
write!(f, ", ")?;
} else {
first = false;
}
item.fmt(f)?;
}
write!(f, ")")
}
__NonExhaustive => unreachable!(),
}
}
}
impl From<ErrorUnknownField> for ErrorKind {
fn from(err: ErrorUnknownField) -> Self {
ErrorKind::UnknownField(err)
}
}
/// An error for an unknown field, with a possible "did-you-mean" suggestion to get
/// the user back on the right track.
#[derive(Debug)]
// Don't want to publicly commit to ErrorKind supporting equality yet, but
// not having it makes testing very difficult.
#[cfg_attr(test, derive(Clone, PartialEq, Eq))]
pub(in error) struct ErrorUnknownField {
name: String,
did_you_mean: Option<String>,
}
impl ErrorUnknownField {
pub fn new<I: Into<String>>(name: I, did_you_mean: Option<String>) -> Self {
ErrorUnknownField {
name: name.into(),
did_you_mean,
}
}
pub fn with_alts<'a, T, I>(field: &str, alternates: I) -> Self
where
T: AsRef<str> + 'a,
I: IntoIterator<Item = &'a T>,
{
ErrorUnknownField::new(field, did_you_mean(field, alternates))
}
#[cfg(feature = "diagnostics")]
pub fn to_diagnostic(self, span: Option<::proc_macro2::Span>) -> ::proc_macro::Diagnostic {
let base = span
.unwrap_or_else(::proc_macro2::Span::call_site)
.unwrap()
.error(self.top_line());
match self.did_you_mean {
Some(alt_name) => base.help(format!("did you mean `{}`?", alt_name)),
None => base,
}
}
#[cfg(feature = "diagnostics")]
fn top_line(&self) -> String {
format!("Unknown field: `{}`", self.name)
}
}
impl From<String> for ErrorUnknownField {
fn from(name: String) -> Self {
ErrorUnknownField::new(name, None)
}
}
impl<'a> From<&'a str> for ErrorUnknownField {
fn from(name: &'a str) -> Self {
ErrorUnknownField::new(name, None)
}
}
impl fmt::Display for ErrorUnknownField {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Unknown field: `{}`", self.name)?;
if let Some(ref did_you_mean) = self.did_you_mean {
write!(f, ". Did you mean `{}`?", did_you_mean)?;
}
Ok(())
}
}
#[cfg(feature = "suggestions")]
fn did_you_mean<'a, T, I>(field: &str, alternates: I) -> Option<String>
where
T: AsRef<str> + 'a,
I: IntoIterator<Item = &'a T>,
{
let mut candidate: Option<(f64, &str)> = None;
for pv in alternates {
let confidence = ::strsim::jaro_winkler(field, pv.as_ref());
if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence))
{
candidate = Some((confidence, pv.as_ref()));
}
}
match candidate {
None => None,
Some((_, candidate)) => Some(candidate.into()),
}
}
#[cfg(not(feature = "suggestions"))]
fn did_you_mean<'a, T, I>(_field: &str, _alternates: I) -> Option<String>
where
T: AsRef<str> + 'a,
I: IntoIterator<Item = &'a T>,
{
None
}

505
third_party/rust/darling_core/src/error/mod.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,505 @@
//! The `darling::Error` type and its internals.
//!
//! Error handling is one of the core values of `darling`; creating great errors is hard and
//! never the reason that a proc-macro author started writing their crate. As a result, the
//! `Error` type in `darling` tries to make adding span information, suggestions, and other
//! help content easy when manually implementing `darling` traits, and automatic when deriving
//! them.
use proc_macro2::{Span, TokenStream};
use std::error::Error as StdError;
use std::fmt;
use std::iter::{self, Iterator};
use std::string::ToString;
use std::vec;
use syn::spanned::Spanned;
use syn::{Lit, LitStr};
mod kind;
use self::kind::{ErrorKind, ErrorUnknownField};
/// An alias of `Result` specific to attribute parsing.
pub type Result<T> = ::std::result::Result<T, Error>;
/// An error encountered during attribute parsing.
///
/// Given that most errors darling encounters represent code bugs in dependent crates,
/// the internal structure of the error is deliberately opaque.
#[derive(Debug)]
#[cfg_attr(test, derive(Clone))]
pub struct Error {
kind: ErrorKind,
locations: Vec<String>,
/// The span to highlight in the emitted diagnostic.
span: Option<Span>,
}
/// Error creation functions
impl Error {
pub(in error) fn new(kind: ErrorKind) -> Self {
Error {
kind,
locations: Vec::new(),
span: None,
}
}
/// Creates a new error with a custom message.
pub fn custom<T: fmt::Display>(msg: T) -> Self {
Error::new(ErrorKind::Custom(msg.to_string()))
}
/// Creates a new error for a field that appears twice in the input.
pub fn duplicate_field(name: &str) -> Self {
Error::new(ErrorKind::DuplicateField(name.into()))
}
/// Creates a new error for a non-optional field that does not appear in the input.
pub fn missing_field(name: &str) -> Self {
Error::new(ErrorKind::MissingField(name.into()))
}
/// Creates a new error for a field name that appears in the input but does not correspond
/// to a known field.
pub fn unknown_field(name: &str) -> Self {
Error::new(ErrorKind::UnknownField(name.into()))
}
/// Creates a new error for a field name that appears in the input but does not correspond to
/// a known attribute. The second argument is the list of known attributes; if a similar name
/// is found that will be shown in the emitted error message.
pub fn unknown_field_with_alts<'a, T, I>(field: &str, alternates: I) -> Self
where
T: AsRef<str> + 'a,
I: IntoIterator<Item = &'a T>,
{
Error::new(ErrorUnknownField::with_alts(field, alternates).into())
}
/// Creates a new error for a struct or variant that does not adhere to the supported shape.
pub fn unsupported_shape(shape: &str) -> Self {
Error::new(ErrorKind::UnsupportedShape(shape.into()))
}
pub fn unsupported_format(format: &str) -> Self {
Error::new(ErrorKind::UnexpectedFormat(format.into()))
}
/// Creates a new error for a field which has an unexpected literal type.
pub fn unexpected_type(ty: &str) -> Self {
Error::new(ErrorKind::UnexpectedType(ty.into()))
}
/// Creates a new error for a field which has an unexpected literal type. This will automatically
/// extract the literal type name from the passed-in `Lit` and set the span to encompass only the
/// literal value.
///
/// # Usage
/// This is most frequently used in overrides of the `FromMeta::from_value` method.
///
/// ```rust
/// # // pretend darling_core is darling so the doc example looks correct.
/// # extern crate darling_core as darling;
/// # extern crate syn;
///
/// use darling::{FromMeta, Error, Result};
/// use syn::{Lit, LitStr};
///
/// pub struct Foo(String);
///
/// impl FromMeta for Foo {
/// fn from_value(value: &Lit) -> Result<Self> {
/// if let Lit::Str(ref lit_str) = value {
/// Ok(Foo(lit_str.value()))
/// } else {
/// Err(Error::unexpected_lit_type(value))
/// }
/// }
/// }
///
/// # fn main() {}
/// ```
pub fn unexpected_lit_type(lit: &Lit) -> Self {
Error::unexpected_type(match *lit {
Lit::Str(_) => "string",
Lit::ByteStr(_) => "byte string",
Lit::Byte(_) => "byte",
Lit::Char(_) => "char",
Lit::Int(_) => "int",
Lit::Float(_) => "float",
Lit::Bool(_) => "bool",
Lit::Verbatim(_) => "verbatim",
})
.with_span(lit)
}
/// Creates a new error for a value which doesn't match a set of expected literals.
pub fn unknown_value(value: &str) -> Self {
Error::new(ErrorKind::UnknownValue(value.into()))
}
/// Creates a new error for a list which did not get enough items to proceed.
pub fn too_few_items(min: usize) -> Self {
Error::new(ErrorKind::TooFewItems(min))
}
/// Creates a new error when a list got more items than it supports. The `max` argument
/// is the largest number of items the receiver could accept.
pub fn too_many_items(max: usize) -> Self {
Error::new(ErrorKind::TooManyItems(max))
}
/// Bundle a set of multiple errors into a single `Error` instance.
///
/// # Panics
/// This function will panic if `errors.is_empty() == true`.
pub fn multiple(mut errors: Vec<Error>) -> Self {
if errors.len() > 1 {
Error::new(ErrorKind::Multiple(errors))
} else if errors.len() == 1 {
errors
.pop()
.expect("Error array of length 1 has a first item")
} else {
panic!("Can't deal with 0 errors")
}
}
}
impl Error {
/// Create a new error about a literal string that doesn't match a set of known
/// or permissible values. This function can be made public if the API proves useful
/// beyond impls for `syn` types.
pub(crate) fn unknown_lit_str_value(value: &LitStr) -> Self {
Error::unknown_value(&value.value()).with_span(value)
}
}
/// Error instance methods
impl Error {
/// Check if this error is associated with a span in the token stream.
pub fn has_span(&self) -> bool {
self.span.is_some()
}
/// Override the source code location of this error with a new one.
#[deprecated(
since = "0.8.3",
note = "Callers should not broaden error spans. Use with_span instead."
)]
pub fn set_span(&mut self, span: Span) {
self.span = Some(span)
}
/// Tie a span to the error if none is already present. This is used in `darling::FromMeta`
/// and other traits to attach errors to the most specific possible location in the input
/// source code.
///
/// All `darling`-built impls, either from the crate or from the proc macro, will call this
/// when appropriate during parsing, so it should not be necessary to call this unless you have
/// overridden:
///
/// * `FromMeta::from_meta`
/// * `FromMeta::from_nested_meta`
/// * `FromMeta::from_value`
pub fn with_span<T: Spanned>(mut self, node: &T) -> Self {
if !self.has_span() {
self.span = Some(node.span());
}
self
}
/// Recursively converts a tree of errors to a flattened list.
pub fn flatten(self) -> Self {
Error::multiple(self.into_vec())
}
fn into_vec(self) -> Vec<Self> {
if let ErrorKind::Multiple(errors) = self.kind {
let mut flat = Vec::new();
for error in errors {
flat.extend(error.prepend_at(self.locations.clone()).into_vec());
}
flat
} else {
vec![self]
}
}
/// Adds a location to the error, such as a field or variant.
/// Locations must be added in reverse order of specificity.
pub fn at<T: fmt::Display>(mut self, location: T) -> Self {
self.locations.insert(0, location.to_string());
self
}
/// Gets the number of individual errors in this error.
///
/// This function never returns `0`, as it's impossible to construct
/// a multi-error from an empty `Vec`.
pub fn len(&self) -> usize {
self.kind.len()
}
/// Adds a location chain to the head of the error's existing locations.
fn prepend_at(mut self, mut locations: Vec<String>) -> Self {
if !locations.is_empty() {
locations.extend(self.locations);
self.locations = locations;
}
self
}
/// Gets the location slice.
#[cfg(test)]
pub(crate) fn location(&self) -> Vec<&str> {
self.locations.iter().map(|i| i.as_str()).collect()
}
/// Write this error and any children as compile errors into a `TokenStream` to
/// be returned by the proc-macro.
///
/// The behavior of this method will be slightly different if the `diagnostics` feature
/// is enabled: In that case, the diagnostics will be emitted immediately by this call,
/// and an empty `TokenStream` will be returned.
///
/// Return these tokens unmodified to avoid disturbing the attached span information.
///
/// # Usage
/// ```rust,ignore
/// // in your proc-macro function
/// let opts = match MyOptions::from_derive_input(&ast) {
/// Ok(val) => val,
/// Err(err) => {
/// return err.write_errors();
/// }
/// }
/// ```
pub fn write_errors(self) -> TokenStream {
#[cfg(feature = "diagnostics")]
{
self.emit();
quote!()
}
#[cfg(not(feature = "diagnostics"))]
{
self.flatten()
.into_iter()
.map(|e| e.single_to_syn_error().to_compile_error())
.collect()
}
}
#[cfg(not(feature = "diagnostics"))]
fn single_to_syn_error(self) -> ::syn::Error {
match self.span {
Some(span) => ::syn::Error::new(span, self.kind),
None => ::syn::Error::new(Span::call_site(), self),
}
}
#[cfg(feature = "diagnostics")]
fn single_to_diagnostic(self) -> ::proc_macro::Diagnostic {
use proc_macro::{Diagnostic, Level};
// Delegate to dedicated error formatters when applicable.
//
// If span information is available, don't include the error property path
// since it's redundant and not consistent with native compiler diagnostics.
match self.kind {
ErrorKind::UnknownField(euf) => euf.to_diagnostic(self.span),
_ => match self.span {
Some(span) => span.unwrap().error(self.kind.to_string()),
None => Diagnostic::new(Level::Error, self.to_string()),
},
}
}
/// Transform this error and its children into a list of compiler diagnostics
/// and emit them. If the `Error` has associated span information, the diagnostics
/// will identify the correct location in source code automatically.
///
/// # Stability
/// This is only available on `nightly` until the compiler `proc_macro_diagnostic`
/// feature stabilizes. Until then, it may break at any time.
#[cfg(feature = "diagnostics")]
pub fn emit(self) {
for error in self.flatten() {
error.single_to_diagnostic().emit()
}
}
/// Transform the error into a compiler diagnostic and - if the diagnostic points to
/// a specific code location - add a spanned help child diagnostic that points to the
/// parent derived trait.
///
/// This is experimental and therefore not exposed outside the crate.
#[cfg(feature = "diagnostics")]
#[allow(dead_code)]
fn emit_with_macro_help_span(self) {
use proc_macro::Diagnostic;
for error in self.flatten() {
let needs_help = error.has_span();
let diagnostic = error.single_to_diagnostic();
Diagnostic::emit(if needs_help {
diagnostic.span_help(
Span::call_site().unwrap(),
"Encountered as part of this derive-mode-macro",
)
} else {
diagnostic
})
}
}
}
impl StdError for Error {
fn description(&self) -> &str {
&self.kind.description()
}
fn cause(&self) -> Option<&StdError> {
None
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.kind)?;
if !self.locations.is_empty() {
write!(f, " at {}", self.locations.join("/"))?;
}
Ok(())
}
}
// Don't want to publicly commit to Error supporting equality yet, but
// not having it makes testing very difficult. Note that spans are not
// considered for equality since that would break testing in most cases.
#[cfg(test)]
impl PartialEq for Error {
fn eq(&self, other: &Self) -> bool {
self.kind == other.kind && self.locations == other.locations
}
}
#[cfg(test)]
impl Eq for Error {}
impl IntoIterator for Error {
type Item = Error;
type IntoIter = IntoIter;
fn into_iter(self) -> IntoIter {
if let ErrorKind::Multiple(errors) = self.kind {
IntoIter {
inner: IntoIterEnum::Multiple(errors.into_iter()),
}
} else {
IntoIter {
inner: IntoIterEnum::Single(iter::once(self)),
}
}
}
}
enum IntoIterEnum {
Single(iter::Once<Error>),
Multiple(vec::IntoIter<Error>),
}
impl Iterator for IntoIterEnum {
type Item = Error;
fn next(&mut self) -> Option<Self::Item> {
match *self {
IntoIterEnum::Single(ref mut content) => content.next(),
IntoIterEnum::Multiple(ref mut content) => content.next(),
}
}
}
/// An iterator that moves out of an `Error`.
pub struct IntoIter {
inner: IntoIterEnum,
}
impl Iterator for IntoIter {
type Item = Error;
fn next(&mut self) -> Option<Error> {
self.inner.next()
}
}
#[cfg(test)]
mod tests {
use super::Error;
#[test]
fn flatten_noop() {
let err = Error::duplicate_field("hello").at("world");
assert_eq!(err.clone().flatten(), err);
}
#[test]
fn flatten_simple() {
let err = Error::multiple(vec![
Error::unknown_field("hello").at("world"),
Error::missing_field("hell_no").at("world"),
])
.at("foo")
.flatten();
assert!(err.location().is_empty());
let mut err_iter = err.into_iter();
let first = err_iter.next();
assert!(first.is_some());
assert_eq!(first.unwrap().location(), vec!["foo", "world"]);
let second = err_iter.next();
assert!(second.is_some());
assert_eq!(second.unwrap().location(), vec!["foo", "world"]);
assert!(err_iter.next().is_none());
}
#[test]
fn len_single() {
let err = Error::duplicate_field("hello");
assert_eq!(1, err.len());
}
#[test]
fn len_multiple() {
let err = Error::multiple(vec![
Error::duplicate_field("hello"),
Error::missing_field("hell_no"),
]);
assert_eq!(2, err.len());
}
#[test]
fn len_nested() {
let err = Error::multiple(vec![
Error::duplicate_field("hello"),
Error::multiple(vec![
Error::duplicate_field("hi"),
Error::missing_field("bye"),
Error::multiple(vec![Error::duplicate_field("whatsup")]),
]),
]);
assert_eq!(4, err.len());
}
}

252
third_party/rust/darling_core/src/from_meta.rs поставляемый
Просмотреть файл

@ -1,5 +1,6 @@
use std::cell::RefCell;
use std::collections::hash_map::{Entry, HashMap};
use std::hash::BuildHasher;
use std::rc::Rc;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
@ -26,6 +27,10 @@ use {Error, Result};
/// * As a string literal, e.g. `foo = "hello"`.
/// * As a raw string literal, e.g. `foo = r#"hello "world""#`.
///
/// ## Number
/// * As a string literal, e.g. `foo = "-25"`.
/// * As an unquoted positive value, e.g. `foo = 404`. Negative numbers must be in quotation marks.
///
/// ## ()
/// * Word with no value specified, e.g. `foo`. This is best used with `Option`.
/// See `darling::util::Flag` for a more strongly-typed alternative.
@ -38,26 +43,34 @@ use {Error, Result};
/// parse attempt.
pub trait FromMeta: Sized {
fn from_nested_meta(item: &NestedMeta) -> Result<Self> {
match *item {
(match *item {
NestedMeta::Literal(ref lit) => Self::from_value(lit),
NestedMeta::Meta(ref mi) => Self::from_meta(mi),
}
})
.map_err(|e| e.with_span(item))
}
/// Create an instance from a `syn::Meta` by dispatching to the format-appropriate
/// trait function. This generally should not be overridden by implementers.
///
/// # Error Spans
/// If this method is overridden and can introduce errors that weren't passed up from
/// other `from_meta` calls, the override must call `with_span` on the error using the
/// `item` to make sure that the emitted diagnostic points to the correct location in
/// source code.
fn from_meta(item: &Meta) -> Result<Self> {
match *item {
(match *item {
Meta::Word(_) => Self::from_word(),
Meta::List(ref value) => Self::from_list(
&value
.nested
.clone()
.into_iter()
.iter()
.cloned()
.collect::<Vec<syn::NestedMeta>>()[..],
),
Meta::NameValue(ref value) => Self::from_value(&value.lit),
}
})
.map_err(|e| e.with_span(item))
}
/// Create an instance from the presence of the word in the attribute with no
@ -75,12 +88,17 @@ pub trait FromMeta: Sized {
/// Create an instance from a literal value of either `foo = "bar"` or `foo("bar")`.
/// This dispatches to the appropriate method based on the type of literal encountered,
/// and generally should not be overridden by implementers.
///
/// # Error Spans
/// If this method is overridden, the override must make sure to add `value`'s span
/// information to the returned error by calling `with_span(value)` on the `Error` instance.
fn from_value(value: &Lit) -> Result<Self> {
match *value {
(match *value {
Lit::Bool(ref b) => Self::from_bool(b.value),
Lit::Str(ref s) => Self::from_string(&s.value()),
ref _other => Err(Error::unexpected_type("other")),
}
_ => Err(Error::unexpected_lit_type(value)),
})
.map_err(|e| e.with_span(value))
}
/// Create an instance from a char literal in a value position.
@ -126,7 +144,9 @@ impl FromMeta for bool {
impl FromMeta for AtomicBool {
fn from_meta(mi: &Meta) -> Result<Self> {
FromMeta::from_meta(mi).map(AtomicBool::new)
FromMeta::from_meta(mi)
.map(AtomicBool::new)
.map_err(|e| e.with_span(mi))
}
}
@ -136,84 +156,127 @@ impl FromMeta for String {
}
}
impl FromMeta for u8 {
fn from_string(s: &str) -> Result<Self> {
s.parse().map_err(|_| Error::unknown_value(s))
}
/// Generate an impl of `FromMeta` that will accept strings which parse to numbers or
/// integer literals.
macro_rules! from_meta_num {
($ty:ident) => {
impl FromMeta for $ty {
fn from_string(s: &str) -> Result<Self> {
s.parse().map_err(|_| Error::unknown_value(s))
}
fn from_value(value: &Lit) -> Result<Self> {
(match *value {
Lit::Str(ref s) => Self::from_string(&s.value()),
Lit::Int(ref s) => Ok(s.value() as $ty),
_ => Err(Error::unexpected_lit_type(value)),
})
.map_err(|e| e.with_span(value))
}
}
};
}
impl FromMeta for u16 {
fn from_string(s: &str) -> Result<Self> {
s.parse().map_err(|_| Error::unknown_value(s))
}
from_meta_num!(u8);
from_meta_num!(u16);
from_meta_num!(u32);
from_meta_num!(u64);
from_meta_num!(usize);
from_meta_num!(i8);
from_meta_num!(i16);
from_meta_num!(i32);
from_meta_num!(i64);
from_meta_num!(isize);
/// Generate an impl of `FromMeta` that will accept strings which parse to floats or
/// float literals.
macro_rules! from_meta_float {
($ty:ident) => {
impl FromMeta for $ty {
fn from_string(s: &str) -> Result<Self> {
s.parse().map_err(|_| Error::unknown_value(s))
}
fn from_value(value: &Lit) -> Result<Self> {
(match *value {
Lit::Str(ref s) => Self::from_string(&s.value()),
Lit::Float(ref s) => Ok(s.value() as $ty),
_ => Err(Error::unexpected_lit_type(value)),
})
.map_err(|e| e.with_span(value))
}
}
};
}
impl FromMeta for u32 {
fn from_string(s: &str) -> Result<Self> {
s.parse().map_err(|_| Error::unknown_value(s))
}
}
impl FromMeta for u64 {
fn from_string(s: &str) -> Result<Self> {
s.parse().map_err(|_| Error::unknown_value(s))
}
}
impl FromMeta for usize {
fn from_string(s: &str) -> Result<Self> {
s.parse().map_err(|_| Error::unknown_value(s))
}
}
impl FromMeta for i8 {
fn from_string(s: &str) -> Result<Self> {
s.parse().map_err(|_| Error::unknown_value(s))
}
}
impl FromMeta for i16 {
fn from_string(s: &str) -> Result<Self> {
s.parse().map_err(|_| Error::unknown_value(s))
}
}
impl FromMeta for i32 {
fn from_string(s: &str) -> Result<Self> {
s.parse().map_err(|_| Error::unknown_value(s))
}
}
impl FromMeta for i64 {
fn from_string(s: &str) -> Result<Self> {
s.parse().map_err(|_| Error::unknown_value(s))
}
}
impl FromMeta for isize {
fn from_string(s: &str) -> Result<Self> {
s.parse().map_err(|_| Error::unknown_value(s))
}
}
from_meta_float!(f32);
from_meta_float!(f64);
/// Parsing support for identifiers. This attempts to preserve span information
/// when available, but also supports parsing strings with the call site as the
/// emitted span.
impl FromMeta for syn::Ident {
fn from_string(value: &str) -> Result<Self> {
Ok(syn::Ident::new(value, ::proc_macro2::Span::call_site()))
}
fn from_value(value: &Lit) -> Result<Self> {
if let Lit::Str(ref ident) = *value {
ident
.parse()
.map_err(|_| Error::unknown_lit_str_value(ident))
} else {
Err(Error::unexpected_lit_type(value))
}
}
}
/// Parsing support for paths. This attempts to preserve span information when available,
/// but also supports parsing strings with the call site as the emitted span.
impl FromMeta for syn::Path {
fn from_string(value: &str) -> Result<Self> {
syn::parse_str(value).map_err(|_| Error::unknown_value(value))
}
}
/*
impl FromMeta for syn::TypeParamBound {
fn from_string(value: &str) -> Result<Self> {
Ok(syn::TypeParamBound::from(value))
fn from_value(value: &Lit) -> Result<Self> {
if let Lit::Str(ref path_str) = *value {
path_str
.parse()
.map_err(|_| Error::unknown_lit_str_value(path_str))
} else {
Err(Error::unexpected_lit_type(value))
}
}
}
*/
impl FromMeta for syn::Lit {
fn from_value(value: &Lit) -> Result<Self> {
Ok(value.clone())
}
}
macro_rules! from_meta_lit {
($impl_ty:path, $lit_variant:path) => {
impl FromMeta for $impl_ty {
fn from_value(value: &Lit) -> Result<Self> {
if let $lit_variant(ref value) = *value {
Ok(value.clone())
} else {
Err(Error::unexpected_lit_type(value))
}
}
}
};
}
from_meta_lit!(syn::LitInt, Lit::Int);
from_meta_lit!(syn::LitFloat, Lit::Float);
from_meta_lit!(syn::LitStr, Lit::Str);
from_meta_lit!(syn::LitByte, Lit::Byte);
from_meta_lit!(syn::LitByteStr, Lit::ByteStr);
from_meta_lit!(syn::LitChar, Lit::Char);
from_meta_lit!(syn::LitBool, Lit::Bool);
from_meta_lit!(syn::LitVerbatim, Lit::Verbatim);
impl FromMeta for syn::Meta {
fn from_meta(value: &syn::Meta) -> Result<Self> {
@ -286,14 +349,20 @@ impl<T: FromMeta> FromMeta for RefCell<T> {
}
}
impl<V: FromMeta> FromMeta for HashMap<String, V> {
impl<V: FromMeta, S: BuildHasher + Default> FromMeta for HashMap<String, V, S> {
fn from_list(nested: &[syn::NestedMeta]) -> Result<Self> {
let mut map = HashMap::with_capacity(nested.len());
let mut map = HashMap::with_capacity_and_hasher(nested.len(), Default::default());
for item in nested {
if let syn::NestedMeta::Meta(ref inner) = *item {
match map.entry(inner.name().to_string()) {
Entry::Occupied(_) => return Err(Error::duplicate_field(&inner.name().to_string())),
Entry::Occupied(_) => {
return Err(
Error::duplicate_field(&inner.name().to_string()).with_span(inner)
);
}
Entry::Vacant(entry) => {
// In the error case, extend the error's path, but assume the inner `from_meta`
// set the span, and that subsequently we don't have to.
entry.insert(FromMeta::from_meta(inner).map_err(|e| e.at(inner.name()))?);
}
}
@ -311,7 +380,7 @@ mod tests {
use proc_macro2::TokenStream;
use syn;
use {FromMeta, Result};
use {Error, FromMeta, Result};
/// parse a string as a syn::Meta instance.
fn pm(tokens: TokenStream) -> ::std::result::Result<syn::Meta, String> {
@ -356,6 +425,24 @@ mod tests {
fn number_succeeds() {
assert_eq!(fm::<u8>(quote!(ignore = "2")), 2u8);
assert_eq!(fm::<i16>(quote!(ignore = "-25")), -25i16);
assert_eq!(fm::<f64>(quote!(ignore = "1.4e10")), 1.4e10);
}
#[test]
fn int_without_quotes() {
assert_eq!(fm::<u8>(quote!(ignore = 2)), 2u8);
assert_eq!(fm::<u16>(quote!(ignore = 255)), 255u16);
assert_eq!(fm::<u32>(quote!(ignore = 5000)), 5000u32);
// Check that we aren't tripped up by incorrect suffixes
assert_eq!(fm::<u32>(quote!(ignore = 5000i32)), 5000u32);
}
#[test]
fn float_without_quotes() {
assert_eq!(fm::<f32>(quote!(ignore = 2.)), 2.0f32);
assert_eq!(fm::<f32>(quote!(ignore = 2.0)), 2.0f32);
assert_eq!(fm::<f64>(quote!(ignore = 1.4e10)), 1.4e10f64);
}
#[test]
@ -386,6 +473,21 @@ mod tests {
);
}
/// Check that a `HashMap` cannot have duplicate keys, and that the generated error
/// is assigned a span to correctly target the diagnostic message.
#[test]
fn hash_map_duplicate() {
use std::collections::HashMap;
let err: Result<HashMap<String, bool>> =
FromMeta::from_meta(&pm(quote!(ignore(hello, hello = false))).unwrap());
let err = err.expect_err("Duplicate keys in HashMap should error");
assert!(err.has_span());
assert_eq!(err.to_string(), Error::duplicate_field("hello").to_string());
}
/// Tests that fallible parsing will always produce an outer `Ok` (from `fm`),
/// and will accurately preserve the inner contents.
#[test]

12
third_party/rust/darling_core/src/lib.rs поставляемый
Просмотреть файл

@ -1,14 +1,17 @@
#![recursion_limit = "256"]
#![cfg_attr(feature = "diagnostics", feature(proc_macro_diagnostic))]
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;
extern crate proc_macro2;
extern crate fnv;
extern crate ident_case;
#[cfg(feature = "diagnostics")]
extern crate proc_macro;
extern crate proc_macro2;
#[cfg(feature = "suggestions")]
extern crate strsim;
#[macro_use]
mod macros_private;
@ -17,6 +20,7 @@ mod macros_public;
pub mod ast;
pub mod codegen;
pub mod derive;
pub mod error;
mod from_derive_input;
mod from_field;
@ -40,4 +44,4 @@ pub use from_variant::FromVariant;
// Re-export tokenizer
#[doc(hidden)]
pub use quote::ToTokens;
pub use quote::ToTokens;

Просмотреть файл

@ -4,6 +4,7 @@ use syn;
use ast::{Data, Fields, Style};
use codegen;
use options::{DefaultExpression, InputField, InputVariant, ParseAttribute, ParseData};
use util::Flag;
use {Error, FromMeta, Result};
/// A struct or enum which should have `FromMeta` or `FromDeriveInput` implementations
@ -33,6 +34,9 @@ pub struct Core {
/// The custom bound to apply to the generated impl
pub bound: Option<Vec<syn::WherePredicate>>,
/// Whether or not unknown fields should produce an error at compilation time.
pub allow_unknown_fields: Flag,
}
impl Core {
@ -52,6 +56,7 @@ impl Core {
},
map: Default::default(),
bound: Default::default(),
allow_unknown_fields: Default::default(),
}
}
@ -70,7 +75,7 @@ impl ParseAttribute for Core {
match mi.name().to_string().as_str() {
"default" => {
if self.default.is_some() {
Err(Error::duplicate_field("default"))
Err(Error::duplicate_field("default").with_span(mi))
} else {
self.default = FromMeta::from_meta(mi)?;
Ok(())
@ -84,7 +89,7 @@ impl ParseAttribute for Core {
}
"map" => {
if self.map.is_some() {
Err(Error::duplicate_field("map"))
Err(Error::duplicate_field("map").with_span(mi))
} else {
self.map = FromMeta::from_meta(mi)?;
Ok(())
@ -94,7 +99,15 @@ impl ParseAttribute for Core {
self.bound = FromMeta::from_meta(mi)?;
Ok(())
}
n => Err(Error::unknown_field(n.as_ref())),
"allow_unknown_fields" => {
if self.allow_unknown_fields.is_some() {
Err(Error::duplicate_field("allow_unknown_fields").with_span(mi))
} else {
self.allow_unknown_fields = FromMeta::from_meta(mi)?;
Ok(())
}
}
n => Err(Error::unknown_field(n).with_span(mi)),
}
}
}
@ -133,13 +146,15 @@ impl<'a> From<&'a Core> for codegen::TraitImpl<'a> {
codegen::TraitImpl {
ident: &v.ident,
generics: &v.generics,
data: v.data
data: v
.data
.as_ref()
.map_struct_fields(InputField::as_codegen_field)
.map_enum_variants(|variant| variant.as_codegen_variant(&v.ident)),
default: v.as_codegen_default(),
map: v.map.as_ref(),
bound: v.bound.as_ref().map(|i| i.as_slice()),
allow_unknown_fields: v.allow_unknown_fields.into(),
}
}
}

Просмотреть файл

@ -1,6 +1,8 @@
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::{self, Ident};
use codegen;
use codegen::FromDeriveInputImpl;
use options::{OuterFrom, ParseAttribute, ParseData, Shape};
use {FromMeta, Result};
@ -27,8 +29,9 @@ impl FdiOptions {
generics: Default::default(),
data: Default::default(),
supports: Default::default(),
}).parse_attributes(&di.attrs)?
.parse_body(&di.data)
})
.parse_attributes(&di.attrs)?
.parse_body(&di.data)
}
}
@ -74,9 +77,9 @@ impl ParseData for FdiOptions {
}
}
impl<'a> From<&'a FdiOptions> for codegen::FromDeriveInputImpl<'a> {
impl<'a> From<&'a FdiOptions> for FromDeriveInputImpl<'a> {
fn from(v: &'a FdiOptions) -> Self {
codegen::FromDeriveInputImpl {
FromDeriveInputImpl {
base: (&v.base.container).into(),
attr_names: &v.base.attr_names,
from_ident: v.base.from_ident,
@ -90,3 +93,9 @@ impl<'a> From<&'a FdiOptions> for codegen::FromDeriveInputImpl<'a> {
}
}
}
impl ToTokens for FdiOptions {
fn to_tokens(&self, tokens: &mut TokenStream) {
FromDeriveInputImpl::from(self).to_tokens(tokens)
}
}

Просмотреть файл

@ -1,3 +1,5 @@
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::{self, Ident};
use codegen::FromFieldImpl;
@ -17,8 +19,9 @@ impl FromFieldOptions {
base: OuterFrom::start(di),
vis: Default::default(),
ty: Default::default(),
}).parse_attributes(&di.attrs)?
.parse_body(&di.data)
})
.parse_attributes(&di.attrs)?
.parse_body(&di.data)
}
}
@ -68,3 +71,9 @@ impl<'a> From<&'a FromFieldOptions> for FromFieldImpl<'a> {
}
}
}
impl ToTokens for FromFieldOptions {
fn to_tokens(&self, tokens: &mut TokenStream) {
FromFieldImpl::from(self).to_tokens(tokens)
}
}

Просмотреть файл

@ -1,6 +1,8 @@
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn;
use codegen;
use codegen::FromMetaImpl;
use options::{Core, ParseAttribute, ParseData};
use Result;
@ -12,8 +14,9 @@ impl FromMetaOptions {
pub fn new(di: &syn::DeriveInput) -> Result<Self> {
(FromMetaOptions {
base: Core::start(di),
}).parse_attributes(&di.attrs)?
.parse_body(&di.data)
})
.parse_attributes(&di.attrs)?
.parse_body(&di.data)
}
}
@ -33,10 +36,16 @@ impl ParseData for FromMetaOptions {
}
}
impl<'a> From<&'a FromMetaOptions> for codegen::FromMetaImpl<'a> {
impl<'a> From<&'a FromMetaOptions> for FromMetaImpl<'a> {
fn from(v: &'a FromMetaOptions) -> Self {
codegen::FromMetaImpl {
FromMetaImpl {
base: (&v.base).into(),
}
}
}
impl ToTokens for FromMetaOptions {
fn to_tokens(&self, tokens: &mut TokenStream) {
FromMetaImpl::from(self).to_tokens(tokens)
}
}

Просмотреть файл

@ -1,3 +1,5 @@
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::{self, Ident};
use codegen::FromTypeParamImpl;
@ -17,8 +19,9 @@ impl FromTypeParamOptions {
base: OuterFrom::start(di),
bounds: None,
default: None,
}).parse_attributes(&di.attrs)?
.parse_body(&di.data)
})
.parse_attributes(&di.attrs)?
.parse_body(&di.data)
}
}
@ -68,3 +71,9 @@ impl<'a> From<&'a FromTypeParamOptions> for FromTypeParamImpl<'a> {
}
}
}
impl ToTokens for FromTypeParamOptions {
fn to_tokens(&self, tokens: &mut TokenStream) {
FromTypeParamImpl::from(self).to_tokens(tokens)
}
}

Просмотреть файл

@ -1,3 +1,5 @@
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::{DeriveInput, Field, Ident, Meta};
use codegen::FromVariantImpl;
@ -17,8 +19,9 @@ impl FromVariantOptions {
base: OuterFrom::start(di),
fields: Default::default(),
supports: Default::default(),
}).parse_attributes(&di.attrs)?
.parse_body(&di.data)
})
.parse_attributes(&di.attrs)?
.parse_body(&di.data)
}
}
@ -66,3 +69,9 @@ impl ParseData for FromVariantOptions {
}
}
}
impl ToTokens for FromVariantOptions {
fn to_tokens(&self, tokens: &mut TokenStream) {
FromVariantImpl::from(self).to_tokens(tokens)
}
}

Просмотреть файл

@ -1,3 +1,5 @@
use std::borrow::Cow;
use syn;
use codegen;
@ -24,14 +26,16 @@ impl InputField {
pub fn as_codegen_field<'a>(&'a self) -> codegen::Field<'a> {
codegen::Field {
ident: &self.ident,
name_in_attr: self.attr_name
.clone()
.unwrap_or_else(|| self.ident.to_string()),
name_in_attr: self
.attr_name
.as_ref()
.map_or_else(|| Cow::Owned(self.ident.to_string()), Cow::Borrowed),
ty: &self.ty,
default_expression: self.as_codegen_default(),
with_path: self.with
.clone()
.unwrap_or_else(|| parse_quote!(::darling::FromMeta::from_meta)),
with_path: self.with.as_ref().map_or_else(
|| Cow::Owned(parse_quote!(::darling::FromMeta::from_meta)),
Cow::Borrowed,
),
skip: self.skip,
map: self.map.as_ref(),
multiple: self.multiple,
@ -62,10 +66,10 @@ impl InputField {
}
pub fn from_field(f: &syn::Field, parent: Option<&Core>) -> Result<Self> {
let ident = f.ident.clone().unwrap_or_else(|| syn::Ident::new(
"__unnamed",
::proc_macro2::Span::call_site(),
));
let ident = f
.ident
.clone()
.unwrap_or_else(|| syn::Ident::new("__unnamed", ::proc_macro2::Span::call_site()));
let ty = f.ty.clone();
let base = Self::new(ident, ty).parse_attributes(&f.attrs)?;
@ -137,7 +141,7 @@ impl ParseAttribute for InputField {
self.multiple = FromMeta::from_meta(mi)?;
Ok(())
}
n => Err(Error::unknown_field(n)),
n => Err(Error::unknown_field(n).with_span(mi)),
}
}
}

Просмотреть файл

@ -1,6 +1,8 @@
use std::borrow::Cow;
use syn;
use ast::{Fields, Style};
use ast::Fields;
use codegen;
use options::{Core, InputField, ParseAttribute};
use {Error, FromMeta, Result};
@ -11,6 +13,8 @@ pub struct InputVariant {
attr_name: Option<String>,
data: Fields<InputField>,
skip: bool,
/// Whether or not unknown fields are acceptable in this
allow_unknown_fields: Option<bool>,
}
impl InputVariant {
@ -18,11 +22,13 @@ impl InputVariant {
codegen::Variant {
ty_ident,
variant_ident: &self.ident,
name_in_attr: self.attr_name
.clone()
.unwrap_or_else(|| self.ident.to_string()),
name_in_attr: self
.attr_name
.as_ref()
.map_or_else(|| Cow::Owned(self.ident.to_string()), Cow::Borrowed),
data: self.data.as_ref().map(InputField::as_codegen_field),
skip: self.skip,
allow_unknown_fields: self.allow_unknown_fields.unwrap_or_default(),
}
}
@ -32,20 +38,19 @@ impl InputVariant {
attr_name: Default::default(),
data: Fields::empty_from(&v.fields),
skip: Default::default(),
}).parse_attributes(&v.attrs)?;
allow_unknown_fields: None,
})
.parse_attributes(&v.attrs)?;
starter.data = match v.fields {
syn::Fields::Unit => Style::Unit.into(),
starter.data.fields = match v.fields {
syn::Fields::Unit => vec![],
syn::Fields::Unnamed(ref fields) => {
let mut items = Vec::with_capacity(fields.unnamed.len());
for item in &fields.unnamed {
items.push(InputField::from_field(item, parent)?);
}
Fields {
style: v.fields.clone().into(),
fields: items,
}
items
}
syn::Fields::Named(ref fields) => {
let mut items = Vec::with_capacity(fields.named.len());
@ -53,10 +58,7 @@ impl InputVariant {
items.push(InputField::from_field(item, parent)?);
}
Fields {
style: v.fields.clone().into(),
fields: items,
}
items
}
};
@ -72,6 +74,10 @@ impl InputVariant {
self.attr_name = Some(parent.rename_rule.apply_to_variant(self.ident.to_string()));
}
if self.allow_unknown_fields.is_none() {
self.allow_unknown_fields = Some(parent.allow_unknown_fields.is_some());
}
self
}
}
@ -88,7 +94,7 @@ impl ParseAttribute for InputVariant {
self.skip = FromMeta::from_meta(mi)?;
Ok(())
}
n => Err(Error::unknown_field(n)),
n => Err(Error::unknown_field(n).with_span(mi)),
}
}
}

Просмотреть файл

@ -42,23 +42,37 @@ impl FromMeta for DefaultExpression {
Ok(DefaultExpression::Trait)
}
fn from_string(lit: &str) -> Result<Self> {
Ok(DefaultExpression::Explicit(
syn::parse_str(lit).map_err(|_| Error::unknown_value(lit))?
))
fn from_value(value: &syn::Lit) -> Result<Self> {
syn::Path::from_value(value).map(DefaultExpression::Explicit)
}
}
/// Middleware for extracting attribute values.
/// Run a parsing task, and if it produces an error push it into `$errors`
macro_rules! collect_error {
($errors:ident, $task:expr) => {
if let Err(e) = $task {
$errors.push(e);
}
};
}
/// Middleware for extracting attribute values. Implementers are expected to override
/// `parse_nested` so they can apply individual items to themselves, while `parse_attributes`
/// is responsible for looping through distinct outer attributes and collecting errors.
pub trait ParseAttribute: Sized {
fn parse_attributes(mut self, attrs: &[syn::Attribute]) -> Result<Self> {
let mut errors = Vec::new();
for attr in attrs {
if attr.path == parse_quote!(darling) {
parse_attr(attr, &mut self)?;
collect_error!(errors, parse_attr(attr, &mut self));
}
}
Ok(self)
if !errors.is_empty() {
Err(Error::multiple(errors))
} else {
Ok(self)
}
}
/// Read a meta-item, and apply its values to the current instance.
@ -66,66 +80,75 @@ pub trait ParseAttribute: Sized {
}
fn parse_attr<T: ParseAttribute>(attr: &syn::Attribute, target: &mut T) -> Result<()> {
match attr.interpret_meta() {
let mut errors = Vec::new();
match attr.parse_meta().ok() {
Some(syn::Meta::List(data)) => {
for item in data.nested {
if let syn::NestedMeta::Meta(ref mi) = item {
target.parse_nested(mi)?;
collect_error!(errors, target.parse_nested(mi));
} else {
panic!("Wasn't able to parse: `{:?}`", item);
}
}
Ok(())
if !errors.is_empty() {
Err(Error::multiple(errors))
} else {
Ok(())
}
}
Some(ref item) => panic!("Wasn't able to parse: `{:?}`", item),
None => panic!("Unable to parse {:?}", attr),
}
}
/// Middleware for extracting values from the body of the derive input. Implementers are
/// expected to override `parse_field` or `parse_variant` as appropriate for their use-case,
/// while `parse_body` dispatches to the appropriate methods and handles error collection.
pub trait ParseData: Sized {
fn parse_body(mut self, body: &syn::Data) -> Result<Self> {
use syn::{Data, Fields};
let mut errors = Vec::new();
match *body {
Data::Struct(ref data) => match data.fields {
Fields::Unit => Ok(self),
Fields::Unit => {}
Fields::Named(ref fields) => {
for field in &fields.named {
self.parse_field(field)?;
collect_error!(errors, self.parse_field(field));
}
Ok(self)
}
Fields::Unnamed(ref fields) => {
for field in &fields.unnamed {
self.parse_field(field)?;
collect_error!(errors, self.parse_field(field));
}
Ok(self)
}
},
Data::Enum(ref data) => {
for variant in &data.variants {
self.parse_variant(variant)?;
collect_error!(errors, self.parse_variant(variant));
}
Ok(self)
}
Data::Union(_) => unreachable!(),
};
if !errors.is_empty() {
Err(Error::multiple(errors))
} else {
Ok(self)
}
}
/// Apply the next found variant to the object, returning an error
/// if parsing goes wrong.
#[allow(unused_variables)]
fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> {
Err(Error::unsupported_format("enum variant"))
Err(Error::unsupported_format("enum variant").with_span(variant))
}
/// Apply the next found struct field to the object, returning an error
/// if parsing goes wrong.
#[allow(unused_variables)]
fn parse_field(&mut self, field: &syn::Field) -> Result<()> {
Err(Error::unsupported_format("struct field"))
Err(Error::unsupported_format("struct field").with_span(field))
}
}

Просмотреть файл

@ -1,5 +1,5 @@
use proc_macro2::TokenStream;
use quote::{TokenStreamExt, ToTokens};
use quote::{ToTokens, TokenStreamExt};
use syn::{Meta, NestedMeta};
use {Error, FromMeta, Result};
@ -40,14 +40,18 @@ impl FromMeta for Shape {
if word == "any" {
new.any = true;
} else if word.starts_with("enum_") {
new.enum_values.set_word(word)?;
new.enum_values
.set_word(word)
.map_err(|e| e.with_span(ident))?;
} else if word.starts_with("struct_") {
new.struct_values.set_word(word)?;
new.struct_values
.set_word(word)
.map_err(|e| e.with_span(ident))?;
} else {
return Err(Error::unknown_value(word));
return Err(Error::unknown_value(word).with_span(ident));
}
} else {
return Err(Error::unsupported_format("non-word"));
return Err(Error::unsupported_format("non-word").with_span(item));
}
}
@ -57,7 +61,7 @@ impl FromMeta for Shape {
impl ToTokens for Shape {
fn to_tokens(&self, tokens: &mut TokenStream) {
let fn_body = if self.any == true {
let fn_body = if self.any {
quote!(::darling::export::Ok(()))
} else {
let en = &self.enum_values;
@ -84,24 +88,27 @@ impl ToTokens for Shape {
}
};
// FIXME: Remove the &[]
tokens.append_all(&[quote!{
tokens.append_all(quote! {
#[allow(unused_variables)]
fn __validate_body(__body: &::syn::Data) -> ::darling::Result<()> {
#fn_body
}
}]);
});
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct DataShape {
/// The kind of shape being described. This can be `struct_` or `enum_`.
prefix: &'static str,
newtype: bool,
named: bool,
tuple: bool,
unit: bool,
any: bool,
/// Control whether the emitted code should be inside a function or not.
/// This is `true` when creating a `Shape` for `FromDeriveInput`, but false
/// when deriving `FromVariant`.
embedded: bool,
}
@ -147,16 +154,24 @@ impl DataShape {
impl FromMeta for DataShape {
fn from_list(items: &[NestedMeta]) -> Result<Self> {
let mut errors = Vec::new();
let mut new = DataShape::default();
for item in items {
if let NestedMeta::Meta(Meta::Word(ref ident)) = *item {
new.set_word(ident.to_string().as_str())?;
if let Err(e) = new.set_word(&ident.to_string()) {
errors.push(e.with_span(ident));
}
} else {
return Err(Error::unsupported_format("non-word"));
errors.push(Error::unsupported_format("non-word").with_span(item));
}
}
Ok(new)
if !errors.is_empty() {
Err(Error::multiple(errors))
} else {
Ok(new)
}
}
}
@ -183,15 +198,13 @@ impl ToTokens for DataShape {
};
if self.embedded {
// FIXME: Remove the &[]
tokens.append_all(&[body]);
body.to_tokens(tokens);
} else {
// FIXME: Remove the &[]
tokens.append_all(&[quote! {
tokens.append_all(quote! {
fn __validate_data(data: &::syn::Fields) -> ::darling::Result<()> {
#body
}
}]);
});
}
}
}
@ -215,7 +228,7 @@ mod tests {
/// parse a string as a syn::Meta instance.
fn pm(tokens: TokenStream) -> ::std::result::Result<syn::Meta, String> {
let attribute: syn::Attribute = parse_quote!(#[#tokens]);
attribute.interpret_meta().ok_or("Unable to parse".into())
attribute.parse_meta().or(Err("Unable to parse".into()))
}
fn fm<T: FromMeta>(tokens: TokenStream) -> T {

Просмотреть файл

@ -99,10 +99,9 @@ impl<T: UsesLifetimes> UsesLifetimes for Option<T> {
options: &Options,
lifetimes: &'a LifetimeSet,
) -> LifetimeRefSet<'a> {
self.as_ref().map_or_else(
|| Default::default(),
|v| v.uses_lifetimes(options, lifetimes),
)
self.as_ref()
.map(|v| v.uses_lifetimes(options, lifetimes))
.unwrap_or_default()
}
}
@ -288,13 +287,14 @@ mod tests {
use usage::GenericsExt;
use usage::Purpose::*;
fn parse(src: &str) -> DeriveInput {
syn::parse_str(src).unwrap()
}
#[test]
fn struct_named() {
let input = parse("struct Foo<'a, 'b: 'a> { parent: &'b Bar, child: &'a Baz, }");
let input: DeriveInput = parse_quote! {
struct Foo<'a, 'b: 'a> {
parent: &'b Bar,
child: &'a Baz,
}
};
let omitted = syn::Lifetime::new("'c", Span::call_site());
let lifetimes = {
@ -309,9 +309,12 @@ mod tests {
#[test]
fn qself() {
let input = parse(
"struct Foo<'a, 'b: 'a> { parent: &'b Bar, child: <Bar<'a> as MyIterator>::Item, }",
);
let input: DeriveInput = parse_quote! {
struct Foo<'a, 'b: 'a> {
parent: &'b Bar,
child: <Bar<'a> as MyIterator>::Item,
}
};
let lifetimes = input.generics.declared_lifetimes();
let matches = input.data.uses_lifetimes(&BoundImpl.into(), &lifetimes);
assert_eq!(matches.len(), 1);

Просмотреть файл

@ -246,16 +246,12 @@ impl UsesTypeParams for syn::TypeParamBound {
#[cfg(test)]
mod tests {
use proc_macro2::Span;
use syn::{self, Ident};
use syn::{DeriveInput, Ident};
use super::UsesTypeParams;
use usage::IdentSet;
use usage::Purpose::*;
fn given_src(src: &str) -> syn::DeriveInput {
syn::parse_str(src).unwrap()
}
fn ident_set(idents: Vec<&str>) -> IdentSet {
idents
.into_iter()
@ -265,7 +261,7 @@ mod tests {
#[test]
fn finds_simple() {
let input = given_src("struct Foo<T, U>(T, i32, A, U);");
let input: DeriveInput = parse_quote! { struct Foo<T, U>(T, i32, A, U); };
let generics = ident_set(vec!["T", "U", "X"]);
let matches = input.data.uses_type_params(&BoundImpl.into(), &generics);
assert_eq!(matches.len(), 2);
@ -277,14 +273,12 @@ mod tests {
#[test]
fn finds_named() {
let input = given_src(
r#"
struct Foo<T, U = usize> {
bar: T,
world: U,
}
"#,
);
let input: DeriveInput = parse_quote! {
struct Foo<T, U = usize> {
bar: T,
world: U,
}
};
let generics = ident_set(vec!["T", "U", "X"]);
@ -299,14 +293,12 @@ mod tests {
#[test]
fn finds_as_type_arg() {
let input = given_src(
r#"
struct Foo<T, U> {
bar: T,
world: Vec<U>,
}
"#,
);
let input: DeriveInput = parse_quote! {
struct Foo<T, U> {
bar: T,
world: Vec<U>,
}
};
let generics = ident_set(vec!["T", "U", "X"]);
@ -321,7 +313,8 @@ mod tests {
#[test]
fn associated_type() {
let input = given_src("struct Foo<'a, T> where T: Iterator { peek: T::Item }");
let input: DeriveInput =
parse_quote! { struct Foo<'a, T> where T: Iterator { peek: T::Item } };
let generics = ident_set(vec!["T", "INTO"]);
let matches = input.data.uses_type_params(&BoundImpl.into(), &generics);
assert_eq!(matches.len(), 1);
@ -329,7 +322,7 @@ mod tests {
#[test]
fn box_fn_output() {
let input = given_src("struct Foo<T>(Box<Fn() -> T>);");
let input: DeriveInput = parse_quote! { struct Foo<T>(Box<Fn() -> T>); };
let generics = ident_set(vec!["T"]);
let matches = input.data.uses_type_params(&BoundImpl.into(), &generics);
assert_eq!(matches.len(), 1);
@ -338,7 +331,7 @@ mod tests {
#[test]
fn box_fn_input() {
let input = given_src("struct Foo<T>(Box<Fn(&T) -> ()>);");
let input: DeriveInput = parse_quote! { struct Foo<T>(Box<Fn(&T) -> ()>); };
let generics = ident_set(vec!["T"]);
let matches = input.data.uses_type_params(&BoundImpl.into(), &generics);
assert_eq!(matches.len(), 1);
@ -349,7 +342,8 @@ mod tests {
/// search can execute in.
#[test]
fn qself_vec() {
let input = given_src("struct Foo<T>(<Vec<T> as a::b::Trait>::AssociatedItem);");
let input: DeriveInput =
parse_quote! { struct Foo<T>(<Vec<T> as a::b::Trait>::AssociatedItem); };
let generics = ident_set(vec!["T", "U"]);
let bound_matches = input.data.uses_type_params(&BoundImpl.into(), &generics);

Просмотреть файл

@ -52,10 +52,50 @@ impl FromMeta for IdentList {
if let NestedMeta::Meta(Meta::Word(ref ident)) = *nmi {
idents.push(ident.clone());
} else {
return Err(Error::unexpected_type("non-word"));
return Err(Error::unexpected_type("non-word").with_span(nmi));
}
}
Ok(IdentList(idents))
}
}
#[cfg(test)]
mod tests {
use super::IdentList;
use proc_macro2::TokenStream;
use FromMeta;
/// parse a string as a syn::Meta instance.
fn pm(tokens: TokenStream) -> ::std::result::Result<syn::Meta, String> {
let attribute: syn::Attribute = parse_quote!(#[#tokens]);
attribute.interpret_meta().ok_or("Unable to parse".into())
}
fn fm<T: FromMeta>(tokens: TokenStream) -> T {
FromMeta::from_meta(&pm(tokens).expect("Tests should pass well-formed input"))
.expect("Tests should pass valid input")
}
#[test]
fn succeeds() {
let idents = fm::<IdentList>(quote!(ignore(Debug, Clone, Eq)));
assert_eq!(
idents.to_strings(),
vec![
String::from("Debug"),
String::from("Clone"),
String::from("Eq")
]
);
}
/// Check that the parser rejects non-word members of the list, and that the error
/// has an associated span.
#[test]
fn fails_non_word() {
let input = IdentList::from_meta(&pm(quote!(ignore(Debug, Clone = false))).unwrap());
let err = input.unwrap_err();
assert!(err.has_span());
}
}

Просмотреть файл

@ -1,4 +1,5 @@
use std::fmt;
use std::hash::{Hash, Hasher};
use proc_macro2::{Span, TokenStream};
use quote::ToTokens;
@ -9,7 +10,7 @@ use {FromMeta, Result};
/// A wrapper for an `Ident` which also keeps the value as a string.
///
/// This struct can be used to perform string comparisons and operations.
#[derive(Clone, Hash, PartialOrd, Ord)]
#[derive(Clone, PartialOrd, Ord)]
pub struct IdentString {
ident: Ident,
string: String,
@ -104,6 +105,12 @@ impl<'a> PartialEq<&'a str> for IdentString {
}
}
impl Hash for IdentString {
fn hash<H: Hasher>(&self, state: &mut H) {
self.ident.hash(state);
}
}
impl ToTokens for IdentString {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.ident.to_tokens(tokens);

Просмотреть файл

@ -10,11 +10,13 @@ mod ident_string;
mod ignored;
mod over_ride;
mod with_original;
mod spanned_value;
pub use self::ident_list::IdentList;
pub use self::ident_string::IdentString;
pub use self::ignored::Ignored;
pub use self::over_ride::Override;
pub use self::spanned_value::SpannedValue;
pub use self::with_original::WithOriginal;
/// Marker type equivalent to `Option<()>` for use in attribute parsing.

104
third_party/rust/darling_core/src/util/spanned_value.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,104 @@
use proc_macro2::Span;
use std::ops::{Deref, DerefMut};
use syn;
use syn::spanned::Spanned;
use {
FromDeriveInput, FromField, FromGenericParam, FromGenerics, FromMeta, FromTypeParam,
FromVariant, Result,
};
/// A value and an associated position in source code. The main use case for this is
/// to preserve position information to emit warnings from proc macros. You can use
/// a `SpannedValue<T>` as a field in any struct that implements or derives any of
/// `darling`'s core traits.
///
/// To access the underlying value, use the struct's `Deref` implementation.
///
/// # Defaulting
/// This type is meant to be used in conjunction with attribute-extracted options,
/// but the user may not always explicitly set those options in their source code.
/// In this case, using `Default::default()` will create an instance which points
/// to `Span::call_site()`.
#[derive(Debug, Clone)]
pub struct SpannedValue<T> {
value: T,
span: Span,
}
impl<T> SpannedValue<T> {
pub fn new(value: T, span: Span) -> Self {
SpannedValue { value, span }
}
/// Get the source code location referenced by this struct.
pub fn span(&self) -> Span {
self.span
}
}
impl<T: Default> Default for SpannedValue<T> {
fn default() -> Self {
SpannedValue::new(Default::default(), Span::call_site())
}
}
impl<T> Deref for SpannedValue<T> {
type Target = T;
fn deref(&self) -> &T {
&self.value
}
}
impl<T> DerefMut for SpannedValue<T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.value
}
}
impl<T> AsRef<T> for SpannedValue<T> {
fn as_ref(&self) -> &T {
&self.value
}
}
macro_rules! spanned {
($trayt:ident, $method:ident, $syn:path) => {
impl<T: $trayt> $trayt for SpannedValue<T> {
fn $method(value: &$syn) -> Result<Self> {
Ok(SpannedValue::new(
$trayt::$method(value).map_err(|e| e.with_span(value))?,
value.span(),
))
}
}
};
}
spanned!(FromGenericParam, from_generic_param, syn::GenericParam);
spanned!(FromGenerics, from_generics, syn::Generics);
spanned!(FromTypeParam, from_type_param, syn::TypeParam);
spanned!(FromMeta, from_meta, syn::Meta);
spanned!(FromDeriveInput, from_derive_input, syn::DeriveInput);
spanned!(FromField, from_field, syn::Field);
spanned!(FromVariant, from_variant, syn::Variant);
impl<T: Spanned> From<T> for SpannedValue<T> {
fn from(value: T) -> Self {
let span = value.span();
SpannedValue::new(value, span)
}
}
#[cfg(test)]
mod tests {
use super::*;
use proc_macro2::Span;
/// Make sure that `SpannedValue` can be seamlessly used as its underlying type.
#[test]
fn deref() {
let test = SpannedValue::new("hello", Span::call_site());
assert_eq!("hello", test.trim());
}
}

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"a062c325e8c632ab4da20f1f5918efb2b8ebdcaa45c7cc23fad00d546fa8fc46","src/lib.rs":"8343bf4500faeaf72e0cafb9e2c378be176bfe41529ba8f0d5e315336de422bf"},"package":"99c4eff4bcbeaf6a22578012ff79c95910338668278d1901e528bd34a22f575d"}
{"files":{"Cargo.toml":"7f87d565ab1cb6661d23c51bca2b37b15f0f97456cdace142b54ef39f1f17d0a","LICENSE":"8ea93490d74a5a1b1af3ff71d786271b3f1e5f0bea79ac16e02ec533cef040d6","src/lib.rs":"88141a58dc13b9001a83ca7559b6213ab44641510b6d642a3280c244ad735cec"},"package":"244e8987bd4e174385240cde20a3657f607fb0797563c28255c353b5819a07b1"}

6
third_party/rust/darling_macro/Cargo.toml поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
[package]
name = "darling_macro"
version = "0.8.1"
version = "0.8.6"
authors = ["Ted Driggs <ted.driggs@outlook.com>"]
description = "Internal support for a proc-macro library for reading attributes into structs when\nimplementing custom derives. Use https://crates.io/crates/darling in your code.\n"
license = "MIT"
@ -21,10 +21,10 @@ repository = "https://github.com/TedDriggs/darling"
[lib]
proc-macro = true
[dependencies.darling_core]
version = "=0.8.1"
version = "=0.8.6"
[dependencies.quote]
version = "0.6"
[dependencies.syn]
version = "0.15"
version = "0.15.26"

21
third_party/rust/darling_macro/LICENSE поставляемый Normal file
Просмотреть файл

@ -0,0 +1,21 @@
MIT 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.

49
third_party/rust/darling_macro/src/lib.rs поставляемый
Просмотреть файл

@ -1,72 +1,41 @@
extern crate proc_macro;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;
extern crate darling_core;
use proc_macro::TokenStream;
use darling_core::{codegen, options};
use darling_core::{derive, Error};
#[proc_macro_derive(FromMeta, attributes(darling))]
pub fn derive_from_meta(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as syn::DeriveInput);
let container = options::FromMetaOptions::new(&ast).unwrap();
let trait_impl = codegen::FromMetaImpl::from(&container);
let result = quote!(#trait_impl);
result.into()
derive::from_meta(&parse_macro_input!(input)).into()
}
#[proc_macro_derive(FromMetaItem, attributes(darling))]
pub fn derive_from_meta_item(_input: TokenStream) -> TokenStream {
panic!("darling::FromMetaItem has been replaced by darling::FromMeta");
Error::custom("darling::FromMetaItem has been replaced by darling::FromMeta")
.write_errors()
.into()
}
#[proc_macro_derive(FromDeriveInput, attributes(darling))]
pub fn derive_from_input(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as syn::DeriveInput);
let container = options::FdiOptions::new(&ast).unwrap();
let trait_impl = codegen::FromDeriveInputImpl::from(&container);
let result = quote!(#trait_impl);
result.into()
derive::from_derive_input(&parse_macro_input!(input)).into()
}
#[proc_macro_derive(FromField, attributes(darling))]
pub fn derive_field(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as syn::DeriveInput);
let fdic = options::FromFieldOptions::new(&ast).unwrap();
let trait_impl = codegen::FromFieldImpl::from(&fdic);
let result = quote!(#trait_impl);
result.into()
derive::from_field(&parse_macro_input!(input)).into()
}
#[proc_macro_derive(FromTypeParam, attributes(darling))]
pub fn derive_type_param(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as syn::DeriveInput);
let fdic = options::FromTypeParamOptions::new(&ast).unwrap();
let trait_impl = codegen::FromTypeParamImpl::from(&fdic);
let result = quote!(#trait_impl);
result.into()
derive::from_type_param(&parse_macro_input!(input)).into()
}
#[proc_macro_derive(FromVariant, attributes(darling))]
pub fn derive_variant(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as syn::DeriveInput);
let fdic = options::FromVariantOptions::new(&ast).unwrap();
let trait_impl = codegen::FromVariantImpl::from(&fdic);
let result = quote!(#trait_impl);
result.into()
derive::from_variant(&parse_macro_input!(input)).into()
}

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"f020c87cba7dd2260861239307b2cb93e16c2bed6e2ef6c9178642b1dfcc43a3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"538fd635d385b6a90ef4cc1e361aad717162a139e932a6192212cad8407aa8e1","build.rs":"7698abdd3087e0f3308916c37ade3349b6b000165186b80913013af18d36ecb6","src/lib.rs":"c5c276236d828189a5151c890a66f2b7d1c02beca98f08f2d9c01166df441eb2","src/stable.rs":"a1f29e850e5fc4c602ee1204847124e266087175695d77ec448016db910acb6b","src/strnom.rs":"807c377bdb49b8b1c67d013089b8ff33fe93ffd3fa36b6440dbb1d6fe8cd9c17","src/unstable.rs":"0b7f86862d8254104330d14837ea6ec89e7b3bf2ffe910b73629269f2bc282de","tests/marker.rs":"0227d07bbc7f2e2ad34662a6acb65668b7dc2f79141c4faa672703a04e27bea0","tests/test.rs":"427821bab498926aa56bfcea7d28c36fb24a7d63d7f59d3e7e097bcfc77fe95b"},"package":"77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"}
{"files":{"Cargo.toml":"b523856472549844b4bf20eca0473d955a7e5eeb95c70eddd31a05ac455427bb","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"89857eaaa305afe540abcf56fabae0194dfb4e7906a8098b7206acb23ed11ce8","build.rs":"36fa668f3bf309f243d0e977e8428446cc424303139c1f63410b3c2e30445aec","src/fallback.rs":"e4d1bcb1e92383a2285e6c947dd74b0e34144904948db68127faea627f5dd6ff","src/lib.rs":"896a1d212e30902ff051313808007406ca4471c27880a6ef19508f0ebb8333ee","src/strnom.rs":"60f5380106dbe568cca7abd09877e133c874fbee95d502e4830425c4613a640d","src/wrapper.rs":"0d7fe28ab2b7ee02b8eb8c5a636da364c60f6704b23e7db0a1ddd57c742f54b1","tests/marker.rs":"0227d07bbc7f2e2ad34662a6acb65668b7dc2f79141c4faa672703a04e27bea0","tests/test.rs":"166d35835355bdaa85bcf69de4dfb56ccddd8acf2e1a8cbc506782632b151674"},"package":"4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"}

5
third_party/rust/proc-macro2/Cargo.toml поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
[package]
name = "proc-macro2"
version = "0.4.24"
version = "0.4.27"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
build = "build.rs"
description = "A stable implementation of the upcoming new `proc_macro` API. Comes with an\noption, off by default, to also reimplement itself in terms of the upstream\nunstable API.\n"
@ -32,7 +32,8 @@ version = "0.6"
[features]
default = ["proc-macro"]
nightly = ["proc-macro"]
nightly = []
proc-macro = []
span-locations = []
[badges.travis-ci]
repository = "alexcrichton/proc-macro2"

66
third_party/rust/proc-macro2/README.md поставляемый
Просмотреть файл

@ -1,60 +1,76 @@
# proc-macro2
[![Build Status](https://api.travis-ci.org/alexcrichton/proc-macro2.svg?branch=master)](https://travis-ci.org/alexcrichton/proc-macro2)
[![Build Status](https://api.travis-ci.com/alexcrichton/proc-macro2.svg?branch=master)](https://travis-ci.com/alexcrichton/proc-macro2)
[![Latest Version](https://img.shields.io/crates/v/proc-macro2.svg)](https://crates.io/crates/proc-macro2)
[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/proc-macro2)
A small shim over the `proc_macro` crate in the compiler intended to multiplex
the stable interface as of 1.15.0 and the interface as of 1.30.0.
A wrapper around the procedural macro API of the compiler's `proc_macro` crate.
This library serves three purposes:
New features added in Rust 1.30.0 include:
- **Bring proc-macro-like functionality to other contexts like build.rs and
main.rs.** Types from `proc_macro` are entirely specific to procedural macros
and cannot ever exist in code outside of a procedural macro. Meanwhile
`proc_macro2` types may exist anywhere including non-macro code. By developing
foundational libraries like [syn] and [quote] against `proc_macro2` rather
than `proc_macro`, the procedural macro ecosystem becomes easily applicable to
many other use cases and we avoid reimplementing non-macro equivalents of
those libraries.
* Span information on tokens
* No need to go in/out through strings
* Structured input/output
- **Make procedural macros unit testable.** As a consequence of being specific
to procedural macros, nothing that uses `proc_macro` can be executed from a
unit test. In order for helper libraries or components of a macro to be
testable in isolation, they must be implemented using `proc_macro2`.
Libraries ported to `proc_macro2` can retain support for older compilers while
continuing to get all the nice benefits of using a 1.30.0+ compiler.
- **Provide the latest and greatest APIs across all compiler versions.**
Procedural macros were first introduced to Rust in 1.15.0 with an extremely
minimal interface. Since then, many improvements have landed to make macros
more flexible and easier to write. This library tracks the procedural macro
API of the most recent stable compiler but employs a polyfill to provide that
API consistently across any compiler since 1.15.0.
[syn]: https://github.com/dtolnay/syn
[quote]: https://github.com/dtolnay/quote
## Usage
This crate compiles on all 1.15.0+ stable compilers and usage looks like:
```toml
[dependencies]
proc-macro2 = "0.4"
```
followed by
The skeleton of a typical procedural macro typically looks like this:
```rust
extern crate proc_macro;
extern crate proc_macro2;
#[proc_macro_derive(MyDerive)]
pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input: proc_macro2::TokenStream = input.into();
let input = proc_macro2::TokenStream::from(input);
let output: proc_macro2::TokenStream = {
/* transform input */
};
output.into()
proc_macro::TokenStream::from(output)
}
```
The 1.30.0 compiler is automatically detected and its interfaces are used when
available.
If parsing with [Syn], you'll use [`parse_macro_input!`] instead to propagate
parse errors correctly back to the compiler when parsing fails.
## Unstable Features
[`parse_macro_input!`]: https://docs.rs/syn/0.15/syn/macro.parse_macro_input.html
`proc-macro2` supports exporting some methods from `proc_macro` which are
currently highly unstable, and are not stabilized in the first pass of
`proc_macro` stabilizations. These features are not exported by default. Minor
versions of `proc-macro2` may make breaking changes to them at any time.
## Unstable features
To enable these features, the `procmacro2_semver_exempt` config flag must be
passed to rustc.
The default feature set of proc-macro2 tracks the most recent stable compiler
API. Functionality in `proc_macro` that is not yet stable is not exposed by
proc-macro2 by default.
To opt into the additional APIs available in the most recent nightly compiler,
the `procmacro2_semver_exempt` config flag must be passed to rustc. As usual, we
will polyfill those nightly-only APIs all the way back to Rust 1.15.0. As these
are unstable APIs that track the nightly compiler, minor versions of proc-macro2
may make breaking changes to them at any time.
```
RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build
@ -64,6 +80,8 @@ Note that this must not only be done for your crate, but for any crate that
depends on your crate. This infectious nature is intentional, as it serves as a
reminder that you are outside of the normal semver guarantees.
Semver exempt methods are marked as such in the proc-macro2 documentation.
# License
This project is licensed under either of

92
third_party/rust/proc-macro2/build.rs поставляемый
Просмотреть файл

@ -1,3 +1,43 @@
// rustc-cfg emitted by the build script:
//
// "u128"
// Include u128 and i128 constructors for proc_macro2::Literal. Enabled on
// any compiler 1.26+.
//
// "use_proc_macro"
// Link to extern crate proc_macro. Available on any compiler and any target
// except wasm32. Requires "proc-macro" Cargo cfg to be enabled (default is
// enabled). On wasm32 we never link to proc_macro even if "proc-macro" cfg
// is enabled.
//
// "wrap_proc_macro"
// Wrap types from libproc_macro rather than polyfilling the whole API.
// Enabled on rustc 1.29+ as long as procmacro2_semver_exempt is not set,
// because we can't emulate the unstable API without emulating everything
// else. Also enabled unconditionally on nightly, in which case the
// procmacro2_semver_exempt surface area is implemented by using the
// nightly-only proc_macro API.
//
// "slow_extend"
// Fallback when `impl Extend for TokenStream` is not available. These impls
// were added one version later than the rest of the proc_macro token API.
// Enabled on rustc 1.29 only.
//
// "nightly"
// Enable the Span::unwrap method. This is to support proc_macro_span and
// proc_macro_diagnostic use on the nightly channel without requiring the
// semver exemption opt-in. Enabled when building with nightly.
//
// "super_unstable"
// Implement the semver exempt API in terms of the nightly-only proc_macro
// API. Enabled when using procmacro2_semver_exempt on a nightly compiler.
//
// "span_locations"
// Provide methods Span::start and Span::end which give the line/column
// location of a token. Enabled by procmacro2_semver_exempt or the
// "span-locations" Cargo cfg. This is behind a cfg because tracking
// location inside spans is a performance hit.
use std::env;
use std::process::Command;
use std::str;
@ -7,34 +47,47 @@ fn main() {
let target = env::var("TARGET").unwrap();
let minor = match rustc_minor_version() {
Some(n) => n,
let version = match rustc_version() {
Some(version) => version,
None => return,
};
if minor >= 26 {
if version.minor >= 26 {
println!("cargo:rustc-cfg=u128");
}
let semver_exempt = cfg!(procmacro2_semver_exempt);
if semver_exempt {
// https://github.com/alexcrichton/proc-macro2/issues/147
println!("cargo:rustc-cfg=procmacro2_semver_exempt");
}
if semver_exempt || cfg!(feature = "span-locations") {
println!("cargo:rustc-cfg=span_locations");
}
if !enable_use_proc_macro(&target) {
return;
}
println!("cargo:rustc-cfg=use_proc_macro");
// Rust 1.29 stabilized the necessary APIs in the `proc_macro` crate
if (minor >= 29 && !cfg!(procmacro2_semver_exempt)) || cfg!(feature = "nightly") {
if version.nightly || version.minor >= 29 && !semver_exempt {
println!("cargo:rustc-cfg=wrap_proc_macro");
if cfg!(procmacro2_semver_exempt) {
println!("cargo:rustc-cfg=super_unstable");
// https://github.com/alexcrichton/proc-macro2/issues/147
println!("cargo:rustc-cfg=procmacro2_semver_exempt");
}
}
if minor == 29 {
if version.minor == 29 {
println!("cargo:rustc-cfg=slow_extend");
}
if version.nightly {
println!("cargo:rustc-cfg=nightly");
}
if semver_exempt && version.nightly {
println!("cargo:rustc-cfg=super_unstable");
}
}
fn enable_use_proc_macro(target: &str) -> bool {
@ -47,7 +100,12 @@ fn enable_use_proc_macro(target: &str) -> bool {
cfg!(feature = "proc-macro")
}
fn rustc_minor_version() -> Option<u32> {
struct RustcVersion {
minor: u32,
nightly: bool,
}
fn rustc_version() -> Option<RustcVersion> {
macro_rules! otry {
($e:expr) => {
match $e {
@ -56,12 +114,20 @@ fn rustc_minor_version() -> Option<u32> {
}
};
}
let rustc = otry!(env::var_os("RUSTC"));
let output = otry!(Command::new(rustc).arg("--version").output().ok());
let version = otry!(str::from_utf8(&output.stdout).ok());
let nightly = version.contains("nightly");
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
otry!(pieces.next()).parse().ok()
let minor = otry!(pieces.next());
let minor = otry!(minor.parse().ok());
Some(RustcVersion {
minor: minor,
nightly: nightly,
})
}

Просмотреть файл

@ -1,6 +1,4 @@
#![cfg_attr(not(procmacro2_semver_exempt), allow(dead_code))]
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
use std::cell::RefCell;
#[cfg(procmacro2_semver_exempt)]
use std::cmp;
@ -35,7 +33,7 @@ impl TokenStream {
}
}
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
fn get_cursor(src: &str) -> Cursor {
// Create a dummy file & add it to the codemap
CODEMAP.with(|cm| {
@ -49,7 +47,7 @@ fn get_cursor(src: &str) -> Cursor {
})
}
#[cfg(not(procmacro2_semver_exempt))]
#[cfg(not(span_locations))]
fn get_cursor(src: &str) -> Cursor {
Cursor { rest: src }
}
@ -225,27 +223,41 @@ pub struct LineColumn {
pub column: usize,
}
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
thread_local! {
static CODEMAP: RefCell<Codemap> = RefCell::new(Codemap {
// NOTE: We start with a single dummy file which all call_site() and
// def_site() spans reference.
files: vec![FileInfo {
name: "<unspecified>".to_owned(),
span: Span { lo: 0, hi: 0 },
lines: vec![0],
files: vec![{
#[cfg(procmacro2_semver_exempt)]
{
FileInfo {
name: "<unspecified>".to_owned(),
span: Span { lo: 0, hi: 0 },
lines: vec![0],
}
}
#[cfg(not(procmacro2_semver_exempt))]
{
FileInfo {
span: Span { lo: 0, hi: 0 },
lines: vec![0],
}
}
}],
});
}
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
struct FileInfo {
#[cfg(procmacro2_semver_exempt)]
name: String,
span: Span,
lines: Vec<usize>,
}
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
impl FileInfo {
fn offset_line_column(&self, offset: usize) -> LineColumn {
assert!(self.span_within(Span {
@ -271,7 +283,7 @@ impl FileInfo {
}
/// Computesthe offsets of each line in the given source string.
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
fn lines_offsets(s: &str) -> Vec<usize> {
let mut lines = vec![0];
let mut prev = 0;
@ -282,12 +294,12 @@ fn lines_offsets(s: &str) -> Vec<usize> {
lines
}
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
struct Codemap {
files: Vec<FileInfo>,
}
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
impl Codemap {
fn next_start_pos(&self) -> u32 {
// Add 1 so there's always space between files.
@ -306,12 +318,20 @@ impl Codemap {
hi: lo + (src.len() as u32),
};
#[cfg(procmacro2_semver_exempt)]
self.files.push(FileInfo {
name: name.to_owned(),
span: span,
lines: lines,
});
#[cfg(not(procmacro2_semver_exempt))]
self.files.push(FileInfo {
span: span,
lines: lines,
});
let _ = name;
span
}
@ -327,27 +347,29 @@ impl Codemap {
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Span {
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
lo: u32,
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
hi: u32,
}
impl Span {
#[cfg(not(procmacro2_semver_exempt))]
#[cfg(not(span_locations))]
pub fn call_site() -> Span {
Span {}
}
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
pub fn call_site() -> Span {
Span { lo: 0, hi: 0 }
}
#[cfg(procmacro2_semver_exempt)]
pub fn def_site() -> Span {
Span::call_site()
}
#[cfg(procmacro2_semver_exempt)]
pub fn resolved_at(&self, _other: Span) -> Span {
// Stable spans consist only of line/column information, so
// `resolved_at` and `located_at` only select which span the
@ -355,6 +377,7 @@ impl Span {
*self
}
#[cfg(procmacro2_semver_exempt)]
pub fn located_at(&self, other: Span) -> Span {
other
}
@ -370,7 +393,7 @@ impl Span {
})
}
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
pub fn start(&self) -> LineColumn {
CODEMAP.with(|cm| {
let cm = cm.borrow();
@ -379,7 +402,7 @@ impl Span {
})
}
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
pub fn end(&self) -> LineColumn {
CODEMAP.with(|cm| {
let cm = cm.borrow();
@ -414,6 +437,12 @@ impl fmt::Debug for Span {
}
}
pub fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
if cfg!(procmacro2_semver_exempt) {
debug.field("span", &span);
}
}
#[derive(Clone)]
pub struct Group {
delimiter: Delimiter,
@ -442,10 +471,12 @@ impl Group {
self.span
}
#[cfg(procmacro2_semver_exempt)]
pub fn span_open(&self) -> Span {
self.span
}
#[cfg(procmacro2_semver_exempt)]
pub fn span_close(&self) -> Span {
self.span
}
@ -782,16 +813,16 @@ fn token_stream(mut input: Cursor) -> PResult<TokenStream> {
Ok((input, TokenStream { inner: trees }))
}
#[cfg(not(procmacro2_semver_exempt))]
#[cfg(not(span_locations))]
fn spanned<'a, T>(
input: Cursor<'a>,
f: fn(Cursor<'a>) -> PResult<'a, T>,
) -> PResult<'a, (T, ::Span)> {
let (a, b) = f(skip_whitespace(input))?;
Ok((a, ((b, ::Span::_new_stable(Span {})))))
Ok((a, ((b, ::Span::_new_stable(Span::call_site())))))
}
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
fn spanned<'a, T>(
input: Cursor<'a>,
f: fn(Cursor<'a>) -> PResult<'a, T>,

171
third_party/rust/proc-macro2/src/lib.rs поставляемый
Просмотреть файл

@ -1,35 +1,72 @@
//! A "shim crate" intended to multiplex the [`proc_macro`] API on to stable
//! Rust.
//! A wrapper around the procedural macro API of the compiler's [`proc_macro`]
//! crate. This library serves three purposes:
//!
//! Procedural macros in Rust operate over the upstream
//! [`proc_macro::TokenStream`][ts] type. This type currently is quite
//! conservative and exposed no internal implementation details. Nightly
//! compilers, however, contain a much richer interface. This richer interface
//! allows fine-grained inspection of the token stream which avoids
//! stringification/re-lexing and also preserves span information.
//! [`proc_macro`]: https://doc.rust-lang.org/proc_macro/
//!
//! The upcoming APIs added to [`proc_macro`] upstream are the foundation for
//! productive procedural macros in the ecosystem. To help prepare the ecosystem
//! for using them this crate serves to both compile on stable and nightly and
//! mirrors the API-to-be. The intention is that procedural macros which switch
//! to use this crate will be trivially able to switch to the upstream
//! `proc_macro` crate once its API stabilizes.
//! - **Bring proc-macro-like functionality to other contexts like build.rs and
//! main.rs.** Types from `proc_macro` are entirely specific to procedural
//! macros and cannot ever exist in code outside of a procedural macro.
//! Meanwhile `proc_macro2` types may exist anywhere including non-macro code.
//! By developing foundational libraries like [syn] and [quote] against
//! `proc_macro2` rather than `proc_macro`, the procedural macro ecosystem
//! becomes easily applicable to many other use cases and we avoid
//! reimplementing non-macro equivalents of those libraries.
//!
//! In the meantime this crate also has a `nightly` Cargo feature which
//! enables it to reimplement itself with the unstable API of [`proc_macro`].
//! This'll allow immediate usage of the beneficial upstream API, particularly
//! around preserving span information.
//! - **Make procedural macros unit testable.** As a consequence of being
//! specific to procedural macros, nothing that uses `proc_macro` can be
//! executed from a unit test. In order for helper libraries or components of
//! a macro to be testable in isolation, they must be implemented using
//! `proc_macro2`.
//!
//! # Unstable Features
//! - **Provide the latest and greatest APIs across all compiler versions.**
//! Procedural macros were first introduced to Rust in 1.15.0 with an
//! extremely minimal interface. Since then, many improvements have landed to
//! make macros more flexible and easier to write. This library tracks the
//! procedural macro API of the most recent stable compiler but employs a
//! polyfill to provide that API consistently across any compiler since
//! 1.15.0.
//!
//! `proc-macro2` supports exporting some methods from `proc_macro` which are
//! currently highly unstable, and may not be stabilized in the first pass of
//! `proc_macro` stabilizations. These features are not exported by default.
//! Minor versions of `proc-macro2` may make breaking changes to them at any
//! time.
//! [syn]: https://github.com/dtolnay/syn
//! [quote]: https://github.com/dtolnay/quote
//!
//! To enable these features, the `procmacro2_semver_exempt` config flag must be
//! passed to rustc.
//! # Usage
//!
//! The skeleton of a typical procedural macro typically looks like this:
//!
//! ```edition2018
//! extern crate proc_macro;
//!
//! # const IGNORE: &str = stringify! {
//! #[proc_macro_derive(MyDerive)]
//! # };
//! pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
//! let input = proc_macro2::TokenStream::from(input);
//!
//! let output: proc_macro2::TokenStream = {
//! /* transform input */
//! # input
//! };
//!
//! proc_macro::TokenStream::from(output)
//! }
//! ```
//!
//! If parsing with [Syn], you'll use [`parse_macro_input!`] instead to
//! propagate parse errors correctly back to the compiler when parsing fails.
//!
//! [`parse_macro_input!`]: https://docs.rs/syn/0.15/syn/macro.parse_macro_input.html
//!
//! # Unstable features
//!
//! The default feature set of proc-macro2 tracks the most recent stable
//! compiler API. Functionality in `proc_macro` that is not yet stable is not
//! exposed by proc-macro2 by default.
//!
//! To opt into the additional APIs available in the most recent nightly
//! compiler, the `procmacro2_semver_exempt` config flag must be passed to
//! rustc. As usual, we will polyfill those nightly-only APIs all the way back
//! to Rust 1.15.0. As these are unstable APIs that track the nightly compiler,
//! minor versions of proc-macro2 may make breaking changes to them at any time.
//!
//! ```sh
//! RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build
@ -39,15 +76,12 @@
//! depends on your crate. This infectious nature is intentional, as it serves
//! as a reminder that you are outside of the normal semver guarantees.
//!
//! [`proc_macro`]: https://doc.rust-lang.org/proc_macro/
//! [ts]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html
//! Semver exempt methods are marked as such in the proc-macro2 documentation.
// Proc-macro2 types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/proc-macro2/0.4.24")]
#![cfg_attr(
super_unstable,
feature(proc_macro_raw_ident, proc_macro_span, proc_macro_def_site)
)]
#![doc(html_root_url = "https://docs.rs/proc-macro2/0.4.27")]
#![cfg_attr(nightly, feature(proc_macro_span))]
#![cfg_attr(super_unstable, feature(proc_macro_raw_ident, proc_macro_def_site))]
#[cfg(use_proc_macro)]
extern crate proc_macro;
@ -65,11 +99,11 @@ use std::str::FromStr;
#[macro_use]
mod strnom;
mod stable;
mod fallback;
#[cfg(not(wrap_proc_macro))]
use stable as imp;
#[path = "unstable.rs"]
use fallback as imp;
#[path = "wrapper.rs"]
#[cfg(wrap_proc_macro)]
mod imp;
@ -100,7 +134,7 @@ impl TokenStream {
}
}
fn _new_stable(inner: stable::TokenStream) -> TokenStream {
fn _new_stable(inner: fallback::TokenStream) -> TokenStream {
TokenStream {
inner: inner.into(),
_marker: marker::PhantomData,
@ -266,7 +300,7 @@ impl fmt::Debug for SourceFile {
/// A line-column pair representing the start or end of a `Span`.
///
/// This type is semver exempt and not exposed by default.
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
pub struct LineColumn {
/// The 1-indexed line in the source file on which the span starts or ends
/// (inclusive).
@ -291,7 +325,7 @@ impl Span {
}
}
fn _new_stable(inner: stable::Span) -> Span {
fn _new_stable(inner: fallback::Span) -> Span {
Span {
inner: inner.into(),
_marker: marker::PhantomData,
@ -333,11 +367,26 @@ impl Span {
Span::_new(self.inner.located_at(other.inner))
}
/// This method is only available when the `"nightly"` feature is enabled.
/// Convert `proc_macro2::Span` to `proc_macro::Span`.
///
/// This method is available when building with a nightly compiler, or when
/// building with rustc 1.29+ *without* semver exempt features.
///
/// # Panics
///
/// Panics if called from outside of a procedural macro. Unlike
/// `proc_macro2::Span`, the `proc_macro::Span` type can only exist within
/// the context of a procedural macro invocation.
#[cfg(wrap_proc_macro)]
pub fn unwrap(self) -> proc_macro::Span {
self.inner.unwrap()
}
// Soft deprecated. Please use Span::unwrap.
#[cfg(wrap_proc_macro)]
#[doc(hidden)]
#[cfg(any(feature = "nightly", super_unstable))]
pub fn unstable(self) -> proc_macro::Span {
self.inner.unstable()
self.unwrap()
}
/// The original source file into which this span points.
@ -350,8 +399,8 @@ impl Span {
/// Get the starting line/column in the source file for this span.
///
/// This method is semver exempt and not exposed by default.
#[cfg(procmacro2_semver_exempt)]
/// This method requires the `"span-locations"` feature to be enabled.
#[cfg(span_locations)]
pub fn start(&self) -> LineColumn {
let imp::LineColumn { line, column } = self.inner.start();
LineColumn {
@ -362,8 +411,8 @@ impl Span {
/// Get the ending line/column in the source file for this span.
///
/// This method is semver exempt and not exposed by default.
#[cfg(procmacro2_semver_exempt)]
/// This method requires the `"span-locations"` feature to be enabled.
#[cfg(span_locations)]
pub fn end(&self) -> LineColumn {
let imp::LineColumn { line, column } = self.inner.end();
LineColumn {
@ -487,8 +536,7 @@ impl fmt::Debug for TokenTree {
TokenTree::Ident(ref t) => {
let mut debug = f.debug_struct("Ident");
debug.field("sym", &format_args!("{}", t));
#[cfg(any(feature = "nightly", procmacro2_semver_exempt))]
debug.field("span", &t.span());
imp::debug_span_field_if_nontrivial(&mut debug, t.span().inner);
debug.finish()
}
TokenTree::Punct(ref t) => t.fmt(f),
@ -527,12 +575,10 @@ pub enum Delimiter {
impl Group {
fn _new(inner: imp::Group) -> Self {
Group {
inner: inner,
}
Group { inner: inner }
}
fn _new_stable(inner: stable::Group) -> Self {
fn _new_stable(inner: fallback::Group) -> Self {
Group {
inner: inner.into(),
}
@ -699,8 +745,7 @@ impl fmt::Debug for Punct {
let mut debug = fmt.debug_struct("Punct");
debug.field("op", &self.op);
debug.field("spacing", &self.spacing);
#[cfg(procmacro2_semver_exempt)]
debug.field("span", &self.span);
imp::debug_span_field_if_nontrivial(&mut debug, self.span.inner);
debug.finish()
}
}
@ -727,9 +772,7 @@ impl fmt::Debug for Punct {
/// A span must be provided explicitly which governs the name resolution
/// behavior of the resulting identifier.
///
/// ```rust
/// extern crate proc_macro2;
///
/// ```edition2018
/// use proc_macro2::{Ident, Span};
///
/// fn main() {
@ -741,13 +784,9 @@ impl fmt::Debug for Punct {
///
/// An ident can be interpolated into a token stream using the `quote!` macro.
///
/// ```rust
/// #[macro_use]
/// extern crate quote;
///
/// extern crate proc_macro2;
///
/// ```edition2018
/// use proc_macro2::{Ident, Span};
/// use quote::quote;
///
/// fn main() {
/// let ident = Ident::new("demo", Span::call_site());
@ -764,9 +803,7 @@ impl fmt::Debug for Punct {
/// A string representation of the ident is available through the `to_string()`
/// method.
///
/// ```rust
/// # extern crate proc_macro2;
/// #
/// ```edition2018
/// # use proc_macro2::{Ident, Span};
/// #
/// # let ident = Ident::new("another_identifier", Span::call_site());
@ -954,7 +991,7 @@ impl Literal {
}
}
fn _new_stable(inner: stable::Literal) -> Literal {
fn _new_stable(inner: fallback::Literal) -> Literal {
Literal {
inner: inner.into(),
_marker: marker::PhantomData,

8
third_party/rust/proc-macro2/src/strnom.rs поставляемый
Просмотреть файл

@ -4,23 +4,23 @@ use std::str::{Bytes, CharIndices, Chars};
use unicode_xid::UnicodeXID;
use stable::LexError;
use fallback::LexError;
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Cursor<'a> {
pub rest: &'a str,
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
pub off: u32,
}
impl<'a> Cursor<'a> {
#[cfg(not(procmacro2_semver_exempt))]
#[cfg(not(span_locations))]
pub fn advance(&self, amt: usize) -> Cursor<'a> {
Cursor {
rest: &self.rest[amt..],
}
}
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
pub fn advance(&self, amt: usize) -> Cursor<'a> {
Cursor {
rest: &self.rest[amt..],

Просмотреть файл

@ -1,5 +1,3 @@
#![cfg_attr(not(super_unstable), allow(dead_code))]
use std::fmt;
use std::iter;
use std::panic::{self, PanicInfo};
@ -7,20 +5,20 @@ use std::panic::{self, PanicInfo};
use std::path::PathBuf;
use std::str::FromStr;
use fallback;
use proc_macro;
use stable;
use {Delimiter, Punct, Spacing, TokenTree};
#[derive(Clone)]
pub enum TokenStream {
Nightly(proc_macro::TokenStream),
Stable(stable::TokenStream),
Compiler(proc_macro::TokenStream),
Fallback(fallback::TokenStream),
}
pub enum LexError {
Nightly(proc_macro::LexError),
Stable(stable::LexError),
Compiler(proc_macro::LexError),
Fallback(fallback::LexError),
}
fn nightly_works() -> bool {
@ -87,30 +85,30 @@ fn mismatch() -> ! {
impl TokenStream {
pub fn new() -> TokenStream {
if nightly_works() {
TokenStream::Nightly(proc_macro::TokenStream::new())
TokenStream::Compiler(proc_macro::TokenStream::new())
} else {
TokenStream::Stable(stable::TokenStream::new())
TokenStream::Fallback(fallback::TokenStream::new())
}
}
pub fn is_empty(&self) -> bool {
match self {
TokenStream::Nightly(tts) => tts.is_empty(),
TokenStream::Stable(tts) => tts.is_empty(),
TokenStream::Compiler(tts) => tts.is_empty(),
TokenStream::Fallback(tts) => tts.is_empty(),
}
}
fn unwrap_nightly(self) -> proc_macro::TokenStream {
match self {
TokenStream::Nightly(s) => s,
TokenStream::Stable(_) => mismatch(),
TokenStream::Compiler(s) => s,
TokenStream::Fallback(_) => mismatch(),
}
}
fn unwrap_stable(self) -> stable::TokenStream {
fn unwrap_stable(self) -> fallback::TokenStream {
match self {
TokenStream::Nightly(_) => mismatch(),
TokenStream::Stable(s) => s,
TokenStream::Compiler(_) => mismatch(),
TokenStream::Fallback(s) => s,
}
}
}
@ -120,9 +118,9 @@ impl FromStr for TokenStream {
fn from_str(src: &str) -> Result<TokenStream, LexError> {
if nightly_works() {
Ok(TokenStream::Nightly(src.parse()?))
Ok(TokenStream::Compiler(src.parse()?))
} else {
Ok(TokenStream::Stable(src.parse()?))
Ok(TokenStream::Fallback(src.parse()?))
}
}
}
@ -130,37 +128,37 @@ impl FromStr for TokenStream {
impl fmt::Display for TokenStream {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
TokenStream::Nightly(tts) => tts.fmt(f),
TokenStream::Stable(tts) => tts.fmt(f),
TokenStream::Compiler(tts) => tts.fmt(f),
TokenStream::Fallback(tts) => tts.fmt(f),
}
}
}
impl From<proc_macro::TokenStream> for TokenStream {
fn from(inner: proc_macro::TokenStream) -> TokenStream {
TokenStream::Nightly(inner)
TokenStream::Compiler(inner)
}
}
impl From<TokenStream> for proc_macro::TokenStream {
fn from(inner: TokenStream) -> proc_macro::TokenStream {
match inner {
TokenStream::Nightly(inner) => inner,
TokenStream::Stable(inner) => inner.to_string().parse().unwrap(),
TokenStream::Compiler(inner) => inner,
TokenStream::Fallback(inner) => inner.to_string().parse().unwrap(),
}
}
}
impl From<stable::TokenStream> for TokenStream {
fn from(inner: stable::TokenStream) -> TokenStream {
TokenStream::Stable(inner)
impl From<fallback::TokenStream> for TokenStream {
fn from(inner: fallback::TokenStream) -> TokenStream {
TokenStream::Fallback(inner)
}
}
impl From<TokenTree> for TokenStream {
fn from(token: TokenTree) -> TokenStream {
if !nightly_works() {
return TokenStream::Stable(token.into());
return TokenStream::Fallback(token.into());
}
let tt: proc_macro::TokenTree = match token {
TokenTree::Group(tt) => tt.inner.unwrap_nightly().into(),
@ -176,7 +174,7 @@ impl From<TokenTree> for TokenStream {
TokenTree::Ident(tt) => tt.inner.unwrap_nightly().into(),
TokenTree::Literal(tt) => tt.inner.unwrap_nightly().into(),
};
TokenStream::Nightly(tt.into())
TokenStream::Compiler(tt.into())
}
}
@ -187,12 +185,12 @@ impl iter::FromIterator<TokenTree> for TokenStream {
.into_iter()
.map(TokenStream::from)
.flat_map(|t| match t {
TokenStream::Nightly(s) => s,
TokenStream::Stable(_) => mismatch(),
TokenStream::Compiler(s) => s,
TokenStream::Fallback(_) => mismatch(),
});
TokenStream::Nightly(trees.collect())
TokenStream::Compiler(trees.collect())
} else {
TokenStream::Stable(trees.into_iter().collect())
TokenStream::Fallback(trees.into_iter().collect())
}
}
}
@ -202,36 +200,31 @@ impl iter::FromIterator<TokenStream> for TokenStream {
let mut streams = streams.into_iter();
match streams.next() {
#[cfg(slow_extend)]
Some(TokenStream::Nightly(first)) => {
let stream = iter::once(first).chain(streams.map(|s| {
match s {
TokenStream::Nightly(s) => s,
TokenStream::Stable(_) => mismatch(),
}
})).collect();
TokenStream::Nightly(stream)
Some(TokenStream::Compiler(first)) => {
let stream = iter::once(first)
.chain(streams.map(|s| match s {
TokenStream::Compiler(s) => s,
TokenStream::Fallback(_) => mismatch(),
}))
.collect();
TokenStream::Compiler(stream)
}
#[cfg(not(slow_extend))]
Some(TokenStream::Nightly(mut first)) => {
first.extend(streams.map(|s| {
match s {
TokenStream::Nightly(s) => s,
TokenStream::Stable(_) => mismatch(),
}
Some(TokenStream::Compiler(mut first)) => {
first.extend(streams.map(|s| match s {
TokenStream::Compiler(s) => s,
TokenStream::Fallback(_) => mismatch(),
}));
TokenStream::Nightly(first)
TokenStream::Compiler(first)
}
Some(TokenStream::Stable(mut first)) => {
first.extend(streams.map(|s| {
match s {
TokenStream::Stable(s) => s,
TokenStream::Nightly(_) => mismatch(),
}
Some(TokenStream::Fallback(mut first)) => {
first.extend(streams.map(|s| match s {
TokenStream::Fallback(s) => s,
TokenStream::Compiler(_) => mismatch(),
}));
TokenStream::Stable(first)
TokenStream::Fallback(first)
}
None => TokenStream::new(),
}
}
}
@ -239,7 +232,7 @@ impl iter::FromIterator<TokenStream> for TokenStream {
impl Extend<TokenTree> for TokenStream {
fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) {
match self {
TokenStream::Nightly(tts) => {
TokenStream::Compiler(tts) => {
#[cfg(not(slow_extend))]
{
tts.extend(
@ -250,21 +243,19 @@ impl Extend<TokenTree> for TokenStream {
}
#[cfg(slow_extend)]
{
*tts = tts
.clone()
.into_iter()
.chain(
streams
.into_iter()
.map(TokenStream::from)
.flat_map(|t| match t {
TokenStream::Nightly(tts) => tts.into_iter(),
*tts =
tts.clone()
.into_iter()
.chain(streams.into_iter().map(TokenStream::from).flat_map(
|t| match t {
TokenStream::Compiler(tts) => tts.into_iter(),
_ => mismatch(),
}),
).collect();
},
))
.collect();
}
}
TokenStream::Stable(tts) => tts.extend(streams),
TokenStream::Fallback(tts) => tts.extend(streams),
}
}
}
@ -272,7 +263,7 @@ impl Extend<TokenTree> for TokenStream {
impl Extend<TokenStream> for TokenStream {
fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
match self {
TokenStream::Nightly(tts) => {
TokenStream::Compiler(tts) => {
#[cfg(not(slow_extend))]
{
tts.extend(streams.into_iter().map(|stream| stream.unwrap_nightly()));
@ -282,17 +273,14 @@ impl Extend<TokenStream> for TokenStream {
*tts = tts
.clone()
.into_iter()
.chain(
streams
.into_iter()
.flat_map(|t| match t {
TokenStream::Nightly(tts) => tts.into_iter(),
_ => mismatch(),
}),
).collect();
.chain(streams.into_iter().flat_map(|t| match t {
TokenStream::Compiler(tts) => tts.into_iter(),
_ => mismatch(),
}))
.collect();
}
}
TokenStream::Stable(tts) => {
TokenStream::Fallback(tts) => {
tts.extend(streams.into_iter().map(|stream| stream.unwrap_stable()))
}
}
@ -302,36 +290,36 @@ impl Extend<TokenStream> for TokenStream {
impl fmt::Debug for TokenStream {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
TokenStream::Nightly(tts) => tts.fmt(f),
TokenStream::Stable(tts) => tts.fmt(f),
TokenStream::Compiler(tts) => tts.fmt(f),
TokenStream::Fallback(tts) => tts.fmt(f),
}
}
}
impl From<proc_macro::LexError> for LexError {
fn from(e: proc_macro::LexError) -> LexError {
LexError::Nightly(e)
LexError::Compiler(e)
}
}
impl From<stable::LexError> for LexError {
fn from(e: stable::LexError) -> LexError {
LexError::Stable(e)
impl From<fallback::LexError> for LexError {
fn from(e: fallback::LexError) -> LexError {
LexError::Fallback(e)
}
}
impl fmt::Debug for LexError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
LexError::Nightly(e) => e.fmt(f),
LexError::Stable(e) => e.fmt(f),
LexError::Compiler(e) => e.fmt(f),
LexError::Fallback(e) => e.fmt(f),
}
}
}
pub enum TokenTreeIter {
Nightly(proc_macro::token_stream::IntoIter),
Stable(stable::TokenTreeIter),
Compiler(proc_macro::token_stream::IntoIter),
Fallback(fallback::TokenTreeIter),
}
impl IntoIterator for TokenStream {
@ -340,8 +328,8 @@ impl IntoIterator for TokenStream {
fn into_iter(self) -> TokenTreeIter {
match self {
TokenStream::Nightly(tts) => TokenTreeIter::Nightly(tts.into_iter()),
TokenStream::Stable(tts) => TokenTreeIter::Stable(tts.into_iter()),
TokenStream::Compiler(tts) => TokenTreeIter::Compiler(tts.into_iter()),
TokenStream::Fallback(tts) => TokenTreeIter::Fallback(tts.into_iter()),
}
}
}
@ -351,29 +339,29 @@ impl Iterator for TokenTreeIter {
fn next(&mut self) -> Option<TokenTree> {
let token = match self {
TokenTreeIter::Nightly(iter) => iter.next()?,
TokenTreeIter::Stable(iter) => return iter.next(),
TokenTreeIter::Compiler(iter) => iter.next()?,
TokenTreeIter::Fallback(iter) => return iter.next(),
};
Some(match token {
proc_macro::TokenTree::Group(tt) => ::Group::_new(Group::Nightly(tt)).into(),
proc_macro::TokenTree::Group(tt) => ::Group::_new(Group::Compiler(tt)).into(),
proc_macro::TokenTree::Punct(tt) => {
let spacing = match tt.spacing() {
proc_macro::Spacing::Joint => Spacing::Joint,
proc_macro::Spacing::Alone => Spacing::Alone,
};
let mut o = Punct::new(tt.as_char(), spacing);
o.set_span(::Span::_new(Span::Nightly(tt.span())));
o.set_span(::Span::_new(Span::Compiler(tt.span())));
o.into()
}
proc_macro::TokenTree::Ident(s) => ::Ident::_new(Ident::Nightly(s)).into(),
proc_macro::TokenTree::Literal(l) => ::Literal::_new(Literal::Nightly(l)).into(),
proc_macro::TokenTree::Ident(s) => ::Ident::_new(Ident::Compiler(s)).into(),
proc_macro::TokenTree::Literal(l) => ::Literal::_new(Literal::Compiler(l)).into(),
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
TokenTreeIter::Nightly(tts) => tts.size_hint(),
TokenTreeIter::Stable(tts) => tts.size_hint(),
TokenTreeIter::Compiler(tts) => tts.size_hint(),
TokenTreeIter::Fallback(tts) => tts.size_hint(),
}
}
}
@ -387,28 +375,28 @@ impl fmt::Debug for TokenTreeIter {
#[derive(Clone, PartialEq, Eq)]
#[cfg(super_unstable)]
pub enum SourceFile {
Nightly(proc_macro::SourceFile),
Stable(stable::SourceFile),
Compiler(proc_macro::SourceFile),
Fallback(fallback::SourceFile),
}
#[cfg(super_unstable)]
impl SourceFile {
fn nightly(sf: proc_macro::SourceFile) -> Self {
SourceFile::Nightly(sf)
SourceFile::Compiler(sf)
}
/// Get the path to this source file as a string.
pub fn path(&self) -> PathBuf {
match self {
SourceFile::Nightly(a) => a.path(),
SourceFile::Stable(a) => a.path(),
SourceFile::Compiler(a) => a.path(),
SourceFile::Fallback(a) => a.path(),
}
}
pub fn is_real(&self) -> bool {
match self {
SourceFile::Nightly(a) => a.is_real(),
SourceFile::Stable(a) => a.is_real(),
SourceFile::Compiler(a) => a.is_real(),
SourceFile::Fallback(a) => a.is_real(),
}
}
}
@ -417,12 +405,13 @@ impl SourceFile {
impl fmt::Debug for SourceFile {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
SourceFile::Nightly(a) => a.fmt(f),
SourceFile::Stable(a) => a.fmt(f),
SourceFile::Compiler(a) => a.fmt(f),
SourceFile::Fallback(a) => a.fmt(f),
}
}
}
#[cfg(any(super_unstable, feature = "span-locations"))]
pub struct LineColumn {
pub line: usize,
pub column: usize,
@ -430,33 +419,33 @@ pub struct LineColumn {
#[derive(Copy, Clone)]
pub enum Span {
Nightly(proc_macro::Span),
Stable(stable::Span),
Compiler(proc_macro::Span),
Fallback(fallback::Span),
}
impl Span {
pub fn call_site() -> Span {
if nightly_works() {
Span::Nightly(proc_macro::Span::call_site())
Span::Compiler(proc_macro::Span::call_site())
} else {
Span::Stable(stable::Span::call_site())
Span::Fallback(fallback::Span::call_site())
}
}
#[cfg(super_unstable)]
pub fn def_site() -> Span {
if nightly_works() {
Span::Nightly(proc_macro::Span::def_site())
Span::Compiler(proc_macro::Span::def_site())
} else {
Span::Stable(stable::Span::def_site())
Span::Fallback(fallback::Span::def_site())
}
}
#[cfg(super_unstable)]
pub fn resolved_at(&self, other: Span) -> Span {
match (self, other) {
(Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.resolved_at(b)),
(Span::Stable(a), Span::Stable(b)) => Span::Stable(a.resolved_at(b)),
(Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)),
(Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)),
_ => mismatch(),
}
}
@ -464,50 +453,56 @@ impl Span {
#[cfg(super_unstable)]
pub fn located_at(&self, other: Span) -> Span {
match (self, other) {
(Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.located_at(b)),
(Span::Stable(a), Span::Stable(b)) => Span::Stable(a.located_at(b)),
(Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)),
(Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)),
_ => mismatch(),
}
}
pub fn unstable(self) -> proc_macro::Span {
pub fn unwrap(self) -> proc_macro::Span {
match self {
Span::Nightly(s) => s,
Span::Stable(_) => mismatch(),
Span::Compiler(s) => s,
Span::Fallback(_) => panic!("proc_macro::Span is only available in procedural macros"),
}
}
#[cfg(super_unstable)]
pub fn source_file(&self) -> SourceFile {
match self {
Span::Nightly(s) => SourceFile::nightly(s.source_file()),
Span::Stable(s) => SourceFile::Stable(s.source_file()),
Span::Compiler(s) => SourceFile::nightly(s.source_file()),
Span::Fallback(s) => SourceFile::Fallback(s.source_file()),
}
}
#[cfg(super_unstable)]
#[cfg(any(super_unstable, feature = "span-locations"))]
pub fn start(&self) -> LineColumn {
match self {
Span::Nightly(s) => {
#[cfg(nightly)]
Span::Compiler(s) => {
let proc_macro::LineColumn { line, column } = s.start();
LineColumn { line, column }
}
Span::Stable(s) => {
let stable::LineColumn { line, column } = s.start();
#[cfg(not(nightly))]
Span::Compiler(_) => LineColumn { line: 0, column: 0 },
Span::Fallback(s) => {
let fallback::LineColumn { line, column } = s.start();
LineColumn { line, column }
}
}
}
#[cfg(super_unstable)]
#[cfg(any(super_unstable, feature = "span-locations"))]
pub fn end(&self) -> LineColumn {
match self {
Span::Nightly(s) => {
#[cfg(nightly)]
Span::Compiler(s) => {
let proc_macro::LineColumn { line, column } = s.end();
LineColumn { line, column }
}
Span::Stable(s) => {
let stable::LineColumn { line, column } = s.end();
#[cfg(not(nightly))]
Span::Compiler(_) => LineColumn { line: 0, column: 0 },
Span::Fallback(s) => {
let fallback::LineColumn { line, column } = s.end();
LineColumn { line, column }
}
}
@ -516,8 +511,8 @@ impl Span {
#[cfg(super_unstable)]
pub fn join(&self, other: Span) -> Option<Span> {
let ret = match (self, other) {
(Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.join(b)?),
(Span::Stable(a), Span::Stable(b)) => Span::Stable(a.join(b)?),
(Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.join(b)?),
(Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.join(b)?),
_ => return None,
};
Some(ret)
@ -526,134 +521,143 @@ impl Span {
#[cfg(super_unstable)]
pub fn eq(&self, other: &Span) -> bool {
match (self, other) {
(Span::Nightly(a), Span::Nightly(b)) => a.eq(b),
(Span::Stable(a), Span::Stable(b)) => a.eq(b),
(Span::Compiler(a), Span::Compiler(b)) => a.eq(b),
(Span::Fallback(a), Span::Fallback(b)) => a.eq(b),
_ => false,
}
}
fn unwrap_nightly(self) -> proc_macro::Span {
match self {
Span::Nightly(s) => s,
Span::Stable(_) => mismatch(),
Span::Compiler(s) => s,
Span::Fallback(_) => mismatch(),
}
}
}
impl From<proc_macro::Span> for ::Span {
fn from(proc_span: proc_macro::Span) -> ::Span {
::Span::_new(Span::Nightly(proc_span))
::Span::_new(Span::Compiler(proc_span))
}
}
impl From<stable::Span> for Span {
fn from(inner: stable::Span) -> Span {
Span::Stable(inner)
impl From<fallback::Span> for Span {
fn from(inner: fallback::Span) -> Span {
Span::Fallback(inner)
}
}
impl fmt::Debug for Span {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Span::Nightly(s) => s.fmt(f),
Span::Stable(s) => s.fmt(f),
Span::Compiler(s) => s.fmt(f),
Span::Fallback(s) => s.fmt(f),
}
}
}
pub fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
match span {
Span::Compiler(s) => {
debug.field("span", &s);
}
Span::Fallback(s) => fallback::debug_span_field_if_nontrivial(debug, s),
}
}
#[derive(Clone)]
pub enum Group {
Nightly(proc_macro::Group),
Stable(stable::Group),
Compiler(proc_macro::Group),
Fallback(fallback::Group),
}
impl Group {
pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group {
match stream {
TokenStream::Nightly(stream) => {
TokenStream::Compiler(stream) => {
let delimiter = match delimiter {
Delimiter::Parenthesis => proc_macro::Delimiter::Parenthesis,
Delimiter::Bracket => proc_macro::Delimiter::Bracket,
Delimiter::Brace => proc_macro::Delimiter::Brace,
Delimiter::None => proc_macro::Delimiter::None,
};
Group::Nightly(proc_macro::Group::new(delimiter, stream))
Group::Compiler(proc_macro::Group::new(delimiter, stream))
}
TokenStream::Stable(stream) => {
Group::Stable(stable::Group::new(delimiter, stream))
TokenStream::Fallback(stream) => {
Group::Fallback(fallback::Group::new(delimiter, stream))
}
}
}
pub fn delimiter(&self) -> Delimiter {
match self {
Group::Nightly(g) => match g.delimiter() {
Group::Compiler(g) => match g.delimiter() {
proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis,
proc_macro::Delimiter::Bracket => Delimiter::Bracket,
proc_macro::Delimiter::Brace => Delimiter::Brace,
proc_macro::Delimiter::None => Delimiter::None,
}
Group::Stable(g) => g.delimiter(),
},
Group::Fallback(g) => g.delimiter(),
}
}
pub fn stream(&self) -> TokenStream {
match self {
Group::Nightly(g) => TokenStream::Nightly(g.stream()),
Group::Stable(g) => TokenStream::Stable(g.stream()),
Group::Compiler(g) => TokenStream::Compiler(g.stream()),
Group::Fallback(g) => TokenStream::Fallback(g.stream()),
}
}
pub fn span(&self) -> Span {
match self {
Group::Nightly(g) => Span::Nightly(g.span()),
Group::Stable(g) => Span::Stable(g.span()),
Group::Compiler(g) => Span::Compiler(g.span()),
Group::Fallback(g) => Span::Fallback(g.span()),
}
}
#[cfg(super_unstable)]
pub fn span_open(&self) -> Span {
match self {
Group::Nightly(g) => Span::Nightly(g.span_open()),
Group::Stable(g) => Span::Stable(g.span_open()),
Group::Compiler(g) => Span::Compiler(g.span_open()),
Group::Fallback(g) => Span::Fallback(g.span_open()),
}
}
#[cfg(super_unstable)]
pub fn span_close(&self) -> Span {
match self {
Group::Nightly(g) => Span::Nightly(g.span_close()),
Group::Stable(g) => Span::Stable(g.span_close()),
Group::Compiler(g) => Span::Compiler(g.span_close()),
Group::Fallback(g) => Span::Fallback(g.span_close()),
}
}
pub fn set_span(&mut self, span: Span) {
match (self, span) {
(Group::Nightly(g), Span::Nightly(s)) => g.set_span(s),
(Group::Stable(g), Span::Stable(s)) => g.set_span(s),
(Group::Compiler(g), Span::Compiler(s)) => g.set_span(s),
(Group::Fallback(g), Span::Fallback(s)) => g.set_span(s),
_ => mismatch(),
}
}
fn unwrap_nightly(self) -> proc_macro::Group {
match self {
Group::Nightly(g) => g,
Group::Stable(_) => mismatch(),
Group::Compiler(g) => g,
Group::Fallback(_) => mismatch(),
}
}
}
impl From<stable::Group> for Group {
fn from(g: stable::Group) -> Self {
Group::Stable(g)
impl From<fallback::Group> for Group {
fn from(g: fallback::Group) -> Self {
Group::Fallback(g)
}
}
impl fmt::Display for Group {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
Group::Nightly(group) => group.fmt(formatter),
Group::Stable(group) => group.fmt(formatter),
Group::Compiler(group) => group.fmt(formatter),
Group::Fallback(group) => group.fmt(formatter),
}
}
}
@ -661,29 +665,29 @@ impl fmt::Display for Group {
impl fmt::Debug for Group {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
Group::Nightly(group) => group.fmt(formatter),
Group::Stable(group) => group.fmt(formatter),
Group::Compiler(group) => group.fmt(formatter),
Group::Fallback(group) => group.fmt(formatter),
}
}
}
#[derive(Clone)]
pub enum Ident {
Nightly(proc_macro::Ident),
Stable(stable::Ident),
Compiler(proc_macro::Ident),
Fallback(fallback::Ident),
}
impl Ident {
pub fn new(string: &str, span: Span) -> Ident {
match span {
Span::Nightly(s) => Ident::Nightly(proc_macro::Ident::new(string, s)),
Span::Stable(s) => Ident::Stable(stable::Ident::new(string, s)),
Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new(string, s)),
Span::Fallback(s) => Ident::Fallback(fallback::Ident::new(string, s)),
}
}
pub fn new_raw(string: &str, span: Span) -> Ident {
match span {
Span::Nightly(s) => {
Span::Compiler(s) => {
let p: proc_macro::TokenStream = string.parse().unwrap();
let ident = match p.into_iter().next() {
Some(proc_macro::TokenTree::Ident(mut i)) => {
@ -692,31 +696,31 @@ impl Ident {
}
_ => panic!(),
};
Ident::Nightly(ident)
Ident::Compiler(ident)
}
Span::Stable(s) => Ident::Stable(stable::Ident::new_raw(string, s)),
Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_raw(string, s)),
}
}
pub fn span(&self) -> Span {
match self {
Ident::Nightly(t) => Span::Nightly(t.span()),
Ident::Stable(t) => Span::Stable(t.span()),
Ident::Compiler(t) => Span::Compiler(t.span()),
Ident::Fallback(t) => Span::Fallback(t.span()),
}
}
pub fn set_span(&mut self, span: Span) {
match (self, span) {
(Ident::Nightly(t), Span::Nightly(s)) => t.set_span(s),
(Ident::Stable(t), Span::Stable(s)) => t.set_span(s),
(Ident::Compiler(t), Span::Compiler(s)) => t.set_span(s),
(Ident::Fallback(t), Span::Fallback(s)) => t.set_span(s),
_ => mismatch(),
}
}
fn unwrap_nightly(self) -> proc_macro::Ident {
match self {
Ident::Nightly(s) => s,
Ident::Stable(_) => mismatch(),
Ident::Compiler(s) => s,
Ident::Fallback(_) => mismatch(),
}
}
}
@ -724,8 +728,8 @@ impl Ident {
impl PartialEq for Ident {
fn eq(&self, other: &Ident) -> bool {
match (self, other) {
(Ident::Nightly(t), Ident::Nightly(o)) => t.to_string() == o.to_string(),
(Ident::Stable(t), Ident::Stable(o)) => t == o,
(Ident::Compiler(t), Ident::Compiler(o)) => t.to_string() == o.to_string(),
(Ident::Fallback(t), Ident::Fallback(o)) => t == o,
_ => mismatch(),
}
}
@ -738,8 +742,8 @@ where
fn eq(&self, other: &T) -> bool {
let other = other.as_ref();
match self {
Ident::Nightly(t) => t.to_string() == other,
Ident::Stable(t) => t == other,
Ident::Compiler(t) => t.to_string() == other,
Ident::Fallback(t) => t == other,
}
}
}
@ -747,8 +751,8 @@ where
impl fmt::Display for Ident {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Ident::Nightly(t) => t.fmt(f),
Ident::Stable(t) => t.fmt(f),
Ident::Compiler(t) => t.fmt(f),
Ident::Fallback(t) => t.fmt(f),
}
}
}
@ -756,25 +760,25 @@ impl fmt::Display for Ident {
impl fmt::Debug for Ident {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Ident::Nightly(t) => t.fmt(f),
Ident::Stable(t) => t.fmt(f),
Ident::Compiler(t) => t.fmt(f),
Ident::Fallback(t) => t.fmt(f),
}
}
}
#[derive(Clone)]
pub enum Literal {
Nightly(proc_macro::Literal),
Stable(stable::Literal),
Compiler(proc_macro::Literal),
Fallback(fallback::Literal),
}
macro_rules! suffixed_numbers {
($($name:ident => $kind:ident,)*) => ($(
pub fn $name(n: $kind) -> Literal {
if nightly_works() {
Literal::Nightly(proc_macro::Literal::$name(n))
Literal::Compiler(proc_macro::Literal::$name(n))
} else {
Literal::Stable(stable::Literal::$name(n))
Literal::Fallback(fallback::Literal::$name(n))
}
}
)*)
@ -784,9 +788,9 @@ macro_rules! unsuffixed_integers {
($($name:ident => $kind:ident,)*) => ($(
pub fn $name(n: $kind) -> Literal {
if nightly_works() {
Literal::Nightly(proc_macro::Literal::$name(n))
Literal::Compiler(proc_macro::Literal::$name(n))
} else {
Literal::Stable(stable::Literal::$name(n))
Literal::Fallback(fallback::Literal::$name(n))
}
}
)*)
@ -836,78 +840,78 @@ impl Literal {
pub fn f32_unsuffixed(f: f32) -> Literal {
if nightly_works() {
Literal::Nightly(proc_macro::Literal::f32_unsuffixed(f))
Literal::Compiler(proc_macro::Literal::f32_unsuffixed(f))
} else {
Literal::Stable(stable::Literal::f32_unsuffixed(f))
Literal::Fallback(fallback::Literal::f32_unsuffixed(f))
}
}
pub fn f64_unsuffixed(f: f64) -> Literal {
if nightly_works() {
Literal::Nightly(proc_macro::Literal::f64_unsuffixed(f))
Literal::Compiler(proc_macro::Literal::f64_unsuffixed(f))
} else {
Literal::Stable(stable::Literal::f64_unsuffixed(f))
Literal::Fallback(fallback::Literal::f64_unsuffixed(f))
}
}
pub fn string(t: &str) -> Literal {
if nightly_works() {
Literal::Nightly(proc_macro::Literal::string(t))
Literal::Compiler(proc_macro::Literal::string(t))
} else {
Literal::Stable(stable::Literal::string(t))
Literal::Fallback(fallback::Literal::string(t))
}
}
pub fn character(t: char) -> Literal {
if nightly_works() {
Literal::Nightly(proc_macro::Literal::character(t))
Literal::Compiler(proc_macro::Literal::character(t))
} else {
Literal::Stable(stable::Literal::character(t))
Literal::Fallback(fallback::Literal::character(t))
}
}
pub fn byte_string(bytes: &[u8]) -> Literal {
if nightly_works() {
Literal::Nightly(proc_macro::Literal::byte_string(bytes))
Literal::Compiler(proc_macro::Literal::byte_string(bytes))
} else {
Literal::Stable(stable::Literal::byte_string(bytes))
Literal::Fallback(fallback::Literal::byte_string(bytes))
}
}
pub fn span(&self) -> Span {
match self {
Literal::Nightly(lit) => Span::Nightly(lit.span()),
Literal::Stable(lit) => Span::Stable(lit.span()),
Literal::Compiler(lit) => Span::Compiler(lit.span()),
Literal::Fallback(lit) => Span::Fallback(lit.span()),
}
}
pub fn set_span(&mut self, span: Span) {
match (self, span) {
(Literal::Nightly(lit), Span::Nightly(s)) => lit.set_span(s),
(Literal::Stable(lit), Span::Stable(s)) => lit.set_span(s),
(Literal::Compiler(lit), Span::Compiler(s)) => lit.set_span(s),
(Literal::Fallback(lit), Span::Fallback(s)) => lit.set_span(s),
_ => mismatch(),
}
}
fn unwrap_nightly(self) -> proc_macro::Literal {
match self {
Literal::Nightly(s) => s,
Literal::Stable(_) => mismatch(),
Literal::Compiler(s) => s,
Literal::Fallback(_) => mismatch(),
}
}
}
impl From<stable::Literal> for Literal {
fn from(s: stable::Literal) -> Literal {
Literal::Stable(s)
impl From<fallback::Literal> for Literal {
fn from(s: fallback::Literal) -> Literal {
Literal::Fallback(s)
}
}
impl fmt::Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Literal::Nightly(t) => t.fmt(f),
Literal::Stable(t) => t.fmt(f),
Literal::Compiler(t) => t.fmt(f),
Literal::Fallback(t) => t.fmt(f),
}
}
}
@ -915,8 +919,8 @@ impl fmt::Display for Literal {
impl fmt::Debug for Literal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Literal::Nightly(t) => t.fmt(f),
Literal::Stable(t) => t.fmt(f),
Literal::Compiler(t) => t.fmt(f),
Literal::Fallback(t) => t.fmt(f),
}
}
}

5
third_party/rust/proc-macro2/tests/test.rs поставляемый
Просмотреть файл

@ -137,7 +137,7 @@ fn fail() {
fail("r#_");
}
#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
#[test]
fn span_test() {
use proc_macro2::TokenTree;
@ -193,7 +193,7 @@ testing 123
}
#[cfg(procmacro2_semver_exempt)]
#[cfg(not(feature = "nightly"))]
#[cfg(not(nightly))]
#[test]
fn default_span() {
let start = Span::call_site().start();
@ -329,7 +329,6 @@ fn test_debug_ident() {
}
#[test]
#[cfg(not(feature = "nightly"))]
fn test_debug_tokenstream() {
let tts = TokenStream::from_str("[a + 1]").unwrap();

2
third_party/rust/quote/.cargo-checksum.json поставляемый
Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"44cf9d3a28be1b21f4247572b6ca4d38dc3fd42fa84c4a4e0e5632aa27bee083","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"b43ef9b9c61628f8de7036271e61322cba23d878d056748e571f4f6cf9fba1b1","src/ext.rs":"a2def0b0f24c822b3f936a781c347e5f6fdc75120f85874c94f5e7eb708168c2","src/lib.rs":"f1ba768690c57252e8135ee474a20bdd513fd0bd0664e9e9b697800163f39d08","src/to_tokens.rs":"86c419a72017846ef33a0acc53caee7312c750c90b3f1d3b58e33f20efcb94f4","tests/conditional/integer128.rs":"d83e21a91efbaa801a82ae499111bdda2d31edaa620e78c0199eba42d69c9ee6","tests/test.rs":"810013d7fd77b738abd0ace90ce2f2f3e219c757652eabab29bc1c0ce4a73b24"},"package":"53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"}
{"files":{"Cargo.toml":"68f4dc89836a05a2347086addab1849567ef8073c552ec0dfca8f96fd20550f9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"d9392d4c7af3bf9714f0a95801d64de46ffd4558cdfeea0eb85b414e555abb72","src/ext.rs":"03919239a20f8393288783a21bf6fdee12e405d13d162c9faa6f8f5ce54b003b","src/lib.rs":"5345b4d2e6f923724cec35c62d7397e6f04d5503d2d813bff7bbaa7ffc39a9cf","src/to_tokens.rs":"0dcd15cba2aa83abeb47b9a1babce7a29643b5efa2fe620b070cb37bb21a84f1","tests/conditional/integer128.rs":"d83e21a91efbaa801a82ae499111bdda2d31edaa620e78c0199eba42d69c9ee6","tests/test.rs":"810013d7fd77b738abd0ace90ce2f2f3e219c757652eabab29bc1c0ce4a73b24"},"package":"cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"}

2
third_party/rust/quote/Cargo.toml поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
[package]
name = "quote"
version = "0.6.10"
version = "0.6.11"
authors = ["David Tolnay <dtolnay@gmail.com>"]
include = ["Cargo.toml", "src/**/*.rs", "tests/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
description = "Quasi-quoting macro quote!(...)"

114
third_party/rust/quote/README.md поставляемый
Просмотреть файл

@ -38,18 +38,11 @@ first support for procedural macros in Rust 1.15.0.*
quote = "0.6"
```
```rust
#[macro_use]
extern crate quote;
```
## Syntax
The quote crate provides a [`quote!`] macro within which you can write Rust code
that gets packaged into a [`TokenStream`] and can be treated as data. You should
think of `TokenStream` as representing a fragment of Rust source code. This type
can be returned directly back to the compiler by a procedural macro to get
compiled into the caller's crate.
think of `TokenStream` as representing a fragment of Rust source code.
[`TokenStream`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.TokenStream.html
@ -64,7 +57,7 @@ most Rust primitive types as well as most of the syntax tree types from [`syn`].
let tokens = quote! {
struct SerializeWith #generics #where_clause {
value: &'a #field_ty,
phantom: ::std::marker::PhantomData<#item_ty>,
phantom: core::marker::PhantomData<#item_ty>,
}
impl #generics serde::Serialize for SerializeWith #generics #where_clause {
@ -78,7 +71,7 @@ let tokens = quote! {
SerializeWith {
value: #value,
phantom: ::std::marker::PhantomData::<#item_ty>,
phantom: core::marker::PhantomData::<#item_ty>,
}
};
```
@ -100,6 +93,107 @@ Note that there is a difference between `#(#var ,)*` and `#(#var),*`—the latte
does not produce a trailing comma. This matches the behavior of delimiters in
`macro_rules!`.
## Returning tokens to the compiler
The `quote!` macro evaluates to an expression of type
`proc_macro2::TokenStream`. Meanwhile Rust procedural macros are expected to
return the type `proc_macro::TokenStream`.
The difference between the two types is that `proc_macro` types are entirely
specific to procedural macros and cannot ever exist in code outside of a
procedural macro, while `proc_macro2` types may exist anywhere including tests
and non-macro code like main.rs and build.rs. This is why even the procedural
macro ecosystem is largely built around `proc_macro2`, because that ensures the
libraries are unit testable and accessible in non-macro contexts.
There is a [`From`]-conversion in both directions so returning the output of
`quote!` from a procedural macro usually looks like `tokens.into()` or
`proc_macro::TokenStream::from(tokens)`.
[`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
## Examples
### Combining quoted fragments
Usually you don't end up constructing an entire final `TokenStream` in one
piece. Different parts may come from different helper functions. The tokens
produced by `quote!` themselves implement `ToTokens` and so can be interpolated
into later `quote!` invocations to build up a final result.
```rust
let type_definition = quote! {...};
let methods = quote! {...};
let tokens = quote! {
#type_definition
#methods
};
```
### Constructing identifiers
Suppose we have an identifier `ident` which came from somewhere in a macro
input and we need to modify it in some way for the macro output. Let's consider
prepending the identifier with an underscore.
Simply interpolating the identifier next to an underscore will not have the
behavior of concatenating them. The underscore and the identifier will continue
to be two separate tokens as if you had written `_ x`.
```rust
// incorrect
quote! {
let mut _#ident = 0;
}
```
The solution is to perform token-level manipulations using the APIs provided by
Syn and proc-macro2.
```rust
let concatenated = format!("_{}", ident);
let varname = syn::Ident::new(&concatenated, ident.span());
quote! {
let mut #varname = 0;
}
```
### Making method calls
Let's say our macro requires some type specified in the macro input to have a
constructor called `new`. We have the type in a variable called `field_type` of
type `syn::Type` and want to invoke the constructor.
```rust
// incorrect
quote! {
let value = #field_type::new();
}
```
This works only sometimes. If `field_type` is `String`, the expanded code
contains `String::new()` which is fine. But if `field_type` is something like
`Vec<i32>` then the expanded code is `Vec<i32>::new()` which is invalid syntax.
Ordinarily in handwritten Rust we would write `Vec::<i32>::new()` but for macros
often the following is more convenient.
```rust
quote! {
let value = <#field_type>::new();
}
```
This expands to `<Vec<i32>>::new()` which behaves correctly.
A similar pattern is appropriate for trait methods.
```rust
quote! {
let value = <#field_type as core::default::Default>::default();
}
```
## Hygiene
Any interpolated tokens preserve the `Span` information provided by their

79
third_party/rust/quote/src/ext.rs поставляемый
Просмотреть файл

@ -8,47 +8,19 @@ use proc_macro2::{TokenStream, TokenTree};
///
/// This trait is sealed and cannot be implemented outside of the `quote` crate.
pub trait TokenStreamExt: private::Sealed {
fn append<U>(&mut self, token: U)
where
U: Into<TokenTree>;
fn append_all<T, I>(&mut self, iter: I)
where
T: ToTokens,
I: IntoIterator<Item = T>;
fn append_separated<T, I, U>(&mut self, iter: I, op: U)
where
T: ToTokens,
I: IntoIterator<Item = T>,
U: ToTokens;
fn append_terminated<T, I, U>(&mut self, iter: I, term: U)
where
T: ToTokens,
I: IntoIterator<Item = T>,
U: ToTokens;
}
impl TokenStreamExt for TokenStream {
/// For use by `ToTokens` implementations.
///
/// Appends the token specified to this list of tokens.
fn append<U>(&mut self, token: U)
where
U: Into<TokenTree>,
{
self.extend(iter::once(token.into()));
}
U: Into<TokenTree>;
/// For use by `ToTokens` implementations.
///
/// ```
/// # #[macro_use] extern crate quote;
/// # extern crate proc_macro2;
/// # use quote::{TokenStreamExt, ToTokens};
/// ```edition2018
/// # use quote::{quote, TokenStreamExt, ToTokens};
/// # use proc_macro2::TokenStream;
/// # fn main() {
/// #
/// struct X;
///
/// impl ToTokens for X {
@ -59,8 +31,41 @@ impl TokenStreamExt for TokenStream {
///
/// let tokens = quote!(#X);
/// assert_eq!(tokens.to_string(), "true false");
/// # }
/// ```
fn append_all<T, I>(&mut self, iter: I)
where
T: ToTokens,
I: IntoIterator<Item = T>;
/// For use by `ToTokens` implementations.
///
/// Appends all of the items in the iterator `I`, separated by the tokens
/// `U`.
fn append_separated<T, I, U>(&mut self, iter: I, op: U)
where
T: ToTokens,
I: IntoIterator<Item = T>,
U: ToTokens;
/// For use by `ToTokens` implementations.
///
/// Appends all tokens in the iterator `I`, appending `U` after each
/// element, including after the last element of the iterator.
fn append_terminated<T, I, U>(&mut self, iter: I, term: U)
where
T: ToTokens,
I: IntoIterator<Item = T>,
U: ToTokens;
}
impl TokenStreamExt for TokenStream {
fn append<U>(&mut self, token: U)
where
U: Into<TokenTree>,
{
self.extend(iter::once(token.into()));
}
fn append_all<T, I>(&mut self, iter: I)
where
T: ToTokens,
@ -71,10 +76,6 @@ impl TokenStreamExt for TokenStream {
}
}
/// For use by `ToTokens` implementations.
///
/// Appends all of the items in the iterator `I`, separated by the tokens
/// `U`.
fn append_separated<T, I, U>(&mut self, iter: I, op: U)
where
T: ToTokens,
@ -89,10 +90,6 @@ impl TokenStreamExt for TokenStream {
}
}
/// For use by `ToTokens` implementations.
///
/// Appends all tokens in the iterator `I`, appending `U` after each
/// element, including after the last element of the iterator.
fn append_terminated<T, I, U>(&mut self, iter: I, term: U)
where
T: ToTokens,

205
third_party/rust/quote/src/lib.rs поставляемый
Просмотреть файл

@ -29,13 +29,6 @@
//! quote = "0.6"
//! ```
//!
//! ```
//! #[macro_use]
//! extern crate quote;
//! #
//! # fn main() {}
//! ```
//!
//! # Example
//!
//! The following quasi-quoted block of code is something you might find in [a]
@ -48,22 +41,20 @@
//! [a]: https://serde.rs/
//! [`quote_spanned!`]: macro.quote_spanned.html
//!
//! ```
//! # #[macro_use]
//! # extern crate quote;
//! ```edition2018
//! # use quote::quote;
//! #
//! # fn main() {
//! # let generics = "";
//! # let where_clause = "";
//! # let field_ty = "";
//! # let item_ty = "";
//! # let path = "";
//! # let value = "";
//! # let generics = "";
//! # let where_clause = "";
//! # let field_ty = "";
//! # let item_ty = "";
//! # let path = "";
//! # let value = "";
//! #
//! let tokens = quote! {
//! struct SerializeWith #generics #where_clause {
//! value: &'a #field_ty,
//! phantom: ::std::marker::PhantomData<#item_ty>,
//! phantom: core::marker::PhantomData<#item_ty>,
//! }
//!
//! impl #generics serde::Serialize for SerializeWith #generics #where_clause {
@ -77,14 +68,12 @@
//!
//! SerializeWith {
//! value: #value,
//! phantom: ::std::marker::PhantomData::<#item_ty>,
//! phantom: core::marker::PhantomData::<#item_ty>,
//! }
//! };
//! #
//! # }
//! ```
//!
//! ## Recursion limit
//! # Recursion limit
//!
//! The `quote!` macro relies on deep recursion so some large invocations may
//! fail with "recursion limit reached" when you compile. If it fails, bump up
@ -92,7 +81,7 @@
//! An even higher limit may be necessary for especially large invocations.
// Quote types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/quote/0.6.10")]
#![doc(html_root_url = "https://docs.rs/quote/0.6.11")]
#[cfg(all(
not(all(target_arch = "wasm32", target_os = "unknown")),
@ -277,17 +266,43 @@ pub mod __rt {
///
/// [`quote_spanned!`]: macro.quote_spanned.html
///
/// # Example
/// # Return type
///
/// ```
/// The macro evaluates to an expression of type `proc_macro2::TokenStream`.
/// Meanwhile Rust procedural macros are expected to return the type
/// `proc_macro::TokenStream`.
///
/// The difference between the two types is that `proc_macro` types are entirely
/// specific to procedural macros and cannot ever exist in code outside of a
/// procedural macro, while `proc_macro2` types may exist anywhere including
/// tests and non-macro code like main.rs and build.rs. This is why even the
/// procedural macro ecosystem is largely built around `proc_macro2`, because
/// that ensures the libraries are unit testable and accessible in non-macro
/// contexts.
///
/// There is a [`From`]-conversion in both directions so returning the output of
/// `quote!` from a procedural macro usually looks like `tokens.into()` or
/// `proc_macro::TokenStream::from(tokens)`.
///
/// [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
///
/// # Examples
///
/// ## Procedural macro
///
/// The structure of a basic procedural macro is as follows. Refer to the [Syn]
/// crate for further useful guidance on using `quote!` as part of a procedural
/// macro.
///
/// [Syn]: https://github.com/dtolnay/syn
///
/// ```edition2018
/// # #[cfg(any())]
/// extern crate proc_macro;
/// # extern crate proc_macro2 as proc_macro;
///
/// #[macro_use]
/// extern crate quote;
/// # use proc_macro2 as proc_macro;
///
/// use proc_macro::TokenStream;
/// use quote::quote;
///
/// # const IGNORE_TOKENS: &'static str = stringify! {
/// #[proc_macro_derive(HeapSize)]
@ -304,7 +319,7 @@ pub mod __rt {
///
/// let expanded = quote! {
/// // The generated impl.
/// impl ::heapsize::HeapSize for #name {
/// impl heapsize::HeapSize for #name {
/// fn heap_size_of_children(&self) -> usize {
/// #expr
/// }
@ -312,10 +327,117 @@ pub mod __rt {
/// };
///
/// // Hand the output tokens back to the compiler.
/// expanded.into()
/// TokenStream::from(expanded)
/// }
/// ```
///
/// ## Combining quoted fragments
///
/// Usually you don't end up constructing an entire final `TokenStream` in one
/// piece. Different parts may come from different helper functions. The tokens
/// produced by `quote!` themselves implement `ToTokens` and so can be
/// interpolated into later `quote!` invocations to build up a final result.
///
/// ```edition2018
/// # use quote::quote;
/// #
/// # fn main() {}
/// let type_definition = quote! {...};
/// let methods = quote! {...};
///
/// let tokens = quote! {
/// #type_definition
/// #methods
/// };
/// ```
///
/// ## Constructing identifiers
///
/// Suppose we have an identifier `ident` which came from somewhere in a macro
/// input and we need to modify it in some way for the macro output. Let's
/// consider prepending the identifier with an underscore.
///
/// Simply interpolating the identifier next to an underscore will not have the
/// behavior of concatenating them. The underscore and the identifier will
/// continue to be two separate tokens as if you had written `_ x`.
///
/// ```edition2018
/// # use proc_macro2::{self as syn, Span};
/// # use quote::quote;
/// #
/// # let ident = syn::Ident::new("i", Span::call_site());
/// #
/// // incorrect
/// quote! {
/// let mut _#ident = 0;
/// }
/// # ;
/// ```
///
/// The solution is to perform token-level manipulations using the APIs provided
/// by Syn and proc-macro2.
///
/// ```edition2018
/// # use proc_macro2::{self as syn, Span};
/// # use quote::quote;
/// #
/// # let ident = syn::Ident::new("i", Span::call_site());
/// #
/// let concatenated = format!("_{}", ident);
/// let varname = syn::Ident::new(&concatenated, ident.span());
/// quote! {
/// let mut #varname = 0;
/// }
/// # ;
/// ```
///
/// ## Making method calls
///
/// Let's say our macro requires some type specified in the macro input to have
/// a constructor called `new`. We have the type in a variable called
/// `field_type` of type `syn::Type` and want to invoke the constructor.
///
/// ```edition2018
/// # use quote::quote;
/// #
/// # let field_type = quote!(...);
/// #
/// // incorrect
/// quote! {
/// let value = #field_type::new();
/// }
/// # ;
/// ```
///
/// This works only sometimes. If `field_type` is `String`, the expanded code
/// contains `String::new()` which is fine. But if `field_type` is something
/// like `Vec<i32>` then the expanded code is `Vec<i32>::new()` which is invalid
/// syntax. Ordinarily in handwritten Rust we would write `Vec::<i32>::new()`
/// but for macros often the following is more convenient.
///
/// ```edition2018
/// # use quote::quote;
/// #
/// # let field_type = quote!(...);
/// #
/// quote! {
/// let value = <#field_type>::new();
/// }
/// # ;
/// ```
///
/// This expands to `<Vec<i32>>::new()` which behaves correctly.
///
/// A similar pattern is appropriate for trait methods.
///
/// ```edition2018
/// # use quote::quote;
/// #
/// # let field_type = quote!(...);
/// #
/// quote! {
/// let value = <#field_type as core::default::Default>::default();
/// }
/// # ;
/// ```
#[macro_export(local_inner_macros)]
macro_rules! quote {
@ -333,14 +455,10 @@ macro_rules! quote {
///
/// [`Span`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.Span.html
///
/// ```
/// # #[macro_use]
/// # extern crate quote;
/// # extern crate proc_macro2;
/// #
/// ```edition2018
/// # use proc_macro2::Span;
/// # use quote::quote_spanned;
/// #
/// # fn main() {
/// # const IGNORE_TOKENS: &'static str = stringify! {
/// let span = /* ... */;
/// # };
@ -354,7 +472,6 @@ macro_rules! quote {
/// let tokens = quote_spanned! {span=>
/// Box::into_raw(Box::new(#init))
/// };
/// # }
/// ```
///
/// The lack of space before the `=>` should look jarring to Rust programmers
@ -377,12 +494,8 @@ macro_rules! quote {
///
/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
///
/// ```
/// # #[macro_use]
/// # extern crate quote;
/// # extern crate proc_macro2;
/// #
/// # use quote::{TokenStreamExt, ToTokens};
/// ```edition2018
/// # use quote::{quote_spanned, TokenStreamExt, ToTokens};
/// # use proc_macro2::{Span, TokenStream};
/// #
/// # struct Type;
@ -397,7 +510,6 @@ macro_rules! quote {
/// # fn to_tokens(&self, _tokens: &mut TokenStream) {}
/// # }
/// #
/// # fn main() {
/// # let ty = Type;
/// # let call_site = Span::call_site();
/// #
@ -405,7 +517,6 @@ macro_rules! quote {
/// let assert_sync = quote_spanned! {ty_span=>
/// struct _AssertSync where #ty: Sync;
/// };
/// # }
/// ```
///
/// If the assertion fails, the user will see an error like the following. The

9
third_party/rust/quote/src/to_tokens.rs поставляемый
Просмотреть файл

@ -21,12 +21,9 @@ pub trait ToTokens {
/// Example implementation for a struct representing Rust paths like
/// `std::cmp::PartialEq`:
///
/// ```
/// extern crate quote;
/// use quote::{TokenStreamExt, ToTokens};
///
/// extern crate proc_macro2;
/// ```edition2018
/// use proc_macro2::{TokenTree, Spacing, Span, Punct, TokenStream};
/// use quote::{TokenStreamExt, ToTokens};
///
/// pub struct Path {
/// pub global: bool,
@ -53,8 +50,6 @@ pub trait ToTokens {
/// # unimplemented!()
/// # }
/// # }
/// #
/// # fn main() {}
/// ```
fn to_tokens(&self, tokens: &mut TokenStream);

2
third_party/rust/syn/.cargo-checksum.json поставляемый
Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"fdac1ee690fa3d33b906be9d09a8551741db11ddba7f755cb75c8d74fd2d918b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"3f3d105c0f1bae3bdb5ed3cc32a8e5a02f3de6f62a9f17f5ba03af3f813d0881","src/attr.rs":"9210a8dc5fea0ee3004b14a9e2923142932c53986b56685d62d9aa115fe093b0","src/buffer.rs":"fac77febe022ab4982078c73ca502f9d698a402b3eca0f8e9c7a2796af01e5f4","src/data.rs":"54ee54c3c650bc5e200d4bea947d6e89093a39f2444cd43e8861f5852975e0bc","src/derive.rs":"eb041b47a73bace73c2872cd9a8e190de7e2b3b57cd57213770f088ec19ab3c6","src/error.rs":"0bcf09b0892c6d5f5f31f7f758866ded1e47463833cad60694329348ac1fb44a","src/export.rs":"1f7e017dac9426e91c796445e733c390c408c808ba9c21cb7df7799b67352fde","src/expr.rs":"3fe98f69af9be770d4d549d869d35136f3dea66452e4cb4b9e387982e3b7aea2","src/ext.rs":"1881179e634681cdd472ecac502192b5a5a7759056d1c49497706749fdab1bdf","src/file.rs":"abb9f5e71a8a6b52649c15da21d3f99e25a727d87c2f87d2744ac3970c1d683f","src/gen/fold.rs":"7f7ab907e3c17b503a72707e2f8d9fc29d9139269d810ea9b6511af9de7d3080","src/gen/visit.rs":"0a4543ac9f82d8ab7ccf02c55e8325ff9b859e36ea08d3e187a4836f470eef1c","src/gen/visit_mut.rs":"66441522f544056cd464740e8ba614688a5f417857c649550eeba2b589ef6096","src/gen_helper.rs":"644b1d31987919c0239891d8f90c09f3bf541a71fb85e744438e4814cc6dff89","src/generics.rs":"6ee5bba532b95f7de7c6bbe8caadabc6a71c45e7f8d7636d823075ff27f28937","src/group.rs":"03487f75d0abd302f06e50eb09d14ab83fb60c67e1f2602be53ca3f28a833b90","src/ident.rs":"61534c48949ebfa03e948874ef64174e1c8111c3b953edd58f79748fe9e00507","src/item.rs":"6799adb332bedaa68c3801055e71a5665cc7b9c4ba53960f6b91487408e7e10c","src/keyword.rs":"7dde0b4a0d70527921be16f50f8d88e4b5ad7e5fd70e9badd2bb351fd796dfb8","src/lib.rs":"254744712dae7c30ce7f97ce4685fc6256cf125e7872397d3dd9e32632273262","src/lifetime.rs":"7912a4c77ee805e912fb28c7f434836ea82540263d549877cd5edfbe32d1bf95","src/lit.rs":"b6aef4f2787201edbeb85529fc0c333bd8083d697a08f28c812b6b2f765939f5","src/lookahead.rs":"5b3c55ae8c1b1d0ed813c296dc6fa586379a99e7792a3cb0d634ae6ca74f54b5","src/mac.rs":"a91623ed9c1de7b18ef752db79a242002e95156497a52a1790a75069915d22ee","src/macros.rs":"2f91e07a1aec4b385986c0a0f66274e8de1c1aa81f95d398a5cd364b3c451bb4","src/op.rs":"01edb1e07b6d60b266797ca4b30788b0a511452228e04073a11f0b61f106a0e7","src/parse.rs":"d907b9822943bafbcb1e005f09a145e46c162e7702fce703b57f9b7ccbdf85a2","src/parse_macro_input.rs":"8df7b4c1b361171f3fefb0490dec570ad29c024c04e35184b296725f97f2002c","src/parse_quote.rs":"d5e613fbba06900d882f2aaa042f10c1bee1b1dffaa1d9ee9a73d1e504a08fad","src/path.rs":"d6a319db75e4b34783912aed0ddfad92cdec05798d8d378f2f23231437cab3e1","src/print.rs":"7ebb68123898f2ebbae12abf028747c05bea7b08f1e96b17164f1dcebdab7355","src/punctuated.rs":"5ad6885e602cb1c79b49f11e1c739bdb7c33ecfa1ca9c709d711b0778ae48085","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"83b4ab1e2138ac9340eaa8234ad1d9f7468b450ddf3a852e574cac18e4f766b8","src/synom.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/thread.rs":"798dd0a6cca7807f1d55c1f79cec967314a75c4e8e2cfdb5644499c22618b307","src/token.rs":"8fa7ffb89da61d5187ab0ff40de7b3b1135ace6cf770c8d84fce8371854698a9","src/tt.rs":"b3d99cbd68cd50749f26f4afa138e6366d327099ed566b30c315ccb58fa26ded","src/ty.rs":"4ac9d1b84f9bf269516348e1b923b1c8e3f7562b98ec7ef66174c31fffb8dce5"},"package":"734ecc29cd36e8123850d9bf21dfd62ef8300aaa8f879aabaa899721808be37c"}
{"files":{"Cargo.toml":"ebf2c860a726b1210648f946b92b56a54414f2a009043d8affefdb1a0e4bd234","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"3f3d105c0f1bae3bdb5ed3cc32a8e5a02f3de6f62a9f17f5ba03af3f813d0881","build.rs":"9f3b0dc6ae4c0065c3cf001a40a2ff9c5a86cac5edf66fa0e80d0bcd37c0d4fc","src/attr.rs":"9210a8dc5fea0ee3004b14a9e2923142932c53986b56685d62d9aa115fe093b0","src/buffer.rs":"fac77febe022ab4982078c73ca502f9d698a402b3eca0f8e9c7a2796af01e5f4","src/data.rs":"54ee54c3c650bc5e200d4bea947d6e89093a39f2444cd43e8861f5852975e0bc","src/derive.rs":"eb041b47a73bace73c2872cd9a8e190de7e2b3b57cd57213770f088ec19ab3c6","src/error.rs":"0bcf09b0892c6d5f5f31f7f758866ded1e47463833cad60694329348ac1fb44a","src/export.rs":"1f7e017dac9426e91c796445e733c390c408c808ba9c21cb7df7799b67352fde","src/expr.rs":"c9000092a57412dcbef401cd51195b816ebfae96736deeebcece5bdc73471cdc","src/ext.rs":"1881179e634681cdd472ecac502192b5a5a7759056d1c49497706749fdab1bdf","src/file.rs":"abb9f5e71a8a6b52649c15da21d3f99e25a727d87c2f87d2744ac3970c1d683f","src/gen/fold.rs":"5507dde16c41e4f11b8903938a5f442fff9f94468afccbf0a37a4fa14f2eddde","src/gen/visit.rs":"4c8f499d1fd988b9c9ff820ef76c0c93b1e5ee91e6a94e0892298f5e6f424893","src/gen/visit_mut.rs":"d1f905b2b5afd685ace07532b6cbc67175e2d104508c7ed86ed4e9d1567c7c7b","src/gen_helper.rs":"644b1d31987919c0239891d8f90c09f3bf541a71fb85e744438e4814cc6dff89","src/generics.rs":"6ee5bba532b95f7de7c6bbe8caadabc6a71c45e7f8d7636d823075ff27f28937","src/group.rs":"03487f75d0abd302f06e50eb09d14ab83fb60c67e1f2602be53ca3f28a833b90","src/ident.rs":"bd7884de0031d942c556f929905532dd8799f8ca2450e65b8e4e8dfa78cf4fee","src/item.rs":"92b5ceca78590d9236dbdd008b97d817d051a16b10cb4dac8614199a09bda03e","src/keyword.rs":"aaca18ec0226f454ed5eecf8d99ef01afb8dd2457c9cae4f91b262accc0c0c41","src/lib.rs":"d36df1838b3454cd63a4ca214044c2be9281a33b533581f5da622bc66e2446d2","src/lifetime.rs":"7912a4c77ee805e912fb28c7f434836ea82540263d549877cd5edfbe32d1bf95","src/lit.rs":"bc034e4443a32f2066b41f62e05946143f60397fbbd05016c0020c4818e0a0f8","src/lookahead.rs":"5b3c55ae8c1b1d0ed813c296dc6fa586379a99e7792a3cb0d634ae6ca74f54b5","src/mac.rs":"a91623ed9c1de7b18ef752db79a242002e95156497a52a1790a75069915d22ee","src/macros.rs":"2f91e07a1aec4b385986c0a0f66274e8de1c1aa81f95d398a5cd364b3c451bb4","src/op.rs":"01edb1e07b6d60b266797ca4b30788b0a511452228e04073a11f0b61f106a0e7","src/parse.rs":"d907b9822943bafbcb1e005f09a145e46c162e7702fce703b57f9b7ccbdf85a2","src/parse_macro_input.rs":"8df7b4c1b361171f3fefb0490dec570ad29c024c04e35184b296725f97f2002c","src/parse_quote.rs":"d5e613fbba06900d882f2aaa042f10c1bee1b1dffaa1d9ee9a73d1e504a08fad","src/path.rs":"18b5c17b5acb7814a63517bbc473e1120895b4f7ff8f856279f31493663cc7fa","src/print.rs":"7ebb68123898f2ebbae12abf028747c05bea7b08f1e96b17164f1dcebdab7355","src/punctuated.rs":"3abae461aa47b71f00ede80e42691da5617a21c6f4864c40b2f984bb34a9a277","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"83b4ab1e2138ac9340eaa8234ad1d9f7468b450ddf3a852e574cac18e4f766b8","src/thread.rs":"ac3f4aa972b0dee5b9ae5202c5cd6bef46823fc91ff83787a3fe1bdfb8f79135","src/token.rs":"20868cd459ac8eea83e8891cf0b5d7c9dc179b0ff76953d5d0a2a29f17c0c7af","src/tt.rs":"b3d99cbd68cd50749f26f4afa138e6366d327099ed566b30c315ccb58fa26ded","src/ty.rs":"4ac9d1b84f9bf269516348e1b923b1c8e3f7562b98ec7ef66174c31fffb8dce5"},"package":"66c8865bf5a7cbb662d8b011950060b3c8743dca141b054bf7195b20d314d8e2"}

17
third_party/rust/syn/Cargo.toml поставляемый
Просмотреть файл

@ -3,7 +3,7 @@
# 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
# 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
@ -12,9 +12,9 @@
[package]
name = "syn"
version = "0.15.24"
version = "0.15.30"
authors = ["David Tolnay <dtolnay@gmail.com>"]
include = ["/Cargo.toml", "/src/**/*.rs", "/README.md", "/LICENSE-APACHE", "/LICENSE-MIT"]
include = ["/build.rs", "/Cargo.toml", "/LICENSE-APACHE", "/LICENSE-MIT", "/README.md", "/src/**/*.rs"]
description = "Parser for Rust source code"
documentation = "https://docs.rs/syn"
readme = "README.md"
@ -29,11 +29,6 @@ all-features = true
[lib]
name = "syn"
[[example]]
name = "dump-syntax"
path = "examples/dump-syntax/main.rs"
required-features = ["full", "parsing", "extra-traits"]
[dependencies.proc-macro2]
version = "0.4.4"
default-features = false
@ -45,6 +40,12 @@ default-features = false
[dependencies.unicode-xid]
version = "0.1"
[dev-dependencies.colored]
version = "1.7"
[dev-dependencies.insta]
version = "0.7"
[dev-dependencies.rayon]
version = "1.0"

68
third_party/rust/syn/build.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,68 @@
use std::env;
use std::process::Command;
use std::str::{self, FromStr};
// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
let compiler = match rustc_version() {
Some(compiler) => compiler,
None => return,
};
if compiler.minor >= 19 {
println!("cargo:rustc-cfg=syn_can_use_thread_id");
}
// Macro modularization allows re-exporting the `quote!` macro in 1.30+.
if compiler.minor >= 30 {
println!("cargo:rustc-cfg=syn_can_call_macro_by_path");
}
if !compiler.nightly {
println!("cargo:rustc-cfg=syn_disable_nightly_tests");
}
}
struct Compiler {
minor: u32,
nightly: bool,
}
fn rustc_version() -> Option<Compiler> {
let rustc = match env::var_os("RUSTC") {
Some(rustc) => rustc,
None => return None,
};
let output = match Command::new(rustc).arg("--version").output() {
Ok(output) => output,
Err(_) => return None,
};
let version = match str::from_utf8(&output.stdout) {
Ok(version) => version,
Err(_) => return None,
};
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
let next = match pieces.next() {
Some(next) => next,
None => return None,
};
let minor = match u32::from_str(next) {
Ok(minor) => minor,
Err(_) => return None,
};
Some(Compiler {
minor: minor,
nightly: version.contains("nightly"),
})
}

45
third_party/rust/syn/src/expr.rs поставляемый
Просмотреть файл

@ -799,8 +799,8 @@ ast_enum_of_structs! {
/// A path pattern like `Color::Red`, optionally qualified with a
/// self-type.
///
/// Unquailfied path patterns can legally refer to variants, structs,
/// constants or associated constants. Quailfied path patterns like
/// Unqualified path patterns can legally refer to variants, structs,
/// constants or associated constants. Qualified path patterns like
/// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
/// associated constants.
///
@ -1508,7 +1508,7 @@ pub mod parsing {
} else if input.peek(Token![loop]) {
input.call(expr_loop).map(Expr::Loop)
} else if input.peek(Token![match]) {
input.call(expr_match).map(Expr::Match)
input.parse().map(Expr::Match)
} else if input.peek(Token![yield]) {
input.call(expr_yield).map(Expr::Yield)
} else if input.peek(Token![unsafe]) {
@ -1703,7 +1703,7 @@ pub mod parsing {
} else if input.peek(Token![loop]) {
Expr::Loop(input.call(expr_loop)?)
} else if input.peek(Token![match]) {
Expr::Match(input.call(expr_match)?)
Expr::Match(input.parse()?)
} else if input.peek(Token![try]) && input.peek2(token::Brace) {
Expr::TryBlock(input.call(expr_try_block)?)
} else if input.peek(Token![unsafe]) {
@ -1775,6 +1775,7 @@ pub mod parsing {
let_token: input.parse()?,
pats: {
let mut pats = Punctuated::new();
input.parse::<Option<Token![|]>>()?;
let value: Pat = input.parse()?;
pats.push_value(value);
while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
@ -1876,26 +1877,28 @@ pub mod parsing {
}
#[cfg(feature = "full")]
fn expr_match(input: ParseStream) -> Result<ExprMatch> {
let match_token: Token![match] = input.parse()?;
let expr = expr_no_struct(input)?;
impl Parse for ExprMatch {
fn parse(input: ParseStream) -> Result<Self> {
let match_token: Token![match] = input.parse()?;
let expr = expr_no_struct(input)?;
let content;
let brace_token = braced!(content in input);
let inner_attrs = content.call(Attribute::parse_inner)?;
let content;
let brace_token = braced!(content in input);
let inner_attrs = content.call(Attribute::parse_inner)?;
let mut arms = Vec::new();
while !content.is_empty() {
arms.push(content.call(Arm::parse)?);
let mut arms = Vec::new();
while !content.is_empty() {
arms.push(content.call(Arm::parse)?);
}
Ok(ExprMatch {
attrs: inner_attrs,
match_token: match_token,
expr: Box::new(expr),
brace_token: brace_token,
arms: arms,
})
}
Ok(ExprMatch {
attrs: inner_attrs,
match_token: match_token,
expr: Box::new(expr),
brace_token: brace_token,
arms: arms,
})
}
#[cfg(feature = "full")]

615
third_party/rust/syn/src/gen/fold.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

498
third_party/rust/syn/src/gen/visit.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

500
third_party/rust/syn/src/gen/visit_mut.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

2
third_party/rust/syn/src/ident.rs поставляемый
Просмотреть файл

@ -81,6 +81,6 @@ ident_from_token!(extern);
impl From<Token![_]> for Ident {
fn from(token: Token![_]) -> Ident {
Ident::new("_", token.spans[0])
Ident::new("_", token.span)
}
}

27
third_party/rust/syn/src/item.rs поставляемый
Просмотреть файл

@ -1092,6 +1092,13 @@ pub mod parsing {
let content;
let paren_token = parenthesized!(content in input);
let inputs = content.parse_terminated(FnArg::parse)?;
let variadic: Option<Token![...]> = match inputs.last() {
Some(punctuated::Pair::End(&FnArg::Captured(ArgCaptured {
ty: Type::Verbatim(TypeVerbatim { ref tts }),
..
}))) => parse2(tts.clone()).ok(),
_ => None,
};
let output: ReturnType = input.parse()?;
let where_clause: Option<WhereClause> = input.parse()?;
@ -1114,7 +1121,7 @@ pub mod parsing {
paren_token: paren_token,
inputs: inputs,
output: output,
variadic: None,
variadic: variadic,
generics: Generics {
where_clause: where_clause,
..generics
@ -1179,7 +1186,23 @@ pub mod parsing {
Ok(ArgCaptured {
pat: input.parse()?,
colon_token: input.parse()?,
ty: input.parse()?,
ty: match input.parse::<Token![...]>() {
Ok(dot3) => {
let mut args = vec![
TokenTree::Punct(Punct::new('.', Spacing::Joint)),
TokenTree::Punct(Punct::new('.', Spacing::Joint)),
TokenTree::Punct(Punct::new('.', Spacing::Alone)),
];
let tokens = TokenStream::from_iter(args.into_iter().zip(&dot3.spans).map(
|(mut arg, span)| {
arg.set_span(*span);
arg
},
));
Type::Verbatim(TypeVerbatim { tts: tokens })
}
Err(_) => input.parse()?,
},
})
}

3
third_party/rust/syn/src/keyword.rs поставляемый
Просмотреть файл

@ -29,7 +29,7 @@
/// [Peeking]: parse/struct.ParseBuffer.html#method.peek
/// [Parsing]: parse/struct.ParseBuffer.html#method.parse
/// [Printing]: https://docs.rs/quote/0.6/quote/trait.ToTokens.html
/// [`Span`]: struct.Span.html
/// [`Span`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.Span.html
///
/// # Example
///
@ -89,6 +89,7 @@
#[macro_export(local_inner_macros)]
macro_rules! custom_keyword {
($ident:ident) => {
#[allow(non_camel_case_types)]
pub struct $ident {
pub span: $crate::export::Span,
}

7
third_party/rust/syn/src/lib.rs поставляемый
Просмотреть файл

@ -222,7 +222,7 @@
//! dynamic library libproc_macro from rustc toolchain.
// Syn types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/syn/0.15.24")]
#![doc(html_root_url = "https://docs.rs/syn/0.15.30")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy lints.
@ -230,8 +230,8 @@
feature = "cargo-clippy",
allow(
block_in_if_condition_stmt,
cognitive_complexity,
const_static_lifetime,
cyclomatic_complexity,
deprecated_cfg_attr,
doc_markdown,
eval_order_dependence,
@ -672,7 +672,8 @@ pub fn parse_str<T: parse::Parse>(s: &str) -> Result<T> {
///
/// If present, either of these would be an error using `from_str`.
///
/// *This function is available if Syn is built with the `"parsing"` and `"full"` features.*
/// *This function is available if Syn is built with the `"parsing"` and
/// `"full"` features.*
///
/// # Examples
///

52
third_party/rust/syn/src/lit.rs поставляемый
Просмотреть файл

@ -6,8 +6,6 @@ use proc_macro2::Ident;
#[cfg(feature = "parsing")]
use proc_macro2::TokenStream;
#[cfg(feature = "parsing")]
use Error;
use proc_macro2::TokenTree;
@ -17,7 +15,7 @@ use std::hash::{Hash, Hasher};
#[cfg(feature = "parsing")]
use lookahead;
#[cfg(feature = "parsing")]
use parse::Parse;
use parse::{Parse, Parser, Result};
ast_enum_of_structs! {
/// A Rust literal such as a string or integer or boolean.
@ -140,23 +138,44 @@ impl LitStr {
/// lit_str.parse().map(Some)
/// }
/// _ => {
/// let error_span = attr.bracket_token.span;
/// let message = "expected #[path = \"...\"]";
/// Err(Error::new(error_span, message))
/// Err(Error::new_spanned(attr, message))
/// }
/// }
/// }
/// ```
#[cfg(feature = "parsing")]
pub fn parse<T: Parse>(&self) -> Result<T, Error> {
use proc_macro2::Group;
pub fn parse<T: Parse>(&self) -> Result<T> {
self.parse_with(T::parse)
}
// Parse string literal into a token stream with every span equal to the
// original literal's span.
fn spanned_tokens(s: &LitStr) -> Result<TokenStream, Error> {
let stream = ::parse_str(&s.value())?;
Ok(respan_token_stream(stream, s.span()))
}
/// Invoke parser on the content of this string literal.
///
/// All spans in the syntax tree will point to the span of this `LitStr`.
///
/// # Example
///
/// ```edition2018
/// # use proc_macro2::Span;
/// # use syn::{LitStr, Result};
/// #
/// # fn main() -> Result<()> {
/// # let lit_str = LitStr::new("a::b::c", Span::call_site());
/// #
/// # const IGNORE: &str = stringify! {
/// let lit_str: LitStr = /* ... */;
/// # };
///
/// // Parse a string literal like "a::b::c" into a Path, not allowing
/// // generic arguments on any of the path segments.
/// let basic_path = lit_str.parse_with(syn::Path::parse_mod_style)?;
/// #
/// # Ok(())
/// # }
/// ```
#[cfg(feature = "parsing")]
pub fn parse_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
use proc_macro2::Group;
// Token stream with every span replaced by the given one.
fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream {
@ -179,7 +198,12 @@ impl LitStr {
token
}
spanned_tokens(self).and_then(::parse2)
// Parse string literal into a token stream with every span equal to the
// original literal's span.
let mut tokens = ::parse_str(&self.value())?;
tokens = respan_token_stream(tokens, self.span());
parser.parse2(tokens)
}
pub fn span(&self) -> Span {

4
third_party/rust/syn/src/path.rs поставляемый
Просмотреть файл

@ -86,6 +86,7 @@ impl PathArguments {
}
}
#[cfg(feature = "parsing")]
fn is_none(&self) -> bool {
match *self {
PathArguments::None => true,
@ -427,6 +428,9 @@ pub mod parsing {
/// - the first path segment has no angle bracketed or parenthesized
/// path arguments
/// - and the ident of the first path segment is equal to the given one.
///
/// *This function is available if Syn is built with the `"parsing"`
/// feature.*
pub fn is_ident<I>(&self, ident: I) -> bool
where
Ident: PartialEq<I>,

11
third_party/rust/syn/src/punctuated.rs поставляемый
Просмотреть файл

@ -4,7 +4,8 @@
//!
//! - The fields of a struct are `Punctuated<Field, Token![,]>`.
//! - The segments of a path are `Punctuated<PathSegment, Token![::]>`.
//! - The bounds on a generic parameter are `Punctuated<TypeParamBound, Token![+]>`.
//! - The bounds on a generic parameter are `Punctuated<TypeParamBound,
//! Token![+]>`.
//! - The arguments to a function call are `Punctuated<Expr, Token![,]>`.
//!
//! This module provides a common representation for these punctuated sequences
@ -104,7 +105,7 @@ impl<T, P> Punctuated<T, P> {
Iter {
inner: Box::new(PrivateIter {
inner: self.inner.iter(),
last: self.last.as_ref().map(|t| t.as_ref()).into_iter(),
last: self.last.as_ref().map(Box::as_ref).into_iter(),
}),
}
}
@ -115,7 +116,7 @@ impl<T, P> Punctuated<T, P> {
IterMut {
inner: Box::new(PrivateIterMut {
inner: self.inner.iter_mut(),
last: self.last.as_mut().map(|t| t.as_mut()).into_iter(),
last: self.last.as_mut().map(Box::as_mut).into_iter(),
}),
}
}
@ -125,7 +126,7 @@ impl<T, P> Punctuated<T, P> {
pub fn pairs(&self) -> Pairs<T, P> {
Pairs {
inner: self.inner.iter(),
last: self.last.as_ref().map(|t| t.as_ref()).into_iter(),
last: self.last.as_ref().map(Box::as_ref).into_iter(),
}
}
@ -134,7 +135,7 @@ impl<T, P> Punctuated<T, P> {
pub fn pairs_mut(&mut self) -> PairsMut<T, P> {
PairsMut {
inner: self.inner.iter_mut(),
last: self.last.as_mut().map(|t| t.as_mut()).into_iter(),
last: self.last.as_mut().map(Box::as_mut).into_iter(),
}
}

0
third_party/rust/syn/src/synom.rs поставляемый
Просмотреть файл

2
third_party/rust/syn/src/thread.rs поставляемый
Просмотреть файл

@ -54,10 +54,12 @@ mod thread_id {
#[cfg(not(syn_can_use_thread_id))]
mod thread_id {
#[allow(deprecated)]
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
thread_local! {
static THREAD_ID: usize = {
#[allow(deprecated)]
static NEXT_THREAD_ID: AtomicUsize = ATOMIC_USIZE_INIT;
// Ordering::Relaxed because our only requirement for the ids is

57
third_party/rust/syn/src/token.rs поставляемый
Просмотреть файл

@ -68,6 +68,25 @@
//! }
//! }
//! ```
//!
//! # Other operations
//!
//! Every keyword and punctuation token supports the following operations.
//!
//! - [Peeking] — `input.peek(Token![...])`
//!
//! - [Parsing] — `input.parse::<Token![...]>()?`
//!
//! - [Printing] — `quote!( ... #the_token ... )`
//!
//! - Construction from a [`Span`] — `let the_token = Token![...](sp)`
//!
//! - Field access to its span — `let sp = the_token.span`
//!
//! [Peeking]: ../parse/struct.ParseBuffer.html#method.peek
//! [Parsing]: ../parse/struct.ParseBuffer.html#method.parse
//! [Printing]: https://docs.rs/quote/0.6/quote/trait.ToTokens.html
//! [`Span`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.Span.html
use std;
#[cfg(feature = "extra-traits")]
@ -76,6 +95,7 @@ use std::cmp;
use std::fmt::{self, Debug};
#[cfg(feature = "extra-traits")]
use std::hash::{Hash, Hasher};
use std::ops::{Deref, DerefMut};
#[cfg(feature = "parsing")]
use proc_macro2::Delimiter;
@ -87,6 +107,7 @@ use proc_macro2::TokenStream;
#[cfg(feature = "printing")]
use quote::{ToTokens, TokenStreamExt};
use self::private::WithSpan;
#[cfg(feature = "parsing")]
use buffer::Cursor;
#[cfg(feature = "parsing")]
@ -117,9 +138,18 @@ pub trait Token: private::Sealed {
fn display() -> &'static str;
}
#[cfg(feature = "parsing")]
mod private {
use proc_macro2::Span;
#[cfg(feature = "parsing")]
pub trait Sealed {}
/// Support writing `token.span` rather than `token.spans[0]` on tokens that
/// hold a single span.
#[repr(C)]
pub struct WithSpan {
pub span: Span,
}
}
#[cfg(feature = "parsing")]
@ -285,10 +315,31 @@ macro_rules! define_keywords {
};
}
macro_rules! impl_deref_if_len_is_1 {
($name:ident/1) => {
impl Deref for $name {
type Target = WithSpan;
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const Self as *const WithSpan) }
}
}
impl DerefMut for $name {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self as *mut Self as *mut WithSpan) }
}
}
};
($name:ident/$len:tt) => {};
}
macro_rules! define_punctuation_structs {
($($token:tt pub struct $name:ident/$len:tt #[$doc:meta])*) => {
$(
#[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
#[repr(C)]
#[$doc]
///
/// Don't try to remember the name of this type -- use the [`Token!`]
@ -336,6 +387,8 @@ macro_rules! define_punctuation_structs {
impl Hash for $name {
fn hash<H: Hasher>(&self, _state: &mut H) {}
}
impl_deref_if_len_is_1!($name/$len);
)*
};
}
@ -450,7 +503,7 @@ define_punctuation_structs! {
#[cfg(feature = "printing")]
impl ToTokens for Underscore {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append(Ident::new("_", self.spans[0]));
tokens.append(Ident::new("_", self.span));
}
}