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