blob: 0d70c7ce9d9d541d6a7d3aa0149cbdfdea080e40 [file] [log] [blame]
David Tolnay35f071f2019-05-08 12:40:13 -07001//! # 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/0.15/syn/visit/index.html
17//! [`visit_mut`]: https://docs.rs/syn/0.15/syn/visit_mut/index.html
18//! [`fold`]: https://docs.rs/syn/0.15/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
David Tolnay14d463e2019-02-15 14:23:51 -080028use indexmap::IndexMap;
David Tolnay822790e2019-02-15 21:12:30 -080029use semver::Version;
David Tolnay10227122019-02-15 20:53:45 -080030use serde::{Deserialize, Deserializer, Serialize};
David Tolnay14d463e2019-02-15 14:23:51 -080031
David Tolnay440fe582019-02-15 20:23:14 -080032use std::collections::{BTreeMap, BTreeSet};
Carl Lerche058ff472019-02-13 16:23:52 -080033
David Tolnay5b2cd852019-05-08 13:09:33 -070034/// Top-level content of the syntax tree description.
David Tolnay4bc55232019-02-15 21:09:00 -080035#[derive(Debug, PartialEq, Serialize, Deserialize)]
David Tolnayf9bb8ff2019-02-15 13:10:14 -080036pub struct Definitions {
David Tolnay5b2cd852019-05-08 13:09:33 -070037 /// The Syn version whose syntax tree is described by this data.
David Tolnay822790e2019-02-15 21:12:30 -080038 pub version: Version,
David Tolnay5b2cd852019-05-08 13:09:33 -070039
40 /// Syntax tree types defined by Syn.
David Tolnayf9bb8ff2019-02-15 13:10:14 -080041 pub types: Vec<Node>,
David Tolnay5b2cd852019-05-08 13:09:33 -070042
43 /// Token types defined by Syn (keywords as well as punctuation).
44 ///
45 /// The keys in the map are the Rust type name for the token. The values in
46 /// the map are the printed token representation.
47 ///
48 /// These tokens are accessible in the Syn public API as `syn::token::#name`
49 /// or alternatively `syn::Token![#repr]`.
David Tolnayf9bb8ff2019-02-15 13:10:14 -080050 pub tokens: BTreeMap<String, String>,
51}
52
David Tolnay5b2cd852019-05-08 13:09:33 -070053/// Syntax tree type defined by Syn.
David Tolnay4bc55232019-02-15 21:09:00 -080054#[derive(Debug, PartialEq, Serialize, Deserialize)]
David Tolnayc2be7b22019-02-15 18:48:31 -080055pub struct Node {
David Tolnay5b2cd852019-05-08 13:09:33 -070056 /// Name of the type.
57 ///
58 /// This type is accessible in the Syn public API as `syn::#name`.
David Tolnayc2be7b22019-02-15 18:48:31 -080059 pub ident: String,
David Tolnay5b2cd852019-05-08 13:09:33 -070060
61 /// Features behind which this type is cfg gated.
David Tolnayc2be7b22019-02-15 18:48:31 -080062 pub features: Features,
David Tolnay5b2cd852019-05-08 13:09:33 -070063
64 /// Content of the data structure.
David Tolnayc2be7b22019-02-15 18:48:31 -080065 #[serde(
66 flatten,
67 skip_serializing_if = "is_private",
David Tolnay6f1b7f22019-02-15 21:38:54 -080068 deserialize_with = "private_if_absent"
David Tolnayc2be7b22019-02-15 18:48:31 -080069 )]
70 pub data: Data,
Carl Lerche058ff472019-02-13 16:23:52 -080071}
72
David Tolnay5b2cd852019-05-08 13:09:33 -070073/// Content of a syntax tree data structure.
David Tolnay4bc55232019-02-15 21:09:00 -080074#[derive(Debug, PartialEq, Serialize, Deserialize)]
David Tolnayc2be7b22019-02-15 18:48:31 -080075pub enum Data {
David Tolnay5b2cd852019-05-08 13:09:33 -070076 /// This is an opaque type with no publicy accessible structure.
David Tolnayc2be7b22019-02-15 18:48:31 -080077 Private,
David Tolnay5b2cd852019-05-08 13:09:33 -070078
79 /// This type is a braced struct with named fields.
David Tolnayc2be7b22019-02-15 18:48:31 -080080 #[serde(rename = "fields")]
David Tolnay75c5a172019-02-15 20:35:41 -080081 Struct(Fields),
David Tolnay5b2cd852019-05-08 13:09:33 -070082
83 /// This type is an enum.
David Tolnayc2be7b22019-02-15 18:48:31 -080084 #[serde(rename = "variants")]
David Tolnay75c5a172019-02-15 20:35:41 -080085 Enum(Variants),
Carl Lerche058ff472019-02-13 16:23:52 -080086}
87
David Tolnay5b2cd852019-05-08 13:09:33 -070088/// Fields of a braced struct syntax tree node with named fields.
89///
90/// The keys in the map are the field names.
David Tolnay75c5a172019-02-15 20:35:41 -080091pub type Fields = IndexMap<String, Type>;
David Tolnay5b2cd852019-05-08 13:09:33 -070092
93/// Variants of an enum syntax tree node.
94///
95/// The keys in the map are the variant names.
96///
97/// Variants are unit variants if they hold no data and tuple variants
98/// otherwise. The Syn syntax tree does not make use of braced variants.
David Tolnay75c5a172019-02-15 20:35:41 -080099pub type Variants = IndexMap<String, Vec<Type>>;
Carl Lerche058ff472019-02-13 16:23:52 -0800100
David Tolnay5b2cd852019-05-08 13:09:33 -0700101/// Type of a struct field or tuple variant field in the syntax tree.
David Tolnay4bc55232019-02-15 21:09:00 -0800102#[derive(Debug, PartialEq, Serialize, Deserialize)]
David Tolnay295141b2019-02-15 12:45:33 -0800103#[serde(rename_all = "lowercase")]
Carl Lerche058ff472019-02-13 16:23:52 -0800104pub enum Type {
David Tolnay5b2cd852019-05-08 13:09:33 -0700105 /// Syntax tree type defined by Syn.
106 ///
107 /// This name will match the ident of some `Node`.
David Tolnayd3076572019-02-15 13:32:44 -0800108 Syn(String),
Carl Lerche058ff472019-02-13 16:23:52 -0800109
David Tolnay5b2cd852019-05-08 13:09:33 -0700110 /// Type defined by the Rust language or standard library.
111 ///
112 /// All such types used by Syn are accessible in the Rust prelude and can be
113 /// used without a qualifying path in most Rust code.
Carl Lerche058ff472019-02-13 16:23:52 -0800114 Std(String),
115
David Tolnay5b2cd852019-05-08 13:09:33 -0700116 /// Type defined by proc-macro2.
117 ///
118 /// The type is accessible in the proc-macro2 public API as
119 /// `proc_macro2::#name`.
David Tolnayd3076572019-02-15 13:32:44 -0800120 #[serde(rename = "proc_macro2")]
Carl Lerche058ff472019-02-13 16:23:52 -0800121 Ext(String),
122
David Tolnay5b2cd852019-05-08 13:09:33 -0700123 /// Keyword or punctuation token type defined by Syn.
124 ///
125 /// This name will match one of the keys in the `tokens` map.
David Tolnay157c7eb2019-02-15 13:21:48 -0800126 Token(String),
Carl Lerche058ff472019-02-13 16:23:52 -0800127
David Tolnay5b2cd852019-05-08 13:09:33 -0700128 /// Grouping token defined by Syn.
129 ///
130 /// The type is accessible in the Syn public API as `syn::token::#name`.
David Tolnay295141b2019-02-15 12:45:33 -0800131 Group(String),
Carl Lerche058ff472019-02-13 16:23:52 -0800132
David Tolnay5b2cd852019-05-08 13:09:33 -0700133 /// Punctuated list.
134 ///
135 /// This refers to `syn::punctuated::Punctuated<T, P>` with the specified
136 /// element type and punctuation.
David Tolnay295141b2019-02-15 12:45:33 -0800137 Punctuated(Punctuated),
138
David Tolnay5b2cd852019-05-08 13:09:33 -0700139 /// `std::option::Option`
Carl Lerche058ff472019-02-13 16:23:52 -0800140 Option(Box<Type>),
David Tolnay5b2cd852019-05-08 13:09:33 -0700141
142 /// `std::boxed::Box`
Carl Lerche058ff472019-02-13 16:23:52 -0800143 Box(Box<Type>),
David Tolnay5b2cd852019-05-08 13:09:33 -0700144
145 /// `std::vec::Vec`
Carl Lerche058ff472019-02-13 16:23:52 -0800146 Vec(Box<Type>),
David Tolnay5b2cd852019-05-08 13:09:33 -0700147
148 /// Rust tuple with two or more fields.
Carl Lerche058ff472019-02-13 16:23:52 -0800149 Tuple(Vec<Type>),
150}
151
David Tolnay5b2cd852019-05-08 13:09:33 -0700152/// Type of a punctuated list.
153///
154/// This refers to `syn::punctuated::Punctuated<#element, #punct>`.
155///
156/// The punct string will match one of the keys in the `tokens` map.
David Tolnay4bc55232019-02-15 21:09:00 -0800157#[derive(Debug, PartialEq, Serialize, Deserialize)]
David Tolnay295141b2019-02-15 12:45:33 -0800158pub struct Punctuated {
David Tolnay485973a2019-02-15 14:42:48 -0800159 pub element: Box<Type>,
160 pub punct: String,
David Tolnay295141b2019-02-15 12:45:33 -0800161}
162
David Tolnay5b2cd852019-05-08 13:09:33 -0700163/// Features behind which a syntax tree type is cfg gated.
David Tolnay4bc55232019-02-15 21:09:00 -0800164#[derive(Debug, Default, PartialEq, Serialize, Deserialize)]
Carl Lerche058ff472019-02-13 16:23:52 -0800165pub struct Features {
David Tolnay5b2cd852019-05-08 13:09:33 -0700166 /// Type is accessible if at least one of these features is enabled against
167 /// the Syn dependency.
David Tolnay440fe582019-02-15 20:23:14 -0800168 pub any: BTreeSet<String>,
Carl Lerche058ff472019-02-13 16:23:52 -0800169}
David Tolnayc2be7b22019-02-15 18:48:31 -0800170
171fn is_private(data: &Data) -> bool {
172 match data {
173 Data::Private => true,
174 Data::Struct(_) | Data::Enum(_) => false,
175 }
176}
177
David Tolnay6f1b7f22019-02-15 21:38:54 -0800178fn private_if_absent<'de, D>(deserializer: D) -> Result<Data, D::Error>
David Tolnayc2be7b22019-02-15 18:48:31 -0800179where
180 D: Deserializer<'de>,
181{
182 let option = Option::deserialize(deserializer)?;
183 Ok(option.unwrap_or(Data::Private))
184}