Fix dangling module comments (#7456)

This commit is contained in:
Micha Reiser
2023-09-17 16:56:41 +02:00
committed by GitHub
parent 959338d39d
commit 26ae0a6e8d
8 changed files with 58 additions and 32 deletions

View File

@@ -0,0 +1,4 @@
# hehehe >:)a

View File

@@ -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,
@@ -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) => {
@@ -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

View File

@@ -8,8 +8,7 @@ expression: comments.debug(test_case.source_code)
range: 0..0,
source: ``,
}: {
"leading": [],
"dangling": [
"leading": [
SourceComment {
text: "# Some comment",
position: OwnLine,
@@ -21,6 +20,7 @@ expression: comments.debug(test_case.source_code)
formatted: false,
},
],
"dangling": [],
"trailing": [],
},
}

View File

@@ -1,10 +1,10 @@
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;
@@ -12,13 +12,11 @@ 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()
]

View File

@@ -17,6 +17,7 @@ magic-trailing-comma = Respect
```
```py
```
@@ -30,6 +31,7 @@ magic-trailing-comma = Respect
```
```py
```
@@ -43,6 +45,7 @@ magic-trailing-comma = Respect
```
```py
```

View File

@@ -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
# hehehe >:)a
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1 +0,0 @@
-
```
## Ruff Output
## Output
```py
```
## Black Output
```py
# hehehe >:)a
```