syn/
file.rs

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