blob: b32d67ca12a50d5c19d344ac6f3b332417001c9c [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]
David Tolnay87003d02018-05-20 19:45:13 -070071//! syn = "0.14"
72//! quote = "0.6"
David Tolnay5e84e972018-01-05 17:51:06 -080073//!
74//! [lib]
75//! proc-macro = true
76//! ```
77//!
78//! ```rust
David Tolnay9b00f652018-09-01 10:31:02 -070079//! # extern crate proc_macro;
80//! # extern crate quote;
81//! # extern crate syn;
82//! #
David Tolnay5e84e972018-01-05 17:51:06 -080083//! use proc_macro::TokenStream;
David Tolnay9b00f652018-09-01 10:31:02 -070084//! use quote::quote;
David Tolnay5e84e972018-01-05 17:51:06 -080085//! use syn::DeriveInput;
86//!
87//! # const IGNORE_TOKENS: &str = stringify! {
88//! #[proc_macro_derive(MyMacro)]
89//! # };
90//! pub fn my_macro(input: TokenStream) -> TokenStream {
91//! // Parse the input tokens into a syntax tree
92//! let input: DeriveInput = syn::parse(input).unwrap();
93//!
94//! // Build the output, possibly using quasi-quotation
95//! let expanded = quote! {
96//! // ...
97//! };
98//!
99//! // Hand the output tokens back to the compiler
100//! expanded.into()
101//! }
102//! #
103//! # fn main() {}
104//! ```
105//!
106//! The [`heapsize`] example directory shows a complete working Macros 1.1
107//! implementation of a custom derive. It works on any Rust compiler \>=1.15.0.
108//! The example derives a `HeapSize` trait which computes an estimate of the
109//! amount of heap memory owned by a value.
110//!
111//! [`heapsize`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize
112//!
113//! ```rust
114//! pub trait HeapSize {
115//! /// Total number of bytes of heap memory owned by `self`.
116//! fn heap_size_of_children(&self) -> usize;
117//! }
118//! ```
119//!
120//! The custom derive allows users to write `#[derive(HeapSize)]` on data
121//! structures in their program.
122//!
123//! ```rust
124//! # const IGNORE_TOKENS: &str = stringify! {
125//! #[derive(HeapSize)]
126//! # };
127//! struct Demo<'a, T: ?Sized> {
128//! a: Box<T>,
129//! b: u8,
130//! c: &'a str,
131//! d: String,
132//! }
133//! ```
134//!
135//! ## Spans and error reporting
136//!
137//! The [`heapsize2`] example directory is an extension of the `heapsize`
138//! example that demonstrates some of the hygiene and error reporting properties
139//! of Macros 2.0. This example currently requires a nightly Rust compiler
140//! \>=1.24.0-nightly but we are working to stabilize all of the APIs involved.
141//!
142//! [`heapsize2`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize2
143//!
144//! The token-based procedural macro API provides great control over where the
145//! compiler's error messages are displayed in user code. Consider the error the
146//! user sees if one of their field types does not implement `HeapSize`.
147//!
148//! ```rust
149//! # const IGNORE_TOKENS: &str = stringify! {
150//! #[derive(HeapSize)]
151//! # };
152//! struct Broken {
153//! ok: String,
154//! bad: std::thread::Thread,
155//! }
156//! ```
157//!
158//! In the Macros 1.1 string-based procedural macro world, the resulting error
159//! would point unhelpfully to the invocation of the derive macro and not to the
160//! actual problematic field.
161//!
162//! ```text
163//! error[E0599]: no method named `heap_size_of_children` found for type `std::thread::Thread` in the current scope
164//! --> src/main.rs:4:10
165//! |
166//! 4 | #[derive(HeapSize)]
167//! | ^^^^^^^^
168//! ```
169//!
170//! By tracking span information all the way through the expansion of a
171//! procedural macro as shown in the `heapsize2` example, token-based macros in
172//! Syn are able to trigger errors that directly pinpoint the source of the
173//! problem.
174//!
175//! ```text
176//! error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
177//! --> src/main.rs:7:5
178//! |
179//! 7 | bad: std::thread::Thread,
David Tolnayefff2ff2018-01-07 11:49:52 -0800180//! | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `Thread`
David Tolnay5e84e972018-01-05 17:51:06 -0800181//! ```
182//!
183//! ## Parsing a custom syntax using combinators
184//!
185//! The [`lazy-static`] example directory shows the implementation of a
186//! `functionlike!(...)` procedural macro in which the input tokens are parsed
187//! using [`nom`]-style parser combinators.
188//!
189//! [`lazy-static`]: https://github.com/dtolnay/syn/tree/master/examples/lazy-static
190//! [`nom`]: https://github.com/Geal/nom
191//!
192//! The example reimplements the popular `lazy_static` crate from crates.io as a
193//! procedural macro.
194//!
195//! ```
196//! # macro_rules! lazy_static {
197//! # ($($tt:tt)*) => {}
198//! # }
199//! #
200//! lazy_static! {
201//! static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
202//! }
203//! ```
204//!
205//! The implementation shows how to trigger custom warnings and error messages
206//! on the macro input.
207//!
208//! ```text
209//! warning: come on, pick a more creative name
210//! --> src/main.rs:10:16
211//! |
212//! 10 | static ref FOO: String = "lazy_static".to_owned();
213//! | ^^^
214//! ```
215//!
216//! ## Debugging
217//!
218//! When developing a procedural macro it can be helpful to look at what the
219//! generated code looks like. Use `cargo rustc -- -Zunstable-options
220//! --pretty=expanded` or the [`cargo expand`] subcommand.
221//!
David Tolnay324db2d2018-01-07 11:51:09 -0800222//! [`cargo expand`]: https://github.com/dtolnay/cargo-expand
David Tolnay5e84e972018-01-05 17:51:06 -0800223//!
224//! To show the expanded code for some crate that uses your procedural macro,
225//! run `cargo expand` from that crate. To show the expanded code for one of
226//! your own test cases, run `cargo expand --test the_test_case` where the last
227//! argument is the name of the test file without the `.rs` extension.
228//!
229//! This write-up by Brandon W Maister discusses debugging in more detail:
230//! [Debugging Rust's new Custom Derive system][debugging].
231//!
232//! [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
233//!
234//! ## Optional features
235//!
236//! Syn puts a lot of functionality behind optional features in order to
237//! optimize compile time for the most common use cases. The following features
238//! are available.
239//!
240//! - **`derive`** *(enabled by default)* — Data structures for representing the
241//! possible input to a custom derive, including structs and enums and types.
242//! - **`full`** — Data structures for representing the syntax tree of all valid
243//! Rust source code, including items and expressions.
244//! - **`parsing`** *(enabled by default)* — Ability to parse input tokens into
245//! a syntax tree node of a chosen type.
246//! - **`printing`** *(enabled by default)* — Ability to print a syntax tree
247//! node as tokens of Rust source code.
248//! - **`visit`** — Trait for traversing a syntax tree.
David Tolnay34981cf2018-01-06 16:22:35 -0800249//! - **`visit-mut`** — Trait for traversing and mutating in place a syntax
David Tolnay5e84e972018-01-05 17:51:06 -0800250//! tree.
251//! - **`fold`** — Trait for transforming an owned syntax tree.
252//! - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
253//! types.
254//! - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree
255//! types.
hcpl4b72a382018-04-04 14:50:24 +0300256//! - **`proc-macro`** *(enabled by default)* — Runtime dependency on the
257//! dynamic library libproc_macro from rustc toolchain.
David Tolnay5e84e972018-01-05 17:51:06 -0800258
David Tolnay4cf7db82018-01-07 15:22:01 -0800259// Syn types in rustdoc of other crates get linked to here.
David Tolnaye6ec9e02018-08-21 21:32:03 -0400260#![doc(html_root_url = "https://docs.rs/syn/0.14.9")]
David Tolnay34071ba2018-05-20 20:00:41 -0700261#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
David Tolnay34071ba2018-05-20 20:00:41 -0700262// Ignored clippy lints.
David Tolnay94d2b792018-04-29 12:26:10 -0700263#![cfg_attr(
264 feature = "cargo-clippy",
265 allow(
David Tolnay4831ac62018-08-30 21:04:16 -0700266 block_in_if_condition_stmt,
David Tolnay0cec3e62018-07-21 09:08:30 -0700267 const_static_lifetime,
David Tolnay24b079d2018-08-27 08:28:10 -0700268 cyclomatic_complexity,
David Tolnay0cec3e62018-07-21 09:08:30 -0700269 doc_markdown,
David Tolnay24b079d2018-08-27 08:28:10 -0700270 eval_order_dependence,
David Tolnay0cec3e62018-07-21 09:08:30 -0700271 large_enum_variant,
272 match_bool,
273 redundant_closure,
274 needless_pass_by_value,
275 redundant_field_names,
276 trivially_copy_pass_by_ref
David Tolnay94d2b792018-04-29 12:26:10 -0700277 )
278)]
David Tolnay34071ba2018-05-20 20:00:41 -0700279// Ignored clippy_pedantic lints.
280#![cfg_attr(
281 feature = "cargo-clippy",
282 allow(
David Tolnay0cec3e62018-07-21 09:08:30 -0700283 cast_possible_truncation,
284 cast_possible_wrap,
David Tolnayb1617752018-08-24 21:16:33 -0400285 empty_enum,
David Tolnay0cec3e62018-07-21 09:08:30 -0700286 if_not_else,
287 indexing_slicing,
288 items_after_statements,
David Tolnay151f92f2018-08-14 22:44:53 -0700289 shadow_unrelated,
David Tolnay0cec3e62018-07-21 09:08:30 -0700290 similar_names,
291 single_match_else,
292 stutter,
293 unseparated_literal_suffix,
294 use_self,
295 used_underscore_binding
David Tolnay34071ba2018-05-20 20:00:41 -0700296 )
297)]
David Tolnayad2836d2017-04-20 10:11:43 -0700298
David Tolnay278f9e32018-08-14 22:41:11 -0700299#[cfg(all(
300 not(all(target_arch = "wasm32", target_os = "unknown")),
301 feature = "proc-macro"
302))]
David Tolnay51382052017-12-27 13:46:21 -0500303extern crate proc_macro;
David Tolnay94d2b792018-04-29 12:26:10 -0700304extern crate proc_macro2;
David Tolnay570695e2017-06-03 16:15:13 -0700305extern crate unicode_xid;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700306
David Tolnay1cf80912017-12-31 18:35:12 -0500307#[cfg(feature = "printing")]
David Tolnay87d0b442016-09-04 11:52:12 -0700308extern crate quote;
309
Alex Crichton62a0a592017-05-22 13:58:53 -0700310#[macro_use]
311mod macros;
312
David Tolnay734079e2018-09-01 02:03:37 -0700313// Not public API.
David Tolnay852bff72018-08-27 08:24:02 -0700314#[cfg(feature = "parsing")]
David Tolnay734079e2018-09-01 02:03:37 -0700315#[doc(hidden)]
David Tolnay852bff72018-08-27 08:24:02 -0700316#[macro_use]
David Tolnay734079e2018-09-01 02:03:37 -0700317pub mod group;
David Tolnay852bff72018-08-27 08:24:02 -0700318
David Tolnayc5ab8c62017-12-26 16:43:39 -0500319#[macro_use]
David Tolnay32954ef2017-12-26 22:43:16 -0500320pub mod token;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500321
David Tolnay4fb71232018-08-25 23:14:50 -0400322mod ident;
323pub use ident::Ident;
David Tolnaye303b7c2018-05-20 16:46:35 -0700324
David Tolnay3cfd1d32018-01-03 00:22:08 -0800325#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700326mod attr;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800327#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayaaadd782018-01-06 22:58:13 -0800328pub use attr::{AttrStyle, Attribute, Meta, MetaList, MetaNameValue, NestedMeta};
David Tolnay35161ff2016-09-03 11:33:15 -0700329
David Tolnay3cfd1d32018-01-03 00:22:08 -0800330#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf38cdf62016-09-23 19:07:09 -0700331mod data;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800332#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700333pub use data::{
334 Field, Fields, FieldsNamed, FieldsUnnamed, Variant, VisCrate, VisPublic, VisRestricted,
335 Visibility,
336};
David Tolnayf38cdf62016-09-23 19:07:09 -0700337
David Tolnay3cfd1d32018-01-03 00:22:08 -0800338#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700339mod expr;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800340#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700341pub use expr::{
David Tolnay02a9c6f2018-08-24 18:58:45 -0400342 Expr, ExprArray, ExprAssign, ExprAssignOp, ExprAsync, ExprBinary, ExprBlock, ExprBox,
343 ExprBreak, ExprCall, ExprCast, ExprClosure, ExprContinue, ExprField, ExprForLoop, ExprGroup,
344 ExprIf, ExprIfLet, ExprInPlace, ExprIndex, ExprLit, ExprLoop, ExprMacro, ExprMatch,
345 ExprMethodCall, ExprParen, ExprPath, ExprRange, ExprReference, ExprRepeat, ExprReturn,
346 ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprType, ExprUnary, ExprUnsafe, ExprVerbatim,
347 ExprWhile, ExprWhileLet, ExprYield, Index, Member,
David Tolnayb57c8492018-05-05 00:32:04 -0700348};
Michael Layzell734adb42017-06-07 16:58:31 -0400349
350#[cfg(feature = "full")]
David Tolnayb57c8492018-05-05 00:32:04 -0700351pub use expr::{
352 Arm, Block, FieldPat, FieldValue, GenericMethodArgument, Label, Local, MethodTurbofish, Pat,
353 PatBox, PatIdent, PatLit, PatMacro, PatPath, PatRange, PatRef, PatSlice, PatStruct, PatTuple,
354 PatTupleStruct, PatVerbatim, PatWild, RangeLimits, Stmt,
355};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700356
David Tolnay3cfd1d32018-01-03 00:22:08 -0800357#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700358mod generics;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800359#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700360pub use generics::{
361 BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeDef, PredicateEq,
362 PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound,
363 WhereClause, WherePredicate,
364};
David Tolnay278f9e32018-08-14 22:41:11 -0700365#[cfg(all(
366 any(feature = "full", feature = "derive"),
367 feature = "printing"
368))]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800369pub use generics::{ImplGenerics, Turbofish, TypeGenerics};
David Tolnay35161ff2016-09-03 11:33:15 -0700370
David Tolnayf38cdf62016-09-23 19:07:09 -0700371#[cfg(feature = "full")]
David Tolnayb79ee962016-09-04 09:39:20 -0700372mod item;
David Tolnayf38cdf62016-09-23 19:07:09 -0700373#[cfg(feature = "full")]
David Tolnayb57c8492018-05-05 00:32:04 -0700374pub use item::{
David Tolnay435c1782018-08-24 16:15:44 -0400375 ArgCaptured, ArgSelf, ArgSelfRef, FnArg, FnDecl, ForeignItem, ForeignItemFn, ForeignItemMacro,
376 ForeignItemStatic, ForeignItemType, ForeignItemVerbatim, ImplItem, ImplItemConst,
David Tolnaybb82ef02018-08-24 20:15:45 -0400377 ImplItemExistential, ImplItemMacro, ImplItemMethod, ImplItemType, ImplItemVerbatim, Item,
378 ItemConst, ItemEnum, ItemExistential, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl,
David Tolnayc6b04dd2018-08-30 23:22:51 -0700379 ItemMacro, ItemMacro2, ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType,
380 ItemUnion, ItemUse, ItemVerbatim, MethodSig, TraitItem, TraitItemConst, TraitItemMacro,
381 TraitItemMethod, TraitItemType, TraitItemVerbatim, UseGlob, UseGroup, UseName, UsePath,
382 UseRename, UseTree,
David Tolnayb57c8492018-05-05 00:32:04 -0700383};
David Tolnay35161ff2016-09-03 11:33:15 -0700384
David Tolnay631cb8c2016-11-10 17:16:41 -0800385#[cfg(feature = "full")]
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700386mod file;
David Tolnay631cb8c2016-11-10 17:16:41 -0800387#[cfg(feature = "full")]
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700388pub use file::File;
David Tolnay631cb8c2016-11-10 17:16:41 -0800389
David Tolnay63e3dee2017-06-03 20:13:17 -0700390mod lifetime;
391pub use lifetime::Lifetime;
392
David Tolnay3cfd1d32018-01-03 00:22:08 -0800393#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700394mod lit;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800395#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700396pub use lit::{
397 FloatSuffix, IntSuffix, Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr,
398 LitVerbatim, StrStyle,
399};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700400
David Tolnay3cfd1d32018-01-03 00:22:08 -0800401#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700402mod mac;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800403#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayab919512017-12-30 23:31:51 -0500404pub use mac::{Macro, MacroDelimiter};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700405
David Tolnay3cfd1d32018-01-03 00:22:08 -0800406#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay0e837402016-12-22 17:25:55 -0500407mod derive;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800408#[cfg(feature = "derive")]
David Tolnaye3d41b72017-12-31 15:24:00 -0500409pub use derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
David Tolnayf38cdf62016-09-23 19:07:09 -0700410
David Tolnay3cfd1d32018-01-03 00:22:08 -0800411#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay3cb23a92016-10-07 23:02:21 -0700412mod op;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800413#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay3cb23a92016-10-07 23:02:21 -0700414pub use op::{BinOp, UnOp};
415
David Tolnay3cfd1d32018-01-03 00:22:08 -0800416#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700417mod ty;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800418#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700419pub use ty::{
420 Abi, BareFnArg, BareFnArgName, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,
421 TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference,
422 TypeSlice, TypeTraitObject, TypeTuple, TypeVerbatim,
423};
David Tolnay056de302018-01-05 14:29:05 -0800424
425#[cfg(any(feature = "full", feature = "derive"))]
426mod path;
David Tolnay278f9e32018-08-14 22:41:11 -0700427#[cfg(all(
428 any(feature = "full", feature = "derive"),
429 feature = "printing"
430))]
David Tolnay94d2b792018-04-29 12:26:10 -0700431pub use path::PathTokens;
David Tolnay056de302018-01-05 14:29:05 -0800432#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700433pub use path::{
434 AngleBracketedGenericArguments, Binding, GenericArgument, ParenthesizedGenericArguments, Path,
435 PathArguments, PathSegment, QSelf,
436};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700437
David Tolnay1b752fb2017-12-26 21:41:39 -0500438#[cfg(feature = "parsing")]
David Tolnaydfc886b2018-01-06 08:03:09 -0800439pub mod buffer;
David Tolnay94d304f2018-08-30 23:43:53 -0700440#[cfg(feature = "parsing")]
441pub mod ext;
David Tolnay94d2b792018-04-29 12:26:10 -0700442pub mod punctuated;
David Tolnay3779bb72018-08-26 18:46:07 -0700443#[cfg(all(
444 any(feature = "full", feature = "derive"),
445 feature = "extra-traits"
446))]
David Tolnaye0824032017-12-27 15:25:56 -0500447mod tt;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500448
David Tolnaye83ef5a2018-01-11 15:18:36 -0800449// Not public API except the `parse_quote!` macro.
David Tolnay491680a2018-01-23 00:34:40 -0800450#[cfg(feature = "parsing")]
David Tolnaye83ef5a2018-01-11 15:18:36 -0800451#[doc(hidden)]
452pub mod parse_quote;
453
David Tolnay4d942b42018-01-02 22:14:04 -0800454#[cfg(all(feature = "parsing", feature = "printing"))]
David Tolnayf790b612017-12-31 18:46:57 -0500455pub mod spanned;
456
Nika Layzella6f46c42017-10-26 15:26:16 -0400457mod gen {
David Tolnayded2d682018-01-06 18:53:53 -0800458 /// Syntax tree traversal to walk a shared borrow of a syntax tree.
459 ///
460 /// Each method of the [`Visit`] trait is a hook that can be overridden to
461 /// customize the behavior when visiting the corresponding type of node. By
462 /// default, every method recursively visits the substructure of the input
463 /// by invoking the right visitor method of each of its fields.
464 ///
465 /// [`Visit`]: trait.Visit.html
466 ///
467 /// ```rust
468 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
469 /// #
470 /// pub trait Visit<'ast> {
471 /// /* ... */
472 ///
473 /// fn visit_expr_binary(&mut self, node: &'ast ExprBinary) {
474 /// for attr in &node.attrs {
475 /// self.visit_attribute(attr);
476 /// }
477 /// self.visit_expr(&*node.left);
478 /// self.visit_bin_op(&node.op);
479 /// self.visit_expr(&*node.right);
480 /// }
481 ///
482 /// /* ... */
483 /// # fn visit_attribute(&mut self, node: &'ast Attribute);
484 /// # fn visit_expr(&mut self, node: &'ast Expr);
485 /// # fn visit_bin_op(&mut self, node: &'ast BinOp);
486 /// }
487 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800488 ///
489 /// *This module is available if Syn is built with the `"visit"` feature.*
Nika Layzella6f46c42017-10-26 15:26:16 -0400490 #[cfg(feature = "visit")]
491 pub mod visit;
David Tolnay55337722016-09-11 12:58:56 -0700492
David Tolnayded2d682018-01-06 18:53:53 -0800493 /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in
494 /// place.
495 ///
496 /// Each method of the [`VisitMut`] trait is a hook that can be overridden
497 /// to customize the behavior when mutating the corresponding type of node.
498 /// By default, every method recursively visits the substructure of the
499 /// input by invoking the right visitor method of each of its fields.
500 ///
501 /// [`VisitMut`]: trait.VisitMut.html
502 ///
503 /// ```rust
504 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
505 /// #
506 /// pub trait VisitMut {
507 /// /* ... */
508 ///
509 /// fn visit_expr_binary_mut(&mut self, node: &mut ExprBinary) {
510 /// for attr in &mut node.attrs {
511 /// self.visit_attribute_mut(attr);
512 /// }
513 /// self.visit_expr_mut(&mut *node.left);
514 /// self.visit_bin_op_mut(&mut node.op);
515 /// self.visit_expr_mut(&mut *node.right);
516 /// }
517 ///
518 /// /* ... */
519 /// # fn visit_attribute_mut(&mut self, node: &mut Attribute);
520 /// # fn visit_expr_mut(&mut self, node: &mut Expr);
521 /// # fn visit_bin_op_mut(&mut self, node: &mut BinOp);
522 /// }
523 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800524 ///
525 /// *This module is available if Syn is built with the `"visit-mut"`
526 /// feature.*
David Tolnay9df02c42018-01-06 13:52:48 -0800527 #[cfg(feature = "visit-mut")]
Nika Layzella6f46c42017-10-26 15:26:16 -0400528 pub mod visit_mut;
Nika Layzell27726662017-10-24 23:16:35 -0400529
David Tolnayded2d682018-01-06 18:53:53 -0800530 /// Syntax tree traversal to transform the nodes of an owned syntax tree.
531 ///
532 /// Each method of the [`Fold`] trait is a hook that can be overridden to
533 /// customize the behavior when transforming the corresponding type of node.
534 /// By default, every method recursively visits the substructure of the
535 /// input by invoking the right visitor method of each of its fields.
536 ///
537 /// [`Fold`]: trait.Fold.html
538 ///
539 /// ```rust
540 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
541 /// #
542 /// pub trait Fold {
543 /// /* ... */
544 ///
545 /// fn fold_expr_binary(&mut self, node: ExprBinary) -> ExprBinary {
546 /// ExprBinary {
547 /// attrs: node.attrs
548 /// .into_iter()
549 /// .map(|attr| self.fold_attribute(attr))
550 /// .collect(),
551 /// left: Box::new(self.fold_expr(*node.left)),
552 /// op: self.fold_bin_op(node.op),
553 /// right: Box::new(self.fold_expr(*node.right)),
554 /// }
555 /// }
556 ///
557 /// /* ... */
558 /// # fn fold_attribute(&mut self, node: Attribute) -> Attribute;
559 /// # fn fold_expr(&mut self, node: Expr) -> Expr;
560 /// # fn fold_bin_op(&mut self, node: BinOp) -> BinOp;
561 /// }
562 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800563 ///
564 /// *This module is available if Syn is built with the `"fold"` feature.*
Nika Layzella6f46c42017-10-26 15:26:16 -0400565 #[cfg(feature = "fold")]
566 pub mod fold;
David Tolnayf60f4262017-12-28 19:17:58 -0500567
David Tolnay0a0d78c2018-01-05 15:24:01 -0800568 #[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf60f4262017-12-28 19:17:58 -0500569 #[path = "../gen_helper.rs"]
570 mod helper;
Nika Layzella6f46c42017-10-26 15:26:16 -0400571}
572pub use gen::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100573
David Tolnay456c9822018-08-25 08:09:46 -0400574// Not public API.
575#[doc(hidden)]
576pub mod export;
577
David Tolnay776f8e02018-08-24 22:32:10 -0400578#[cfg(feature = "parsing")]
David Tolnayb6254182018-08-25 08:44:54 -0400579mod lookahead;
580
581#[cfg(feature = "parsing")]
582pub mod parse;
583
David Tolnay776f8e02018-08-24 22:32:10 -0400584mod span;
585
David Tolnay64023912018-08-31 09:51:12 -0700586#[cfg(all(
587 any(feature = "full", feature = "derive"),
588 feature = "printing"
589))]
590mod print;
591
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700592////////////////////////////////////////////////////////////////////////////////
593
David Tolnayaa77a852018-08-31 11:15:10 -0700594#[cfg(any(feature = "parsing", feature = "full", feature = "derive"))]
David Tolnay94f06632018-08-31 10:17:17 -0700595#[allow(non_camel_case_types)]
David Tolnay10951d52018-08-31 10:27:39 -0700596struct private;
David Tolnay94f06632018-08-31 10:17:17 -0700597
598////////////////////////////////////////////////////////////////////////////////
599
David Tolnay55337722016-09-11 12:58:56 -0700600#[cfg(feature = "parsing")]
David Tolnayb6254182018-08-25 08:44:54 -0400601mod error;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500602#[cfg(feature = "parsing")]
David Tolnayad4b2472018-08-25 08:25:24 -0400603use error::Error;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500604
David Tolnayccab0be2018-01-06 22:24:47 -0800605/// Parse tokens of source code into the chosen syntax tree node.
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700606///
607/// This is preferred over parsing a string because tokens are able to preserve
608/// information about where in the user's code they were originally written (the
609/// "span" of the token), possibly allowing the compiler to produce better error
610/// messages.
611///
David Tolnayccab0be2018-01-06 22:24:47 -0800612/// This function parses a `proc_macro::TokenStream` which is the type used for
613/// interop with the compiler in a procedural macro. To parse a
614/// `proc_macro2::TokenStream`, use [`syn::parse2`] instead.
615///
616/// [`syn::parse2`]: fn.parse2.html
617///
hcpl4b72a382018-04-04 14:50:24 +0300618/// *This function is available if Syn is built with both the `"parsing"` and
619/// `"proc-macro"` features.*
David Tolnay461d98e2018-01-07 11:07:19 -0800620///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700621/// # Examples
622///
David Tolnaybcf26022017-12-25 22:10:52 -0500623/// ```rust
David Tolnay9b00f652018-09-01 10:31:02 -0700624/// # extern crate proc_macro;
625/// # extern crate quote;
626/// # extern crate syn;
627/// #
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700628/// use proc_macro::TokenStream;
David Tolnay9b00f652018-09-01 10:31:02 -0700629/// use quote::quote;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700630/// use syn::DeriveInput;
631///
David Tolnaybcf26022017-12-25 22:10:52 -0500632/// # const IGNORE_TOKENS: &str = stringify! {
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700633/// #[proc_macro_derive(MyMacro)]
David Tolnaybcf26022017-12-25 22:10:52 -0500634/// # };
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700635/// pub fn my_macro(input: TokenStream) -> TokenStream {
636/// // Parse the tokens into a syntax tree
637/// let ast: DeriveInput = syn::parse(input).unwrap();
638///
639/// // Build the output, possibly using quasi-quotation
640/// let expanded = quote! {
641/// /* ... */
642/// };
643///
David Tolnaybcf26022017-12-25 22:10:52 -0500644/// // Convert into a token stream and return it
645/// expanded.into()
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700646/// }
David Tolnaybcf26022017-12-25 22:10:52 -0500647/// #
648/// # fn main() {}
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700649/// ```
David Tolnay278f9e32018-08-14 22:41:11 -0700650#[cfg(all(
651 not(all(target_arch = "wasm32", target_os = "unknown")),
652 feature = "parsing",
653 feature = "proc-macro"
654))]
David Tolnaye82a2b12018-08-30 16:31:10 -0700655pub fn parse<T: parse::Parse>(tokens: proc_macro::TokenStream) -> Result<T, Error> {
David Tolnay80a914f2018-08-30 23:49:53 -0700656 parse::Parser::parse(T::parse, tokens)
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700657}
658
David Tolnayccab0be2018-01-06 22:24:47 -0800659/// Parse a proc-macro2 token stream into the chosen syntax tree node.
660///
661/// This function parses a `proc_macro2::TokenStream` which is commonly useful
662/// when the input comes from a node of the Syn syntax tree, for example the tts
663/// of a [`Macro`] node. When in a procedural macro parsing the
664/// `proc_macro::TokenStream` provided by the compiler, use [`syn::parse`]
665/// instead.
666///
667/// [`Macro`]: struct.Macro.html
668/// [`syn::parse`]: fn.parse.html
David Tolnay461d98e2018-01-07 11:07:19 -0800669///
670/// *This function is available if Syn is built with the `"parsing"` feature.*
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700671#[cfg(feature = "parsing")]
David Tolnaye82a2b12018-08-30 16:31:10 -0700672pub fn parse2<T: parse::Parse>(tokens: proc_macro2::TokenStream) -> Result<T, Error> {
David Tolnay80a914f2018-08-30 23:49:53 -0700673 parse::Parser::parse2(T::parse, tokens)
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700674}
Alex Crichton954046c2017-05-30 21:49:42 -0700675
David Tolnayccab0be2018-01-06 22:24:47 -0800676/// Parse a string of Rust code into the chosen syntax tree node.
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700677///
David Tolnay461d98e2018-01-07 11:07:19 -0800678/// *This function is available if Syn is built with the `"parsing"` feature.*
679///
David Tolnay3f5b06f2018-01-11 21:02:00 -0800680/// # Hygiene
681///
682/// Every span in the resulting syntax tree will be set to resolve at the macro
683/// call site.
684///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700685/// # Examples
686///
687/// ```rust
David Tolnay9b00f652018-09-01 10:31:02 -0700688/// # extern crate syn;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700689/// #
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700690/// use syn::Expr;
David Tolnay9b00f652018-09-01 10:31:02 -0700691/// use syn::parse::Result;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700692///
693/// fn run() -> Result<()> {
694/// let code = "assert_eq!(u8::max_value(), 255)";
695/// let expr = syn::parse_str::<Expr>(code)?;
696/// println!("{:#?}", expr);
697/// Ok(())
698/// }
699/// #
700/// # fn main() { run().unwrap() }
701/// ```
702#[cfg(feature = "parsing")]
David Tolnaye82a2b12018-08-30 16:31:10 -0700703pub fn parse_str<T: parse::Parse>(s: &str) -> Result<T, Error> {
David Tolnay80a914f2018-08-30 23:49:53 -0700704 parse::Parser::parse_str(T::parse, s)
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700705}
Alex Crichton954046c2017-05-30 21:49:42 -0700706
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700707// FIXME the name parse_file makes it sound like you might pass in a path to a
708// file, rather than the content.
709/// Parse the content of a file of Rust code.
710///
711/// This is different from `syn::parse_str::<File>(content)` in two ways:
712///
713/// - It discards a leading byte order mark `\u{FEFF}` if the file has one.
714/// - It preserves the shebang line of the file, such as `#!/usr/bin/env rustx`.
715///
716/// If present, either of these would be an error using `from_str`.
717///
Christopher Serr9727ef22018-02-03 16:42:12 +0100718/// *This function is available if Syn is built with the `"parsing"` and `"full"` features.*
David Tolnay461d98e2018-01-07 11:07:19 -0800719///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700720/// # Examples
721///
722/// ```rust,no_run
David Tolnay9b00f652018-09-01 10:31:02 -0700723/// # extern crate syn;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700724/// #
David Tolnay9b00f652018-09-01 10:31:02 -0700725/// use std::error::Error;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700726/// use std::fs::File;
727/// use std::io::Read;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700728///
David Tolnay9b00f652018-09-01 10:31:02 -0700729/// fn run() -> Result<(), Box<Error>> {
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700730/// let mut file = File::open("path/to/code.rs")?;
731/// let mut content = String::new();
732/// file.read_to_string(&mut content)?;
733///
734/// let ast = syn::parse_file(&content)?;
735/// if let Some(shebang) = ast.shebang {
736/// println!("{}", shebang);
737/// }
738/// println!("{} items", ast.items.len());
739///
740/// Ok(())
741/// }
742/// #
743/// # fn main() { run().unwrap() }
744/// ```
745#[cfg(all(feature = "parsing", feature = "full"))]
David Tolnayad4b2472018-08-25 08:25:24 -0400746pub fn parse_file(mut content: &str) -> Result<File, Error> {
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700747 // Strip the BOM if it is present
748 const BOM: &'static str = "\u{feff}";
749 if content.starts_with(BOM) {
750 content = &content[BOM.len()..];
David Tolnay35161ff2016-09-03 11:33:15 -0700751 }
Michael Layzell5e107ff2017-01-24 19:58:39 -0500752
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700753 let mut shebang = None;
754 if content.starts_with("#!") && !content.starts_with("#![") {
755 if let Some(idx) = content.find('\n') {
756 shebang = Some(content[..idx].to_string());
757 content = &content[idx..];
758 } else {
759 shebang = Some(content.to_string());
760 content = "";
761 }
Alex Crichton954046c2017-05-30 21:49:42 -0700762 }
David Tolnay0a8972b2017-02-27 02:10:01 -0800763
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700764 let mut file: File = parse_str(content)?;
765 file.shebang = shebang;
766 Ok(file)
Michael Layzell5e107ff2017-01-24 19:58:39 -0500767}
Alex Crichton259ee532017-07-14 06:51:02 -0700768
David Tolnayd641ee32018-08-30 17:11:09 -0700769/// Parse the input TokenStream of a macro, triggering a compile error if the
770/// tokens fail to parse.
771///
772/// # Intended usage
773///
774/// ```rust
775/// # extern crate proc_macro;
776/// # extern crate syn;
777/// #
778/// use proc_macro::TokenStream;
779/// use syn::parse_macro_input;
780/// use syn::parse::{Parse, ParseStream, Result};
781///
782/// struct MyMacroInput {
783/// /* ... */
784/// }
785///
786/// impl Parse for MyMacroInput {
787/// fn parse(input: ParseStream) -> Result<Self> {
788/// /* ... */
789/// # Ok(MyMacroInput {})
790/// }
791/// }
792///
793/// # const IGNORE: &str = stringify! {
794/// #[proc_macro]
795/// # };
796/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
797/// let input = parse_macro_input!(tokens as MyMacroInput);
798///
799/// /* ... */
800/// # "".parse().unwrap()
801/// }
802/// #
803/// # fn main() {}
804/// ```
805#[cfg(feature = "proc-macro")]
806#[macro_export]
807macro_rules! parse_macro_input {
808 ($tokenstream:ident as $ty:ty) => {
David Tolnay02465352018-08-30 23:38:00 -0700809 match $crate::parse::<$ty>($tokenstream) {
David Tolnayd641ee32018-08-30 17:11:09 -0700810 $crate::export::Ok(data) => data,
811 $crate::export::Err(err) => {
812 return $crate::export::TokenStream::from(err.into_compile_error());
813 }
814 };
815 };
816}