mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-24 05:26:23 +00:00
Preserve trailing statement semicolons when using fmt: skip
(#8273)
This commit is contained in:
parent
e799f90782
commit
2c84f911c4
5 changed files with 85 additions and 3 deletions
10
crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/trailing_semi.py
vendored
Normal file
10
crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/trailing_semi.py
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
x = 1; # fmt: skip
|
||||
|
||||
x = 1 ; # fmt: skip
|
||||
|
||||
x = 1 \
|
||||
; # fmt: skip
|
||||
|
||||
x = 1 # ; # fmt: skip
|
||||
|
||||
_; #unrelated semicolon
|
|
@ -1,5 +1,7 @@
|
|||
use ruff_formatter::{FormatOwnedWithRule, FormatRefWithRule};
|
||||
use ruff_python_ast::Stmt;
|
||||
use ruff_python_ast::{AnyNodeRef, Stmt};
|
||||
use ruff_python_trivia::{SimpleToken, SimpleTokenKind, SimpleTokenizer};
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
|
@ -81,3 +83,25 @@ impl<'ast> IntoFormat<PyFormatContext<'ast>> for Stmt {
|
|||
FormatOwnedWithRule::new(self, FormatStmt)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the range of the semicolon terminating the statement or `None` if the statement
|
||||
/// isn't terminated by a semicolon.
|
||||
pub(super) fn trailing_semicolon(node: AnyNodeRef, source: &str) -> Option<TextRange> {
|
||||
debug_assert!(node.is_statement());
|
||||
|
||||
let tokenizer = SimpleTokenizer::starts_at(node.end(), source);
|
||||
|
||||
let next_token = tokenizer
|
||||
.take_while(|token| !token.kind().is_comment())
|
||||
.find(|token| !token.kind().is_trivia());
|
||||
|
||||
if let Some(SimpleToken {
|
||||
kind: SimpleTokenKind::Semi,
|
||||
range,
|
||||
}) = next_token
|
||||
{
|
||||
Some(range)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use crate::comments::{leading_comments, trailing_comments, SourceComment};
|
|||
use crate::prelude::*;
|
||||
use crate::statement::clause::ClauseHeader;
|
||||
use crate::statement::suite::SuiteChildStatement;
|
||||
use crate::statement::trailing_semicolon;
|
||||
|
||||
/// Disables formatting for all statements between the `first_suppressed` that has a leading `fmt: off` comment
|
||||
/// and the first trailing or leading `fmt: on` comment. The statements are formatted as they appear in the source code.
|
||||
|
@ -902,6 +903,15 @@ impl Format<PyFormatContext<'_>> for FormatSuppressedNode<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
// Some statements may end with a semicolon. Preserve the semicolon
|
||||
let semicolon_range = self
|
||||
.node
|
||||
.is_statement()
|
||||
.then(|| trailing_semicolon(self.node, f.context().source()))
|
||||
.flatten();
|
||||
let verbatim_range = semicolon_range.map_or(self.node.range(), |semicolon| {
|
||||
TextRange::new(self.node.start(), semicolon.end())
|
||||
});
|
||||
comments.mark_verbatim_node_comments_formatted(self.node);
|
||||
|
||||
// Write the outer comments and format the node as verbatim
|
||||
|
@ -909,7 +919,7 @@ impl Format<PyFormatContext<'_>> for FormatSuppressedNode<'_> {
|
|||
f,
|
||||
[
|
||||
leading_comments(node_comments.leading),
|
||||
verbatim_text(self.node),
|
||||
verbatim_text(verbatim_range),
|
||||
trailing_comments(node_comments.trailing)
|
||||
]
|
||||
)
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/trailing_semi.py
|
||||
---
|
||||
## Input
|
||||
```py
|
||||
x = 1; # fmt: skip
|
||||
|
||||
x = 1 ; # fmt: skip
|
||||
|
||||
x = 1 \
|
||||
; # fmt: skip
|
||||
|
||||
x = 1 # ; # fmt: skip
|
||||
|
||||
_; #unrelated semicolon
|
||||
```
|
||||
|
||||
## Output
|
||||
```py
|
||||
x = 1; # fmt: skip
|
||||
|
||||
x = 1 ; # fmt: skip
|
||||
|
||||
x = 1 \
|
||||
; # fmt: skip
|
||||
|
||||
x = 1 # ; # fmt: skip
|
||||
|
||||
_ # unrelated semicolon
|
||||
```
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue