blob: 948dd3e8a56841f4c41d9748068c671749c67b71 [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnay5e84e972018-01-05 17:51:06 -08009//! Syn is a parsing library for parsing a stream of Rust tokens into a syntax
10//! tree of Rust source code.
11//!
12//! Currently this library is geared toward the [custom derive] use case but
13//! contains some APIs that may be useful for Rust procedural macros more
14//! generally.
15//!
16//! [custom derive]: https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md
17//!
18//! - **Data structures** — Syn provides a complete syntax tree that can
19//! represent any valid Rust source code. The syntax tree is rooted at
20//! [`syn::File`] which represents a full source file, but there are other
21//! entry points that may be useful to procedural macros including
22//! [`syn::Item`], [`syn::Expr`] and [`syn::Type`].
23//!
24//! - **Custom derives** — Of particular interest to custom derives is
25//! [`syn::DeriveInput`] which is any of the three legal input items to a
26//! derive macro. An example below shows using this type in a library that can
27//! derive implementations of a trait of your own.
28//!
29//! - **Parser combinators** — Parsing in Syn is built on a suite of public
30//! parser combinator macros that you can use for parsing any token-based
31//! syntax you dream up within a `functionlike!(...)` procedural macro. Every
32//! syntax tree node defined by Syn is individually parsable and may be used
33//! as a building block for custom syntaxes, or you may do it all yourself
34//! working from the most primitive tokens.
35//!
36//! - **Location information** — Every token parsed by Syn is associated with a
37//! `Span` that tracks line and column information back to the source of that
38//! token. These spans allow a procedural macro to display detailed error
39//! messages pointing to all the right places in the user's code. There is an
40//! example of this below.
41//!
42//! - **Feature flags** — Functionality is aggressively feature gated so your
43//! procedural macros enable only what they need, and do not pay in compile
44//! time for all the rest.
45//!
46//! [`syn::File`]: struct.File.html
47//! [`syn::Item`]: enum.Item.html
48//! [`syn::Expr`]: enum.Expr.html
49//! [`syn::Type`]: enum.Type.html
50//! [`syn::DeriveInput`]: struct.DeriveInput.html
51//!
52//! *Version requirement: Syn supports any compiler version back to Rust's very
53//! first support for procedural macros in Rust 1.15.0. Some features especially
54//! around error reporting are only available in newer compilers or on the
55//! nightly channel.*
56//!
57//! ## Example of a custom derive
58//!
59//! The canonical custom derive using Syn looks like this. We write an ordinary
60//! Rust function tagged with a `proc_macro_derive` attribute and the name of
61//! the trait we are deriving. Any time that derive appears in the user's code,
62//! the Rust compiler passes their data structure as tokens into our macro. We
63//! get to execute arbitrary Rust code to figure out what to do with those
64//! tokens, then hand some tokens back to the compiler to compile into the
65//! user's crate.
66//!
67//! [`TokenStream`]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html
68//!
69//! ```toml
70//! [dependencies]
71//! syn = "0.12"
72//! quote = "0.4"
73//!
74//! [lib]
75//! proc-macro = true
76//! ```
77//!
78//! ```rust
79//! extern crate proc_macro;
80//! extern crate syn;
81//!
82//! #[macro_use]
83//! extern crate quote;
84//!
85//! use proc_macro::TokenStream;
86//! use syn::DeriveInput;
87//!
88//! # const IGNORE_TOKENS: &str = stringify! {
89//! #[proc_macro_derive(MyMacro)]
90//! # };
91//! pub fn my_macro(input: TokenStream) -> TokenStream {
92//! // Parse the input tokens into a syntax tree
93//! let input: DeriveInput = syn::parse(input).unwrap();
94//!
95//! // Build the output, possibly using quasi-quotation
96//! let expanded = quote! {
97//! // ...
98//! };
99//!
100//! // Hand the output tokens back to the compiler
101//! expanded.into()
102//! }
103//! #
104//! # fn main() {}
105//! ```
106//!
107//! The [`heapsize`] example directory shows a complete working Macros 1.1
108//! implementation of a custom derive. It works on any Rust compiler \>=1.15.0.
109//! The example derives a `HeapSize` trait which computes an estimate of the
110//! amount of heap memory owned by a value.
111//!
112//! [`heapsize`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize
113//!
114//! ```rust
115//! pub trait HeapSize {
116//! /// Total number of bytes of heap memory owned by `self`.
117//! fn heap_size_of_children(&self) -> usize;
118//! }
119//! ```
120//!
121//! The custom derive allows users to write `#[derive(HeapSize)]` on data
122//! structures in their program.
123//!
124//! ```rust
125//! # const IGNORE_TOKENS: &str = stringify! {
126//! #[derive(HeapSize)]
127//! # };
128//! struct Demo<'a, T: ?Sized> {
129//! a: Box<T>,
130//! b: u8,
131//! c: &'a str,
132//! d: String,
133//! }
134//! ```
135//!
136//! ## Spans and error reporting
137//!
138//! The [`heapsize2`] example directory is an extension of the `heapsize`
139//! example that demonstrates some of the hygiene and error reporting properties
140//! of Macros 2.0. This example currently requires a nightly Rust compiler
141//! \>=1.24.0-nightly but we are working to stabilize all of the APIs involved.
142//!
143//! [`heapsize2`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize2
144//!
145//! The token-based procedural macro API provides great control over where the
146//! compiler's error messages are displayed in user code. Consider the error the
147//! user sees if one of their field types does not implement `HeapSize`.
148//!
149//! ```rust
150//! # const IGNORE_TOKENS: &str = stringify! {
151//! #[derive(HeapSize)]
152//! # };
153//! struct Broken {
154//! ok: String,
155//! bad: std::thread::Thread,
156//! }
157//! ```
158//!
159//! In the Macros 1.1 string-based procedural macro world, the resulting error
160//! would point unhelpfully to the invocation of the derive macro and not to the
161//! actual problematic field.
162//!
163//! ```text
164//! error[E0599]: no method named `heap_size_of_children` found for type `std::thread::Thread` in the current scope
165//! --> src/main.rs:4:10
166//! |
167//! 4 | #[derive(HeapSize)]
168//! | ^^^^^^^^
169//! ```
170//!
171//! By tracking span information all the way through the expansion of a
172//! procedural macro as shown in the `heapsize2` example, token-based macros in
173//! Syn are able to trigger errors that directly pinpoint the source of the
174//! problem.
175//!
176//! ```text
177//! error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
178//! --> src/main.rs:7:5
179//! |
180//! 7 | bad: std::thread::Thread,
181//! | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `std::thread::Thread`
182//! ```
183//!
184//! ## Parsing a custom syntax using combinators
185//!
186//! The [`lazy-static`] example directory shows the implementation of a
187//! `functionlike!(...)` procedural macro in which the input tokens are parsed
188//! using [`nom`]-style parser combinators.
189//!
190//! [`lazy-static`]: https://github.com/dtolnay/syn/tree/master/examples/lazy-static
191//! [`nom`]: https://github.com/Geal/nom
192//!
193//! The example reimplements the popular `lazy_static` crate from crates.io as a
194//! procedural macro.
195//!
196//! ```
197//! # macro_rules! lazy_static {
198//! # ($($tt:tt)*) => {}
199//! # }
200//! #
201//! lazy_static! {
202//! static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
203//! }
204//! ```
205//!
206//! The implementation shows how to trigger custom warnings and error messages
207//! on the macro input.
208//!
209//! ```text
210//! warning: come on, pick a more creative name
211//! --> src/main.rs:10:16
212//! |
213//! 10 | static ref FOO: String = "lazy_static".to_owned();
214//! | ^^^
215//! ```
216//!
217//! ## Debugging
218//!
219//! When developing a procedural macro it can be helpful to look at what the
220//! generated code looks like. Use `cargo rustc -- -Zunstable-options
221//! --pretty=expanded` or the [`cargo expand`] subcommand.
222//!
223//! [`cargo-expand`]: https://github.com/dtolnay/cargo-expand
224//!
225//! To show the expanded code for some crate that uses your procedural macro,
226//! run `cargo expand` from that crate. To show the expanded code for one of
227//! your own test cases, run `cargo expand --test the_test_case` where the last
228//! argument is the name of the test file without the `.rs` extension.
229//!
230//! This write-up by Brandon W Maister discusses debugging in more detail:
231//! [Debugging Rust's new Custom Derive system][debugging].
232//!
233//! [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
234//!
235//! ## Optional features
236//!
237//! Syn puts a lot of functionality behind optional features in order to
238//! optimize compile time for the most common use cases. The following features
239//! are available.
240//!
241//! - **`derive`** *(enabled by default)* — Data structures for representing the
242//! possible input to a custom derive, including structs and enums and types.
243//! - **`full`** — Data structures for representing the syntax tree of all valid
244//! Rust source code, including items and expressions.
245//! - **`parsing`** *(enabled by default)* — Ability to parse input tokens into
246//! a syntax tree node of a chosen type.
247//! - **`printing`** *(enabled by default)* — Ability to print a syntax tree
248//! node as tokens of Rust source code.
249//! - **`visit`** — Trait for traversing a syntax tree.
David Tolnay34981cf2018-01-06 16:22:35 -0800250//! - **`visit-mut`** — Trait for traversing and mutating in place a syntax
David Tolnay5e84e972018-01-05 17:51:06 -0800251//! tree.
252//! - **`fold`** — Trait for transforming an owned syntax tree.
253//! - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
254//! types.
255//! - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree
256//! types.
257
David Tolnayad2836d2017-04-20 10:11:43 -0700258#![doc(html_root_url = "https://dtolnay.github.io/syn")]
David Tolnay51382052017-12-27 13:46:21 -0500259#![cfg_attr(feature = "cargo-clippy",
260 allow(const_static_lifetime, doc_markdown, large_enum_variant, match_bool,
David Tolnay76ebcdd2018-01-05 17:07:26 -0800261 redundant_closure, needless_pass_by_value))]
David Tolnayad2836d2017-04-20 10:11:43 -0700262
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700263extern crate proc_macro2;
David Tolnay51382052017-12-27 13:46:21 -0500264extern crate proc_macro;
David Tolnay570695e2017-06-03 16:15:13 -0700265extern crate unicode_xid;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700266
David Tolnay1cf80912017-12-31 18:35:12 -0500267#[cfg(feature = "printing")]
David Tolnay87d0b442016-09-04 11:52:12 -0700268extern crate quote;
269
David Tolnay1b752fb2017-12-26 21:41:39 -0500270#[cfg(feature = "parsing")]
David Tolnayf8db7ba2017-11-11 22:52:16 -0800271#[macro_use]
David Tolnayc5ab8c62017-12-26 16:43:39 -0500272#[doc(hidden)]
273pub mod parsers;
David Tolnay35161ff2016-09-03 11:33:15 -0700274
Alex Crichton62a0a592017-05-22 13:58:53 -0700275#[macro_use]
276mod macros;
277
David Tolnayc5ab8c62017-12-26 16:43:39 -0500278#[macro_use]
David Tolnay32954ef2017-12-26 22:43:16 -0500279pub mod token;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500280
David Tolnay3cfd1d32018-01-03 00:22:08 -0800281#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700282mod attr;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800283#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayaaadd782018-01-06 22:58:13 -0800284pub use attr::{AttrStyle, Attribute, Meta, MetaList, MetaNameValue, NestedMeta};
David Tolnay35161ff2016-09-03 11:33:15 -0700285
David Tolnay3cfd1d32018-01-03 00:22:08 -0800286#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf38cdf62016-09-23 19:07:09 -0700287mod data;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800288#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay61037c62018-01-05 16:21:03 -0800289pub use data::{Field, Fields, FieldsNamed, FieldsUnnamed, Variant, VisCrate, VisPublic,
290 VisRestricted, Visibility};
David Tolnayf38cdf62016-09-23 19:07:09 -0700291
David Tolnay3cfd1d32018-01-03 00:22:08 -0800292#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700293mod expr;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800294#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay51382052017-12-27 13:46:21 -0500295pub use expr::{Expr, ExprAddrOf, ExprArray, ExprAssign, ExprAssignOp, ExprBinary, ExprBlock,
296 ExprBox, ExprBreak, ExprCall, ExprCast, ExprCatch, ExprClosure, ExprContinue,
297 ExprField, ExprForLoop, ExprGroup, ExprIf, ExprIfLet, ExprInPlace, ExprIndex,
David Tolnay61037c62018-01-05 16:21:03 -0800298 ExprLit, ExprLoop, ExprMacro, ExprMatch, ExprMethodCall, ExprParen, ExprPath,
299 ExprRange, ExprRepeat, ExprReturn, ExprStruct, ExprTry, ExprTuple, ExprType,
300 ExprUnary, ExprUnsafe, ExprVerbatim, ExprWhile, ExprWhileLet, ExprYield, Index,
301 Member};
Michael Layzell734adb42017-06-07 16:58:31 -0400302
303#[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -0500304pub use expr::{Arm, Block, FieldPat, FieldValue, GenericMethodArgument, Label, Local,
David Tolnay61037c62018-01-05 16:21:03 -0800305 MethodTurbofish, Pat, PatBox, PatIdent, PatLit, PatMacro, PatPath, PatRange,
306 PatRef, PatSlice, PatStruct, PatTuple, PatTupleStruct, PatVerbatim, PatWild,
307 RangeLimits, Stmt};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700308
David Tolnay3cfd1d32018-01-03 00:22:08 -0800309#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700310mod generics;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800311#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay61037c62018-01-05 16:21:03 -0800312pub use generics::{BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeDef, PredicateEq,
313 PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam,
314 TypeParamBound, WhereClause, WherePredicate};
David Tolnay3cfd1d32018-01-03 00:22:08 -0800315#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800316pub use generics::{ImplGenerics, Turbofish, TypeGenerics};
David Tolnay35161ff2016-09-03 11:33:15 -0700317
David Tolnay55337722016-09-11 12:58:56 -0700318mod ident;
David Tolnaydaaf7742016-10-03 11:11:43 -0700319pub use ident::Ident;
David Tolnay55337722016-09-11 12:58:56 -0700320
David Tolnayf38cdf62016-09-23 19:07:09 -0700321#[cfg(feature = "full")]
David Tolnayb79ee962016-09-04 09:39:20 -0700322mod item;
David Tolnayf38cdf62016-09-23 19:07:09 -0700323#[cfg(feature = "full")]
David Tolnay61037c62018-01-05 16:21:03 -0800324pub use item::{ArgCaptured, ArgSelf, ArgSelfRef, FnArg, FnDecl, ForeignItem, ForeignItemFn,
325 ForeignItemStatic, ForeignItemType, ForeignItemVerbatim, ImplItem, ImplItemConst,
326 ImplItemMacro, ImplItemMethod, ImplItemType, ImplItemVerbatim, Item, ItemConst,
327 ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMacro2,
328 ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemType, ItemUnion, ItemUse,
329 ItemVerbatim, MethodSig, TraitItem, TraitItemConst, TraitItemMacro,
330 TraitItemMethod, TraitItemType, TraitItemVerbatim, UseGlob, UseList, UsePath,
331 UseTree};
David Tolnay35161ff2016-09-03 11:33:15 -0700332
David Tolnay631cb8c2016-11-10 17:16:41 -0800333#[cfg(feature = "full")]
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700334mod file;
David Tolnay631cb8c2016-11-10 17:16:41 -0800335#[cfg(feature = "full")]
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700336pub use file::File;
David Tolnay631cb8c2016-11-10 17:16:41 -0800337
David Tolnay3cfd1d32018-01-03 00:22:08 -0800338#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay63e3dee2017-06-03 20:13:17 -0700339mod lifetime;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800340#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay63e3dee2017-06-03 20:13:17 -0700341pub use lifetime::Lifetime;
342
David Tolnay3cfd1d32018-01-03 00:22:08 -0800343#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700344mod lit;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800345#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay61037c62018-01-05 16:21:03 -0800346pub use lit::{FloatSuffix, IntSuffix, Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat,
347 LitInt, LitStr, LitVerbatim, StrStyle};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700348
David Tolnay3cfd1d32018-01-03 00:22:08 -0800349#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700350mod mac;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800351#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayab919512017-12-30 23:31:51 -0500352pub use mac::{Macro, MacroDelimiter};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700353
David Tolnay3cfd1d32018-01-03 00:22:08 -0800354#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay0e837402016-12-22 17:25:55 -0500355mod derive;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800356#[cfg(feature = "derive")]
David Tolnaye3d41b72017-12-31 15:24:00 -0500357pub use derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
David Tolnayf38cdf62016-09-23 19:07:09 -0700358
David Tolnay3cfd1d32018-01-03 00:22:08 -0800359#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay3cb23a92016-10-07 23:02:21 -0700360mod op;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800361#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay3cb23a92016-10-07 23:02:21 -0700362pub use op::{BinOp, UnOp};
363
David Tolnay3cfd1d32018-01-03 00:22:08 -0800364#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700365mod ty;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800366#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay61037c62018-01-05 16:21:03 -0800367pub use ty::{Abi, BareFnArg, BareFnArgName, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,
368 TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr,
369 TypeReference, TypeSlice, TypeTraitObject, TypeTuple, TypeVerbatim};
David Tolnay056de302018-01-05 14:29:05 -0800370
371#[cfg(any(feature = "full", feature = "derive"))]
372mod path;
373#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay61037c62018-01-05 16:21:03 -0800374pub use path::{AngleBracketedGenericArguments, Binding, GenericArgument,
375 ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf};
David Tolnay3cfd1d32018-01-03 00:22:08 -0800376#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
David Tolnay056de302018-01-05 14:29:05 -0800377pub use path::PathTokens;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700378
David Tolnay1b752fb2017-12-26 21:41:39 -0500379#[cfg(feature = "parsing")]
David Tolnaydfc886b2018-01-06 08:03:09 -0800380pub mod buffer;
David Tolnay1b752fb2017-12-26 21:41:39 -0500381#[cfg(feature = "parsing")]
David Tolnayc5ab8c62017-12-26 16:43:39 -0500382pub mod synom;
David Tolnayf2cfd722017-12-31 18:02:51 -0500383pub mod punctuated;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800384#[cfg(all(any(feature = "full", feature = "derive"), feature = "parsing"))]
David Tolnaye0824032017-12-27 15:25:56 -0500385mod tt;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500386
David Tolnay4d942b42018-01-02 22:14:04 -0800387#[cfg(all(feature = "parsing", feature = "printing"))]
David Tolnayf790b612017-12-31 18:46:57 -0500388pub mod spanned;
389
Nika Layzella6f46c42017-10-26 15:26:16 -0400390mod gen {
David Tolnayded2d682018-01-06 18:53:53 -0800391 /// Syntax tree traversal to walk a shared borrow of a syntax tree.
392 ///
393 /// Each method of the [`Visit`] trait is a hook that can be overridden to
394 /// customize the behavior when visiting the corresponding type of node. By
395 /// default, every method recursively visits the substructure of the input
396 /// by invoking the right visitor method of each of its fields.
397 ///
398 /// [`Visit`]: trait.Visit.html
399 ///
400 /// ```rust
401 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
402 /// #
403 /// pub trait Visit<'ast> {
404 /// /* ... */
405 ///
406 /// fn visit_expr_binary(&mut self, node: &'ast ExprBinary) {
407 /// for attr in &node.attrs {
408 /// self.visit_attribute(attr);
409 /// }
410 /// self.visit_expr(&*node.left);
411 /// self.visit_bin_op(&node.op);
412 /// self.visit_expr(&*node.right);
413 /// }
414 ///
415 /// /* ... */
416 /// # fn visit_attribute(&mut self, node: &'ast Attribute);
417 /// # fn visit_expr(&mut self, node: &'ast Expr);
418 /// # fn visit_bin_op(&mut self, node: &'ast BinOp);
419 /// }
420 /// ```
Nika Layzella6f46c42017-10-26 15:26:16 -0400421 #[cfg(feature = "visit")]
422 pub mod visit;
David Tolnay55337722016-09-11 12:58:56 -0700423
David Tolnayded2d682018-01-06 18:53:53 -0800424
425 /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in
426 /// place.
427 ///
428 /// Each method of the [`VisitMut`] trait is a hook that can be overridden
429 /// to customize the behavior when mutating the corresponding type of node.
430 /// By default, every method recursively visits the substructure of the
431 /// input by invoking the right visitor method of each of its fields.
432 ///
433 /// [`VisitMut`]: trait.VisitMut.html
434 ///
435 /// ```rust
436 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
437 /// #
438 /// pub trait VisitMut {
439 /// /* ... */
440 ///
441 /// fn visit_expr_binary_mut(&mut self, node: &mut ExprBinary) {
442 /// for attr in &mut node.attrs {
443 /// self.visit_attribute_mut(attr);
444 /// }
445 /// self.visit_expr_mut(&mut *node.left);
446 /// self.visit_bin_op_mut(&mut node.op);
447 /// self.visit_expr_mut(&mut *node.right);
448 /// }
449 ///
450 /// /* ... */
451 /// # fn visit_attribute_mut(&mut self, node: &mut Attribute);
452 /// # fn visit_expr_mut(&mut self, node: &mut Expr);
453 /// # fn visit_bin_op_mut(&mut self, node: &mut BinOp);
454 /// }
455 /// ```
David Tolnay9df02c42018-01-06 13:52:48 -0800456 #[cfg(feature = "visit-mut")]
Nika Layzella6f46c42017-10-26 15:26:16 -0400457 pub mod visit_mut;
Nika Layzell27726662017-10-24 23:16:35 -0400458
David Tolnayded2d682018-01-06 18:53:53 -0800459 /// Syntax tree traversal to transform the nodes of an owned syntax tree.
460 ///
461 /// Each method of the [`Fold`] trait is a hook that can be overridden to
462 /// customize the behavior when transforming 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 /// [`Fold`]: trait.Fold.html
467 ///
468 /// ```rust
469 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
470 /// #
471 /// pub trait Fold {
472 /// /* ... */
473 ///
474 /// fn fold_expr_binary(&mut self, node: ExprBinary) -> ExprBinary {
475 /// ExprBinary {
476 /// attrs: node.attrs
477 /// .into_iter()
478 /// .map(|attr| self.fold_attribute(attr))
479 /// .collect(),
480 /// left: Box::new(self.fold_expr(*node.left)),
481 /// op: self.fold_bin_op(node.op),
482 /// right: Box::new(self.fold_expr(*node.right)),
483 /// }
484 /// }
485 ///
486 /// /* ... */
487 /// # fn fold_attribute(&mut self, node: Attribute) -> Attribute;
488 /// # fn fold_expr(&mut self, node: Expr) -> Expr;
489 /// # fn fold_bin_op(&mut self, node: BinOp) -> BinOp;
490 /// }
491 /// ```
Nika Layzella6f46c42017-10-26 15:26:16 -0400492 #[cfg(feature = "fold")]
493 pub mod fold;
David Tolnayf60f4262017-12-28 19:17:58 -0500494
David Tolnay0a0d78c2018-01-05 15:24:01 -0800495 #[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf60f4262017-12-28 19:17:58 -0500496 #[path = "../gen_helper.rs"]
497 mod helper;
Nika Layzella6f46c42017-10-26 15:26:16 -0400498}
499pub use gen::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100500
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700501////////////////////////////////////////////////////////////////////////////////
502
David Tolnay55337722016-09-11 12:58:56 -0700503#[cfg(feature = "parsing")]
David Tolnayc5ab8c62017-12-26 16:43:39 -0500504use synom::Synom;
505#[cfg(feature = "parsing")]
David Tolnaydfc886b2018-01-06 08:03:09 -0800506use buffer::TokenBuffer;
Ted Driggs054abbb2017-05-01 12:20:52 -0700507
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700508#[cfg(feature = "parsing")]
David Tolnayc5ab8c62017-12-26 16:43:39 -0500509mod error;
510#[cfg(feature = "parsing")]
David Tolnay203557a2017-12-27 23:59:33 -0500511use error::ParseError;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500512
513// Not public API.
David Tolnay1b752fb2017-12-26 21:41:39 -0500514#[cfg(feature = "parsing")]
David Tolnayc5ab8c62017-12-26 16:43:39 -0500515#[doc(hidden)]
516pub use error::parse_error;
Michael Layzell416724e2017-05-24 21:12:34 -0400517
David Tolnayccab0be2018-01-06 22:24:47 -0800518/// Parse tokens of source code into the chosen syntax tree node.
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700519///
520/// This is preferred over parsing a string because tokens are able to preserve
521/// information about where in the user's code they were originally written (the
522/// "span" of the token), possibly allowing the compiler to produce better error
523/// messages.
524///
David Tolnayccab0be2018-01-06 22:24:47 -0800525/// This function parses a `proc_macro::TokenStream` which is the type used for
526/// interop with the compiler in a procedural macro. To parse a
527/// `proc_macro2::TokenStream`, use [`syn::parse2`] instead.
528///
529/// [`syn::parse2`]: fn.parse2.html
530///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700531/// # Examples
532///
David Tolnaybcf26022017-12-25 22:10:52 -0500533/// ```rust
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700534/// extern crate proc_macro;
535/// use proc_macro::TokenStream;
536///
537/// extern crate syn;
538///
539/// #[macro_use]
540/// extern crate quote;
541///
542/// use syn::DeriveInput;
543///
David Tolnaybcf26022017-12-25 22:10:52 -0500544/// # const IGNORE_TOKENS: &str = stringify! {
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700545/// #[proc_macro_derive(MyMacro)]
David Tolnaybcf26022017-12-25 22:10:52 -0500546/// # };
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700547/// pub fn my_macro(input: TokenStream) -> TokenStream {
548/// // Parse the tokens into a syntax tree
549/// let ast: DeriveInput = syn::parse(input).unwrap();
550///
551/// // Build the output, possibly using quasi-quotation
552/// let expanded = quote! {
553/// /* ... */
554/// };
555///
David Tolnaybcf26022017-12-25 22:10:52 -0500556/// // Convert into a token stream and return it
557/// expanded.into()
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700558/// }
David Tolnaybcf26022017-12-25 22:10:52 -0500559/// #
560/// # fn main() {}
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700561/// ```
562#[cfg(feature = "parsing")]
563pub fn parse<T>(tokens: proc_macro::TokenStream) -> Result<T, ParseError>
David Tolnay51382052017-12-27 13:46:21 -0500564where
565 T: Synom,
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700566{
David Tolnay04c5dca2018-01-05 20:12:21 -0800567 parse2(tokens.into())
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700568}
569
David Tolnayccab0be2018-01-06 22:24:47 -0800570/// Parse a proc-macro2 token stream into the chosen syntax tree node.
571///
572/// This function parses a `proc_macro2::TokenStream` which is commonly useful
573/// when the input comes from a node of the Syn syntax tree, for example the tts
574/// of a [`Macro`] node. When in a procedural macro parsing the
575/// `proc_macro::TokenStream` provided by the compiler, use [`syn::parse`]
576/// instead.
577///
578/// [`Macro`]: struct.Macro.html
579/// [`syn::parse`]: fn.parse.html
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700580#[cfg(feature = "parsing")]
David Tolnay04c5dca2018-01-05 20:12:21 -0800581pub fn parse2<T>(tokens: proc_macro2::TokenStream) -> Result<T, ParseError>
David Tolnay51382052017-12-27 13:46:21 -0500582where
583 T: Synom,
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700584{
David Tolnay7c3e77d2018-01-06 17:42:53 -0800585 let buf = TokenBuffer::new2(tokens);
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700586 let result = T::parse(buf.begin());
587 let err = match result {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500588 Ok((t, rest)) => {
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700589 if rest.eof() {
590 return Ok(t);
591 } else if rest == buf.begin() {
592 // parsed nothing
593 ParseError::new("failed to parse anything")
594 } else {
595 ParseError::new("failed to parse all tokens")
David Tolnay55337722016-09-11 12:58:56 -0700596 }
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700597 }
598 Err(err) => err,
599 };
600 match T::description() {
Alex Crichtonc1b76f52017-07-06 15:04:24 -0700601 Some(s) => Err(ParseError::new(format!("failed to parse {}: {}", s, err))),
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700602 None => Err(err),
603 }
604}
Alex Crichton954046c2017-05-30 21:49:42 -0700605
David Tolnayccab0be2018-01-06 22:24:47 -0800606/// Parse a string of Rust code into the chosen syntax tree node.
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700607///
608/// # Examples
609///
610/// ```rust
611/// extern crate syn;
612/// #
David Tolnay9174b972017-11-09 22:27:50 -0800613/// #
614/// # type Result<T> = std::result::Result<T, Box<std::error::Error>>;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700615///
616/// use syn::Expr;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700617///
618/// fn run() -> Result<()> {
619/// let code = "assert_eq!(u8::max_value(), 255)";
620/// let expr = syn::parse_str::<Expr>(code)?;
621/// println!("{:#?}", expr);
622/// Ok(())
623/// }
624/// #
625/// # fn main() { run().unwrap() }
626/// ```
627#[cfg(feature = "parsing")]
628pub fn parse_str<T: Synom>(s: &str) -> Result<T, ParseError> {
David Tolnayffb1f4d2017-12-28 00:07:59 -0500629 match s.parse() {
David Tolnay04c5dca2018-01-05 20:12:21 -0800630 Ok(tts) => parse2(tts),
David Tolnayffb1f4d2017-12-28 00:07:59 -0500631 Err(_) => Err(ParseError::new("error while lexing input string")),
632 }
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700633}
Alex Crichton954046c2017-05-30 21:49:42 -0700634
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700635// FIXME the name parse_file makes it sound like you might pass in a path to a
636// file, rather than the content.
637/// Parse the content of a file of Rust code.
638///
639/// This is different from `syn::parse_str::<File>(content)` in two ways:
640///
641/// - It discards a leading byte order mark `\u{FEFF}` if the file has one.
642/// - It preserves the shebang line of the file, such as `#!/usr/bin/env rustx`.
643///
644/// If present, either of these would be an error using `from_str`.
645///
646/// # Examples
647///
648/// ```rust,no_run
649/// extern crate syn;
650/// #
David Tolnay9174b972017-11-09 22:27:50 -0800651/// #
652/// # type Result<T> = std::result::Result<T, Box<std::error::Error>>;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700653///
654/// use std::fs::File;
655/// use std::io::Read;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700656///
657/// fn run() -> Result<()> {
658/// let mut file = File::open("path/to/code.rs")?;
659/// let mut content = String::new();
660/// file.read_to_string(&mut content)?;
661///
662/// let ast = syn::parse_file(&content)?;
663/// if let Some(shebang) = ast.shebang {
664/// println!("{}", shebang);
665/// }
666/// println!("{} items", ast.items.len());
667///
668/// Ok(())
669/// }
670/// #
671/// # fn main() { run().unwrap() }
672/// ```
673#[cfg(all(feature = "parsing", feature = "full"))]
674pub fn parse_file(mut content: &str) -> Result<File, ParseError> {
675 // Strip the BOM if it is present
676 const BOM: &'static str = "\u{feff}";
677 if content.starts_with(BOM) {
678 content = &content[BOM.len()..];
David Tolnay35161ff2016-09-03 11:33:15 -0700679 }
Michael Layzell5e107ff2017-01-24 19:58:39 -0500680
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700681 let mut shebang = None;
682 if content.starts_with("#!") && !content.starts_with("#![") {
683 if let Some(idx) = content.find('\n') {
684 shebang = Some(content[..idx].to_string());
685 content = &content[idx..];
686 } else {
687 shebang = Some(content.to_string());
688 content = "";
689 }
Alex Crichton954046c2017-05-30 21:49:42 -0700690 }
David Tolnay0a8972b2017-02-27 02:10:01 -0800691
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700692 let mut file: File = parse_str(content)?;
693 file.shebang = shebang;
694 Ok(file)
Michael Layzell5e107ff2017-01-24 19:58:39 -0500695}
Alex Crichton259ee532017-07-14 06:51:02 -0700696
David Tolnaydace3f12018-01-06 21:33:29 -0800697/// Quasi-quotation macro that accepts input like the [`quote!`] macro but uses
698/// type inference to figure out a return type for those tokens.
699///
700/// [`quote!`]: https://docs.rs/quote/0.4/quote/index.html
701///
702/// The return type can be any syntax tree node that implements the [`Synom`]
703/// trait.
704///
705/// [`Synom`]: synom/trait.Synom.html
706///
707/// ```
708/// #[macro_use]
709/// extern crate syn;
710///
711/// #[macro_use]
712/// extern crate quote;
713///
714/// use syn::Stmt;
715///
716/// fn main() {
717/// let name = quote!(v);
718/// let ty = quote!(u8);
719///
720/// let stmt: Stmt = parse_quote! {
721/// let #name: #ty = Default::default();
722/// };
723///
724/// println!("{:#?}", stmt);
725/// }
726/// ```
727///
728/// # Example
729///
730/// The following helper function adds a bound `T: HeapSize` to every type
731/// parameter `T` in the input generics.
732///
733/// ```
734/// # #[macro_use]
735/// # extern crate syn;
736/// #
737/// # #[macro_use]
738/// # extern crate quote;
739/// #
740/// # use syn::{Generics, GenericParam};
741/// #
742/// // Add a bound `T: HeapSize` to every type parameter T.
743/// fn add_trait_bounds(mut generics: Generics) -> Generics {
744/// for param in &mut generics.params {
745/// if let GenericParam::Type(ref mut type_param) = *param {
746/// type_param.bounds.push(parse_quote!(HeapSize));
747/// }
748/// }
749/// generics
750/// }
751/// #
752/// # fn main() {}
753/// ```
754///
755/// # Panics
756///
757/// Panics if the tokens fail to parse as the expected syntax tree type. The
758/// caller is responsible for ensuring that the input tokens are syntactically
759/// valid.
David Tolnay01cc0202018-01-02 11:13:07 -0800760#[cfg(all(feature = "parsing", feature = "printing"))]
761#[macro_export]
762macro_rules! parse_quote {
763 ($($tt:tt)*) => {
764 ::std::result::Result::unwrap(
David Tolnaydace3f12018-01-06 21:33:29 -0800765 $crate::parse2(
David Tolnay01cc0202018-01-02 11:13:07 -0800766 ::std::convert::Into::into(
767 quote!($($tt)*))))
768 };
769}
770
David Tolnay3cfd1d32018-01-03 00:22:08 -0800771#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
Alex Crichton259ee532017-07-14 06:51:02 -0700772struct TokensOrDefault<'a, T: 'a>(&'a Option<T>);
773
David Tolnay3cfd1d32018-01-03 00:22:08 -0800774#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
Alex Crichton259ee532017-07-14 06:51:02 -0700775impl<'a, T> quote::ToTokens for TokensOrDefault<'a, T>
David Tolnay51382052017-12-27 13:46:21 -0500776where
777 T: quote::ToTokens + Default,
Alex Crichton259ee532017-07-14 06:51:02 -0700778{
779 fn to_tokens(&self, tokens: &mut quote::Tokens) {
780 match *self.0 {
781 Some(ref t) => t.to_tokens(tokens),
782 None => T::default().to_tokens(tokens),
783 }
784 }
785}