Skip to main content

syn/
lib.rs

1//! [![github]](https://github.com/dtolnay/syn) [![crates-io]](https://crates.io/crates/syn) [![docs-rs]](crate)
2//!
3//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
4//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
6//!
7//! <br>
8//!
9//! 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 use in Rust procedural macros, but
13//! contains some APIs that may be useful more generally.
14//!
15//! - **Data structures** — Syn provides a syntax tree that can represent most
16//!   stable Rust source code and some unstable syntax. The syntax tree is
17//!   rooted at [`syn::File`] which represents a full source file, but there are
18//!   other entry points that may be useful to procedural macros including
19//!   [`syn::Item`], [`syn::Expr`] and [`syn::Type`].
20//!
21//! - **Derives** — Of particular interest to derive macros 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 user-defined trait.
25//!
26//! - **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.
31//!
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`]: File
43//! [`syn::Item`]: Item
44//! [`syn::Expr`]: Expr
45//! [`syn::Type`]: Type
46//! [`syn::DeriveInput`]: DeriveInput
47//! [parser functions]: mod@parse
48//!
49//! <br>
50//!
51//! # Example of a derive macro
52//!
53//! The canonical derive macro using Syn looks like this. We write an ordinary
54//! Rust function tagged with a `proc_macro_derive` attribute and the name of
55//! the trait we are deriving. Any time that derive appears in the user's code,
56//! the Rust compiler passes their data structure as tokens into our macro. We
57//! get to execute arbitrary Rust code to figure out what to do with those
58//! tokens, then hand some tokens back to the compiler to compile into the
59//! user's crate.
60//!
61//! [`TokenStream`]: proc_macro::TokenStream
62//!
63//! ```toml
64//! # Cargo.toml
65//! [package]
66//! ...
67//!
68//! [lib]
69//! proc-macro = true
70//!
71//! [dependencies]
72//! syn = "3"
73//! quote = "1"
74//! ```
75//!
76//! ```
77//! # extern crate proc_macro;
78//! #
79//! use proc_macro::TokenStream;
80//! use quote::quote;
81//! use syn::{parse_macro_input, DeriveInput};
82//!
83//! # const IGNORE_TOKENS: &str = stringify! {
84//! #[proc_macro_derive(MyMacro)]
85//! # };
86//! pub fn my_macro(input: TokenStream) -> TokenStream {
87//!     // Parse the input tokens into a syntax tree
88//!     let input = parse_macro_input!(input as DeriveInput);
89//!
90//!     // Build the output, possibly using quasi-quotation
91//!     let expanded = quote! {
92//!         // ...
93//!     };
94//!
95//!     // Hand the output tokens back to the compiler
96//!     TokenStream::from(expanded)
97//! }
98//! ```
99//!
100//! The [`heapsize`] example directory shows a complete working implementation
101//! of a derive macro. The example derives a `HeapSize` trait which computes an
102//! estimate of the amount of heap memory owned by a value.
103//!
104//! [`heapsize`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize
105//!
106//! ```
107//! pub trait HeapSize {
108//!     /// Total number of bytes of heap memory owned by `self`.
109//!     fn heap_size_of_children(&self) -> usize;
110//! }
111//! ```
112//!
113//! The derive macro allows users to write `#[derive(HeapSize)]` on data
114//! structures in their program.
115//!
116//! ```
117//! # const IGNORE_TOKENS: &str = stringify! {
118//! #[derive(HeapSize)]
119//! # };
120//! struct Demo<'a, T: ?Sized> {
121//!     a: Box<T>,
122//!     b: u8,
123//!     c: &'a str,
124//!     d: String,
125//! }
126//! ```
127//!
128//! <p><br></p>
129//!
130//! # Spans and error reporting
131//!
132//! The token-based procedural macro API provides great control over where the
133//! compiler's error messages are displayed in user code. Consider the error the
134//! user sees if one of their field types does not implement `HeapSize`.
135//!
136//! ```
137//! # const IGNORE_TOKENS: &str = stringify! {
138//! #[derive(HeapSize)]
139//! # };
140//! struct Broken {
141//!     ok: String,
142//!     bad: std::thread::Thread,
143//! }
144//! ```
145//!
146//! By tracking span information all the way through the expansion of a
147//! procedural macro as shown in the `heapsize` example, token-based macros in
148//! Syn are able to trigger errors that directly pinpoint the source of the
149//! problem.
150//!
151//! ```text
152//! error[E0277]: the trait bound `Thread: HeapSize` is not satisfied
153//!  --> src/main.rs:9:5
154//!   |
155//! 3 | #[derive(HeapSize)]
156//!   |          -------- required by a bound introduced by this call
157//! ...
158//! 9 |     bad: std::thread::Thread,
159//!   |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `Thread`
160//!   |
161//!   = help: the following other types implement trait `HeapSize`:
162//!             &'a T
163//!             Box<T>
164//!             Demo<'a, T>
165//!             String
166//!             [T]
167//!             u8
168//! ```
169//!
170//! <br>
171//!
172//! # Parsing a custom syntax
173//!
174//! The [`lazy-static`] example directory shows the implementation of a
175//! `functionlike!(...)` procedural macro in which the input tokens are parsed
176//! using Syn's parsing API.
177//!
178//! [`lazy-static`]: https://github.com/dtolnay/syn/tree/master/examples/lazy-static
179//!
180//! The example reimplements the popular `lazy_static` crate from crates.io as a
181//! procedural macro.
182//!
183//! ```
184//! # macro_rules! lazy_static {
185//! #     ($($tt:tt)*) => {}
186//! # }
187//! #
188//! lazy_static! {
189//!     static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
190//! }
191//! ```
192//!
193//! The implementation shows how to trigger custom warnings and error messages
194//! on the macro input.
195//!
196//! ```text
197//! warning: come on, pick a more creative name
198//!   --> src/main.rs:10:16
199//!    |
200//! 10 |     static ref FOO: String = "lazy_static".to_owned();
201//!    |                ^^^
202//! ```
203//!
204//! <br>
205//!
206//! # Testing
207//!
208//! When testing macros, we often care not just that the macro can be used
209//! successfully but also that when the macro is provided with invalid input it
210//! produces maximally helpful error messages. Consider using the [`trybuild`]
211//! crate to write tests for errors that are emitted by your macro or errors
212//! detected by the Rust compiler in the expanded code following misuse of the
213//! macro. Such tests help avoid regressions from later refactors that
214//! mistakenly make an error no longer trigger or be less helpful than it used
215//! to be.
216//!
217//! [`trybuild`]: https://github.com/dtolnay/trybuild
218//!
219//! <br>
220//!
221//! # Debugging
222//!
223//! When developing a procedural macro it can be helpful to look at what the
224//! generated code looks like. Use `cargo rustc -- -Zunstable-options
225//! -Zunpretty=expanded` or the [`cargo expand`] subcommand.
226//!
227//! [`cargo expand`]: https://github.com/dtolnay/cargo-expand
228//!
229//! To show the expanded code for some crate that uses your procedural macro,
230//! run `cargo expand` from that crate. To show the expanded code for one of
231//! your own test cases, run `cargo expand --test the_test_case` where the last
232//! argument is the name of the test file without the `.rs` extension.
233//!
234//! This write-up by Brandon W Maister discusses debugging in more detail:
235//! [Debugging Rust's new Custom Derive system][debugging].
236//!
237//! [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
238//!
239//! <br>
240//!
241//! # Optional features
242//!
243//! Syn puts a lot of functionality behind optional features in order to
244//! optimize compile time for the most common use cases. The following features
245//! are available.
246//!
247//! - **`derive`** *(enabled by default)* — Data structures for representing the
248//!   possible input to a derive macro, including structs and enums and types.
249//! - **`full`** — Data structures for representing the syntax tree of all valid
250//!   Rust source code, including items and expressions.
251//! - **`parsing`** *(enabled by default)* — Ability to parse input tokens into
252//!   a syntax tree node of a chosen type.
253//! - **`printing`** *(enabled by default)* — Ability to print a syntax tree
254//!   node as tokens of Rust source code.
255//! - **`visit`** — Trait for traversing a syntax tree.
256//! - **`visit-mut`** — Trait for traversing and mutating in place a syntax
257//!   tree.
258//! - **`fold`** — Trait for transforming an owned syntax tree.
259//! - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
260//!   types.
261//! - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree
262//!   types.
263//! - **`proc-macro`** *(enabled by default)* — Runtime dependency on the
264//!   dynamic library libproc_macro from rustc toolchain.
265
266#![no_std]
267#![doc(html_root_url = "https://docs.rs/syn/3.0.2")]
268#![cfg_attr(docsrs, feature(doc_cfg), doc(auto_cfg = false))]
269#![deny(unsafe_op_in_unsafe_fn)]
270#![allow(non_camel_case_types)]
271#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
272#![allow(
273    clippy::bool_to_int_with_if,
274    clippy::cast_lossless,
275    clippy::cast_possible_truncation,
276    clippy::cast_possible_wrap,
277    clippy::cast_ptr_alignment,
278    clippy::default_trait_access,
279    clippy::derivable_impls,
280    clippy::diverging_sub_expression,
281    clippy::doc_markdown,
282    clippy::elidable_lifetime_names,
283    clippy::enum_glob_use,
284    clippy::expl_impl_clone_on_copy,
285    clippy::explicit_auto_deref,
286    clippy::fn_params_excessive_bools,
287    clippy::if_not_else,
288    clippy::inherent_to_string,
289    clippy::into_iter_without_iter,
290    clippy::items_after_statements,
291    clippy::large_enum_variant,
292    clippy::let_underscore_untyped, // https://github.com/rust-lang/rust-clippy/issues/10410
293    clippy::manual_assert,
294    clippy::manual_let_else,
295    clippy::manual_map,
296    clippy::match_like_matches_macro,
297    clippy::match_same_arms,
298    clippy::match_wildcard_for_single_variants, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
299    clippy::missing_errors_doc,
300    clippy::missing_panics_doc,
301    clippy::module_name_repetitions,
302    clippy::must_use_candidate,
303    clippy::needless_doctest_main,
304    clippy::needless_lifetimes,
305    clippy::needless_pass_by_value,
306    clippy::needless_update,
307    clippy::never_loop,
308    clippy::range_plus_one,
309    clippy::redundant_else,
310    clippy::ref_option,
311    clippy::return_self_not_must_use,
312    clippy::similar_names,
313    clippy::single_match_else,
314    clippy::struct_excessive_bools,
315    clippy::too_many_arguments,
316    clippy::too_many_lines,
317    clippy::trivially_copy_pass_by_ref,
318    clippy::type_complexity,
319    clippy::unconditional_recursion, // https://github.com/rust-lang/rust-clippy/issues/12133
320    clippy::uninhabited_references,
321    clippy::uninlined_format_args,
322    clippy::unnecessary_box_returns,
323    clippy::unnecessary_unwrap,
324    clippy::used_underscore_binding,
325    clippy::wildcard_imports,
326)]
327#![allow(unknown_lints, mismatched_lifetime_syntaxes)]
328
329extern crate alloc;
330extern crate std;
331
332extern crate self as syn;
333
334#[cfg(feature = "proc-macro")]
335extern crate proc_macro;
336
337#[macro_use]
338mod macros;
339
340#[cfg(feature = "parsing")]
341#[macro_use]
342mod group;
343
344#[macro_use]
345pub mod token;
346
347#[cfg(any(feature = "full", feature = "derive"))]
348mod attr;
349#[cfg(any(feature = "full", feature = "derive"))]
350#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
351pub use crate::attr::{AttrStyle, Attribute, Meta, MetaList, MetaNameValue};
352
353mod bigint;
354
355#[cfg(feature = "parsing")]
356#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
357pub mod buffer;
358
359#[cfg(any(
360    all(feature = "parsing", feature = "full"),
361    all(feature = "printing", any(feature = "full", feature = "derive")),
362))]
363mod classify;
364
365mod custom_keyword;
366
367mod custom_punctuation;
368
369#[cfg(any(feature = "full", feature = "derive"))]
370mod data;
371#[cfg(any(feature = "full", feature = "derive"))]
372#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
373pub use crate::data::{Field, FieldModifiers, Fields, FieldsNamed, FieldsUnnamed, Variant};
374
375#[cfg(any(feature = "full", feature = "derive"))]
376mod derive;
377#[cfg(feature = "derive")]
378#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
379pub use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
380
381mod drops;
382
383mod error;
384pub use crate::error::{Error, Result};
385
386#[cfg(any(feature = "full", feature = "derive"))]
387mod expr;
388#[cfg(feature = "full")]
389#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
390pub use crate::expr::{Arm, BlockModifiers, ClosureModifiers, Label, RangeLimits};
391#[cfg(any(feature = "full", feature = "derive"))]
392#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
393pub use crate::expr::{
394    Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprIndex, ExprLit, ExprMacro, ExprMethodCall,
395    ExprParen, ExprPath, ExprReference, ExprStruct, ExprUnary, FieldValue, Index, Member,
396};
397#[cfg(any(feature = "full", feature = "derive"))]
398#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
399pub use crate::expr::{
400    ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure, ExprConst,
401    ExprContinue, ExprForLoop, ExprGroup, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
402    ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprTuple, ExprUnsafe,
403    ExprWhile, ExprYield,
404};
405
406pub mod ext;
407
408#[cfg(feature = "full")]
409mod file;
410#[cfg(feature = "full")]
411#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
412pub use crate::file::{File, Frontmatter};
413
414#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
415mod fixup;
416
417#[cfg(any(feature = "full", feature = "derive"))]
418mod generics;
419#[cfg(any(feature = "full", feature = "derive"))]
420#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
421pub use crate::generics::{
422    BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime,
423    PredicateType, TraitBound, TraitBoundModifiers, TypeParam, TypeParamBound, WhereClause,
424    WherePredicate,
425};
426#[cfg(feature = "full")]
427#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
428pub use crate::generics::{CapturedParam, PreciseCapture};
429#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
430#[cfg_attr(
431    docsrs,
432    doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
433)]
434pub use crate::generics::{ImplGenerics, Turbofish, TypeGenerics};
435
436mod ident;
437#[doc(inline)]
438pub use crate::ident::Ident;
439
440#[cfg(feature = "full")]
441mod item;
442#[cfg(feature = "full")]
443#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
444pub use crate::item::{
445    ConstModifiers, FnArg, FnModifiers, ForeignItem, ForeignItemFn, ForeignItemMacro,
446    ForeignItemStatic, ForeignItemType, ImplItem, ImplItemConst, ImplItemFn, ImplItemMacro,
447    ImplItemType, ImplModifiers, Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn,
448    ItemForeignMod, ItemImpl, ItemMacro, ItemMod, ItemStatic, ItemStruct, ItemTrait,
449    ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver, ReceiverKind, Safety, Signature,
450    StaticMutability, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType,
451    TraitModifiers, TypeModifiers, UseGlob, UseGroup, UseName, UsePath, UseRename, UseTree,
452    Variadic, WhereClausePlacement,
453};
454
455mod lifetime;
456#[doc(inline)]
457pub use crate::lifetime::Lifetime;
458
459mod lit;
460#[doc(inline)]
461pub use crate::lit::{
462    Lit, LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitInt, LitStr,
463};
464
465#[cfg(feature = "parsing")]
466mod lookahead;
467
468#[cfg(any(feature = "full", feature = "derive"))]
469mod mac;
470#[cfg(any(feature = "full", feature = "derive"))]
471#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
472pub use crate::mac::{Macro, MacroDelimiter};
473
474#[cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))]
475#[cfg_attr(
476    docsrs,
477    doc(cfg(all(feature = "parsing", any(feature = "full", feature = "derive"))))
478)]
479pub mod meta;
480
481#[cfg(any(feature = "full", feature = "derive"))]
482mod op;
483#[cfg(any(feature = "full", feature = "derive"))]
484#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
485pub use crate::op::{BinOp, UnOp};
486
487#[cfg(feature = "parsing")]
488#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
489pub mod parse;
490
491#[cfg(all(feature = "parsing", feature = "proc-macro"))]
492mod parse_macro_input;
493
494#[cfg(all(feature = "parsing", feature = "printing"))]
495mod parse_quote;
496
497#[cfg(feature = "full")]
498mod pat;
499#[cfg(feature = "full")]
500#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
501pub use crate::pat::{
502    FieldPat, Pat, PatConst, PatGuard, PatIdent, PatLit, PatMacro, PatOr, PatParen, PatPath,
503    PatRange, PatReference, PatRest, PatSlice, PatStruct, PatTuple, PatTupleStruct, PatType,
504    PatWild,
505};
506
507#[cfg(any(feature = "full", feature = "derive"))]
508mod path;
509#[cfg(any(feature = "full", feature = "derive"))]
510#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
511pub use crate::path::{
512    AngleBracketedGenericArguments, AssocConst, AssocType, Constraint, GenericArgument,
513    ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
514};
515
516#[cfg(all(
517    any(feature = "full", feature = "derive"),
518    any(feature = "parsing", feature = "printing")
519))]
520mod precedence;
521
522#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
523mod print;
524
525pub mod punctuated;
526
527#[cfg(any(feature = "full", feature = "derive"))]
528mod restriction;
529#[cfg(any(feature = "full", feature = "derive"))]
530#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
531pub use crate::restriction::{VisRestricted, Visibility};
532
533mod sealed;
534
535#[cfg(all(feature = "parsing", feature = "derive", not(feature = "full")))]
536mod scan_expr;
537
538mod span;
539
540#[cfg(all(feature = "parsing", feature = "printing"))]
541#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))]
542pub mod spanned;
543
544#[cfg(feature = "full")]
545mod stmt;
546#[cfg(feature = "full")]
547#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
548pub use crate::stmt::{Block, Local, LocalInit, LocalModifiers, Stmt, StmtMacro};
549
550mod thread;
551
552#[cfg(all(any(feature = "full", feature = "derive"), feature = "extra-traits"))]
553mod tt;
554
555#[cfg(any(feature = "full", feature = "derive"))]
556mod ty;
557#[cfg(any(feature = "full", feature = "derive"))]
558#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
559pub use crate::ty::{
560    Abi, FnPtrVariadic, NamedArg, PointerMutability, ReturnType, Type, TypeArray, TypeFnPtr,
561    TypeGroup, TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr,
562    TypeReference, TypeSlice, TypeTraitObject, TypeTuple,
563};
564
565#[cfg(all(any(feature = "full", feature = "derive"), feature = "parsing"))]
566mod verbatim;
567
568#[cfg(all(feature = "parsing", feature = "full"))]
569mod whitespace;
570
571#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/6176
572mod gen {
573    /// Syntax tree traversal to transform the nodes of an owned syntax tree.
574    ///
575    /// Each method of the [`Fold`] trait is a hook that can be overridden to
576    /// customize the behavior when transforming the corresponding type of node.
577    /// By default, every method recursively visits the substructure of the
578    /// input by invoking the right visitor method of each of its fields.
579    ///
580    /// [`Fold`]: fold::Fold
581    ///
582    /// ```
583    /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
584    /// #
585    /// pub trait Fold {
586    ///     /* ... */
587    ///
588    ///     fn fold_expr_binary(&mut self, node: ExprBinary) -> ExprBinary {
589    ///         fold_expr_binary(self, node)
590    ///     }
591    ///
592    ///     /* ... */
593    ///     # fn fold_attribute(&mut self, node: Attribute) -> Attribute;
594    ///     # fn fold_expr(&mut self, node: Expr) -> Expr;
595    ///     # fn fold_bin_op(&mut self, node: BinOp) -> BinOp;
596    /// }
597    ///
598    /// pub fn fold_expr_binary<V>(v: &mut V, node: ExprBinary) -> ExprBinary
599    /// where
600    ///     V: Fold + ?Sized,
601    /// {
602    ///     ExprBinary {
603    ///         attrs: node
604    ///             .attrs
605    ///             .into_iter()
606    ///             .map(|attr| v.fold_attribute(attr))
607    ///             .collect(),
608    ///         left: Box::new(v.fold_expr(*node.left)),
609    ///         op: v.fold_bin_op(node.op),
610    ///         right: Box::new(v.fold_expr(*node.right)),
611    ///     }
612    /// }
613    ///
614    /// /* ... */
615    /// ```
616    ///
617    /// <br>
618    ///
619    /// # Example
620    ///
621    /// This fold inserts parentheses to fully parenthesizes any expression.
622    ///
623    /// ```
624    /// // [dependencies]
625    /// // quote = "1"
626    /// // syn = { version = "3", features = ["fold", "full"] }
627    ///
628    /// use quote::quote;
629    /// use syn::fold::{fold_expr, Fold};
630    /// use syn::{token, Expr, ExprParen};
631    ///
632    /// struct ParenthesizeEveryExpr;
633    ///
634    /// impl Fold for ParenthesizeEveryExpr {
635    ///     fn fold_expr(&mut self, expr: Expr) -> Expr {
636    ///         Expr::Paren(ExprParen {
637    ///             attrs: Vec::new(),
638    ///             expr: Box::new(fold_expr(self, expr)),
639    ///             paren_token: token::Paren::default(),
640    ///         })
641    ///     }
642    /// }
643    ///
644    /// fn main() {
645    ///     let code = quote! { a() + b(1) * c.d };
646    ///     let expr: Expr = syn::parse2(code).unwrap();
647    ///     let parenthesized = ParenthesizeEveryExpr.fold_expr(expr);
648    ///     println!("{}", quote!(#parenthesized));
649    ///
650    ///     // Output: (((a)()) + (((b)((1))) * ((c).d)))
651    /// }
652    /// ```
653    #[cfg(feature = "fold")]
654    #[cfg_attr(docsrs, doc(cfg(feature = "fold")))]
655    #[rustfmt::skip]
656    pub mod fold;
657
658    /// Syntax tree traversal to walk a shared borrow of a syntax tree.
659    ///
660    /// Each method of the [`Visit`] trait is a hook that can be overridden to
661    /// customize the behavior when visiting the corresponding type of node. By
662    /// default, every method recursively visits the substructure of the input
663    /// by invoking the right visitor method of each of its fields.
664    ///
665    /// [`Visit`]: visit::Visit
666    ///
667    /// ```
668    /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
669    /// #
670    /// pub trait Visit<'ast> {
671    ///     /* ... */
672    ///
673    ///     fn visit_expr_binary(&mut self, node: &'ast ExprBinary) {
674    ///         visit_expr_binary(self, node);
675    ///     }
676    ///
677    ///     /* ... */
678    ///     # fn visit_attribute(&mut self, node: &'ast Attribute);
679    ///     # fn visit_expr(&mut self, node: &'ast Expr);
680    ///     # fn visit_bin_op(&mut self, node: &'ast BinOp);
681    /// }
682    ///
683    /// pub fn visit_expr_binary<'ast, V>(v: &mut V, node: &'ast ExprBinary)
684    /// where
685    ///     V: Visit<'ast> + ?Sized,
686    /// {
687    ///     for attr in &node.attrs {
688    ///         v.visit_attribute(attr);
689    ///     }
690    ///     v.visit_expr(&*node.left);
691    ///     v.visit_bin_op(&node.op);
692    ///     v.visit_expr(&*node.right);
693    /// }
694    ///
695    /// /* ... */
696    /// ```
697    ///
698    /// <br>
699    ///
700    /// # Example
701    ///
702    /// This visitor will print the name of every freestanding function in the
703    /// syntax tree, including nested functions.
704    ///
705    /// ```
706    /// // [dependencies]
707    /// // quote = "1"
708    /// // syn = { version = "3", features = ["full", "visit"] }
709    ///
710    /// use quote::quote;
711    /// use syn::visit::{self, Visit};
712    /// use syn::{File, ItemFn};
713    ///
714    /// struct FnVisitor;
715    ///
716    /// impl<'ast> Visit<'ast> for FnVisitor {
717    ///     fn visit_item_fn(&mut self, node: &'ast ItemFn) {
718    ///         println!("Function with name={}", node.sig.ident);
719    ///
720    ///         // Delegate to the default impl to visit any nested functions.
721    ///         visit::visit_item_fn(self, node);
722    ///     }
723    /// }
724    ///
725    /// fn main() {
726    ///     let code = quote! {
727    ///         pub fn f() {
728    ///             fn g() {}
729    ///         }
730    ///     };
731    ///
732    ///     let syntax_tree: File = syn::parse2(code).unwrap();
733    ///     FnVisitor.visit_file(&syntax_tree);
734    /// }
735    /// ```
736    ///
737    /// The `'ast` lifetime on the input references means that the syntax tree
738    /// outlives the complete recursive visit call, so the visitor is allowed to
739    /// hold on to references into the syntax tree.
740    ///
741    /// ```
742    /// use quote::quote;
743    /// use syn::visit::{self, Visit};
744    /// use syn::{File, ItemFn};
745    ///
746    /// struct FnVisitor<'ast> {
747    ///     functions: Vec<&'ast ItemFn>,
748    /// }
749    ///
750    /// impl<'ast> Visit<'ast> for FnVisitor<'ast> {
751    ///     fn visit_item_fn(&mut self, node: &'ast ItemFn) {
752    ///         self.functions.push(node);
753    ///         visit::visit_item_fn(self, node);
754    ///     }
755    /// }
756    ///
757    /// fn main() {
758    ///     let code = quote! {
759    ///         pub fn f() {
760    ///             fn g() {}
761    ///         }
762    ///     };
763    ///
764    ///     let syntax_tree: File = syn::parse2(code).unwrap();
765    ///     let mut visitor = FnVisitor { functions: Vec::new() };
766    ///     visitor.visit_file(&syntax_tree);
767    ///     for f in visitor.functions {
768    ///         println!("Function with name={}", f.sig.ident);
769    ///     }
770    /// }
771    /// ```
772    #[cfg(feature = "visit")]
773    #[cfg_attr(docsrs, doc(cfg(feature = "visit")))]
774    #[rustfmt::skip]
775    pub mod visit;
776
777    /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in
778    /// place.
779    ///
780    /// Each method of the [`VisitMut`] trait is a hook that can be overridden
781    /// to customize the behavior when mutating the corresponding type of node.
782    /// By default, every method recursively visits the substructure of the
783    /// input by invoking the right visitor method of each of its fields.
784    ///
785    /// [`VisitMut`]: visit_mut::VisitMut
786    ///
787    /// ```
788    /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
789    /// #
790    /// pub trait VisitMut {
791    ///     /* ... */
792    ///
793    ///     fn visit_expr_binary_mut(&mut self, node: &mut ExprBinary) {
794    ///         visit_expr_binary_mut(self, node);
795    ///     }
796    ///
797    ///     /* ... */
798    ///     # fn visit_attribute_mut(&mut self, node: &mut Attribute);
799    ///     # fn visit_expr_mut(&mut self, node: &mut Expr);
800    ///     # fn visit_bin_op_mut(&mut self, node: &mut BinOp);
801    /// }
802    ///
803    /// pub fn visit_expr_binary_mut<V>(v: &mut V, node: &mut ExprBinary)
804    /// where
805    ///     V: VisitMut + ?Sized,
806    /// {
807    ///     for attr in &mut node.attrs {
808    ///         v.visit_attribute_mut(attr);
809    ///     }
810    ///     v.visit_expr_mut(&mut *node.left);
811    ///     v.visit_bin_op_mut(&mut node.op);
812    ///     v.visit_expr_mut(&mut *node.right);
813    /// }
814    ///
815    /// /* ... */
816    /// ```
817    ///
818    /// <br>
819    ///
820    /// # Example
821    ///
822    /// This mut visitor replace occurrences of u256 suffixed integer literals
823    /// like `999u256` with a macro invocation `bigint::u256!(999)`.
824    ///
825    /// ```
826    /// // [dependencies]
827    /// // quote = "1"
828    /// // syn = { version = "3", features = ["full", "visit-mut"] }
829    ///
830    /// use quote::quote;
831    /// use syn::visit_mut::{self, VisitMut};
832    /// use syn::{parse_quote, Expr, File, Lit, LitInt};
833    ///
834    /// struct BigintReplace;
835    ///
836    /// impl VisitMut for BigintReplace {
837    ///     fn visit_expr_mut(&mut self, node: &mut Expr) {
838    ///         if let Expr::Lit(expr) = &node {
839    ///             if let Lit::Int(int) = &expr.lit {
840    ///                 if int.suffix() == "u256" {
841    ///                     let digits = int.base10_digits();
842    ///                     let unsuffixed: LitInt = syn::parse_str(digits).unwrap();
843    ///                     *node = parse_quote!(bigint::u256!(#unsuffixed));
844    ///                     return;
845    ///                 }
846    ///             }
847    ///         }
848    ///
849    ///         // Delegate to the default impl to visit nested expressions.
850    ///         visit_mut::visit_expr_mut(self, node);
851    ///     }
852    /// }
853    ///
854    /// fn main() {
855    ///     let code = quote! {
856    ///         fn main() {
857    ///             let _ = 999u256;
858    ///         }
859    ///     };
860    ///
861    ///     let mut syntax_tree: File = syn::parse2(code).unwrap();
862    ///     BigintReplace.visit_file_mut(&mut syntax_tree);
863    ///     println!("{}", quote!(#syntax_tree));
864    /// }
865    /// ```
866    #[cfg(feature = "visit-mut")]
867    #[cfg_attr(docsrs, doc(cfg(feature = "visit-mut")))]
868    #[rustfmt::skip]
869    pub mod visit_mut;
870
871    #[cfg(feature = "clone-impls")]
872    #[rustfmt::skip]
873    mod clone;
874
875    #[cfg(feature = "extra-traits")]
876    #[rustfmt::skip]
877    mod debug;
878
879    #[cfg(feature = "extra-traits")]
880    #[rustfmt::skip]
881    mod eq;
882
883    #[cfg(feature = "extra-traits")]
884    #[rustfmt::skip]
885    mod hash;
886}
887
888#[cfg(feature = "fold")]
889#[cfg_attr(docsrs, doc(cfg(feature = "fold")))]
890pub use crate::gen::fold;
891
892#[cfg(feature = "visit")]
893#[cfg_attr(docsrs, doc(cfg(feature = "visit")))]
894pub use crate::gen::visit;
895
896#[cfg(feature = "visit-mut")]
897#[cfg_attr(docsrs, doc(cfg(feature = "visit-mut")))]
898pub use crate::gen::visit_mut;
899
900// Not public API.
901#[doc(hidden)]
902#[path = "export.rs"]
903pub mod __private;
904
905#[cfg(all(feature = "parsing", feature = "full"))]
906use alloc::string::ToString;
907
908/// Parse tokens of source code into the chosen syntax tree node.
909///
910/// This is preferred over parsing a string because tokens are able to preserve
911/// information about where in the user's code they were originally written (the
912/// "span" of the token), possibly allowing the compiler to produce better error
913/// messages.
914///
915/// This function parses a `proc_macro::TokenStream` which is the type used for
916/// interop with the compiler in a procedural macro. To parse a
917/// `proc_macro2::TokenStream`, use [`syn::parse2`] instead.
918///
919/// [`syn::parse2`]: parse2
920///
921/// This function enforces that the input is fully parsed. If there are any
922/// unparsed tokens at the end of the stream, an error is returned.
923#[cfg(all(feature = "parsing", feature = "proc-macro"))]
924#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))]
925pub fn parse<T: parse::Parse>(tokens: proc_macro::TokenStream) -> Result<T> {
926    parse::Parser::parse(T::parse, tokens)
927}
928
929/// Parse a proc-macro2 token stream into the chosen syntax tree node.
930///
931/// This function parses a `proc_macro2::TokenStream` which is commonly useful
932/// when the input comes from a node of the Syn syntax tree, for example the
933/// body tokens of a [`Macro`] node. When in a procedural macro parsing the
934/// `proc_macro::TokenStream` provided by the compiler, use [`syn::parse`]
935/// instead.
936///
937/// [`syn::parse`]: parse()
938///
939/// This function enforces that the input is fully parsed. If there are any
940/// unparsed tokens at the end of the stream, an error is returned.
941#[cfg(feature = "parsing")]
942#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
943pub fn parse2<T: parse::Parse>(tokens: proc_macro2::TokenStream) -> Result<T> {
944    parse::Parser::parse2(T::parse, tokens)
945}
946
947/// Parse a string of Rust code into the chosen syntax tree node.
948///
949/// This function enforces that the input is fully parsed. If there are any
950/// unparsed tokens at the end of the stream, an error is returned.
951///
952/// # Hygiene
953///
954/// Every span in the resulting syntax tree will be set to resolve at the macro
955/// call site.
956///
957/// # Examples
958///
959/// ```
960/// use syn::{Expr, Result};
961///
962/// fn run() -> Result<()> {
963///     let code = "assert_eq!(u8::max_value(), 255)";
964///     let expr = syn::parse_str::<Expr>(code)?;
965///     println!("{:#?}", expr);
966///     Ok(())
967/// }
968/// #
969/// # run().unwrap();
970/// ```
971#[cfg(feature = "parsing")]
972#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
973pub fn parse_str<T: parse::Parse>(s: &str) -> Result<T> {
974    parse::Parser::parse_str(T::parse, s)
975}
976
977/// Parse the content of a file of Rust code.
978///
979/// This is different from `syn::parse_str::<File>(content)` in two ways:
980///
981/// - It discards a leading byte order mark `\u{FEFF}` if the file has one.
982/// - It preserves the shebang line of the file, such as `#!/usr/bin/env rustx`.
983///
984/// If present, either of these would be an error using `from_str`.
985///
986/// # Examples
987///
988/// ```no_run
989/// use std::error::Error;
990/// use std::fs;
991/// use std::io::Read;
992///
993/// fn run() -> Result<(), Box<dyn Error>> {
994///     let content = fs::read_to_string("path/to/code.rs")?;
995///     let ast = syn::parse_file(&content)?;
996///     if let Some(shebang) = ast.shebang {
997///         println!("{}", shebang);
998///     }
999///     println!("{} items", ast.items.len());
1000///
1001///     Ok(())
1002/// }
1003/// #
1004/// # run().unwrap();
1005/// ```
1006#[cfg(all(feature = "parsing", feature = "full"))]
1007#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "full"))))]
1008pub fn parse_file(mut content: &str) -> Result<File> {
1009    // Strip the BOM if it is present
1010    const BOM: &str = "\u{feff}";
1011    if content.starts_with(BOM) {
1012        content = &content[BOM.len()..];
1013    }
1014
1015    let mut shebang = None;
1016    if content.starts_with("#!") {
1017        let rest = whitespace::skip(&content[2..]);
1018        if !rest.starts_with('[') {
1019            if let Some(idx) = content.find('\n') {
1020                shebang = Some(content[..idx].to_string());
1021                content = &content[idx..];
1022            } else {
1023                shebang = Some(content.to_string());
1024                content = "";
1025            }
1026        }
1027    }
1028
1029    let mut file: File = parse_str(content)?;
1030    file.shebang = shebang;
1031    Ok(file)
1032}