Skip to content

Commit

Permalink
Support fmt: skip on statement and decorator level
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaReiser committed Aug 15, 2023
1 parent be450a6 commit ef86a00
Show file tree
Hide file tree
Showing 40 changed files with 540 additions and 304 deletions.
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
@@ -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
12 changes: 12 additions & 0 deletions crates/ruff_python_formatter/src/comments/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,18 @@ pub(crate) enum SuppressionKind {
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 {
#[inline]
fn range(&self) -> TextRange {
Expand Down
2 changes: 1 addition & 1 deletion crates/ruff_python_formatter/src/comments/placement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ fn handle_leading_class_with_decorators_comment<'a>(
comment: DecoratedComment<'a>,
class_def: &'a ast::StmtClassDef,
) -> 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 decorator.end() < comment.start() {
return CommentPlacement::dangling(class_def, comment);
Expand Down
2 changes: 1 addition & 1 deletion crates/ruff_python_formatter/src/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl FormatRule<Expr, PyFormatContext<'_>> for FormatExpr {
Expr::List(expr) => expr.format().fmt(f),
Expr::Tuple(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 {
Expand Down
35 changes: 22 additions & 13 deletions crates/ruff_python_formatter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::comments::{
};
use crate::context::PyFormatContext;
pub use crate::options::{MagicTrailingComma, PyFormatOptions, QuoteStyle};
use crate::verbatim::suppressed_node;

pub(crate) mod builders;
pub mod cli;
Expand Down Expand Up @@ -50,10 +51,14 @@ where

let node_comments = comments.leading_dangling_trailing_comments(node.as_any_node_ref());

leading_comments(node_comments.leading).fmt(f)?;
self.fmt_node(node, f)?;
self.fmt_dangling_comments(node_comments.dangling, f)?;
trailing_comments(node_comments.trailing).fmt(f)
if self.is_suppressed(node_comments.trailing, f.context()) {
suppressed_node(node.as_any_node_ref()).fmt(f)
} else {
leading_comments(node_comments.leading).fmt(f)?;
self.fmt_node(node, f)?;
self.fmt_dangling_comments(node_comments.dangling, f)?;
trailing_comments(node_comments.trailing).fmt(f)
}
}

/// Formats the node without comments. Ignores any suppression comments.
Expand All @@ -80,6 +85,14 @@ where
) -> FormatResult<()> {
dangling_comments(dangling_node_comments).fmt(f)
}

fn is_suppressed(
&self,
_trailing_comments: &[SourceComment],
_context: &PyFormatContext,
) -> bool {
false
}
}

#[derive(Error, Debug)]
Expand Down Expand Up @@ -263,16 +276,12 @@ if True:
#[ignore]
#[test]
fn quick_test() {
let src = r#"def test():
# fmt: off
a + b
# suppressed comments
let src = r#"
@MyDecorator(list = a) # fmt: skip
# trailing comment
class Test:
pass
a + b # formatted
"#;
// Tokenize once
Expand Down
9 changes: 9 additions & 0 deletions crates/ruff_python_formatter/src/other/decorator.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::comments::{SourceComment, SuppressionKind};
use crate::expression::maybe_parenthesize_expression;
use crate::expression::parentheses::Parenthesize;
use crate::prelude::*;
Expand All @@ -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())
}
}
5 changes: 3 additions & 2 deletions crates/ruff_python_formatter/src/statement/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::prelude::*;
use ruff_formatter::{FormatOwnedWithRule, FormatRefWithRule};
use ruff_python_ast::Stmt;

use crate::prelude::*;

pub(crate) mod stmt_ann_assign;
pub(crate) mod stmt_assert;
pub(crate) mod stmt_assign;
Expand Down Expand Up @@ -59,7 +60,7 @@ impl FormatRule<Stmt, PyFormatContext<'_>> for FormatStmt {
Stmt::Break(x) => x.format().fmt(f),
Stmt::Continue(x) => x.format().fmt(f),
Stmt::TypeAlias(x) => x.format().fmt(f),
Stmt::IpyEscapeCommand(_) => todo!(),
Stmt::IpyEscapeCommand(x) => x.format().fmt(f),
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions crates/ruff_python_formatter/src/statement/stmt_ann_assign.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::comments::{SourceComment, SuppressionKind};
use crate::expression::maybe_parenthesize_expression;
use crate::expression::parentheses::Parenthesize;
use crate::prelude::*;
Expand Down Expand Up @@ -42,4 +43,12 @@ impl FormatNodeRule<StmtAnnAssign> for FormatStmtAnnAssign {

Ok(())
}

fn is_suppressed(
&self,
trailing_comments: &[SourceComment],
context: &PyFormatContext,
) -> bool {
SuppressionKind::has_skip_comment(trailing_comments, context.source())
}
}
10 changes: 10 additions & 0 deletions crates/ruff_python_formatter/src/statement/stmt_assert.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::comments::{SourceComment, SuppressionKind};
use crate::context::PyFormatContext;
use crate::expression::maybe_parenthesize_expression;
use crate::expression::parentheses::Parenthesize;
use crate::{FormatNodeRule, PyFormatter};
Expand Down Expand Up @@ -38,4 +40,12 @@ impl FormatNodeRule<StmtAssert> for FormatStmtAssert {

Ok(())
}

fn is_suppressed(
&self,
trailing_comments: &[SourceComment],
context: &PyFormatContext,
) -> bool {
SuppressionKind::has_skip_comment(trailing_comments, context.source())
}
}
9 changes: 9 additions & 0 deletions crates/ruff_python_formatter/src/statement/stmt_assign.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::comments::{SourceComment, SuppressionKind};
use ruff_formatter::{format_args, write, FormatError};
use ruff_python_ast::{Expr, StmtAssign};

Expand Down Expand Up @@ -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())
}
}

struct FormatTargets<'a> {
Expand Down
18 changes: 14 additions & 4 deletions crates/ruff_python_formatter/src/statement/stmt_aug_assign.rs
Original file line number Diff line number Diff line change
@@ -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::parentheses::Parenthesize;
use crate::{AsFormat, FormatNodeRule, PyFormatter};
use ruff_formatter::prelude::{space, text};
use ruff_formatter::{write, Buffer, FormatResult};
use ruff_python_ast::StmtAugAssign;
use crate::prelude::*;
use crate::{AsFormat, FormatNodeRule};

#[derive(Default)]
pub struct FormatStmtAugAssign;
Expand All @@ -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())
}
}
15 changes: 12 additions & 3 deletions crates/ruff_python_formatter/src/statement/stmt_break.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
use crate::{FormatNodeRule, PyFormatter};
use ruff_formatter::prelude::text;
use ruff_formatter::{Format, FormatResult};
use ruff_python_ast::StmtBreak;

use crate::comments::{SourceComment, SuppressionKind};
use crate::prelude::*;
use crate::FormatNodeRule;

#[derive(Default)]
pub struct FormatStmtBreak;

impl FormatNodeRule<StmtBreak> for FormatStmtBreak {
fn fmt_fields(&self, _item: &StmtBreak, f: &mut PyFormatter) -> FormatResult<()> {
text("break").fmt(f)
}

fn is_suppressed(
&self,
trailing_comments: &[SourceComment],
context: &PyFormatContext,
) -> bool {
SuppressionKind::has_skip_comment(trailing_comments, context.source())
}
}
72 changes: 46 additions & 26 deletions crates/ruff_python_formatter/src/statement/stmt_class_def.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ruff_formatter::{write, Buffer};
use ruff_python_ast::{Ranged, StmtClassDef};
use ruff_formatter::write;
use ruff_python_ast::{Decorator, Ranged, StmtClassDef};
use ruff_python_trivia::lines_after_ignoring_trivia;

use crate::comments::{leading_comments, trailing_comments, SourceComment};
Expand Down Expand Up @@ -30,31 +30,11 @@ impl FormatNodeRule<StmtClassDef> for FormatStmtClassDef {
let (leading_definition_comments, trailing_definition_comments) =
dangling_comments.split_at(trailing_definition_comments_start);

if let Some(last_decorator) = decorator_list.last() {
f.join_with(hard_line_break())
.entries(decorator_list.iter().formatted())
.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)]
)?;
}
FormatDecorators {
decorators: decorator_list,
leading_definition_comments,
}
.fmt(f)?;

write!(f, [text("class"), space(), name.format()])?;

Expand Down Expand Up @@ -136,3 +116,43 @@ impl FormatNodeRule<StmtClassDef> for FormatStmtClassDef {
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(())
}
}
15 changes: 12 additions & 3 deletions crates/ruff_python_formatter/src/statement/stmt_continue.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
use crate::{FormatNodeRule, PyFormatter};
use ruff_formatter::prelude::text;
use ruff_formatter::{Format, FormatResult};
use crate::comments::{SourceComment, SuppressionKind};
use ruff_python_ast::StmtContinue;

use crate::prelude::*;
use crate::FormatNodeRule;

#[derive(Default)]
pub struct FormatStmtContinue;

impl FormatNodeRule<StmtContinue> for FormatStmtContinue {
fn fmt_fields(&self, _item: &StmtContinue, f: &mut PyFormatter) -> FormatResult<()> {
text("continue").fmt(f)
}

fn is_suppressed(
&self,
trailing_comments: &[SourceComment],
context: &PyFormatContext,
) -> bool {
SuppressionKind::has_skip_comment(trailing_comments, context.source())
}
}
Loading

0 comments on commit ef86a00

Please sign in to comment.