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

@ -1,7 +1,6 @@
use ruff_python_ast::Decorator;
use ruff_python_ast::call_path::from_qualified_name;
use ruff_python_ast::helpers::map_callable;
use ruff_python_ast::Decorator;
use crate::model::SemanticModel;
use crate::scope::{Scope, ScopeKind};
@ -23,7 +22,7 @@ pub fn classify(
classmethod_decorators: &[String],
staticmethod_decorators: &[String],
) -> FunctionType {
let ScopeKind::Class(scope) = &scope.kind else {
let ScopeKind::Class(class_def) = &scope.kind else {
return FunctionType::Function;
};
if decorator_list.iter().any(|decorator| {
@ -43,7 +42,7 @@ pub fn classify(
FunctionType::StaticMethod
} else if matches!(name, "__new__" | "__init_subclass__" | "__class_getitem__")
// Special-case class method, like `__new__`.
|| scope.bases.iter().any(|expr| {
|| class_def.bases().any(|expr| {
// The class itself extends a known metaclass, so all methods are class methods.
semantic
.resolve_call_path(map_callable(expr))