Skip to main content

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