syn/
file.rs

1use crate::attr::Attribute;
2use crate::item::Item;
3use alloc::string::String;
4use alloc::vec::Vec;
5
6#[doc = r" A complete file of Rust source code."]
#[doc = r""]
#[doc = r" Typically `File` objects are created with [`parse_file`]."]
#[doc = r""]
#[doc = r" [`parse_file`]: crate::parse_file"]
#[doc = r""]
#[doc = r" # Example"]
#[doc = r""]
#[doc = r" Parse a Rust source file into a `syn::File` and print out a debug"]
#[doc = r" representation of the syntax tree."]
#[doc = r""]
#[doc = r" ```"]
#[doc = r" use std::env;"]
#[doc = r" use std::fs;"]
#[doc = r" use std::process;"]
#[doc = r""]
#[doc = r" fn main() {"]
#[doc = r" # }"]
#[doc = r" #"]
#[doc = r" # fn fake_main() {"]
#[doc = r"     let mut args = env::args();"]
#[doc = r"     let _ = args.next(); // executable name"]
#[doc = r""]
#[doc = r"     let filename = match (args.next(), args.next()) {"]
#[doc = r"         (Some(filename), None) => filename,"]
#[doc = r"         _ => {"]
#[doc =
r#"             eprintln!("Usage: dump-syntax path/to/filename.rs");"#]
#[doc = r"             process::exit(1);"]
#[doc = r"         }"]
#[doc = r"     };"]
#[doc = r""]
#[doc =
r#"     let src = fs::read_to_string(&filename).expect("unable to read file");"#]
#[doc =
r#"     let syntax = syn::parse_file(&src).expect("unable to parse file");"#]
#[doc = r""]
#[doc =
r#"     // Debug impl is available if Syn is built with "extra-traits" feature."#]
#[doc = r#"     println!("{:#?}", syntax);"#]
#[doc = r" }"]
#[doc = r" ```"]
#[doc = r""]
#[doc =
r" Running with its own source code as input, this program prints output"]
#[doc = r" that begins with:"]
#[doc = r""]
#[doc = r" ```text"]
#[doc = r" File {"]
#[doc = r"     shebang: None,"]
#[doc = r"     attrs: [],"]
#[doc = r"     items: ["]
#[doc = r"         Use("]
#[doc = r"             ItemUse {"]
#[doc = r"                 attrs: [],"]
#[doc = r"                 vis: Inherited,"]
#[doc = r"                 use_token: Use,"]
#[doc = r"                 leading_colon: None,"]
#[doc = r"                 tree: Path("]
#[doc = r"                     UsePath {"]
#[doc = r"                         ident: Ident("]
#[doc = r"                             std,"]
#[doc = r"                         ),"]
#[doc = r"                         colon2_token: Colon2,"]
#[doc = r"                         tree: Name("]
#[doc = r"                             UseName {"]
#[doc = r"                                 ident: Ident("]
#[doc = r"                                     env,"]
#[doc = r"                                 ),"]
#[doc = r"                             },"]
#[doc = r"                         ),"]
#[doc = r"                     },"]
#[doc = r"                 ),"]
#[doc = r"                 semi_token: Semi,"]
#[doc = r"             },"]
#[doc = r"         ),"]
#[doc = r" ..."]
#[doc = r" ```"]
pub struct File {
    pub shebang: Option<String>,
    pub attrs: Vec<Attribute>,
    pub items: Vec<Item>,
}ast_struct! {
7    /// A complete file of Rust source code.
8    ///
9    /// Typically `File` objects are created with [`parse_file`].
10    ///
11    /// [`parse_file`]: crate::parse_file
12    ///
13    /// # Example
14    ///
15    /// Parse a Rust source file into a `syn::File` and print out a debug
16    /// representation of the syntax tree.
17    ///
18    /// ```
19    /// use std::env;
20    /// use std::fs;
21    /// use std::process;
22    ///
23    /// fn main() {
24    /// # }
25    /// #
26    /// # fn fake_main() {
27    ///     let mut args = env::args();
28    ///     let _ = args.next(); // executable name
29    ///
30    ///     let filename = match (args.next(), args.next()) {
31    ///         (Some(filename), None) => filename,
32    ///         _ => {
33    ///             eprintln!("Usage: dump-syntax path/to/filename.rs");
34    ///             process::exit(1);
35    ///         }
36    ///     };
37    ///
38    ///     let src = fs::read_to_string(&filename).expect("unable to read file");
39    ///     let syntax = syn::parse_file(&src).expect("unable to parse file");
40    ///
41    ///     // Debug impl is available if Syn is built with "extra-traits" feature.
42    ///     println!("{:#?}", syntax);
43    /// }
44    /// ```
45    ///
46    /// Running with its own source code as input, this program prints output
47    /// that begins with:
48    ///
49    /// ```text
50    /// File {
51    ///     shebang: None,
52    ///     attrs: [],
53    ///     items: [
54    ///         Use(
55    ///             ItemUse {
56    ///                 attrs: [],
57    ///                 vis: Inherited,
58    ///                 use_token: Use,
59    ///                 leading_colon: None,
60    ///                 tree: Path(
61    ///                     UsePath {
62    ///                         ident: Ident(
63    ///                             std,
64    ///                         ),
65    ///                         colon2_token: Colon2,
66    ///                         tree: Name(
67    ///                             UseName {
68    ///                                 ident: Ident(
69    ///                                     env,
70    ///                                 ),
71    ///                             },
72    ///                         ),
73    ///                     },
74    ///                 ),
75    ///                 semi_token: Semi,
76    ///             },
77    ///         ),
78    /// ...
79    /// ```
80    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
81    pub struct File {
82        pub shebang: Option<String>,
83        pub attrs: Vec<Attribute>,
84        pub items: Vec<Item>,
85    }
86}
87
88#[cfg(feature = "parsing")]
89pub(crate) mod parsing {
90    use crate::attr::Attribute;
91    use crate::error::Result;
92    use crate::file::File;
93    use crate::parse::{Parse, ParseStream};
94    use alloc::vec::Vec;
95
96    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
97    impl Parse for File {
98        fn parse(input: ParseStream) -> Result<Self> {
99            Ok(File {
100                shebang: None,
101                attrs: input.call(Attribute::parse_inner)?,
102                items: {
103                    let mut items = Vec::new();
104                    while !input.is_empty() {
105                        items.push(input.parse()?);
106                    }
107                    items
108                },
109            })
110        }
111    }
112}
113
114#[cfg(feature = "printing")]
115mod printing {
116    use crate::attr::FilterAttrs;
117    use crate::file::File;
118    use proc_macro2::TokenStream;
119    use quote::{ToTokens, TokenStreamExt as _};
120
121    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
122    impl ToTokens for File {
123        fn to_tokens(&self, tokens: &mut TokenStream) {
124            tokens.append_all(self.attrs.inner());
125            tokens.append_all(&self.items);
126        }
127    }
128}