1//! # Data structures that describe Syn's syntax tree. 2//! 3//! The Syn syntax tree is made up of more than 200 types. Occasionally it can 4//! come up that you need to implement some behavior across them all. 5//! 6//! - For example [the Rust integration for AST Explorer][astexplorer] wants to 7//! turn a syntax tree from Syn into a JavaScript value understood by the 8//! platform's existing cross-language syntax tree visualization code. 9//! 10//! [astexplorer]: https://astexplorer.net/#/gist/388150a52f74d45a355d2b5e865ded96/0c6d563f28d900472f699c21a1845ad20ae9927f 11//! 12//! - As another example from within Syn itself, the traits and implementations 13//! of the [`visit`], [`visit_mut`], and [`fold`] modules can be generated 14//! programmatically from a description of the syntax tree. 15//! 16//! [`visit`]: https://docs.rs/syn/2.0/syn/visit/index.html 17//! [`visit_mut`]: https://docs.rs/syn/2.0/syn/visit_mut/index.html 18//! [`fold`]: https://docs.rs/syn/2.0/syn/fold/index.html 19//! 20//! To make this type of code as easy as possible to implement in any language, 21//! every Syn release comes with a machine-readable description of that version 22//! of the syntax tree as a JSON file [syn.json]. This `syn-codegen` crate 23//! provides the canonical data structures for parsing and making use of the 24//! representation in syn.json from Rust code. 25//! 26//! [syn.json]: https://raw.githubusercontent.com/dtolnay/syn/master/syn.json 27//! 28//! ## Example 29//! 30//! ``` 31//! use syn_codegen::Definitions; 32//! 33//! # const IGNORE: &str = stringify! { 34//! const SYN: &str = include_str!("syn.json"); 35//! # }; 36//! # const SYN: &str = include_str!("../../syn.json"); 37//! 38//! fn main() { 39//! let defs: Definitions = serde_json::from_str(SYN).unwrap(); 40//! 41//! for node in &defs.types { 42//! println!("syn::{}", node.ident); 43//! } 44//! } 45//! ``` 46 47#![doc(html_root_url = "https://docs.rs/syn-codegen/0.4.1")] 48 49use indexmap::IndexMap; 50use semver::Version; 51use serde::de::{Deserialize, Deserializer}; 52use serde_derive::{Deserialize, Serialize}; 53use std::collections::{BTreeMap, BTreeSet}; 54 55/// Top-level content of the syntax tree description. 56#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] 57pub struct Definitions { 58 /// The Syn version whose syntax tree is described by this data. 59 pub version: Version, 60 61 /// Syntax tree types defined by Syn. 62 pub types: Vec<Node>, 63 64 /// Token types defined by Syn (keywords as well as punctuation). 65 /// 66 /// The keys in the map are the Rust type name for the token. The values in 67 /// the map are the printed token representation. 68 /// 69 /// These tokens are accessible in the Syn public API as `syn::token::#name` 70 /// or alternatively `syn::Token![#repr]`. 71 pub tokens: BTreeMap<String, String>, 72} 73 74/// Syntax tree type defined by Syn. 75#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] 76pub struct Node { 77 /// Name of the type. 78 /// 79 /// This type is accessible in the Syn public API as `syn::#name`. 80 pub ident: String, 81 82 /// Features behind which this type is cfg gated. 83 pub features: Features, 84 85 /// Content of the data structure. 86 #[serde( 87 flatten, 88 skip_serializing_if = "is_private", 89 deserialize_with = "private_if_absent" 90 )] 91 pub data: Data, 92 93 #[serde(skip_serializing_if = "is_true", default = "bool_true")] 94 pub exhaustive: bool, 95} 96 97/// Content of a syntax tree data structure. 98#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] 99pub enum Data { 100 /// This is an opaque type with no publicly accessible structure. 101 Private, 102 103 /// This type is a braced struct with named fields. 104 #[serde(rename = "fields")] 105 Struct(Fields), 106 107 /// This type is an enum. 108 #[serde(rename = "variants")] 109 Enum(Variants), 110} 111 112/// Fields of a braced struct syntax tree node with named fields. 113/// 114/// The keys in the map are the field names. 115pub type Fields = IndexMap<String, Type>; 116 117/// Variants of an enum syntax tree node. 118/// 119/// The keys in the map are the variant names. 120/// 121/// Variants are unit variants if they hold no data and tuple variants 122/// otherwise. The Syn syntax tree does not make use of braced variants. 123pub type Variants = IndexMap<String, Vec<Type>>; 124 125/// Type of a struct field or tuple variant field in the syntax tree. 126#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] 127#[serde(rename_all = "lowercase")] 128pub enum Type { 129 /// Syntax tree type defined by Syn. 130 /// 131 /// This name will match the ident of some `Node`. 132 Syn(String), 133 134 /// Type defined by the Rust language or standard library. 135 /// 136 /// All such types used by Syn are accessible in the Rust prelude and can be 137 /// used without a qualifying path in most Rust code. 138 Std(String), 139 140 /// Type defined by proc-macro2. 141 /// 142 /// The type is accessible in the proc-macro2 public API as 143 /// `proc_macro2::#name`. 144 #[serde(rename = "proc_macro2")] 145 Ext(String), 146 147 /// Keyword or punctuation token type defined by Syn. 148 /// 149 /// This name will match one of the keys in the `tokens` map. 150 Token(String), 151 152 /// Grouping token defined by Syn. 153 /// 154 /// The type is accessible in the Syn public API as `syn::token::#name`. 155 Group(String), 156 157 /// Punctuated list. 158 /// 159 /// This refers to `syn::punctuated::Punctuated<T, P>` with the specified 160 /// element type and punctuation. 161 Punctuated(Punctuated), 162 163 /// `std::option::Option` 164 Option(Box<Type>), 165 166 /// `std::boxed::Box` 167 Box(Box<Type>), 168 169 /// `std::vec::Vec` 170 Vec(Box<Type>), 171 172 /// Rust tuple with two or more fields. 173 Tuple(Vec<Type>), 174} 175 176/// Type of a punctuated list. 177/// 178/// This refers to `syn::punctuated::Punctuated<#element, #punct>`. 179/// 180/// The punct string will match one of the keys in the `tokens` map. 181#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] 182pub struct Punctuated { 183 pub element: Box<Type>, 184 pub punct: String, 185} 186 187/// Features behind which a syntax tree type is cfg gated. 188#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] 189pub struct Features { 190 /// Type is accessible if at least one of these features is enabled against 191 /// the Syn dependency. 192 pub any: BTreeSet<String>, 193} 194 195fn is_private(data: &Data) -> bool { 196 match data { 197 Data::Private => true, 198 Data::Struct(_) | Data::Enum(_) => false, 199 } 200} 201 202fn private_if_absent<'de, D>(deserializer: D) -> Result<Data, D::Error> 203where 204 D: Deserializer<'de>, 205{ 206 let option = Option::deserialize(deserializer)?; 207 Ok(option.unwrap_or(Data::Private)) 208} 209 210fn is_true(b: &bool) -> bool { 211 *b 212} 213 214fn bool_true() -> bool { 215 true 216} 217