blob: 03d59f3f8c691ed3127197c42afb7c5bba686ff6 [file] [log] [blame]
David Tolnay5e84e972018-01-05 17:51:06 -08001//! Syn is a parsing library for parsing a stream of Rust tokens into a syntax
2//! tree of Rust source code.
3//!
David Tolnay6b889eb2018-09-01 18:12:17 -07004//! Currently this library is geared toward use in Rust procedural macros, but
5//! contains some APIs that may be useful more generally.
David Tolnay5e84e972018-01-05 17:51:06 -08006//!
7//! - **Data structures** — Syn provides a complete syntax tree that can
8//! represent any valid Rust source code. The syntax tree is rooted at
9//! [`syn::File`] which represents a full source file, but there are other
10//! entry points that may be useful to procedural macros including
11//! [`syn::Item`], [`syn::Expr`] and [`syn::Type`].
12//!
13//! - **Custom derives** — Of particular interest to custom derives is
14//! [`syn::DeriveInput`] which is any of the three legal input items to a
15//! derive macro. An example below shows using this type in a library that can
16//! derive implementations of a trait of your own.
17//!
David Tolnay6b889eb2018-09-01 18:12:17 -070018//! - **Parsing** — Parsing in Syn is built around [parser functions] with the
19//! signature `fn(ParseStream) -> Result<T>`. Every syntax tree node defined
20//! by Syn is individually parsable and may be used as a building block for
21//! custom syntaxes, or you may dream up your own brand new syntax without
22//! involving any of our syntax tree types.
David Tolnay5e84e972018-01-05 17:51:06 -080023//!
24//! - **Location information** — Every token parsed by Syn is associated with a
25//! `Span` that tracks line and column information back to the source of that
26//! token. These spans allow a procedural macro to display detailed error
27//! messages pointing to all the right places in the user's code. There is an
28//! example of this below.
29//!
30//! - **Feature flags** — Functionality is aggressively feature gated so your
31//! procedural macros enable only what they need, and do not pay in compile
32//! time for all the rest.
33//!
34//! [`syn::File`]: struct.File.html
35//! [`syn::Item`]: enum.Item.html
36//! [`syn::Expr`]: enum.Expr.html
37//! [`syn::Type`]: enum.Type.html
38//! [`syn::DeriveInput`]: struct.DeriveInput.html
David Tolnay6b889eb2018-09-01 18:12:17 -070039//! [parser functions]: parse/index.html
David Tolnay5e84e972018-01-05 17:51:06 -080040//!
41//! *Version requirement: Syn supports any compiler version back to Rust's very
42//! first support for procedural macros in Rust 1.15.0. Some features especially
43//! around error reporting are only available in newer compilers or on the
44//! nightly channel.*
45//!
46//! ## Example of a custom derive
47//!
48//! The canonical custom derive using Syn looks like this. We write an ordinary
49//! Rust function tagged with a `proc_macro_derive` attribute and the name of
50//! the trait we are deriving. Any time that derive appears in the user's code,
51//! the Rust compiler passes their data structure as tokens into our macro. We
52//! get to execute arbitrary Rust code to figure out what to do with those
53//! tokens, then hand some tokens back to the compiler to compile into the
54//! user's crate.
55//!
56//! [`TokenStream`]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html
57//!
58//! ```toml
59//! [dependencies]
David Tolnayb28acf32018-09-06 09:01:40 -070060//! syn = "0.15"
David Tolnay87003d02018-05-20 19:45:13 -070061//! quote = "0.6"
David Tolnay5e84e972018-01-05 17:51:06 -080062//!
63//! [lib]
64//! proc-macro = true
65//! ```
66//!
David Tolnay95989db2019-01-01 15:05:57 -050067//! ```edition2018
David Tolnaya1c98072018-09-06 08:58:10 -070068//! extern crate proc_macro;
69//!
David Tolnay5e84e972018-01-05 17:51:06 -080070//! use proc_macro::TokenStream;
David Tolnayfd5b1172018-12-31 17:54:36 -050071//! use quote::quote;
72//! use syn::{parse_macro_input, DeriveInput};
David Tolnay5e84e972018-01-05 17:51:06 -080073//!
74//! # const IGNORE_TOKENS: &str = stringify! {
75//! #[proc_macro_derive(MyMacro)]
76//! # };
77//! pub fn my_macro(input: TokenStream) -> TokenStream {
78//! // Parse the input tokens into a syntax tree
David Tolnay6b889eb2018-09-01 18:12:17 -070079//! let input = parse_macro_input!(input as DeriveInput);
David Tolnay5e84e972018-01-05 17:51:06 -080080//!
81//! // Build the output, possibly using quasi-quotation
82//! let expanded = quote! {
83//! // ...
84//! };
85//!
86//! // Hand the output tokens back to the compiler
David Tolnay35b498e2018-09-01 20:10:40 -070087//! TokenStream::from(expanded)
David Tolnay5e84e972018-01-05 17:51:06 -080088//! }
David Tolnay5e84e972018-01-05 17:51:06 -080089//! ```
90//!
91//! The [`heapsize`] example directory shows a complete working Macros 1.1
David Tolnayb4f57242018-10-28 17:57:08 -070092//! implementation of a custom derive. It works on any Rust compiler 1.15+.
David Tolnay5e84e972018-01-05 17:51:06 -080093//! The example derives a `HeapSize` trait which computes an estimate of the
94//! amount of heap memory owned by a value.
95//!
96//! [`heapsize`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize
97//!
David Tolnay95989db2019-01-01 15:05:57 -050098//! ```edition2018
David Tolnay5e84e972018-01-05 17:51:06 -080099//! pub trait HeapSize {
100//! /// Total number of bytes of heap memory owned by `self`.
101//! fn heap_size_of_children(&self) -> usize;
102//! }
103//! ```
104//!
105//! The custom derive allows users to write `#[derive(HeapSize)]` on data
106//! structures in their program.
107//!
David Tolnay95989db2019-01-01 15:05:57 -0500108//! ```edition2018
David Tolnay5e84e972018-01-05 17:51:06 -0800109//! # const IGNORE_TOKENS: &str = stringify! {
110//! #[derive(HeapSize)]
111//! # };
112//! struct Demo<'a, T: ?Sized> {
113//! a: Box<T>,
114//! b: u8,
115//! c: &'a str,
116//! d: String,
117//! }
118//! ```
119//!
120//! ## Spans and error reporting
121//!
David Tolnay5e84e972018-01-05 17:51:06 -0800122//! The token-based procedural macro API provides great control over where the
123//! compiler's error messages are displayed in user code. Consider the error the
124//! user sees if one of their field types does not implement `HeapSize`.
125//!
David Tolnay95989db2019-01-01 15:05:57 -0500126//! ```edition2018
David Tolnay5e84e972018-01-05 17:51:06 -0800127//! # const IGNORE_TOKENS: &str = stringify! {
128//! #[derive(HeapSize)]
129//! # };
130//! struct Broken {
131//! ok: String,
132//! bad: std::thread::Thread,
133//! }
134//! ```
135//!
David Tolnay5e84e972018-01-05 17:51:06 -0800136//! By tracking span information all the way through the expansion of a
David Tolnay3be1b782018-10-28 17:41:41 -0700137//! procedural macro as shown in the `heapsize` example, token-based macros in
David Tolnay5e84e972018-01-05 17:51:06 -0800138//! Syn are able to trigger errors that directly pinpoint the source of the
139//! problem.
140//!
141//! ```text
142//! error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
143//! --> src/main.rs:7:5
144//! |
145//! 7 | bad: std::thread::Thread,
David Tolnayefff2ff2018-01-07 11:49:52 -0800146//! | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `Thread`
David Tolnay5e84e972018-01-05 17:51:06 -0800147//! ```
148//!
David Tolnay6b889eb2018-09-01 18:12:17 -0700149//! ## Parsing a custom syntax
David Tolnay5e84e972018-01-05 17:51:06 -0800150//!
151//! The [`lazy-static`] example directory shows the implementation of a
152//! `functionlike!(...)` procedural macro in which the input tokens are parsed
David Tolnay6b889eb2018-09-01 18:12:17 -0700153//! using Syn's parsing API.
David Tolnay5e84e972018-01-05 17:51:06 -0800154//!
155//! [`lazy-static`]: https://github.com/dtolnay/syn/tree/master/examples/lazy-static
David Tolnay5e84e972018-01-05 17:51:06 -0800156//!
157//! The example reimplements the popular `lazy_static` crate from crates.io as a
158//! procedural macro.
159//!
David Tolnay95989db2019-01-01 15:05:57 -0500160//! ```edition2018
David Tolnay5e84e972018-01-05 17:51:06 -0800161//! # macro_rules! lazy_static {
162//! # ($($tt:tt)*) => {}
163//! # }
164//! #
165//! lazy_static! {
166//! static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
167//! }
168//! ```
169//!
170//! The implementation shows how to trigger custom warnings and error messages
171//! on the macro input.
172//!
173//! ```text
174//! warning: come on, pick a more creative name
175//! --> src/main.rs:10:16
176//! |
177//! 10 | static ref FOO: String = "lazy_static".to_owned();
178//! | ^^^
179//! ```
180//!
David Tolnay162dac12019-05-07 18:34:26 -0700181//! ## Testing
182//!
183//! When testing macros, we often care not just that the macro can be used
184//! successfully but also that when the macro is provided with invalid input it
185//! produces maximally helpful error messages. Consider using the [`trybuild`]
186//! crate to write tests for errors that are emitted by your macro or errors
187//! detected by the Rust compiler in the expanded code following misuse of the
188//! macro. Such tests help avoid regressions from later refactors that
189//! mistakenly make an error no longer trigger or be less helpful than it used
190//! to be.
191//!
192//! [`trybuild`]: https://github.com/dtolnay/trybuild
193//!
David Tolnay5e84e972018-01-05 17:51:06 -0800194//! ## Debugging
195//!
196//! When developing a procedural macro it can be helpful to look at what the
197//! generated code looks like. Use `cargo rustc -- -Zunstable-options
198//! --pretty=expanded` or the [`cargo expand`] subcommand.
199//!
David Tolnay324db2d2018-01-07 11:51:09 -0800200//! [`cargo expand`]: https://github.com/dtolnay/cargo-expand
David Tolnay5e84e972018-01-05 17:51:06 -0800201//!
202//! To show the expanded code for some crate that uses your procedural macro,
203//! run `cargo expand` from that crate. To show the expanded code for one of
204//! your own test cases, run `cargo expand --test the_test_case` where the last
205//! argument is the name of the test file without the `.rs` extension.
206//!
207//! This write-up by Brandon W Maister discusses debugging in more detail:
208//! [Debugging Rust's new Custom Derive system][debugging].
209//!
210//! [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
211//!
212//! ## Optional features
213//!
214//! Syn puts a lot of functionality behind optional features in order to
215//! optimize compile time for the most common use cases. The following features
216//! are available.
217//!
218//! - **`derive`** *(enabled by default)* — Data structures for representing the
219//! possible input to a custom derive, including structs and enums and types.
220//! - **`full`** — Data structures for representing the syntax tree of all valid
221//! Rust source code, including items and expressions.
222//! - **`parsing`** *(enabled by default)* — Ability to parse input tokens into
223//! a syntax tree node of a chosen type.
224//! - **`printing`** *(enabled by default)* — Ability to print a syntax tree
225//! node as tokens of Rust source code.
226//! - **`visit`** — Trait for traversing a syntax tree.
David Tolnay34981cf2018-01-06 16:22:35 -0800227//! - **`visit-mut`** — Trait for traversing and mutating in place a syntax
David Tolnay5e84e972018-01-05 17:51:06 -0800228//! tree.
229//! - **`fold`** — Trait for transforming an owned syntax tree.
230//! - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
231//! types.
232//! - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree
233//! types.
hcpl4b72a382018-04-04 14:50:24 +0300234//! - **`proc-macro`** *(enabled by default)* — Runtime dependency on the
235//! dynamic library libproc_macro from rustc toolchain.
David Tolnay5e84e972018-01-05 17:51:06 -0800236
David Tolnay4cf7db82018-01-07 15:22:01 -0800237// Syn types in rustdoc of other crates get linked to here.
David Tolnay1139c5e2019-06-23 14:22:46 -0700238#![doc(html_root_url = "https://docs.rs/syn/0.15.38")]
David Tolnay479881f2019-06-04 22:55:48 -0700239#![allow(unknown_lints, bare_trait_objects, ellipsis_inclusive_range_patterns)]
David Tolnay46b17c02018-09-22 13:27:40 -0700240#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
David Tolnay34071ba2018-05-20 20:00:41 -0700241#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
David Tolnay34071ba2018-05-20 20:00:41 -0700242// Ignored clippy lints.
David Tolnay94d2b792018-04-29 12:26:10 -0700243#![cfg_attr(
244 feature = "cargo-clippy",
245 allow(
David Tolnay4831ac62018-08-30 21:04:16 -0700246 block_in_if_condition_stmt,
David Tolnay50144d92019-03-09 23:20:56 -0800247 cognitive_complexity,
David Tolnay267eac62018-11-06 20:30:36 -0800248 deprecated_cfg_attr,
David Tolnay0cec3e62018-07-21 09:08:30 -0700249 doc_markdown,
David Tolnay24b079d2018-08-27 08:28:10 -0700250 eval_order_dependence,
David Tolnay0cec3e62018-07-21 09:08:30 -0700251 large_enum_variant,
David Tolnayaba1ed12018-11-10 14:26:40 -0800252 needless_pass_by_value,
David Tolnay6fb87462018-09-01 16:51:49 -0700253 never_loop,
David Tolnay0cec3e62018-07-21 09:08:30 -0700254 redundant_field_names,
David Tolnay5f929c72019-06-21 10:33:12 -0700255 redundant_static_lifetimes,
David Tolnayaba1ed12018-11-10 14:26:40 -0800256 too_many_arguments,
David Tolnay94d2b792018-04-29 12:26:10 -0700257 )
258)]
David Tolnay34071ba2018-05-20 20:00:41 -0700259// Ignored clippy_pedantic lints.
260#![cfg_attr(
261 feature = "cargo-clippy",
262 allow(
David Tolnay0cec3e62018-07-21 09:08:30 -0700263 cast_possible_truncation,
264 cast_possible_wrap,
David Tolnayb1617752018-08-24 21:16:33 -0400265 empty_enum,
David Tolnay0cec3e62018-07-21 09:08:30 -0700266 if_not_else,
David Tolnay0cec3e62018-07-21 09:08:30 -0700267 items_after_statements,
David Tolnay24cff8a2018-12-31 18:21:23 -0500268 module_name_repetitions,
David Tolnay151f92f2018-08-14 22:44:53 -0700269 shadow_unrelated,
David Tolnay0cec3e62018-07-21 09:08:30 -0700270 similar_names,
271 single_match_else,
David Tolnay0cec3e62018-07-21 09:08:30 -0700272 unseparated_literal_suffix,
273 use_self,
David Tolnaya06d8642018-11-06 20:31:05 -0800274 used_underscore_binding,
David Tolnay34071ba2018-05-20 20:00:41 -0700275 )
276)]
David Tolnayad2836d2017-04-20 10:11:43 -0700277
David Tolnay278f9e32018-08-14 22:41:11 -0700278#[cfg(all(
279 not(all(target_arch = "wasm32", target_os = "unknown")),
280 feature = "proc-macro"
281))]
David Tolnay51382052017-12-27 13:46:21 -0500282extern crate proc_macro;
David Tolnay94d2b792018-04-29 12:26:10 -0700283extern crate proc_macro2;
David Tolnay570695e2017-06-03 16:15:13 -0700284extern crate unicode_xid;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700285
David Tolnay1cf80912017-12-31 18:35:12 -0500286#[cfg(feature = "printing")]
David Tolnay87d0b442016-09-04 11:52:12 -0700287extern crate quote;
288
Alex Crichton62a0a592017-05-22 13:58:53 -0700289#[macro_use]
290mod macros;
291
David Tolnay734079e2018-09-01 02:03:37 -0700292// Not public API.
David Tolnay852bff72018-08-27 08:24:02 -0700293#[cfg(feature = "parsing")]
David Tolnay734079e2018-09-01 02:03:37 -0700294#[doc(hidden)]
David Tolnay852bff72018-08-27 08:24:02 -0700295#[macro_use]
David Tolnay734079e2018-09-01 02:03:37 -0700296pub mod group;
David Tolnay852bff72018-08-27 08:24:02 -0700297
David Tolnayc5ab8c62017-12-26 16:43:39 -0500298#[macro_use]
David Tolnay32954ef2017-12-26 22:43:16 -0500299pub mod token;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500300
David Tolnay4fb71232018-08-25 23:14:50 -0400301mod ident;
302pub use ident::Ident;
David Tolnaye303b7c2018-05-20 16:46:35 -0700303
David Tolnay3cfd1d32018-01-03 00:22:08 -0800304#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700305mod attr;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800306#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay161f2de2018-10-13 14:38:20 -0700307pub use attr::{AttrStyle, Attribute, AttributeArgs, Meta, MetaList, MetaNameValue, NestedMeta};
David Tolnay35161ff2016-09-03 11:33:15 -0700308
David Tolnay3cfd1d32018-01-03 00:22:08 -0800309#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf38cdf62016-09-23 19:07:09 -0700310mod data;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800311#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700312pub use data::{
313 Field, Fields, FieldsNamed, FieldsUnnamed, Variant, VisCrate, VisPublic, VisRestricted,
314 Visibility,
315};
David Tolnayf38cdf62016-09-23 19:07:09 -0700316
David Tolnay3cfd1d32018-01-03 00:22:08 -0800317#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700318mod expr;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800319#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700320pub use expr::{
David Tolnay02a9c6f2018-08-24 18:58:45 -0400321 Expr, ExprArray, ExprAssign, ExprAssignOp, ExprAsync, ExprBinary, ExprBlock, ExprBox,
322 ExprBreak, ExprCall, ExprCast, ExprClosure, ExprContinue, ExprField, ExprForLoop, ExprGroup,
David Tolnay9c119122018-09-01 18:47:02 -0700323 ExprIf, ExprInPlace, ExprIndex, ExprLet, ExprLit, ExprLoop, ExprMacro, ExprMatch,
David Tolnay02a9c6f2018-08-24 18:58:45 -0400324 ExprMethodCall, ExprParen, ExprPath, ExprRange, ExprReference, ExprRepeat, ExprReturn,
325 ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprType, ExprUnary, ExprUnsafe, ExprVerbatim,
David Tolnay9c119122018-09-01 18:47:02 -0700326 ExprWhile, ExprYield, Index, Member,
David Tolnayb57c8492018-05-05 00:32:04 -0700327};
Michael Layzell734adb42017-06-07 16:58:31 -0400328
329#[cfg(feature = "full")]
David Tolnayb57c8492018-05-05 00:32:04 -0700330pub use expr::{
331 Arm, Block, FieldPat, FieldValue, GenericMethodArgument, Label, Local, MethodTurbofish, Pat,
332 PatBox, PatIdent, PatLit, PatMacro, PatPath, PatRange, PatRef, PatSlice, PatStruct, PatTuple,
333 PatTupleStruct, PatVerbatim, PatWild, RangeLimits, Stmt,
334};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700335
David Tolnay3cfd1d32018-01-03 00:22:08 -0800336#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700337mod generics;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800338#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700339pub use generics::{
340 BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeDef, PredicateEq,
341 PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound,
342 WhereClause, WherePredicate,
343};
David Tolnaye614f282018-10-27 22:50:12 -0700344#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800345pub use generics::{ImplGenerics, Turbofish, TypeGenerics};
David Tolnay35161ff2016-09-03 11:33:15 -0700346
David Tolnayf38cdf62016-09-23 19:07:09 -0700347#[cfg(feature = "full")]
David Tolnayb79ee962016-09-04 09:39:20 -0700348mod item;
David Tolnayf38cdf62016-09-23 19:07:09 -0700349#[cfg(feature = "full")]
David Tolnayb57c8492018-05-05 00:32:04 -0700350pub use item::{
David Tolnay435c1782018-08-24 16:15:44 -0400351 ArgCaptured, ArgSelf, ArgSelfRef, FnArg, FnDecl, ForeignItem, ForeignItemFn, ForeignItemMacro,
352 ForeignItemStatic, ForeignItemType, ForeignItemVerbatim, ImplItem, ImplItemConst,
David Tolnaybb82ef02018-08-24 20:15:45 -0400353 ImplItemExistential, ImplItemMacro, ImplItemMethod, ImplItemType, ImplItemVerbatim, Item,
354 ItemConst, ItemEnum, ItemExistential, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl,
David Tolnayc6b04dd2018-08-30 23:22:51 -0700355 ItemMacro, ItemMacro2, ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType,
356 ItemUnion, ItemUse, ItemVerbatim, MethodSig, TraitItem, TraitItemConst, TraitItemMacro,
357 TraitItemMethod, TraitItemType, TraitItemVerbatim, UseGlob, UseGroup, UseName, UsePath,
358 UseRename, UseTree,
David Tolnayb57c8492018-05-05 00:32:04 -0700359};
David Tolnay35161ff2016-09-03 11:33:15 -0700360
David Tolnay631cb8c2016-11-10 17:16:41 -0800361#[cfg(feature = "full")]
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700362mod file;
David Tolnay631cb8c2016-11-10 17:16:41 -0800363#[cfg(feature = "full")]
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700364pub use file::File;
David Tolnay631cb8c2016-11-10 17:16:41 -0800365
David Tolnay63e3dee2017-06-03 20:13:17 -0700366mod lifetime;
367pub use lifetime::Lifetime;
368
David Tolnay3cfd1d32018-01-03 00:22:08 -0800369#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700370mod lit;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800371#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700372pub use lit::{
373 FloatSuffix, IntSuffix, Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr,
374 LitVerbatim, StrStyle,
375};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700376
David Tolnay3cfd1d32018-01-03 00:22:08 -0800377#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700378mod mac;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800379#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayab919512017-12-30 23:31:51 -0500380pub use mac::{Macro, MacroDelimiter};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700381
David Tolnay3cfd1d32018-01-03 00:22:08 -0800382#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay0e837402016-12-22 17:25:55 -0500383mod derive;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800384#[cfg(feature = "derive")]
David Tolnaye3d41b72017-12-31 15:24:00 -0500385pub use derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
David Tolnayf38cdf62016-09-23 19:07:09 -0700386
David Tolnay3cfd1d32018-01-03 00:22:08 -0800387#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay3cb23a92016-10-07 23:02:21 -0700388mod op;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800389#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay3cb23a92016-10-07 23:02:21 -0700390pub use op::{BinOp, UnOp};
391
David Tolnay3cfd1d32018-01-03 00:22:08 -0800392#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb79ee962016-09-04 09:39:20 -0700393mod ty;
David Tolnay3cfd1d32018-01-03 00:22:08 -0800394#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700395pub use ty::{
396 Abi, BareFnArg, BareFnArgName, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,
397 TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference,
398 TypeSlice, TypeTraitObject, TypeTuple, TypeVerbatim,
399};
David Tolnay056de302018-01-05 14:29:05 -0800400
401#[cfg(any(feature = "full", feature = "derive"))]
402mod path;
403#[cfg(any(feature = "full", feature = "derive"))]
David Tolnayb57c8492018-05-05 00:32:04 -0700404pub use path::{
David Tolnay9d0882a2018-09-01 19:49:14 -0700405 AngleBracketedGenericArguments, Binding, Constraint, GenericArgument,
406 ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
David Tolnayb57c8492018-05-05 00:32:04 -0700407};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700408
David Tolnay1b752fb2017-12-26 21:41:39 -0500409#[cfg(feature = "parsing")]
David Tolnaydfc886b2018-01-06 08:03:09 -0800410pub mod buffer;
David Tolnay94d304f2018-08-30 23:43:53 -0700411#[cfg(feature = "parsing")]
412pub mod ext;
David Tolnay94d2b792018-04-29 12:26:10 -0700413pub mod punctuated;
David Tolnaye614f282018-10-27 22:50:12 -0700414#[cfg(all(any(feature = "full", feature = "derive"), feature = "extra-traits"))]
David Tolnaye0824032017-12-27 15:25:56 -0500415mod tt;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500416
David Tolnaye83ef5a2018-01-11 15:18:36 -0800417// Not public API except the `parse_quote!` macro.
David Tolnay491680a2018-01-23 00:34:40 -0800418#[cfg(feature = "parsing")]
David Tolnaye83ef5a2018-01-11 15:18:36 -0800419#[doc(hidden)]
420pub mod parse_quote;
421
David Tolnayf98865f2018-10-13 14:37:07 -0700422// Not public API except the `parse_macro_input!` macro.
423#[cfg(all(
424 not(all(target_arch = "wasm32", target_os = "unknown")),
425 feature = "parsing",
426 feature = "proc-macro"
427))]
428#[doc(hidden)]
429pub mod parse_macro_input;
430
David Tolnay4d942b42018-01-02 22:14:04 -0800431#[cfg(all(feature = "parsing", feature = "printing"))]
David Tolnayf790b612017-12-31 18:46:57 -0500432pub mod spanned;
433
Nika Layzella6f46c42017-10-26 15:26:16 -0400434mod gen {
David Tolnayded2d682018-01-06 18:53:53 -0800435 /// Syntax tree traversal to walk a shared borrow of a syntax tree.
436 ///
437 /// Each method of the [`Visit`] trait is a hook that can be overridden to
438 /// customize the behavior when visiting the corresponding type of node. By
439 /// default, every method recursively visits the substructure of the input
440 /// by invoking the right visitor method of each of its fields.
441 ///
442 /// [`Visit`]: trait.Visit.html
443 ///
David Tolnay95989db2019-01-01 15:05:57 -0500444 /// ```edition2018
David Tolnayded2d682018-01-06 18:53:53 -0800445 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
446 /// #
447 /// pub trait Visit<'ast> {
448 /// /* ... */
449 ///
450 /// fn visit_expr_binary(&mut self, node: &'ast ExprBinary) {
451 /// for attr in &node.attrs {
452 /// self.visit_attribute(attr);
453 /// }
454 /// self.visit_expr(&*node.left);
455 /// self.visit_bin_op(&node.op);
456 /// self.visit_expr(&*node.right);
457 /// }
458 ///
459 /// /* ... */
460 /// # fn visit_attribute(&mut self, node: &'ast Attribute);
461 /// # fn visit_expr(&mut self, node: &'ast Expr);
462 /// # fn visit_bin_op(&mut self, node: &'ast BinOp);
463 /// }
464 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800465 ///
466 /// *This module is available if Syn is built with the `"visit"` feature.*
Nika Layzella6f46c42017-10-26 15:26:16 -0400467 #[cfg(feature = "visit")]
468 pub mod visit;
David Tolnay55337722016-09-11 12:58:56 -0700469
David Tolnayded2d682018-01-06 18:53:53 -0800470 /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in
471 /// place.
472 ///
473 /// Each method of the [`VisitMut`] trait is a hook that can be overridden
474 /// to customize the behavior when mutating the corresponding type of node.
475 /// By default, every method recursively visits the substructure of the
476 /// input by invoking the right visitor method of each of its fields.
477 ///
478 /// [`VisitMut`]: trait.VisitMut.html
479 ///
David Tolnay95989db2019-01-01 15:05:57 -0500480 /// ```edition2018
David Tolnayded2d682018-01-06 18:53:53 -0800481 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
482 /// #
483 /// pub trait VisitMut {
484 /// /* ... */
485 ///
486 /// fn visit_expr_binary_mut(&mut self, node: &mut ExprBinary) {
487 /// for attr in &mut node.attrs {
488 /// self.visit_attribute_mut(attr);
489 /// }
490 /// self.visit_expr_mut(&mut *node.left);
491 /// self.visit_bin_op_mut(&mut node.op);
492 /// self.visit_expr_mut(&mut *node.right);
493 /// }
494 ///
495 /// /* ... */
496 /// # fn visit_attribute_mut(&mut self, node: &mut Attribute);
497 /// # fn visit_expr_mut(&mut self, node: &mut Expr);
498 /// # fn visit_bin_op_mut(&mut self, node: &mut BinOp);
499 /// }
500 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800501 ///
502 /// *This module is available if Syn is built with the `"visit-mut"`
503 /// feature.*
David Tolnay9df02c42018-01-06 13:52:48 -0800504 #[cfg(feature = "visit-mut")]
Nika Layzella6f46c42017-10-26 15:26:16 -0400505 pub mod visit_mut;
Nika Layzell27726662017-10-24 23:16:35 -0400506
David Tolnayded2d682018-01-06 18:53:53 -0800507 /// Syntax tree traversal to transform the nodes of an owned syntax tree.
508 ///
509 /// Each method of the [`Fold`] trait is a hook that can be overridden to
510 /// customize the behavior when transforming the corresponding type of node.
511 /// By default, every method recursively visits the substructure of the
512 /// input by invoking the right visitor method of each of its fields.
513 ///
514 /// [`Fold`]: trait.Fold.html
515 ///
David Tolnay95989db2019-01-01 15:05:57 -0500516 /// ```edition2018
David Tolnayded2d682018-01-06 18:53:53 -0800517 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
518 /// #
519 /// pub trait Fold {
520 /// /* ... */
521 ///
522 /// fn fold_expr_binary(&mut self, node: ExprBinary) -> ExprBinary {
523 /// ExprBinary {
524 /// attrs: node.attrs
525 /// .into_iter()
526 /// .map(|attr| self.fold_attribute(attr))
527 /// .collect(),
528 /// left: Box::new(self.fold_expr(*node.left)),
529 /// op: self.fold_bin_op(node.op),
530 /// right: Box::new(self.fold_expr(*node.right)),
531 /// }
532 /// }
533 ///
534 /// /* ... */
535 /// # fn fold_attribute(&mut self, node: Attribute) -> Attribute;
536 /// # fn fold_expr(&mut self, node: Expr) -> Expr;
537 /// # fn fold_bin_op(&mut self, node: BinOp) -> BinOp;
538 /// }
539 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800540 ///
541 /// *This module is available if Syn is built with the `"fold"` feature.*
Nika Layzella6f46c42017-10-26 15:26:16 -0400542 #[cfg(feature = "fold")]
543 pub mod fold;
David Tolnayf60f4262017-12-28 19:17:58 -0500544
David Tolnay0a0d78c2018-01-05 15:24:01 -0800545 #[cfg(any(feature = "full", feature = "derive"))]
David Tolnayf60f4262017-12-28 19:17:58 -0500546 #[path = "../gen_helper.rs"]
547 mod helper;
Nika Layzella6f46c42017-10-26 15:26:16 -0400548}
549pub use gen::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100550
David Tolnay456c9822018-08-25 08:09:46 -0400551// Not public API.
552#[doc(hidden)]
553pub mod export;
554
David Tolnay9bfd1122019-04-14 12:43:31 -0700555mod custom_keyword;
556mod custom_punctuation;
David Tolnayb8a68e42019-04-22 14:01:56 -0700557mod sealed;
David Tolnayb6254182018-08-25 08:44:54 -0400558
559#[cfg(feature = "parsing")]
David Tolnay7fb11e72018-09-06 01:02:27 -0700560mod lookahead;
Louis Kureuil Personc0beaf32018-09-05 00:12:43 +0200561
562#[cfg(feature = "parsing")]
David Tolnayb6254182018-08-25 08:44:54 -0400563pub mod parse;
564
David Tolnay776f8e02018-08-24 22:32:10 -0400565mod span;
566
David Tolnaye614f282018-10-27 22:50:12 -0700567#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
David Tolnay64023912018-08-31 09:51:12 -0700568mod print;
569
David Tolnay32874802018-11-11 08:52:19 -0800570mod thread;
571
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700572////////////////////////////////////////////////////////////////////////////////
573
David Tolnayaa77a852018-08-31 11:15:10 -0700574#[cfg(any(feature = "parsing", feature = "full", feature = "derive"))]
David Tolnay94f06632018-08-31 10:17:17 -0700575#[allow(non_camel_case_types)]
David Tolnay10951d52018-08-31 10:27:39 -0700576struct private;
David Tolnay94f06632018-08-31 10:17:17 -0700577
578////////////////////////////////////////////////////////////////////////////////
579
David Tolnayb6254182018-08-25 08:44:54 -0400580mod error;
David Tolnayc647b7d2018-11-23 22:06:13 -0800581pub use error::{Error, Result};
David Tolnayc5ab8c62017-12-26 16:43:39 -0500582
David Tolnayccab0be2018-01-06 22:24:47 -0800583/// Parse tokens of source code into the chosen syntax tree node.
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700584///
585/// This is preferred over parsing a string because tokens are able to preserve
586/// information about where in the user's code they were originally written (the
587/// "span" of the token), possibly allowing the compiler to produce better error
588/// messages.
589///
David Tolnayccab0be2018-01-06 22:24:47 -0800590/// This function parses a `proc_macro::TokenStream` which is the type used for
591/// interop with the compiler in a procedural macro. To parse a
592/// `proc_macro2::TokenStream`, use [`syn::parse2`] instead.
593///
594/// [`syn::parse2`]: fn.parse2.html
595///
hcpl4b72a382018-04-04 14:50:24 +0300596/// *This function is available if Syn is built with both the `"parsing"` and
597/// `"proc-macro"` features.*
David Tolnay461d98e2018-01-07 11:07:19 -0800598///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700599/// # Examples
600///
David Tolnay95989db2019-01-01 15:05:57 -0500601/// ```edition2018
David Tolnaya1c98072018-09-06 08:58:10 -0700602/// extern crate proc_macro;
David Tolnaya1c98072018-09-06 08:58:10 -0700603///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700604/// use proc_macro::TokenStream;
David Tolnayfd5b1172018-12-31 17:54:36 -0500605/// use quote::quote;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700606/// use syn::DeriveInput;
607///
David Tolnaybcf26022017-12-25 22:10:52 -0500608/// # const IGNORE_TOKENS: &str = stringify! {
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700609/// #[proc_macro_derive(MyMacro)]
David Tolnaybcf26022017-12-25 22:10:52 -0500610/// # };
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700611/// pub fn my_macro(input: TokenStream) -> TokenStream {
612/// // Parse the tokens into a syntax tree
613/// let ast: DeriveInput = syn::parse(input).unwrap();
614///
615/// // Build the output, possibly using quasi-quotation
616/// let expanded = quote! {
617/// /* ... */
618/// };
619///
David Tolnaybcf26022017-12-25 22:10:52 -0500620/// // Convert into a token stream and return it
621/// expanded.into()
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700622/// }
623/// ```
David Tolnay278f9e32018-08-14 22:41:11 -0700624#[cfg(all(
625 not(all(target_arch = "wasm32", target_os = "unknown")),
626 feature = "parsing",
627 feature = "proc-macro"
628))]
David Tolnayc647b7d2018-11-23 22:06:13 -0800629pub fn parse<T: parse::Parse>(tokens: proc_macro::TokenStream) -> Result<T> {
David Tolnay80a914f2018-08-30 23:49:53 -0700630 parse::Parser::parse(T::parse, tokens)
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700631}
632
David Tolnayccab0be2018-01-06 22:24:47 -0800633/// Parse a proc-macro2 token stream into the chosen syntax tree node.
634///
635/// This function parses a `proc_macro2::TokenStream` which is commonly useful
636/// when the input comes from a node of the Syn syntax tree, for example the tts
637/// of a [`Macro`] node. When in a procedural macro parsing the
638/// `proc_macro::TokenStream` provided by the compiler, use [`syn::parse`]
639/// instead.
640///
641/// [`Macro`]: struct.Macro.html
642/// [`syn::parse`]: fn.parse.html
David Tolnay461d98e2018-01-07 11:07:19 -0800643///
644/// *This function is available if Syn is built with the `"parsing"` feature.*
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700645#[cfg(feature = "parsing")]
David Tolnayc647b7d2018-11-23 22:06:13 -0800646pub fn parse2<T: parse::Parse>(tokens: proc_macro2::TokenStream) -> Result<T> {
David Tolnay80a914f2018-08-30 23:49:53 -0700647 parse::Parser::parse2(T::parse, tokens)
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700648}
Alex Crichton954046c2017-05-30 21:49:42 -0700649
David Tolnayccab0be2018-01-06 22:24:47 -0800650/// Parse a string of Rust code into the chosen syntax tree node.
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700651///
David Tolnay461d98e2018-01-07 11:07:19 -0800652/// *This function is available if Syn is built with the `"parsing"` feature.*
653///
David Tolnay3f5b06f2018-01-11 21:02:00 -0800654/// # Hygiene
655///
656/// Every span in the resulting syntax tree will be set to resolve at the macro
657/// call site.
658///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700659/// # Examples
660///
David Tolnay95989db2019-01-01 15:05:57 -0500661/// ```edition2018
David Tolnay67fea042018-11-24 14:50:20 -0800662/// use syn::{Expr, Result};
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700663///
664/// fn run() -> Result<()> {
665/// let code = "assert_eq!(u8::max_value(), 255)";
666/// let expr = syn::parse_str::<Expr>(code)?;
667/// println!("{:#?}", expr);
668/// Ok(())
669/// }
670/// #
David Tolnayfd5b1172018-12-31 17:54:36 -0500671/// # fn main() {
672/// # run().unwrap();
673/// # }
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700674/// ```
675#[cfg(feature = "parsing")]
David Tolnayc647b7d2018-11-23 22:06:13 -0800676pub fn parse_str<T: parse::Parse>(s: &str) -> Result<T> {
David Tolnay80a914f2018-08-30 23:49:53 -0700677 parse::Parser::parse_str(T::parse, s)
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700678}
Alex Crichton954046c2017-05-30 21:49:42 -0700679
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700680// FIXME the name parse_file makes it sound like you might pass in a path to a
681// file, rather than the content.
682/// Parse the content of a file of Rust code.
683///
684/// This is different from `syn::parse_str::<File>(content)` in two ways:
685///
686/// - It discards a leading byte order mark `\u{FEFF}` if the file has one.
687/// - It preserves the shebang line of the file, such as `#!/usr/bin/env rustx`.
688///
689/// If present, either of these would be an error using `from_str`.
690///
David Tolnayc8b0e0f2019-03-07 22:46:32 -0800691/// *This function is available if Syn is built with the `"parsing"` and
692/// `"full"` features.*
David Tolnay461d98e2018-01-07 11:07:19 -0800693///
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700694/// # Examples
695///
David Tolnay95989db2019-01-01 15:05:57 -0500696/// ```edition2018,no_run
David Tolnay9b00f652018-09-01 10:31:02 -0700697/// use std::error::Error;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700698/// use std::fs::File;
699/// use std::io::Read;
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700700///
David Tolnay9b00f652018-09-01 10:31:02 -0700701/// fn run() -> Result<(), Box<Error>> {
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700702/// let mut file = File::open("path/to/code.rs")?;
703/// let mut content = String::new();
704/// file.read_to_string(&mut content)?;
705///
706/// let ast = syn::parse_file(&content)?;
707/// if let Some(shebang) = ast.shebang {
708/// println!("{}", shebang);
709/// }
710/// println!("{} items", ast.items.len());
711///
712/// Ok(())
713/// }
714/// #
David Tolnayfd5b1172018-12-31 17:54:36 -0500715/// # fn main() {
716/// # run().unwrap();
717/// # }
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700718/// ```
719#[cfg(all(feature = "parsing", feature = "full"))]
David Tolnayc647b7d2018-11-23 22:06:13 -0800720pub fn parse_file(mut content: &str) -> Result<File> {
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700721 // Strip the BOM if it is present
722 const BOM: &'static str = "\u{feff}";
723 if content.starts_with(BOM) {
724 content = &content[BOM.len()..];
David Tolnay35161ff2016-09-03 11:33:15 -0700725 }
Michael Layzell5e107ff2017-01-24 19:58:39 -0500726
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700727 let mut shebang = None;
728 if content.starts_with("#!") && !content.starts_with("#![") {
729 if let Some(idx) = content.find('\n') {
730 shebang = Some(content[..idx].to_string());
731 content = &content[idx..];
732 } else {
733 shebang = Some(content.to_string());
734 content = "";
735 }
Alex Crichton954046c2017-05-30 21:49:42 -0700736 }
David Tolnay0a8972b2017-02-27 02:10:01 -0800737
David Tolnayc7a5d3d2017-06-04 12:11:05 -0700738 let mut file: File = parse_str(content)?;
739 file.shebang = shebang;
740 Ok(file)
Michael Layzell5e107ff2017-01-24 19:58:39 -0500741}