xref: /linux/rust/syn/file.rs (revision 69942c0a8965f311ed7ddf842f160c9cfdcda73a)
1 // SPDX-License-Identifier: Apache-2.0 OR MIT
2 
3 use crate::attr::Attribute;
4 use crate::item::Item;
5 
6 ast_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     ///     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(docsrs, 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")]
89 pub(crate) mod parsing {
90     use crate::attr::Attribute;
91     use crate::error::Result;
92     use crate::file::File;
93     use crate::parse::{Parse, ParseStream};
94 
95     #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
96     impl Parse for File {
97         fn parse(input: ParseStream) -> Result<Self> {
98             Ok(File {
99                 shebang: None,
100                 attrs: input.call(Attribute::parse_inner)?,
101                 items: {
102                     let mut items = Vec::new();
103                     while !input.is_empty() {
104                         items.push(input.parse()?);
105                     }
106                     items
107                 },
108             })
109         }
110     }
111 }
112 
113 #[cfg(feature = "printing")]
114 mod printing {
115     use crate::attr::FilterAttrs;
116     use crate::file::File;
117     use proc_macro2::TokenStream;
118     use quote::{ToTokens, TokenStreamExt};
119 
120     #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
121     impl ToTokens for File {
122         fn to_tokens(&self, tokens: &mut TokenStream) {
123             tokens.append_all(self.attrs.inner());
124             tokens.append_all(&self.items);
125         }
126     }
127 }
128