Skip to content

Commit

Permalink
Introduce AST nodes for PatternMatchClass arguments (#6881)
Browse files Browse the repository at this point in the history
## 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 #6866.

Closes #6880.
  • Loading branch information
charliermarsh committed Aug 26, 2023
1 parent ed1b412 commit 15b73bd
Show file tree
Hide file tree
Showing 19 changed files with 11,069 additions and 11,594 deletions.
52 changes: 37 additions & 15 deletions crates/ruff_python_ast/src/comparable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,36 @@ impl<'a> From<&'a ast::WithItem> for ComparableWithItem<'a> {
}
}

#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparablePatternArguments<'a> {
patterns: Vec<ComparablePattern<'a>>,
keywords: Vec<ComparablePatternKeyword<'a>>,
}

impl<'a> From<&'a ast::PatternArguments> for ComparablePatternArguments<'a> {
fn from(parameters: &'a ast::PatternArguments) -> Self {
Self {
patterns: parameters.patterns.iter().map(Into::into).collect(),
keywords: parameters.keywords.iter().map(Into::into).collect(),
}
}
}

#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparablePatternKeyword<'a> {
attr: &'a str,
pattern: ComparablePattern<'a>,
}

impl<'a> From<&'a ast::PatternKeyword> for ComparablePatternKeyword<'a> {
fn from(keyword: &'a ast::PatternKeyword) -> Self {
Self {
attr: keyword.attr.as_str(),
pattern: (&keyword.pattern).into(),
}
}
}

#[derive(Debug, PartialEq, Eq, Hash)]
pub struct PatternMatchValue<'a> {
value: ComparableExpr<'a>,
Expand All @@ -178,9 +208,7 @@ pub struct PatternMatchMapping<'a> {
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct PatternMatchClass<'a> {
cls: ComparableExpr<'a>,
patterns: Vec<ComparablePattern<'a>>,
kwd_attrs: Vec<&'a str>,
kwd_patterns: Vec<ComparablePattern<'a>>,
arguments: ComparablePatternArguments<'a>,
}

#[derive(Debug, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -240,18 +268,12 @@ impl<'a> From<&'a ast::Pattern> for ComparablePattern<'a> {
patterns: patterns.iter().map(Into::into).collect(),
rest: rest.as_deref(),
}),
ast::Pattern::MatchClass(ast::PatternMatchClass {
cls,
patterns,
kwd_attrs,
kwd_patterns,
..
}) => Self::MatchClass(PatternMatchClass {
cls: cls.into(),
patterns: patterns.iter().map(Into::into).collect(),
kwd_attrs: kwd_attrs.iter().map(ast::Identifier::as_str).collect(),
kwd_patterns: kwd_patterns.iter().map(Into::into).collect(),
}),
ast::Pattern::MatchClass(ast::PatternMatchClass { cls, arguments, .. }) => {
Self::MatchClass(PatternMatchClass {
cls: cls.into(),
arguments: arguments.into(),
})
}
ast::Pattern::MatchStar(ast::PatternMatchStar { name, .. }) => {
Self::MatchStar(PatternMatchStar {
name: name.as_deref(),
Expand Down
15 changes: 6 additions & 9 deletions crates/ruff_python_ast/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,19 +279,16 @@ where
.iter()
.any(|pattern| any_over_pattern(pattern, func))
}
Pattern::MatchClass(ast::PatternMatchClass {
cls,
patterns,
kwd_patterns,
..
}) => {
Pattern::MatchClass(ast::PatternMatchClass { cls, arguments, .. }) => {
any_over_expr(cls, func)
|| patterns
|| arguments
.patterns
.iter()
.any(|pattern| any_over_pattern(pattern, func))
|| kwd_patterns
|| arguments
.keywords
.iter()
.any(|pattern| any_over_pattern(pattern, func))
.any(|keyword| any_over_pattern(&keyword.pattern, func))
}
Pattern::MatchStar(_) => false,
Pattern::MatchAs(ast::PatternMatchAs { pattern, .. }) => pattern
Expand Down
Loading

0 comments on commit 15b73bd

Please sign in to comment.