Skip to main content

syn/
file.rs

1use crate::attr::Attribute;
2use crate::item::Item;
3use alloc::string::String;
4use alloc::vec::Vec;
5
6ast_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    ///     frontmatter: None,
53    ///     attrs: [],
54    ///     items: [
55    ///         Item::Use {
56    ///             attrs: [],
57    ///             vis: Visibility::Inherited,
58    ///             use_token: Token![use],
59    ///             leading_colon: None,
60    ///             tree: UseTree::Path(
61    ///                 UsePath {
62    ///                     ident: Ident(
63    ///                         std,
64    ///                     ),
65    ///                     colon2_token: Token![::],
66    ///                     tree: UseTree::Name(
67    ///                         UseName {
68    ///                             ident: Ident(
69    ///                                 env,
70    ///                             ),
71    ///                         },
72    ///                     ),
73    ///                 },
74    ///             ),
75    ///             semi_token: Token![;],
76    ///         },
77    /// ...
78    /// ```
79    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
80    pub struct File {
81        pub shebang: Option<String>,
82        pub frontmatter: Option<Frontmatter>,
83        pub attrs: Vec<Attribute>,
84        pub items: Vec<Item>,
85    }
86}
87
88ast_struct! {
89    /// A frontmatter section fenced by `---`.
90    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
91    #[non_exhaustive]
92    pub struct Frontmatter {}
93}
94
95#[cfg(feature = "parsing")]
96pub(crate) mod parsing {
97    use crate::attr::Attribute;
98    use crate::error::Result;
99    use crate::file::File;
100    use crate::parse::{Parse, ParseStream};
101    use alloc::vec::Vec;
102
103    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
104    impl Parse for File {
105        fn parse(input: ParseStream) -> Result<Self> {
106            Ok(File {
107                shebang: None,
108                frontmatter: None,
109                attrs: input.call(Attribute::parse_inner)?,
110                items: {
111                    let mut items = Vec::new();
112                    while !input.is_empty() {
113                        items.push(input.parse()?);
114                    }
115                    items
116                },
117            })
118        }
119    }
120}
121
122#[cfg(feature = "printing")]
123mod printing {
124    use crate::attr::FilterAttrs;
125    use crate::file::File;
126    use proc_macro2::TokenStream;
127    use quote::{ToTokens, TokenStreamExt as _};
128
129    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
130    impl ToTokens for File {
131        fn to_tokens(&self, tokens: &mut TokenStream) {
132            tokens.append_all(self.attrs.inner());
133            tokens.append_all(&self.items);
134        }
135    }
136}