lib.rs 33 KB

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