diff options
Diffstat (limited to 'src/librustc_builtin_macros/format.rs')
| -rw-r--r-- | src/librustc_builtin_macros/format.rs | 119 |
1 files changed, 11 insertions, 108 deletions
diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index efce6288198..eed01b262bf 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -108,8 +108,6 @@ struct Context<'a, 'b> { arg_spans: Vec<Span>, /// All the formatting arguments that have formatting flags set, in order for diagnostics. arg_with_formatting: Vec<parse::FormatSpec<'a>>, - /// Whether this formatting string is a literal or it comes from a macro. - is_literal: bool, } /// Parses the arguments from the given list of tokens, returning the diagnostic @@ -324,7 +322,7 @@ impl<'a, 'b> Context<'a, 'b> { /// format string. fn report_invalid_references(&self, numbered_position_args: bool) { let mut e; - let sp = if self.is_literal { + let sp = if !self.arg_spans.is_empty() { // Point at the formatting arguments. MultiSpan::from_spans(self.arg_spans.clone()) } else { @@ -372,7 +370,7 @@ impl<'a, 'b> Context<'a, 'b> { let reg = refs.pop().unwrap(); (format!("arguments {head} and {tail}", head = refs.join(", "), tail = reg,), pos) }; - if !self.is_literal { + if self.arg_spans.is_empty() { sp = MultiSpan::from_span(self.fmtsp); } @@ -502,11 +500,7 @@ impl<'a, 'b> Context<'a, 'b> { } None => { let msg = format!("there is no argument named `{}`", name); - let sp = if self.is_literal { - *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp) - } else { - self.fmtsp - }; + let sp = *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp); let mut err = self.ecx.struct_span_err(sp, &msg[..]); err.emit(); } @@ -892,110 +886,20 @@ pub fn expand_preparsed_format_args( } }; - let (is_literal, fmt_snippet) = match ecx.source_map().span_to_snippet(fmt_sp) { - Ok(s) => (s.starts_with('"') || s.starts_with("r#"), Some(s)), - _ => (false, None), - }; - let str_style = match fmt_style { ast::StrStyle::Cooked => None, ast::StrStyle::Raw(raw) => Some(raw as usize), }; - /// Finds the indices of all characters that have been processed and differ between the actual - /// written code (code snippet) and the `InternedString` that gets processed in the `Parser` - /// in order to properly synthethise the intra-string `Span`s for error diagnostics. - fn find_skips(snippet: &str, is_raw: bool) -> Vec<usize> { - let mut eat_ws = false; - let mut s = snippet.chars().enumerate().peekable(); - let mut skips = vec![]; - while let Some((pos, c)) = s.next() { - match (c, s.peek()) { - // skip whitespace and empty lines ending in '\\' - ('\\', Some((next_pos, '\n'))) if !is_raw => { - eat_ws = true; - skips.push(pos); - skips.push(*next_pos); - let _ = s.next(); - } - ('\\', Some((next_pos, '\n' | 'n' | 't'))) if eat_ws => { - skips.push(pos); - skips.push(*next_pos); - let _ = s.next(); - } - (' ' | '\n' | '\t', _) if eat_ws => { - skips.push(pos); - } - ('\\', Some((next_pos, 'n' | 't' | '0' | '\\' | '\'' | '\"'))) => { - skips.push(*next_pos); - let _ = s.next(); - } - ('\\', Some((_, 'x'))) if !is_raw => { - for _ in 0..3 { - // consume `\xAB` literal - if let Some((pos, _)) = s.next() { - skips.push(pos); - } else { - break; - } - } - } - ('\\', Some((_, 'u'))) if !is_raw => { - if let Some((pos, _)) = s.next() { - skips.push(pos); - } - if let Some((next_pos, next_c)) = s.next() { - if next_c == '{' { - skips.push(next_pos); - let mut i = 0; // consume up to 6 hexanumeric chars + closing `}` - while let (Some((next_pos, c)), true) = (s.next(), i < 7) { - if c.is_digit(16) { - skips.push(next_pos); - } else if c == '}' { - skips.push(next_pos); - break; - } else { - break; - } - i += 1; - } - } else if next_c.is_digit(16) { - skips.push(next_pos); - // We suggest adding `{` and `}` when appropriate, accept it here as if - // it were correct - let mut i = 0; // consume up to 6 hexanumeric chars - while let (Some((next_pos, c)), _) = (s.next(), i < 6) { - if c.is_digit(16) { - skips.push(next_pos); - } else { - break; - } - i += 1; - } - } - } - } - _ if eat_ws => { - // `take_while(|c| c.is_whitespace())` - eat_ws = false; - } - _ => {} - } - } - skips - } - - let skips = if let (true, Some(ref snippet)) = (is_literal, fmt_snippet.as_ref()) { - let r_start = str_style.map(|r| r + 1).unwrap_or(0); - let r_end = str_style.map(|r| r).unwrap_or(0); - let s = &snippet[r_start + 1..snippet.len() - r_end - 1]; - find_skips(s, str_style.is_some()) - } else { - vec![] - }; - let fmt_str = &fmt_str.as_str(); // for the suggestions below - let mut parser = parse::Parser::new(fmt_str, str_style, skips, append_newline); + let fmt_snippet = ecx.source_map().span_to_snippet(fmt_sp).ok(); + let mut parser = parse::Parser::new( + fmt_str, + str_style, + fmt_snippet, + append_newline, + parse::ParseMode::Format, + ); let mut unverified_pieces = Vec::new(); while let Some(piece) = parser.next() { @@ -1048,7 +952,6 @@ pub fn expand_preparsed_format_args( invalid_refs: Vec::new(), arg_spans, arg_with_formatting: Vec::new(), - is_literal, }; // This needs to happen *after* the Parser has consumed all pieces to create all the spans |
