diff options
author | Chih-Hung Hsieh <chh@google.com> | 2019-10-29 11:20:20 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-10-29 11:20:20 -0700 |
commit | ec06d6de3a92f954f0677cc471e9e47ee8feea14 (patch) | |
tree | 4ddf85cf2a25a2c5997c0a3cfb87df65667592b9 | |
parent | 01f0fbb7fddcc04c30905cdc29669505e1baa260 (diff) | |
parent | f790783e0e661ee737b736de847da5230b70766b (diff) | |
download | syn-ec06d6de3a92f954f0677cc471e9e47ee8feea14.tar.gz |
Use released syn-0.15.42 at crates.io am: ec8f5e4e5d am: e7d1f08620
am: f790783e0e
Change-Id: I28cbe2a8480ff6ccb5d590ac7141a15dce759de0
53 files changed, 153 insertions, 9256 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json new file mode 100644 index 00000000..86ad91ef --- /dev/null +++ b/.cargo_vcs_info.json @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "b48a2b922e19968c3335fa8fd5a27eadbfa4414f" + } +} diff --git a/.gitignore b/.gitignore deleted file mode 100644 index aba0fb5d..00000000 --- a/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -target -Cargo.lock -tests/rust/* -!tests/rust/clone.sh diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 19b988d4..00000000 --- a/.travis.yml +++ /dev/null @@ -1,72 +0,0 @@ -sudo: false -language: rust - -rust: - - nightly - - stable - - beta - - 1.15.1 - -before_script: - - set -o errexit - -script: - - shopt -s expand_aliases - - alias build="cargo build ${TARGET+--target=$TARGET}" - - build --no-default-features - - build - - build --features full - - build --features 'fold visit visit-mut' - - build --features 'full fold visit visit-mut' - - build --no-default-features --features derive - - build --no-default-features --features 'derive parsing' - - build --no-default-features --features 'derive printing' - - build --no-default-features --features 'proc-macro parsing printing' - - build --no-default-features --features full - - build --no-default-features --features 'full parsing' - - build --no-default-features --features 'full printing' - - build --no-default-features --features 'full parsing printing' - - build --no-default-features --features 'fold visit visit-mut parsing printing' - - build --no-default-features --features 'full fold visit visit-mut parsing printing' - -matrix: - include: - - rust: nightly - name: Tests - script: - - cargo test --all-features --release - - rust: nightly - name: Examples - script: - - cargo check --manifest-path examples/dump-syntax/Cargo.toml - - cargo check --manifest-path examples/heapsize/example/Cargo.toml - - cargo check --manifest-path examples/lazy-static/example/Cargo.toml - - cargo check --manifest-path examples/trace-var/example/Cargo.toml - - rust: nightly - name: Codegen - script: - - (cd codegen && cargo run) - - git diff --exit-code - - rust: nightly - name: Minimal versions - script: - - cargo update -Z minimal-versions - - cargo build --all-features - - rust: nightly - name: Clippy - script: - - rustup component add clippy || travis_terminate 0 - - cargo clippy --all-features - - rust: nightly - name: WebAssembly - env: TARGET=wasm32-unknown-unknown - install: - - rustup target add "${TARGET}" - allow_failures: - - rust: nightly - name: Clippy - fast_finish: true - -env: - global: - - RUST_MIN_STACK=20000000 @@ -1,23 +1,32 @@ +// This file is generated by cargo2android.py. + rust_library_rlib { name: "libsyn", - deny_warnings: false, + host_supported: true, crate_name: "syn", - edition: "2015", srcs: ["src/lib.rs"], - host_supported: true, - + edition: "2015", features: [ - "full", - "visit-mut", + "clone-impls", + "default", "derive", + "full", "parsing", "printing", - "clone-impls", "proc-macro", + "quote", + "visit-mut", + ], + flags: [ + "--cfg syn_can_call_macro_by_path", + "--cfg syn_can_match_trailing_dollar", + "--cfg syn_can_use_associated_constants", + "--cfg syn_can_use_thread_id", + "--cfg syn_disable_nightly_tests", ], rlibs: [ "libproc_macro2", - "libunicode_xid", "libquote", + "libunicode_xid", ], } @@ -1,69 +1,82 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + [package] name = "syn" -version = "0.15.42" # don't forget to update html_root_url and syn.json +version = "0.15.42" authors = ["David Tolnay <dtolnay@gmail.com>"] -license = "MIT OR Apache-2.0" +include = ["/benches/**", "/build.rs", "/Cargo.toml", "/LICENSE-APACHE", "/LICENSE-MIT", "/README.md", "/src/**", "/tests/**"] description = "Parser for Rust source code" -repository = "https://github.com/dtolnay/syn" documentation = "https://docs.rs/syn" -categories = ["development-tools::procedural-macro-helpers"] readme = "README.md" -include = [ - "/benches/**", - "/build.rs", - "/Cargo.toml", - "/LICENSE-APACHE", - "/LICENSE-MIT", - "/README.md", - "/src/**", - "/tests/**", -] - -[features] -default = ["derive", "parsing", "printing", "clone-impls", "proc-macro"] -derive = [] -full = [] -parsing = [] -printing = ["quote"] -visit = [] -visit-mut = [] -fold = [] -clone-impls = [] -extra-traits = [] -proc-macro = ["proc-macro2/proc-macro", "quote/proc-macro"] - -[dependencies] -proc-macro2 = { version = "0.4.4", default-features = false } -quote = { version = "0.6", optional = true, default-features = false } -unicode-xid = "0.1" +categories = ["development-tools::procedural-macro-helpers"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/syn" +[package.metadata.docs.rs] +all-features = true -[dev-dependencies] -insta = "0.8" -rayon = "1.0" -ref-cast = "0.2" -regex = "1.0" -termcolor = "1.0" -walkdir = "2.1" +[package.metadata.playground] +all-features = true [[bench]] name = "rust" -edition = "2018" harness = false required-features = ["full", "parsing"] +edition = "2018" [[bench]] name = "file" -edition = "2018" required-features = ["full", "parsing"] +edition = "2018" +[dependencies.proc-macro2] +version = "0.4.4" +default-features = false -[package.metadata.docs.rs] -all-features = true +[dependencies.quote] +version = "0.6" +optional = true +default-features = false -[package.metadata.playground] -all-features = true +[dependencies.unicode-xid] +version = "0.1" +[dev-dependencies.insta] +version = "0.8" + +[dev-dependencies.rayon] +version = "1.0" + +[dev-dependencies.ref-cast] +version = "0.2" + +[dev-dependencies.regex] +version = "1.0" + +[dev-dependencies.termcolor] +version = "1.0" -[badges] -travis-ci = { repository = "dtolnay/syn" } +[dev-dependencies.walkdir] +version = "2.1" -[workspace] -members = ["dev", "json"] +[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"] +visit = [] +visit-mut = [] +[badges.travis-ci] +repository = "dtolnay/syn" diff --git a/Cargo.toml.orig b/Cargo.toml.orig new file mode 100644 index 00000000..b518df96 --- /dev/null +++ b/Cargo.toml.orig @@ -0,0 +1,69 @@ +[package] +name = "syn" +version = "0.15.42" # don't forget to update html_root_url and syn.json +authors = ["David Tolnay <dtolnay@gmail.com>"] +license = "MIT OR Apache-2.0" +description = "Parser for Rust source code" +repository = "https://github.com/dtolnay/syn" +documentation = "https://docs.rs/syn" +categories = ["development-tools::procedural-macro-helpers"] +readme = "README.md" +include = [ + "/benches/**", + "/build.rs", + "/Cargo.toml", + "/LICENSE-APACHE", + "/LICENSE-MIT", + "/README.md", + "/src/**", + "/tests/**", +] + +[features] +default = ["derive", "parsing", "printing", "clone-impls", "proc-macro"] +derive = [] +full = [] +parsing = [] +printing = ["quote"] +visit = [] +visit-mut = [] +fold = [] +clone-impls = [] +extra-traits = [] +proc-macro = ["proc-macro2/proc-macro", "quote/proc-macro"] + +[dependencies] +proc-macro2 = { version = "0.4.4", default-features = false } +quote = { version = "0.6", optional = true, default-features = false } +unicode-xid = "0.1" + +[dev-dependencies] +insta = "0.8" +rayon = "1.0" +ref-cast = "0.2" +regex = "1.0" +termcolor = "1.0" +walkdir = "2.1" + +[[bench]] +name = "rust" +edition = "2018" +harness = false +required-features = ["full", "parsing"] + +[[bench]] +name = "file" +edition = "2018" +required-features = ["full", "parsing"] + +[package.metadata.docs.rs] +all-features = true + +[package.metadata.playground] +all-features = true + +[badges] +travis-ci = { repository = "dtolnay/syn" } + +[workspace] +members = ["dev", "json"] diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 020c8ac6..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,16 +0,0 @@ -environment: - matrix: - - TARGET: x86_64-pc-windows-msvc - -install: - - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" - - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - - SET PATH=%PATH%;C:\MinGW\bin - - rustc -V - - cargo -V - -build: false - -test_script: - - cargo build --all-features diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml deleted file mode 100644 index 2828494b..00000000 --- a/codegen/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "syn-internal-codegen" -version = "0.0.0" -authors = ["Nika Layzell <nika@thelayzells.com>"] -edition = "2018" - -publish = false # this is an internal crate which should never be published - -[dependencies] -syn = { path = "..", features = ["full", "extra-traits"] } -quote = "0.6" -failure = "0.1" -indexmap = { version = "1.0", features = ["serde-1"] } -inflections = "1.1" -proc-macro2 = "0.4" -rustfmt = { package = "rustfmt-nightly", git = "https://github.com/rust-lang-nursery/rustfmt" } -serde = { version = "1.0.88", features = ["derive"] } -serde_json = "1.0.38" -toml = "0.4.10" -semver = { version = "0.9", features = ["serde"] } -syn-codegen = { path = "../json" } - -[workspace] -# Prefer that `cargo clean` in syn's directory does not require a rebuild of -# rustfmt in the codegen directory. diff --git a/codegen/README.md b/codegen/README.md deleted file mode 100644 index df46bd25..00000000 --- a/codegen/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# syn_codegen - -This is an internal (not published on crates.io) crate which is used to generate -the files in the `gen/` directory of `syn`. It is used to ensure that the -implementations for `Fold`, `Visit`, and `VisitMut` remain in sync with the -actual AST. - -To run this program, run `cargo run` in this directory, and the `gen/` folder -will be re-generated. - -This program is slow, and is therefore not run when building `syn` as part of -the build script to save on compile time. diff --git a/codegen/src/debug.rs b/codegen/src/debug.rs deleted file mode 100644 index f4578104..00000000 --- a/codegen/src/debug.rs +++ /dev/null @@ -1,291 +0,0 @@ -use crate::error::Result; -use crate::file; -use proc_macro2::{Ident, Span, TokenStream}; -use quote::quote; -use syn::Index; -use syn_codegen::{Data, Definitions, Node, Type}; - -const DEBUG_SRC: &str = "../tests/debug/gen.rs"; - -fn rust_type(ty: &Type) -> TokenStream { - match ty { - Type::Syn(ty) => { - let ident = Ident::new(ty, Span::call_site()); - quote!(syn::#ident) - } - Type::Std(ty) => { - let ident = Ident::new(ty, Span::call_site()); - quote!(#ident) - } - Type::Ext(ty) => { - let ident = Ident::new(ty, Span::call_site()); - quote!(proc_macro2::#ident) - } - Type::Token(ty) | Type::Group(ty) => { - let ident = Ident::new(ty, Span::call_site()); - quote!(syn::token::#ident) - } - Type::Punctuated(ty) => { - let element = rust_type(&ty.element); - let punct = Ident::new(&ty.punct, Span::call_site()); - quote!(syn::punctuated::Punctuated<#element, #punct>) - } - Type::Option(ty) => { - let inner = rust_type(ty); - quote!(Option<#inner>) - } - Type::Box(ty) => { - let inner = rust_type(ty); - quote!(Box<#inner>) - } - Type::Vec(ty) => { - let inner = rust_type(ty); - quote!(Vec<#inner>) - } - Type::Tuple(ty) => { - let inner = ty.iter().map(rust_type); - quote!((#(#inner,)*)) - } - } -} - -fn is_printable(ty: &Type) -> bool { - match ty { - Type::Ext(name) => name != "Span", - Type::Box(ty) => is_printable(ty), - Type::Tuple(ty) => ty.iter().any(is_printable), - Type::Token(_) | Type::Group(_) => false, - Type::Syn(_) | Type::Std(_) | Type::Punctuated(_) | Type::Option(_) | Type::Vec(_) => true, - } -} - -fn format_field(val: &TokenStream, ty: &Type) -> Option<TokenStream> { - if !is_printable(ty) { - return None; - } - let format = match ty { - Type::Option(ty) => { - let inner = quote!(_val); - let format = format_field(&inner, ty).map(|format| { - quote! { - formatter.write_str("(")?; - Debug::fmt(#format, formatter)?; - formatter.write_str(")")?; - } - }); - let ty = rust_type(ty); - quote!({ - #[derive(RefCast)] - #[repr(transparent)] - struct Print(Option<#ty>); - impl Debug for Print { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - match &self.0 { - Some(#inner) => { - formatter.write_str("Some")?; - #format - Ok(()) - } - None => formatter.write_str("None"), - } - } - } - Print::ref_cast(#val) - }) - } - Type::Tuple(ty) => { - let printable: Vec<TokenStream> = ty - .iter() - .enumerate() - .filter_map(|(i, ty)| { - let index = Index::from(i); - let val = quote!(&#val.#index); - format_field(&val, ty) - }) - .collect(); - if printable.len() == 1 { - printable.into_iter().next().unwrap() - } else { - quote! { - &(#(#printable),*) - } - } - } - _ => quote! { Lite(#val) }, - }; - Some(format) -} - -fn syntax_tree_enum<'a>(outer: &str, inner: &str, fields: &'a [Type]) -> Option<&'a str> { - if fields.len() != 1 { - return None; - } - const WHITELIST: &[&str] = &["PathArguments", "Visibility"]; - match &fields[0] { - Type::Syn(ty) if WHITELIST.contains(&outer) || outer.to_owned() + inner == *ty => Some(ty), - _ => None, - } -} - -fn lookup<'a>(defs: &'a Definitions, name: &str) -> &'a Node { - for node in &defs.types { - if node.ident == name { - return node; - } - } - panic!("not found: {}", name) -} - -fn expand_impl_body(defs: &Definitions, node: &Node, name: &str) -> TokenStream { - let ident = Ident::new(&node.ident, Span::call_site()); - - match &node.data { - Data::Enum(variants) => { - let arms = variants.iter().map(|(v, fields)| { - let variant = Ident::new(v, Span::call_site()); - if fields.is_empty() { - quote! { - syn::#ident::#variant => formatter.write_str(#v), - } - } else if let Some(inner) = syntax_tree_enum(name, v, fields) { - let path = format!("{}::{}", name, v); - let format = expand_impl_body(defs, lookup(defs, inner), &path); - quote! { - syn::#ident::#variant(_val) => { - #format - } - } - } else if fields.len() == 1 { - let ty = &fields[0]; - let val = quote!(_val); - let format = format_field(&val, ty).map(|format| { - quote! { - formatter.write_str("(")?; - Debug::fmt(#format, formatter)?; - formatter.write_str(")")?; - } - }); - quote! { - syn::#ident::#variant(_val) => { - formatter.write_str(#v)?; - #format - Ok(()) - } - } - } else { - let pats = (0..fields.len()) - .map(|i| Ident::new(&format!("_v{}", i), Span::call_site())); - let fields = fields.iter().enumerate().filter_map(|(i, ty)| { - let index = Ident::new(&format!("_v{}", i), Span::call_site()); - let val = quote!(#index); - let format = format_field(&val, ty)?; - Some(quote! { - formatter.field(#format); - }) - }); - quote! { - syn::#ident::#variant(#(#pats),*) => { - let mut formatter = formatter.debug_tuple(#v); - #(#fields)* - formatter.finish() - } - } - } - }); - quote! { - match _val { - #(#arms)* - } - } - } - Data::Struct(fields) => { - let fields = fields.iter().filter_map(|(f, ty)| { - let ident = Ident::new(f, Span::call_site()); - if let Type::Option(ty) = ty { - let inner = quote!(_val); - let format = format_field(&inner, ty).map(|format| { - quote! { - let #inner = &self.0; - formatter.write_str("(")?; - Debug::fmt(#format, formatter)?; - formatter.write_str(")")?; - } - }); - let ty = rust_type(ty); - Some(quote! { - if let Some(val) = &_val.#ident { - #[derive(RefCast)] - #[repr(transparent)] - struct Print(#ty); - impl Debug for Print { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("Some")?; - #format - Ok(()) - } - } - formatter.field(#f, Print::ref_cast(val)); - } - }) - } else { - let val = quote!(&_val.#ident); - let format = format_field(&val, ty)?; - let mut call = quote! { - formatter.field(#f, #format); - }; - if let Type::Vec(_) | Type::Punctuated(_) = ty { - call = quote! { - if !_val.#ident.is_empty() { - #call - } - }; - } - Some(call) - } - }); - quote! { - let mut formatter = formatter.debug_struct(#name); - #(#fields)* - formatter.finish() - } - } - Data::Private => { - quote! { - write!(formatter, "{:?}", _val.value()) - } - } - } -} - -fn expand_impl(defs: &Definitions, node: &Node) -> TokenStream { - let ident = Ident::new(&node.ident, Span::call_site()); - let body = expand_impl_body(defs, node, &node.ident); - - quote! { - impl Debug for Lite<syn::#ident> { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - let _val = &self.value; - #body - } - } - } -} - -pub fn generate(defs: &Definitions) -> Result<()> { - let mut impls = TokenStream::new(); - for node in &defs.types { - impls.extend(expand_impl(&defs, node)); - } - - file::write( - DEBUG_SRC, - quote! { - use super::{Lite, RefCast}; - use std::fmt::{self, Debug}; - - #impls - }, - )?; - - Ok(()) -} diff --git a/codegen/src/error.rs b/codegen/src/error.rs deleted file mode 100644 index 0b3f191d..00000000 --- a/codegen/src/error.rs +++ /dev/null @@ -1,59 +0,0 @@ -use std::fmt::{self, Display}; -use std::io; - -pub type Result<T> = std::result::Result<T, Error>; - -#[derive(Debug)] -pub enum Error { - Io(io::Error), - Json(serde_json::Error), - Rustfmt(rustfmt::ErrorKind), - Syn(syn::Error), - Toml(toml::de::Error), -} - -impl Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::Error::*; - - match self { - Io(e) => write!(f, "{}", e), - Json(e) => write!(f, "{}", e), - Rustfmt(e) => write!(f, "{}", e), - Syn(e) => write!(f, "{}", e), - Toml(e) => write!(f, "{}", e), - } - } -} - -impl std::error::Error for Error {} - -impl From<io::Error> for Error { - fn from(e: io::Error) -> Self { - Error::Io(e) - } -} - -impl From<rustfmt::ErrorKind> for Error { - fn from(e: rustfmt::ErrorKind) -> Self { - Error::Rustfmt(e) - } -} - -impl From<serde_json::Error> for Error { - fn from(e: serde_json::Error) -> Self { - Error::Json(e) - } -} - -impl From<syn::Error> for Error { - fn from(e: syn::Error) -> Self { - Error::Syn(e) - } -} - -impl From<toml::de::Error> for Error { - fn from(e: toml::de::Error) -> Self { - Error::Toml(e) - } -} diff --git a/codegen/src/file.rs b/codegen/src/file.rs deleted file mode 100644 index 8029afe3..00000000 --- a/codegen/src/file.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::error::Result; -use proc_macro2::TokenStream; -use std::fs; -use std::io::Write; -use std::path::Path; - -pub fn write<P: AsRef<Path>>(path: P, content: TokenStream) -> Result<()> { - let mut formatted = Vec::new(); - writeln!(formatted, "// This file is @generated by syn-internal-codegen.")?; - writeln!(formatted, "// It is not intended for manual editing.")?; - writeln!(formatted)?; - - let mut config = rustfmt::Config::default(); - config.set().emit_mode(rustfmt::EmitMode::Stdout); - config.set().verbose(rustfmt::Verbosity::Quiet); - config.set().format_macro_matchers(true); - config.set().normalize_doc_attributes(true); - - let mut session = rustfmt::Session::new(config, Some(&mut formatted)); - session.format(rustfmt::Input::Text(content.to_string()))?; - drop(session); - - if path.as_ref().is_file() && fs::read(&path)? == formatted { - return Ok(()); - } - - fs::write(path, formatted)?; - Ok(()) -} diff --git a/codegen/src/fold.rs b/codegen/src/fold.rs deleted file mode 100644 index 21e8f3bf..00000000 --- a/codegen/src/fold.rs +++ /dev/null @@ -1,262 +0,0 @@ -use crate::error::Result; -use crate::{file, full, gen}; -use proc_macro2::{Ident, Span, TokenStream}; -use quote::quote; -use syn::Index; -use syn_codegen::{Data, Definitions, Features, Node, Type}; - -const FOLD_SRC: &str = "../src/gen/fold.rs"; - -fn simple_visit(item: &str, name: &TokenStream) -> TokenStream { - let ident = gen::under_name(item); - let method = Ident::new(&format!("fold_{}", ident), Span::call_site()); - quote! { - _visitor.#method(#name) - } -} - -fn visit( - ty: &Type, - features: &Features, - defs: &Definitions, - name: &TokenStream, -) -> Option<TokenStream> { - match ty { - Type::Box(t) => { - let res = visit(t, features, defs, "e!(*#name))?; - Some(quote! { - Box::new(#res) - }) - } - Type::Vec(t) => { - let operand = quote!(it); - let val = visit(t, features, defs, &operand)?; - Some(quote! { - FoldHelper::lift(#name, |it| { #val }) - }) - } - Type::Punctuated(p) => { - let operand = quote!(it); - let val = visit(&p.element, features, defs, &operand)?; - Some(quote! { - FoldHelper::lift(#name, |it| { #val }) - }) - } - Type::Option(t) => { - let it = quote!(it); - let val = visit(t, features, defs, &it)?; - Some(quote! { - (#name).map(|it| { #val }) - }) - } - Type::Tuple(t) => { - let mut code = TokenStream::new(); - for (i, elem) in t.iter().enumerate() { - let i = Index::from(i); - let it = quote!((#name).#i); - let val = visit(elem, features, defs, &it).unwrap_or(it); - code.extend(val); - code.extend(quote!(,)); - } - Some(quote! { - (#code) - }) - } - Type::Token(t) => { - let repr = &defs.tokens[t]; - let is_keyword = repr.chars().next().unwrap().is_alphabetic(); - let spans = if is_keyword { - quote!(span) - } else { - quote!(spans) - }; - let ty: TokenStream = syn::parse_str(&format!("Token![{}]", repr)).unwrap(); - Some(quote! { - #ty(tokens_helper(_visitor, &#name.#spans)) - }) - } - Type::Group(t) => { - let ty = Ident::new(t, Span::call_site()); - Some(quote! { - #ty(tokens_helper(_visitor, &#name.span)) - }) - } - Type::Syn(t) => { - fn requires_full(features: &Features) -> bool { - features.any.contains("full") && features.any.len() == 1 - } - let mut res = simple_visit(t, name); - let target = defs.types.iter().find(|ty| ty.ident == *t).unwrap(); - if requires_full(&target.features) && !requires_full(features) { - res = quote!(full!(#res)); - } - Some(res) - } - Type::Ext(t) if gen::TERMINAL_TYPES.contains(&&t[..]) => Some(simple_visit(t, name)), - Type::Ext(_) | Type::Std(_) => None, - } -} - -fn node(traits: &mut TokenStream, impls: &mut TokenStream, s: &Node, defs: &Definitions) { - let under_name = gen::under_name(&s.ident); - let ty = Ident::new(&s.ident, Span::call_site()); - let fold_fn = Ident::new(&format!("fold_{}", under_name), Span::call_site()); - - let mut fold_impl = TokenStream::new(); - - match &s.data { - Data::Enum(variants) => { - let mut fold_variants = TokenStream::new(); - - for (variant, fields) in variants { - let variant_ident = Ident::new(variant, Span::call_site()); - - if fields.is_empty() { - fold_variants.extend(quote! { - #ty::#variant_ident => { - #ty::#variant_ident - } - }); - } else { - let mut bind_fold_fields = TokenStream::new(); - let mut fold_fields = TokenStream::new(); - - for (idx, ty) in fields.iter().enumerate() { - let name = format!("_binding_{}", idx); - let binding = Ident::new(&name, Span::call_site()); - - bind_fold_fields.extend(quote! { - #binding, - }); - - let owned_binding = quote!(#binding); - - fold_fields.extend( - visit(ty, &s.features, defs, &owned_binding).unwrap_or(owned_binding), - ); - - fold_fields.extend(quote!(,)); - } - - fold_variants.extend(quote! { - #ty::#variant_ident(#bind_fold_fields) => { - #ty::#variant_ident( - #fold_fields - ) - } - }); - } - } - - fold_impl.extend(quote! { - match _i { - #fold_variants - } - }); - } - Data::Struct(fields) => { - let mut fold_fields = TokenStream::new(); - - for (field, ty) in fields { - let id = Ident::new(&field, Span::call_site()); - let ref_toks = quote!(_i.#id); - let fold = visit(&ty, &s.features, defs, &ref_toks).unwrap_or(ref_toks); - - fold_fields.extend(quote! { - #id: #fold, - }); - } - - if !fields.is_empty() { - fold_impl.extend(quote! { - #ty { - #fold_fields - } - }) - } else { - if ty == "Ident" { - fold_impl.extend(quote! { - let mut _i = _i; - let span = _visitor.fold_span(_i.span()); - _i.set_span(span); - }); - } - fold_impl.extend(quote! { - _i - }); - } - } - Data::Private => { - if ty == "Ident" { - fold_impl.extend(quote! { - let mut _i = _i; - let span = _visitor.fold_span(_i.span()); - _i.set_span(span); - }); - } - fold_impl.extend(quote! { - _i - }); - } - } - - let fold_span_only = - s.data == Data::Private && !gen::TERMINAL_TYPES.contains(&s.ident.as_str()); - if fold_span_only { - fold_impl = quote! { - let span = _visitor.fold_span(_i.span()); - let mut _i = _i; - _i.set_span(span); - _i - }; - } - - traits.extend(quote! { - fn #fold_fn(&mut self, i: #ty) -> #ty { - #fold_fn(self, i) - } - }); - - impls.extend(quote! { - pub fn #fold_fn<V: Fold + ?Sized>( - _visitor: &mut V, _i: #ty - ) -> #ty { - #fold_impl - } - }); -} - -pub fn generate(defs: &Definitions) -> Result<()> { - let (traits, impls) = gen::traverse(defs, node); - let full_macro = full::get_macro(); - file::write( - FOLD_SRC, - quote! { - // Unreachable code is generated sometimes without the full feature. - #![allow(unreachable_code)] - - use *; - #[cfg(any(feature = "full", feature = "derive"))] - use token::{Brace, Bracket, Paren, Group}; - use proc_macro2::Span; - #[cfg(any(feature = "full", feature = "derive"))] - use gen::helper::fold::*; - - #full_macro - - /// Syntax tree traversal to transform the nodes of an owned syntax tree. - /// - /// See the [module documentation] for details. - /// - /// [module documentation]: self - /// - /// *This trait is available if Syn is built with the `"fold"` feature.* - pub trait Fold { - #traits - } - - #impls - }, - )?; - Ok(()) -} diff --git a/codegen/src/full.rs b/codegen/src/full.rs deleted file mode 100644 index a4100318..00000000 --- a/codegen/src/full.rs +++ /dev/null @@ -1,20 +0,0 @@ -use proc_macro2::TokenStream; -use quote::quote; - -pub fn get_macro() -> TokenStream { - quote! { - #[cfg(feature = "full")] - macro_rules! full { - ($e:expr) => { - $e - }; - } - - #[cfg(all(feature = "derive", not(feature = "full")))] - macro_rules! full { - ($e:expr) => { - unreachable!() - }; - } - } -} diff --git a/codegen/src/gen.rs b/codegen/src/gen.rs deleted file mode 100644 index ba86fbf0..00000000 --- a/codegen/src/gen.rs +++ /dev/null @@ -1,38 +0,0 @@ -use inflections::Inflect; -use proc_macro2::{Ident, Span, TokenStream}; -use quote::quote; -use syn_codegen::{Data, Definitions, Features, Node}; - -pub const TERMINAL_TYPES: &[&str] = &["Span", "Ident"]; - -pub fn under_name(name: &str) -> Ident { - Ident::new(&name.to_snake_case(), Span::call_site()) -} - -pub fn traverse( - defs: &Definitions, - node: fn(&mut TokenStream, &mut TokenStream, &Node, &Definitions), -) -> (TokenStream, TokenStream) { - let mut traits = TokenStream::new(); - let mut impls = TokenStream::new(); - for s in &defs.types { - let features = &s.features.any; - let features = match features.len() { - 0 => quote!(), - 1 => quote!(#[cfg(feature = #(#features)*)]), - _ => quote!(#[cfg(any(#(feature = #features),*))]), - }; - traits.extend(features.clone()); - impls.extend(features); - node(&mut traits, &mut impls, s, defs); - } - for tt in TERMINAL_TYPES { - let s = Node { - ident: tt.to_string(), - features: Features::default(), - data: Data::Private, - }; - node(&mut traits, &mut impls, &s, defs); - } - (traits, impls) -} diff --git a/codegen/src/json.rs b/codegen/src/json.rs deleted file mode 100644 index e202bbec..00000000 --- a/codegen/src/json.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::error::Result; -use std::fs; -use std::path::Path; -use syn_codegen::Definitions; - -pub fn generate(defs: &Definitions) -> Result<()> { - let mut j = serde_json::to_string_pretty(&defs)?; - j.push('\n'); - - let check: Definitions = serde_json::from_str(&j)?; - assert_eq!(*defs, check); - - let codegen_root = Path::new(env!("CARGO_MANIFEST_DIR")); - let json_path = codegen_root.join("../syn.json"); - fs::write(json_path, j)?; - - Ok(()) -} diff --git a/codegen/src/main.rs b/codegen/src/main.rs deleted file mode 100644 index 3dc73836..00000000 --- a/codegen/src/main.rs +++ /dev/null @@ -1,46 +0,0 @@ -// This crate crawls the Syn source directory to find all structs and enums that -// form the Syn syntax tree. -// -// A machine-readable representation of the syntax tree is saved to syn.json in -// the repo root for other code generation tools to consume. The syn-codegen -// crate (https://docs.rs/syn-codegen/) provides the data structures for parsing -// and making use of syn.json from Rust code. -// -// Finally this crate generates the Visit, VisitMut, and Fold traits in Syn -// programmatically from the syntax tree description. - -#![recursion_limit = "128"] -#![allow(clippy::needless_pass_by_value)] - -mod debug; -mod error; -mod file; -mod fold; -mod full; -mod gen; -mod json; -mod operand; -mod parse; -mod version; -mod visit; -mod visit_mut; - -use crate::error::Result; -use std::process; - -fn main() { - if let Err(err) = do_main() { - let _ = eprintln!("error: {}", err); - process::exit(1); - } -} - -fn do_main() -> Result<()> { - let defs = parse::parse()?; - json::generate(&defs)?; - fold::generate(&defs)?; - visit::generate(&defs)?; - visit_mut::generate(&defs)?; - debug::generate(&defs)?; - Ok(()) -} diff --git a/codegen/src/operand.rs b/codegen/src/operand.rs deleted file mode 100644 index db3bd187..00000000 --- a/codegen/src/operand.rs +++ /dev/null @@ -1,38 +0,0 @@ -use proc_macro2::TokenStream; -use quote::quote; - -pub enum Operand { - Borrowed(TokenStream), - Owned(TokenStream), -} - -pub use self::Operand::*; - -impl Operand { - pub fn tokens(&self) -> &TokenStream { - match self { - Borrowed(n) | Owned(n) => n, - } - } - - pub fn ref_tokens(&self) -> TokenStream { - match self { - Borrowed(n) => n.clone(), - Owned(n) => quote!(&#n), - } - } - - pub fn ref_mut_tokens(&self) -> TokenStream { - match self { - Borrowed(n) => n.clone(), - Owned(n) => quote!(&mut #n), - } - } - - pub fn owned_tokens(&self) -> TokenStream { - match self { - Borrowed(n) => quote!(*#n), - Owned(n) => n.clone(), - } - } -} diff --git a/codegen/src/parse.rs b/codegen/src/parse.rs deleted file mode 100644 index 81ce58f2..00000000 --- a/codegen/src/parse.rs +++ /dev/null @@ -1,642 +0,0 @@ -use crate::error::Result; -use crate::version; - -use indexmap::IndexMap; -use quote::quote; -use syn::parse::Parser; -use syn::{parse_quote, Data, DataStruct, DeriveInput, Ident, Item}; -use syn_codegen as types; - -use std::collections::BTreeMap; -use std::fs::File; -use std::io::Read; -use std::path::Path; - -const SYN_CRATE_ROOT: &str = "../src/lib.rs"; -const TOKEN_SRC: &str = "../src/token.rs"; -const IGNORED_MODS: &[&str] = &["fold", "visit", "visit_mut"]; -const EXTRA_TYPES: &[&str] = &["Lifetime"]; - -// NOTE: BTreeMap is used here instead of HashMap to have deterministic output. -type ItemLookup = BTreeMap<Ident, AstItem>; -type TokenLookup = BTreeMap<String, String>; - -/// Parse the contents of `src` and return a list of AST types. -pub fn parse() -> Result<types::Definitions> { - let mut item_lookup = BTreeMap::new(); - load_file(SYN_CRATE_ROOT, &[], &mut item_lookup)?; - - let token_lookup = load_token_file(TOKEN_SRC)?; - - let version = version::get()?; - - let types = item_lookup - .values() - .map(|item| introspect_item(item, &item_lookup, &token_lookup)) - .collect(); - - let tokens = token_lookup - .into_iter() - .map(|(name, ty)| (ty, name)) - .collect(); - - Ok(types::Definitions { - version, - types, - tokens, - }) -} - -/// Data extracted from syn source -#[derive(Clone)] -pub struct AstItem { - ast: DeriveInput, - features: Vec<syn::Attribute>, -} - -fn introspect_item(item: &AstItem, items: &ItemLookup, tokens: &TokenLookup) -> types::Node { - let features = introspect_features(&item.features); - - match &item.ast.data { - Data::Enum(ref data) => types::Node { - ident: item.ast.ident.to_string(), - features, - data: types::Data::Enum(introspect_enum(data, items, tokens)), - }, - Data::Struct(ref data) => types::Node { - ident: item.ast.ident.to_string(), - features, - data: { - if data.fields.iter().all(|f| is_pub(&f.vis)) { - types::Data::Struct(introspect_struct(data, items, tokens)) - } else { - types::Data::Private - } - }, - }, - Data::Union(..) => panic!("Union not supported"), - } -} - -fn introspect_enum( - item: &syn::DataEnum, - items: &ItemLookup, - tokens: &TokenLookup, -) -> types::Variants { - item.variants - .iter() - .map(|variant| { - let fields = match &variant.fields { - syn::Fields::Unnamed(fields) => fields - .unnamed - .iter() - .map(|field| introspect_type(&field.ty, items, tokens)) - .collect(), - syn::Fields::Unit => vec![], - _ => panic!("Enum representation not supported"), - }; - - (variant.ident.to_string(), fields) - }) - .collect() -} - -fn introspect_struct( - item: &syn::DataStruct, - items: &ItemLookup, - tokens: &TokenLookup, -) -> types::Fields { - match &item.fields { - syn::Fields::Named(fields) => fields - .named - .iter() - .map(|field| { - ( - field.ident.as_ref().unwrap().to_string(), - introspect_type(&field.ty, items, tokens), - ) - }) - .collect(), - syn::Fields::Unit => IndexMap::new(), - _ => panic!("Struct representation not supported"), - } -} - -fn introspect_type(item: &syn::Type, items: &ItemLookup, tokens: &TokenLookup) -> types::Type { - match item { - syn::Type::Path(syn::TypePath { - qself: None, - ref path, - }) => { - let last = path.segments.last().unwrap().into_value(); - let string = last.ident.to_string(); - - match string.as_str() { - "Option" => { - let nested = introspect_type(first_arg(&last.arguments), items, tokens); - types::Type::Option(Box::new(nested)) - } - "Punctuated" => { - let nested = introspect_type(first_arg(&last.arguments), items, tokens); - let punct = match introspect_type(last_arg(&last.arguments), items, tokens) { - types::Type::Token(s) => s, - _ => panic!(), - }; - - types::Type::Punctuated(types::Punctuated { - element: Box::new(nested), - punct, - }) - } - "Vec" => { - let nested = introspect_type(first_arg(&last.arguments), items, tokens); - types::Type::Vec(Box::new(nested)) - } - "Box" => { - let nested = introspect_type(first_arg(&last.arguments), items, tokens); - types::Type::Box(Box::new(nested)) - } - "Brace" | "Bracket" | "Paren" | "Group" => types::Type::Group(string), - "TokenStream" | "Literal" | "Ident" | "Span" => types::Type::Ext(string), - "String" | "u32" | "usize" | "bool" => types::Type::Std(string), - _ => { - if items.get(&last.ident).is_some() { - types::Type::Syn(string) - } else { - unimplemented!("{}", string); - } - } - } - } - syn::Type::Tuple(syn::TypeTuple { ref elems, .. }) => { - let tys = elems - .iter() - .map(|ty| introspect_type(&ty, items, tokens)) - .collect(); - types::Type::Tuple(tys) - } - syn::Type::Macro(syn::TypeMacro { ref mac }) - if mac.path.segments.last().unwrap().into_value().ident == "Token" => - { - let content = mac.tts.to_string(); - let ty = tokens.get(&content).unwrap().to_string(); - - types::Type::Token(ty) - } - _ => panic!("{}", quote!(#item).to_string()), - } -} - -fn introspect_features(attrs: &[syn::Attribute]) -> types::Features { - let mut ret = types::Features::default(); - - for attr in attrs { - if !attr.path.is_ident("cfg") { - continue; - } - - let features = parsing::parse_features.parse2(attr.tts.clone()).unwrap(); - - if ret.any.is_empty() { - ret = features; - } else if ret.any.len() < features.any.len() { - assert!(ret.any.iter().all(|f| features.any.contains(f))); - } else { - assert!(features.any.iter().all(|f| ret.any.contains(f))); - ret = features; - } - } - - ret -} - -fn is_pub(vis: &syn::Visibility) -> bool { - match vis { - syn::Visibility::Public(_) => true, - _ => false, - } -} - -fn first_arg(params: &syn::PathArguments) -> &syn::Type { - let data = match *params { - syn::PathArguments::AngleBracketed(ref data) => data, - _ => panic!("Expected at least 1 type argument here"), - }; - - match **data - .args - .first() - .expect("Expected at least 1 type argument here") - .value() - { - syn::GenericArgument::Type(ref ty) => ty, - _ => panic!("Expected at least 1 type argument here"), - } -} - -fn last_arg(params: &syn::PathArguments) -> &syn::Type { - let data = match *params { - syn::PathArguments::AngleBracketed(ref data) => data, - _ => panic!("Expected at least 1 type argument here"), - }; - - match **data - .args - .last() - .expect("Expected at least 1 type argument here") - .value() - { - syn::GenericArgument::Type(ref ty) => ty, - _ => panic!("Expected at least 1 type argument here"), - } -} - -mod parsing { - use super::{AstItem, TokenLookup}; - - use proc_macro2::{TokenStream, TokenTree}; - use quote::quote; - use syn; - use syn::parse::{Parse, ParseStream, Result}; - use syn::*; - use syn_codegen as types; - - use std::collections::{BTreeMap, BTreeSet}; - - fn peek_tag(input: ParseStream, tag: &str) -> bool { - let ahead = input.fork(); - ahead.parse::<Token![#]>().is_ok() - && ahead - .parse::<Ident>() - .map(|ident| ident == tag) - .unwrap_or(false) - } - - // Parses #full - returns #[cfg(feature = "full")] if it is present, and - // nothing otherwise. - fn full(input: ParseStream) -> Vec<syn::Attribute> { - if peek_tag(input, "full") { - input.parse::<Token![#]>().unwrap(); - input.parse::<Ident>().unwrap(); - vec![parse_quote!(#[cfg(feature = "full")])] - } else { - vec![] - } - } - - fn skip_manual_extra_traits(input: ParseStream) { - if peek_tag(input, "manual_extra_traits") { - input.parse::<Token![#]>().unwrap(); - input.parse::<Ident>().unwrap(); - } - } - - // Parses a simple AstStruct without the `pub struct` prefix. - fn ast_struct_inner(input: ParseStream) -> Result<AstItem> { - let ident: Ident = input.parse()?; - let features = full(input); - skip_manual_extra_traits(input); - let rest: TokenStream = input.parse()?; - Ok(AstItem { - ast: syn::parse2(quote! { - pub struct #ident #rest - })?, - features, - }) - } - - // ast_struct! parsing - pub struct AstStruct(pub(super) Vec<AstItem>); - impl Parse for AstStruct { - fn parse(input: ParseStream) -> Result<Self> { - input.call(Attribute::parse_outer)?; - input.parse::<Token![pub]>()?; - input.parse::<Token![struct]>()?; - let res = input.call(ast_struct_inner)?; - Ok(AstStruct(vec![res])) - } - } - - fn no_visit(input: ParseStream) -> bool { - if peek_tag(input, "no_visit") { - input.parse::<Token![#]>().unwrap(); - input.parse::<Ident>().unwrap(); - true - } else { - false - } - } - - // ast_enum! parsing - pub struct AstEnum(pub Vec<AstItem>); - impl Parse for AstEnum { - fn parse(input: ParseStream) -> Result<Self> { - input.call(Attribute::parse_outer)?; - input.parse::<Token![pub]>()?; - input.parse::<Token![enum]>()?; - let ident: Ident = input.parse()?; - let no_visit = no_visit(input); - let rest: TokenStream = input.parse()?; - Ok(AstEnum(if no_visit { - vec![] - } else { - vec![AstItem { - ast: syn::parse2(quote! { - pub enum #ident #rest - })?, - features: vec![], - }] - })) - } - } - - // A single variant of an ast_enum_of_structs! - struct EosVariant { - name: Ident, - member: Option<Path>, - inner: Option<AstItem>, - } - fn eos_variant(input: ParseStream) -> Result<EosVariant> { - input.call(Attribute::parse_outer)?; - input.parse::<Token![pub]>()?; - let variant: Ident = input.parse()?; - let (member, inner) = if input.peek(token::Paren) { - let content; - parenthesized!(content in input); - if content.fork().call(ast_struct_inner).is_ok() { - let item = content.call(ast_struct_inner)?; - (Some(Path::from(item.ast.ident.clone())), Some(item)) - } else { - let path: Path = content.parse()?; - (Some(path), None) - } - } else { - (None, None) - }; - input.parse::<Token![,]>()?; - Ok(EosVariant { - name: variant, - member, - inner, - }) - } - - // ast_enum_of_structs! parsing - pub struct AstEnumOfStructs(pub Vec<AstItem>); - impl Parse for AstEnumOfStructs { - fn parse(input: ParseStream) -> Result<Self> { - input.call(Attribute::parse_outer)?; - input.parse::<Token![pub]>()?; - input.parse::<Token![enum]>()?; - let ident: Ident = input.parse()?; - - let content; - braced!(content in input); - let mut variants = Vec::new(); - while !content.is_empty() { - variants.push(content.call(eos_variant)?); - } - - if let Some(ident) = input.parse::<Option<Ident>>()? { - assert_eq!(ident, "do_not_generate_to_tokens"); - } - - let enum_item = { - let variants = variants.iter().map(|v| { - let name = v.name.clone(); - match v.member { - Some(ref member) => quote!(#name(#member)), - None => quote!(#name), - } - }); - parse_quote! { - pub enum #ident { - #(#variants),* - } - } - }; - let mut items = vec![AstItem { - ast: enum_item, - features: vec![], - }]; - items.extend(variants.into_iter().filter_map(|v| v.inner)); - Ok(AstEnumOfStructs(items)) - } - } - - mod kw { - syn::custom_keyword!(macro_rules); - syn::custom_keyword!(Token); - } - - pub fn parse_token_macro(input: ParseStream) -> Result<TokenLookup> { - input.parse::<TokenTree>()?; - input.parse::<Token![=>]>()?; - - let definition; - braced!(definition in input); - definition.call(Attribute::parse_outer)?; - definition.parse::<kw::macro_rules>()?; - definition.parse::<Token![!]>()?; - definition.parse::<kw::Token>()?; - - let rules; - braced!(rules in definition); - input.parse::<Token![;]>()?; - - let mut tokens = BTreeMap::new(); - while !rules.peek(Token![$]) { - let pattern; - parenthesized!(pattern in rules); - let token = pattern.parse::<TokenStream>()?.to_string(); - rules.parse::<Token![=>]>()?; - let expansion; - braced!(expansion in rules); - rules.parse::<Token![;]>()?; - expansion.parse::<Token![$]>()?; - let path: Path = expansion.parse()?; - let ty = path.segments.last().unwrap().into_value().ident.to_string(); - tokens.insert(token, ty.to_string()); - } - rules.parse::<TokenStream>()?; - tokens.insert("$".to_owned(), "Dollar".to_owned()); - Ok(tokens) - } - - fn parse_feature(input: ParseStream) -> Result<String> { - let i: syn::Ident = input.parse()?; - assert_eq!(i, "feature"); - - input.parse::<Token![=]>()?; - let s = input.parse::<syn::LitStr>()?; - - Ok(s.value()) - } - - pub fn parse_features(input: ParseStream) -> Result<types::Features> { - let mut features = BTreeSet::new(); - - let level_1; - parenthesized!(level_1 in input); - - let i: syn::Ident = level_1.fork().parse()?; - - if i == "any" { - level_1.parse::<syn::Ident>()?; - - let level_2; - parenthesized!(level_2 in level_1); - - while !level_2.is_empty() { - features.insert(parse_feature(&level_2)?); - - if !level_2.is_empty() { - level_2.parse::<Token![,]>()?; - } - } - } else if i == "feature" { - features.insert(parse_feature(&level_1)?); - assert!(level_1.is_empty()); - } else { - panic!("{:?}", i); - } - - assert!(input.is_empty()); - - Ok(types::Features { any: features }) - } -} - -fn get_features(attrs: &[syn::Attribute], base: &[syn::Attribute]) -> Vec<syn::Attribute> { - let mut ret = base.to_owned(); - - for attr in attrs { - if attr.path.is_ident("cfg") { - ret.push(attr.clone()); - } - } - - ret -} - -fn load_file<P: AsRef<Path>>( - name: P, - features: &[syn::Attribute], - lookup: &mut ItemLookup, -) -> Result<()> { - let name = name.as_ref(); - let parent = name.parent().expect("no parent path"); - - let mut f = File::open(name)?; - let mut src = String::new(); - f.read_to_string(&mut src)?; - - // Parse the file - let file = syn::parse_file(&src)?; - - // Collect all of the interesting AstItems declared in this file or submodules. - 'items: for item in file.items { - match item { - Item::Mod(item) => { - // Don't inspect inline modules. - if item.content.is_some() { - continue; - } - - // We don't want to try to load the generated rust files and - // parse them, so we ignore them here. - for name in IGNORED_MODS { - if item.ident == name { - continue 'items; - } - } - - // Lookup any #[cfg()] attributes on the module and add them to - // the feature set. - // - // The derive module is weird because it is built with either - // `full` or `derive` but exported only under `derive`. - let features = if item.ident == "derive" { - vec![parse_quote!(#[cfg(feature = "derive")])] - } else { - get_features(&item.attrs, features) - }; - - // Look up the submodule file, and recursively parse it. - // XXX: Only handles same-directory .rs file submodules. - let path = parent.join(&format!("{}.rs", item.ident)); - load_file(path, &features, lookup)?; - } - Item::Macro(item) => { - // Lookip any #[cfg()] attributes directly on the macro - // invocation, and add them to the feature set. - let features = get_features(&item.attrs, features); - - // Try to parse the AstItem declaration out of the item. - let tts = &item.mac.tts; - let found = if item.mac.path.is_ident("ast_struct") { - syn::parse2::<parsing::AstStruct>(quote!(#tts))?.0 - } else if item.mac.path.is_ident("ast_enum") { - syn::parse2::<parsing::AstEnum>(quote!(#tts))?.0 - } else if item.mac.path.is_ident("ast_enum_of_structs") { - syn::parse2::<parsing::AstEnumOfStructs>(quote!(#tts))?.0 - } else { - continue; - }; - - // Record our features on the parsed AstItems. - for mut item in found { - item.features.extend(features.clone()); - lookup.insert(item.ast.ident.clone(), item); - } - } - Item::Struct(item) => { - let ident = item.ident; - if EXTRA_TYPES.contains(&&ident.to_string()[..]) { - lookup.insert( - ident.clone(), - AstItem { - ast: DeriveInput { - ident, - vis: item.vis, - attrs: item.attrs, - generics: item.generics, - data: Data::Struct(DataStruct { - fields: item.fields, - struct_token: item.struct_token, - semi_token: item.semi_token, - }), - }, - features: features.to_owned(), - }, - ); - } - } - _ => {} - } - } - Ok(()) -} - -fn load_token_file<P: AsRef<Path>>(name: P) -> Result<TokenLookup> { - let name = name.as_ref(); - let mut f = File::open(name)?; - let mut src = String::new(); - f.read_to_string(&mut src)?; - let file = syn::parse_file(&src)?; - for item in file.items { - match item { - Item::Macro(item) => { - match item.ident { - Some(ref i) if i == "export_token_macro" => {} - _ => continue, - } - let tokens = item.mac.parse_body_with(parsing::parse_token_macro)?; - return Ok(tokens); - } - _ => {} - } - } - - panic!("failed to parse Token macro") -} diff --git a/codegen/src/version.rs b/codegen/src/version.rs deleted file mode 100644 index 7ccca608..00000000 --- a/codegen/src/version.rs +++ /dev/null @@ -1,24 +0,0 @@ -use crate::error::Result; -use semver::Version; -use serde::Deserialize; - -use std::fs; -use std::path::Path; - -pub fn get() -> Result<Version> { - let codegen_root = Path::new(env!("CARGO_MANIFEST_DIR")); - let syn_cargo_toml = codegen_root.join("../Cargo.toml"); - let manifest = fs::read_to_string(syn_cargo_toml)?; - let parsed: Manifest = toml::from_str(&manifest)?; - Ok(parsed.package.version) -} - -#[derive(Debug, Deserialize)] -struct Manifest { - package: Package, -} - -#[derive(Debug, Deserialize)] -struct Package { - version: Version, -} diff --git a/codegen/src/visit.rs b/codegen/src/visit.rs deleted file mode 100644 index 5d6fbee1..00000000 --- a/codegen/src/visit.rs +++ /dev/null @@ -1,236 +0,0 @@ -use crate::error::Result; -use crate::operand::{Borrowed, Operand, Owned}; -use crate::{file, full, gen}; -use proc_macro2::{Ident, Span, TokenStream}; -use quote::quote; -use syn::Index; -use syn_codegen::{Data, Definitions, Features, Node, Type}; - -const VISIT_SRC: &str = "../src/gen/visit.rs"; - -fn simple_visit(item: &str, name: &Operand) -> TokenStream { - let ident = gen::under_name(item); - let method = Ident::new(&format!("visit_{}", ident), Span::call_site()); - let name = name.ref_tokens(); - quote! { - _visitor.#method(#name) - } -} - -fn noop_visit(name: &Operand) -> TokenStream { - let name = name.tokens(); - quote! { - skip!(#name) - } -} - -fn visit( - ty: &Type, - features: &Features, - defs: &Definitions, - name: &Operand, -) -> Option<TokenStream> { - match ty { - Type::Box(t) => { - let name = name.owned_tokens(); - visit(t, features, defs, &Owned(quote!(*#name))) - } - Type::Vec(t) => { - let operand = Borrowed(quote!(it)); - let val = visit(t, features, defs, &operand)?; - let name = name.ref_tokens(); - Some(quote! { - for it in #name { - #val - } - }) - } - Type::Punctuated(p) => { - let operand = Borrowed(quote!(it)); - let val = visit(&p.element, features, defs, &operand)?; - let name = name.ref_tokens(); - Some(quote! { - for el in Punctuated::pairs(#name) { - let it = el.value(); - #val - } - }) - } - Type::Option(t) => { - let it = Borrowed(quote!(it)); - let val = visit(t, features, defs, &it)?; - let name = name.owned_tokens(); - Some(quote! { - if let Some(ref it) = #name { - #val - } - }) - } - Type::Tuple(t) => { - let mut code = TokenStream::new(); - for (i, elem) in t.iter().enumerate() { - let name = name.tokens(); - let i = Index::from(i); - let it = Owned(quote!((#name).#i)); - let val = visit(elem, features, defs, &it).unwrap_or_else(|| noop_visit(&it)); - code.extend(val); - code.extend(quote!(;)); - } - Some(code) - } - Type::Token(t) => { - let name = name.tokens(); - let repr = &defs.tokens[t]; - let is_keyword = repr.chars().next().unwrap().is_alphabetic(); - let spans = if is_keyword { - quote!(span) - } else { - quote!(spans) - }; - Some(quote! { - tokens_helper(_visitor, &#name.#spans) - }) - } - Type::Group(_) => { - let name = name.tokens(); - Some(quote! { - tokens_helper(_visitor, &#name.span) - }) - } - Type::Syn(t) => { - fn requires_full(features: &Features) -> bool { - features.any.contains("full") && features.any.len() == 1 - } - let mut res = simple_visit(t, name); - let target = defs.types.iter().find(|ty| ty.ident == *t).unwrap(); - if requires_full(&target.features) && !requires_full(features) { - res = quote!(full!(#res)); - } - Some(res) - } - Type::Ext(t) if gen::TERMINAL_TYPES.contains(&&t[..]) => Some(simple_visit(t, name)), - Type::Ext(_) | Type::Std(_) => None, - } -} - -fn node(traits: &mut TokenStream, impls: &mut TokenStream, s: &Node, defs: &Definitions) { - let under_name = gen::under_name(&s.ident); - let ty = Ident::new(&s.ident, Span::call_site()); - let visit_fn = Ident::new(&format!("visit_{}", under_name), Span::call_site()); - - let mut visit_impl = TokenStream::new(); - - match &s.data { - Data::Enum(variants) => { - let mut visit_variants = TokenStream::new(); - - for (variant, fields) in variants { - let variant_ident = Ident::new(variant, Span::call_site()); - - if fields.is_empty() { - visit_variants.extend(quote! { - #ty::#variant_ident => {} - }); - } else { - let mut bind_visit_fields = TokenStream::new(); - let mut visit_fields = TokenStream::new(); - - for (idx, ty) in fields.iter().enumerate() { - let name = format!("_binding_{}", idx); - let binding = Ident::new(&name, Span::call_site()); - - bind_visit_fields.extend(quote! { - ref #binding, - }); - - let borrowed_binding = Borrowed(quote!(#binding)); - - visit_fields.extend( - visit(ty, &s.features, defs, &borrowed_binding) - .unwrap_or_else(|| noop_visit(&borrowed_binding)), - ); - - visit_fields.extend(quote!(;)); - } - - visit_variants.extend(quote! { - #ty::#variant_ident(#bind_visit_fields) => { - #visit_fields - } - }); - } - } - - visit_impl.extend(quote! { - match *_i { - #visit_variants - } - }); - } - Data::Struct(fields) => { - for (field, ty) in fields { - let id = Ident::new(&field, Span::call_site()); - let ref_toks = Owned(quote!(_i.#id)); - let visit_field = visit(&ty, &s.features, defs, &ref_toks) - .unwrap_or_else(|| noop_visit(&ref_toks)); - visit_impl.extend(quote! { - #visit_field; - }); - } - } - Data::Private => {} - } - - traits.extend(quote! { - fn #visit_fn(&mut self, i: &'ast #ty) { - #visit_fn(self, i) - } - }); - - impls.extend(quote! { - pub fn #visit_fn<'ast, V: Visit<'ast> + ?Sized>( - _visitor: &mut V, _i: &'ast #ty - ) { - #visit_impl - } - }); -} - -pub fn generate(defs: &Definitions) -> Result<()> { - let (traits, impls) = gen::traverse(defs, node); - let full_macro = full::get_macro(); - file::write( - VISIT_SRC, - quote! { - #![cfg_attr(feature = "cargo-clippy", allow(trivially_copy_pass_by_ref))] - - use *; - #[cfg(any(feature = "full", feature = "derive"))] - use punctuated::Punctuated; - use proc_macro2::Span; - #[cfg(any(feature = "full", feature = "derive"))] - use gen::helper::visit::*; - - #full_macro - - #[cfg(any(feature = "full", feature = "derive"))] - macro_rules! skip { - ($($tt:tt)*) => {}; - } - - /// Syntax tree traversal to walk a shared borrow of a syntax tree. - /// - /// See the [module documentation] for details. - /// - /// [module documentation]: self - /// - /// *This trait is available if Syn is built with the `"visit"` feature.* - pub trait Visit<'ast> { - #traits - } - - #impls - }, - )?; - Ok(()) -} diff --git a/codegen/src/visit_mut.rs b/codegen/src/visit_mut.rs deleted file mode 100644 index 4cfb2be0..00000000 --- a/codegen/src/visit_mut.rs +++ /dev/null @@ -1,235 +0,0 @@ -use crate::error::Result; -use crate::operand::{Borrowed, Operand, Owned}; -use crate::{file, full, gen}; -use proc_macro2::{Ident, Span, TokenStream}; -use quote::quote; -use syn::Index; -use syn_codegen::{Data, Definitions, Features, Node, Type}; - -const VISIT_MUT_SRC: &str = "../src/gen/visit_mut.rs"; - -fn simple_visit(item: &str, name: &Operand) -> TokenStream { - let ident = gen::under_name(item); - let method = Ident::new(&format!("visit_{}_mut", ident), Span::call_site()); - let name = name.ref_mut_tokens(); - quote! { - _visitor.#method(#name) - } -} - -fn noop_visit(name: &Operand) -> TokenStream { - let name = name.tokens(); - quote! { - skip!(#name) - } -} - -fn visit( - ty: &Type, - features: &Features, - defs: &Definitions, - name: &Operand, -) -> Option<TokenStream> { - match ty { - Type::Box(t) => { - let name = name.owned_tokens(); - visit(t, features, defs, &Owned(quote!(*#name))) - } - Type::Vec(t) => { - let operand = Borrowed(quote!(it)); - let val = visit(t, features, defs, &operand)?; - let name = name.ref_mut_tokens(); - Some(quote! { - for it in #name { - #val - } - }) - } - Type::Punctuated(p) => { - let operand = Borrowed(quote!(it)); - let val = visit(&p.element, features, defs, &operand)?; - let name = name.ref_mut_tokens(); - Some(quote! { - for mut el in Punctuated::pairs_mut(#name) { - let it = el.value_mut(); - #val - } - }) - } - Type::Option(t) => { - let it = Borrowed(quote!(it)); - let val = visit(t, features, defs, &it)?; - let name = name.owned_tokens(); - Some(quote! { - if let Some(ref mut it) = #name { - #val - } - }) - } - Type::Tuple(t) => { - let mut code = TokenStream::new(); - for (i, elem) in t.iter().enumerate() { - let name = name.tokens(); - let i = Index::from(i); - let it = Owned(quote!((#name).#i)); - let val = visit(elem, features, defs, &it).unwrap_or_else(|| noop_visit(&it)); - code.extend(val); - code.extend(quote!(;)); - } - Some(code) - } - Type::Token(t) => { - let name = name.tokens(); - let repr = &defs.tokens[t]; - let is_keyword = repr.chars().next().unwrap().is_alphabetic(); - let spans = if is_keyword { - quote!(span) - } else { - quote!(spans) - }; - Some(quote! { - tokens_helper(_visitor, &mut #name.#spans) - }) - } - Type::Group(_) => { - let name = name.tokens(); - Some(quote! { - tokens_helper(_visitor, &mut #name.span) - }) - } - Type::Syn(t) => { - fn requires_full(features: &Features) -> bool { - features.any.contains("full") && features.any.len() == 1 - } - let mut res = simple_visit(t, name); - let target = defs.types.iter().find(|ty| ty.ident == *t).unwrap(); - if requires_full(&target.features) && !requires_full(features) { - res = quote!(full!(#res)); - } - Some(res) - } - Type::Ext(t) if gen::TERMINAL_TYPES.contains(&&t[..]) => Some(simple_visit(t, name)), - Type::Ext(_) | Type::Std(_) => None, - } -} - -fn node(traits: &mut TokenStream, impls: &mut TokenStream, s: &Node, defs: &Definitions) { - let under_name = gen::under_name(&s.ident); - let ty = Ident::new(&s.ident, Span::call_site()); - let visit_mut_fn = Ident::new(&format!("visit_{}_mut", under_name), Span::call_site()); - - let mut visit_mut_impl = TokenStream::new(); - - match &s.data { - Data::Enum(variants) => { - let mut visit_mut_variants = TokenStream::new(); - - for (variant, fields) in variants { - let variant_ident = Ident::new(variant, Span::call_site()); - - if fields.is_empty() { - visit_mut_variants.extend(quote! { - #ty::#variant_ident => {} - }); - } else { - let mut bind_visit_mut_fields = TokenStream::new(); - let mut visit_mut_fields = TokenStream::new(); - - for (idx, ty) in fields.iter().enumerate() { - let name = format!("_binding_{}", idx); - let binding = Ident::new(&name, Span::call_site()); - - bind_visit_mut_fields.extend(quote! { - ref mut #binding, - }); - - let borrowed_binding = Borrowed(quote!(#binding)); - - visit_mut_fields.extend( - visit(ty, &s.features, defs, &borrowed_binding) - .unwrap_or_else(|| noop_visit(&borrowed_binding)), - ); - - visit_mut_fields.extend(quote!(;)); - } - - visit_mut_variants.extend(quote! { - #ty::#variant_ident(#bind_visit_mut_fields) => { - #visit_mut_fields - } - }); - } - } - - visit_mut_impl.extend(quote! { - match *_i { - #visit_mut_variants - } - }); - } - Data::Struct(fields) => { - for (field, ty) in fields { - let id = Ident::new(&field, Span::call_site()); - let ref_toks = Owned(quote!(_i.#id)); - let visit_mut_field = visit(&ty, &s.features, defs, &ref_toks) - .unwrap_or_else(|| noop_visit(&ref_toks)); - visit_mut_impl.extend(quote! { - #visit_mut_field; - }); - } - } - Data::Private => {} - } - - traits.extend(quote! { - fn #visit_mut_fn(&mut self, i: &mut #ty) { - #visit_mut_fn(self, i) - } - }); - - impls.extend(quote! { - pub fn #visit_mut_fn<V: VisitMut + ?Sized>( - _visitor: &mut V, _i: &mut #ty - ) { - #visit_mut_impl - } - }); -} - -pub fn generate(defs: &Definitions) -> Result<()> { - let (traits, impls) = gen::traverse(defs, node); - let full_macro = full::get_macro(); - file::write( - VISIT_MUT_SRC, - quote! { - use *; - #[cfg(any(feature = "full", feature = "derive"))] - use punctuated::Punctuated; - use proc_macro2::Span; - #[cfg(any(feature = "full", feature = "derive"))] - use gen::helper::visit_mut::*; - - #full_macro - - #[cfg(any(feature = "full", feature = "derive"))] - macro_rules! skip { - ($($tt:tt)*) => {}; - } - - /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in - /// place. - /// - /// See the [module documentation] for details. - /// - /// [module documentation]: self - /// - /// *This trait is available if Syn is built with the `"visit-mut"` feature.* - pub trait VisitMut { - #traits - } - - #impls - }, - )?; - Ok(()) -} diff --git a/dev/Cargo.toml b/dev/Cargo.toml deleted file mode 100644 index f4dc1284..00000000 --- a/dev/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "syn-dev" -version = "0.0.0" -authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -publish = false - -[lib] -path = "parse.rs" -proc-macro = true - -[[bin]] -path = "main.rs" -name = "syn-dev" - -[dependencies] -quote = "0.6" - -[dependencies.syn] -path = ".." -default-features = false -features = ["parsing", "full", "extra-traits", "proc-macro"] diff --git a/dev/README.md b/dev/README.md deleted file mode 100644 index 91b98460..00000000 --- a/dev/README.md +++ /dev/null @@ -1,6 +0,0 @@ -A little project skeleton for troubleshooting Syn's parsers during development, -especially when adding support for new Rust syntax. - -Place a sample of the syntax you are working on into main.rs and then run `cargo -check` to try parsing it, revealing the resulting syntax tree or else showing -the position and error message if the input fails to parse. diff --git a/dev/main.rs b/dev/main.rs deleted file mode 100644 index eb675465..00000000 --- a/dev/main.rs +++ /dev/null @@ -1,4 +0,0 @@ -syn_dev::r#mod! { - // Write Rust code here and run `cargo check` to have Syn parse it. - -} diff --git a/dev/parse.rs b/dev/parse.rs deleted file mode 100644 index 2a925505..00000000 --- a/dev/parse.rs +++ /dev/null @@ -1,18 +0,0 @@ -extern crate proc_macro; - -use proc_macro::TokenStream; -use quote::quote; -use syn::File; - -#[proc_macro] -pub fn r#mod(input: TokenStream) -> TokenStream { - let compile_error = syn::parse::<File>(input) - .map(|file| println!("{:#?}", file)) - .map_err(|err| err.to_compile_error()) - .err(); - - TokenStream::from(quote! { - #compile_error - fn main() {} - }) -} diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index ea59c021..00000000 --- a/examples/README.md +++ /dev/null @@ -1,20 +0,0 @@ -### [`dump-syntax`](dump-syntax) - -Little utility to parse a Rust source file into a `syn::File` and print out a -debug representation of the syntax tree. - -### [`heapsize`](heapsize) - -A complete working implementation of a custom derive. Works on any Rust compiler -1.15+. - -### [`lazy-static`](lazy-static) - -An example of parsing a custom syntax within a `functionlike!(...)` procedural -macro. Demonstrates how to trigger custom warnings and error messages on -individual tokens of the input. - -### [`trace-var`](trace-var) - -An attribute procedural macro that uses a syntax tree traversal to transform -certain syntax tree nodes in a function body. diff --git a/examples/dump-syntax/Cargo.toml b/examples/dump-syntax/Cargo.toml deleted file mode 100644 index 619a2dea..00000000 --- a/examples/dump-syntax/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "dump-syntax" -version = "0.0.0" -authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -publish = false - -[dependencies] -proc-macro2 = { version = "0.4.27", features = ["span-locations"] } -colored = "1.7" - -[dependencies.syn] -path = "../.." -default-features = false -features = ["parsing", "full", "extra-traits"] - -[workspace] diff --git a/examples/dump-syntax/README.md b/examples/dump-syntax/README.md deleted file mode 100644 index 37c84d80..00000000 --- a/examples/dump-syntax/README.md +++ /dev/null @@ -1,28 +0,0 @@ -Parse a Rust source file into a `syn::File` and print out a debug representation -of the syntax tree. - -Use the following command from this directory to test this program by running it -on its own source code: - -``` -cargo run -- src/main.rs -``` - -The output will begin with: - -``` -File { - shebang: None, - attrs: [ - Attribute { - pound_token: Pound, - style: Inner( - Bang - ), - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - ... -} -``` diff --git a/examples/dump-syntax/src/main.rs b/examples/dump-syntax/src/main.rs deleted file mode 100644 index 240b7a29..00000000 --- a/examples/dump-syntax/src/main.rs +++ /dev/null @@ -1,149 +0,0 @@ -//! Parse a Rust source file into a `syn::File` and print out a debug -//! representation of the syntax tree. -//! -//! Use the following command from this directory to test this program by -//! running it on its own source code: -//! -//! cargo run -- src/main.rs -//! -//! The output will begin with: -//! -//! File { -//! shebang: None, -//! attrs: [ -//! Attribute { -//! pound_token: Pound, -//! style: Inner( -//! ... -//! } - -use std::borrow::Cow; -use std::env; -use std::ffi::OsStr; -use std::fmt::{self, Display}; -use std::fs; -use std::io::{self, Write}; -use std::path::{Path, PathBuf}; -use std::process; - -use colored::Colorize; - -enum Error { - IncorrectUsage, - ReadFile(io::Error), - ParseFile { - error: syn::Error, - filepath: PathBuf, - source_code: String, - }, -} - -impl Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::Error::*; - - match self { - IncorrectUsage => write!(f, "Usage: dump-syntax path/to/filename.rs"), - ReadFile(error) => write!(f, "Unable to read file: {}", error), - ParseFile { - error, - filepath, - source_code, - } => render_location(f, error, filepath, source_code), - } - } -} - -fn main() { - if let Err(error) = try_main() { - let _ = writeln!(io::stderr(), "{}", error); - process::exit(1); - } -} - -fn try_main() -> Result<(), Error> { - let mut args = env::args_os(); - let _ = args.next(); // executable name - - let filepath = match (args.next(), args.next()) { - (Some(arg), None) => PathBuf::from(arg), - _ => return Err(Error::IncorrectUsage), - }; - - let code = fs::read_to_string(&filepath).map_err(Error::ReadFile)?; - let syntax = syn::parse_file(&code).map_err({ - |error| Error::ParseFile { - error, - filepath, - source_code: code, - } - })?; - println!("{:#?}", syntax); - - Ok(()) -} - -// Render a rustc-style error message, including colors. -// -// error: Syn unable to parse file -// --> main.rs:40:17 -// | -// 40 | fn fmt(&self formatter: &mut fmt::Formatter) -> fmt::Result { -// | ^^^^^^^^^ expected `,` -// -fn render_location( - formatter: &mut fmt::Formatter, - err: &syn::Error, - filepath: &Path, - code: &str, -) -> fmt::Result { - let start = err.span().start(); - let mut end = err.span().end(); - - if start.line == end.line && start.column == end.column { - return render_fallback(formatter, err); - } - - let code_line = match code.lines().nth(start.line - 1) { - Some(line) => line, - None => return render_fallback(formatter, err), - }; - - if end.line > start.line { - end.line = start.line; - end.column = code_line.len(); - } - - let filename = filepath - .file_name() - .map(OsStr::to_string_lossy) - .unwrap_or(Cow::Borrowed("main.rs")); - - write!( - formatter, - "\n\ - {error}{header}\n\ - {indent}{arrow} {filename}:{linenum}:{colnum}\n\ - {indent} {pipe}\n\ - {label} {pipe} {code}\n\ - {indent} {pipe} {offset}{underline} {message}\n\ - ", - error = "error".red().bold(), - header = ": Syn unable to parse file".bold(), - indent = " ".repeat(start.line.to_string().len()), - arrow = "-->".blue().bold(), - filename = filename, - linenum = start.line, - colnum = start.column, - pipe = "|".blue().bold(), - label = start.line.to_string().blue().bold(), - code = code_line.trim_end(), - offset = " ".repeat(start.column), - underline = "^".repeat(end.column - start.column).red().bold(), - message = err.to_string().red(), - ) -} - -fn render_fallback(formatter: &mut fmt::Formatter, err: &syn::Error) -> fmt::Result { - write!(formatter, "Unable to parse file: {}", err) -} diff --git a/examples/heapsize/Cargo.toml b/examples/heapsize/Cargo.toml deleted file mode 100644 index 9b192140..00000000 --- a/examples/heapsize/Cargo.toml +++ /dev/null @@ -1,2 +0,0 @@ -[workspace] -members = ["example", "heapsize", "heapsize_derive"] diff --git a/examples/heapsize/README.md b/examples/heapsize/README.md deleted file mode 100644 index a1f32d96..00000000 --- a/examples/heapsize/README.md +++ /dev/null @@ -1,73 +0,0 @@ -A complete working implementation of a custom derive. Written in Rust 2018 style -but otherwise works on any Rust compiler 1.15+. - -- [`heapsize/src/lib.rs`](heapsize/src/lib.rs) -- [`heapsize_derive/src/lib.rs`](heapsize_derive/src/lib.rs) -- [`example/src/main.rs`](example/src/main.rs) - -We are deriving the `HeapSize` trait which computes an estimate of the amount of -heap memory owned by a value. - -```rust -pub trait HeapSize { - /// Total number of bytes of heap memory owned by `self`. - fn heap_size_of_children(&self) -> usize; -} -``` - -The custom derive 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, -} -``` - -The trait impl generated by the custom derive here would look like: - -```rust -impl<'a, T: ?Sized + heapsize::HeapSize> heapsize::HeapSize for Demo<'a, T> { - fn heap_size_of_children(&self) -> usize { - 0 + heapsize::HeapSize::heap_size_of_children(&self.a) - + heapsize::HeapSize::heap_size_of_children(&self.b) - + heapsize::HeapSize::heap_size_of_children(&self.c) - + heapsize::HeapSize::heap_size_of_children(&self.d) - } -} -``` - -The implementation of `heapsize_derive` demonstrates some attention to "spans" -of error messages. For each subexpression in the generated code we apply the -span of the input fragment under which we would want to trigger a compiler error -if the subexpression fails to compile. In this example, each recursive call to -`heap_size_of_children` is associated with the span of the corresponding struct -field. Thus we get errors in the right place if any of the field types do not -implement the `HeapSize` trait. - -``` -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` -``` - -Some unstable APIs in the `proc-macro2` crate let us improve this further by -joining together the span of the field name and the field type. There is no -difference in our code -- everything is as shown in this directory -- but -building the example crate with `cargo build` shows errors like the one above -and building with `RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build` is -able to show errors like the following. - -``` -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` -``` diff --git a/examples/heapsize/example/Cargo.toml b/examples/heapsize/example/Cargo.toml deleted file mode 100644 index 85c7699c..00000000 --- a/examples/heapsize/example/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "heapsize_example" -version = "0.0.0" -authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -publish = false - -[dependencies] -heapsize = { path = "../heapsize" } diff --git a/examples/heapsize/example/src/main.rs b/examples/heapsize/example/src/main.rs deleted file mode 100644 index 9332b11c..00000000 --- a/examples/heapsize/example/src/main.rs +++ /dev/null @@ -1,28 +0,0 @@ -use heapsize::HeapSize; - -#[derive(HeapSize)] -struct Demo<'a, T: ?Sized> { - a: Box<T>, - b: u8, - c: &'a str, - d: String, -} - -fn main() { - let demo = Demo { - a: b"bytestring".to_vec().into_boxed_slice(), - b: 255, - c: "&'static str", - d: "String".to_owned(), - }; - - // 10 + 0 + 0 + 6 = 16 - println!( - "heap size = {} + {} + {} + {} = {}", - demo.a.heap_size_of_children(), - demo.b.heap_size_of_children(), - demo.c.heap_size_of_children(), - demo.d.heap_size_of_children(), - demo.heap_size_of_children() - ); -} diff --git a/examples/heapsize/heapsize/Cargo.toml b/examples/heapsize/heapsize/Cargo.toml deleted file mode 100644 index 27bb9541..00000000 --- a/examples/heapsize/heapsize/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "heapsize" -version = "0.0.0" -authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -publish = false - -[dependencies] -heapsize_derive = { path = "../heapsize_derive" } diff --git a/examples/heapsize/heapsize/src/lib.rs b/examples/heapsize/heapsize/src/lib.rs deleted file mode 100644 index 30bb6d60..00000000 --- a/examples/heapsize/heapsize/src/lib.rs +++ /dev/null @@ -1,64 +0,0 @@ -use std::mem; - -pub use heapsize_derive::*; - -pub trait HeapSize { - /// Total number of bytes of heap memory owned by `self`. - /// - /// Does not include the size of `self` itself, which may or may not be on - /// the heap. Includes only children of `self`, meaning things pointed to by - /// `self`. - fn heap_size_of_children(&self) -> usize; -} - -// -// In a real version of this library there would be lots more impls here, but -// here are some interesting ones. -// - -impl HeapSize for u8 { - /// A `u8` does not own any heap memory. - fn heap_size_of_children(&self) -> usize { - 0 - } -} - -impl HeapSize for String { - /// A `String` owns enough heap memory to hold its reserved capacity. - fn heap_size_of_children(&self) -> usize { - self.capacity() - } -} - -impl<T> HeapSize for Box<T> -where - T: ?Sized + HeapSize, -{ - /// A `Box` owns however much heap memory was allocated to hold the value of - /// type `T` that we placed on the heap, plus transitively however much `T` - /// itself owns. - fn heap_size_of_children(&self) -> usize { - mem::size_of_val(&**self) + (**self).heap_size_of_children() - } -} - -impl<T> HeapSize for [T] -where - T: HeapSize, -{ - /// Sum of heap memory owned by each element of a dynamically sized slice of - /// `T`. - fn heap_size_of_children(&self) -> usize { - self.iter().map(HeapSize::heap_size_of_children).sum() - } -} - -impl<'a, T> HeapSize for &'a T -where - T: ?Sized, -{ - /// A shared reference does not own heap memory. - fn heap_size_of_children(&self) -> usize { - 0 - } -} diff --git a/examples/heapsize/heapsize_derive/Cargo.toml b/examples/heapsize/heapsize_derive/Cargo.toml deleted file mode 100644 index 6958c326..00000000 --- a/examples/heapsize/heapsize_derive/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "heapsize_derive" -version = "0.0.0" -authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -publish = false - -[lib] -proc-macro = true - -[dependencies] -proc-macro2 = "0.4" -quote = "0.6" -syn = { path = "../../.." } diff --git a/examples/heapsize/heapsize_derive/src/lib.rs b/examples/heapsize/heapsize_derive/src/lib.rs deleted file mode 100644 index 9176b29a..00000000 --- a/examples/heapsize/heapsize_derive/src/lib.rs +++ /dev/null @@ -1,96 +0,0 @@ -extern crate proc_macro; - -use proc_macro2::TokenStream; -use quote::{quote, quote_spanned}; -use syn::spanned::Spanned; -use syn::{parse_macro_input, parse_quote, Data, DeriveInput, Fields, GenericParam, Generics, Index}; - -#[proc_macro_derive(HeapSize)] -pub fn derive_heap_size(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - // Parse the input tokens into a syntax tree. - let input = parse_macro_input!(input as DeriveInput); - - // Used in the quasi-quotation below as `#name`. - let name = input.ident; - - // Add a bound `T: HeapSize` to every type parameter T. - let generics = add_trait_bounds(input.generics); - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - - // Generate an expression to sum up the heap size of each field. - let sum = heap_size_sum(&input.data); - - let expanded = quote! { - // The generated impl. - impl #impl_generics heapsize::HeapSize for #name #ty_generics #where_clause { - fn heap_size_of_children(&self) -> usize { - #sum - } - } - }; - - // Hand the output tokens back to the compiler. - proc_macro::TokenStream::from(expanded) -} - -// 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(ref mut type_param) = *param { - type_param.bounds.push(parse_quote!(heapsize::HeapSize)); - } - } - generics -} - -// Generate an expression to sum up the heap size of each field. -fn heap_size_sum(data: &Data) -> TokenStream { - match *data { - Data::Struct(ref data) => { - match data.fields { - Fields::Named(ref fields) => { - // Expands to an expression like - // - // 0 + self.x.heap_size() + self.y.heap_size() + self.z.heap_size() - // - // but using fully qualified function call syntax. - // - // We take some care to use the span of each `syn::Field` as - // the span of the corresponding `heap_size_of_children` - // call. This way if one of the field types does not - // implement `HeapSize` then the compiler's error message - // underlines which field it is. An example is shown in the - // readme of the parent directory. - let recurse = fields.named.iter().map(|f| { - let name = &f.ident; - quote_spanned! {f.span()=> - heapsize::HeapSize::heap_size_of_children(&self.#name) - } - }); - quote! { - 0 #(+ #recurse)* - } - } - Fields::Unnamed(ref fields) => { - // Expands to an expression like - // - // 0 + self.0.heap_size() + self.1.heap_size() + self.2.heap_size() - let recurse = fields.unnamed.iter().enumerate().map(|(i, f)| { - let index = Index::from(i); - quote_spanned! {f.span()=> - heapsize::HeapSize::heap_size_of_children(&self.#index) - } - }); - quote! { - 0 #(+ #recurse)* - } - } - Fields::Unit => { - // Unit structs cannot own more than 0 bytes of heap memory. - quote!(0) - } - } - } - Data::Enum(_) | Data::Union(_) => unimplemented!(), - } -} diff --git a/examples/lazy-static/Cargo.toml b/examples/lazy-static/Cargo.toml deleted file mode 100644 index 586e547f..00000000 --- a/examples/lazy-static/Cargo.toml +++ /dev/null @@ -1,2 +0,0 @@ -[workspace] -members = ["example", "lazy-static"] diff --git a/examples/lazy-static/README.md b/examples/lazy-static/README.md deleted file mode 100644 index bc645854..00000000 --- a/examples/lazy-static/README.md +++ /dev/null @@ -1,42 +0,0 @@ -An example of parsing a custom syntax within a `functionlike!(...)` procedural -macro. Demonstrates how to trigger custom warnings and error messages on -individual tokens of the input. - -- [`lazy-static/src/lib.rs`](lazy-static/src/lib.rs) -- [`example/src/main.rs`](example/src/main.rs) - -The library implements a `lazy_static!` macro similar to the one from the real -[`lazy_static`](https://docs.rs/lazy_static/1.0.0/lazy_static/) crate on -crates.io. - -```rust -lazy_static! { - static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap(); -} -``` - -Compile and run the example by doing `cargo run` in the directory of the -`example` crate. - -The implementation shows how to trigger custom warnings and error messages on -the macro input. For example if you try adding an uncreatively named `FOO` lazy -static, the macro will scold you with the following warning. - -``` -warning: come on, pick a more creative name - --> src/main.rs:10:16 - | -10 | static ref FOO: String = "lazy_static".to_owned(); - | ^^^ -``` - -And if you try to lazily initialize `() = ()`, the macro will outright refuse to -compile it for you. - -``` -error: I can't think of a legitimate use for lazily initializing the value `()` - --> src/main.rs:10:27 - | -10 | static ref UNIT: () = (); - | ^^ -``` diff --git a/examples/lazy-static/example/Cargo.toml b/examples/lazy-static/example/Cargo.toml deleted file mode 100644 index 716b08c0..00000000 --- a/examples/lazy-static/example/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "example" -version = "0.0.0" -authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -publish = false - -[dependencies] -lazy_static = { path = "../lazy-static" } -regex = "0.2" diff --git a/examples/lazy-static/example/src/main.rs b/examples/lazy-static/example/src/main.rs deleted file mode 100644 index c4f64af9..00000000 --- a/examples/lazy-static/example/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use lazy_static::lazy_static; -use regex::Regex; - -lazy_static! { - static ref USERNAME: Regex = { - println!("Compiling username regex..."); - Regex::new("^[a-z0-9_-]{3,16}$").unwrap() - }; -} - -fn main() { - println!("Let's validate some usernames."); - validate("fergie"); - validate("will.i.am"); -} - -fn validate(name: &str) { - // The USERNAME regex is compiled lazily the first time its value is accessed. - println!("is_match({:?}): {}", name, USERNAME.is_match(name)); -} diff --git a/examples/lazy-static/lazy-static/Cargo.toml b/examples/lazy-static/lazy-static/Cargo.toml deleted file mode 100644 index c1a9dfc1..00000000 --- a/examples/lazy-static/lazy-static/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "lazy_static" -version = "0.0.0" -authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -publish = false - -[lib] -proc-macro = true - -[dependencies] -syn = { path = "../../../", features = ["full"] } -quote = "0.6" -proc-macro2 = { version = "0.4", features = ["nightly"] } diff --git a/examples/lazy-static/lazy-static/src/lib.rs b/examples/lazy-static/lazy-static/src/lib.rs deleted file mode 100644 index 5481a30a..00000000 --- a/examples/lazy-static/lazy-static/src/lib.rs +++ /dev/null @@ -1,143 +0,0 @@ -#![recursion_limit = "128"] -#![feature(proc_macro_diagnostic)] - -extern crate proc_macro; -use self::proc_macro::TokenStream; - -use quote::{quote, quote_spanned}; -use syn::parse::{Parse, ParseStream, Result}; -use syn::spanned::Spanned; -use syn::{parse_macro_input, Expr, Ident, Token, Type, Visibility}; - -/// Parses the following syntax, which aligns with the input of the real -/// `lazy_static` crate. -/// -/// lazy_static! { -/// $VISIBILITY static ref $NAME: $TYPE = $EXPR; -/// } -/// -/// For example: -/// -/// lazy_static! { -/// static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap(); -/// } -struct LazyStatic { - visibility: Visibility, - name: Ident, - ty: Type, - init: Expr, -} - -impl Parse for LazyStatic { - fn parse(input: ParseStream) -> Result<Self> { - let visibility: Visibility = input.parse()?; - input.parse::<Token![static]>()?; - input.parse::<Token![ref]>()?; - let name: Ident = input.parse()?; - input.parse::<Token![:]>()?; - let ty: Type = input.parse()?; - input.parse::<Token![=]>()?; - let init: Expr = input.parse()?; - input.parse::<Token![;]>()?; - Ok(LazyStatic { - visibility, - name, - ty, - init, - }) - } -} - -#[proc_macro] -pub fn lazy_static(input: TokenStream) -> TokenStream { - let LazyStatic { - visibility, - name, - ty, - init, - } = parse_macro_input!(input as LazyStatic); - - // The warning looks like this. - // - // warning: come on, pick a more creative name - // --> src/main.rs:10:16 - // | - // 10 | static ref FOO: String = "lazy_static".to_owned(); - // | ^^^ - if name == "FOO" { - name.span() - .unwrap() - .warning("come on, pick a more creative name") - .emit(); - } - - // The error looks like this. - // - // error: I can't think of a legitimate use for lazily initializing the value `()` - // --> src/main.rs:10:27 - // | - // 10 | static ref UNIT: () = (); - // | ^^ - if let Expr::Tuple(ref init) = init { - if init.elems.is_empty() { - init.span() - .unwrap() - .error("I can't think of a legitimate use for lazily initializing the value `()`") - .emit(); - return TokenStream::new(); - } - } - - // Assert that the static type implements Sync. If not, user sees an error - // message like the following. We span this assertion with the field type's - // line/column so that the error message appears in the correct place. - // - // error[E0277]: the trait bound `*const (): std::marker::Sync` is not satisfied - // --> src/main.rs:10:21 - // | - // 10 | static ref PTR: *const () = &(); - // | ^^^^^^^^^ `*const ()` cannot be shared between threads safely - let assert_sync = quote_spanned! {ty.span()=> - struct _AssertSync where #ty: std::marker::Sync; - }; - - // Check for Sized. Not vital to check here, but the error message is less - // confusing this way than if they get a Sized error in one of our - // implementation details where it assumes Sized. - // - // error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied - // --> src/main.rs:10:19 - // | - // 10 | static ref A: str = ""; - // | ^^^ `str` does not have a constant size known at compile-time - let assert_sized = quote_spanned! {ty.span()=> - struct _AssertSized where #ty: std::marker::Sized; - }; - - let init_ptr = quote_spanned! {init.span()=> - Box::into_raw(Box::new(#init)) - }; - - let expanded = quote! { - #visibility struct #name; - - impl std::ops::Deref for #name { - type Target = #ty; - - fn deref(&self) -> &#ty { - #assert_sync - #assert_sized - - static ONCE: std::sync::Once = std::sync::ONCE_INIT; - static mut VALUE: *mut #ty = 0 as *mut #ty; - - unsafe { - ONCE.call_once(|| VALUE = #init_ptr); - &*VALUE - } - } - } - }; - - TokenStream::from(expanded) -} diff --git a/examples/trace-var/Cargo.toml b/examples/trace-var/Cargo.toml deleted file mode 100644 index b54454d5..00000000 --- a/examples/trace-var/Cargo.toml +++ /dev/null @@ -1,2 +0,0 @@ -[workspace] -members = ["example", "trace-var"] diff --git a/examples/trace-var/README.md b/examples/trace-var/README.md deleted file mode 100644 index 09f5f1ac..00000000 --- a/examples/trace-var/README.md +++ /dev/null @@ -1,61 +0,0 @@ -An example of an attribute procedural macro. The `#[trace_var(...)]` attribute -prints the value of the given variables each time they are reassigned. - -- [`trace-var/src/lib.rs`](trace-var/src/lib.rs) -- [`example/src/main.rs`](example/src/main.rs) - -Consider the following factorial implementation. - -```rust -#[trace_var(p, n)] -fn factorial(mut n: u64) -> u64 { - let mut p = 1; - while n > 1 { - p *= n; - n -= 1; - } - p -} -``` - -Invoking this with `factorial(8)` prints all the values of `p` and `n` during -the execution of the function. - -``` -p = 1 -p = 8 -n = 7 -p = 56 -n = 6 -p = 336 -n = 5 -p = 1680 -n = 4 -p = 6720 -n = 3 -p = 20160 -n = 2 -p = 40320 -n = 1 -``` - -The procedural macro uses a syntax tree [`Fold`] to rewrite every `let` -statement and assignment expression in the following way: - -[`Fold`]: https://docs.rs/syn/0.15/syn/fold/trait.Fold.html - -```rust -// Before -let VAR = INIT; - -// After -let VAR = { let VAR = INIT; println!("VAR = {:?}", VAR); VAR }; -``` - -```rust -// Before -VAR = INIT - -// After -{ VAR = INIT; println!("VAR = {:?}", VAR); } -``` diff --git a/examples/trace-var/example/Cargo.toml b/examples/trace-var/example/Cargo.toml deleted file mode 100644 index d2ad6502..00000000 --- a/examples/trace-var/example/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "example" -version = "0.0.0" -authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -publish = false - -[dependencies] -trace-var = { path = "../trace-var" } diff --git a/examples/trace-var/example/src/main.rs b/examples/trace-var/example/src/main.rs deleted file mode 100644 index da2c10b8..00000000 --- a/examples/trace-var/example/src/main.rs +++ /dev/null @@ -1,15 +0,0 @@ -use trace_var::trace_var; - -fn main() { - println!("{}", factorial(8)); -} - -#[trace_var(p, n)] -fn factorial(mut n: u64) -> u64 { - let mut p = 1; - while n > 1 { - p *= n; - n -= 1; - } - p -} diff --git a/examples/trace-var/trace-var/Cargo.toml b/examples/trace-var/trace-var/Cargo.toml deleted file mode 100644 index 0228ed5b..00000000 --- a/examples/trace-var/trace-var/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "trace-var" -version = "0.0.0" -authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -publish = false - -[lib] -proc-macro = true - -[dependencies] -syn = { path = "../../../", features = ["full", "fold"] } -quote = "0.6" -proc-macro2 = { version = "0.4", features = ["nightly"] } diff --git a/examples/trace-var/trace-var/src/lib.rs b/examples/trace-var/trace-var/src/lib.rs deleted file mode 100644 index 606c87a6..00000000 --- a/examples/trace-var/trace-var/src/lib.rs +++ /dev/null @@ -1,186 +0,0 @@ -extern crate proc_macro; -use self::proc_macro::TokenStream; - -use quote::{quote, ToTokens}; -use std::collections::HashSet as Set; -use syn::fold::{self, Fold}; -use syn::parse::{Parse, ParseStream, Result}; -use syn::punctuated::Punctuated; -use syn::{parse_macro_input, parse_quote, Expr, Ident, ItemFn, Local, Pat, Stmt, Token}; - -/// Parses a list of variable names separated by commas. -/// -/// a, b, c -/// -/// This is how the compiler passes in arguments to our attribute -- it is -/// everything inside the delimiters after the attribute name. -/// -/// #[trace_var(a, b, c)] -/// ^^^^^^^ -struct Args { - vars: Set<Ident>, -} - -impl Parse for Args { - fn parse(input: ParseStream) -> Result<Self> { - let vars = Punctuated::<Ident, Token![,]>::parse_terminated(input)?; - Ok(Args { - vars: vars.into_iter().collect(), - }) - } -} - -impl Args { - /// Determines whether the given `Expr` is a path referring to one of the - /// variables we intend to print. Expressions are used as the left-hand side - /// of the assignment operator. - fn should_print_expr(&self, e: &Expr) -> bool { - match *e { - Expr::Path(ref e) => { - if e.path.leading_colon.is_some() { - false - } else if e.path.segments.len() != 1 { - false - } else { - let first = e.path.segments.first().unwrap(); - let segment = first.value(); - self.vars.contains(&segment.ident) && segment.arguments.is_empty() - } - } - _ => false, - } - } - - /// Determines whether the given `Pat` is an identifier equal to one of the - /// variables we intend to print. Patterns are used as the left-hand side of - /// a `let` binding. - fn should_print_pat(&self, p: &Punctuated<Pat, Token![|]>) -> bool { - if p.len() != 1 { - return false; - } - match p[0] { - Pat::Ident(ref p) => self.vars.contains(&p.ident), - _ => false, - } - } - - /// Produces an expression that assigns the right-hand side to the left-hand - /// side and then prints the value. - /// - /// // Before - /// VAR = INIT - /// - /// // After - /// { VAR = INIT; println!("VAR = {:?}", VAR); } - fn assign_and_print(&mut self, left: Expr, op: &ToTokens, right: Expr) -> Expr { - let right = fold::fold_expr(self, right); - parse_quote!({ - #left #op #right; - println!(concat!(stringify!(#left), " = {:?}"), #left); - }) - } - - /// Produces a let-binding that assigns the right-hand side to the left-hand - /// side and then prints the value. - /// - /// // Before - /// let VAR = INIT; - /// - /// // After - /// let VAR = { let VAR = INIT; println!("VAR = {:?}", VAR); VAR }; - fn let_and_print(&mut self, local: Local) -> Stmt { - let Local { pats, ty, init, .. } = local; - let pat = &pats[0]; - let ty = ty.map(|(colon_token, ty)| quote!(#colon_token #ty)); - let init = self.fold_expr(*init.unwrap().1); - let ident = match *pat { - Pat::Ident(ref p) => &p.ident, - _ => unreachable!(), - }; - parse_quote! { - let #pat #ty = { - #[allow(unused_mut)] - let #pat = #init; - println!(concat!(stringify!(#ident), " = {:?}"), #ident); - #ident - }; - } - } -} - -/// The `Fold` trait is a way to traverse an owned syntax tree and replace some -/// of its nodes. -/// -/// Syn provides two other syntax tree traversal traits: `Visit` which walks a -/// shared borrow of a syntax tree, and `VisitMut` which walks an exclusive -/// borrow of a syntax tree and can mutate it in place. -/// -/// All three traits have a method corresponding to each type of node in Syn's -/// syntax tree. All of these methods have default no-op implementations that -/// simply recurse on any child nodes. We can override only those methods for -/// which we want non-default behavior. In this case the traversal needs to -/// transform `Expr` and `Stmt` nodes. -impl Fold for Args { - fn fold_expr(&mut self, e: Expr) -> Expr { - match e { - Expr::Assign(e) => { - if self.should_print_expr(&e.left) { - self.assign_and_print(*e.left, &e.eq_token, *e.right) - } else { - Expr::Assign(fold::fold_expr_assign(self, e)) - } - } - Expr::AssignOp(e) => { - if self.should_print_expr(&e.left) { - self.assign_and_print(*e.left, &e.op, *e.right) - } else { - Expr::AssignOp(fold::fold_expr_assign_op(self, e)) - } - } - _ => fold::fold_expr(self, e), - } - } - - fn fold_stmt(&mut self, s: Stmt) -> Stmt { - match s { - Stmt::Local(s) => { - if s.init.is_some() && self.should_print_pat(&s.pats) { - self.let_and_print(s) - } else { - Stmt::Local(fold::fold_local(self, s)) - } - } - _ => fold::fold_stmt(self, s), - } - } -} - -/// Attribute to print the value of the given variables each time they are -/// reassigned. -/// -/// # Example -/// -/// ``` -/// #[trace_var(p, n)] -/// fn factorial(mut n: u64) -> u64 { -/// let mut p = 1; -/// while n > 1 { -/// p *= n; -/// n -= 1; -/// } -/// p -/// } -/// ``` -#[proc_macro_attribute] -pub fn trace_var(args: TokenStream, input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as ItemFn); - - // Parse the list of variables the user wanted to print. - let mut args = parse_macro_input!(args as Args); - - // Use a syntax tree traversal to transform the function body. - let output = args.fold_item_fn(input); - - // Hand the resulting function body back to the compiler. - TokenStream::from(quote!(#output)) -} diff --git a/json/Cargo.toml b/json/Cargo.toml deleted file mode 100644 index 77104dc8..00000000 --- a/json/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "syn-codegen" -version = "0.1.0" -authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -license = "MIT OR Apache-2.0" -description = "Syntax tree describing Syn's syntax tree" -repository = "https://github.com/dtolnay/syn" -documentation = "https://docs.rs/syn-codegen" -categories = ["development-tools::procedural-macro-helpers"] - -[dependencies] -indexmap = { version = "1.0", features = ["serde-1"] } -semver = { version = "0.9", features = ["serde"] } -serde = { version = "1.0.88", features = ["derive"] } - -[dev-dependencies] -serde_json = "1.0" diff --git a/json/src/lib.rs b/json/src/lib.rs deleted file mode 100644 index be0ac5fc..00000000 --- a/json/src/lib.rs +++ /dev/null @@ -1,203 +0,0 @@ -//! # Data structures that describe Syn's syntax tree. -//! -//! The Syn syntax tree is made up of more than 200 types. Occasionally it can -//! come up that you need to implement some behavior across them all. -//! -//! - For example [the Rust integration for AST Explorer][astexplorer] wants to -//! turn a syntax tree from Syn into a JavaScript value understood by the -//! platform's existing cross-language syntax tree visualization code. -//! -//! [astexplorer]: https://astexplorer.net/#/gist/388150a52f74d45a355d2b5e865ded96/0c6d563f28d900472f699c21a1845ad20ae9927f -//! -//! - As another example from within Syn itself, the traits and implementations -//! of the [`visit`], [`visit_mut`], and [`fold`] modules can be generated -//! programmatically from a description of the syntax tree. -//! -//! [`visit`]: https://docs.rs/syn/0.15/syn/visit/index.html -//! [`visit_mut`]: https://docs.rs/syn/0.15/syn/visit_mut/index.html -//! [`fold`]: https://docs.rs/syn/0.15/syn/fold/index.html -//! -//! To make this type of code as easy as possible to implement in any language, -//! every Syn release comes with a machine-readable description of that version -//! of the syntax tree as a JSON file [syn.json]. This `syn-codegen` crate -//! provides the canonical data structures for parsing and making use of the -//! representation in syn.json from Rust code. -//! -//! [syn.json]: https://raw.githubusercontent.com/dtolnay/syn/master/syn.json -//! -//! ## Example -//! -//! ``` -//! use syn_codegen::Definitions; -//! -//! # const IGNORE: &str = stringify! { -//! const SYN: &str = include_str!("syn.json"); -//! # }; -//! # const SYN: &str = include_str!("../../syn.json"); -//! -//! fn main() { -//! let defs: Definitions = serde_json::from_str(SYN).unwrap(); -//! -//! for node in &defs.types { -//! println!("syn::{}", node.ident); -//! } -//! } -//! ``` - -use indexmap::IndexMap; -use semver::Version; -use serde::{Deserialize, Deserializer, Serialize}; - -use std::collections::{BTreeMap, BTreeSet}; - -/// Top-level content of the syntax tree description. -#[derive(Debug, PartialEq, Serialize, Deserialize)] -pub struct Definitions { - /// The Syn version whose syntax tree is described by this data. - pub version: Version, - - /// Syntax tree types defined by Syn. - pub types: Vec<Node>, - - /// Token types defined by Syn (keywords as well as punctuation). - /// - /// The keys in the map are the Rust type name for the token. The values in - /// the map are the printed token representation. - /// - /// These tokens are accessible in the Syn public API as `syn::token::#name` - /// or alternatively `syn::Token![#repr]`. - pub tokens: BTreeMap<String, String>, -} - -/// Syntax tree type defined by Syn. -#[derive(Debug, PartialEq, Serialize, Deserialize)] -pub struct Node { - /// Name of the type. - /// - /// This type is accessible in the Syn public API as `syn::#name`. - pub ident: String, - - /// Features behind which this type is cfg gated. - pub features: Features, - - /// Content of the data structure. - #[serde( - flatten, - skip_serializing_if = "is_private", - deserialize_with = "private_if_absent" - )] - pub data: Data, -} - -/// Content of a syntax tree data structure. -#[derive(Debug, PartialEq, Serialize, Deserialize)] -pub enum Data { - /// This is an opaque type with no publicy accessible structure. - Private, - - /// This type is a braced struct with named fields. - #[serde(rename = "fields")] - Struct(Fields), - - /// This type is an enum. - #[serde(rename = "variants")] - Enum(Variants), -} - -/// Fields of a braced struct syntax tree node with named fields. -/// -/// The keys in the map are the field names. -pub type Fields = IndexMap<String, Type>; - -/// Variants of an enum syntax tree node. -/// -/// The keys in the map are the variant names. -/// -/// Variants are unit variants if they hold no data and tuple variants -/// otherwise. The Syn syntax tree does not make use of braced variants. -pub type Variants = IndexMap<String, Vec<Type>>; - -/// Type of a struct field or tuple variant field in the syntax tree. -#[derive(Debug, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "lowercase")] -pub enum Type { - /// Syntax tree type defined by Syn. - /// - /// This name will match the ident of some `Node`. - Syn(String), - - /// Type defined by the Rust language or standard library. - /// - /// All such types used by Syn are accessible in the Rust prelude and can be - /// used without a qualifying path in most Rust code. - Std(String), - - /// Type defined by proc-macro2. - /// - /// The type is accessible in the proc-macro2 public API as - /// `proc_macro2::#name`. - #[serde(rename = "proc_macro2")] - Ext(String), - - /// Keyword or punctuation token type defined by Syn. - /// - /// This name will match one of the keys in the `tokens` map. - Token(String), - - /// Grouping token defined by Syn. - /// - /// The type is accessible in the Syn public API as `syn::token::#name`. - Group(String), - - /// Punctuated list. - /// - /// This refers to `syn::punctuated::Punctuated<T, P>` with the specified - /// element type and punctuation. - Punctuated(Punctuated), - - /// `std::option::Option` - Option(Box<Type>), - - /// `std::boxed::Box` - Box(Box<Type>), - - /// `std::vec::Vec` - Vec(Box<Type>), - - /// Rust tuple with two or more fields. - Tuple(Vec<Type>), -} - -/// Type of a punctuated list. -/// -/// This refers to `syn::punctuated::Punctuated<#element, #punct>`. -/// -/// The punct string will match one of the keys in the `tokens` map. -#[derive(Debug, PartialEq, Serialize, Deserialize)] -pub struct Punctuated { - pub element: Box<Type>, - pub punct: String, -} - -/// Features behind which a syntax tree type is cfg gated. -#[derive(Debug, Default, PartialEq, Serialize, Deserialize)] -pub struct Features { - /// Type is accessible if at least one of these features is enabled against - /// the Syn dependency. - pub any: BTreeSet<String>, -} - -fn is_private(data: &Data) -> bool { - match data { - Data::Private => true, - Data::Struct(_) | Data::Enum(_) => false, - } -} - -fn private_if_absent<'de, D>(deserializer: D) -> Result<Data, D::Error> -where - D: Deserializer<'de>, -{ - let option = Option::deserialize(deserializer)?; - Ok(option.unwrap_or(Data::Private)) -} diff --git a/syn.json b/syn.json deleted file mode 100644 index 8d35d4a7..00000000 --- a/syn.json +++ /dev/null @@ -1,5834 +0,0 @@ -{ - "version": "0.15.42", - "types": [ - { - "ident": "Abi", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "extern_token": { - "token": "Extern" - }, - "name": { - "option": { - "syn": "LitStr" - } - } - } - }, - { - "ident": "AngleBracketedGenericArguments", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "colon2_token": { - "option": { - "token": "Colon2" - } - }, - "lt_token": { - "token": "Lt" - }, - "args": { - "punctuated": { - "element": { - "syn": "GenericArgument" - }, - "punct": "Comma" - } - }, - "gt_token": { - "token": "Gt" - } - } - }, - { - "ident": "ArgCaptured", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "pat": { - "syn": "Pat" - }, - "colon_token": { - "token": "Colon" - }, - "ty": { - "syn": "Type" - } - } - }, - { - "ident": "ArgSelf", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "mutability": { - "option": { - "token": "Mut" - } - }, - "self_token": { - "token": "SelfValue" - } - } - }, - { - "ident": "ArgSelfRef", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "and_token": { - "token": "And" - }, - "lifetime": { - "option": { - "syn": "Lifetime" - } - }, - "mutability": { - "option": { - "token": "Mut" - } - }, - "self_token": { - "token": "SelfValue" - } - } - }, - { - "ident": "Arm", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "leading_vert": { - "option": { - "token": "Or" - } - }, - "pats": { - "punctuated": { - "element": { - "syn": "Pat" - }, - "punct": "Or" - } - }, - "guard": { - "option": { - "tuple": [ - { - "token": "If" - }, - { - "box": { - "syn": "Expr" - } - } - ] - } - }, - "fat_arrow_token": { - "token": "FatArrow" - }, - "body": { - "box": { - "syn": "Expr" - } - }, - "comma": { - "option": { - "token": "Comma" - } - } - } - }, - { - "ident": "AttrStyle", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Outer": [], - "Inner": [ - { - "token": "Bang" - } - ] - } - }, - { - "ident": "Attribute", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "pound_token": { - "token": "Pound" - }, - "style": { - "syn": "AttrStyle" - }, - "bracket_token": { - "group": "Bracket" - }, - "path": { - "syn": "Path" - }, - "tts": { - "proc_macro2": "TokenStream" - } - } - }, - { - "ident": "BareFnArg", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "name": { - "option": { - "tuple": [ - { - "syn": "BareFnArgName" - }, - { - "token": "Colon" - } - ] - } - }, - "ty": { - "syn": "Type" - } - } - }, - { - "ident": "BareFnArgName", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Named": [ - { - "proc_macro2": "Ident" - } - ], - "Wild": [ - { - "token": "Underscore" - } - ] - } - }, - { - "ident": "BinOp", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Add": [ - { - "token": "Add" - } - ], - "Sub": [ - { - "token": "Sub" - } - ], - "Mul": [ - { - "token": "Star" - } - ], - "Div": [ - { - "token": "Div" - } - ], - "Rem": [ - { - "token": "Rem" - } - ], - "And": [ - { - "token": "AndAnd" - } - ], - "Or": [ - { - "token": "OrOr" - } - ], - "BitXor": [ - { - "token": "Caret" - } - ], - "BitAnd": [ - { - "token": "And" - } - ], - "BitOr": [ - { - "token": "Or" - } - ], - "Shl": [ - { - "token": "Shl" - } - ], - "Shr": [ - { - "token": "Shr" - } - ], - "Eq": [ - { - "token": "EqEq" - } - ], - "Lt": [ - { - "token": "Lt" - } - ], - "Le": [ - { - "token": "Le" - } - ], - "Ne": [ - { - "token": "Ne" - } - ], - "Ge": [ - { - "token": "Ge" - } - ], - "Gt": [ - { - "token": "Gt" - } - ], - "AddEq": [ - { - "token": "AddEq" - } - ], - "SubEq": [ - { - "token": "SubEq" - } - ], - "MulEq": [ - { - "token": "MulEq" - } - ], - "DivEq": [ - { - "token": "DivEq" - } - ], - "RemEq": [ - { - "token": "RemEq" - } - ], - "BitXorEq": [ - { - "token": "CaretEq" - } - ], - "BitAndEq": [ - { - "token": "AndEq" - } - ], - "BitOrEq": [ - { - "token": "OrEq" - } - ], - "ShlEq": [ - { - "token": "ShlEq" - } - ], - "ShrEq": [ - { - "token": "ShrEq" - } - ] - } - }, - { - "ident": "Binding", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "ident": { - "proc_macro2": "Ident" - }, - "eq_token": { - "token": "Eq" - }, - "ty": { - "syn": "Type" - } - } - }, - { - "ident": "Block", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "brace_token": { - "group": "Brace" - }, - "stmts": { - "vec": { - "syn": "Stmt" - } - } - } - }, - { - "ident": "BoundLifetimes", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "for_token": { - "token": "For" - }, - "lt_token": { - "token": "Lt" - }, - "lifetimes": { - "punctuated": { - "element": { - "syn": "LifetimeDef" - }, - "punct": "Comma" - } - }, - "gt_token": { - "token": "Gt" - } - } - }, - { - "ident": "ConstParam", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "const_token": { - "token": "Const" - }, - "ident": { - "proc_macro2": "Ident" - }, - "colon_token": { - "token": "Colon" - }, - "ty": { - "syn": "Type" - }, - "eq_token": { - "option": { - "token": "Eq" - } - }, - "default": { - "option": { - "syn": "Expr" - } - } - } - }, - { - "ident": "Constraint", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "ident": { - "proc_macro2": "Ident" - }, - "colon_token": { - "token": "Colon" - }, - "bounds": { - "punctuated": { - "element": { - "syn": "TypeParamBound" - }, - "punct": "Add" - } - } - } - }, - { - "ident": "Data", - "features": { - "any": [ - "derive" - ] - }, - "variants": { - "Struct": [ - { - "syn": "DataStruct" - } - ], - "Enum": [ - { - "syn": "DataEnum" - } - ], - "Union": [ - { - "syn": "DataUnion" - } - ] - } - }, - { - "ident": "DataEnum", - "features": { - "any": [ - "derive" - ] - }, - "fields": { - "enum_token": { - "token": "Enum" - }, - "brace_token": { - "group": "Brace" - }, - "variants": { - "punctuated": { - "element": { - "syn": "Variant" - }, - "punct": "Comma" - } - } - } - }, - { - "ident": "DataStruct", - "features": { - "any": [ - "derive" - ] - }, - "fields": { - "struct_token": { - "token": "Struct" - }, - "fields": { - "syn": "Fields" - }, - "semi_token": { - "option": { - "token": "Semi" - } - } - } - }, - { - "ident": "DataUnion", - "features": { - "any": [ - "derive" - ] - }, - "fields": { - "union_token": { - "token": "Union" - }, - "fields": { - "syn": "FieldsNamed" - } - } - }, - { - "ident": "DeriveInput", - "features": { - "any": [ - "derive" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "ident": { - "proc_macro2": "Ident" - }, - "generics": { - "syn": "Generics" - }, - "data": { - "syn": "Data" - } - } - }, - { - "ident": "Expr", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Box": [ - { - "syn": "ExprBox" - } - ], - "InPlace": [ - { - "syn": "ExprInPlace" - } - ], - "Array": [ - { - "syn": "ExprArray" - } - ], - "Call": [ - { - "syn": "ExprCall" - } - ], - "MethodCall": [ - { - "syn": "ExprMethodCall" - } - ], - "Tuple": [ - { - "syn": "ExprTuple" - } - ], - "Binary": [ - { - "syn": "ExprBinary" - } - ], - "Unary": [ - { - "syn": "ExprUnary" - } - ], - "Lit": [ - { - "syn": "ExprLit" - } - ], - "Cast": [ - { - "syn": "ExprCast" - } - ], - "Type": [ - { - "syn": "ExprType" - } - ], - "Let": [ - { - "syn": "ExprLet" - } - ], - "If": [ - { - "syn": "ExprIf" - } - ], - "While": [ - { - "syn": "ExprWhile" - } - ], - "ForLoop": [ - { - "syn": "ExprForLoop" - } - ], - "Loop": [ - { - "syn": "ExprLoop" - } - ], - "Match": [ - { - "syn": "ExprMatch" - } - ], - "Closure": [ - { - "syn": "ExprClosure" - } - ], - "Unsafe": [ - { - "syn": "ExprUnsafe" - } - ], - "Block": [ - { - "syn": "ExprBlock" - } - ], - "Assign": [ - { - "syn": "ExprAssign" - } - ], - "AssignOp": [ - { - "syn": "ExprAssignOp" - } - ], - "Field": [ - { - "syn": "ExprField" - } - ], - "Index": [ - { - "syn": "ExprIndex" - } - ], - "Range": [ - { - "syn": "ExprRange" - } - ], - "Path": [ - { - "syn": "ExprPath" - } - ], - "Reference": [ - { - "syn": "ExprReference" - } - ], - "Break": [ - { - "syn": "ExprBreak" - } - ], - "Continue": [ - { - "syn": "ExprContinue" - } - ], - "Return": [ - { - "syn": "ExprReturn" - } - ], - "Macro": [ - { - "syn": "ExprMacro" - } - ], - "Struct": [ - { - "syn": "ExprStruct" - } - ], - "Repeat": [ - { - "syn": "ExprRepeat" - } - ], - "Paren": [ - { - "syn": "ExprParen" - } - ], - "Group": [ - { - "syn": "ExprGroup" - } - ], - "Try": [ - { - "syn": "ExprTry" - } - ], - "Async": [ - { - "syn": "ExprAsync" - } - ], - "TryBlock": [ - { - "syn": "ExprTryBlock" - } - ], - "Yield": [ - { - "syn": "ExprYield" - } - ], - "Verbatim": [ - { - "syn": "ExprVerbatim" - } - ] - } - }, - { - "ident": "ExprArray", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "bracket_token": { - "group": "Bracket" - }, - "elems": { - "punctuated": { - "element": { - "syn": "Expr" - }, - "punct": "Comma" - } - } - } - }, - { - "ident": "ExprAssign", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "left": { - "box": { - "syn": "Expr" - } - }, - "eq_token": { - "token": "Eq" - }, - "right": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "ExprAssignOp", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "left": { - "box": { - "syn": "Expr" - } - }, - "op": { - "syn": "BinOp" - }, - "right": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "ExprAsync", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "async_token": { - "token": "Async" - }, - "capture": { - "option": { - "token": "Move" - } - }, - "block": { - "syn": "Block" - } - } - }, - { - "ident": "ExprBinary", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "left": { - "box": { - "syn": "Expr" - } - }, - "op": { - "syn": "BinOp" - }, - "right": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "ExprBlock", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "label": { - "option": { - "syn": "Label" - } - }, - "block": { - "syn": "Block" - } - } - }, - { - "ident": "ExprBox", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "box_token": { - "token": "Box" - }, - "expr": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "ExprBreak", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "break_token": { - "token": "Break" - }, - "label": { - "option": { - "syn": "Lifetime" - } - }, - "expr": { - "option": { - "box": { - "syn": "Expr" - } - } - } - } - }, - { - "ident": "ExprCall", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "func": { - "box": { - "syn": "Expr" - } - }, - "paren_token": { - "group": "Paren" - }, - "args": { - "punctuated": { - "element": { - "syn": "Expr" - }, - "punct": "Comma" - } - } - } - }, - { - "ident": "ExprCast", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "expr": { - "box": { - "syn": "Expr" - } - }, - "as_token": { - "token": "As" - }, - "ty": { - "box": { - "syn": "Type" - } - } - } - }, - { - "ident": "ExprClosure", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "asyncness": { - "option": { - "token": "Async" - } - }, - "movability": { - "option": { - "token": "Static" - } - }, - "capture": { - "option": { - "token": "Move" - } - }, - "or1_token": { - "token": "Or" - }, - "inputs": { - "punctuated": { - "element": { - "syn": "FnArg" - }, - "punct": "Comma" - } - }, - "or2_token": { - "token": "Or" - }, - "output": { - "syn": "ReturnType" - }, - "body": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "ExprContinue", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "continue_token": { - "token": "Continue" - }, - "label": { - "option": { - "syn": "Lifetime" - } - } - } - }, - { - "ident": "ExprField", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "base": { - "box": { - "syn": "Expr" - } - }, - "dot_token": { - "token": "Dot" - }, - "member": { - "syn": "Member" - } - } - }, - { - "ident": "ExprForLoop", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "label": { - "option": { - "syn": "Label" - } - }, - "for_token": { - "token": "For" - }, - "pat": { - "box": { - "syn": "Pat" - } - }, - "in_token": { - "token": "In" - }, - "expr": { - "box": { - "syn": "Expr" - } - }, - "body": { - "syn": "Block" - } - } - }, - { - "ident": "ExprGroup", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "group_token": { - "group": "Group" - }, - "expr": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "ExprIf", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "if_token": { - "token": "If" - }, - "cond": { - "box": { - "syn": "Expr" - } - }, - "then_branch": { - "syn": "Block" - }, - "else_branch": { - "option": { - "tuple": [ - { - "token": "Else" - }, - { - "box": { - "syn": "Expr" - } - } - ] - } - } - } - }, - { - "ident": "ExprInPlace", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "place": { - "box": { - "syn": "Expr" - } - }, - "arrow_token": { - "token": "LArrow" - }, - "value": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "ExprIndex", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "expr": { - "box": { - "syn": "Expr" - } - }, - "bracket_token": { - "group": "Bracket" - }, - "index": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "ExprLet", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "let_token": { - "token": "Let" - }, - "pats": { - "punctuated": { - "element": { - "syn": "Pat" - }, - "punct": "Or" - } - }, - "eq_token": { - "token": "Eq" - }, - "expr": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "ExprLit", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "lit": { - "syn": "Lit" - } - } - }, - { - "ident": "ExprLoop", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "label": { - "option": { - "syn": "Label" - } - }, - "loop_token": { - "token": "Loop" - }, - "body": { - "syn": "Block" - } - } - }, - { - "ident": "ExprMacro", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "mac": { - "syn": "Macro" - } - } - }, - { - "ident": "ExprMatch", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "match_token": { - "token": "Match" - }, - "expr": { - "box": { - "syn": "Expr" - } - }, - "brace_token": { - "group": "Brace" - }, - "arms": { - "vec": { - "syn": "Arm" - } - } - } - }, - { - "ident": "ExprMethodCall", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "receiver": { - "box": { - "syn": "Expr" - } - }, - "dot_token": { - "token": "Dot" - }, - "method": { - "proc_macro2": "Ident" - }, - "turbofish": { - "option": { - "syn": "MethodTurbofish" - } - }, - "paren_token": { - "group": "Paren" - }, - "args": { - "punctuated": { - "element": { - "syn": "Expr" - }, - "punct": "Comma" - } - } - } - }, - { - "ident": "ExprParen", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "paren_token": { - "group": "Paren" - }, - "expr": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "ExprPath", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "qself": { - "option": { - "syn": "QSelf" - } - }, - "path": { - "syn": "Path" - } - } - }, - { - "ident": "ExprRange", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "from": { - "option": { - "box": { - "syn": "Expr" - } - } - }, - "limits": { - "syn": "RangeLimits" - }, - "to": { - "option": { - "box": { - "syn": "Expr" - } - } - } - } - }, - { - "ident": "ExprReference", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "and_token": { - "token": "And" - }, - "mutability": { - "option": { - "token": "Mut" - } - }, - "expr": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "ExprRepeat", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "bracket_token": { - "group": "Bracket" - }, - "expr": { - "box": { - "syn": "Expr" - } - }, - "semi_token": { - "token": "Semi" - }, - "len": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "ExprReturn", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "return_token": { - "token": "Return" - }, - "expr": { - "option": { - "box": { - "syn": "Expr" - } - } - } - } - }, - { - "ident": "ExprStruct", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "path": { - "syn": "Path" - }, - "brace_token": { - "group": "Brace" - }, - "fields": { - "punctuated": { - "element": { - "syn": "FieldValue" - }, - "punct": "Comma" - } - }, - "dot2_token": { - "option": { - "token": "Dot2" - } - }, - "rest": { - "option": { - "box": { - "syn": "Expr" - } - } - } - } - }, - { - "ident": "ExprTry", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "expr": { - "box": { - "syn": "Expr" - } - }, - "question_token": { - "token": "Question" - } - } - }, - { - "ident": "ExprTryBlock", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "try_token": { - "token": "Try" - }, - "block": { - "syn": "Block" - } - } - }, - { - "ident": "ExprTuple", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "paren_token": { - "group": "Paren" - }, - "elems": { - "punctuated": { - "element": { - "syn": "Expr" - }, - "punct": "Comma" - } - } - } - }, - { - "ident": "ExprType", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "expr": { - "box": { - "syn": "Expr" - } - }, - "colon_token": { - "token": "Colon" - }, - "ty": { - "box": { - "syn": "Type" - } - } - } - }, - { - "ident": "ExprUnary", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "op": { - "syn": "UnOp" - }, - "expr": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "ExprUnsafe", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "unsafe_token": { - "token": "Unsafe" - }, - "block": { - "syn": "Block" - } - } - }, - { - "ident": "ExprVerbatim", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "tts": { - "proc_macro2": "TokenStream" - } - } - }, - { - "ident": "ExprWhile", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "label": { - "option": { - "syn": "Label" - } - }, - "while_token": { - "token": "While" - }, - "cond": { - "box": { - "syn": "Expr" - } - }, - "body": { - "syn": "Block" - } - } - }, - { - "ident": "ExprYield", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "yield_token": { - "token": "Yield" - }, - "expr": { - "option": { - "box": { - "syn": "Expr" - } - } - } - } - }, - { - "ident": "Field", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "ident": { - "option": { - "proc_macro2": "Ident" - } - }, - "colon_token": { - "option": { - "token": "Colon" - } - }, - "ty": { - "syn": "Type" - } - } - }, - { - "ident": "FieldPat", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "member": { - "syn": "Member" - }, - "colon_token": { - "option": { - "token": "Colon" - } - }, - "pat": { - "box": { - "syn": "Pat" - } - } - } - }, - { - "ident": "FieldValue", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "member": { - "syn": "Member" - }, - "colon_token": { - "option": { - "token": "Colon" - } - }, - "expr": { - "syn": "Expr" - } - } - }, - { - "ident": "Fields", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Named": [ - { - "syn": "FieldsNamed" - } - ], - "Unnamed": [ - { - "syn": "FieldsUnnamed" - } - ], - "Unit": [] - } - }, - { - "ident": "FieldsNamed", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "brace_token": { - "group": "Brace" - }, - "named": { - "punctuated": { - "element": { - "syn": "Field" - }, - "punct": "Comma" - } - } - } - }, - { - "ident": "FieldsUnnamed", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "paren_token": { - "group": "Paren" - }, - "unnamed": { - "punctuated": { - "element": { - "syn": "Field" - }, - "punct": "Comma" - } - } - } - }, - { - "ident": "File", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "shebang": { - "option": { - "std": "String" - } - }, - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "items": { - "vec": { - "syn": "Item" - } - } - } - }, - { - "ident": "FnArg", - "features": { - "any": [ - "full" - ] - }, - "variants": { - "SelfRef": [ - { - "syn": "ArgSelfRef" - } - ], - "SelfValue": [ - { - "syn": "ArgSelf" - } - ], - "Captured": [ - { - "syn": "ArgCaptured" - } - ], - "Inferred": [ - { - "syn": "Pat" - } - ], - "Ignored": [ - { - "syn": "Type" - } - ] - } - }, - { - "ident": "FnDecl", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "fn_token": { - "token": "Fn" - }, - "generics": { - "syn": "Generics" - }, - "paren_token": { - "group": "Paren" - }, - "inputs": { - "punctuated": { - "element": { - "syn": "FnArg" - }, - "punct": "Comma" - } - }, - "variadic": { - "option": { - "token": "Dot3" - } - }, - "output": { - "syn": "ReturnType" - } - } - }, - { - "ident": "ForeignItem", - "features": { - "any": [ - "full" - ] - }, - "variants": { - "Fn": [ - { - "syn": "ForeignItemFn" - } - ], - "Static": [ - { - "syn": "ForeignItemStatic" - } - ], - "Type": [ - { - "syn": "ForeignItemType" - } - ], - "Macro": [ - { - "syn": "ForeignItemMacro" - } - ], - "Verbatim": [ - { - "syn": "ForeignItemVerbatim" - } - ] - } - }, - { - "ident": "ForeignItemFn", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "ident": { - "proc_macro2": "Ident" - }, - "decl": { - "box": { - "syn": "FnDecl" - } - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "ForeignItemMacro", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "mac": { - "syn": "Macro" - }, - "semi_token": { - "option": { - "token": "Semi" - } - } - } - }, - { - "ident": "ForeignItemStatic", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "static_token": { - "token": "Static" - }, - "mutability": { - "option": { - "token": "Mut" - } - }, - "ident": { - "proc_macro2": "Ident" - }, - "colon_token": { - "token": "Colon" - }, - "ty": { - "box": { - "syn": "Type" - } - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "ForeignItemType", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "type_token": { - "token": "Type" - }, - "ident": { - "proc_macro2": "Ident" - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "ForeignItemVerbatim", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "tts": { - "proc_macro2": "TokenStream" - } - } - }, - { - "ident": "GenericArgument", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Lifetime": [ - { - "syn": "Lifetime" - } - ], - "Type": [ - { - "syn": "Type" - } - ], - "Binding": [ - { - "syn": "Binding" - } - ], - "Constraint": [ - { - "syn": "Constraint" - } - ], - "Const": [ - { - "syn": "Expr" - } - ] - } - }, - { - "ident": "GenericMethodArgument", - "features": { - "any": [ - "full" - ] - }, - "variants": { - "Type": [ - { - "syn": "Type" - } - ], - "Const": [ - { - "syn": "Expr" - } - ] - } - }, - { - "ident": "GenericParam", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Type": [ - { - "syn": "TypeParam" - } - ], - "Lifetime": [ - { - "syn": "LifetimeDef" - } - ], - "Const": [ - { - "syn": "ConstParam" - } - ] - } - }, - { - "ident": "Generics", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "lt_token": { - "option": { - "token": "Lt" - } - }, - "params": { - "punctuated": { - "element": { - "syn": "GenericParam" - }, - "punct": "Comma" - } - }, - "gt_token": { - "option": { - "token": "Gt" - } - }, - "where_clause": { - "option": { - "syn": "WhereClause" - } - } - } - }, - { - "ident": "ImplItem", - "features": { - "any": [ - "full" - ] - }, - "variants": { - "Const": [ - { - "syn": "ImplItemConst" - } - ], - "Method": [ - { - "syn": "ImplItemMethod" - } - ], - "Type": [ - { - "syn": "ImplItemType" - } - ], - "Existential": [ - { - "syn": "ImplItemExistential" - } - ], - "Macro": [ - { - "syn": "ImplItemMacro" - } - ], - "Verbatim": [ - { - "syn": "ImplItemVerbatim" - } - ] - } - }, - { - "ident": "ImplItemConst", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "defaultness": { - "option": { - "token": "Default" - } - }, - "const_token": { - "token": "Const" - }, - "ident": { - "proc_macro2": "Ident" - }, - "colon_token": { - "token": "Colon" - }, - "ty": { - "syn": "Type" - }, - "eq_token": { - "token": "Eq" - }, - "expr": { - "syn": "Expr" - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "ImplItemExistential", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "existential_token": { - "token": "Existential" - }, - "type_token": { - "token": "Type" - }, - "ident": { - "proc_macro2": "Ident" - }, - "generics": { - "syn": "Generics" - }, - "colon_token": { - "option": { - "token": "Colon" - } - }, - "bounds": { - "punctuated": { - "element": { - "syn": "TypeParamBound" - }, - "punct": "Add" - } - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "ImplItemMacro", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "mac": { - "syn": "Macro" - }, - "semi_token": { - "option": { - "token": "Semi" - } - } - } - }, - { - "ident": "ImplItemMethod", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "defaultness": { - "option": { - "token": "Default" - } - }, - "sig": { - "syn": "MethodSig" - }, - "block": { - "syn": "Block" - } - } - }, - { - "ident": "ImplItemType", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "defaultness": { - "option": { - "token": "Default" - } - }, - "type_token": { - "token": "Type" - }, - "ident": { - "proc_macro2": "Ident" - }, - "generics": { - "syn": "Generics" - }, - "eq_token": { - "token": "Eq" - }, - "ty": { - "syn": "Type" - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "ImplItemVerbatim", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "tts": { - "proc_macro2": "TokenStream" - } - } - }, - { - "ident": "Index", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "index": { - "std": "u32" - }, - "span": { - "proc_macro2": "Span" - } - } - }, - { - "ident": "Item", - "features": { - "any": [ - "full" - ] - }, - "variants": { - "ExternCrate": [ - { - "syn": "ItemExternCrate" - } - ], - "Use": [ - { - "syn": "ItemUse" - } - ], - "Static": [ - { - "syn": "ItemStatic" - } - ], - "Const": [ - { - "syn": "ItemConst" - } - ], - "Fn": [ - { - "syn": "ItemFn" - } - ], - "Mod": [ - { - "syn": "ItemMod" - } - ], - "ForeignMod": [ - { - "syn": "ItemForeignMod" - } - ], - "Type": [ - { - "syn": "ItemType" - } - ], - "Existential": [ - { - "syn": "ItemExistential" - } - ], - "Struct": [ - { - "syn": "ItemStruct" - } - ], - "Enum": [ - { - "syn": "ItemEnum" - } - ], - "Union": [ - { - "syn": "ItemUnion" - } - ], - "Trait": [ - { - "syn": "ItemTrait" - } - ], - "TraitAlias": [ - { - "syn": "ItemTraitAlias" - } - ], - "Impl": [ - { - "syn": "ItemImpl" - } - ], - "Macro": [ - { - "syn": "ItemMacro" - } - ], - "Macro2": [ - { - "syn": "ItemMacro2" - } - ], - "Verbatim": [ - { - "syn": "ItemVerbatim" - } - ] - } - }, - { - "ident": "ItemConst", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "const_token": { - "token": "Const" - }, - "ident": { - "proc_macro2": "Ident" - }, - "colon_token": { - "token": "Colon" - }, - "ty": { - "box": { - "syn": "Type" - } - }, - "eq_token": { - "token": "Eq" - }, - "expr": { - "box": { - "syn": "Expr" - } - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "ItemEnum", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "enum_token": { - "token": "Enum" - }, - "ident": { - "proc_macro2": "Ident" - }, - "generics": { - "syn": "Generics" - }, - "brace_token": { - "group": "Brace" - }, - "variants": { - "punctuated": { - "element": { - "syn": "Variant" - }, - "punct": "Comma" - } - } - } - }, - { - "ident": "ItemExistential", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "existential_token": { - "token": "Existential" - }, - "type_token": { - "token": "Type" - }, - "ident": { - "proc_macro2": "Ident" - }, - "generics": { - "syn": "Generics" - }, - "colon_token": { - "option": { - "token": "Colon" - } - }, - "bounds": { - "punctuated": { - "element": { - "syn": "TypeParamBound" - }, - "punct": "Add" - } - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "ItemExternCrate", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "extern_token": { - "token": "Extern" - }, - "crate_token": { - "token": "Crate" - }, - "ident": { - "proc_macro2": "Ident" - }, - "rename": { - "option": { - "tuple": [ - { - "token": "As" - }, - { - "proc_macro2": "Ident" - } - ] - } - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "ItemFn", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "constness": { - "option": { - "token": "Const" - } - }, - "asyncness": { - "option": { - "token": "Async" - } - }, - "unsafety": { - "option": { - "token": "Unsafe" - } - }, - "abi": { - "option": { - "syn": "Abi" - } - }, - "ident": { - "proc_macro2": "Ident" - }, - "decl": { - "box": { - "syn": "FnDecl" - } - }, - "block": { - "box": { - "syn": "Block" - } - } - } - }, - { - "ident": "ItemForeignMod", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "abi": { - "syn": "Abi" - }, - "brace_token": { - "group": "Brace" - }, - "items": { - "vec": { - "syn": "ForeignItem" - } - } - } - }, - { - "ident": "ItemImpl", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "defaultness": { - "option": { - "token": "Default" - } - }, - "unsafety": { - "option": { - "token": "Unsafe" - } - }, - "impl_token": { - "token": "Impl" - }, - "generics": { - "syn": "Generics" - }, - "trait_": { - "option": { - "tuple": [ - { - "option": { - "token": "Bang" - } - }, - { - "syn": "Path" - }, - { - "token": "For" - } - ] - } - }, - "self_ty": { - "box": { - "syn": "Type" - } - }, - "brace_token": { - "group": "Brace" - }, - "items": { - "vec": { - "syn": "ImplItem" - } - } - } - }, - { - "ident": "ItemMacro", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "ident": { - "option": { - "proc_macro2": "Ident" - } - }, - "mac": { - "syn": "Macro" - }, - "semi_token": { - "option": { - "token": "Semi" - } - } - } - }, - { - "ident": "ItemMacro2", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "macro_token": { - "token": "Macro" - }, - "ident": { - "proc_macro2": "Ident" - }, - "paren_token": { - "group": "Paren" - }, - "args": { - "proc_macro2": "TokenStream" - }, - "brace_token": { - "group": "Brace" - }, - "body": { - "proc_macro2": "TokenStream" - } - } - }, - { - "ident": "ItemMod", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "mod_token": { - "token": "Mod" - }, - "ident": { - "proc_macro2": "Ident" - }, - "content": { - "option": { - "tuple": [ - { - "group": "Brace" - }, - { - "vec": { - "syn": "Item" - } - } - ] - } - }, - "semi": { - "option": { - "token": "Semi" - } - } - } - }, - { - "ident": "ItemStatic", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "static_token": { - "token": "Static" - }, - "mutability": { - "option": { - "token": "Mut" - } - }, - "ident": { - "proc_macro2": "Ident" - }, - "colon_token": { - "token": "Colon" - }, - "ty": { - "box": { - "syn": "Type" - } - }, - "eq_token": { - "token": "Eq" - }, - "expr": { - "box": { - "syn": "Expr" - } - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "ItemStruct", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "struct_token": { - "token": "Struct" - }, - "ident": { - "proc_macro2": "Ident" - }, - "generics": { - "syn": "Generics" - }, - "fields": { - "syn": "Fields" - }, - "semi_token": { - "option": { - "token": "Semi" - } - } - } - }, - { - "ident": "ItemTrait", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "unsafety": { - "option": { - "token": "Unsafe" - } - }, - "auto_token": { - "option": { - "token": "Auto" - } - }, - "trait_token": { - "token": "Trait" - }, - "ident": { - "proc_macro2": "Ident" - }, - "generics": { - "syn": "Generics" - }, - "colon_token": { - "option": { - "token": "Colon" - } - }, - "supertraits": { - "punctuated": { - "element": { - "syn": "TypeParamBound" - }, - "punct": "Add" - } - }, - "brace_token": { - "group": "Brace" - }, - "items": { - "vec": { - "syn": "TraitItem" - } - } - } - }, - { - "ident": "ItemTraitAlias", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "trait_token": { - "token": "Trait" - }, - "ident": { - "proc_macro2": "Ident" - }, - "generics": { - "syn": "Generics" - }, - "eq_token": { - "token": "Eq" - }, - "bounds": { - "punctuated": { - "element": { - "syn": "TypeParamBound" - }, - "punct": "Add" - } - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "ItemType", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "type_token": { - "token": "Type" - }, - "ident": { - "proc_macro2": "Ident" - }, - "generics": { - "syn": "Generics" - }, - "eq_token": { - "token": "Eq" - }, - "ty": { - "box": { - "syn": "Type" - } - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "ItemUnion", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "union_token": { - "token": "Union" - }, - "ident": { - "proc_macro2": "Ident" - }, - "generics": { - "syn": "Generics" - }, - "fields": { - "syn": "FieldsNamed" - } - } - }, - { - "ident": "ItemUse", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "vis": { - "syn": "Visibility" - }, - "use_token": { - "token": "Use" - }, - "leading_colon": { - "option": { - "token": "Colon2" - } - }, - "tree": { - "syn": "UseTree" - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "ItemVerbatim", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "tts": { - "proc_macro2": "TokenStream" - } - } - }, - { - "ident": "Label", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "name": { - "syn": "Lifetime" - }, - "colon_token": { - "token": "Colon" - } - } - }, - { - "ident": "Lifetime", - "features": { - "any": [] - }, - "fields": { - "apostrophe": { - "proc_macro2": "Span" - }, - "ident": { - "proc_macro2": "Ident" - } - } - }, - { - "ident": "LifetimeDef", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "lifetime": { - "syn": "Lifetime" - }, - "colon_token": { - "option": { - "token": "Colon" - } - }, - "bounds": { - "punctuated": { - "element": { - "syn": "Lifetime" - }, - "punct": "Add" - } - } - } - }, - { - "ident": "Lit", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Str": [ - { - "syn": "LitStr" - } - ], - "ByteStr": [ - { - "syn": "LitByteStr" - } - ], - "Byte": [ - { - "syn": "LitByte" - } - ], - "Char": [ - { - "syn": "LitChar" - } - ], - "Int": [ - { - "syn": "LitInt" - } - ], - "Float": [ - { - "syn": "LitFloat" - } - ], - "Bool": [ - { - "syn": "LitBool" - } - ], - "Verbatim": [ - { - "syn": "LitVerbatim" - } - ] - } - }, - { - "ident": "LitBool", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "value": { - "std": "bool" - }, - "span": { - "proc_macro2": "Span" - } - } - }, - { - "ident": "LitByte", - "features": { - "any": [ - "derive", - "full" - ] - } - }, - { - "ident": "LitByteStr", - "features": { - "any": [ - "derive", - "full" - ] - } - }, - { - "ident": "LitChar", - "features": { - "any": [ - "derive", - "full" - ] - } - }, - { - "ident": "LitFloat", - "features": { - "any": [ - "derive", - "full" - ] - } - }, - { - "ident": "LitInt", - "features": { - "any": [ - "derive", - "full" - ] - } - }, - { - "ident": "LitStr", - "features": { - "any": [ - "derive", - "full" - ] - } - }, - { - "ident": "LitVerbatim", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "token": { - "proc_macro2": "Literal" - } - } - }, - { - "ident": "Local", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "let_token": { - "token": "Let" - }, - "pats": { - "punctuated": { - "element": { - "syn": "Pat" - }, - "punct": "Or" - } - }, - "ty": { - "option": { - "tuple": [ - { - "token": "Colon" - }, - { - "box": { - "syn": "Type" - } - } - ] - } - }, - "init": { - "option": { - "tuple": [ - { - "token": "Eq" - }, - { - "box": { - "syn": "Expr" - } - } - ] - } - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "Macro", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "path": { - "syn": "Path" - }, - "bang_token": { - "token": "Bang" - }, - "delimiter": { - "syn": "MacroDelimiter" - }, - "tts": { - "proc_macro2": "TokenStream" - } - } - }, - { - "ident": "MacroDelimiter", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Paren": [ - { - "group": "Paren" - } - ], - "Brace": [ - { - "group": "Brace" - } - ], - "Bracket": [ - { - "group": "Bracket" - } - ] - } - }, - { - "ident": "Member", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Named": [ - { - "proc_macro2": "Ident" - } - ], - "Unnamed": [ - { - "syn": "Index" - } - ] - } - }, - { - "ident": "Meta", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Word": [ - { - "proc_macro2": "Ident" - } - ], - "List": [ - { - "syn": "MetaList" - } - ], - "NameValue": [ - { - "syn": "MetaNameValue" - } - ] - } - }, - { - "ident": "MetaList", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "ident": { - "proc_macro2": "Ident" - }, - "paren_token": { - "group": "Paren" - }, - "nested": { - "punctuated": { - "element": { - "syn": "NestedMeta" - }, - "punct": "Comma" - } - } - } - }, - { - "ident": "MetaNameValue", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "ident": { - "proc_macro2": "Ident" - }, - "eq_token": { - "token": "Eq" - }, - "lit": { - "syn": "Lit" - } - } - }, - { - "ident": "MethodSig", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "constness": { - "option": { - "token": "Const" - } - }, - "asyncness": { - "option": { - "token": "Async" - } - }, - "unsafety": { - "option": { - "token": "Unsafe" - } - }, - "abi": { - "option": { - "syn": "Abi" - } - }, - "ident": { - "proc_macro2": "Ident" - }, - "decl": { - "syn": "FnDecl" - } - } - }, - { - "ident": "MethodTurbofish", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "colon2_token": { - "token": "Colon2" - }, - "lt_token": { - "token": "Lt" - }, - "args": { - "punctuated": { - "element": { - "syn": "GenericMethodArgument" - }, - "punct": "Comma" - } - }, - "gt_token": { - "token": "Gt" - } - } - }, - { - "ident": "NestedMeta", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Meta": [ - { - "syn": "Meta" - } - ], - "Literal": [ - { - "syn": "Lit" - } - ] - } - }, - { - "ident": "ParenthesizedGenericArguments", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "paren_token": { - "group": "Paren" - }, - "inputs": { - "punctuated": { - "element": { - "syn": "Type" - }, - "punct": "Comma" - } - }, - "output": { - "syn": "ReturnType" - } - } - }, - { - "ident": "Pat", - "features": { - "any": [ - "full" - ] - }, - "variants": { - "Wild": [ - { - "syn": "PatWild" - } - ], - "Ident": [ - { - "syn": "PatIdent" - } - ], - "Struct": [ - { - "syn": "PatStruct" - } - ], - "TupleStruct": [ - { - "syn": "PatTupleStruct" - } - ], - "Path": [ - { - "syn": "PatPath" - } - ], - "Tuple": [ - { - "syn": "PatTuple" - } - ], - "Box": [ - { - "syn": "PatBox" - } - ], - "Ref": [ - { - "syn": "PatRef" - } - ], - "Lit": [ - { - "syn": "PatLit" - } - ], - "Range": [ - { - "syn": "PatRange" - } - ], - "Slice": [ - { - "syn": "PatSlice" - } - ], - "Macro": [ - { - "syn": "PatMacro" - } - ], - "Verbatim": [ - { - "syn": "PatVerbatim" - } - ] - } - }, - { - "ident": "PatBox", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "box_token": { - "token": "Box" - }, - "pat": { - "box": { - "syn": "Pat" - } - } - } - }, - { - "ident": "PatIdent", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "by_ref": { - "option": { - "token": "Ref" - } - }, - "mutability": { - "option": { - "token": "Mut" - } - }, - "ident": { - "proc_macro2": "Ident" - }, - "subpat": { - "option": { - "tuple": [ - { - "token": "At" - }, - { - "box": { - "syn": "Pat" - } - } - ] - } - } - } - }, - { - "ident": "PatLit", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "expr": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "PatMacro", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "mac": { - "syn": "Macro" - } - } - }, - { - "ident": "PatPath", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "qself": { - "option": { - "syn": "QSelf" - } - }, - "path": { - "syn": "Path" - } - } - }, - { - "ident": "PatRange", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "lo": { - "box": { - "syn": "Expr" - } - }, - "limits": { - "syn": "RangeLimits" - }, - "hi": { - "box": { - "syn": "Expr" - } - } - } - }, - { - "ident": "PatRef", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "and_token": { - "token": "And" - }, - "mutability": { - "option": { - "token": "Mut" - } - }, - "pat": { - "box": { - "syn": "Pat" - } - } - } - }, - { - "ident": "PatSlice", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "bracket_token": { - "group": "Bracket" - }, - "front": { - "punctuated": { - "element": { - "syn": "Pat" - }, - "punct": "Comma" - } - }, - "middle": { - "option": { - "box": { - "syn": "Pat" - } - } - }, - "dot2_token": { - "option": { - "token": "Dot2" - } - }, - "comma_token": { - "option": { - "token": "Comma" - } - }, - "back": { - "punctuated": { - "element": { - "syn": "Pat" - }, - "punct": "Comma" - } - } - } - }, - { - "ident": "PatStruct", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "path": { - "syn": "Path" - }, - "brace_token": { - "group": "Brace" - }, - "fields": { - "punctuated": { - "element": { - "syn": "FieldPat" - }, - "punct": "Comma" - } - }, - "dot2_token": { - "option": { - "token": "Dot2" - } - } - } - }, - { - "ident": "PatTuple", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "paren_token": { - "group": "Paren" - }, - "front": { - "punctuated": { - "element": { - "syn": "Pat" - }, - "punct": "Comma" - } - }, - "dot2_token": { - "option": { - "token": "Dot2" - } - }, - "comma_token": { - "option": { - "token": "Comma" - } - }, - "back": { - "punctuated": { - "element": { - "syn": "Pat" - }, - "punct": "Comma" - } - } - } - }, - { - "ident": "PatTupleStruct", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "path": { - "syn": "Path" - }, - "pat": { - "syn": "PatTuple" - } - } - }, - { - "ident": "PatVerbatim", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "tts": { - "proc_macro2": "TokenStream" - } - } - }, - { - "ident": "PatWild", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "underscore_token": { - "token": "Underscore" - } - } - }, - { - "ident": "Path", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "leading_colon": { - "option": { - "token": "Colon2" - } - }, - "segments": { - "punctuated": { - "element": { - "syn": "PathSegment" - }, - "punct": "Colon2" - } - } - } - }, - { - "ident": "PathArguments", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "None": [], - "AngleBracketed": [ - { - "syn": "AngleBracketedGenericArguments" - } - ], - "Parenthesized": [ - { - "syn": "ParenthesizedGenericArguments" - } - ] - } - }, - { - "ident": "PathSegment", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "ident": { - "proc_macro2": "Ident" - }, - "arguments": { - "syn": "PathArguments" - } - } - }, - { - "ident": "PredicateEq", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "lhs_ty": { - "syn": "Type" - }, - "eq_token": { - "token": "Eq" - }, - "rhs_ty": { - "syn": "Type" - } - } - }, - { - "ident": "PredicateLifetime", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "lifetime": { - "syn": "Lifetime" - }, - "colon_token": { - "token": "Colon" - }, - "bounds": { - "punctuated": { - "element": { - "syn": "Lifetime" - }, - "punct": "Add" - } - } - } - }, - { - "ident": "PredicateType", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "lifetimes": { - "option": { - "syn": "BoundLifetimes" - } - }, - "bounded_ty": { - "syn": "Type" - }, - "colon_token": { - "token": "Colon" - }, - "bounds": { - "punctuated": { - "element": { - "syn": "TypeParamBound" - }, - "punct": "Add" - } - } - } - }, - { - "ident": "QSelf", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "lt_token": { - "token": "Lt" - }, - "ty": { - "box": { - "syn": "Type" - } - }, - "position": { - "std": "usize" - }, - "as_token": { - "option": { - "token": "As" - } - }, - "gt_token": { - "token": "Gt" - } - } - }, - { - "ident": "RangeLimits", - "features": { - "any": [ - "full" - ] - }, - "variants": { - "HalfOpen": [ - { - "token": "Dot2" - } - ], - "Closed": [ - { - "token": "DotDotEq" - } - ] - } - }, - { - "ident": "ReturnType", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Default": [], - "Type": [ - { - "token": "RArrow" - }, - { - "box": { - "syn": "Type" - } - } - ] - } - }, - { - "ident": "Stmt", - "features": { - "any": [ - "full" - ] - }, - "variants": { - "Local": [ - { - "syn": "Local" - } - ], - "Item": [ - { - "syn": "Item" - } - ], - "Expr": [ - { - "syn": "Expr" - } - ], - "Semi": [ - { - "syn": "Expr" - }, - { - "token": "Semi" - } - ] - } - }, - { - "ident": "TraitBound", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "paren_token": { - "option": { - "group": "Paren" - } - }, - "modifier": { - "syn": "TraitBoundModifier" - }, - "lifetimes": { - "option": { - "syn": "BoundLifetimes" - } - }, - "path": { - "syn": "Path" - } - } - }, - { - "ident": "TraitBoundModifier", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "None": [], - "Maybe": [ - { - "token": "Question" - } - ] - } - }, - { - "ident": "TraitItem", - "features": { - "any": [ - "full" - ] - }, - "variants": { - "Const": [ - { - "syn": "TraitItemConst" - } - ], - "Method": [ - { - "syn": "TraitItemMethod" - } - ], - "Type": [ - { - "syn": "TraitItemType" - } - ], - "Macro": [ - { - "syn": "TraitItemMacro" - } - ], - "Verbatim": [ - { - "syn": "TraitItemVerbatim" - } - ] - } - }, - { - "ident": "TraitItemConst", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "const_token": { - "token": "Const" - }, - "ident": { - "proc_macro2": "Ident" - }, - "colon_token": { - "token": "Colon" - }, - "ty": { - "syn": "Type" - }, - "default": { - "option": { - "tuple": [ - { - "token": "Eq" - }, - { - "syn": "Expr" - } - ] - } - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "TraitItemMacro", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "mac": { - "syn": "Macro" - }, - "semi_token": { - "option": { - "token": "Semi" - } - } - } - }, - { - "ident": "TraitItemMethod", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "sig": { - "syn": "MethodSig" - }, - "default": { - "option": { - "syn": "Block" - } - }, - "semi_token": { - "option": { - "token": "Semi" - } - } - } - }, - { - "ident": "TraitItemType", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "type_token": { - "token": "Type" - }, - "ident": { - "proc_macro2": "Ident" - }, - "generics": { - "syn": "Generics" - }, - "colon_token": { - "option": { - "token": "Colon" - } - }, - "bounds": { - "punctuated": { - "element": { - "syn": "TypeParamBound" - }, - "punct": "Add" - } - }, - "default": { - "option": { - "tuple": [ - { - "token": "Eq" - }, - { - "syn": "Type" - } - ] - } - }, - "semi_token": { - "token": "Semi" - } - } - }, - { - "ident": "TraitItemVerbatim", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "tts": { - "proc_macro2": "TokenStream" - } - } - }, - { - "ident": "Type", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Slice": [ - { - "syn": "TypeSlice" - } - ], - "Array": [ - { - "syn": "TypeArray" - } - ], - "Ptr": [ - { - "syn": "TypePtr" - } - ], - "Reference": [ - { - "syn": "TypeReference" - } - ], - "BareFn": [ - { - "syn": "TypeBareFn" - } - ], - "Never": [ - { - "syn": "TypeNever" - } - ], - "Tuple": [ - { - "syn": "TypeTuple" - } - ], - "Path": [ - { - "syn": "TypePath" - } - ], - "TraitObject": [ - { - "syn": "TypeTraitObject" - } - ], - "ImplTrait": [ - { - "syn": "TypeImplTrait" - } - ], - "Paren": [ - { - "syn": "TypeParen" - } - ], - "Group": [ - { - "syn": "TypeGroup" - } - ], - "Infer": [ - { - "syn": "TypeInfer" - } - ], - "Macro": [ - { - "syn": "TypeMacro" - } - ], - "Verbatim": [ - { - "syn": "TypeVerbatim" - } - ] - } - }, - { - "ident": "TypeArray", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "bracket_token": { - "group": "Bracket" - }, - "elem": { - "box": { - "syn": "Type" - } - }, - "semi_token": { - "token": "Semi" - }, - "len": { - "syn": "Expr" - } - } - }, - { - "ident": "TypeBareFn", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "lifetimes": { - "option": { - "syn": "BoundLifetimes" - } - }, - "unsafety": { - "option": { - "token": "Unsafe" - } - }, - "abi": { - "option": { - "syn": "Abi" - } - }, - "fn_token": { - "token": "Fn" - }, - "paren_token": { - "group": "Paren" - }, - "inputs": { - "punctuated": { - "element": { - "syn": "BareFnArg" - }, - "punct": "Comma" - } - }, - "variadic": { - "option": { - "token": "Dot3" - } - }, - "output": { - "syn": "ReturnType" - } - } - }, - { - "ident": "TypeGroup", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "group_token": { - "group": "Group" - }, - "elem": { - "box": { - "syn": "Type" - } - } - } - }, - { - "ident": "TypeImplTrait", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "impl_token": { - "token": "Impl" - }, - "bounds": { - "punctuated": { - "element": { - "syn": "TypeParamBound" - }, - "punct": "Add" - } - } - } - }, - { - "ident": "TypeInfer", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "underscore_token": { - "token": "Underscore" - } - } - }, - { - "ident": "TypeMacro", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "mac": { - "syn": "Macro" - } - } - }, - { - "ident": "TypeNever", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "bang_token": { - "token": "Bang" - } - } - }, - { - "ident": "TypeParam", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "ident": { - "proc_macro2": "Ident" - }, - "colon_token": { - "option": { - "token": "Colon" - } - }, - "bounds": { - "punctuated": { - "element": { - "syn": "TypeParamBound" - }, - "punct": "Add" - } - }, - "eq_token": { - "option": { - "token": "Eq" - } - }, - "default": { - "option": { - "syn": "Type" - } - } - } - }, - { - "ident": "TypeParamBound", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Trait": [ - { - "syn": "TraitBound" - } - ], - "Lifetime": [ - { - "syn": "Lifetime" - } - ] - } - }, - { - "ident": "TypeParen", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "paren_token": { - "group": "Paren" - }, - "elem": { - "box": { - "syn": "Type" - } - } - } - }, - { - "ident": "TypePath", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "qself": { - "option": { - "syn": "QSelf" - } - }, - "path": { - "syn": "Path" - } - } - }, - { - "ident": "TypePtr", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "star_token": { - "token": "Star" - }, - "const_token": { - "option": { - "token": "Const" - } - }, - "mutability": { - "option": { - "token": "Mut" - } - }, - "elem": { - "box": { - "syn": "Type" - } - } - } - }, - { - "ident": "TypeReference", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "and_token": { - "token": "And" - }, - "lifetime": { - "option": { - "syn": "Lifetime" - } - }, - "mutability": { - "option": { - "token": "Mut" - } - }, - "elem": { - "box": { - "syn": "Type" - } - } - } - }, - { - "ident": "TypeSlice", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "bracket_token": { - "group": "Bracket" - }, - "elem": { - "box": { - "syn": "Type" - } - } - } - }, - { - "ident": "TypeTraitObject", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "dyn_token": { - "option": { - "token": "Dyn" - } - }, - "bounds": { - "punctuated": { - "element": { - "syn": "TypeParamBound" - }, - "punct": "Add" - } - } - } - }, - { - "ident": "TypeTuple", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "paren_token": { - "group": "Paren" - }, - "elems": { - "punctuated": { - "element": { - "syn": "Type" - }, - "punct": "Comma" - } - } - } - }, - { - "ident": "TypeVerbatim", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "tts": { - "proc_macro2": "TokenStream" - } - } - }, - { - "ident": "UnOp", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Deref": [ - { - "token": "Star" - } - ], - "Not": [ - { - "token": "Bang" - } - ], - "Neg": [ - { - "token": "Sub" - } - ] - } - }, - { - "ident": "UseGlob", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "star_token": { - "token": "Star" - } - } - }, - { - "ident": "UseGroup", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "brace_token": { - "group": "Brace" - }, - "items": { - "punctuated": { - "element": { - "syn": "UseTree" - }, - "punct": "Comma" - } - } - } - }, - { - "ident": "UseName", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "ident": { - "proc_macro2": "Ident" - } - } - }, - { - "ident": "UsePath", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "ident": { - "proc_macro2": "Ident" - }, - "colon2_token": { - "token": "Colon2" - }, - "tree": { - "box": { - "syn": "UseTree" - } - } - } - }, - { - "ident": "UseRename", - "features": { - "any": [ - "full" - ] - }, - "fields": { - "ident": { - "proc_macro2": "Ident" - }, - "as_token": { - "token": "As" - }, - "rename": { - "proc_macro2": "Ident" - } - } - }, - { - "ident": "UseTree", - "features": { - "any": [ - "full" - ] - }, - "variants": { - "Path": [ - { - "syn": "UsePath" - } - ], - "Name": [ - { - "syn": "UseName" - } - ], - "Rename": [ - { - "syn": "UseRename" - } - ], - "Glob": [ - { - "syn": "UseGlob" - } - ], - "Group": [ - { - "syn": "UseGroup" - } - ] - } - }, - { - "ident": "Variant", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "attrs": { - "vec": { - "syn": "Attribute" - } - }, - "ident": { - "proc_macro2": "Ident" - }, - "fields": { - "syn": "Fields" - }, - "discriminant": { - "option": { - "tuple": [ - { - "token": "Eq" - }, - { - "syn": "Expr" - } - ] - } - } - } - }, - { - "ident": "VisCrate", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "crate_token": { - "token": "Crate" - } - } - }, - { - "ident": "VisPublic", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "pub_token": { - "token": "Pub" - } - } - }, - { - "ident": "VisRestricted", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "pub_token": { - "token": "Pub" - }, - "paren_token": { - "group": "Paren" - }, - "in_token": { - "option": { - "token": "In" - } - }, - "path": { - "box": { - "syn": "Path" - } - } - } - }, - { - "ident": "Visibility", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Public": [ - { - "syn": "VisPublic" - } - ], - "Crate": [ - { - "syn": "VisCrate" - } - ], - "Restricted": [ - { - "syn": "VisRestricted" - } - ], - "Inherited": [] - } - }, - { - "ident": "WhereClause", - "features": { - "any": [ - "derive", - "full" - ] - }, - "fields": { - "where_token": { - "token": "Where" - }, - "predicates": { - "punctuated": { - "element": { - "syn": "WherePredicate" - }, - "punct": "Comma" - } - } - } - }, - { - "ident": "WherePredicate", - "features": { - "any": [ - "derive", - "full" - ] - }, - "variants": { - "Type": [ - { - "syn": "PredicateType" - } - ], - "Lifetime": [ - { - "syn": "PredicateLifetime" - } - ], - "Eq": [ - { - "syn": "PredicateEq" - } - ] - } - } - ], - "tokens": { - "Abstract": "abstract", - "Add": "+", - "AddEq": "+=", - "And": "&", - "AndAnd": "&&", - "AndEq": "&=", - "As": "as", - "Async": "async", - "At": "@", - "Auto": "auto", - "Bang": "!", - "Become": "become", - "Box": "box", - "Break": "break", - "Caret": "^", - "CaretEq": "^=", - "Colon": ":", - "Colon2": "::", - "Comma": ",", - "Const": "const", - "Continue": "continue", - "Crate": "crate", - "Default": "default", - "Div": "/", - "DivEq": "/=", - "Do": "do", - "Dollar": "$", - "Dot": ".", - "Dot2": "..", - "Dot3": "...", - "DotDotEq": "..=", - "Dyn": "dyn", - "Else": "else", - "Enum": "enum", - "Eq": "=", - "EqEq": "==", - "Existential": "existential", - "Extern": "extern", - "FatArrow": "=>", - "Final": "final", - "Fn": "fn", - "For": "for", - "Ge": ">=", - "Gt": ">", - "If": "if", - "Impl": "impl", - "In": "in", - "LArrow": "<-", - "Le": "<=", - "Let": "let", - "Loop": "loop", - "Lt": "<", - "Macro": "macro", - "Match": "match", - "Mod": "mod", - "Move": "move", - "MulEq": "*=", - "Mut": "mut", - "Ne": "!=", - "Or": "|", - "OrEq": "|=", - "OrOr": "||", - "Override": "override", - "Pound": "#", - "Priv": "priv", - "Pub": "pub", - "Question": "?", - "RArrow": "->", - "Ref": "ref", - "Rem": "%", - "RemEq": "%=", - "Return": "return", - "SelfType": "Self", - "SelfValue": "self", - "Semi": ";", - "Shl": "<<", - "ShlEq": "<<=", - "Shr": ">>", - "ShrEq": ">>=", - "Star": "*", - "Static": "static", - "Struct": "struct", - "Sub": "-", - "SubEq": "-=", - "Super": "super", - "Tilde": "~", - "Trait": "trait", - "Try": "try", - "Type": "type", - "Typeof": "typeof", - "Underscore": "_", - "Union": "union", - "Unsafe": "unsafe", - "Unsized": "unsized", - "Use": "use", - "Virtual": "virtual", - "Where": "where", - "While": "while", - "Yield": "yield" - } -} |