Bug 1719535 - Part 12. Update icu_provider_macros not to depend on syn 1.0. r=supply-chain-reviewers,firefox-build-system-reviewers,glandium

Depends on D167745

Differential Revision: https://phabricator.services.mozilla.com/D184369
This commit is contained in:
Makoto Kato 2023-08-07 06:24:03 +00:00
Родитель db15d49824
Коммит 16b2031a07
105 изменённых файлов: 223 добавлений и 57698 удалений

5
Cargo.lock сгенерированный
Просмотреть файл

@ -2666,12 +2666,11 @@ dependencies = [
[[package]]
name = "icu_provider_macros"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b728b9421e93eff1d9f8681101b78fa745e0748c95c655c83f337044a7e10"
source = "git+https://github.com/unicode-org/icu4x?rev=14e9a3a9857be74582abe2dfa7ab799c5eaac873#14e9a3a9857be74582abe2dfa7ab799c5eaac873"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.107",
"syn",
]
[[package]]

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

@ -210,6 +210,7 @@ webext-storage = { git = "https://github.com/mozilla/application-services", rev
# ICU4X 1.2 with synstructure 0.13.x / syn 2.x. When updating to next version, this should be removed.
diplomat = { git = "https://github.com/rust-diplomat/diplomat", rev = "8d125999893fedfdf30595e97334c21ec4b18da9" }
diplomat-runtime = { git = "https://github.com/rust-diplomat/diplomat", rev = "8d125999893fedfdf30595e97334c21ec4b18da9" }
icu_provider_macros = { git = "https://github.com/unicode-org/icu4x", rev = "14e9a3a9857be74582abe2dfa7ab799c5eaac873" }
yoke-derive = { git = "https://github.com/unicode-org/icu4x", rev = "14e9a3a9857be74582abe2dfa7ab799c5eaac873" }
zerofrom-derive = { git = "https://github.com/unicode-org/icu4x", rev = "14e9a3a9857be74582abe2dfa7ab799c5eaac873" }
zerovec-derive = { git = "https://github.com/unicode-org/icu4x", rev = "14e9a3a9857be74582abe2dfa7ab799c5eaac873" }

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

@ -1877,6 +1877,11 @@ criteria = "safe-to-deploy"
version = "1.2.0"
notes = "This crate is macros for ICU4X's data provider implementer. This has no unsafe code and uses no ambient capabilities."
[[audits.icu_provider_macros]]
who = "Makoto Kato <m_kato@ga2.so-net.ne.jp>"
criteria = "safe-to-deploy"
delta = "1.2.0 -> 1.2.0@git:14e9a3a9857be74582abe2dfa7ab799c5eaac873"
[[audits.icu_segmenter]]
who = "Makoto Kato <m_kato@ga2.so-net.ne.jp>"
criteria = "safe-to-deploy"

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

@ -76,6 +76,10 @@ notes = "Used for fuzzing."
criteria = "safe-to-run"
notes = "Used for testing."
[policy.icu_provider_macros]
audit-as-crates-io = true
notes = "Upstream version not to use syn 1.x"
[policy.icu_testdata]
audit-as-crates-io = false
notes = "Customized ICU4X baked data only that Gecko wants"

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

@ -1 +1 @@
{"files":{"Cargo.toml":"8c8bf034fddb240e039b17b73842d93216c87c0f8a0d3486302187a004bcb461","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"f9f95075851c9c3b7d0559c25794ebcad5dee957c7fb27c343418a3324f15b8a","src/lib.rs":"1376fd3fb06bc354eb24c97b1bf47f80b0d408644f1aa5885db3f374aa39f74a","src/tests.rs":"3a34d070c375eade0808b7dbe11157450bc62d5a6f056c38ac129104487d8ea9"},"package":"dd8b728b9421e93eff1d9f8681101b78fa745e0748c95c655c83f337044a7e10"}
{"files":{"Cargo.toml":"b9ec4f3a3fc22a8cc088cb7f9ac0b6eb84bc436a983892b56650b73d08a6cef1","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"f9f95075851c9c3b7d0559c25794ebcad5dee957c7fb27c343418a3324f15b8a","src/lib.rs":"c0054aa93de7c712039bcbf3c8cae870595161d65b3ede67cebdd566469258df","src/tests.rs":"ea671ded3510a3b7ac8707c8059974da4468858f56250c2d7350edd850620d25"},"package":null}

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

@ -33,14 +33,20 @@ repository = "https://github.com/unicode-org/icu4x"
path = "src/lib.rs"
proc-macro = true
[dependencies.proc-macro2]
version = "1.0.27"
[dependencies.quote]
version = "1.0.9"
[dependencies]
proc-macro2 = "1.0.27"
quote = "1.0.9"
[dependencies.syn]
version = "1.0.73"
features = ["full"]
version = "2"
features = [
"full",
"parsing",
]
[dev-dependencies]
[dev-dependencies.icu]
path = "../../components/icu"
[dev-dependencies.icu_provider]
path = "../core"
features = ["macros"]

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

@ -24,16 +24,16 @@
extern crate proc_macro;
use proc_macro::TokenStream;
use proc_macro2::Span;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::parenthesized;
use syn::parse::{self, Parse, ParseStream};
use syn::parse_macro_input;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::AttributeArgs;
use syn::DeriveInput;
use syn::Lit;
use syn::Meta;
use syn::NestedMeta;
use syn::{Ident, LitStr, Path, Token};
#[cfg(test)]
mod tests;
@ -92,12 +92,172 @@ mod tests;
/// implement it on the markers.
pub fn data_struct(attr: TokenStream, item: TokenStream) -> TokenStream {
TokenStream::from(data_struct_impl(
parse_macro_input!(attr as AttributeArgs),
parse_macro_input!(attr as DataStructArgs),
parse_macro_input!(item as DeriveInput),
))
}
fn data_struct_impl(attr: AttributeArgs, input: DeriveInput) -> TokenStream2 {
pub(crate) struct DataStructArgs {
args: Punctuated<DataStructArg, Token![,]>,
}
impl Parse for DataStructArgs {
fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
let args = input.parse_terminated(DataStructArg::parse, Token![,])?;
Ok(Self { args })
}
}
struct DataStructArg {
marker_name: Path,
key_lit: Option<LitStr>,
fallback_by: Option<LitStr>,
extension_key: Option<LitStr>,
fallback_supplement: Option<LitStr>,
}
impl DataStructArg {
fn new(marker_name: Path) -> Self {
Self {
marker_name,
key_lit: None,
fallback_by: None,
extension_key: None,
fallback_supplement: None,
}
}
}
impl Parse for DataStructArg {
fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
let path: Path = input.parse()?;
fn at_most_one_option<T>(
o: &mut Option<T>,
new: T,
name: &str,
span: Span,
) -> parse::Result<()> {
if o.replace(new).is_some() {
Err(parse::Error::new(
span,
format!("marker() cannot contain multiple {name}s"),
))
} else {
Ok(())
}
}
if path.is_ident("marker") {
let content;
let paren = parenthesized!(content in input);
let mut marker_name: Option<Path> = None;
let mut key_lit: Option<LitStr> = None;
let mut fallback_by: Option<LitStr> = None;
let mut extension_key: Option<LitStr> = None;
let mut fallback_supplement: Option<LitStr> = None;
let punct = content.parse_terminated(DataStructMarkerArg::parse, Token![,])?;
for entry in punct.into_iter() {
match entry {
DataStructMarkerArg::Path(path) => {
at_most_one_option(&mut marker_name, path, "marker", input.span())?;
}
DataStructMarkerArg::NameValue(name, value) => {
if name == "fallback_by" {
at_most_one_option(
&mut fallback_by,
value,
"fallback_by",
paren.span.join(),
)?;
} else if name == "extension_key" {
at_most_one_option(
&mut extension_key,
value,
"extension_key",
paren.span.join(),
)?;
} else if name == "fallback_supplement" {
at_most_one_option(
&mut fallback_supplement,
value,
"fallback_supplement",
paren.span.join(),
)?;
} else {
return Err(parse::Error::new(
name.span(),
format!("unknown option {name} in marker()"),
));
}
}
DataStructMarkerArg::Lit(lit) => {
at_most_one_option(&mut key_lit, lit, "literal key", input.span())?;
}
}
}
let marker_name = if let Some(marker_name) = marker_name {
marker_name
} else {
return Err(parse::Error::new(
input.span(),
"marker() must contain a marker!",
));
};
Ok(Self {
marker_name,
key_lit,
fallback_by,
extension_key,
fallback_supplement,
})
} else {
let mut this = DataStructArg::new(path);
let lookahead = input.lookahead1();
if lookahead.peek(Token![=]) {
let _t: Token![=] = input.parse()?;
let lit: LitStr = input.parse()?;
this.key_lit = Some(lit);
Ok(this)
} else {
Ok(this)
}
}
}
}
/// A single argument to `marker()` in `#[data_struct(..., marker(...), ...)]
enum DataStructMarkerArg {
Path(Path),
NameValue(Ident, LitStr),
Lit(LitStr),
}
impl Parse for DataStructMarkerArg {
fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(LitStr) {
Ok(DataStructMarkerArg::Lit(input.parse()?))
} else {
let path: Path = input.parse()?;
let lookahead = input.lookahead1();
if lookahead.peek(Token![=]) {
let _tok: Token![=] = input.parse()?;
let ident = path.get_ident().ok_or_else(|| {
parse::Error::new(path.span(), "Expected identifier before `=`, found path")
})?;
Ok(DataStructMarkerArg::NameValue(
ident.clone(),
input.parse()?,
))
} else {
Ok(DataStructMarkerArg::Path(path))
}
}
}
}
fn data_struct_impl(attr: DataStructArgs, input: DeriveInput) -> TokenStream2 {
if input.generics.type_params().count() > 0 {
return syn::Error::new(
input.generics.span(),
@ -126,7 +286,7 @@ fn data_struct_impl(attr: AttributeArgs, input: DeriveInput) -> TokenStream2 {
let bake_derive = input
.attrs
.iter()
.find(|a| a.path.is_ident("databake"))
.find(|a| a.path().is_ident("databake"))
.map(|a| {
quote! {
#[derive(databake::Bake)]
@ -137,74 +297,22 @@ fn data_struct_impl(attr: AttributeArgs, input: DeriveInput) -> TokenStream2 {
let mut result = TokenStream2::new();
for single_attr in attr.into_iter() {
let mut marker_name: Option<syn::Path> = None;
let mut key_lit: Option<syn::LitStr> = None;
let mut fallback_by: Option<syn::LitStr> = None;
let mut extension_key: Option<syn::LitStr> = None;
let mut fallback_supplement: Option<syn::LitStr> = None;
for single_attr in attr.args.into_iter() {
let DataStructArg {
marker_name,
key_lit,
fallback_by,
extension_key,
fallback_supplement,
} = single_attr;
match single_attr {
NestedMeta::Meta(Meta::List(meta_list)) => {
match meta_list.path.get_ident() {
Some(ident) if ident.to_string().as_str() == "marker" => (),
_ => panic!("Meta list must be `marker(...)`"),
}
for inner_meta in meta_list.nested.into_iter() {
match inner_meta {
NestedMeta::Meta(Meta::Path(path)) => {
marker_name = Some(path);
}
NestedMeta::Lit(Lit::Str(lit_str)) => {
key_lit = Some(lit_str);
}
NestedMeta::Meta(Meta::NameValue(name_value)) => {
let lit_str = match name_value.lit {
Lit::Str(lit_str) => lit_str,
_ => panic!("Values in marker() must be strings"),
};
let name_ident_str = match name_value.path.get_ident() {
Some(ident) => ident.to_string(),
None => panic!("Names in marker() must be identifiers"),
};
match name_ident_str.as_str() {
"fallback_by" => fallback_by = Some(lit_str),
"extension_key" => extension_key = Some(lit_str),
"fallback_supplement" => fallback_supplement = Some(lit_str),
_ => panic!("Invalid argument name in marker()"),
}
}
_ => panic!("Invalid argument in marker()"),
}
}
}
NestedMeta::Meta(Meta::NameValue(name_value)) => {
marker_name = Some(name_value.path);
match name_value.lit {
syn::Lit::Str(lit_str) => key_lit = Some(lit_str),
_ => panic!("Key must be a string"),
};
}
NestedMeta::Meta(Meta::Path(path)) => {
marker_name = Some(path);
}
_ => {
panic!("Invalid attribute to #[data_struct]")
}
}
let marker_name = match marker_name {
Some(path) => path,
None => panic!("#[data_struct] arguments must include a marker name"),
};
let docs = if let Some(key_lit) = &key_lit {
let fallback_by_docs_str = match &fallback_by {
Some(fallback_by) => fallback_by.value(),
let docs = if let Some(ref key_lit) = key_lit {
let fallback_by_docs_str = match fallback_by {
Some(ref fallback_by) => fallback_by.value(),
None => "language (default)".to_string(),
};
let extension_key_docs_str = match &extension_key {
Some(extension_key) => extension_key.value(),
let extension_key_docs_str = match extension_key {
Some(ref extension_key) => extension_key.value(),
None => "none (default)".to_string(),
};
format!("Marker type for [`{}`]: \"{}\"\n\n- Fallback priority: {}\n- Extension keyword: {}", name, key_lit.value(), fallback_by_docs_str, extension_key_docs_str)
@ -221,7 +329,7 @@ fn data_struct_impl(attr: AttributeArgs, input: DeriveInput) -> TokenStream2 {
}
));
if let Some(key_lit) = &key_lit {
if let Some(key_lit) = key_lit {
let key_str = key_lit.value();
let fallback_by_expr = if let Some(fallback_by_lit) = fallback_by {
match fallback_by_lit.value().as_str() {

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

@ -5,16 +5,9 @@
use crate::data_struct_impl;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{DeriveInput, NestedMeta};
fn check(attr: Vec<TokenStream2>, item: TokenStream2, expected: TokenStream2) {
let actual = data_struct_impl(
attr.into_iter()
.map(syn::parse2)
.collect::<syn::parse::Result<Vec<NestedMeta>>>()
.unwrap(),
syn::parse2::<DeriveInput>(item).unwrap(),
);
fn check(attr: TokenStream2, item: TokenStream2, expected: TokenStream2) {
let actual = data_struct_impl(syn::parse2(attr).unwrap(), syn::parse2(item).unwrap());
assert_eq!(expected.to_string(), actual.to_string());
}
@ -23,7 +16,7 @@ fn check(attr: Vec<TokenStream2>, item: TokenStream2, expected: TokenStream2) {
fn test_basic() {
// #[data_struct]
check(
vec![],
quote!(),
quote!(
pub struct FooV1;
),
@ -38,7 +31,7 @@ fn test_basic() {
fn test_data_marker() {
// #[data_struct(FooV1Marker)]
check(
vec![quote!(FooV1Marker)],
quote!(FooV1Marker),
quote!(
pub struct FooV1;
),
@ -58,7 +51,7 @@ fn test_data_marker() {
fn test_keyed_data_marker() {
// #[data_struct(BarV1Marker = "demo/bar@1")]
check(
vec![quote!(BarV1Marker = "demo/bar@1")],
quote!(BarV1Marker = "demo/bar@1"),
quote!(
pub struct FooV1;
),
@ -87,10 +80,10 @@ fn test_keyed_data_marker() {
fn test_multi_named_keyed_data_marker() {
// #[data_struct(FooV1Marker, BarV1Marker = "demo/bar@1", BazV1Marker = "demo/baz@1")]
check(
vec![
quote!(FooV1Marker),
quote!(BarV1Marker = "demo/bar@1"),
quote!(BazV1Marker = "demo/baz@1"),
quote![
FooV1Marker,
BarV1Marker = "demo/bar@1",
BazV1Marker = "demo/baz@1",
],
quote!(
pub struct FooV1<'data>;
@ -138,7 +131,7 @@ fn test_multi_named_keyed_data_marker() {
#[test]
fn test_databake() {
check(
vec![quote!(BarV1Marker = "demo/bar@1")],
quote!(BarV1Marker = "demo/bar@1"),
quote!(
#[databake(path = test::path)]
pub struct FooV1;
@ -171,15 +164,15 @@ fn test_databake() {
fn test_attributes() {
// #[data_struct(FooV1Marker, marker(BarV1Marker, "demo/bar@1", fallback_by = "region", extension_kw = "ca"))]
check(
vec![
quote!(FooV1Marker),
quote!(marker(
quote![
FooV1Marker,
marker(
BarV1Marker,
"demo/bar@1",
fallback_by = "region",
extension_key = "ca",
fallback_supplement = "collation"
)),
),
],
quote!(
pub struct FooV1<'data>;

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

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

@ -1,147 +0,0 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
rust-version = "1.31"
name = "syn"
version = "1.0.107"
authors = ["David Tolnay <dtolnay@gmail.com>"]
include = [
"/benches/**",
"/build.rs",
"/Cargo.toml",
"/LICENSE-APACHE",
"/LICENSE-MIT",
"/README.md",
"/src/**",
"/tests/**",
]
description = "Parser for Rust source code"
documentation = "https://docs.rs/syn"
readme = "README.md"
keywords = [
"macros",
"syn",
]
categories = [
"development-tools::procedural-macro-helpers",
"parser-implementations",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/dtolnay/syn"
[package.metadata.docs.rs]
all-features = true
targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = [
"--cfg",
"doc_cfg",
]
[package.metadata.playground]
features = [
"full",
"visit",
"visit-mut",
"fold",
"extra-traits",
]
[lib]
doc-scrape-examples = false
[[bench]]
name = "rust"
harness = false
required-features = [
"full",
"parsing",
]
[[bench]]
name = "file"
required-features = [
"full",
"parsing",
]
[dependencies.proc-macro2]
version = "1.0.46"
default-features = false
[dependencies.quote]
version = "1.0"
optional = true
default-features = false
[dependencies.unicode-ident]
version = "1.0"
[dev-dependencies.anyhow]
version = "1.0"
[dev-dependencies.automod]
version = "1.0"
[dev-dependencies.flate2]
version = "1.0"
[dev-dependencies.insta]
version = "1.0"
[dev-dependencies.rayon]
version = "1.0"
[dev-dependencies.ref-cast]
version = "1.0"
[dev-dependencies.regex]
version = "1.0"
[dev-dependencies.reqwest]
version = "0.11"
features = ["blocking"]
[dev-dependencies.syn-test-suite]
version = "0"
[dev-dependencies.tar]
version = "0.4.16"
[dev-dependencies.termcolor]
version = "1.0"
[dev-dependencies.walkdir]
version = "2.1"
[features]
clone-impls = []
default = [
"derive",
"parsing",
"printing",
"clone-impls",
"proc-macro",
]
derive = []
extra-traits = []
fold = []
full = []
parsing = []
printing = ["quote"]
proc-macro = [
"proc-macro2/proc-macro",
"quote/proc-macro",
]
test = ["syn-test-suite/all-features"]
visit = []
visit-mut = []

201
third_party/rust/syn-1.0.107/LICENSE-APACHE поставляемый
Просмотреть файл

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

23
third_party/rust/syn-1.0.107/LICENSE-MIT поставляемый
Просмотреть файл

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

285
third_party/rust/syn-1.0.107/README.md поставляемый
Просмотреть файл

@ -1,285 +0,0 @@
Parser for Rust source code
===========================
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/syn-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/syn)
[<img alt="crates.io" src="https://img.shields.io/crates/v/syn.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/syn)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-syn-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/syn)
[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/syn/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/syn/actions?query=branch%3Amaster)
Syn is a parsing library for parsing a stream of Rust tokens into a syntax tree
of Rust source code.
Currently this library is geared toward use in Rust procedural macros, but
contains some APIs that may be useful more generally.
- **Data structures** — Syn provides a complete syntax tree that can represent
any valid Rust source code. The syntax tree is rooted at [`syn::File`] which
represents a full source file, but there are other entry points that may be
useful to procedural macros including [`syn::Item`], [`syn::Expr`] and
[`syn::Type`].
- **Derives** — Of particular interest to derive macros is [`syn::DeriveInput`]
which is any of the three legal input items to a derive macro. An example
below shows using this type in a library that can derive implementations of a
user-defined trait.
- **Parsing** — Parsing in Syn is built around [parser functions] with the
signature `fn(ParseStream) -> Result<T>`. Every syntax tree node defined by
Syn is individually parsable and may be used as a building block for custom
syntaxes, or you may dream up your own brand new syntax without involving any
of our syntax tree types.
- **Location information** — Every token parsed by Syn is associated with a
`Span` that tracks line and column information back to the source of that
token. These spans allow a procedural macro to display detailed error messages
pointing to all the right places in the user's code. There is an example of
this below.
- **Feature flags** — Functionality is aggressively feature gated so your
procedural macros enable only what they need, and do not pay in compile time
for all the rest.
[`syn::File`]: https://docs.rs/syn/1.0/syn/struct.File.html
[`syn::Item`]: https://docs.rs/syn/1.0/syn/enum.Item.html
[`syn::Expr`]: https://docs.rs/syn/1.0/syn/enum.Expr.html
[`syn::Type`]: https://docs.rs/syn/1.0/syn/enum.Type.html
[`syn::DeriveInput`]: https://docs.rs/syn/1.0/syn/struct.DeriveInput.html
[parser functions]: https://docs.rs/syn/1.0/syn/parse/index.html
*Version requirement: Syn supports rustc 1.31 and up.*
[*Release notes*](https://github.com/dtolnay/syn/releases)
<br>
## Resources
The best way to learn about procedural macros is by writing some. Consider
working through [this procedural macro workshop][workshop] to get familiar with
the different types of procedural macros. The workshop contains relevant links
into the Syn documentation as you work through each project.
[workshop]: https://github.com/dtolnay/proc-macro-workshop
<br>
## Example of a derive macro
The canonical derive macro using Syn looks like this. We write an ordinary Rust
function tagged with a `proc_macro_derive` attribute and the name of the trait
we are deriving. Any time that derive appears in the user's code, the Rust
compiler passes their data structure as tokens into our macro. We get to execute
arbitrary Rust code to figure out what to do with those tokens, then hand some
tokens back to the compiler to compile into the user's crate.
[`TokenStream`]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html
```toml
[dependencies]
syn = "1.0"
quote = "1.0"
[lib]
proc-macro = true
```
```rust
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
#[proc_macro_derive(MyMacro)]
pub fn my_macro(input: TokenStream) -> TokenStream {
// Parse the input tokens into a syntax tree
let input = parse_macro_input!(input as DeriveInput);
// Build the output, possibly using quasi-quotation
let expanded = quote! {
// ...
};
// Hand the output tokens back to the compiler
TokenStream::from(expanded)
}
```
The [`heapsize`] example directory shows a complete working implementation of a
derive macro. It works on any Rust compiler 1.31+. The example derives a
`HeapSize` trait which computes an estimate of the amount of heap memory owned
by a value.
[`heapsize`]: examples/heapsize
```rust
pub trait HeapSize {
/// Total number of bytes of heap memory owned by `self`.
fn heap_size_of_children(&self) -> usize;
}
```
The derive macro allows users to write `#[derive(HeapSize)]` on data structures
in their program.
```rust
#[derive(HeapSize)]
struct Demo<'a, T: ?Sized> {
a: Box<T>,
b: u8,
c: &'a str,
d: String,
}
```
<br>
## Spans and error reporting
The token-based procedural macro API provides great control over where the
compiler's error messages are displayed in user code. Consider the error the
user sees if one of their field types does not implement `HeapSize`.
```rust
#[derive(HeapSize)]
struct Broken {
ok: String,
bad: std::thread::Thread,
}
```
By tracking span information all the way through the expansion of a procedural
macro as shown in the `heapsize` example, token-based macros in Syn are able to
trigger errors that directly pinpoint the source of the problem.
```console
error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
--> src/main.rs:7:5
|
7 | bad: std::thread::Thread,
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `std::thread::Thread`
```
<br>
## Parsing a custom syntax
The [`lazy-static`] example directory shows the implementation of a
`functionlike!(...)` procedural macro in which the input tokens are parsed using
Syn's parsing API.
[`lazy-static`]: examples/lazy-static
The example reimplements the popular `lazy_static` crate from crates.io as a
procedural macro.
```rust
lazy_static! {
static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
}
```
The implementation shows how to trigger custom warnings and error messages on
the macro input.
```console
warning: come on, pick a more creative name
--> src/main.rs:10:16
|
10 | static ref FOO: String = "lazy_static".to_owned();
| ^^^
```
<br>
## Testing
When testing macros, we often care not just that the macro can be used
successfully but also that when the macro is provided with invalid input it
produces maximally helpful error messages. Consider using the [`trybuild`] crate
to write tests for errors that are emitted by your macro or errors detected by
the Rust compiler in the expanded code following misuse of the macro. Such tests
help avoid regressions from later refactors that mistakenly make an error no
longer trigger or be less helpful than it used to be.
[`trybuild`]: https://github.com/dtolnay/trybuild
<br>
## Debugging
When developing a procedural macro it can be helpful to look at what the
generated code looks like. Use `cargo rustc -- -Zunstable-options
--pretty=expanded` or the [`cargo expand`] subcommand.
[`cargo expand`]: https://github.com/dtolnay/cargo-expand
To show the expanded code for some crate that uses your procedural macro, run
`cargo expand` from that crate. To show the expanded code for one of your own
test cases, run `cargo expand --test the_test_case` where the last argument is
the name of the test file without the `.rs` extension.
This write-up by Brandon W Maister discusses debugging in more detail:
[Debugging Rust's new Custom Derive system][debugging].
[debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
<br>
## Optional features
Syn puts a lot of functionality behind optional features in order to optimize
compile time for the most common use cases. The following features are
available.
- **`derive`** *(enabled by default)* — Data structures for representing the
possible input to a derive macro, including structs and enums and types.
- **`full`** — Data structures for representing the syntax tree of all valid
Rust source code, including items and expressions.
- **`parsing`** *(enabled by default)* — Ability to parse input tokens into a
syntax tree node of a chosen type.
- **`printing`** *(enabled by default)* — Ability to print a syntax tree node as
tokens of Rust source code.
- **`visit`** — Trait for traversing a syntax tree.
- **`visit-mut`** — Trait for traversing and mutating in place a syntax tree.
- **`fold`** — Trait for transforming an owned syntax tree.
- **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
types.
- **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree
types.
- **`proc-macro`** *(enabled by default)* — Runtime dependency on the dynamic
library libproc_macro from rustc toolchain.
<br>
## Proc macro shim
Syn operates on the token representation provided by the [proc-macro2] crate
from crates.io rather than using the compiler's built in proc-macro crate
directly. This enables code using Syn to execute outside of the context of a
procedural macro, such as in unit tests or build.rs, and we avoid needing
incompatible ecosystems for proc macros vs non-macro use cases.
In general all of your code should be written against proc-macro2 rather than
proc-macro. The one exception is in the signatures of procedural macro entry
points, which are required by the language to use `proc_macro::TokenStream`.
The proc-macro2 crate will automatically detect and use the compiler's data
structures when a procedural macro is active.
[proc-macro2]: https://docs.rs/proc-macro2/1.0/proc_macro2/
<br>
#### License
<sup>
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
</sup>
<br>
<sub>
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.
</sub>

55
third_party/rust/syn-1.0.107/benches/file.rs поставляемый
Просмотреть файл

@ -1,55 +0,0 @@
// $ cargo bench --features full,test --bench file
#![feature(rustc_private, test)]
#![recursion_limit = "1024"]
#![allow(
clippy::items_after_statements,
clippy::missing_panics_doc,
clippy::must_use_candidate
)]
extern crate test;
#[macro_use]
#[path = "../tests/macros/mod.rs"]
mod macros;
#[path = "../tests/common/mod.rs"]
mod common;
#[path = "../tests/repo/mod.rs"]
pub mod repo;
use proc_macro2::{Span, TokenStream};
use std::fs;
use std::str::FromStr;
use syn::parse::{ParseStream, Parser};
use test::Bencher;
const FILE: &str = "tests/rust/library/core/src/str/mod.rs";
fn get_tokens() -> TokenStream {
repo::clone_rust();
let content = fs::read_to_string(FILE).unwrap();
TokenStream::from_str(&content).unwrap()
}
#[bench]
fn baseline(b: &mut Bencher) {
let tokens = get_tokens();
b.iter(|| drop(tokens.clone()));
}
#[bench]
fn create_token_buffer(b: &mut Bencher) {
let tokens = get_tokens();
fn immediate_fail(_input: ParseStream) -> syn::Result<()> {
Err(syn::Error::new(Span::call_site(), ""))
}
b.iter(|| immediate_fail.parse2(tokens.clone()));
}
#[bench]
fn parse_file(b: &mut Bencher) {
let tokens = get_tokens();
b.iter(|| syn::parse2::<syn::File>(tokens.clone()));
}

170
third_party/rust/syn-1.0.107/benches/rust.rs поставляемый
Просмотреть файл

@ -1,170 +0,0 @@
// $ cargo bench --features full,test --bench rust
//
// Syn only, useful for profiling:
// $ RUSTFLAGS='--cfg syn_only' cargo build --release --features full,test --bench rust
#![cfg_attr(not(syn_only), feature(rustc_private))]
#![recursion_limit = "1024"]
#![allow(clippy::cast_lossless, clippy::unnecessary_wraps)]
#[macro_use]
#[path = "../tests/macros/mod.rs"]
mod macros;
#[path = "../tests/common/mod.rs"]
mod common;
#[path = "../tests/repo/mod.rs"]
mod repo;
use std::fs;
use std::time::{Duration, Instant};
#[cfg(not(syn_only))]
mod tokenstream_parse {
use proc_macro2::TokenStream;
use std::str::FromStr;
pub fn bench(content: &str) -> Result<(), ()> {
TokenStream::from_str(content).map(drop).map_err(drop)
}
}
mod syn_parse {
pub fn bench(content: &str) -> Result<(), ()> {
syn::parse_file(content).map(drop).map_err(drop)
}
}
#[cfg(not(syn_only))]
mod librustc_parse {
extern crate rustc_data_structures;
extern crate rustc_error_messages;
extern crate rustc_errors;
extern crate rustc_parse;
extern crate rustc_session;
extern crate rustc_span;
use rustc_data_structures::sync::Lrc;
use rustc_error_messages::FluentBundle;
use rustc_errors::{emitter::Emitter, translation::Translate, Diagnostic, Handler};
use rustc_session::parse::ParseSess;
use rustc_span::source_map::{FilePathMapping, SourceMap};
use rustc_span::{edition::Edition, FileName};
pub fn bench(content: &str) -> Result<(), ()> {
struct SilentEmitter;
impl Emitter for SilentEmitter {
fn emit_diagnostic(&mut self, _diag: &Diagnostic) {}
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
None
}
}
impl Translate for SilentEmitter {
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
None
}
fn fallback_fluent_bundle(&self) -> &FluentBundle {
panic!("silent emitter attempted to translate a diagnostic");
}
}
rustc_span::create_session_if_not_set_then(Edition::Edition2018, |_| {
let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
let emitter = Box::new(SilentEmitter);
let handler = Handler::with_emitter(false, None, emitter);
let sess = ParseSess::with_span_handler(handler, cm);
if let Err(diagnostic) = rustc_parse::parse_crate_from_source_str(
FileName::Custom("bench".to_owned()),
content.to_owned(),
&sess,
) {
diagnostic.cancel();
return Err(());
};
Ok(())
})
}
}
#[cfg(not(syn_only))]
mod read_from_disk {
pub fn bench(content: &str) -> Result<(), ()> {
_ = content;
Ok(())
}
}
fn exec(mut codepath: impl FnMut(&str) -> Result<(), ()>) -> Duration {
let begin = Instant::now();
let mut success = 0;
let mut total = 0;
walkdir::WalkDir::new("tests/rust/src")
.into_iter()
.filter_entry(repo::base_dir_filter)
.for_each(|entry| {
let entry = entry.unwrap();
let path = entry.path();
if path.is_dir() {
return;
}
let content = fs::read_to_string(path).unwrap();
let ok = codepath(&content).is_ok();
success += ok as usize;
total += 1;
if !ok {
eprintln!("FAIL {}", path.display());
}
});
assert_eq!(success, total);
begin.elapsed()
}
fn main() {
repo::clone_rust();
macro_rules! testcases {
($($(#[$cfg:meta])* $name:ident,)*) => {
[
$(
$(#[$cfg])*
(stringify!($name), $name::bench as fn(&str) -> Result<(), ()>),
)*
]
};
}
#[cfg(not(syn_only))]
{
let mut lines = 0;
let mut files = 0;
exec(|content| {
lines += content.lines().count();
files += 1;
Ok(())
});
eprintln!("\n{} lines in {} files", lines, files);
}
for (name, f) in testcases!(
#[cfg(not(syn_only))]
read_from_disk,
#[cfg(not(syn_only))]
tokenstream_parse,
syn_parse,
#[cfg(not(syn_only))]
librustc_parse,
) {
eprint!("{:20}", format!("{}:", name));
let elapsed = exec(f);
eprintln!(
"elapsed={}.{:03}s",
elapsed.as_secs(),
elapsed.subsec_millis(),
);
}
eprintln!();
}

51
third_party/rust/syn-1.0.107/build.rs поставляемый
Просмотреть файл

@ -1,51 +0,0 @@
use std::env;
use std::process::Command;
use std::str;
// 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 < 36 {
println!("cargo:rustc-cfg=syn_omit_await_from_token_macro");
}
if compiler.minor < 39 {
println!("cargo:rustc-cfg=syn_no_const_vec_new");
}
if compiler.minor < 40 {
println!("cargo:rustc-cfg=syn_no_non_exhaustive");
}
if compiler.minor < 56 {
println!("cargo:rustc-cfg=syn_no_negative_literal_parse");
}
if !compiler.nightly {
println!("cargo:rustc-cfg=syn_disable_nightly_tests");
}
}
struct Compiler {
minor: u32,
nightly: bool,
}
fn rustc_version() -> Option<Compiler> {
let rustc = env::var_os("RUSTC")?;
let output = Command::new(rustc).arg("--version").output().ok()?;
let version = str::from_utf8(&output.stdout).ok()?;
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
let minor = pieces.next()?.parse().ok()?;
let nightly = version.contains("nightly") || version.ends_with("-dev");
Some(Compiler { minor, nightly })
}

662
third_party/rust/syn-1.0.107/src/attr.rs поставляемый
Просмотреть файл

@ -1,662 +0,0 @@
use super::*;
use crate::punctuated::Punctuated;
use proc_macro2::TokenStream;
use std::iter;
use std::slice;
#[cfg(feature = "parsing")]
use crate::parse::{Parse, ParseBuffer, ParseStream, Parser, Result};
#[cfg(feature = "parsing")]
use crate::punctuated::Pair;
ast_struct! {
/// An attribute like `#[repr(transparent)]`.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
///
/// <br>
///
/// # Syntax
///
/// Rust has six types of attributes.
///
/// - Outer attributes like `#[repr(transparent)]`. These appear outside or
/// in front of the item they describe.
/// - Inner attributes like `#![feature(proc_macro)]`. These appear inside
/// of the item they describe, usually a module.
/// - Outer doc comments like `/// # Example`.
/// - Inner doc comments like `//! Please file an issue`.
/// - Outer block comments `/** # Example */`.
/// - Inner block comments `/*! Please file an issue */`.
///
/// The `style` field of type `AttrStyle` distinguishes whether an attribute
/// is outer or inner. Doc comments and block comments are promoted to
/// attributes, as this is how they are processed by the compiler and by
/// `macro_rules!` macros.
///
/// The `path` field gives the possibly colon-delimited path against which
/// the attribute is resolved. It is equal to `"doc"` for desugared doc
/// comments. The `tokens` field contains the rest of the attribute body as
/// tokens.
///
/// ```text
/// #[derive(Copy)] #[crate::precondition x < 5]
/// ^^^^^^~~~~~~ ^^^^^^^^^^^^^^^^^^^ ~~~~~
/// path tokens path tokens
/// ```
///
/// <br>
///
/// # Parsing from tokens to Attribute
///
/// This type does not implement the [`Parse`] trait and thus cannot be
/// parsed directly by [`ParseStream::parse`]. Instead use
/// [`ParseStream::call`] with one of the two parser functions
/// [`Attribute::parse_outer`] or [`Attribute::parse_inner`] depending on
/// which you intend to parse.
///
/// [`Parse`]: parse::Parse
/// [`ParseStream::parse`]: parse::ParseBuffer::parse
/// [`ParseStream::call`]: parse::ParseBuffer::call
///
/// ```
/// use syn::{Attribute, Ident, Result, Token};
/// use syn::parse::{Parse, ParseStream};
///
/// // Parses a unit struct with attributes.
/// //
/// // #[path = "s.tmpl"]
/// // struct S;
/// struct UnitStruct {
/// attrs: Vec<Attribute>,
/// struct_token: Token![struct],
/// name: Ident,
/// semi_token: Token![;],
/// }
///
/// impl Parse for UnitStruct {
/// fn parse(input: ParseStream) -> Result<Self> {
/// Ok(UnitStruct {
/// attrs: input.call(Attribute::parse_outer)?,
/// struct_token: input.parse()?,
/// name: input.parse()?,
/// semi_token: input.parse()?,
/// })
/// }
/// }
/// ```
///
/// <p><br></p>
///
/// # Parsing from Attribute to structured arguments
///
/// The grammar of attributes in Rust is very flexible, which makes the
/// syntax tree not that useful on its own. In particular, arguments of the
/// attribute are held in an arbitrary `tokens: TokenStream`. Macros are
/// expected to check the `path` of the attribute, decide whether they
/// recognize it, and then parse the remaining tokens according to whatever
/// grammar they wish to require for that kind of attribute.
///
/// If the attribute you are parsing is expected to conform to the
/// conventional structured form of attribute, use [`parse_meta()`] to
/// obtain that structured representation. If the attribute follows some
/// other grammar of its own, use [`parse_args()`] to parse that into the
/// expected data structure.
///
/// [`parse_meta()`]: Attribute::parse_meta
/// [`parse_args()`]: Attribute::parse_args
///
/// <p><br></p>
///
/// # Doc comments
///
/// The compiler transforms doc comments, such as `/// comment` and `/*!
/// comment */`, into attributes before macros are expanded. Each comment is
/// expanded into an attribute of the form `#[doc = r"comment"]`.
///
/// As an example, the following `mod` items are expanded identically:
///
/// ```
/// # use syn::{ItemMod, parse_quote};
/// let doc: ItemMod = parse_quote! {
/// /// Single line doc comments
/// /// We write so many!
/// /**
/// * Multi-line comments...
/// * May span many lines
/// */
/// mod example {
/// //! Of course, they can be inner too
/// /*! And fit in a single line */
/// }
/// };
/// let attr: ItemMod = parse_quote! {
/// #[doc = r" Single line doc comments"]
/// #[doc = r" We write so many!"]
/// #[doc = r"
/// * Multi-line comments...
/// * May span many lines
/// "]
/// mod example {
/// #![doc = r" Of course, they can be inner too"]
/// #![doc = r" And fit in a single line "]
/// }
/// };
/// assert_eq!(doc, attr);
/// ```
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct Attribute {
pub pound_token: Token![#],
pub style: AttrStyle,
pub bracket_token: token::Bracket,
pub path: Path,
pub tokens: TokenStream,
}
}
impl Attribute {
/// Parses the content of the attribute, consisting of the path and tokens,
/// as a [`Meta`] if possible.
///
/// *This function is available only if Syn is built with the `"parsing"`
/// feature.*
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn parse_meta(&self) -> Result<Meta> {
fn clone_ident_segment(segment: &PathSegment) -> PathSegment {
PathSegment {
ident: segment.ident.clone(),
arguments: PathArguments::None,
}
}
let path = Path {
leading_colon: self
.path
.leading_colon
.as_ref()
.map(|colon| Token![::](colon.spans)),
segments: self
.path
.segments
.pairs()
.map(|pair| match pair {
Pair::Punctuated(seg, punct) => {
Pair::Punctuated(clone_ident_segment(seg), Token![::](punct.spans))
}
Pair::End(seg) => Pair::End(clone_ident_segment(seg)),
})
.collect(),
};
let parser = |input: ParseStream| parsing::parse_meta_after_path(path, input);
parse::Parser::parse2(parser, self.tokens.clone())
}
/// Parse the arguments to the attribute as a syntax tree.
///
/// This is similar to `syn::parse2::<T>(attr.tokens)` except that:
///
/// - the surrounding delimiters are *not* included in the input to the
/// parser; and
/// - the error message has a more useful span when `tokens` is empty.
///
/// ```text
/// #[my_attr(value < 5)]
/// ^^^^^^^^^ what gets parsed
/// ```
///
/// *This function is available only if Syn is built with the `"parsing"`
/// feature.*
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn parse_args<T: Parse>(&self) -> Result<T> {
self.parse_args_with(T::parse)
}
/// Parse the arguments to the attribute using the given parser.
///
/// *This function is available only if Syn is built with the `"parsing"`
/// feature.*
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn parse_args_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
let parser = |input: ParseStream| {
let args = enter_args(self, input)?;
parse::parse_stream(parser, &args)
};
parser.parse2(self.tokens.clone())
}
/// Parses zero or more outer attributes from the stream.
///
/// *This function is available only if Syn is built with the `"parsing"`
/// feature.*
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn parse_outer(input: ParseStream) -> Result<Vec<Self>> {
let mut attrs = Vec::new();
while input.peek(Token![#]) {
attrs.push(input.call(parsing::single_parse_outer)?);
}
Ok(attrs)
}
/// Parses zero or more inner attributes from the stream.
///
/// *This function is available only if Syn is built with the `"parsing"`
/// feature.*
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn parse_inner(input: ParseStream) -> Result<Vec<Self>> {
let mut attrs = Vec::new();
parsing::parse_inner(input, &mut attrs)?;
Ok(attrs)
}
}
#[cfg(feature = "parsing")]
fn expected_parentheses(attr: &Attribute) -> String {
let style = match attr.style {
AttrStyle::Outer => "#",
AttrStyle::Inner(_) => "#!",
};
let mut path = String::new();
for segment in &attr.path.segments {
if !path.is_empty() || attr.path.leading_colon.is_some() {
path += "::";
}
path += &segment.ident.to_string();
}
format!("{}[{}(...)]", style, path)
}
#[cfg(feature = "parsing")]
fn enter_args<'a>(attr: &Attribute, input: ParseStream<'a>) -> Result<ParseBuffer<'a>> {
if input.is_empty() {
let expected = expected_parentheses(attr);
let msg = format!("expected attribute arguments in parentheses: {}", expected);
return Err(crate::error::new2(
attr.pound_token.span,
attr.bracket_token.span,
msg,
));
} else if input.peek(Token![=]) {
let expected = expected_parentheses(attr);
let msg = format!("expected parentheses: {}", expected);
return Err(input.error(msg));
};
let content;
if input.peek(token::Paren) {
parenthesized!(content in input);
} else if input.peek(token::Bracket) {
bracketed!(content in input);
} else if input.peek(token::Brace) {
braced!(content in input);
} else {
return Err(input.error("unexpected token in attribute arguments"));
}
if input.is_empty() {
Ok(content)
} else {
Err(input.error("unexpected token in attribute arguments"))
}
}
ast_enum! {
/// Distinguishes between attributes that decorate an item and attributes
/// that are contained within an item.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
///
/// # Outer attributes
///
/// - `#[repr(transparent)]`
/// - `/// # Example`
/// - `/** Please file an issue */`
///
/// # Inner attributes
///
/// - `#![feature(proc_macro)]`
/// - `//! # Example`
/// - `/*! Please file an issue */`
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub enum AttrStyle {
Outer,
Inner(Token![!]),
}
}
ast_enum_of_structs! {
/// Content of a compile-time structured attribute.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
///
/// ## Path
///
/// A meta path is like the `test` in `#[test]`.
///
/// ## List
///
/// A meta list is like the `derive(Copy)` in `#[derive(Copy)]`.
///
/// ## NameValue
///
/// A name-value meta is like the `path = "..."` in `#[path =
/// "sys/windows.rs"]`.
///
/// # Syntax tree enum
///
/// This type is a [syntax tree enum].
///
/// [syntax tree enum]: Expr#syntax-tree-enums
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub enum Meta {
Path(Path),
/// A structured list within an attribute, like `derive(Copy, Clone)`.
List(MetaList),
/// A name-value pair within an attribute, like `feature = "nightly"`.
NameValue(MetaNameValue),
}
}
ast_struct! {
/// A structured list within an attribute, like `derive(Copy, Clone)`.
///
/// *This type is available only if Syn is built with the `"derive"` or
/// `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct MetaList {
pub path: Path,
pub paren_token: token::Paren,
pub nested: Punctuated<NestedMeta, Token![,]>,
}
}
ast_struct! {
/// A name-value pair within an attribute, like `feature = "nightly"`.
///
/// *This type is available only if Syn is built with the `"derive"` or
/// `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct MetaNameValue {
pub path: Path,
pub eq_token: Token![=],
pub lit: Lit,
}
}
impl Meta {
/// Returns the identifier that begins this structured meta item.
///
/// For example this would return the `test` in `#[test]`, the `derive` in
/// `#[derive(Copy)]`, and the `path` in `#[path = "sys/windows.rs"]`.
pub fn path(&self) -> &Path {
match self {
Meta::Path(path) => path,
Meta::List(meta) => &meta.path,
Meta::NameValue(meta) => &meta.path,
}
}
}
ast_enum_of_structs! {
/// Element of a compile-time attribute list.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub enum NestedMeta {
/// A structured meta item, like the `Copy` in `#[derive(Copy)]` which
/// would be a nested `Meta::Path`.
Meta(Meta),
/// A Rust literal, like the `"new_name"` in `#[rename("new_name")]`.
Lit(Lit),
}
}
/// Conventional argument type associated with an invocation of an attribute
/// macro.
///
/// For example if we are developing an attribute macro that is intended to be
/// invoked on function items as follows:
///
/// ```
/// # const IGNORE: &str = stringify! {
/// #[my_attribute(path = "/v1/refresh")]
/// # };
/// pub fn refresh() {
/// /* ... */
/// }
/// ```
///
/// The implementation of this macro would want to parse its attribute arguments
/// as type `AttributeArgs`.
///
/// ```
/// # extern crate proc_macro;
/// #
/// use proc_macro::TokenStream;
/// use syn::{parse_macro_input, AttributeArgs, ItemFn};
///
/// # const IGNORE: &str = stringify! {
/// #[proc_macro_attribute]
/// # };
/// pub fn my_attribute(args: TokenStream, input: TokenStream) -> TokenStream {
/// let args = parse_macro_input!(args as AttributeArgs);
/// let input = parse_macro_input!(input as ItemFn);
///
/// /* ... */
/// # "".parse().unwrap()
/// }
/// ```
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub type AttributeArgs = Vec<NestedMeta>;
pub trait FilterAttrs<'a> {
type Ret: Iterator<Item = &'a Attribute>;
fn outer(self) -> Self::Ret;
fn inner(self) -> Self::Ret;
}
impl<'a> FilterAttrs<'a> for &'a [Attribute] {
type Ret = iter::Filter<slice::Iter<'a, Attribute>, fn(&&Attribute) -> bool>;
fn outer(self) -> Self::Ret {
fn is_outer(attr: &&Attribute) -> bool {
match attr.style {
AttrStyle::Outer => true,
AttrStyle::Inner(_) => false,
}
}
self.iter().filter(is_outer)
}
fn inner(self) -> Self::Ret {
fn is_inner(attr: &&Attribute) -> bool {
match attr.style {
AttrStyle::Inner(_) => true,
AttrStyle::Outer => false,
}
}
self.iter().filter(is_inner)
}
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use crate::ext::IdentExt;
use crate::parse::{Parse, ParseStream, Result};
pub fn parse_inner(input: ParseStream, attrs: &mut Vec<Attribute>) -> Result<()> {
while input.peek(Token![#]) && input.peek2(Token![!]) {
attrs.push(input.call(parsing::single_parse_inner)?);
}
Ok(())
}
pub fn single_parse_inner(input: ParseStream) -> Result<Attribute> {
let content;
Ok(Attribute {
pound_token: input.parse()?,
style: AttrStyle::Inner(input.parse()?),
bracket_token: bracketed!(content in input),
path: content.call(Path::parse_mod_style)?,
tokens: content.parse()?,
})
}
pub fn single_parse_outer(input: ParseStream) -> Result<Attribute> {
let content;
Ok(Attribute {
pound_token: input.parse()?,
style: AttrStyle::Outer,
bracket_token: bracketed!(content in input),
path: content.call(Path::parse_mod_style)?,
tokens: content.parse()?,
})
}
// Like Path::parse_mod_style but accepts keywords in the path.
fn parse_meta_path(input: ParseStream) -> Result<Path> {
Ok(Path {
leading_colon: input.parse()?,
segments: {
let mut segments = Punctuated::new();
while input.peek(Ident::peek_any) {
let ident = Ident::parse_any(input)?;
segments.push_value(PathSegment::from(ident));
if !input.peek(Token![::]) {
break;
}
let punct = input.parse()?;
segments.push_punct(punct);
}
if segments.is_empty() {
return Err(input.error("expected path"));
} else if segments.trailing_punct() {
return Err(input.error("expected path segment"));
}
segments
},
})
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Meta {
fn parse(input: ParseStream) -> Result<Self> {
let path = input.call(parse_meta_path)?;
parse_meta_after_path(path, input)
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for MetaList {
fn parse(input: ParseStream) -> Result<Self> {
let path = input.call(parse_meta_path)?;
parse_meta_list_after_path(path, input)
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for MetaNameValue {
fn parse(input: ParseStream) -> Result<Self> {
let path = input.call(parse_meta_path)?;
parse_meta_name_value_after_path(path, input)
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for NestedMeta {
fn parse(input: ParseStream) -> Result<Self> {
if input.peek(Lit) && !(input.peek(LitBool) && input.peek2(Token![=])) {
input.parse().map(NestedMeta::Lit)
} else if input.peek(Ident::peek_any)
|| input.peek(Token![::]) && input.peek3(Ident::peek_any)
{
input.parse().map(NestedMeta::Meta)
} else {
Err(input.error("expected identifier or literal"))
}
}
}
pub fn parse_meta_after_path(path: Path, input: ParseStream) -> Result<Meta> {
if input.peek(token::Paren) {
parse_meta_list_after_path(path, input).map(Meta::List)
} else if input.peek(Token![=]) {
parse_meta_name_value_after_path(path, input).map(Meta::NameValue)
} else {
Ok(Meta::Path(path))
}
}
fn parse_meta_list_after_path(path: Path, input: ParseStream) -> Result<MetaList> {
let content;
Ok(MetaList {
path,
paren_token: parenthesized!(content in input),
nested: content.parse_terminated(NestedMeta::parse)?,
})
}
fn parse_meta_name_value_after_path(path: Path, input: ParseStream) -> Result<MetaNameValue> {
Ok(MetaNameValue {
path,
eq_token: input.parse()?,
lit: input.parse()?,
})
}
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use proc_macro2::TokenStream;
use quote::ToTokens;
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for Attribute {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.pound_token.to_tokens(tokens);
if let AttrStyle::Inner(b) = &self.style {
b.to_tokens(tokens);
}
self.bracket_token.surround(tokens, |tokens| {
self.path.to_tokens(tokens);
self.tokens.to_tokens(tokens);
});
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for MetaList {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.path.to_tokens(tokens);
self.paren_token.surround(tokens, |tokens| {
self.nested.to_tokens(tokens);
});
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for MetaNameValue {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.path.to_tokens(tokens);
self.eq_token.to_tokens(tokens);
self.lit.to_tokens(tokens);
}
}
}

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

@ -1,2 +0,0 @@
// See include!("await.rs") in token.rs.
export_token_macro! {[await]}

66
third_party/rust/syn-1.0.107/src/bigint.rs поставляемый
Просмотреть файл

@ -1,66 +0,0 @@
use std::ops::{AddAssign, MulAssign};
// For implementing base10_digits() accessor on LitInt.
pub struct BigInt {
digits: Vec<u8>,
}
impl BigInt {
pub fn new() -> Self {
BigInt { digits: Vec::new() }
}
pub fn to_string(&self) -> String {
let mut repr = String::with_capacity(self.digits.len());
let mut has_nonzero = false;
for digit in self.digits.iter().rev() {
has_nonzero |= *digit != 0;
if has_nonzero {
repr.push((*digit + b'0') as char);
}
}
if repr.is_empty() {
repr.push('0');
}
repr
}
fn reserve_two_digits(&mut self) {
let len = self.digits.len();
let desired =
len + !self.digits.ends_with(&[0, 0]) as usize + !self.digits.ends_with(&[0]) as usize;
self.digits.resize(desired, 0);
}
}
impl AddAssign<u8> for BigInt {
// Assumes increment <16.
fn add_assign(&mut self, mut increment: u8) {
self.reserve_two_digits();
let mut i = 0;
while increment > 0 {
let sum = self.digits[i] + increment;
self.digits[i] = sum % 10;
increment = sum / 10;
i += 1;
}
}
}
impl MulAssign<u8> for BigInt {
// Assumes base <=16.
fn mul_assign(&mut self, base: u8) {
self.reserve_two_digits();
let mut carry = 0;
for digit in &mut self.digits {
let prod = *digit * base + carry;
*digit = prod % 10;
carry = prod / 10;
}
}
}

398
third_party/rust/syn-1.0.107/src/buffer.rs поставляемый
Просмотреть файл

@ -1,398 +0,0 @@
//! A stably addressed token buffer supporting efficient traversal based on a
//! cheaply copyable cursor.
//!
//! *This module is available only if Syn is built with the `"parsing"` feature.*
// This module is heavily commented as it contains most of the unsafe code in
// Syn, and caution should be used when editing it. The public-facing interface
// is 100% safe but the implementation is fragile internally.
#[cfg(all(
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
feature = "proc-macro"
))]
use crate::proc_macro as pm;
use crate::Lifetime;
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
use std::cmp::Ordering;
use std::marker::PhantomData;
/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
enum Entry {
// Mimicking types from proc-macro.
// Group entries contain the offset to the matching End entry.
Group(Group, usize),
Ident(Ident),
Punct(Punct),
Literal(Literal),
// End entries contain the offset (negative) to the start of the buffer.
End(isize),
}
/// A buffer that can be efficiently traversed multiple times, unlike
/// `TokenStream` which requires a deep copy in order to traverse more than
/// once.
///
/// *This type is available only if Syn is built with the `"parsing"` feature.*
pub struct TokenBuffer {
// NOTE: Do not implement clone on this - while the current design could be
// cloned, other designs which could be desirable may not be cloneable.
entries: Box<[Entry]>,
}
impl TokenBuffer {
fn recursive_new(entries: &mut Vec<Entry>, stream: TokenStream) {
for tt in stream {
match tt {
TokenTree::Ident(ident) => entries.push(Entry::Ident(ident)),
TokenTree::Punct(punct) => entries.push(Entry::Punct(punct)),
TokenTree::Literal(literal) => entries.push(Entry::Literal(literal)),
TokenTree::Group(group) => {
let group_start_index = entries.len();
entries.push(Entry::End(0)); // we replace this below
Self::recursive_new(entries, group.stream());
let group_end_index = entries.len();
entries.push(Entry::End(-(group_end_index as isize)));
let group_end_offset = group_end_index - group_start_index;
entries[group_start_index] = Entry::Group(group, group_end_offset);
}
}
}
}
/// Creates a `TokenBuffer` containing all the tokens from the input
/// `proc_macro::TokenStream`.
///
/// *This method is available only if Syn is built with both the `"parsing"` and
/// `"proc-macro"` features.*
#[cfg(all(
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
feature = "proc-macro"
))]
pub fn new(stream: pm::TokenStream) -> Self {
Self::new2(stream.into())
}
/// Creates a `TokenBuffer` containing all the tokens from the input
/// `proc_macro2::TokenStream`.
pub fn new2(stream: TokenStream) -> Self {
let mut entries = Vec::new();
Self::recursive_new(&mut entries, stream);
entries.push(Entry::End(-(entries.len() as isize)));
Self {
entries: entries.into_boxed_slice(),
}
}
/// Creates a cursor referencing the first token in the buffer and able to
/// traverse until the end of the buffer.
pub fn begin(&self) -> Cursor {
let ptr = self.entries.as_ptr();
unsafe { Cursor::create(ptr, ptr.add(self.entries.len() - 1)) }
}
}
/// A cheaply copyable cursor into a `TokenBuffer`.
///
/// This cursor holds a shared reference into the immutable data which is used
/// internally to represent a `TokenStream`, and can be efficiently manipulated
/// and copied around.
///
/// An empty `Cursor` can be created directly, or one may create a `TokenBuffer`
/// object and get a cursor to its first token with `begin()`.
///
/// Two cursors are equal if they have the same location in the same input
/// stream, and have the same scope.
///
/// *This type is available only if Syn is built with the `"parsing"` feature.*
pub struct Cursor<'a> {
// The current entry which the `Cursor` is pointing at.
ptr: *const Entry,
// This is the only `Entry::End` object which this cursor is allowed to
// point at. All other `End` objects are skipped over in `Cursor::create`.
scope: *const Entry,
// Cursor is covariant in 'a. This field ensures that our pointers are still
// valid.
marker: PhantomData<&'a Entry>,
}
impl<'a> Cursor<'a> {
/// Creates a cursor referencing a static empty TokenStream.
pub fn empty() -> Self {
// It's safe in this situation for us to put an `Entry` object in global
// storage, despite it not actually being safe to send across threads
// (`Ident` is a reference into a thread-local table). This is because
// this entry never includes a `Ident` object.
//
// This wrapper struct allows us to break the rules and put a `Sync`
// object in global storage.
struct UnsafeSyncEntry(Entry);
unsafe impl Sync for UnsafeSyncEntry {}
static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0));
Cursor {
ptr: &EMPTY_ENTRY.0,
scope: &EMPTY_ENTRY.0,
marker: PhantomData,
}
}
/// This create method intelligently exits non-explicitly-entered
/// `None`-delimited scopes when the cursor reaches the end of them,
/// allowing for them to be treated transparently.
unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
// NOTE: If we're looking at a `End`, we want to advance the cursor
// past it, unless `ptr == scope`, which means that we're at the edge of
// our cursor's scope. We should only have `ptr != scope` at the exit
// from None-delimited groups entered with `ignore_none`.
while let Entry::End(_) = *ptr {
if ptr == scope {
break;
}
ptr = ptr.add(1);
}
Cursor {
ptr,
scope,
marker: PhantomData,
}
}
/// Get the current entry.
fn entry(self) -> &'a Entry {
unsafe { &*self.ptr }
}
/// Bump the cursor to point at the next token after the current one. This
/// is undefined behavior if the cursor is currently looking at an
/// `Entry::End`.
///
/// If the cursor is looking at an `Entry::Group`, the bumped cursor will
/// point at the first token in the group (with the same scope end).
unsafe fn bump_ignore_group(self) -> Cursor<'a> {
Cursor::create(self.ptr.offset(1), self.scope)
}
/// While the cursor is looking at a `None`-delimited group, move it to look
/// at the first token inside instead. If the group is empty, this will move
/// the cursor past the `None`-delimited group.
///
/// WARNING: This mutates its argument.
fn ignore_none(&mut self) {
while let Entry::Group(group, _) = self.entry() {
if group.delimiter() == Delimiter::None {
unsafe { *self = self.bump_ignore_group() };
} else {
break;
}
}
}
/// Checks whether the cursor is currently pointing at the end of its valid
/// scope.
pub fn eof(self) -> bool {
// We're at eof if we're at the end of our scope.
self.ptr == self.scope
}
/// If the cursor is pointing at a `Group` with the given delimiter, returns
/// a cursor into that group and one pointing to the next `TokenTree`.
pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, Span, Cursor<'a>)> {
// If we're not trying to enter a none-delimited group, we want to
// ignore them. We have to make sure to _not_ ignore them when we want
// to enter them, of course. For obvious reasons.
if delim != Delimiter::None {
self.ignore_none();
}
if let Entry::Group(group, end_offset) = self.entry() {
if group.delimiter() == delim {
let end_of_group = unsafe { self.ptr.add(*end_offset) };
let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) };
let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
return Some((inside_of_group, group.span(), after_group));
}
}
None
}
/// If the cursor is pointing at a `Ident`, returns it along with a cursor
/// pointing at the next `TokenTree`.
pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> {
self.ignore_none();
match self.entry() {
Entry::Ident(ident) => Some((ident.clone(), unsafe { self.bump_ignore_group() })),
_ => None,
}
}
/// If the cursor is pointing at a `Punct`, returns it along with a cursor
/// pointing at the next `TokenTree`.
pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
self.ignore_none();
match self.entry() {
Entry::Punct(punct) if punct.as_char() != '\'' => {
Some((punct.clone(), unsafe { self.bump_ignore_group() }))
}
_ => None,
}
}
/// If the cursor is pointing at a `Literal`, return it along with a cursor
/// pointing at the next `TokenTree`.
pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
self.ignore_none();
match self.entry() {
Entry::Literal(literal) => Some((literal.clone(), unsafe { self.bump_ignore_group() })),
_ => None,
}
}
/// If the cursor is pointing at a `Lifetime`, returns it along with a
/// cursor pointing at the next `TokenTree`.
pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> {
self.ignore_none();
match self.entry() {
Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
let next = unsafe { self.bump_ignore_group() };
let (ident, rest) = next.ident()?;
let lifetime = Lifetime {
apostrophe: punct.span(),
ident,
};
Some((lifetime, rest))
}
_ => None,
}
}
/// Copies all remaining tokens visible from this cursor into a
/// `TokenStream`.
pub fn token_stream(self) -> TokenStream {
let mut tts = Vec::new();
let mut cursor = self;
while let Some((tt, rest)) = cursor.token_tree() {
tts.push(tt);
cursor = rest;
}
tts.into_iter().collect()
}
/// If the cursor is pointing at a `TokenTree`, returns it along with a
/// cursor pointing at the next `TokenTree`.
///
/// Returns `None` if the cursor has reached the end of its stream.
///
/// This method does not treat `None`-delimited groups as transparent, and
/// will return a `Group(None, ..)` if the cursor is looking at one.
pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
let (tree, len) = match self.entry() {
Entry::Group(group, end_offset) => (group.clone().into(), *end_offset),
Entry::Literal(literal) => (literal.clone().into(), 1),
Entry::Ident(ident) => (ident.clone().into(), 1),
Entry::Punct(punct) => (punct.clone().into(), 1),
Entry::End(_) => return None,
};
let rest = unsafe { Cursor::create(self.ptr.add(len), self.scope) };
Some((tree, rest))
}
/// Returns the `Span` of the current token, or `Span::call_site()` if this
/// cursor points to eof.
pub fn span(self) -> Span {
match self.entry() {
Entry::Group(group, _) => group.span(),
Entry::Literal(literal) => literal.span(),
Entry::Ident(ident) => ident.span(),
Entry::Punct(punct) => punct.span(),
Entry::End(_) => Span::call_site(),
}
}
/// Skip over the next token without cloning it. Returns `None` if this
/// cursor points to eof.
///
/// This method treats `'lifetimes` as a single token.
pub(crate) fn skip(self) -> Option<Cursor<'a>> {
let len = match self.entry() {
Entry::End(_) => return None,
// Treat lifetimes as a single tt for the purposes of 'skip'.
Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
match unsafe { &*self.ptr.add(1) } {
Entry::Ident(_) => 2,
_ => 1,
}
}
Entry::Group(_, end_offset) => *end_offset,
_ => 1,
};
Some(unsafe { Cursor::create(self.ptr.add(len), self.scope) })
}
}
impl<'a> Copy for Cursor<'a> {}
impl<'a> Clone for Cursor<'a> {
fn clone(&self) -> Self {
*self
}
}
impl<'a> Eq for Cursor<'a> {}
impl<'a> PartialEq for Cursor<'a> {
fn eq(&self, other: &Self) -> bool {
self.ptr == other.ptr
}
}
impl<'a> PartialOrd for Cursor<'a> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if same_buffer(*self, *other) {
Some(self.ptr.cmp(&other.ptr))
} else {
None
}
}
}
pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool {
a.scope == b.scope
}
pub(crate) fn same_buffer(a: Cursor, b: Cursor) -> bool {
unsafe {
match (&*a.scope, &*b.scope) {
(Entry::End(a_offset), Entry::End(b_offset)) => {
a.scope.offset(*a_offset) == b.scope.offset(*b_offset)
}
_ => unreachable!(),
}
}
}
#[cfg(any(feature = "full", feature = "derive"))]
pub(crate) fn cmp_assuming_same_buffer(a: Cursor, b: Cursor) -> Ordering {
a.ptr.cmp(&b.ptr)
}
pub(crate) fn open_span_of_group(cursor: Cursor) -> Span {
match cursor.entry() {
Entry::Group(group, _) => group.span_open(),
_ => cursor.span(),
}
}
pub(crate) fn close_span_of_group(cursor: Cursor) -> Span {
match cursor.entry() {
Entry::Group(group, _) => group.span_close(),
_ => cursor.span(),
}
}

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

@ -1,253 +0,0 @@
/// Define a type that supports parsing and printing a given identifier as if it
/// were a keyword.
///
/// # Usage
///
/// As a convention, it is recommended that this macro be invoked within a
/// module called `kw` or `keyword` and that the resulting parser be invoked
/// with a `kw::` or `keyword::` prefix.
///
/// ```
/// mod kw {
/// syn::custom_keyword!(whatever);
/// }
/// ```
///
/// The generated syntax tree node supports the following operations just like
/// any built-in keyword token.
///
/// - [Peeking] — `input.peek(kw::whatever)`
///
/// - [Parsing] — `input.parse::<kw::whatever>()?`
///
/// - [Printing] — `quote!( ... #whatever_token ... )`
///
/// - Construction from a [`Span`] — `let whatever_token = kw::whatever(sp)`
///
/// - Field access to its span — `let sp = whatever_token.span`
///
/// [Peeking]: crate::parse::ParseBuffer::peek
/// [Parsing]: crate::parse::ParseBuffer::parse
/// [Printing]: quote::ToTokens
/// [`Span`]: proc_macro2::Span
///
/// # Example
///
/// This example parses input that looks like `bool = true` or `str = "value"`.
/// The key must be either the identifier `bool` or the identifier `str`. If
/// `bool`, the value may be either `true` or `false`. If `str`, the value may
/// be any string literal.
///
/// The symbols `bool` and `str` are not reserved keywords in Rust so these are
/// not considered keywords in the `syn::token` module. Like any other
/// identifier that is not a keyword, these can be declared as custom keywords
/// by crates that need to use them as such.
///
/// ```
/// use syn::{LitBool, LitStr, Result, Token};
/// use syn::parse::{Parse, ParseStream};
///
/// mod kw {
/// syn::custom_keyword!(bool);
/// syn::custom_keyword!(str);
/// }
///
/// enum Argument {
/// Bool {
/// bool_token: kw::bool,
/// eq_token: Token![=],
/// value: LitBool,
/// },
/// Str {
/// str_token: kw::str,
/// eq_token: Token![=],
/// value: LitStr,
/// },
/// }
///
/// impl Parse for Argument {
/// fn parse(input: ParseStream) -> Result<Self> {
/// let lookahead = input.lookahead1();
/// if lookahead.peek(kw::bool) {
/// Ok(Argument::Bool {
/// bool_token: input.parse::<kw::bool>()?,
/// eq_token: input.parse()?,
/// value: input.parse()?,
/// })
/// } else if lookahead.peek(kw::str) {
/// Ok(Argument::Str {
/// str_token: input.parse::<kw::str>()?,
/// eq_token: input.parse()?,
/// value: input.parse()?,
/// })
/// } else {
/// Err(lookahead.error())
/// }
/// }
/// }
/// ```
#[macro_export]
macro_rules! custom_keyword {
($ident:ident) => {
#[allow(non_camel_case_types)]
pub struct $ident {
pub span: $crate::__private::Span,
}
#[doc(hidden)]
#[allow(dead_code, non_snake_case)]
pub fn $ident<__S: $crate::__private::IntoSpans<[$crate::__private::Span; 1]>>(
span: __S,
) -> $ident {
$ident {
span: $crate::__private::IntoSpans::into_spans(span)[0],
}
}
impl $crate::__private::Default for $ident {
fn default() -> Self {
$ident {
span: $crate::__private::Span::call_site(),
}
}
}
$crate::impl_parse_for_custom_keyword!($ident);
$crate::impl_to_tokens_for_custom_keyword!($ident);
$crate::impl_clone_for_custom_keyword!($ident);
$crate::impl_extra_traits_for_custom_keyword!($ident);
};
}
// Not public API.
#[cfg(feature = "parsing")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_parse_for_custom_keyword {
($ident:ident) => {
// For peek.
impl $crate::token::CustomToken for $ident {
fn peek(cursor: $crate::buffer::Cursor) -> $crate::__private::bool {
if let $crate::__private::Some((ident, _rest)) = cursor.ident() {
ident == stringify!($ident)
} else {
false
}
}
fn display() -> &'static $crate::__private::str {
concat!("`", stringify!($ident), "`")
}
}
impl $crate::parse::Parse for $ident {
fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> {
input.step(|cursor| {
if let $crate::__private::Some((ident, rest)) = cursor.ident() {
if ident == stringify!($ident) {
return $crate::__private::Ok(($ident { span: ident.span() }, rest));
}
}
$crate::__private::Err(cursor.error(concat!(
"expected `",
stringify!($ident),
"`"
)))
})
}
}
};
}
// Not public API.
#[cfg(not(feature = "parsing"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_parse_for_custom_keyword {
($ident:ident) => {};
}
// Not public API.
#[cfg(feature = "printing")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_to_tokens_for_custom_keyword {
($ident:ident) => {
impl $crate::__private::ToTokens for $ident {
fn to_tokens(&self, tokens: &mut $crate::__private::TokenStream2) {
let ident = $crate::Ident::new(stringify!($ident), self.span);
$crate::__private::TokenStreamExt::append(tokens, ident);
}
}
};
}
// Not public API.
#[cfg(not(feature = "printing"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_to_tokens_for_custom_keyword {
($ident:ident) => {};
}
// Not public API.
#[cfg(feature = "clone-impls")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_clone_for_custom_keyword {
($ident:ident) => {
impl $crate::__private::Copy for $ident {}
#[allow(clippy::expl_impl_clone_on_copy)]
impl $crate::__private::Clone for $ident {
fn clone(&self) -> Self {
*self
}
}
};
}
// Not public API.
#[cfg(not(feature = "clone-impls"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_clone_for_custom_keyword {
($ident:ident) => {};
}
// Not public API.
#[cfg(feature = "extra-traits")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_extra_traits_for_custom_keyword {
($ident:ident) => {
impl $crate::__private::Debug for $ident {
fn fmt(&self, f: &mut $crate::__private::Formatter) -> $crate::__private::fmt::Result {
$crate::__private::Formatter::write_str(
f,
concat!("Keyword [", stringify!($ident), "]"),
)
}
}
impl $crate::__private::Eq for $ident {}
impl $crate::__private::PartialEq for $ident {
fn eq(&self, _other: &Self) -> $crate::__private::bool {
true
}
}
impl $crate::__private::Hash for $ident {
fn hash<__H: $crate::__private::Hasher>(&self, _state: &mut __H) {}
}
};
}
// Not public API.
#[cfg(not(feature = "extra-traits"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_extra_traits_for_custom_keyword {
($ident:ident) => {};
}

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

@ -1,300 +0,0 @@
/// Define a type that supports parsing and printing a multi-character symbol
/// as if it were a punctuation token.
///
/// # Usage
///
/// ```
/// syn::custom_punctuation!(LeftRightArrow, <=>);
/// ```
///
/// The generated syntax tree node supports the following operations just like
/// any built-in punctuation token.
///
/// - [Peeking] — `input.peek(LeftRightArrow)`
///
/// - [Parsing] — `input.parse::<LeftRightArrow>()?`
///
/// - [Printing] — `quote!( ... #lrarrow ... )`
///
/// - Construction from a [`Span`] — `let lrarrow = LeftRightArrow(sp)`
///
/// - Construction from multiple [`Span`] — `let lrarrow = LeftRightArrow([sp, sp, sp])`
///
/// - Field access to its spans — `let spans = lrarrow.spans`
///
/// [Peeking]: crate::parse::ParseBuffer::peek
/// [Parsing]: crate::parse::ParseBuffer::parse
/// [Printing]: quote::ToTokens
/// [`Span`]: proc_macro2::Span
///
/// # Example
///
/// ```
/// use proc_macro2::{TokenStream, TokenTree};
/// use syn::parse::{Parse, ParseStream, Peek, Result};
/// use syn::punctuated::Punctuated;
/// use syn::Expr;
///
/// syn::custom_punctuation!(PathSeparator, </>);
///
/// // expr </> expr </> expr ...
/// struct PathSegments {
/// segments: Punctuated<Expr, PathSeparator>,
/// }
///
/// impl Parse for PathSegments {
/// fn parse(input: ParseStream) -> Result<Self> {
/// let mut segments = Punctuated::new();
///
/// let first = parse_until(input, PathSeparator)?;
/// segments.push_value(syn::parse2(first)?);
///
/// while input.peek(PathSeparator) {
/// segments.push_punct(input.parse()?);
///
/// let next = parse_until(input, PathSeparator)?;
/// segments.push_value(syn::parse2(next)?);
/// }
///
/// Ok(PathSegments { segments })
/// }
/// }
///
/// fn parse_until<E: Peek>(input: ParseStream, end: E) -> Result<TokenStream> {
/// let mut tokens = TokenStream::new();
/// while !input.is_empty() && !input.peek(end) {
/// let next: TokenTree = input.parse()?;
/// tokens.extend(Some(next));
/// }
/// Ok(tokens)
/// }
///
/// fn main() {
/// let input = r#" a::b </> c::d::e "#;
/// let _: PathSegments = syn::parse_str(input).unwrap();
/// }
/// ```
#[macro_export]
macro_rules! custom_punctuation {
($ident:ident, $($tt:tt)+) => {
pub struct $ident {
pub spans: $crate::custom_punctuation_repr!($($tt)+),
}
#[doc(hidden)]
#[allow(dead_code, non_snake_case)]
pub fn $ident<__S: $crate::__private::IntoSpans<$crate::custom_punctuation_repr!($($tt)+)>>(
spans: __S,
) -> $ident {
let _validate_len = 0 $(+ $crate::custom_punctuation_len!(strict, $tt))*;
$ident {
spans: $crate::__private::IntoSpans::into_spans(spans)
}
}
impl $crate::__private::Default for $ident {
fn default() -> Self {
$ident($crate::__private::Span::call_site())
}
}
$crate::impl_parse_for_custom_punctuation!($ident, $($tt)+);
$crate::impl_to_tokens_for_custom_punctuation!($ident, $($tt)+);
$crate::impl_clone_for_custom_punctuation!($ident, $($tt)+);
$crate::impl_extra_traits_for_custom_punctuation!($ident, $($tt)+);
};
}
// Not public API.
#[cfg(feature = "parsing")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_parse_for_custom_punctuation {
($ident:ident, $($tt:tt)+) => {
impl $crate::token::CustomToken for $ident {
fn peek(cursor: $crate::buffer::Cursor) -> bool {
$crate::token::parsing::peek_punct(cursor, $crate::stringify_punct!($($tt)+))
}
fn display() -> &'static $crate::__private::str {
concat!("`", $crate::stringify_punct!($($tt)+), "`")
}
}
impl $crate::parse::Parse for $ident {
fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> {
let spans: $crate::custom_punctuation_repr!($($tt)+) =
$crate::token::parsing::punct(input, $crate::stringify_punct!($($tt)+))?;
Ok($ident(spans))
}
}
};
}
// Not public API.
#[cfg(not(feature = "parsing"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_parse_for_custom_punctuation {
($ident:ident, $($tt:tt)+) => {};
}
// Not public API.
#[cfg(feature = "printing")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_to_tokens_for_custom_punctuation {
($ident:ident, $($tt:tt)+) => {
impl $crate::__private::ToTokens for $ident {
fn to_tokens(&self, tokens: &mut $crate::__private::TokenStream2) {
$crate::token::printing::punct($crate::stringify_punct!($($tt)+), &self.spans, tokens)
}
}
};
}
// Not public API.
#[cfg(not(feature = "printing"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_to_tokens_for_custom_punctuation {
($ident:ident, $($tt:tt)+) => {};
}
// Not public API.
#[cfg(feature = "clone-impls")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_clone_for_custom_punctuation {
($ident:ident, $($tt:tt)+) => {
impl $crate::__private::Copy for $ident {}
#[allow(clippy::expl_impl_clone_on_copy)]
impl $crate::__private::Clone for $ident {
fn clone(&self) -> Self {
*self
}
}
};
}
// Not public API.
#[cfg(not(feature = "clone-impls"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_clone_for_custom_punctuation {
($ident:ident, $($tt:tt)+) => {};
}
// Not public API.
#[cfg(feature = "extra-traits")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_extra_traits_for_custom_punctuation {
($ident:ident, $($tt:tt)+) => {
impl $crate::__private::Debug for $ident {
fn fmt(&self, f: &mut $crate::__private::Formatter) -> $crate::__private::fmt::Result {
$crate::__private::Formatter::write_str(f, stringify!($ident))
}
}
impl $crate::__private::Eq for $ident {}
impl $crate::__private::PartialEq for $ident {
fn eq(&self, _other: &Self) -> $crate::__private::bool {
true
}
}
impl $crate::__private::Hash for $ident {
fn hash<__H: $crate::__private::Hasher>(&self, _state: &mut __H) {}
}
};
}
// Not public API.
#[cfg(not(feature = "extra-traits"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_extra_traits_for_custom_punctuation {
($ident:ident, $($tt:tt)+) => {};
}
// Not public API.
#[doc(hidden)]
#[macro_export]
macro_rules! custom_punctuation_repr {
($($tt:tt)+) => {
[$crate::__private::Span; 0 $(+ $crate::custom_punctuation_len!(lenient, $tt))+]
};
}
// Not public API.
#[doc(hidden)]
#[macro_export]
#[rustfmt::skip]
macro_rules! custom_punctuation_len {
($mode:ident, +) => { 1 };
($mode:ident, +=) => { 2 };
($mode:ident, &) => { 1 };
($mode:ident, &&) => { 2 };
($mode:ident, &=) => { 2 };
($mode:ident, @) => { 1 };
($mode:ident, !) => { 1 };
($mode:ident, ^) => { 1 };
($mode:ident, ^=) => { 2 };
($mode:ident, :) => { 1 };
($mode:ident, ::) => { 2 };
($mode:ident, ,) => { 1 };
($mode:ident, /) => { 1 };
($mode:ident, /=) => { 2 };
($mode:ident, .) => { 1 };
($mode:ident, ..) => { 2 };
($mode:ident, ...) => { 3 };
($mode:ident, ..=) => { 3 };
($mode:ident, =) => { 1 };
($mode:ident, ==) => { 2 };
($mode:ident, >=) => { 2 };
($mode:ident, >) => { 1 };
($mode:ident, <=) => { 2 };
($mode:ident, <) => { 1 };
($mode:ident, *=) => { 2 };
($mode:ident, !=) => { 2 };
($mode:ident, |) => { 1 };
($mode:ident, |=) => { 2 };
($mode:ident, ||) => { 2 };
($mode:ident, #) => { 1 };
($mode:ident, ?) => { 1 };
($mode:ident, ->) => { 2 };
($mode:ident, <-) => { 2 };
($mode:ident, %) => { 1 };
($mode:ident, %=) => { 2 };
($mode:ident, =>) => { 2 };
($mode:ident, ;) => { 1 };
($mode:ident, <<) => { 2 };
($mode:ident, <<=) => { 3 };
($mode:ident, >>) => { 2 };
($mode:ident, >>=) => { 3 };
($mode:ident, *) => { 1 };
($mode:ident, -) => { 1 };
($mode:ident, -=) => { 2 };
($mode:ident, ~) => { 1 };
(lenient, $tt:tt) => { 0 };
(strict, $tt:tt) => {{ $crate::custom_punctuation_unexpected!($tt); 0 }};
}
// Not public API.
#[doc(hidden)]
#[macro_export]
macro_rules! custom_punctuation_unexpected {
() => {};
}
// Not public API.
#[doc(hidden)]
#[macro_export]
macro_rules! stringify_punct {
($($tt:tt)+) => {
concat!($(stringify!($tt)),+)
};
}

493
third_party/rust/syn-1.0.107/src/data.rs поставляемый
Просмотреть файл

@ -1,493 +0,0 @@
use super::*;
use crate::punctuated::Punctuated;
ast_struct! {
/// An enum variant.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct Variant {
/// Attributes tagged on the variant.
pub attrs: Vec<Attribute>,
/// Name of the variant.
pub ident: Ident,
/// Content stored in the variant.
pub fields: Fields,
/// Explicit discriminant: `Variant = 1`
pub discriminant: Option<(Token![=], Expr)>,
}
}
ast_enum_of_structs! {
/// Data stored within an enum variant or struct.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
///
/// # Syntax tree enum
///
/// This type is a [syntax tree enum].
///
/// [syntax tree enum]: Expr#syntax-tree-enums
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub enum Fields {
/// Named fields of a struct or struct variant such as `Point { x: f64,
/// y: f64 }`.
Named(FieldsNamed),
/// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
Unnamed(FieldsUnnamed),
/// Unit struct or unit variant such as `None`.
Unit,
}
}
ast_struct! {
/// Named fields of a struct or struct variant such as `Point { x: f64,
/// y: f64 }`.
///
/// *This type is available only if Syn is built with the `"derive"` or
/// `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct FieldsNamed {
pub brace_token: token::Brace,
pub named: Punctuated<Field, Token![,]>,
}
}
ast_struct! {
/// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
///
/// *This type is available only if Syn is built with the `"derive"` or
/// `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct FieldsUnnamed {
pub paren_token: token::Paren,
pub unnamed: Punctuated<Field, Token![,]>,
}
}
impl Fields {
/// Get an iterator over the borrowed [`Field`] items in this object. This
/// iterator can be used to iterate over a named or unnamed struct or
/// variant's fields uniformly.
pub fn iter(&self) -> punctuated::Iter<Field> {
match self {
Fields::Unit => crate::punctuated::empty_punctuated_iter(),
Fields::Named(f) => f.named.iter(),
Fields::Unnamed(f) => f.unnamed.iter(),
}
}
/// Get an iterator over the mutably borrowed [`Field`] items in this
/// object. This iterator can be used to iterate over a named or unnamed
/// struct or variant's fields uniformly.
pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
match self {
Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(),
Fields::Named(f) => f.named.iter_mut(),
Fields::Unnamed(f) => f.unnamed.iter_mut(),
}
}
/// Returns the number of fields.
pub fn len(&self) -> usize {
match self {
Fields::Unit => 0,
Fields::Named(f) => f.named.len(),
Fields::Unnamed(f) => f.unnamed.len(),
}
}
/// Returns `true` if there are zero fields.
pub fn is_empty(&self) -> bool {
match self {
Fields::Unit => true,
Fields::Named(f) => f.named.is_empty(),
Fields::Unnamed(f) => f.unnamed.is_empty(),
}
}
}
impl IntoIterator for Fields {
type Item = Field;
type IntoIter = punctuated::IntoIter<Field>;
fn into_iter(self) -> Self::IntoIter {
match self {
Fields::Unit => Punctuated::<Field, ()>::new().into_iter(),
Fields::Named(f) => f.named.into_iter(),
Fields::Unnamed(f) => f.unnamed.into_iter(),
}
}
}
impl<'a> IntoIterator for &'a Fields {
type Item = &'a Field;
type IntoIter = punctuated::Iter<'a, Field>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> IntoIterator for &'a mut Fields {
type Item = &'a mut Field;
type IntoIter = punctuated::IterMut<'a, Field>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
ast_struct! {
/// A field of a struct or enum variant.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct Field {
/// Attributes tagged on the field.
pub attrs: Vec<Attribute>,
/// Visibility of the field.
pub vis: Visibility,
/// Name of the field, if any.
///
/// Fields of tuple structs have no names.
pub ident: Option<Ident>,
pub colon_token: Option<Token![:]>,
/// Type of the field.
pub ty: Type,
}
}
ast_enum_of_structs! {
/// The visibility level of an item: inherited or `pub` or
/// `pub(restricted)`.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
///
/// # Syntax tree enum
///
/// This type is a [syntax tree enum].
///
/// [syntax tree enum]: Expr#syntax-tree-enums
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub enum Visibility {
/// A public visibility level: `pub`.
Public(VisPublic),
/// A crate-level visibility: `crate`.
Crate(VisCrate),
/// A visibility level restricted to some path: `pub(self)` or
/// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
Restricted(VisRestricted),
/// An inherited visibility, which usually means private.
Inherited,
}
}
ast_struct! {
/// A public visibility level: `pub`.
///
/// *This type is available only if Syn is built with the `"derive"` or
/// `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct VisPublic {
pub pub_token: Token![pub],
}
}
ast_struct! {
/// A crate-level visibility: `crate`.
///
/// *This type is available only if Syn is built with the `"derive"` or
/// `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct VisCrate {
pub crate_token: Token![crate],
}
}
ast_struct! {
/// A visibility level restricted to some path: `pub(self)` or
/// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
///
/// *This type is available only if Syn is built with the `"derive"` or
/// `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct VisRestricted {
pub pub_token: Token![pub],
pub paren_token: token::Paren,
pub in_token: Option<Token![in]>,
pub path: Box<Path>,
}
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use crate::ext::IdentExt;
use crate::parse::discouraged::Speculative;
use crate::parse::{Parse, ParseStream, Result};
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Variant {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let _visibility: Visibility = input.parse()?;
let ident: Ident = input.parse()?;
let fields = if input.peek(token::Brace) {
Fields::Named(input.parse()?)
} else if input.peek(token::Paren) {
Fields::Unnamed(input.parse()?)
} else {
Fields::Unit
};
let discriminant = if input.peek(Token![=]) {
let eq_token: Token![=] = input.parse()?;
let discriminant: Expr = input.parse()?;
Some((eq_token, discriminant))
} else {
None
};
Ok(Variant {
attrs,
ident,
fields,
discriminant,
})
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for FieldsNamed {
fn parse(input: ParseStream) -> Result<Self> {
let content;
Ok(FieldsNamed {
brace_token: braced!(content in input),
named: content.parse_terminated(Field::parse_named)?,
})
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for FieldsUnnamed {
fn parse(input: ParseStream) -> Result<Self> {
let content;
Ok(FieldsUnnamed {
paren_token: parenthesized!(content in input),
unnamed: content.parse_terminated(Field::parse_unnamed)?,
})
}
}
impl Field {
/// Parses a named (braced struct) field.
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn parse_named(input: ParseStream) -> Result<Self> {
Ok(Field {
attrs: input.call(Attribute::parse_outer)?,
vis: input.parse()?,
ident: Some(if input.peek(Token![_]) {
input.call(Ident::parse_any)
} else {
input.parse()
}?),
colon_token: Some(input.parse()?),
ty: input.parse()?,
})
}
/// Parses an unnamed (tuple struct) field.
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
Ok(Field {
attrs: input.call(Attribute::parse_outer)?,
vis: input.parse()?,
ident: None,
colon_token: None,
ty: input.parse()?,
})
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Visibility {
fn parse(input: ParseStream) -> Result<Self> {
// Recognize an empty None-delimited group, as produced by a $:vis
// matcher that matched no tokens.
if input.peek(token::Group) {
let ahead = input.fork();
let group = crate::group::parse_group(&ahead)?;
if group.content.is_empty() {
input.advance_to(&ahead);
return Ok(Visibility::Inherited);
}
}
if input.peek(Token![pub]) {
Self::parse_pub(input)
} else if input.peek(Token![crate]) {
Self::parse_crate(input)
} else {
Ok(Visibility::Inherited)
}
}
}
impl Visibility {
fn parse_pub(input: ParseStream) -> Result<Self> {
let pub_token = input.parse::<Token![pub]>()?;
if input.peek(token::Paren) {
let ahead = input.fork();
let content;
let paren_token = parenthesized!(content in ahead);
if content.peek(Token![crate])
|| content.peek(Token![self])
|| content.peek(Token![super])
{
let path = content.call(Ident::parse_any)?;
// Ensure there are no additional tokens within `content`.
// Without explicitly checking, we may misinterpret a tuple
// field as a restricted visibility, causing a parse error.
// e.g. `pub (crate::A, crate::B)` (Issue #720).
if content.is_empty() {
input.advance_to(&ahead);
return Ok(Visibility::Restricted(VisRestricted {
pub_token,
paren_token,
in_token: None,
path: Box::new(Path::from(path)),
}));
}
} else if content.peek(Token![in]) {
let in_token: Token![in] = content.parse()?;
let path = content.call(Path::parse_mod_style)?;
input.advance_to(&ahead);
return Ok(Visibility::Restricted(VisRestricted {
pub_token,
paren_token,
in_token: Some(in_token),
path: Box::new(path),
}));
}
}
Ok(Visibility::Public(VisPublic { pub_token }))
}
fn parse_crate(input: ParseStream) -> Result<Self> {
if input.peek2(Token![::]) {
Ok(Visibility::Inherited)
} else {
Ok(Visibility::Crate(VisCrate {
crate_token: input.parse()?,
}))
}
}
#[cfg(feature = "full")]
pub(crate) fn is_some(&self) -> bool {
match self {
Visibility::Inherited => false,
_ => true,
}
}
}
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use crate::print::TokensOrDefault;
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt};
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for Variant {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(&self.attrs);
self.ident.to_tokens(tokens);
self.fields.to_tokens(tokens);
if let Some((eq_token, disc)) = &self.discriminant {
eq_token.to_tokens(tokens);
disc.to_tokens(tokens);
}
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for FieldsNamed {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.brace_token.surround(tokens, |tokens| {
self.named.to_tokens(tokens);
});
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for FieldsUnnamed {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.paren_token.surround(tokens, |tokens| {
self.unnamed.to_tokens(tokens);
});
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for Field {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(&self.attrs);
self.vis.to_tokens(tokens);
if let Some(ident) = &self.ident {
ident.to_tokens(tokens);
TokensOrDefault(&self.colon_token).to_tokens(tokens);
}
self.ty.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for VisPublic {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.pub_token.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for VisCrate {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.crate_token.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for VisRestricted {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.pub_token.to_tokens(tokens);
self.paren_token.surround(tokens, |tokens| {
// TODO: If we have a path which is not "self" or "super" or
// "crate", automatically add the "in" token.
self.in_token.to_tokens(tokens);
self.path.to_tokens(tokens);
});
}
}
}

274
third_party/rust/syn-1.0.107/src/derive.rs поставляемый
Просмотреть файл

@ -1,274 +0,0 @@
use super::*;
use crate::punctuated::Punctuated;
ast_struct! {
/// Data structure sent to a `proc_macro_derive` macro.
///
/// *This type is available only if Syn is built with the `"derive"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
pub struct DeriveInput {
/// Attributes tagged on the whole struct or enum.
pub attrs: Vec<Attribute>,
/// Visibility of the struct or enum.
pub vis: Visibility,
/// Name of the struct or enum.
pub ident: Ident,
/// Generics required to complete the definition.
pub generics: Generics,
/// Data within the struct or enum.
pub data: Data,
}
}
ast_enum_of_structs! {
/// The storage of a struct, enum or union data structure.
///
/// *This type is available only if Syn is built with the `"derive"` feature.*
///
/// # Syntax tree enum
///
/// This type is a [syntax tree enum].
///
/// [syntax tree enum]: Expr#syntax-tree-enums
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
pub enum Data {
/// A struct input to a `proc_macro_derive` macro.
Struct(DataStruct),
/// An enum input to a `proc_macro_derive` macro.
Enum(DataEnum),
/// An untagged union input to a `proc_macro_derive` macro.
Union(DataUnion),
}
do_not_generate_to_tokens
}
ast_struct! {
/// A struct input to a `proc_macro_derive` macro.
///
/// *This type is available only if Syn is built with the `"derive"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
pub struct DataStruct {
pub struct_token: Token![struct],
pub fields: Fields,
pub semi_token: Option<Token![;]>,
}
}
ast_struct! {
/// An enum input to a `proc_macro_derive` macro.
///
/// *This type is available only if Syn is built with the `"derive"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
pub struct DataEnum {
pub enum_token: Token![enum],
pub brace_token: token::Brace,
pub variants: Punctuated<Variant, Token![,]>,
}
}
ast_struct! {
/// An untagged union input to a `proc_macro_derive` macro.
///
/// *This type is available only if Syn is built with the `"derive"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
pub struct DataUnion {
pub union_token: Token![union],
pub fields: FieldsNamed,
}
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use crate::parse::{Parse, ParseStream, Result};
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for DeriveInput {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let vis = input.parse::<Visibility>()?;
let lookahead = input.lookahead1();
if lookahead.peek(Token![struct]) {
let struct_token = input.parse::<Token![struct]>()?;
let ident = input.parse::<Ident>()?;
let generics = input.parse::<Generics>()?;
let (where_clause, fields, semi) = data_struct(input)?;
Ok(DeriveInput {
attrs,
vis,
ident,
generics: Generics {
where_clause,
..generics
},
data: Data::Struct(DataStruct {
struct_token,
fields,
semi_token: semi,
}),
})
} else if lookahead.peek(Token![enum]) {
let enum_token = input.parse::<Token![enum]>()?;
let ident = input.parse::<Ident>()?;
let generics = input.parse::<Generics>()?;
let (where_clause, brace, variants) = data_enum(input)?;
Ok(DeriveInput {
attrs,
vis,
ident,
generics: Generics {
where_clause,
..generics
},
data: Data::Enum(DataEnum {
enum_token,
brace_token: brace,
variants,
}),
})
} else if lookahead.peek(Token![union]) {
let union_token = input.parse::<Token![union]>()?;
let ident = input.parse::<Ident>()?;
let generics = input.parse::<Generics>()?;
let (where_clause, fields) = data_union(input)?;
Ok(DeriveInput {
attrs,
vis,
ident,
generics: Generics {
where_clause,
..generics
},
data: Data::Union(DataUnion {
union_token,
fields,
}),
})
} else {
Err(lookahead.error())
}
}
}
pub fn data_struct(
input: ParseStream,
) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)> {
let mut lookahead = input.lookahead1();
let mut where_clause = None;
if lookahead.peek(Token![where]) {
where_clause = Some(input.parse()?);
lookahead = input.lookahead1();
}
if where_clause.is_none() && lookahead.peek(token::Paren) {
let fields = input.parse()?;
lookahead = input.lookahead1();
if lookahead.peek(Token![where]) {
where_clause = Some(input.parse()?);
lookahead = input.lookahead1();
}
if lookahead.peek(Token![;]) {
let semi = input.parse()?;
Ok((where_clause, Fields::Unnamed(fields), Some(semi)))
} else {
Err(lookahead.error())
}
} else if lookahead.peek(token::Brace) {
let fields = input.parse()?;
Ok((where_clause, Fields::Named(fields), None))
} else if lookahead.peek(Token![;]) {
let semi = input.parse()?;
Ok((where_clause, Fields::Unit, Some(semi)))
} else {
Err(lookahead.error())
}
}
pub fn data_enum(
input: ParseStream,
) -> Result<(
Option<WhereClause>,
token::Brace,
Punctuated<Variant, Token![,]>,
)> {
let where_clause = input.parse()?;
let content;
let brace = braced!(content in input);
let variants = content.parse_terminated(Variant::parse)?;
Ok((where_clause, brace, variants))
}
pub fn data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)> {
let where_clause = input.parse()?;
let fields = input.parse()?;
Ok((where_clause, fields))
}
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use crate::attr::FilterAttrs;
use crate::print::TokensOrDefault;
use proc_macro2::TokenStream;
use quote::ToTokens;
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for DeriveInput {
fn to_tokens(&self, tokens: &mut TokenStream) {
for attr in self.attrs.outer() {
attr.to_tokens(tokens);
}
self.vis.to_tokens(tokens);
match &self.data {
Data::Struct(d) => d.struct_token.to_tokens(tokens),
Data::Enum(d) => d.enum_token.to_tokens(tokens),
Data::Union(d) => d.union_token.to_tokens(tokens),
}
self.ident.to_tokens(tokens);
self.generics.to_tokens(tokens);
match &self.data {
Data::Struct(data) => match &data.fields {
Fields::Named(fields) => {
self.generics.where_clause.to_tokens(tokens);
fields.to_tokens(tokens);
}
Fields::Unnamed(fields) => {
fields.to_tokens(tokens);
self.generics.where_clause.to_tokens(tokens);
TokensOrDefault(&data.semi_token).to_tokens(tokens);
}
Fields::Unit => {
self.generics.where_clause.to_tokens(tokens);
TokensOrDefault(&data.semi_token).to_tokens(tokens);
}
},
Data::Enum(data) => {
self.generics.where_clause.to_tokens(tokens);
data.brace_token.surround(tokens, |tokens| {
data.variants.to_tokens(tokens);
});
}
Data::Union(data) => {
self.generics.where_clause.to_tokens(tokens);
data.fields.to_tokens(tokens);
}
}
}
}
}

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

@ -1,194 +0,0 @@
//! Extensions to the parsing API with niche applicability.
use super::*;
/// Extensions to the `ParseStream` API to support speculative parsing.
pub trait Speculative {
/// Advance this parse stream to the position of a forked parse stream.
///
/// This is the opposite operation to [`ParseStream::fork`]. You can fork a
/// parse stream, perform some speculative parsing, then join the original
/// stream to the fork to "commit" the parsing from the fork to the main
/// stream.
///
/// If you can avoid doing this, you should, as it limits the ability to
/// generate useful errors. That said, it is often the only way to parse
/// syntax of the form `A* B*` for arbitrary syntax `A` and `B`. The problem
/// is that when the fork fails to parse an `A`, it's impossible to tell
/// whether that was because of a syntax error and the user meant to provide
/// an `A`, or that the `A`s are finished and it's time to start parsing
/// `B`s. Use with care.
///
/// Also note that if `A` is a subset of `B`, `A* B*` can be parsed by
/// parsing `B*` and removing the leading members of `A` from the
/// repetition, bypassing the need to involve the downsides associated with
/// speculative parsing.
///
/// [`ParseStream::fork`]: ParseBuffer::fork
///
/// # Example
///
/// There has been chatter about the possibility of making the colons in the
/// turbofish syntax like `path::to::<T>` no longer required by accepting
/// `path::to<T>` in expression position. Specifically, according to [RFC
/// 2544], [`PathSegment`] parsing should always try to consume a following
/// `<` token as the start of generic arguments, and reset to the `<` if
/// that fails (e.g. the token is acting as a less-than operator).
///
/// This is the exact kind of parsing behavior which requires the "fork,
/// try, commit" behavior that [`ParseStream::fork`] discourages. With
/// `advance_to`, we can avoid having to parse the speculatively parsed
/// content a second time.
///
/// This change in behavior can be implemented in syn by replacing just the
/// `Parse` implementation for `PathSegment`:
///
/// ```
/// # use syn::ext::IdentExt;
/// use syn::parse::discouraged::Speculative;
/// # use syn::parse::{Parse, ParseStream};
/// # use syn::{Ident, PathArguments, Result, Token};
///
/// pub struct PathSegment {
/// pub ident: Ident,
/// pub arguments: PathArguments,
/// }
/// #
/// # impl<T> From<T> for PathSegment
/// # where
/// # T: Into<Ident>,
/// # {
/// # fn from(ident: T) -> Self {
/// # PathSegment {
/// # ident: ident.into(),
/// # arguments: PathArguments::None,
/// # }
/// # }
/// # }
///
/// impl Parse for PathSegment {
/// fn parse(input: ParseStream) -> Result<Self> {
/// if input.peek(Token![super])
/// || input.peek(Token![self])
/// || input.peek(Token![Self])
/// || input.peek(Token![crate])
/// {
/// let ident = input.call(Ident::parse_any)?;
/// return Ok(PathSegment::from(ident));
/// }
///
/// let ident = input.parse()?;
/// if input.peek(Token![::]) && input.peek3(Token![<]) {
/// return Ok(PathSegment {
/// ident,
/// arguments: PathArguments::AngleBracketed(input.parse()?),
/// });
/// }
/// if input.peek(Token![<]) && !input.peek(Token![<=]) {
/// let fork = input.fork();
/// if let Ok(arguments) = fork.parse() {
/// input.advance_to(&fork);
/// return Ok(PathSegment {
/// ident,
/// arguments: PathArguments::AngleBracketed(arguments),
/// });
/// }
/// }
/// Ok(PathSegment::from(ident))
/// }
/// }
///
/// # syn::parse_str::<PathSegment>("a<b,c>").unwrap();
/// ```
///
/// # Drawbacks
///
/// The main drawback of this style of speculative parsing is in error
/// presentation. Even if the lookahead is the "correct" parse, the error
/// that is shown is that of the "fallback" parse. To use the same example
/// as the turbofish above, take the following unfinished "turbofish":
///
/// ```text
/// let _ = f<&'a fn(), for<'a> serde::>();
/// ```
///
/// If this is parsed as generic arguments, we can provide the error message
///
/// ```text
/// error: expected identifier
/// --> src.rs:L:C
/// |
/// L | let _ = f<&'a fn(), for<'a> serde::>();
/// | ^
/// ```
///
/// but if parsed using the above speculative parsing, it falls back to
/// assuming that the `<` is a less-than when it fails to parse the generic
/// arguments, and tries to interpret the `&'a` as the start of a labelled
/// loop, resulting in the much less helpful error
///
/// ```text
/// error: expected `:`
/// --> src.rs:L:C
/// |
/// L | let _ = f<&'a fn(), for<'a> serde::>();
/// | ^^
/// ```
///
/// This can be mitigated with various heuristics (two examples: show both
/// forks' parse errors, or show the one that consumed more tokens), but
/// when you can control the grammar, sticking to something that can be
/// parsed LL(3) and without the LL(*) speculative parsing this makes
/// possible, displaying reasonable errors becomes much more simple.
///
/// [RFC 2544]: https://github.com/rust-lang/rfcs/pull/2544
/// [`PathSegment`]: crate::PathSegment
///
/// # Performance
///
/// This method performs a cheap fixed amount of work that does not depend
/// on how far apart the two streams are positioned.
///
/// # Panics
///
/// The forked stream in the argument of `advance_to` must have been
/// obtained by forking `self`. Attempting to advance to any other stream
/// will cause a panic.
fn advance_to(&self, fork: &Self);
}
impl<'a> Speculative for ParseBuffer<'a> {
fn advance_to(&self, fork: &Self) {
if !crate::buffer::same_scope(self.cursor(), fork.cursor()) {
panic!("Fork was not derived from the advancing parse stream");
}
let (self_unexp, self_sp) = inner_unexpected(self);
let (fork_unexp, fork_sp) = inner_unexpected(fork);
if !Rc::ptr_eq(&self_unexp, &fork_unexp) {
match (fork_sp, self_sp) {
// Unexpected set on the fork, but not on `self`, copy it over.
(Some(span), None) => {
self_unexp.set(Unexpected::Some(span));
}
// Unexpected unset. Use chain to propagate errors from fork.
(None, None) => {
fork_unexp.set(Unexpected::Chain(self_unexp));
// Ensure toplevel 'unexpected' tokens from the fork don't
// bubble up the chain by replacing the root `unexpected`
// pointer, only 'unexpected' tokens from existing group
// parsers should bubble.
fork.unexpected
.set(Some(Rc::new(Cell::new(Unexpected::None))));
}
// Unexpected has been set on `self`. No changes needed.
(_, Some(_)) => {}
}
}
// See comment on `cell` in the struct definition.
self.cell
.set(unsafe { mem::transmute::<Cursor, Cursor<'static>>(fork.cursor()) });
}
}

58
third_party/rust/syn-1.0.107/src/drops.rs поставляемый
Просмотреть файл

@ -1,58 +0,0 @@
use std::iter;
use std::mem::ManuallyDrop;
use std::ops::{Deref, DerefMut};
use std::option;
use std::slice;
#[repr(transparent)]
pub(crate) struct NoDrop<T: ?Sized>(ManuallyDrop<T>);
impl<T> NoDrop<T> {
pub(crate) fn new(value: T) -> Self
where
T: TrivialDrop,
{
NoDrop(ManuallyDrop::new(value))
}
}
impl<T: ?Sized> Deref for NoDrop<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: ?Sized> DerefMut for NoDrop<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub(crate) trait TrivialDrop {}
impl<T> TrivialDrop for iter::Empty<T> {}
impl<'a, T> TrivialDrop for slice::Iter<'a, T> {}
impl<'a, T> TrivialDrop for slice::IterMut<'a, T> {}
impl<'a, T> TrivialDrop for option::IntoIter<&'a T> {}
impl<'a, T> TrivialDrop for option::IntoIter<&'a mut T> {}
#[test]
fn test_needs_drop() {
use std::mem::needs_drop;
struct NeedsDrop;
impl Drop for NeedsDrop {
fn drop(&mut self) {}
}
assert!(needs_drop::<NeedsDrop>());
// Test each of the types with a handwritten TrivialDrop impl above.
assert!(!needs_drop::<iter::Empty<NeedsDrop>>());
assert!(!needs_drop::<slice::Iter<NeedsDrop>>());
assert!(!needs_drop::<slice::IterMut<NeedsDrop>>());
assert!(!needs_drop::<option::IntoIter<&NeedsDrop>>());
assert!(!needs_drop::<option::IntoIter<&mut NeedsDrop>>());
}

428
third_party/rust/syn-1.0.107/src/error.rs поставляемый
Просмотреть файл

@ -1,428 +0,0 @@
#[cfg(feature = "parsing")]
use crate::buffer::Cursor;
use crate::thread::ThreadBound;
use proc_macro2::{
Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
#[cfg(feature = "printing")]
use quote::ToTokens;
use std::fmt::{self, Debug, Display};
use std::iter::FromIterator;
use std::slice;
use std::vec;
/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;
/// Error returned when a Syn parser cannot parse the input tokens.
///
/// # Error reporting in proc macros
///
/// The correct way to report errors back to the compiler from a procedural
/// macro is by emitting an appropriately spanned invocation of
/// [`compile_error!`] in the generated code. This produces a better diagnostic
/// message than simply panicking the macro.
///
/// [`compile_error!`]: std::compile_error!
///
/// When parsing macro input, the [`parse_macro_input!`] macro handles the
/// conversion to `compile_error!` automatically.
///
/// [`parse_macro_input!`]: crate::parse_macro_input!
///
/// ```
/// # extern crate proc_macro;
/// #
/// use proc_macro::TokenStream;
/// use syn::{parse_macro_input, AttributeArgs, ItemFn};
///
/// # const IGNORE: &str = stringify! {
/// #[proc_macro_attribute]
/// # };
/// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream {
/// let args = parse_macro_input!(args as AttributeArgs);
/// let input = parse_macro_input!(input as ItemFn);
///
/// /* ... */
/// # TokenStream::new()
/// }
/// ```
///
/// For errors that arise later than the initial parsing stage, the
/// [`.to_compile_error()`] or [`.into_compile_error()`] methods can be used to
/// perform an explicit conversion to `compile_error!`.
///
/// [`.to_compile_error()`]: Error::to_compile_error
/// [`.into_compile_error()`]: Error::into_compile_error
///
/// ```
/// # extern crate proc_macro;
/// #
/// # use proc_macro::TokenStream;
/// # use syn::{parse_macro_input, DeriveInput};
/// #
/// # const IGNORE: &str = stringify! {
/// #[proc_macro_derive(MyDerive)]
/// # };
/// pub fn my_derive(input: TokenStream) -> TokenStream {
/// let input = parse_macro_input!(input as DeriveInput);
///
/// // fn(DeriveInput) -> syn::Result<proc_macro2::TokenStream>
/// expand::my_derive(input)
/// .unwrap_or_else(syn::Error::into_compile_error)
/// .into()
/// }
/// #
/// # mod expand {
/// # use proc_macro2::TokenStream;
/// # use syn::{DeriveInput, Result};
/// #
/// # pub fn my_derive(input: DeriveInput) -> Result<TokenStream> {
/// # unimplemented!()
/// # }
/// # }
/// ```
pub struct Error {
messages: Vec<ErrorMessage>,
}
struct ErrorMessage {
// Span is implemented as an index into a thread-local interner to keep the
// size small. It is not safe to access from a different thread. We want
// errors to be Send and Sync to play nicely with the Failure crate, so pin
// the span we're given to its original thread and assume it is
// Span::call_site if accessed from any other thread.
start_span: ThreadBound<Span>,
end_span: ThreadBound<Span>,
message: String,
}
#[cfg(test)]
struct _Test
where
Error: Send + Sync;
impl Error {
/// Usually the [`ParseStream::error`] method will be used instead, which
/// automatically uses the correct span from the current position of the
/// parse stream.
///
/// Use `Error::new` when the error needs to be triggered on some span other
/// than where the parse stream is currently positioned.
///
/// [`ParseStream::error`]: crate::parse::ParseBuffer::error
///
/// # Example
///
/// ```
/// use syn::{Error, Ident, LitStr, Result, Token};
/// use syn::parse::ParseStream;
///
/// // Parses input that looks like `name = "string"` where the key must be
/// // the identifier `name` and the value may be any string literal.
/// // Returns the string literal.
/// fn parse_name(input: ParseStream) -> Result<LitStr> {
/// let name_token: Ident = input.parse()?;
/// if name_token != "name" {
/// // Trigger an error not on the current position of the stream,
/// // but on the position of the unexpected identifier.
/// return Err(Error::new(name_token.span(), "expected `name`"));
/// }
/// input.parse::<Token![=]>()?;
/// let s: LitStr = input.parse()?;
/// Ok(s)
/// }
/// ```
pub fn new<T: Display>(span: Span, message: T) -> Self {
return new(span, message.to_string());
fn new(span: Span, message: String) -> Error {
Error {
messages: vec![ErrorMessage {
start_span: ThreadBound::new(span),
end_span: ThreadBound::new(span),
message,
}],
}
}
}
/// Creates an error with the specified message spanning the given syntax
/// tree node.
///
/// Unlike the `Error::new` constructor, this constructor takes an argument
/// `tokens` which is a syntax tree node. This allows the resulting `Error`
/// to attempt to span all tokens inside of `tokens`. While you would
/// typically be able to use the `Spanned` trait with the above `Error::new`
/// constructor, implementation limitations today mean that
/// `Error::new_spanned` may provide a higher-quality error message on
/// stable Rust.
///
/// When in doubt it's recommended to stick to `Error::new` (or
/// `ParseStream::error`)!
#[cfg(feature = "printing")]
pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
return new_spanned(tokens.into_token_stream(), message.to_string());
fn new_spanned(tokens: TokenStream, message: String) -> Error {
let mut iter = tokens.into_iter();
let start = iter.next().map_or_else(Span::call_site, |t| t.span());
let end = iter.last().map_or(start, |t| t.span());
Error {
messages: vec![ErrorMessage {
start_span: ThreadBound::new(start),
end_span: ThreadBound::new(end),
message,
}],
}
}
}
/// The source location of the error.
///
/// Spans are not thread-safe so this function returns `Span::call_site()`
/// if called from a different thread than the one on which the `Error` was
/// originally created.
pub fn span(&self) -> Span {
let start = match self.messages[0].start_span.get() {
Some(span) => *span,
None => return Span::call_site(),
};
let end = match self.messages[0].end_span.get() {
Some(span) => *span,
None => return Span::call_site(),
};
start.join(end).unwrap_or(start)
}
/// Render the error as an invocation of [`compile_error!`].
///
/// The [`parse_macro_input!`] macro provides a convenient way to invoke
/// this method correctly in a procedural macro.
///
/// [`compile_error!`]: std::compile_error!
/// [`parse_macro_input!`]: crate::parse_macro_input!
pub fn to_compile_error(&self) -> TokenStream {
self.messages
.iter()
.map(ErrorMessage::to_compile_error)
.collect()
}
/// Render the error as an invocation of [`compile_error!`].
///
/// [`compile_error!`]: std::compile_error!
///
/// # Example
///
/// ```
/// # extern crate proc_macro;
/// #
/// use proc_macro::TokenStream;
/// use syn::{parse_macro_input, DeriveInput, Error};
///
/// # const _: &str = stringify! {
/// #[proc_macro_derive(MyTrait)]
/// # };
/// pub fn derive_my_trait(input: TokenStream) -> TokenStream {
/// let input = parse_macro_input!(input as DeriveInput);
/// my_trait::expand(input)
/// .unwrap_or_else(Error::into_compile_error)
/// .into()
/// }
///
/// mod my_trait {
/// use proc_macro2::TokenStream;
/// use syn::{DeriveInput, Result};
///
/// pub(crate) fn expand(input: DeriveInput) -> Result<TokenStream> {
/// /* ... */
/// # unimplemented!()
/// }
/// }
/// ```
pub fn into_compile_error(self) -> TokenStream {
self.to_compile_error()
}
/// Add another error message to self such that when `to_compile_error()` is
/// called, both errors will be emitted together.
pub fn combine(&mut self, another: Error) {
self.messages.extend(another.messages);
}
}
impl ErrorMessage {
fn to_compile_error(&self) -> TokenStream {
let start = self
.start_span
.get()
.cloned()
.unwrap_or_else(Span::call_site);
let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
// compile_error!($message)
TokenStream::from_iter(vec![
TokenTree::Ident(Ident::new("compile_error", start)),
TokenTree::Punct({
let mut punct = Punct::new('!', Spacing::Alone);
punct.set_span(start);
punct
}),
TokenTree::Group({
let mut group = Group::new(Delimiter::Brace, {
TokenStream::from_iter(vec![TokenTree::Literal({
let mut string = Literal::string(&self.message);
string.set_span(end);
string
})])
});
group.set_span(end);
group
}),
])
}
}
#[cfg(feature = "parsing")]
pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
if cursor.eof() {
Error::new(scope, format!("unexpected end of input, {}", message))
} else {
let span = crate::buffer::open_span_of_group(cursor);
Error::new(span, message)
}
}
#[cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))]
pub fn new2<T: Display>(start: Span, end: Span, message: T) -> Error {
return new2(start, end, message.to_string());
fn new2(start: Span, end: Span, message: String) -> Error {
Error {
messages: vec![ErrorMessage {
start_span: ThreadBound::new(start),
end_span: ThreadBound::new(end),
message,
}],
}
}
}
impl Debug for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
if self.messages.len() == 1 {
formatter
.debug_tuple("Error")
.field(&self.messages[0])
.finish()
} else {
formatter
.debug_tuple("Error")
.field(&self.messages)
.finish()
}
}
}
impl Debug for ErrorMessage {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.message, formatter)
}
}
impl Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(&self.messages[0].message)
}
}
impl Clone for Error {
fn clone(&self) -> Self {
Error {
messages: self.messages.clone(),
}
}
}
impl Clone for ErrorMessage {
fn clone(&self) -> Self {
let start = self
.start_span
.get()
.cloned()
.unwrap_or_else(Span::call_site);
let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
ErrorMessage {
start_span: ThreadBound::new(start),
end_span: ThreadBound::new(end),
message: self.message.clone(),
}
}
}
impl std::error::Error for Error {}
impl From<LexError> for Error {
fn from(err: LexError) -> Self {
Error::new(err.span(), "lex error")
}
}
impl IntoIterator for Error {
type Item = Error;
type IntoIter = IntoIter;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
messages: self.messages.into_iter(),
}
}
}
pub struct IntoIter {
messages: vec::IntoIter<ErrorMessage>,
}
impl Iterator for IntoIter {
type Item = Error;
fn next(&mut self) -> Option<Self::Item> {
Some(Error {
messages: vec![self.messages.next()?],
})
}
}
impl<'a> IntoIterator for &'a Error {
type Item = Error;
type IntoIter = Iter<'a>;
fn into_iter(self) -> Self::IntoIter {
Iter {
messages: self.messages.iter(),
}
}
}
pub struct Iter<'a> {
messages: slice::Iter<'a, ErrorMessage>,
}
impl<'a> Iterator for Iter<'a> {
type Item = Error;
fn next(&mut self) -> Option<Self::Item> {
Some(Error {
messages: vec![self.messages.next()?.clone()],
})
}
}
impl Extend<Error> for Error {
fn extend<T: IntoIterator<Item = Error>>(&mut self, iter: T) {
for err in iter {
self.combine(err);
}
}
}

39
third_party/rust/syn-1.0.107/src/export.rs поставляемый
Просмотреть файл

@ -1,39 +0,0 @@
pub use std::clone::Clone;
pub use std::cmp::{Eq, PartialEq};
pub use std::default::Default;
pub use std::fmt::{self, Debug, Formatter};
pub use std::hash::{Hash, Hasher};
pub use std::marker::Copy;
pub use std::option::Option::{None, Some};
pub use std::result::Result::{Err, Ok};
#[cfg(feature = "printing")]
pub extern crate quote;
pub use proc_macro2::{Span, TokenStream as TokenStream2};
#[cfg(feature = "parsing")]
pub use crate::group::{parse_braces, parse_brackets, parse_parens};
pub use crate::span::IntoSpans;
#[cfg(all(
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
feature = "proc-macro"
))]
pub use proc_macro::TokenStream;
#[cfg(feature = "printing")]
pub use quote::{ToTokens, TokenStreamExt};
#[allow(non_camel_case_types)]
pub type bool = help::Bool;
#[allow(non_camel_case_types)]
pub type str = help::Str;
mod help {
pub type Bool = bool;
pub type Str = str;
}
pub struct private(pub(crate) ());

3558
third_party/rust/syn-1.0.107/src/expr.rs поставляемый

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

139
third_party/rust/syn-1.0.107/src/ext.rs поставляемый
Просмотреть файл

@ -1,139 +0,0 @@
//! Extension traits to provide parsing methods on foreign types.
//!
//! *This module is available only if Syn is built with the `"parsing"` feature.*
use crate::buffer::Cursor;
use crate::parse::Peek;
use crate::parse::{ParseStream, Result};
use crate::sealed::lookahead;
use crate::token::CustomToken;
use proc_macro2::Ident;
/// Additional methods for `Ident` not provided by proc-macro2 or libproc_macro.
///
/// This trait is sealed and cannot be implemented for types outside of Syn. It
/// is implemented only for `proc_macro2::Ident`.
///
/// *This trait is available only if Syn is built with the `"parsing"` feature.*
pub trait IdentExt: Sized + private::Sealed {
/// Parses any identifier including keywords.
///
/// This is useful when parsing macro input which allows Rust keywords as
/// identifiers.
///
/// # Example
///
/// ```
/// use syn::{Error, Ident, Result, Token};
/// use syn::ext::IdentExt;
/// use syn::parse::ParseStream;
///
/// mod kw {
/// syn::custom_keyword!(name);
/// }
///
/// // Parses input that looks like `name = NAME` where `NAME` can be
/// // any identifier.
/// //
/// // Examples:
/// //
/// // name = anything
/// // name = impl
/// fn parse_dsl(input: ParseStream) -> Result<Ident> {
/// input.parse::<kw::name>()?;
/// input.parse::<Token![=]>()?;
/// let name = input.call(Ident::parse_any)?;
/// Ok(name)
/// }
/// ```
fn parse_any(input: ParseStream) -> Result<Self>;
/// Peeks any identifier including keywords. Usage:
/// `input.peek(Ident::peek_any)`
///
/// This is different from `input.peek(Ident)` which only returns true in
/// the case of an ident which is not a Rust keyword.
#[allow(non_upper_case_globals)]
const peek_any: private::PeekFn = private::PeekFn;
/// Strips the raw marker `r#`, if any, from the beginning of an ident.
///
/// - unraw(`x`) = `x`
/// - unraw(`move`) = `move`
/// - unraw(`r#move`) = `move`
///
/// # Example
///
/// In the case of interop with other languages like Python that have a
/// different set of keywords than Rust, we might come across macro input
/// that involves raw identifiers to refer to ordinary variables in the
/// other language with a name that happens to be a Rust keyword.
///
/// The function below appends an identifier from the caller's input onto a
/// fixed prefix. Without using `unraw()`, this would tend to produce
/// invalid identifiers like `__pyo3_get_r#move`.
///
/// ```
/// use proc_macro2::Span;
/// use syn::Ident;
/// use syn::ext::IdentExt;
///
/// fn ident_for_getter(variable: &Ident) -> Ident {
/// let getter = format!("__pyo3_get_{}", variable.unraw());
/// Ident::new(&getter, Span::call_site())
/// }
/// ```
fn unraw(&self) -> Ident;
}
impl IdentExt for Ident {
fn parse_any(input: ParseStream) -> Result<Self> {
input.step(|cursor| match cursor.ident() {
Some((ident, rest)) => Ok((ident, rest)),
None => Err(cursor.error("expected ident")),
})
}
fn unraw(&self) -> Ident {
let string = self.to_string();
if string.starts_with("r#") {
Ident::new(&string[2..], self.span())
} else {
self.clone()
}
}
}
impl Peek for private::PeekFn {
type Token = private::IdentAny;
}
impl CustomToken for private::IdentAny {
fn peek(cursor: Cursor) -> bool {
cursor.ident().is_some()
}
fn display() -> &'static str {
"identifier"
}
}
impl lookahead::Sealed for private::PeekFn {}
mod private {
use proc_macro2::Ident;
pub trait Sealed {}
impl Sealed for Ident {}
pub struct PeekFn;
pub struct IdentAny;
impl Copy for PeekFn {}
impl Clone for PeekFn {
fn clone(&self) -> Self {
*self
}
}
}

125
third_party/rust/syn-1.0.107/src/file.rs поставляемый
Просмотреть файл

@ -1,125 +0,0 @@
use super::*;
ast_struct! {
/// A complete file of Rust source code.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
///
/// # Example
///
/// Parse a Rust source file into a `syn::File` and print out a debug
/// representation of the syntax tree.
///
/// ```
/// use std::env;
/// use std::fs::File;
/// use std::io::Read;
/// use std::process;
///
/// fn main() {
/// # }
/// #
/// # fn fake_main() {
/// let mut args = env::args();
/// let _ = args.next(); // executable name
///
/// let filename = match (args.next(), args.next()) {
/// (Some(filename), None) => filename,
/// _ => {
/// eprintln!("Usage: dump-syntax path/to/filename.rs");
/// process::exit(1);
/// }
/// };
///
/// let mut file = File::open(&filename).expect("Unable to open file");
///
/// let mut src = String::new();
/// file.read_to_string(&mut src).expect("Unable to read file");
///
/// let syntax = syn::parse_file(&src).expect("Unable to parse file");
///
/// // Debug impl is available if Syn is built with "extra-traits" feature.
/// println!("{:#?}", syntax);
/// }
/// ```
///
/// Running with its own source code as input, this program prints output
/// that begins with:
///
/// ```text
/// File {
/// shebang: None,
/// attrs: [],
/// items: [
/// Use(
/// ItemUse {
/// attrs: [],
/// vis: Inherited,
/// use_token: Use,
/// leading_colon: None,
/// tree: Path(
/// UsePath {
/// ident: Ident(
/// std,
/// ),
/// colon2_token: Colon2,
/// tree: Name(
/// UseName {
/// ident: Ident(
/// env,
/// ),
/// },
/// ),
/// },
/// ),
/// semi_token: Semi,
/// },
/// ),
/// ...
/// ```
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct File {
pub shebang: Option<String>,
pub attrs: Vec<Attribute>,
pub items: Vec<Item>,
}
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use crate::parse::{Parse, ParseStream, Result};
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for File {
fn parse(input: ParseStream) -> Result<Self> {
Ok(File {
shebang: None,
attrs: input.call(Attribute::parse_inner)?,
items: {
let mut items = Vec::new();
while !input.is_empty() {
items.push(input.parse()?);
}
items
},
})
}
}
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use crate::attr::FilterAttrs;
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt};
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for File {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.inner());
tokens.append_all(&self.items);
}
}
}

2241
third_party/rust/syn-1.0.107/src/gen/clone.rs поставляемый

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

3042
third_party/rust/syn-1.0.107/src/gen/debug.rs поставляемый

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

2195
third_party/rust/syn-1.0.107/src/gen/eq.rs поставляемый

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

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

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

2869
third_party/rust/syn-1.0.107/src/gen/hash.rs поставляемый

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

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

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

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

154
third_party/rust/syn-1.0.107/src/gen_helper.rs поставляемый
Просмотреть файл

@ -1,154 +0,0 @@
#[cfg(feature = "fold")]
pub mod fold {
use crate::fold::Fold;
use crate::punctuated::{Pair, Punctuated};
use proc_macro2::Span;
pub trait FoldHelper {
type Item;
fn lift<F>(self, f: F) -> Self
where
F: FnMut(Self::Item) -> Self::Item;
}
impl<T> FoldHelper for Vec<T> {
type Item = T;
fn lift<F>(self, f: F) -> Self
where
F: FnMut(Self::Item) -> Self::Item,
{
self.into_iter().map(f).collect()
}
}
impl<T, U> FoldHelper for Punctuated<T, U> {
type Item = T;
fn lift<F>(self, mut f: F) -> Self
where
F: FnMut(Self::Item) -> Self::Item,
{
self.into_pairs()
.map(Pair::into_tuple)
.map(|(t, u)| Pair::new(f(t), u))
.collect()
}
}
pub fn tokens_helper<F: Fold + ?Sized, S: Spans>(folder: &mut F, spans: &S) -> S {
spans.fold(folder)
}
pub trait Spans {
fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self;
}
impl Spans for Span {
fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self {
folder.fold_span(*self)
}
}
impl Spans for [Span; 1] {
fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self {
[folder.fold_span(self[0])]
}
}
impl Spans for [Span; 2] {
fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self {
[folder.fold_span(self[0]), folder.fold_span(self[1])]
}
}
impl Spans for [Span; 3] {
fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self {
[
folder.fold_span(self[0]),
folder.fold_span(self[1]),
folder.fold_span(self[2]),
]
}
}
}
#[cfg(feature = "visit")]
pub mod visit {
use crate::visit::Visit;
use proc_macro2::Span;
pub fn tokens_helper<'ast, V: Visit<'ast> + ?Sized, S: Spans>(visitor: &mut V, spans: &S) {
spans.visit(visitor);
}
pub trait Spans {
fn visit<'ast, V: Visit<'ast> + ?Sized>(&self, visitor: &mut V);
}
impl Spans for Span {
fn visit<'ast, V: Visit<'ast> + ?Sized>(&self, visitor: &mut V) {
visitor.visit_span(self);
}
}
impl Spans for [Span; 1] {
fn visit<'ast, V: Visit<'ast> + ?Sized>(&self, visitor: &mut V) {
visitor.visit_span(&self[0]);
}
}
impl Spans for [Span; 2] {
fn visit<'ast, V: Visit<'ast> + ?Sized>(&self, visitor: &mut V) {
visitor.visit_span(&self[0]);
visitor.visit_span(&self[1]);
}
}
impl Spans for [Span; 3] {
fn visit<'ast, V: Visit<'ast> + ?Sized>(&self, visitor: &mut V) {
visitor.visit_span(&self[0]);
visitor.visit_span(&self[1]);
visitor.visit_span(&self[2]);
}
}
}
#[cfg(feature = "visit-mut")]
pub mod visit_mut {
use crate::visit_mut::VisitMut;
use proc_macro2::Span;
pub fn tokens_helper<V: VisitMut + ?Sized, S: Spans>(visitor: &mut V, spans: &mut S) {
spans.visit_mut(visitor);
}
pub trait Spans {
fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V);
}
impl Spans for Span {
fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V) {
visitor.visit_span_mut(self);
}
}
impl Spans for [Span; 1] {
fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V) {
visitor.visit_span_mut(&mut self[0]);
}
}
impl Spans for [Span; 2] {
fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V) {
visitor.visit_span_mut(&mut self[0]);
visitor.visit_span_mut(&mut self[1]);
}
}
impl Spans for [Span; 3] {
fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V) {
visitor.visit_span_mut(&mut self[0]);
visitor.visit_span_mut(&mut self[1]);
visitor.visit_span_mut(&mut self[2]);
}
}
}

1362
third_party/rust/syn-1.0.107/src/generics.rs поставляемый

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

282
third_party/rust/syn-1.0.107/src/group.rs поставляемый
Просмотреть файл

@ -1,282 +0,0 @@
use crate::error::Result;
use crate::parse::ParseBuffer;
use crate::token;
use proc_macro2::{Delimiter, Span};
// Not public API.
#[doc(hidden)]
pub struct Parens<'a> {
pub token: token::Paren,
pub content: ParseBuffer<'a>,
}
// Not public API.
#[doc(hidden)]
pub struct Braces<'a> {
pub token: token::Brace,
pub content: ParseBuffer<'a>,
}
// Not public API.
#[doc(hidden)]
pub struct Brackets<'a> {
pub token: token::Bracket,
pub content: ParseBuffer<'a>,
}
// Not public API.
#[cfg(any(feature = "full", feature = "derive"))]
#[doc(hidden)]
pub struct Group<'a> {
pub token: token::Group,
pub content: ParseBuffer<'a>,
}
// Not public API.
#[doc(hidden)]
pub fn parse_parens<'a>(input: &ParseBuffer<'a>) -> Result<Parens<'a>> {
parse_delimited(input, Delimiter::Parenthesis).map(|(span, content)| Parens {
token: token::Paren(span),
content,
})
}
// Not public API.
#[doc(hidden)]
pub fn parse_braces<'a>(input: &ParseBuffer<'a>) -> Result<Braces<'a>> {
parse_delimited(input, Delimiter::Brace).map(|(span, content)| Braces {
token: token::Brace(span),
content,
})
}
// Not public API.
#[doc(hidden)]
pub fn parse_brackets<'a>(input: &ParseBuffer<'a>) -> Result<Brackets<'a>> {
parse_delimited(input, Delimiter::Bracket).map(|(span, content)| Brackets {
token: token::Bracket(span),
content,
})
}
#[cfg(any(feature = "full", feature = "derive"))]
pub(crate) fn parse_group<'a>(input: &ParseBuffer<'a>) -> Result<Group<'a>> {
parse_delimited(input, Delimiter::None).map(|(span, content)| Group {
token: token::Group(span),
content,
})
}
fn parse_delimited<'a>(
input: &ParseBuffer<'a>,
delimiter: Delimiter,
) -> Result<(Span, ParseBuffer<'a>)> {
input.step(|cursor| {
if let Some((content, span, rest)) = cursor.group(delimiter) {
let scope = crate::buffer::close_span_of_group(*cursor);
let nested = crate::parse::advance_step_cursor(cursor, content);
let unexpected = crate::parse::get_unexpected(input);
let content = crate::parse::new_parse_buffer(scope, nested, unexpected);
Ok(((span, content), rest))
} else {
let message = match delimiter {
Delimiter::Parenthesis => "expected parentheses",
Delimiter::Brace => "expected curly braces",
Delimiter::Bracket => "expected square brackets",
Delimiter::None => "expected invisible group",
};
Err(cursor.error(message))
}
})
}
/// Parse a set of parentheses and expose their content to subsequent parsers.
///
/// # Example
///
/// ```
/// # use quote::quote;
/// #
/// use syn::{parenthesized, token, Ident, Result, Token, Type};
/// use syn::parse::{Parse, ParseStream};
/// use syn::punctuated::Punctuated;
///
/// // Parse a simplified tuple struct syntax like:
/// //
/// // struct S(A, B);
/// struct TupleStruct {
/// struct_token: Token![struct],
/// ident: Ident,
/// paren_token: token::Paren,
/// fields: Punctuated<Type, Token![,]>,
/// semi_token: Token![;],
/// }
///
/// impl Parse for TupleStruct {
/// fn parse(input: ParseStream) -> Result<Self> {
/// let content;
/// Ok(TupleStruct {
/// struct_token: input.parse()?,
/// ident: input.parse()?,
/// paren_token: parenthesized!(content in input),
/// fields: content.parse_terminated(Type::parse)?,
/// semi_token: input.parse()?,
/// })
/// }
/// }
/// #
/// # fn main() {
/// # let input = quote! {
/// # struct S(A, B);
/// # };
/// # syn::parse2::<TupleStruct>(input).unwrap();
/// # }
/// ```
#[macro_export]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
macro_rules! parenthesized {
($content:ident in $cursor:expr) => {
match $crate::__private::parse_parens(&$cursor) {
$crate::__private::Ok(parens) => {
$content = parens.content;
parens.token
}
$crate::__private::Err(error) => {
return $crate::__private::Err(error);
}
}
};
}
/// Parse a set of curly braces and expose their content to subsequent parsers.
///
/// # Example
///
/// ```
/// # use quote::quote;
/// #
/// use syn::{braced, token, Ident, Result, Token, Type};
/// use syn::parse::{Parse, ParseStream};
/// use syn::punctuated::Punctuated;
///
/// // Parse a simplified struct syntax like:
/// //
/// // struct S {
/// // a: A,
/// // b: B,
/// // }
/// struct Struct {
/// struct_token: Token![struct],
/// ident: Ident,
/// brace_token: token::Brace,
/// fields: Punctuated<Field, Token![,]>,
/// }
///
/// struct Field {
/// name: Ident,
/// colon_token: Token![:],
/// ty: Type,
/// }
///
/// impl Parse for Struct {
/// fn parse(input: ParseStream) -> Result<Self> {
/// let content;
/// Ok(Struct {
/// struct_token: input.parse()?,
/// ident: input.parse()?,
/// brace_token: braced!(content in input),
/// fields: content.parse_terminated(Field::parse)?,
/// })
/// }
/// }
///
/// impl Parse for Field {
/// fn parse(input: ParseStream) -> Result<Self> {
/// Ok(Field {
/// name: input.parse()?,
/// colon_token: input.parse()?,
/// ty: input.parse()?,
/// })
/// }
/// }
/// #
/// # fn main() {
/// # let input = quote! {
/// # struct S {
/// # a: A,
/// # b: B,
/// # }
/// # };
/// # syn::parse2::<Struct>(input).unwrap();
/// # }
/// ```
#[macro_export]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
macro_rules! braced {
($content:ident in $cursor:expr) => {
match $crate::__private::parse_braces(&$cursor) {
$crate::__private::Ok(braces) => {
$content = braces.content;
braces.token
}
$crate::__private::Err(error) => {
return $crate::__private::Err(error);
}
}
};
}
/// Parse a set of square brackets and expose their content to subsequent
/// parsers.
///
/// # Example
///
/// ```
/// # use quote::quote;
/// #
/// use proc_macro2::TokenStream;
/// use syn::{bracketed, token, Result, Token};
/// use syn::parse::{Parse, ParseStream};
///
/// // Parse an outer attribute like:
/// //
/// // #[repr(C, packed)]
/// struct OuterAttribute {
/// pound_token: Token![#],
/// bracket_token: token::Bracket,
/// content: TokenStream,
/// }
///
/// impl Parse for OuterAttribute {
/// fn parse(input: ParseStream) -> Result<Self> {
/// let content;
/// Ok(OuterAttribute {
/// pound_token: input.parse()?,
/// bracket_token: bracketed!(content in input),
/// content: content.parse()?,
/// })
/// }
/// }
/// #
/// # fn main() {
/// # let input = quote! {
/// # #[repr(C, packed)]
/// # };
/// # syn::parse2::<OuterAttribute>(input).unwrap();
/// # }
/// ```
#[macro_export]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
macro_rules! bracketed {
($content:ident in $cursor:expr) => {
match $crate::__private::parse_brackets(&$cursor) {
$crate::__private::Ok(brackets) => {
$content = brackets.content;
brackets.token
}
$crate::__private::Err(error) => {
return $crate::__private::Err(error);
}
}
};
}

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

@ -1,101 +0,0 @@
#[cfg(feature = "parsing")]
use crate::buffer::Cursor;
#[cfg(feature = "parsing")]
use crate::lookahead;
#[cfg(feature = "parsing")]
use crate::parse::{Parse, ParseStream, Result};
#[cfg(feature = "parsing")]
use crate::token::Token;
pub use proc_macro2::Ident;
#[cfg(feature = "parsing")]
#[doc(hidden)]
#[allow(non_snake_case)]
pub fn Ident(marker: lookahead::TokenMarker) -> Ident {
match marker {}
}
#[cfg(feature = "parsing")]
fn accept_as_ident(ident: &Ident) -> bool {
match ident.to_string().as_str() {
"_" |
// Based on https://doc.rust-lang.org/grammar.html#keywords
// and https://github.com/rust-lang/rfcs/blob/master/text/2421-unreservations-2018.md
// and https://github.com/rust-lang/rfcs/blob/master/text/2420-unreserve-proc.md
"abstract" | "as" | "become" | "box" | "break" | "const" | "continue" |
"crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" |
"for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" |
"mod" | "move" | "mut" | "override" | "priv" | "pub" | "ref" |
"return" | "Self" | "self" | "static" | "struct" | "super" | "trait" |
"true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" |
"where" | "while" | "yield" => false,
_ => true,
}
}
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Ident {
fn parse(input: ParseStream) -> Result<Self> {
input.step(|cursor| {
if let Some((ident, rest)) = cursor.ident() {
if accept_as_ident(&ident) {
return Ok((ident, rest));
}
}
Err(cursor.error("expected identifier"))
})
}
}
#[cfg(feature = "parsing")]
impl Token for Ident {
fn peek(cursor: Cursor) -> bool {
if let Some((ident, _rest)) = cursor.ident() {
accept_as_ident(&ident)
} else {
false
}
}
fn display() -> &'static str {
"identifier"
}
}
macro_rules! ident_from_token {
($token:ident) => {
impl From<Token![$token]> for Ident {
fn from(token: Token![$token]) -> Ident {
Ident::new(stringify!($token), token.span)
}
}
};
}
ident_from_token!(self);
ident_from_token!(Self);
ident_from_token!(super);
ident_from_token!(crate);
ident_from_token!(extern);
impl From<Token![_]> for Ident {
fn from(token: Token![_]) -> Ident {
Ident::new("_", token.span)
}
}
pub fn xid_ok(symbol: &str) -> bool {
let mut chars = symbol.chars();
let first = chars.next().unwrap();
if !(first == '_' || unicode_ident::is_xid_start(first)) {
return false;
}
for ch in chars {
if !unicode_ident::is_xid_continue(ch) {
return false;
}
}
true
}

3313
third_party/rust/syn-1.0.107/src/item.rs поставляемый

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

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

@ -1,984 +0,0 @@
//! [![github]](https://github.com/dtolnay/syn)&ensp;[![crates-io]](https://crates.io/crates/syn)&ensp;[![docs-rs]](crate)
//!
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
//!
//! <br>
//!
//! Syn is a parsing library for parsing a stream of Rust tokens into a syntax
//! tree of Rust source code.
//!
//! Currently this library is geared toward use in Rust procedural macros, but
//! contains some APIs that may be useful more generally.
//!
//! - **Data structures** — Syn provides a complete syntax tree that can
//! represent any valid Rust source code. The syntax tree is rooted at
//! [`syn::File`] which represents a full source file, but there are other
//! entry points that may be useful to procedural macros including
//! [`syn::Item`], [`syn::Expr`] and [`syn::Type`].
//!
//! - **Derives** — Of particular interest to derive macros is
//! [`syn::DeriveInput`] which is any of the three legal input items to a
//! derive macro. An example below shows using this type in a library that can
//! derive implementations of a user-defined trait.
//!
//! - **Parsing** — Parsing in Syn is built around [parser functions] with the
//! signature `fn(ParseStream) -> Result<T>`. Every syntax tree node defined
//! by Syn is individually parsable and may be used as a building block for
//! custom syntaxes, or you may dream up your own brand new syntax without
//! involving any of our syntax tree types.
//!
//! - **Location information** — Every token parsed by Syn is associated with a
//! `Span` that tracks line and column information back to the source of that
//! token. These spans allow a procedural macro to display detailed error
//! messages pointing to all the right places in the user's code. There is an
//! example of this below.
//!
//! - **Feature flags** — Functionality is aggressively feature gated so your
//! procedural macros enable only what they need, and do not pay in compile
//! time for all the rest.
//!
//! [`syn::File`]: File
//! [`syn::Item`]: Item
//! [`syn::Expr`]: Expr
//! [`syn::Type`]: Type
//! [`syn::DeriveInput`]: DeriveInput
//! [parser functions]: mod@parse
//!
//! <br>
//!
//! # Example of a derive macro
//!
//! The canonical derive macro using Syn looks like this. We write an ordinary
//! Rust function tagged with a `proc_macro_derive` attribute and the name of
//! the trait we are deriving. Any time that derive appears in the user's code,
//! the Rust compiler passes their data structure as tokens into our macro. We
//! get to execute arbitrary Rust code to figure out what to do with those
//! tokens, then hand some tokens back to the compiler to compile into the
//! user's crate.
//!
//! [`TokenStream`]: proc_macro::TokenStream
//!
//! ```toml
//! [dependencies]
//! syn = "1.0"
//! quote = "1.0"
//!
//! [lib]
//! proc-macro = true
//! ```
//!
//! ```
//! # extern crate proc_macro;
//! #
//! use proc_macro::TokenStream;
//! use quote::quote;
//! use syn::{parse_macro_input, DeriveInput};
//!
//! # const IGNORE_TOKENS: &str = stringify! {
//! #[proc_macro_derive(MyMacro)]
//! # };
//! pub fn my_macro(input: TokenStream) -> TokenStream {
//! // Parse the input tokens into a syntax tree
//! let input = parse_macro_input!(input as DeriveInput);
//!
//! // Build the output, possibly using quasi-quotation
//! let expanded = quote! {
//! // ...
//! };
//!
//! // Hand the output tokens back to the compiler
//! TokenStream::from(expanded)
//! }
//! ```
//!
//! The [`heapsize`] example directory shows a complete working implementation
//! of a derive macro. It works on any Rust compiler 1.31+. The example derives
//! a `HeapSize` trait which computes an estimate of the amount of heap memory
//! owned by a value.
//!
//! [`heapsize`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize
//!
//! ```
//! pub trait HeapSize {
//! /// Total number of bytes of heap memory owned by `self`.
//! fn heap_size_of_children(&self) -> usize;
//! }
//! ```
//!
//! The derive macro allows users to write `#[derive(HeapSize)]` on data
//! structures in their program.
//!
//! ```
//! # const IGNORE_TOKENS: &str = stringify! {
//! #[derive(HeapSize)]
//! # };
//! struct Demo<'a, T: ?Sized> {
//! a: Box<T>,
//! b: u8,
//! c: &'a str,
//! d: String,
//! }
//! ```
//!
//! <p><br></p>
//!
//! # Spans and error reporting
//!
//! The token-based procedural macro API provides great control over where the
//! compiler's error messages are displayed in user code. Consider the error the
//! user sees if one of their field types does not implement `HeapSize`.
//!
//! ```
//! # const IGNORE_TOKENS: &str = stringify! {
//! #[derive(HeapSize)]
//! # };
//! struct Broken {
//! ok: String,
//! bad: std::thread::Thread,
//! }
//! ```
//!
//! By tracking span information all the way through the expansion of a
//! procedural macro as shown in the `heapsize` example, token-based macros in
//! Syn are able to trigger errors that directly pinpoint the source of the
//! problem.
//!
//! ```text
//! error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
//! --> src/main.rs:7:5
//! |
//! 7 | bad: std::thread::Thread,
//! | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `Thread`
//! ```
//!
//! <br>
//!
//! # Parsing a custom syntax
//!
//! The [`lazy-static`] example directory shows the implementation of a
//! `functionlike!(...)` procedural macro in which the input tokens are parsed
//! using Syn's parsing API.
//!
//! [`lazy-static`]: https://github.com/dtolnay/syn/tree/master/examples/lazy-static
//!
//! The example reimplements the popular `lazy_static` crate from crates.io as a
//! procedural macro.
//!
//! ```
//! # macro_rules! lazy_static {
//! # ($($tt:tt)*) => {}
//! # }
//! #
//! lazy_static! {
//! static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
//! }
//! ```
//!
//! The implementation shows how to trigger custom warnings and error messages
//! on the macro input.
//!
//! ```text
//! warning: come on, pick a more creative name
//! --> src/main.rs:10:16
//! |
//! 10 | static ref FOO: String = "lazy_static".to_owned();
//! | ^^^
//! ```
//!
//! <br>
//!
//! # Testing
//!
//! When testing macros, we often care not just that the macro can be used
//! successfully but also that when the macro is provided with invalid input it
//! produces maximally helpful error messages. Consider using the [`trybuild`]
//! crate to write tests for errors that are emitted by your macro or errors
//! detected by the Rust compiler in the expanded code following misuse of the
//! macro. Such tests help avoid regressions from later refactors that
//! mistakenly make an error no longer trigger or be less helpful than it used
//! to be.
//!
//! [`trybuild`]: https://github.com/dtolnay/trybuild
//!
//! <br>
//!
//! # Debugging
//!
//! When developing a procedural macro it can be helpful to look at what the
//! generated code looks like. Use `cargo rustc -- -Zunstable-options
//! --pretty=expanded` or the [`cargo expand`] subcommand.
//!
//! [`cargo expand`]: https://github.com/dtolnay/cargo-expand
//!
//! To show the expanded code for some crate that uses your procedural macro,
//! run `cargo expand` from that crate. To show the expanded code for one of
//! your own test cases, run `cargo expand --test the_test_case` where the last
//! argument is the name of the test file without the `.rs` extension.
//!
//! This write-up by Brandon W Maister discusses debugging in more detail:
//! [Debugging Rust's new Custom Derive system][debugging].
//!
//! [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
//!
//! <br>
//!
//! # Optional features
//!
//! Syn puts a lot of functionality behind optional features in order to
//! optimize compile time for the most common use cases. The following features
//! are available.
//!
//! - **`derive`** *(enabled by default)* — Data structures for representing the
//! possible input to a derive macro, including structs and enums and types.
//! - **`full`** — Data structures for representing the syntax tree of all valid
//! Rust source code, including items and expressions.
//! - **`parsing`** *(enabled by default)* — Ability to parse input tokens into
//! a syntax tree node of a chosen type.
//! - **`printing`** *(enabled by default)* — Ability to print a syntax tree
//! node as tokens of Rust source code.
//! - **`visit`** — Trait for traversing a syntax tree.
//! - **`visit-mut`** — Trait for traversing and mutating in place a syntax
//! tree.
//! - **`fold`** — Trait for transforming an owned syntax tree.
//! - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
//! types.
//! - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree
//! types.
//! - **`proc-macro`** *(enabled by default)* — Runtime dependency on the
//! 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/1.0.107")]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![allow(non_camel_case_types)]
#![allow(
clippy::bool_to_int_with_if,
clippy::cast_lossless,
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_ptr_alignment,
clippy::default_trait_access,
clippy::doc_markdown,
clippy::expl_impl_clone_on_copy,
clippy::explicit_auto_deref,
clippy::if_not_else,
clippy::inherent_to_string,
clippy::items_after_statements,
clippy::large_enum_variant,
clippy::manual_assert,
clippy::match_on_vec_items,
clippy::match_same_arms,
clippy::match_wildcard_for_single_variants, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
clippy::missing_errors_doc,
clippy::missing_panics_doc,
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::needless_doctest_main,
clippy::needless_pass_by_value,
clippy::never_loop,
clippy::redundant_else,
clippy::return_self_not_must_use,
clippy::similar_names,
clippy::single_match_else,
clippy::too_many_arguments,
clippy::too_many_lines,
clippy::trivially_copy_pass_by_ref,
clippy::unnecessary_unwrap,
clippy::used_underscore_binding,
clippy::wildcard_imports
)]
#[cfg(all(
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
feature = "proc-macro"
))]
extern crate proc_macro;
extern crate proc_macro2;
#[cfg(feature = "printing")]
extern crate quote;
#[macro_use]
mod macros;
#[cfg(feature = "parsing")]
#[macro_use]
mod group;
#[macro_use]
pub mod token;
mod ident;
pub use crate::ident::Ident;
#[cfg(any(feature = "full", feature = "derive"))]
mod attr;
#[cfg(any(feature = "full", feature = "derive"))]
pub use crate::attr::{
AttrStyle, Attribute, AttributeArgs, Meta, MetaList, MetaNameValue, NestedMeta,
};
mod bigint;
#[cfg(any(feature = "full", feature = "derive"))]
mod data;
#[cfg(any(feature = "full", feature = "derive"))]
pub use crate::data::{
Field, Fields, FieldsNamed, FieldsUnnamed, Variant, VisCrate, VisPublic, VisRestricted,
Visibility,
};
#[cfg(any(feature = "full", feature = "derive"))]
mod expr;
#[cfg(feature = "full")]
pub use crate::expr::{
Arm, FieldValue, GenericMethodArgument, Label, MethodTurbofish, RangeLimits,
};
#[cfg(any(feature = "full", feature = "derive"))]
pub use crate::expr::{
Expr, ExprArray, ExprAssign, ExprAssignOp, ExprAsync, ExprAwait, ExprBinary, ExprBlock,
ExprBox, ExprBreak, ExprCall, ExprCast, ExprClosure, ExprContinue, ExprField, ExprForLoop,
ExprGroup, ExprIf, ExprIndex, ExprLet, ExprLit, ExprLoop, ExprMacro, ExprMatch, ExprMethodCall,
ExprParen, ExprPath, ExprRange, ExprReference, ExprRepeat, ExprReturn, ExprStruct, ExprTry,
ExprTryBlock, ExprTuple, ExprType, ExprUnary, ExprUnsafe, ExprWhile, ExprYield, Index, Member,
};
#[cfg(any(feature = "full", feature = "derive"))]
mod generics;
#[cfg(any(feature = "full", feature = "derive"))]
pub use crate::generics::{
BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeDef, PredicateEq,
PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound,
WhereClause, WherePredicate,
};
#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
pub use crate::generics::{ImplGenerics, Turbofish, TypeGenerics};
#[cfg(feature = "full")]
mod item;
#[cfg(feature = "full")]
pub use crate::item::{
FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType,
ImplItem, ImplItemConst, ImplItemMacro, ImplItemMethod, ImplItemType, Item, ItemConst,
ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMacro2, ItemMod,
ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver,
Signature, TraitItem, TraitItemConst, TraitItemMacro, TraitItemMethod, TraitItemType, UseGlob,
UseGroup, UseName, UsePath, UseRename, UseTree,
};
#[cfg(feature = "full")]
mod file;
#[cfg(feature = "full")]
pub use crate::file::File;
mod lifetime;
pub use crate::lifetime::Lifetime;
mod lit;
pub use crate::lit::{
Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr, StrStyle,
};
#[cfg(any(feature = "full", feature = "derive"))]
mod mac;
#[cfg(any(feature = "full", feature = "derive"))]
pub use crate::mac::{Macro, MacroDelimiter};
#[cfg(any(feature = "full", feature = "derive"))]
mod derive;
#[cfg(feature = "derive")]
pub use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
#[cfg(any(feature = "full", feature = "derive"))]
mod op;
#[cfg(any(feature = "full", feature = "derive"))]
pub use crate::op::{BinOp, UnOp};
#[cfg(feature = "full")]
mod stmt;
#[cfg(feature = "full")]
pub use crate::stmt::{Block, Local, Stmt};
#[cfg(any(feature = "full", feature = "derive"))]
mod ty;
#[cfg(any(feature = "full", feature = "derive"))]
pub use crate::ty::{
Abi, BareFnArg, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait, TypeInfer,
TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, TypeSlice, TypeTraitObject,
TypeTuple, Variadic,
};
#[cfg(feature = "full")]
mod pat;
#[cfg(feature = "full")]
pub use crate::pat::{
FieldPat, Pat, PatBox, PatIdent, PatLit, PatMacro, PatOr, PatPath, PatRange, PatReference,
PatRest, PatSlice, PatStruct, PatTuple, PatTupleStruct, PatType, PatWild,
};
#[cfg(any(feature = "full", feature = "derive"))]
mod path;
#[cfg(any(feature = "full", feature = "derive"))]
pub use crate::path::{
AngleBracketedGenericArguments, Binding, Constraint, GenericArgument,
ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
};
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub mod buffer;
mod drops;
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub mod ext;
pub mod punctuated;
#[cfg(all(any(feature = "full", feature = "derive"), feature = "extra-traits"))]
mod tt;
// Not public API except the `parse_quote!` macro.
#[cfg(feature = "parsing")]
#[doc(hidden)]
pub mod parse_quote;
// Not public API except the `parse_macro_input!` macro.
#[cfg(all(
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
feature = "parsing",
feature = "proc-macro"
))]
#[doc(hidden)]
pub mod parse_macro_input;
#[cfg(all(feature = "parsing", feature = "printing"))]
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))]
pub mod spanned;
#[cfg(all(feature = "parsing", feature = "full"))]
mod whitespace;
mod gen {
/// Syntax tree traversal to walk a shared borrow of a syntax tree.
///
/// Each method of the [`Visit`] trait is a hook that can be overridden to
/// customize the behavior when visiting the corresponding type of node. By
/// default, every method recursively visits the substructure of the input
/// by invoking the right visitor method of each of its fields.
///
/// [`Visit`]: visit::Visit
///
/// ```
/// # use syn::{Attribute, BinOp, Expr, ExprBinary};
/// #
/// pub trait Visit<'ast> {
/// /* ... */
///
/// fn visit_expr_binary(&mut self, node: &'ast ExprBinary) {
/// visit_expr_binary(self, node);
/// }
///
/// /* ... */
/// # fn visit_attribute(&mut self, node: &'ast Attribute);
/// # fn visit_expr(&mut self, node: &'ast Expr);
/// # fn visit_bin_op(&mut self, node: &'ast BinOp);
/// }
///
/// pub fn visit_expr_binary<'ast, V>(v: &mut V, node: &'ast ExprBinary)
/// where
/// V: Visit<'ast> + ?Sized,
/// {
/// for attr in &node.attrs {
/// v.visit_attribute(attr);
/// }
/// v.visit_expr(&*node.left);
/// v.visit_bin_op(&node.op);
/// v.visit_expr(&*node.right);
/// }
///
/// /* ... */
/// ```
///
/// *This module is available only if Syn is built with the `"visit"` feature.*
///
/// <br>
///
/// # Example
///
/// This visitor will print the name of every freestanding function in the
/// syntax tree, including nested functions.
///
/// ```
/// // [dependencies]
/// // quote = "1.0"
/// // syn = { version = "1.0", features = ["full", "visit"] }
///
/// use quote::quote;
/// use syn::visit::{self, Visit};
/// use syn::{File, ItemFn};
///
/// struct FnVisitor;
///
/// impl<'ast> Visit<'ast> for FnVisitor {
/// fn visit_item_fn(&mut self, node: &'ast ItemFn) {
/// println!("Function with name={}", node.sig.ident);
///
/// // Delegate to the default impl to visit any nested functions.
/// visit::visit_item_fn(self, node);
/// }
/// }
///
/// fn main() {
/// let code = quote! {
/// pub fn f() {
/// fn g() {}
/// }
/// };
///
/// let syntax_tree: File = syn::parse2(code).unwrap();
/// FnVisitor.visit_file(&syntax_tree);
/// }
/// ```
///
/// The `'ast` lifetime on the input references means that the syntax tree
/// outlives the complete recursive visit call, so the visitor is allowed to
/// hold on to references into the syntax tree.
///
/// ```
/// use quote::quote;
/// use syn::visit::{self, Visit};
/// use syn::{File, ItemFn};
///
/// struct FnVisitor<'ast> {
/// functions: Vec<&'ast ItemFn>,
/// }
///
/// impl<'ast> Visit<'ast> for FnVisitor<'ast> {
/// fn visit_item_fn(&mut self, node: &'ast ItemFn) {
/// self.functions.push(node);
/// visit::visit_item_fn(self, node);
/// }
/// }
///
/// fn main() {
/// let code = quote! {
/// pub fn f() {
/// fn g() {}
/// }
/// };
///
/// let syntax_tree: File = syn::parse2(code).unwrap();
/// let mut visitor = FnVisitor { functions: Vec::new() };
/// visitor.visit_file(&syntax_tree);
/// for f in visitor.functions {
/// println!("Function with name={}", f.sig.ident);
/// }
/// }
/// ```
#[cfg(feature = "visit")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "visit")))]
#[rustfmt::skip]
pub mod visit;
/// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in
/// place.
///
/// Each method of the [`VisitMut`] trait is a hook that can be overridden
/// to customize the behavior when mutating the corresponding type of node.
/// By default, every method recursively visits the substructure of the
/// input by invoking the right visitor method of each of its fields.
///
/// [`VisitMut`]: visit_mut::VisitMut
///
/// ```
/// # use syn::{Attribute, BinOp, Expr, ExprBinary};
/// #
/// pub trait VisitMut {
/// /* ... */
///
/// fn visit_expr_binary_mut(&mut self, node: &mut ExprBinary) {
/// visit_expr_binary_mut(self, node);
/// }
///
/// /* ... */
/// # fn visit_attribute_mut(&mut self, node: &mut Attribute);
/// # fn visit_expr_mut(&mut self, node: &mut Expr);
/// # fn visit_bin_op_mut(&mut self, node: &mut BinOp);
/// }
///
/// pub fn visit_expr_binary_mut<V>(v: &mut V, node: &mut ExprBinary)
/// where
/// V: VisitMut + ?Sized,
/// {
/// for attr in &mut node.attrs {
/// v.visit_attribute_mut(attr);
/// }
/// v.visit_expr_mut(&mut *node.left);
/// v.visit_bin_op_mut(&mut node.op);
/// v.visit_expr_mut(&mut *node.right);
/// }
///
/// /* ... */
/// ```
///
/// *This module is available only if Syn is built with the `"visit-mut"`
/// feature.*
///
/// <br>
///
/// # Example
///
/// This mut visitor replace occurrences of u256 suffixed integer literals
/// like `999u256` with a macro invocation `bigint::u256!(999)`.
///
/// ```
/// // [dependencies]
/// // quote = "1.0"
/// // syn = { version = "1.0", features = ["full", "visit-mut"] }
///
/// use quote::quote;
/// use syn::visit_mut::{self, VisitMut};
/// use syn::{parse_quote, Expr, File, Lit, LitInt};
///
/// struct BigintReplace;
///
/// impl VisitMut for BigintReplace {
/// fn visit_expr_mut(&mut self, node: &mut Expr) {
/// if let Expr::Lit(expr) = &node {
/// if let Lit::Int(int) = &expr.lit {
/// if int.suffix() == "u256" {
/// let digits = int.base10_digits();
/// let unsuffixed: LitInt = syn::parse_str(digits).unwrap();
/// *node = parse_quote!(bigint::u256!(#unsuffixed));
/// return;
/// }
/// }
/// }
///
/// // Delegate to the default impl to visit nested expressions.
/// visit_mut::visit_expr_mut(self, node);
/// }
/// }
///
/// fn main() {
/// let code = quote! {
/// fn main() {
/// let _ = 999u256;
/// }
/// };
///
/// let mut syntax_tree: File = syn::parse2(code).unwrap();
/// BigintReplace.visit_file_mut(&mut syntax_tree);
/// println!("{}", quote!(#syntax_tree));
/// }
/// ```
#[cfg(feature = "visit-mut")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "visit-mut")))]
#[rustfmt::skip]
pub mod visit_mut;
/// Syntax tree traversal to transform the nodes of an owned syntax tree.
///
/// Each method of the [`Fold`] trait is a hook that can be overridden to
/// customize the behavior when transforming the corresponding type of node.
/// By default, every method recursively visits the substructure of the
/// input by invoking the right visitor method of each of its fields.
///
/// [`Fold`]: fold::Fold
///
/// ```
/// # use syn::{Attribute, BinOp, Expr, ExprBinary};
/// #
/// pub trait Fold {
/// /* ... */
///
/// fn fold_expr_binary(&mut self, node: ExprBinary) -> ExprBinary {
/// fold_expr_binary(self, node)
/// }
///
/// /* ... */
/// # fn fold_attribute(&mut self, node: Attribute) -> Attribute;
/// # fn fold_expr(&mut self, node: Expr) -> Expr;
/// # fn fold_bin_op(&mut self, node: BinOp) -> BinOp;
/// }
///
/// pub fn fold_expr_binary<V>(v: &mut V, node: ExprBinary) -> ExprBinary
/// where
/// V: Fold + ?Sized,
/// {
/// ExprBinary {
/// attrs: node
/// .attrs
/// .into_iter()
/// .map(|attr| v.fold_attribute(attr))
/// .collect(),
/// left: Box::new(v.fold_expr(*node.left)),
/// op: v.fold_bin_op(node.op),
/// right: Box::new(v.fold_expr(*node.right)),
/// }
/// }
///
/// /* ... */
/// ```
///
/// *This module is available only if Syn is built with the `"fold"` feature.*
///
/// <br>
///
/// # Example
///
/// This fold inserts parentheses to fully parenthesizes any expression.
///
/// ```
/// // [dependencies]
/// // quote = "1.0"
/// // syn = { version = "1.0", features = ["fold", "full"] }
///
/// use quote::quote;
/// use syn::fold::{fold_expr, Fold};
/// use syn::{token, Expr, ExprParen};
///
/// struct ParenthesizeEveryExpr;
///
/// impl Fold for ParenthesizeEveryExpr {
/// fn fold_expr(&mut self, expr: Expr) -> Expr {
/// Expr::Paren(ExprParen {
/// attrs: Vec::new(),
/// expr: Box::new(fold_expr(self, expr)),
/// paren_token: token::Paren::default(),
/// })
/// }
/// }
///
/// fn main() {
/// let code = quote! { a() + b(1) * c.d };
/// let expr: Expr = syn::parse2(code).unwrap();
/// let parenthesized = ParenthesizeEveryExpr.fold_expr(expr);
/// println!("{}", quote!(#parenthesized));
///
/// // Output: (((a)()) + (((b)((1))) * ((c).d)))
/// }
/// ```
#[cfg(feature = "fold")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "fold")))]
#[rustfmt::skip]
pub mod fold;
#[cfg(feature = "clone-impls")]
#[rustfmt::skip]
mod clone;
#[cfg(feature = "extra-traits")]
#[rustfmt::skip]
mod eq;
#[cfg(feature = "extra-traits")]
#[rustfmt::skip]
mod hash;
#[cfg(feature = "extra-traits")]
#[rustfmt::skip]
mod debug;
#[cfg(any(feature = "full", feature = "derive"))]
#[path = "../gen_helper.rs"]
mod helper;
}
pub use crate::gen::*;
// Not public API.
#[doc(hidden)]
#[path = "export.rs"]
pub mod __private;
mod custom_keyword;
mod custom_punctuation;
mod sealed;
mod span;
mod thread;
#[cfg(feature = "parsing")]
mod lookahead;
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub mod parse;
#[cfg(feature = "full")]
mod reserved;
#[cfg(all(any(feature = "full", feature = "derive"), feature = "parsing"))]
mod verbatim;
#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
mod print;
////////////////////////////////////////////////////////////////////////////////
mod error;
pub use crate::error::{Error, Result};
/// Parse tokens of source code into the chosen syntax tree node.
///
/// This is preferred over parsing a string because tokens are able to preserve
/// information about where in the user's code they were originally written (the
/// "span" of the token), possibly allowing the compiler to produce better error
/// messages.
///
/// This function parses a `proc_macro::TokenStream` which is the type used for
/// interop with the compiler in a procedural macro. To parse a
/// `proc_macro2::TokenStream`, use [`syn::parse2`] instead.
///
/// [`syn::parse2`]: parse2
///
/// *This function is available only if Syn is built with both the `"parsing"` and
/// `"proc-macro"` features.*
///
/// # Examples
///
/// ```
/// # extern crate proc_macro;
/// #
/// use proc_macro::TokenStream;
/// use quote::quote;
/// use syn::DeriveInput;
///
/// # const IGNORE_TOKENS: &str = stringify! {
/// #[proc_macro_derive(MyMacro)]
/// # };
/// pub fn my_macro(input: TokenStream) -> TokenStream {
/// // Parse the tokens into a syntax tree
/// let ast: DeriveInput = syn::parse(input).unwrap();
///
/// // Build the output, possibly using quasi-quotation
/// let expanded = quote! {
/// /* ... */
/// };
///
/// // Convert into a token stream and return it
/// expanded.into()
/// }
/// ```
#[cfg(all(
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
feature = "parsing",
feature = "proc-macro"
))]
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))]
pub fn parse<T: parse::Parse>(tokens: proc_macro::TokenStream) -> Result<T> {
parse::Parser::parse(T::parse, tokens)
}
/// Parse a proc-macro2 token stream into the chosen syntax tree node.
///
/// This function will check that the input is fully parsed. If there are
/// any unparsed tokens at the end of the stream, an error is returned.
///
/// This function parses a `proc_macro2::TokenStream` which is commonly useful
/// when the input comes from a node of the Syn syntax tree, for example the
/// body tokens of a [`Macro`] node. When in a procedural macro parsing the
/// `proc_macro::TokenStream` provided by the compiler, use [`syn::parse`]
/// instead.
///
/// [`syn::parse`]: parse()
///
/// *This function is available only if Syn is built with the `"parsing"` feature.*
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn parse2<T: parse::Parse>(tokens: proc_macro2::TokenStream) -> Result<T> {
parse::Parser::parse2(T::parse, tokens)
}
/// Parse a string of Rust code into the chosen syntax tree node.
///
/// *This function is available only if Syn is built with the `"parsing"` feature.*
///
/// # Hygiene
///
/// Every span in the resulting syntax tree will be set to resolve at the macro
/// call site.
///
/// # Examples
///
/// ```
/// use syn::{Expr, Result};
///
/// fn run() -> Result<()> {
/// let code = "assert_eq!(u8::max_value(), 255)";
/// let expr = syn::parse_str::<Expr>(code)?;
/// println!("{:#?}", expr);
/// Ok(())
/// }
/// #
/// # run().unwrap();
/// ```
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn parse_str<T: parse::Parse>(s: &str) -> Result<T> {
parse::Parser::parse_str(T::parse, s)
}
// FIXME the name parse_file makes it sound like you might pass in a path to a
// file, rather than the content.
/// Parse the content of a file of Rust code.
///
/// This is different from `syn::parse_str::<File>(content)` in two ways:
///
/// - It discards a leading byte order mark `\u{FEFF}` if the file has one.
/// - It preserves the shebang line of the file, such as `#!/usr/bin/env rustx`.
///
/// If present, either of these would be an error using `from_str`.
///
/// *This function is available only if Syn is built with the `"parsing"` and
/// `"full"` features.*
///
/// # Examples
///
/// ```no_run
/// use std::error::Error;
/// use std::fs::File;
/// use std::io::Read;
///
/// fn run() -> Result<(), Box<Error>> {
/// let mut file = File::open("path/to/code.rs")?;
/// let mut content = String::new();
/// file.read_to_string(&mut content)?;
///
/// let ast = syn::parse_file(&content)?;
/// if let Some(shebang) = ast.shebang {
/// println!("{}", shebang);
/// }
/// println!("{} items", ast.items.len());
///
/// Ok(())
/// }
/// #
/// # run().unwrap();
/// ```
#[cfg(all(feature = "parsing", feature = "full"))]
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "full"))))]
pub fn parse_file(mut content: &str) -> Result<File> {
// Strip the BOM if it is present
const BOM: &str = "\u{feff}";
if content.starts_with(BOM) {
content = &content[BOM.len()..];
}
let mut shebang = None;
if content.starts_with("#!") {
let rest = whitespace::skip(&content[2..]);
if !rest.starts_with('[') {
if let Some(idx) = content.find('\n') {
shebang = Some(content[..idx].to_string());
content = &content[idx..];
} else {
shebang = Some(content.to_string());
content = "";
}
}
}
let mut file: File = parse_str(content)?;
file.shebang = shebang;
Ok(file)
}

154
third_party/rust/syn-1.0.107/src/lifetime.rs поставляемый
Просмотреть файл

@ -1,154 +0,0 @@
use proc_macro2::{Ident, Span};
use std::cmp::Ordering;
use std::fmt::{self, Display};
use std::hash::{Hash, Hasher};
#[cfg(feature = "parsing")]
use crate::lookahead;
/// A Rust lifetime: `'a`.
///
/// Lifetime names must conform to the following rules:
///
/// - Must start with an apostrophe.
/// - Must not consist of just an apostrophe: `'`.
/// - Character after the apostrophe must be `_` or a Unicode code point with
/// the XID_Start property.
/// - All following characters must be Unicode code points with the XID_Continue
/// property.
pub struct Lifetime {
pub apostrophe: Span,
pub ident: Ident,
}
impl Lifetime {
/// # Panics
///
/// Panics if the lifetime does not conform to the bulleted rules above.
///
/// # Invocation
///
/// ```
/// # use proc_macro2::Span;
/// # use syn::Lifetime;
/// #
/// # fn f() -> Lifetime {
/// Lifetime::new("'a", Span::call_site())
/// # }
/// ```
pub fn new(symbol: &str, span: Span) -> Self {
if !symbol.starts_with('\'') {
panic!(
"lifetime name must start with apostrophe as in \"'a\", got {:?}",
symbol
);
}
if symbol == "'" {
panic!("lifetime name must not be empty");
}
if !crate::ident::xid_ok(&symbol[1..]) {
panic!("{:?} is not a valid lifetime name", symbol);
}
Lifetime {
apostrophe: span,
ident: Ident::new(&symbol[1..], span),
}
}
pub fn span(&self) -> Span {
self.apostrophe
.join(self.ident.span())
.unwrap_or(self.apostrophe)
}
pub fn set_span(&mut self, span: Span) {
self.apostrophe = span;
self.ident.set_span(span);
}
}
impl Display for Lifetime {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
"'".fmt(formatter)?;
self.ident.fmt(formatter)
}
}
impl Clone for Lifetime {
fn clone(&self) -> Self {
Lifetime {
apostrophe: self.apostrophe,
ident: self.ident.clone(),
}
}
}
impl PartialEq for Lifetime {
fn eq(&self, other: &Lifetime) -> bool {
self.ident.eq(&other.ident)
}
}
impl Eq for Lifetime {}
impl PartialOrd for Lifetime {
fn partial_cmp(&self, other: &Lifetime) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Lifetime {
fn cmp(&self, other: &Lifetime) -> Ordering {
self.ident.cmp(&other.ident)
}
}
impl Hash for Lifetime {
fn hash<H: Hasher>(&self, h: &mut H) {
self.ident.hash(h);
}
}
#[cfg(feature = "parsing")]
#[doc(hidden)]
#[allow(non_snake_case)]
pub fn Lifetime(marker: lookahead::TokenMarker) -> Lifetime {
match marker {}
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use crate::parse::{Parse, ParseStream, Result};
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Lifetime {
fn parse(input: ParseStream) -> Result<Self> {
input.step(|cursor| {
cursor
.lifetime()
.ok_or_else(|| cursor.error("expected lifetime"))
})
}
}
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use proc_macro2::{Punct, Spacing, TokenStream};
use quote::{ToTokens, TokenStreamExt};
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for Lifetime {
fn to_tokens(&self, tokens: &mut TokenStream) {
let mut apostrophe = Punct::new('\'', Spacing::Joint);
apostrophe.set_span(self.apostrophe);
tokens.append(apostrophe);
self.ident.to_tokens(tokens);
}
}
}

1600
third_party/rust/syn-1.0.107/src/lit.rs поставляемый

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

169
third_party/rust/syn-1.0.107/src/lookahead.rs поставляемый
Просмотреть файл

@ -1,169 +0,0 @@
use crate::buffer::Cursor;
use crate::error::{self, Error};
use crate::sealed::lookahead::Sealed;
use crate::span::IntoSpans;
use crate::token::Token;
use proc_macro2::{Delimiter, Span};
use std::cell::RefCell;
/// Support for checking the next token in a stream to decide how to parse.
///
/// An important advantage over [`ParseStream::peek`] is that here we
/// automatically construct an appropriate error message based on the token
/// alternatives that get peeked. If you are producing your own error message,
/// go ahead and use `ParseStream::peek` instead.
///
/// Use [`ParseStream::lookahead1`] to construct this object.
///
/// [`ParseStream::peek`]: crate::parse::ParseBuffer::peek
/// [`ParseStream::lookahead1`]: crate::parse::ParseBuffer::lookahead1
///
/// Consuming tokens from the source stream after constructing a lookahead
/// object does not also advance the lookahead object.
///
/// # Example
///
/// ```
/// use syn::{ConstParam, Ident, Lifetime, LifetimeDef, Result, Token, TypeParam};
/// use syn::parse::{Parse, ParseStream};
///
/// // A generic parameter, a single one of the comma-separated elements inside
/// // angle brackets in:
/// //
/// // fn f<T: Clone, 'a, 'b: 'a, const N: usize>() { ... }
/// //
/// // On invalid input, lookahead gives us a reasonable error message.
/// //
/// // error: expected one of: identifier, lifetime, `const`
/// // |
/// // 5 | fn f<!Sized>() {}
/// // | ^
/// enum GenericParam {
/// Type(TypeParam),
/// Lifetime(LifetimeDef),
/// Const(ConstParam),
/// }
///
/// impl Parse for GenericParam {
/// fn parse(input: ParseStream) -> Result<Self> {
/// let lookahead = input.lookahead1();
/// if lookahead.peek(Ident) {
/// input.parse().map(GenericParam::Type)
/// } else if lookahead.peek(Lifetime) {
/// input.parse().map(GenericParam::Lifetime)
/// } else if lookahead.peek(Token![const]) {
/// input.parse().map(GenericParam::Const)
/// } else {
/// Err(lookahead.error())
/// }
/// }
/// }
/// ```
pub struct Lookahead1<'a> {
scope: Span,
cursor: Cursor<'a>,
comparisons: RefCell<Vec<&'static str>>,
}
pub fn new(scope: Span, cursor: Cursor) -> Lookahead1 {
Lookahead1 {
scope,
cursor,
comparisons: RefCell::new(Vec::new()),
}
}
fn peek_impl(
lookahead: &Lookahead1,
peek: fn(Cursor) -> bool,
display: fn() -> &'static str,
) -> bool {
if peek(lookahead.cursor) {
return true;
}
lookahead.comparisons.borrow_mut().push(display());
false
}
impl<'a> Lookahead1<'a> {
/// Looks at the next token in the parse stream to determine whether it
/// matches the requested type of token.
///
/// # Syntax
///
/// Note that this method does not use turbofish syntax. Pass the peek type
/// inside of parentheses.
///
/// - `input.peek(Token![struct])`
/// - `input.peek(Token![==])`
/// - `input.peek(Ident)`&emsp;*(does not accept keywords)*
/// - `input.peek(Ident::peek_any)`
/// - `input.peek(Lifetime)`
/// - `input.peek(token::Brace)`
pub fn peek<T: Peek>(&self, token: T) -> bool {
let _ = token;
peek_impl(self, T::Token::peek, T::Token::display)
}
/// Triggers an error at the current position of the parse stream.
///
/// The error message will identify all of the expected token types that
/// have been peeked against this lookahead instance.
pub fn error(self) -> Error {
let comparisons = self.comparisons.borrow();
match comparisons.len() {
0 => {
if self.cursor.eof() {
Error::new(self.scope, "unexpected end of input")
} else {
Error::new(self.cursor.span(), "unexpected token")
}
}
1 => {
let message = format!("expected {}", comparisons[0]);
error::new_at(self.scope, self.cursor, message)
}
2 => {
let message = format!("expected {} or {}", comparisons[0], comparisons[1]);
error::new_at(self.scope, self.cursor, message)
}
_ => {
let join = comparisons.join(", ");
let message = format!("expected one of: {}", join);
error::new_at(self.scope, self.cursor, message)
}
}
}
}
/// Types that can be parsed by looking at just one token.
///
/// Use [`ParseStream::peek`] to peek one of these types in a parse stream
/// without consuming it from the stream.
///
/// This trait is sealed and cannot be implemented for types outside of Syn.
///
/// [`ParseStream::peek`]: crate::parse::ParseBuffer::peek
pub trait Peek: Sealed {
// Not public API.
#[doc(hidden)]
type Token: Token;
}
impl<F: Copy + FnOnce(TokenMarker) -> T, T: Token> Peek for F {
type Token = T;
}
pub enum TokenMarker {}
impl<S> IntoSpans<S> for TokenMarker {
fn into_spans(self) -> S {
match self {}
}
}
pub fn is_delimiter(cursor: Cursor, delimiter: Delimiter) -> bool {
cursor.group(delimiter).is_some()
}
impl<F: Copy + FnOnce(TokenMarker) -> T, T: Token> Sealed for F {}

219
third_party/rust/syn-1.0.107/src/mac.rs поставляемый
Просмотреть файл

@ -1,219 +0,0 @@
use super::*;
use crate::token::{Brace, Bracket, Paren};
use proc_macro2::TokenStream;
#[cfg(feature = "parsing")]
use proc_macro2::{Delimiter, Group, Span, TokenTree};
#[cfg(feature = "parsing")]
use crate::parse::{Parse, ParseStream, Parser, Result};
ast_struct! {
/// A macro invocation: `println!("{}", mac)`.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct Macro {
pub path: Path,
pub bang_token: Token![!],
pub delimiter: MacroDelimiter,
pub tokens: TokenStream,
}
}
ast_enum! {
/// A grouping token that surrounds a macro body: `m!(...)` or `m!{...}` or `m![...]`.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub enum MacroDelimiter {
Paren(Paren),
Brace(Brace),
Bracket(Bracket),
}
}
#[cfg(feature = "parsing")]
fn delimiter_span_close(macro_delimiter: &MacroDelimiter) -> Span {
let delimiter = match macro_delimiter {
MacroDelimiter::Paren(_) => Delimiter::Parenthesis,
MacroDelimiter::Brace(_) => Delimiter::Brace,
MacroDelimiter::Bracket(_) => Delimiter::Bracket,
};
let mut group = Group::new(delimiter, TokenStream::new());
group.set_span(match macro_delimiter {
MacroDelimiter::Paren(token) => token.span,
MacroDelimiter::Brace(token) => token.span,
MacroDelimiter::Bracket(token) => token.span,
});
group.span_close()
}
impl Macro {
/// Parse the tokens within the macro invocation's delimiters into a syntax
/// tree.
///
/// This is equivalent to `syn::parse2::<T>(mac.tokens)` except that it
/// produces a more useful span when `tokens` is empty.
///
/// # Example
///
/// ```
/// use syn::{parse_quote, Expr, ExprLit, Ident, Lit, LitStr, Macro, Token};
/// use syn::ext::IdentExt;
/// use syn::parse::{Error, Parse, ParseStream, Result};
/// use syn::punctuated::Punctuated;
///
/// // The arguments expected by libcore's format_args macro, and as a
/// // result most other formatting and printing macros like println.
/// //
/// // println!("{} is {number:.prec$}", "x", prec=5, number=0.01)
/// struct FormatArgs {
/// format_string: Expr,
/// positional_args: Vec<Expr>,
/// named_args: Vec<(Ident, Expr)>,
/// }
///
/// impl Parse for FormatArgs {
/// fn parse(input: ParseStream) -> Result<Self> {
/// let format_string: Expr;
/// let mut positional_args = Vec::new();
/// let mut named_args = Vec::new();
///
/// format_string = input.parse()?;
/// while !input.is_empty() {
/// input.parse::<Token![,]>()?;
/// if input.is_empty() {
/// break;
/// }
/// if input.peek(Ident::peek_any) && input.peek2(Token![=]) {
/// while !input.is_empty() {
/// let name: Ident = input.call(Ident::parse_any)?;
/// input.parse::<Token![=]>()?;
/// let value: Expr = input.parse()?;
/// named_args.push((name, value));
/// if input.is_empty() {
/// break;
/// }
/// input.parse::<Token![,]>()?;
/// }
/// break;
/// }
/// positional_args.push(input.parse()?);
/// }
///
/// Ok(FormatArgs {
/// format_string,
/// positional_args,
/// named_args,
/// })
/// }
/// }
///
/// // Extract the first argument, the format string literal, from an
/// // invocation of a formatting or printing macro.
/// fn get_format_string(m: &Macro) -> Result<LitStr> {
/// let args: FormatArgs = m.parse_body()?;
/// match args.format_string {
/// Expr::Lit(ExprLit { lit: Lit::Str(lit), .. }) => Ok(lit),
/// other => {
/// // First argument was not a string literal expression.
/// // Maybe something like: println!(concat!(...), ...)
/// Err(Error::new_spanned(other, "format string must be a string literal"))
/// }
/// }
/// }
///
/// fn main() {
/// let invocation = parse_quote! {
/// println!("{:?}", Instant::now())
/// };
/// let lit = get_format_string(&invocation).unwrap();
/// assert_eq!(lit.value(), "{:?}");
/// }
/// ```
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn parse_body<T: Parse>(&self) -> Result<T> {
self.parse_body_with(T::parse)
}
/// Parse the tokens within the macro invocation's delimiters using the
/// given parser.
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn parse_body_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
let scope = delimiter_span_close(&self.delimiter);
crate::parse::parse_scoped(parser, scope, self.tokens.clone())
}
}
#[cfg(feature = "parsing")]
pub fn parse_delimiter(input: ParseStream) -> Result<(MacroDelimiter, TokenStream)> {
input.step(|cursor| {
if let Some((TokenTree::Group(g), rest)) = cursor.token_tree() {
let span = g.span();
let delimiter = match g.delimiter() {
Delimiter::Parenthesis => MacroDelimiter::Paren(Paren(span)),
Delimiter::Brace => MacroDelimiter::Brace(Brace(span)),
Delimiter::Bracket => MacroDelimiter::Bracket(Bracket(span)),
Delimiter::None => {
return Err(cursor.error("expected delimiter"));
}
};
Ok(((delimiter, g.stream()), rest))
} else {
Err(cursor.error("expected delimiter"))
}
})
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use crate::parse::{Parse, ParseStream, Result};
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Macro {
fn parse(input: ParseStream) -> Result<Self> {
let tokens;
Ok(Macro {
path: input.call(Path::parse_mod_style)?,
bang_token: input.parse()?,
delimiter: {
let (delimiter, content) = parse_delimiter(input)?;
tokens = content;
delimiter
},
tokens,
})
}
}
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use proc_macro2::TokenStream;
use quote::ToTokens;
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for Macro {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.path.to_tokens(tokens);
self.bang_token.to_tokens(tokens);
match &self.delimiter {
MacroDelimiter::Paren(paren) => {
paren.surround(tokens, |tokens| self.tokens.to_tokens(tokens));
}
MacroDelimiter::Brace(brace) => {
brace.surround(tokens, |tokens| self.tokens.to_tokens(tokens));
}
MacroDelimiter::Bracket(bracket) => {
bracket.surround(tokens, |tokens| self.tokens.to_tokens(tokens));
}
}
}
}
}

177
third_party/rust/syn-1.0.107/src/macros.rs поставляемый
Просмотреть файл

@ -1,177 +0,0 @@
#[cfg_attr(
not(any(feature = "full", feature = "derive")),
allow(unknown_lints, unused_macro_rules)
)]
macro_rules! ast_struct {
(
[$($attrs_pub:tt)*]
struct $name:ident #full $($rest:tt)*
) => {
#[cfg(feature = "full")]
$($attrs_pub)* struct $name $($rest)*
#[cfg(not(feature = "full"))]
$($attrs_pub)* struct $name {
_noconstruct: ::std::marker::PhantomData<::proc_macro2::Span>,
}
#[cfg(all(not(feature = "full"), feature = "printing"))]
impl ::quote::ToTokens for $name {
fn to_tokens(&self, _: &mut ::proc_macro2::TokenStream) {
unreachable!()
}
}
};
(
[$($attrs_pub:tt)*]
struct $name:ident $($rest:tt)*
) => {
$($attrs_pub)* struct $name $($rest)*
};
($($t:tt)*) => {
strip_attrs_pub!(ast_struct!($($t)*));
};
}
macro_rules! ast_enum {
// Drop the `#no_visit` attribute, if present.
(
[$($attrs_pub:tt)*]
enum $name:ident #no_visit $($rest:tt)*
) => (
ast_enum!([$($attrs_pub)*] enum $name $($rest)*);
);
(
[$($attrs_pub:tt)*]
enum $name:ident $($rest:tt)*
) => (
$($attrs_pub)* enum $name $($rest)*
);
($($t:tt)*) => {
strip_attrs_pub!(ast_enum!($($t)*));
};
}
macro_rules! ast_enum_of_structs {
(
$(#[$enum_attr:meta])*
$pub:ident $enum:ident $name:ident $body:tt
$($remaining:tt)*
) => {
ast_enum!($(#[$enum_attr])* $pub $enum $name $body);
ast_enum_of_structs_impl!($pub $enum $name $body $($remaining)*);
};
}
macro_rules! ast_enum_of_structs_impl {
(
$pub:ident $enum:ident $name:ident {
$(
$(#[cfg $cfg_attr:tt])*
$(#[doc $($doc_attr:tt)*])*
$variant:ident $( ($($member:ident)::+) )*,
)*
}
$($remaining:tt)*
) => {
check_keyword_matches!(pub $pub);
check_keyword_matches!(enum $enum);
$($(
ast_enum_from_struct!($name::$variant, $($member)::+);
)*)*
#[cfg(feature = "printing")]
generate_to_tokens! {
$($remaining)*
()
tokens
$name {
$(
$(#[cfg $cfg_attr])*
$(#[doc $($doc_attr)*])*
$variant $($($member)::+)*,
)*
}
}
};
}
macro_rules! ast_enum_from_struct {
// No From<TokenStream> for verbatim variants.
($name:ident::Verbatim, $member:ident) => {};
($name:ident::$variant:ident, $member:ident) => {
impl From<$member> for $name {
fn from(e: $member) -> $name {
$name::$variant(e)
}
}
};
}
#[cfg(feature = "printing")]
#[cfg_attr(
not(any(feature = "full", feature = "derive")),
allow(unknown_lints, unused_macro_rules)
)]
macro_rules! generate_to_tokens {
(do_not_generate_to_tokens $($foo:tt)*) => ();
(
($($arms:tt)*) $tokens:ident $name:ident {
$(#[cfg $cfg_attr:tt])*
$(#[doc $($doc_attr:tt)*])*
$variant:ident,
$($next:tt)*
}
) => {
generate_to_tokens!(
($($arms)* $(#[cfg $cfg_attr])* $name::$variant => {})
$tokens $name { $($next)* }
);
};
(
($($arms:tt)*) $tokens:ident $name:ident {
$(#[cfg $cfg_attr:tt])*
$(#[doc $($doc_attr:tt)*])*
$variant:ident $member:ident,
$($next:tt)*
}
) => {
generate_to_tokens!(
($($arms)* $(#[cfg $cfg_attr])* $name::$variant(_e) => _e.to_tokens($tokens),)
$tokens $name { $($next)* }
);
};
(($($arms:tt)*) $tokens:ident $name:ident {}) => {
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ::quote::ToTokens for $name {
fn to_tokens(&self, $tokens: &mut ::proc_macro2::TokenStream) {
match self {
$($arms)*
}
}
}
};
}
macro_rules! strip_attrs_pub {
($mac:ident!($(#[$m:meta])* $pub:ident $($t:tt)*)) => {
check_keyword_matches!(pub $pub);
$mac!([$(#[$m])* $pub] $($t)*);
};
}
macro_rules! check_keyword_matches {
(enum enum) => {};
(pub pub) => {};
}

234
third_party/rust/syn-1.0.107/src/op.rs поставляемый
Просмотреть файл

@ -1,234 +0,0 @@
ast_enum! {
/// A binary operator: `+`, `+=`, `&`.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub enum BinOp {
/// The `+` operator (addition)
Add(Token![+]),
/// The `-` operator (subtraction)
Sub(Token![-]),
/// The `*` operator (multiplication)
Mul(Token![*]),
/// The `/` operator (division)
Div(Token![/]),
/// The `%` operator (modulus)
Rem(Token![%]),
/// The `&&` operator (logical and)
And(Token![&&]),
/// The `||` operator (logical or)
Or(Token![||]),
/// The `^` operator (bitwise xor)
BitXor(Token![^]),
/// The `&` operator (bitwise and)
BitAnd(Token![&]),
/// The `|` operator (bitwise or)
BitOr(Token![|]),
/// The `<<` operator (shift left)
Shl(Token![<<]),
/// The `>>` operator (shift right)
Shr(Token![>>]),
/// The `==` operator (equality)
Eq(Token![==]),
/// The `<` operator (less than)
Lt(Token![<]),
/// The `<=` operator (less than or equal to)
Le(Token![<=]),
/// The `!=` operator (not equal to)
Ne(Token![!=]),
/// The `>=` operator (greater than or equal to)
Ge(Token![>=]),
/// The `>` operator (greater than)
Gt(Token![>]),
/// The `+=` operator
AddEq(Token![+=]),
/// The `-=` operator
SubEq(Token![-=]),
/// The `*=` operator
MulEq(Token![*=]),
/// The `/=` operator
DivEq(Token![/=]),
/// The `%=` operator
RemEq(Token![%=]),
/// The `^=` operator
BitXorEq(Token![^=]),
/// The `&=` operator
BitAndEq(Token![&=]),
/// The `|=` operator
BitOrEq(Token![|=]),
/// The `<<=` operator
ShlEq(Token![<<=]),
/// The `>>=` operator
ShrEq(Token![>>=]),
}
}
ast_enum! {
/// A unary operator: `*`, `!`, `-`.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub enum UnOp {
/// The `*` operator for dereferencing
Deref(Token![*]),
/// The `!` operator for logical inversion
Not(Token![!]),
/// The `-` operator for negation
Neg(Token![-]),
}
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use crate::parse::{Parse, ParseStream, Result};
fn parse_binop(input: ParseStream) -> Result<BinOp> {
if input.peek(Token![&&]) {
input.parse().map(BinOp::And)
} else if input.peek(Token![||]) {
input.parse().map(BinOp::Or)
} else if input.peek(Token![<<]) {
input.parse().map(BinOp::Shl)
} else if input.peek(Token![>>]) {
input.parse().map(BinOp::Shr)
} else if input.peek(Token![==]) {
input.parse().map(BinOp::Eq)
} else if input.peek(Token![<=]) {
input.parse().map(BinOp::Le)
} else if input.peek(Token![!=]) {
input.parse().map(BinOp::Ne)
} else if input.peek(Token![>=]) {
input.parse().map(BinOp::Ge)
} else if input.peek(Token![+]) {
input.parse().map(BinOp::Add)
} else if input.peek(Token![-]) {
input.parse().map(BinOp::Sub)
} else if input.peek(Token![*]) {
input.parse().map(BinOp::Mul)
} else if input.peek(Token![/]) {
input.parse().map(BinOp::Div)
} else if input.peek(Token![%]) {
input.parse().map(BinOp::Rem)
} else if input.peek(Token![^]) {
input.parse().map(BinOp::BitXor)
} else if input.peek(Token![&]) {
input.parse().map(BinOp::BitAnd)
} else if input.peek(Token![|]) {
input.parse().map(BinOp::BitOr)
} else if input.peek(Token![<]) {
input.parse().map(BinOp::Lt)
} else if input.peek(Token![>]) {
input.parse().map(BinOp::Gt)
} else {
Err(input.error("expected binary operator"))
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for BinOp {
#[cfg(not(feature = "full"))]
fn parse(input: ParseStream) -> Result<Self> {
parse_binop(input)
}
#[cfg(feature = "full")]
fn parse(input: ParseStream) -> Result<Self> {
if input.peek(Token![+=]) {
input.parse().map(BinOp::AddEq)
} else if input.peek(Token![-=]) {
input.parse().map(BinOp::SubEq)
} else if input.peek(Token![*=]) {
input.parse().map(BinOp::MulEq)
} else if input.peek(Token![/=]) {
input.parse().map(BinOp::DivEq)
} else if input.peek(Token![%=]) {
input.parse().map(BinOp::RemEq)
} else if input.peek(Token![^=]) {
input.parse().map(BinOp::BitXorEq)
} else if input.peek(Token![&=]) {
input.parse().map(BinOp::BitAndEq)
} else if input.peek(Token![|=]) {
input.parse().map(BinOp::BitOrEq)
} else if input.peek(Token![<<=]) {
input.parse().map(BinOp::ShlEq)
} else if input.peek(Token![>>=]) {
input.parse().map(BinOp::ShrEq)
} else {
parse_binop(input)
}
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for UnOp {
fn parse(input: ParseStream) -> Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(Token![*]) {
input.parse().map(UnOp::Deref)
} else if lookahead.peek(Token![!]) {
input.parse().map(UnOp::Not)
} else if lookahead.peek(Token![-]) {
input.parse().map(UnOp::Neg)
} else {
Err(lookahead.error())
}
}
}
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use proc_macro2::TokenStream;
use quote::ToTokens;
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for BinOp {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
BinOp::Add(t) => t.to_tokens(tokens),
BinOp::Sub(t) => t.to_tokens(tokens),
BinOp::Mul(t) => t.to_tokens(tokens),
BinOp::Div(t) => t.to_tokens(tokens),
BinOp::Rem(t) => t.to_tokens(tokens),
BinOp::And(t) => t.to_tokens(tokens),
BinOp::Or(t) => t.to_tokens(tokens),
BinOp::BitXor(t) => t.to_tokens(tokens),
BinOp::BitAnd(t) => t.to_tokens(tokens),
BinOp::BitOr(t) => t.to_tokens(tokens),
BinOp::Shl(t) => t.to_tokens(tokens),
BinOp::Shr(t) => t.to_tokens(tokens),
BinOp::Eq(t) => t.to_tokens(tokens),
BinOp::Lt(t) => t.to_tokens(tokens),
BinOp::Le(t) => t.to_tokens(tokens),
BinOp::Ne(t) => t.to_tokens(tokens),
BinOp::Ge(t) => t.to_tokens(tokens),
BinOp::Gt(t) => t.to_tokens(tokens),
BinOp::AddEq(t) => t.to_tokens(tokens),
BinOp::SubEq(t) => t.to_tokens(tokens),
BinOp::MulEq(t) => t.to_tokens(tokens),
BinOp::DivEq(t) => t.to_tokens(tokens),
BinOp::RemEq(t) => t.to_tokens(tokens),
BinOp::BitXorEq(t) => t.to_tokens(tokens),
BinOp::BitAndEq(t) => t.to_tokens(tokens),
BinOp::BitOrEq(t) => t.to_tokens(tokens),
BinOp::ShlEq(t) => t.to_tokens(tokens),
BinOp::ShrEq(t) => t.to_tokens(tokens),
}
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for UnOp {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
UnOp::Deref(t) => t.to_tokens(tokens),
UnOp::Not(t) => t.to_tokens(tokens),
UnOp::Neg(t) => t.to_tokens(tokens),
}
}
}
}

1314
third_party/rust/syn-1.0.107/src/parse.rs поставляемый

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

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

@ -1,179 +0,0 @@
/// Parse the input TokenStream of a macro, triggering a compile error if the
/// tokens fail to parse.
///
/// Refer to the [`parse` module] documentation for more details about parsing
/// in Syn.
///
/// [`parse` module]: mod@crate::parse
///
/// <br>
///
/// # Intended usage
///
/// This macro must be called from a function that returns
/// `proc_macro::TokenStream`. Usually this will be your proc macro entry point,
/// the function that has the #\[proc_macro\] / #\[proc_macro_derive\] /
/// #\[proc_macro_attribute\] attribute.
///
/// ```
/// # extern crate proc_macro;
/// #
/// use proc_macro::TokenStream;
/// use syn::{parse_macro_input, Result};
/// use syn::parse::{Parse, ParseStream};
///
/// struct MyMacroInput {
/// /* ... */
/// }
///
/// impl Parse for MyMacroInput {
/// fn parse(input: ParseStream) -> Result<Self> {
/// /* ... */
/// # Ok(MyMacroInput {})
/// }
/// }
///
/// # const IGNORE: &str = stringify! {
/// #[proc_macro]
/// # };
/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
/// let input = parse_macro_input!(tokens as MyMacroInput);
///
/// /* ... */
/// # "".parse().unwrap()
/// }
/// ```
///
/// <br>
///
/// # Usage with Parser
///
/// This macro can also be used with the [`Parser` trait] for types that have
/// multiple ways that they can be parsed.
///
/// [`Parser` trait]: crate::parse::Parser
///
/// ```
/// # extern crate proc_macro;
/// #
/// # use proc_macro::TokenStream;
/// # use syn::{parse_macro_input, Result};
/// # use syn::parse::ParseStream;
/// #
/// # struct MyMacroInput {}
/// #
/// impl MyMacroInput {
/// fn parse_alternate(input: ParseStream) -> Result<Self> {
/// /* ... */
/// # Ok(MyMacroInput {})
/// }
/// }
///
/// # const IGNORE: &str = stringify! {
/// #[proc_macro]
/// # };
/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
/// let input = parse_macro_input!(tokens with MyMacroInput::parse_alternate);
///
/// /* ... */
/// # "".parse().unwrap()
/// }
/// ```
///
/// <br>
///
/// # Expansion
///
/// `parse_macro_input!($variable as $Type)` expands to something like:
///
/// ```no_run
/// # extern crate proc_macro;
/// #
/// # macro_rules! doc_test {
/// # ($variable:ident as $Type:ty) => {
/// match syn::parse::<$Type>($variable) {
/// Ok(syntax_tree) => syntax_tree,
/// Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()),
/// }
/// # };
/// # }
/// #
/// # fn test(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
/// # let _ = doc_test!(input as syn::Ident);
/// # proc_macro::TokenStream::new()
/// # }
/// ```
#[macro_export]
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))]
macro_rules! parse_macro_input {
($tokenstream:ident as $ty:ty) => {
match $crate::parse_macro_input::parse::<$ty>($tokenstream) {
$crate::__private::Ok(data) => data,
$crate::__private::Err(err) => {
return $crate::__private::TokenStream::from(err.to_compile_error());
}
}
};
($tokenstream:ident with $parser:path) => {
match $crate::parse::Parser::parse($parser, $tokenstream) {
$crate::__private::Ok(data) => data,
$crate::__private::Err(err) => {
return $crate::__private::TokenStream::from(err.to_compile_error());
}
}
};
($tokenstream:ident) => {
$crate::parse_macro_input!($tokenstream as _)
};
}
////////////////////////////////////////////////////////////////////////////////
// Can parse any type that implements Parse.
use crate::parse::{Parse, ParseStream, Parser, Result};
use proc_macro::TokenStream;
// Not public API.
#[doc(hidden)]
pub fn parse<T: ParseMacroInput>(token_stream: TokenStream) -> Result<T> {
T::parse.parse(token_stream)
}
// Not public API.
#[doc(hidden)]
pub trait ParseMacroInput: Sized {
fn parse(input: ParseStream) -> Result<Self>;
}
impl<T: Parse> ParseMacroInput for T {
fn parse(input: ParseStream) -> Result<Self> {
<T as Parse>::parse(input)
}
}
////////////////////////////////////////////////////////////////////////////////
// Any other types that we want `parse_macro_input!` to be able to parse.
#[cfg(any(feature = "full", feature = "derive"))]
use crate::AttributeArgs;
#[cfg(any(feature = "full", feature = "derive"))]
impl ParseMacroInput for AttributeArgs {
fn parse(input: ParseStream) -> Result<Self> {
let mut metas = Vec::new();
loop {
if input.is_empty() {
break;
}
let value = input.parse()?;
metas.push(value);
if input.is_empty() {
break;
}
input.parse::<Token![,]>()?;
}
Ok(metas)
}
}

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

@ -1,167 +0,0 @@
/// Quasi-quotation macro that accepts input like the [`quote!`] macro but uses
/// type inference to figure out a return type for those tokens.
///
/// [`quote!`]: https://docs.rs/quote/1.0/quote/index.html
///
/// The return type can be any syntax tree node that implements the [`Parse`]
/// trait.
///
/// [`Parse`]: crate::parse::Parse
///
/// ```
/// use quote::quote;
/// use syn::{parse_quote, Stmt};
///
/// fn main() {
/// let name = quote!(v);
/// let ty = quote!(u8);
///
/// let stmt: Stmt = parse_quote! {
/// let #name: #ty = Default::default();
/// };
///
/// println!("{:#?}", stmt);
/// }
/// ```
///
/// *This macro is available only if Syn is built with the `"parsing"` feature,
/// although interpolation of syntax tree nodes into the quoted tokens is only
/// supported if Syn is built with the `"printing"` feature as well.*
///
/// # Example
///
/// The following helper function adds a bound `T: HeapSize` to every type
/// parameter `T` in the input generics.
///
/// ```
/// use syn::{parse_quote, Generics, GenericParam};
///
/// // Add a bound `T: HeapSize` to every type parameter T.
/// fn add_trait_bounds(mut generics: Generics) -> Generics {
/// for param in &mut generics.params {
/// if let GenericParam::Type(type_param) = param {
/// type_param.bounds.push(parse_quote!(HeapSize));
/// }
/// }
/// generics
/// }
/// ```
///
/// # Special cases
///
/// This macro can parse the following additional types as a special case even
/// though they do not implement the `Parse` trait.
///
/// - [`Attribute`] — parses one attribute, allowing either outer like `#[...]`
/// or inner like `#![...]`
/// - [`Punctuated<T, P>`] — parses zero or more `T` separated by punctuation
/// `P` with optional trailing punctuation
/// - [`Vec<Stmt>`] — parses the same as `Block::parse_within`
///
/// [`Vec<Stmt>`]: Block::parse_within
///
/// # Panics
///
/// Panics if the tokens fail to parse as the expected syntax tree type. The
/// caller is responsible for ensuring that the input tokens are syntactically
/// valid.
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))]
#[macro_export]
macro_rules! parse_quote {
($($tt:tt)*) => {
$crate::parse_quote::parse($crate::__private::quote::quote!($($tt)*))
};
}
/// This macro is [`parse_quote!`] + [`quote_spanned!`][quote::quote_spanned].
///
/// Please refer to each of their documentation.
///
/// # Example
///
/// ```
/// use quote::{quote, quote_spanned};
/// use syn::spanned::Spanned;
/// use syn::{parse_quote_spanned, ReturnType, Signature};
///
/// // Changes `fn()` to `fn() -> Pin<Box<dyn Future<Output = ()>>>`,
/// // and `fn() -> T` to `fn() -> Pin<Box<dyn Future<Output = T>>>`,
/// // without introducing any call_site() spans.
/// fn make_ret_pinned_future(sig: &mut Signature) {
/// let ret = match &sig.output {
/// ReturnType::Default => quote_spanned!(sig.paren_token.span=> ()),
/// ReturnType::Type(_, ret) => quote!(#ret),
/// };
/// sig.output = parse_quote_spanned! {ret.span()=>
/// -> ::std::pin::Pin<::std::boxed::Box<dyn ::std::future::Future<Output = #ret>>>
/// };
/// }
/// ```
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))]
#[macro_export]
macro_rules! parse_quote_spanned {
($span:expr=> $($tt:tt)*) => {
$crate::parse_quote::parse($crate::__private::quote::quote_spanned!($span=> $($tt)*))
};
}
////////////////////////////////////////////////////////////////////////////////
// Can parse any type that implements Parse.
use crate::parse::{Parse, ParseStream, Parser, Result};
use proc_macro2::TokenStream;
// Not public API.
#[doc(hidden)]
pub fn parse<T: ParseQuote>(token_stream: TokenStream) -> T {
let parser = T::parse;
match parser.parse2(token_stream) {
Ok(t) => t,
Err(err) => panic!("{}", err),
}
}
// Not public API.
#[doc(hidden)]
pub trait ParseQuote: Sized {
fn parse(input: ParseStream) -> Result<Self>;
}
impl<T: Parse> ParseQuote for T {
fn parse(input: ParseStream) -> Result<Self> {
<T as Parse>::parse(input)
}
}
////////////////////////////////////////////////////////////////////////////////
// Any other types that we want `parse_quote!` to be able to parse.
use crate::punctuated::Punctuated;
#[cfg(any(feature = "full", feature = "derive"))]
use crate::{attr, Attribute};
#[cfg(feature = "full")]
use crate::{Block, Stmt};
#[cfg(any(feature = "full", feature = "derive"))]
impl ParseQuote for Attribute {
fn parse(input: ParseStream) -> Result<Self> {
if input.peek(Token![#]) && input.peek2(Token![!]) {
attr::parsing::single_parse_inner(input)
} else {
attr::parsing::single_parse_outer(input)
}
}
}
impl<T: Parse, P: Parse> ParseQuote for Punctuated<T, P> {
fn parse(input: ParseStream) -> Result<Self> {
Self::parse_terminated(input)
}
}
#[cfg(feature = "full")]
impl ParseQuote for Vec<Stmt> {
fn parse(input: ParseStream) -> Result<Self> {
Block::parse_within(input)
}
}

927
third_party/rust/syn-1.0.107/src/pat.rs поставляемый
Просмотреть файл

@ -1,927 +0,0 @@
use super::*;
use crate::punctuated::Punctuated;
use proc_macro2::TokenStream;
ast_enum_of_structs! {
/// A pattern in a local binding, function signature, match expression, or
/// various other places.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
///
/// # Syntax tree enum
///
/// This type is a [syntax tree enum].
///
/// [syntax tree enum]: Expr#syntax-tree-enums
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
#[cfg_attr(not(syn_no_non_exhaustive), non_exhaustive)]
pub enum Pat {
/// A box pattern: `box v`.
Box(PatBox),
/// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
Ident(PatIdent),
/// A literal pattern: `0`.
///
/// This holds an `Expr` rather than a `Lit` because negative numbers
/// are represented as an `Expr::Unary`.
Lit(PatLit),
/// A macro in pattern position.
Macro(PatMacro),
/// A pattern that matches any one of a set of cases.
Or(PatOr),
/// A path pattern like `Color::Red`, optionally qualified with a
/// self-type.
///
/// 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.
Path(PatPath),
/// A range pattern: `1..=2`.
Range(PatRange),
/// A reference pattern: `&mut var`.
Reference(PatReference),
/// The dots in a tuple or slice pattern: `[0, 1, ..]`
Rest(PatRest),
/// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
Slice(PatSlice),
/// A struct or struct variant pattern: `Variant { x, y, .. }`.
Struct(PatStruct),
/// A tuple pattern: `(a, b)`.
Tuple(PatTuple),
/// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
TupleStruct(PatTupleStruct),
/// A type ascription pattern: `foo: f64`.
Type(PatType),
/// Tokens in pattern position not interpreted by Syn.
Verbatim(TokenStream),
/// A pattern that matches any value: `_`.
Wild(PatWild),
// Not public API.
//
// For testing exhaustiveness in downstream code, use the following idiom:
//
// match pat {
// Pat::Box(pat) => {...}
// Pat::Ident(pat) => {...}
// ...
// Pat::Wild(pat) => {...}
//
// #[cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
// _ => { /* some sane fallback */ }
// }
//
// This way we fail your tests but don't break your library when adding
// a variant. You will be notified by a test failure when a variant is
// added, so that you can add code to handle it, but your library will
// continue to compile and work for downstream users in the interim.
#[cfg(syn_no_non_exhaustive)]
#[doc(hidden)]
__NonExhaustive,
}
}
ast_struct! {
/// A box pattern: `box v`.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatBox {
pub attrs: Vec<Attribute>,
pub box_token: Token![box],
pub pat: Box<Pat>,
}
}
ast_struct! {
/// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
///
/// It may also be a unit struct or struct variant (e.g. `None`), or a
/// constant; these cannot be distinguished syntactically.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatIdent {
pub attrs: Vec<Attribute>,
pub by_ref: Option<Token![ref]>,
pub mutability: Option<Token![mut]>,
pub ident: Ident,
pub subpat: Option<(Token![@], Box<Pat>)>,
}
}
ast_struct! {
/// A literal pattern: `0`.
///
/// This holds an `Expr` rather than a `Lit` because negative numbers
/// are represented as an `Expr::Unary`.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatLit {
pub attrs: Vec<Attribute>,
pub expr: Box<Expr>,
}
}
ast_struct! {
/// A macro in pattern position.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatMacro {
pub attrs: Vec<Attribute>,
pub mac: Macro,
}
}
ast_struct! {
/// A pattern that matches any one of a set of cases.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatOr {
pub attrs: Vec<Attribute>,
pub leading_vert: Option<Token![|]>,
pub cases: Punctuated<Pat, Token![|]>,
}
}
ast_struct! {
/// A path pattern like `Color::Red`, optionally qualified with a
/// self-type.
///
/// 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.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatPath {
pub attrs: Vec<Attribute>,
pub qself: Option<QSelf>,
pub path: Path,
}
}
ast_struct! {
/// A range pattern: `1..=2`.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatRange {
pub attrs: Vec<Attribute>,
pub lo: Box<Expr>,
pub limits: RangeLimits,
pub hi: Box<Expr>,
}
}
ast_struct! {
/// A reference pattern: `&mut var`.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatReference {
pub attrs: Vec<Attribute>,
pub and_token: Token![&],
pub mutability: Option<Token![mut]>,
pub pat: Box<Pat>,
}
}
ast_struct! {
/// The dots in a tuple or slice pattern: `[0, 1, ..]`
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatRest {
pub attrs: Vec<Attribute>,
pub dot2_token: Token![..],
}
}
ast_struct! {
/// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatSlice {
pub attrs: Vec<Attribute>,
pub bracket_token: token::Bracket,
pub elems: Punctuated<Pat, Token![,]>,
}
}
ast_struct! {
/// A struct or struct variant pattern: `Variant { x, y, .. }`.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatStruct {
pub attrs: Vec<Attribute>,
pub path: Path,
pub brace_token: token::Brace,
pub fields: Punctuated<FieldPat, Token![,]>,
pub dot2_token: Option<Token![..]>,
}
}
ast_struct! {
/// A tuple pattern: `(a, b)`.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatTuple {
pub attrs: Vec<Attribute>,
pub paren_token: token::Paren,
pub elems: Punctuated<Pat, Token![,]>,
}
}
ast_struct! {
/// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatTupleStruct {
pub attrs: Vec<Attribute>,
pub path: Path,
pub pat: PatTuple,
}
}
ast_struct! {
/// A type ascription pattern: `foo: f64`.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatType {
pub attrs: Vec<Attribute>,
pub pat: Box<Pat>,
pub colon_token: Token![:],
pub ty: Box<Type>,
}
}
ast_struct! {
/// A pattern that matches any value: `_`.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct PatWild {
pub attrs: Vec<Attribute>,
pub underscore_token: Token![_],
}
}
ast_struct! {
/// A single field in a struct pattern.
///
/// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
/// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct FieldPat {
pub attrs: Vec<Attribute>,
pub member: Member,
pub colon_token: Option<Token![:]>,
pub pat: Box<Pat>,
}
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use crate::ext::IdentExt;
use crate::parse::{Parse, ParseBuffer, ParseStream, Result};
use crate::path;
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Pat {
fn parse(input: ParseStream) -> Result<Self> {
let begin = input.fork();
let lookahead = input.lookahead1();
if {
let ahead = input.fork();
ahead.parse::<Option<Ident>>()?.is_some()
&& (ahead.peek(Token![::])
|| ahead.peek(Token![!])
|| ahead.peek(token::Brace)
|| ahead.peek(token::Paren)
|| ahead.peek(Token![..])
&& ahead.parse::<RangeLimits>().is_ok()
&& !(ahead.is_empty() || ahead.peek(Token![,])))
} || {
let ahead = input.fork();
ahead.parse::<Option<Token![self]>>()?.is_some() && ahead.peek(Token![::])
} || lookahead.peek(Token![::])
|| lookahead.peek(Token![<])
|| input.peek(Token![Self])
|| input.peek(Token![super])
|| input.peek(Token![crate])
{
pat_path_or_macro_or_struct_or_range(input)
} else if lookahead.peek(Token![_]) {
input.call(pat_wild).map(Pat::Wild)
} else if input.peek(Token![box]) {
input.call(pat_box).map(Pat::Box)
} else if input.peek(Token![-]) || lookahead.peek(Lit) || lookahead.peek(Token![const])
{
pat_lit_or_range(input)
} else if lookahead.peek(Token![ref])
|| lookahead.peek(Token![mut])
|| input.peek(Token![self])
|| input.peek(Ident)
{
input.call(pat_ident).map(Pat::Ident)
} else if lookahead.peek(Token![&]) {
input.call(pat_reference).map(Pat::Reference)
} else if lookahead.peek(token::Paren) {
input.call(pat_tuple).map(Pat::Tuple)
} else if lookahead.peek(token::Bracket) {
input.call(pat_slice).map(Pat::Slice)
} else if lookahead.peek(Token![..]) && !input.peek(Token![...]) {
pat_range_half_open(input, begin)
} else if lookahead.peek(Token![const]) {
input.call(pat_const).map(Pat::Verbatim)
} else {
Err(lookahead.error())
}
}
}
fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
let begin = input.fork();
let (qself, path) = path::parsing::qpath(input, true)?;
if qself.is_none() && input.peek(Token![!]) && !input.peek(Token![!=]) {
let mut contains_arguments = false;
for segment in &path.segments {
match segment.arguments {
PathArguments::None => {}
PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
contains_arguments = true;
}
}
}
if !contains_arguments {
let bang_token: Token![!] = input.parse()?;
let (delimiter, tokens) = mac::parse_delimiter(input)?;
return Ok(Pat::Macro(PatMacro {
attrs: Vec::new(),
mac: Macro {
path,
bang_token,
delimiter,
tokens,
},
}));
}
}
if input.peek(token::Brace) {
let pat = pat_struct(begin.fork(), input, path)?;
if qself.is_some() {
Ok(Pat::Verbatim(verbatim::between(begin, input)))
} else {
Ok(pat)
}
} else if input.peek(token::Paren) {
let pat = pat_tuple_struct(input, path)?;
if qself.is_some() {
Ok(Pat::Verbatim(verbatim::between(begin, input)))
} else {
Ok(Pat::TupleStruct(pat))
}
} else if input.peek(Token![..]) {
pat_range(input, begin, qself, path)
} else {
Ok(Pat::Path(PatPath {
attrs: Vec::new(),
qself,
path,
}))
}
}
fn pat_wild(input: ParseStream) -> Result<PatWild> {
Ok(PatWild {
attrs: Vec::new(),
underscore_token: input.parse()?,
})
}
fn pat_box(input: ParseStream) -> Result<PatBox> {
Ok(PatBox {
attrs: Vec::new(),
box_token: input.parse()?,
pat: input.parse()?,
})
}
fn pat_ident(input: ParseStream) -> Result<PatIdent> {
Ok(PatIdent {
attrs: Vec::new(),
by_ref: input.parse()?,
mutability: input.parse()?,
ident: input.call(Ident::parse_any)?,
subpat: {
if input.peek(Token![@]) {
let at_token: Token![@] = input.parse()?;
let subpat: Pat = input.parse()?;
Some((at_token, Box::new(subpat)))
} else {
None
}
},
})
}
fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> {
Ok(PatTupleStruct {
attrs: Vec::new(),
path,
pat: input.call(pat_tuple)?,
})
}
fn pat_struct(begin: ParseBuffer, input: ParseStream, path: Path) -> Result<Pat> {
let content;
let brace_token = braced!(content in input);
let mut fields = Punctuated::new();
let mut dot2_token = None;
while !content.is_empty() {
let attrs = content.call(Attribute::parse_outer)?;
if content.peek(Token![..]) {
dot2_token = Some(content.parse()?);
if !attrs.is_empty() {
return Ok(Pat::Verbatim(verbatim::between(begin, input)));
}
break;
}
let mut value = content.call(field_pat)?;
value.attrs = attrs;
fields.push_value(value);
if content.is_empty() {
break;
}
let punct: Token![,] = content.parse()?;
fields.push_punct(punct);
}
Ok(Pat::Struct(PatStruct {
attrs: Vec::new(),
path,
brace_token,
fields,
dot2_token,
}))
}
impl Member {
fn is_unnamed(&self) -> bool {
match *self {
Member::Named(_) => false,
Member::Unnamed(_) => true,
}
}
}
fn field_pat(input: ParseStream) -> Result<FieldPat> {
let boxed: Option<Token![box]> = input.parse()?;
let by_ref: Option<Token![ref]> = input.parse()?;
let mutability: Option<Token![mut]> = input.parse()?;
let member: Member = input.parse()?;
if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
|| member.is_unnamed()
{
return Ok(FieldPat {
attrs: Vec::new(),
member,
colon_token: input.parse()?,
pat: Box::new(multi_pat_with_leading_vert(input)?),
});
}
let ident = match member {
Member::Named(ident) => ident,
Member::Unnamed(_) => unreachable!(),
};
let mut pat = Pat::Ident(PatIdent {
attrs: Vec::new(),
by_ref,
mutability,
ident: ident.clone(),
subpat: None,
});
if let Some(boxed) = boxed {
pat = Pat::Box(PatBox {
attrs: Vec::new(),
box_token: boxed,
pat: Box::new(pat),
});
}
Ok(FieldPat {
attrs: Vec::new(),
member: Member::Named(ident),
colon_token: None,
pat: Box::new(pat),
})
}
fn pat_range(
input: ParseStream,
begin: ParseBuffer,
qself: Option<QSelf>,
path: Path,
) -> Result<Pat> {
let limits: RangeLimits = input.parse()?;
let hi = input.call(pat_lit_expr)?;
if let Some(hi) = hi {
Ok(Pat::Range(PatRange {
attrs: Vec::new(),
lo: Box::new(Expr::Path(ExprPath {
attrs: Vec::new(),
qself,
path,
})),
limits,
hi,
}))
} else {
Ok(Pat::Verbatim(verbatim::between(begin, input)))
}
}
fn pat_range_half_open(input: ParseStream, begin: ParseBuffer) -> Result<Pat> {
let limits: RangeLimits = input.parse()?;
let hi = input.call(pat_lit_expr)?;
if hi.is_some() {
Ok(Pat::Verbatim(verbatim::between(begin, input)))
} else {
match limits {
RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest {
attrs: Vec::new(),
dot2_token,
})),
RangeLimits::Closed(_) => Err(input.error("expected range upper bound")),
}
}
}
fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
let content;
let paren_token = parenthesized!(content in input);
let mut elems = Punctuated::new();
while !content.is_empty() {
let value = multi_pat_with_leading_vert(&content)?;
elems.push_value(value);
if content.is_empty() {
break;
}
let punct = content.parse()?;
elems.push_punct(punct);
}
Ok(PatTuple {
attrs: Vec::new(),
paren_token,
elems,
})
}
fn pat_reference(input: ParseStream) -> Result<PatReference> {
Ok(PatReference {
attrs: Vec::new(),
and_token: input.parse()?,
mutability: input.parse()?,
pat: input.parse()?,
})
}
fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
let begin = input.fork();
let lo = input.call(pat_lit_expr)?.unwrap();
if input.peek(Token![..]) {
let limits: RangeLimits = input.parse()?;
let hi = input.call(pat_lit_expr)?;
if let Some(hi) = hi {
Ok(Pat::Range(PatRange {
attrs: Vec::new(),
lo,
limits,
hi,
}))
} else {
Ok(Pat::Verbatim(verbatim::between(begin, input)))
}
} else if let Expr::Verbatim(verbatim) = *lo {
Ok(Pat::Verbatim(verbatim))
} else {
Ok(Pat::Lit(PatLit {
attrs: Vec::new(),
expr: lo,
}))
}
}
fn pat_lit_expr(input: ParseStream) -> Result<Option<Box<Expr>>> {
if input.is_empty()
|| input.peek(Token![|])
|| input.peek(Token![=])
|| input.peek(Token![:]) && !input.peek(Token![::])
|| input.peek(Token![,])
|| input.peek(Token![;])
{
return Ok(None);
}
let neg: Option<Token![-]> = input.parse()?;
let lookahead = input.lookahead1();
let expr = if lookahead.peek(Lit) {
Expr::Lit(input.parse()?)
} else if lookahead.peek(Ident)
|| lookahead.peek(Token![::])
|| lookahead.peek(Token![<])
|| lookahead.peek(Token![self])
|| lookahead.peek(Token![Self])
|| lookahead.peek(Token![super])
|| lookahead.peek(Token![crate])
{
Expr::Path(input.parse()?)
} else if lookahead.peek(Token![const]) {
Expr::Verbatim(input.call(expr::parsing::expr_const)?)
} else {
return Err(lookahead.error());
};
Ok(Some(Box::new(if let Some(neg) = neg {
Expr::Unary(ExprUnary {
attrs: Vec::new(),
op: UnOp::Neg(neg),
expr: Box::new(expr),
})
} else {
expr
})))
}
fn pat_slice(input: ParseStream) -> Result<PatSlice> {
let content;
let bracket_token = bracketed!(content in input);
let mut elems = Punctuated::new();
while !content.is_empty() {
let value = multi_pat_with_leading_vert(&content)?;
elems.push_value(value);
if content.is_empty() {
break;
}
let punct = content.parse()?;
elems.push_punct(punct);
}
Ok(PatSlice {
attrs: Vec::new(),
bracket_token,
elems,
})
}
fn pat_const(input: ParseStream) -> Result<TokenStream> {
let begin = input.fork();
input.parse::<Token![const]>()?;
let content;
braced!(content in input);
content.call(Attribute::parse_inner)?;
content.call(Block::parse_within)?;
Ok(verbatim::between(begin, input))
}
pub fn multi_pat(input: ParseStream) -> Result<Pat> {
multi_pat_impl(input, None)
}
pub fn multi_pat_with_leading_vert(input: ParseStream) -> Result<Pat> {
let leading_vert: Option<Token![|]> = input.parse()?;
multi_pat_impl(input, leading_vert)
}
fn multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat> {
let mut pat: Pat = input.parse()?;
if leading_vert.is_some()
|| input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=])
{
let mut cases = Punctuated::new();
cases.push_value(pat);
while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
let punct = input.parse()?;
cases.push_punct(punct);
let pat: Pat = input.parse()?;
cases.push_value(pat);
}
pat = Pat::Or(PatOr {
attrs: Vec::new(),
leading_vert,
cases,
});
}
Ok(pat)
}
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use crate::attr::FilterAttrs;
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt};
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatWild {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
self.underscore_token.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatIdent {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
self.by_ref.to_tokens(tokens);
self.mutability.to_tokens(tokens);
self.ident.to_tokens(tokens);
if let Some((at_token, subpat)) = &self.subpat {
at_token.to_tokens(tokens);
subpat.to_tokens(tokens);
}
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatStruct {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
self.path.to_tokens(tokens);
self.brace_token.surround(tokens, |tokens| {
self.fields.to_tokens(tokens);
// NOTE: We need a comma before the dot2 token if it is present.
if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
<Token![,]>::default().to_tokens(tokens);
}
self.dot2_token.to_tokens(tokens);
});
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatTupleStruct {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
self.path.to_tokens(tokens);
self.pat.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatType {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
self.pat.to_tokens(tokens);
self.colon_token.to_tokens(tokens);
self.ty.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatPath {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
path::printing::print_path(tokens, &self.qself, &self.path);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatTuple {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
self.paren_token.surround(tokens, |tokens| {
self.elems.to_tokens(tokens);
});
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatBox {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
self.box_token.to_tokens(tokens);
self.pat.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatReference {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
self.and_token.to_tokens(tokens);
self.mutability.to_tokens(tokens);
self.pat.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatRest {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
self.dot2_token.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatLit {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
self.expr.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatRange {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
self.lo.to_tokens(tokens);
self.limits.to_tokens(tokens);
self.hi.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatSlice {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
self.bracket_token.surround(tokens, |tokens| {
self.elems.to_tokens(tokens);
});
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatMacro {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
self.mac.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PatOr {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
self.leading_vert.to_tokens(tokens);
self.cases.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for FieldPat {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
if let Some(colon_token) = &self.colon_token {
self.member.to_tokens(tokens);
colon_token.to_tokens(tokens);
}
self.pat.to_tokens(tokens);
}
}
}

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

@ -1,854 +0,0 @@
use super::*;
use crate::punctuated::Punctuated;
ast_struct! {
/// A path at which a named item is exported (e.g. `std::collections::HashMap`).
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct Path {
pub leading_colon: Option<Token![::]>,
pub segments: Punctuated<PathSegment, Token![::]>,
}
}
impl<T> From<T> for Path
where
T: Into<PathSegment>,
{
fn from(segment: T) -> Self {
let mut path = Path {
leading_colon: None,
segments: Punctuated::new(),
};
path.segments.push_value(segment.into());
path
}
}
ast_struct! {
/// A segment of a path together with any path arguments on that segment.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct PathSegment {
pub ident: Ident,
pub arguments: PathArguments,
}
}
impl<T> From<T> for PathSegment
where
T: Into<Ident>,
{
fn from(ident: T) -> Self {
PathSegment {
ident: ident.into(),
arguments: PathArguments::None,
}
}
}
ast_enum! {
/// Angle bracketed or parenthesized arguments of a path segment.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
///
/// ## Angle bracketed
///
/// The `<'a, T>` in `std::slice::iter<'a, T>`.
///
/// ## Parenthesized
///
/// The `(A, B) -> C` in `Fn(A, B) -> C`.
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub enum PathArguments {
None,
/// The `<'a, T>` in `std::slice::iter<'a, T>`.
AngleBracketed(AngleBracketedGenericArguments),
/// The `(A, B) -> C` in `Fn(A, B) -> C`.
Parenthesized(ParenthesizedGenericArguments),
}
}
impl Default for PathArguments {
fn default() -> Self {
PathArguments::None
}
}
impl PathArguments {
pub fn is_empty(&self) -> bool {
match self {
PathArguments::None => true,
PathArguments::AngleBracketed(bracketed) => bracketed.args.is_empty(),
PathArguments::Parenthesized(_) => false,
}
}
pub fn is_none(&self) -> bool {
match self {
PathArguments::None => true,
PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => false,
}
}
}
ast_enum! {
/// An individual generic argument, like `'a`, `T`, or `Item = T`.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub enum GenericArgument {
/// A lifetime argument.
Lifetime(Lifetime),
/// A type argument.
Type(Type),
/// A const expression. Must be inside of a block.
///
/// NOTE: Identity expressions are represented as Type arguments, as
/// they are indistinguishable syntactically.
Const(Expr),
/// A binding (equality constraint) on an associated type: the `Item =
/// u8` in `Iterator<Item = u8>`.
Binding(Binding),
/// An associated type bound: `Iterator<Item: Display>`.
Constraint(Constraint),
}
}
ast_struct! {
/// Angle bracketed arguments of a path segment: the `<K, V>` in `HashMap<K,
/// V>`.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct AngleBracketedGenericArguments {
pub colon2_token: Option<Token![::]>,
pub lt_token: Token![<],
pub args: Punctuated<GenericArgument, Token![,]>,
pub gt_token: Token![>],
}
}
ast_struct! {
/// A binding (equality constraint) on an associated type: `Item = u8`.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct Binding {
pub ident: Ident,
pub eq_token: Token![=],
pub ty: Type,
}
}
ast_struct! {
/// An associated type bound: `Iterator<Item: Display>`.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct Constraint {
pub ident: Ident,
pub colon_token: Token![:],
pub bounds: Punctuated<TypeParamBound, Token![+]>,
}
}
ast_struct! {
/// Arguments of a function path segment: the `(A, B) -> C` in `Fn(A,B) ->
/// C`.
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct ParenthesizedGenericArguments {
pub paren_token: token::Paren,
/// `(A, B)`
pub inputs: Punctuated<Type, Token![,]>,
/// `C`
pub output: ReturnType,
}
}
ast_struct! {
/// The explicit Self type in a qualified path: the `T` in `<T as
/// Display>::fmt`.
///
/// The actual path, including the trait and the associated item, is stored
/// separately. The `position` field represents the index of the associated
/// item qualified with this Self type.
///
/// ```text
/// <Vec<T> as a::b::Trait>::AssociatedItem
/// ^~~~~~ ~~~~~~~~~~~~~~^
/// ty position = 3
///
/// <Vec<T>>::AssociatedItem
/// ^~~~~~ ^
/// ty position = 0
/// ```
///
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
pub struct QSelf {
pub lt_token: Token![<],
pub ty: Box<Type>,
pub position: usize,
pub as_token: Option<Token![as]>,
pub gt_token: Token![>],
}
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use crate::ext::IdentExt;
use crate::parse::{Parse, ParseStream, Result};
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Path {
fn parse(input: ParseStream) -> Result<Self> {
Self::parse_helper(input, false)
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for GenericArgument {
fn parse(input: ParseStream) -> Result<Self> {
if input.peek(Lifetime) && !input.peek2(Token![+]) {
return Ok(GenericArgument::Lifetime(input.parse()?));
}
if input.peek(Ident) && input.peek2(Token![=]) {
let ident: Ident = input.parse()?;
let eq_token: Token![=] = input.parse()?;
let ty = if input.peek(Lit) {
let begin = input.fork();
input.parse::<Lit>()?;
Type::Verbatim(verbatim::between(begin, input))
} else if input.peek(token::Brace) {
let begin = input.fork();
#[cfg(feature = "full")]
{
input.parse::<ExprBlock>()?;
}
#[cfg(not(feature = "full"))]
{
let content;
braced!(content in input);
content.parse::<Expr>()?;
}
Type::Verbatim(verbatim::between(begin, input))
} else {
input.parse()?
};
return Ok(GenericArgument::Binding(Binding {
ident,
eq_token,
ty,
}));
}
#[cfg(feature = "full")]
{
if input.peek(Ident) && input.peek2(Token![:]) && !input.peek2(Token![::]) {
return Ok(GenericArgument::Constraint(input.parse()?));
}
}
if input.peek(Lit) || input.peek(token::Brace) {
return const_argument(input).map(GenericArgument::Const);
}
#[cfg(feature = "full")]
let begin = input.fork();
let argument: Type = input.parse()?;
#[cfg(feature = "full")]
{
if match &argument {
Type::Path(argument)
if argument.qself.is_none()
&& argument.path.leading_colon.is_none()
&& argument.path.segments.len() == 1 =>
{
match argument.path.segments[0].arguments {
PathArguments::AngleBracketed(_) => true,
_ => false,
}
}
_ => false,
} && if input.peek(Token![=]) {
input.parse::<Token![=]>()?;
input.parse::<Type>()?;
true
} else if input.peek(Token![:]) {
input.parse::<Token![:]>()?;
input.call(constraint_bounds)?;
true
} else {
false
} {
let verbatim = verbatim::between(begin, input);
return Ok(GenericArgument::Type(Type::Verbatim(verbatim)));
}
}
Ok(GenericArgument::Type(argument))
}
}
pub fn const_argument(input: ParseStream) -> Result<Expr> {
let lookahead = input.lookahead1();
if input.peek(Lit) {
let lit = input.parse()?;
return Ok(Expr::Lit(lit));
}
#[cfg(feature = "full")]
{
if input.peek(Ident) {
let ident: Ident = input.parse()?;
return Ok(Expr::Path(ExprPath {
attrs: Vec::new(),
qself: None,
path: Path::from(ident),
}));
}
}
if input.peek(token::Brace) {
#[cfg(feature = "full")]
{
let block: ExprBlock = input.parse()?;
return Ok(Expr::Block(block));
}
#[cfg(not(feature = "full"))]
{
let begin = input.fork();
let content;
braced!(content in input);
content.parse::<Expr>()?;
let verbatim = verbatim::between(begin, input);
return Ok(Expr::Verbatim(verbatim));
}
}
Err(lookahead.error())
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for AngleBracketedGenericArguments {
fn parse(input: ParseStream) -> Result<Self> {
Ok(AngleBracketedGenericArguments {
colon2_token: input.parse()?,
lt_token: input.parse()?,
args: {
let mut args = Punctuated::new();
loop {
if input.peek(Token![>]) {
break;
}
let value = input.parse()?;
args.push_value(value);
if input.peek(Token![>]) {
break;
}
let punct = input.parse()?;
args.push_punct(punct);
}
args
},
gt_token: input.parse()?,
})
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for ParenthesizedGenericArguments {
fn parse(input: ParseStream) -> Result<Self> {
let content;
Ok(ParenthesizedGenericArguments {
paren_token: parenthesized!(content in input),
inputs: content.parse_terminated(Type::parse)?,
output: input.call(ReturnType::without_plus)?,
})
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for PathSegment {
fn parse(input: ParseStream) -> Result<Self> {
Self::parse_helper(input, false)
}
}
impl PathSegment {
fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> {
if input.peek(Token![super]) || input.peek(Token![self]) || input.peek(Token![crate]) {
let ident = input.call(Ident::parse_any)?;
return Ok(PathSegment::from(ident));
}
let ident = if input.peek(Token![Self]) {
input.call(Ident::parse_any)?
} else {
input.parse()?
};
if !expr_style && input.peek(Token![<]) && !input.peek(Token![<=])
|| input.peek(Token![::]) && input.peek3(Token![<])
{
Ok(PathSegment {
ident,
arguments: PathArguments::AngleBracketed(input.parse()?),
})
} else {
Ok(PathSegment::from(ident))
}
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Binding {
fn parse(input: ParseStream) -> Result<Self> {
Ok(Binding {
ident: input.parse()?,
eq_token: input.parse()?,
ty: input.parse()?,
})
}
}
#[cfg(feature = "full")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Constraint {
fn parse(input: ParseStream) -> Result<Self> {
Ok(Constraint {
ident: input.parse()?,
colon_token: input.parse()?,
bounds: constraint_bounds(input)?,
})
}
}
#[cfg(feature = "full")]
fn constraint_bounds(input: ParseStream) -> Result<Punctuated<TypeParamBound, Token![+]>> {
let mut bounds = Punctuated::new();
loop {
if input.peek(Token![,]) || input.peek(Token![>]) {
break;
}
let value = input.parse()?;
bounds.push_value(value);
if !input.peek(Token![+]) {
break;
}
let punct = input.parse()?;
bounds.push_punct(punct);
}
Ok(bounds)
}
impl Path {
/// Parse a `Path` containing no path arguments on any of its segments.
///
/// *This function is available only if Syn is built with the `"parsing"`
/// feature.*
///
/// # Example
///
/// ```
/// use syn::{Path, Result, Token};
/// use syn::parse::{Parse, ParseStream};
///
/// // A simplified single `use` statement like:
/// //
/// // use std::collections::HashMap;
/// //
/// // Note that generic parameters are not allowed in a `use` statement
/// // so the following must not be accepted.
/// //
/// // use a::<b>::c;
/// struct SingleUse {
/// use_token: Token![use],
/// path: Path,
/// }
///
/// impl Parse for SingleUse {
/// fn parse(input: ParseStream) -> Result<Self> {
/// Ok(SingleUse {
/// use_token: input.parse()?,
/// path: input.call(Path::parse_mod_style)?,
/// })
/// }
/// }
/// ```
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn parse_mod_style(input: ParseStream) -> Result<Self> {
Ok(Path {
leading_colon: input.parse()?,
segments: {
let mut segments = Punctuated::new();
loop {
if !input.peek(Ident)
&& !input.peek(Token![super])
&& !input.peek(Token![self])
&& !input.peek(Token![Self])
&& !input.peek(Token![crate])
{
break;
}
let ident = Ident::parse_any(input)?;
segments.push_value(PathSegment::from(ident));
if !input.peek(Token![::]) {
break;
}
let punct = input.parse()?;
segments.push_punct(punct);
}
if segments.is_empty() {
return Err(input.error("expected path"));
} else if segments.trailing_punct() {
return Err(input.error("expected path segment"));
}
segments
},
})
}
/// Determines whether this is a path of length 1 equal to the given
/// ident.
///
/// For them to compare equal, it must be the case that:
///
/// - the path has no leading colon,
/// - the number of path segments is 1,
/// - 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 only if Syn is built with the `"parsing"`
/// feature.*
///
/// # Example
///
/// ```
/// use syn::{Attribute, Error, Meta, NestedMeta, Result};
/// # use std::iter::FromIterator;
///
/// fn get_serde_meta_items(attr: &Attribute) -> Result<Vec<NestedMeta>> {
/// if attr.path.is_ident("serde") {
/// match attr.parse_meta()? {
/// Meta::List(meta) => Ok(Vec::from_iter(meta.nested)),
/// bad => Err(Error::new_spanned(bad, "unrecognized attribute")),
/// }
/// } else {
/// Ok(Vec::new())
/// }
/// }
/// ```
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn is_ident<I: ?Sized>(&self, ident: &I) -> bool
where
Ident: PartialEq<I>,
{
match self.get_ident() {
Some(id) => id == ident,
None => false,
}
}
/// If this path consists of a single ident, returns the ident.
///
/// A path is considered an ident if:
///
/// - the path has no leading colon,
/// - the number of path segments is 1, and
/// - the first path segment has no angle bracketed or parenthesized
/// path arguments.
///
/// *This function is available only if Syn is built with the `"parsing"`
/// feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn get_ident(&self) -> Option<&Ident> {
if self.leading_colon.is_none()
&& self.segments.len() == 1
&& self.segments[0].arguments.is_none()
{
Some(&self.segments[0].ident)
} else {
None
}
}
pub(crate) fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> {
let mut path = Path {
leading_colon: input.parse()?,
segments: {
let mut segments = Punctuated::new();
let value = PathSegment::parse_helper(input, expr_style)?;
segments.push_value(value);
segments
},
};
Path::parse_rest(input, &mut path, expr_style)?;
Ok(path)
}
pub(crate) fn parse_rest(
input: ParseStream,
path: &mut Self,
expr_style: bool,
) -> Result<()> {
while input.peek(Token![::]) && !input.peek3(token::Paren) {
let punct: Token![::] = input.parse()?;
path.segments.push_punct(punct);
let value = PathSegment::parse_helper(input, expr_style)?;
path.segments.push_value(value);
}
Ok(())
}
}
pub fn qpath(input: ParseStream, expr_style: bool) -> Result<(Option<QSelf>, Path)> {
if input.peek(Token![<]) {
let lt_token: Token![<] = input.parse()?;
let this: Type = input.parse()?;
let path = if input.peek(Token![as]) {
let as_token: Token![as] = input.parse()?;
let path: Path = input.parse()?;
Some((as_token, path))
} else {
None
};
let gt_token: Token![>] = input.parse()?;
let colon2_token: Token![::] = input.parse()?;
let mut rest = Punctuated::new();
loop {
let path = PathSegment::parse_helper(input, expr_style)?;
rest.push_value(path);
if !input.peek(Token![::]) {
break;
}
let punct: Token![::] = input.parse()?;
rest.push_punct(punct);
}
let (position, as_token, path) = match path {
Some((as_token, mut path)) => {
let pos = path.segments.len();
path.segments.push_punct(colon2_token);
path.segments.extend(rest.into_pairs());
(pos, Some(as_token), path)
}
None => {
let path = Path {
leading_colon: Some(colon2_token),
segments: rest,
};
(0, None, path)
}
};
let qself = QSelf {
lt_token,
ty: Box::new(this),
position,
as_token,
gt_token,
};
Ok((Some(qself), path))
} else {
let path = Path::parse_helper(input, expr_style)?;
Ok((None, path))
}
}
}
#[cfg(feature = "printing")]
pub(crate) mod printing {
use super::*;
use crate::print::TokensOrDefault;
use proc_macro2::TokenStream;
use quote::ToTokens;
use std::cmp;
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for Path {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.leading_colon.to_tokens(tokens);
self.segments.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PathSegment {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.ident.to_tokens(tokens);
self.arguments.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for PathArguments {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
PathArguments::None => {}
PathArguments::AngleBracketed(arguments) => {
arguments.to_tokens(tokens);
}
PathArguments::Parenthesized(arguments) => {
arguments.to_tokens(tokens);
}
}
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for GenericArgument {
#[allow(clippy::match_same_arms)]
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
GenericArgument::Lifetime(lt) => lt.to_tokens(tokens),
GenericArgument::Type(ty) => ty.to_tokens(tokens),
GenericArgument::Const(e) => match *e {
Expr::Lit(_) => e.to_tokens(tokens),
// NOTE: We should probably support parsing blocks with only
// expressions in them without the full feature for const
// generics.
#[cfg(feature = "full")]
Expr::Block(_) => e.to_tokens(tokens),
// ERROR CORRECTION: Add braces to make sure that the
// generated code is valid.
_ => token::Brace::default().surround(tokens, |tokens| {
e.to_tokens(tokens);
}),
},
GenericArgument::Binding(tb) => tb.to_tokens(tokens),
GenericArgument::Constraint(tc) => tc.to_tokens(tokens),
}
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for AngleBracketedGenericArguments {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.colon2_token.to_tokens(tokens);
self.lt_token.to_tokens(tokens);
// Print lifetimes before types/consts/bindings, regardless of their
// order in self.args.
let mut trailing_or_empty = true;
for param in self.args.pairs() {
match **param.value() {
GenericArgument::Lifetime(_) => {
param.to_tokens(tokens);
trailing_or_empty = param.punct().is_some();
}
GenericArgument::Type(_)
| GenericArgument::Const(_)
| GenericArgument::Binding(_)
| GenericArgument::Constraint(_) => {}
}
}
for param in self.args.pairs() {
match **param.value() {
GenericArgument::Type(_)
| GenericArgument::Const(_)
| GenericArgument::Binding(_)
| GenericArgument::Constraint(_) => {
if !trailing_or_empty {
<Token![,]>::default().to_tokens(tokens);
}
param.to_tokens(tokens);
trailing_or_empty = param.punct().is_some();
}
GenericArgument::Lifetime(_) => {}
}
}
self.gt_token.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for Binding {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.ident.to_tokens(tokens);
self.eq_token.to_tokens(tokens);
self.ty.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for Constraint {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.ident.to_tokens(tokens);
self.colon_token.to_tokens(tokens);
self.bounds.to_tokens(tokens);
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for ParenthesizedGenericArguments {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.paren_token.surround(tokens, |tokens| {
self.inputs.to_tokens(tokens);
});
self.output.to_tokens(tokens);
}
}
pub(crate) fn print_path(tokens: &mut TokenStream, qself: &Option<QSelf>, path: &Path) {
let qself = match qself {
Some(qself) => qself,
None => {
path.to_tokens(tokens);
return;
}
};
qself.lt_token.to_tokens(tokens);
qself.ty.to_tokens(tokens);
let pos = cmp::min(qself.position, path.segments.len());
let mut segments = path.segments.pairs();
if pos > 0 {
TokensOrDefault(&qself.as_token).to_tokens(tokens);
path.leading_colon.to_tokens(tokens);
for (i, segment) in segments.by_ref().take(pos).enumerate() {
if i + 1 == pos {
segment.value().to_tokens(tokens);
qself.gt_token.to_tokens(tokens);
segment.punct().to_tokens(tokens);
} else {
segment.to_tokens(tokens);
}
}
} else {
qself.gt_token.to_tokens(tokens);
path.leading_colon.to_tokens(tokens);
}
for segment in segments {
segment.to_tokens(tokens);
}
}
}

16
third_party/rust/syn-1.0.107/src/print.rs поставляемый
Просмотреть файл

@ -1,16 +0,0 @@
use proc_macro2::TokenStream;
use quote::ToTokens;
pub struct TokensOrDefault<'a, T: 'a>(pub &'a Option<T>);
impl<'a, T> ToTokens for TokensOrDefault<'a, T>
where
T: ToTokens + Default,
{
fn to_tokens(&self, tokens: &mut TokenStream) {
match self.0 {
Some(t) => t.to_tokens(tokens),
None => T::default().to_tokens(tokens),
}
}
}

1087
third_party/rust/syn-1.0.107/src/punctuated.rs поставляемый

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

44
third_party/rust/syn-1.0.107/src/reserved.rs поставляемый
Просмотреть файл

@ -1,44 +0,0 @@
// Type for a syntax tree node that is reserved for future use.
//
// For example ExprReference contains a field `raw` of type Reserved. If `&raw
// place` syntax becomes a thing as per https://github.com/rust-lang/rfcs/pull/2582,
// we can backward compatibly change `raw`'s type to Option<Token![raw]> without
// the possibility of breaking any code.
use proc_macro2::Span;
use std::marker::PhantomData;
#[cfg(feature = "extra-traits")]
use std::fmt::{self, Debug};
ast_struct! {
pub struct Reserved {
_private: PhantomData<Span>,
}
}
impl Default for Reserved {
fn default() -> Self {
Reserved {
_private: PhantomData,
}
}
}
#[cfg(feature = "clone-impls")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
impl Clone for Reserved {
fn clone(&self) -> Self {
Reserved {
_private: self._private,
}
}
}
#[cfg(feature = "extra-traits")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
impl Debug for Reserved {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.debug_struct("Reserved").finish()
}
}

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

@ -1,4 +0,0 @@
#[cfg(feature = "parsing")]
pub mod lookahead {
pub trait Sealed: Copy {}
}

67
third_party/rust/syn-1.0.107/src/span.rs поставляемый
Просмотреть файл

@ -1,67 +0,0 @@
use proc_macro2::Span;
pub trait IntoSpans<S> {
fn into_spans(self) -> S;
}
impl IntoSpans<[Span; 1]> for Span {
fn into_spans(self) -> [Span; 1] {
[self]
}
}
impl IntoSpans<[Span; 2]> for Span {
fn into_spans(self) -> [Span; 2] {
[self, self]
}
}
impl IntoSpans<[Span; 3]> for Span {
fn into_spans(self) -> [Span; 3] {
[self, self, self]
}
}
impl IntoSpans<[Span; 1]> for [Span; 1] {
fn into_spans(self) -> [Span; 1] {
self
}
}
impl IntoSpans<[Span; 2]> for [Span; 2] {
fn into_spans(self) -> [Span; 2] {
self
}
}
impl IntoSpans<[Span; 3]> for [Span; 3] {
fn into_spans(self) -> [Span; 3] {
self
}
}
#[cfg(feature = "parsing")]
pub trait FromSpans: Sized {
fn from_spans(spans: &[Span]) -> Self;
}
#[cfg(feature = "parsing")]
impl FromSpans for [Span; 1] {
fn from_spans(spans: &[Span]) -> Self {
[spans[0]]
}
}
#[cfg(feature = "parsing")]
impl FromSpans for [Span; 2] {
fn from_spans(spans: &[Span]) -> Self {
[spans[0], spans[1]]
}
}
#[cfg(feature = "parsing")]
impl FromSpans for [Span; 3] {
fn from_spans(spans: &[Span]) -> Self {
[spans[0], spans[1], spans[2]]
}
}

114
third_party/rust/syn-1.0.107/src/spanned.rs поставляемый
Просмотреть файл

@ -1,114 +0,0 @@
//! A trait that can provide the `Span` of the complete contents of a syntax
//! tree node.
//!
//! *This module is available only if Syn is built with both the `"parsing"` and
//! `"printing"` features.*
//!
//! <br>
//!
//! # Example
//!
//! Suppose in a procedural macro we have a [`Type`] that we want to assert
//! implements the [`Sync`] trait. Maybe this is the type of one of the fields
//! of a struct for which we are deriving a trait implementation, and we need to
//! be able to pass a reference to one of those fields across threads.
//!
//! [`Type`]: crate::Type
//! [`Sync`]: std::marker::Sync
//!
//! If the field type does *not* implement `Sync` as required, we want the
//! compiler to report an error pointing out exactly which type it was.
//!
//! The following macro code takes a variable `ty` of type `Type` and produces a
//! static assertion that `Sync` is implemented for that type.
//!
//! ```
//! # extern crate proc_macro;
//! #
//! use proc_macro::TokenStream;
//! use proc_macro2::Span;
//! use quote::quote_spanned;
//! use syn::Type;
//! use syn::spanned::Spanned;
//!
//! # const IGNORE_TOKENS: &str = stringify! {
//! #[proc_macro_derive(MyMacro)]
//! # };
//! pub fn my_macro(input: TokenStream) -> TokenStream {
//! # let ty = get_a_type();
//! /* ... */
//!
//! let assert_sync = quote_spanned! {ty.span()=>
//! struct _AssertSync where #ty: Sync;
//! };
//!
//! /* ... */
//! # input
//! }
//! #
//! # fn get_a_type() -> Type {
//! # unimplemented!()
//! # }
//! ```
//!
//! By inserting this `assert_sync` fragment into the output code generated by
//! our macro, the user's code will fail to compile if `ty` does not implement
//! `Sync`. The errors they would see look like the following.
//!
//! ```text
//! error[E0277]: the trait bound `*const i32: std::marker::Sync` is not satisfied
//! --> src/main.rs:10:21
//! |
//! 10 | bad_field: *const i32,
//! | ^^^^^^^^^^ `*const i32` cannot be shared between threads safely
//! ```
//!
//! In this technique, using the `Type`'s span for the error message makes the
//! error appear in the correct place underlining the right type.
//!
//! <br>
//!
//! # Limitations
//!
//! The underlying [`proc_macro::Span::join`] method is nightly-only. When
//! called from within a procedural macro in a nightly compiler, `Spanned` will
//! use `join` to produce the intended span. When not using a nightly compiler,
//! only the span of the *first token* of the syntax tree node is returned.
//!
//! In the common case of wanting to use the joined span as the span of a
//! `syn::Error`, consider instead using [`syn::Error::new_spanned`] which is
//! able to span the error correctly under the complete syntax tree node without
//! needing the unstable `join`.
//!
//! [`syn::Error::new_spanned`]: crate::Error::new_spanned
use proc_macro2::Span;
use quote::spanned::Spanned as ToTokens;
/// A trait that can provide the `Span` of the complete contents of a syntax
/// tree node.
///
/// This trait is automatically implemented for all types that implement
/// [`ToTokens`] from the `quote` crate, as well as for `Span` itself.
///
/// [`ToTokens`]: quote::ToTokens
///
/// See the [module documentation] for an example.
///
/// [module documentation]: self
///
/// *This trait is available only if Syn is built with both the `"parsing"` and
/// `"printing"` features.*
pub trait Spanned {
/// Returns a `Span` covering the complete contents of this syntax tree
/// node, or [`Span::call_site()`] if this node is empty.
///
/// [`Span::call_site()`]: proc_macro2::Span::call_site
fn span(&self) -> Span;
}
impl<T: ?Sized + ToTokens> Spanned for T {
fn span(&self) -> Span {
self.__span()
}
}

349
third_party/rust/syn-1.0.107/src/stmt.rs поставляемый
Просмотреть файл

@ -1,349 +0,0 @@
use super::*;
ast_struct! {
/// A braced block containing Rust statements.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct Block {
pub brace_token: token::Brace,
/// Statements in a block
pub stmts: Vec<Stmt>,
}
}
ast_enum! {
/// A statement, usually ending in a semicolon.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub enum Stmt {
/// A local (let) binding.
Local(Local),
/// An item definition.
Item(Item),
/// Expr without trailing semicolon.
Expr(Expr),
/// Expression with trailing semicolon.
Semi(Expr, Token![;]),
}
}
ast_struct! {
/// A local `let` binding: `let x: u64 = s.parse()?`.
///
/// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct Local {
pub attrs: Vec<Attribute>,
pub let_token: Token![let],
pub pat: Pat,
pub init: Option<(Token![=], Box<Expr>)>,
pub semi_token: Token![;],
}
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use crate::parse::discouraged::Speculative;
use crate::parse::{Parse, ParseBuffer, ParseStream, Result};
use proc_macro2::TokenStream;
impl Block {
/// Parse the body of a block as zero or more statements, possibly
/// including one trailing expression.
///
/// *This function is available only if Syn is built with the `"parsing"`
/// feature.*
///
/// # Example
///
/// ```
/// use syn::{braced, token, Attribute, Block, Ident, Result, Stmt, Token};
/// use syn::parse::{Parse, ParseStream};
///
/// // Parse a function with no generics or parameter list.
/// //
/// // fn playground {
/// // let mut x = 1;
/// // x += 1;
/// // println!("{}", x);
/// // }
/// struct MiniFunction {
/// attrs: Vec<Attribute>,
/// fn_token: Token![fn],
/// name: Ident,
/// brace_token: token::Brace,
/// stmts: Vec<Stmt>,
/// }
///
/// impl Parse for MiniFunction {
/// fn parse(input: ParseStream) -> Result<Self> {
/// let outer_attrs = input.call(Attribute::parse_outer)?;
/// let fn_token: Token![fn] = input.parse()?;
/// let name: Ident = input.parse()?;
///
/// let content;
/// let brace_token = braced!(content in input);
/// let inner_attrs = content.call(Attribute::parse_inner)?;
/// let stmts = content.call(Block::parse_within)?;
///
/// Ok(MiniFunction {
/// attrs: {
/// let mut attrs = outer_attrs;
/// attrs.extend(inner_attrs);
/// attrs
/// },
/// fn_token,
/// name,
/// brace_token,
/// stmts,
/// })
/// }
/// }
/// ```
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
let mut stmts = Vec::new();
loop {
while let Some(semi) = input.parse::<Option<Token![;]>>()? {
stmts.push(Stmt::Semi(Expr::Verbatim(TokenStream::new()), semi));
}
if input.is_empty() {
break;
}
let s = parse_stmt(input, true)?;
let requires_semicolon = if let Stmt::Expr(s) = &s {
expr::requires_terminator(s)
} else {
false
};
stmts.push(s);
if input.is_empty() {
break;
} else if requires_semicolon {
return Err(input.error("unexpected token"));
}
}
Ok(stmts)
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Block {
fn parse(input: ParseStream) -> Result<Self> {
let content;
Ok(Block {
brace_token: braced!(content in input),
stmts: content.call(Block::parse_within)?,
})
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Stmt {
fn parse(input: ParseStream) -> Result<Self> {
parse_stmt(input, false)
}
}
fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
let begin = input.fork();
let mut attrs = input.call(Attribute::parse_outer)?;
// brace-style macros; paren and bracket macros get parsed as
// expression statements.
let ahead = input.fork();
if let Ok(path) = ahead.call(Path::parse_mod_style) {
if ahead.peek(Token![!])
&& (ahead.peek2(token::Brace)
&& !(ahead.peek3(Token![.]) || ahead.peek3(Token![?]))
|| ahead.peek2(Ident))
{
input.advance_to(&ahead);
return stmt_mac(input, attrs, path);
}
}
if input.peek(Token![let]) {
stmt_local(input, attrs, begin)
} else if input.peek(Token![pub])
|| input.peek(Token![crate]) && !input.peek2(Token![::])
|| input.peek(Token![extern])
|| input.peek(Token![use])
|| input.peek(Token![static])
&& (input.peek2(Token![mut])
|| input.peek2(Ident)
&& !(input.peek2(Token![async])
&& (input.peek3(Token![move]) || input.peek3(Token![|]))))
|| input.peek(Token![const]) && !input.peek2(token::Brace)
|| input.peek(Token![unsafe]) && !input.peek2(token::Brace)
|| input.peek(Token![async])
&& (input.peek2(Token![unsafe])
|| input.peek2(Token![extern])
|| input.peek2(Token![fn]))
|| input.peek(Token![fn])
|| input.peek(Token![mod])
|| input.peek(Token![type])
|| input.peek(Token![struct])
|| input.peek(Token![enum])
|| input.peek(Token![union]) && input.peek2(Ident)
|| input.peek(Token![auto]) && input.peek2(Token![trait])
|| input.peek(Token![trait])
|| input.peek(Token![default])
&& (input.peek2(Token![unsafe]) || input.peek2(Token![impl]))
|| input.peek(Token![impl])
|| input.peek(Token![macro])
{
let mut item: Item = input.parse()?;
attrs.extend(item.replace_attrs(Vec::new()));
item.replace_attrs(attrs);
Ok(Stmt::Item(item))
} else {
stmt_expr(input, allow_nosemi, attrs)
}
}
fn stmt_mac(input: ParseStream, attrs: Vec<Attribute>, path: Path) -> Result<Stmt> {
let bang_token: Token![!] = input.parse()?;
let ident: Option<Ident> = input.parse()?;
let (delimiter, tokens) = mac::parse_delimiter(input)?;
let semi_token: Option<Token![;]> = input.parse()?;
Ok(Stmt::Item(Item::Macro(ItemMacro {
attrs,
ident,
mac: Macro {
path,
bang_token,
delimiter,
tokens,
},
semi_token,
})))
}
fn stmt_local(input: ParseStream, attrs: Vec<Attribute>, begin: ParseBuffer) -> Result<Stmt> {
let let_token: Token![let] = input.parse()?;
let mut pat: Pat = pat::parsing::multi_pat_with_leading_vert(input)?;
if input.peek(Token![:]) {
let colon_token: Token![:] = input.parse()?;
let ty: Type = input.parse()?;
pat = Pat::Type(PatType {
attrs: Vec::new(),
pat: Box::new(pat),
colon_token,
ty: Box::new(ty),
});
}
let init = if input.peek(Token![=]) {
let eq_token: Token![=] = input.parse()?;
let init: Expr = input.parse()?;
if input.peek(Token![else]) {
input.parse::<Token![else]>()?;
let content;
braced!(content in input);
content.call(Block::parse_within)?;
let verbatim = Expr::Verbatim(verbatim::between(begin, input));
let semi_token: Token![;] = input.parse()?;
return Ok(Stmt::Semi(verbatim, semi_token));
}
Some((eq_token, Box::new(init)))
} else {
None
};
let semi_token: Token![;] = input.parse()?;
Ok(Stmt::Local(Local {
attrs,
let_token,
pat,
init,
semi_token,
}))
}
fn stmt_expr(
input: ParseStream,
allow_nosemi: bool,
mut attrs: Vec<Attribute>,
) -> Result<Stmt> {
let mut e = expr::parsing::expr_early(input)?;
let mut attr_target = &mut e;
loop {
attr_target = match attr_target {
Expr::Assign(e) => &mut e.left,
Expr::AssignOp(e) => &mut e.left,
Expr::Binary(e) => &mut e.left,
_ => break,
};
}
attrs.extend(attr_target.replace_attrs(Vec::new()));
attr_target.replace_attrs(attrs);
if input.peek(Token![;]) {
return Ok(Stmt::Semi(e, input.parse()?));
}
if allow_nosemi || !expr::requires_terminator(&e) {
Ok(Stmt::Expr(e))
} else {
Err(input.error("expected semicolon"))
}
}
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt};
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for Block {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.brace_token.surround(tokens, |tokens| {
tokens.append_all(&self.stmts);
});
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for Stmt {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
Stmt::Local(local) => local.to_tokens(tokens),
Stmt::Item(item) => item.to_tokens(tokens),
Stmt::Expr(expr) => expr.to_tokens(tokens),
Stmt::Semi(expr, semi) => {
expr.to_tokens(tokens);
semi.to_tokens(tokens);
}
}
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
impl ToTokens for Local {
fn to_tokens(&self, tokens: &mut TokenStream) {
expr::printing::outer_attrs_to_tokens(&self.attrs, tokens);
self.let_token.to_tokens(tokens);
self.pat.to_tokens(tokens);
if let Some((eq_token, init)) = &self.init {
eq_token.to_tokens(tokens);
init.to_tokens(tokens);
}
self.semi_token.to_tokens(tokens);
}
}
}

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

@ -1,41 +0,0 @@
use std::fmt::{self, Debug};
use std::thread::{self, ThreadId};
/// ThreadBound is a Sync-maker and Send-maker that allows accessing a value
/// of type T only from the original thread on which the ThreadBound was
/// constructed.
pub struct ThreadBound<T> {
value: T,
thread_id: ThreadId,
}
unsafe impl<T> Sync for ThreadBound<T> {}
// Send bound requires Copy, as otherwise Drop could run in the wrong place.
unsafe impl<T: Copy> Send for ThreadBound<T> {}
impl<T> ThreadBound<T> {
pub fn new(value: T) -> Self {
ThreadBound {
value,
thread_id: thread::current().id(),
}
}
pub fn get(&self) -> Option<&T> {
if thread::current().id() == self.thread_id {
Some(&self.value)
} else {
None
}
}
}
impl<T: Debug> Debug for ThreadBound<T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self.get() {
Some(value) => Debug::fmt(value, formatter),
None => formatter.write_str("unknown"),
}
}
}

1013
third_party/rust/syn-1.0.107/src/token.rs поставляемый

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

107
third_party/rust/syn-1.0.107/src/tt.rs поставляемый
Просмотреть файл

@ -1,107 +0,0 @@
use proc_macro2::{Delimiter, TokenStream, TokenTree};
use std::hash::{Hash, Hasher};
pub struct TokenTreeHelper<'a>(pub &'a TokenTree);
impl<'a> PartialEq for TokenTreeHelper<'a> {
fn eq(&self, other: &Self) -> bool {
use proc_macro2::Spacing;
match (self.0, other.0) {
(TokenTree::Group(g1), TokenTree::Group(g2)) => {
match (g1.delimiter(), g2.delimiter()) {
(Delimiter::Parenthesis, Delimiter::Parenthesis)
| (Delimiter::Brace, Delimiter::Brace)
| (Delimiter::Bracket, Delimiter::Bracket)
| (Delimiter::None, Delimiter::None) => {}
_ => return false,
}
let s1 = g1.stream().into_iter();
let mut s2 = g2.stream().into_iter();
for item1 in s1 {
let item2 = match s2.next() {
Some(item) => item,
None => return false,
};
if TokenTreeHelper(&item1) != TokenTreeHelper(&item2) {
return false;
}
}
s2.next().is_none()
}
(TokenTree::Punct(o1), TokenTree::Punct(o2)) => {
o1.as_char() == o2.as_char()
&& match (o1.spacing(), o2.spacing()) {
(Spacing::Alone, Spacing::Alone) | (Spacing::Joint, Spacing::Joint) => true,
_ => false,
}
}
(TokenTree::Literal(l1), TokenTree::Literal(l2)) => l1.to_string() == l2.to_string(),
(TokenTree::Ident(s1), TokenTree::Ident(s2)) => s1 == s2,
_ => false,
}
}
}
impl<'a> Hash for TokenTreeHelper<'a> {
fn hash<H: Hasher>(&self, h: &mut H) {
use proc_macro2::Spacing;
match self.0 {
TokenTree::Group(g) => {
0u8.hash(h);
match g.delimiter() {
Delimiter::Parenthesis => 0u8.hash(h),
Delimiter::Brace => 1u8.hash(h),
Delimiter::Bracket => 2u8.hash(h),
Delimiter::None => 3u8.hash(h),
}
for item in g.stream() {
TokenTreeHelper(&item).hash(h);
}
0xffu8.hash(h); // terminator w/ a variant we don't normally hash
}
TokenTree::Punct(op) => {
1u8.hash(h);
op.as_char().hash(h);
match op.spacing() {
Spacing::Alone => 0u8.hash(h),
Spacing::Joint => 1u8.hash(h),
}
}
TokenTree::Literal(lit) => (2u8, lit.to_string()).hash(h),
TokenTree::Ident(word) => (3u8, word).hash(h),
}
}
}
pub struct TokenStreamHelper<'a>(pub &'a TokenStream);
impl<'a> PartialEq for TokenStreamHelper<'a> {
fn eq(&self, other: &Self) -> bool {
let left = self.0.clone().into_iter().collect::<Vec<_>>();
let right = other.0.clone().into_iter().collect::<Vec<_>>();
if left.len() != right.len() {
return false;
}
for (a, b) in left.into_iter().zip(right) {
if TokenTreeHelper(&a) != TokenTreeHelper(&b) {
return false;
}
}
true
}
}
impl<'a> Hash for TokenStreamHelper<'a> {
fn hash<H: Hasher>(&self, state: &mut H) {
let tts = self.0.clone().into_iter().collect::<Vec<_>>();
tts.len().hash(state);
for tt in tts {
TokenTreeHelper(&tt).hash(state);
}
}
}

1304
third_party/rust/syn-1.0.107/src/ty.rs поставляемый

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

33
third_party/rust/syn-1.0.107/src/verbatim.rs поставляемый
Просмотреть файл

@ -1,33 +0,0 @@
use crate::parse::{ParseBuffer, ParseStream};
use proc_macro2::{Delimiter, TokenStream};
use std::cmp::Ordering;
use std::iter;
pub fn between<'a>(begin: ParseBuffer<'a>, end: ParseStream<'a>) -> TokenStream {
let end = end.cursor();
let mut cursor = begin.cursor();
assert!(crate::buffer::same_buffer(end, cursor));
let mut tokens = TokenStream::new();
while cursor != end {
let (tt, next) = cursor.token_tree().unwrap();
if crate::buffer::cmp_assuming_same_buffer(end, next) == Ordering::Less {
// A syntax node can cross the boundary of a None-delimited group
// due to such groups being transparent to the parser in most cases.
// Any time this occurs the group is known to be semantically
// irrelevant. https://github.com/dtolnay/syn/issues/1235
if let Some((inside, _span, after)) = cursor.group(Delimiter::None) {
assert!(next == after);
cursor = inside;
continue;
} else {
panic!("verbatim end must not be inside a delimited group");
}
}
tokens.extend(iter::once(tt));
cursor = next;
}
tokens
}

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

@ -1,65 +0,0 @@
pub fn skip(mut s: &str) -> &str {
'skip: while !s.is_empty() {
let byte = s.as_bytes()[0];
if byte == b'/' {
if s.starts_with("//")
&& (!s.starts_with("///") || s.starts_with("////"))
&& !s.starts_with("//!")
{
if let Some(i) = s.find('\n') {
s = &s[i + 1..];
continue;
} else {
return "";
}
} else if s.starts_with("/**/") {
s = &s[4..];
continue;
} else if s.starts_with("/*")
&& (!s.starts_with("/**") || s.starts_with("/***"))
&& !s.starts_with("/*!")
{
let mut depth = 0;
let bytes = s.as_bytes();
let mut i = 0;
let upper = bytes.len() - 1;
while i < upper {
if bytes[i] == b'/' && bytes[i + 1] == b'*' {
depth += 1;
i += 1; // eat '*'
} else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
depth -= 1;
if depth == 0 {
s = &s[i + 2..];
continue 'skip;
}
i += 1; // eat '/'
}
i += 1;
}
return s;
}
}
match byte {
b' ' | 0x09..=0x0d => {
s = &s[1..];
continue;
}
b if b <= 0x7f => {}
_ => {
let ch = s.chars().next().unwrap();
if is_whitespace(ch) {
s = &s[ch.len_utf8()..];
continue;
}
}
}
return s;
}
s
}
fn is_whitespace(ch: char) -> bool {
// Rust treats left-to-right mark and right-to-left mark as whitespace
ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}'
}

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

@ -1,806 +0,0 @@
#![allow(unused_macro_rules)]
extern crate rustc_ast;
extern crate rustc_data_structures;
extern crate rustc_span;
extern crate thin_vec;
use rustc_ast::ast::AngleBracketedArg;
use rustc_ast::ast::AngleBracketedArgs;
use rustc_ast::ast::AnonConst;
use rustc_ast::ast::Arm;
use rustc_ast::ast::AssocConstraint;
use rustc_ast::ast::AssocConstraintKind;
use rustc_ast::ast::AssocItemKind;
use rustc_ast::ast::Async;
use rustc_ast::ast::AttrArgs;
use rustc_ast::ast::AttrArgsEq;
use rustc_ast::ast::AttrId;
use rustc_ast::ast::AttrItem;
use rustc_ast::ast::AttrKind;
use rustc_ast::ast::AttrStyle;
use rustc_ast::ast::Attribute;
use rustc_ast::ast::BareFnTy;
use rustc_ast::ast::BinOpKind;
use rustc_ast::ast::BindingAnnotation;
use rustc_ast::ast::Block;
use rustc_ast::ast::BlockCheckMode;
use rustc_ast::ast::BorrowKind;
use rustc_ast::ast::ByRef;
use rustc_ast::ast::CaptureBy;
use rustc_ast::ast::Closure;
use rustc_ast::ast::ClosureBinder;
use rustc_ast::ast::Const;
use rustc_ast::ast::Crate;
use rustc_ast::ast::Defaultness;
use rustc_ast::ast::DelimArgs;
use rustc_ast::ast::EnumDef;
use rustc_ast::ast::Expr;
use rustc_ast::ast::ExprField;
use rustc_ast::ast::ExprKind;
use rustc_ast::ast::Extern;
use rustc_ast::ast::FieldDef;
use rustc_ast::ast::FloatTy;
use rustc_ast::ast::Fn;
use rustc_ast::ast::FnDecl;
use rustc_ast::ast::FnHeader;
use rustc_ast::ast::FnRetTy;
use rustc_ast::ast::FnSig;
use rustc_ast::ast::ForeignItemKind;
use rustc_ast::ast::ForeignMod;
use rustc_ast::ast::GenericArg;
use rustc_ast::ast::GenericArgs;
use rustc_ast::ast::GenericBound;
use rustc_ast::ast::GenericParam;
use rustc_ast::ast::GenericParamKind;
use rustc_ast::ast::Generics;
use rustc_ast::ast::Impl;
use rustc_ast::ast::ImplPolarity;
use rustc_ast::ast::Inline;
use rustc_ast::ast::InlineAsm;
use rustc_ast::ast::InlineAsmOperand;
use rustc_ast::ast::InlineAsmOptions;
use rustc_ast::ast::InlineAsmRegOrRegClass;
use rustc_ast::ast::InlineAsmSym;
use rustc_ast::ast::InlineAsmTemplatePiece;
use rustc_ast::ast::IntTy;
use rustc_ast::ast::IsAuto;
use rustc_ast::ast::Item;
use rustc_ast::ast::ItemKind;
use rustc_ast::ast::Label;
use rustc_ast::ast::Lifetime;
use rustc_ast::ast::LitFloatType;
use rustc_ast::ast::LitIntType;
use rustc_ast::ast::LitKind;
use rustc_ast::ast::Local;
use rustc_ast::ast::LocalKind;
use rustc_ast::ast::MacCall;
use rustc_ast::ast::MacCallStmt;
use rustc_ast::ast::MacDelimiter;
use rustc_ast::ast::MacStmtStyle;
use rustc_ast::ast::MacroDef;
use rustc_ast::ast::MetaItemLit;
use rustc_ast::ast::MethodCall;
use rustc_ast::ast::ModKind;
use rustc_ast::ast::ModSpans;
use rustc_ast::ast::Movability;
use rustc_ast::ast::MutTy;
use rustc_ast::ast::Mutability;
use rustc_ast::ast::NodeId;
use rustc_ast::ast::NormalAttr;
use rustc_ast::ast::Param;
use rustc_ast::ast::ParenthesizedArgs;
use rustc_ast::ast::Pat;
use rustc_ast::ast::PatField;
use rustc_ast::ast::PatKind;
use rustc_ast::ast::Path;
use rustc_ast::ast::PathSegment;
use rustc_ast::ast::PolyTraitRef;
use rustc_ast::ast::QSelf;
use rustc_ast::ast::RangeEnd;
use rustc_ast::ast::RangeLimits;
use rustc_ast::ast::RangeSyntax;
use rustc_ast::ast::Stmt;
use rustc_ast::ast::StmtKind;
use rustc_ast::ast::StrLit;
use rustc_ast::ast::StrStyle;
use rustc_ast::ast::StructExpr;
use rustc_ast::ast::StructRest;
use rustc_ast::ast::Term;
use rustc_ast::ast::Trait;
use rustc_ast::ast::TraitBoundModifier;
use rustc_ast::ast::TraitObjectSyntax;
use rustc_ast::ast::TraitRef;
use rustc_ast::ast::Ty;
use rustc_ast::ast::TyAlias;
use rustc_ast::ast::TyAliasWhereClause;
use rustc_ast::ast::TyKind;
use rustc_ast::ast::UintTy;
use rustc_ast::ast::UnOp;
use rustc_ast::ast::Unsafe;
use rustc_ast::ast::UnsafeSource;
use rustc_ast::ast::UseTree;
use rustc_ast::ast::UseTreeKind;
use rustc_ast::ast::Variant;
use rustc_ast::ast::VariantData;
use rustc_ast::ast::Visibility;
use rustc_ast::ast::VisibilityKind;
use rustc_ast::ast::WhereBoundPredicate;
use rustc_ast::ast::WhereClause;
use rustc_ast::ast::WhereEqPredicate;
use rustc_ast::ast::WherePredicate;
use rustc_ast::ast::WhereRegionPredicate;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, CommentKind, Delimiter, Lit, Nonterminal, Token, TokenKind};
use rustc_ast::tokenstream::{
AttrTokenStream, AttrTokenTree, AttributesData, DelimSpan, LazyAttrTokenStream, Spacing,
TokenStream, TokenTree,
};
use rustc_data_structures::sync::Lrc;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{sym, Ident};
use rustc_span::{Span, Symbol, SyntaxContext, DUMMY_SP};
use thin_vec::ThinVec;
pub trait SpanlessEq {
fn eq(&self, other: &Self) -> bool;
}
impl<T: ?Sized + SpanlessEq> SpanlessEq for Box<T> {
fn eq(&self, other: &Self) -> bool {
SpanlessEq::eq(&**self, &**other)
}
}
impl<T: ?Sized + SpanlessEq> SpanlessEq for P<T> {
fn eq(&self, other: &Self) -> bool {
SpanlessEq::eq(&**self, &**other)
}
}
impl<T: ?Sized + SpanlessEq> SpanlessEq for Lrc<T> {
fn eq(&self, other: &Self) -> bool {
SpanlessEq::eq(&**self, &**other)
}
}
impl<T: SpanlessEq> SpanlessEq for Option<T> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(None, None) => true,
(Some(this), Some(other)) => SpanlessEq::eq(this, other),
_ => false,
}
}
}
impl<T: SpanlessEq> SpanlessEq for [T] {
fn eq(&self, other: &Self) -> bool {
self.len() == other.len() && self.iter().zip(other).all(|(a, b)| SpanlessEq::eq(a, b))
}
}
impl<T: SpanlessEq> SpanlessEq for Vec<T> {
fn eq(&self, other: &Self) -> bool {
<[T] as SpanlessEq>::eq(self, other)
}
}
impl<T: SpanlessEq> SpanlessEq for ThinVec<T> {
fn eq(&self, other: &Self) -> bool {
self.len() == other.len()
&& self
.iter()
.zip(other.iter())
.all(|(a, b)| SpanlessEq::eq(a, b))
}
}
impl<T: SpanlessEq> SpanlessEq for Spanned<T> {
fn eq(&self, other: &Self) -> bool {
SpanlessEq::eq(&self.node, &other.node)
}
}
impl<A: SpanlessEq, B: SpanlessEq> SpanlessEq for (A, B) {
fn eq(&self, other: &Self) -> bool {
SpanlessEq::eq(&self.0, &other.0) && SpanlessEq::eq(&self.1, &other.1)
}
}
impl<A: SpanlessEq, B: SpanlessEq, C: SpanlessEq> SpanlessEq for (A, B, C) {
fn eq(&self, other: &Self) -> bool {
SpanlessEq::eq(&self.0, &other.0)
&& SpanlessEq::eq(&self.1, &other.1)
&& SpanlessEq::eq(&self.2, &other.2)
}
}
macro_rules! spanless_eq_true {
($name:ty) => {
impl SpanlessEq for $name {
fn eq(&self, _other: &Self) -> bool {
true
}
}
};
}
spanless_eq_true!(Span);
spanless_eq_true!(DelimSpan);
spanless_eq_true!(AttrId);
spanless_eq_true!(NodeId);
spanless_eq_true!(SyntaxContext);
spanless_eq_true!(Spacing);
macro_rules! spanless_eq_partial_eq {
($name:ty) => {
impl SpanlessEq for $name {
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(self, other)
}
}
};
}
spanless_eq_partial_eq!(bool);
spanless_eq_partial_eq!(u8);
spanless_eq_partial_eq!(u16);
spanless_eq_partial_eq!(u128);
spanless_eq_partial_eq!(usize);
spanless_eq_partial_eq!(char);
spanless_eq_partial_eq!(String);
spanless_eq_partial_eq!(Symbol);
spanless_eq_partial_eq!(CommentKind);
spanless_eq_partial_eq!(Delimiter);
spanless_eq_partial_eq!(InlineAsmOptions);
spanless_eq_partial_eq!(token::LitKind);
macro_rules! spanless_eq_struct {
{
$($name:ident)::+ $(<$param:ident>)?
$([$field:tt $this:ident $other:ident])*
$(![$ignore:tt])*;
} => {
impl $(<$param: SpanlessEq>)* SpanlessEq for $($name)::+ $(<$param>)* {
fn eq(&self, other: &Self) -> bool {
let $($name)::+ { $($field: $this,)* $($ignore: _,)* } = self;
let $($name)::+ { $($field: $other,)* $($ignore: _,)* } = other;
true $(&& SpanlessEq::eq($this, $other))*
}
}
};
{
$($name:ident)::+ $(<$param:ident>)?
$([$field:tt $this:ident $other:ident])*
$(![$ignore:tt])*;
!$next:tt
$($rest:tt)*
} => {
spanless_eq_struct! {
$($name)::+ $(<$param>)*
$([$field $this $other])*
$(![$ignore])*
![$next];
$($rest)*
}
};
{
$($name:ident)::+ $(<$param:ident>)?
$([$field:tt $this:ident $other:ident])*
$(![$ignore:tt])*;
$next:tt
$($rest:tt)*
} => {
spanless_eq_struct! {
$($name)::+ $(<$param>)*
$([$field $this $other])*
[$next this other]
$(![$ignore])*;
$($rest)*
}
};
}
macro_rules! spanless_eq_enum {
{
$($name:ident)::+;
$([$($variant:ident)::+; $([$field:tt $this:ident $other:ident])* $(![$ignore:tt])*])*
} => {
impl SpanlessEq for $($name)::+ {
fn eq(&self, other: &Self) -> bool {
match self {
$(
$($variant)::+ { .. } => {}
)*
}
#[allow(unreachable_patterns)]
match (self, other) {
$(
(
$($variant)::+ { $($field: $this,)* $($ignore: _,)* },
$($variant)::+ { $($field: $other,)* $($ignore: _,)* },
) => {
true $(&& SpanlessEq::eq($this, $other))*
}
)*
_ => false,
}
}
}
};
{
$($name:ident)::+;
$([$($variant:ident)::+; $($fields:tt)*])*
$next:ident [$([$($named:tt)*])* $(![$ignore:tt])*] (!$i:tt $($field:tt)*)
$($rest:tt)*
} => {
spanless_eq_enum! {
$($name)::+;
$([$($variant)::+; $($fields)*])*
$next [$([$($named)*])* $(![$ignore])* ![$i]] ($($field)*)
$($rest)*
}
};
{
$($name:ident)::+;
$([$($variant:ident)::+; $($fields:tt)*])*
$next:ident [$([$($named:tt)*])* $(![$ignore:tt])*] ($i:tt $($field:tt)*)
$($rest:tt)*
} => {
spanless_eq_enum! {
$($name)::+;
$([$($variant)::+; $($fields)*])*
$next [$([$($named)*])* [$i this other] $(![$ignore])*] ($($field)*)
$($rest)*
}
};
{
$($name:ident)::+;
$([$($variant:ident)::+; $($fields:tt)*])*
$next:ident [$($named:tt)*] ()
$($rest:tt)*
} => {
spanless_eq_enum! {
$($name)::+;
$([$($variant)::+; $($fields)*])*
[$($name)::+::$next; $($named)*]
$($rest)*
}
};
{
$($name:ident)::+;
$([$($variant:ident)::+; $($fields:tt)*])*
$next:ident ($($field:tt)*)
$($rest:tt)*
} => {
spanless_eq_enum! {
$($name)::+;
$([$($variant)::+; $($fields)*])*
$next [] ($($field)*)
$($rest)*
}
};
{
$($name:ident)::+;
$([$($variant:ident)::+; $($fields:tt)*])*
$next:ident
$($rest:tt)*
} => {
spanless_eq_enum! {
$($name)::+;
$([$($variant)::+; $($fields)*])*
[$($name)::+::$next;]
$($rest)*
}
};
}
spanless_eq_struct!(AngleBracketedArgs; span args);
spanless_eq_struct!(AnonConst; id value);
spanless_eq_struct!(Arm; attrs pat guard body span id is_placeholder);
spanless_eq_struct!(AssocConstraint; id ident gen_args kind span);
spanless_eq_struct!(AttrItem; path args tokens);
spanless_eq_struct!(AttrTokenStream; 0);
spanless_eq_struct!(Attribute; kind id style span);
spanless_eq_struct!(AttributesData; attrs tokens);
spanless_eq_struct!(BareFnTy; unsafety ext generic_params decl decl_span);
spanless_eq_struct!(BindingAnnotation; 0 1);
spanless_eq_struct!(Block; stmts id rules span tokens could_be_bare_literal);
spanless_eq_struct!(Closure; binder capture_clause asyncness movability fn_decl body !fn_decl_span);
spanless_eq_struct!(Crate; attrs items spans id is_placeholder);
spanless_eq_struct!(DelimArgs; dspan delim tokens);
spanless_eq_struct!(EnumDef; variants);
spanless_eq_struct!(Expr; id kind span attrs !tokens);
spanless_eq_struct!(ExprField; attrs id span ident expr is_shorthand is_placeholder);
spanless_eq_struct!(FieldDef; attrs id span vis ident ty is_placeholder);
spanless_eq_struct!(FnDecl; inputs output);
spanless_eq_struct!(FnHeader; constness asyncness unsafety ext);
spanless_eq_struct!(Fn; defaultness generics sig body);
spanless_eq_struct!(FnSig; header decl span);
spanless_eq_struct!(ForeignMod; unsafety abi items);
spanless_eq_struct!(GenericParam; id ident attrs bounds is_placeholder kind !colon_span);
spanless_eq_struct!(Generics; params where_clause span);
spanless_eq_struct!(Impl; defaultness unsafety generics constness polarity of_trait self_ty items);
spanless_eq_struct!(InlineAsm; template template_strs operands clobber_abis options line_spans);
spanless_eq_struct!(InlineAsmSym; id qself path);
spanless_eq_struct!(Item<K>; attrs id span vis ident kind !tokens);
spanless_eq_struct!(Label; ident);
spanless_eq_struct!(Lifetime; id ident);
spanless_eq_struct!(Lit; kind symbol suffix);
spanless_eq_struct!(Local; pat ty kind id span attrs !tokens);
spanless_eq_struct!(MacCall; path args prior_type_ascription);
spanless_eq_struct!(MacCallStmt; mac style attrs tokens);
spanless_eq_struct!(MacroDef; body macro_rules);
spanless_eq_struct!(MetaItemLit; token_lit kind span);
spanless_eq_struct!(MethodCall; seg receiver args !span);
spanless_eq_struct!(ModSpans; !inner_span !inject_use_span);
spanless_eq_struct!(MutTy; ty mutbl);
spanless_eq_struct!(NormalAttr; item tokens);
spanless_eq_struct!(ParenthesizedArgs; span inputs inputs_span output);
spanless_eq_struct!(Pat; id kind span tokens);
spanless_eq_struct!(PatField; ident pat is_shorthand attrs id span is_placeholder);
spanless_eq_struct!(Path; span segments tokens);
spanless_eq_struct!(PathSegment; ident id args);
spanless_eq_struct!(PolyTraitRef; bound_generic_params trait_ref span);
spanless_eq_struct!(QSelf; ty path_span position);
spanless_eq_struct!(Stmt; id kind span);
spanless_eq_struct!(StrLit; style symbol suffix span symbol_unescaped);
spanless_eq_struct!(StructExpr; qself path fields rest);
spanless_eq_struct!(Token; kind span);
spanless_eq_struct!(Trait; unsafety is_auto generics bounds items);
spanless_eq_struct!(TraitRef; path ref_id);
spanless_eq_struct!(Ty; id kind span tokens);
spanless_eq_struct!(TyAlias; defaultness generics where_clauses !where_predicates_split bounds ty);
spanless_eq_struct!(TyAliasWhereClause; !0 1);
spanless_eq_struct!(UseTree; prefix kind span);
spanless_eq_struct!(Variant; attrs id span !vis ident data disr_expr is_placeholder);
spanless_eq_struct!(Visibility; kind span tokens);
spanless_eq_struct!(WhereBoundPredicate; span bound_generic_params bounded_ty bounds);
spanless_eq_struct!(WhereClause; has_where_token predicates span);
spanless_eq_struct!(WhereEqPredicate; span lhs_ty rhs_ty);
spanless_eq_struct!(WhereRegionPredicate; span lifetime bounds);
spanless_eq_enum!(AngleBracketedArg; Arg(0) Constraint(0));
spanless_eq_enum!(AssocItemKind; Const(0 1 2) Fn(0) Type(0) MacCall(0));
spanless_eq_enum!(AssocConstraintKind; Equality(term) Bound(bounds));
spanless_eq_enum!(Async; Yes(span closure_id return_impl_trait_id) No);
spanless_eq_enum!(AttrArgs; Empty Delimited(0) Eq(0 1));
spanless_eq_enum!(AttrArgsEq; Ast(0) Hir(0));
spanless_eq_enum!(AttrStyle; Outer Inner);
spanless_eq_enum!(AttrTokenTree; Token(0 1) Delimited(0 1 2) Attributes(0));
spanless_eq_enum!(BinOpKind; Add Sub Mul Div Rem And Or BitXor BitAnd BitOr Shl Shr Eq Lt Le Ne Ge Gt);
spanless_eq_enum!(BlockCheckMode; Default Unsafe(0));
spanless_eq_enum!(BorrowKind; Ref Raw);
spanless_eq_enum!(ByRef; Yes No);
spanless_eq_enum!(CaptureBy; Value Ref);
spanless_eq_enum!(ClosureBinder; NotPresent For(span generic_params));
spanless_eq_enum!(Const; Yes(0) No);
spanless_eq_enum!(Defaultness; Default(0) Final);
spanless_eq_enum!(Extern; None Implicit(0) Explicit(0 1));
spanless_eq_enum!(FloatTy; F32 F64);
spanless_eq_enum!(FnRetTy; Default(0) Ty(0));
spanless_eq_enum!(ForeignItemKind; Static(0 1 2) Fn(0) TyAlias(0) MacCall(0));
spanless_eq_enum!(GenericArg; Lifetime(0) Type(0) Const(0));
spanless_eq_enum!(GenericArgs; AngleBracketed(0) Parenthesized(0));
spanless_eq_enum!(GenericBound; Trait(0 1) Outlives(0));
spanless_eq_enum!(GenericParamKind; Lifetime Type(default) Const(ty kw_span default));
spanless_eq_enum!(ImplPolarity; Positive Negative(0));
spanless_eq_enum!(Inline; Yes No);
spanless_eq_enum!(InlineAsmRegOrRegClass; Reg(0) RegClass(0));
spanless_eq_enum!(InlineAsmTemplatePiece; String(0) Placeholder(operand_idx modifier span));
spanless_eq_enum!(IntTy; Isize I8 I16 I32 I64 I128);
spanless_eq_enum!(IsAuto; Yes No);
spanless_eq_enum!(LitFloatType; Suffixed(0) Unsuffixed);
spanless_eq_enum!(LitIntType; Signed(0) Unsigned(0) Unsuffixed);
spanless_eq_enum!(LocalKind; Decl Init(0) InitElse(0 1));
spanless_eq_enum!(MacDelimiter; Parenthesis Bracket Brace);
spanless_eq_enum!(MacStmtStyle; Semicolon Braces NoBraces);
spanless_eq_enum!(ModKind; Loaded(0 1 2) Unloaded);
spanless_eq_enum!(Movability; Static Movable);
spanless_eq_enum!(Mutability; Mut Not);
spanless_eq_enum!(RangeEnd; Included(0) Excluded);
spanless_eq_enum!(RangeLimits; HalfOpen Closed);
spanless_eq_enum!(StmtKind; Local(0) Item(0) Expr(0) Semi(0) Empty MacCall(0));
spanless_eq_enum!(StrStyle; Cooked Raw(0));
spanless_eq_enum!(StructRest; Base(0) Rest(0) None);
spanless_eq_enum!(Term; Ty(0) Const(0));
spanless_eq_enum!(TokenTree; Token(0 1) Delimited(0 1 2));
spanless_eq_enum!(TraitBoundModifier; None Maybe MaybeConst MaybeConstMaybe);
spanless_eq_enum!(TraitObjectSyntax; Dyn DynStar None);
spanless_eq_enum!(UintTy; Usize U8 U16 U32 U64 U128);
spanless_eq_enum!(UnOp; Deref Not Neg);
spanless_eq_enum!(Unsafe; Yes(0) No);
spanless_eq_enum!(UnsafeSource; CompilerGenerated UserProvided);
spanless_eq_enum!(UseTreeKind; Simple(0) Nested(0) Glob);
spanless_eq_enum!(VariantData; Struct(0 1) Tuple(0 1) Unit(0));
spanless_eq_enum!(VisibilityKind; Public Restricted(path id shorthand) Inherited);
spanless_eq_enum!(WherePredicate; BoundPredicate(0) RegionPredicate(0) EqPredicate(0));
spanless_eq_enum!(ExprKind; Box(0) Array(0) ConstBlock(0) Call(0 1)
MethodCall(0) Tup(0) Binary(0 1 2) Unary(0 1) Lit(0) Cast(0 1) Type(0 1)
Let(0 1 2) If(0 1 2) While(0 1 2) ForLoop(0 1 2 3) Loop(0 1 2) Match(0 1)
Closure(0) Block(0 1) Async(0 1 2) Await(0) TryBlock(0) Assign(0 1 2)
AssignOp(0 1 2) Field(0 1) Index(0 1) Underscore Range(0 1 2) Path(0 1)
AddrOf(0 1 2) Break(0 1) Continue(0) Ret(0) InlineAsm(0) MacCall(0)
Struct(0) Repeat(0 1) Paren(0) Try(0) Yield(0) Yeet(0) IncludedBytes(0)
Err);
spanless_eq_enum!(InlineAsmOperand; In(reg expr) Out(reg late expr)
InOut(reg late expr) SplitInOut(reg late in_expr out_expr) Const(anon_const)
Sym(sym));
spanless_eq_enum!(ItemKind; ExternCrate(0) Use(0) Static(0 1 2) Const(0 1 2)
Fn(0) Mod(0 1) ForeignMod(0) GlobalAsm(0) TyAlias(0) Enum(0 1) Struct(0 1)
Union(0 1) Trait(0) TraitAlias(0 1) Impl(0) MacCall(0) MacroDef(0));
spanless_eq_enum!(LitKind; Str(0 1) ByteStr(0) Byte(0) Char(0) Int(0 1)
Float(0 1) Bool(0) Err);
spanless_eq_enum!(PatKind; Wild Ident(0 1 2) Struct(0 1 2 3) TupleStruct(0 1 2)
Or(0) Path(0 1) Tuple(0) Box(0) Ref(0 1) Lit(0) Range(0 1 2) Slice(0) Rest
Paren(0) MacCall(0));
spanless_eq_enum!(TyKind; Slice(0) Array(0 1) Ptr(0) Rptr(0 1) BareFn(0) Never
Tup(0) Path(0 1) TraitObject(0 1) ImplTrait(0 1) Paren(0) Typeof(0) Infer
ImplicitSelf MacCall(0) Err CVarArgs);
impl SpanlessEq for Ident {
fn eq(&self, other: &Self) -> bool {
self.as_str() == other.as_str()
}
}
impl SpanlessEq for RangeSyntax {
fn eq(&self, _other: &Self) -> bool {
match self {
RangeSyntax::DotDotDot | RangeSyntax::DotDotEq => true,
}
}
}
impl SpanlessEq for Param {
fn eq(&self, other: &Self) -> bool {
let Param {
attrs,
ty,
pat,
id,
span: _,
is_placeholder,
} = self;
let Param {
attrs: attrs2,
ty: ty2,
pat: pat2,
id: id2,
span: _,
is_placeholder: is_placeholder2,
} = other;
SpanlessEq::eq(id, id2)
&& SpanlessEq::eq(is_placeholder, is_placeholder2)
&& (matches!(ty.kind, TyKind::Err)
|| matches!(ty2.kind, TyKind::Err)
|| SpanlessEq::eq(attrs, attrs2)
&& SpanlessEq::eq(ty, ty2)
&& SpanlessEq::eq(pat, pat2))
}
}
impl SpanlessEq for TokenKind {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(TokenKind::Literal(this), TokenKind::Literal(other)) => SpanlessEq::eq(this, other),
(TokenKind::DotDotEq, _) | (TokenKind::DotDotDot, _) => match other {
TokenKind::DotDotEq | TokenKind::DotDotDot => true,
_ => false,
},
(TokenKind::Interpolated(this), TokenKind::Interpolated(other)) => {
match (this.as_ref(), other.as_ref()) {
(Nonterminal::NtExpr(this), Nonterminal::NtExpr(other)) => {
SpanlessEq::eq(this, other)
}
_ => this == other,
}
}
_ => self == other,
}
}
}
impl SpanlessEq for TokenStream {
fn eq(&self, other: &Self) -> bool {
let mut this_trees = self.trees();
let mut other_trees = other.trees();
loop {
let this = match this_trees.next() {
None => return other_trees.next().is_none(),
Some(tree) => tree,
};
let other = match other_trees.next() {
None => return false,
Some(tree) => tree,
};
if SpanlessEq::eq(this, other) {
continue;
}
if let (TokenTree::Token(this, _), TokenTree::Token(other, _)) = (this, other) {
if match (&this.kind, &other.kind) {
(TokenKind::Literal(this), TokenKind::Literal(other)) => {
SpanlessEq::eq(this, other)
}
(TokenKind::DocComment(_kind, style, symbol), TokenKind::Pound) => {
doc_comment(*style, *symbol, &mut other_trees)
}
(TokenKind::Pound, TokenKind::DocComment(_kind, style, symbol)) => {
doc_comment(*style, *symbol, &mut this_trees)
}
_ => false,
} {
continue;
}
}
return false;
}
}
}
fn doc_comment<'a>(
style: AttrStyle,
unescaped: Symbol,
trees: &mut impl Iterator<Item = &'a TokenTree>,
) -> bool {
if match style {
AttrStyle::Outer => false,
AttrStyle::Inner => true,
} {
match trees.next() {
Some(TokenTree::Token(
Token {
kind: TokenKind::Not,
span: _,
},
_spacing,
)) => {}
_ => return false,
}
}
let stream = match trees.next() {
Some(TokenTree::Delimited(_span, Delimiter::Bracket, stream)) => stream,
_ => return false,
};
let mut trees = stream.trees();
match trees.next() {
Some(TokenTree::Token(
Token {
kind: TokenKind::Ident(symbol, false),
span: _,
},
_spacing,
)) if *symbol == sym::doc => {}
_ => return false,
}
match trees.next() {
Some(TokenTree::Token(
Token {
kind: TokenKind::Eq,
span: _,
},
_spacing,
)) => {}
_ => return false,
}
match trees.next() {
Some(TokenTree::Token(token, _spacing)) => {
is_escaped_literal_token(token, unescaped) && trees.next().is_none()
}
_ => false,
}
}
fn is_escaped_literal_token(token: &Token, unescaped: Symbol) -> bool {
match token {
Token {
kind: TokenKind::Literal(lit),
span: _,
} => match MetaItemLit::from_token_lit(*lit, DUMMY_SP) {
Ok(lit) => is_escaped_literal_meta_item_lit(&lit, unescaped),
Err(_) => false,
},
Token {
kind: TokenKind::Interpolated(nonterminal),
span: _,
} => match nonterminal.as_ref() {
Nonterminal::NtExpr(expr) => match &expr.kind {
ExprKind::Lit(lit) => is_escaped_lit(lit, unescaped),
_ => false,
},
_ => false,
},
_ => false,
}
}
fn is_escaped_literal_attr_args(value: &AttrArgsEq, unescaped: Symbol) -> bool {
match value {
AttrArgsEq::Ast(expr) => match &expr.kind {
ExprKind::Lit(lit) => is_escaped_lit(lit, unescaped),
_ => false,
},
AttrArgsEq::Hir(lit) => is_escaped_literal_meta_item_lit(lit, unescaped),
}
}
fn is_escaped_literal_meta_item_lit(lit: &MetaItemLit, unescaped: Symbol) -> bool {
match lit {
MetaItemLit {
token_lit:
Lit {
kind: token::LitKind::Str,
symbol: _,
suffix: None,
},
kind,
span: _,
} => is_escaped_lit_kind(kind, unescaped),
_ => false,
}
}
fn is_escaped_lit(lit: &Lit, unescaped: Symbol) -> bool {
match lit {
Lit {
kind: token::LitKind::Str,
symbol: _,
suffix: None,
} => match LitKind::from_token_lit(*lit) {
Ok(lit_kind) => is_escaped_lit_kind(&lit_kind, unescaped),
_ => false,
},
_ => false,
}
}
fn is_escaped_lit_kind(kind: &LitKind, unescaped: Symbol) -> bool {
match kind {
LitKind::Str(symbol, StrStyle::Cooked) => {
symbol.as_str().replace('\r', "") == unescaped.as_str().replace('\r', "")
}
_ => false,
}
}
impl SpanlessEq for LazyAttrTokenStream {
fn eq(&self, other: &Self) -> bool {
let this = self.to_attr_token_stream();
let other = other.to_attr_token_stream();
SpanlessEq::eq(&this, &other)
}
}
impl SpanlessEq for AttrKind {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(AttrKind::Normal(normal), AttrKind::Normal(normal2)) => {
SpanlessEq::eq(normal, normal2)
}
(AttrKind::DocComment(kind, symbol), AttrKind::DocComment(kind2, symbol2)) => {
SpanlessEq::eq(kind, kind2) && SpanlessEq::eq(symbol, symbol2)
}
(AttrKind::DocComment(kind, unescaped), AttrKind::Normal(normal2)) => {
match kind {
CommentKind::Line | CommentKind::Block => {}
}
let path = Path::from_ident(Ident::with_dummy_span(sym::doc));
SpanlessEq::eq(&path, &normal2.item.path)
&& match &normal2.item.args {
AttrArgs::Empty | AttrArgs::Delimited(_) => false,
AttrArgs::Eq(_span, value) => {
is_escaped_literal_attr_args(value, *unescaped)
}
}
}
(AttrKind::Normal(_), AttrKind::DocComment(..)) => SpanlessEq::eq(other, self),
}
}
}

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

@ -1,28 +0,0 @@
#![allow(dead_code)]
#![allow(clippy::module_name_repetitions, clippy::shadow_unrelated)]
use rayon::ThreadPoolBuilder;
use std::env;
pub mod eq;
pub mod parse;
/// Read the `ABORT_AFTER_FAILURE` environment variable, and parse it.
pub fn abort_after() -> usize {
match env::var("ABORT_AFTER_FAILURE") {
Ok(s) => s.parse().expect("failed to parse ABORT_AFTER_FAILURE"),
Err(_) => usize::max_value(),
}
}
/// Configure Rayon threadpool.
pub fn rayon_init() {
let stack_size = match env::var("RUST_MIN_STACK") {
Ok(s) => s.parse().expect("failed to parse RUST_MIN_STACK"),
Err(_) => 20 * 1024 * 1024,
};
ThreadPoolBuilder::new()
.stack_size(stack_size)
.build_global()
.unwrap();
}

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

@ -1,48 +0,0 @@
extern crate rustc_ast;
extern crate rustc_expand;
extern crate rustc_parse as parse;
extern crate rustc_session;
extern crate rustc_span;
use rustc_ast::ast;
use rustc_ast::ptr::P;
use rustc_session::parse::ParseSess;
use rustc_span::source_map::FilePathMapping;
use rustc_span::FileName;
use std::panic;
pub fn librustc_expr(input: &str) -> Option<P<ast::Expr>> {
match panic::catch_unwind(|| {
let sess = ParseSess::new(FilePathMapping::empty());
let e = parse::new_parser_from_source_str(
&sess,
FileName::Custom("test_precedence".to_string()),
input.to_string(),
)
.parse_expr();
match e {
Ok(expr) => Some(expr),
Err(mut diagnostic) => {
diagnostic.emit();
None
}
}
}) {
Ok(Some(e)) => Some(e),
Ok(None) => None,
Err(_) => {
errorf!("librustc panicked\n");
None
}
}
}
pub fn syn_expr(input: &str) -> Option<syn::Expr> {
match syn::parse_str(input) {
Ok(e) => Some(e),
Err(msg) => {
errorf!("syn failed to parse\n{:?}\n", msg);
None
}
}
}

5640
third_party/rust/syn-1.0.107/tests/debug/gen.rs поставляемый

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

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

@ -1,125 +0,0 @@
#![allow(
clippy::no_effect_underscore_binding,
clippy::too_many_lines,
clippy::used_underscore_binding
)]
#[rustfmt::skip]
mod gen;
use proc_macro2::{Ident, Literal, TokenStream};
use ref_cast::RefCast;
use std::fmt::{self, Debug};
use std::ops::Deref;
use syn::punctuated::Punctuated;
#[derive(RefCast)]
#[repr(transparent)]
pub struct Lite<T: ?Sized> {
value: T,
}
#[allow(non_snake_case)]
pub fn Lite<T: ?Sized>(value: &T) -> &Lite<T> {
Lite::ref_cast(value)
}
impl<T: ?Sized> Deref for Lite<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl Debug for Lite<bool> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{}", self.value)
}
}
impl Debug for Lite<u32> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{}", self.value)
}
}
impl Debug for Lite<usize> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{}", self.value)
}
}
impl Debug for Lite<String> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{:?}", self.value)
}
}
impl Debug for Lite<Ident> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{:?}", self.value.to_string())
}
}
impl Debug for Lite<Literal> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{}", self.value)
}
}
impl Debug for Lite<TokenStream> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let string = self.value.to_string();
if string.len() <= 80 {
write!(formatter, "TokenStream(`{}`)", self.value)
} else {
formatter
.debug_tuple("TokenStream")
.field(&format_args!("`{}`", string))
.finish()
}
}
}
impl<'a, T> Debug for Lite<&'a T>
where
Lite<T>: Debug,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(Lite(self.value), formatter)
}
}
impl<T> Debug for Lite<Box<T>>
where
Lite<T>: Debug,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(Lite(&*self.value), formatter)
}
}
impl<T> Debug for Lite<Vec<T>>
where
Lite<T>: Debug,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
.debug_list()
.entries(self.value.iter().map(Lite))
.finish()
}
}
impl<T, P> Debug for Lite<Punctuated<T, P>>
where
Lite<T>: Debug,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
.debug_list()
.entries(self.value.iter().map(Lite))
.finish()
}
}

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

@ -1,79 +0,0 @@
#![allow(unused_macros, unused_macro_rules)]
#[path = "../debug/mod.rs"]
pub mod debug;
use syn::parse::{Parse, Result};
macro_rules! errorf {
($($tt:tt)*) => {{
use ::std::io::Write;
let stderr = ::std::io::stderr();
write!(stderr.lock(), $($tt)*).unwrap();
}};
}
macro_rules! punctuated {
($($e:expr,)+) => {{
let mut seq = ::syn::punctuated::Punctuated::new();
$(
seq.push($e);
)+
seq
}};
($($e:expr),+) => {
punctuated!($($e,)+)
};
}
macro_rules! snapshot {
($($args:tt)*) => {
snapshot_impl!(() $($args)*)
};
}
macro_rules! snapshot_impl {
(($expr:ident) as $t:ty, @$snapshot:literal) => {
let $expr = crate::macros::Tokens::parse::<$t>($expr).unwrap();
let debug = crate::macros::debug::Lite(&$expr);
if !cfg!(miri) {
insta::assert_debug_snapshot!(debug, @$snapshot);
}
};
(($($expr:tt)*) as $t:ty, @$snapshot:literal) => {{
let syntax_tree = crate::macros::Tokens::parse::<$t>($($expr)*).unwrap();
let debug = crate::macros::debug::Lite(&syntax_tree);
if !cfg!(miri) {
insta::assert_debug_snapshot!(debug, @$snapshot);
}
syntax_tree
}};
(($($expr:tt)*) , @$snapshot:literal) => {{
let syntax_tree = $($expr)*;
let debug = crate::macros::debug::Lite(&syntax_tree);
if !cfg!(miri) {
insta::assert_debug_snapshot!(debug, @$snapshot);
}
syntax_tree
}};
(($($expr:tt)*) $next:tt $($rest:tt)*) => {
snapshot_impl!(($($expr)* $next) $($rest)*)
};
}
pub trait Tokens {
fn parse<T: Parse>(self) -> Result<T>;
}
impl<'a> Tokens for &'a str {
fn parse<T: Parse>(self) -> Result<T> {
syn::parse_str(self)
}
}
impl Tokens for proc_macro2::TokenStream {
fn parse<T: Parse>(self) -> Result<T> {
syn::parse2(self)
}
}

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

@ -1,3 +0,0 @@
mod regression {
automod::dir!("tests/regression");
}

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

@ -1,5 +0,0 @@
#[test]
fn issue1108() {
let data = "impl<x<>>::x for";
_ = syn::parse_file(data);
}

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

@ -1,32 +0,0 @@
use proc_macro2::{Delimiter, Group};
use quote::quote;
#[test]
fn main() {
// Okay. Rustc allows top-level `static` with no value syntactically, but
// not semantically. Syn parses as Item::Verbatim.
let tokens = quote! {
pub static FOO: usize;
pub static BAR: usize;
};
let file = syn::parse2::<syn::File>(tokens).unwrap();
println!("{:#?}", file);
// Okay.
let inner = Group::new(
Delimiter::None,
quote!(static FOO: usize = 0; pub static BAR: usize = 0),
);
let tokens = quote!(pub #inner;);
let file = syn::parse2::<syn::File>(tokens).unwrap();
println!("{:#?}", file);
// Formerly parser crash.
let inner = Group::new(
Delimiter::None,
quote!(static FOO: usize; pub static BAR: usize),
);
let tokens = quote!(pub #inner;);
let file = syn::parse2::<syn::File>(tokens).unwrap();
println!("{:#?}", file);
}

215
third_party/rust/syn-1.0.107/tests/repo/mod.rs поставляемый
Просмотреть файл

@ -1,215 +0,0 @@
#![allow(clippy::manual_assert)]
mod progress;
use self::progress::Progress;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;
const REVISION: &str = "98ad6a5519651af36e246c0335c964dd52c554ba";
#[rustfmt::skip]
static EXCLUDE_FILES: &[&str] = &[
// TODO: impl ~const T {}
// https://github.com/dtolnay/syn/issues/1051
"src/test/ui/rfc-2632-const-trait-impl/syntax.rs",
// Compile-fail expr parameter in const generic position: f::<1 + 2>()
"src/test/ui/const-generics/early/closing-args-token.rs",
"src/test/ui/const-generics/early/const-expression-parameter.rs",
// Need at least one trait in impl Trait, no such type as impl 'static
"src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs",
// Deprecated anonymous parameter syntax in traits
"src/test/ui/issues/issue-13105.rs",
"src/test/ui/issues/issue-13775.rs",
"src/test/ui/issues/issue-34074.rs",
"src/test/ui/proc-macro/trait-fn-args-2015.rs",
"src/tools/rustfmt/tests/source/trait.rs",
"src/tools/rustfmt/tests/target/trait.rs",
// Various extensions to Rust syntax made up by rust-analyzer
"src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0012_type_item_where_clause.rs",
"src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rs",
"src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0131_existential_type.rs",
"src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0179_use_tree_abs_star.rs",
"src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rs",
"src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0015_use_tree.rs",
"src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0029_range_forms.rs",
"src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs",
"src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0055_dot_dot_dot.rs",
"src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0068_item_modifiers.rs",
"src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0031_block_inner_attrs.rs",
"src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0045_ambiguous_trait_object.rs",
"src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0046_mutable_const_item.rs",
// Placeholder syntax for "throw expressions"
"src/test/pretty/yeet-expr.rs",
"src/test/ui/try-trait/yeet-for-option.rs",
"src/test/ui/try-trait/yeet-for-result.rs",
// Excessive nesting
"src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs",
// Testing tools on invalid syntax
"src/test/run-make/translation/test.rs",
"src/test/ui/generics/issue-94432-garbage-ice.rs",
"src/tools/rustfmt/tests/coverage/target/comments.rs",
"src/tools/rustfmt/tests/parser/issue-4126/invalid.rs",
"src/tools/rustfmt/tests/parser/issue_4418.rs",
"src/tools/rustfmt/tests/parser/unclosed-delims/issue_4466.rs",
"src/tools/rustfmt/tests/source/configs/disable_all_formatting/true.rs",
"src/tools/rustfmt/tests/source/configs/spaces_around_ranges/false.rs",
"src/tools/rustfmt/tests/source/configs/spaces_around_ranges/true.rs",
"src/tools/rustfmt/tests/source/type.rs",
"src/tools/rustfmt/tests/target/configs/spaces_around_ranges/false.rs",
"src/tools/rustfmt/tests/target/configs/spaces_around_ranges/true.rs",
"src/tools/rustfmt/tests/target/type.rs",
// Generated file containing a top-level expression, used with `include!`
"compiler/rustc_codegen_gcc/src/intrinsic/archs.rs",
// Clippy lint lists represented as expressions
"src/tools/clippy/clippy_lints/src/lib.deprecated.rs",
"src/tools/clippy/clippy_lints/src/lib.register_all.rs",
"src/tools/clippy/clippy_lints/src/lib.register_cargo.rs",
"src/tools/clippy/clippy_lints/src/lib.register_complexity.rs",
"src/tools/clippy/clippy_lints/src/lib.register_correctness.rs",
"src/tools/clippy/clippy_lints/src/lib.register_internal.rs",
"src/tools/clippy/clippy_lints/src/lib.register_lints.rs",
"src/tools/clippy/clippy_lints/src/lib.register_nursery.rs",
"src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs",
"src/tools/clippy/clippy_lints/src/lib.register_perf.rs",
"src/tools/clippy/clippy_lints/src/lib.register_restriction.rs",
"src/tools/clippy/clippy_lints/src/lib.register_style.rs",
"src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs",
// Not actually test cases
"src/test/ui/lint/expansion-time-include.rs",
"src/test/ui/macros/auxiliary/macro-comma-support.rs",
"src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
"src/test/ui/macros/include-single-expr-helper.rs",
"src/test/ui/macros/include-single-expr-helper-1.rs",
"src/test/ui/parser/issues/auxiliary/issue-21146-inc.rs",
];
#[rustfmt::skip]
static EXCLUDE_DIRS: &[&str] = &[
// Inputs that intentionally do not parse
"src/tools/rust-analyzer/crates/parser/test_data/parser/err",
"src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err",
// Inputs that lex but do not necessarily parse
"src/tools/rust-analyzer/crates/parser/test_data/lexer",
// Inputs that used to crash rust-analyzer, but aren't necessarily supposed to parse
"src/tools/rust-analyzer/crates/syntax/test_data/parser/fuzz-failures",
"src/tools/rust-analyzer/crates/syntax/test_data/reparse/fuzz-failures",
];
pub fn base_dir_filter(entry: &DirEntry) -> bool {
let path = entry.path();
let mut path_string = path.to_string_lossy();
if cfg!(windows) {
path_string = path_string.replace('\\', "/").into();
}
let path_string = if path_string == "tests/rust" {
return true;
} else if let Some(path) = path_string.strip_prefix("tests/rust/") {
path
} else {
panic!("unexpected path in Rust dist: {}", path_string);
};
if path.is_dir() {
return !EXCLUDE_DIRS.contains(&path_string);
}
if path.extension().map_or(true, |e| e != "rs") {
return false;
}
if path_string.starts_with("src/test/ui") || path_string.starts_with("src/test/rustdoc-ui") {
let stderr_path = path.with_extension("stderr");
if stderr_path.exists() {
// Expected to fail in some way
return false;
}
}
!EXCLUDE_FILES.contains(&path_string)
}
#[allow(dead_code)]
pub fn edition(path: &Path) -> &'static str {
if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
"2015"
} else {
"2018"
}
}
pub fn clone_rust() {
let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
Err(_) => true,
Ok(contents) => contents.trim() != REVISION,
};
if needs_clone {
download_and_unpack().unwrap();
}
let mut missing = String::new();
let test_src = Path::new("tests/rust");
for exclude in EXCLUDE_FILES {
if !test_src.join(exclude).is_file() {
missing += "\ntests/rust/";
missing += exclude;
}
}
for exclude in EXCLUDE_DIRS {
if !test_src.join(exclude).is_dir() {
missing += "\ntests/rust/";
missing += exclude;
missing += "/";
}
}
if !missing.is_empty() {
panic!("excluded test file does not exist:{}\n", missing);
}
}
fn download_and_unpack() -> Result<()> {
let url = format!(
"https://github.com/rust-lang/rust/archive/{}.tar.gz",
REVISION
);
let response = reqwest::blocking::get(url)?.error_for_status()?;
let progress = Progress::new(response);
let decoder = GzDecoder::new(progress);
let mut archive = Archive::new(decoder);
let prefix = format!("rust-{}", REVISION);
let tests_rust = Path::new("tests/rust");
if tests_rust.exists() {
fs::remove_dir_all(tests_rust)?;
}
for entry in archive.entries()? {
let mut entry = entry?;
let path = entry.path()?;
if path == Path::new("pax_global_header") {
continue;
}
let relative = path.strip_prefix(&prefix)?;
let out = tests_rust.join(relative);
entry.unpack(&out)?;
}
fs::write("tests/rust/COMMIT", REVISION)?;
Ok(())
}

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

@ -1,37 +0,0 @@
use std::io::{Read, Result};
use std::time::{Duration, Instant};
pub struct Progress<R> {
bytes: usize,
tick: Instant,
stream: R,
}
impl<R> Progress<R> {
pub fn new(stream: R) -> Self {
Progress {
bytes: 0,
tick: Instant::now() + Duration::from_millis(2000),
stream,
}
}
}
impl<R: Read> Read for Progress<R> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let num = self.stream.read(buf)?;
self.bytes += num;
let now = Instant::now();
if now > self.tick {
self.tick = now + Duration::from_millis(500);
errorf!("downloading... {} bytes\n", self.bytes);
}
Ok(num)
}
}
impl<R> Drop for Progress<R> {
fn drop(&mut self) {
errorf!("done ({} bytes)\n", self.bytes);
}
}

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

@ -1,37 +0,0 @@
#[macro_use]
mod macros;
use syn::{Expr, Item};
#[test]
fn test_async_fn() {
let input = "async fn process() {}";
snapshot!(input as Item, @r###"
Item::Fn {
vis: Inherited,
sig: Signature {
asyncness: Some,
ident: "process",
generics: Generics,
output: Default,
},
block: Block,
}
"###);
}
#[test]
fn test_async_closure() {
let input = "async || {}";
snapshot!(input as Expr, @r###"
Expr::Closure {
asyncness: Some,
output: Default,
body: Expr::Block {
block: Block,
},
}
"###);
}

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

@ -1,336 +0,0 @@
#[macro_use]
mod macros;
use syn::parse::Parser;
use syn::{Attribute, Meta};
#[test]
fn test_meta_item_word() {
let meta = test("#[foo]");
snapshot!(meta, @r###"
Path(Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
})
"###);
}
#[test]
fn test_meta_item_name_value() {
let meta = test("#[foo = 5]");
snapshot!(meta, @r###"
Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
lit: 5,
}
"###);
}
#[test]
fn test_meta_item_bool_value() {
let meta = test("#[foo = true]");
snapshot!(meta, @r###"
Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
lit: Lit::Bool {
value: true,
},
}
"###);
let meta = test("#[foo = false]");
snapshot!(meta, @r###"
Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
lit: Lit::Bool {
value: false,
},
}
"###);
}
#[test]
fn test_meta_item_list_lit() {
let meta = test("#[foo(5)]");
snapshot!(meta, @r###"
Meta::List {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
nested: [
Lit(5),
],
}
"###);
}
#[test]
fn test_meta_item_list_word() {
let meta = test("#[foo(bar)]");
snapshot!(meta, @r###"
Meta::List {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
nested: [
Meta(Path(Path {
segments: [
PathSegment {
ident: "bar",
arguments: None,
},
],
})),
],
}
"###);
}
#[test]
fn test_meta_item_list_name_value() {
let meta = test("#[foo(bar = 5)]");
snapshot!(meta, @r###"
Meta::List {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
nested: [
Meta(Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "bar",
arguments: None,
},
],
},
lit: 5,
}),
],
}
"###);
}
#[test]
fn test_meta_item_list_bool_value() {
let meta = test("#[foo(bar = true)]");
snapshot!(meta, @r###"
Meta::List {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
nested: [
Meta(Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "bar",
arguments: None,
},
],
},
lit: Lit::Bool {
value: true,
},
}),
],
}
"###);
}
#[test]
fn test_meta_item_multiple() {
let meta = test("#[foo(word, name = 5, list(name2 = 6), word2)]");
snapshot!(meta, @r###"
Meta::List {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
nested: [
Meta(Path(Path {
segments: [
PathSegment {
ident: "word",
arguments: None,
},
],
})),
Meta(Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "name",
arguments: None,
},
],
},
lit: 5,
}),
Meta(Meta::List {
path: Path {
segments: [
PathSegment {
ident: "list",
arguments: None,
},
],
},
nested: [
Meta(Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "name2",
arguments: None,
},
],
},
lit: 6,
}),
],
}),
Meta(Path(Path {
segments: [
PathSegment {
ident: "word2",
arguments: None,
},
],
})),
],
}
"###);
}
#[test]
fn test_bool_lit() {
let meta = test("#[foo(true)]");
snapshot!(meta, @r###"
Meta::List {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
nested: [
Lit(Lit::Bool {
value: true,
}),
],
}
"###);
}
#[test]
fn test_negative_lit() {
let meta = test("#[form(min = -1, max = 200)]");
snapshot!(meta, @r###"
Meta::List {
path: Path {
segments: [
PathSegment {
ident: "form",
arguments: None,
},
],
},
nested: [
Meta(Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "min",
arguments: None,
},
],
},
lit: -1,
}),
Meta(Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "max",
arguments: None,
},
],
},
lit: 200,
}),
],
}
"###);
}
fn test(input: &str) -> Meta {
let attrs = Attribute::parse_outer.parse_str(input).unwrap();
assert_eq!(attrs.len(), 1);
let attr = attrs.into_iter().next().unwrap();
attr.parse_meta().unwrap()
}

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

@ -1,894 +0,0 @@
#![allow(clippy::assertions_on_result_states, clippy::too_many_lines)]
#[macro_use]
mod macros;
use quote::quote;
use syn::{Data, DeriveInput};
#[test]
fn test_unit() {
let input = quote! {
struct Unit;
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
vis: Inherited,
ident: "Unit",
generics: Generics,
data: Data::Struct {
fields: Unit,
semi_token: Some,
},
}
"###);
}
#[test]
fn test_struct() {
let input = quote! {
#[derive(Debug, Clone)]
pub struct Item {
pub ident: Ident,
pub attrs: Vec<Attribute>
}
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
attrs: [
Attribute {
style: Outer,
path: Path {
segments: [
PathSegment {
ident: "derive",
arguments: None,
},
],
},
tokens: TokenStream(`(Debug , Clone)`),
},
],
vis: Visibility::Public,
ident: "Item",
generics: Generics,
data: Data::Struct {
fields: Fields::Named {
named: [
Field {
vis: Visibility::Public,
ident: Some("ident"),
colon_token: Some,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "Ident",
arguments: None,
},
],
},
},
},
Field {
vis: Visibility::Public,
ident: Some("attrs"),
colon_token: Some,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "Vec",
arguments: PathArguments::AngleBracketed {
args: [
Type(Type::Path {
path: Path {
segments: [
PathSegment {
ident: "Attribute",
arguments: None,
},
],
},
}),
],
},
},
],
},
},
},
],
},
},
}
"###);
snapshot!(input.attrs[0].parse_meta().unwrap(), @r###"
Meta::List {
path: Path {
segments: [
PathSegment {
ident: "derive",
arguments: None,
},
],
},
nested: [
Meta(Path(Path {
segments: [
PathSegment {
ident: "Debug",
arguments: None,
},
],
})),
Meta(Path(Path {
segments: [
PathSegment {
ident: "Clone",
arguments: None,
},
],
})),
],
}
"###);
}
#[test]
fn test_union() {
let input = quote! {
union MaybeUninit<T> {
uninit: (),
value: T
}
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
vis: Inherited,
ident: "MaybeUninit",
generics: Generics {
lt_token: Some,
params: [
Type(TypeParam {
ident: "T",
}),
],
gt_token: Some,
},
data: Data::Union {
fields: FieldsNamed {
named: [
Field {
vis: Inherited,
ident: Some("uninit"),
colon_token: Some,
ty: Type::Tuple,
},
Field {
vis: Inherited,
ident: Some("value"),
colon_token: Some,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "T",
arguments: None,
},
],
},
},
},
],
},
},
}
"###);
}
#[test]
#[cfg(feature = "full")]
fn test_enum() {
let input = quote! {
/// See the std::result module documentation for details.
#[must_use]
pub enum Result<T, E> {
Ok(T),
Err(E),
Surprise = 0isize,
// Smuggling data into a proc_macro_derive,
// in the style of https://github.com/dtolnay/proc-macro-hack
ProcMacroHack = (0, "data").0
}
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
attrs: [
Attribute {
style: Outer,
path: Path {
segments: [
PathSegment {
ident: "doc",
arguments: None,
},
],
},
tokens: TokenStream(`= r" See the std::result module documentation for details."`),
},
Attribute {
style: Outer,
path: Path {
segments: [
PathSegment {
ident: "must_use",
arguments: None,
},
],
},
tokens: TokenStream(``),
},
],
vis: Visibility::Public,
ident: "Result",
generics: Generics {
lt_token: Some,
params: [
Type(TypeParam {
ident: "T",
}),
Type(TypeParam {
ident: "E",
}),
],
gt_token: Some,
},
data: Data::Enum {
variants: [
Variant {
ident: "Ok",
fields: Fields::Unnamed {
unnamed: [
Field {
vis: Inherited,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "T",
arguments: None,
},
],
},
},
},
],
},
},
Variant {
ident: "Err",
fields: Fields::Unnamed {
unnamed: [
Field {
vis: Inherited,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "E",
arguments: None,
},
],
},
},
},
],
},
},
Variant {
ident: "Surprise",
fields: Unit,
discriminant: Some(Expr::Lit {
lit: 0isize,
}),
},
Variant {
ident: "ProcMacroHack",
fields: Unit,
discriminant: Some(Expr::Field {
base: Expr::Tuple {
elems: [
Expr::Lit {
lit: 0,
},
Expr::Lit {
lit: "data",
},
],
},
member: Unnamed(Index {
index: 0,
}),
}),
},
],
},
}
"###);
let meta_items: Vec<_> = input
.attrs
.into_iter()
.map(|attr| attr.parse_meta().unwrap())
.collect();
snapshot!(meta_items, @r###"
[
Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "doc",
arguments: None,
},
],
},
lit: " See the std::result module documentation for details.",
},
Path(Path {
segments: [
PathSegment {
ident: "must_use",
arguments: None,
},
],
}),
]
"###);
}
#[test]
fn test_attr_with_path() {
let input = quote! {
#[::attr_args::identity
fn main() { assert_eq!(foo(), "Hello, world!"); }]
struct Dummy;
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
attrs: [
Attribute {
style: Outer,
path: Path {
leading_colon: Some,
segments: [
PathSegment {
ident: "attr_args",
arguments: None,
},
PathSegment {
ident: "identity",
arguments: None,
},
],
},
tokens: TokenStream(`fn main () { assert_eq ! (foo () , "Hello, world!") ; }`),
},
],
vis: Inherited,
ident: "Dummy",
generics: Generics,
data: Data::Struct {
fields: Unit,
semi_token: Some,
},
}
"###);
assert!(input.attrs[0].parse_meta().is_err());
}
#[test]
fn test_attr_with_non_mod_style_path() {
let input = quote! {
#[inert <T>]
struct S;
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
attrs: [
Attribute {
style: Outer,
path: Path {
segments: [
PathSegment {
ident: "inert",
arguments: None,
},
],
},
tokens: TokenStream(`< T >`),
},
],
vis: Inherited,
ident: "S",
generics: Generics,
data: Data::Struct {
fields: Unit,
semi_token: Some,
},
}
"###);
assert!(input.attrs[0].parse_meta().is_err());
}
#[test]
fn test_attr_with_mod_style_path_with_self() {
let input = quote! {
#[foo::self]
struct S;
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
attrs: [
Attribute {
style: Outer,
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
PathSegment {
ident: "self",
arguments: None,
},
],
},
tokens: TokenStream(``),
},
],
vis: Inherited,
ident: "S",
generics: Generics,
data: Data::Struct {
fields: Unit,
semi_token: Some,
},
}
"###);
snapshot!(input.attrs[0].parse_meta().unwrap(), @r###"
Path(Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
PathSegment {
ident: "self",
arguments: None,
},
],
})
"###);
}
#[test]
fn test_pub_restricted() {
// Taken from tests/rust/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs
let input = quote! {
pub(in m) struct Z(pub(in m::n) u8);
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
vis: Visibility::Restricted {
in_token: Some,
path: Path {
segments: [
PathSegment {
ident: "m",
arguments: None,
},
],
},
},
ident: "Z",
generics: Generics,
data: Data::Struct {
fields: Fields::Unnamed {
unnamed: [
Field {
vis: Visibility::Restricted {
in_token: Some,
path: Path {
segments: [
PathSegment {
ident: "m",
arguments: None,
},
PathSegment {
ident: "n",
arguments: None,
},
],
},
},
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "u8",
arguments: None,
},
],
},
},
},
],
},
semi_token: Some,
},
}
"###);
}
#[test]
fn test_vis_crate() {
let input = quote! {
crate struct S;
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
vis: Visibility::Crate,
ident: "S",
generics: Generics,
data: Data::Struct {
fields: Unit,
semi_token: Some,
},
}
"###);
}
#[test]
fn test_pub_restricted_crate() {
let input = quote! {
pub(crate) struct S;
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
vis: Visibility::Restricted {
path: Path {
segments: [
PathSegment {
ident: "crate",
arguments: None,
},
],
},
},
ident: "S",
generics: Generics,
data: Data::Struct {
fields: Unit,
semi_token: Some,
},
}
"###);
}
#[test]
fn test_pub_restricted_super() {
let input = quote! {
pub(super) struct S;
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
vis: Visibility::Restricted {
path: Path {
segments: [
PathSegment {
ident: "super",
arguments: None,
},
],
},
},
ident: "S",
generics: Generics,
data: Data::Struct {
fields: Unit,
semi_token: Some,
},
}
"###);
}
#[test]
fn test_pub_restricted_in_super() {
let input = quote! {
pub(in super) struct S;
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
vis: Visibility::Restricted {
in_token: Some,
path: Path {
segments: [
PathSegment {
ident: "super",
arguments: None,
},
],
},
},
ident: "S",
generics: Generics,
data: Data::Struct {
fields: Unit,
semi_token: Some,
},
}
"###);
}
#[test]
fn test_fields_on_unit_struct() {
let input = quote! {
struct S;
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
vis: Inherited,
ident: "S",
generics: Generics,
data: Data::Struct {
fields: Unit,
semi_token: Some,
},
}
"###);
let data = match input.data {
Data::Struct(data) => data,
_ => panic!("expected a struct"),
};
assert_eq!(0, data.fields.iter().count());
}
#[test]
fn test_fields_on_named_struct() {
let input = quote! {
struct S {
foo: i32,
pub bar: String,
}
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
vis: Inherited,
ident: "S",
generics: Generics,
data: Data::Struct {
fields: Fields::Named {
named: [
Field {
vis: Inherited,
ident: Some("foo"),
colon_token: Some,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "i32",
arguments: None,
},
],
},
},
},
Field {
vis: Visibility::Public,
ident: Some("bar"),
colon_token: Some,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "String",
arguments: None,
},
],
},
},
},
],
},
},
}
"###);
let data = match input.data {
Data::Struct(data) => data,
_ => panic!("expected a struct"),
};
snapshot!(data.fields.into_iter().collect::<Vec<_>>(), @r###"
[
Field {
vis: Inherited,
ident: Some("foo"),
colon_token: Some,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "i32",
arguments: None,
},
],
},
},
},
Field {
vis: Visibility::Public,
ident: Some("bar"),
colon_token: Some,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "String",
arguments: None,
},
],
},
},
},
]
"###);
}
#[test]
fn test_fields_on_tuple_struct() {
let input = quote! {
struct S(i32, pub String);
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
vis: Inherited,
ident: "S",
generics: Generics,
data: Data::Struct {
fields: Fields::Unnamed {
unnamed: [
Field {
vis: Inherited,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "i32",
arguments: None,
},
],
},
},
},
Field {
vis: Visibility::Public,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "String",
arguments: None,
},
],
},
},
},
],
},
semi_token: Some,
},
}
"###);
let data = match input.data {
Data::Struct(data) => data,
_ => panic!("expected a struct"),
};
snapshot!(data.fields.iter().collect::<Vec<_>>(), @r###"
[
Field {
vis: Inherited,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "i32",
arguments: None,
},
],
},
},
},
Field {
vis: Visibility::Public,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "String",
arguments: None,
},
],
},
},
},
]
"###);
}
#[test]
fn test_ambiguous_crate() {
let input = quote! {
// The field type is `(crate::X)` not `crate (::X)`.
struct S(crate::X);
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
vis: Inherited,
ident: "S",
generics: Generics,
data: Data::Struct {
fields: Fields::Unnamed {
unnamed: [
Field {
vis: Inherited,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "crate",
arguments: None,
},
PathSegment {
ident: "X",
arguments: None,
},
],
},
},
},
],
},
semi_token: Some,
},
}
"###);
}

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

@ -1,306 +0,0 @@
#[macro_use]
mod macros;
use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::{Expr, ExprRange};
#[test]
fn test_expr_parse() {
let tokens = quote!(..100u32);
snapshot!(tokens as Expr, @r###"
Expr::Range {
limits: HalfOpen,
to: Some(Expr::Lit {
lit: 100u32,
}),
}
"###);
let tokens = quote!(..100u32);
snapshot!(tokens as ExprRange, @r###"
ExprRange {
limits: HalfOpen,
to: Some(Expr::Lit {
lit: 100u32,
}),
}
"###);
}
#[test]
fn test_await() {
// Must not parse as Expr::Field.
let tokens = quote!(fut.await);
snapshot!(tokens as Expr, @r###"
Expr::Await {
base: Expr::Path {
path: Path {
segments: [
PathSegment {
ident: "fut",
arguments: None,
},
],
},
},
}
"###);
}
#[rustfmt::skip]
#[test]
fn test_tuple_multi_index() {
let expected = snapshot!("tuple.0.0" as Expr, @r###"
Expr::Field {
base: Expr::Field {
base: Expr::Path {
path: Path {
segments: [
PathSegment {
ident: "tuple",
arguments: None,
},
],
},
},
member: Unnamed(Index {
index: 0,
}),
},
member: Unnamed(Index {
index: 0,
}),
}
"###);
for &input in &[
"tuple .0.0",
"tuple. 0.0",
"tuple.0 .0",
"tuple.0. 0",
"tuple . 0 . 0",
] {
assert_eq!(expected, syn::parse_str(input).unwrap());
}
for tokens in vec![
quote!(tuple.0.0),
quote!(tuple .0.0),
quote!(tuple. 0.0),
quote!(tuple.0 .0),
quote!(tuple.0. 0),
quote!(tuple . 0 . 0),
] {
assert_eq!(expected, syn::parse2(tokens).unwrap());
}
}
#[test]
fn test_macro_variable_func() {
// mimics the token stream corresponding to `$fn()`
let tokens = TokenStream::from_iter(vec![
TokenTree::Group(Group::new(Delimiter::None, quote! { f })),
TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
]);
snapshot!(tokens as Expr, @r###"
Expr::Call {
func: Expr::Group {
expr: Expr::Path {
path: Path {
segments: [
PathSegment {
ident: "f",
arguments: None,
},
],
},
},
},
}
"###);
let tokens = TokenStream::from_iter(vec![
TokenTree::Punct(Punct::new('#', Spacing::Alone)),
TokenTree::Group(Group::new(Delimiter::Bracket, quote! { outside })),
TokenTree::Group(Group::new(Delimiter::None, quote! { #[inside] f })),
TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
]);
snapshot!(tokens as Expr, @r###"
Expr::Call {
attrs: [
Attribute {
style: Outer,
path: Path {
segments: [
PathSegment {
ident: "outside",
arguments: None,
},
],
},
tokens: TokenStream(``),
},
],
func: Expr::Group {
expr: Expr::Path {
attrs: [
Attribute {
style: Outer,
path: Path {
segments: [
PathSegment {
ident: "inside",
arguments: None,
},
],
},
tokens: TokenStream(``),
},
],
path: Path {
segments: [
PathSegment {
ident: "f",
arguments: None,
},
],
},
},
},
}
"###);
}
#[test]
fn test_macro_variable_macro() {
// mimics the token stream corresponding to `$macro!()`
let tokens = TokenStream::from_iter(vec![
TokenTree::Group(Group::new(Delimiter::None, quote! { m })),
TokenTree::Punct(Punct::new('!', Spacing::Alone)),
TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
]);
snapshot!(tokens as Expr, @r###"
Expr::Macro {
mac: Macro {
path: Path {
segments: [
PathSegment {
ident: "m",
arguments: None,
},
],
},
delimiter: Paren,
tokens: TokenStream(``),
},
}
"###);
}
#[test]
fn test_macro_variable_struct() {
// mimics the token stream corresponding to `$struct {}`
let tokens = TokenStream::from_iter(vec![
TokenTree::Group(Group::new(Delimiter::None, quote! { S })),
TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
]);
snapshot!(tokens as Expr, @r###"
Expr::Struct {
path: Path {
segments: [
PathSegment {
ident: "S",
arguments: None,
},
],
},
}
"###);
}
#[test]
fn test_macro_variable_match_arm() {
// mimics the token stream corresponding to `match v { _ => $expr }`
let tokens = TokenStream::from_iter(vec![
TokenTree::Ident(Ident::new("match", Span::call_site())),
TokenTree::Ident(Ident::new("v", Span::call_site())),
TokenTree::Group(Group::new(
Delimiter::Brace,
TokenStream::from_iter(vec![
TokenTree::Punct(Punct::new('_', Spacing::Alone)),
TokenTree::Punct(Punct::new('=', Spacing::Joint)),
TokenTree::Punct(Punct::new('>', Spacing::Alone)),
TokenTree::Group(Group::new(Delimiter::None, quote! { #[a] () })),
]),
)),
]);
snapshot!(tokens as Expr, @r###"
Expr::Match {
expr: Expr::Path {
path: Path {
segments: [
PathSegment {
ident: "v",
arguments: None,
},
],
},
},
arms: [
Arm {
pat: Pat::Wild,
body: Expr::Group {
expr: Expr::Tuple {
attrs: [
Attribute {
style: Outer,
path: Path {
segments: [
PathSegment {
ident: "a",
arguments: None,
},
],
},
tokens: TokenStream(``),
},
],
},
},
},
],
}
"###);
}
// https://github.com/dtolnay/syn/issues/1019
#[test]
fn test_closure_vs_rangefull() {
#[rustfmt::skip] // rustfmt bug: https://github.com/rust-lang/rustfmt/issues/4808
let tokens = quote!(|| .. .method());
snapshot!(tokens as Expr, @r###"
Expr::MethodCall {
receiver: Expr::Closure {
output: Default,
body: Expr::Range {
limits: HalfOpen,
},
},
method: "method",
}
"###);
}
#[test]
fn test_postfix_operator_after_cast() {
syn::parse_str::<Expr>("|| &x as T[0]").unwrap_err();
syn::parse_str::<Expr>("|| () as ()()").unwrap_err();
}

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

@ -1,285 +0,0 @@
#![allow(clippy::too_many_lines)]
#[macro_use]
mod macros;
use quote::quote;
use syn::{DeriveInput, ItemFn, TypeParamBound, WhereClause, WherePredicate};
#[test]
fn test_split_for_impl() {
let input = quote! {
struct S<'a, 'b: 'a, #[may_dangle] T: 'a = ()> where T: Debug;
};
snapshot!(input as DeriveInput, @r###"
DeriveInput {
vis: Inherited,
ident: "S",
generics: Generics {
lt_token: Some,
params: [
Lifetime(LifetimeDef {
lifetime: Lifetime {
ident: "a",
},
}),
Lifetime(LifetimeDef {
lifetime: Lifetime {
ident: "b",
},
colon_token: Some,
bounds: [
Lifetime {
ident: "a",
},
],
}),
Type(TypeParam {
attrs: [
Attribute {
style: Outer,
path: Path {
segments: [
PathSegment {
ident: "may_dangle",
arguments: None,
},
],
},
tokens: TokenStream(``),
},
],
ident: "T",
colon_token: Some,
bounds: [
Lifetime(Lifetime {
ident: "a",
}),
],
eq_token: Some,
default: Some(Type::Tuple),
}),
],
gt_token: Some,
where_clause: Some(WhereClause {
predicates: [
Type(PredicateType {
bounded_ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "T",
arguments: None,
},
],
},
},
bounds: [
Trait(TraitBound {
modifier: None,
path: Path {
segments: [
PathSegment {
ident: "Debug",
arguments: None,
},
],
},
}),
],
}),
],
}),
},
data: Data::Struct {
fields: Unit,
semi_token: Some,
},
}
"###);
let generics = input.generics;
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let generated = quote! {
impl #impl_generics MyTrait for Test #ty_generics #where_clause {}
};
let expected = quote! {
impl<'a, 'b: 'a, #[may_dangle] T: 'a> MyTrait
for Test<'a, 'b, T>
where
T: Debug
{}
};
assert_eq!(generated.to_string(), expected.to_string());
let turbofish = ty_generics.as_turbofish();
let generated = quote! {
Test #turbofish
};
let expected = quote! {
Test::<'a, 'b, T>
};
assert_eq!(generated.to_string(), expected.to_string());
}
#[test]
fn test_ty_param_bound() {
let tokens = quote!('a);
snapshot!(tokens as TypeParamBound, @r###"
Lifetime(Lifetime {
ident: "a",
})
"###);
let tokens = quote!('_);
snapshot!(tokens as TypeParamBound, @r###"
Lifetime(Lifetime {
ident: "_",
})
"###);
let tokens = quote!(Debug);
snapshot!(tokens as TypeParamBound, @r###"
Trait(TraitBound {
modifier: None,
path: Path {
segments: [
PathSegment {
ident: "Debug",
arguments: None,
},
],
},
})
"###);
let tokens = quote!(?Sized);
snapshot!(tokens as TypeParamBound, @r###"
Trait(TraitBound {
modifier: Maybe,
path: Path {
segments: [
PathSegment {
ident: "Sized",
arguments: None,
},
],
},
})
"###);
}
#[test]
fn test_fn_precedence_in_where_clause() {
// This should parse as two separate bounds, `FnOnce() -> i32` and `Send` - not
// `FnOnce() -> (i32 + Send)`.
let input = quote! {
fn f<G>()
where
G: FnOnce() -> i32 + Send,
{
}
};
snapshot!(input as ItemFn, @r###"
ItemFn {
vis: Inherited,
sig: Signature {
ident: "f",
generics: Generics {
lt_token: Some,
params: [
Type(TypeParam {
ident: "G",
}),
],
gt_token: Some,
where_clause: Some(WhereClause {
predicates: [
Type(PredicateType {
bounded_ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "G",
arguments: None,
},
],
},
},
bounds: [
Trait(TraitBound {
modifier: None,
path: Path {
segments: [
PathSegment {
ident: "FnOnce",
arguments: PathArguments::Parenthesized {
output: Type(
Type::Path {
path: Path {
segments: [
PathSegment {
ident: "i32",
arguments: None,
},
],
},
},
),
},
},
],
},
}),
Trait(TraitBound {
modifier: None,
path: Path {
segments: [
PathSegment {
ident: "Send",
arguments: None,
},
],
},
}),
],
}),
],
}),
},
output: Default,
},
block: Block,
}
"###);
let where_clause = input.sig.generics.where_clause.as_ref().unwrap();
assert_eq!(where_clause.predicates.len(), 1);
let predicate = match &where_clause.predicates[0] {
WherePredicate::Type(pred) => pred,
_ => panic!("wrong predicate kind"),
};
assert_eq!(predicate.bounds.len(), 2, "{:#?}", predicate.bounds);
let first_bound = &predicate.bounds[0];
assert_eq!(quote!(#first_bound).to_string(), "FnOnce () -> i32");
let second_bound = &predicate.bounds[1];
assert_eq!(quote!(#second_bound).to_string(), "Send");
}
#[test]
fn test_where_clause_at_end_of_input() {
let input = quote! {
where
};
snapshot!(input as WhereClause, @"WhereClause");
assert_eq!(input.predicates.len(), 0);
}

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

@ -1,52 +0,0 @@
#[macro_use]
mod macros;
use proc_macro2::{Delimiter, Group, Literal, Punct, Spacing, TokenStream, TokenTree};
use std::iter::FromIterator;
use syn::Expr;
#[test]
fn test_grouping() {
let tokens: TokenStream = TokenStream::from_iter(vec![
TokenTree::Literal(Literal::i32_suffixed(1)),
TokenTree::Punct(Punct::new('+', Spacing::Alone)),
TokenTree::Group(Group::new(
Delimiter::None,
TokenStream::from_iter(vec![
TokenTree::Literal(Literal::i32_suffixed(2)),
TokenTree::Punct(Punct::new('+', Spacing::Alone)),
TokenTree::Literal(Literal::i32_suffixed(3)),
]),
)),
TokenTree::Punct(Punct::new('*', Spacing::Alone)),
TokenTree::Literal(Literal::i32_suffixed(4)),
]);
assert_eq!(tokens.to_string(), "1i32 + 2i32 + 3i32 * 4i32");
snapshot!(tokens as Expr, @r###"
Expr::Binary {
left: Expr::Lit {
lit: 1i32,
},
op: Add,
right: Expr::Binary {
left: Expr::Group {
expr: Expr::Binary {
left: Expr::Lit {
lit: 2i32,
},
op: Add,
right: Expr::Lit {
lit: 3i32,
},
},
},
op: Mul,
right: Expr::Lit {
lit: 4i32,
},
},
}
"###);
}

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

@ -1,85 +0,0 @@
use proc_macro2::{Ident, Span, TokenStream};
use std::str::FromStr;
use syn::Result;
fn parse(s: &str) -> Result<Ident> {
syn::parse2(TokenStream::from_str(s).unwrap())
}
fn new(s: &str) -> Ident {
Ident::new(s, Span::call_site())
}
#[test]
fn ident_parse() {
parse("String").unwrap();
}
#[test]
fn ident_parse_keyword() {
parse("abstract").unwrap_err();
}
#[test]
fn ident_parse_empty() {
parse("").unwrap_err();
}
#[test]
fn ident_parse_lifetime() {
parse("'static").unwrap_err();
}
#[test]
fn ident_parse_underscore() {
parse("_").unwrap_err();
}
#[test]
fn ident_parse_number() {
parse("255").unwrap_err();
}
#[test]
fn ident_parse_invalid() {
parse("a#").unwrap_err();
}
#[test]
fn ident_new() {
new("String");
}
#[test]
fn ident_new_keyword() {
new("abstract");
}
#[test]
#[should_panic(expected = "use Option<Ident>")]
fn ident_new_empty() {
new("");
}
#[test]
#[should_panic(expected = "not a valid Ident")]
fn ident_new_lifetime() {
new("'static");
}
#[test]
fn ident_new_underscore() {
new("_");
}
#[test]
#[should_panic(expected = "use Literal instead")]
fn ident_new_number() {
new("255");
}
#[test]
#[should_panic(expected = "\"a#\" is not a valid Ident")]
fn ident_new_invalid() {
new("a#");
}

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

@ -1,336 +0,0 @@
#[macro_use]
mod macros;
use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::{Item, ItemTrait};
#[test]
fn test_macro_variable_attr() {
// mimics the token stream corresponding to `$attr fn f() {}`
let tokens = TokenStream::from_iter(vec![
TokenTree::Group(Group::new(Delimiter::None, quote! { #[test] })),
TokenTree::Ident(Ident::new("fn", Span::call_site())),
TokenTree::Ident(Ident::new("f", Span::call_site())),
TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
]);
snapshot!(tokens as Item, @r###"
Item::Fn {
attrs: [
Attribute {
style: Outer,
path: Path {
segments: [
PathSegment {
ident: "test",
arguments: None,
},
],
},
tokens: TokenStream(``),
},
],
vis: Inherited,
sig: Signature {
ident: "f",
generics: Generics,
output: Default,
},
block: Block,
}
"###);
}
#[test]
fn test_negative_impl() {
// Rustc parses all of the following.
#[cfg(any())]
impl ! {}
let tokens = quote! {
impl ! {}
};
snapshot!(tokens as Item, @r###"
Item::Impl {
generics: Generics,
self_ty: Type::Never,
}
"###);
#[cfg(any())]
#[rustfmt::skip]
impl !Trait {}
let tokens = quote! {
impl !Trait {}
};
snapshot!(tokens as Item, @r###"
Item::Impl {
generics: Generics,
self_ty: Verbatim(`! Trait`),
}
"###);
#[cfg(any())]
impl !Trait for T {}
let tokens = quote! {
impl !Trait for T {}
};
snapshot!(tokens as Item, @r###"
Item::Impl {
generics: Generics,
trait_: Some((
Some,
Path {
segments: [
PathSegment {
ident: "Trait",
arguments: None,
},
],
},
)),
self_ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "T",
arguments: None,
},
],
},
},
}
"###);
#[cfg(any())]
#[rustfmt::skip]
impl !! {}
let tokens = quote! {
impl !! {}
};
snapshot!(tokens as Item, @r###"
Item::Impl {
generics: Generics,
self_ty: Verbatim(`! !`),
}
"###);
}
#[test]
fn test_macro_variable_impl() {
// mimics the token stream corresponding to `impl $trait for $ty {}`
let tokens = TokenStream::from_iter(vec![
TokenTree::Ident(Ident::new("impl", Span::call_site())),
TokenTree::Group(Group::new(Delimiter::None, quote!(Trait))),
TokenTree::Ident(Ident::new("for", Span::call_site())),
TokenTree::Group(Group::new(Delimiter::None, quote!(Type))),
TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
]);
snapshot!(tokens as Item, @r###"
Item::Impl {
generics: Generics,
trait_: Some((
None,
Path {
segments: [
PathSegment {
ident: "Trait",
arguments: None,
},
],
},
)),
self_ty: Type::Group {
elem: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "Type",
arguments: None,
},
],
},
},
},
}
"###);
}
#[test]
fn test_supertraits() {
// Rustc parses all of the following.
#[rustfmt::skip]
let tokens = quote!(trait Trait where {});
snapshot!(tokens as ItemTrait, @r###"
ItemTrait {
vis: Inherited,
ident: "Trait",
generics: Generics {
where_clause: Some(WhereClause),
},
}
"###);
#[rustfmt::skip]
let tokens = quote!(trait Trait: where {});
snapshot!(tokens as ItemTrait, @r###"
ItemTrait {
vis: Inherited,
ident: "Trait",
generics: Generics {
where_clause: Some(WhereClause),
},
colon_token: Some,
}
"###);
#[rustfmt::skip]
let tokens = quote!(trait Trait: Sized where {});
snapshot!(tokens as ItemTrait, @r###"
ItemTrait {
vis: Inherited,
ident: "Trait",
generics: Generics {
where_clause: Some(WhereClause),
},
colon_token: Some,
supertraits: [
Trait(TraitBound {
modifier: None,
path: Path {
segments: [
PathSegment {
ident: "Sized",
arguments: None,
},
],
},
}),
],
}
"###);
#[rustfmt::skip]
let tokens = quote!(trait Trait: Sized + where {});
snapshot!(tokens as ItemTrait, @r###"
ItemTrait {
vis: Inherited,
ident: "Trait",
generics: Generics {
where_clause: Some(WhereClause),
},
colon_token: Some,
supertraits: [
Trait(TraitBound {
modifier: None,
path: Path {
segments: [
PathSegment {
ident: "Sized",
arguments: None,
},
],
},
}),
],
}
"###);
}
#[test]
fn test_type_empty_bounds() {
#[rustfmt::skip]
let tokens = quote! {
trait Foo {
type Bar: ;
}
};
snapshot!(tokens as ItemTrait, @r###"
ItemTrait {
vis: Inherited,
ident: "Foo",
generics: Generics,
items: [
TraitItem::Type {
ident: "Bar",
generics: Generics,
colon_token: Some,
},
],
}
"###);
}
#[test]
fn test_impl_visibility() {
let tokens = quote! {
pub default unsafe impl union {}
};
snapshot!(tokens as Item, @"Verbatim(`pub default unsafe impl union { }`)");
}
#[test]
fn test_impl_type_parameter_defaults() {
#[cfg(any())]
impl<T = ()> () {}
let tokens = quote! {
impl<T = ()> () {}
};
snapshot!(tokens as Item, @r###"
Item::Impl {
generics: Generics {
lt_token: Some,
params: [
Type(TypeParam {
ident: "T",
eq_token: Some,
default: Some(Type::Tuple),
}),
],
gt_token: Some,
},
self_ty: Type::Tuple,
}"###);
}
#[test]
fn test_impl_trait_trailing_plus() {
let tokens = quote! {
fn f() -> impl Sized + {}
};
snapshot!(tokens as Item, @r###"
Item::Fn {
vis: Inherited,
sig: Signature {
ident: "f",
generics: Generics,
output: Type(
Type::ImplTrait {
bounds: [
Trait(TraitBound {
modifier: None,
path: Path {
segments: [
PathSegment {
ident: "Sized",
arguments: None,
},
],
},
}),
],
},
),
},
block: Block,
}
"###);
}

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

@ -1,68 +0,0 @@
use syn::punctuated::{Pair, Punctuated};
use syn::Token;
#[macro_use]
mod macros;
macro_rules! check_exact_size_iterator {
($iter:expr) => {{
let iter = $iter;
let size_hint = iter.size_hint();
let len = iter.len();
let count = iter.count();
assert_eq!(len, count);
assert_eq!(size_hint, (count, Some(count)));
}};
}
#[test]
fn pairs() {
let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4);
check_exact_size_iterator!(p.pairs());
check_exact_size_iterator!(p.pairs_mut());
check_exact_size_iterator!(p.into_pairs());
let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4);
assert_eq!(p.pairs().next_back().map(Pair::into_value), Some(&4));
assert_eq!(
p.pairs_mut().next_back().map(Pair::into_value),
Some(&mut 4)
);
assert_eq!(p.into_pairs().next_back().map(Pair::into_value), Some(4));
}
#[test]
fn iter() {
let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4);
check_exact_size_iterator!(p.iter());
check_exact_size_iterator!(p.iter_mut());
check_exact_size_iterator!(p.into_iter());
let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4);
assert_eq!(p.iter().next_back(), Some(&4));
assert_eq!(p.iter_mut().next_back(), Some(&mut 4));
assert_eq!(p.into_iter().next_back(), Some(4));
}
#[test]
fn may_dangle() {
let p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4);
for element in &p {
if *element == 2 {
drop(p);
break;
}
}
let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4);
for element in &mut p {
if *element == 2 {
drop(p);
break;
}
}
}

266
third_party/rust/syn-1.0.107/tests/test_lit.rs поставляемый
Просмотреть файл

@ -1,266 +0,0 @@
#![allow(clippy::float_cmp, clippy::non_ascii_literal)]
#[macro_use]
mod macros;
use proc_macro2::{Delimiter, Group, Literal, Span, TokenStream, TokenTree};
use quote::ToTokens;
use std::iter::FromIterator;
use std::str::FromStr;
use syn::{Lit, LitFloat, LitInt, LitStr};
fn lit(s: &str) -> Lit {
match TokenStream::from_str(s)
.unwrap()
.into_iter()
.next()
.unwrap()
{
TokenTree::Literal(lit) => Lit::new(lit),
_ => panic!(),
}
}
#[test]
fn strings() {
fn test_string(s: &str, value: &str) {
match lit(s) {
Lit::Str(lit) => {
assert_eq!(lit.value(), value);
let again = lit.into_token_stream().to_string();
if again != s {
test_string(&again, value);
}
}
wrong => panic!("{:?}", wrong),
}
}
test_string("\"a\"", "a");
test_string("\"\\n\"", "\n");
test_string("\"\\r\"", "\r");
test_string("\"\\t\"", "\t");
test_string("\"🐕\"", "🐕"); // NOTE: This is an emoji
test_string("\"\\\"\"", "\"");
test_string("\"'\"", "'");
test_string("\"\"", "");
test_string("\"\\u{1F415}\"", "\u{1F415}");
test_string("\"\\u{1_2__3_}\"", "\u{123}");
test_string(
"\"contains\nnewlines\\\nescaped newlines\"",
"contains\nnewlinesescaped newlines",
);
test_string("r\"raw\nstring\\\nhere\"", "raw\nstring\\\nhere");
test_string("\"...\"q", "...");
test_string("r\"...\"q", "...");
test_string("r##\"...\"##q", "...");
}
#[test]
fn byte_strings() {
fn test_byte_string(s: &str, value: &[u8]) {
match lit(s) {
Lit::ByteStr(lit) => {
assert_eq!(lit.value(), value);
let again = lit.into_token_stream().to_string();
if again != s {
test_byte_string(&again, value);
}
}
wrong => panic!("{:?}", wrong),
}
}
test_byte_string("b\"a\"", b"a");
test_byte_string("b\"\\n\"", b"\n");
test_byte_string("b\"\\r\"", b"\r");
test_byte_string("b\"\\t\"", b"\t");
test_byte_string("b\"\\\"\"", b"\"");
test_byte_string("b\"'\"", b"'");
test_byte_string("b\"\"", b"");
test_byte_string(
"b\"contains\nnewlines\\\nescaped newlines\"",
b"contains\nnewlinesescaped newlines",
);
test_byte_string("br\"raw\nstring\\\nhere\"", b"raw\nstring\\\nhere");
test_byte_string("b\"...\"q", b"...");
test_byte_string("br\"...\"q", b"...");
test_byte_string("br##\"...\"##q", b"...");
}
#[test]
fn bytes() {
fn test_byte(s: &str, value: u8) {
match lit(s) {
Lit::Byte(lit) => {
assert_eq!(lit.value(), value);
let again = lit.into_token_stream().to_string();
assert_eq!(again, s);
}
wrong => panic!("{:?}", wrong),
}
}
test_byte("b'a'", b'a');
test_byte("b'\\n'", b'\n');
test_byte("b'\\r'", b'\r');
test_byte("b'\\t'", b'\t');
test_byte("b'\\''", b'\'');
test_byte("b'\"'", b'"');
test_byte("b'a'q", b'a');
}
#[test]
fn chars() {
fn test_char(s: &str, value: char) {
match lit(s) {
Lit::Char(lit) => {
assert_eq!(lit.value(), value);
let again = lit.into_token_stream().to_string();
if again != s {
test_char(&again, value);
}
}
wrong => panic!("{:?}", wrong),
}
}
test_char("'a'", 'a');
test_char("'\\n'", '\n');
test_char("'\\r'", '\r');
test_char("'\\t'", '\t');
test_char("'🐕'", '🐕'); // NOTE: This is an emoji
test_char("'\\''", '\'');
test_char("'\"'", '"');
test_char("'\\u{1F415}'", '\u{1F415}');
test_char("'a'q", 'a');
}
#[test]
fn ints() {
fn test_int(s: &str, value: u64, suffix: &str) {
match lit(s) {
Lit::Int(lit) => {
assert_eq!(lit.base10_digits().parse::<u64>().unwrap(), value);
assert_eq!(lit.suffix(), suffix);
let again = lit.into_token_stream().to_string();
if again != s {
test_int(&again, value, suffix);
}
}
wrong => panic!("{:?}", wrong),
}
}
test_int("5", 5, "");
test_int("5u32", 5, "u32");
test_int("0E", 0, "E");
test_int("0ECMA", 0, "ECMA");
test_int("0o0A", 0, "A");
test_int("5_0", 50, "");
test_int("5_____0_____", 50, "");
test_int("0x7f", 127, "");
test_int("0x7F", 127, "");
test_int("0b1001", 9, "");
test_int("0o73", 59, "");
test_int("0x7Fu8", 127, "u8");
test_int("0b1001i8", 9, "i8");
test_int("0o73u32", 59, "u32");
test_int("0x__7___f_", 127, "");
test_int("0x__7___F_", 127, "");
test_int("0b_1_0__01", 9, "");
test_int("0o_7__3", 59, "");
test_int("0x_7F__u8", 127, "u8");
test_int("0b__10__0_1i8", 9, "i8");
test_int("0o__7__________________3u32", 59, "u32");
test_int("0e1\u{5c5}", 0, "e1\u{5c5}");
}
#[test]
fn floats() {
fn test_float(s: &str, value: f64, suffix: &str) {
match lit(s) {
Lit::Float(lit) => {
assert_eq!(lit.base10_digits().parse::<f64>().unwrap(), value);
assert_eq!(lit.suffix(), suffix);
let again = lit.into_token_stream().to_string();
if again != s {
test_float(&again, value, suffix);
}
}
wrong => panic!("{:?}", wrong),
}
}
test_float("5.5", 5.5, "");
test_float("5.5E12", 5.5e12, "");
test_float("5.5e12", 5.5e12, "");
test_float("1.0__3e-12", 1.03e-12, "");
test_float("1.03e+12", 1.03e12, "");
test_float("9e99e99", 9e99, "e99");
test_float("1e_0", 1.0, "");
test_float("0.0ECMA", 0.0, "ECMA");
}
#[test]
fn negative() {
let span = Span::call_site();
assert_eq!("-1", LitInt::new("-1", span).to_string());
assert_eq!("-1i8", LitInt::new("-1i8", span).to_string());
assert_eq!("-1i16", LitInt::new("-1i16", span).to_string());
assert_eq!("-1i32", LitInt::new("-1i32", span).to_string());
assert_eq!("-1i64", LitInt::new("-1i64", span).to_string());
assert_eq!("-1.5", LitFloat::new("-1.5", span).to_string());
assert_eq!("-1.5f32", LitFloat::new("-1.5f32", span).to_string());
assert_eq!("-1.5f64", LitFloat::new("-1.5f64", span).to_string());
}
#[test]
fn suffix() {
fn get_suffix(token: &str) -> String {
let lit = syn::parse_str::<Lit>(token).unwrap();
match lit {
Lit::Str(lit) => lit.suffix().to_owned(),
Lit::ByteStr(lit) => lit.suffix().to_owned(),
Lit::Byte(lit) => lit.suffix().to_owned(),
Lit::Char(lit) => lit.suffix().to_owned(),
Lit::Int(lit) => lit.suffix().to_owned(),
Lit::Float(lit) => lit.suffix().to_owned(),
_ => unimplemented!(),
}
}
assert_eq!(get_suffix("\"\"s"), "s");
assert_eq!(get_suffix("r\"\"r"), "r");
assert_eq!(get_suffix("b\"\"b"), "b");
assert_eq!(get_suffix("br\"\"br"), "br");
assert_eq!(get_suffix("r#\"\"#r"), "r");
assert_eq!(get_suffix("'c'c"), "c");
assert_eq!(get_suffix("b'b'b"), "b");
assert_eq!(get_suffix("1i32"), "i32");
assert_eq!(get_suffix("1_i32"), "i32");
assert_eq!(get_suffix("1.0f32"), "f32");
assert_eq!(get_suffix("1.0_f32"), "f32");
}
#[test]
fn test_deep_group_empty() {
let tokens = TokenStream::from_iter(vec![TokenTree::Group(Group::new(
Delimiter::None,
TokenStream::from_iter(vec![TokenTree::Group(Group::new(
Delimiter::None,
TokenStream::from_iter(vec![TokenTree::Literal(Literal::string("hi"))]),
))]),
))]);
snapshot!(tokens as Lit, @r#""hi""# );
}
#[test]
fn test_error() {
let err = syn::parse_str::<LitStr>("...").unwrap_err();
assert_eq!("expected string literal", err.to_string());
let err = syn::parse_str::<LitStr>("5").unwrap_err();
assert_eq!("expected string literal", err.to_string());
}

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

@ -1,378 +0,0 @@
#![allow(clippy::shadow_unrelated, clippy::too_many_lines)]
#[macro_use]
mod macros;
use syn::{Meta, MetaList, MetaNameValue, NestedMeta};
#[test]
fn test_parse_meta_item_word() {
let input = "hello";
snapshot!(input as Meta, @r###"
Path(Path {
segments: [
PathSegment {
ident: "hello",
arguments: None,
},
],
})
"###);
}
#[test]
fn test_parse_meta_name_value() {
let input = "foo = 5";
let (inner, meta) = (input, input);
snapshot!(inner as MetaNameValue, @r###"
MetaNameValue {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
lit: 5,
}
"###);
snapshot!(meta as Meta, @r###"
Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
lit: 5,
}
"###);
assert_eq!(meta, inner.into());
}
#[test]
fn test_parse_meta_name_value_with_keyword() {
let input = "static = 5";
let (inner, meta) = (input, input);
snapshot!(inner as MetaNameValue, @r###"
MetaNameValue {
path: Path {
segments: [
PathSegment {
ident: "static",
arguments: None,
},
],
},
lit: 5,
}
"###);
snapshot!(meta as Meta, @r###"
Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "static",
arguments: None,
},
],
},
lit: 5,
}
"###);
assert_eq!(meta, inner.into());
}
#[test]
fn test_parse_meta_name_value_with_bool() {
let input = "true = 5";
let (inner, meta) = (input, input);
snapshot!(inner as MetaNameValue, @r###"
MetaNameValue {
path: Path {
segments: [
PathSegment {
ident: "true",
arguments: None,
},
],
},
lit: 5,
}
"###);
snapshot!(meta as Meta, @r###"
Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "true",
arguments: None,
},
],
},
lit: 5,
}
"###);
assert_eq!(meta, inner.into());
}
#[test]
fn test_parse_meta_item_list_lit() {
let input = "foo(5)";
let (inner, meta) = (input, input);
snapshot!(inner as MetaList, @r###"
MetaList {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
nested: [
Lit(5),
],
}
"###);
snapshot!(meta as Meta, @r###"
Meta::List {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
nested: [
Lit(5),
],
}
"###);
assert_eq!(meta, inner.into());
}
#[test]
fn test_parse_meta_item_multiple() {
let input = "foo(word, name = 5, list(name2 = 6), word2)";
let (inner, meta) = (input, input);
snapshot!(inner as MetaList, @r###"
MetaList {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
nested: [
Meta(Path(Path {
segments: [
PathSegment {
ident: "word",
arguments: None,
},
],
})),
Meta(Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "name",
arguments: None,
},
],
},
lit: 5,
}),
Meta(Meta::List {
path: Path {
segments: [
PathSegment {
ident: "list",
arguments: None,
},
],
},
nested: [
Meta(Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "name2",
arguments: None,
},
],
},
lit: 6,
}),
],
}),
Meta(Path(Path {
segments: [
PathSegment {
ident: "word2",
arguments: None,
},
],
})),
],
}
"###);
snapshot!(meta as Meta, @r###"
Meta::List {
path: Path {
segments: [
PathSegment {
ident: "foo",
arguments: None,
},
],
},
nested: [
Meta(Path(Path {
segments: [
PathSegment {
ident: "word",
arguments: None,
},
],
})),
Meta(Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "name",
arguments: None,
},
],
},
lit: 5,
}),
Meta(Meta::List {
path: Path {
segments: [
PathSegment {
ident: "list",
arguments: None,
},
],
},
nested: [
Meta(Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "name2",
arguments: None,
},
],
},
lit: 6,
}),
],
}),
Meta(Path(Path {
segments: [
PathSegment {
ident: "word2",
arguments: None,
},
],
})),
],
}
"###);
assert_eq!(meta, inner.into());
}
#[test]
fn test_parse_nested_meta() {
let input = "5";
snapshot!(input as NestedMeta, @"Lit(5)");
let input = "list(name2 = 6)";
snapshot!(input as NestedMeta, @r###"
Meta(Meta::List {
path: Path {
segments: [
PathSegment {
ident: "list",
arguments: None,
},
],
},
nested: [
Meta(Meta::NameValue {
path: Path {
segments: [
PathSegment {
ident: "name2",
arguments: None,
},
],
},
lit: 6,
}),
],
})
"###);
}
#[test]
fn test_parse_path() {
let input = "::serde::Serialize";
snapshot!(input as Meta, @r###"
Path(Path {
leading_colon: Some,
segments: [
PathSegment {
ident: "serde",
arguments: None,
},
PathSegment {
ident: "Serialize",
arguments: None,
},
],
})
"###);
let input = "::serde::Serialize";
snapshot!(input as NestedMeta, @r###"
Meta(Path(Path {
leading_colon: Some,
segments: [
PathSegment {
ident: "serde",
arguments: None,
},
PathSegment {
ident: "Serialize",
arguments: None,
},
],
}))
"###);
}

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

@ -1,92 +0,0 @@
#![allow(clippy::non_ascii_literal)]
use proc_macro2::{Delimiter, Group, Punct, Spacing, TokenStream, TokenTree};
use std::iter::FromIterator;
use syn::parse::{discouraged::Speculative, Parse, ParseStream, Parser, Result};
use syn::{parenthesized, Token};
#[test]
#[should_panic(expected = "Fork was not derived from the advancing parse stream")]
fn smuggled_speculative_cursor_between_sources() {
struct BreakRules;
impl Parse for BreakRules {
fn parse(input1: ParseStream) -> Result<Self> {
let nested = |input2: ParseStream| {
input1.advance_to(input2);
Ok(Self)
};
nested.parse_str("")
}
}
syn::parse_str::<BreakRules>("").unwrap();
}
#[test]
#[should_panic(expected = "Fork was not derived from the advancing parse stream")]
fn smuggled_speculative_cursor_between_brackets() {
struct BreakRules;
impl Parse for BreakRules {
fn parse(input: ParseStream) -> Result<Self> {
let a;
let b;
parenthesized!(a in input);
parenthesized!(b in input);
a.advance_to(&b);
Ok(Self)
}
}
syn::parse_str::<BreakRules>("()()").unwrap();
}
#[test]
#[should_panic(expected = "Fork was not derived from the advancing parse stream")]
fn smuggled_speculative_cursor_into_brackets() {
struct BreakRules;
impl Parse for BreakRules {
fn parse(input: ParseStream) -> Result<Self> {
let a;
parenthesized!(a in input);
input.advance_to(&a);
Ok(Self)
}
}
syn::parse_str::<BreakRules>("()").unwrap();
}
#[test]
fn trailing_empty_none_group() {
fn parse(input: ParseStream) -> Result<()> {
input.parse::<Token![+]>()?;
let content;
parenthesized!(content in input);
content.parse::<Token![+]>()?;
Ok(())
}
// `+ ( + <Ø Ø> ) <Ø <Ø Ø> Ø>`
let tokens = TokenStream::from_iter(vec![
TokenTree::Punct(Punct::new('+', Spacing::Alone)),
TokenTree::Group(Group::new(
Delimiter::Parenthesis,
TokenStream::from_iter(vec![
TokenTree::Punct(Punct::new('+', Spacing::Alone)),
TokenTree::Group(Group::new(Delimiter::None, TokenStream::new())),
]),
)),
TokenTree::Group(Group::new(Delimiter::None, TokenStream::new())),
TokenTree::Group(Group::new(
Delimiter::None,
TokenStream::from_iter(vec![TokenTree::Group(Group::new(
Delimiter::None,
TokenStream::new(),
))]),
)),
]);
parse.parse2(tokens).unwrap();
}

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

@ -1,12 +0,0 @@
use syn::ext::IdentExt;
use syn::parse::ParseStream;
use syn::{Ident, Token};
#[test]
fn test_peek() {
_ = |input: ParseStream| {
_ = input.peek(Ident);
_ = input.peek(Ident::peek_any);
_ = input.peek(Token![::]);
};
}

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

@ -1,67 +0,0 @@
#[macro_use]
mod macros;
use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::{Item, Pat, Stmt};
#[test]
fn test_pat_ident() {
match syn::parse2(quote!(self)).unwrap() {
Pat::Ident(_) => (),
value => panic!("expected PatIdent, got {:?}", value),
}
}
#[test]
fn test_pat_path() {
match syn::parse2(quote!(self::CONST)).unwrap() {
Pat::Path(_) => (),
value => panic!("expected PatPath, got {:?}", value),
}
}
#[test]
fn test_leading_vert() {
// https://github.com/rust-lang/rust/blob/1.43.0/src/test/ui/or-patterns/remove-leading-vert.rs
syn::parse_str::<Item>("fn f() {}").unwrap();
syn::parse_str::<Item>("fn fun1(| A: E) {}").unwrap_err();
syn::parse_str::<Item>("fn fun2(|| A: E) {}").unwrap_err();
syn::parse_str::<Stmt>("let | () = ();").unwrap();
syn::parse_str::<Stmt>("let (| A): E;").unwrap();
syn::parse_str::<Stmt>("let (|| A): (E);").unwrap_err();
syn::parse_str::<Stmt>("let (| A,): (E,);").unwrap();
syn::parse_str::<Stmt>("let [| A]: [E; 1];").unwrap();
syn::parse_str::<Stmt>("let [|| A]: [E; 1];").unwrap_err();
syn::parse_str::<Stmt>("let TS(| A): TS;").unwrap();
syn::parse_str::<Stmt>("let TS(|| A): TS;").unwrap_err();
syn::parse_str::<Stmt>("let NS { f: | A }: NS;").unwrap();
syn::parse_str::<Stmt>("let NS { f: || A }: NS;").unwrap_err();
}
#[test]
fn test_group() {
let group = Group::new(Delimiter::None, quote!(Some(_)));
let tokens = TokenStream::from_iter(vec![TokenTree::Group(group)]);
snapshot!(tokens as Pat, @r###"
Pat::TupleStruct {
path: Path {
segments: [
PathSegment {
ident: "Some",
arguments: None,
},
],
},
pat: PatTuple {
elems: [
Pat::Wild,
],
},
}
"###);
}

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

@ -1,126 +0,0 @@
#[macro_use]
mod macros;
use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
use quote::{quote, ToTokens};
use std::iter::FromIterator;
use syn::{parse_quote, Expr, Type, TypePath};
#[test]
fn parse_interpolated_leading_component() {
// mimics the token stream corresponding to `$mod::rest`
let tokens = TokenStream::from_iter(vec![
TokenTree::Group(Group::new(Delimiter::None, quote! { first })),
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
TokenTree::Ident(Ident::new("rest", Span::call_site())),
]);
snapshot!(tokens.clone() as Expr, @r###"
Expr::Path {
path: Path {
segments: [
PathSegment {
ident: "first",
arguments: None,
},
PathSegment {
ident: "rest",
arguments: None,
},
],
},
}
"###);
snapshot!(tokens as Type, @r###"
Type::Path {
path: Path {
segments: [
PathSegment {
ident: "first",
arguments: None,
},
PathSegment {
ident: "rest",
arguments: None,
},
],
},
}
"###);
}
#[test]
fn print_incomplete_qpath() {
// qpath with `as` token
let mut ty: TypePath = parse_quote!(<Self as A>::Q);
snapshot!(ty.to_token_stream(), @r###"
TokenStream(`< Self as A > :: Q`)
"###);
assert!(ty.path.segments.pop().is_some());
snapshot!(ty.to_token_stream(), @r###"
TokenStream(`< Self as A > ::`)
"###);
assert!(ty.path.segments.pop().is_some());
snapshot!(ty.to_token_stream(), @r###"
TokenStream(`< Self >`)
"###);
assert!(ty.path.segments.pop().is_none());
// qpath without `as` token
let mut ty: TypePath = parse_quote!(<Self>::A::B);
snapshot!(ty.to_token_stream(), @r###"
TokenStream(`< Self > :: A :: B`)
"###);
assert!(ty.path.segments.pop().is_some());
snapshot!(ty.to_token_stream(), @r###"
TokenStream(`< Self > :: A ::`)
"###);
assert!(ty.path.segments.pop().is_some());
snapshot!(ty.to_token_stream(), @r###"
TokenStream(`< Self > ::`)
"###);
assert!(ty.path.segments.pop().is_none());
// normal path
let mut ty: TypePath = parse_quote!(Self::A::B);
snapshot!(ty.to_token_stream(), @r###"
TokenStream(`Self :: A :: B`)
"###);
assert!(ty.path.segments.pop().is_some());
snapshot!(ty.to_token_stream(), @r###"
TokenStream(`Self :: A ::`)
"###);
assert!(ty.path.segments.pop().is_some());
snapshot!(ty.to_token_stream(), @r###"
TokenStream(`Self ::`)
"###);
assert!(ty.path.segments.pop().is_some());
snapshot!(ty.to_token_stream(), @r###"
TokenStream(``)
"###);
assert!(ty.path.segments.pop().is_none());
}
#[test]
fn parse_parenthesized_path_arguments_with_disambiguator() {
#[rustfmt::skip]
let tokens = quote!(FnOnce::() -> !);
snapshot!(tokens as Type, @r###"
Type::Path {
path: Path {
segments: [
PathSegment {
ident: "FnOnce",
arguments: PathArguments::Parenthesized {
output: Type(
Type::Never,
),
},
},
],
},
}
"###);
}

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

@ -1,460 +0,0 @@
#![cfg(not(syn_disable_nightly_tests))]
#![cfg(not(miri))]
#![recursion_limit = "1024"]
#![feature(rustc_private)]
#![allow(
clippy::explicit_deref_methods,
clippy::manual_assert,
clippy::match_wildcard_for_single_variants,
clippy::too_many_lines
)]
//! The tests in this module do the following:
//!
//! 1. Parse a given expression in both `syn` and `librustc`.
//! 2. Fold over the expression adding brackets around each subexpression (with
//! some complications - see the `syn_brackets` and `librustc_brackets`
//! methods).
//! 3. Serialize the `syn` expression back into a string, and re-parse it with
//! `librustc`.
//! 4. Respan all of the expressions, replacing the spans with the default
//! spans.
//! 5. Compare the expressions with one another, if they are not equal fail.
extern crate rustc_ast;
extern crate rustc_data_structures;
extern crate rustc_span;
extern crate thin_vec;
use crate::common::eq::SpanlessEq;
use crate::common::parse;
use quote::quote;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use regex::Regex;
use rustc_ast::ast;
use rustc_ast::ptr::P;
use rustc_span::edition::Edition;
use std::fs;
use std::process;
use std::sync::atomic::{AtomicUsize, Ordering};
use walkdir::{DirEntry, WalkDir};
#[macro_use]
mod macros;
#[allow(dead_code)]
mod common;
mod repo;
/// Test some pre-set expressions chosen by us.
#[test]
fn test_simple_precedence() {
const EXPRS: &[&str] = &[
"1 + 2 * 3 + 4",
"1 + 2 * ( 3 + 4 )",
"{ for i in r { } *some_ptr += 1; }",
"{ loop { break 5; } }",
"{ if true { () }.mthd() }",
"{ for i in unsafe { 20 } { } }",
];
let mut failed = 0;
for input in EXPRS {
let expr = if let Some(expr) = parse::syn_expr(input) {
expr
} else {
failed += 1;
continue;
};
let pf = match test_expressions(Edition::Edition2018, vec![expr]) {
(1, 0) => "passed",
(0, 1) => {
failed += 1;
"failed"
}
_ => unreachable!(),
};
errorf!("=== {}: {}\n", input, pf);
}
if failed > 0 {
panic!("Failed {} tests", failed);
}
}
/// Test expressions from rustc, like in `test_round_trip`.
#[test]
fn test_rustc_precedence() {
common::rayon_init();
repo::clone_rust();
let abort_after = common::abort_after();
if abort_after == 0 {
panic!("Skipping all precedence tests");
}
let passed = AtomicUsize::new(0);
let failed = AtomicUsize::new(0);
// 2018 edition is hard
let edition_regex = Regex::new(r"\b(async|try)[!(]").unwrap();
WalkDir::new("tests/rust")
.sort_by(|a, b| a.file_name().cmp(b.file_name()))
.into_iter()
.filter_entry(repo::base_dir_filter)
.collect::<Result<Vec<DirEntry>, walkdir::Error>>()
.unwrap()
.into_par_iter()
.for_each(|entry| {
let path = entry.path();
if path.is_dir() {
return;
}
let content = fs::read_to_string(path).unwrap();
let content = edition_regex.replace_all(&content, "_$0");
let (l_passed, l_failed) = match syn::parse_file(&content) {
Ok(file) => {
let edition = repo::edition(path).parse().unwrap();
let exprs = collect_exprs(file);
test_expressions(edition, exprs)
}
Err(msg) => {
errorf!("syn failed to parse\n{:?}\n", msg);
(0, 1)
}
};
errorf!(
"=== {}: {} passed | {} failed\n",
path.display(),
l_passed,
l_failed
);
passed.fetch_add(l_passed, Ordering::Relaxed);
let prev_failed = failed.fetch_add(l_failed, Ordering::Relaxed);
if prev_failed + l_failed >= abort_after {
process::exit(1);
}
});
let passed = passed.load(Ordering::Relaxed);
let failed = failed.load(Ordering::Relaxed);
errorf!("\n===== Precedence Test Results =====\n");
errorf!("{} passed | {} failed\n", passed, failed);
if failed > 0 {
panic!("{} failures", failed);
}
}
fn test_expressions(edition: Edition, exprs: Vec<syn::Expr>) -> (usize, usize) {
let mut passed = 0;
let mut failed = 0;
rustc_span::create_session_if_not_set_then(edition, |_| {
for expr in exprs {
let raw = quote!(#expr).to_string();
let librustc_ast = if let Some(e) = librustc_parse_and_rewrite(&raw) {
e
} else {
failed += 1;
errorf!("\nFAIL - librustc failed to parse raw\n");
continue;
};
let syn_expr = syn_brackets(expr);
let syn_ast = if let Some(e) = parse::librustc_expr(&quote!(#syn_expr).to_string()) {
e
} else {
failed += 1;
errorf!("\nFAIL - librustc failed to parse bracketed\n");
continue;
};
if SpanlessEq::eq(&syn_ast, &librustc_ast) {
passed += 1;
} else {
failed += 1;
errorf!("\nFAIL\n{:?}\n!=\n{:?}\n", syn_ast, librustc_ast);
}
}
});
(passed, failed)
}
fn librustc_parse_and_rewrite(input: &str) -> Option<P<ast::Expr>> {
parse::librustc_expr(input).and_then(librustc_brackets)
}
/// Wrap every expression which is not already wrapped in parens with parens, to
/// reveal the precedence of the parsed expressions, and produce a stringified
/// form of the resulting expression.
///
/// This method operates on librustc objects.
fn librustc_brackets(mut librustc_expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
use rustc_ast::ast::{
Attribute, Block, BorrowKind, Expr, ExprField, ExprKind, GenericArg, Local, LocalKind, Pat,
Stmt, StmtKind, StructExpr, StructRest, Ty,
};
use rustc_ast::mut_visit::{noop_visit_generic_arg, noop_visit_local, MutVisitor};
use rustc_data_structures::map_in_place::MapInPlace;
use rustc_span::DUMMY_SP;
use std::mem;
use std::ops::DerefMut;
use thin_vec::ThinVec;
struct BracketsVisitor {
failed: bool,
}
fn flat_map_field<T: MutVisitor>(mut f: ExprField, vis: &mut T) -> Vec<ExprField> {
if f.is_shorthand {
noop_visit_expr(&mut f.expr, vis);
} else {
vis.visit_expr(&mut f.expr);
}
vec![f]
}
fn flat_map_stmt<T: MutVisitor>(stmt: Stmt, vis: &mut T) -> Vec<Stmt> {
let kind = match stmt.kind {
// Don't wrap toplevel expressions in statements.
StmtKind::Expr(mut e) => {
noop_visit_expr(&mut e, vis);
StmtKind::Expr(e)
}
StmtKind::Semi(mut e) => {
noop_visit_expr(&mut e, vis);
StmtKind::Semi(e)
}
s => s,
};
vec![Stmt { kind, ..stmt }]
}
fn noop_visit_expr<T: MutVisitor>(e: &mut Expr, vis: &mut T) {
use rustc_ast::mut_visit::{noop_visit_expr, visit_attrs};
match &mut e.kind {
ExprKind::AddrOf(BorrowKind::Raw, ..) => {}
ExprKind::Struct(expr) => {
let StructExpr {
qself,
path,
fields,
rest,
} = expr.deref_mut();
vis.visit_qself(qself);
vis.visit_path(path);
fields.flat_map_in_place(|field| flat_map_field(field, vis));
if let StructRest::Base(rest) = rest {
vis.visit_expr(rest);
}
vis.visit_id(&mut e.id);
vis.visit_span(&mut e.span);
visit_attrs(&mut e.attrs, vis);
}
_ => noop_visit_expr(e, vis),
}
}
impl MutVisitor for BracketsVisitor {
fn visit_expr(&mut self, e: &mut P<Expr>) {
match e.kind {
ExprKind::ConstBlock(..) => {}
_ => noop_visit_expr(e, self),
}
match e.kind {
ExprKind::If(..) | ExprKind::Block(..) | ExprKind::Let(..) => {}
_ => {
let inner = mem::replace(
e,
P(Expr {
id: ast::DUMMY_NODE_ID,
kind: ExprKind::Err,
span: DUMMY_SP,
attrs: ThinVec::new(),
tokens: None,
}),
);
e.kind = ExprKind::Paren(inner);
}
}
}
fn visit_generic_arg(&mut self, arg: &mut GenericArg) {
match arg {
// Don't wrap unbraced const generic arg as that's invalid syntax.
GenericArg::Const(anon_const) => {
if let ExprKind::Block(..) = &mut anon_const.value.kind {
noop_visit_expr(&mut anon_const.value, self);
}
}
_ => noop_visit_generic_arg(arg, self),
}
}
fn visit_block(&mut self, block: &mut P<Block>) {
self.visit_id(&mut block.id);
block
.stmts
.flat_map_in_place(|stmt| flat_map_stmt(stmt, self));
self.visit_span(&mut block.span);
}
fn visit_local(&mut self, local: &mut P<Local>) {
match local.kind {
LocalKind::InitElse(..) => {}
_ => noop_visit_local(local, self),
}
}
// We don't want to look at expressions that might appear in patterns or
// types yet. We'll look into comparing those in the future. For now
// focus on expressions appearing in other places.
fn visit_pat(&mut self, pat: &mut P<Pat>) {
_ = pat;
}
fn visit_ty(&mut self, ty: &mut P<Ty>) {
_ = ty;
}
fn visit_attribute(&mut self, attr: &mut Attribute) {
_ = attr;
}
}
let mut folder = BracketsVisitor { failed: false };
folder.visit_expr(&mut librustc_expr);
if folder.failed {
None
} else {
Some(librustc_expr)
}
}
/// Wrap every expression which is not already wrapped in parens with parens, to
/// reveal the precedence of the parsed expressions, and produce a stringified
/// form of the resulting expression.
fn syn_brackets(syn_expr: syn::Expr) -> syn::Expr {
use syn::fold::{fold_expr, fold_generic_argument, fold_generic_method_argument, Fold};
use syn::{token, Expr, ExprParen, GenericArgument, GenericMethodArgument, Pat, Stmt, Type};
struct ParenthesizeEveryExpr;
impl Fold for ParenthesizeEveryExpr {
fn fold_expr(&mut self, expr: Expr) -> Expr {
match expr {
Expr::Group(_) => unreachable!(),
Expr::If(..) | Expr::Unsafe(..) | Expr::Block(..) | Expr::Let(..) => {
fold_expr(self, expr)
}
_ => Expr::Paren(ExprParen {
attrs: Vec::new(),
expr: Box::new(fold_expr(self, expr)),
paren_token: token::Paren::default(),
}),
}
}
fn fold_generic_argument(&mut self, arg: GenericArgument) -> GenericArgument {
match arg {
GenericArgument::Const(arg) => GenericArgument::Const(match arg {
Expr::Block(_) => fold_expr(self, arg),
// Don't wrap unbraced const generic arg as that's invalid syntax.
_ => arg,
}),
_ => fold_generic_argument(self, arg),
}
}
fn fold_generic_method_argument(
&mut self,
arg: GenericMethodArgument,
) -> GenericMethodArgument {
match arg {
GenericMethodArgument::Const(arg) => GenericMethodArgument::Const(match arg {
Expr::Block(_) => fold_expr(self, arg),
// Don't wrap unbraced const generic arg as that's invalid syntax.
_ => arg,
}),
_ => fold_generic_method_argument(self, arg),
}
}
fn fold_stmt(&mut self, stmt: Stmt) -> Stmt {
match stmt {
// Don't wrap toplevel expressions in statements.
Stmt::Expr(e) => Stmt::Expr(fold_expr(self, e)),
Stmt::Semi(e, semi) => {
if let Expr::Verbatim(_) = e {
Stmt::Semi(e, semi)
} else {
Stmt::Semi(fold_expr(self, e), semi)
}
}
s => s,
}
}
// We don't want to look at expressions that might appear in patterns or
// types yet. We'll look into comparing those in the future. For now
// focus on expressions appearing in other places.
fn fold_pat(&mut self, pat: Pat) -> Pat {
pat
}
fn fold_type(&mut self, ty: Type) -> Type {
ty
}
}
let mut folder = ParenthesizeEveryExpr;
folder.fold_expr(syn_expr)
}
/// Walk through a crate collecting all expressions we can find in it.
fn collect_exprs(file: syn::File) -> Vec<syn::Expr> {
use syn::fold::Fold;
use syn::punctuated::Punctuated;
use syn::{token, ConstParam, Expr, ExprTuple, Path};
struct CollectExprs(Vec<Expr>);
impl Fold for CollectExprs {
fn fold_expr(&mut self, expr: Expr) -> Expr {
match expr {
Expr::Verbatim(_) => {}
_ => self.0.push(expr),
}
Expr::Tuple(ExprTuple {
attrs: vec![],
elems: Punctuated::new(),
paren_token: token::Paren::default(),
})
}
fn fold_path(&mut self, path: Path) -> Path {
// Skip traversing into const generic path arguments
path
}
fn fold_const_param(&mut self, const_param: ConstParam) -> ConstParam {
const_param
}
}
let mut folder = CollectExprs(vec![]);
folder.fold_file(file);
folder.0
}

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

@ -1,127 +0,0 @@
use syn::{parse_quote, FnArg, Receiver, TraitItemMethod};
#[test]
fn test_by_value() {
let TraitItemMethod { sig, .. } = parse_quote! {
fn by_value(self: Self);
};
match sig.receiver() {
Some(FnArg::Typed(_)) => (),
value => panic!("expected FnArg::Typed, got {:?}", value),
}
}
#[test]
fn test_by_mut_value() {
let TraitItemMethod { sig, .. } = parse_quote! {
fn by_mut(mut self: Self);
};
match sig.receiver() {
Some(FnArg::Typed(_)) => (),
value => panic!("expected FnArg::Typed, got {:?}", value),
}
}
#[test]
fn test_by_ref() {
let TraitItemMethod { sig, .. } = parse_quote! {
fn by_ref(self: &Self);
};
match sig.receiver() {
Some(FnArg::Typed(_)) => (),
value => panic!("expected FnArg::Typed, got {:?}", value),
}
}
#[test]
fn test_by_box() {
let TraitItemMethod { sig, .. } = parse_quote! {
fn by_box(self: Box<Self>);
};
match sig.receiver() {
Some(FnArg::Typed(_)) => (),
value => panic!("expected FnArg::Typed, got {:?}", value),
}
}
#[test]
fn test_by_pin() {
let TraitItemMethod { sig, .. } = parse_quote! {
fn by_pin(self: Pin<Self>);
};
match sig.receiver() {
Some(FnArg::Typed(_)) => (),
value => panic!("expected FnArg::Typed, got {:?}", value),
}
}
#[test]
fn test_explicit_type() {
let TraitItemMethod { sig, .. } = parse_quote! {
fn explicit_type(self: Pin<MyType>);
};
match sig.receiver() {
Some(FnArg::Typed(_)) => (),
value => panic!("expected FnArg::Typed, got {:?}", value),
}
}
#[test]
fn test_value_shorthand() {
let TraitItemMethod { sig, .. } = parse_quote! {
fn value_shorthand(self);
};
match sig.receiver() {
Some(FnArg::Receiver(Receiver {
reference: None,
mutability: None,
..
})) => (),
value => panic!("expected FnArg::Receiver without ref/mut, got {:?}", value),
}
}
#[test]
fn test_mut_value_shorthand() {
let TraitItemMethod { sig, .. } = parse_quote! {
fn mut_value_shorthand(mut self);
};
match sig.receiver() {
Some(FnArg::Receiver(Receiver {
reference: None,
mutability: Some(_),
..
})) => (),
value => panic!("expected FnArg::Receiver with mut, got {:?}", value),
}
}
#[test]
fn test_ref_shorthand() {
let TraitItemMethod { sig, .. } = parse_quote! {
fn ref_shorthand(&self);
};
match sig.receiver() {
Some(FnArg::Receiver(Receiver {
reference: Some(_),
mutability: None,
..
})) => (),
value => panic!("expected FnArg::Receiver with ref, got {:?}", value),
}
}
#[test]
fn test_ref_mut_shorthand() {
let TraitItemMethod { sig, .. } = parse_quote! {
fn ref_mut_shorthand(&mut self);
};
match sig.receiver() {
Some(FnArg::Receiver(Receiver {
reference: Some(_),
mutability: Some(_),
..
})) => (),
value => panic!("expected FnArg::Receiver with ref+mut, got {:?}", value),
}
}

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

@ -1,241 +0,0 @@
#![cfg(not(syn_disable_nightly_tests))]
#![cfg(not(miri))]
#![recursion_limit = "1024"]
#![feature(rustc_private)]
#![allow(clippy::manual_assert)]
extern crate rustc_ast;
extern crate rustc_data_structures;
extern crate rustc_error_messages;
extern crate rustc_errors;
extern crate rustc_expand;
extern crate rustc_parse as parse;
extern crate rustc_session;
extern crate rustc_span;
use crate::common::eq::SpanlessEq;
use quote::quote;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use rustc_ast::ast::{
AngleBracketedArg, AngleBracketedArgs, Crate, GenericArg, GenericParamKind, Generics,
WhereClause,
};
use rustc_ast::mut_visit::{self, MutVisitor};
use rustc_error_messages::{DiagnosticMessage, LazyFallbackBundle};
use rustc_errors::{translation, Diagnostic, PResult};
use rustc_session::parse::ParseSess;
use rustc_span::source_map::FilePathMapping;
use rustc_span::FileName;
use std::fs;
use std::panic;
use std::path::Path;
use std::process;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Instant;
use walkdir::{DirEntry, WalkDir};
#[macro_use]
mod macros;
#[allow(dead_code)]
mod common;
mod repo;
#[test]
fn test_round_trip() {
common::rayon_init();
repo::clone_rust();
let abort_after = common::abort_after();
if abort_after == 0 {
panic!("Skipping all round_trip tests");
}
let failed = AtomicUsize::new(0);
WalkDir::new("tests/rust")
.sort_by(|a, b| a.file_name().cmp(b.file_name()))
.into_iter()
.filter_entry(repo::base_dir_filter)
.collect::<Result<Vec<DirEntry>, walkdir::Error>>()
.unwrap()
.into_par_iter()
.for_each(|entry| {
let path = entry.path();
if !path.is_dir() {
test(path, &failed, abort_after);
}
});
let failed = failed.load(Ordering::Relaxed);
if failed > 0 {
panic!("{} failures", failed);
}
}
fn test(path: &Path, failed: &AtomicUsize, abort_after: usize) {
let content = fs::read_to_string(path).unwrap();
let start = Instant::now();
let (krate, elapsed) = match syn::parse_file(&content) {
Ok(krate) => (krate, start.elapsed()),
Err(msg) => {
errorf!("=== {}: syn failed to parse\n{:?}\n", path.display(), msg);
let prev_failed = failed.fetch_add(1, Ordering::Relaxed);
if prev_failed + 1 >= abort_after {
process::exit(1);
}
return;
}
};
let back = quote!(#krate).to_string();
let edition = repo::edition(path).parse().unwrap();
rustc_span::create_session_if_not_set_then(edition, |_| {
let equal = match panic::catch_unwind(|| {
let sess = ParseSess::new(FilePathMapping::empty());
let before = match librustc_parse(content, &sess) {
Ok(before) => before,
Err(diagnostic) => {
errorf!(
"=== {}: ignore - librustc failed to parse original content: {}\n",
path.display(),
translate_message(&diagnostic),
);
diagnostic.cancel();
return Err(true);
}
};
let after = match librustc_parse(back, &sess) {
Ok(after) => after,
Err(mut diagnostic) => {
errorf!("=== {}: librustc failed to parse", path.display());
diagnostic.emit();
return Err(false);
}
};
Ok((before, after))
}) {
Err(_) => {
errorf!("=== {}: ignoring librustc panic\n", path.display());
true
}
Ok(Err(equal)) => equal,
Ok(Ok((mut before, mut after))) => {
normalize(&mut before);
normalize(&mut after);
if SpanlessEq::eq(&before, &after) {
errorf!(
"=== {}: pass in {}ms\n",
path.display(),
elapsed.as_secs() * 1000 + u64::from(elapsed.subsec_nanos()) / 1_000_000
);
true
} else {
errorf!(
"=== {}: FAIL\nbefore: {:#?}\nafter: {:#?}\n",
path.display(),
before,
after,
);
false
}
}
};
if !equal {
let prev_failed = failed.fetch_add(1, Ordering::Relaxed);
if prev_failed + 1 >= abort_after {
process::exit(1);
}
}
});
}
fn librustc_parse(content: String, sess: &ParseSess) -> PResult<Crate> {
static COUNTER: AtomicUsize = AtomicUsize::new(0);
let counter = COUNTER.fetch_add(1, Ordering::Relaxed);
let name = FileName::Custom(format!("test_round_trip{}", counter));
parse::parse_crate_from_source_str(name, content, sess)
}
fn translate_message(diagnostic: &Diagnostic) -> String {
thread_local! {
static FLUENT_BUNDLE: LazyFallbackBundle = {
let resources = rustc_error_messages::DEFAULT_LOCALE_RESOURCES;
let with_directionality_markers = false;
rustc_error_messages::fallback_fluent_bundle(resources, with_directionality_markers)
};
}
let message = &diagnostic.message[0].0;
let args = translation::to_fluent_args(diagnostic.args());
let (identifier, attr) = match message {
DiagnosticMessage::Str(msg) | DiagnosticMessage::Eager(msg) => return msg.clone(),
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
};
FLUENT_BUNDLE.with(|fluent_bundle| {
let message = fluent_bundle
.get_message(identifier)
.expect("missing diagnostic in fluent bundle");
let value = match attr {
Some(attr) => message
.get_attribute(attr)
.expect("missing attribute in fluent message")
.value(),
None => message.value().expect("missing value in fluent message"),
};
let mut err = Vec::new();
let translated = fluent_bundle.format_pattern(value, Some(&args), &mut err);
assert!(err.is_empty());
translated.into_owned()
})
}
fn normalize(krate: &mut Crate) {
struct NormalizeVisitor;
impl MutVisitor for NormalizeVisitor {
fn visit_angle_bracketed_parameter_data(&mut self, e: &mut AngleBracketedArgs) {
#[derive(Ord, PartialOrd, Eq, PartialEq)]
enum Group {
Lifetimes,
TypesAndConsts,
Constraints,
}
e.args.sort_by_key(|arg| match arg {
AngleBracketedArg::Arg(arg) => match arg {
GenericArg::Lifetime(_) => Group::Lifetimes,
GenericArg::Type(_) | GenericArg::Const(_) => Group::TypesAndConsts,
},
AngleBracketedArg::Constraint(_) => Group::Constraints,
});
mut_visit::noop_visit_angle_bracketed_parameter_data(e, self);
}
fn visit_generics(&mut self, e: &mut Generics) {
#[derive(Ord, PartialOrd, Eq, PartialEq)]
enum Group {
Lifetimes,
TypesAndConsts,
}
e.params.sort_by_key(|param| match param.kind {
GenericParamKind::Lifetime => Group::Lifetimes,
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
Group::TypesAndConsts
}
});
mut_visit::noop_visit_generics(e, self);
}
fn visit_where_clause(&mut self, e: &mut WhereClause) {
if e.predicates.is_empty() {
e.has_where_token = false;
}
}
}
NormalizeVisitor.visit_crate(krate);
}

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

@ -1,59 +0,0 @@
#[macro_use]
mod macros;
#[test]
fn test_basic() {
let content = "#!/usr/bin/env rustx\nfn main() {}";
let file = syn::parse_file(content).unwrap();
snapshot!(file, @r###"
File {
shebang: Some("#!/usr/bin/env rustx"),
items: [
Item::Fn {
vis: Inherited,
sig: Signature {
ident: "main",
generics: Generics,
output: Default,
},
block: Block,
},
],
}
"###);
}
#[test]
fn test_comment() {
let content = "#!//am/i/a/comment\n[allow(dead_code)] fn main() {}";
let file = syn::parse_file(content).unwrap();
snapshot!(file, @r###"
File {
attrs: [
Attribute {
style: Inner,
path: Path {
segments: [
PathSegment {
ident: "allow",
arguments: None,
},
],
},
tokens: TokenStream(`(dead_code)`),
},
],
items: [
Item::Fn {
vis: Inherited,
sig: Signature {
ident: "main",
generics: Generics,
output: Default,
},
block: Block,
},
],
}
"###);
}

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

@ -1,45 +0,0 @@
macro_rules! should_parse {
($name:ident, { $($in:tt)* }) => {
#[test]
fn $name() {
// Make sure we can parse the file!
syn::parse_file(stringify!($($in)*)).unwrap();
}
}
}
should_parse!(generic_associated_type, {
impl Foo {
type Item = &'a i32;
fn foo<'a>(&'a self) -> Self::Item<'a> {}
}
});
#[rustfmt::skip]
should_parse!(const_generics_use, {
type X = Foo<5>;
type Y = Foo<"foo">;
type Z = Foo<X>;
type W = Foo<{ X + 10 }>;
});
should_parse!(trailing_plus_type, {
type A = Box<Foo>;
type A = Box<Foo + 'a>;
type A = Box<'a + Foo>;
});
should_parse!(generic_associated_type_where, {
trait Foo {
type Item;
fn foo<T>(&self, t: T) -> Self::Item<T>;
}
});
should_parse!(match_with_block_expr, {
fn main() {
match false {
_ => {}.a(),
}
}
});

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

@ -1,29 +0,0 @@
#![cfg(target_pointer_width = "64")]
use std::mem;
use syn::{Expr, Item, Lit, Pat, Type};
#[test]
fn test_expr_size() {
assert_eq!(mem::size_of::<Expr>(), 272);
}
#[test]
fn test_item_size() {
assert_eq!(mem::size_of::<Item>(), 320);
}
#[test]
fn test_type_size() {
assert_eq!(mem::size_of::<Type>(), 288);
}
#[test]
fn test_pat_size() {
assert_eq!(mem::size_of::<Pat>(), 144);
}
#[test]
fn test_lit_size() {
assert_eq!(mem::size_of::<Lit>(), 32);
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше