Skip to content

Commit

Permalink
Avoid an allocation and add another edge-case test
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexWaygood committed Aug 27, 2024
1 parent 30cce39 commit 25805a2
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,5 @@
_ = "\12 and more""0" # fix should be "\12 and more0"
_ = "\8""0" # fix should be "\80"
_ = "\12""8" # fix should be "\128"
_ = "\12""foo" # fix should be "\12foo"
_ = "\12""foo" # fix should be "\12foo"
_ = "\12" "" # fix should be "\12"
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::borrow::Cow;

use itertools::Itertools;

use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
Expand Down Expand Up @@ -173,13 +175,13 @@ fn concatenate_strings(a_range: TextRange, b_range: TextRange, locator: &Locator
}

let mut a_body =
a_text[a_leading_quote.len()..a_text.len() - a_trailing_quote.len()].to_string();
Cow::Borrowed(&a_text[a_leading_quote.len()..a_text.len() - a_trailing_quote.len()]);
let b_body = &b_text[b_leading_quote.len()..b_text.len() - b_trailing_quote.len()];

if a_leading_quote.find(['r', 'R']).is_none()
&& b_body.starts_with(['0', '1', '2', '3', '4', '5', '6', '7'])
&& matches!(b_body.bytes().next(), Some(b'0'..=b'7'))
{
a_body = normalize_ending_octal(&a_body);
normalize_ending_octal(&mut a_body);
}

let concatenation = format!("{a_leading_quote}{a_body}{b_body}{a_trailing_quote}");
Expand All @@ -193,31 +195,30 @@ fn concatenate_strings(a_range: TextRange, b_range: TextRange, locator: &Locator

/// Pads an octal at the end of the string
/// to three digits, if necessary.
fn normalize_ending_octal(text: &str) -> String {
fn normalize_ending_octal(text: &mut Cow<'_, str>) {
// Early return for short strings
if text.len() < 2 {
return text.to_string();
return;
}

let mut rev_bytes = text.bytes().rev();
if let Some(last_byte @ b'0'..=b'7') = rev_bytes.next() {
// "\y" -> "\00y"
if has_odd_consecutive_backslashes(&mut rev_bytes.clone()) {
let prefix = &text[..text.len() - 2];
return format!("{prefix}\\00{}", last_byte as char);
*text = Cow::Owned(format!("{prefix}\\00{}", last_byte as char));
}
// "\xy" -> "\0xy"
if let Some(penultimate_byte @ b'0'..=b'7') = rev_bytes.next() {
else if let Some(penultimate_byte @ b'0'..=b'7') = rev_bytes.next() {
if has_odd_consecutive_backslashes(&mut rev_bytes.clone()) {
let prefix = &text[..text.len() - 3];
return format!(
*text = Cow::Owned(format!(
"{prefix}\\0{}{}",
penultimate_byte as char, last_byte as char
);
));
}
}
}
text.to_string()
}

fn has_odd_consecutive_backslashes(mut itr: impl Iterator<Item = u8>) -> bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ ISC.py:90:5: ISC001 [*] Implicitly concatenated string literals on one line
90 |+_ = "\80" # fix should be "\80"
91 91 | _ = "\12""8" # fix should be "\128"
92 92 | _ = "\12""foo" # fix should be "\12foo"
93 93 | _ = "\12" "" # fix should be "\12"

ISC.py:91:5: ISC001 [*] Implicitly concatenated string literals on one line
|
Expand All @@ -448,6 +449,7 @@ ISC.py:91:5: ISC001 [*] Implicitly concatenated string literals on one line
91 | _ = "\12""8" # fix should be "\128"
| ^^^^^^^^ ISC001
92 | _ = "\12""foo" # fix should be "\12foo"
93 | _ = "\12" "" # fix should be "\12"
|
= help: Combine string literals

Expand All @@ -458,13 +460,15 @@ ISC.py:91:5: ISC001 [*] Implicitly concatenated string literals on one line
91 |-_ = "\12""8" # fix should be "\128"
91 |+_ = "\128" # fix should be "\128"
92 92 | _ = "\12""foo" # fix should be "\12foo"
93 93 | _ = "\12" "" # fix should be "\12"

ISC.py:92:5: ISC001 [*] Implicitly concatenated string literals on one line
|
90 | _ = "\8""0" # fix should be "\80"
91 | _ = "\12""8" # fix should be "\128"
92 | _ = "\12""foo" # fix should be "\12foo"
| ^^^^^^^^^^ ISC001
93 | _ = "\12" "" # fix should be "\12"
|
= help: Combine string literals

Expand All @@ -474,3 +478,20 @@ ISC.py:92:5: ISC001 [*] Implicitly concatenated string literals on one line
91 91 | _ = "\12""8" # fix should be "\128"
92 |-_ = "\12""foo" # fix should be "\12foo"
92 |+_ = "\12foo" # fix should be "\12foo"
93 93 | _ = "\12" "" # fix should be "\12"

ISC.py:93:5: ISC001 [*] Implicitly concatenated string literals on one line
|
91 | _ = "\12""8" # fix should be "\128"
92 | _ = "\12""foo" # fix should be "\12foo"
93 | _ = "\12" "" # fix should be "\12"
| ^^^^^^^^ ISC001
|
= help: Combine string literals

Safe fix
90 90 | _ = "\8""0" # fix should be "\80"
91 91 | _ = "\12""8" # fix should be "\128"
92 92 | _ = "\12""foo" # fix should be "\12foo"
93 |-_ = "\12" "" # fix should be "\12"
93 |+_ = "\12" # fix should be "\12"
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ ISC.py:90:5: ISC001 [*] Implicitly concatenated string literals on one line
90 |+_ = "\80" # fix should be "\80"
91 91 | _ = "\12""8" # fix should be "\128"
92 92 | _ = "\12""foo" # fix should be "\12foo"
93 93 | _ = "\12" "" # fix should be "\12"

ISC.py:91:5: ISC001 [*] Implicitly concatenated string literals on one line
|
Expand All @@ -448,6 +449,7 @@ ISC.py:91:5: ISC001 [*] Implicitly concatenated string literals on one line
91 | _ = "\12""8" # fix should be "\128"
| ^^^^^^^^ ISC001
92 | _ = "\12""foo" # fix should be "\12foo"
93 | _ = "\12" "" # fix should be "\12"
|
= help: Combine string literals

Expand All @@ -458,13 +460,15 @@ ISC.py:91:5: ISC001 [*] Implicitly concatenated string literals on one line
91 |-_ = "\12""8" # fix should be "\128"
91 |+_ = "\128" # fix should be "\128"
92 92 | _ = "\12""foo" # fix should be "\12foo"
93 93 | _ = "\12" "" # fix should be "\12"

ISC.py:92:5: ISC001 [*] Implicitly concatenated string literals on one line
|
90 | _ = "\8""0" # fix should be "\80"
91 | _ = "\12""8" # fix should be "\128"
92 | _ = "\12""foo" # fix should be "\12foo"
| ^^^^^^^^^^ ISC001
93 | _ = "\12" "" # fix should be "\12"
|
= help: Combine string literals

Expand All @@ -474,3 +478,20 @@ ISC.py:92:5: ISC001 [*] Implicitly concatenated string literals on one line
91 91 | _ = "\12""8" # fix should be "\128"
92 |-_ = "\12""foo" # fix should be "\12foo"
92 |+_ = "\12foo" # fix should be "\12foo"
93 93 | _ = "\12" "" # fix should be "\12"

ISC.py:93:5: ISC001 [*] Implicitly concatenated string literals on one line
|
91 | _ = "\12""8" # fix should be "\128"
92 | _ = "\12""foo" # fix should be "\12foo"
93 | _ = "\12" "" # fix should be "\12"
| ^^^^^^^^ ISC001
|
= help: Combine string literals

Safe fix
90 90 | _ = "\8""0" # fix should be "\80"
91 91 | _ = "\12""8" # fix should be "\128"
92 92 | _ = "\12""foo" # fix should be "\12foo"
93 |-_ = "\12" "" # fix should be "\12"
93 |+_ = "\12" # fix should be "\12"

0 comments on commit 25805a2

Please sign in to comment.