Skip to content

Commit

Permalink
Fix dangling module comments (#7456)
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaReiser authored Sep 17, 2023
1 parent 959338d commit 26ae0a6
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 29 deletions.
2 changes: 1 addition & 1 deletion crates/ruff_formatter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ pub type FormatResult<F> = Result<F, FormatError>;
/// let paragraph = Paragraph(String::from("test"));
/// let formatted = format!(SimpleFormatContext::default(), [paragraph])?;
///
/// assert_eq!("test\n", formatted.print()?.as_code());
/// assert_eq!("\ntest\n", formatted.print()?.as_code());
/// # Ok(())
/// # }
/// ```
Expand Down
2 changes: 1 addition & 1 deletion crates/ruff_formatter/src/printer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ impl<'a> Printer<'a> {
self.flush_line_suffixes(queue, stack, Some(element));
} else {
// Only print a newline if the current line isn't already empty
if self.state.line_width > 0 {
if self.state.line_width > 0 || self.state.buffer.is_empty() {
self.print_char('\n');
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@



# hehehe >:)a
39 changes: 36 additions & 3 deletions crates/ruff_python_formatter/src/comments/placement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::cmp::Ordering;

use ruff_python_ast::node::AnyNodeRef;
use ruff_python_ast::whitespace::indentation;
use ruff_python_ast::{self as ast, Comprehension, Expr, MatchCase, Parameters};
use ruff_python_ast::{self as ast, Comprehension, Expr, MatchCase, ModModule, Parameters};
use ruff_python_trivia::{
find_only_token_in_range, indentation_at_offset, BackwardsTokenizer, CommentRanges,
SimpleToken, SimpleTokenKind, SimpleTokenizer,
Expand Down Expand Up @@ -229,8 +229,12 @@ fn handle_enclosed_comment<'a>(
CommentPlacement::Default(comment)
}
}
AnyNodeRef::ModModule(_) => {
handle_module_level_own_line_comment_before_class_or_function_comment(comment, locator)
AnyNodeRef::ModModule(module) => {
handle_trailing_module_comment(module, comment).or_else(|comment| {
handle_module_level_own_line_comment_before_class_or_function_comment(
comment, locator,
)
})
}
AnyNodeRef::WithItem(_) => handle_with_item_comment(comment, locator),
AnyNodeRef::PatternMatchSequence(pattern_match_sequence) => {
Expand Down Expand Up @@ -882,6 +886,35 @@ fn handle_trailing_binary_like_comment<'a>(
}
}

/// Handles trailing comments after the last statement in a module.
/// Ruff's parser sets the module range to exclude trailing comments and the result is that
/// [`CommentPlacement::Default`] makes these comments dangling comments.
///
/// This method overrides the handling to make these comments trailing comments of the last
/// statement instead.
///
/// ```python
/// a
///
/// # trailing comment
/// ```
///
/// Comments of an all empty module are leading module comments
fn handle_trailing_module_comment<'a>(
module: &'a ModModule,
comment: DecoratedComment<'a>,
) -> CommentPlacement<'a> {
if comment.preceding_node().is_none() && comment.following_node().is_none() {
if let Some(last_statement) = module.body.last() {
CommentPlacement::trailing(last_statement, comment)
} else {
CommentPlacement::leading(comment.enclosing_node(), comment)
}
} else {
CommentPlacement::Default(comment)
}
}

/// Handles own line comments on the module level before a class or function statement.
/// A comment only becomes the leading comment of a class or function if it isn't separated by an empty
/// line from the class. Comments that are separated by at least one empty line from the header of the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ expression: comments.debug(test_case.source_code)
range: 0..0,
source: ``,
}: {
"leading": [],
"dangling": [
"leading": [
SourceComment {
text: "# Some comment",
position: OwnLine,
Expand All @@ -21,6 +20,7 @@ expression: comments.debug(test_case.source_code)
formatted: false,
},
],
"dangling": [],
"trailing": [],
},
}
10 changes: 4 additions & 6 deletions crates/ruff_python_formatter/src/module/mod_module.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
use ruff_formatter::prelude::hard_line_break;
use ruff_formatter::{Buffer, FormatResult};
use ruff_formatter::write;
use ruff_python_ast::ModModule;

use crate::comments::{trailing_comments, SourceComment};
use crate::comments::SourceComment;
use crate::prelude::*;
use crate::statement::suite::SuiteKind;
use crate::{write, AsFormat, FormatNodeRule, PyFormatter};
use crate::FormatNodeRule;

#[derive(Default)]
pub struct FormatModModule;

impl FormatNodeRule<ModModule> for FormatModModule {
fn fmt_fields(&self, item: &ModModule, f: &mut PyFormatter) -> FormatResult<()> {
let ModModule { range: _, body } = item;
let comments = f.context().comments().clone();

write!(
f,
[
body.format().with_options(SuiteKind::TopLevel),
trailing_comments(comments.dangling(item)),
// Trailing newline at the end of the file
hard_line_break()
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ magic-trailing-comma = Respect
```

```py
```


Expand All @@ -30,6 +31,7 @@ magic-trailing-comma = Respect
```

```py
```


Expand All @@ -43,6 +45,7 @@ magic-trailing-comma = Respect
```

```py
```


Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/whitespace.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/module_comment.py
---
## Input

```py
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1 +0,0 @@
-
# hehehe >:)a
```

## Ruff Output

## Output
```py
# hehehe >:)a
```

## Black Output

```py
```


0 comments on commit 26ae0a6

Please sign in to comment.