syn/file.rs
1use crate::attr::Attribute;
2use crate::item::Item;
3use alloc::string::String;
4use alloc::vec::Vec;
5
6ast_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 /// frontmatter: None,
53 /// attrs: [],
54 /// items: [
55 /// Item::Use {
56 /// attrs: [],
57 /// vis: Visibility::Inherited,
58 /// use_token: Token![use],
59 /// leading_colon: None,
60 /// tree: UseTree::Path(
61 /// UsePath {
62 /// ident: Ident(
63 /// std,
64 /// ),
65 /// colon2_token: Token![::],
66 /// tree: UseTree::Name(
67 /// UseName {
68 /// ident: Ident(
69 /// env,
70 /// ),
71 /// },
72 /// ),
73 /// },
74 /// ),
75 /// semi_token: Token![;],
76 /// },
77 /// ...
78 /// ```
79 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
80 pub struct File {
81 pub shebang: Option<String>,
82 pub frontmatter: Option<Frontmatter>,
83 pub attrs: Vec<Attribute>,
84 pub items: Vec<Item>,
85 }
86}
87
88ast_struct! {
89 /// A frontmatter section fenced by `---`.
90 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
91 #[non_exhaustive]
92 pub struct Frontmatter {}
93}
94
95#[cfg(feature = "parsing")]
96pub(crate) mod parsing {
97 use crate::attr::Attribute;
98 use crate::error::Result;
99 use crate::file::File;
100 use crate::parse::{Parse, ParseStream};
101 use alloc::vec::Vec;
102
103 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
104 impl Parse for File {
105 fn parse(input: ParseStream) -> Result<Self> {
106 Ok(File {
107 shebang: None,
108 frontmatter: None,
109 attrs: input.call(Attribute::parse_inner)?,
110 items: {
111 let mut items = Vec::new();
112 while !input.is_empty() {
113 items.push(input.parse()?);
114 }
115 items
116 },
117 })
118 }
119 }
120}
121
122#[cfg(feature = "printing")]
123mod printing {
124 use crate::attr::FilterAttrs;
125 use crate::file::File;
126 use proc_macro2::TokenStream;
127 use quote::{ToTokens, TokenStreamExt as _};
128
129 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
130 impl ToTokens for File {
131 fn to_tokens(&self, tokens: &mut TokenStream) {
132 tokens.append_all(self.attrs.inner());
133 tokens.append_all(&self.items);
134 }
135 }
136}