mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-20 02:20:42 +00:00
Introduce AST nodes for PatternMatchClass
arguments (#6881)
## Summary This PR introduces two new AST nodes to improve the representation of `PatternMatchClass`. As a reminder, `PatternMatchClass` looks like this: ```python case Point2D(0, 0, x=1, y=2): ... ``` Historically, this was represented as a vector of patterns (for the `0, 0` portion) and parallel vectors of keyword names (for `x` and `y`) and values (for `1` and `2`). This introduces a bunch of challenges for the formatter, but importantly, it's also really different from how we represent similar nodes, like arguments (`func(0, 0, x=1, y=2)`) or parameters (`def func(x, y)`). So, firstly, we now use a single node (`PatternArguments`) for the entire parenthesized region, making it much more consistent with our other nodes. So, above, `PatternArguments` would be `(0, 0, x=1, y=2)`. Secondly, we now have a `PatternKeyword` node for `x=1` and `y=2`. This is much more similar to the how `Keyword` is represented within `Arguments` for call expressions. Closes https://github.com/astral-sh/ruff/issues/6866. Closes https://github.com/astral-sh/ruff/issues/6880.
This commit is contained in:
parent
ed1b4122d0
commit
15b73bdb8a
19 changed files with 25299 additions and 25824 deletions
|
@ -174,7 +174,7 @@ fn handle_enclosed_comment<'a>(
|
|||
}
|
||||
})
|
||||
}
|
||||
AnyNodeRef::Arguments(_) | AnyNodeRef::TypeParams(_) => {
|
||||
AnyNodeRef::Arguments(_) | AnyNodeRef::TypeParams(_) | AnyNodeRef::PatternArguments(_) => {
|
||||
handle_bracketed_end_of_line_comment(comment, locator)
|
||||
}
|
||||
AnyNodeRef::Comprehension(comprehension) => {
|
||||
|
@ -220,9 +220,7 @@ fn handle_enclosed_comment<'a>(
|
|||
CommentPlacement::Default(comment)
|
||||
}
|
||||
}
|
||||
AnyNodeRef::PatternMatchClass(class) => {
|
||||
handle_pattern_match_class_comment(comment, class, locator)
|
||||
}
|
||||
AnyNodeRef::PatternMatchClass(class) => handle_pattern_match_class_comment(comment, class),
|
||||
AnyNodeRef::PatternMatchAs(_) => handle_pattern_match_as_comment(comment, locator),
|
||||
AnyNodeRef::PatternMatchStar(_) => handle_pattern_match_star_comment(comment),
|
||||
AnyNodeRef::PatternMatchMapping(pattern) => {
|
||||
|
@ -1233,75 +1231,23 @@ fn handle_with_item_comment<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Handles trailing comments after the `as` keyword of a pattern match item:
|
||||
///
|
||||
/// Handles trailing comments between the class name and its arguments in:
|
||||
/// ```python
|
||||
/// case (
|
||||
/// Pattern
|
||||
/// # dangling
|
||||
/// ( # dangling
|
||||
/// # dangling
|
||||
/// )
|
||||
/// (...)
|
||||
/// ): ...
|
||||
/// ```
|
||||
fn handle_pattern_match_class_comment<'a>(
|
||||
comment: DecoratedComment<'a>,
|
||||
class: &'a ast::PatternMatchClass,
|
||||
locator: &Locator,
|
||||
) -> CommentPlacement<'a> {
|
||||
// Find the open parentheses on the arguments.
|
||||
let Some(left_paren) = SimpleTokenizer::starts_at(class.cls.end(), locator.contents())
|
||||
.skip_trivia()
|
||||
.find(|token| token.kind == SimpleTokenKind::LParen)
|
||||
else {
|
||||
return CommentPlacement::Default(comment);
|
||||
};
|
||||
|
||||
// If the comment appears before the open parenthesis, it's dangling:
|
||||
// ```python
|
||||
// case (
|
||||
// Pattern
|
||||
// # dangling
|
||||
// (...)
|
||||
// ): ...
|
||||
// ```
|
||||
if comment.end() < left_paren.start() {
|
||||
return CommentPlacement::dangling(comment.enclosing_node(), comment);
|
||||
if class.cls.end() < comment.start() && comment.end() < class.arguments.start() {
|
||||
CommentPlacement::dangling(comment.enclosing_node(), comment)
|
||||
} else {
|
||||
CommentPlacement::Default(comment)
|
||||
}
|
||||
|
||||
let Some(first_item) = class
|
||||
.patterns
|
||||
.first()
|
||||
.map(Ranged::start)
|
||||
.or_else(|| class.kwd_attrs.first().map(Ranged::start))
|
||||
else {
|
||||
// If there are no items, then the comment must be dangling:
|
||||
// ```python
|
||||
// case (
|
||||
// Pattern(
|
||||
// # dangling
|
||||
// )
|
||||
// ): ...
|
||||
// ```
|
||||
return CommentPlacement::dangling(comment.enclosing_node(), comment);
|
||||
};
|
||||
|
||||
// If the comment appears before the first item or its parentheses, then it's dangling:
|
||||
// ```python
|
||||
// case (
|
||||
// Pattern( # dangling
|
||||
// 0,
|
||||
// 0,
|
||||
// )
|
||||
// ): ...
|
||||
// ```
|
||||
if comment.line_position().is_end_of_line() {
|
||||
if comment.end() < first_item {
|
||||
return CommentPlacement::dangling(comment.enclosing_node(), comment);
|
||||
}
|
||||
}
|
||||
|
||||
CommentPlacement::Default(comment)
|
||||
}
|
||||
|
||||
/// Handles trailing comments after the `as` keyword of a pattern match item:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue