file.rs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // SPDX-License-Identifier: Apache-2.0 OR MIT
  2. use crate::attr::Attribute;
  3. use crate::item::Item;
  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. #[cfg(feature = "parsing")]
  86. pub(crate) mod parsing {
  87. use crate::attr::Attribute;
  88. use crate::error::Result;
  89. use crate::file::File;
  90. use crate::parse::{Parse, ParseStream};
  91. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  92. impl Parse for File {
  93. fn parse(input: ParseStream) -> Result<Self> {
  94. Ok(File {
  95. shebang: None,
  96. attrs: input.call(Attribute::parse_inner)?,
  97. items: {
  98. let mut items = Vec::new();
  99. while !input.is_empty() {
  100. items.push(input.parse()?);
  101. }
  102. items
  103. },
  104. })
  105. }
  106. }
  107. }
  108. #[cfg(feature = "printing")]
  109. mod printing {
  110. use crate::attr::FilterAttrs;
  111. use crate::file::File;
  112. use proc_macro2::TokenStream;
  113. use quote::{ToTokens, TokenStreamExt};
  114. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  115. impl ToTokens for File {
  116. fn to_tokens(&self, tokens: &mut TokenStream) {
  117. tokens.append_all(self.attrs.inner());
  118. tokens.append_all(&self.items);
  119. }
  120. }
  121. }