mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-03 07:04:53 +00:00
Implement visitation of type aliases and parameters (#5927)
<!-- Thank you for contributing to Ruff! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary <!-- What's the purpose of the change? What does it do, and why? --> Part of #5062 Requires https://github.com/astral-sh/RustPython-Parser/pull/32 Adds visitation of type alias statements and type parameters in class and function definitions. Duplicates tests for `PreorderVisitor` into `Visitor` with new snapshots. Testing required node implementations for the `TypeParam` enum, which is a chunk of the diff and the reason we need `Ranged` implementations in https://github.com/astral-sh/RustPython-Parser/pull/32. ## Test Plan <!-- How was it tested? --> Adds unit tests with snapshots.
This commit is contained in:
parent
3000a47fe8
commit
389fe13c93
18 changed files with 837 additions and 8 deletions
|
@ -1,7 +1,8 @@
|
|||
use rustpython_ast::{ArgWithDefault, ElifElseClause, Mod, TypeIgnore};
|
||||
use rustpython_parser::ast::{
|
||||
self, Alias, Arg, Arguments, BoolOp, CmpOp, Comprehension, Constant, Decorator, ExceptHandler,
|
||||
Expr, Keyword, MatchCase, Operator, Pattern, Stmt, UnaryOp, WithItem,
|
||||
Expr, Keyword, MatchCase, Operator, Pattern, Stmt, TypeParam, TypeParamTypeVar, UnaryOp,
|
||||
WithItem,
|
||||
};
|
||||
|
||||
/// Visitor that traverses all nodes recursively in pre-order.
|
||||
|
@ -80,6 +81,10 @@ pub trait PreorderVisitor<'a> {
|
|||
walk_with_item(self, with_item);
|
||||
}
|
||||
|
||||
fn visit_type_param(&mut self, type_param: &'a TypeParam) {
|
||||
walk_type_param(self, type_param);
|
||||
}
|
||||
|
||||
fn visit_match_case(&mut self, match_case: &'a MatchCase) {
|
||||
walk_match_case(self, match_case);
|
||||
}
|
||||
|
@ -156,6 +161,7 @@ where
|
|||
body,
|
||||
decorator_list,
|
||||
returns,
|
||||
type_params,
|
||||
..
|
||||
})
|
||||
| Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef {
|
||||
|
@ -163,12 +169,17 @@ where
|
|||
body,
|
||||
decorator_list,
|
||||
returns,
|
||||
type_params,
|
||||
..
|
||||
}) => {
|
||||
for decorator in decorator_list {
|
||||
visitor.visit_decorator(decorator);
|
||||
}
|
||||
|
||||
for type_param in type_params {
|
||||
visitor.visit_type_param(type_param);
|
||||
}
|
||||
|
||||
visitor.visit_arguments(args);
|
||||
|
||||
for expr in returns {
|
||||
|
@ -183,12 +194,17 @@ where
|
|||
keywords,
|
||||
body,
|
||||
decorator_list,
|
||||
type_params,
|
||||
..
|
||||
}) => {
|
||||
for decorator in decorator_list {
|
||||
visitor.visit_decorator(decorator);
|
||||
}
|
||||
|
||||
for type_param in type_params {
|
||||
visitor.visit_type_param(type_param);
|
||||
}
|
||||
|
||||
for expr in bases {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
|
@ -218,6 +234,19 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
Stmt::TypeAlias(ast::StmtTypeAlias {
|
||||
range: _range,
|
||||
name,
|
||||
type_params,
|
||||
value,
|
||||
}) => {
|
||||
visitor.visit_expr(name);
|
||||
for type_param in type_params {
|
||||
visitor.visit_type_param(type_param);
|
||||
}
|
||||
visitor.visit_expr(value);
|
||||
}
|
||||
|
||||
Stmt::Assign(ast::StmtAssign {
|
||||
targets,
|
||||
value,
|
||||
|
@ -400,7 +429,6 @@ where
|
|||
| Stmt::Continue(_)
|
||||
| Stmt::Global(_)
|
||||
| Stmt::Nonlocal(_) => {}
|
||||
Stmt::TypeAlias(_) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -805,6 +833,24 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn walk_type_param<'a, V>(visitor: &mut V, type_param: &'a TypeParam)
|
||||
where
|
||||
V: PreorderVisitor<'a> + ?Sized,
|
||||
{
|
||||
match type_param {
|
||||
TypeParam::TypeVar(TypeParamTypeVar {
|
||||
bound,
|
||||
name: _,
|
||||
range: _,
|
||||
}) => {
|
||||
if let Some(expr) = bound {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
}
|
||||
TypeParam::TypeVarTuple(_) | TypeParam::ParamSpec(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_match_case<'a, V>(visitor: &mut V, match_case: &'a MatchCase)
|
||||
where
|
||||
V: PreorderVisitor<'a> + ?Sized,
|
||||
|
@ -947,9 +993,9 @@ mod tests {
|
|||
use crate::visitor::preorder::{
|
||||
walk_alias, walk_arg, walk_arguments, walk_comprehension, walk_except_handler, walk_expr,
|
||||
walk_keyword, walk_match_case, walk_module, walk_pattern, walk_stmt, walk_type_ignore,
|
||||
walk_with_item, Alias, Arg, Arguments, BoolOp, CmpOp, Comprehension, Constant,
|
||||
ExceptHandler, Expr, Keyword, MatchCase, Mod, Operator, Pattern, PreorderVisitor, Stmt,
|
||||
TypeIgnore, UnaryOp, WithItem,
|
||||
walk_type_param, walk_with_item, Alias, Arg, Arguments, BoolOp, CmpOp, Comprehension,
|
||||
Constant, ExceptHandler, Expr, Keyword, MatchCase, Mod, Operator, Pattern, PreorderVisitor,
|
||||
Stmt, TypeIgnore, TypeParam, UnaryOp, WithItem,
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
@ -1038,6 +1084,33 @@ class A:
|
|||
assert_snapshot!(trace);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_aliases() {
|
||||
let source = r#"type X[T: str, U, *Ts, **P] = list[T]"#;
|
||||
|
||||
let trace = trace_preorder_visitation(source);
|
||||
|
||||
assert_snapshot!(trace);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn class_type_parameters() {
|
||||
let source = r#"class X[T: str, U, *Ts, **P]: ..."#;
|
||||
|
||||
let trace = trace_preorder_visitation(source);
|
||||
|
||||
assert_snapshot!(trace);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn function_type_parameters() {
|
||||
let source = r#"def X[T: str, U, *Ts, **P](): ..."#;
|
||||
|
||||
let trace = trace_preorder_visitation(source);
|
||||
|
||||
assert_snapshot!(trace);
|
||||
}
|
||||
|
||||
fn trace_preorder_visitation(source: &str) -> String {
|
||||
let tokens = lex(source, Mode::Module);
|
||||
let parsed = parse_tokens(tokens, Mode::Module, "test.py").unwrap();
|
||||
|
@ -1188,5 +1261,11 @@ class A:
|
|||
walk_type_ignore(self, type_ignore);
|
||||
self.exit_node();
|
||||
}
|
||||
|
||||
fn visit_type_param(&mut self, type_param: &TypeParam) {
|
||||
self.enter_node(type_param);
|
||||
walk_type_param(self, type_param);
|
||||
self.exit_node();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue