Skip to content

Commit

Permalink
Make quoting decision per f-string instead of entire f-string expression
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaReiser committed Oct 7, 2024
1 parent 0f47c8a commit 9972106
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -313,4 +313,5 @@
_ = (
'This string should change its quotes to double quotes'
f'This string uses double quotes in an expression {"woah"}'
f'This f-string does not use any quotes.'
)
38 changes: 33 additions & 5 deletions crates/ruff_python_formatter/src/other/f_string.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use crate::prelude::*;
use crate::preview::{
is_f_string_formatting_enabled, is_f_string_implicit_concatenated_string_literal_quotes_enabled,
};
use crate::string::{Quoting, StringNormalizer, StringQuotes};
use ruff_formatter::write;
use ruff_python_ast::{AnyStringFlags, FString, StringFlags};
use ruff_source_file::Locator;

use crate::prelude::*;
use crate::preview::is_f_string_formatting_enabled;
use crate::string::{Quoting, StringNormalizer, StringQuotes};
use ruff_text_size::Ranged;

use super::f_string_element::FormatFStringElement;

Expand All @@ -29,8 +31,17 @@ impl Format<PyFormatContext<'_>> for FormatFString<'_> {
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
let locator = f.context().locator();

// If the preview style is enabled, make the decision on what quotes to use locally for each
// f-string instead of globally for the entire f-string expression.
let quoting =
if is_f_string_implicit_concatenated_string_literal_quotes_enabled(f.context()) {
f_string_quoting(self.value, &locator)
} else {
self.quoting
};

let normalizer = StringNormalizer::from_context(f.context())
.with_quoting(self.quoting)
.with_quoting(quoting)
.with_preferred_quote_style(f.options().quote_style());

// If f-string formatting is disabled (not in preview), then we will
Expand Down Expand Up @@ -140,3 +151,20 @@ impl FStringLayout {
matches!(self, FStringLayout::Multiline)
}
}

fn f_string_quoting(f_string: &FString, locator: &Locator) -> Quoting {
let triple_quoted = f_string.flags.is_triple_quoted();

if f_string.elements.expressions().any(|expression| {
let string_content = locator.slice(expression.range());
if triple_quoted {
string_content.contains(r#"""""#) || string_content.contains("'''")
} else {
string_content.contains(['"', '\''])
}
}) {
Quoting::Preserve
} else {
Quoting::CanChange
}
}
5 changes: 4 additions & 1 deletion crates/ruff_python_formatter/src/other/string_literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,11 @@ impl StringLiteralKind {
StringLiteralKind::String | StringLiteralKind::Docstring => Quoting::CanChange,
#[allow(deprecated)]
StringLiteralKind::InImplicitlyConcatenatedFString(quoting) => {
// Allow string literals to pick the "optimal" quote character
// even if any other fstring in the implicit concatenation uses an expression
// containing a quote character.
// TODO: Remove StringLiteralKind::InImplicitlyConcatenatedFString when promoting
// this style to stable
// this style to stable and remove the layout from `AnyStringPart::String`.
if is_f_string_implicit_concatenated_string_literal_quotes_enabled(context) {
Quoting::CanChange
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ hello {
_ = (
'This string should change its quotes to double quotes'
f'This string uses double quotes in an expression {"woah"}'
f'This f-string does not use any quotes.'
)
```

Expand Down Expand Up @@ -662,6 +663,7 @@ hello {
_ = (
"This string should change its quotes to double quotes"
f'This string uses double quotes in an expression {"woah"}'
f"This f-string does not use any quotes."
)
```

Expand Down Expand Up @@ -993,6 +995,7 @@ hello {
_ = (
'This string should change its quotes to double quotes'
f'This string uses double quotes in an expression {"woah"}'
f'This f-string does not use any quotes.'
)
```

Expand Down Expand Up @@ -1300,7 +1303,7 @@ _ = (
# comment 27
# comment 28
} woah {x}"
@@ -287,26 +299,26 @@
@@ -287,27 +299,27 @@
if indent2:
foo = f"""hello world
hello {
Expand Down Expand Up @@ -1342,5 +1345,7 @@ _ = (
- 'This string should change its quotes to double quotes'
+ "This string should change its quotes to double quotes"
f'This string uses double quotes in an expression {"woah"}'
- f'This f-string does not use any quotes.'
+ f"This f-string does not use any quotes."
)
```

0 comments on commit 9972106

Please # to comment.