diff --git a/Cargo.lock b/Cargo.lock index 2631b2b0c7..e4ee07522f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1700,7 +1700,7 @@ dependencies = [ [[package]] name = "rust-python-linter" -version = "0.0.11" +version = "0.0.12" dependencies = [ "anyhow", "bincode", diff --git a/Cargo.toml b/Cargo.toml index 03f3f1905d..5bda01349f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rust-python-linter" -version = "0.0.11" +version = "0.0.12" edition = "2021" [lib] diff --git a/README.md b/README.md index 89ef70d594..c239d6d6a8 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ in Rust. Features: -- Python 3.9 compatibility +- Python 3.10 compatibility - [ESLint](https://eslint.org/docs/latest/user-guide/command-line-interface#caching)-inspired cache semantics - [TypeScript](https://www.typescriptlang.org/docs/handbook/configuring-watch.html)-inspired `--watch` semantics - `pyproject.toml` support diff --git a/src/visitor.rs b/src/visitor.rs index 4631190e63..968bcf5f8d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,7 +1,7 @@ use rustpython_parser::ast::{ Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, Excepthandler, - ExcepthandlerKind, Expr, ExprContext, ExprKind, Keyword, Operator, Stmt, StmtKind, Unaryop, - Withitem, + ExcepthandlerKind, Expr, ExprContext, ExprKind, Keyword, MatchCase, Operator, Pattern, + PatternKind, Stmt, StmtKind, Unaryop, Withitem, }; pub trait Visitor { @@ -53,9 +53,14 @@ pub trait Visitor { fn visit_withitem(&mut self, withitem: &Withitem) { walk_withitem(self, withitem); } + fn visit_match_case(&mut self, match_case: &MatchCase) { + walk_match_case(self, match_case); + } + fn visit_pattern(&mut self, pattern: &Pattern) { + walk_pattern(self, pattern); + } } -#[allow(unused_variables)] pub fn walk_stmt(visitor: &mut V, stmt: &Stmt) { match &stmt.node { StmtKind::FunctionDef { @@ -64,7 +69,7 @@ pub fn walk_stmt(visitor: &mut V, stmt: &Stmt) { body, decorator_list, returns, - type_comment, + .. } => { visitor.visit_ident(name); visitor.visit_arguments(args); @@ -84,7 +89,7 @@ pub fn walk_stmt(visitor: &mut V, stmt: &Stmt) { body, decorator_list, returns, - type_comment, + .. } => { visitor.visit_ident(name); visitor.visit_arguments(args); @@ -129,11 +134,7 @@ pub fn walk_stmt(visitor: &mut V, stmt: &Stmt) { visitor.visit_expr(expr) } } - StmtKind::Assign { - targets, - value, - type_comment, - } => { + StmtKind::Assign { targets, value, .. } => { for expr in targets { visitor.visit_expr(expr) } @@ -148,7 +149,7 @@ pub fn walk_stmt(visitor: &mut V, stmt: &Stmt) { target, annotation, value, - simple, + .. } => { visitor.visit_expr(target); visitor.visit_expr(annotation); @@ -161,7 +162,7 @@ pub fn walk_stmt(visitor: &mut V, stmt: &Stmt) { iter, body, orelse, - type_comment, + .. } => { visitor.visit_expr(target); visitor.visit_expr(iter); @@ -177,7 +178,7 @@ pub fn walk_stmt(visitor: &mut V, stmt: &Stmt) { iter, body, orelse, - type_comment, + .. } => { visitor.visit_expr(target); visitor.visit_expr(iter); @@ -206,11 +207,7 @@ pub fn walk_stmt(visitor: &mut V, stmt: &Stmt) { visitor.visit_stmt(stmt) } } - StmtKind::With { - items, - body, - type_comment, - } => { + StmtKind::With { items, body, .. } => { for withitem in items { visitor.visit_withitem(withitem); } @@ -218,11 +215,7 @@ pub fn walk_stmt(visitor: &mut V, stmt: &Stmt) { visitor.visit_stmt(stmt) } } - StmtKind::AsyncWith { - items, - body, - type_comment, - } => { + StmtKind::AsyncWith { items, body, .. } => { for withitem in items { visitor.visit_withitem(withitem); } @@ -230,9 +223,12 @@ pub fn walk_stmt(visitor: &mut V, stmt: &Stmt) { visitor.visit_stmt(stmt) } } - StmtKind::Match { subject, .. } => { + StmtKind::Match { subject, cases } => { // TODO(charlie): Handle `cases`. visitor.visit_expr(subject); + for match_case in cases { + visitor.visit_match_case(match_case); + } } StmtKind::Raise { exc, cause } => { if let Some(expr) = exc { @@ -272,11 +268,10 @@ pub fn walk_stmt(visitor: &mut V, stmt: &Stmt) { visitor.visit_alias(alias); } } - StmtKind::ImportFrom { - module, - names, - level, - } => { + StmtKind::ImportFrom { module, names, .. } => { + if let Some(ident) = module { + visitor.visit_ident(ident); + } for alias in names { visitor.visit_alias(alias); } @@ -298,7 +293,6 @@ pub fn walk_stmt(visitor: &mut V, stmt: &Stmt) { } } -#[allow(unused_variables)] pub fn walk_expr(visitor: &mut V, expr: &Expr) { match &expr.node { ExprKind::BoolOp { op, values } => { @@ -405,9 +399,7 @@ pub fn walk_expr(visitor: &mut V, expr: &Expr) { } } ExprKind::FormattedValue { - value, - conversion, - format_spec, + value, format_spec, .. } => { visitor.visit_expr(value); if let Some(expr) = format_spec { @@ -419,8 +411,8 @@ pub fn walk_expr(visitor: &mut V, expr: &Expr) { visitor.visit_expr(expr) } } - ExprKind::Constant { value, kind } => visitor.visit_constant(value), - ExprKind::Attribute { value, attr, ctx } => { + ExprKind::Constant { value, .. } => visitor.visit_constant(value), + ExprKind::Attribute { value, ctx, .. } => { visitor.visit_expr(value); visitor.visit_expr_context(ctx); } @@ -463,7 +455,6 @@ pub fn walk_expr(visitor: &mut V, expr: &Expr) { } } -#[allow(unused_variables)] pub fn walk_constant(visitor: &mut V, constant: &Constant) { if let Constant::Tuple(constants) = constant { for constant in constants { @@ -472,7 +463,6 @@ pub fn walk_constant(visitor: &mut V, constant: &Constant) } } -#[allow(unused_variables)] pub fn walk_comprehension(visitor: &mut V, comprehension: &Comprehension) { visitor.visit_expr(&comprehension.target); visitor.visit_expr(&comprehension.iter); @@ -481,21 +471,22 @@ pub fn walk_comprehension(visitor: &mut V, comprehension: & } } -#[allow(unused_variables)] pub fn walk_excepthandler(visitor: &mut V, excepthandler: &Excepthandler) { match &excepthandler.node { ExcepthandlerKind::ExceptHandler { type_, name, body } => { if let Some(expr) = type_ { - visitor.visit_expr(expr) + visitor.visit_expr(expr); + } + if let Some(ident) = name { + visitor.visit_ident(ident); } for stmt in body { - visitor.visit_stmt(stmt) + visitor.visit_stmt(stmt); } } } } -#[allow(unused_variables)] pub fn walk_arguments(visitor: &mut V, arguments: &Arguments) { for arg in &arguments.posonlyargs { visitor.visit_arg(arg); @@ -520,19 +511,16 @@ pub fn walk_arguments(visitor: &mut V, arguments: &Argument } } -#[allow(unused_variables)] pub fn walk_arg(visitor: &mut V, arg: &Arg) { if let Some(expr) = &arg.node.annotation { visitor.visit_expr(expr) } } -#[allow(unused_variables)] pub fn walk_keyword(visitor: &mut V, keyword: &Keyword) { visitor.visit_expr(&keyword.node.value); } -#[allow(unused_variables)] pub fn walk_withitem(visitor: &mut V, withitem: &Withitem) { visitor.visit_expr(&withitem.context_expr); if let Some(expr) = &withitem.optional_vars { @@ -540,6 +528,78 @@ pub fn walk_withitem(visitor: &mut V, withitem: &Withitem) } } +pub fn walk_match_case(visitor: &mut V, match_case: &MatchCase) { + visitor.visit_pattern(&match_case.pattern); + if let Some(expr) = &match_case.guard { + visitor.visit_expr(expr); + } + for stmt in &match_case.body { + visitor.visit_stmt(stmt); + } +} + +pub fn walk_pattern(visitor: &mut V, pattern: &Pattern) { + match &pattern.node { + PatternKind::MatchValue { value } => visitor.visit_expr(value), + PatternKind::MatchSingleton { value } => visitor.visit_constant(value), + PatternKind::MatchSequence { patterns } => { + for pattern in patterns { + visitor.visit_pattern(pattern) + } + } + PatternKind::MatchMapping { + keys, + patterns, + rest, + } => { + for expr in keys { + visitor.visit_expr(expr); + } + for pattern in patterns { + visitor.visit_pattern(pattern); + } + if let Some(ident) = rest { + visitor.visit_ident(ident); + } + } + PatternKind::MatchClass { + cls, + patterns, + kwd_attrs, + kwd_patterns, + } => { + visitor.visit_expr(cls); + for pattern in patterns { + visitor.visit_pattern(pattern); + } + for ident in kwd_attrs { + visitor.visit_ident(ident); + } + for pattern in kwd_patterns { + visitor.visit_pattern(pattern); + } + } + PatternKind::MatchStar { name } => { + if let Some(ident) = name { + visitor.visit_ident(ident) + } + } + PatternKind::MatchAs { pattern, name } => { + if let Some(pattern) = pattern { + visitor.visit_pattern(pattern) + } + if let Some(ident) = name { + visitor.visit_ident(ident) + } + } + PatternKind::MatchOr { patterns } => { + for pattern in patterns { + visitor.visit_pattern(pattern); + } + } + } +} + #[allow(unused_variables)] pub fn walk_ident(visitor: &mut V, ident: &str) {}