From 5e20a29b4fdc8a2d442d1093681b396dcb4b816b Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Tue, 7 Jan 2020 11:18:04 +0000 Subject: Add structopt dependency in version 0.3.7 This patch series replaces argparse with structopt in the argument handling code. As a first step, we need structopt as a dependency. Import subrepo structopt/:structopt at efbdda4753592e27bc430fb01f7b9650b2f3174d Import subrepo bitflags/:bitflags at 30668016aca6bd3b02c766e8347e0b4080d4c296 Import subrepo clap/:clap at 784524f7eb193e35f81082cc69454c8c21b948f7 Import subrepo heck/:heck at 093d56fbf001e1506e56dbfa38631d99b1066df1 Import subrepo proc-macro-error/:proc-macro-error at 6c4cfe79a622c5de8ae68557993542be46eacae2 Import subrepo proc-macro2/:proc-macro2 at d5d48eddca4566e5438e8a2cbed4a74e049544de Import subrepo quote/:quote at 727436c6c137b20f0f34dde5d8fda2679b9747ad Import subrepo rustversion/:rustversion at 0c5663313516263059ce9059ef81fc7a1cf655ca Import subrepo syn-mid/:syn-mid at 5d3d85414a9e6674e1857ec22a87b96e04a6851a Import subrepo syn/:syn at e87c27e87f6f4ef8919d0372bdb056d53ef0d8f3 Import subrepo textwrap/:textwrap at abcd618beae3f74841032aa5b53c1086b0a57ca2 Import subrepo unicode-segmentation/:unicode-segmentation at 637c9874c4fe0c205ff27787faf150a40295c6c3 Import subrepo unicode-width/:unicode-width at 3033826f8bf05e82724140a981d5941e48fce393 Import subrepo unicode-xid/:unicode-xid at 4baae9fffb156ba229665b972a9cd5991787ceb7 --- syn/json/Cargo.toml | 18 +++++ syn/json/src/lib.rs | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 syn/json/Cargo.toml create mode 100644 syn/json/src/lib.rs (limited to 'syn/json') diff --git a/syn/json/Cargo.toml b/syn/json/Cargo.toml new file mode 100644 index 0000000..77104dc --- /dev/null +++ b/syn/json/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "syn-codegen" +version = "0.1.0" +authors = ["David Tolnay "] +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/syn/json/src/lib.rs b/syn/json/src/lib.rs new file mode 100644 index 0000000..e3546d9 --- /dev/null +++ b/syn/json/src/lib.rs @@ -0,0 +1,214 @@ +//! # 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/1.0/syn/visit/index.html +//! [`visit_mut`]: https://docs.rs/syn/1.0/syn/visit_mut/index.html +//! [`fold`]: https://docs.rs/syn/1.0/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(Clone, 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, + + /// 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, +} + +/// Syntax tree type defined by Syn. +#[derive(Clone, 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, + + #[serde(skip_serializing_if = "is_true", default = "bool_true")] + pub exhaustive: bool, +} + +/// Content of a syntax tree data structure. +#[derive(Clone, 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; + +/// 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>; + +/// Type of a struct field or tuple variant field in the syntax tree. +#[derive(Clone, 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` with the specified + /// element type and punctuation. + Punctuated(Punctuated), + + /// `std::option::Option` + Option(Box), + + /// `std::boxed::Box` + Box(Box), + + /// `std::vec::Vec` + Vec(Box), + + /// Rust tuple with two or more fields. + Tuple(Vec), +} + +/// 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(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Punctuated { + pub element: Box, + pub punct: String, +} + +/// Features behind which a syntax tree type is cfg gated. +#[derive(Clone, 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, +} + +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 +where + D: Deserializer<'de>, +{ + let option = Option::deserialize(deserializer)?; + Ok(option.unwrap_or(Data::Private)) +} + +fn is_true(b: &bool) -> bool { + *b +} + +fn bool_true() -> bool { + true +} -- cgit v1.2.3