1 //! Syn is a parsing library for parsing a stream of Rust tokens into a syntax
2 //! tree of Rust source code.
3 //!
4 //! Currently this library is geared toward use in Rust procedural macros, but
5 //! contains some APIs that may be useful more generally.
6 //!
7 //! - **Data structures** — Syn provides a complete syntax tree that can
8 //!   represent any valid Rust source code. The syntax tree is rooted at
9 //!   [`syn::File`] which represents a full source file, but there are other
10 //!   entry points that may be useful to procedural macros including
11 //!   [`syn::Item`], [`syn::Expr`] and [`syn::Type`].
12 //!
13 //! - **Custom derives** — Of particular interest to custom derives is
14 //!   [`syn::DeriveInput`] which is any of the three legal input items to a
15 //!   derive macro. An example below shows using this type in a library that can
16 //!   derive implementations of a trait of your own.
17 //!
18 //! - **Parsing** — Parsing in Syn is built around [parser functions] with the
19 //!   signature `fn(ParseStream) -> Result<T>`. Every syntax tree node defined
20 //!   by Syn is individually parsable and may be used as a building block for
21 //!   custom syntaxes, or you may dream up your own brand new syntax without
22 //!   involving any of our syntax tree types.
23 //!
24 //! - **Location information** — Every token parsed by Syn is associated with a
25 //!   `Span` that tracks line and column information back to the source of that
26 //!   token. These spans allow a procedural macro to display detailed error
27 //!   messages pointing to all the right places in the user's code. There is an
28 //!   example of this below.
29 //!
30 //! - **Feature flags** — Functionality is aggressively feature gated so your
31 //!   procedural macros enable only what they need, and do not pay in compile
32 //!   time for all the rest.
33 //!
34 //! [`syn::File`]: struct.File.html
35 //! [`syn::Item`]: enum.Item.html
36 //! [`syn::Expr`]: enum.Expr.html
37 //! [`syn::Type`]: enum.Type.html
38 //! [`syn::DeriveInput`]: struct.DeriveInput.html
39 //! [parser functions]: parse/index.html
40 //!
41 //! *Version requirement: Syn supports any compiler version back to Rust's very
42 //! first support for procedural macros in Rust 1.15.0. Some features especially
43 //! around error reporting are only available in newer compilers or on the
44 //! nightly channel.*
45 //!
46 //! ## Example of a custom derive
47 //!
48 //! The canonical custom derive using Syn looks like this. We write an ordinary
49 //! Rust function tagged with a `proc_macro_derive` attribute and the name of
50 //! the trait we are deriving. Any time that derive appears in the user's code,
51 //! the Rust compiler passes their data structure as tokens into our macro. We
52 //! get to execute arbitrary Rust code to figure out what to do with those
53 //! tokens, then hand some tokens back to the compiler to compile into the
54 //! user's crate.
55 //!
56 //! [`TokenStream`]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html
57 //!
58 //! ```toml
59 //! [dependencies]
60 //! syn = "0.15"
61 //! quote = "0.6"
62 //!
63 //! [lib]
64 //! proc-macro = true
65 //! ```
66 //!
67 //! ```edition2018
68 //! extern crate proc_macro;
69 //!
70 //! use proc_macro::TokenStream;
71 //! use quote::quote;
72 //! use syn::{parse_macro_input, DeriveInput};
73 //!
74 //! # const IGNORE_TOKENS: &str = stringify! {
75 //! #[proc_macro_derive(MyMacro)]
76 //! # };
77 //! pub fn my_macro(input: TokenStream) -> TokenStream {
78 //!     // Parse the input tokens into a syntax tree
79 //!     let input = parse_macro_input!(input as DeriveInput);
80 //!
81 //!     // Build the output, possibly using quasi-quotation
82 //!     let expanded = quote! {
83 //!         // ...
84 //!     };
85 //!
86 //!     // Hand the output tokens back to the compiler
87 //!     TokenStream::from(expanded)
88 //! }
89 //! ```
90 //!
91 //! The [`heapsize`] example directory shows a complete working Macros 1.1
92 //! implementation of a custom derive. It works on any Rust compiler 1.15+.
93 //! The example derives a `HeapSize` trait which computes an estimate of the
94 //! amount of heap memory owned by a value.
95 //!
96 //! [`heapsize`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize
97 //!
98 //! ```edition2018
99 //! pub trait HeapSize {
100 //!     /// Total number of bytes of heap memory owned by `self`.
101 //!     fn heap_size_of_children(&self) -> usize;
102 //! }
103 //! ```
104 //!
105 //! The custom derive allows users to write `#[derive(HeapSize)]` on data
106 //! structures in their program.
107 //!
108 //! ```edition2018
109 //! # const IGNORE_TOKENS: &str = stringify! {
110 //! #[derive(HeapSize)]
111 //! # };
112 //! struct Demo<'a, T: ?Sized> {
113 //!     a: Box<T>,
114 //!     b: u8,
115 //!     c: &'a str,
116 //!     d: String,
117 //! }
118 //! ```
119 //!
120 //! ## Spans and error reporting
121 //!
122 //! The token-based procedural macro API provides great control over where the
123 //! compiler's error messages are displayed in user code. Consider the error the
124 //! user sees if one of their field types does not implement `HeapSize`.
125 //!
126 //! ```edition2018
127 //! # const IGNORE_TOKENS: &str = stringify! {
128 //! #[derive(HeapSize)]
129 //! # };
130 //! struct Broken {
131 //!     ok: String,
132 //!     bad: std::thread::Thread,
133 //! }
134 //! ```
135 //!
136 //! By tracking span information all the way through the expansion of a
137 //! procedural macro as shown in the `heapsize` example, token-based macros in
138 //! Syn are able to trigger errors that directly pinpoint the source of the
139 //! problem.
140 //!
141 //! ```text
142 //! error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
143 //!  --> src/main.rs:7:5
144 //!   |
145 //! 7 |     bad: std::thread::Thread,
146 //!   |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `Thread`
147 //! ```
148 //!
149 //! ## Parsing a custom syntax
150 //!
151 //! The [`lazy-static`] example directory shows the implementation of a
152 //! `functionlike!(...)` procedural macro in which the input tokens are parsed
153 //! using Syn's parsing API.
154 //!
155 //! [`lazy-static`]: https://github.com/dtolnay/syn/tree/master/examples/lazy-static
156 //!
157 //! The example reimplements the popular `lazy_static` crate from crates.io as a
158 //! procedural macro.
159 //!
160 //! ```edition2018
161 //! # macro_rules! lazy_static {
162 //! #     ($($tt:tt)*) => {}
163 //! # }
164 //! #
165 //! lazy_static! {
166 //!     static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
167 //! }
168 //! ```
169 //!
170 //! The implementation shows how to trigger custom warnings and error messages
171 //! on the macro input.
172 //!
173 //! ```text
174 //! warning: come on, pick a more creative name
175 //!   --> src/main.rs:10:16
176 //!    |
177 //! 10 |     static ref FOO: String = "lazy_static".to_owned();
178 //!    |                ^^^
179 //! ```
180 //!
181 //! ## Testing
182 //!
183 //! When testing macros, we often care not just that the macro can be used
184 //! successfully but also that when the macro is provided with invalid input it
185 //! produces maximally helpful error messages. Consider using the [`trybuild`]
186 //! crate to write tests for errors that are emitted by your macro or errors
187 //! detected by the Rust compiler in the expanded code following misuse of the
188 //! macro. Such tests help avoid regressions from later refactors that
189 //! mistakenly make an error no longer trigger or be less helpful than it used
190 //! to be.
191 //!
192 //! [`trybuild`]: https://github.com/dtolnay/trybuild
193 //!
194 //! ## Debugging
195 //!
196 //! When developing a procedural macro it can be helpful to look at what the
197 //! generated code looks like. Use `cargo rustc -- -Zunstable-options
198 //! --pretty=expanded` or the [`cargo expand`] subcommand.
199 //!
200 //! [`cargo expand`]: https://github.com/dtolnay/cargo-expand
201 //!
202 //! To show the expanded code for some crate that uses your procedural macro,
203 //! run `cargo expand` from that crate. To show the expanded code for one of
204 //! your own test cases, run `cargo expand --test the_test_case` where the last
205 //! argument is the name of the test file without the `.rs` extension.
206 //!
207 //! This write-up by Brandon W Maister discusses debugging in more detail:
208 //! [Debugging Rust's new Custom Derive system][debugging].
209 //!
210 //! [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
211 //!
212 //! ## Optional features
213 //!
214 //! Syn puts a lot of functionality behind optional features in order to
215 //! optimize compile time for the most common use cases. The following features
216 //! are available.
217 //!
218 //! - **`derive`** *(enabled by default)* — Data structures for representing the
219 //!   possible input to a custom derive, including structs and enums and types.
220 //! - **`full`** — Data structures for representing the syntax tree of all valid
221 //!   Rust source code, including items and expressions.
222 //! - **`parsing`** *(enabled by default)* — Ability to parse input tokens into
223 //!   a syntax tree node of a chosen type.
224 //! - **`printing`** *(enabled by default)* — Ability to print a syntax tree
225 //!   node as tokens of Rust source code.
226 //! - **`visit`** — Trait for traversing a syntax tree.
227 //! - **`visit-mut`** — Trait for traversing and mutating in place a syntax
228 //!   tree.
229 //! - **`fold`** — Trait for transforming an owned syntax tree.
230 //! - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
231 //!   types.
232 //! - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree
233 //!   types.
234 //! - **`proc-macro`** *(enabled by default)* — Runtime dependency on the
235 //!   dynamic library libproc_macro from rustc toolchain.
236 
237 // Syn types in rustdoc of other crates get linked to here.
238 #![doc(html_root_url = "https://docs.rs/syn/0.15.44")]
239 #![allow(unknown_lints, bare_trait_objects, ellipsis_inclusive_range_patterns)]
240 #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
241 #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
242 // Ignored clippy lints.
243 #![cfg_attr(
244     feature = "cargo-clippy",
245     allow(
246         block_in_if_condition_stmt,
247         cognitive_complexity,
248         deprecated_cfg_attr,
249         doc_markdown,
250         eval_order_dependence,
251         large_enum_variant,
252         needless_pass_by_value,
253         never_loop,
254         redundant_field_names,
255         redundant_static_lifetimes,
256         too_many_arguments,
257     )
258 )]
259 // Ignored clippy_pedantic lints.
260 #![cfg_attr(
261     feature = "cargo-clippy",
262     allow(
263         cast_possible_truncation,
264         cast_possible_wrap,
265         empty_enum,
266         if_not_else,
267         items_after_statements,
268         module_name_repetitions,
269         shadow_unrelated,
270         similar_names,
271         single_match_else,
272         unseparated_literal_suffix,
273         use_self,
274         used_underscore_binding,
275     )
276 )]
277 
278 #[cfg(all(
279     not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
280     feature = "proc-macro"
281 ))]
282 extern crate proc_macro;
283 extern crate proc_macro2;
284 extern crate unicode_xid;
285 
286 #[cfg(feature = "printing")]
287 extern crate quote;
288 
289 #[macro_use]
290 mod macros;
291 
292 // Not public API.
293 #[cfg(feature = "parsing")]
294 #[doc(hidden)]
295 #[macro_use]
296 pub mod group;
297 
298 #[macro_use]
299 pub mod token;
300 
301 mod ident;
302 pub use ident::Ident;
303 
304 #[cfg(any(feature = "full", feature = "derive"))]
305 mod attr;
306 #[cfg(any(feature = "full", feature = "derive"))]
307 pub use attr::{AttrStyle, Attribute, AttributeArgs, Meta, MetaList, MetaNameValue, NestedMeta};
308 
309 #[cfg(any(feature = "full", feature = "derive"))]
310 mod data;
311 #[cfg(any(feature = "full", feature = "derive"))]
312 pub use data::{
313     Field, Fields, FieldsNamed, FieldsUnnamed, Variant, VisCrate, VisPublic, VisRestricted,
314     Visibility,
315 };
316 
317 #[cfg(any(feature = "full", feature = "derive"))]
318 mod expr;
319 #[cfg(any(feature = "full", feature = "derive"))]
320 pub use expr::{
321     Expr, ExprArray, ExprAssign, ExprAssignOp, ExprAsync, ExprBinary, ExprBlock, ExprBox,
322     ExprBreak, ExprCall, ExprCast, ExprClosure, ExprContinue, ExprField, ExprForLoop, ExprGroup,
323     ExprIf, ExprInPlace, ExprIndex, ExprLet, ExprLit, ExprLoop, ExprMacro, ExprMatch,
324     ExprMethodCall, ExprParen, ExprPath, ExprRange, ExprReference, ExprRepeat, ExprReturn,
325     ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprType, ExprUnary, ExprUnsafe, ExprVerbatim,
326     ExprWhile, ExprYield, Index, Member,
327 };
328 
329 #[cfg(feature = "full")]
330 pub use expr::{
331     Arm, Block, FieldPat, FieldValue, GenericMethodArgument, Label, Local, MethodTurbofish, Pat,
332     PatBox, PatIdent, PatLit, PatMacro, PatPath, PatRange, PatRef, PatSlice, PatStruct, PatTuple,
333     PatTupleStruct, PatVerbatim, PatWild, RangeLimits, Stmt,
334 };
335 
336 #[cfg(any(feature = "full", feature = "derive"))]
337 mod generics;
338 #[cfg(any(feature = "full", feature = "derive"))]
339 pub use generics::{
340     BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeDef, PredicateEq,
341     PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound,
342     WhereClause, WherePredicate,
343 };
344 #[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
345 pub use generics::{ImplGenerics, Turbofish, TypeGenerics};
346 
347 #[cfg(feature = "full")]
348 mod item;
349 #[cfg(feature = "full")]
350 pub use item::{
351     ArgCaptured, ArgSelf, ArgSelfRef, FnArg, FnDecl, ForeignItem, ForeignItemFn, ForeignItemMacro,
352     ForeignItemStatic, ForeignItemType, ForeignItemVerbatim, ImplItem, ImplItemConst,
353     ImplItemExistential, ImplItemMacro, ImplItemMethod, ImplItemType, ImplItemVerbatim, Item,
354     ItemConst, ItemEnum, ItemExistential, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl,
355     ItemMacro, ItemMacro2, ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType,
356     ItemUnion, ItemUse, ItemVerbatim, MethodSig, TraitItem, TraitItemConst, TraitItemMacro,
357     TraitItemMethod, TraitItemType, TraitItemVerbatim, UseGlob, UseGroup, UseName, UsePath,
358     UseRename, UseTree,
359 };
360 
361 #[cfg(feature = "full")]
362 mod file;
363 #[cfg(feature = "full")]
364 pub use file::File;
365 
366 mod lifetime;
367 pub use lifetime::Lifetime;
368 
369 #[cfg(any(feature = "full", feature = "derive"))]
370 mod lit;
371 #[cfg(any(feature = "full", feature = "derive"))]
372 pub use lit::{
373     FloatSuffix, IntSuffix, Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr,
374     LitVerbatim, StrStyle,
375 };
376 
377 #[cfg(any(feature = "full", feature = "derive"))]
378 mod mac;
379 #[cfg(any(feature = "full", feature = "derive"))]
380 pub use mac::{Macro, MacroDelimiter};
381 
382 #[cfg(any(feature = "full", feature = "derive"))]
383 mod derive;
384 #[cfg(feature = "derive")]
385 pub use derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
386 
387 #[cfg(any(feature = "full", feature = "derive"))]
388 mod op;
389 #[cfg(any(feature = "full", feature = "derive"))]
390 pub use op::{BinOp, UnOp};
391 
392 #[cfg(any(feature = "full", feature = "derive"))]
393 mod ty;
394 #[cfg(any(feature = "full", feature = "derive"))]
395 pub use ty::{
396     Abi, BareFnArg, BareFnArgName, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,
397     TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference,
398     TypeSlice, TypeTraitObject, TypeTuple, TypeVerbatim,
399 };
400 
401 #[cfg(any(feature = "full", feature = "derive"))]
402 mod path;
403 #[cfg(any(feature = "full", feature = "derive"))]
404 pub use path::{
405     AngleBracketedGenericArguments, Binding, Constraint, GenericArgument,
406     ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
407 };
408 
409 #[cfg(feature = "parsing")]
410 pub mod buffer;
411 #[cfg(feature = "parsing")]
412 pub mod ext;
413 pub mod punctuated;
414 #[cfg(all(any(feature = "full", feature = "derive"), feature = "extra-traits"))]
415 mod tt;
416 
417 // Not public API except the `parse_quote!` macro.
418 #[cfg(feature = "parsing")]
419 #[doc(hidden)]
420 pub mod parse_quote;
421 
422 // Not public API except the `parse_macro_input!` macro.
423 #[cfg(all(
424     not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
425     feature = "parsing",
426     feature = "proc-macro"
427 ))]
428 #[doc(hidden)]
429 pub mod parse_macro_input;
430 
431 #[cfg(all(feature = "parsing", feature = "printing"))]
432 pub mod spanned;
433 
434 mod gen {
435     /// Syntax tree traversal to walk a shared borrow of a syntax tree.
436     ///
437     /// Each method of the [`Visit`] trait is a hook that can be overridden to
438     /// customize the behavior when visiting the corresponding type of node. By
439     /// default, every method recursively visits the substructure of the input
440     /// by invoking the right visitor method of each of its fields.
441     ///
442     /// [`Visit`]: visit::Visit
443     ///
444     /// ```edition2018
445     /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
446     /// #
447     /// pub trait Visit<'ast> {
448     ///     /* ... */
449     ///
450     ///     fn visit_expr_binary(&mut self, node: &'ast ExprBinary) {
451     ///         for attr in &node.attrs {
452     ///             self.visit_attribute(attr);
453     ///         }
454     ///         self.visit_expr(&*node.left);
455     ///         self.visit_bin_op(&node.op);
456     ///         self.visit_expr(&*node.right);
457     ///     }
458     ///
459     ///     /* ... */
460     ///     # fn visit_attribute(&mut self, node: &'ast Attribute);
461     ///     # fn visit_expr(&mut self, node: &'ast Expr);
462     ///     # fn visit_bin_op(&mut self, node: &'ast BinOp);
463     /// }
464     /// ```
465     ///
466     /// *This module is available if Syn is built with the `"visit"` feature.*
467     #[cfg(feature = "visit")]
468     pub mod visit;
469 
470     /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in
471     /// place.
472     ///
473     /// Each method of the [`VisitMut`] trait is a hook that can be overridden
474     /// to customize the behavior when mutating the corresponding type of node.
475     /// By default, every method recursively visits the substructure of the
476     /// input by invoking the right visitor method of each of its fields.
477     ///
478     /// [`VisitMut`]: visit_mut::VisitMut
479     ///
480     /// ```edition2018
481     /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
482     /// #
483     /// pub trait VisitMut {
484     ///     /* ... */
485     ///
486     ///     fn visit_expr_binary_mut(&mut self, node: &mut ExprBinary) {
487     ///         for attr in &mut node.attrs {
488     ///             self.visit_attribute_mut(attr);
489     ///         }
490     ///         self.visit_expr_mut(&mut *node.left);
491     ///         self.visit_bin_op_mut(&mut node.op);
492     ///         self.visit_expr_mut(&mut *node.right);
493     ///     }
494     ///
495     ///     /* ... */
496     ///     # fn visit_attribute_mut(&mut self, node: &mut Attribute);
497     ///     # fn visit_expr_mut(&mut self, node: &mut Expr);
498     ///     # fn visit_bin_op_mut(&mut self, node: &mut BinOp);
499     /// }
500     /// ```
501     ///
502     /// *This module is available if Syn is built with the `"visit-mut"`
503     /// feature.*
504     #[cfg(feature = "visit-mut")]
505     pub mod visit_mut;
506 
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     /// ```edition2018
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     ///         ExprBinary {
524     ///             attrs: node.attrs
525     ///                        .into_iter()
526     ///                        .map(|attr| self.fold_attribute(attr))
527     ///                        .collect(),
528     ///             left: Box::new(self.fold_expr(*node.left)),
529     ///             op: self.fold_bin_op(node.op),
530     ///             right: Box::new(self.fold_expr(*node.right)),
531     ///         }
532     ///     }
533     ///
534     ///     /* ... */
535     ///     # fn fold_attribute(&mut self, node: Attribute) -> Attribute;
536     ///     # fn fold_expr(&mut self, node: Expr) -> Expr;
537     ///     # fn fold_bin_op(&mut self, node: BinOp) -> BinOp;
538     /// }
539     /// ```
540     ///
541     /// *This module is available if Syn is built with the `"fold"` feature.*
542     #[cfg(feature = "fold")]
543     pub mod fold;
544 
545     #[cfg(any(feature = "full", feature = "derive"))]
546     #[path = "../gen_helper.rs"]
547     mod helper;
548 }
549 pub use gen::*;
550 
551 // Not public API.
552 #[doc(hidden)]
553 pub mod export;
554 
555 mod custom_keyword;
556 mod custom_punctuation;
557 mod sealed;
558 
559 #[cfg(feature = "parsing")]
560 mod lookahead;
561 
562 #[cfg(feature = "parsing")]
563 pub mod parse;
564 
565 mod span;
566 
567 #[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
568 mod print;
569 
570 mod thread;
571 
572 ////////////////////////////////////////////////////////////////////////////////
573 
574 #[cfg(any(feature = "parsing", feature = "full", feature = "derive"))]
575 #[allow(non_camel_case_types)]
576 struct private;
577 
578 ////////////////////////////////////////////////////////////////////////////////
579 
580 mod error;
581 pub use error::{Error, Result};
582 
583 /// Parse tokens of source code into the chosen syntax tree node.
584 ///
585 /// This is preferred over parsing a string because tokens are able to preserve
586 /// information about where in the user's code they were originally written (the
587 /// "span" of the token), possibly allowing the compiler to produce better error
588 /// messages.
589 ///
590 /// This function parses a `proc_macro::TokenStream` which is the type used for
591 /// interop with the compiler in a procedural macro. To parse a
592 /// `proc_macro2::TokenStream`, use [`syn::parse2`] instead.
593 ///
594 /// [`syn::parse2`]: parse2
595 ///
596 /// *This function is available if Syn is built with both the `"parsing"` and
597 /// `"proc-macro"` features.*
598 ///
599 /// # Examples
600 ///
601 /// ```edition2018
602 /// extern crate proc_macro;
603 ///
604 /// use proc_macro::TokenStream;
605 /// use quote::quote;
606 /// use syn::DeriveInput;
607 ///
608 /// # const IGNORE_TOKENS: &str = stringify! {
609 /// #[proc_macro_derive(MyMacro)]
610 /// # };
611 /// pub fn my_macro(input: TokenStream) -> TokenStream {
612 ///     // Parse the tokens into a syntax tree
613 ///     let ast: DeriveInput = syn::parse(input).unwrap();
614 ///
615 ///     // Build the output, possibly using quasi-quotation
616 ///     let expanded = quote! {
617 ///         /* ... */
618 ///     };
619 ///
620 ///     // Convert into a token stream and return it
621 ///     expanded.into()
622 /// }
623 /// ```
624 #[cfg(all(
625     not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
626     feature = "parsing",
627     feature = "proc-macro"
628 ))]
parse<T: parse::Parse>(tokens: proc_macro::TokenStream) -> Result<T>629 pub fn parse<T: parse::Parse>(tokens: proc_macro::TokenStream) -> Result<T> {
630     parse::Parser::parse(T::parse, tokens)
631 }
632 
633 /// Parse a proc-macro2 token stream into the chosen syntax tree node.
634 ///
635 /// This function parses a `proc_macro2::TokenStream` which is commonly useful
636 /// when the input comes from a node of the Syn syntax tree, for example the tts
637 /// of a [`Macro`] node. When in a procedural macro parsing the
638 /// `proc_macro::TokenStream` provided by the compiler, use [`syn::parse`]
639 /// instead.
640 ///
641 /// [`syn::parse`]: parse()
642 ///
643 /// *This function is available if Syn is built with the `"parsing"` feature.*
644 #[cfg(feature = "parsing")]
parse2<T: parse::Parse>(tokens: proc_macro2::TokenStream) -> Result<T>645 pub fn parse2<T: parse::Parse>(tokens: proc_macro2::TokenStream) -> Result<T> {
646     parse::Parser::parse2(T::parse, tokens)
647 }
648 
649 /// Parse a string of Rust code into the chosen syntax tree node.
650 ///
651 /// *This function is available if Syn is built with the `"parsing"` feature.*
652 ///
653 /// # Hygiene
654 ///
655 /// Every span in the resulting syntax tree will be set to resolve at the macro
656 /// call site.
657 ///
658 /// # Examples
659 ///
660 /// ```edition2018
661 /// use syn::{Expr, Result};
662 ///
663 /// fn run() -> Result<()> {
664 ///     let code = "assert_eq!(u8::max_value(), 255)";
665 ///     let expr = syn::parse_str::<Expr>(code)?;
666 ///     println!("{:#?}", expr);
667 ///     Ok(())
668 /// }
669 /// #
670 /// # fn main() {
671 /// #     run().unwrap();
672 /// # }
673 /// ```
674 #[cfg(feature = "parsing")]
parse_str<T: parse::Parse>(s: &str) -> Result<T>675 pub fn parse_str<T: parse::Parse>(s: &str) -> Result<T> {
676     parse::Parser::parse_str(T::parse, s)
677 }
678 
679 // FIXME the name parse_file makes it sound like you might pass in a path to a
680 // file, rather than the content.
681 /// Parse the content of a file of Rust code.
682 ///
683 /// This is different from `syn::parse_str::<File>(content)` in two ways:
684 ///
685 /// - It discards a leading byte order mark `\u{FEFF}` if the file has one.
686 /// - It preserves the shebang line of the file, such as `#!/usr/bin/env rustx`.
687 ///
688 /// If present, either of these would be an error using `from_str`.
689 ///
690 /// *This function is available if Syn is built with the `"parsing"` and
691 /// `"full"` features.*
692 ///
693 /// # Examples
694 ///
695 /// ```edition2018,no_run
696 /// use std::error::Error;
697 /// use std::fs::File;
698 /// use std::io::Read;
699 ///
700 /// fn run() -> Result<(), Box<Error>> {
701 ///     let mut file = File::open("path/to/code.rs")?;
702 ///     let mut content = String::new();
703 ///     file.read_to_string(&mut content)?;
704 ///
705 ///     let ast = syn::parse_file(&content)?;
706 ///     if let Some(shebang) = ast.shebang {
707 ///         println!("{}", shebang);
708 ///     }
709 ///     println!("{} items", ast.items.len());
710 ///
711 ///     Ok(())
712 /// }
713 /// #
714 /// # fn main() {
715 /// #     run().unwrap();
716 /// # }
717 /// ```
718 #[cfg(all(feature = "parsing", feature = "full"))]
parse_file(mut content: &str) -> Result<File>719 pub fn parse_file(mut content: &str) -> Result<File> {
720     // Strip the BOM if it is present
721     const BOM: &'static str = "\u{feff}";
722     if content.starts_with(BOM) {
723         content = &content[BOM.len()..];
724     }
725 
726     let mut shebang = None;
727     if content.starts_with("#!") && !content.starts_with("#![") {
728         if let Some(idx) = content.find('\n') {
729             shebang = Some(content[..idx].to_string());
730             content = &content[idx..];
731         } else {
732             shebang = Some(content.to_string());
733             content = "";
734         }
735     }
736 
737     let mut file: File = parse_str(content)?;
738     file.shebang = shebang;
739     Ok(file)
740 }
741