mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-22 20:45:11 +00:00
Support fmt: skip
for simple-statements and decorators (#6561)
This commit is contained in:
parent
e3ecbe660e
commit
4dc32a00d0
40 changed files with 545 additions and 316 deletions
19
crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/decorators.py
vendored
Normal file
19
crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/decorators.py
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
@FormattedDecorator(a =b)
|
||||||
|
# leading comment
|
||||||
|
@MyDecorator( # dangling comment
|
||||||
|
list = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12], x = some_other_function_call({ "test": "value", "more": "other"})) # fmt: skip
|
||||||
|
# leading class comment
|
||||||
|
class Test:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@FormattedDecorator(a =b)
|
||||||
|
# leading comment
|
||||||
|
@MyDecorator( # dangling comment
|
||||||
|
list = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12], x = some_other_function_call({ "test": "value", "more": "other"})) # fmt: skip
|
||||||
|
# leading class comment
|
||||||
|
def test():
|
||||||
|
pass
|
||||||
|
|
13
crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/docstrings.py
vendored
Normal file
13
crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/docstrings.py
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
def test():
|
||||||
|
# leading comment
|
||||||
|
""" This docstring does not
|
||||||
|
get formatted
|
||||||
|
""" # fmt: skip
|
||||||
|
# trailing comment
|
||||||
|
|
||||||
|
def test():
|
||||||
|
# leading comment
|
||||||
|
""" This docstring gets formatted
|
||||||
|
""" # trailing comment
|
||||||
|
|
||||||
|
and_this + gets + formatted + too
|
|
@ -215,6 +215,18 @@ pub(crate) enum SuppressionKind {
|
||||||
Skip,
|
Skip,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SuppressionKind {
|
||||||
|
pub(crate) fn has_skip_comment(trailing_comments: &[SourceComment], source: &str) -> bool {
|
||||||
|
trailing_comments.iter().any(|comment| {
|
||||||
|
comment.line_position().is_end_of_line()
|
||||||
|
&& matches!(
|
||||||
|
comment.suppression_kind(source),
|
||||||
|
Some(SuppressionKind::Skip | SuppressionKind::Off)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Ranged for SourceComment {
|
impl Ranged for SourceComment {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn range(&self) -> TextRange {
|
fn range(&self) -> TextRange {
|
||||||
|
|
|
@ -905,7 +905,7 @@ fn handle_leading_class_with_decorators_comment<'a>(
|
||||||
comment: DecoratedComment<'a>,
|
comment: DecoratedComment<'a>,
|
||||||
class_def: &'a ast::StmtClassDef,
|
class_def: &'a ast::StmtClassDef,
|
||||||
) -> CommentPlacement<'a> {
|
) -> CommentPlacement<'a> {
|
||||||
if comment.start() < class_def.name.start() {
|
if comment.line_position().is_own_line() && comment.start() < class_def.name.start() {
|
||||||
if let Some(decorator) = class_def.decorator_list.last() {
|
if let Some(decorator) = class_def.decorator_list.last() {
|
||||||
if decorator.end() < comment.start() {
|
if decorator.end() < comment.start() {
|
||||||
return CommentPlacement::dangling(class_def, comment);
|
return CommentPlacement::dangling(class_def, comment);
|
||||||
|
|
|
@ -94,7 +94,7 @@ impl FormatRule<Expr, PyFormatContext<'_>> for FormatExpr {
|
||||||
Expr::List(expr) => expr.format().fmt(f),
|
Expr::List(expr) => expr.format().fmt(f),
|
||||||
Expr::Tuple(expr) => expr.format().fmt(f),
|
Expr::Tuple(expr) => expr.format().fmt(f),
|
||||||
Expr::Slice(expr) => expr.format().fmt(f),
|
Expr::Slice(expr) => expr.format().fmt(f),
|
||||||
Expr::IpyEscapeCommand(_) => todo!(),
|
Expr::IpyEscapeCommand(expr) => expr.format().fmt(f),
|
||||||
});
|
});
|
||||||
|
|
||||||
let parenthesize = match parentheses {
|
let parenthesize = match parentheses {
|
||||||
|
|
|
@ -19,6 +19,7 @@ use crate::comments::{
|
||||||
};
|
};
|
||||||
use crate::context::PyFormatContext;
|
use crate::context::PyFormatContext;
|
||||||
pub use crate::options::{MagicTrailingComma, PyFormatOptions, QuoteStyle};
|
pub use crate::options::{MagicTrailingComma, PyFormatOptions, QuoteStyle};
|
||||||
|
use crate::verbatim::suppressed_node;
|
||||||
|
|
||||||
pub(crate) mod builders;
|
pub(crate) mod builders;
|
||||||
pub mod cli;
|
pub mod cli;
|
||||||
|
@ -50,24 +51,21 @@ where
|
||||||
|
|
||||||
let node_comments = comments.leading_dangling_trailing_comments(node.as_any_node_ref());
|
let node_comments = comments.leading_dangling_trailing_comments(node.as_any_node_ref());
|
||||||
|
|
||||||
write!(
|
if self.is_suppressed(node_comments.trailing, f.context()) {
|
||||||
f,
|
suppressed_node(node.as_any_node_ref()).fmt(f)
|
||||||
[
|
} else {
|
||||||
leading_comments(node_comments.leading),
|
leading_comments(node_comments.leading).fmt(f)?;
|
||||||
source_position(node.start())
|
self.fmt_fields(node, f)?;
|
||||||
]
|
self.fmt_dangling_comments(node_comments.dangling, f)?;
|
||||||
)?;
|
|
||||||
|
|
||||||
self.fmt_fields(node, f)?;
|
write!(
|
||||||
self.fmt_dangling_comments(node_comments.dangling, f)?;
|
f,
|
||||||
|
[
|
||||||
write!(
|
source_position(node.end()),
|
||||||
f,
|
trailing_comments(node_comments.trailing)
|
||||||
[
|
]
|
||||||
source_position(node.end()),
|
)
|
||||||
trailing_comments(node_comments.trailing)
|
}
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Formats the node's fields.
|
/// Formats the node's fields.
|
||||||
|
@ -87,6 +85,14 @@ where
|
||||||
) -> FormatResult<()> {
|
) -> FormatResult<()> {
|
||||||
dangling_comments(dangling_node_comments).fmt(f)
|
dangling_comments(dangling_node_comments).fmt(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
_trailing_comments: &[SourceComment],
|
||||||
|
_context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
@ -236,16 +242,12 @@ if True:
|
||||||
#[ignore]
|
#[ignore]
|
||||||
#[test]
|
#[test]
|
||||||
fn quick_test() {
|
fn quick_test() {
|
||||||
let src = r#"def test():
|
let src = r#"
|
||||||
# fmt: off
|
@MyDecorator(list = a) # fmt: skip
|
||||||
|
# trailing comment
|
||||||
|
class Test:
|
||||||
|
pass
|
||||||
|
|
||||||
a + b
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# suppressed comments
|
|
||||||
|
|
||||||
a + b # formatted
|
|
||||||
|
|
||||||
"#;
|
"#;
|
||||||
// Tokenize once
|
// Tokenize once
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
use crate::expression::maybe_parenthesize_expression;
|
use crate::expression::maybe_parenthesize_expression;
|
||||||
use crate::expression::parentheses::Parenthesize;
|
use crate::expression::parentheses::Parenthesize;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
@ -23,4 +24,12 @@ impl FormatNodeRule<Decorator> for FormatDecorator {
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::prelude::*;
|
|
||||||
use ruff_formatter::{FormatOwnedWithRule, FormatRefWithRule};
|
use ruff_formatter::{FormatOwnedWithRule, FormatRefWithRule};
|
||||||
use ruff_python_ast::Stmt;
|
use ruff_python_ast::Stmt;
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub(crate) mod stmt_ann_assign;
|
pub(crate) mod stmt_ann_assign;
|
||||||
pub(crate) mod stmt_assert;
|
pub(crate) mod stmt_assert;
|
||||||
pub(crate) mod stmt_assign;
|
pub(crate) mod stmt_assign;
|
||||||
|
@ -59,7 +60,7 @@ impl FormatRule<Stmt, PyFormatContext<'_>> for FormatStmt {
|
||||||
Stmt::Break(x) => x.format().fmt(f),
|
Stmt::Break(x) => x.format().fmt(f),
|
||||||
Stmt::Continue(x) => x.format().fmt(f),
|
Stmt::Continue(x) => x.format().fmt(f),
|
||||||
Stmt::TypeAlias(x) => x.format().fmt(f),
|
Stmt::TypeAlias(x) => x.format().fmt(f),
|
||||||
Stmt::IpyEscapeCommand(_) => todo!(),
|
Stmt::IpyEscapeCommand(x) => x.format().fmt(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
use crate::expression::maybe_parenthesize_expression;
|
use crate::expression::maybe_parenthesize_expression;
|
||||||
use crate::expression::parentheses::Parenthesize;
|
use crate::expression::parentheses::Parenthesize;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
@ -42,4 +43,12 @@ impl FormatNodeRule<StmtAnnAssign> for FormatStmtAnnAssign {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
|
use crate::context::PyFormatContext;
|
||||||
use crate::expression::maybe_parenthesize_expression;
|
use crate::expression::maybe_parenthesize_expression;
|
||||||
use crate::expression::parentheses::Parenthesize;
|
use crate::expression::parentheses::Parenthesize;
|
||||||
use crate::{FormatNodeRule, PyFormatter};
|
use crate::{FormatNodeRule, PyFormatter};
|
||||||
|
@ -38,4 +40,12 @@ impl FormatNodeRule<StmtAssert> for FormatStmtAssert {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
use ruff_formatter::{format_args, write, FormatError};
|
use ruff_formatter::{format_args, write, FormatError};
|
||||||
use ruff_python_ast::{Expr, StmtAssign};
|
use ruff_python_ast::{Expr, StmtAssign};
|
||||||
|
|
||||||
|
@ -42,6 +43,14 @@ impl FormatNodeRule<StmtAssign> for FormatStmtAssign {
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
use ruff_formatter::write;
|
||||||
|
use ruff_python_ast::StmtAugAssign;
|
||||||
|
|
||||||
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
use crate::expression::maybe_parenthesize_expression;
|
use crate::expression::maybe_parenthesize_expression;
|
||||||
use crate::expression::parentheses::Parenthesize;
|
use crate::expression::parentheses::Parenthesize;
|
||||||
use crate::{AsFormat, FormatNodeRule, PyFormatter};
|
use crate::prelude::*;
|
||||||
use ruff_formatter::prelude::{space, text};
|
use crate::{AsFormat, FormatNodeRule};
|
||||||
use ruff_formatter::{write, Buffer, FormatResult};
|
|
||||||
use ruff_python_ast::StmtAugAssign;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatStmtAugAssign;
|
pub struct FormatStmtAugAssign;
|
||||||
|
@ -28,4 +30,12 @@ impl FormatNodeRule<StmtAugAssign> for FormatStmtAugAssign {
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::{FormatNodeRule, PyFormatter};
|
|
||||||
use ruff_formatter::prelude::text;
|
|
||||||
use ruff_formatter::{Format, FormatResult};
|
|
||||||
use ruff_python_ast::StmtBreak;
|
use ruff_python_ast::StmtBreak;
|
||||||
|
|
||||||
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
|
use crate::prelude::*;
|
||||||
|
use crate::FormatNodeRule;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatStmtBreak;
|
pub struct FormatStmtBreak;
|
||||||
|
|
||||||
|
@ -10,4 +11,12 @@ impl FormatNodeRule<StmtBreak> for FormatStmtBreak {
|
||||||
fn fmt_fields(&self, _item: &StmtBreak, f: &mut PyFormatter) -> FormatResult<()> {
|
fn fmt_fields(&self, _item: &StmtBreak, f: &mut PyFormatter) -> FormatResult<()> {
|
||||||
text("break").fmt(f)
|
text("break").fmt(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use ruff_formatter::{write, Buffer};
|
use ruff_formatter::write;
|
||||||
use ruff_python_ast::{Ranged, StmtClassDef};
|
use ruff_python_ast::{Decorator, Ranged, StmtClassDef};
|
||||||
use ruff_python_trivia::lines_after_ignoring_trivia;
|
use ruff_python_trivia::lines_after_ignoring_trivia;
|
||||||
|
|
||||||
use crate::comments::{leading_comments, trailing_comments, SourceComment};
|
use crate::comments::{leading_comments, trailing_comments, SourceComment};
|
||||||
|
@ -30,31 +30,11 @@ impl FormatNodeRule<StmtClassDef> for FormatStmtClassDef {
|
||||||
let (leading_definition_comments, trailing_definition_comments) =
|
let (leading_definition_comments, trailing_definition_comments) =
|
||||||
dangling_comments.split_at(trailing_definition_comments_start);
|
dangling_comments.split_at(trailing_definition_comments_start);
|
||||||
|
|
||||||
if let Some(last_decorator) = decorator_list.last() {
|
FormatDecorators {
|
||||||
f.join_with(hard_line_break())
|
decorators: decorator_list,
|
||||||
.entries(decorator_list.iter().formatted())
|
leading_definition_comments,
|
||||||
.finish()?;
|
|
||||||
|
|
||||||
if leading_definition_comments.is_empty() {
|
|
||||||
write!(f, [hard_line_break()])?;
|
|
||||||
} else {
|
|
||||||
// Write any leading definition comments (between last decorator and the header)
|
|
||||||
// while maintaining the right amount of empty lines between the comment
|
|
||||||
// and the last decorator.
|
|
||||||
let leading_line =
|
|
||||||
if lines_after_ignoring_trivia(last_decorator.end(), f.context().source()) <= 1
|
|
||||||
{
|
|
||||||
hard_line_break()
|
|
||||||
} else {
|
|
||||||
empty_line()
|
|
||||||
};
|
|
||||||
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
[leading_line, leading_comments(leading_definition_comments)]
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
.fmt(f)?;
|
||||||
|
|
||||||
write!(f, [text("class"), space(), name.format()])?;
|
write!(f, [text("class"), space(), name.format()])?;
|
||||||
|
|
||||||
|
@ -136,3 +116,43 @@ impl FormatNodeRule<StmtClassDef> for FormatStmtClassDef {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) struct FormatDecorators<'a> {
|
||||||
|
pub(super) decorators: &'a [Decorator],
|
||||||
|
pub(super) leading_definition_comments: &'a [SourceComment],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Format<PyFormatContext<'_>> for FormatDecorators<'_> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
|
||||||
|
if let Some(last_decorator) = self.decorators.last() {
|
||||||
|
f.join_with(hard_line_break())
|
||||||
|
.entries(self.decorators.iter().formatted())
|
||||||
|
.finish()?;
|
||||||
|
|
||||||
|
if self.leading_definition_comments.is_empty() {
|
||||||
|
write!(f, [hard_line_break()])?;
|
||||||
|
} else {
|
||||||
|
// Write any leading definition comments (between last decorator and the header)
|
||||||
|
// while maintaining the right amount of empty lines between the comment
|
||||||
|
// and the last decorator.
|
||||||
|
let leading_line =
|
||||||
|
if lines_after_ignoring_trivia(last_decorator.end(), f.context().source()) <= 1
|
||||||
|
{
|
||||||
|
hard_line_break()
|
||||||
|
} else {
|
||||||
|
empty_line()
|
||||||
|
};
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
[
|
||||||
|
leading_line,
|
||||||
|
leading_comments(self.leading_definition_comments)
|
||||||
|
]
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::{FormatNodeRule, PyFormatter};
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
use ruff_formatter::prelude::text;
|
|
||||||
use ruff_formatter::{Format, FormatResult};
|
|
||||||
use ruff_python_ast::StmtContinue;
|
use ruff_python_ast::StmtContinue;
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
use crate::FormatNodeRule;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatStmtContinue;
|
pub struct FormatStmtContinue;
|
||||||
|
|
||||||
|
@ -10,4 +11,12 @@ impl FormatNodeRule<StmtContinue> for FormatStmtContinue {
|
||||||
fn fmt_fields(&self, _item: &StmtContinue, f: &mut PyFormatter) -> FormatResult<()> {
|
fn fmt_fields(&self, _item: &StmtContinue, f: &mut PyFormatter) -> FormatResult<()> {
|
||||||
text("continue").fmt(f)
|
text("continue").fmt(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
|
use ruff_formatter::write;
|
||||||
|
use ruff_python_ast::{Ranged, StmtDelete};
|
||||||
|
|
||||||
use crate::builders::{parenthesize_if_expands, PyFormatterExtensions};
|
use crate::builders::{parenthesize_if_expands, PyFormatterExtensions};
|
||||||
use crate::comments::{dangling_node_comments, SourceComment};
|
use crate::comments::{dangling_node_comments, SourceComment, SuppressionKind};
|
||||||
use crate::expression::maybe_parenthesize_expression;
|
use crate::expression::maybe_parenthesize_expression;
|
||||||
use crate::expression::parentheses::Parenthesize;
|
use crate::expression::parentheses::Parenthesize;
|
||||||
use crate::{FormatNodeRule, PyFormatter};
|
use crate::prelude::*;
|
||||||
use ruff_formatter::prelude::{block_indent, format_with, space, text};
|
use crate::FormatNodeRule;
|
||||||
use ruff_formatter::{write, Buffer, Format, FormatResult};
|
|
||||||
use ruff_python_ast::{Ranged, StmtDelete};
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatStmtDelete;
|
pub struct FormatStmtDelete;
|
||||||
|
@ -61,4 +62,12 @@ impl FormatNodeRule<StmtDelete> for FormatStmtDelete {
|
||||||
// Handled in `fmt_fields`
|
// Handled in `fmt_fields`
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
use ruff_python_ast as ast;
|
use ruff_python_ast as ast;
|
||||||
use ruff_python_ast::{Expr, Operator, StmtExpr};
|
use ruff_python_ast::{Expr, Operator, StmtExpr};
|
||||||
|
|
||||||
|
@ -19,6 +20,14 @@ impl FormatNodeRule<StmtExpr> for FormatStmtExpr {
|
||||||
value.format().fmt(f)
|
value.format().fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn is_arithmetic_like(expression: &Expr) -> bool {
|
const fn is_arithmetic_like(expression: &Expr) -> bool {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use ruff_formatter::{format_args, write, Buffer, FormatResult};
|
use ruff_formatter::{format_args, write};
|
||||||
use ruff_python_ast::{Expr, Ranged, Stmt, StmtFor};
|
use ruff_python_ast::{Expr, Ranged, Stmt, StmtFor};
|
||||||
|
|
||||||
use crate::comments::{leading_alternate_branch_comments, trailing_comments, SourceComment};
|
use crate::comments::{leading_alternate_branch_comments, trailing_comments, SourceComment};
|
||||||
|
@ -6,7 +6,7 @@ use crate::expression::expr_tuple::TupleParentheses;
|
||||||
use crate::expression::maybe_parenthesize_expression;
|
use crate::expression::maybe_parenthesize_expression;
|
||||||
use crate::expression::parentheses::Parenthesize;
|
use crate::expression::parentheses::Parenthesize;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::{FormatNodeRule, PyFormatter};
|
use crate::FormatNodeRule;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ExprTupleWithoutParentheses<'a>(&'a Expr);
|
struct ExprTupleWithoutParentheses<'a>(&'a Expr);
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use ruff_formatter::write;
|
use ruff_formatter::write;
|
||||||
use ruff_python_ast::{Parameters, Ranged, StmtFunctionDef};
|
use ruff_python_ast::{Parameters, Ranged, StmtFunctionDef};
|
||||||
use ruff_python_trivia::{lines_after_ignoring_trivia, SimpleTokenKind, SimpleTokenizer};
|
use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
|
||||||
|
|
||||||
use crate::comments::{leading_comments, trailing_comments, SourceComment};
|
use crate::comments::{trailing_comments, SourceComment};
|
||||||
use crate::expression::maybe_parenthesize_expression;
|
use crate::expression::maybe_parenthesize_expression;
|
||||||
use crate::expression::parentheses::{Parentheses, Parenthesize};
|
use crate::expression::parentheses::{Parentheses, Parenthesize};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::statement::stmt_class_def::FormatDecorators;
|
||||||
use crate::statement::suite::SuiteKind;
|
use crate::statement::suite::SuiteKind;
|
||||||
use crate::FormatNodeRule;
|
use crate::FormatNodeRule;
|
||||||
|
|
||||||
|
@ -14,6 +15,17 @@ pub struct FormatStmtFunctionDef;
|
||||||
|
|
||||||
impl FormatNodeRule<StmtFunctionDef> for FormatStmtFunctionDef {
|
impl FormatNodeRule<StmtFunctionDef> for FormatStmtFunctionDef {
|
||||||
fn fmt_fields(&self, item: &StmtFunctionDef, f: &mut PyFormatter) -> FormatResult<()> {
|
fn fmt_fields(&self, item: &StmtFunctionDef, f: &mut PyFormatter) -> FormatResult<()> {
|
||||||
|
let StmtFunctionDef {
|
||||||
|
range: _,
|
||||||
|
is_async,
|
||||||
|
decorator_list,
|
||||||
|
name,
|
||||||
|
type_params,
|
||||||
|
parameters,
|
||||||
|
returns,
|
||||||
|
body,
|
||||||
|
} = item;
|
||||||
|
|
||||||
let comments = f.context().comments().clone();
|
let comments = f.context().comments().clone();
|
||||||
|
|
||||||
let dangling_comments = comments.dangling_comments(item);
|
let dangling_comments = comments.dangling_comments(item);
|
||||||
|
@ -23,46 +35,26 @@ impl FormatNodeRule<StmtFunctionDef> for FormatStmtFunctionDef {
|
||||||
let (leading_definition_comments, trailing_definition_comments) =
|
let (leading_definition_comments, trailing_definition_comments) =
|
||||||
dangling_comments.split_at(trailing_definition_comments_start);
|
dangling_comments.split_at(trailing_definition_comments_start);
|
||||||
|
|
||||||
if let Some(last_decorator) = item.decorator_list.last() {
|
FormatDecorators {
|
||||||
f.join_with(hard_line_break())
|
decorators: decorator_list,
|
||||||
.entries(item.decorator_list.iter().formatted())
|
leading_definition_comments,
|
||||||
.finish()?;
|
|
||||||
|
|
||||||
if leading_definition_comments.is_empty() {
|
|
||||||
write!(f, [hard_line_break()])?;
|
|
||||||
} else {
|
|
||||||
// Write any leading definition comments (between last decorator and the header)
|
|
||||||
// while maintaining the right amount of empty lines between the comment
|
|
||||||
// and the last decorator.
|
|
||||||
let leading_line =
|
|
||||||
if lines_after_ignoring_trivia(last_decorator.end(), f.context().source()) <= 1
|
|
||||||
{
|
|
||||||
hard_line_break()
|
|
||||||
} else {
|
|
||||||
empty_line()
|
|
||||||
};
|
|
||||||
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
[leading_line, leading_comments(leading_definition_comments)]
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
.fmt(f)?;
|
||||||
|
|
||||||
if item.is_async {
|
if *is_async {
|
||||||
write!(f, [text("async"), space()])?;
|
write!(f, [text("async"), space()])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, [text("def"), space(), item.name.format()])?;
|
write!(f, [text("def"), space(), name.format()])?;
|
||||||
|
|
||||||
if let Some(type_params) = item.type_params.as_ref() {
|
if let Some(type_params) = type_params.as_ref() {
|
||||||
write!(f, [type_params.format()])?;
|
write!(f, [type_params.format()])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let format_inner = format_with(|f: &mut PyFormatter| {
|
let format_inner = format_with(|f: &mut PyFormatter| {
|
||||||
write!(f, [item.parameters.format()])?;
|
write!(f, [parameters.format()])?;
|
||||||
|
|
||||||
if let Some(return_annotation) = item.returns.as_ref() {
|
if let Some(return_annotation) = returns.as_ref() {
|
||||||
write!(f, [space(), text("->"), space()])?;
|
write!(f, [space(), text("->"), space()])?;
|
||||||
|
|
||||||
if return_annotation.is_tuple_expr() {
|
if return_annotation.is_tuple_expr() {
|
||||||
|
@ -110,7 +102,7 @@ impl FormatNodeRule<StmtFunctionDef> for FormatStmtFunctionDef {
|
||||||
[maybe_parenthesize_expression(
|
[maybe_parenthesize_expression(
|
||||||
return_annotation,
|
return_annotation,
|
||||||
item,
|
item,
|
||||||
if empty_parameters(&item.parameters, f.context().source()) {
|
if empty_parameters(parameters, f.context().source()) {
|
||||||
// If the parameters are empty, add parentheses if the return annotation
|
// If the parameters are empty, add parentheses if the return annotation
|
||||||
// breaks at all.
|
// breaks at all.
|
||||||
Parenthesize::IfBreaksOrIfRequired
|
Parenthesize::IfBreaksOrIfRequired
|
||||||
|
@ -142,7 +134,7 @@ impl FormatNodeRule<StmtFunctionDef> for FormatStmtFunctionDef {
|
||||||
[
|
[
|
||||||
text(":"),
|
text(":"),
|
||||||
trailing_comments(trailing_definition_comments),
|
trailing_comments(trailing_definition_comments),
|
||||||
block_indent(&item.body.format().with_options(SuiteKind::Function))
|
block_indent(&body.format().with_options(SuiteKind::Function))
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
use ruff_formatter::{format_args, write};
|
use ruff_formatter::{format_args, write};
|
||||||
use ruff_python_ast::node::AstNode;
|
use ruff_python_ast::node::AstNode;
|
||||||
use ruff_python_ast::StmtGlobal;
|
use ruff_python_ast::StmtGlobal;
|
||||||
|
@ -50,4 +51,12 @@ impl FormatNodeRule<StmtGlobal> for FormatStmtGlobal {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
use crate::{FormatNodeRule, FormattedIterExt, PyFormatter};
|
use crate::prelude::*;
|
||||||
use ruff_formatter::prelude::{format_args, format_with, space, text};
|
use ruff_formatter::{format_args, write};
|
||||||
use ruff_formatter::{write, Buffer, FormatResult};
|
|
||||||
use ruff_python_ast::StmtImport;
|
use ruff_python_ast::StmtImport;
|
||||||
|
|
||||||
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
|
use crate::FormatNodeRule;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatStmtImport;
|
pub struct FormatStmtImport;
|
||||||
|
|
||||||
|
@ -16,4 +18,12 @@ impl FormatNodeRule<StmtImport> for FormatStmtImport {
|
||||||
});
|
});
|
||||||
write!(f, [text("import"), space(), names])
|
write!(f, [text("import"), space(), names])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use ruff_formatter::prelude::{dynamic_text, format_with, space, text};
|
use ruff_formatter::write;
|
||||||
use ruff_formatter::{write, Buffer, Format, FormatResult};
|
|
||||||
use ruff_python_ast::node::AstNode;
|
use ruff_python_ast::node::AstNode;
|
||||||
use ruff_python_ast::{Ranged, StmtImportFrom};
|
use ruff_python_ast::{Ranged, StmtImportFrom};
|
||||||
|
|
||||||
use crate::builders::{parenthesize_if_expands, PyFormatterExtensions, TrailingComma};
|
use crate::builders::{parenthesize_if_expands, PyFormatterExtensions, TrailingComma};
|
||||||
use crate::comments::SourceComment;
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
use crate::expression::parentheses::parenthesized;
|
use crate::expression::parentheses::parenthesized;
|
||||||
use crate::{AsFormat, FormatNodeRule, PyFormatter};
|
use crate::prelude::*;
|
||||||
|
use crate::FormatNodeRule;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatStmtImportFrom;
|
pub struct FormatStmtImportFrom;
|
||||||
|
@ -78,4 +78,12 @@ impl FormatNodeRule<StmtImportFrom> for FormatStmtImportFrom {
|
||||||
// Handled in `fmt_fields`
|
// Handled in `fmt_fields`
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use ruff_python_ast::{Ranged, StmtIpyEscapeCommand};
|
use ruff_python_ast::{Ranged, StmtIpyEscapeCommand};
|
||||||
|
|
||||||
|
@ -8,4 +9,12 @@ impl FormatNodeRule<StmtIpyEscapeCommand> for FormatStmtIpyEscapeCommand {
|
||||||
fn fmt_fields(&self, item: &StmtIpyEscapeCommand, f: &mut PyFormatter) -> FormatResult<()> {
|
fn fmt_fields(&self, item: &StmtIpyEscapeCommand, f: &mut PyFormatter) -> FormatResult<()> {
|
||||||
source_text_slice(item.range(), ContainsNewlines::No).fmt(f)
|
source_text_slice(item.range(), ContainsNewlines::No).fmt(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use ruff_formatter::{format_args, write, Buffer, FormatResult};
|
use ruff_formatter::{format_args, write};
|
||||||
use ruff_python_ast::StmtMatch;
|
use ruff_python_ast::StmtMatch;
|
||||||
|
|
||||||
use crate::comments::{leading_alternate_branch_comments, trailing_comments, SourceComment};
|
use crate::comments::{leading_alternate_branch_comments, trailing_comments, SourceComment};
|
||||||
|
@ -6,7 +6,7 @@ use crate::context::{NodeLevel, WithNodeLevel};
|
||||||
use crate::expression::maybe_parenthesize_expression;
|
use crate::expression::maybe_parenthesize_expression;
|
||||||
use crate::expression::parentheses::Parenthesize;
|
use crate::expression::parentheses::Parenthesize;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::{FormatNodeRule, PyFormatter};
|
use crate::FormatNodeRule;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatStmtMatch;
|
pub struct FormatStmtMatch;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
use ruff_formatter::{format_args, write};
|
use ruff_formatter::{format_args, write};
|
||||||
use ruff_python_ast::node::AstNode;
|
use ruff_python_ast::node::AstNode;
|
||||||
use ruff_python_ast::StmtNonlocal;
|
use ruff_python_ast::StmtNonlocal;
|
||||||
|
@ -50,4 +51,12 @@ impl FormatNodeRule<StmtNonlocal> for FormatStmtNonlocal {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::{FormatNodeRule, PyFormatter};
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
use ruff_formatter::prelude::text;
|
|
||||||
use ruff_formatter::{Format, FormatResult};
|
|
||||||
use ruff_python_ast::StmtPass;
|
use ruff_python_ast::StmtPass;
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
use crate::FormatNodeRule;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatStmtPass;
|
pub struct FormatStmtPass;
|
||||||
|
|
||||||
|
@ -10,4 +11,12 @@ impl FormatNodeRule<StmtPass> for FormatStmtPass {
|
||||||
fn fmt_fields(&self, _item: &StmtPass, f: &mut PyFormatter) -> FormatResult<()> {
|
fn fmt_fields(&self, _item: &StmtPass, f: &mut PyFormatter) -> FormatResult<()> {
|
||||||
text("pass").fmt(f)
|
text("pass").fmt(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use crate::expression::parentheses::Parenthesize;
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
use crate::{FormatNodeRule, PyFormatter};
|
use ruff_formatter::write;
|
||||||
use ruff_formatter::prelude::{space, text};
|
use ruff_python_ast::StmtRaise;
|
||||||
use ruff_formatter::{write, Buffer, Format, FormatResult};
|
|
||||||
|
|
||||||
use crate::expression::maybe_parenthesize_expression;
|
use crate::expression::maybe_parenthesize_expression;
|
||||||
use ruff_python_ast::StmtRaise;
|
use crate::expression::parentheses::Parenthesize;
|
||||||
|
use crate::prelude::*;
|
||||||
|
use crate::FormatNodeRule;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatStmtRaise;
|
pub struct FormatStmtRaise;
|
||||||
|
@ -42,4 +43,12 @@ impl FormatNodeRule<StmtRaise> for FormatStmtRaise {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
use ruff_formatter::write;
|
||||||
|
use ruff_python_ast::StmtReturn;
|
||||||
|
|
||||||
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
use crate::expression::maybe_parenthesize_expression;
|
use crate::expression::maybe_parenthesize_expression;
|
||||||
use crate::expression::parentheses::Parenthesize;
|
use crate::expression::parentheses::Parenthesize;
|
||||||
use crate::{FormatNodeRule, PyFormatter};
|
use crate::prelude::*;
|
||||||
use ruff_formatter::prelude::{space, text};
|
use crate::FormatNodeRule;
|
||||||
use ruff_formatter::{write, Buffer, Format, FormatResult};
|
|
||||||
use ruff_python_ast::StmtReturn;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatStmtReturn;
|
pub struct FormatStmtReturn;
|
||||||
|
@ -24,4 +26,12 @@ impl FormatNodeRule<StmtReturn> for FormatStmtReturn {
|
||||||
text("return").fmt(f)
|
text("return").fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use ruff_formatter::FormatRuleWithOptions;
|
use ruff_formatter::{write, FormatRuleWithOptions};
|
||||||
use ruff_formatter::{write, Buffer, FormatResult};
|
|
||||||
use ruff_python_ast::{ExceptHandler, Ranged, StmtTry, Suite};
|
use ruff_python_ast::{ExceptHandler, Ranged, StmtTry, Suite};
|
||||||
|
|
||||||
use crate::comments;
|
use crate::comments;
|
||||||
use crate::comments::{leading_alternate_branch_comments, trailing_comments, SourceComment};
|
use crate::comments::SourceComment;
|
||||||
|
use crate::comments::{leading_alternate_branch_comments, trailing_comments};
|
||||||
use crate::other::except_handler_except_handler::ExceptHandlerKind;
|
use crate::other::except_handler_except_handler::ExceptHandlerKind;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::statement::{FormatRefWithRule, Stmt};
|
use crate::statement::{FormatRefWithRule, Stmt};
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
use crate::comments::{SourceComment, SuppressionKind};
|
||||||
|
use ruff_formatter::write;
|
||||||
|
use ruff_python_ast::StmtTypeAlias;
|
||||||
|
|
||||||
use crate::expression::maybe_parenthesize_expression;
|
use crate::expression::maybe_parenthesize_expression;
|
||||||
use crate::expression::parentheses::Parenthesize;
|
use crate::expression::parentheses::Parenthesize;
|
||||||
use crate::AsFormat;
|
use crate::prelude::*;
|
||||||
use crate::{FormatNodeRule, PyFormatter};
|
use crate::FormatNodeRule;
|
||||||
use ruff_formatter::prelude::{space, text};
|
|
||||||
use ruff_formatter::{write, Buffer, FormatResult};
|
|
||||||
use ruff_python_ast::StmtTypeAlias;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatStmtTypeAlias;
|
pub struct FormatStmtTypeAlias;
|
||||||
|
@ -34,4 +35,12 @@ impl FormatNodeRule<StmtTypeAlias> for FormatStmtTypeAlias {
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_suppressed(
|
||||||
|
&self,
|
||||||
|
trailing_comments: &[SourceComment],
|
||||||
|
context: &PyFormatContext,
|
||||||
|
) -> bool {
|
||||||
|
SuppressionKind::has_skip_comment(trailing_comments, context.source())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
|
use ruff_formatter::write;
|
||||||
|
use ruff_python_ast::node::AstNode;
|
||||||
|
use ruff_python_ast::{Ranged, Stmt, StmtWhile};
|
||||||
|
|
||||||
use crate::comments::{leading_alternate_branch_comments, trailing_comments, SourceComment};
|
use crate::comments::{leading_alternate_branch_comments, trailing_comments, SourceComment};
|
||||||
use crate::expression::maybe_parenthesize_expression;
|
use crate::expression::maybe_parenthesize_expression;
|
||||||
use crate::expression::parentheses::Parenthesize;
|
use crate::expression::parentheses::Parenthesize;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::FormatNodeRule;
|
use crate::FormatNodeRule;
|
||||||
use ruff_formatter::write;
|
|
||||||
use ruff_python_ast::node::AstNode;
|
|
||||||
use ruff_python_ast::{Ranged, Stmt, StmtWhile};
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatStmtWhile;
|
pub struct FormatStmtWhile;
|
||||||
|
|
|
@ -10,8 +10,9 @@ use crate::context::{NodeLevel, WithNodeLevel};
|
||||||
use crate::expression::expr_constant::ExprConstantLayout;
|
use crate::expression::expr_constant::ExprConstantLayout;
|
||||||
use crate::expression::string::StringLayout;
|
use crate::expression::string::StringLayout;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::statement::stmt_expr::FormatStmtExpr;
|
||||||
use crate::verbatim::{
|
use crate::verbatim::{
|
||||||
write_suppressed_statements_starting_with_leading_comment,
|
suppressed_node, write_suppressed_statements_starting_with_leading_comment,
|
||||||
write_suppressed_statements_starting_with_trailing_comment,
|
write_suppressed_statements_starting_with_trailing_comment,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -399,27 +400,33 @@ impl<'a> DocstringStmt<'a> {
|
||||||
|
|
||||||
impl Format<PyFormatContext<'_>> for DocstringStmt<'_> {
|
impl Format<PyFormatContext<'_>> for DocstringStmt<'_> {
|
||||||
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
|
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
|
||||||
// SAFETY: Safe because `DocStringStmt` guarantees that it only ever wraps a `ExprStmt` containing a `ConstantExpr`.
|
|
||||||
let constant = self
|
|
||||||
.0
|
|
||||||
.as_expr_stmt()
|
|
||||||
.unwrap()
|
|
||||||
.value
|
|
||||||
.as_constant_expr()
|
|
||||||
.unwrap();
|
|
||||||
let comments = f.context().comments().clone();
|
let comments = f.context().comments().clone();
|
||||||
|
let node_comments = comments.leading_dangling_trailing_comments(self.0);
|
||||||
|
|
||||||
// We format the expression, but the statement carries the comments
|
if FormatStmtExpr.is_suppressed(node_comments.trailing, f.context()) {
|
||||||
write!(
|
suppressed_node(self.0).fmt(f)
|
||||||
f,
|
} else {
|
||||||
[
|
// SAFETY: Safe because `DocStringStmt` guarantees that it only ever wraps a `ExprStmt` containing a `ConstantExpr`.
|
||||||
leading_comments(comments.leading_comments(self.0)),
|
let constant = self
|
||||||
constant
|
.0
|
||||||
.format()
|
.as_expr_stmt()
|
||||||
.with_options(ExprConstantLayout::String(StringLayout::DocString)),
|
.unwrap()
|
||||||
trailing_comments(comments.trailing_comments(self.0)),
|
.value
|
||||||
]
|
.as_constant_expr()
|
||||||
)
|
.unwrap();
|
||||||
|
|
||||||
|
// We format the expression, but the statement carries the comments
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
[
|
||||||
|
leading_comments(node_comments.leading),
|
||||||
|
constant
|
||||||
|
.format()
|
||||||
|
.with_options(ExprConstantLayout::String(StringLayout::DocString)),
|
||||||
|
trailing_comments(node_comments.trailing),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -882,3 +882,51 @@ impl Format<PyFormatContext<'_>> for VerbatimText {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Disables formatting for `node` and instead uses the same formatting as the node has in source.
|
||||||
|
///
|
||||||
|
/// The `node` gets indented as any formatted node to avoid syntax errors when the indentation string changes (e.g. from 2 spaces to 4).
|
||||||
|
/// The `node`s leading and trailing comments are formatted as usual, except if they fall into the suppressed node's range.
|
||||||
|
#[cold]
|
||||||
|
pub(crate) fn suppressed_node<'a, N>(node: N) -> FormatSuppressedNode<'a>
|
||||||
|
where
|
||||||
|
N: Into<AnyNodeRef<'a>>,
|
||||||
|
{
|
||||||
|
FormatSuppressedNode { node: node.into() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct FormatSuppressedNode<'a> {
|
||||||
|
node: AnyNodeRef<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Format<PyFormatContext<'_>> for FormatSuppressedNode<'_> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
|
||||||
|
let comments = f.context().comments().clone();
|
||||||
|
let node_comments = comments.leading_dangling_trailing_comments(self.node);
|
||||||
|
|
||||||
|
// Mark all comments as formatted that fall into the node range
|
||||||
|
for comment in node_comments.leading {
|
||||||
|
if comment.start() > self.node.start() {
|
||||||
|
comment.mark_formatted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for comment in node_comments.trailing {
|
||||||
|
if comment.start() < self.node.end() {
|
||||||
|
comment.mark_formatted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
comments.mark_verbatim_node_comments_formatted(self.node);
|
||||||
|
|
||||||
|
// Write the outer comments and format the node as verbatim
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
[
|
||||||
|
leading_comments(node_comments.leading),
|
||||||
|
verbatim_text(self.node, ContainsNewlines::Detect),
|
||||||
|
trailing_comments(node_comments.trailing)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -238,7 +238,7 @@ d={'a':1,
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
|
|
||||||
@@ -178,7 +180,7 @@
|
@@ -178,14 +180,18 @@
|
||||||
$
|
$
|
||||||
""",
|
""",
|
||||||
# fmt: off
|
# fmt: off
|
||||||
|
@ -247,6 +247,18 @@ d={'a':1,
|
||||||
# fmt: on
|
# fmt: on
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def single_literal_yapf_disable():
|
||||||
|
"""Black does not support this."""
|
||||||
|
- BAZ = {(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)} # yapf: disable
|
||||||
|
+ BAZ = {
|
||||||
|
+ (1, 2, 3, 4),
|
||||||
|
+ (5, 6, 7, 8),
|
||||||
|
+ (9, 10, 11, 12)
|
||||||
|
+ } # yapf: disable
|
||||||
|
|
||||||
|
|
||||||
|
cfg.rule(
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ruff Output
|
## Ruff Output
|
||||||
|
@ -441,7 +453,11 @@ def long_lines():
|
||||||
|
|
||||||
def single_literal_yapf_disable():
|
def single_literal_yapf_disable():
|
||||||
"""Black does not support this."""
|
"""Black does not support this."""
|
||||||
BAZ = {(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)} # yapf: disable
|
BAZ = {
|
||||||
|
(1, 2, 3, 4),
|
||||||
|
(5, 6, 7, 8),
|
||||||
|
(9, 10, 11, 12)
|
||||||
|
} # yapf: disable
|
||||||
|
|
||||||
|
|
||||||
cfg.rule(
|
cfg.rule(
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
---
|
|
||||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip.py
|
|
||||||
---
|
|
||||||
## Input
|
|
||||||
|
|
||||||
```py
|
|
||||||
a, b = 1, 2
|
|
||||||
c = 6 # fmt: skip
|
|
||||||
d = 5
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Differences
|
|
||||||
|
|
||||||
```diff
|
|
||||||
--- Black
|
|
||||||
+++ Ruff
|
|
||||||
@@ -1,3 +1,3 @@
|
|
||||||
a, b = 1, 2
|
|
||||||
-c = 6 # fmt: skip
|
|
||||||
+c = 6 # fmt: skip
|
|
||||||
d = 5
|
|
||||||
```
|
|
||||||
|
|
||||||
## Ruff Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
a, b = 1, 2
|
|
||||||
c = 6 # fmt: skip
|
|
||||||
d = 5
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
a, b = 1, 2
|
|
||||||
c = 6 # fmt: skip
|
|
||||||
d = 5
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
---
|
|
||||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip2.py
|
|
||||||
---
|
|
||||||
## Input
|
|
||||||
|
|
||||||
```py
|
|
||||||
l1 = ["This list should be broken up", "into multiple lines", "because it is way too long"]
|
|
||||||
l2 = ["But this list shouldn't", "even though it also has", "way too many characters in it"] # fmt: skip
|
|
||||||
l3 = ["I have", "trailing comma", "so I should be braked",]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Differences
|
|
||||||
|
|
||||||
```diff
|
|
||||||
--- Black
|
|
||||||
+++ Ruff
|
|
||||||
@@ -3,7 +3,11 @@
|
|
||||||
"into multiple lines",
|
|
||||||
"because it is way too long",
|
|
||||||
]
|
|
||||||
-l2 = ["But this list shouldn't", "even though it also has", "way too many characters in it"] # fmt: skip
|
|
||||||
+l2 = [
|
|
||||||
+ "But this list shouldn't",
|
|
||||||
+ "even though it also has",
|
|
||||||
+ "way too many characters in it",
|
|
||||||
+] # fmt: skip
|
|
||||||
l3 = [
|
|
||||||
"I have",
|
|
||||||
"trailing comma",
|
|
||||||
```
|
|
||||||
|
|
||||||
## Ruff Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
l1 = [
|
|
||||||
"This list should be broken up",
|
|
||||||
"into multiple lines",
|
|
||||||
"because it is way too long",
|
|
||||||
]
|
|
||||||
l2 = [
|
|
||||||
"But this list shouldn't",
|
|
||||||
"even though it also has",
|
|
||||||
"way too many characters in it",
|
|
||||||
] # fmt: skip
|
|
||||||
l3 = [
|
|
||||||
"I have",
|
|
||||||
"trailing comma",
|
|
||||||
"so I should be braked",
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
l1 = [
|
|
||||||
"This list should be broken up",
|
|
||||||
"into multiple lines",
|
|
||||||
"because it is way too long",
|
|
||||||
]
|
|
||||||
l2 = ["But this list shouldn't", "even though it also has", "way too many characters in it"] # fmt: skip
|
|
||||||
l3 = [
|
|
||||||
"I have",
|
|
||||||
"trailing comma",
|
|
||||||
"so I should be braked",
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
---
|
|
||||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip7.py
|
|
||||||
---
|
|
||||||
## Input
|
|
||||||
|
|
||||||
```py
|
|
||||||
a = "this is some code"
|
|
||||||
b = 5 #fmt:skip
|
|
||||||
c = 9 #fmt: skip
|
|
||||||
d = "thisisasuperlongstringthisisasuperlongstringthisisasuperlongstringthisisasuperlongstring" #fmt:skip
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Differences
|
|
||||||
|
|
||||||
```diff
|
|
||||||
--- Black
|
|
||||||
+++ Ruff
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
a = "this is some code"
|
|
||||||
-b = 5 # fmt:skip
|
|
||||||
+b = 5 # fmt:skip
|
|
||||||
c = 9 # fmt: skip
|
|
||||||
d = "thisisasuperlongstringthisisasuperlongstringthisisasuperlongstringthisisasuperlongstring" # fmt:skip
|
|
||||||
```
|
|
||||||
|
|
||||||
## Ruff Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
a = "this is some code"
|
|
||||||
b = 5 # fmt:skip
|
|
||||||
c = 9 # fmt: skip
|
|
||||||
d = "thisisasuperlongstringthisisasuperlongstringthisisasuperlongstringthisisasuperlongstring" # fmt:skip
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
a = "this is some code"
|
|
||||||
b = 5 # fmt:skip
|
|
||||||
c = 9 # fmt: skip
|
|
||||||
d = "thisisasuperlongstringthisisasuperlongstringthisisasuperlongstringthisisasuperlongstring" # fmt:skip
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||||
|
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/decorators.py
|
||||||
|
---
|
||||||
|
## Input
|
||||||
|
```py
|
||||||
|
|
||||||
|
@FormattedDecorator(a =b)
|
||||||
|
# leading comment
|
||||||
|
@MyDecorator( # dangling comment
|
||||||
|
list = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12], x = some_other_function_call({ "test": "value", "more": "other"})) # fmt: skip
|
||||||
|
# leading class comment
|
||||||
|
class Test:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@FormattedDecorator(a =b)
|
||||||
|
# leading comment
|
||||||
|
@MyDecorator( # dangling comment
|
||||||
|
list = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12], x = some_other_function_call({ "test": "value", "more": "other"})) # fmt: skip
|
||||||
|
# leading class comment
|
||||||
|
def test():
|
||||||
|
pass
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output
|
||||||
|
```py
|
||||||
|
@FormattedDecorator(a=b)
|
||||||
|
# leading comment
|
||||||
|
@MyDecorator( # dangling comment
|
||||||
|
list = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12], x = some_other_function_call({ "test": "value", "more": "other"})) # fmt: skip
|
||||||
|
# leading class comment
|
||||||
|
class Test:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@FormattedDecorator(a=b)
|
||||||
|
# leading comment
|
||||||
|
@MyDecorator( # dangling comment
|
||||||
|
list = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12], x = some_other_function_call({ "test": "value", "more": "other"})) # fmt: skip
|
||||||
|
# leading class comment
|
||||||
|
def test():
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||||
|
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/docstrings.py
|
||||||
|
---
|
||||||
|
## Input
|
||||||
|
```py
|
||||||
|
def test():
|
||||||
|
# leading comment
|
||||||
|
""" This docstring does not
|
||||||
|
get formatted
|
||||||
|
""" # fmt: skip
|
||||||
|
# trailing comment
|
||||||
|
|
||||||
|
def test():
|
||||||
|
# leading comment
|
||||||
|
""" This docstring gets formatted
|
||||||
|
""" # trailing comment
|
||||||
|
|
||||||
|
and_this + gets + formatted + too
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output
|
||||||
|
```py
|
||||||
|
def test():
|
||||||
|
# leading comment
|
||||||
|
""" This docstring does not
|
||||||
|
get formatted
|
||||||
|
""" # fmt: skip
|
||||||
|
# trailing comment
|
||||||
|
|
||||||
|
|
||||||
|
def test():
|
||||||
|
# leading comment
|
||||||
|
"""This docstring gets formatted""" # trailing comment
|
||||||
|
|
||||||
|
and_this + gets + formatted + too
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue