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