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 { |
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" )] |
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 { |
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 | |