1use super::*;
2
3ast_struct! {
4 /// A complete file of Rust source code.
5 ///
6 /// Typically `File` objects are created with [`parse_file`].
7 ///
8 /// # Example
9 ///
10 /// Parse a Rust source file into a `syn::File` and print out a debug
11 /// representation of the syntax tree.
12 ///
13 /// ```
14 /// use std::env;
15 /// use std::fs::File;
16 /// use std::io::Read;
17 /// use std::process;
18 ///
19 /// fn main() {
20 /// # }
21 /// #
22 /// # fn fake_main() {
23 /// let mut args = env::args();
24 /// let _ = args.next(); // executable name
25 ///
26 /// let filename = match (args.next(), args.next()) {
27 /// (Some(filename), None) => filename,
28 /// _ => {
29 /// eprintln!("Usage: dump-syntax path/to/filename.rs");
30 /// process::exit(1);
31 /// }
32 /// };
33 ///
34 /// let mut file = File::open(&filename).expect("Unable to open file");
35 ///
36 /// let mut src = String::new();
37 /// file.read_to_string(&mut src).expect("Unable to read file");
38 ///
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(doc_cfg, 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 super::*;
91 use crate::parse::{Parse, ParseStream, Result};
92
93 #[cfg_attr(doc_cfg, 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 super::*;
114 use crate::attr::FilterAttrs;
115 use proc_macro2::TokenStream;
116 use quote::{ToTokens, TokenStreamExt};
117
118 #[cfg_attr(doc_cfg, 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}
126