• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/1.0/syn/visit/index.html
17 //!   [`visit_mut`]: https://docs.rs/syn/1.0/syn/visit_mut/index.html
18 //!   [`fold`]: https://docs.rs/syn/1.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.2.0")]
48 
49 use indexmap::IndexMap;
50 use semver::Version;
51 use serde::{Deserialize, Deserializer, Serialize};
52 use std::collections::{BTreeMap, BTreeSet};
53 
54 /// Top-level content of the syntax tree description.
55 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
56 pub struct Definitions {
57     /// The Syn version whose syntax tree is described by this data.
58     pub version: Version,
59 
60     /// Syntax tree types defined by Syn.
61     pub types: Vec<Node>,
62 
63     /// Token types defined by Syn (keywords as well as punctuation).
64     ///
65     /// The keys in the map are the Rust type name for the token. The values in
66     /// the map are the printed token representation.
67     ///
68     /// These tokens are accessible in the Syn public API as `syn::token::#name`
69     /// or alternatively `syn::Token![#repr]`.
70     pub tokens: BTreeMap<String, String>,
71 }
72 
73 /// Syntax tree type defined by Syn.
74 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
75 pub struct Node {
76     /// Name of the type.
77     ///
78     /// This type is accessible in the Syn public API as `syn::#name`.
79     pub ident: String,
80 
81     /// Features behind which this type is cfg gated.
82     pub features: Features,
83 
84     /// Content of the data structure.
85     #[serde(
86         flatten,
87         skip_serializing_if = "is_private",
88         deserialize_with = "private_if_absent"
89     )]
90     pub data: Data,
91 
92     #[serde(skip_serializing_if = "is_true", default = "bool_true")]
93     pub exhaustive: bool,
94 }
95 
96 /// Content of a syntax tree data structure.
97 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
98 pub enum Data {
99     /// This is an opaque type with no publicy accessible structure.
100     Private,
101 
102     /// This type is a braced struct with named fields.
103     #[serde(rename = "fields")]
104     Struct(Fields),
105 
106     /// This type is an enum.
107     #[serde(rename = "variants")]
108     Enum(Variants),
109 }
110 
111 /// Fields of a braced struct syntax tree node with named fields.
112 ///
113 /// The keys in the map are the field names.
114 pub type Fields = IndexMap<String, Type>;
115 
116 /// Variants of an enum syntax tree node.
117 ///
118 /// The keys in the map are the variant names.
119 ///
120 /// Variants are unit variants if they hold no data and tuple variants
121 /// otherwise. The Syn syntax tree does not make use of braced variants.
122 pub type Variants = IndexMap<String, Vec<Type>>;
123 
124 /// Type of a struct field or tuple variant field in the syntax tree.
125 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
126 #[serde(rename_all = "lowercase")]
127 pub enum Type {
128     /// Syntax tree type defined by Syn.
129     ///
130     /// This name will match the ident of some `Node`.
131     Syn(String),
132 
133     /// Type defined by the Rust language or standard library.
134     ///
135     /// All such types used by Syn are accessible in the Rust prelude and can be
136     /// used without a qualifying path in most Rust code.
137     Std(String),
138 
139     /// Type defined by proc-macro2.
140     ///
141     /// The type is accessible in the proc-macro2 public API as
142     /// `proc_macro2::#name`.
143     #[serde(rename = "proc_macro2")]
144     Ext(String),
145 
146     /// Keyword or punctuation token type defined by Syn.
147     ///
148     /// This name will match one of the keys in the `tokens` map.
149     Token(String),
150 
151     /// Grouping token defined by Syn.
152     ///
153     /// The type is accessible in the Syn public API as `syn::token::#name`.
154     Group(String),
155 
156     /// Punctuated list.
157     ///
158     /// This refers to `syn::punctuated::Punctuated<T, P>` with the specified
159     /// element type and punctuation.
160     Punctuated(Punctuated),
161 
162     /// `std::option::Option`
163     Option(Box<Type>),
164 
165     /// `std::boxed::Box`
166     Box(Box<Type>),
167 
168     /// `std::vec::Vec`
169     Vec(Box<Type>),
170 
171     /// Rust tuple with two or more fields.
172     Tuple(Vec<Type>),
173 }
174 
175 /// Type of a punctuated list.
176 ///
177 /// This refers to `syn::punctuated::Punctuated<#element, #punct>`.
178 ///
179 /// The punct string will match one of the keys in the `tokens` map.
180 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
181 pub struct Punctuated {
182     pub element: Box<Type>,
183     pub punct: String,
184 }
185 
186 /// Features behind which a syntax tree type is cfg gated.
187 #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
188 pub struct Features {
189     /// Type is accessible if at least one of these features is enabled against
190     /// the Syn dependency.
191     pub any: BTreeSet<String>,
192 }
193 
is_private(data: &Data) -> bool194 fn is_private(data: &Data) -> bool {
195     match data {
196         Data::Private => true,
197         Data::Struct(_) | Data::Enum(_) => false,
198     }
199 }
200 
private_if_absent<'de, D>(deserializer: D) -> Result<Data, D::Error> where D: Deserializer<'de>,201 fn private_if_absent<'de, D>(deserializer: D) -> Result<Data, D::Error>
202 where
203     D: Deserializer<'de>,
204 {
205     let option = Option::deserialize(deserializer)?;
206     Ok(option.unwrap_or(Data::Private))
207 }
208 
is_true(b: &bool) -> bool209 fn is_true(b: &bool) -> bool {
210     *b
211 }
212 
bool_true() -> bool213 fn bool_true() -> bool {
214     true
215 }
216