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(function:Attribute::parse_inner)?,
104 items: {
105 let mut items: Vec = 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}
131