Skip to content

Commit 84f7391

Browse files
Use Cow in printf rewrite rule (#7986)
Small thing that bothered me when looking into the regex update.
1 parent 7da4e28 commit 84f7391

File tree

2 files changed

+31
-31
lines changed

2 files changed

+31
-31
lines changed
Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
use once_cell::sync::Lazy;
22
use regex::{Captures, Regex};
3+
use std::borrow::Cow;
34

45
static CURLY_BRACES: Lazy<Regex> = Lazy::new(|| Regex::new(r"(\\N\{[^}]+})|([{}])").unwrap());
56

6-
pub(super) fn curly_escape(text: &str) -> String {
7+
pub(super) fn curly_escape(text: &str) -> Cow<'_, str> {
78
// Match all curly braces. This will include named unicode escapes (like
89
// \N{SNOWMAN}), which we _don't_ want to escape, so take care to preserve them.
9-
CURLY_BRACES
10-
.replace_all(text, |caps: &Captures| {
11-
if let Some(match_) = caps.get(1) {
12-
match_.as_str().to_string()
10+
CURLY_BRACES.replace_all(text, |caps: &Captures| {
11+
if let Some(match_) = caps.get(1) {
12+
match_.as_str().to_string()
13+
} else {
14+
if &caps[2] == "{" {
15+
"{{".to_string()
1316
} else {
14-
if &caps[2] == "{" {
15-
"{{".to_string()
16-
} else {
17-
"}}".to_string()
18-
}
17+
"}}".to_string()
1918
}
20-
})
21-
.to_string()
19+
}
20+
})
2221
}

crates/ruff_linter/src/rules/pyupgrade/rules/printf_string_formatting.rs

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::borrow::Cow;
12
use std::str::FromStr;
23

34
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
@@ -105,7 +106,7 @@ fn simplify_conversion_flag(flags: CConversionFlags) -> String {
105106
}
106107

107108
/// Convert a [`PercentFormat`] struct into a `String`.
108-
fn handle_part(part: &CFormatPart<String>) -> String {
109+
fn handle_part(part: &CFormatPart<String>) -> Cow<'_, str> {
109110
match part {
110111
CFormatPart::Literal(item) => curly_escape(item),
111112
CFormatPart::Spec(spec) => {
@@ -114,7 +115,7 @@ fn handle_part(part: &CFormatPart<String>) -> String {
114115
// TODO(charlie): What case is this?
115116
if spec.format_char == '%' {
116117
format_string.push('%');
117-
return format_string;
118+
return Cow::Owned(format_string);
118119
}
119120

120121
format_string.push('{');
@@ -171,37 +172,38 @@ fn handle_part(part: &CFormatPart<String>) -> String {
171172
format_string.push(spec.format_char);
172173
}
173174
format_string.push('}');
174-
format_string
175+
Cow::Owned(format_string)
175176
}
176177
}
177178
}
178179

179180
/// Convert a [`CFormatString`] into a `String`.
180181
fn percent_to_format(format_string: &CFormatString) -> String {
181-
let mut contents = String::new();
182-
for (.., format_part) in format_string.iter() {
183-
contents.push_str(&handle_part(format_part));
184-
}
185-
contents
182+
format_string
183+
.iter()
184+
.map(|(_, part)| handle_part(part))
185+
.collect()
186186
}
187187

188188
/// If a tuple has one argument, remove the comma; otherwise, return it as-is.
189-
fn clean_params_tuple(right: &Expr, locator: &Locator) -> String {
190-
let mut contents = locator.slice(right).to_string();
189+
fn clean_params_tuple<'a>(right: &Expr, locator: &Locator<'a>) -> Cow<'a, str> {
191190
if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &right {
192191
if elts.len() == 1 {
193192
if !locator.contains_line_break(right.range()) {
193+
let mut contents = locator.slice(right).to_string();
194194
for (i, character) in contents.chars().rev().enumerate() {
195195
if character == ',' {
196196
let correct_index = contents.len() - i - 1;
197197
contents.remove(correct_index);
198198
break;
199199
}
200200
}
201+
return Cow::Owned(contents);
201202
}
202203
}
203204
}
204-
contents
205+
206+
Cow::Borrowed(locator.slice(right))
205207
}
206208

207209
/// Converts a dictionary to a function call while preserving as much styling as
@@ -419,16 +421,16 @@ pub(crate) fn printf_string_formatting(checker: &mut Checker, expr: &Expr, right
419421
// Parse the parameters.
420422
let params_string = match right {
421423
Expr::Constant(_) | Expr::FString(_) => {
422-
format!("({})", checker.locator().slice(right))
424+
Cow::Owned(format!("({})", checker.locator().slice(right)))
423425
}
424426
Expr::Name(_) | Expr::Attribute(_) | Expr::Subscript(_) | Expr::Call(_) => {
425427
if num_keyword_arguments > 0 {
426428
// If we have _any_ named fields, assume the right-hand side is a mapping.
427-
format!("(**{})", checker.locator().slice(right))
429+
Cow::Owned(format!("(**{})", checker.locator().slice(right)))
428430
} else if num_positional_arguments > 1 {
429431
// If we have multiple fields, but no named fields, assume the right-hand side is a
430432
// tuple.
431-
format!("(*{})", checker.locator().slice(right))
433+
Cow::Owned(format!("(*{})", checker.locator().slice(right)))
432434
} else {
433435
// Otherwise, if we have a single field, we can't make any assumptions about the
434436
// right-hand side. It _could_ be a tuple, but it could also be a single value,
@@ -444,13 +446,12 @@ pub(crate) fn printf_string_formatting(checker: &mut Checker, expr: &Expr, right
444446
}
445447
Expr::Tuple(_) => clean_params_tuple(right, checker.locator()),
446448
Expr::Dict(_) => {
447-
if let Some(params_string) =
449+
let Some(params_string) =
448450
clean_params_dictionary(right, checker.locator(), checker.stylist())
449-
{
450-
params_string
451-
} else {
451+
else {
452452
return;
453-
}
453+
};
454+
Cow::Owned(params_string)
454455
}
455456
_ => return,
456457
};

0 commit comments

Comments
 (0)