diff options
Diffstat (limited to 'crates/hir_expand/src/builtin_macro.rs')
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 45 |
1 files changed, 25 insertions, 20 deletions
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 57bc6fbd7..6fbb9570a 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -6,7 +6,7 @@ use crate::{ | |||
6 | 6 | ||
7 | use base_db::{AnchoredPath, FileId}; | 7 | use base_db::{AnchoredPath, FileId}; |
8 | use either::Either; | 8 | use either::Either; |
9 | use mbe::{parse_to_token_tree, ExpandResult}; | 9 | use mbe::{parse_exprs_with_sep, parse_to_token_tree, ExpandResult}; |
10 | use parser::FragmentKind; | 10 | use parser::FragmentKind; |
11 | use syntax::ast::{self, AstToken}; | 11 | use syntax::ast::{self, AstToken}; |
12 | 12 | ||
@@ -238,35 +238,21 @@ fn format_args_expand( | |||
238 | // ]) | 238 | // ]) |
239 | // ```, | 239 | // ```, |
240 | // which is still not really correct, but close enough for now | 240 | // which is still not really correct, but close enough for now |
241 | let mut args = Vec::new(); | 241 | let mut args = parse_exprs_with_sep(tt, ','); |
242 | let mut current = Vec::new(); | 242 | |
243 | for tt in tt.token_trees.iter().cloned() { | ||
244 | match tt { | ||
245 | tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => { | ||
246 | args.push(current); | ||
247 | current = Vec::new(); | ||
248 | } | ||
249 | _ => { | ||
250 | current.push(tt); | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | if !current.is_empty() { | ||
255 | args.push(current); | ||
256 | } | ||
257 | if args.is_empty() { | 243 | if args.is_empty() { |
258 | return ExpandResult::only_err(mbe::ExpandError::NoMatchingRule); | 244 | return ExpandResult::only_err(mbe::ExpandError::NoMatchingRule); |
259 | } | 245 | } |
260 | for arg in &mut args { | 246 | for arg in &mut args { |
261 | // Remove `key =`. | 247 | // Remove `key =`. |
262 | if matches!(arg.get(1), Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p))) if p.char == '=' && p.spacing != tt::Spacing::Joint) | 248 | if matches!(arg.token_trees.get(1), Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p))) if p.char == '=' && p.spacing != tt::Spacing::Joint) |
263 | { | 249 | { |
264 | arg.drain(..2); | 250 | arg.token_trees.drain(..2); |
265 | } | 251 | } |
266 | } | 252 | } |
267 | let _format_string = args.remove(0); | 253 | let _format_string = args.remove(0); |
268 | let arg_tts = args.into_iter().flat_map(|arg| { | 254 | let arg_tts = args.into_iter().flat_map(|arg| { |
269 | quote! { std::fmt::ArgumentV1::new(&(##arg), std::fmt::Display::fmt), } | 255 | quote! { std::fmt::ArgumentV1::new(&(#arg), std::fmt::Display::fmt), } |
270 | }.token_trees).collect::<Vec<_>>(); | 256 | }.token_trees).collect::<Vec<_>>(); |
271 | let expanded = quote! { | 257 | let expanded = quote! { |
272 | std::fmt::Arguments::new_v1(&[], &[##arg_tts]) | 258 | std::fmt::Arguments::new_v1(&[], &[##arg_tts]) |
@@ -720,6 +706,25 @@ mod tests { | |||
720 | } | 706 | } |
721 | 707 | ||
722 | #[test] | 708 | #[test] |
709 | fn test_format_args_expand_with_comma_exprs() { | ||
710 | let expanded = expand_builtin_macro( | ||
711 | r#" | ||
712 | #[rustc_builtin_macro] | ||
713 | macro_rules! format_args { | ||
714 | ($fmt:expr) => ({ /* compiler built-in */ }); | ||
715 | ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) | ||
716 | } | ||
717 | format_args!("{} {:?}", a::<A,B>(), b); | ||
718 | "#, | ||
719 | ); | ||
720 | |||
721 | assert_eq!( | ||
722 | expanded, | ||
723 | r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a::<A,B>()),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(b),std::fmt::Display::fmt),])"# | ||
724 | ); | ||
725 | } | ||
726 | |||
727 | #[test] | ||
723 | fn test_include_bytes_expand() { | 728 | fn test_include_bytes_expand() { |
724 | let expanded = expand_builtin_macro( | 729 | let expanded = expand_builtin_macro( |
725 | r#" | 730 | r#" |