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
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 58 additions and 32 deletions

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": [],
},
}