• 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/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 
49 use indexmap::IndexMap;
50 use semver::Version;
51 use serde::de::{Deserialize, Deserializer};
52 use serde_derive::{Deserialize, Serialize};
53 use std::collections::{BTreeMap, BTreeSet};
54 
55 /// Top-level content of the syntax tree description.
56 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
57 pub 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)]
76 pub 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)]
99 pub 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.
115 pub 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.
123 pub 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")]
128 pub 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)]
182 pub 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)]
189 pub 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 
is_private(data: &Data) -> bool195 fn is_private(data: &Data) -> bool {
196     match data {
197         Data::Private => true,
198         Data::Struct(_) | Data::Enum(_) => false,
199     }
200 }
201 
private_if_absent<'de, D>(deserializer: D) -> Result<Data, D::Error> where D: Deserializer<'de>,202 fn private_if_absent<'de, D>(deserializer: D) -> Result<Data, D::Error>
203 where
204     D: Deserializer<'de>,
205 {
206     let option = Option::deserialize(deserializer)?;
207     Ok(option.unwrap_or(Data::Private))
208 }
209 
is_true(b: &bool) -> bool210 fn is_true(b: &bool) -> bool {
211     *b
212 }
213 
bool_true() -> bool214 fn bool_true() -> bool {
215     true
216 }
217