David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 1 | //! Syn is a parsing library for parsing a stream of Rust tokens into a syntax |
| 2 | //! tree of Rust source code. |
| 3 | //! |
David Tolnay | 6b889eb | 2018-09-01 18:12:17 -0700 | [diff] [blame] | 4 | //! Currently this library is geared toward use in Rust procedural macros, but |
| 5 | //! contains some APIs that may be useful more generally. |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 6 | //! |
| 7 | //! - **Data structures** — Syn provides a complete syntax tree that can |
| 8 | //! represent any valid Rust source code. The syntax tree is rooted at |
| 9 | //! [`syn::File`] which represents a full source file, but there are other |
| 10 | //! entry points that may be useful to procedural macros including |
| 11 | //! [`syn::Item`], [`syn::Expr`] and [`syn::Type`]. |
| 12 | //! |
| 13 | //! - **Custom derives** — Of particular interest to custom derives is |
| 14 | //! [`syn::DeriveInput`] which is any of the three legal input items to a |
| 15 | //! derive macro. An example below shows using this type in a library that can |
| 16 | //! derive implementations of a trait of your own. |
| 17 | //! |
David Tolnay | 6b889eb | 2018-09-01 18:12:17 -0700 | [diff] [blame] | 18 | //! - **Parsing** — Parsing in Syn is built around [parser functions] with the |
| 19 | //! signature `fn(ParseStream) -> Result<T>`. Every syntax tree node defined |
| 20 | //! by Syn is individually parsable and may be used as a building block for |
| 21 | //! custom syntaxes, or you may dream up your own brand new syntax without |
| 22 | //! involving any of our syntax tree types. |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 23 | //! |
| 24 | //! - **Location information** — Every token parsed by Syn is associated with a |
| 25 | //! `Span` that tracks line and column information back to the source of that |
| 26 | //! token. These spans allow a procedural macro to display detailed error |
| 27 | //! messages pointing to all the right places in the user's code. There is an |
| 28 | //! example of this below. |
| 29 | //! |
| 30 | //! - **Feature flags** — Functionality is aggressively feature gated so your |
| 31 | //! procedural macros enable only what they need, and do not pay in compile |
| 32 | //! time for all the rest. |
| 33 | //! |
| 34 | //! [`syn::File`]: struct.File.html |
| 35 | //! [`syn::Item`]: enum.Item.html |
| 36 | //! [`syn::Expr`]: enum.Expr.html |
| 37 | //! [`syn::Type`]: enum.Type.html |
| 38 | //! [`syn::DeriveInput`]: struct.DeriveInput.html |
David Tolnay | 6b889eb | 2018-09-01 18:12:17 -0700 | [diff] [blame] | 39 | //! [parser functions]: parse/index.html |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 40 | //! |
| 41 | //! *Version requirement: Syn supports any compiler version back to Rust's very |
| 42 | //! first support for procedural macros in Rust 1.15.0. Some features especially |
| 43 | //! around error reporting are only available in newer compilers or on the |
| 44 | //! nightly channel.* |
| 45 | //! |
| 46 | //! ## Example of a custom derive |
| 47 | //! |
| 48 | //! The canonical custom derive using Syn looks like this. We write an ordinary |
| 49 | //! Rust function tagged with a `proc_macro_derive` attribute and the name of |
| 50 | //! the trait we are deriving. Any time that derive appears in the user's code, |
| 51 | //! the Rust compiler passes their data structure as tokens into our macro. We |
| 52 | //! get to execute arbitrary Rust code to figure out what to do with those |
| 53 | //! tokens, then hand some tokens back to the compiler to compile into the |
| 54 | //! user's crate. |
| 55 | //! |
| 56 | //! [`TokenStream`]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html |
| 57 | //! |
| 58 | //! ```toml |
| 59 | //! [dependencies] |
David Tolnay | b28acf3 | 2018-09-06 09:01:40 -0700 | [diff] [blame] | 60 | //! syn = "0.15" |
David Tolnay | 87003d0 | 2018-05-20 19:45:13 -0700 | [diff] [blame] | 61 | //! quote = "0.6" |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 62 | //! |
| 63 | //! [lib] |
| 64 | //! proc-macro = true |
| 65 | //! ``` |
| 66 | //! |
David Tolnay | 95989db | 2019-01-01 15:05:57 -0500 | [diff] [blame] | 67 | //! ```edition2018 |
David Tolnay | a1c9807 | 2018-09-06 08:58:10 -0700 | [diff] [blame] | 68 | //! extern crate proc_macro; |
| 69 | //! |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 70 | //! use proc_macro::TokenStream; |
David Tolnay | fd5b117 | 2018-12-31 17:54:36 -0500 | [diff] [blame] | 71 | //! use quote::quote; |
| 72 | //! use syn::{parse_macro_input, DeriveInput}; |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 73 | //! |
| 74 | //! # const IGNORE_TOKENS: &str = stringify! { |
| 75 | //! #[proc_macro_derive(MyMacro)] |
| 76 | //! # }; |
| 77 | //! pub fn my_macro(input: TokenStream) -> TokenStream { |
| 78 | //! // Parse the input tokens into a syntax tree |
David Tolnay | 6b889eb | 2018-09-01 18:12:17 -0700 | [diff] [blame] | 79 | //! let input = parse_macro_input!(input as DeriveInput); |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 80 | //! |
| 81 | //! // Build the output, possibly using quasi-quotation |
| 82 | //! let expanded = quote! { |
| 83 | //! // ... |
| 84 | //! }; |
| 85 | //! |
| 86 | //! // Hand the output tokens back to the compiler |
David Tolnay | 35b498e | 2018-09-01 20:10:40 -0700 | [diff] [blame] | 87 | //! TokenStream::from(expanded) |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 88 | //! } |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 89 | //! ``` |
| 90 | //! |
| 91 | //! The [`heapsize`] example directory shows a complete working Macros 1.1 |
David Tolnay | b4f5724 | 2018-10-28 17:57:08 -0700 | [diff] [blame] | 92 | //! implementation of a custom derive. It works on any Rust compiler 1.15+. |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 93 | //! The example derives a `HeapSize` trait which computes an estimate of the |
| 94 | //! amount of heap memory owned by a value. |
| 95 | //! |
| 96 | //! [`heapsize`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize |
| 97 | //! |
David Tolnay | 95989db | 2019-01-01 15:05:57 -0500 | [diff] [blame] | 98 | //! ```edition2018 |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 99 | //! pub trait HeapSize { |
| 100 | //! /// Total number of bytes of heap memory owned by `self`. |
| 101 | //! fn heap_size_of_children(&self) -> usize; |
| 102 | //! } |
| 103 | //! ``` |
| 104 | //! |
| 105 | //! The custom derive allows users to write `#[derive(HeapSize)]` on data |
| 106 | //! structures in their program. |
| 107 | //! |
David Tolnay | 95989db | 2019-01-01 15:05:57 -0500 | [diff] [blame] | 108 | //! ```edition2018 |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 109 | //! # const IGNORE_TOKENS: &str = stringify! { |
| 110 | //! #[derive(HeapSize)] |
| 111 | //! # }; |
| 112 | //! struct Demo<'a, T: ?Sized> { |
| 113 | //! a: Box<T>, |
| 114 | //! b: u8, |
| 115 | //! c: &'a str, |
| 116 | //! d: String, |
| 117 | //! } |
| 118 | //! ``` |
| 119 | //! |
| 120 | //! ## Spans and error reporting |
| 121 | //! |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 122 | //! The token-based procedural macro API provides great control over where the |
| 123 | //! compiler's error messages are displayed in user code. Consider the error the |
| 124 | //! user sees if one of their field types does not implement `HeapSize`. |
| 125 | //! |
David Tolnay | 95989db | 2019-01-01 15:05:57 -0500 | [diff] [blame] | 126 | //! ```edition2018 |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 127 | //! # const IGNORE_TOKENS: &str = stringify! { |
| 128 | //! #[derive(HeapSize)] |
| 129 | //! # }; |
| 130 | //! struct Broken { |
| 131 | //! ok: String, |
| 132 | //! bad: std::thread::Thread, |
| 133 | //! } |
| 134 | //! ``` |
| 135 | //! |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 136 | //! By tracking span information all the way through the expansion of a |
David Tolnay | 3be1b78 | 2018-10-28 17:41:41 -0700 | [diff] [blame] | 137 | //! procedural macro as shown in the `heapsize` example, token-based macros in |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 138 | //! Syn are able to trigger errors that directly pinpoint the source of the |
| 139 | //! problem. |
| 140 | //! |
| 141 | //! ```text |
| 142 | //! error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied |
| 143 | //! --> src/main.rs:7:5 |
| 144 | //! | |
| 145 | //! 7 | bad: std::thread::Thread, |
David Tolnay | efff2ff | 2018-01-07 11:49:52 -0800 | [diff] [blame] | 146 | //! | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `Thread` |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 147 | //! ``` |
| 148 | //! |
David Tolnay | 6b889eb | 2018-09-01 18:12:17 -0700 | [diff] [blame] | 149 | //! ## Parsing a custom syntax |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 150 | //! |
| 151 | //! The [`lazy-static`] example directory shows the implementation of a |
| 152 | //! `functionlike!(...)` procedural macro in which the input tokens are parsed |
David Tolnay | 6b889eb | 2018-09-01 18:12:17 -0700 | [diff] [blame] | 153 | //! using Syn's parsing API. |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 154 | //! |
| 155 | //! [`lazy-static`]: https://github.com/dtolnay/syn/tree/master/examples/lazy-static |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 156 | //! |
| 157 | //! The example reimplements the popular `lazy_static` crate from crates.io as a |
| 158 | //! procedural macro. |
| 159 | //! |
David Tolnay | 95989db | 2019-01-01 15:05:57 -0500 | [diff] [blame] | 160 | //! ```edition2018 |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 161 | //! # macro_rules! lazy_static { |
| 162 | //! # ($($tt:tt)*) => {} |
| 163 | //! # } |
| 164 | //! # |
| 165 | //! lazy_static! { |
| 166 | //! static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap(); |
| 167 | //! } |
| 168 | //! ``` |
| 169 | //! |
| 170 | //! The implementation shows how to trigger custom warnings and error messages |
| 171 | //! on the macro input. |
| 172 | //! |
| 173 | //! ```text |
| 174 | //! warning: come on, pick a more creative name |
| 175 | //! --> src/main.rs:10:16 |
| 176 | //! | |
| 177 | //! 10 | static ref FOO: String = "lazy_static".to_owned(); |
| 178 | //! | ^^^ |
| 179 | //! ``` |
| 180 | //! |
| 181 | //! ## Debugging |
| 182 | //! |
| 183 | //! When developing a procedural macro it can be helpful to look at what the |
| 184 | //! generated code looks like. Use `cargo rustc -- -Zunstable-options |
| 185 | //! --pretty=expanded` or the [`cargo expand`] subcommand. |
| 186 | //! |
David Tolnay | 324db2d | 2018-01-07 11:51:09 -0800 | [diff] [blame] | 187 | //! [`cargo expand`]: https://github.com/dtolnay/cargo-expand |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 188 | //! |
| 189 | //! To show the expanded code for some crate that uses your procedural macro, |
| 190 | //! run `cargo expand` from that crate. To show the expanded code for one of |
| 191 | //! your own test cases, run `cargo expand --test the_test_case` where the last |
| 192 | //! argument is the name of the test file without the `.rs` extension. |
| 193 | //! |
| 194 | //! This write-up by Brandon W Maister discusses debugging in more detail: |
| 195 | //! [Debugging Rust's new Custom Derive system][debugging]. |
| 196 | //! |
| 197 | //! [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/ |
| 198 | //! |
| 199 | //! ## Optional features |
| 200 | //! |
| 201 | //! Syn puts a lot of functionality behind optional features in order to |
| 202 | //! optimize compile time for the most common use cases. The following features |
| 203 | //! are available. |
| 204 | //! |
| 205 | //! - **`derive`** *(enabled by default)* — Data structures for representing the |
| 206 | //! possible input to a custom derive, including structs and enums and types. |
| 207 | //! - **`full`** — Data structures for representing the syntax tree of all valid |
| 208 | //! Rust source code, including items and expressions. |
| 209 | //! - **`parsing`** *(enabled by default)* — Ability to parse input tokens into |
| 210 | //! a syntax tree node of a chosen type. |
| 211 | //! - **`printing`** *(enabled by default)* — Ability to print a syntax tree |
| 212 | //! node as tokens of Rust source code. |
| 213 | //! - **`visit`** — Trait for traversing a syntax tree. |
David Tolnay | 34981cf | 2018-01-06 16:22:35 -0800 | [diff] [blame] | 214 | //! - **`visit-mut`** — Trait for traversing and mutating in place a syntax |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 215 | //! tree. |
| 216 | //! - **`fold`** — Trait for transforming an owned syntax tree. |
| 217 | //! - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree |
| 218 | //! types. |
| 219 | //! - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree |
| 220 | //! types. |
hcpl | 4b72a38 | 2018-04-04 14:50:24 +0300 | [diff] [blame] | 221 | //! - **`proc-macro`** *(enabled by default)* — Runtime dependency on the |
| 222 | //! dynamic library libproc_macro from rustc toolchain. |
David Tolnay | 5e84e97 | 2018-01-05 17:51:06 -0800 | [diff] [blame] | 223 | |
David Tolnay | 4cf7db8 | 2018-01-07 15:22:01 -0800 | [diff] [blame] | 224 | // Syn types in rustdoc of other crates get linked to here. |
David Tolnay | c1a8efe | 2019-04-02 09:14:24 -0700 | [diff] [blame^] | 225 | #![doc(html_root_url = "https://docs.rs/syn/0.15.30")] |
David Tolnay | 46b17c0 | 2018-09-22 13:27:40 -0700 | [diff] [blame] | 226 | #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] |
David Tolnay | 34071ba | 2018-05-20 20:00:41 -0700 | [diff] [blame] | 227 | #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))] |
David Tolnay | 34071ba | 2018-05-20 20:00:41 -0700 | [diff] [blame] | 228 | // Ignored clippy lints. |
David Tolnay | 94d2b79 | 2018-04-29 12:26:10 -0700 | [diff] [blame] | 229 | #![cfg_attr( |
| 230 | feature = "cargo-clippy", |
| 231 | allow( |
David Tolnay | 4831ac6 | 2018-08-30 21:04:16 -0700 | [diff] [blame] | 232 | block_in_if_condition_stmt, |
David Tolnay | 50144d9 | 2019-03-09 23:20:56 -0800 | [diff] [blame] | 233 | cognitive_complexity, |
David Tolnay | 0cec3e6 | 2018-07-21 09:08:30 -0700 | [diff] [blame] | 234 | const_static_lifetime, |
David Tolnay | 267eac6 | 2018-11-06 20:30:36 -0800 | [diff] [blame] | 235 | deprecated_cfg_attr, |
David Tolnay | 0cec3e6 | 2018-07-21 09:08:30 -0700 | [diff] [blame] | 236 | doc_markdown, |
David Tolnay | 24b079d | 2018-08-27 08:28:10 -0700 | [diff] [blame] | 237 | eval_order_dependence, |
David Tolnay | 0cec3e6 | 2018-07-21 09:08:30 -0700 | [diff] [blame] | 238 | large_enum_variant, |
David Tolnay | aba1ed1 | 2018-11-10 14:26:40 -0800 | [diff] [blame] | 239 | needless_pass_by_value, |
David Tolnay | 6fb8746 | 2018-09-01 16:51:49 -0700 | [diff] [blame] | 240 | never_loop, |
David Tolnay | 0cec3e6 | 2018-07-21 09:08:30 -0700 | [diff] [blame] | 241 | redundant_field_names, |
David Tolnay | aba1ed1 | 2018-11-10 14:26:40 -0800 | [diff] [blame] | 242 | too_many_arguments, |
David Tolnay | 94d2b79 | 2018-04-29 12:26:10 -0700 | [diff] [blame] | 243 | ) |
| 244 | )] |
David Tolnay | 34071ba | 2018-05-20 20:00:41 -0700 | [diff] [blame] | 245 | // Ignored clippy_pedantic lints. |
| 246 | #![cfg_attr( |
| 247 | feature = "cargo-clippy", |
| 248 | allow( |
David Tolnay | 0cec3e6 | 2018-07-21 09:08:30 -0700 | [diff] [blame] | 249 | cast_possible_truncation, |
| 250 | cast_possible_wrap, |
David Tolnay | b161775 | 2018-08-24 21:16:33 -0400 | [diff] [blame] | 251 | empty_enum, |
David Tolnay | 0cec3e6 | 2018-07-21 09:08:30 -0700 | [diff] [blame] | 252 | if_not_else, |
David Tolnay | 0cec3e6 | 2018-07-21 09:08:30 -0700 | [diff] [blame] | 253 | items_after_statements, |
David Tolnay | 24cff8a | 2018-12-31 18:21:23 -0500 | [diff] [blame] | 254 | module_name_repetitions, |
David Tolnay | 151f92f | 2018-08-14 22:44:53 -0700 | [diff] [blame] | 255 | shadow_unrelated, |
David Tolnay | 0cec3e6 | 2018-07-21 09:08:30 -0700 | [diff] [blame] | 256 | similar_names, |
| 257 | single_match_else, |
David Tolnay | 0cec3e6 | 2018-07-21 09:08:30 -0700 | [diff] [blame] | 258 | unseparated_literal_suffix, |
| 259 | use_self, |
David Tolnay | a06d864 | 2018-11-06 20:31:05 -0800 | [diff] [blame] | 260 | used_underscore_binding, |
David Tolnay | 34071ba | 2018-05-20 20:00:41 -0700 | [diff] [blame] | 261 | ) |
| 262 | )] |
David Tolnay | ad2836d | 2017-04-20 10:11:43 -0700 | [diff] [blame] | 263 | |
David Tolnay | 278f9e3 | 2018-08-14 22:41:11 -0700 | [diff] [blame] | 264 | #[cfg(all( |
| 265 | not(all(target_arch = "wasm32", target_os = "unknown")), |
| 266 | feature = "proc-macro" |
| 267 | ))] |
David Tolnay | 5138205 | 2017-12-27 13:46:21 -0500 | [diff] [blame] | 268 | extern crate proc_macro; |
David Tolnay | 94d2b79 | 2018-04-29 12:26:10 -0700 | [diff] [blame] | 269 | extern crate proc_macro2; |
David Tolnay | 570695e | 2017-06-03 16:15:13 -0700 | [diff] [blame] | 270 | extern crate unicode_xid; |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame] | 271 | |
David Tolnay | 1cf8091 | 2017-12-31 18:35:12 -0500 | [diff] [blame] | 272 | #[cfg(feature = "printing")] |
David Tolnay | 87d0b44 | 2016-09-04 11:52:12 -0700 | [diff] [blame] | 273 | extern crate quote; |
| 274 | |
Alex Crichton | 62a0a59 | 2017-05-22 13:58:53 -0700 | [diff] [blame] | 275 | #[macro_use] |
| 276 | mod macros; |
| 277 | |
David Tolnay | 734079e | 2018-09-01 02:03:37 -0700 | [diff] [blame] | 278 | // Not public API. |
David Tolnay | 852bff7 | 2018-08-27 08:24:02 -0700 | [diff] [blame] | 279 | #[cfg(feature = "parsing")] |
David Tolnay | 734079e | 2018-09-01 02:03:37 -0700 | [diff] [blame] | 280 | #[doc(hidden)] |
David Tolnay | 852bff7 | 2018-08-27 08:24:02 -0700 | [diff] [blame] | 281 | #[macro_use] |
David Tolnay | 734079e | 2018-09-01 02:03:37 -0700 | [diff] [blame] | 282 | pub mod group; |
David Tolnay | 852bff7 | 2018-08-27 08:24:02 -0700 | [diff] [blame] | 283 | |
David Tolnay | c5ab8c6 | 2017-12-26 16:43:39 -0500 | [diff] [blame] | 284 | #[macro_use] |
David Tolnay | 32954ef | 2017-12-26 22:43:16 -0500 | [diff] [blame] | 285 | pub mod token; |
David Tolnay | c5ab8c6 | 2017-12-26 16:43:39 -0500 | [diff] [blame] | 286 | |
David Tolnay | 4fb7123 | 2018-08-25 23:14:50 -0400 | [diff] [blame] | 287 | mod ident; |
| 288 | pub use ident::Ident; |
David Tolnay | e303b7c | 2018-05-20 16:46:35 -0700 | [diff] [blame] | 289 | |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 290 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | b79ee96 | 2016-09-04 09:39:20 -0700 | [diff] [blame] | 291 | mod attr; |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 292 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | 161f2de | 2018-10-13 14:38:20 -0700 | [diff] [blame] | 293 | pub use attr::{AttrStyle, Attribute, AttributeArgs, Meta, MetaList, MetaNameValue, NestedMeta}; |
David Tolnay | 35161ff | 2016-09-03 11:33:15 -0700 | [diff] [blame] | 294 | |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 295 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | f38cdf6 | 2016-09-23 19:07:09 -0700 | [diff] [blame] | 296 | mod data; |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 297 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | b57c849 | 2018-05-05 00:32:04 -0700 | [diff] [blame] | 298 | pub use data::{ |
| 299 | Field, Fields, FieldsNamed, FieldsUnnamed, Variant, VisCrate, VisPublic, VisRestricted, |
| 300 | Visibility, |
| 301 | }; |
David Tolnay | f38cdf6 | 2016-09-23 19:07:09 -0700 | [diff] [blame] | 302 | |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 303 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 304 | mod expr; |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 305 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | b57c849 | 2018-05-05 00:32:04 -0700 | [diff] [blame] | 306 | pub use expr::{ |
David Tolnay | 02a9c6f | 2018-08-24 18:58:45 -0400 | [diff] [blame] | 307 | Expr, ExprArray, ExprAssign, ExprAssignOp, ExprAsync, ExprBinary, ExprBlock, ExprBox, |
| 308 | ExprBreak, ExprCall, ExprCast, ExprClosure, ExprContinue, ExprField, ExprForLoop, ExprGroup, |
David Tolnay | 9c11912 | 2018-09-01 18:47:02 -0700 | [diff] [blame] | 309 | ExprIf, ExprInPlace, ExprIndex, ExprLet, ExprLit, ExprLoop, ExprMacro, ExprMatch, |
David Tolnay | 02a9c6f | 2018-08-24 18:58:45 -0400 | [diff] [blame] | 310 | ExprMethodCall, ExprParen, ExprPath, ExprRange, ExprReference, ExprRepeat, ExprReturn, |
| 311 | ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprType, ExprUnary, ExprUnsafe, ExprVerbatim, |
David Tolnay | 9c11912 | 2018-09-01 18:47:02 -0700 | [diff] [blame] | 312 | ExprWhile, ExprYield, Index, Member, |
David Tolnay | b57c849 | 2018-05-05 00:32:04 -0700 | [diff] [blame] | 313 | }; |
Michael Layzell | 734adb4 | 2017-06-07 16:58:31 -0400 | [diff] [blame] | 314 | |
| 315 | #[cfg(feature = "full")] |
David Tolnay | b57c849 | 2018-05-05 00:32:04 -0700 | [diff] [blame] | 316 | pub use expr::{ |
| 317 | Arm, Block, FieldPat, FieldValue, GenericMethodArgument, Label, Local, MethodTurbofish, Pat, |
| 318 | PatBox, PatIdent, PatLit, PatMacro, PatPath, PatRange, PatRef, PatSlice, PatStruct, PatTuple, |
| 319 | PatTupleStruct, PatVerbatim, PatWild, RangeLimits, Stmt, |
| 320 | }; |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 321 | |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 322 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | b79ee96 | 2016-09-04 09:39:20 -0700 | [diff] [blame] | 323 | mod generics; |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 324 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | b57c849 | 2018-05-05 00:32:04 -0700 | [diff] [blame] | 325 | pub use generics::{ |
| 326 | BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeDef, PredicateEq, |
| 327 | PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, |
| 328 | WhereClause, WherePredicate, |
| 329 | }; |
David Tolnay | e614f28 | 2018-10-27 22:50:12 -0700 | [diff] [blame] | 330 | #[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))] |
David Tolnay | fd6bf5c | 2017-11-12 09:41:14 -0800 | [diff] [blame] | 331 | pub use generics::{ImplGenerics, Turbofish, TypeGenerics}; |
David Tolnay | 35161ff | 2016-09-03 11:33:15 -0700 | [diff] [blame] | 332 | |
David Tolnay | f38cdf6 | 2016-09-23 19:07:09 -0700 | [diff] [blame] | 333 | #[cfg(feature = "full")] |
David Tolnay | b79ee96 | 2016-09-04 09:39:20 -0700 | [diff] [blame] | 334 | mod item; |
David Tolnay | f38cdf6 | 2016-09-23 19:07:09 -0700 | [diff] [blame] | 335 | #[cfg(feature = "full")] |
David Tolnay | b57c849 | 2018-05-05 00:32:04 -0700 | [diff] [blame] | 336 | pub use item::{ |
David Tolnay | 435c178 | 2018-08-24 16:15:44 -0400 | [diff] [blame] | 337 | ArgCaptured, ArgSelf, ArgSelfRef, FnArg, FnDecl, ForeignItem, ForeignItemFn, ForeignItemMacro, |
| 338 | ForeignItemStatic, ForeignItemType, ForeignItemVerbatim, ImplItem, ImplItemConst, |
David Tolnay | bb82ef0 | 2018-08-24 20:15:45 -0400 | [diff] [blame] | 339 | ImplItemExistential, ImplItemMacro, ImplItemMethod, ImplItemType, ImplItemVerbatim, Item, |
| 340 | ItemConst, ItemEnum, ItemExistential, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, |
David Tolnay | c6b04dd | 2018-08-30 23:22:51 -0700 | [diff] [blame] | 341 | ItemMacro, ItemMacro2, ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, |
| 342 | ItemUnion, ItemUse, ItemVerbatim, MethodSig, TraitItem, TraitItemConst, TraitItemMacro, |
| 343 | TraitItemMethod, TraitItemType, TraitItemVerbatim, UseGlob, UseGroup, UseName, UsePath, |
| 344 | UseRename, UseTree, |
David Tolnay | b57c849 | 2018-05-05 00:32:04 -0700 | [diff] [blame] | 345 | }; |
David Tolnay | 35161ff | 2016-09-03 11:33:15 -0700 | [diff] [blame] | 346 | |
David Tolnay | 631cb8c | 2016-11-10 17:16:41 -0800 | [diff] [blame] | 347 | #[cfg(feature = "full")] |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 348 | mod file; |
David Tolnay | 631cb8c | 2016-11-10 17:16:41 -0800 | [diff] [blame] | 349 | #[cfg(feature = "full")] |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 350 | pub use file::File; |
David Tolnay | 631cb8c | 2016-11-10 17:16:41 -0800 | [diff] [blame] | 351 | |
David Tolnay | 63e3dee | 2017-06-03 20:13:17 -0700 | [diff] [blame] | 352 | mod lifetime; |
| 353 | pub use lifetime::Lifetime; |
| 354 | |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 355 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 356 | mod lit; |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 357 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | b57c849 | 2018-05-05 00:32:04 -0700 | [diff] [blame] | 358 | pub use lit::{ |
| 359 | FloatSuffix, IntSuffix, Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr, |
| 360 | LitVerbatim, StrStyle, |
| 361 | }; |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 362 | |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 363 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 364 | mod mac; |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 365 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | ab91951 | 2017-12-30 23:31:51 -0500 | [diff] [blame] | 366 | pub use mac::{Macro, MacroDelimiter}; |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 367 | |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 368 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | 0e83740 | 2016-12-22 17:25:55 -0500 | [diff] [blame] | 369 | mod derive; |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 370 | #[cfg(feature = "derive")] |
David Tolnay | e3d41b7 | 2017-12-31 15:24:00 -0500 | [diff] [blame] | 371 | pub use derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput}; |
David Tolnay | f38cdf6 | 2016-09-23 19:07:09 -0700 | [diff] [blame] | 372 | |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 373 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | 3cb23a9 | 2016-10-07 23:02:21 -0700 | [diff] [blame] | 374 | mod op; |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 375 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | 3cb23a9 | 2016-10-07 23:02:21 -0700 | [diff] [blame] | 376 | pub use op::{BinOp, UnOp}; |
| 377 | |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 378 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | b79ee96 | 2016-09-04 09:39:20 -0700 | [diff] [blame] | 379 | mod ty; |
David Tolnay | 3cfd1d3 | 2018-01-03 00:22:08 -0800 | [diff] [blame] | 380 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | b57c849 | 2018-05-05 00:32:04 -0700 | [diff] [blame] | 381 | pub use ty::{ |
| 382 | Abi, BareFnArg, BareFnArgName, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup, |
| 383 | TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, |
| 384 | TypeSlice, TypeTraitObject, TypeTuple, TypeVerbatim, |
| 385 | }; |
David Tolnay | 056de30 | 2018-01-05 14:29:05 -0800 | [diff] [blame] | 386 | |
| 387 | #[cfg(any(feature = "full", feature = "derive"))] |
| 388 | mod path; |
| 389 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | b57c849 | 2018-05-05 00:32:04 -0700 | [diff] [blame] | 390 | pub use path::{ |
David Tolnay | 9d0882a | 2018-09-01 19:49:14 -0700 | [diff] [blame] | 391 | AngleBracketedGenericArguments, Binding, Constraint, GenericArgument, |
| 392 | ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf, |
David Tolnay | b57c849 | 2018-05-05 00:32:04 -0700 | [diff] [blame] | 393 | }; |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame] | 394 | |
David Tolnay | 1b752fb | 2017-12-26 21:41:39 -0500 | [diff] [blame] | 395 | #[cfg(feature = "parsing")] |
David Tolnay | dfc886b | 2018-01-06 08:03:09 -0800 | [diff] [blame] | 396 | pub mod buffer; |
David Tolnay | 94d304f | 2018-08-30 23:43:53 -0700 | [diff] [blame] | 397 | #[cfg(feature = "parsing")] |
| 398 | pub mod ext; |
David Tolnay | 94d2b79 | 2018-04-29 12:26:10 -0700 | [diff] [blame] | 399 | pub mod punctuated; |
David Tolnay | e614f28 | 2018-10-27 22:50:12 -0700 | [diff] [blame] | 400 | #[cfg(all(any(feature = "full", feature = "derive"), feature = "extra-traits"))] |
David Tolnay | e082403 | 2017-12-27 15:25:56 -0500 | [diff] [blame] | 401 | mod tt; |
David Tolnay | c5ab8c6 | 2017-12-26 16:43:39 -0500 | [diff] [blame] | 402 | |
David Tolnay | e83ef5a | 2018-01-11 15:18:36 -0800 | [diff] [blame] | 403 | // Not public API except the `parse_quote!` macro. |
David Tolnay | 491680a | 2018-01-23 00:34:40 -0800 | [diff] [blame] | 404 | #[cfg(feature = "parsing")] |
David Tolnay | e83ef5a | 2018-01-11 15:18:36 -0800 | [diff] [blame] | 405 | #[doc(hidden)] |
| 406 | pub mod parse_quote; |
| 407 | |
David Tolnay | f98865f | 2018-10-13 14:37:07 -0700 | [diff] [blame] | 408 | // Not public API except the `parse_macro_input!` macro. |
| 409 | #[cfg(all( |
| 410 | not(all(target_arch = "wasm32", target_os = "unknown")), |
| 411 | feature = "parsing", |
| 412 | feature = "proc-macro" |
| 413 | ))] |
| 414 | #[doc(hidden)] |
| 415 | pub mod parse_macro_input; |
| 416 | |
David Tolnay | 4d942b4 | 2018-01-02 22:14:04 -0800 | [diff] [blame] | 417 | #[cfg(all(feature = "parsing", feature = "printing"))] |
David Tolnay | f790b61 | 2017-12-31 18:46:57 -0500 | [diff] [blame] | 418 | pub mod spanned; |
| 419 | |
Nika Layzell | a6f46c4 | 2017-10-26 15:26:16 -0400 | [diff] [blame] | 420 | mod gen { |
David Tolnay | ded2d68 | 2018-01-06 18:53:53 -0800 | [diff] [blame] | 421 | /// Syntax tree traversal to walk a shared borrow of a syntax tree. |
| 422 | /// |
| 423 | /// Each method of the [`Visit`] trait is a hook that can be overridden to |
| 424 | /// customize the behavior when visiting the corresponding type of node. By |
| 425 | /// default, every method recursively visits the substructure of the input |
| 426 | /// by invoking the right visitor method of each of its fields. |
| 427 | /// |
| 428 | /// [`Visit`]: trait.Visit.html |
| 429 | /// |
David Tolnay | 95989db | 2019-01-01 15:05:57 -0500 | [diff] [blame] | 430 | /// ```edition2018 |
David Tolnay | ded2d68 | 2018-01-06 18:53:53 -0800 | [diff] [blame] | 431 | /// # use syn::{Attribute, BinOp, Expr, ExprBinary}; |
| 432 | /// # |
| 433 | /// pub trait Visit<'ast> { |
| 434 | /// /* ... */ |
| 435 | /// |
| 436 | /// fn visit_expr_binary(&mut self, node: &'ast ExprBinary) { |
| 437 | /// for attr in &node.attrs { |
| 438 | /// self.visit_attribute(attr); |
| 439 | /// } |
| 440 | /// self.visit_expr(&*node.left); |
| 441 | /// self.visit_bin_op(&node.op); |
| 442 | /// self.visit_expr(&*node.right); |
| 443 | /// } |
| 444 | /// |
| 445 | /// /* ... */ |
| 446 | /// # fn visit_attribute(&mut self, node: &'ast Attribute); |
| 447 | /// # fn visit_expr(&mut self, node: &'ast Expr); |
| 448 | /// # fn visit_bin_op(&mut self, node: &'ast BinOp); |
| 449 | /// } |
| 450 | /// ``` |
David Tolnay | 461d98e | 2018-01-07 11:07:19 -0800 | [diff] [blame] | 451 | /// |
| 452 | /// *This module is available if Syn is built with the `"visit"` feature.* |
Nika Layzell | a6f46c4 | 2017-10-26 15:26:16 -0400 | [diff] [blame] | 453 | #[cfg(feature = "visit")] |
| 454 | pub mod visit; |
David Tolnay | 5533772 | 2016-09-11 12:58:56 -0700 | [diff] [blame] | 455 | |
David Tolnay | ded2d68 | 2018-01-06 18:53:53 -0800 | [diff] [blame] | 456 | /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in |
| 457 | /// place. |
| 458 | /// |
| 459 | /// Each method of the [`VisitMut`] trait is a hook that can be overridden |
| 460 | /// to customize the behavior when mutating the corresponding type of node. |
| 461 | /// By default, every method recursively visits the substructure of the |
| 462 | /// input by invoking the right visitor method of each of its fields. |
| 463 | /// |
| 464 | /// [`VisitMut`]: trait.VisitMut.html |
| 465 | /// |
David Tolnay | 95989db | 2019-01-01 15:05:57 -0500 | [diff] [blame] | 466 | /// ```edition2018 |
David Tolnay | ded2d68 | 2018-01-06 18:53:53 -0800 | [diff] [blame] | 467 | /// # use syn::{Attribute, BinOp, Expr, ExprBinary}; |
| 468 | /// # |
| 469 | /// pub trait VisitMut { |
| 470 | /// /* ... */ |
| 471 | /// |
| 472 | /// fn visit_expr_binary_mut(&mut self, node: &mut ExprBinary) { |
| 473 | /// for attr in &mut node.attrs { |
| 474 | /// self.visit_attribute_mut(attr); |
| 475 | /// } |
| 476 | /// self.visit_expr_mut(&mut *node.left); |
| 477 | /// self.visit_bin_op_mut(&mut node.op); |
| 478 | /// self.visit_expr_mut(&mut *node.right); |
| 479 | /// } |
| 480 | /// |
| 481 | /// /* ... */ |
| 482 | /// # fn visit_attribute_mut(&mut self, node: &mut Attribute); |
| 483 | /// # fn visit_expr_mut(&mut self, node: &mut Expr); |
| 484 | /// # fn visit_bin_op_mut(&mut self, node: &mut BinOp); |
| 485 | /// } |
| 486 | /// ``` |
David Tolnay | 461d98e | 2018-01-07 11:07:19 -0800 | [diff] [blame] | 487 | /// |
| 488 | /// *This module is available if Syn is built with the `"visit-mut"` |
| 489 | /// feature.* |
David Tolnay | 9df02c4 | 2018-01-06 13:52:48 -0800 | [diff] [blame] | 490 | #[cfg(feature = "visit-mut")] |
Nika Layzell | a6f46c4 | 2017-10-26 15:26:16 -0400 | [diff] [blame] | 491 | pub mod visit_mut; |
Nika Layzell | 2772666 | 2017-10-24 23:16:35 -0400 | [diff] [blame] | 492 | |
David Tolnay | ded2d68 | 2018-01-06 18:53:53 -0800 | [diff] [blame] | 493 | /// Syntax tree traversal to transform the nodes of an owned syntax tree. |
| 494 | /// |
| 495 | /// Each method of the [`Fold`] trait is a hook that can be overridden to |
| 496 | /// customize the behavior when transforming the corresponding type of node. |
| 497 | /// By default, every method recursively visits the substructure of the |
| 498 | /// input by invoking the right visitor method of each of its fields. |
| 499 | /// |
| 500 | /// [`Fold`]: trait.Fold.html |
| 501 | /// |
David Tolnay | 95989db | 2019-01-01 15:05:57 -0500 | [diff] [blame] | 502 | /// ```edition2018 |
David Tolnay | ded2d68 | 2018-01-06 18:53:53 -0800 | [diff] [blame] | 503 | /// # use syn::{Attribute, BinOp, Expr, ExprBinary}; |
| 504 | /// # |
| 505 | /// pub trait Fold { |
| 506 | /// /* ... */ |
| 507 | /// |
| 508 | /// fn fold_expr_binary(&mut self, node: ExprBinary) -> ExprBinary { |
| 509 | /// ExprBinary { |
| 510 | /// attrs: node.attrs |
| 511 | /// .into_iter() |
| 512 | /// .map(|attr| self.fold_attribute(attr)) |
| 513 | /// .collect(), |
| 514 | /// left: Box::new(self.fold_expr(*node.left)), |
| 515 | /// op: self.fold_bin_op(node.op), |
| 516 | /// right: Box::new(self.fold_expr(*node.right)), |
| 517 | /// } |
| 518 | /// } |
| 519 | /// |
| 520 | /// /* ... */ |
| 521 | /// # fn fold_attribute(&mut self, node: Attribute) -> Attribute; |
| 522 | /// # fn fold_expr(&mut self, node: Expr) -> Expr; |
| 523 | /// # fn fold_bin_op(&mut self, node: BinOp) -> BinOp; |
| 524 | /// } |
| 525 | /// ``` |
David Tolnay | 461d98e | 2018-01-07 11:07:19 -0800 | [diff] [blame] | 526 | /// |
| 527 | /// *This module is available if Syn is built with the `"fold"` feature.* |
Nika Layzell | a6f46c4 | 2017-10-26 15:26:16 -0400 | [diff] [blame] | 528 | #[cfg(feature = "fold")] |
| 529 | pub mod fold; |
David Tolnay | f60f426 | 2017-12-28 19:17:58 -0500 | [diff] [blame] | 530 | |
David Tolnay | 0a0d78c | 2018-01-05 15:24:01 -0800 | [diff] [blame] | 531 | #[cfg(any(feature = "full", feature = "derive"))] |
David Tolnay | f60f426 | 2017-12-28 19:17:58 -0500 | [diff] [blame] | 532 | #[path = "../gen_helper.rs"] |
| 533 | mod helper; |
Nika Layzell | a6f46c4 | 2017-10-26 15:26:16 -0400 | [diff] [blame] | 534 | } |
| 535 | pub use gen::*; |
gnzlbg | 9ae88d8 | 2017-01-26 20:45:17 +0100 | [diff] [blame] | 536 | |
David Tolnay | 456c982 | 2018-08-25 08:09:46 -0400 | [diff] [blame] | 537 | // Not public API. |
| 538 | #[doc(hidden)] |
| 539 | pub mod export; |
| 540 | |
David Tolnay | 7fb11e7 | 2018-09-06 01:02:27 -0700 | [diff] [blame] | 541 | mod keyword; |
David Tolnay | b625418 | 2018-08-25 08:44:54 -0400 | [diff] [blame] | 542 | |
| 543 | #[cfg(feature = "parsing")] |
David Tolnay | 7fb11e7 | 2018-09-06 01:02:27 -0700 | [diff] [blame] | 544 | mod lookahead; |
Louis Kureuil Person | c0beaf3 | 2018-09-05 00:12:43 +0200 | [diff] [blame] | 545 | |
| 546 | #[cfg(feature = "parsing")] |
David Tolnay | b625418 | 2018-08-25 08:44:54 -0400 | [diff] [blame] | 547 | pub mod parse; |
| 548 | |
David Tolnay | 776f8e0 | 2018-08-24 22:32:10 -0400 | [diff] [blame] | 549 | mod span; |
| 550 | |
David Tolnay | e614f28 | 2018-10-27 22:50:12 -0700 | [diff] [blame] | 551 | #[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))] |
David Tolnay | 6402391 | 2018-08-31 09:51:12 -0700 | [diff] [blame] | 552 | mod print; |
| 553 | |
David Tolnay | 3287480 | 2018-11-11 08:52:19 -0800 | [diff] [blame] | 554 | mod thread; |
| 555 | |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 556 | //////////////////////////////////////////////////////////////////////////////// |
| 557 | |
David Tolnay | aa77a85 | 2018-08-31 11:15:10 -0700 | [diff] [blame] | 558 | #[cfg(any(feature = "parsing", feature = "full", feature = "derive"))] |
David Tolnay | 94f0663 | 2018-08-31 10:17:17 -0700 | [diff] [blame] | 559 | #[allow(non_camel_case_types)] |
David Tolnay | 10951d5 | 2018-08-31 10:27:39 -0700 | [diff] [blame] | 560 | struct private; |
David Tolnay | 94f0663 | 2018-08-31 10:17:17 -0700 | [diff] [blame] | 561 | |
| 562 | //////////////////////////////////////////////////////////////////////////////// |
| 563 | |
David Tolnay | b625418 | 2018-08-25 08:44:54 -0400 | [diff] [blame] | 564 | mod error; |
David Tolnay | c647b7d | 2018-11-23 22:06:13 -0800 | [diff] [blame] | 565 | pub use error::{Error, Result}; |
David Tolnay | c5ab8c6 | 2017-12-26 16:43:39 -0500 | [diff] [blame] | 566 | |
David Tolnay | ccab0be | 2018-01-06 22:24:47 -0800 | [diff] [blame] | 567 | /// Parse tokens of source code into the chosen syntax tree node. |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 568 | /// |
| 569 | /// This is preferred over parsing a string because tokens are able to preserve |
| 570 | /// information about where in the user's code they were originally written (the |
| 571 | /// "span" of the token), possibly allowing the compiler to produce better error |
| 572 | /// messages. |
| 573 | /// |
David Tolnay | ccab0be | 2018-01-06 22:24:47 -0800 | [diff] [blame] | 574 | /// This function parses a `proc_macro::TokenStream` which is the type used for |
| 575 | /// interop with the compiler in a procedural macro. To parse a |
| 576 | /// `proc_macro2::TokenStream`, use [`syn::parse2`] instead. |
| 577 | /// |
| 578 | /// [`syn::parse2`]: fn.parse2.html |
| 579 | /// |
hcpl | 4b72a38 | 2018-04-04 14:50:24 +0300 | [diff] [blame] | 580 | /// *This function is available if Syn is built with both the `"parsing"` and |
| 581 | /// `"proc-macro"` features.* |
David Tolnay | 461d98e | 2018-01-07 11:07:19 -0800 | [diff] [blame] | 582 | /// |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 583 | /// # Examples |
| 584 | /// |
David Tolnay | 95989db | 2019-01-01 15:05:57 -0500 | [diff] [blame] | 585 | /// ```edition2018 |
David Tolnay | a1c9807 | 2018-09-06 08:58:10 -0700 | [diff] [blame] | 586 | /// extern crate proc_macro; |
David Tolnay | a1c9807 | 2018-09-06 08:58:10 -0700 | [diff] [blame] | 587 | /// |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 588 | /// use proc_macro::TokenStream; |
David Tolnay | fd5b117 | 2018-12-31 17:54:36 -0500 | [diff] [blame] | 589 | /// use quote::quote; |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 590 | /// use syn::DeriveInput; |
| 591 | /// |
David Tolnay | bcf2602 | 2017-12-25 22:10:52 -0500 | [diff] [blame] | 592 | /// # const IGNORE_TOKENS: &str = stringify! { |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 593 | /// #[proc_macro_derive(MyMacro)] |
David Tolnay | bcf2602 | 2017-12-25 22:10:52 -0500 | [diff] [blame] | 594 | /// # }; |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 595 | /// pub fn my_macro(input: TokenStream) -> TokenStream { |
| 596 | /// // Parse the tokens into a syntax tree |
| 597 | /// let ast: DeriveInput = syn::parse(input).unwrap(); |
| 598 | /// |
| 599 | /// // Build the output, possibly using quasi-quotation |
| 600 | /// let expanded = quote! { |
| 601 | /// /* ... */ |
| 602 | /// }; |
| 603 | /// |
David Tolnay | bcf2602 | 2017-12-25 22:10:52 -0500 | [diff] [blame] | 604 | /// // Convert into a token stream and return it |
| 605 | /// expanded.into() |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 606 | /// } |
| 607 | /// ``` |
David Tolnay | 278f9e3 | 2018-08-14 22:41:11 -0700 | [diff] [blame] | 608 | #[cfg(all( |
| 609 | not(all(target_arch = "wasm32", target_os = "unknown")), |
| 610 | feature = "parsing", |
| 611 | feature = "proc-macro" |
| 612 | ))] |
David Tolnay | c647b7d | 2018-11-23 22:06:13 -0800 | [diff] [blame] | 613 | pub fn parse<T: parse::Parse>(tokens: proc_macro::TokenStream) -> Result<T> { |
David Tolnay | 80a914f | 2018-08-30 23:49:53 -0700 | [diff] [blame] | 614 | parse::Parser::parse(T::parse, tokens) |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 615 | } |
| 616 | |
David Tolnay | ccab0be | 2018-01-06 22:24:47 -0800 | [diff] [blame] | 617 | /// Parse a proc-macro2 token stream into the chosen syntax tree node. |
| 618 | /// |
| 619 | /// This function parses a `proc_macro2::TokenStream` which is commonly useful |
| 620 | /// when the input comes from a node of the Syn syntax tree, for example the tts |
| 621 | /// of a [`Macro`] node. When in a procedural macro parsing the |
| 622 | /// `proc_macro::TokenStream` provided by the compiler, use [`syn::parse`] |
| 623 | /// instead. |
| 624 | /// |
| 625 | /// [`Macro`]: struct.Macro.html |
| 626 | /// [`syn::parse`]: fn.parse.html |
David Tolnay | 461d98e | 2018-01-07 11:07:19 -0800 | [diff] [blame] | 627 | /// |
| 628 | /// *This function is available if Syn is built with the `"parsing"` feature.* |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 629 | #[cfg(feature = "parsing")] |
David Tolnay | c647b7d | 2018-11-23 22:06:13 -0800 | [diff] [blame] | 630 | pub fn parse2<T: parse::Parse>(tokens: proc_macro2::TokenStream) -> Result<T> { |
David Tolnay | 80a914f | 2018-08-30 23:49:53 -0700 | [diff] [blame] | 631 | parse::Parser::parse2(T::parse, tokens) |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 632 | } |
Alex Crichton | 954046c | 2017-05-30 21:49:42 -0700 | [diff] [blame] | 633 | |
David Tolnay | ccab0be | 2018-01-06 22:24:47 -0800 | [diff] [blame] | 634 | /// Parse a string of Rust code into the chosen syntax tree node. |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 635 | /// |
David Tolnay | 461d98e | 2018-01-07 11:07:19 -0800 | [diff] [blame] | 636 | /// *This function is available if Syn is built with the `"parsing"` feature.* |
| 637 | /// |
David Tolnay | 3f5b06f | 2018-01-11 21:02:00 -0800 | [diff] [blame] | 638 | /// # Hygiene |
| 639 | /// |
| 640 | /// Every span in the resulting syntax tree will be set to resolve at the macro |
| 641 | /// call site. |
| 642 | /// |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 643 | /// # Examples |
| 644 | /// |
David Tolnay | 95989db | 2019-01-01 15:05:57 -0500 | [diff] [blame] | 645 | /// ```edition2018 |
David Tolnay | 67fea04 | 2018-11-24 14:50:20 -0800 | [diff] [blame] | 646 | /// use syn::{Expr, Result}; |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 647 | /// |
| 648 | /// fn run() -> Result<()> { |
| 649 | /// let code = "assert_eq!(u8::max_value(), 255)"; |
| 650 | /// let expr = syn::parse_str::<Expr>(code)?; |
| 651 | /// println!("{:#?}", expr); |
| 652 | /// Ok(()) |
| 653 | /// } |
| 654 | /// # |
David Tolnay | fd5b117 | 2018-12-31 17:54:36 -0500 | [diff] [blame] | 655 | /// # fn main() { |
| 656 | /// # run().unwrap(); |
| 657 | /// # } |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 658 | /// ``` |
| 659 | #[cfg(feature = "parsing")] |
David Tolnay | c647b7d | 2018-11-23 22:06:13 -0800 | [diff] [blame] | 660 | pub fn parse_str<T: parse::Parse>(s: &str) -> Result<T> { |
David Tolnay | 80a914f | 2018-08-30 23:49:53 -0700 | [diff] [blame] | 661 | parse::Parser::parse_str(T::parse, s) |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 662 | } |
Alex Crichton | 954046c | 2017-05-30 21:49:42 -0700 | [diff] [blame] | 663 | |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 664 | // FIXME the name parse_file makes it sound like you might pass in a path to a |
| 665 | // file, rather than the content. |
| 666 | /// Parse the content of a file of Rust code. |
| 667 | /// |
| 668 | /// This is different from `syn::parse_str::<File>(content)` in two ways: |
| 669 | /// |
| 670 | /// - It discards a leading byte order mark `\u{FEFF}` if the file has one. |
| 671 | /// - It preserves the shebang line of the file, such as `#!/usr/bin/env rustx`. |
| 672 | /// |
| 673 | /// If present, either of these would be an error using `from_str`. |
| 674 | /// |
David Tolnay | c8b0e0f | 2019-03-07 22:46:32 -0800 | [diff] [blame] | 675 | /// *This function is available if Syn is built with the `"parsing"` and |
| 676 | /// `"full"` features.* |
David Tolnay | 461d98e | 2018-01-07 11:07:19 -0800 | [diff] [blame] | 677 | /// |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 678 | /// # Examples |
| 679 | /// |
David Tolnay | 95989db | 2019-01-01 15:05:57 -0500 | [diff] [blame] | 680 | /// ```edition2018,no_run |
David Tolnay | 9b00f65 | 2018-09-01 10:31:02 -0700 | [diff] [blame] | 681 | /// use std::error::Error; |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 682 | /// use std::fs::File; |
| 683 | /// use std::io::Read; |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 684 | /// |
David Tolnay | 9b00f65 | 2018-09-01 10:31:02 -0700 | [diff] [blame] | 685 | /// fn run() -> Result<(), Box<Error>> { |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 686 | /// let mut file = File::open("path/to/code.rs")?; |
| 687 | /// let mut content = String::new(); |
| 688 | /// file.read_to_string(&mut content)?; |
| 689 | /// |
| 690 | /// let ast = syn::parse_file(&content)?; |
| 691 | /// if let Some(shebang) = ast.shebang { |
| 692 | /// println!("{}", shebang); |
| 693 | /// } |
| 694 | /// println!("{} items", ast.items.len()); |
| 695 | /// |
| 696 | /// Ok(()) |
| 697 | /// } |
| 698 | /// # |
David Tolnay | fd5b117 | 2018-12-31 17:54:36 -0500 | [diff] [blame] | 699 | /// # fn main() { |
| 700 | /// # run().unwrap(); |
| 701 | /// # } |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 702 | /// ``` |
| 703 | #[cfg(all(feature = "parsing", feature = "full"))] |
David Tolnay | c647b7d | 2018-11-23 22:06:13 -0800 | [diff] [blame] | 704 | pub fn parse_file(mut content: &str) -> Result<File> { |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 705 | // Strip the BOM if it is present |
| 706 | const BOM: &'static str = "\u{feff}"; |
| 707 | if content.starts_with(BOM) { |
| 708 | content = &content[BOM.len()..]; |
David Tolnay | 35161ff | 2016-09-03 11:33:15 -0700 | [diff] [blame] | 709 | } |
Michael Layzell | 5e107ff | 2017-01-24 19:58:39 -0500 | [diff] [blame] | 710 | |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 711 | let mut shebang = None; |
| 712 | if content.starts_with("#!") && !content.starts_with("#![") { |
| 713 | if let Some(idx) = content.find('\n') { |
| 714 | shebang = Some(content[..idx].to_string()); |
| 715 | content = &content[idx..]; |
| 716 | } else { |
| 717 | shebang = Some(content.to_string()); |
| 718 | content = ""; |
| 719 | } |
Alex Crichton | 954046c | 2017-05-30 21:49:42 -0700 | [diff] [blame] | 720 | } |
David Tolnay | 0a8972b | 2017-02-27 02:10:01 -0800 | [diff] [blame] | 721 | |
David Tolnay | c7a5d3d | 2017-06-04 12:11:05 -0700 | [diff] [blame] | 722 | let mut file: File = parse_str(content)?; |
| 723 | file.shebang = shebang; |
| 724 | Ok(file) |
Michael Layzell | 5e107ff | 2017-01-24 19:58:39 -0500 | [diff] [blame] | 725 | } |