helpers.rs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // SPDX-License-Identifier: GPL-2.0
  2. use proc_macro::{token_stream, Group, TokenStream, TokenTree};
  3. pub(crate) fn try_ident(it: &mut token_stream::IntoIter) -> Option<String> {
  4. if let Some(TokenTree::Ident(ident)) = it.next() {
  5. Some(ident.to_string())
  6. } else {
  7. None
  8. }
  9. }
  10. pub(crate) fn try_literal(it: &mut token_stream::IntoIter) -> Option<String> {
  11. if let Some(TokenTree::Literal(literal)) = it.next() {
  12. Some(literal.to_string())
  13. } else {
  14. None
  15. }
  16. }
  17. pub(crate) fn try_string(it: &mut token_stream::IntoIter) -> Option<String> {
  18. try_literal(it).and_then(|string| {
  19. if string.starts_with('\"') && string.ends_with('\"') {
  20. let content = &string[1..string.len() - 1];
  21. if content.contains('\\') {
  22. panic!("Escape sequences in string literals not yet handled");
  23. }
  24. Some(content.to_string())
  25. } else if string.starts_with("r\"") {
  26. panic!("Raw string literals are not yet handled");
  27. } else {
  28. None
  29. }
  30. })
  31. }
  32. pub(crate) fn expect_ident(it: &mut token_stream::IntoIter) -> String {
  33. try_ident(it).expect("Expected Ident")
  34. }
  35. pub(crate) fn expect_punct(it: &mut token_stream::IntoIter) -> char {
  36. if let TokenTree::Punct(punct) = it.next().expect("Reached end of token stream for Punct") {
  37. punct.as_char()
  38. } else {
  39. panic!("Expected Punct");
  40. }
  41. }
  42. pub(crate) fn expect_string(it: &mut token_stream::IntoIter) -> String {
  43. try_string(it).expect("Expected string")
  44. }
  45. pub(crate) fn expect_string_ascii(it: &mut token_stream::IntoIter) -> String {
  46. let string = try_string(it).expect("Expected string");
  47. assert!(string.is_ascii(), "Expected ASCII string");
  48. string
  49. }
  50. pub(crate) fn expect_group(it: &mut token_stream::IntoIter) -> Group {
  51. if let TokenTree::Group(group) = it.next().expect("Reached end of token stream for Group") {
  52. group
  53. } else {
  54. panic!("Expected Group");
  55. }
  56. }
  57. pub(crate) fn expect_end(it: &mut token_stream::IntoIter) {
  58. if it.next().is_some() {
  59. panic!("Expected end");
  60. }
  61. }
  62. /// Parsed generics.
  63. ///
  64. /// See the field documentation for an explanation what each of the fields represents.
  65. ///
  66. /// # Examples
  67. ///
  68. /// ```rust,ignore
  69. /// # let input = todo!();
  70. /// let (Generics { decl_generics, impl_generics, ty_generics }, rest) = parse_generics(input);
  71. /// quote! {
  72. /// struct Foo<$($decl_generics)*> {
  73. /// // ...
  74. /// }
  75. ///
  76. /// impl<$impl_generics> Foo<$ty_generics> {
  77. /// fn foo() {
  78. /// // ...
  79. /// }
  80. /// }
  81. /// }
  82. /// ```
  83. pub(crate) struct Generics {
  84. /// The generics with bounds and default values (e.g. `T: Clone, const N: usize = 0`).
  85. ///
  86. /// Use this on type definitions e.g. `struct Foo<$decl_generics> ...` (or `union`/`enum`).
  87. pub(crate) decl_generics: Vec<TokenTree>,
  88. /// The generics with bounds (e.g. `T: Clone, const N: usize`).
  89. ///
  90. /// Use this on `impl` blocks e.g. `impl<$impl_generics> Trait for ...`.
  91. pub(crate) impl_generics: Vec<TokenTree>,
  92. /// The generics without bounds and without default values (e.g. `T, N`).
  93. ///
  94. /// Use this when you use the type that is declared with these generics e.g.
  95. /// `Foo<$ty_generics>`.
  96. pub(crate) ty_generics: Vec<TokenTree>,
  97. }
  98. /// Parses the given `TokenStream` into `Generics` and the rest.
  99. ///
  100. /// The generics are not present in the rest, but a where clause might remain.
  101. pub(crate) fn parse_generics(input: TokenStream) -> (Generics, Vec<TokenTree>) {
  102. // The generics with bounds and default values.
  103. let mut decl_generics = vec![];
  104. // `impl_generics`, the declared generics with their bounds.
  105. let mut impl_generics = vec![];
  106. // Only the names of the generics, without any bounds.
  107. let mut ty_generics = vec![];
  108. // Tokens not related to the generics e.g. the `where` token and definition.
  109. let mut rest = vec![];
  110. // The current level of `<`.
  111. let mut nesting = 0;
  112. let mut toks = input.into_iter();
  113. // If we are at the beginning of a generic parameter.
  114. let mut at_start = true;
  115. let mut skip_until_comma = false;
  116. while let Some(tt) = toks.next() {
  117. if nesting == 1 && matches!(&tt, TokenTree::Punct(p) if p.as_char() == '>') {
  118. // Found the end of the generics.
  119. break;
  120. } else if nesting >= 1 {
  121. decl_generics.push(tt.clone());
  122. }
  123. match tt.clone() {
  124. TokenTree::Punct(p) if p.as_char() == '<' => {
  125. if nesting >= 1 && !skip_until_comma {
  126. // This is inside of the generics and part of some bound.
  127. impl_generics.push(tt);
  128. }
  129. nesting += 1;
  130. }
  131. TokenTree::Punct(p) if p.as_char() == '>' => {
  132. // This is a parsing error, so we just end it here.
  133. if nesting == 0 {
  134. break;
  135. } else {
  136. nesting -= 1;
  137. if nesting >= 1 && !skip_until_comma {
  138. // We are still inside of the generics and part of some bound.
  139. impl_generics.push(tt);
  140. }
  141. }
  142. }
  143. TokenTree::Punct(p) if skip_until_comma && p.as_char() == ',' => {
  144. if nesting == 1 {
  145. impl_generics.push(tt.clone());
  146. impl_generics.push(tt);
  147. skip_until_comma = false;
  148. }
  149. }
  150. _ if !skip_until_comma => {
  151. match nesting {
  152. // If we haven't entered the generics yet, we still want to keep these tokens.
  153. 0 => rest.push(tt),
  154. 1 => {
  155. // Here depending on the token, it might be a generic variable name.
  156. match tt.clone() {
  157. TokenTree::Ident(i) if at_start && i.to_string() == "const" => {
  158. let Some(name) = toks.next() else {
  159. // Parsing error.
  160. break;
  161. };
  162. impl_generics.push(tt);
  163. impl_generics.push(name.clone());
  164. ty_generics.push(name.clone());
  165. decl_generics.push(name);
  166. at_start = false;
  167. }
  168. TokenTree::Ident(_) if at_start => {
  169. impl_generics.push(tt.clone());
  170. ty_generics.push(tt);
  171. at_start = false;
  172. }
  173. TokenTree::Punct(p) if p.as_char() == ',' => {
  174. impl_generics.push(tt.clone());
  175. ty_generics.push(tt);
  176. at_start = true;
  177. }
  178. // Lifetimes begin with `'`.
  179. TokenTree::Punct(p) if p.as_char() == '\'' && at_start => {
  180. impl_generics.push(tt.clone());
  181. ty_generics.push(tt);
  182. }
  183. // Generics can have default values, we skip these.
  184. TokenTree::Punct(p) if p.as_char() == '=' => {
  185. skip_until_comma = true;
  186. }
  187. _ => impl_generics.push(tt),
  188. }
  189. }
  190. _ => impl_generics.push(tt),
  191. }
  192. }
  193. _ => {}
  194. }
  195. }
  196. rest.extend(toks);
  197. (
  198. Generics {
  199. impl_generics,
  200. decl_generics,
  201. ty_generics,
  202. },
  203. rest,
  204. )
  205. }