blob: 04124bc2d72b494505b0ceba3a8da1991d8b8ce3 [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//!
David Tolnay6b889eb2018-09-01 18:12:17 -070012//! Currently this library is geared toward use in Rust procedural macros, but
13//! contains some APIs that may be useful more generally.
David Tolnay5e84e972018-01-05 17:51:06 -080014//!
15//! - **Data structures** — Syn provides a complete syntax tree that can
16//! represent any valid Rust source code. The syntax tree is rooted at
17//! [`syn::File`] which represents a full source file, but there are other
18//! entry points that may be useful to procedural macros including
19//! [`syn::Item`], [`syn::Expr`] and [`syn::Type`].
20//!
21//! - **Custom derives** — Of particular interest to custom derives is
22//! [`syn::DeriveInput`] which is any of the three legal input items to a
23//! derive macro. An example below shows using this type in a library that can
24//! derive implementations of a trait of your own.
25//!
David Tolnay6b889eb2018-09-01 18:12:17 -070026//! - **Parsing** — Parsing in Syn is built around [parser functions] with the
27//! signature `fn(ParseStream) -> Result<T>`. Every syntax tree node defined
28//! by Syn is individually parsable and may be used as a building block for
29//! custom syntaxes, or you may dream up your own brand new syntax without
30//! involving any of our syntax tree types.
David Tolnay5e84e972018-01-05 17:51:06 -080031//!
32//! - **Location information** — Every token parsed by Syn is associated with a
33//! `Span` that tracks line and column information back to the source of that
34//! token. These spans allow a procedural macro to display detailed error
35//! messages pointing to all the right places in the user's code. There is an
36//! example of this below.
37//!
38//! - **Feature flags** — Functionality is aggressively feature gated so your
39//! procedural macros enable only what they need, and do not pay in compile
40//! time for all the rest.
41//!
42//! [`syn::File`]: struct.File.html
43//! [`syn::Item`]: enum.Item.html
44//! [`syn::Expr`]: enum.Expr.html
45//! [`syn::Type`]: enum.Type.html
46//! [`syn::DeriveInput`]: struct.DeriveInput.html
David Tolnay6b889eb2018-09-01 18:12:17 -070047//! [parser functions]: parse/index.html
David Tolnay5e84e972018-01-05 17:51:06 -080048//!
49//! *Version requirement: Syn supports any compiler version back to Rust's very
50//! first support for procedural macros in Rust 1.15.0. Some features especially
51//! around error reporting are only available in newer compilers or on the
52//! nightly channel.*
53//!
54//! ## Example of a custom derive
55//!
56//! The canonical custom derive using Syn looks like this. We write an ordinary
57//! Rust function tagged with a `proc_macro_derive` attribute and the name of
58//! the trait we are deriving. Any time that derive appears in the user's code,
59//! the Rust compiler passes their data structure as tokens into our macro. We
60//! get to execute arbitrary Rust code to figure out what to do with those
61//! tokens, then hand some tokens back to the compiler to compile into the
62//! user's crate.
63//!
64//! [`TokenStream`]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html
65//!
66//! ```toml
67//! [dependencies]
David Tolnayb28acf32018-09-06 09:01:40 -070068//! syn = "0.15"
David Tolnay87003d02018-05-20 19:45:13 -070069//! quote = "0.6"
David Tolnay5e84e972018-01-05 17:51:06 -080070//!
71//! [lib]
72//! proc-macro = true
73//! ```
74//!
75//! ```rust
David Tolnaya1c98072018-09-06 08:58:10 -070076//! #[macro_use]
77//! extern crate quote;
78//! #[macro_use]
79//! extern crate syn;
80//!
81//! extern crate proc_macro;
82//!
David Tolnay5e84e972018-01-05 17:51:06 -080083//! use proc_macro::TokenStream;
David Tolnaya1c98072018-09-06 08:58:10 -070084//! use syn::DeriveInput;
David Tolnay5e84e972018-01-05 17:51:06 -080085//!
86//! # const IGNORE_TOKENS: &str = stringify! {
87//! #[proc_macro_derive(MyMacro)]
88//! # };
89//! pub fn my_macro(input: TokenStream) -> TokenStream {
90//! // Parse the input tokens into a syntax tree
David Tolnay6b889eb2018-09-01 18:12:17 -070091//! let input = parse_macro_input!(input as DeriveInput);
David Tolnay5e84e972018-01-05 17:51:06 -080092//!
93//! // Build the output, possibly using quasi-quotation
94//! let expanded = quote! {
95//! // ...
96//! };
97//!
98//! // Hand the output tokens back to the compiler
David Tolnay35b498e2018-09-01 20:10:40 -070099//! TokenStream::from(expanded)
David Tolnay5e84e972018-01-05 17:51:06 -0800100//! }
101//! #
102//! # fn main() {}
103//! ```
104//!
105//! The [`heapsize`] example directory shows a complete working Macros 1.1
106//! implementation of a custom derive. It works on any Rust compiler \>=1.15.0.
107//! The example derives a `HeapSize` trait which computes an estimate of the
108//! amount of heap memory owned by a value.
109//!
110//! [`heapsize`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize
111//!
112//! ```rust
113//! pub trait HeapSize {
114//! /// Total number of bytes of heap memory owned by `self`.
115//! fn heap_size_of_children(&self) -> usize;
116//! }
117//! ```
118//!
119//! The custom derive allows users to write `#[derive(HeapSize)]` on data
120//! structures in their program.
121//!
122//! ```rust
123//! # const IGNORE_TOKENS: &str = stringify! {
124//! #[derive(HeapSize)]
125//! # };
126//! struct Demo<'a, T: ?Sized> {
127//! a: Box<T>,
128//! b: u8,
129//! c: &'a str,
130//! d: String,
131//! }
132//! ```
133//!
134//! ## Spans and error reporting
135//!
136//! The [`heapsize2`] example directory is an extension of the `heapsize`
137//! example that demonstrates some of the hygiene and error reporting properties
138//! of Macros 2.0. This example currently requires a nightly Rust compiler
139//! \>=1.24.0-nightly but we are working to stabilize all of the APIs involved.
140//!
141//! [`heapsize2`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize2
142//!
143//! The token-based procedural macro API provides great control over where the
144//! compiler's error messages are displayed in user code. Consider the error the
145//! user sees if one of their field types does not implement `HeapSize`.
146//!
147//! ```rust
148//! # const IGNORE_TOKENS: &str = stringify! {
149//! #[derive(HeapSize)]
150//! # };
151//! struct Broken {
152//! ok: String,
153//! bad: std::thread::Thread,
154//! }
155//! ```
156//!
157//! In the Macros 1.1 string-based procedural macro world, the resulting error
158//! would point unhelpfully to the invocation of the derive macro and not to the
159//! actual problematic field.
160//!
161//! ```text
162//! error[E0599]: no method named `heap_size_of_children` found for type `std::thread::Thread` in the current scope
163//! --> src/main.rs:4:10
164//! |
165//! 4 | #[derive(HeapSize)]
166//! | ^^^^^^^^
167//! ```
168//!
169//! By tracking span information all the way through the expansion of a
170//! procedural macro as shown in the `heapsize2` example, token-based macros in
171//! Syn are able to trigger errors that directly pinpoint the source of the
172//! problem.
173//!
174//! ```text
175//! error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
176//! --> src/main.rs:7:5
177//! |
178//! 7 | bad: std::thread::Thread,
David Tolnayefff2ff2018-01-07 11:49:52 -0800179//! | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `Thread`
David Tolnay5e84e972018-01-05 17:51:06 -0800180//! ```
181//!
David Tolnay6b889eb2018-09-01 18:12:17 -0700182//! ## Parsing a custom syntax
David Tolnay5e84e972018-01-05 17:51:06 -0800183//!
184//! The [`lazy-static`] example directory shows the implementation of a
185//! `functionlike!(...)` procedural macro in which the input tokens are parsed
David Tolnay6b889eb2018-09-01 18:12:17 -0700186//! using Syn's parsing API.
David Tolnay5e84e972018-01-05 17:51:06 -0800187//!
188//! [`lazy-static`]: https://github.com/dtolnay/syn/tree/master/examples/lazy-static
David Tolnay5e84e972018-01-05 17:51:06 -0800189//!
190//! The example reimplements the popular `lazy_static` crate from crates.io as a
191//! procedural macro.
192//!
193//! ```
194//! # macro_rules! lazy_static {
195//! # ($($tt:tt)*) => {}
196//! # }
197//! #
198//! lazy_static! {
199//! static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
200//! }
201//! ```
202//!
203//! The implementation shows how to trigger custom warnings and error messages
204//! on the macro input.
205//!
206//! ```text
207//! warning: come on, pick a more creative name
208//! --> src/main.rs:10:16
209//! |
210//! 10 | static ref FOO: String = "lazy_static".to_owned();
211//! | ^^^
212//! ```
213//!
214//! ## Debugging
215//!
216//! When developing a procedural macro it can be helpful to look at what the
217//! generated code looks like. Use `cargo rustc -- -Zunstable-options
218//! --pretty=expanded` or the [`cargo expand`] subcommand.
219//!
David Tolnay324db2d2018-01-07 11:51:09 -0800220//! [`cargo expand`]: https://github.com/dtolnay/cargo-expand
David Tolnay5e84e972018-01-05 17:51:06 -0800221//!
222//! To show the expanded code for some crate that uses your procedural macro,
223//! run `cargo expand` from that crate. To show the expanded code for one of
224//! your own test cases, run `cargo expand --test the_test_case` where the last
225//! argument is the name of the test file without the `.rs` extension.
226//!
227//! This write-up by Brandon W Maister discusses debugging in more detail:
228//! [Debugging Rust's new Custom Derive system][debugging].
229//!
230//! [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
231//!
232//! ## Optional features
233//!
234//! Syn puts a lot of functionality behind optional features in order to
235//! optimize compile time for the most common use cases. The following features
236//! are available.
237//!
238//! - **`derive`** *(enabled by default)* — Data structures for representing the
239//! possible input to a custom derive, including structs and enums and types.
240//! - **`full`** — Data structures for representing the syntax tree of all valid
241//! Rust source code, including items and expressions.
242//! - **`parsing`** *(enabled by default)* — Ability to parse input tokens into
243//! a syntax tree node of a chosen type.
244//! - **`printing`** *(enabled by default)* — Ability to print a syntax tree
245//! node as tokens of Rust source code.
246//! - **`visit`** — Trait for traversing a syntax tree.
David Tolnay34981cf2018-01-06 16:22:35 -0800247//! - **`visit-mut`** — Trait for traversing and mutating in place a syntax
David Tolnay5e84e972018-01-05 17:51:06 -0800248//! tree.
249//! - **`fold`** — Trait for transforming an owned syntax tree.
250//! - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
251//! types.
252//! - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree
253//! types.
hcpl4b72a382018-04-04 14:50:24 +0300254//! - **`proc-macro`** *(enabled by default)* — Runtime dependency on the
255//! dynamic library libproc_macro from rustc toolchain.
David Tolnay5e84e972018-01-05 17:51:06 -0800256
David Tolnay4cf7db82018-01-07 15:22:01 -0800257// Syn types in rustdoc of other crates get linked to here.
David Tolnay0587ab22018-10-13 19:56:16 -0700258#![doc(html_root_url = "https://docs.rs/syn/0.15.11")]
David Tolnay46b17c02018-09-22 13:27:40 -0700259#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
David Tolnay34071ba2018-05-20 20:00:41 -0700260#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
David Tolnay34071ba2018-05-20 20:00:41 -0700261// Ignored clippy lints.
David Tolnay94d2b792018-04-29 12:26:10 -0700262#![cfg_attr(
263 feature = "cargo-clippy",
264 allow(
David Tolnay4831ac62018-08-30 21:04:16 -0700265 block_in_if_condition_stmt,
David Tolnay0cec3e62018-07-21 09:08:30 -0700266 const_static_lifetime,
David Tolnay24b079d2018-08-27 08:28:10 -0700267 cyclomatic_complexity,
David Tolnay0cec3e62018-07-21 09:08:30 -0700268 doc_markdown,
David Tolnay24b079d2018-08-27 08:28:10 -0700269 eval_order_dependence,
David Tolnay0cec3e62018-07-21 09:08:30 -0700270 large_enum_variant,
271 match_bool,
David Tolnay6fb87462018-09-01 16:51:49 -0700272 never_loop,
David Tolnay0cec3e62018-07-21 09:08:30 -0700273 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 Tolnayb503da62018-10-12 21:29:26 -0700298// False positive: https://github.com/rust-lang-nursery/rust-clippy/issues/3274
299#![cfg_attr(feature = "cargo-clippy", allow(map_clone))]
David Tolnayad2836d2017-04-20 10:11:43 -0700300
David Tolnay278f9e32018-08-14 22:41:11 -0700301#[cfg(all(
302 not(all(target_arch = "wasm32", target_os = "unknown")),
303 feature = "proc-macro"
304))]
David Tolnay51382052017-12-27 13:46:21 -0500305extern crate proc_macro;
David Tolnay94d2b792018-04-29 12:26:10 -0700306extern crate proc_macro2;
David Tolnay570695e2017-06-03 16:15:13 -0700307extern crate unicode_xid;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700308
David Tolnay1cf80912017-12-31 18:35:12 -0500309#[cfg(feature = "printing")]
David Tolnay87d0b442016-09-04 11:52:12 -0700310extern crate quote;
311
Alex Crichton62a0a592017-05-22 13:58:53 -0700312#[macro_use]
313mod macros;
314
David Tolnay734079e2018-09-01 02:03:37 -0700315// Not public API.
David Tolnay852bff72018-08-27 08:24:02 -0700316#[cfg(feature = "parsing")]
David Tolnay734079e2018-09-01 02:03:37 -0700317#[doc(hidden)]
David Tolnay852bff72018-08-27 08:24:02 -0700318#[macro_use]
David Tolnay734079e2018-09-01 02:03:37 -0700319pub mod group;
David Tolnay852bff72018-08-27 08:24:02 -0700320
David Tolnayc5ab8c62017-12-26 16:43:39 -0500321#[macro_use]
David Tolnay32954ef2017-12-26 22:43:16 -0500322pub mod token;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500323
David Tolnay4fb71232018-08-25 23:14:50 -0400324mod ident;
325pub use ident::Ident;
David Tolnaye303b7c2018-05-20 16:46:35 -0700326
David Tolnay3cfd1d32018-01-03 00:22:08 -0800327#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700328mod attr;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800329#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay161f2de2018-10-13 14:38:20 -0700330pub use attr::{AttrStyle, Attribute, AttributeArgs, Meta, MetaList, MetaNameValue, NestedMeta};
David Tolnay35161ff2016-09-03 11:33:15 -0700331
David Tolnay3cfd1d32018-01-03 00:22:08 -0800332#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf38cdf62016-09-23 19:07:09 -0700333mod data;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800334#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700335pub use data::{
336 Field, Fields, FieldsNamed, FieldsUnnamed, Variant, VisCrate, VisPublic, VisRestricted,
337 Visibility,
338};
David Tolnayf38cdf62016-09-23 19:07:09 -0700339
David Tolnay3cfd1d32018-01-03 00:22:08 -0800340#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700341mod expr;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800342#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700343pub use expr::{
David Tolnay02a9c6f2018-08-24 18:58:45 -0400344 Expr, ExprArray, ExprAssign, ExprAssignOp, ExprAsync, ExprBinary, ExprBlock, ExprBox,
345 ExprBreak, ExprCall, ExprCast, ExprClosure, ExprContinue, ExprField, ExprForLoop, ExprGroup,
David Tolnay9c119122018-09-01 18:47:02 -0700346 ExprIf, ExprInPlace, ExprIndex, ExprLet, ExprLit, ExprLoop, ExprMacro, ExprMatch,
David Tolnay02a9c6f2018-08-24 18:58:45 -0400347 ExprMethodCall, ExprParen, ExprPath, ExprRange, ExprReference, ExprRepeat, ExprReturn,
348 ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprType, ExprUnary, ExprUnsafe, ExprVerbatim,
David Tolnay9c119122018-09-01 18:47:02 -0700349 ExprWhile, ExprYield, Index, Member,
David Tolnayb57c8492018-05-05 00:32:04 -0700350};
Michael Layzell734adb42017-06-07 16:58:31 -0400351
352#[cfg(feature = "full")]
David Tolnayb57c8492018-05-05 00:32:04 -0700353pub use expr::{
354 Arm, Block, FieldPat, FieldValue, GenericMethodArgument, Label, Local, MethodTurbofish, Pat,
355 PatBox, PatIdent, PatLit, PatMacro, PatPath, PatRange, PatRef, PatSlice, PatStruct, PatTuple,
356 PatTupleStruct, PatVerbatim, PatWild, RangeLimits, Stmt,
357};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700358
David Tolnay3cfd1d32018-01-03 00:22:08 -0800359#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700360mod generics;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800361#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700362pub use generics::{
363 BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeDef, PredicateEq,
364 PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound,
365 WhereClause, WherePredicate,
366};
David Tolnay278f9e32018-08-14 22:41:11 -0700367#[cfg(all(
368 any(feature = "full", feature = "derive"),
369 feature = "printing"
370))]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800371pub use generics::{ImplGenerics, Turbofish, TypeGenerics};
David Tolnay35161ff2016-09-03 11:33:15 -0700372
David Tolnayf38cdf62016-09-23 19:07:09 -0700373#[cfg(feature = "full")]
David Tolnayb79ee962016-09-04 09:39:20 -0700374mod item;
David Tolnayf38cdf62016-09-23 19:07:09 -0700375#[cfg(feature = "full")]
David Tolnayb57c8492018-05-05 00:32:04 -0700376pub use item::{
David Tolnay435c1782018-08-24 16:15:44 -0400377 ArgCaptured, ArgSelf, ArgSelfRef, FnArg, FnDecl, ForeignItem, ForeignItemFn, ForeignItemMacro,
378 ForeignItemStatic, ForeignItemType, ForeignItemVerbatim, ImplItem, ImplItemConst,
David Tolnaybb82ef02018-08-24 20:15:45 -0400379 ImplItemExistential, ImplItemMacro, ImplItemMethod, ImplItemType, ImplItemVerbatim, Item,
380 ItemConst, ItemEnum, ItemExistential, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl,
David Tolnayc6b04dd2018-08-30 23:22:51 -0700381 ItemMacro, ItemMacro2, ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType,
382 ItemUnion, ItemUse, ItemVerbatim, MethodSig, TraitItem, TraitItemConst, TraitItemMacro,
383 TraitItemMethod, TraitItemType, TraitItemVerbatim, UseGlob, UseGroup, UseName, UsePath,
384 UseRename, UseTree,
David Tolnayb57c8492018-05-05 00:32:04 -0700385};
David Tolnay35161ff2016-09-03 11:33:15 -0700386
David Tolnay631cb8c2016-11-10 17:16:41 -0800387#[cfg(feature = "full")]
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700388mod file;
David Tolnay631cb8c2016-11-10 17:16:41 -0800389#[cfg(feature = "full")]
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700390pub use file::File;
David Tolnay631cb8c2016-11-10 17:16:41 -0800391
David Tolnay63e3dee2017-06-03 20:13:17 -0700392mod lifetime;
393pub use lifetime::Lifetime;
394
David Tolnay3cfd1d32018-01-03 00:22:08 -0800395#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700396mod lit;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800397#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700398pub use lit::{
399 FloatSuffix, IntSuffix, Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr,
400 LitVerbatim, StrStyle,
401};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700402
David Tolnay3cfd1d32018-01-03 00:22:08 -0800403#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700404mod mac;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800405#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayab919512017-12-30 23:31:51 -0500406pub use mac::{Macro, MacroDelimiter};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700407
David Tolnay3cfd1d32018-01-03 00:22:08 -0800408#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay0e837402016-12-22 17:25:55 -0500409mod derive;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800410#[cfg(feature = "derive")]
David Tolnaye3d41b72017-12-31 15:24:00 -0500411pub use derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
David Tolnayf38cdf62016-09-23 19:07:09 -0700412
David Tolnay3cfd1d32018-01-03 00:22:08 -0800413#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay3cb23a92016-10-07 23:02:21 -0700414mod op;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800415#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay3cb23a92016-10-07 23:02:21 -0700416pub use op::{BinOp, UnOp};
417
David Tolnay3cfd1d32018-01-03 00:22:08 -0800418#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700419mod ty;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800420#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700421pub use ty::{
422 Abi, BareFnArg, BareFnArgName, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,
423 TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference,
424 TypeSlice, TypeTraitObject, TypeTuple, TypeVerbatim,
425};
David Tolnay056de302018-01-05 14:29:05 -0800426
427#[cfg(any(feature = "full", feature = "derive"))]
428mod path;
429#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700430pub use path::{
David Tolnay9d0882a2018-09-01 19:49:14 -0700431 AngleBracketedGenericArguments, Binding, Constraint, GenericArgument,
432 ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
David Tolnayb57c8492018-05-05 00:32:04 -0700433};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700434
David Tolnay1b752fb2017-12-26 21:41:39 -0500435#[cfg(feature = "parsing")]
David Tolnaydfc886b2018-01-06 08:03:09 -0800436pub mod buffer;
David Tolnay94d304f2018-08-30 23:43:53 -0700437#[cfg(feature = "parsing")]
438pub mod ext;
David Tolnay94d2b792018-04-29 12:26:10 -0700439pub mod punctuated;
David Tolnay3779bb72018-08-26 18:46:07 -0700440#[cfg(all(
441 any(feature = "full", feature = "derive"),
442 feature = "extra-traits"
443))]
David Tolnaye0824032017-12-27 15:25:56 -0500444mod tt;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500445
David Tolnaye83ef5a2018-01-11 15:18:36 -0800446// Not public API except the `parse_quote!` macro.
David Tolnay491680a2018-01-23 00:34:40 -0800447#[cfg(feature = "parsing")]
David Tolnaye83ef5a2018-01-11 15:18:36 -0800448#[doc(hidden)]
449pub mod parse_quote;
450
David Tolnayf98865f2018-10-13 14:37:07 -0700451// Not public API except the `parse_macro_input!` macro.
452#[cfg(all(
453 not(all(target_arch = "wasm32", target_os = "unknown")),
454 feature = "parsing",
455 feature = "proc-macro"
456))]
457#[doc(hidden)]
458pub mod parse_macro_input;
459
David Tolnay4d942b42018-01-02 22:14:04 -0800460#[cfg(all(feature = "parsing", feature = "printing"))]
David Tolnayf790b612017-12-31 18:46:57 -0500461pub mod spanned;
462
Nika Layzella6f46c42017-10-26 15:26:16 -0400463mod gen {
David Tolnayded2d682018-01-06 18:53:53 -0800464 /// Syntax tree traversal to walk a shared borrow of a syntax tree.
465 ///
466 /// Each method of the [`Visit`] trait is a hook that can be overridden to
467 /// customize the behavior when visiting the corresponding type of node. By
468 /// default, every method recursively visits the substructure of the input
469 /// by invoking the right visitor method of each of its fields.
470 ///
471 /// [`Visit`]: trait.Visit.html
472 ///
473 /// ```rust
474 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
475 /// #
476 /// pub trait Visit<'ast> {
477 /// /* ... */
478 ///
479 /// fn visit_expr_binary(&mut self, node: &'ast ExprBinary) {
480 /// for attr in &node.attrs {
481 /// self.visit_attribute(attr);
482 /// }
483 /// self.visit_expr(&*node.left);
484 /// self.visit_bin_op(&node.op);
485 /// self.visit_expr(&*node.right);
486 /// }
487 ///
488 /// /* ... */
489 /// # fn visit_attribute(&mut self, node: &'ast Attribute);
490 /// # fn visit_expr(&mut self, node: &'ast Expr);
491 /// # fn visit_bin_op(&mut self, node: &'ast BinOp);
492 /// }
493 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800494 ///
495 /// *This module is available if Syn is built with the `"visit"` feature.*
Nika Layzella6f46c42017-10-26 15:26:16 -0400496 #[cfg(feature = "visit")]
497 pub mod visit;
David Tolnay55337722016-09-11 12:58:56 -0700498
David Tolnayded2d682018-01-06 18:53:53 -0800499 /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in
500 /// place.
501 ///
502 /// Each method of the [`VisitMut`] trait is a hook that can be overridden
503 /// to customize the behavior when mutating the corresponding type of node.
504 /// By default, every method recursively visits the substructure of the
505 /// input by invoking the right visitor method of each of its fields.
506 ///
507 /// [`VisitMut`]: trait.VisitMut.html
508 ///
509 /// ```rust
510 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
511 /// #
512 /// pub trait VisitMut {
513 /// /* ... */
514 ///
515 /// fn visit_expr_binary_mut(&mut self, node: &mut ExprBinary) {
516 /// for attr in &mut node.attrs {
517 /// self.visit_attribute_mut(attr);
518 /// }
519 /// self.visit_expr_mut(&mut *node.left);
520 /// self.visit_bin_op_mut(&mut node.op);
521 /// self.visit_expr_mut(&mut *node.right);
522 /// }
523 ///
524 /// /* ... */
525 /// # fn visit_attribute_mut(&mut self, node: &mut Attribute);
526 /// # fn visit_expr_mut(&mut self, node: &mut Expr);
527 /// # fn visit_bin_op_mut(&mut self, node: &mut BinOp);
528 /// }
529 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800530 ///
531 /// *This module is available if Syn is built with the `"visit-mut"`
532 /// feature.*
David Tolnay9df02c42018-01-06 13:52:48 -0800533 #[cfg(feature = "visit-mut")]
Nika Layzella6f46c42017-10-26 15:26:16 -0400534 pub mod visit_mut;
Nika Layzell27726662017-10-24 23:16:35 -0400535
David Tolnayded2d682018-01-06 18:53:53 -0800536 /// Syntax tree traversal to transform the nodes of an owned syntax tree.
537 ///
538 /// Each method of the [`Fold`] trait is a hook that can be overridden to
539 /// customize the behavior when transforming the corresponding type of node.
540 /// By default, every method recursively visits the substructure of the
541 /// input by invoking the right visitor method of each of its fields.
542 ///
543 /// [`Fold`]: trait.Fold.html
544 ///
545 /// ```rust
546 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
547 /// #
548 /// pub trait Fold {
549 /// /* ... */
550 ///
551 /// fn fold_expr_binary(&mut self, node: ExprBinary) -> ExprBinary {
552 /// ExprBinary {
553 /// attrs: node.attrs
554 /// .into_iter()
555 /// .map(|attr| self.fold_attribute(attr))
556 /// .collect(),
557 /// left: Box::new(self.fold_expr(*node.left)),
558 /// op: self.fold_bin_op(node.op),
559 /// right: Box::new(self.fold_expr(*node.right)),
560 /// }
561 /// }
562 ///
563 /// /* ... */
564 /// # fn fold_attribute(&mut self, node: Attribute) -> Attribute;
565 /// # fn fold_expr(&mut self, node: Expr) -> Expr;
566 /// # fn fold_bin_op(&mut self, node: BinOp) -> BinOp;
567 /// }
568 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800569 ///
570 /// *This module is available if Syn is built with the `"fold"` feature.*
Nika Layzella6f46c42017-10-26 15:26:16 -0400571 #[cfg(feature = "fold")]
572 pub mod fold;
David Tolnayf60f4262017-12-28 19:17:58 -0500573
David Tolnay0a0d78c2018-01-05 15:24:01 -0800574 #[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf60f4262017-12-28 19:17:58 -0500575 #[path = "../gen_helper.rs"]
576 mod helper;
Nika Layzella6f46c42017-10-26 15:26:16 -0400577}
578pub use gen::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100579
David Tolnay456c9822018-08-25 08:09:46 -0400580// Not public API.
581#[doc(hidden)]
582pub mod export;
583
David Tolnay7fb11e72018-09-06 01:02:27 -0700584mod keyword;
David Tolnayb6254182018-08-25 08:44:54 -0400585
586#[cfg(feature = "parsing")]
David Tolnay7fb11e72018-09-06 01:02:27 -0700587mod lookahead;
Louis Kureuil Personc0beaf32018-09-05 00:12:43 +0200588
589#[cfg(feature = "parsing")]
David Tolnayb6254182018-08-25 08:44:54 -0400590pub mod parse;
591
David Tolnay776f8e02018-08-24 22:32:10 -0400592mod span;
593
David Tolnay64023912018-08-31 09:51:12 -0700594#[cfg(all(
595 any(feature = "full", feature = "derive"),
596 feature = "printing"
597))]
598mod print;
599
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700600////////////////////////////////////////////////////////////////////////////////
601
David Tolnayaa77a852018-08-31 11:15:10 -0700602#[cfg(any(feature = "parsing", feature = "full", feature = "derive"))]
David Tolnay94f06632018-08-31 10:17:17 -0700603#[allow(non_camel_case_types)]
David Tolnay10951d52018-08-31 10:27:39 -0700604struct private;
David Tolnay94f06632018-08-31 10:17:17 -0700605
606////////////////////////////////////////////////////////////////////////////////
607
David Tolnay55337722016-09-11 12:58:56 -0700608#[cfg(feature = "parsing")]
David Tolnayb6254182018-08-25 08:44:54 -0400609mod error;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500610#[cfg(feature = "parsing")]
David Tolnayad4b2472018-08-25 08:25:24 -0400611use error::Error;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500612
David Tolnayccab0be2018-01-06 22:24:47 -0800613/// Parse tokens of source code into the chosen syntax tree node.
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700614///
615/// This is preferred over parsing a string because tokens are able to preserve
616/// information about where in the user's code they were originally written (the
617/// "span" of the token), possibly allowing the compiler to produce better error
618/// messages.
619///
David Tolnayccab0be2018-01-06 22:24:47 -0800620/// This function parses a `proc_macro::TokenStream` which is the type used for
621/// interop with the compiler in a procedural macro. To parse a
622/// `proc_macro2::TokenStream`, use [`syn::parse2`] instead.
623///
624/// [`syn::parse2`]: fn.parse2.html
625///
hcpl4b72a382018-04-04 14:50:24 +0300626/// *This function is available if Syn is built with both the `"parsing"` and
627/// `"proc-macro"` features.*
David Tolnay461d98e2018-01-07 11:07:19 -0800628///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700629/// # Examples
630///
David Tolnaybcf26022017-12-25 22:10:52 -0500631/// ```rust
David Tolnaya1c98072018-09-06 08:58:10 -0700632/// #[macro_use]
633/// extern crate quote;
634///
635/// extern crate proc_macro;
636/// extern crate syn;
637///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700638/// use proc_macro::TokenStream;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700639/// use syn::DeriveInput;
640///
David Tolnaybcf26022017-12-25 22:10:52 -0500641/// # const IGNORE_TOKENS: &str = stringify! {
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700642/// #[proc_macro_derive(MyMacro)]
David Tolnaybcf26022017-12-25 22:10:52 -0500643/// # };
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700644/// pub fn my_macro(input: TokenStream) -> TokenStream {
645/// // Parse the tokens into a syntax tree
646/// let ast: DeriveInput = syn::parse(input).unwrap();
647///
648/// // Build the output, possibly using quasi-quotation
649/// let expanded = quote! {
650/// /* ... */
651/// };
652///
David Tolnaybcf26022017-12-25 22:10:52 -0500653/// // Convert into a token stream and return it
654/// expanded.into()
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700655/// }
David Tolnaybcf26022017-12-25 22:10:52 -0500656/// #
657/// # fn main() {}
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700658/// ```
David Tolnay278f9e32018-08-14 22:41:11 -0700659#[cfg(all(
660 not(all(target_arch = "wasm32", target_os = "unknown")),
661 feature = "parsing",
662 feature = "proc-macro"
663))]
David Tolnaye82a2b12018-08-30 16:31:10 -0700664pub fn parse<T: parse::Parse>(tokens: proc_macro::TokenStream) -> Result<T, Error> {
David Tolnay80a914f2018-08-30 23:49:53 -0700665 parse::Parser::parse(T::parse, tokens)
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700666}
667
David Tolnayccab0be2018-01-06 22:24:47 -0800668/// Parse a proc-macro2 token stream into the chosen syntax tree node.
669///
670/// This function parses a `proc_macro2::TokenStream` which is commonly useful
671/// when the input comes from a node of the Syn syntax tree, for example the tts
672/// of a [`Macro`] node. When in a procedural macro parsing the
673/// `proc_macro::TokenStream` provided by the compiler, use [`syn::parse`]
674/// instead.
675///
676/// [`Macro`]: struct.Macro.html
677/// [`syn::parse`]: fn.parse.html
David Tolnay461d98e2018-01-07 11:07:19 -0800678///
679/// *This function is available if Syn is built with the `"parsing"` feature.*
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700680#[cfg(feature = "parsing")]
David Tolnaye82a2b12018-08-30 16:31:10 -0700681pub fn parse2<T: parse::Parse>(tokens: proc_macro2::TokenStream) -> Result<T, Error> {
David Tolnay80a914f2018-08-30 23:49:53 -0700682 parse::Parser::parse2(T::parse, tokens)
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700683}
Alex Crichton954046c2017-05-30 21:49:42 -0700684
David Tolnayccab0be2018-01-06 22:24:47 -0800685/// Parse a string of Rust code into the chosen syntax tree node.
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700686///
David Tolnay461d98e2018-01-07 11:07:19 -0800687/// *This function is available if Syn is built with the `"parsing"` feature.*
688///
David Tolnay3f5b06f2018-01-11 21:02:00 -0800689/// # Hygiene
690///
691/// Every span in the resulting syntax tree will be set to resolve at the macro
692/// call site.
693///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700694/// # Examples
695///
696/// ```rust
David Tolnay9b00f652018-09-01 10:31:02 -0700697/// # extern crate syn;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700698/// #
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700699/// use syn::Expr;
David Tolnay9b00f652018-09-01 10:31:02 -0700700/// use syn::parse::Result;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700701///
702/// fn run() -> Result<()> {
703/// let code = "assert_eq!(u8::max_value(), 255)";
704/// let expr = syn::parse_str::<Expr>(code)?;
705/// println!("{:#?}", expr);
706/// Ok(())
707/// }
708/// #
709/// # fn main() { run().unwrap() }
710/// ```
711#[cfg(feature = "parsing")]
David Tolnaye82a2b12018-08-30 16:31:10 -0700712pub fn parse_str<T: parse::Parse>(s: &str) -> Result<T, Error> {
David Tolnay80a914f2018-08-30 23:49:53 -0700713 parse::Parser::parse_str(T::parse, s)
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700714}
Alex Crichton954046c2017-05-30 21:49:42 -0700715
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700716// FIXME the name parse_file makes it sound like you might pass in a path to a
717// file, rather than the content.
718/// Parse the content of a file of Rust code.
719///
720/// This is different from `syn::parse_str::<File>(content)` in two ways:
721///
722/// - It discards a leading byte order mark `\u{FEFF}` if the file has one.
723/// - It preserves the shebang line of the file, such as `#!/usr/bin/env rustx`.
724///
725/// If present, either of these would be an error using `from_str`.
726///
Christopher Serr9727ef22018-02-03 16:42:12 +0100727/// *This function is available if Syn is built with the `"parsing"` and `"full"` features.*
David Tolnay461d98e2018-01-07 11:07:19 -0800728///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700729/// # Examples
730///
731/// ```rust,no_run
David Tolnay9b00f652018-09-01 10:31:02 -0700732/// # extern crate syn;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700733/// #
David Tolnay9b00f652018-09-01 10:31:02 -0700734/// use std::error::Error;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700735/// use std::fs::File;
736/// use std::io::Read;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700737///
David Tolnay9b00f652018-09-01 10:31:02 -0700738/// fn run() -> Result<(), Box<Error>> {
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700739/// let mut file = File::open("path/to/code.rs")?;
740/// let mut content = String::new();
741/// file.read_to_string(&mut content)?;
742///
743/// let ast = syn::parse_file(&content)?;
744/// if let Some(shebang) = ast.shebang {
745/// println!("{}", shebang);
746/// }
747/// println!("{} items", ast.items.len());
748///
749/// Ok(())
750/// }
751/// #
752/// # fn main() { run().unwrap() }
753/// ```
754#[cfg(all(feature = "parsing", feature = "full"))]
David Tolnayad4b2472018-08-25 08:25:24 -0400755pub fn parse_file(mut content: &str) -> Result<File, Error> {
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700756 // Strip the BOM if it is present
757 const BOM: &'static str = "\u{feff}";
758 if content.starts_with(BOM) {
759 content = &content[BOM.len()..];
David Tolnay35161ff2016-09-03 11:33:15 -0700760 }
Michael Layzell5e107ff2017-01-24 19:58:39 -0500761
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700762 let mut shebang = None;
763 if content.starts_with("#!") && !content.starts_with("#![") {
764 if let Some(idx) = content.find('\n') {
765 shebang = Some(content[..idx].to_string());
766 content = &content[idx..];
767 } else {
768 shebang = Some(content.to_string());
769 content = "";
770 }
Alex Crichton954046c2017-05-30 21:49:42 -0700771 }
David Tolnay0a8972b2017-02-27 02:10:01 -0800772
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700773 let mut file: File = parse_str(content)?;
774 file.shebang = shebang;
775 Ok(file)
Michael Layzell5e107ff2017-01-24 19:58:39 -0500776}