-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Closed
Description
# Input
pattern_esc = r"'\', '\\'"
# Ruff
pattern_esc = r"'', '\\'"Expected: Same as input
Probably relevant code:
ruff/crates/ruff_python_formatter/src/expression/string.rs
Lines 413 to 481 in 0301889
| fn normalize_string(input: &str, quotes: StringQuotes) -> (Cow<str>, ContainsNewlines) { | |
| // The normalized string if `input` is not yet normalized. | |
| // `output` must remain empty if `input` is already normalized. | |
| let mut output = String::new(); | |
| // Tracks the last index of `input` that has been written to `output`. | |
| // If `last_index` is `0` at the end, then the input is already normalized and can be returned as is. | |
| let mut last_index = 0; | |
| let mut newlines = ContainsNewlines::No; | |
| let style = quotes.style; | |
| let preferred_quote = style.as_char(); | |
| let opposite_quote = style.invert().as_char(); | |
| let mut chars = input.char_indices(); | |
| while let Some((index, c)) = chars.next() { | |
| if c == '\r' { | |
| output.push_str(&input[last_index..index]); | |
| // Skip over the '\r' character, keep the `\n` | |
| if input.as_bytes().get(index + 1).copied() == Some(b'\n') { | |
| chars.next(); | |
| } | |
| // Replace the `\r` with a `\n` | |
| else { | |
| output.push('\n'); | |
| } | |
| last_index = index + '\r'.len_utf8(); | |
| newlines = ContainsNewlines::Yes; | |
| } else if c == '\n' { | |
| newlines = ContainsNewlines::Yes; | |
| } else if !quotes.triple { | |
| if c == '\\' { | |
| if let Some(next) = input.as_bytes().get(index + 1).copied().map(char::from) { | |
| #[allow(clippy::if_same_then_else)] | |
| if next == opposite_quote { | |
| // Remove the escape by ending before the backslash and starting again with the quote | |
| chars.next(); | |
| output.push_str(&input[last_index..index]); | |
| last_index = index + '\\'.len_utf8(); | |
| } else if next == preferred_quote { | |
| // Quote is already escaped, skip over it. | |
| chars.next(); | |
| } else if next == '\\' { | |
| // Skip over escaped backslashes | |
| chars.next(); | |
| } | |
| } | |
| } else if c == preferred_quote { | |
| // Escape the quote | |
| output.push_str(&input[last_index..index]); | |
| output.push('\\'); | |
| output.push(c); | |
| last_index = index + preferred_quote.len_utf8(); | |
| } | |
| } | |
| } | |
| let normalized = if last_index == 0 { | |
| Cow::Borrowed(input) | |
| } else { | |
| output.push_str(&input[last_index..]); | |
| Cow::Owned(output) | |
| }; | |
| (normalized, newlines) | |
| } |
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
formatterRelated to the formatterRelated to the formatter