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 { parse(input: ParseStream) -> Result<Self>100 fn parse(input: ParseStream) -> Result<Self> { 101 Ok(File { 102 shebang: None, 103 attrs: input.call(Attribute::parse_inner)?, 104 items: { 105 let mut items = 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 { to_tokens(&self, tokens: &mut TokenStream)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