blob: b4590ddd1cfeeed8dd17933ba05612c35806e1bf [file] [log] [blame]
David Tolnay5e84e972018-01-05 17:51:06 -08001//! Syn is a parsing library for parsing a stream of Rust tokens into a syntax
2//! tree of Rust source code.
3//!
David Tolnay6b889eb2018-09-01 18:12:17 -07004//! Currently this library is geared toward use in Rust procedural macros, but
5//! contains some APIs that may be useful more generally.
David Tolnay5e84e972018-01-05 17:51:06 -08006//!
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 Tolnay6b889eb2018-09-01 18:12:17 -070018//! - **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 Tolnay5e84e972018-01-05 17:51:06 -080023//!
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 Tolnay6b889eb2018-09-01 18:12:17 -070039//! [parser functions]: parse/index.html
David Tolnay5e84e972018-01-05 17:51:06 -080040//!
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 Tolnayb28acf32018-09-06 09:01:40 -070060//! syn = "0.15"
David Tolnay87003d02018-05-20 19:45:13 -070061//! quote = "0.6"
David Tolnay5e84e972018-01-05 17:51:06 -080062//!
63//! [lib]
64//! proc-macro = true
65//! ```
66//!
David Tolnay95989db2019-01-01 15:05:57 -050067//! ```edition2018
David Tolnayfd5b1172018-12-31 17:54:36 -050068//! # extern crate quote;
69//! #
David Tolnaya1c98072018-09-06 08:58:10 -070070//! extern crate proc_macro;
71//!
David Tolnay5e84e972018-01-05 17:51:06 -080072//! use proc_macro::TokenStream;
David Tolnayfd5b1172018-12-31 17:54:36 -050073//! use quote::quote;
74//! use syn::{parse_macro_input, DeriveInput};
David Tolnay5e84e972018-01-05 17:51:06 -080075//!
76//! # const IGNORE_TOKENS: &str = stringify! {
77//! #[proc_macro_derive(MyMacro)]
78//! # };
79//! pub fn my_macro(input: TokenStream) -> TokenStream {
80//! // Parse the input tokens into a syntax tree
David Tolnay6b889eb2018-09-01 18:12:17 -070081//! let input = parse_macro_input!(input as DeriveInput);
David Tolnay5e84e972018-01-05 17:51:06 -080082//!
83//! // Build the output, possibly using quasi-quotation
84//! let expanded = quote! {
85//! // ...
86//! };
87//!
88//! // Hand the output tokens back to the compiler
David Tolnay35b498e2018-09-01 20:10:40 -070089//! TokenStream::from(expanded)
David Tolnay5e84e972018-01-05 17:51:06 -080090//! }
David Tolnay5e84e972018-01-05 17:51:06 -080091//! ```
92//!
93//! The [`heapsize`] example directory shows a complete working Macros 1.1
David Tolnayb4f57242018-10-28 17:57:08 -070094//! implementation of a custom derive. It works on any Rust compiler 1.15+.
David Tolnay5e84e972018-01-05 17:51:06 -080095//! The example derives a `HeapSize` trait which computes an estimate of the
96//! amount of heap memory owned by a value.
97//!
98//! [`heapsize`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize
99//!
David Tolnay95989db2019-01-01 15:05:57 -0500100//! ```edition2018
David Tolnay5e84e972018-01-05 17:51:06 -0800101//! pub trait HeapSize {
102//! /// Total number of bytes of heap memory owned by `self`.
103//! fn heap_size_of_children(&self) -> usize;
104//! }
105//! ```
106//!
107//! The custom derive allows users to write `#[derive(HeapSize)]` on data
108//! structures in their program.
109//!
David Tolnay95989db2019-01-01 15:05:57 -0500110//! ```edition2018
David Tolnay5e84e972018-01-05 17:51:06 -0800111//! # const IGNORE_TOKENS: &str = stringify! {
112//! #[derive(HeapSize)]
113//! # };
114//! struct Demo<'a, T: ?Sized> {
115//! a: Box<T>,
116//! b: u8,
117//! c: &'a str,
118//! d: String,
119//! }
120//! ```
121//!
122//! ## Spans and error reporting
123//!
David Tolnay5e84e972018-01-05 17:51:06 -0800124//! The token-based procedural macro API provides great control over where the
125//! compiler's error messages are displayed in user code. Consider the error the
126//! user sees if one of their field types does not implement `HeapSize`.
127//!
David Tolnay95989db2019-01-01 15:05:57 -0500128//! ```edition2018
David Tolnay5e84e972018-01-05 17:51:06 -0800129//! # const IGNORE_TOKENS: &str = stringify! {
130//! #[derive(HeapSize)]
131//! # };
132//! struct Broken {
133//! ok: String,
134//! bad: std::thread::Thread,
135//! }
136//! ```
137//!
David Tolnay5e84e972018-01-05 17:51:06 -0800138//! By tracking span information all the way through the expansion of a
David Tolnay3be1b782018-10-28 17:41:41 -0700139//! procedural macro as shown in the `heapsize` example, token-based macros in
David Tolnay5e84e972018-01-05 17:51:06 -0800140//! Syn are able to trigger errors that directly pinpoint the source of the
141//! problem.
142//!
143//! ```text
144//! error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
145//! --> src/main.rs:7:5
146//! |
147//! 7 | bad: std::thread::Thread,
David Tolnayefff2ff2018-01-07 11:49:52 -0800148//! | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `Thread`
David Tolnay5e84e972018-01-05 17:51:06 -0800149//! ```
150//!
David Tolnay6b889eb2018-09-01 18:12:17 -0700151//! ## Parsing a custom syntax
David Tolnay5e84e972018-01-05 17:51:06 -0800152//!
153//! The [`lazy-static`] example directory shows the implementation of a
154//! `functionlike!(...)` procedural macro in which the input tokens are parsed
David Tolnay6b889eb2018-09-01 18:12:17 -0700155//! using Syn's parsing API.
David Tolnay5e84e972018-01-05 17:51:06 -0800156//!
157//! [`lazy-static`]: https://github.com/dtolnay/syn/tree/master/examples/lazy-static
David Tolnay5e84e972018-01-05 17:51:06 -0800158//!
159//! The example reimplements the popular `lazy_static` crate from crates.io as a
160//! procedural macro.
161//!
David Tolnay95989db2019-01-01 15:05:57 -0500162//! ```edition2018
David Tolnay5e84e972018-01-05 17:51:06 -0800163//! # macro_rules! lazy_static {
164//! # ($($tt:tt)*) => {}
165//! # }
166//! #
167//! lazy_static! {
168//! static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
169//! }
170//! ```
171//!
172//! The implementation shows how to trigger custom warnings and error messages
173//! on the macro input.
174//!
175//! ```text
176//! warning: come on, pick a more creative name
177//! --> src/main.rs:10:16
178//! |
179//! 10 | static ref FOO: String = "lazy_static".to_owned();
180//! | ^^^
181//! ```
182//!
183//! ## Debugging
184//!
185//! When developing a procedural macro it can be helpful to look at what the
186//! generated code looks like. Use `cargo rustc -- -Zunstable-options
187//! --pretty=expanded` or the [`cargo expand`] subcommand.
188//!
David Tolnay324db2d2018-01-07 11:51:09 -0800189//! [`cargo expand`]: https://github.com/dtolnay/cargo-expand
David Tolnay5e84e972018-01-05 17:51:06 -0800190//!
191//! To show the expanded code for some crate that uses your procedural macro,
192//! run `cargo expand` from that crate. To show the expanded code for one of
193//! your own test cases, run `cargo expand --test the_test_case` where the last
194//! argument is the name of the test file without the `.rs` extension.
195//!
196//! This write-up by Brandon W Maister discusses debugging in more detail:
197//! [Debugging Rust's new Custom Derive system][debugging].
198//!
199//! [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
200//!
201//! ## Optional features
202//!
203//! Syn puts a lot of functionality behind optional features in order to
204//! optimize compile time for the most common use cases. The following features
205//! are available.
206//!
207//! - **`derive`** *(enabled by default)* — Data structures for representing the
208//! possible input to a custom derive, including structs and enums and types.
209//! - **`full`** — Data structures for representing the syntax tree of all valid
210//! Rust source code, including items and expressions.
211//! - **`parsing`** *(enabled by default)* — Ability to parse input tokens into
212//! a syntax tree node of a chosen type.
213//! - **`printing`** *(enabled by default)* — Ability to print a syntax tree
214//! node as tokens of Rust source code.
215//! - **`visit`** — Trait for traversing a syntax tree.
David Tolnay34981cf2018-01-06 16:22:35 -0800216//! - **`visit-mut`** — Trait for traversing and mutating in place a syntax
David Tolnay5e84e972018-01-05 17:51:06 -0800217//! tree.
218//! - **`fold`** — Trait for transforming an owned syntax tree.
219//! - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
220//! types.
221//! - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree
222//! types.
hcpl4b72a382018-04-04 14:50:24 +0300223//! - **`proc-macro`** *(enabled by default)* — Runtime dependency on the
224//! dynamic library libproc_macro from rustc toolchain.
David Tolnay5e84e972018-01-05 17:51:06 -0800225
David Tolnay4cf7db82018-01-07 15:22:01 -0800226// Syn types in rustdoc of other crates get linked to here.
David Tolnayab3ff962018-12-15 00:53:40 -0800227#![doc(html_root_url = "https://docs.rs/syn/0.15.23")]
David Tolnay46b17c02018-09-22 13:27:40 -0700228#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
David Tolnay34071ba2018-05-20 20:00:41 -0700229#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
David Tolnay34071ba2018-05-20 20:00:41 -0700230// Ignored clippy lints.
David Tolnay94d2b792018-04-29 12:26:10 -0700231#![cfg_attr(
232 feature = "cargo-clippy",
233 allow(
David Tolnay4831ac62018-08-30 21:04:16 -0700234 block_in_if_condition_stmt,
David Tolnay0cec3e62018-07-21 09:08:30 -0700235 const_static_lifetime,
David Tolnay24b079d2018-08-27 08:28:10 -0700236 cyclomatic_complexity,
David Tolnay267eac62018-11-06 20:30:36 -0800237 deprecated_cfg_attr,
David Tolnay0cec3e62018-07-21 09:08:30 -0700238 doc_markdown,
David Tolnay24b079d2018-08-27 08:28:10 -0700239 eval_order_dependence,
David Tolnay0cec3e62018-07-21 09:08:30 -0700240 large_enum_variant,
David Tolnayaba1ed12018-11-10 14:26:40 -0800241 needless_pass_by_value,
David Tolnay6fb87462018-09-01 16:51:49 -0700242 never_loop,
David Tolnay0cec3e62018-07-21 09:08:30 -0700243 redundant_field_names,
David Tolnayaba1ed12018-11-10 14:26:40 -0800244 too_many_arguments,
David Tolnay94d2b792018-04-29 12:26:10 -0700245 )
246)]
David Tolnay34071ba2018-05-20 20:00:41 -0700247// Ignored clippy_pedantic lints.
248#![cfg_attr(
249 feature = "cargo-clippy",
250 allow(
David Tolnay0cec3e62018-07-21 09:08:30 -0700251 cast_possible_truncation,
252 cast_possible_wrap,
David Tolnayb1617752018-08-24 21:16:33 -0400253 empty_enum,
David Tolnay0cec3e62018-07-21 09:08:30 -0700254 if_not_else,
David Tolnay0cec3e62018-07-21 09:08:30 -0700255 items_after_statements,
David Tolnay24cff8a2018-12-31 18:21:23 -0500256 module_name_repetitions,
David Tolnay151f92f2018-08-14 22:44:53 -0700257 shadow_unrelated,
David Tolnay0cec3e62018-07-21 09:08:30 -0700258 similar_names,
259 single_match_else,
David Tolnay0cec3e62018-07-21 09:08:30 -0700260 unseparated_literal_suffix,
261 use_self,
David Tolnaya06d8642018-11-06 20:31:05 -0800262 used_underscore_binding,
David Tolnay34071ba2018-05-20 20:00:41 -0700263 )
264)]
David Tolnayad2836d2017-04-20 10:11:43 -0700265
David Tolnay278f9e32018-08-14 22:41:11 -0700266#[cfg(all(
267 not(all(target_arch = "wasm32", target_os = "unknown")),
268 feature = "proc-macro"
269))]
David Tolnay51382052017-12-27 13:46:21 -0500270extern crate proc_macro;
David Tolnay94d2b792018-04-29 12:26:10 -0700271extern crate proc_macro2;
David Tolnay570695e2017-06-03 16:15:13 -0700272extern crate unicode_xid;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700273
David Tolnay1cf80912017-12-31 18:35:12 -0500274#[cfg(feature = "printing")]
David Tolnay87d0b442016-09-04 11:52:12 -0700275extern crate quote;
276
Alex Crichton62a0a592017-05-22 13:58:53 -0700277#[macro_use]
278mod macros;
279
David Tolnay734079e2018-09-01 02:03:37 -0700280// Not public API.
David Tolnay852bff72018-08-27 08:24:02 -0700281#[cfg(feature = "parsing")]
David Tolnay734079e2018-09-01 02:03:37 -0700282#[doc(hidden)]
David Tolnay852bff72018-08-27 08:24:02 -0700283#[macro_use]
David Tolnay734079e2018-09-01 02:03:37 -0700284pub mod group;
David Tolnay852bff72018-08-27 08:24:02 -0700285
David Tolnayc5ab8c62017-12-26 16:43:39 -0500286#[macro_use]
David Tolnay32954ef2017-12-26 22:43:16 -0500287pub mod token;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500288
David Tolnay4fb71232018-08-25 23:14:50 -0400289mod ident;
290pub use ident::Ident;
David Tolnaye303b7c2018-05-20 16:46:35 -0700291
David Tolnay3cfd1d32018-01-03 00:22:08 -0800292#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700293mod attr;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800294#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay161f2de2018-10-13 14:38:20 -0700295pub use attr::{AttrStyle, Attribute, AttributeArgs, Meta, MetaList, MetaNameValue, NestedMeta};
David Tolnay35161ff2016-09-03 11:33:15 -0700296
David Tolnay3cfd1d32018-01-03 00:22:08 -0800297#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf38cdf62016-09-23 19:07:09 -0700298mod data;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800299#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700300pub use data::{
301 Field, Fields, FieldsNamed, FieldsUnnamed, Variant, VisCrate, VisPublic, VisRestricted,
302 Visibility,
303};
David Tolnayf38cdf62016-09-23 19:07:09 -0700304
David Tolnay3cfd1d32018-01-03 00:22:08 -0800305#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700306mod expr;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800307#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700308pub use expr::{
David Tolnay02a9c6f2018-08-24 18:58:45 -0400309 Expr, ExprArray, ExprAssign, ExprAssignOp, ExprAsync, ExprBinary, ExprBlock, ExprBox,
310 ExprBreak, ExprCall, ExprCast, ExprClosure, ExprContinue, ExprField, ExprForLoop, ExprGroup,
David Tolnay9c119122018-09-01 18:47:02 -0700311 ExprIf, ExprInPlace, ExprIndex, ExprLet, ExprLit, ExprLoop, ExprMacro, ExprMatch,
David Tolnay02a9c6f2018-08-24 18:58:45 -0400312 ExprMethodCall, ExprParen, ExprPath, ExprRange, ExprReference, ExprRepeat, ExprReturn,
313 ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprType, ExprUnary, ExprUnsafe, ExprVerbatim,
David Tolnay9c119122018-09-01 18:47:02 -0700314 ExprWhile, ExprYield, Index, Member,
David Tolnayb57c8492018-05-05 00:32:04 -0700315};
Michael Layzell734adb42017-06-07 16:58:31 -0400316
317#[cfg(feature = "full")]
David Tolnayb57c8492018-05-05 00:32:04 -0700318pub use expr::{
319 Arm, Block, FieldPat, FieldValue, GenericMethodArgument, Label, Local, MethodTurbofish, Pat,
320 PatBox, PatIdent, PatLit, PatMacro, PatPath, PatRange, PatRef, PatSlice, PatStruct, PatTuple,
321 PatTupleStruct, PatVerbatim, PatWild, RangeLimits, Stmt,
322};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700323
David Tolnay3cfd1d32018-01-03 00:22:08 -0800324#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700325mod generics;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800326#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700327pub use generics::{
328 BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeDef, PredicateEq,
329 PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound,
330 WhereClause, WherePredicate,
331};
David Tolnaye614f282018-10-27 22:50:12 -0700332#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800333pub use generics::{ImplGenerics, Turbofish, TypeGenerics};
David Tolnay35161ff2016-09-03 11:33:15 -0700334
David Tolnayf38cdf62016-09-23 19:07:09 -0700335#[cfg(feature = "full")]
David Tolnayb79ee962016-09-04 09:39:20 -0700336mod item;
David Tolnayf38cdf62016-09-23 19:07:09 -0700337#[cfg(feature = "full")]
David Tolnayb57c8492018-05-05 00:32:04 -0700338pub use item::{
David Tolnay435c1782018-08-24 16:15:44 -0400339 ArgCaptured, ArgSelf, ArgSelfRef, FnArg, FnDecl, ForeignItem, ForeignItemFn, ForeignItemMacro,
340 ForeignItemStatic, ForeignItemType, ForeignItemVerbatim, ImplItem, ImplItemConst,
David Tolnaybb82ef02018-08-24 20:15:45 -0400341 ImplItemExistential, ImplItemMacro, ImplItemMethod, ImplItemType, ImplItemVerbatim, Item,
342 ItemConst, ItemEnum, ItemExistential, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl,
David Tolnayc6b04dd2018-08-30 23:22:51 -0700343 ItemMacro, ItemMacro2, ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType,
344 ItemUnion, ItemUse, ItemVerbatim, MethodSig, TraitItem, TraitItemConst, TraitItemMacro,
345 TraitItemMethod, TraitItemType, TraitItemVerbatim, UseGlob, UseGroup, UseName, UsePath,
346 UseRename, UseTree,
David Tolnayb57c8492018-05-05 00:32:04 -0700347};
David Tolnay35161ff2016-09-03 11:33:15 -0700348
David Tolnay631cb8c2016-11-10 17:16:41 -0800349#[cfg(feature = "full")]
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700350mod file;
David Tolnay631cb8c2016-11-10 17:16:41 -0800351#[cfg(feature = "full")]
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700352pub use file::File;
David Tolnay631cb8c2016-11-10 17:16:41 -0800353
David Tolnay63e3dee2017-06-03 20:13:17 -0700354mod lifetime;
355pub use lifetime::Lifetime;
356
David Tolnay3cfd1d32018-01-03 00:22:08 -0800357#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700358mod lit;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800359#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700360pub use lit::{
361 FloatSuffix, IntSuffix, Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr,
362 LitVerbatim, StrStyle,
363};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700364
David Tolnay3cfd1d32018-01-03 00:22:08 -0800365#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700366mod mac;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800367#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayab919512017-12-30 23:31:51 -0500368pub use mac::{Macro, MacroDelimiter};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700369
David Tolnay3cfd1d32018-01-03 00:22:08 -0800370#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay0e837402016-12-22 17:25:55 -0500371mod derive;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800372#[cfg(feature = "derive")]
David Tolnaye3d41b72017-12-31 15:24:00 -0500373pub use derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
David Tolnayf38cdf62016-09-23 19:07:09 -0700374
David Tolnay3cfd1d32018-01-03 00:22:08 -0800375#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay3cb23a92016-10-07 23:02:21 -0700376mod op;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800377#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay3cb23a92016-10-07 23:02:21 -0700378pub use op::{BinOp, UnOp};
379
David Tolnay3cfd1d32018-01-03 00:22:08 -0800380#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700381mod ty;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800382#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700383pub use ty::{
384 Abi, BareFnArg, BareFnArgName, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,
385 TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference,
386 TypeSlice, TypeTraitObject, TypeTuple, TypeVerbatim,
387};
David Tolnay056de302018-01-05 14:29:05 -0800388
389#[cfg(any(feature = "full", feature = "derive"))]
390mod path;
391#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700392pub use path::{
David Tolnay9d0882a2018-09-01 19:49:14 -0700393 AngleBracketedGenericArguments, Binding, Constraint, GenericArgument,
394 ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
David Tolnayb57c8492018-05-05 00:32:04 -0700395};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700396
David Tolnay1b752fb2017-12-26 21:41:39 -0500397#[cfg(feature = "parsing")]
David Tolnaydfc886b2018-01-06 08:03:09 -0800398pub mod buffer;
David Tolnay94d304f2018-08-30 23:43:53 -0700399#[cfg(feature = "parsing")]
400pub mod ext;
David Tolnay94d2b792018-04-29 12:26:10 -0700401pub mod punctuated;
David Tolnaye614f282018-10-27 22:50:12 -0700402#[cfg(all(any(feature = "full", feature = "derive"), feature = "extra-traits"))]
David Tolnaye0824032017-12-27 15:25:56 -0500403mod tt;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500404
David Tolnaye83ef5a2018-01-11 15:18:36 -0800405// Not public API except the `parse_quote!` macro.
David Tolnay491680a2018-01-23 00:34:40 -0800406#[cfg(feature = "parsing")]
David Tolnaye83ef5a2018-01-11 15:18:36 -0800407#[doc(hidden)]
408pub mod parse_quote;
409
David Tolnayf98865f2018-10-13 14:37:07 -0700410// Not public API except the `parse_macro_input!` macro.
411#[cfg(all(
412 not(all(target_arch = "wasm32", target_os = "unknown")),
413 feature = "parsing",
414 feature = "proc-macro"
415))]
416#[doc(hidden)]
417pub mod parse_macro_input;
418
David Tolnay4d942b42018-01-02 22:14:04 -0800419#[cfg(all(feature = "parsing", feature = "printing"))]
David Tolnayf790b612017-12-31 18:46:57 -0500420pub mod spanned;
421
Nika Layzella6f46c42017-10-26 15:26:16 -0400422mod gen {
David Tolnayded2d682018-01-06 18:53:53 -0800423 /// Syntax tree traversal to walk a shared borrow of a syntax tree.
424 ///
425 /// Each method of the [`Visit`] trait is a hook that can be overridden to
426 /// customize the behavior when visiting the corresponding type of node. By
427 /// default, every method recursively visits the substructure of the input
428 /// by invoking the right visitor method of each of its fields.
429 ///
430 /// [`Visit`]: trait.Visit.html
431 ///
David Tolnay95989db2019-01-01 15:05:57 -0500432 /// ```edition2018
David Tolnayded2d682018-01-06 18:53:53 -0800433 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
434 /// #
435 /// pub trait Visit<'ast> {
436 /// /* ... */
437 ///
438 /// fn visit_expr_binary(&mut self, node: &'ast ExprBinary) {
439 /// for attr in &node.attrs {
440 /// self.visit_attribute(attr);
441 /// }
442 /// self.visit_expr(&*node.left);
443 /// self.visit_bin_op(&node.op);
444 /// self.visit_expr(&*node.right);
445 /// }
446 ///
447 /// /* ... */
448 /// # fn visit_attribute(&mut self, node: &'ast Attribute);
449 /// # fn visit_expr(&mut self, node: &'ast Expr);
450 /// # fn visit_bin_op(&mut self, node: &'ast BinOp);
451 /// }
452 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800453 ///
454 /// *This module is available if Syn is built with the `"visit"` feature.*
Nika Layzella6f46c42017-10-26 15:26:16 -0400455 #[cfg(feature = "visit")]
456 pub mod visit;
David Tolnay55337722016-09-11 12:58:56 -0700457
David Tolnayded2d682018-01-06 18:53:53 -0800458 /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in
459 /// place.
460 ///
461 /// Each method of the [`VisitMut`] trait is a hook that can be overridden
462 /// to customize the behavior when mutating the corresponding type of node.
463 /// By default, every method recursively visits the substructure of the
464 /// input by invoking the right visitor method of each of its fields.
465 ///
466 /// [`VisitMut`]: trait.VisitMut.html
467 ///
David Tolnay95989db2019-01-01 15:05:57 -0500468 /// ```edition2018
David Tolnayded2d682018-01-06 18:53:53 -0800469 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
470 /// #
471 /// pub trait VisitMut {
472 /// /* ... */
473 ///
474 /// fn visit_expr_binary_mut(&mut self, node: &mut ExprBinary) {
475 /// for attr in &mut node.attrs {
476 /// self.visit_attribute_mut(attr);
477 /// }
478 /// self.visit_expr_mut(&mut *node.left);
479 /// self.visit_bin_op_mut(&mut node.op);
480 /// self.visit_expr_mut(&mut *node.right);
481 /// }
482 ///
483 /// /* ... */
484 /// # fn visit_attribute_mut(&mut self, node: &mut Attribute);
485 /// # fn visit_expr_mut(&mut self, node: &mut Expr);
486 /// # fn visit_bin_op_mut(&mut self, node: &mut BinOp);
487 /// }
488 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800489 ///
490 /// *This module is available if Syn is built with the `"visit-mut"`
491 /// feature.*
David Tolnay9df02c42018-01-06 13:52:48 -0800492 #[cfg(feature = "visit-mut")]
Nika Layzella6f46c42017-10-26 15:26:16 -0400493 pub mod visit_mut;
Nika Layzell27726662017-10-24 23:16:35 -0400494
David Tolnayded2d682018-01-06 18:53:53 -0800495 /// Syntax tree traversal to transform the nodes of an owned syntax tree.
496 ///
497 /// Each method of the [`Fold`] trait is a hook that can be overridden to
498 /// customize the behavior when transforming the corresponding type of node.
499 /// By default, every method recursively visits the substructure of the
500 /// input by invoking the right visitor method of each of its fields.
501 ///
502 /// [`Fold`]: trait.Fold.html
503 ///
David Tolnay95989db2019-01-01 15:05:57 -0500504 /// ```edition2018
David Tolnayded2d682018-01-06 18:53:53 -0800505 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
506 /// #
507 /// pub trait Fold {
508 /// /* ... */
509 ///
510 /// fn fold_expr_binary(&mut self, node: ExprBinary) -> ExprBinary {
511 /// ExprBinary {
512 /// attrs: node.attrs
513 /// .into_iter()
514 /// .map(|attr| self.fold_attribute(attr))
515 /// .collect(),
516 /// left: Box::new(self.fold_expr(*node.left)),
517 /// op: self.fold_bin_op(node.op),
518 /// right: Box::new(self.fold_expr(*node.right)),
519 /// }
520 /// }
521 ///
522 /// /* ... */
523 /// # fn fold_attribute(&mut self, node: Attribute) -> Attribute;
524 /// # fn fold_expr(&mut self, node: Expr) -> Expr;
525 /// # fn fold_bin_op(&mut self, node: BinOp) -> BinOp;
526 /// }
527 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800528 ///
529 /// *This module is available if Syn is built with the `"fold"` feature.*
Nika Layzella6f46c42017-10-26 15:26:16 -0400530 #[cfg(feature = "fold")]
531 pub mod fold;
David Tolnayf60f4262017-12-28 19:17:58 -0500532
David Tolnay0a0d78c2018-01-05 15:24:01 -0800533 #[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf60f4262017-12-28 19:17:58 -0500534 #[path = "../gen_helper.rs"]
535 mod helper;
Nika Layzella6f46c42017-10-26 15:26:16 -0400536}
537pub use gen::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100538
David Tolnay456c9822018-08-25 08:09:46 -0400539// Not public API.
540#[doc(hidden)]
541pub mod export;
542
David Tolnay7fb11e72018-09-06 01:02:27 -0700543mod keyword;
David Tolnayb6254182018-08-25 08:44:54 -0400544
545#[cfg(feature = "parsing")]
David Tolnay7fb11e72018-09-06 01:02:27 -0700546mod lookahead;
Louis Kureuil Personc0beaf32018-09-05 00:12:43 +0200547
548#[cfg(feature = "parsing")]
David Tolnayb6254182018-08-25 08:44:54 -0400549pub mod parse;
550
David Tolnay776f8e02018-08-24 22:32:10 -0400551mod span;
552
David Tolnaye614f282018-10-27 22:50:12 -0700553#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
David Tolnay64023912018-08-31 09:51:12 -0700554mod print;
555
David Tolnay32874802018-11-11 08:52:19 -0800556mod thread;
557
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700558////////////////////////////////////////////////////////////////////////////////
559
David Tolnayaa77a852018-08-31 11:15:10 -0700560#[cfg(any(feature = "parsing", feature = "full", feature = "derive"))]
David Tolnay94f06632018-08-31 10:17:17 -0700561#[allow(non_camel_case_types)]
David Tolnay10951d52018-08-31 10:27:39 -0700562struct private;
David Tolnay94f06632018-08-31 10:17:17 -0700563
564////////////////////////////////////////////////////////////////////////////////
565
David Tolnayb6254182018-08-25 08:44:54 -0400566mod error;
David Tolnayc647b7d2018-11-23 22:06:13 -0800567pub use error::{Error, Result};
David Tolnayc5ab8c62017-12-26 16:43:39 -0500568
David Tolnayccab0be2018-01-06 22:24:47 -0800569/// Parse tokens of source code into the chosen syntax tree node.
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700570///
571/// This is preferred over parsing a string because tokens are able to preserve
572/// information about where in the user's code they were originally written (the
573/// "span" of the token), possibly allowing the compiler to produce better error
574/// messages.
575///
David Tolnayccab0be2018-01-06 22:24:47 -0800576/// This function parses a `proc_macro::TokenStream` which is the type used for
577/// interop with the compiler in a procedural macro. To parse a
578/// `proc_macro2::TokenStream`, use [`syn::parse2`] instead.
579///
580/// [`syn::parse2`]: fn.parse2.html
581///
hcpl4b72a382018-04-04 14:50:24 +0300582/// *This function is available if Syn is built with both the `"parsing"` and
583/// `"proc-macro"` features.*
David Tolnay461d98e2018-01-07 11:07:19 -0800584///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700585/// # Examples
586///
David Tolnay95989db2019-01-01 15:05:57 -0500587/// ```edition2018
David Tolnayfd5b1172018-12-31 17:54:36 -0500588/// # extern crate quote;
589/// #
David Tolnaya1c98072018-09-06 08:58:10 -0700590/// extern crate proc_macro;
David Tolnaya1c98072018-09-06 08:58:10 -0700591///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700592/// use proc_macro::TokenStream;
David Tolnayfd5b1172018-12-31 17:54:36 -0500593/// use quote::quote;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700594/// use syn::DeriveInput;
595///
David Tolnaybcf26022017-12-25 22:10:52 -0500596/// # const IGNORE_TOKENS: &str = stringify! {
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700597/// #[proc_macro_derive(MyMacro)]
David Tolnaybcf26022017-12-25 22:10:52 -0500598/// # };
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700599/// pub fn my_macro(input: TokenStream) -> TokenStream {
600/// // Parse the tokens into a syntax tree
601/// let ast: DeriveInput = syn::parse(input).unwrap();
602///
603/// // Build the output, possibly using quasi-quotation
604/// let expanded = quote! {
605/// /* ... */
606/// };
607///
David Tolnaybcf26022017-12-25 22:10:52 -0500608/// // Convert into a token stream and return it
609/// expanded.into()
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700610/// }
611/// ```
David Tolnay278f9e32018-08-14 22:41:11 -0700612#[cfg(all(
613 not(all(target_arch = "wasm32", target_os = "unknown")),
614 feature = "parsing",
615 feature = "proc-macro"
616))]
David Tolnayc647b7d2018-11-23 22:06:13 -0800617pub fn parse<T: parse::Parse>(tokens: proc_macro::TokenStream) -> Result<T> {
David Tolnay80a914f2018-08-30 23:49:53 -0700618 parse::Parser::parse(T::parse, tokens)
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700619}
620
David Tolnayccab0be2018-01-06 22:24:47 -0800621/// Parse a proc-macro2 token stream into the chosen syntax tree node.
622///
623/// This function parses a `proc_macro2::TokenStream` which is commonly useful
624/// when the input comes from a node of the Syn syntax tree, for example the tts
625/// of a [`Macro`] node. When in a procedural macro parsing the
626/// `proc_macro::TokenStream` provided by the compiler, use [`syn::parse`]
627/// instead.
628///
629/// [`Macro`]: struct.Macro.html
630/// [`syn::parse`]: fn.parse.html
David Tolnay461d98e2018-01-07 11:07:19 -0800631///
632/// *This function is available if Syn is built with the `"parsing"` feature.*
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700633#[cfg(feature = "parsing")]
David Tolnayc647b7d2018-11-23 22:06:13 -0800634pub fn parse2<T: parse::Parse>(tokens: proc_macro2::TokenStream) -> Result<T> {
David Tolnay80a914f2018-08-30 23:49:53 -0700635 parse::Parser::parse2(T::parse, tokens)
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700636}
Alex Crichton954046c2017-05-30 21:49:42 -0700637
David Tolnayccab0be2018-01-06 22:24:47 -0800638/// Parse a string of Rust code into the chosen syntax tree node.
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700639///
David Tolnay461d98e2018-01-07 11:07:19 -0800640/// *This function is available if Syn is built with the `"parsing"` feature.*
641///
David Tolnay3f5b06f2018-01-11 21:02:00 -0800642/// # Hygiene
643///
644/// Every span in the resulting syntax tree will be set to resolve at the macro
645/// call site.
646///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700647/// # Examples
648///
David Tolnay95989db2019-01-01 15:05:57 -0500649/// ```edition2018
David Tolnay67fea042018-11-24 14:50:20 -0800650/// use syn::{Expr, Result};
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700651///
652/// fn run() -> Result<()> {
653/// let code = "assert_eq!(u8::max_value(), 255)";
654/// let expr = syn::parse_str::<Expr>(code)?;
655/// println!("{:#?}", expr);
656/// Ok(())
657/// }
658/// #
David Tolnayfd5b1172018-12-31 17:54:36 -0500659/// # fn main() {
660/// # run().unwrap();
661/// # }
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700662/// ```
663#[cfg(feature = "parsing")]
David Tolnayc647b7d2018-11-23 22:06:13 -0800664pub fn parse_str<T: parse::Parse>(s: &str) -> Result<T> {
David Tolnay80a914f2018-08-30 23:49:53 -0700665 parse::Parser::parse_str(T::parse, s)
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700666}
Alex Crichton954046c2017-05-30 21:49:42 -0700667
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700668// FIXME the name parse_file makes it sound like you might pass in a path to a
669// file, rather than the content.
670/// Parse the content of a file of Rust code.
671///
672/// This is different from `syn::parse_str::<File>(content)` in two ways:
673///
674/// - It discards a leading byte order mark `\u{FEFF}` if the file has one.
675/// - It preserves the shebang line of the file, such as `#!/usr/bin/env rustx`.
676///
677/// If present, either of these would be an error using `from_str`.
678///
Christopher Serr9727ef22018-02-03 16:42:12 +0100679/// *This function is available if Syn is built with the `"parsing"` and `"full"` features.*
David Tolnay461d98e2018-01-07 11:07:19 -0800680///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700681/// # Examples
682///
David Tolnay95989db2019-01-01 15:05:57 -0500683/// ```edition2018,no_run
David Tolnay9b00f652018-09-01 10:31:02 -0700684/// use std::error::Error;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700685/// use std::fs::File;
686/// use std::io::Read;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700687///
David Tolnay9b00f652018-09-01 10:31:02 -0700688/// fn run() -> Result<(), Box<Error>> {
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700689/// let mut file = File::open("path/to/code.rs")?;
690/// let mut content = String::new();
691/// file.read_to_string(&mut content)?;
692///
693/// let ast = syn::parse_file(&content)?;
694/// if let Some(shebang) = ast.shebang {
695/// println!("{}", shebang);
696/// }
697/// println!("{} items", ast.items.len());
698///
699/// Ok(())
700/// }
701/// #
David Tolnayfd5b1172018-12-31 17:54:36 -0500702/// # fn main() {
703/// # run().unwrap();
704/// # }
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700705/// ```
706#[cfg(all(feature = "parsing", feature = "full"))]
David Tolnayc647b7d2018-11-23 22:06:13 -0800707pub fn parse_file(mut content: &str) -> Result<File> {
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700708 // Strip the BOM if it is present
709 const BOM: &'static str = "\u{feff}";
710 if content.starts_with(BOM) {
711 content = &content[BOM.len()..];
David Tolnay35161ff2016-09-03 11:33:15 -0700712 }
Michael Layzell5e107ff2017-01-24 19:58:39 -0500713
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700714 let mut shebang = None;
715 if content.starts_with("#!") && !content.starts_with("#![") {
716 if let Some(idx) = content.find('\n') {
717 shebang = Some(content[..idx].to_string());
718 content = &content[idx..];
719 } else {
720 shebang = Some(content.to_string());
721 content = "";
722 }
Alex Crichton954046c2017-05-30 21:49:42 -0700723 }
David Tolnay0a8972b2017-02-27 02:10:01 -0800724
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700725 let mut file: File = parse_str(content)?;
726 file.shebang = shebang;
727 Ok(file)
Michael Layzell5e107ff2017-01-24 19:58:39 -0500728}