Skip to content

Commit

Permalink
Preserve dangling f-string comments
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaReiser committed Aug 10, 2023
1 parent ac5c8bb commit e69ff5d
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
(
f'{one}'
f'{two}'
)


rf"Not-so-tricky \"quote"

# Regression test for fstrings dropping comments
result_f = (
'Traceback (most recent call last):\n'
f' File "{__file__}", line {lineno_f+5}, in _check_recursive_traceback_display\n'
' f()\n'
f' File "{__file__}", line {lineno_f+1}, in f\n'
' f()\n'
f' File "{__file__}", line {lineno_f+1}, in f\n'
' f()\n'
f' File "{__file__}", line {lineno_f+1}, in f\n'
' f()\n'
# XXX: The following line changes depending on whether the tests
# are run through the interactive interpreter or with -m
# It also varies depending on the platform (stack size)
# Fortunately, we don't care about exactness here, so we use regex
r' \[Previous line repeated (\d+) more times\]' '\n'
'RecursionError: maximum recursion depth exceeded\n'
)

This file was deleted.

7 changes: 7 additions & 0 deletions crates/ruff_python_formatter/src/comments/placement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ pub(super) fn place_comment<'a>(
handle_leading_class_with_decorators_comment(comment, class_def)
}
AnyNodeRef::StmtImportFrom(import_from) => handle_import_from_comment(comment, import_from),
AnyNodeRef::ExprConstant(_) => {
if let Some(AnyNodeRef::ExprFString(fstring)) = comment.enclosing_parent() {
CommentPlacement::dangling(fstring, comment)
} else {
CommentPlacement::Default(comment)
}
}
AnyNodeRef::ExprList(_)
| AnyNodeRef::ExprSet(_)
| AnyNodeRef::ExprGeneratorExp(_)
Expand Down
8 changes: 8 additions & 0 deletions crates/ruff_python_formatter/src/comments/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ impl<'ast> PreorderVisitor<'ast> for CommentsVisitor<'ast> {
enclosing: enclosing_node,
preceding: self.preceding_node,
following: Some(node),
parent: self.parents.iter().rev().nth(1).copied(),
line_position: text_position(*comment_range, self.source_code),
slice: self.source_code.slice(*comment_range),
};
Expand Down Expand Up @@ -117,6 +118,7 @@ impl<'ast> PreorderVisitor<'ast> for CommentsVisitor<'ast> {

let comment = DecoratedComment {
enclosing: node,
parent: self.parents.last().copied(),
preceding: self.preceding_node,
following: None,
line_position: text_position(*comment_range, self.source_code),
Expand Down Expand Up @@ -179,6 +181,7 @@ pub(super) struct DecoratedComment<'a> {
enclosing: AnyNodeRef<'a>,
preceding: Option<AnyNodeRef<'a>>,
following: Option<AnyNodeRef<'a>>,
parent: Option<AnyNodeRef<'a>>,
line_position: CommentLinePosition,
slice: SourceCodeSlice,
}
Expand All @@ -204,6 +207,11 @@ impl<'a> DecoratedComment<'a> {
self.enclosing
}

/// Returns the parent of the enclosing node, if any
pub(super) fn enclosing_parent(&self) -> Option<AnyNodeRef<'a>> {
self.parent
}

/// Returns the slice into the source code.
pub(super) fn slice(&self) -> &SourceCodeSlice {
&self.slice
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/fstring.py
---
## Input
```py
(
f'{one}'
f'{two}'
)
rf"Not-so-tricky \"quote"
# Regression test for fstrings dropping comments
result_f = (
'Traceback (most recent call last):\n'
f' File "{__file__}", line {lineno_f+5}, in _check_recursive_traceback_display\n'
' f()\n'
f' File "{__file__}", line {lineno_f+1}, in f\n'
' f()\n'
f' File "{__file__}", line {lineno_f+1}, in f\n'
' f()\n'
f' File "{__file__}", line {lineno_f+1}, in f\n'
' f()\n'
# XXX: The following line changes depending on whether the tests
# are run through the interactive interpreter or with -m
# It also varies depending on the platform (stack size)
# Fortunately, we don't care about exactness here, so we use regex
r' \[Previous line repeated (\d+) more times\]' '\n'
'RecursionError: maximum recursion depth exceeded\n'
)
```

## Output
```py
(f"{one}" f"{two}")
rf'Not-so-tricky "quote'
# Regression test for fstrings dropping comments
result_f = (
"Traceback (most recent call last):\n"
f' File "{__file__}", line {lineno_f+5}, in _check_recursive_traceback_display\n'
" f()\n"
f' File "{__file__}", line {lineno_f+1}, in f\n'
" f()\n"
f' File "{__file__}", line {lineno_f+1}, in f\n'
" f()\n"
f' File "{__file__}", line {lineno_f+1}, in f\n'
" f()\n"
# XXX: The following line changes depending on whether the tests
# are run through the interactive interpreter or with -m
# It also varies depending on the platform (stack size)
# Fortunately, we don't care about exactness here, so we use regex
r" \[Previous line repeated (\d+) more times\]"
"\n"
"RecursionError: maximum recursion depth exceeded\n"
)
```



This file was deleted.

0 comments on commit e69ff5d

Please sign in to comment.