| 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; |
| 19 | /// use std::process; |
| 20 | /// |
| 21 | /// fn main() { |
| 22 | /// # } |
| 23 | /// # |
| 24 | /// # fn fake_main() { |
| 25 | /// let mut args = env::args(); |
| 26 | /// let _ = args.next(); // executable name |
| 27 | /// |
| 28 | /// let filename = match (args.next(), args.next()) { |
| 29 | /// (Some(filename), None) => filename, |
| 30 | /// _ => { |
| 31 | /// eprintln!("Usage: dump-syntax path/to/filename.rs"); |
| 32 | /// process::exit(1); |
| 33 | /// } |
| 34 | /// }; |
| 35 | /// |
| 36 | /// let src = fs::read_to_string(&filename).expect("unable to read file"); |
| 37 | /// let syntax = syn::parse_file(&src).expect("unable to parse file"); |
| 38 | /// |
| 39 | /// // Debug impl is available if Syn is built with "extra-traits" feature. |
| 40 | /// println!("{:#?}", syntax); |
| 41 | /// } |
| 42 | /// ``` |
| 43 | /// |
| 44 | /// Running with its own source code as input, this program prints output |
| 45 | /// that begins with: |
| 46 | /// |
| 47 | /// ```text |
| 48 | /// File { |
| 49 | /// shebang: None, |
| 50 | /// attrs: [], |
| 51 | /// items: [ |
| 52 | /// Use( |
| 53 | /// ItemUse { |
| 54 | /// attrs: [], |
| 55 | /// vis: Inherited, |
| 56 | /// use_token: Use, |
| 57 | /// leading_colon: None, |
| 58 | /// tree: Path( |
| 59 | /// UsePath { |
| 60 | /// ident: Ident( |
| 61 | /// std, |
| 62 | /// ), |
| 63 | /// colon2_token: Colon2, |
| 64 | /// tree: Name( |
| 65 | /// UseName { |
| 66 | /// ident: Ident( |
| 67 | /// env, |
| 68 | /// ), |
| 69 | /// }, |
| 70 | /// ), |
| 71 | /// }, |
| 72 | /// ), |
| 73 | /// semi_token: Semi, |
| 74 | /// }, |
| 75 | /// ), |
| 76 | /// ... |
| 77 | /// ``` |
| 78 | #[cfg_attr (docsrs, doc(cfg(feature = "full" )))] |
| 79 | pub struct File { |
| 80 | pub shebang: Option<String>, |
| 81 | pub attrs: Vec<Attribute>, |
| 82 | pub items: Vec<Item>, |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | #[cfg (feature = "parsing" )] |
| 87 | pub(crate) mod parsing { |
| 88 | use crate::attr::Attribute; |
| 89 | use crate::error::Result; |
| 90 | use crate::file::File; |
| 91 | use crate::parse::{Parse, ParseStream}; |
| 92 | |
| 93 | #[cfg_attr (docsrs, 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(function:Attribute::parse_inner)?, |
| 99 | items: { |
| 100 | let mut items: Vec = 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" )] |
| 112 | mod printing { |
| 113 | use crate::attr::FilterAttrs; |
| 114 | use crate::file::File; |
| 115 | use proc_macro2::TokenStream; |
| 116 | use quote::{ToTokens, TokenStreamExt}; |
| 117 | |
| 118 | #[cfg_attr (docsrs, 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 | |