diff --git a/src/macros.rs b/src/macros.rs index b260e15501f..030988e5195 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -33,7 +33,8 @@ use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; use syntax::util::ThinVec; use codemap::SpanUtils; -use comment::{contains_comment, remove_trailing_white_spaces, FindUncommented}; +use comment::{contains_comment, remove_trailing_white_spaces, CharClasses, FindUncommented, + FullCodeCharKind}; use expr::rewrite_array; use lists::{itemize_list, write_list, ListFormatting}; use overflow; @@ -399,6 +400,28 @@ pub fn rewrite_macro_def( Some(result) } +fn register_metavariable( + map: &mut HashMap, + result: &mut String, + name: &str, + dollar_count: usize, +) { + let mut new_name = String::new(); + let mut old_name = String::new(); + + old_name.push('$'); + for _ in 0..(dollar_count - 1) { + new_name.push('$'); + old_name.push('$'); + } + new_name.push('z'); + new_name.push_str(&name); + old_name.push_str(&name); + + result.push_str(&new_name); + map.insert(old_name, new_name); +} + // Replaces `$foo` with `zfoo`. We must check for name overlap to ensure we // aren't causing problems. // This should also work for escaped `$` variables, where we leave earlier `$`s. @@ -409,31 +432,20 @@ fn replace_names(input: &str) -> Option<(String, HashMap)> { let mut dollar_count = 0; let mut cur_name = String::new(); - for c in input.chars() { - if c == '$' { + for (kind, c) in CharClasses::new(input.chars()) { + if kind != FullCodeCharKind::Normal { + result.push(c); + } else if c == '$' { dollar_count += 1; } else if dollar_count == 0 { result.push(c); } else if !c.is_alphanumeric() && !cur_name.is_empty() { // Terminates a name following one or more dollars. - let mut new_name = String::new(); - let mut old_name = String::new(); - old_name.push('$'); - for _ in 0..(dollar_count - 1) { - new_name.push('$'); - old_name.push('$'); - } - new_name.push('z'); - new_name.push_str(&cur_name); - old_name.push_str(&cur_name); - - result.push_str(&new_name); - substs.insert(old_name, new_name); + register_metavariable(&mut substs, &mut result, &cur_name, dollar_count); result.push(c); - dollar_count = 0; - cur_name = String::new(); + cur_name.clear(); } else if c == '(' && cur_name.is_empty() { // FIXME: Support macro def with repeat. return None; @@ -442,21 +454,8 @@ fn replace_names(input: &str) -> Option<(String, HashMap)> { } } - // FIXME: duplicate code if !cur_name.is_empty() { - let mut new_name = String::new(); - let mut old_name = String::new(); - old_name.push('$'); - for _ in 0..(dollar_count - 1) { - new_name.push('$'); - old_name.push('$'); - } - new_name.push('z'); - new_name.push_str(&cur_name); - old_name.push_str(&cur_name); - - result.push_str(&new_name); - substs.insert(old_name, new_name); + register_metavariable(&mut substs, &mut result, &cur_name, dollar_count); } debug!("replace_names `{}` {:?}", result, substs); diff --git a/tests/source/macro_rules.rs b/tests/source/macro_rules.rs index dba1d78f0dd..ea3cefa8738 100644 --- a/tests/source/macro_rules.rs +++ b/tests/source/macro_rules.rs @@ -112,3 +112,19 @@ macro foo($type_name: ident, $docs: expr) { #[derive(Debug, Clone, Copy)] pub struct $type_name; } + +// #2538 +macro_rules! add_message_to_notes { + ($msg:expr) => {{ + let mut lines = message.lines(); + notes.push_str(&format!("\n{}: {}", level, lines.next().unwrap())); + for line in lines { + notes.push_str(&format!( + "\n{:indent$}{line}", + "", + indent = level.len() + 2, + line = line, + )); + } + }} +} diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs index 2136784dec7..bc9c6aa4022 100644 --- a/tests/target/macro_rules.rs +++ b/tests/target/macro_rules.rs @@ -103,3 +103,19 @@ macro foo($type_name: ident, $docs: expr) { #[derive(Debug, Clone, Copy)] pub struct $type_name; } + +// #2538 +macro_rules! add_message_to_notes { + ($msg: expr) => {{ + let mut lines = message.lines(); + notes.push_str(&format!("\n{}: {}", level, lines.next().unwrap())); + for line in lines { + notes.push_str(&format!( + "\n{:indent$}{line}", + "", + indent = level.len() + 2, + line = line, + )); + } + }}; +}