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