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