diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
commit | 4547b622d8d29df964fa2914213088b148c498fc (patch) | |
tree | 9fc6b25f3c3add6b745be9a2400a6e96140046e9 /compiler/rustc_parse_format/src | |
parent | Releasing progress-linux version 1.66.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-4547b622d8d29df964fa2914213088b148c498fc.tar.xz rustc-4547b622d8d29df964fa2914213088b148c498fc.zip |
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_parse_format/src')
-rw-r--r-- | compiler/rustc_parse_format/src/lib.rs | 141 |
1 files changed, 75 insertions, 66 deletions
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 1394993ab..0113eb4e3 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -818,85 +818,94 @@ fn find_skips_from_snippet( _ => return (vec![], false), }; - fn find_skips(snippet: &str, is_raw: bool) -> Vec<usize> { - let mut s = snippet.char_indices().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 => { - skips.push(pos); - skips.push(*next_pos); - let _ = s.next(); + if str_style.is_some() { + return (vec![], true); + } - while let Some((pos, c)) = s.peek() { - if matches!(c, ' ' | '\n' | '\t') { - skips.push(*pos); - let _ = s.next(); - } else { - break; - } - } - } - ('\\', Some((next_pos, 'n' | 't' | 'r' | '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; - } + let snippet = &snippet[1..snippet.len() - 1]; + + let mut s = snippet.char_indices(); + let mut skips = vec![]; + while let Some((pos, c)) = s.next() { + match (c, s.clone().next()) { + // skip whitespace and empty lines ending in '\\' + ('\\', Some((next_pos, '\n'))) => { + skips.push(pos); + skips.push(next_pos); + let _ = s.next(); + + while let Some((pos, c)) = s.clone().next() { + if matches!(c, ' ' | '\n' | '\t') { + skips.push(pos); + let _ = s.next(); + } else { + break; } } - ('\\', Some((_, 'u'))) if !is_raw => { + } + ('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => { + skips.push(next_pos); + let _ = s.next(); + } + ('\\', Some((_, 'x'))) => { + for _ in 0..3 { + // consume `\xAB` literal if let Some((pos, _)) = s.next() { skips.push(pos); + } else { + break; } - 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; + } + } + ('\\', Some((_, 'u'))) => { + if let Some((pos, _)) = s.next() { + skips.push(pos); + } + if let Some((next_pos, next_c)) = s.next() { + if next_c == '{' { + // consume up to 6 hexanumeric chars + let digits_len = + s.clone().take(6).take_while(|(_, c)| c.is_digit(16)).count(); + + let len_utf8 = s + .as_str() + .get(..digits_len) + .and_then(|digits| u32::from_str_radix(digits, 16).ok()) + .and_then(char::from_u32) + .map_or(1, char::len_utf8); + + // Skip the digits, for chars that encode to more than 1 utf-8 byte + // exclude as many digits as it is greater than 1 byte + // + // So for a 3 byte character, exclude 2 digits + let required_skips = digits_len.saturating_sub(len_utf8.saturating_sub(1)); + + // skip '{' and '}' also + for pos in (next_pos..).take(required_skips + 2) { + skips.push(pos) + } + + s.nth(digits_len); + } 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; } } } - _ => {} } + _ => {} } - skips } - - let r_start = str_style.map_or(0, |r| r + 1); - let r_end = str_style.unwrap_or(0); - let s = &snippet[r_start + 1..snippet.len() - r_end - 1]; - (find_skips(s, str_style.is_some()), true) + (skips, true) } #[cfg(test)] |