mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 20:09:22 +00:00
Improve comment handling around PatternMatchAs
(#6797)
## Summary Follows up on https://github.com/astral-sh/ruff/pull/6652#discussion_r1300871033 with some modifications to the `PatternMatchAs` comment handling. Specifically, any comments between the `as` and the end are now formatted as dangling, and we now insert some newlines in the appropriate places. ## Test Plan `cargo test`
This commit is contained in:
parent
d08f697a04
commit
1e6d1182bf
4 changed files with 142 additions and 7 deletions
|
@ -168,6 +168,27 @@ match pattern_comments:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
match pattern_comments:
|
||||||
|
case (
|
||||||
|
pattern
|
||||||
|
# 1
|
||||||
|
as
|
||||||
|
# 2
|
||||||
|
name
|
||||||
|
# 3
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
match subject:
|
||||||
|
case (
|
||||||
|
pattern # 1
|
||||||
|
as # 2
|
||||||
|
name # 3
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case (a as b) as c:
|
case (a as b) as c:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -205,6 +205,7 @@ fn handle_enclosed_comment<'a>(
|
||||||
handle_module_level_own_line_comment_before_class_or_function_comment(comment, locator)
|
handle_module_level_own_line_comment_before_class_or_function_comment(comment, locator)
|
||||||
}
|
}
|
||||||
AnyNodeRef::WithItem(_) => handle_with_item_comment(comment, locator),
|
AnyNodeRef::WithItem(_) => handle_with_item_comment(comment, locator),
|
||||||
|
AnyNodeRef::PatternMatchAs(_) => handle_pattern_match_as_comment(comment, locator),
|
||||||
AnyNodeRef::StmtFunctionDef(_) => handle_leading_function_with_decorators_comment(comment),
|
AnyNodeRef::StmtFunctionDef(_) => handle_leading_function_with_decorators_comment(comment),
|
||||||
AnyNodeRef::StmtClassDef(class_def) => {
|
AnyNodeRef::StmtClassDef(class_def) => {
|
||||||
handle_leading_class_with_decorators_comment(comment, class_def)
|
handle_leading_class_with_decorators_comment(comment, class_def)
|
||||||
|
@ -1145,6 +1146,47 @@ fn handle_with_item_comment<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handles trailing comments after the `as` keyword of a pattern match item:
|
||||||
|
///
|
||||||
|
/// ```python
|
||||||
|
/// case (
|
||||||
|
/// pattern
|
||||||
|
/// as # dangling end of line comment
|
||||||
|
/// # dangling own line comment
|
||||||
|
/// name
|
||||||
|
/// ): ...
|
||||||
|
/// ```
|
||||||
|
fn handle_pattern_match_as_comment<'a>(
|
||||||
|
comment: DecoratedComment<'a>,
|
||||||
|
locator: &Locator,
|
||||||
|
) -> CommentPlacement<'a> {
|
||||||
|
debug_assert!(comment.enclosing_node().is_pattern_match_as());
|
||||||
|
|
||||||
|
let Some(pattern) = comment.preceding_node() else {
|
||||||
|
return CommentPlacement::Default(comment);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut tokens = SimpleTokenizer::starts_at(pattern.end(), locator.contents())
|
||||||
|
.skip_trivia()
|
||||||
|
.skip_while(|token| token.kind == SimpleTokenKind::RParen);
|
||||||
|
|
||||||
|
let Some(as_token) = tokens
|
||||||
|
.next()
|
||||||
|
.filter(|token| token.kind == SimpleTokenKind::As)
|
||||||
|
else {
|
||||||
|
return CommentPlacement::Default(comment);
|
||||||
|
};
|
||||||
|
|
||||||
|
if comment.end() < as_token.start() {
|
||||||
|
// If before the `as` keyword, then it must be a trailing comment of the pattern.
|
||||||
|
CommentPlacement::trailing(pattern, comment)
|
||||||
|
} else {
|
||||||
|
// Otherwise, must be a dangling comment. (Any comments that follow the name will be
|
||||||
|
// trailing comments on the pattern match item, rather than enclosed by it.)
|
||||||
|
CommentPlacement::dangling(comment.enclosing_node(), comment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Handles comments around the `:=` token in a named expression (walrus operator).
|
/// Handles comments around the `:=` token in a named expression (walrus operator).
|
||||||
///
|
///
|
||||||
/// For example, here, `# 1` and `# 2` will be marked as dangling comments on the named expression,
|
/// For example, here, `# 1` and `# 2` will be marked as dangling comments on the named expression,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use ruff_formatter::{write, Buffer, FormatResult};
|
use ruff_formatter::{write, Buffer, FormatResult};
|
||||||
use ruff_python_ast::{Pattern, PatternMatchAs};
|
use ruff_python_ast::{Pattern, PatternMatchAs};
|
||||||
|
|
||||||
|
use crate::comments::{dangling_comments, SourceComment};
|
||||||
use crate::expression::parentheses::parenthesized;
|
use crate::expression::parentheses::parenthesized;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::{FormatNodeRule, PyFormatter};
|
use crate::{FormatNodeRule, PyFormatter};
|
||||||
|
@ -16,6 +17,8 @@ impl FormatNodeRule<PatternMatchAs> for FormatPatternMatchAs {
|
||||||
name,
|
name,
|
||||||
} = item;
|
} = item;
|
||||||
|
|
||||||
|
let comments = f.context().comments().clone();
|
||||||
|
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
if let Some(pattern) = pattern {
|
if let Some(pattern) = pattern {
|
||||||
// Parenthesize nested `PatternMatchAs` like `(a as b) as c`.
|
// Parenthesize nested `PatternMatchAs` like `(a as b) as c`.
|
||||||
|
@ -31,7 +34,24 @@ impl FormatNodeRule<PatternMatchAs> for FormatPatternMatchAs {
|
||||||
pattern.format().fmt(f)?;
|
pattern.format().fmt(f)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, [space(), text("as"), space()])?;
|
if comments.has_trailing(pattern.as_ref()) {
|
||||||
|
write!(f, [hard_line_break()])?;
|
||||||
|
} else {
|
||||||
|
write!(f, [space()])?;
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, [text("as")])?;
|
||||||
|
|
||||||
|
let trailing_as_comments = comments.dangling(item);
|
||||||
|
if trailing_as_comments.is_empty() {
|
||||||
|
write!(f, [space()])?;
|
||||||
|
} else if trailing_as_comments
|
||||||
|
.iter()
|
||||||
|
.all(|comment| comment.line_position().is_own_line())
|
||||||
|
{
|
||||||
|
write!(f, [hard_line_break()])?;
|
||||||
|
}
|
||||||
|
write!(f, [dangling_comments(trailing_as_comments)])?;
|
||||||
}
|
}
|
||||||
name.format().fmt(f)
|
name.format().fmt(f)
|
||||||
} else {
|
} else {
|
||||||
|
@ -39,4 +59,12 @@ impl FormatNodeRule<PatternMatchAs> for FormatPatternMatchAs {
|
||||||
text("_").fmt(f)
|
text("_").fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fmt_dangling_comments(
|
||||||
|
&self,
|
||||||
|
_dangling_comments: &[SourceComment],
|
||||||
|
_f: &mut PyFormatter,
|
||||||
|
) -> FormatResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,6 +174,27 @@ match pattern_comments:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
match pattern_comments:
|
||||||
|
case (
|
||||||
|
pattern
|
||||||
|
# 1
|
||||||
|
as
|
||||||
|
# 2
|
||||||
|
name
|
||||||
|
# 3
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
match subject:
|
||||||
|
case (
|
||||||
|
pattern # 1
|
||||||
|
as # 2
|
||||||
|
name # 3
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case (a as b) as c:
|
case (a as b) as c:
|
||||||
pass
|
pass
|
||||||
|
@ -378,10 +399,11 @@ match pattern_comments:
|
||||||
match pattern_comments:
|
match pattern_comments:
|
||||||
case (
|
case (
|
||||||
# 1
|
# 1
|
||||||
pattern as name # 2
|
pattern # 2
|
||||||
# 3
|
# 3
|
||||||
# 4
|
as # 4
|
||||||
# 5 # 6
|
# 5
|
||||||
|
name # 6
|
||||||
# 7
|
# 7
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
@ -389,15 +411,37 @@ match pattern_comments:
|
||||||
|
|
||||||
match pattern_comments:
|
match pattern_comments:
|
||||||
case (
|
case (
|
||||||
pattern as name
|
pattern
|
||||||
# 1
|
# 1
|
||||||
# 2
|
as # 2
|
||||||
# 3 # 4
|
# 3
|
||||||
|
name # 4
|
||||||
# 5
|
# 5
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
match pattern_comments:
|
||||||
|
case (
|
||||||
|
pattern
|
||||||
|
# 1
|
||||||
|
as
|
||||||
|
# 2
|
||||||
|
name
|
||||||
|
# 3
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
match subject:
|
||||||
|
case (
|
||||||
|
pattern # 1
|
||||||
|
as # 2
|
||||||
|
name # 3
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case (a as b) as c:
|
case (a as b) as c:
|
||||||
pass
|
pass
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue