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 { parse(input: ParseStream) -> Result<Self>95 fn parse(input: ParseStream) -> Result<Self> { 96 Ok(File { 97 shebang: None, 98 attrs: input.call(Attribute::parse_inner)?, 99 items: { 100 let mut items = 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 { to_tokens(&self, tokens: &mut TokenStream)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