Introduce an Arguments AST node for function calls and class definitions (#6259)

## Summary

This PR adds a new `Arguments` AST node, which we can use for function
calls and class definitions.

The `Arguments` node spans from the left (open) to right (close)
parentheses inclusive.

In the case of classes, the `Arguments` is an option, to differentiate
between:

```python
# None
class C: ...

# Some, with empty vectors
class C(): ...
```

In this PR, we don't really leverage this change (except that a few
rules get much simpler, since we don't need to lex to find the start and
end ranges of the parentheses, e.g.,
`crates/ruff/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs`,
`crates/ruff/src/rules/pyupgrade/rules/unnecessary_class_parentheses.rs`).

In future PRs, this will be especially helpful for the formatter, since
we can track comments enclosed on the node itself.

## Test Plan

`cargo test`
This commit is contained in:
Charlie Marsh 2023-08-02 10:01:13 -04:00 committed by GitHub
parent 0d62ad2480
commit 981e64f82b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
107 changed files with 24258 additions and 23835 deletions

View file

@ -339,6 +339,27 @@ impl<'a> From<&'a ast::Constant> for ComparableConstant<'a> {
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableArguments<'a> {
args: Vec<ComparableExpr<'a>>,
keywords: Vec<ComparableKeyword<'a>>,
}
impl<'a> From<&'a ast::Arguments> for ComparableArguments<'a> {
fn from(arguments: &'a ast::Arguments) -> Self {
Self {
args: arguments.args.iter().map(Into::into).collect(),
keywords: arguments.keywords.iter().map(Into::into).collect(),
}
}
}
impl<'a> From<&'a Box<ast::Arguments>> for ComparableArguments<'a> {
fn from(arguments: &'a Box<ast::Arguments>) -> Self {
(arguments.as_ref()).into()
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableParameters<'a> {
posonlyargs: Vec<ComparableParameterWithDefault<'a>>,
@ -583,8 +604,7 @@ pub struct ExprCompare<'a> {
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprCall<'a> {
func: Box<ComparableExpr<'a>>,
args: Vec<ComparableExpr<'a>>,
keywords: Vec<ComparableKeyword<'a>>,
arguments: ComparableArguments<'a>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
@ -837,13 +857,11 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> {
}),
ast::Expr::Call(ast::ExprCall {
func,
args,
keywords,
arguments,
range: _range,
}) => Self::Call(ExprCall {
func: func.into(),
args: args.iter().map(Into::into).collect(),
keywords: keywords.iter().map(Into::into).collect(),
arguments: arguments.into(),
}),
ast::Expr::FormattedValue(ast::ExprFormattedValue {
value,
@ -968,8 +986,7 @@ pub struct StmtAsyncFunctionDef<'a> {
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtClassDef<'a> {
name: &'a str,
bases: Vec<ComparableExpr<'a>>,
keywords: Vec<ComparableKeyword<'a>>,
arguments: Option<ComparableArguments<'a>>,
body: Vec<ComparableStmt<'a>>,
decorator_list: Vec<ComparableDecorator<'a>>,
type_params: Vec<ComparableTypeParam<'a>>,
@ -1240,16 +1257,14 @@ impl<'a> From<&'a ast::Stmt> for ComparableStmt<'a> {
}),
ast::Stmt::ClassDef(ast::StmtClassDef {
name,
bases,
keywords,
arguments,
body,
decorator_list,
type_params,
range: _range,
}) => Self::ClassDef(StmtClassDef {
name: name.as_str(),
bases: bases.iter().map(Into::into).collect(),
keywords: keywords.iter().map(Into::into).collect(),
arguments: arguments.as_ref().map(Into::into),
body: body.iter().map(Into::into).collect(),
decorator_list: decorator_list.iter().map(Into::into).collect(),
type_params: type_params.iter().map(Into::into).collect(),