1 use crate::attr::Attribute;
2 use crate::item::Item;
3 
4 ast_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")]
92 pub(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 {
parse(input: ParseStream) -> Result<Self>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")]
117 mod 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 {
to_tokens(&self, tokens: &mut TokenStream)125         fn to_tokens(&self, tokens: &mut TokenStream) {
126             tokens.append_all(self.attrs.inner());
127             tokens.append_all(&self.items);
128         }
129     }
130 }
131