Skip to content

Commit

Permalink
Preserve multiline implicit concatenated strings in docstring positions
Browse files Browse the repository at this point in the history
## Summary
This is a bug fix for #13928

We failed to preserve multiline implicit concatenated
strings that can't be automatically joined in docstring positions:

```py
def test():
  (
     r"This is a docstring"
     "and Ruff can't automatically join it"
  )
```

## Test plan
Added formatter tests
  • Loading branch information
MichaReiser committed Dec 23, 2024
1 parent 8d32708 commit d9f0ce8
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,20 @@
f"""aaaa{
10}aaaaa""" fr"""bbbbbbbbbbbbbbbbbbbb"""
)

# In docstring positions
def docstring():
(
r"aaaaaaaaa"
"bbbbbbbbbbbbbbbbbbbb"
)

def docstring_flat():
(
r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb"
)

def docstring_flat_overlong():
(
r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
)
40 changes: 32 additions & 8 deletions crates/ruff_python_formatter/src/expression/expr_string_literal.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
use ruff_formatter::FormatRuleWithOptions;
use ruff_python_ast::{AnyNodeRef, ExprStringLiteral, StringLike};

use crate::builders::parenthesize_if_expands;
use crate::expression::parentheses::{
in_parentheses_only_group, NeedsParentheses, OptionalParentheses,
};
use crate::other::string_literal::StringLiteralKind;
use crate::prelude::*;
use crate::string::implicit::FormatImplicitConcatenatedStringFlat;
use crate::string::implicit::{
FormatImplicitConcatenatedStringExpanded, FormatImplicitConcatenatedStringFlat,
ImplicitConcatenatedLayout,
};
use crate::string::{implicit::FormatImplicitConcatenatedString, StringLikeExtensions};
use ruff_formatter::FormatRuleWithOptions;
use ruff_python_ast::{AnyNodeRef, ExprStringLiteral, StringLike};

#[derive(Default)]
pub struct FormatExprStringLiteral {
Expand All @@ -30,17 +33,38 @@ impl FormatNodeRule<ExprStringLiteral> for FormatExprStringLiteral {
if let [string_literal] = value.as_slice() {
string_literal.format().with_options(self.kind).fmt(f)
} else {
// Always join strings that aren't parenthesized and thus, always on a single line.
if !f.context().node_level().is_parenthesized() {
if f.context().node_level().is_parenthesized() {
in_parentheses_only_group(&FormatImplicitConcatenatedString::new(item)).fmt(f)
} else {
// Always join strings that aren't parenthesized and thus, always on a single line.
if let Some(mut format_flat) =
FormatImplicitConcatenatedStringFlat::new(item.into(), f.context())
{
format_flat.set_docstring(self.kind.is_docstring());
return format_flat.fmt(f);
}
}

in_parentheses_only_group(&FormatImplicitConcatenatedString::new(item)).fmt(f)
// ```py
// def test():
// (
// r"a"
// "b"
// )
// ```
if self.kind.is_docstring() {
parenthesize_if_expands(&FormatImplicitConcatenatedStringExpanded::new(
item.into(),
ImplicitConcatenatedLayout::Multipart,
))
.fmt(f)
} else {
FormatImplicitConcatenatedStringExpanded::new(
item.into(),
ImplicitConcatenatedLayout::Multipart,
)
.fmt(f)
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,23 @@ r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb"
f"""aaaa{
10}aaaaa""" fr"""bbbbbbbbbbbbbbbbbbbb"""
)
# In docstring positions
def docstring():
(
r"aaaaaaaaa"
"bbbbbbbbbbbbbbbbbbbb"
)
def docstring_flat():
(
r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb"
)
def docstring_flat_overlong():
(
r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
)
```

## Outputs
Expand Down Expand Up @@ -429,6 +446,22 @@ r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb"
10}aaaaa"""
rf"""bbbbbbbbbbbbbbbbbbbb"""
)
# In docstring positions
def docstring():
r"aaaaaaaaa" "bbbbbbbbbbbbbbbbbbbb"
def docstring_flat():
r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb"
def docstring_flat_overlong():
(
r"aaaaaaaaa"
r"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
)
```


Expand Down Expand Up @@ -495,7 +528,7 @@ r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb"
...
@@ -193,16 +205,8 @@
@@ -193,24 +205,19 @@
r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb"
Expand All @@ -514,6 +547,18 @@ r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb"
- rf"""bbbbbbbbbbbbbbbbbbbb"""
-)
+(f"""aaaa{10}aaaaa""" rf"""bbbbbbbbbbbbbbbbbbbb""")
# In docstring positions
def docstring():
- r"aaaaaaaaa" "bbbbbbbbbbbbbbbbbbbb"
+ (
+ r"aaaaaaaaa"
+ "bbbbbbbbbbbbbbbbbbbb"
+ )
def docstring_flat():
```


Expand Down Expand Up @@ -741,6 +786,22 @@ r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb'
10}aaaaa"""
rf"""bbbbbbbbbbbbbbbbbbbb"""
)
# In docstring positions
def docstring():
r'aaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbb'
def docstring_flat():
r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb'
def docstring_flat_overlong():
(
r'aaaaaaaaa'
r'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
)
```


Expand Down Expand Up @@ -807,7 +868,7 @@ r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb'
...
@@ -193,16 +205,8 @@
@@ -193,24 +205,19 @@
r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb'
Expand All @@ -826,4 +887,16 @@ r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb'
- rf"""bbbbbbbbbbbbbbbbbbbb"""
-)
+(f"""aaaa{10}aaaaa""" rf"""bbbbbbbbbbbbbbbbbbbb""")
# In docstring positions
def docstring():
- r'aaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbb'
+ (
+ r'aaaaaaaaa'
+ 'bbbbbbbbbbbbbbbbbbbb'
+ )
def docstring_flat():
```

0 comments on commit d9f0ce8

Please sign in to comment.