diff --git a/Cargo.lock b/Cargo.lock index 27ee5dcf57..e0e012cdf0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1988,6 +1988,16 @@ dependencies = [ "rustpython-parser", ] +[[package]] +name = "ruff_source_location" +version = "0.0.0" +source = "git+https://github.com/RustPython/Parser.git?rev=718354673eb2cc9645d63fc0c50b4ad08e5595c2#718354673eb2cc9645d63fc0c50b4ad08e5595c2" +dependencies = [ + "memchr", + "once_cell", + "ruff_text_size", +] + [[package]] name = "ruff_testing_macros" version = "0.0.0" @@ -2001,7 +2011,7 @@ dependencies = [ [[package]] name = "ruff_text_size" version = "0.0.0" -source = "git+https://github.com/RustPython/Parser.git?rev=a983f4383fb1ad8c1c66acb1d5b0016e59f95a49#a983f4383fb1ad8c1c66acb1d5b0016e59f95a49" +source = "git+https://github.com/RustPython/Parser.git?rev=718354673eb2cc9645d63fc0c50b4ad08e5595c2#718354673eb2cc9645d63fc0c50b4ad08e5595c2" dependencies = [ "schemars", "serde", @@ -2072,17 +2082,18 @@ dependencies = [ [[package]] name = "rustpython-ast" version = "0.2.0" -source = "git+https://github.com/RustPython/Parser.git?rev=a983f4383fb1ad8c1c66acb1d5b0016e59f95a49#a983f4383fb1ad8c1c66acb1d5b0016e59f95a49" +source = "git+https://github.com/RustPython/Parser.git?rev=718354673eb2cc9645d63fc0c50b4ad08e5595c2#718354673eb2cc9645d63fc0c50b4ad08e5595c2" dependencies = [ "is-macro", "num-bigint", "rustpython-parser-core", + "static_assertions", ] [[package]] name = "rustpython-format" version = "0.2.0" -source = "git+https://github.com/RustPython/Parser.git?rev=a983f4383fb1ad8c1c66acb1d5b0016e59f95a49#a983f4383fb1ad8c1c66acb1d5b0016e59f95a49" +source = "git+https://github.com/RustPython/Parser.git?rev=718354673eb2cc9645d63fc0c50b4ad08e5595c2#718354673eb2cc9645d63fc0c50b4ad08e5595c2" dependencies = [ "bitflags 2.2.1", "itertools", @@ -2094,7 +2105,7 @@ dependencies = [ [[package]] name = "rustpython-literal" version = "0.2.0" -source = "git+https://github.com/RustPython/Parser.git?rev=a983f4383fb1ad8c1c66acb1d5b0016e59f95a49#a983f4383fb1ad8c1c66acb1d5b0016e59f95a49" +source = "git+https://github.com/RustPython/Parser.git?rev=718354673eb2cc9645d63fc0c50b4ad08e5595c2#718354673eb2cc9645d63fc0c50b4ad08e5595c2" dependencies = [ "hexf-parse", "lexical-parse-float", @@ -2105,7 +2116,7 @@ dependencies = [ [[package]] name = "rustpython-parser" version = "0.2.0" -source = "git+https://github.com/RustPython/Parser.git?rev=a983f4383fb1ad8c1c66acb1d5b0016e59f95a49#a983f4383fb1ad8c1c66acb1d5b0016e59f95a49" +source = "git+https://github.com/RustPython/Parser.git?rev=718354673eb2cc9645d63fc0c50b4ad08e5595c2#718354673eb2cc9645d63fc0c50b4ad08e5595c2" dependencies = [ "anyhow", "itertools", @@ -2127,8 +2138,9 @@ dependencies = [ [[package]] name = "rustpython-parser-core" version = "0.2.0" -source = "git+https://github.com/RustPython/Parser.git?rev=a983f4383fb1ad8c1c66acb1d5b0016e59f95a49#a983f4383fb1ad8c1c66acb1d5b0016e59f95a49" +source = "git+https://github.com/RustPython/Parser.git?rev=718354673eb2cc9645d63fc0c50b4ad08e5595c2#718354673eb2cc9645d63fc0c50b4ad08e5595c2" dependencies = [ + "ruff_source_location", "ruff_text_size", ] diff --git a/Cargo.toml b/Cargo.toml index 7dbe91fb3d..243e2ab888 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,10 +31,10 @@ proc-macro2 = { version = "1.0.51" } quote = { version = "1.0.23" } regex = { version = "1.7.1" } rustc-hash = { version = "1.1.0" } -ruff_text_size = { git = "https://github.com/RustPython/Parser.git", rev = "a983f4383fb1ad8c1c66acb1d5b0016e59f95a49" } -rustpython-format = { git = "https://github.com/RustPython/Parser.git", rev = "a983f4383fb1ad8c1c66acb1d5b0016e59f95a49" } -rustpython-literal = { git = "https://github.com/RustPython/Parser.git", rev = "a983f4383fb1ad8c1c66acb1d5b0016e59f95a49" } -rustpython-parser = { git = "https://github.com/RustPython/Parser.git", rev = "a983f4383fb1ad8c1c66acb1d5b0016e59f95a49" , default-features = false} +ruff_text_size = { git = "https://github.com/RustPython/Parser.git", rev = "718354673eb2cc9645d63fc0c50b4ad08e5595c2" } +rustpython-format = { git = "https://github.com/RustPython/Parser.git", rev = "718354673eb2cc9645d63fc0c50b4ad08e5595c2" } +rustpython-literal = { git = "https://github.com/RustPython/Parser.git", rev = "718354673eb2cc9645d63fc0c50b4ad08e5595c2" } +rustpython-parser = { git = "https://github.com/RustPython/Parser.git", rev = "718354673eb2cc9645d63fc0c50b4ad08e5595c2" , features = ["all-nodes-with-ranges"]} schemars = { version = "0.8.12" } serde = { version = "1.0.152", features = ["derive"] } serde_json = { version = "1.0.93", features = ["preserve_order"] } diff --git a/crates/ruff/src/autofix/actions.rs b/crates/ruff/src/autofix/actions.rs index b68610588e..4442304979 100644 --- a/crates/ruff/src/autofix/actions.rs +++ b/crates/ruff/src/autofix/actions.rs @@ -5,7 +5,7 @@ use libcst_native::{ Codegen, CodegenState, ImportNames, ParenthesizableWhitespace, SmallStatement, Statement, }; use ruff_text_size::{TextLen, TextRange, TextSize}; -use rustpython_parser::ast::{self, ExcepthandlerKind, Expr, Keyword, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Excepthandler, Expr, Keyword, Ranged, Stmt}; use rustpython_parser::{lexer, Mode, Tok}; use ruff_diagnostics::Edit; @@ -27,22 +27,22 @@ fn has_single_child(body: &[Stmt], deleted: &[&Stmt]) -> bool { /// Determine if a child is the only statement in its body. fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result { - match &parent.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { body, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) - | StmtKind::ClassDef(ast::StmtClassDef { body, .. }) - | StmtKind::With(ast::StmtWith { body, .. }) - | StmtKind::AsyncWith(ast::StmtAsyncWith { body, .. }) => { + match parent { + Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) + | Stmt::ClassDef(ast::StmtClassDef { body, .. }) + | Stmt::With(ast::StmtWith { body, .. }) + | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { if body.iter().contains(child) { Ok(has_single_child(body, deleted)) } else { bail!("Unable to find child in parent body") } } - StmtKind::For(ast::StmtFor { body, orelse, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) - | StmtKind::While(ast::StmtWhile { body, orelse, .. }) - | StmtKind::If(ast::StmtIf { body, orelse, .. }) => { + Stmt::For(ast::StmtFor { body, orelse, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) + | Stmt::While(ast::StmtWhile { body, orelse, .. }) + | Stmt::If(ast::StmtIf { body, orelse, .. }) => { if body.iter().contains(child) { Ok(has_single_child(body, deleted)) } else if orelse.iter().contains(child) { @@ -51,17 +51,19 @@ fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result bail!("Unable to find child in parent body") } } - StmtKind::Try(ast::StmtTry { + Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, + range: _, }) - | StmtKind::TryStar(ast::StmtTryStar { + | Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, finalbody, + range: _, }) => { if body.iter().contains(child) { Ok(has_single_child(body, deleted)) @@ -69,10 +71,8 @@ fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result Ok(has_single_child(orelse, deleted)) } else if finalbody.iter().contains(child) { Ok(has_single_child(finalbody, deleted)) - } else if let Some(body) = handlers.iter().find_map(|handler| match &handler.node { - ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { - body, .. - }) => { + } else if let Some(body) = handlers.iter().find_map(|handler| match handler { + Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) => { if body.iter().contains(child) { Some(body) } else { @@ -85,7 +85,7 @@ fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result bail!("Unable to find child in parent body") } } - StmtKind::Match(ast::StmtMatch { cases, .. }) => { + Stmt::Match(ast::StmtMatch { cases, .. }) => { if let Some(body) = cases.iter().find_map(|case| { if case.body.iter().contains(child) { Some(&case.body) diff --git a/crates/ruff/src/checkers/ast/mod.rs b/crates/ruff/src/checkers/ast/mod.rs index 9424f0ff93..265e429cd8 100644 --- a/crates/ruff/src/checkers/ast/mod.rs +++ b/crates/ruff/src/checkers/ast/mod.rs @@ -6,9 +6,8 @@ use ruff_text_size::{TextRange, TextSize}; use rustc_hash::{FxHashMap, FxHashSet}; use rustpython_format::cformat::{CFormatError, CFormatErrorType}; use rustpython_parser::ast::{ - self, Arg, Arguments, Comprehension, Constant, Excepthandler, ExcepthandlerKind, Expr, - ExprContext, ExprKind, KeywordData, Operator, Pattern, PatternKind, Stmt, StmtKind, Suite, - Unaryop, + self, Arg, Arguments, Comprehension, Constant, Excepthandler, Expr, ExprContext, Keyword, + Operator, Pattern, Ranged, Stmt, Suite, Unaryop, }; use ruff_diagnostics::{Diagnostic, Fix}; @@ -145,13 +144,13 @@ where self.ctx.push_stmt(stmt); // Track whether we've seen docstrings, non-imports, etc. - match &stmt.node { - StmtKind::ImportFrom(ast::StmtImportFrom { module, names, .. }) => { + match stmt { + Stmt::ImportFrom(ast::StmtImportFrom { module, names, .. }) => { // Allow __future__ imports until we see a non-__future__ import. if let Some("__future__") = module.as_deref() { if names .iter() - .any(|alias| alias.node.name.as_str() == "annotations") + .any(|alias| alias.name.as_str() == "annotations") { self.ctx.flags |= ContextFlags::FUTURE_ANNOTATIONS; } @@ -159,7 +158,7 @@ where self.ctx.flags |= ContextFlags::FUTURES_BOUNDARY; } } - StmtKind::Import(_) => { + Stmt::Import(_) => { self.ctx.flags |= ContextFlags::FUTURES_BOUNDARY; } _ => { @@ -174,7 +173,7 @@ where } // Track each top-level import, to guide import insertions. - if matches!(&stmt.node, StmtKind::Import(_) | StmtKind::ImportFrom(_)) { + if matches!(stmt, Stmt::Import(_) | Stmt::ImportFrom(_)) { if self.ctx.at_top_level() { self.importer.visit_import(stmt); } @@ -185,8 +184,8 @@ where let flags_snapshot = self.ctx.flags; // Pre-visit. - match &stmt.node { - StmtKind::Global(ast::StmtGlobal { names }) => { + match stmt { + Stmt::Global(ast::StmtGlobal { names, range: _ }) => { let ranges: Vec = helpers::find_names(stmt, self.locator).collect(); if !self.ctx.scope_id.is_global() { // Add the binding to the current scope. @@ -216,7 +215,7 @@ where })); } } - StmtKind::Nonlocal(ast::StmtNonlocal { names }) => { + Stmt::Nonlocal(ast::StmtNonlocal { names, range: _ }) => { let ranges: Vec = helpers::find_names(stmt, self.locator).collect(); if !self.ctx.scope_id.is_global() { let context = self.ctx.execution_context(); @@ -272,7 +271,7 @@ where })); } } - StmtKind::Break => { + Stmt::Break(_) => { if self.settings.rules.enabled(Rule::BreakOutsideLoop) { if let Some(diagnostic) = pyflakes::rules::break_outside_loop(stmt, &mut self.ctx.parents().skip(1)) @@ -281,7 +280,7 @@ where } } } - StmtKind::Continue => { + Stmt::Continue(_) => { if self.settings.rules.enabled(Rule::ContinueOutsideLoop) { if let Some(diagnostic) = pyflakes::rules::continue_outside_loop( stmt, @@ -291,7 +290,7 @@ where } } } - StmtKind::FunctionDef(ast::StmtFunctionDef { + Stmt::FunctionDef(ast::StmtFunctionDef { name, decorator_list, returns, @@ -299,7 +298,7 @@ where body, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, decorator_list, returns, @@ -597,7 +596,7 @@ where } } } - StmtKind::Return(_) => { + Stmt::Return(_) => { if self.settings.rules.enabled(Rule::ReturnOutsideFunction) { pyflakes::rules::return_outside_function(self, stmt); } @@ -605,12 +604,13 @@ where pylint::rules::return_in_init(self, stmt); } } - StmtKind::ClassDef(ast::StmtClassDef { + Stmt::ClassDef(ast::StmtClassDef { name, bases, keywords, decorator_list, body, + range: _, }) => { if self .settings @@ -766,7 +766,7 @@ where pylint::rules::duplicate_bases(self, name, bases); } } - StmtKind::Import(ast::StmtImport { names }) => { + Stmt::Import(ast::StmtImport { names, range: _ }) => { if self.settings.rules.enabled(Rule::MultipleImportsOnOneLine) { pycodestyle::rules::multiple_imports_on_one_line(self, stmt, names); } @@ -780,10 +780,10 @@ where if self.settings.rules.enabled(Rule::GlobalStatement) { for name in names.iter() { - if let Some(asname) = name.node.asname.as_ref() { + if let Some(asname) = name.asname.as_ref() { pylint::rules::global_statement(self, asname); } else { - pylint::rules::global_statement(self, &name.node.name); + pylint::rules::global_statement(self, &name.name); } } } @@ -796,8 +796,8 @@ where } for alias in names { - if &alias.node.name == "__future__" { - let name = alias.node.asname.as_ref().unwrap_or(&alias.node.name); + if &alias.name == "__future__" { + let name = alias.asname.as_ref().unwrap_or(&alias.name); self.add_binding( name, Binding { @@ -821,11 +821,11 @@ where )); } } - } else if alias.node.name.contains('.') && alias.node.asname.is_none() { + } else if alias.name.contains('.') && alias.asname.is_none() { // Given `import foo.bar`, `name` would be "foo", and `full_name` would be // "foo.bar". - let name = alias.node.name.split('.').next().unwrap(); - let full_name = &alias.node.name; + let name = alias.name.split('.').next().unwrap(); + let full_name = &alias.name; self.add_binding( name, Binding { @@ -846,13 +846,12 @@ where // Treat explicit re-export as usage (e.g., `from .applications // import FastAPI as FastAPI`). let is_explicit_reexport = alias - .node .asname .as_ref() - .map_or(false, |asname| asname == &alias.node.name); + .map_or(false, |asname| asname == &alias.name); - let name = alias.node.asname.as_ref().unwrap_or(&alias.node.name); - let full_name = &alias.node.name; + let name = alias.asname.as_ref().unwrap_or(&alias.name); + let full_name = &alias.name; self.add_binding( name, Binding { @@ -871,7 +870,7 @@ where }, ); - if let Some(asname) = &alias.node.asname { + if let Some(asname) = &alias.asname { if self.settings.rules.enabled(Rule::BuiltinVariableShadowing) { flake8_builtins::rules::builtin_variable_shadowing( self, asname, stmt, @@ -883,7 +882,7 @@ where // flake8-debugger if self.settings.rules.enabled(Rule::Debugger) { if let Some(diagnostic) = - flake8_debugger::rules::debugger_import(stmt, None, &alias.node.name) + flake8_debugger::rules::debugger_import(stmt, None, &alias.name) { self.diagnostics.push(diagnostic); } @@ -893,7 +892,7 @@ where if self.settings.rules.enabled(Rule::BannedApi) { flake8_tidy_imports::banned_api::name_or_parent_is_banned( self, - &alias.node.name, + &alias.name, alias, ); } @@ -915,8 +914,8 @@ where } } - if let Some(asname) = &alias.node.asname { - let name = alias.node.name.split('.').last().unwrap(); + if let Some(asname) = &alias.asname { + let name = alias.name.split('.').last().unwrap(); if self .settings .rules @@ -992,8 +991,8 @@ where if let Some(diagnostic) = flake8_import_conventions::rules::conventional_import_alias( stmt, - &alias.node.name, - alias.node.asname.as_deref(), + &alias.name, + alias.asname.as_deref(), &self.settings.flake8_import_conventions.aliases, ) { @@ -1002,11 +1001,11 @@ where } if self.settings.rules.enabled(Rule::BannedImportAlias) { - if let Some(asname) = &alias.node.asname { + if let Some(asname) = &alias.asname { if let Some(diagnostic) = flake8_import_conventions::rules::banned_import_alias( stmt, - &alias.node.name, + &alias.name, asname, &self.settings.flake8_import_conventions.banned_aliases, ) @@ -1023,18 +1022,19 @@ where { if let Some(diagnostic) = flake8_pytest_style::rules::import( stmt, - &alias.node.name, - alias.node.asname.as_deref(), + &alias.name, + alias.asname.as_deref(), ) { self.diagnostics.push(diagnostic); } } } } - StmtKind::ImportFrom(ast::StmtImportFrom { + Stmt::ImportFrom(ast::StmtImportFrom { names, module, level, + range: _, }) => { let module = module.as_deref(); let level = level.map(|level| level.to_u32()); @@ -1048,10 +1048,10 @@ where if self.settings.rules.enabled(Rule::GlobalStatement) { for name in names.iter() { - if let Some(asname) = name.node.asname.as_ref() { + if let Some(asname) = name.asname.as_ref() { pylint::rules::global_statement(self, asname); } else { - pylint::rules::global_statement(self, &name.node.name); + pylint::rules::global_statement(self, &name.name); } } } @@ -1086,12 +1086,12 @@ where ); for alias in names { - if &alias.node.name == "*" { + if &alias.name == "*" { continue; } flake8_tidy_imports::banned_api::name_is_banned( self, - format!("{module}.{}", alias.node.name), + format!("{module}.{}", alias.name), alias, ); } @@ -1112,7 +1112,7 @@ where for alias in names { if let Some("__future__") = module { - let name = alias.node.asname.as_ref().unwrap_or(&alias.node.name); + let name = alias.asname.as_ref().unwrap_or(&alias.name); self.add_binding( name, Binding { @@ -1140,7 +1140,7 @@ where )); } } - } else if &alias.node.name == "*" { + } else if &alias.name == "*" { self.ctx .scope_mut() .add_star_import(StarImportation { level, module }); @@ -1174,7 +1174,7 @@ where )); } } else { - if let Some(asname) = &alias.node.asname { + if let Some(asname) = &alias.asname { if self.settings.rules.enabled(Rule::BuiltinVariableShadowing) { flake8_builtins::rules::builtin_variable_shadowing( self, asname, stmt, @@ -1185,17 +1185,16 @@ where // Treat explicit re-export as usage (e.g., `from .applications // import FastAPI as FastAPI`). let is_explicit_reexport = alias - .node .asname .as_ref() - .map_or(false, |asname| asname == &alias.node.name); + .map_or(false, |asname| asname == &alias.name); // Given `from foo import bar`, `name` would be "bar" and `full_name` would // be "foo.bar". Given `from foo import bar as baz`, `name` would be "baz" // and `full_name` would be "foo.bar". - let name = alias.node.asname.as_ref().unwrap_or(&alias.node.name); + let name = alias.asname.as_ref().unwrap_or(&alias.name); let full_name = - helpers::format_import_from_member(level, module, &alias.node.name); + helpers::format_import_from_member(level, module, &alias.name); self.add_binding( name, Binding { @@ -1236,7 +1235,7 @@ where // flake8-debugger if self.settings.rules.enabled(Rule::Debugger) { if let Some(diagnostic) = - flake8_debugger::rules::debugger_import(stmt, module, &alias.node.name) + flake8_debugger::rules::debugger_import(stmt, module, &alias.name) { self.diagnostics.push(diagnostic); } @@ -1244,12 +1243,12 @@ where if self.settings.rules.enabled(Rule::UnconventionalImportAlias) { let full_name = - helpers::format_import_from_member(level, module, &alias.node.name); + helpers::format_import_from_member(level, module, &alias.name); if let Some(diagnostic) = flake8_import_conventions::rules::conventional_import_alias( stmt, &full_name, - alias.node.asname.as_deref(), + alias.asname.as_deref(), &self.settings.flake8_import_conventions.aliases, ) { @@ -1258,9 +1257,9 @@ where } if self.settings.rules.enabled(Rule::BannedImportAlias) { - if let Some(asname) = &alias.node.asname { + if let Some(asname) = &alias.asname { let full_name = - helpers::format_import_from_member(level, module, &alias.node.name); + helpers::format_import_from_member(level, module, &alias.name); if let Some(diagnostic) = flake8_import_conventions::rules::banned_import_alias( stmt, @@ -1274,7 +1273,7 @@ where } } - if let Some(asname) = &alias.node.asname { + if let Some(asname) = &alias.asname { if self .settings .rules @@ -1282,7 +1281,7 @@ where { if let Some(diagnostic) = pep8_naming::rules::constant_imported_as_non_constant( - &alias.node.name, + &alias.name, asname, alias, stmt, @@ -1299,7 +1298,7 @@ where { if let Some(diagnostic) = pep8_naming::rules::lowercase_imported_as_non_lowercase( - &alias.node.name, + &alias.name, asname, alias, stmt, @@ -1316,7 +1315,7 @@ where { if let Some(diagnostic) = pep8_naming::rules::camelcase_imported_as_lowercase( - &alias.node.name, + &alias.name, asname, alias, stmt, @@ -1333,7 +1332,7 @@ where { if let Some(diagnostic) = pep8_naming::rules::camelcase_imported_as_constant( - &alias.node.name, + &alias.name, asname, alias, stmt, @@ -1350,7 +1349,7 @@ where { if let Some(diagnostic) = pep8_naming::rules::camelcase_imported_as_acronym( - &alias.node.name, + &alias.name, asname, alias, stmt, @@ -1387,7 +1386,7 @@ where } } } - StmtKind::Raise(ast::StmtRaise { exc, .. }) => { + Stmt::Raise(ast::StmtRaise { exc, .. }) => { if self.settings.rules.enabled(Rule::RaiseNotImplemented) { if let Some(expr) = exc { pyflakes::rules::raise_not_implemented(self, expr); @@ -1432,16 +1431,21 @@ where } } } - StmtKind::AugAssign(ast::StmtAugAssign { target, .. }) => { + Stmt::AugAssign(ast::StmtAugAssign { target, .. }) => { self.handle_node_load(target); if self.settings.rules.enabled(Rule::GlobalStatement) { - if let ExprKind::Name(ast::ExprName { id, .. }) = &target.node { + if let Expr::Name(ast::ExprName { id, .. }) = target.as_ref() { pylint::rules::global_statement(self, id); } } } - StmtKind::If(ast::StmtIf { test, body, orelse }) => { + Stmt::If(ast::StmtIf { + test, + body, + orelse, + range: _, + }) => { if self.settings.rules.enabled(Rule::IfTuple) { pyflakes::rules::if_tuple(self, stmt, test); } @@ -1516,7 +1520,11 @@ where } } } - StmtKind::Assert(ast::StmtAssert { test, msg }) => { + Stmt::Assert(ast::StmtAssert { + test, + msg, + range: _, + }) => { if !self.ctx.in_type_checking_block() { if self.settings.rules.enabled(Rule::Assert) { self.diagnostics @@ -1547,7 +1555,7 @@ where pygrep_hooks::rules::non_existent_mock_method(self, test); } } - StmtKind::With(ast::StmtWith { items, body, .. }) => { + Stmt::With(ast::StmtWith { items, body, .. }) => { if self.settings.rules.enabled(Rule::AssertRaisesException) { flake8_bugbear::rules::assert_raises_exception(self, stmt, items); } @@ -1570,7 +1578,7 @@ where pylint::rules::redefined_loop_name(self, &Node::Stmt(stmt)); } } - StmtKind::While(ast::StmtWhile { body, orelse, .. }) => { + Stmt::While(ast::StmtWhile { body, orelse, .. }) => { if self.settings.rules.enabled(Rule::FunctionUsesLoopVariable) { flake8_bugbear::rules::function_uses_loop_variable(self, &Node::Stmt(stmt)); } @@ -1578,14 +1586,14 @@ where pylint::rules::useless_else_on_loop(self, stmt, body, orelse); } } - StmtKind::For(ast::StmtFor { + Stmt::For(ast::StmtFor { target, body, iter, orelse, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { + | Stmt::AsyncFor(ast::StmtAsyncFor { target, body, iter, @@ -1614,7 +1622,7 @@ where if self.settings.rules.enabled(Rule::RedefinedLoopName) { pylint::rules::redefined_loop_name(self, &Node::Stmt(stmt)); } - if matches!(stmt.node, StmtKind::For(_)) { + if matches!(stmt, Stmt::For(_)) { if self.settings.rules.enabled(Rule::ReimplementedBuiltin) { flake8_simplify::rules::convert_for_loop_to_any_all( self, @@ -1627,17 +1635,19 @@ where } } } - StmtKind::Try(ast::StmtTry { + Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, + range: _, }) - | StmtKind::TryStar(ast::StmtTryStar { + | Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, finalbody, + range: _, }) => { if self.settings.rules.enabled(Rule::DefaultExceptNotLast) { if let Some(diagnostic) = @@ -1693,7 +1703,7 @@ where tryceratops::rules::error_instead_of_exception(self, handlers); } } - StmtKind::Assign(ast::StmtAssign { targets, value, .. }) => { + Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { if self.settings.rules.enabled(Rule::LambdaAssignment) { if let [target] = &targets[..] { pycodestyle::rules::lambda_assignment(self, target, value, None, stmt); @@ -1714,7 +1724,7 @@ where if self.settings.rules.enabled(Rule::GlobalStatement) { for target in targets.iter() { - if let ExprKind::Name(ast::ExprName { id, .. }) = &target.node { + if let Expr::Name(ast::ExprName { id, .. }) = target { pylint::rules::global_statement(self, id); } } @@ -1778,7 +1788,7 @@ where } } } - StmtKind::AnnAssign(ast::StmtAnnAssign { + Stmt::AnnAssign(ast::StmtAnnAssign { target, value, annotation, @@ -1828,16 +1838,16 @@ where } } } - StmtKind::Delete(ast::StmtDelete { targets }) => { + Stmt::Delete(ast::StmtDelete { targets, range: _ }) => { if self.settings.rules.enabled(Rule::GlobalStatement) { for target in targets.iter() { - if let ExprKind::Name(ast::ExprName { id, .. }) = &target.node { + if let Expr::Name(ast::ExprName { id, .. }) = target { pylint::rules::global_statement(self, id); } } } } - StmtKind::Expr(ast::StmtExpr { value }) => { + Stmt::Expr(ast::StmtExpr { value, range: _ }) => { if self.settings.rules.enabled(Rule::UselessComparison) { flake8_bugbear::rules::useless_comparison(self, value); } @@ -1859,8 +1869,8 @@ where } // Recurse. - match &stmt.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { + match stmt { + Stmt::FunctionDef(ast::StmtFunctionDef { body, name, args, @@ -1868,7 +1878,7 @@ where returns, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, name, args, @@ -1887,7 +1897,7 @@ where let runtime_annotation = !self.ctx.future_annotations(); for arg in &args.posonlyargs { - if let Some(expr) = &arg.node.annotation { + if let Some(expr) = &arg.annotation { if runtime_annotation { self.visit_type_definition(expr); } else { @@ -1896,7 +1906,7 @@ where } } for arg in &args.args { - if let Some(expr) = &arg.node.annotation { + if let Some(expr) = &arg.annotation { if runtime_annotation { self.visit_type_definition(expr); } else { @@ -1905,7 +1915,7 @@ where } } if let Some(arg) = &args.vararg { - if let Some(expr) = &arg.node.annotation { + if let Some(expr) = &arg.annotation { if runtime_annotation { self.visit_type_definition(expr); } else { @@ -1914,7 +1924,7 @@ where } } for arg in &args.kwonlyargs { - if let Some(expr) = &arg.node.annotation { + if let Some(expr) = &arg.annotation { if runtime_annotation { self.visit_type_definition(expr); } else { @@ -1923,7 +1933,7 @@ where } } if let Some(arg) = &args.kwarg { - if let Some(expr) = &arg.node.annotation { + if let Some(expr) = &arg.annotation { if runtime_annotation { self.visit_type_definition(expr); } else { @@ -1995,18 +2005,19 @@ where body, args, decorator_list, - async_: matches!(stmt.node, StmtKind::AsyncFunctionDef(_)), + async_: matches!(stmt, Stmt::AsyncFunctionDef(_)), globals, })); self.deferred.functions.push(self.ctx.snapshot()); } - StmtKind::ClassDef(ast::StmtClassDef { + Stmt::ClassDef(ast::StmtClassDef { body, name, bases, keywords, decorator_list, + range: _, }) => { for expr in bases { self.visit_expr(expr); @@ -2059,17 +2070,19 @@ where self.visit_body(body); } - StmtKind::Try(ast::StmtTry { + Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, + range: _, }) - | StmtKind::TryStar(ast::StmtTryStar { + | Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, finalbody, + range: _, }) => { let mut handled_exceptions = Exceptions::empty(); for type_ in extract_handled_exceptions(handlers) { @@ -2105,7 +2118,7 @@ where self.visit_body(orelse); self.visit_body(finalbody); } - StmtKind::AnnAssign(ast::StmtAnnAssign { + Stmt::AnnAssign(ast::StmtAnnAssign { target, annotation, value, @@ -2153,18 +2166,32 @@ where } self.visit_expr(target); } - StmtKind::Assert(ast::StmtAssert { test, msg }) => { + Stmt::Assert(ast::StmtAssert { + test, + msg, + range: _, + }) => { self.visit_boolean_test(test); if let Some(expr) = msg { self.visit_expr(expr); } } - StmtKind::While(ast::StmtWhile { test, body, orelse }) => { + Stmt::While(ast::StmtWhile { + test, + body, + orelse, + range: _, + }) => { self.visit_boolean_test(test); self.visit_body(body); self.visit_body(orelse); } - StmtKind::If(ast::StmtIf { test, body, orelse }) => { + Stmt::If(ast::StmtIf { + test, + body, + orelse, + range: _, + }) => { self.visit_boolean_test(test); if flake8_type_checking::helpers::is_type_checking_block(&self.ctx, test) { @@ -2183,12 +2210,12 @@ where }; // Post-visit. - match &stmt.node { - StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_) => { + match stmt { + Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) => { self.ctx.pop_scope(); self.ctx.pop_definition(); } - StmtKind::ClassDef(ast::StmtClassDef { name, .. }) => { + Stmt::ClassDef(ast::StmtClassDef { name, .. }) => { self.ctx.pop_scope(); self.ctx.pop_definition(); self.add_binding( @@ -2225,10 +2252,10 @@ where && self.ctx.in_type_definition() && self.ctx.future_annotations() { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(value), .. - }) = &expr.node + }) = expr { self.deferred.string_type_definitions.push(( expr.range(), @@ -2249,12 +2276,12 @@ where // the node. let flags_snapshot = self.ctx.flags; - // If we're in a boolean test (e.g., the `test` of a `StmtKind::If`), but now within a + // If we're in a boolean test (e.g., the `test` of a `Stmt::If`), but now within a // subexpression (e.g., `a` in `f(a)`), then we're no longer in a boolean test. if !matches!( - expr.node, - ExprKind::BoolOp(_) - | ExprKind::UnaryOp(ast::ExprUnaryOp { + expr, + Expr::BoolOp(_) + | Expr::UnaryOp(ast::ExprUnaryOp { op: Unaryop::Not, .. }) @@ -2263,8 +2290,8 @@ where } // Pre-visit. - match &expr.node { - ExprKind::Subscript(ast::ExprSubscript { value, slice, .. }) => { + match expr { + Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => { // Ex) Optional[...], Union[...] if self.settings.rules.any_enabled(&[ Rule::MissingFutureAnnotationsImport, @@ -2323,8 +2350,16 @@ where flake8_simplify::rules::use_capital_environment_variables(self, expr); } } - ExprKind::Tuple(ast::ExprTuple { elts, ctx }) - | ExprKind::List(ast::ExprList { elts, ctx }) => { + Expr::Tuple(ast::ExprTuple { + elts, + ctx, + range: _, + }) + | Expr::List(ast::ExprList { + elts, + ctx, + range: _, + }) => { if matches!(ctx, ExprContext::Store) { let check_too_many_expressions = self .settings @@ -2344,7 +2379,7 @@ where } } } - ExprKind::Name(ast::ExprName { id, ctx }) => { + Expr::Name(ast::ExprName { id, ctx, range: _ }) => { match ctx { ExprContext::Load => { if self.settings.rules.enabled(Rule::TypingTextStrAlias) { @@ -2431,7 +2466,7 @@ where pylint::rules::load_before_global_declaration(self, id, expr); } } - ExprKind::Attribute(ast::ExprAttribute { attr, value, .. }) => { + Expr::Attribute(ast::ExprAttribute { attr, value, .. }) => { // Ex) typing.List[...] if self.settings.rules.any_enabled(&[ Rule::MissingFutureAnnotationsImport, @@ -2489,10 +2524,11 @@ where } pandas_vet::rules::check_attr(self, attr, value, expr); } - ExprKind::Call(ast::ExprCall { + Expr::Call(ast::ExprCall { func, args, keywords, + range: _, }) => { if self.settings.rules.any_enabled(&[ // pyflakes @@ -2507,13 +2543,12 @@ where // flynt Rule::StaticJoinToFString, ]) { - if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &func.node - { + if let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = func.as_ref() { let attr = attr.as_str(); - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(value), .. - }) = &value.node + }) = value.as_ref() { if attr == "join" { // "...".join(...) call @@ -2948,7 +2983,7 @@ where self, args, func, ); } - if let ExprKind::Name(ast::ExprName { id, ctx }) = &func.node { + if let Expr::Name(ast::ExprName { id, ctx, range: _ }) = func.as_ref() { if id == "locals" && matches!(ctx, ExprContext::Load) { let scope = self.ctx.scope_mut(); scope.uses_locals = true; @@ -3223,7 +3258,11 @@ where flake8_django::rules::locals_in_render_function(self, func, args, keywords); } } - ExprKind::Dict(ast::ExprDict { keys, values }) => { + Expr::Dict(ast::ExprDict { + keys, + values, + range: _, + }) => { if self.settings.rules.any_enabled(&[ Rule::MultiValueRepeatedKeyLiteral, Rule::MultiValueRepeatedKeyVariable, @@ -3235,7 +3274,7 @@ where flake8_pie::rules::unnecessary_spread(self, keys, values); } } - ExprKind::Yield(_) => { + Expr::Yield(_) => { if self.settings.rules.enabled(Rule::YieldOutsideFunction) { pyflakes::rules::yield_outside_function(self, expr); } @@ -3243,7 +3282,7 @@ where pylint::rules::yield_in_init(self, expr); } } - ExprKind::YieldFrom(_) => { + Expr::YieldFrom(_) => { if self.settings.rules.enabled(Rule::YieldOutsideFunction) { pyflakes::rules::yield_outside_function(self, expr); } @@ -3251,7 +3290,7 @@ where pylint::rules::yield_in_init(self, expr); } } - ExprKind::Await(_) => { + Expr::Await(_) => { if self.settings.rules.enabled(Rule::YieldOutsideFunction) { pyflakes::rules::yield_outside_function(self, expr); } @@ -3259,7 +3298,7 @@ where pylint::rules::await_outside_async(self, expr); } } - ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => { + Expr::JoinedStr(ast::ExprJoinedStr { values, range: _ }) => { if self .settings .rules @@ -3271,7 +3310,7 @@ where flake8_bandit::rules::hardcoded_sql_expression(self, expr); } } - ExprKind::BinOp(ast::ExprBinOp { + Expr::BinOp(ast::ExprBinOp { left, op: Operator::RShift, .. @@ -3280,15 +3319,16 @@ where pyflakes::rules::invalid_print_syntax(self, left); } } - ExprKind::BinOp(ast::ExprBinOp { + Expr::BinOp(ast::ExprBinOp { left, op: Operator::Mod, right, + range: _, }) => { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(value), .. - }) = &left.node + }) = left.as_ref() { if self.settings.rules.any_enabled(&[ Rule::PercentFormatInvalidFormat, @@ -3413,7 +3453,7 @@ where } } } - ExprKind::BinOp(ast::ExprBinOp { + Expr::BinOp(ast::ExprBinOp { op: Operator::Add, .. }) => { if self @@ -3436,7 +3476,7 @@ where flake8_bandit::rules::hardcoded_sql_expression(self, expr); } } - ExprKind::BinOp(ast::ExprBinOp { + Expr::BinOp(ast::ExprBinOp { op: Operator::BitOr, .. }) => { @@ -3445,8 +3485,8 @@ where && self.ctx.in_type_definition() && self.ctx.expr_parent().map_or(true, |parent| { !matches!( - parent.node, - ExprKind::BinOp(ast::ExprBinOp { + parent, + Expr::BinOp(ast::ExprBinOp { op: Operator::BitOr, .. }) @@ -3457,14 +3497,18 @@ where } } } - ExprKind::UnaryOp(ast::ExprUnaryOp { op, operand }) => { + Expr::UnaryOp(ast::ExprUnaryOp { + op, + operand, + range: _, + }) => { let check_not_in = self.settings.rules.enabled(Rule::NotInTest); let check_not_is = self.settings.rules.enabled(Rule::NotIsTest); if check_not_in || check_not_is { pycodestyle::rules::not_tests( self, expr, - op, + *op, operand, check_not_in, check_not_is, @@ -3472,23 +3516,24 @@ where } if self.settings.rules.enabled(Rule::UnaryPrefixIncrement) { - flake8_bugbear::rules::unary_prefix_increment(self, expr, op, operand); + flake8_bugbear::rules::unary_prefix_increment(self, expr, *op, operand); } if self.settings.rules.enabled(Rule::NegateEqualOp) { - flake8_simplify::rules::negation_with_equal_op(self, expr, op, operand); + flake8_simplify::rules::negation_with_equal_op(self, expr, *op, operand); } if self.settings.rules.enabled(Rule::NegateNotEqualOp) { - flake8_simplify::rules::negation_with_not_equal_op(self, expr, op, operand); + flake8_simplify::rules::negation_with_not_equal_op(self, expr, *op, operand); } if self.settings.rules.enabled(Rule::DoubleNegation) { - flake8_simplify::rules::double_negation(self, expr, op, operand); + flake8_simplify::rules::double_negation(self, expr, *op, operand); } } - ExprKind::Compare(ast::ExprCompare { + Expr::Compare(ast::ExprCompare { left, ops, comparators, + range: _, }) => { let check_none_comparisons = self.settings.rules.enabled(Rule::NoneComparison); let check_true_false_comparisons = @@ -3583,9 +3628,10 @@ where } } } - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: Constant::Str(value), kind, + range: _, }) => { if self.ctx.in_type_definition() && !self.ctx.in_literal() @@ -3621,9 +3667,15 @@ where pyupgrade::rules::unicode_kind_prefix(self, expr, kind.as_deref()); } } - ExprKind::Lambda(ast::ExprLambda { args, body }) => { + Expr::Lambda( + lambda @ ast::ExprLambda { + args, + body, + range: _, + }, + ) => { if self.settings.rules.enabled(Rule::ReimplementedListBuiltin) { - flake8_pie::rules::reimplemented_list_builtin(self, expr); + flake8_pie::rules::reimplemented_list_builtin(self, lambda); } // Visit the default arguments, but avoid the body, which will be deferred. @@ -3636,7 +3688,12 @@ where self.ctx .push_scope(ScopeKind::Lambda(Lambda { args, body })); } - ExprKind::IfExp(ast::ExprIfExp { test, body, orelse }) => { + Expr::IfExp(ast::ExprIfExp { + test, + body, + orelse, + range: _, + }) => { if self.settings.rules.enabled(Rule::IfExprWithTrueFalse) { flake8_simplify::rules::explicit_true_false_in_ifexpr( self, expr, test, body, orelse, @@ -3651,8 +3708,16 @@ where flake8_simplify::rules::twisted_arms_in_ifexpr(self, expr, test, body, orelse); } } - ExprKind::ListComp(ast::ExprListComp { elt, generators }) - | ExprKind::SetComp(ast::ExprSetComp { elt, generators }) => { + Expr::ListComp(ast::ExprListComp { + elt, + generators, + range: _, + }) + | Expr::SetComp(ast::ExprSetComp { + elt, + generators, + range: _, + }) => { if self.settings.rules.enabled(Rule::UnnecessaryComprehension) { flake8_comprehensions::rules::unnecessary_list_set_comprehension( self, expr, elt, generators, @@ -3663,10 +3728,11 @@ where } self.ctx.push_scope(ScopeKind::Generator); } - ExprKind::DictComp(ast::ExprDictComp { + Expr::DictComp(ast::ExprDictComp { key, value, generators, + range: _, }) => { if self.settings.rules.enabled(Rule::UnnecessaryComprehension) { flake8_comprehensions::rules::unnecessary_dict_comprehension( @@ -3678,15 +3744,19 @@ where } self.ctx.push_scope(ScopeKind::Generator); } - ExprKind::GeneratorExp(_) => { + Expr::GeneratorExp(_) => { if self.settings.rules.enabled(Rule::FunctionUsesLoopVariable) { flake8_bugbear::rules::function_uses_loop_variable(self, &Node::Expr(expr)); } self.ctx.push_scope(ScopeKind::Generator); } - ExprKind::BoolOp(ast::ExprBoolOp { op, values }) => { + Expr::BoolOp(ast::ExprBoolOp { + op, + values, + range: _, + }) => { if self.settings.rules.enabled(Rule::RepeatedIsinstanceCalls) { - pylint::rules::repeated_isinstance_calls(self, expr, op, values); + pylint::rules::repeated_isinstance_calls(self, expr, *op, values); } if self.settings.rules.enabled(Rule::MultipleStartsEndsWith) { flake8_pie::rules::multiple_starts_ends_with(self, expr); @@ -3710,7 +3780,7 @@ where flake8_simplify::rules::expr_and_false(self, expr); } } - ExprKind::FormattedValue(ast::ExprFormattedValue { + Expr::FormattedValue(ast::ExprFormattedValue { value, conversion, .. }) => { if self @@ -3725,19 +3795,25 @@ where }; // Recurse. - match &expr.node { - ExprKind::Lambda(_) => { + match expr { + Expr::Lambda(_) => { self.deferred.lambdas.push((expr, self.ctx.snapshot())); } - ExprKind::IfExp(ast::ExprIfExp { test, body, orelse }) => { + Expr::IfExp(ast::ExprIfExp { + test, + body, + orelse, + range: _, + }) => { self.visit_boolean_test(test); self.visit_expr(body); self.visit_expr(orelse); } - ExprKind::Call(ast::ExprCall { + Expr::Call(ast::ExprCall { func, args, keywords, + range: _, }) => { let callable = self.ctx.resolve_call_path(func).and_then(|call_path| { if self.ctx.match_typing_call_path(&call_path, "cast") { @@ -3799,7 +3875,11 @@ where self.visit_type_definition(expr); } for keyword in keywords { - let KeywordData { arg, value } = &keyword.node; + let Keyword { + arg, + value, + range: _, + } = keyword; if let Some(id) = arg { if id == "bound" { self.visit_type_definition(value); @@ -3814,13 +3894,13 @@ where // Ex) NamedTuple("a", [("a", int)]) if args.len() > 1 { - match &args[1].node { - ExprKind::List(ast::ExprList { elts, .. }) - | ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + match &args[1] { + Expr::List(ast::ExprList { elts, .. }) + | Expr::Tuple(ast::ExprTuple { elts, .. }) => { for elt in elts { - match &elt.node { - ExprKind::List(ast::ExprList { elts, .. }) - | ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + match elt { + Expr::List(ast::ExprList { elts, .. }) + | Expr::Tuple(ast::ExprTuple { elts, .. }) => { if elts.len() == 2 { self.visit_non_type_definition(&elts[0]); self.visit_type_definition(&elts[1]); @@ -3836,7 +3916,7 @@ where // Ex) NamedTuple("a", a=int) for keyword in keywords { - let KeywordData { value, .. } = &keyword.node; + let Keyword { value, .. } = keyword; self.visit_type_definition(value); } } @@ -3845,7 +3925,12 @@ where // Ex) TypedDict("a", {"a": int}) if args.len() > 1 { - if let ExprKind::Dict(ast::ExprDict { keys, values }) = &args[1].node { + if let Expr::Dict(ast::ExprDict { + keys, + values, + range: _, + }) = &args[1] + { for key in keys.iter().flatten() { self.visit_non_type_definition(key); } @@ -3857,7 +3942,7 @@ where // Ex) TypedDict("a", a=int) for keyword in keywords { - let KeywordData { value, .. } = &keyword.node; + let Keyword { value, .. } = keyword; self.visit_type_definition(value); } } @@ -3872,13 +3957,17 @@ where self.visit_non_type_definition(arg); } for keyword in keywords { - let KeywordData { value, .. } = &keyword.node; + let Keyword { value, .. } = keyword; self.visit_non_type_definition(value); } } else { // Ex) DefaultNamedArg(type="bool", name="some_prop_name") for keyword in keywords { - let KeywordData { value, arg } = &keyword.node; + let Keyword { + value, + arg, + range: _, + } = keyword; if arg.as_ref().map_or(false, |arg| arg == "type") { self.visit_type_definition(value); } else { @@ -3896,13 +3985,18 @@ where self.visit_non_type_definition(arg); } for keyword in keywords { - let KeywordData { value, .. } = &keyword.node; + let Keyword { value, .. } = keyword; self.visit_non_type_definition(value); } } } } - ExprKind::Subscript(ast::ExprSubscript { value, slice, ctx }) => { + Expr::Subscript(ast::ExprSubscript { + value, + slice, + ctx, + range: _, + }) => { // Only allow annotations in `ExprContext::Load`. If we have, e.g., // `obj["foo"]["bar"]`, we need to avoid treating the `obj["foo"]` // portion as an annotation, despite having `ExprContext::Load`. Thus, we track @@ -3931,8 +4025,11 @@ where // First argument is a type (including forward references); the // rest are arbitrary Python objects. self.visit_expr(value); - if let ExprKind::Tuple(ast::ExprTuple { elts, ctx }) = - &slice.node + if let Expr::Tuple(ast::ExprTuple { + elts, + ctx, + range: _, + }) = slice.as_ref() { if let Some(expr) = elts.first() { self.visit_expr(expr); @@ -3943,7 +4040,7 @@ where } } else { error!( - "Found non-ExprKind::Tuple argument to PEP 593 \ + "Found non-Expr::Tuple argument to PEP 593 \ Annotation." ); } @@ -3954,7 +4051,7 @@ where } } } - ExprKind::JoinedStr(_) => { + Expr::JoinedStr(_) => { self.ctx.flags |= ContextFlags::F_STRING; visitor::walk_expr(self, expr); } @@ -3962,12 +4059,12 @@ where } // Post-visit. - match &expr.node { - ExprKind::Lambda(_) - | ExprKind::GeneratorExp(_) - | ExprKind::ListComp(_) - | ExprKind::DictComp(_) - | ExprKind::SetComp(_) => { + match expr { + Expr::Lambda(_) + | Expr::GeneratorExp(_) + | Expr::ListComp(_) + | Expr::DictComp(_) + | Expr::SetComp(_) => { self.ctx.pop_scope(); } _ => {} @@ -3993,11 +4090,12 @@ where } fn visit_excepthandler(&mut self, excepthandler: &'b Excepthandler) { - match &excepthandler.node { - ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { + match excepthandler { + ast::Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, name, body, + range: _, }) => { let name = name.as_deref(); if self.settings.rules.enabled(Rule::BareExcept) { @@ -4083,26 +4181,22 @@ where if self.ctx.scope().defines(name) { self.handle_node_store( name, - &Expr::new( - name_range, - ExprKind::Name(ast::ExprName { - id: name.into(), - ctx: ExprContext::Store, - }), - ), + &Expr::Name(ast::ExprName { + id: name.into(), + ctx: ExprContext::Store, + range: name_range, + }), ); } let definition = self.ctx.scope().get(name).copied(); self.handle_node_store( name, - &Expr::new( - name_range, - ExprKind::Name(ast::ExprName { - id: name.into(), - ctx: ExprContext::Store, - }), - ), + &Expr::Name(ast::ExprName { + id: name.into(), + ctx: ExprContext::Store, + range: name_range, + }), ); walk_excepthandler(self, excepthandler); @@ -4143,8 +4237,8 @@ where } fn visit_format_spec(&mut self, format_spec: &'b Expr) { - match &format_spec.node { - ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => { + match format_spec { + Expr::JoinedStr(ast::ExprJoinedStr { values, range: _ }) => { for value in values { self.visit_expr(value); } @@ -4203,7 +4297,7 @@ where // Bind, but intentionally avoid walking the annotation, as we handle it // upstream. self.add_binding( - &arg.node.arg, + &arg.arg, Binding { kind: BindingKind::Argument, runtime_usage: None, @@ -4218,7 +4312,7 @@ where if self.settings.rules.enabled(Rule::AmbiguousVariableName) { if let Some(diagnostic) = - pycodestyle::rules::ambiguous_variable_name(&arg.node.arg, arg.range()) + pycodestyle::rules::ambiguous_variable_name(&arg.arg, arg.range()) { self.diagnostics.push(diagnostic); } @@ -4226,7 +4320,7 @@ where if self.settings.rules.enabled(Rule::InvalidArgumentName) { if let Some(diagnostic) = pep8_naming::rules::invalid_argument_name( - &arg.node.arg, + &arg.arg, arg, &self.settings.pep8_naming.ignore_names, ) { @@ -4235,18 +4329,21 @@ where } if self.settings.rules.enabled(Rule::BuiltinArgumentShadowing) { - flake8_builtins::rules::builtin_argument_shadowing(self, &arg.node.arg, arg); + flake8_builtins::rules::builtin_argument_shadowing(self, &arg.arg, arg); } } fn visit_pattern(&mut self, pattern: &'b Pattern) { - if let PatternKind::MatchAs(ast::PatternMatchAs { + if let Pattern::MatchAs(ast::PatternMatchAs { name: Some(name), .. }) - | PatternKind::MatchStar(ast::PatternMatchStar { name: Some(name) }) - | PatternKind::MatchMapping(ast::PatternMatchMapping { + | Pattern::MatchStar(ast::PatternMatchStar { + name: Some(name), + range: _, + }) + | Pattern::MatchMapping(ast::PatternMatchMapping { rest: Some(name), .. - }) = &pattern.node + }) = pattern { self.add_binding( name, @@ -4406,7 +4503,7 @@ impl<'a> Checker<'a> { ); if let Some(parent) = binding.source { let parent = self.ctx.stmts[parent]; - if matches!(parent.node, StmtKind::ImportFrom(_)) + if matches!(parent, Stmt::ImportFrom(_)) && parent.range().contains_range(binding.range) { diagnostic.set_parent(parent.start()); @@ -4506,7 +4603,7 @@ impl<'a> Checker<'a> { } fn handle_node_load(&mut self, expr: &Expr) { - let ExprKind::Name(ast::ExprName { id, .. } )= &expr.node else { + let Expr::Name(ast::ExprName { id, .. } )= expr else { return; }; let id = id.as_str(); @@ -4704,8 +4801,8 @@ impl<'a> Checker<'a> { } if matches!( - parent.node, - StmtKind::AnnAssign(ast::StmtAnnAssign { value: None, .. }) + parent, + Stmt::AnnAssign(ast::StmtAnnAssign { value: None, .. }) ) { self.add_binding( id, @@ -4723,7 +4820,7 @@ impl<'a> Checker<'a> { return; } - if matches!(parent.node, StmtKind::For(_) | StmtKind::AsyncFor(_)) { + if matches!(parent, Stmt::For(_) | Stmt::AsyncFor(_)) { self.add_binding( id, Binding { @@ -4762,29 +4859,27 @@ impl<'a> Checker<'a> { if id == "__all__" && scope.kind.is_module() && matches!( - parent.node, - StmtKind::Assign(_) | StmtKind::AugAssign(_) | StmtKind::AnnAssign(_) + parent, + Stmt::Assign(_) | Stmt::AugAssign(_) | Stmt::AnnAssign(_) ) { - if match &parent.node { - StmtKind::Assign(ast::StmtAssign { targets, .. }) => { - if let Some(ExprKind::Name(ast::ExprName { id, .. })) = - targets.first().map(|target| &target.node) - { + if match parent { + Stmt::Assign(ast::StmtAssign { targets, .. }) => { + if let Some(Expr::Name(ast::ExprName { id, .. })) = targets.first() { id == "__all__" } else { false } } - StmtKind::AugAssign(ast::StmtAugAssign { target, .. }) => { - if let ExprKind::Name(ast::ExprName { id, .. }) = &target.node { + Stmt::AugAssign(ast::StmtAugAssign { target, .. }) => { + if let Expr::Name(ast::ExprName { id, .. }) = target.as_ref() { id == "__all__" } else { false } } - StmtKind::AnnAssign(ast::StmtAnnAssign { target, .. }) => { - if let ExprKind::Name(ast::ExprName { id, .. }) = &target.node { + Stmt::AnnAssign(ast::StmtAnnAssign { target, .. }) => { + if let Expr::Name(ast::ExprName { id, .. }) = target.as_ref() { id == "__all__" } else { false @@ -4797,7 +4892,7 @@ impl<'a> Checker<'a> { extract_all_names(parent, |name| self.ctx.is_builtin(name)); // Grab the existing bound __all__ values. - if let StmtKind::AugAssign(_) = &parent.node { + if let Stmt::AugAssign(_) = parent { if let Some(index) = scope.get("__all__") { if let BindingKind::Export(Export { names: existing }) = &self.ctx.bindings[*index].kind @@ -4844,7 +4939,7 @@ impl<'a> Checker<'a> { if self .ctx .expr_ancestors() - .any(|expr| matches!(expr.node, ExprKind::NamedExpr(_))) + .any(|expr| matches!(expr, Expr::NamedExpr(_))) { self.add_binding( id, @@ -4878,7 +4973,7 @@ impl<'a> Checker<'a> { } fn handle_node_delete(&mut self, expr: &'a Expr) { - let ExprKind::Name(ast::ExprName { id, .. } )= &expr.node else { + let Expr::Name(ast::ExprName { id, .. } )= expr else { return; }; if helpers::on_conditional_branch(&mut self.ctx.parents()) { @@ -4965,16 +5060,14 @@ impl<'a> Checker<'a> { for snapshot in deferred_functions { self.ctx.restore(snapshot); - match &self.ctx.stmt().node { - StmtKind::FunctionDef(ast::StmtFunctionDef { body, args, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { - body, args, .. - }) => { + match &self.ctx.stmt() { + Stmt::FunctionDef(ast::StmtFunctionDef { body, args, .. }) + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, args, .. }) => { self.visit_arguments(args); self.visit_body(body); } _ => { - unreachable!("Expected StmtKind::FunctionDef | StmtKind::AsyncFunctionDef") + unreachable!("Expected Stmt::FunctionDef | Stmt::AsyncFunctionDef") } } @@ -4989,11 +5082,16 @@ impl<'a> Checker<'a> { for (expr, snapshot) in lambdas { self.ctx.restore(snapshot); - if let ExprKind::Lambda(ast::ExprLambda { args, body }) = &expr.node { + if let Expr::Lambda(ast::ExprLambda { + args, + body, + range: _, + }) = expr + { self.visit_arguments(args); self.visit_expr(body); } else { - unreachable!("Expected ExprKind::Lambda"); + unreachable!("Expected Expr::Lambda"); } self.deferred.assignments.push(snapshot); @@ -5046,15 +5144,14 @@ impl<'a> Checker<'a> { for snapshot in for_loops { self.ctx.restore(snapshot); - if let StmtKind::For(ast::StmtFor { target, body, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { target, body, .. }) = - &self.ctx.stmt().node + if let Stmt::For(ast::StmtFor { target, body, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { target, body, .. }) = &self.ctx.stmt() { if self.settings.rules.enabled(Rule::UnusedLoopControlVariable) { flake8_bugbear::rules::unused_loop_control_variable(self, target, body); } } else { - unreachable!("Expected ExprKind::For | ExprKind::AsyncFor"); + unreachable!("Expected Expr::For | Expr::AsyncFor"); } } } @@ -5084,11 +5181,13 @@ impl<'a> Checker<'a> { // Mark anything referenced in `__all__` as used. let all_bindings: Option<(Vec, TextRange)> = { let global_scope = self.ctx.global_scope(); - let all_names: Option<(&Vec<&str>, TextRange)> = global_scope + let all_names: Option<(&[&str], TextRange)> = global_scope .get("__all__") .map(|index| &self.ctx.bindings[*index]) .and_then(|binding| match &binding.kind { - BindingKind::Export(Export { names }) => Some((names, binding.range)), + BindingKind::Export(Export { names }) => { + Some((names.as_slice(), binding.range)) + } _ => None, }); @@ -5180,11 +5279,11 @@ impl<'a> Checker<'a> { .dedup() .collect(); if !sources.is_empty() { - for &name in names.iter() { + for name in names.iter() { if !scope.defines(name) { diagnostics.push(Diagnostic::new( pyflakes::rules::UndefinedLocalWithImportStarUsage { - name: name.to_string(), + name: (*name).to_string(), sources: sources.clone(), }, *range, @@ -5203,7 +5302,7 @@ impl<'a> Checker<'a> { if binding.kind.is_global() { if let Some(source) = binding.source { let stmt = &self.ctx.stmts[source]; - if matches!(stmt.node, StmtKind::Global(_)) { + if matches!(stmt, Stmt::Global(_)) { diagnostics.push(Diagnostic::new( pylint::rules::GlobalVariableNotAssigned { name: (*name).to_string(), @@ -5267,7 +5366,7 @@ impl<'a> Checker<'a> { ); if let Some(source) = rebound.source { let parent = &self.ctx.stmts[source]; - if matches!(parent.node, StmtKind::ImportFrom(_)) + if matches!(parent, Stmt::ImportFrom(_)) && parent.range().contains_range(rebound.range) { diagnostic.set_parent(parent.start()); @@ -5351,7 +5450,7 @@ impl<'a> Checker<'a> { let exceptions = binding.exceptions; let diagnostic_offset = binding.range.start(); let child = &self.ctx.stmts[child_id]; - let parent_offset = if matches!(child.node, StmtKind::ImportFrom(_)) { + let parent_offset = if matches!(child, Stmt::ImportFrom(_)) { Some(child.start()) } else { None @@ -5427,7 +5526,7 @@ impl<'a> Checker<'a> { }, *range, ); - if matches!(child.node, StmtKind::ImportFrom(_)) { + if matches!(child, Stmt::ImportFrom(_)) { diagnostic.set_parent(child.start()); } @@ -5461,7 +5560,7 @@ impl<'a> Checker<'a> { }, *range, ); - if matches!(child.node, StmtKind::ImportFrom(_)) { + if matches!(child, Stmt::ImportFrom(_)) { diagnostic.set_parent(child.start()); } diagnostics.push(diagnostic); diff --git a/crates/ruff/src/checkers/imports.rs b/crates/ruff/src/checkers/imports.rs index 31a5ff5f1f..979da3e0c3 100644 --- a/crates/ruff/src/checkers/imports.rs +++ b/crates/ruff/src/checkers/imports.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::path::Path; -use rustpython_parser::ast::{self, StmtKind, Suite}; +use rustpython_parser::ast::{self, Ranged, Stmt, Suite}; use ruff_diagnostics::Diagnostic; use ruff_python_ast::helpers::to_module_path; @@ -28,18 +28,19 @@ fn extract_import_map(path: &Path, package: Option<&Path>, blocks: &[&Block]) -> let num_imports = blocks.iter().map(|block| block.imports.len()).sum(); let mut module_imports = Vec::with_capacity(num_imports); for stmt in blocks.iter().flat_map(|block| &block.imports) { - match &stmt.node { - StmtKind::Import(ast::StmtImport { names }) => { + match stmt { + Stmt::Import(ast::StmtImport { names, range: _ }) => { module_imports.extend( names .iter() - .map(|name| ModuleImport::new(name.node.name.to_string(), stmt.range())), + .map(|name| ModuleImport::new(name.name.to_string(), stmt.range())), ); } - StmtKind::ImportFrom(ast::StmtImportFrom { + Stmt::ImportFrom(ast::StmtImportFrom { module, names, level, + range: _, }) => { let level = level.map_or(0, |level| level.to_usize()); let module = if let Some(module) = module { @@ -60,10 +61,10 @@ fn extract_import_map(path: &Path, package: Option<&Path>, blocks: &[&Block]) -> Cow::Owned(module_path[..module_path.len() - level].join(".")) }; module_imports.extend(names.iter().map(|name| { - ModuleImport::new(format!("{}.{}", module, name.node.name), name.range()) + ModuleImport::new(format!("{}.{}", module, name.name), name.range()) })); } - _ => panic!("Expected StmtKind::Import | StmtKind::ImportFrom"), + _ => panic!("Expected Stmt::Import | Stmt::ImportFrom"), } } diff --git a/crates/ruff/src/cst/helpers.rs b/crates/ruff/src/cst/helpers.rs index faa0e34535..c2cc95f79c 100644 --- a/crates/ruff/src/cst/helpers.rs +++ b/crates/ruff/src/cst/helpers.rs @@ -1,7 +1,7 @@ use libcst_native::{Expression, NameOrAttribute}; fn compose_call_path_inner<'a>(expr: &'a Expression, parts: &mut Vec<&'a str>) { - match &expr { + match expr { Expression::Call(expr) => { compose_call_path_inner(&expr.func, parts); } diff --git a/crates/ruff/src/doc_lines.rs b/crates/ruff/src/doc_lines.rs index e506c05e55..38e09c6ea1 100644 --- a/crates/ruff/src/doc_lines.rs +++ b/crates/ruff/src/doc_lines.rs @@ -4,7 +4,7 @@ use std::iter::FusedIterator; use ruff_text_size::{TextRange, TextSize}; -use rustpython_parser::ast::{self, Constant, ExprKind, Stmt, StmtKind, Suite}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged, Stmt, Suite}; use rustpython_parser::lexer::LexResult; use rustpython_parser::Tok; @@ -79,11 +79,11 @@ struct StringLinesVisitor<'a> { impl StatementVisitor<'_> for StringLinesVisitor<'_> { fn visit_stmt(&mut self, stmt: &Stmt) { - if let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node { - if let ExprKind::Constant(ast::ExprConstant { + if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = stmt { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(..), .. - }) = &value.node + }) = value.as_ref() { for line in UniversalNewlineIterator::with_offset( self.locator.slice(value.range()), diff --git a/crates/ruff/src/docstrings/extraction.rs b/crates/ruff/src/docstrings/extraction.rs index f6574de642..aa64249425 100644 --- a/crates/ruff/src/docstrings/extraction.rs +++ b/crates/ruff/src/docstrings/extraction.rs @@ -1,6 +1,6 @@ //! Extract docstrings from an AST. -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Constant, Expr, Stmt}; use ruff_python_semantic::definition::{Definition, DefinitionId, Definitions, Member, MemberKind}; @@ -8,13 +8,13 @@ use ruff_python_semantic::definition::{Definition, DefinitionId, Definitions, Me pub(crate) fn docstring_from(suite: &[Stmt]) -> Option<&Expr> { let stmt = suite.first()?; // Require the docstring to be a standalone expression. - let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node else { + let Stmt::Expr(ast::StmtExpr { value, range: _ }) = stmt else { return None; }; // Only match strings. if !matches!( - &value.node, - ExprKind::Constant(ast::ExprConstant { + value.as_ref(), + Expr::Constant(ast::ExprConstant { value: Constant::Str(_), .. }) @@ -29,10 +29,9 @@ pub(crate) fn extract_docstring<'a>(definition: &'a Definition<'a>) -> Option<&' match definition { Definition::Module(module) => docstring_from(module.python_ast), Definition::Member(member) => { - if let StmtKind::ClassDef(ast::StmtClassDef { body, .. }) - | StmtKind::FunctionDef(ast::StmtFunctionDef { body, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) = - &member.stmt.node + if let Stmt::ClassDef(ast::StmtClassDef { body, .. }) + | Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) = &member.stmt { docstring_from(body) } else { diff --git a/crates/ruff/src/docstrings/mod.rs b/crates/ruff/src/docstrings/mod.rs index e5f8715827..6790264b98 100644 --- a/crates/ruff/src/docstrings/mod.rs +++ b/crates/ruff/src/docstrings/mod.rs @@ -2,7 +2,7 @@ use std::fmt::{Debug, Formatter}; use std::ops::Deref; use ruff_text_size::{TextRange, TextSize}; -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_python_semantic::definition::Definition; @@ -29,15 +29,15 @@ impl<'a> Docstring<'a> { DocstringBody { docstring: self } } - pub(crate) const fn start(&self) -> TextSize { + pub(crate) fn start(&self) -> TextSize { self.expr.start() } - pub(crate) const fn end(&self) -> TextSize { + pub(crate) fn end(&self) -> TextSize { self.expr.end() } - pub(crate) const fn range(&self) -> TextRange { + pub(crate) fn range(&self) -> TextRange { self.expr.range() } diff --git a/crates/ruff/src/importer.rs b/crates/ruff/src/importer.rs index b02c3c7b9f..82d03f71b8 100644 --- a/crates/ruff/src/importer.rs +++ b/crates/ruff/src/importer.rs @@ -3,7 +3,7 @@ use anyhow::Result; use libcst_native::{Codegen, CodegenState, ImportAlias, Name, NameOrAttribute}; use ruff_text_size::TextSize; -use rustpython_parser::ast::{self, Stmt, StmtKind, Suite}; +use rustpython_parser::ast::{self, Ranged, Stmt, Suite}; use rustpython_parser::{lexer, Mode, Tok}; use ruff_diagnostics::Edit; @@ -71,7 +71,7 @@ impl<'a> Importer<'a> { } } - /// Return the top-level [`Stmt`] that imports the given module using `StmtKind::ImportFrom` + /// Return the top-level [`Stmt`] that imports the given module using `Stmt::ImportFrom` /// preceding the given position, if any. pub fn find_import_from(&self, module: &str, at: TextSize) -> Option<&Stmt> { let mut import_from = None; @@ -79,11 +79,11 @@ impl<'a> Importer<'a> { if stmt.start() >= at { break; } - if let StmtKind::ImportFrom(ast::StmtImportFrom { + if let Stmt::ImportFrom(ast::StmtImportFrom { module: name, level, .. - }) = &stmt.node + }) = stmt { if level.map_or(true, |level| level.to_u32() == 0) && name.as_ref().map_or(false, |name| name == module) @@ -95,7 +95,7 @@ impl<'a> Importer<'a> { import_from } - /// Add the given member to an existing `StmtKind::ImportFrom` statement. + /// Add the given member to an existing `Stmt::ImportFrom` statement. pub fn add_member(&self, stmt: &Stmt, member: &str) -> Result { let mut tree = match_module(self.locator.slice(stmt.range()))?; let import_from = match_import_from(&mut tree)?; diff --git a/crates/ruff/src/rules/flake8_2020/rules.rs b/crates/ruff/src/rules/flake8_2020/rules.rs index 40fccf8ead..bd19cccd91 100644 --- a/crates/ruff/src/rules/flake8_2020/rules.rs +++ b/crates/ruff/src/rules/flake8_2020/rules.rs @@ -1,5 +1,5 @@ use num_bigint::BigInt; -use rustpython_parser::ast::{self, Attributed, Cmpop, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Cmpop, Constant, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -123,16 +123,17 @@ fn is_sys(checker: &Checker, expr: &Expr, target: &str) -> bool { /// YTT101, YTT102, YTT301, YTT303 pub(crate) fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) { if is_sys(checker, value, "version") { - match &slice.node { - ExprKind::Slice(ast::ExprSlice { + match slice { + Expr::Slice(ast::ExprSlice { lower: None, upper: Some(upper), step: None, + range: _, }) => { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Int(i), .. - }) = &upper.node + }) = upper.as_ref() { if *i == BigInt::from(1) && checker.settings.rules.enabled(Rule::SysVersionSlice1) @@ -150,7 +151,7 @@ pub(crate) fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) { } } - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: Constant::Int(i), .. }) => { @@ -173,26 +174,22 @@ pub(crate) fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) { /// YTT103, YTT201, YTT203, YTT204, YTT302 pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &[Expr]) { - match &left.node { - ExprKind::Subscript(ast::ExprSubscript { value, slice, .. }) + match left { + Expr::Subscript(ast::ExprSubscript { value, slice, .. }) if is_sys(checker, value, "version_info") => { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Int(i), .. - }) = &slice.node + }) = slice.as_ref() { if *i == BigInt::from(0) { if let ( [Cmpop::Eq | Cmpop::NotEq], - [Attributed { - node: - ExprKind::Constant(ast::ExprConstant { - value: Constant::Int(n), - .. - }), + [Expr::Constant(ast::ExprConstant { + value: Constant::Int(n), .. - }], + })], ) = (ops, comparators) { if *n == BigInt::from(3) @@ -206,14 +203,10 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara } else if *i == BigInt::from(1) { if let ( [Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE], - [Attributed { - node: - ExprKind::Constant(ast::ExprConstant { - value: Constant::Int(_), - .. - }), + [Expr::Constant(ast::ExprConstant { + value: Constant::Int(_), .. - }], + })], ) = (ops, comparators) { if checker.settings.rules.enabled(Rule::SysVersionInfo1CmpInt) { @@ -226,19 +219,15 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara } } - ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) + Expr::Attribute(ast::ExprAttribute { value, attr, .. }) if is_sys(checker, value, "version_info") && attr == "minor" => { if let ( [Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE], - [Attributed { - node: - ExprKind::Constant(ast::ExprConstant { - value: Constant::Int(_), - .. - }), + [Expr::Constant(ast::ExprConstant { + value: Constant::Int(_), .. - }], + })], ) = (ops, comparators) { if checker @@ -259,14 +248,10 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara if is_sys(checker, left, "version") { if let ( [Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE], - [Attributed { - node: - ExprKind::Constant(ast::ExprConstant { - value: Constant::Str(s), - .. - }), + [Expr::Constant(ast::ExprConstant { + value: Constant::Str(s), .. - }], + })], ) = (ops, comparators) { if s.len() == 1 { diff --git a/crates/ruff/src/rules/flake8_annotations/fixes.rs b/crates/ruff/src/rules/flake8_annotations/fixes.rs index e0630fb127..414783482f 100644 --- a/crates/ruff/src/rules/flake8_annotations/fixes.rs +++ b/crates/ruff/src/rules/flake8_annotations/fixes.rs @@ -1,5 +1,5 @@ use anyhow::{bail, Result}; -use rustpython_parser::ast::Stmt; +use rustpython_parser::ast::{Ranged, Stmt}; use rustpython_parser::{lexer, Mode, Tok}; use ruff_diagnostics::Edit; diff --git a/crates/ruff/src/rules/flake8_annotations/helpers.rs b/crates/ruff/src/rules/flake8_annotations/helpers.rs index 6bf9b092d3..6abc9efd4c 100644 --- a/crates/ruff/src/rules/flake8_annotations/helpers.rs +++ b/crates/ruff/src/rules/flake8_annotations/helpers.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Arguments, Expr, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Arguments, Expr, Stmt}; use ruff_python_ast::cast; use ruff_python_semantic::analyze::visibility; @@ -8,9 +8,9 @@ use crate::checkers::ast::Checker; pub(super) fn match_function_def( stmt: &Stmt, -) -> (&str, &Arguments, Option<&Expr>, &Vec, &Vec) { - match &stmt.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { +) -> (&str, &Arguments, Option<&Expr>, &[Stmt], &[Expr]) { + match stmt { + Stmt::FunctionDef(ast::StmtFunctionDef { name, args, returns, @@ -18,7 +18,7 @@ pub(super) fn match_function_def( decorator_list, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, args, returns, diff --git a/crates/ruff/src/rules/flake8_annotations/rules.rs b/crates/ruff/src/rules/flake8_annotations/rules.rs index 52334fdd21..93a43f858e 100644 --- a/crates/ruff/src/rules/flake8_annotations/rules.rs +++ b/crates/ruff/src/rules/flake8_annotations/rules.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, ExprKind, Stmt}; +use rustpython_parser::ast::{Expr, Ranged, Stmt}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -419,8 +419,8 @@ fn is_none_returning(body: &[Stmt]) -> bool { visitor.visit_body(body); for expr in visitor.returns.into_iter().flatten() { if !matches!( - expr.node, - ExprKind::Constant(ref constant) if constant.value.is_none() + expr, + Expr::Constant(ref constant) if constant.value.is_none() ) { return false; } @@ -495,20 +495,20 @@ pub(crate) fn definition( ) { // ANN401 for dynamically typed arguments - if let Some(annotation) = &arg.node.annotation { + if let Some(annotation) = &arg.annotation { has_any_typed_arg = true; if checker.settings.rules.enabled(Rule::AnyType) { check_dynamically_typed( checker, annotation, - || arg.node.arg.to_string(), + || arg.arg.to_string(), &mut diagnostics, is_overridden, ); } } else { if !(checker.settings.flake8_annotations.suppress_dummy_args - && checker.settings.dummy_variable_rgx.is_match(&arg.node.arg)) + && checker.settings.dummy_variable_rgx.is_match(&arg.arg)) { if checker .settings @@ -517,7 +517,7 @@ pub(crate) fn definition( { diagnostics.push(Diagnostic::new( MissingTypeFunctionArgument { - name: arg.node.arg.to_string(), + name: arg.arg.to_string(), }, arg.range(), )); @@ -528,11 +528,11 @@ pub(crate) fn definition( // ANN002, ANN401 if let Some(arg) = &args.vararg { - if let Some(expr) = &arg.node.annotation { + if let Some(expr) = &arg.annotation { has_any_typed_arg = true; if !checker.settings.flake8_annotations.allow_star_arg_any { if checker.settings.rules.enabled(Rule::AnyType) { - let name = &arg.node.arg; + let name = &arg.arg; check_dynamically_typed( checker, expr, @@ -544,12 +544,12 @@ pub(crate) fn definition( } } else { if !(checker.settings.flake8_annotations.suppress_dummy_args - && checker.settings.dummy_variable_rgx.is_match(&arg.node.arg)) + && checker.settings.dummy_variable_rgx.is_match(&arg.arg)) { if checker.settings.rules.enabled(Rule::MissingTypeArgs) { diagnostics.push(Diagnostic::new( MissingTypeArgs { - name: arg.node.arg.to_string(), + name: arg.arg.to_string(), }, arg.range(), )); @@ -560,11 +560,11 @@ pub(crate) fn definition( // ANN003, ANN401 if let Some(arg) = &args.kwarg { - if let Some(expr) = &arg.node.annotation { + if let Some(expr) = &arg.annotation { has_any_typed_arg = true; if !checker.settings.flake8_annotations.allow_star_arg_any { if checker.settings.rules.enabled(Rule::AnyType) { - let name = &arg.node.arg; + let name = &arg.arg; check_dynamically_typed( checker, expr, @@ -576,12 +576,12 @@ pub(crate) fn definition( } } else { if !(checker.settings.flake8_annotations.suppress_dummy_args - && checker.settings.dummy_variable_rgx.is_match(&arg.node.arg)) + && checker.settings.dummy_variable_rgx.is_match(&arg.arg)) { if checker.settings.rules.enabled(Rule::MissingTypeKwargs) { diagnostics.push(Diagnostic::new( MissingTypeKwargs { - name: arg.node.arg.to_string(), + name: arg.arg.to_string(), }, arg.range(), )); @@ -593,12 +593,12 @@ pub(crate) fn definition( // ANN101, ANN102 if is_method && !visibility::is_staticmethod(&checker.ctx, cast::decorator_list(stmt)) { if let Some(arg) = args.posonlyargs.first().or_else(|| args.args.first()) { - if arg.node.annotation.is_none() { + if arg.annotation.is_none() { if visibility::is_classmethod(&checker.ctx, cast::decorator_list(stmt)) { if checker.settings.rules.enabled(Rule::MissingTypeCls) { diagnostics.push(Diagnostic::new( MissingTypeCls { - name: arg.node.arg.to_string(), + name: arg.arg.to_string(), }, arg.range(), )); @@ -607,7 +607,7 @@ pub(crate) fn definition( if checker.settings.rules.enabled(Rule::MissingTypeSelf) { diagnostics.push(Diagnostic::new( MissingTypeSelf { - name: arg.node.arg.to_string(), + name: arg.arg.to_string(), }, arg.range(), )); diff --git a/crates/ruff/src/rules/flake8_async/rules.rs b/crates/ruff/src/rules/flake8_async/rules.rs index 2cc748974e..69abff7291 100644 --- a/crates/ruff/src/rules/flake8_async/rules.rs +++ b/crates/ruff/src/rules/flake8_async/rules.rs @@ -1,5 +1,5 @@ use rustpython_parser::ast; -use rustpython_parser::ast::{Expr, ExprKind}; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -67,12 +67,13 @@ const BLOCKING_HTTP_CALLS: &[&[&str]] = &[ /// ASYNC100 pub(crate) fn blocking_http_call(checker: &mut Checker, expr: &Expr) { if in_async_function(&checker.ctx) { - if let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node { + if let Expr::Call(ast::ExprCall { func, .. }) = expr { if let Some(call_path) = checker.ctx.resolve_call_path(func) { if BLOCKING_HTTP_CALLS.contains(&call_path.as_slice()) { - checker - .diagnostics - .push(Diagnostic::new(BlockingHttpCallInAsyncFunction, func.range)); + checker.diagnostics.push(Diagnostic::new( + BlockingHttpCallInAsyncFunction, + func.range(), + )); } } } @@ -133,12 +134,12 @@ const OPEN_SLEEP_OR_SUBPROCESS_CALL: &[&[&str]] = &[ /// ASYNC101 pub(crate) fn open_sleep_or_subprocess_call(checker: &mut Checker, expr: &Expr) { if in_async_function(&checker.ctx) { - if let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node { + if let Expr::Call(ast::ExprCall { func, .. }) = expr { if let Some(call_path) = checker.ctx.resolve_call_path(func) { if OPEN_SLEEP_OR_SUBPROCESS_CALL.contains(&call_path.as_slice()) { checker.diagnostics.push(Diagnostic::new( OpenSleepOrSubprocessInAsyncFunction, - func.range, + func.range(), )); } } @@ -197,12 +198,12 @@ const UNSAFE_OS_METHODS: &[&[&str]] = &[ /// ASYNC102 pub(crate) fn blocking_os_call(checker: &mut Checker, expr: &Expr) { if in_async_function(&checker.ctx) { - if let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node { + if let Expr::Call(ast::ExprCall { func, .. }) = expr { if let Some(call_path) = checker.ctx.resolve_call_path(func) { if UNSAFE_OS_METHODS.contains(&call_path.as_slice()) { checker .diagnostics - .push(Diagnostic::new(BlockingOsCallInAsyncFunction, func.range)); + .push(Diagnostic::new(BlockingOsCallInAsyncFunction, func.range())); } } } diff --git a/crates/ruff/src/rules/flake8_bandit/helpers.rs b/crates/ruff/src/rules/flake8_bandit/helpers.rs index be617427f0..3158586e6b 100644 --- a/crates/ruff/src/rules/flake8_bandit/helpers.rs +++ b/crates/ruff/src/rules/flake8_bandit/helpers.rs @@ -1,6 +1,6 @@ use once_cell::sync::Lazy; use regex::Regex; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Constant, Expr}; use crate::checkers::ast::Checker; @@ -9,8 +9,8 @@ static PASSWORD_CANDIDATE_REGEX: Lazy = Lazy::new(|| { }); pub(crate) fn string_literal(expr: &Expr) -> Option<&str> { - match &expr.node { - ExprKind::Constant(ast::ExprConstant { + match expr { + Expr::Constant(ast::ExprConstant { value: Constant::Str(string), .. }) => Some(string), @@ -24,7 +24,7 @@ pub(crate) fn matches_password_name(string: &str) -> bool { pub(crate) fn is_untyped_exception(type_: Option<&Expr>, checker: &Checker) -> bool { type_.map_or(true, |type_| { - if let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &type_.node { + if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &type_ { elts.iter().any(|type_| { checker .ctx diff --git a/crates/ruff/src/rules/flake8_bandit/rules/assert_used.rs b/crates/ruff/src/rules/flake8_bandit/rules/assert_used.rs index bb6de4211a..28fba960c0 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/assert_used.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/assert_used.rs @@ -1,5 +1,5 @@ use ruff_text_size::{TextLen, TextRange}; -use rustpython_parser::ast::Stmt; +use rustpython_parser::ast::{Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/flake8_bandit/rules/bad_file_permissions.rs b/crates/ruff/src/rules/flake8_bandit/rules/bad_file_permissions.rs index ac353f986a..95e0d89807 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/bad_file_permissions.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/bad_file_permissions.rs @@ -1,7 +1,7 @@ use num_traits::ToPrimitive; use once_cell::sync::Lazy; use rustc_hash::FxHashMap; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword, Operator}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Operator, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -69,15 +69,20 @@ static PYSTAT_MAPPING: Lazy> = Lazy::new(|| { }); fn get_int_value(expr: &Expr) -> Option { - match &expr.node { - ExprKind::Constant(ast::ExprConstant { + match expr { + Expr::Constant(ast::ExprConstant { value: Constant::Int(value), .. }) => value.to_u16(), - ExprKind::Attribute(_) => { + Expr::Attribute(_) => { compose_call_path(expr).and_then(|path| PYSTAT_MAPPING.get(path.as_str()).copied()) } - ExprKind::BinOp(ast::ExprBinOp { left, op, right }) => { + Expr::BinOp(ast::ExprBinOp { + left, + op, + right, + range: _, + }) => { if let (Some(left_value), Some(right_value)) = (get_int_value(left), get_int_value(right)) { diff --git a/crates/ruff/src/rules/flake8_bandit/rules/exec_used.rs b/crates/ruff/src/rules/flake8_bandit/rules/exec_used.rs index dad79d7eda..3ff3db8ded 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/exec_used.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/exec_used.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -15,7 +15,7 @@ impl Violation for ExecBuiltin { /// S102 pub(crate) fn exec_used(expr: &Expr, func: &Expr) -> Option { - let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else { + let Expr::Name(ast::ExprName { id, .. }) = func else { return None; }; if id != "exec" { diff --git a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_password_default.rs b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_password_default.rs index e687306831..0f61c414df 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_password_default.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_password_default.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Arg, Arguments, Expr}; +use rustpython_parser::ast::{Arg, Arguments, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -23,7 +23,7 @@ impl Violation for HardcodedPasswordDefault { fn check_password_kwarg(arg: &Arg, default: &Expr) -> Option { string_literal(default).filter(|string| !string.is_empty())?; - let kwarg_name = &arg.node.arg; + let kwarg_name = &arg.arg; if !matches_password_name(kwarg_name) { return None; } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_password_func_arg.rs b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_password_func_arg.rs index 4f4b51b3ff..b98b5e5efa 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_password_func_arg.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_password_func_arg.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Keyword; +use rustpython_parser::ast::{Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -26,8 +26,8 @@ pub(crate) fn hardcoded_password_func_arg(keywords: &[Keyword]) -> Vec Option<&str> { - let target_name = match &target.node { + let target_name = match target { // variable = "s3cr3t" - ExprKind::Name(ast::ExprName { id, .. }) => id.as_str(), + Expr::Name(ast::ExprName { id, .. }) => id.as_str(), // d["password"] = "s3cr3t" - ExprKind::Subscript(ast::ExprSubscript { slice, .. }) => match &slice.node { - ExprKind::Constant(ast::ExprConstant { + Expr::Subscript(ast::ExprSubscript { slice, .. }) => match slice.as_ref() { + Expr::Constant(ast::ExprConstant { value: Constant::Str(string), .. }) => string, _ => return None, }, // obj.password = "s3cr3t" - ExprKind::Attribute(ast::ExprAttribute { attr, .. }) => attr, + Expr::Attribute(ast::ExprAttribute { attr, .. }) => attr, _ => return None, }; diff --git a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_sql_expression.rs b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_sql_expression.rs index 112860e3fa..66ebe96ece 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_sql_expression.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_sql_expression.rs @@ -1,6 +1,6 @@ use once_cell::sync::Lazy; use regex::Regex; -use rustpython_parser::ast::{self, Expr, ExprKind, Operator}; +use rustpython_parser::ast::{self, Expr, Operator, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -53,10 +53,10 @@ fn matches_sql_statement(string: &str) -> bool { } fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Option { - match &expr.node { + match expr { // "select * from table where val = " + "str" + ... // "select * from table where val = %s" % ... - ExprKind::BinOp(ast::ExprBinOp { + Expr::BinOp(ast::ExprBinOp { op: Operator::Add | Operator::Mod, .. }) => { @@ -67,7 +67,7 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio return None; }; // Only evaluate the full BinOp, not the nested components. - let ExprKind::BinOp(_ )= &parent.node else { + let Expr::BinOp(_ )= parent else { if any_over_expr(expr, &has_string_literal) { return Some(unparse_expr(expr, checker.stylist)); } @@ -75,8 +75,8 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio }; None } - ExprKind::Call(ast::ExprCall { func, .. }) => { - let ExprKind::Attribute(ast::ExprAttribute { attr, value, .. }) = &func.node else { + Expr::Call(ast::ExprCall { func, .. }) => { + let Expr::Attribute(ast::ExprAttribute { attr, value, .. }) = func.as_ref() else { return None; }; // "select * from table where val = {}".format(...) @@ -86,7 +86,7 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio None } // f"select * from table where val = {val}" - ExprKind::JoinedStr(_) => Some(unparse_expr(expr, checker.stylist)), + Expr::JoinedStr(_) => Some(unparse_expr(expr, checker.stylist)), _ => None, } } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_tmp_directory.rs b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_tmp_directory.rs index ad7dfd12b2..8c27763f80 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_tmp_directory.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_tmp_directory.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/flake8_bandit/rules/hashlib_insecure_hash_functions.rs b/crates/ruff/src/rules/flake8_bandit/rules/hashlib_insecure_hash_functions.rs index 7af865a770..ff6dcd88a9 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/hashlib_insecure_hash_functions.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/hashlib_insecure_hash_functions.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -26,8 +26,8 @@ const WEAK_HASHES: [&str; 4] = ["md4", "md5", "sha", "sha1"]; fn is_used_for_security(call_args: &SimpleCallArgs) -> bool { match call_args.keyword_argument("usedforsecurity") { Some(expr) => !matches!( - &expr.node, - ExprKind::Constant(ast::ExprConstant { + expr, + Expr::Constant(ast::ExprConstant { value: Constant::Bool(false), .. }) diff --git a/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs b/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs index e0ab2d75b4..2855cd5022 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -46,13 +46,13 @@ pub(crate) fn jinja2_autoescape_false( let call_args = SimpleCallArgs::new(args, keywords); if let Some(autoescape_arg) = call_args.keyword_argument("autoescape") { - match &autoescape_arg.node { - ExprKind::Constant(ast::ExprConstant { + match autoescape_arg { + Expr::Constant(ast::ExprConstant { value: Constant::Bool(true), .. }) => (), - ExprKind::Call(ast::ExprCall { func, .. }) => { - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { + Expr::Call(ast::ExprCall { func, .. }) => { + if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { if id != "select_autoescape" { checker.diagnostics.push(Diagnostic::new( Jinja2AutoescapeFalse { value: true }, diff --git a/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs b/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs index 697d7ebca6..762e6093f9 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs b/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs index 2dc6b51148..9870928984 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -56,10 +56,10 @@ pub(crate) fn request_with_no_cert_validation( }) { let call_args = SimpleCallArgs::new(args, keywords); if let Some(verify_arg) = call_args.keyword_argument("verify") { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Bool(false), .. - }) = &verify_arg.node + }) = &verify_arg { checker.diagnostics.push(Diagnostic::new( RequestWithNoCertValidation { diff --git a/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs b/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs index a0fe4f8398..2c12c79e33 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -44,8 +44,8 @@ pub(crate) fn request_without_timeout( { let call_args = SimpleCallArgs::new(args, keywords); if let Some(timeout_arg) = call_args.keyword_argument("timeout") { - if let Some(timeout) = match &timeout_arg.node { - ExprKind::Constant(ast::ExprConstant { + if let Some(timeout) = match timeout_arg { + Expr::Constant(ast::ExprConstant { value: value @ Constant::None, .. }) => Some(unparse_constant(value, checker.stylist)), diff --git a/crates/ruff/src/rules/flake8_bandit/rules/shell_injection.rs b/crates/ruff/src/rules/flake8_bandit/rules/shell_injection.rs index 324f938e99..b571173c19 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/shell_injection.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/shell_injection.rs @@ -2,7 +2,7 @@ use once_cell::sync::Lazy; use regex::Regex; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -141,15 +141,9 @@ struct ShellKeyword<'a> { fn find_shell_keyword<'a>(ctx: &Context, keywords: &'a [Keyword]) -> Option> { keywords .iter() - .find(|keyword| { - keyword - .node - .arg - .as_ref() - .map_or(false, |arg| arg == "shell") - }) + .find(|keyword| keyword.arg.as_ref().map_or(false, |arg| arg == "shell")) .map(|keyword| ShellKeyword { - truthiness: Truthiness::from_expr(&keyword.node.value, |id| ctx.is_builtin(id)), + truthiness: Truthiness::from_expr(&keyword.value, |id| ctx.is_builtin(id)), keyword, }) } @@ -158,8 +152,8 @@ fn find_shell_keyword<'a>(ctx: &Context, keywords: &'a [Keyword]) -> Option bool { matches!( - arg.node, - ExprKind::Constant(ast::ExprConstant { + arg, + Expr::Constant(ast::ExprConstant { value: Constant::Str(_), .. }) @@ -168,8 +162,8 @@ fn shell_call_seems_safe(arg: &Expr) -> bool { /// Return the [`Expr`] as a string literal, if it's a string or a list of strings. fn try_string_literal(expr: &Expr) -> Option<&str> { - match &expr.node { - ExprKind::List(ast::ExprList { elts, .. }) => { + match expr { + Expr::List(ast::ExprList { elts, .. }) => { if elts.is_empty() { None } else { diff --git a/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs b/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs index 0e11699f7b..2add3b236f 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs @@ -1,5 +1,5 @@ use num_traits::{One, Zero}; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -33,10 +33,10 @@ pub(crate) fn snmp_insecure_version( { let call_args = SimpleCallArgs::new(args, keywords); if let Some(mp_model_arg) = call_args.keyword_argument("mpModel") { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Int(value), .. - }) = &mp_model_arg.node + }) = &mp_model_arg { if value.is_zero() || value.is_one() { checker diff --git a/crates/ruff/src/rules/flake8_bandit/rules/snmp_weak_cryptography.rs b/crates/ruff/src/rules/flake8_bandit/rules/snmp_weak_cryptography.rs index 02ddfeffd0..68d6e09d1a 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/snmp_weak_cryptography.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/snmp_weak_cryptography.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/flake8_bandit/rules/suspicious_function_call.rs b/crates/ruff/src/rules/flake8_bandit/rules/suspicious_function_call.rs index 644b7e1957..c0eb38e09a 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/suspicious_function_call.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/suspicious_function_call.rs @@ -1,7 +1,7 @@ //! Check for calls to suspicious functions, or calls into suspicious modules. //! //! See: -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, DiagnosticKind, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -466,7 +466,7 @@ const SUSPICIOUS_MODULES: &[SuspiciousModule] = &[ /// S001 pub(crate) fn suspicious_function_call(checker: &mut Checker, expr: &Expr) { - let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node else { + let Expr::Call(ast::ExprCall { func, .. }) = expr else { return; }; diff --git a/crates/ruff/src/rules/flake8_bandit/rules/try_except_continue.rs b/crates/ruff/src/rules/flake8_bandit/rules/try_except_continue.rs index 274e7509ac..4dd0c0b4a7 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/try_except_continue.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/try_except_continue.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Excepthandler, Expr, Stmt, StmtKind}; +use rustpython_parser::ast::{Excepthandler, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -26,7 +26,7 @@ pub(crate) fn try_except_continue( check_typed_exception: bool, ) { if body.len() == 1 - && body[0].node == StmtKind::Continue + && body[0].is_continue_stmt() && (check_typed_exception || is_untyped_exception(type_, checker)) { checker diff --git a/crates/ruff/src/rules/flake8_bandit/rules/try_except_pass.rs b/crates/ruff/src/rules/flake8_bandit/rules/try_except_pass.rs index e56cdf07e5..429f363858 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/try_except_pass.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/try_except_pass.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Excepthandler, Expr, Stmt, StmtKind}; +use rustpython_parser::ast::{Excepthandler, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -26,7 +26,7 @@ pub(crate) fn try_except_pass( check_typed_exception: bool, ) { if body.len() == 1 - && body[0].node == StmtKind::Pass + && body[0].is_pass_stmt() && (check_typed_exception || is_untyped_exception(type_, checker)) { checker diff --git a/crates/ruff/src/rules/flake8_bandit/rules/unsafe_yaml_load.rs b/crates/ruff/src/rules/flake8_bandit/rules/unsafe_yaml_load.rs index d6f2214d5d..f25b242026 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/unsafe_yaml_load.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/unsafe_yaml_load.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -52,9 +52,9 @@ pub(crate) fn unsafe_yaml_load( || call_path.as_slice() == ["yaml", "CSafeLoader"] }) { - let loader = match &loader_arg.node { - ExprKind::Attribute(ast::ExprAttribute { attr, .. }) => Some(attr.to_string()), - ExprKind::Name(ast::ExprName { id, .. }) => Some(id.to_string()), + let loader = match loader_arg { + Expr::Attribute(ast::ExprAttribute { attr, .. }) => Some(attr.to_string()), + Expr::Name(ast::ExprName { id, .. }) => Some(id.to_string()), _ => None, }; checker.diagnostics.push(Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_blind_except/rules.rs b/crates/ruff/src/rules/flake8_blind_except/rules.rs index 49a3671a84..6837e1d3c5 100644 --- a/crates/ruff/src/rules/flake8_blind_except/rules.rs +++ b/crates/ruff/src/rules/flake8_blind_except/rules.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -30,16 +30,16 @@ pub(crate) fn blind_except( let Some(type_) = type_ else { return; }; - let ExprKind::Name(ast::ExprName { id, .. }) = &type_.node else { + let Expr::Name(ast::ExprName { id, .. }) = &type_ else { return; }; for exception in ["BaseException", "Exception"] { if id == exception && checker.ctx.is_builtin(exception) { // If the exception is re-raised, don't flag an error. if body.iter().any(|stmt| { - if let StmtKind::Raise(ast::StmtRaise { exc, .. }) = &stmt.node { + if let Stmt::Raise(ast::StmtRaise { exc, .. }) = stmt { if let Some(exc) = exc { - if let ExprKind::Name(ast::ExprName { id, .. }) = &exc.node { + if let Expr::Name(ast::ExprName { id, .. }) = exc.as_ref() { name.map_or(false, |name| id == name) } else { false @@ -56,17 +56,17 @@ pub(crate) fn blind_except( // If the exception is logged, don't flag an error. if body.iter().any(|stmt| { - if let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node { - if let ExprKind::Call(ast::ExprCall { func, keywords, .. }) = &value.node { + if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = stmt { + if let Expr::Call(ast::ExprCall { func, keywords, .. }) = value.as_ref() { if logging::is_logger_candidate(&checker.ctx, func) { - if let Some(attribute) = func.node.as_attribute_expr() { + if let Some(attribute) = func.as_attribute_expr() { let attr = attribute.attr.as_str(); if attr == "exception" { return true; } if attr == "error" { if let Some(keyword) = find_keyword(keywords, "exc_info") { - if is_const_true(&keyword.node.value) { + if is_const_true(&keyword.value) { return true; } } diff --git a/crates/ruff/src/rules/flake8_boolean_trap/rules.rs b/crates/ruff/src/rules/flake8_boolean_trap/rules.rs index 050c37800b..d8096410df 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/rules.rs +++ b/crates/ruff/src/rules/flake8_boolean_trap/rules.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Arguments, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Arguments, Constant, Expr, Ranged}; use ruff_diagnostics::Violation; use ruff_diagnostics::{Diagnostic, DiagnosticKind}; @@ -71,11 +71,11 @@ const FUNC_DEF_NAME_ALLOWLIST: &[&str] = &["__setitem__"]; /// `true`, the function name must be explicitly allowed, and the argument must /// be either the first or second argument in the call. fn allow_boolean_trap(func: &Expr) -> bool { - if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node { + if let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func { return FUNC_CALL_NAME_ALLOWLIST.contains(&attr.as_ref()); } - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { + if let Expr::Name(ast::ExprName { id, .. }) = func { return FUNC_CALL_NAME_ALLOWLIST.contains(&id.as_ref()); } @@ -84,8 +84,8 @@ fn allow_boolean_trap(func: &Expr) -> bool { const fn is_boolean_arg(arg: &Expr) -> bool { matches!( - &arg.node, - ExprKind::Constant(ast::ExprConstant { + &arg, + Expr::Constant(ast::ExprConstant { value: Constant::Bool(_), .. }) @@ -115,17 +115,17 @@ pub(crate) fn check_positional_boolean_in_def( } for arg in arguments.posonlyargs.iter().chain(arguments.args.iter()) { - if arg.node.annotation.is_none() { + if arg.annotation.is_none() { continue; } - let Some(expr) = &arg.node.annotation else { + let Some(expr) = &arg.annotation else { continue; }; // check for both bool (python class) and 'bool' (string annotation) - let hint = match &expr.node { - ExprKind::Name(name) => &name.id == "bool", - ExprKind::Constant(ast::ExprConstant { + let hint = match expr.as_ref() { + Expr::Name(name) => &name.id == "bool", + Expr::Constant(ast::ExprConstant { value: Constant::Str(value), .. }) => value == "bool", diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs b/crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs index d54ae2265f..fcc849b2b6 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -37,13 +37,9 @@ impl Violation for EmptyMethodWithoutAbstractDecorator { fn is_abc_class(context: &Context, bases: &[Expr], keywords: &[Keyword]) -> bool { keywords.iter().any(|keyword| { - keyword - .node - .arg - .as_ref() - .map_or(false, |arg| arg == "metaclass") + keyword.arg.as_ref().map_or(false, |arg| arg == "metaclass") && context - .resolve_call_path(&keyword.node.value) + .resolve_call_path(&keyword.value) .map_or(false, |call_path| { call_path.as_slice() == ["abc", "ABCMeta"] }) @@ -55,10 +51,13 @@ fn is_abc_class(context: &Context, bases: &[Expr], keywords: &[Keyword]) -> bool } fn is_empty_body(body: &[Stmt]) -> bool { - body.iter().all(|stmt| match &stmt.node { - StmtKind::Pass => true, - StmtKind::Expr(ast::StmtExpr { value }) => match &value.node { - ExprKind::Constant(ast::ExprConstant { value, .. }) => { + body.iter().all(|stmt| match stmt { + Stmt::Pass(_) => true, + Stmt::Expr(ast::StmtExpr { + value, + range: _range, + }) => match value.as_ref() { + Expr::Constant(ast::ExprConstant { value, .. }) => { matches!(value, Constant::Str(..) | Constant::Ellipsis) } _ => false, @@ -88,24 +87,24 @@ pub(crate) fn abstract_base_class( for stmt in body { // https://github.com/PyCQA/flake8-bugbear/issues/293 // Ignore abc's that declares a class attribute that must be set - if let StmtKind::AnnAssign(_) | StmtKind::Assign(_) = &stmt.node { + if let Stmt::AnnAssign(_) | Stmt::Assign(_) = stmt { has_abstract_method = true; continue; } let ( - StmtKind::FunctionDef(ast::StmtFunctionDef { + Stmt::FunctionDef(ast::StmtFunctionDef { decorator_list, body, name: method_name, .. - }) | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { + }) | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { decorator_list, body, name: method_name, .. }) - ) = &stmt.node else { + ) = stmt else { continue; }; diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/assert_false.rs b/crates/ruff/src/rules/flake8_bugbear/rules/assert_false.rs index 2352418ad1..68e11a885f 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/assert_false.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/assert_false.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Ranged, Stmt}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -23,38 +23,32 @@ impl AlwaysAutofixableViolation for AssertFalse { } fn assertion_error(msg: Option<&Expr>) -> Stmt { - Stmt::new( - TextRange::default(), - StmtKind::Raise(ast::StmtRaise { - exc: Some(Box::new(Expr::new( - TextRange::default(), - ExprKind::Call(ast::ExprCall { - func: Box::new(Expr::new( - TextRange::default(), - ExprKind::Name(ast::ExprName { - id: "AssertionError".into(), - ctx: ExprContext::Load, - }), - )), - args: if let Some(msg) = msg { - vec![msg.clone()] - } else { - vec![] - }, - keywords: vec![], - }), - ))), - cause: None, - }), - ) + Stmt::Raise(ast::StmtRaise { + range: TextRange::default(), + exc: Some(Box::new(Expr::Call(ast::ExprCall { + func: Box::new(Expr::Name(ast::ExprName { + id: "AssertionError".into(), + ctx: ExprContext::Load, + range: TextRange::default(), + })), + args: if let Some(msg) = msg { + vec![msg.clone()] + } else { + vec![] + }, + keywords: vec![], + range: TextRange::default(), + }))), + cause: None, + }) } /// B011 pub(crate) fn assert_false(checker: &mut Checker, stmt: &Stmt, test: &Expr, msg: Option<&Expr>) { - let ExprKind::Constant(ast::ExprConstant { + let Expr::Constant(ast::ExprConstant { value: Constant::Bool(false), .. - } )= &test.node else { + } )= &test else { return; }; diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/assert_raises_exception.rs b/crates/ruff/src/rules/flake8_bugbear/rules/assert_raises_exception.rs index 0bba5f8ae6..04c6255c78 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/assert_raises_exception.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/assert_raises_exception.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, ExprKind, Stmt, Withitem}; +use rustpython_parser::ast::{self, Expr, Ranged, Stmt, Withitem}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -55,7 +55,7 @@ pub(crate) fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items: return; }; let item_context = &item.context_expr; - let ExprKind::Call(ast::ExprCall { func, args, keywords }) = &item_context.node else { + let Expr::Call(ast::ExprCall { func, args, keywords, range: _ }) = &item_context else { return; }; if args.len() != 1 { @@ -74,7 +74,7 @@ pub(crate) fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items: } let kind = { - if matches!(&func.node, ExprKind::Attribute(ast::ExprAttribute { attr, .. }) if attr == "assertRaises") + if matches!(func.as_ref(), Expr::Attribute(ast::ExprAttribute { attr, .. }) if attr == "assertRaises") { AssertionKind::AssertRaises } else if checker @@ -83,13 +83,9 @@ pub(crate) fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items: .map_or(false, |call_path| { call_path.as_slice() == ["pytest", "raises"] }) - && !keywords.iter().any(|keyword| { - keyword - .node - .arg - .as_ref() - .map_or(false, |arg| arg == "match") - }) + && !keywords + .iter() + .any(|keyword| keyword.arg.as_ref().map_or(false, |arg| arg == "match")) { AssertionKind::PytestRaises } else { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/assignment_to_os_environ.rs b/crates/ruff/src/rules/flake8_bugbear/rules/assignment_to_os_environ.rs index 827f0dfd08..fcaa3d6373 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/assignment_to_os_environ.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/assignment_to_os_environ.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -20,15 +20,15 @@ pub(crate) fn assignment_to_os_environ(checker: &mut Checker, targets: &[Expr]) return; } let target = &targets[0]; - let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &target.node else { + let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = target else { return; }; if attr != "environ" { return; } - let ExprKind::Name(ast::ExprName { id, .. } )= &value.node else { - return; - }; + let Expr::Name(ast::ExprName { id, .. } )= value.as_ref() else { + return; + }; if id != "os" { return; } diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/cached_instance_method.rs b/crates/ruff/src/rules/flake8_bugbear/rules/cached_instance_method.rs index bfc94a6027..3d438f01c0 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/cached_instance_method.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/cached_instance_method.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -36,7 +36,7 @@ pub(crate) fn cached_instance_method(checker: &mut Checker, decorator_list: &[Ex for decorator in decorator_list { // TODO(charlie): This should take into account `classmethod-decorators` and // `staticmethod-decorators`. - if let ExprKind::Name(ast::ExprName { id, .. }) = &decorator.node { + if let Expr::Name(ast::ExprName { id, .. }) = decorator { if id == "classmethod" || id == "staticmethod" { return; } @@ -45,8 +45,8 @@ pub(crate) fn cached_instance_method(checker: &mut Checker, decorator_list: &[Ex for decorator in decorator_list { if is_cache_func( checker, - match &decorator.node { - ExprKind::Call(ast::ExprCall { func, .. }) => func, + match decorator { + Expr::Call(ast::ExprCall { func, .. }) => func, _ => decorator, }, ) { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/cannot_raise_literal.rs b/crates/ruff/src/rules/flake8_bugbear/rules/cannot_raise_literal.rs index 391408f525..6b2df20d5b 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/cannot_raise_literal.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/cannot_raise_literal.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, ExprKind}; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -17,7 +17,7 @@ impl Violation for CannotRaiseLiteral { /// B016 pub(crate) fn cannot_raise_literal(checker: &mut Checker, expr: &Expr) { - let ExprKind::Constant ( _) = &expr.node else { + let Expr::Constant ( _) = expr else { return; }; checker diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/duplicate_exceptions.rs b/crates/ruff/src/rules/flake8_bugbear/rules/duplicate_exceptions.rs index 26ee7a3458..38031fecbc 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/duplicate_exceptions.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/duplicate_exceptions.rs @@ -1,7 +1,7 @@ use itertools::Itertools; use ruff_text_size::TextRange; use rustc_hash::{FxHashMap, FxHashSet}; -use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind}; +use rustpython_parser::ast::{self, Excepthandler, Expr, ExprContext, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix}; @@ -49,13 +49,12 @@ impl AlwaysAutofixableViolation for DuplicateHandlerException { } fn type_pattern(elts: Vec<&Expr>) -> Expr { - Expr::new( - TextRange::default(), - ast::ExprTuple { - elts: elts.into_iter().cloned().collect(), - ctx: ExprContext::Load, - }, - ) + ast::ExprTuple { + elts: elts.into_iter().cloned().collect(), + ctx: ExprContext::Load, + range: TextRange::default(), + } + .into() } fn duplicate_handler_exceptions<'a>( @@ -116,11 +115,11 @@ pub(crate) fn duplicate_exceptions(checker: &mut Checker, handlers: &[Excepthand let mut seen: FxHashSet = FxHashSet::default(); let mut duplicates: FxHashMap> = FxHashMap::default(); for handler in handlers { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_: Some(type_), .. }) = &handler.node else { + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_: Some(type_), .. }) = handler else { continue; }; - match &type_.node { - ExprKind::Attribute(_) | ExprKind::Name(_) => { + match type_.as_ref() { + Expr::Attribute(_) | Expr::Name(_) => { if let Some(call_path) = call_path::collect_call_path(type_) { if seen.contains(&call_path) { duplicates.entry(call_path).or_default().push(type_); @@ -129,7 +128,7 @@ pub(crate) fn duplicate_exceptions(checker: &mut Checker, handlers: &[Excepthand } } } - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + Expr::Tuple(ast::ExprTuple { elts, .. }) => { for (name, expr) in duplicate_handler_exceptions(checker, type_, elts) { if seen.contains(&name) { duplicates.entry(name).or_default().push(expr); diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/except_with_empty_tuple.rs b/crates/ruff/src/rules/flake8_bugbear/rules/except_with_empty_tuple.rs index 09c0657bb0..9ee4188a46 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/except_with_empty_tuple.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/except_with_empty_tuple.rs @@ -1,5 +1,5 @@ -use rustpython_parser::ast::Excepthandler; -use rustpython_parser::ast::{self, ExcepthandlerKind, ExprKind}; +use rustpython_parser::ast::{self, Ranged}; +use rustpython_parser::ast::{Excepthandler, Expr}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -18,12 +18,11 @@ impl Violation for ExceptWithEmptyTuple { /// B029 pub(crate) fn except_with_empty_tuple(checker: &mut Checker, excepthandler: &Excepthandler) { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = - &excepthandler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = excepthandler; let Some(type_) = type_ else { return; }; - let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &type_.node else { + let Expr::Tuple(ast::ExprTuple { elts, .. }) = type_.as_ref() else { return; }; if elts.is_empty() { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/except_with_non_exception_classes.rs b/crates/ruff/src/rules/flake8_bugbear/rules/except_with_non_exception_classes.rs index 60ad1e073d..4bfab07f94 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/except_with_non_exception_classes.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/except_with_non_exception_classes.rs @@ -1,6 +1,6 @@ use std::collections::VecDeque; -use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, Expr, ExprKind}; +use rustpython_parser::ast::{self, Excepthandler, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -17,20 +17,20 @@ impl Violation for ExceptWithNonExceptionClasses { } } -/// Given an [`Expr`], flatten any [`ExprKind::Starred`] expressions. +/// Given an [`Expr`], flatten any [`Expr::Starred`] expressions. /// This should leave any unstarred iterables alone (subsequently raising a /// warning for B029). fn flatten_starred_iterables(expr: &Expr) -> Vec<&Expr> { - let ExprKind::Tuple(ast::ExprTuple { elts, .. } )= &expr.node else { + let Expr::Tuple(ast::ExprTuple { elts, .. } )= expr else { return vec![expr]; }; let mut flattened_exprs: Vec<&Expr> = Vec::with_capacity(elts.len()); let mut exprs_to_process: VecDeque<&Expr> = elts.iter().collect(); while let Some(expr) = exprs_to_process.pop_front() { - match &expr.node { - ExprKind::Starred(ast::ExprStarred { value, .. }) => match &value.node { - ExprKind::Tuple(ast::ExprTuple { elts, .. }) - | ExprKind::List(ast::ExprList { elts, .. }) => { + match expr { + Expr::Starred(ast::ExprStarred { value, .. }) => match value.as_ref() { + Expr::Tuple(ast::ExprTuple { elts, .. }) + | Expr::List(ast::ExprList { elts, .. }) => { exprs_to_process.append(&mut elts.iter().collect()); } _ => flattened_exprs.push(value), @@ -46,15 +46,14 @@ pub(crate) fn except_with_non_exception_classes( checker: &mut Checker, excepthandler: &Excepthandler, ) { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = - &excepthandler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = excepthandler; let Some(type_) = type_ else { return; }; for expr in flatten_starred_iterables(type_) { if !matches!( - &expr.node, - ExprKind::Subscript(_) | ExprKind::Attribute(_) | ExprKind::Name(_) | ExprKind::Call(_), + expr, + Expr::Subscript(_) | Expr::Attribute(_) | Expr::Name(_) | Expr::Call(_), ) { checker .diagnostics diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/f_string_docstring.rs b/crates/ruff/src/rules/flake8_bugbear/rules/f_string_docstring.rs index 56f970dc13..5453b71569 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/f_string_docstring.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/f_string_docstring.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Expr, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -23,10 +23,10 @@ pub(crate) fn f_string_docstring(checker: &mut Checker, body: &[Stmt]) { let Some(stmt) = body.first() else { return; }; - let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node else { + let Stmt::Expr(ast::StmtExpr { value, range: _ }) = stmt else { return; }; - let ExprKind::JoinedStr ( _) = value.node else { + let Expr::JoinedStr ( _) = value.as_ref() else { return; }; checker.diagnostics.push(Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/function_call_argument_default.rs b/crates/ruff/src/rules/flake8_bugbear/rules/function_call_argument_default.rs index b1bb94bad9..2dd097d3f7 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/function_call_argument_default.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/function_call_argument_default.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Arguments, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Arguments, Constant, Expr, Ranged}; use ruff_diagnostics::Violation; use ruff_diagnostics::{Diagnostic, DiagnosticKind}; @@ -83,8 +83,8 @@ where 'b: 'a, { fn visit_expr(&mut self, expr: &'b Expr) { - match &expr.node { - ExprKind::Call(ast::ExprCall { func, args, .. }) => { + match expr { + Expr::Call(ast::ExprCall { func, args, .. }) => { if !is_mutable_func(self.checker, func) && !is_immutable_func(&self.checker.ctx, func, &self.extend_immutable_calls) && !is_nan_or_infinity(func, args) @@ -99,14 +99,14 @@ where } visitor::walk_expr(self, expr); } - ExprKind::Lambda(_) => {} + Expr::Lambda(_) => {} _ => visitor::walk_expr(self, expr), } } } fn is_nan_or_infinity(expr: &Expr, args: &[Expr]) -> bool { - let ExprKind::Name(ast::ExprName { id, .. }) = &expr.node else { + let Expr::Name(ast::ExprName { id, .. }) = expr else { return false; }; if id != "float" { @@ -115,10 +115,10 @@ fn is_nan_or_infinity(expr: &Expr, args: &[Expr]) -> bool { let Some(arg) = args.first() else { return false; }; - let ExprKind::Constant(ast::ExprConstant { + let Expr::Constant(ast::ExprConstant { value: Constant::Str(value), .. - } )= &arg.node else { + } )= arg else { return false; }; let lowercased = value.to_lowercase(); diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/function_uses_loop_variable.rs b/crates/ruff/src/rules/flake8_bugbear/rules/function_uses_loop_variable.rs index 9f9da4789a..d6d061534f 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/function_uses_loop_variable.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/function_uses_loop_variable.rs @@ -1,6 +1,5 @@ -use ruff_text_size::TextRange; use rustc_hash::FxHashSet; -use rustpython_parser::ast::{self, Comprehension, Expr, ExprContext, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Comprehension, Expr, ExprContext, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -27,18 +26,18 @@ impl Violation for FunctionUsesLoopVariable { #[derive(Default)] struct LoadedNamesVisitor<'a> { // Tuple of: name, defining expression, and defining range. - loaded: Vec<(&'a str, &'a Expr, TextRange)>, + loaded: Vec<(&'a str, &'a Expr)>, // Tuple of: name, defining expression, and defining range. - stored: Vec<(&'a str, &'a Expr, TextRange)>, + stored: Vec<(&'a str, &'a Expr)>, } /// `Visitor` to collect all used identifiers in a statement. impl<'a> Visitor<'a> for LoadedNamesVisitor<'a> { fn visit_expr(&mut self, expr: &'a Expr) { - match &expr.node { - ExprKind::Name(ast::ExprName { id, ctx }) => match ctx { - ExprContext::Load => self.loaded.push((id, expr, expr.range())), - ExprContext::Store => self.stored.push((id, expr, expr.range())), + match expr { + Expr::Name(ast::ExprName { id, ctx, range: _ }) => match ctx { + ExprContext::Load => self.loaded.push((id, expr)), + ExprContext::Store => self.stored.push((id, expr)), ExprContext::Del => {} }, _ => visitor::walk_expr(self, expr), @@ -48,7 +47,7 @@ impl<'a> Visitor<'a> for LoadedNamesVisitor<'a> { #[derive(Default)] struct SuspiciousVariablesVisitor<'a> { - names: Vec<(&'a str, &'a Expr, TextRange)>, + names: Vec<(&'a str, &'a Expr)>, safe_functions: Vec<&'a Expr>, } @@ -56,9 +55,9 @@ struct SuspiciousVariablesVisitor<'a> { /// functions, but not bound as arguments). impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> { fn visit_stmt(&mut self, stmt: &'a Stmt) { - match &stmt.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { args, body, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { args, body, .. }) => { + match stmt { + Stmt::FunctionDef(ast::StmtFunctionDef { args, body, .. }) + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { args, body, .. }) => { // Collect all loaded variable names. let mut visitor = LoadedNamesVisitor::default(); visitor.visit_body(body); @@ -76,9 +75,12 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> { ); return; } - StmtKind::Return(ast::StmtReturn { value: Some(value) }) => { + Stmt::Return(ast::StmtReturn { + value: Some(value), + range: _, + }) => { // Mark `return lambda: x` as safe. - if matches!(value.node, ExprKind::Lambda(_)) { + if value.is_lambda_expr() { self.safe_functions.push(value); } } @@ -88,44 +90,53 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> { } fn visit_expr(&mut self, expr: &'a Expr) { - match &expr.node { - ExprKind::Call(ast::ExprCall { + match expr { + Expr::Call(ast::ExprCall { func, args, keywords, + range: _, }) => { - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { - let id = id.as_str(); - if id == "filter" || id == "reduce" || id == "map" { - for arg in args { - if matches!(arg.node, ExprKind::Lambda(_)) { - self.safe_functions.push(arg); + match func.as_ref() { + Expr::Name(ast::ExprName { id, .. }) => { + let id = id.as_str(); + if id == "filter" || id == "reduce" || id == "map" { + for arg in args { + if matches!(arg, Expr::Lambda(_)) { + self.safe_functions.push(arg); + } } } } - } - if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &func.node { - if attr == "reduce" { - if let ExprKind::Name(ast::ExprName { id, .. }) = &value.node { - if id == "functools" { - for arg in args { - if matches!(arg.node, ExprKind::Lambda(_)) { - self.safe_functions.push(arg); + Expr::Attribute(ast::ExprAttribute { value, attr, .. }) => { + if attr == "reduce" { + if let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() { + if id == "functools" { + for arg in args { + if arg.is_lambda_expr() { + self.safe_functions.push(arg); + } } } } } } + _ => {} } + for keyword in keywords { - if keyword.node.arg.as_ref().map_or(false, |arg| arg == "key") - && matches!(keyword.node.value.node, ExprKind::Lambda(_)) + if keyword.arg.as_ref().map_or(false, |arg| arg == "key") + && matches!(keyword.value, Expr::Lambda(_)) { - self.safe_functions.push(&keyword.node.value); + self.safe_functions.push(&keyword.value); } } } - ExprKind::Lambda(ast::ExprLambda { args, body }) => { + Expr::Lambda(ast::ExprLambda { + args, + body, + range: _, + }) => { if !self.safe_functions.contains(&expr) { // Collect all loaded variable names. let mut visitor = LoadedNamesVisitor::default(); @@ -160,15 +171,14 @@ struct NamesFromAssignmentsVisitor<'a> { /// `Visitor` to collect all names used in an assignment expression. impl<'a> Visitor<'a> for NamesFromAssignmentsVisitor<'a> { fn visit_expr(&mut self, expr: &'a Expr) { - match &expr.node { - ExprKind::Name(ast::ExprName { id, .. }) => { + match expr { + Expr::Name(ast::ExprName { id, .. }) => { self.names.insert(id.as_str()); } - ExprKind::Starred(ast::ExprStarred { value, .. }) => { + Expr::Starred(ast::ExprStarred { value, .. }) => { self.visit_expr(value); } - ExprKind::List(ast::ExprList { elts, .. }) - | ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + Expr::List(ast::ExprList { elts, .. }) | Expr::Tuple(ast::ExprTuple { elts, .. }) => { for expr in elts { self.visit_expr(expr); } @@ -186,26 +196,23 @@ struct AssignedNamesVisitor<'a> { /// `Visitor` to collect all used identifiers in a statement. impl<'a> Visitor<'a> for AssignedNamesVisitor<'a> { fn visit_stmt(&mut self, stmt: &'a Stmt) { - if matches!( - &stmt.node, - StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_) - ) { + if matches!(stmt, Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_)) { // Don't recurse. return; } - match &stmt.node { - StmtKind::Assign(ast::StmtAssign { targets, .. }) => { + match stmt { + Stmt::Assign(ast::StmtAssign { targets, .. }) => { let mut visitor = NamesFromAssignmentsVisitor::default(); for expr in targets { visitor.visit_expr(expr); } self.names.extend(visitor.names); } - StmtKind::AugAssign(ast::StmtAugAssign { target, .. }) - | StmtKind::AnnAssign(ast::StmtAnnAssign { target, .. }) - | StmtKind::For(ast::StmtFor { target, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { target, .. }) => { + Stmt::AugAssign(ast::StmtAugAssign { target, .. }) + | Stmt::AnnAssign(ast::StmtAnnAssign { target, .. }) + | Stmt::For(ast::StmtFor { target, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { target, .. }) => { let mut visitor = NamesFromAssignmentsVisitor::default(); visitor.visit_expr(target); self.names.extend(visitor.names); @@ -217,7 +224,7 @@ impl<'a> Visitor<'a> for AssignedNamesVisitor<'a> { } fn visit_expr(&mut self, expr: &'a Expr) { - if matches!(&expr.node, ExprKind::Lambda(_)) { + if matches!(expr, Expr::Lambda(_)) { // Don't recurse. return; } @@ -260,7 +267,7 @@ pub(crate) fn function_uses_loop_variable<'a>(checker: &mut Checker<'a>, node: & // If a variable was used in a function or lambda body, and assigned in the // loop, flag it. - for (name, expr, range) in suspicious_variables { + for (name, expr) in suspicious_variables { if reassigned_in_loop.contains(name) { if !checker.flake8_bugbear_seen.contains(&expr) { checker.flake8_bugbear_seen.push(expr); @@ -268,7 +275,7 @@ pub(crate) fn function_uses_loop_variable<'a>(checker: &mut Checker<'a>, node: & FunctionUsesLoopVariable { name: name.to_string(), }, - range, + expr.range(), )); } } diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/getattr_with_constant.rs b/crates/ruff/src/rules/flake8_bugbear/rules/getattr_with_constant.rs index f67cbfddc1..5ea2332ac1 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/getattr_with_constant.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/getattr_with_constant.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Constant, Expr, ExprContext, ExprKind}; +use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -26,14 +26,13 @@ impl AlwaysAutofixableViolation for GetAttrWithConstant { } } fn attribute(value: &Expr, attr: &str) -> Expr { - Expr::new( - TextRange::default(), - ast::ExprAttribute { - value: Box::new(value.clone()), - attr: attr.into(), - ctx: ExprContext::Load, - }, - ) + ast::ExprAttribute { + value: Box::new(value.clone()), + attr: attr.into(), + ctx: ExprContext::Load, + range: TextRange::default(), + } + .into() } /// B009 @@ -43,7 +42,7 @@ pub(crate) fn getattr_with_constant( func: &Expr, args: &[Expr], ) { - let ExprKind::Name(ast::ExprName { id, .. } )= &func.node else { + let Expr::Name(ast::ExprName { id, .. } )= func else { return; }; if id != "getattr" { @@ -52,10 +51,10 @@ pub(crate) fn getattr_with_constant( let [obj, arg] = args else { return; }; - let ExprKind::Constant(ast::ExprConstant { + let Expr::Constant(ast::ExprConstant { value: Constant::Str(value), .. - } )= &arg.node else { + } )= arg else { return; }; if !is_identifier(value) { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/jump_statement_in_finally.rs b/crates/ruff/src/rules/flake8_bugbear/rules/jump_statement_in_finally.rs index a621bb57d8..55160b1b15 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/jump_statement_in_finally.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/jump_statement_in_finally.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -23,35 +23,31 @@ fn walk_stmt(checker: &mut Checker, body: &[Stmt], f: fn(&Stmt) -> bool) { if f(stmt) { checker.diagnostics.push(Diagnostic::new( JumpStatementInFinally { - name: match &stmt.node { - StmtKind::Break => "break", - StmtKind::Continue => "continue", - StmtKind::Return(_) => "return", - _ => unreachable!( - "Expected StmtKind::Break | StmtKind::Continue | StmtKind::Return" - ), + name: match stmt { + Stmt::Break(_) => "break", + Stmt::Continue(_) => "continue", + Stmt::Return(_) => "return", + _ => unreachable!("Expected Stmt::Break | Stmt::Continue | Stmt::Return"), } .to_owned(), }, stmt.range(), )); } - match &stmt.node { - StmtKind::While(ast::StmtWhile { body, .. }) - | StmtKind::For(ast::StmtFor { body, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { body, .. }) => { - walk_stmt(checker, body, |stmt| { - matches!(stmt.node, StmtKind::Return(_)) - }); + match stmt { + Stmt::While(ast::StmtWhile { body, .. }) + | Stmt::For(ast::StmtFor { body, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { body, .. }) => { + walk_stmt(checker, body, |stmt| matches!(stmt, Stmt::Return(_))); } - StmtKind::If(ast::StmtIf { body, .. }) - | StmtKind::Try(ast::StmtTry { body, .. }) - | StmtKind::TryStar(ast::StmtTryStar { body, .. }) - | StmtKind::With(ast::StmtWith { body, .. }) - | StmtKind::AsyncWith(ast::StmtAsyncWith { body, .. }) => { + Stmt::If(ast::StmtIf { body, .. }) + | Stmt::Try(ast::StmtTry { body, .. }) + | Stmt::TryStar(ast::StmtTryStar { body, .. }) + | Stmt::With(ast::StmtWith { body, .. }) + | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { walk_stmt(checker, body, f); } - StmtKind::Match(ast::StmtMatch { cases, .. }) => { + Stmt::Match(ast::StmtMatch { cases, .. }) => { for case in cases { walk_stmt(checker, &case.body, f); } @@ -64,9 +60,6 @@ fn walk_stmt(checker: &mut Checker, body: &[Stmt], f: fn(&Stmt) -> bool) { /// B012 pub(crate) fn jump_statement_in_finally(checker: &mut Checker, finalbody: &[Stmt]) { walk_stmt(checker, finalbody, |stmt| { - matches!( - stmt.node, - StmtKind::Break | StmtKind::Continue | StmtKind::Return(_) - ) + matches!(stmt, Stmt::Break(_) | Stmt::Continue(_) | Stmt::Return(_)) }); } diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/loop_variable_overrides_iterator.rs b/crates/ruff/src/rules/flake8_bugbear/rules/loop_variable_overrides_iterator.rs index 154b5b511d..f8d37590dd 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/loop_variable_overrides_iterator.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/loop_variable_overrides_iterator.rs @@ -1,5 +1,5 @@ use rustc_hash::FxHashMap; -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -31,22 +31,26 @@ where 'b: 'a, { fn visit_expr(&mut self, expr: &'b Expr) { - match &expr.node { - ExprKind::Name(ast::ExprName { id, .. }) => { + match expr { + Expr::Name(ast::ExprName { id, .. }) => { self.names.insert(id, expr); } - ExprKind::ListComp(ast::ExprListComp { generators, .. }) - | ExprKind::DictComp(ast::ExprDictComp { generators, .. }) - | ExprKind::SetComp(ast::ExprSetComp { generators, .. }) - | ExprKind::GeneratorExp(ast::ExprGeneratorExp { generators, .. }) => { + Expr::ListComp(ast::ExprListComp { generators, .. }) + | Expr::DictComp(ast::ExprDictComp { generators, .. }) + | Expr::SetComp(ast::ExprSetComp { generators, .. }) + | Expr::GeneratorExp(ast::ExprGeneratorExp { generators, .. }) => { for comp in generators { self.visit_expr(&comp.iter); } } - ExprKind::Lambda(ast::ExprLambda { args, body }) => { + Expr::Lambda(ast::ExprLambda { + args, + body, + range: _, + }) => { visitor::walk_expr(self, body); for arg in &args.args { - self.names.remove(arg.node.arg.as_str()); + self.names.remove(arg.arg.as_str()); } } _ => visitor::walk_expr(self, expr), diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/mutable_argument_default.rs b/crates/ruff/src/rules/flake8_bugbear/rules/mutable_argument_default.rs index b2151e1b1d..6c680ed630 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/mutable_argument_default.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/mutable_argument_default.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Arguments, Expr, ExprKind}; +use rustpython_parser::ast::{self, Arguments, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -37,14 +37,14 @@ pub(crate) fn is_mutable_func(checker: &Checker, func: &Expr) -> bool { } fn is_mutable_expr(checker: &Checker, expr: &Expr) -> bool { - match &expr.node { - ExprKind::List(_) - | ExprKind::Dict(_) - | ExprKind::Set(_) - | ExprKind::ListComp(_) - | ExprKind::DictComp(_) - | ExprKind::SetComp(_) => true, - ExprKind::Call(ast::ExprCall { func, .. }) => is_mutable_func(checker, func), + match expr { + Expr::List(_) + | Expr::Dict(_) + | Expr::Set(_) + | Expr::ListComp(_) + | Expr::DictComp(_) + | Expr::SetComp(_) => true, + Expr::Call(ast::ExprCall { func, .. }) => is_mutable_func(checker, func), _ => false, } } @@ -68,7 +68,6 @@ pub(crate) fn mutable_argument_default(checker: &mut Checker, arguments: &Argume { if is_mutable_expr(checker, default) && !arg - .node .annotation .as_ref() .map_or(false, |expr| is_immutable_annotation(&checker.ctx, expr)) diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs b/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs index fa6c8f930f..e76c085cbc 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/raise_without_from_inside_except.rs b/crates/ruff/src/rules/flake8_bugbear/rules/raise_without_from_inside_except.rs index b2d187995e..ccb0d84c55 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/raise_without_from_inside_except.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/raise_without_from_inside_except.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, ExprKind, Stmt}; +use rustpython_parser::ast::{self, Expr, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -32,8 +32,8 @@ pub(crate) fn raise_without_from_inside_except(checker: &mut Checker, body: &[St for (range, exc, cause) in raises { if cause.is_none() { if let Some(exc) = exc { - match &exc.node { - ExprKind::Name(ast::ExprName { id, .. }) if is_lower(id) => {} + match exc { + Expr::Name(ast::ExprName { id, .. }) if is_lower(id) => {} _ => { checker .diagnostics diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/redundant_tuple_in_exception_handler.rs b/crates/ruff/src/rules/flake8_bugbear/rules/redundant_tuple_in_exception_handler.rs index 3ae289df6b..17892dd79e 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/redundant_tuple_in_exception_handler.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/redundant_tuple_in_exception_handler.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, ExprKind}; +use rustpython_parser::ast::{self, Excepthandler, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -34,10 +34,10 @@ pub(crate) fn redundant_tuple_in_exception_handler( handlers: &[Excepthandler], ) { for handler in handlers { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_: Some(type_), .. }) = &handler.node else { + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_: Some(type_), .. }) = handler else { continue; }; - let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &type_.node else { + let Expr::Tuple(ast::ExprTuple { elts, .. }) = type_.as_ref() else { continue; }; let [elt] = &elts[..] else { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/reuse_of_groupby_generator.rs b/crates/ruff/src/rules/flake8_bugbear/rules/reuse_of_groupby_generator.rs index 3abc82a8dc..93c0d3c9b8 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/reuse_of_groupby_generator.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/reuse_of_groupby_generator.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Comprehension, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Comprehension, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -84,7 +84,7 @@ impl<'a> GroupNameFinder<'a> { } fn name_matches(&self, expr: &Expr) -> bool { - if let ExprKind::Name(ast::ExprName { id, .. }) = &expr.node { + if let Expr::Name(ast::ExprName { id, .. }) = expr { id == self.group_name } else { false @@ -112,8 +112,8 @@ where if self.overridden { return; } - match &stmt.node { - StmtKind::For(ast::StmtFor { + match stmt { + Stmt::For(ast::StmtFor { target, iter, body, .. }) => { if self.name_matches(target) { @@ -138,15 +138,20 @@ where self.nested = false; } } - StmtKind::While(ast::StmtWhile { body, .. }) => { + Stmt::While(ast::StmtWhile { body, .. }) => { self.nested = true; visitor::walk_body(self, body); self.nested = false; } - StmtKind::If(ast::StmtIf { test, body, orelse }) => { + Stmt::If(ast::StmtIf { + test, + body, + orelse, + range: _, + }) => { // Determine whether we're on an `if` arm (as opposed to an `elif`). let is_if_arm = !self.parent_ifs.iter().any(|parent| { - if let StmtKind::If(ast::StmtIf { orelse, .. }) = &parent.node { + if let Stmt::If(ast::StmtIf { orelse, .. }) = parent { orelse.len() == 1 && &orelse[0] == stmt } else { false @@ -166,12 +171,12 @@ where let has_else = orelse .first() - .map_or(false, |expr| !matches!(expr.node, StmtKind::If(_))); + .map_or(false, |expr| !matches!(expr, Stmt::If(_))); self.parent_ifs.push(stmt); if has_else { - // There's no `StmtKind::Else`; instead, the `else` contents are directly on - // the `orelse` of the `StmtKind::If` node. We want to add a new counter for + // There's no `Stmt::Else`; instead, the `else` contents are directly on + // the `orelse` of the `Stmt::If` node. We want to add a new counter for // the `orelse` branch, but first, we need to visit the `if` body manually. self.visit_expr(test); self.visit_body(body); @@ -193,7 +198,11 @@ where } } } - StmtKind::Match(ast::StmtMatch { subject, cases }) => { + Stmt::Match(ast::StmtMatch { + subject, + cases, + range: _, + }) => { self.counter_stack.push(Vec::with_capacity(cases.len())); self.visit_expr(subject); for match_case in cases { @@ -207,14 +216,14 @@ where self.increment_usage_count(max_count); } } - StmtKind::Assign(ast::StmtAssign { targets, value, .. }) => { + Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { if targets.iter().any(|target| self.name_matches(target)) { self.overridden = true; } else { self.visit_expr(value); } } - StmtKind::AnnAssign(ast::StmtAnnAssign { target, value, .. }) => { + Stmt::AnnAssign(ast::StmtAnnAssign { target, value, .. }) => { if self.name_matches(target) { self.overridden = true; } else if let Some(expr) = value { @@ -241,7 +250,7 @@ where } fn visit_expr(&mut self, expr: &'a Expr) { - if let ExprKind::NamedExpr(ast::ExprNamedExpr { target, .. }) = &expr.node { + if let Expr::NamedExpr(ast::ExprNamedExpr { target, .. }) = expr { if self.name_matches(target) { self.overridden = true; } @@ -250,9 +259,17 @@ where return; } - match &expr.node { - ExprKind::ListComp(ast::ExprListComp { elt, generators }) - | ExprKind::SetComp(ast::ExprSetComp { elt, generators }) => { + match expr { + Expr::ListComp(ast::ExprListComp { + elt, + generators, + range: _, + }) + | Expr::SetComp(ast::ExprSetComp { + elt, + generators, + range: _, + }) => { for comprehension in generators { self.visit_comprehension(comprehension); } @@ -262,10 +279,11 @@ where self.nested = false; } } - ExprKind::DictComp(ast::ExprDictComp { + Expr::DictComp(ast::ExprDictComp { key, value, generators, + range: _, }) => { for comprehension in generators { self.visit_comprehension(comprehension); @@ -308,10 +326,10 @@ pub(crate) fn reuse_of_groupby_generator( body: &[Stmt], iter: &Expr, ) { - let ExprKind::Call(ast::ExprCall { func, .. }) = &iter.node else { + let Expr::Call(ast::ExprCall { func, .. }) = &iter else { return; }; - let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &target.node else { + let Expr::Tuple(ast::ExprTuple { elts, .. }) = target else { // Ignore any `groupby()` invocation that isn't unpacked return; }; @@ -319,7 +337,7 @@ pub(crate) fn reuse_of_groupby_generator( return; } // We have an invocation of groupby which is a simple unpacking - let ExprKind::Name(ast::ExprName { id: group_name, .. }) = &elts[1].node else { + let Expr::Name(ast::ExprName { id: group_name, .. }) = &elts[1] else { return; }; // Check if the function call is `itertools.groupby` diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/setattr_with_constant.rs b/crates/ruff/src/rules/flake8_bugbear/rules/setattr_with_constant.rs index df51a0092c..4a07e4e385 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/setattr_with_constant.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/setattr_with_constant.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Ranged, Stmt}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -28,21 +28,17 @@ impl AlwaysAutofixableViolation for SetAttrWithConstant { } fn assignment(obj: &Expr, name: &str, value: &Expr, stylist: &Stylist) -> String { - let stmt = Stmt::new( - TextRange::default(), - StmtKind::Assign(ast::StmtAssign { - targets: vec![Expr::new( - TextRange::default(), - ExprKind::Attribute(ast::ExprAttribute { - value: Box::new(obj.clone()), - attr: name.into(), - ctx: ExprContext::Store, - }), - )], - value: Box::new(value.clone()), - type_comment: None, - }), - ); + let stmt = Stmt::Assign(ast::StmtAssign { + targets: vec![Expr::Attribute(ast::ExprAttribute { + value: Box::new(obj.clone()), + attr: name.into(), + ctx: ExprContext::Store, + range: TextRange::default(), + })], + value: Box::new(value.clone()), + type_comment: None, + range: TextRange::default(), + }); unparse_stmt(&stmt, stylist) } @@ -53,7 +49,7 @@ pub(crate) fn setattr_with_constant( func: &Expr, args: &[Expr], ) { - let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else { + let Expr::Name(ast::ExprName { id, .. }) = func else { return; }; if id != "setattr" { @@ -62,10 +58,10 @@ pub(crate) fn setattr_with_constant( let [obj, name, value] = args else { return; }; - let ExprKind::Constant(ast::ExprConstant { + let Expr::Constant(ast::ExprConstant { value: Constant::Str(name), .. - } )= &name.node else { + } )= name else { return; }; if !is_identifier(name) { @@ -76,8 +72,12 @@ pub(crate) fn setattr_with_constant( } // We can only replace a `setattr` call (which is an `Expr`) with an assignment // (which is a `Stmt`) if the `Expr` is already being used as a `Stmt` - // (i.e., it's directly within an `StmtKind::Expr`). - if let StmtKind::Expr(ast::StmtExpr { value: child }) = &checker.ctx.stmt().node { + // (i.e., it's directly within an `Stmt::Expr`). + if let Stmt::Expr(ast::StmtExpr { + value: child, + range: _, + }) = &checker.ctx.stmt() + { if expr == child.as_ref() { let mut diagnostic = Diagnostic::new(SetAttrWithConstant, expr.range()); diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/star_arg_unpacking_after_keyword_arg.rs b/crates/ruff/src/rules/flake8_bugbear/rules/star_arg_unpacking_after_keyword_arg.rs index e80c55330a..287f67035f 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/star_arg_unpacking_after_keyword_arg.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/star_arg_unpacking_after_keyword_arg.rs @@ -7,7 +7,7 @@ //! by the unpacked sequence, and this change of ordering can surprise and //! mislead readers. -use rustpython_parser::ast::{Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -34,7 +34,7 @@ pub(crate) fn star_arg_unpacking_after_keyword_arg( return; }; for arg in args { - let ExprKind::Starred (_) = arg.node else { + let Expr::Starred (_) = arg else { continue; }; if arg.start() <= keyword.start() { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/strip_with_multi_characters.rs b/crates/ruff/src/rules/flake8_bugbear/rules/strip_with_multi_characters.rs index 62eabf230d..1fd78729c9 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/strip_with_multi_characters.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/strip_with_multi_characters.rs @@ -1,5 +1,5 @@ use itertools::Itertools; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -23,7 +23,7 @@ pub(crate) fn strip_with_multi_characters( func: &Expr, args: &[Expr], ) { - let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node else { + let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func else { return; }; if !matches!(attr.as_str(), "strip" | "lstrip" | "rstrip") { @@ -33,10 +33,10 @@ pub(crate) fn strip_with_multi_characters( return; } - let ExprKind::Constant(ast::ExprConstant { + let Expr::Constant(ast::ExprConstant { value: Constant::Str(value), .. - } )= &args[0].node else { + } )= &args[0] else { return; }; diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/unary_prefix_increment.rs b/crates/ruff/src/rules/flake8_bugbear/rules/unary_prefix_increment.rs index 10da1ebee6..12f70b9044 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/unary_prefix_increment.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/unary_prefix_increment.rs @@ -17,7 +17,7 @@ //! n += 1 //! ``` -use rustpython_parser::ast::{self, Expr, ExprKind, Unaryop}; +use rustpython_parser::ast::{self, Expr, Ranged, Unaryop}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -38,13 +38,13 @@ impl Violation for UnaryPrefixIncrement { pub(crate) fn unary_prefix_increment( checker: &mut Checker, expr: &Expr, - op: &Unaryop, + op: Unaryop, operand: &Expr, ) { if !matches!(op, Unaryop::UAdd) { return; } - let ExprKind::UnaryOp(ast::ExprUnaryOp { op, .. })= &operand.node else { + let Expr::UnaryOp(ast::ExprUnaryOp { op, .. })= operand else { return; }; if !matches!(op, Unaryop::UAdd) { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/unintentional_type_annotation.rs b/crates/ruff/src/rules/flake8_bugbear/rules/unintentional_type_annotation.rs index cfbcfef1b1..0c5cad9903 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/unintentional_type_annotation.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/unintentional_type_annotation.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Stmt}; +use rustpython_parser::ast::{self, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -43,16 +43,16 @@ pub(crate) fn unintentional_type_annotation( if value.is_some() { return; } - match &target.node { - ExprKind::Subscript(ast::ExprSubscript { value, .. }) => { - if matches!(&value.node, ExprKind::Name(_)) { + match target { + Expr::Subscript(ast::ExprSubscript { value, .. }) => { + if value.is_name_expr() { checker .diagnostics .push(Diagnostic::new(UnintentionalTypeAnnotation, stmt.range())); } } - ExprKind::Attribute(ast::ExprAttribute { value, .. }) => { - if let ExprKind::Name(ast::ExprName { id, .. }) = &value.node { + Expr::Attribute(ast::ExprAttribute { value, .. }) => { + if let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() { if id != "self" { checker .diagnostics diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs b/crates/ruff/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs index 942ca0c2cb..ec1cff4635 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -25,7 +25,7 @@ pub(crate) fn unreliable_callable_check( func: &Expr, args: &[Expr], ) { - let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else { + let Expr::Name(ast::ExprName { id, .. }) = func else { return; }; if id != "getattr" && id != "hasattr" { @@ -34,10 +34,10 @@ pub(crate) fn unreliable_callable_check( if args.len() < 2 { return; }; - let ExprKind::Constant(ast::ExprConstant { + let Expr::Constant(ast::ExprConstant { value: Constant::Str(s), .. - }) = &args[1].node else + }) = &args[1] else { return; }; diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs b/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs index 19a3410245..42638a1b78 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs @@ -19,7 +19,7 @@ //! ``` use rustc_hash::FxHashMap; -use rustpython_parser::ast::{self, Expr, ExprKind, Stmt}; +use rustpython_parser::ast::{self, Expr, Ranged, Stmt}; use serde::{Deserialize, Serialize}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; @@ -74,7 +74,7 @@ impl Violation for UnusedLoopControlVariable { } } -/// Identify all `ExprKind::Name` nodes in an AST. +/// Identify all `Expr::Name` nodes in an AST. struct NameFinder<'a> { /// A map from identifier to defining expression. names: FxHashMap<&'a str, &'a Expr>, @@ -93,7 +93,7 @@ where 'b: 'a, { fn visit_expr(&mut self, expr: &'a Expr) { - if let ExprKind::Name(ast::ExprName { id, .. }) = &expr.node { + if let Expr::Name(ast::ExprName { id, .. }) = expr { self.names.insert(id, expr); } visitor::walk_expr(self, expr); diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/useless_comparison.rs b/crates/ruff/src/rules/flake8_bugbear/rules/useless_comparison.rs index 25bdb2e676..746acc8ec9 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/useless_comparison.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/useless_comparison.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, ExprKind}; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -20,7 +20,7 @@ impl Violation for UselessComparison { /// B015 pub(crate) fn useless_comparison(checker: &mut Checker, expr: &Expr) { - if matches!(expr.node, ExprKind::Compare(_)) { + if matches!(expr, Expr::Compare(_)) { checker .diagnostics .push(Diagnostic::new(UselessComparison, expr.range())); diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/useless_contextlib_suppress.rs b/crates/ruff/src/rules/flake8_bugbear/rules/useless_contextlib_suppress.rs index 445aa72b5f..ad2061ba7f 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/useless_contextlib_suppress.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/useless_contextlib_suppress.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use crate::checkers::ast::Checker; use ruff_diagnostics::{Diagnostic, Violation}; diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs b/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs index 350eed90ef..eb845b78eb 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -36,15 +36,15 @@ impl Violation for UselessExpression { /// B018 pub(crate) fn useless_expression(checker: &mut Checker, value: &Expr) { // Ignore comparisons, as they're handled by `useless_comparison`. - if matches!(value.node, ExprKind::Compare(_)) { + if matches!(value, Expr::Compare(_)) { return; } // Ignore strings, to avoid false positives with docstrings. if matches!( - value.node, - ExprKind::JoinedStr(_) - | ExprKind::Constant(ast::ExprConstant { + value, + Expr::JoinedStr(_) + | Expr::Constant(ast::ExprConstant { value: Constant::Str(..) | Constant::Ellipsis, .. }) @@ -56,7 +56,7 @@ pub(crate) fn useless_expression(checker: &mut Checker, value: &Expr) { if contains_effect(value, |id| checker.ctx.is_builtin(id)) { // Flag attributes as useless expressions, even if they're attached to calls or other // expressions. - if matches!(value.node, ExprKind::Attribute(_)) { + if matches!(value, Expr::Attribute(_)) { checker.diagnostics.push(Diagnostic::new( UselessExpression { kind: Kind::Attribute, diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/zip_without_explicit_strict.rs b/crates/ruff/src/rules/flake8_bugbear/rules/zip_without_explicit_strict.rs index 1a49e65116..5db77e2d38 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/zip_without_explicit_strict.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/zip_without_explicit_strict.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Expr, Keyword, Ranged}; use crate::checkers::ast::Checker; use ruff_diagnostics::{Diagnostic, Violation}; @@ -21,16 +21,12 @@ pub(crate) fn zip_without_explicit_strict( func: &Expr, kwargs: &[Keyword], ) { - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { + if let Expr::Name(ast::ExprName { id, .. }) = func { if id == "zip" && checker.ctx.is_builtin("zip") - && !kwargs.iter().any(|keyword| { - keyword - .node - .arg - .as_ref() - .map_or(false, |name| name == "strict") - }) + && !kwargs + .iter() + .any(|keyword| keyword.arg.as_ref().map_or(false, |name| name == "strict")) { checker .diagnostics diff --git a/crates/ruff/src/rules/flake8_builtins/rules.rs b/crates/ruff/src/rules/flake8_builtins/rules.rs index 17cd5f438b..46193c1e37 100644 --- a/crates/ruff/src/rules/flake8_builtins/rules.rs +++ b/crates/ruff/src/rules/flake8_builtins/rules.rs @@ -1,9 +1,8 @@ -use rustpython_parser::ast::Attributed; - use ruff_diagnostics::Diagnostic; use ruff_diagnostics::Violation; use ruff_macros::{derive_message_formats, violation}; use ruff_python_stdlib::builtins::BUILTINS; +use rustpython_parser::ast::Ranged; use crate::checkers::ast::Checker; @@ -172,11 +171,10 @@ fn shadows_builtin(name: &str, ignorelist: &[String]) -> bool { } /// A001 -pub(crate) fn builtin_variable_shadowing( - checker: &mut Checker, - name: &str, - attributed: &Attributed, -) { +pub(crate) fn builtin_variable_shadowing(checker: &mut Checker, name: &str, attributed: &T) +where + T: Ranged, +{ if shadows_builtin(name, &checker.settings.flake8_builtins.builtins_ignorelist) { checker.diagnostics.push(Diagnostic::new( BuiltinVariableShadowing { @@ -188,11 +186,10 @@ pub(crate) fn builtin_variable_shadowing( } /// A002 -pub(crate) fn builtin_argument_shadowing( - checker: &mut Checker, - name: &str, - attributed: &Attributed, -) { +pub(crate) fn builtin_argument_shadowing(checker: &mut Checker, name: &str, attributed: &T) +where + T: Ranged, +{ if shadows_builtin(name, &checker.settings.flake8_builtins.builtins_ignorelist) { checker.diagnostics.push(Diagnostic::new( BuiltinArgumentShadowing { @@ -204,11 +201,10 @@ pub(crate) fn builtin_argument_shadowing( } /// A003 -pub(crate) fn builtin_attribute_shadowing( - checker: &mut Checker, - name: &str, - attributed: &Attributed, -) { +pub(crate) fn builtin_attribute_shadowing(checker: &mut Checker, name: &str, attributed: &T) +where + T: Ranged, +{ if shadows_builtin(name, &checker.settings.flake8_builtins.builtins_ignorelist) { checker.diagnostics.push(Diagnostic::new( BuiltinAttributeShadowing { diff --git a/crates/ruff/src/rules/flake8_comprehensions/fixes.rs b/crates/ruff/src/rules/flake8_comprehensions/fixes.rs index 5719ff1478..24deb88e1e 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/fixes.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/fixes.rs @@ -7,6 +7,7 @@ use libcst_native::{ ParenthesizedWhitespace, RightCurlyBrace, RightParen, RightSquareBracket, Set, SetComp, SimpleString, SimpleWhitespace, TrailingWhitespace, Tuple, }; +use rustpython_parser::ast::Ranged; use ruff_diagnostics::{Edit, Fix}; use ruff_python_ast::source_code::{Locator, Stylist}; @@ -115,10 +116,8 @@ pub(crate) fn fix_unnecessary_generator_set( // If the expression is embedded in an f-string, surround it with spaces to avoid // syntax errors. - if let Some(parent_element) = parent { - if let &rustpython_parser::ast::ExprKind::FormattedValue(_) = &parent_element.node { - content = format!(" {content} "); - } + if let Some(rustpython_parser::ast::Expr::FormattedValue(_)) = parent { + content = format!(" {content} "); } Ok(Edit::range_replacement(content, expr.range())) @@ -185,10 +184,8 @@ pub(crate) fn fix_unnecessary_generator_dict( // If the expression is embedded in an f-string, surround it with spaces to avoid // syntax errors. - if let Some(parent_element) = parent { - if let &rustpython_parser::ast::ExprKind::FormattedValue(_) = &parent_element.node { - content = format!(" {content} "); - } + if let Some(rustpython_parser::ast::Expr::FormattedValue(_)) = parent { + content = format!(" {content} "); } Ok(Edit::range_replacement(content, expr.range())) @@ -1100,10 +1097,8 @@ pub(crate) fn fix_unnecessary_map( // If the expression is embedded in an f-string, surround it with spaces to avoid // syntax errors. if kind == "set" || kind == "dict" { - if let Some(parent_element) = parent { - if let &rustpython_parser::ast::ExprKind::FormattedValue(_) = &parent_element.node { - content = format!(" {content} "); - } + if let Some(rustpython_parser::ast::Expr::FormattedValue(_)) = parent { + content = format!(" {content} "); } } diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/helpers.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/helpers.rs index 82a989d919..27241912ac 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/helpers.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/helpers.rs @@ -1,7 +1,7 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Expr, Keyword}; pub(crate) fn expr_name(func: &Expr) -> Option<&str> { - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { + if let Expr::Name(ast::ExprName { id, .. }) = func { Some(id) } else { None @@ -13,7 +13,7 @@ pub(crate) fn exactly_one_argument_with_matching_function<'a>( func: &Expr, args: &'a [Expr], keywords: &[Keyword], -) -> Option<&'a ExprKind> { +) -> Option<&'a Expr> { if !keywords.is_empty() { return None; } @@ -23,16 +23,16 @@ pub(crate) fn exactly_one_argument_with_matching_function<'a>( if expr_name(func)? != name { return None; } - Some(&args[0].node) + Some(&args[0]) } pub(crate) fn first_argument_with_matching_function<'a>( name: &str, func: &Expr, args: &'a [Expr], -) -> Option<&'a ExprKind> { +) -> Option<&'a Expr> { if expr_name(func)? == name { - Some(&args.first()?.node) + Some(args.first()?) } else { None } diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs index a2402c059b..4d1514cf9e 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -65,7 +65,7 @@ pub(crate) fn unnecessary_call_around_sorted( let Some(arg) = args.first() else { return; }; - let ExprKind::Call(ast::ExprCall { func, .. }) = &arg.node else { + let Expr::Call(ast::ExprCall { func, .. }) = arg else { return; }; let Some(inner) = helpers::expr_name(func) else { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs index 09fd27a9cd..1789608900 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; use ruff_macros::{derive_message_formats, violation}; @@ -70,7 +70,7 @@ pub(crate) fn unnecessary_collection_call( "dict" if keywords.is_empty() || (!settings.allow_dict_calls_with_keyword_arguments - && keywords.iter().all(|kw| kw.node.arg.is_some())) => + && keywords.iter().all(|kw| kw.arg.is_some())) => { // `dict()` or `dict(a=1)` (as opposed to `dict(**a)`) } diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs index aa7636cb75..24dbdcfbf5 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Comprehension, Expr, ExprKind}; +use rustpython_parser::ast::{self, Comprehension, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; use ruff_macros::{derive_message_formats, violation}; @@ -50,10 +50,10 @@ impl AlwaysAutofixableViolation for UnnecessaryComprehension { /// Add diagnostic for C416 based on the expression node id. fn add_diagnostic(checker: &mut Checker, expr: &Expr) { - let id = match &expr.node { - ExprKind::ListComp(_) => "list", - ExprKind::SetComp(_) => "set", - ExprKind::DictComp(_) => "dict", + let id = match expr { + Expr::ListComp(_) => "list", + Expr::SetComp(_) => "set", + Expr::DictComp(_) => "dict", _ => return, }; if !checker.ctx.is_builtin(id) { @@ -95,7 +95,7 @@ pub(crate) fn unnecessary_dict_comprehension( let Some(value_id) = helpers::expr_name(value) else { return; }; - let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &generator.target.node else { + let Expr::Tuple(ast::ExprTuple { elts, .. }) = &generator.target else { return; }; if elts.len() != 2 { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs index 2f870fd542..0eb7b10d43 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Expr, Keyword, Ranged}; use ruff_diagnostics::Violation; use ruff_diagnostics::{AutofixKind, Diagnostic}; @@ -66,11 +66,11 @@ pub(crate) fn unnecessary_comprehension_any_all( if !keywords.is_empty() { return; } - let ExprKind::Name(ast::ExprName { id, .. } )= &func.node else { + let Expr::Name(ast::ExprName { id, .. } )= func else { return; }; if (matches!(id.as_str(), "all" | "any")) && args.len() == 1 { - let (ExprKind::ListComp(ast::ExprListComp { elt, .. } )| ExprKind::SetComp(ast::ExprSetComp { elt, .. })) = &args[0].node else { + let (Expr::ListComp(ast::ExprListComp { elt, .. } )| Expr::SetComp(ast::ExprSetComp { elt, .. })) = &args[0] else { return; }; if is_async_generator(elt) { @@ -91,5 +91,5 @@ pub(crate) fn unnecessary_comprehension_any_all( /// Return `true` if the `Expr` contains an `await` expression. fn is_async_generator(expr: &Expr) -> bool { - any_over_expr(expr, &|expr| matches!(expr.node, ExprKind::Await(_))) + any_over_expr(expr, &|expr| matches!(expr, Expr::Await(_))) } diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs index 2fe1254d3a..ee0767b056 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; use ruff_macros::{derive_message_formats, violation}; @@ -84,7 +84,7 @@ pub(crate) fn unnecessary_double_cast_or_process( let Some(arg) = args.first() else { return; }; - let ExprKind::Call(ast::ExprCall { func, ..} )= &arg.node else { + let Expr::Call(ast::ExprCall { func, ..} )= arg else { return; }; let Some(inner) = helpers::expr_name(func) else { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_dict.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_dict.rs index 49c3d5bc75..9b337ea8fd 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_dict.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_dict.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Expr, Keyword, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; use ruff_macros::{derive_message_formats, violation}; @@ -53,9 +53,9 @@ pub(crate) fn unnecessary_generator_dict( let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else { return; }; - if let ExprKind::GeneratorExp(ast::ExprGeneratorExp { elt, .. }) = argument { - match &elt.node { - ExprKind::Tuple(ast::ExprTuple { elts, .. }) if elts.len() == 2 => { + if let Expr::GeneratorExp(ast::ExprGeneratorExp { elt, .. }) = argument { + match elt.as_ref() { + Expr::Tuple(ast::ExprTuple { elts, .. }) if elts.len() == 2 => { let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorDict, expr.range()); if checker.patch(diagnostic.kind.rule()) { #[allow(deprecated)] diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs index 0ee58fbcb6..db6a5bcf9f 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; use ruff_macros::{derive_message_formats, violation}; @@ -55,7 +55,7 @@ pub(crate) fn unnecessary_generator_list( if !checker.ctx.is_builtin("list") { return; } - if let ExprKind::GeneratorExp(_) = argument { + if let Expr::GeneratorExp(_) = argument { let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorList, expr.range()); if checker.patch(diagnostic.kind.rule()) { #[allow(deprecated)] diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs index df17c1d6e2..eb80f2b5fc 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; use ruff_macros::{derive_message_formats, violation}; @@ -56,7 +56,7 @@ pub(crate) fn unnecessary_generator_set( if !checker.ctx.is_builtin("set") { return; } - if let ExprKind::GeneratorExp(_) = argument { + if let Expr::GeneratorExp(_) = argument { let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorSet, expr.range()); if checker.patch(diagnostic.kind.rule()) { #[allow(deprecated)] diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs index bdbdf82c78..dd3a7c3cc5 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs index 22b9da504b..12e9ee790c 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Expr, Keyword, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -52,10 +52,10 @@ pub(crate) fn unnecessary_list_comprehension_dict( if !checker.ctx.is_builtin("dict") { return; } - let ExprKind::ListComp(ast::ExprListComp { elt, .. }) = &argument else { + let Expr::ListComp(ast::ExprListComp { elt, .. }) = argument else { return; }; - let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &elt.node else { + let Expr::Tuple(ast::ExprTuple { elts, .. }) = elt.as_ref() else { return; }; if elts.len() != 2 { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs index 41fac334f0..49076501f4 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs index 5490304873..0d1890a502 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Expr, Keyword, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -60,14 +60,15 @@ pub(crate) fn unnecessary_literal_dict( return; } let (kind, elts) = match argument { - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => ("tuple", elts), - ExprKind::List(ast::ExprList { elts, .. }) => ("list", elts), + Expr::Tuple(ast::ExprTuple { elts, .. }) => ("tuple", elts), + Expr::List(ast::ExprList { elts, .. }) => ("list", elts), _ => return, }; // Accept `dict((1, 2), ...))` `dict([(1, 2), ...])`. - if !elts.iter().all( - |elt| matches!(&elt.node, ExprKind::Tuple(ast::ExprTuple { elts, .. } )if elts.len() == 2), - ) { + if !elts + .iter() + .all(|elt| matches!(&elt, Expr::Tuple(ast::ExprTuple { elts, .. } )if elts.len() == 2)) + { return; } let mut diagnostic = Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs index ddcdb3b45d..2d58455da0 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -61,8 +61,8 @@ pub(crate) fn unnecessary_literal_set( return; } let kind = match argument { - ExprKind::List(_) => "list", - ExprKind::Tuple(_) => "tuple", + Expr::List(_) => "list", + Expr::Tuple(_) => "tuple", _ => return, }; let mut diagnostic = Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs index 5a4b32cca2..f48ec9c9fb 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use std::fmt; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; @@ -79,8 +79,8 @@ pub(crate) fn unnecessary_literal_within_dict_call( return; } let argument_kind = match argument { - ExprKind::DictComp(_) => DictKind::Comprehension, - ExprKind::Dict(_) => DictKind::Literal, + Expr::DictComp(_) => DictKind::Comprehension, + Expr::Dict(_) => DictKind::Literal, _ => return, }; let mut diagnostic = Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs index b790971fa0..b4f99d7191 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -82,8 +82,8 @@ pub(crate) fn unnecessary_literal_within_list_call( return; } let argument_kind = match argument { - ExprKind::Tuple(_) => "tuple", - ExprKind::List(_) => "list", + Expr::Tuple(_) => "tuple", + Expr::List(_) => "list", _ => return, }; let mut diagnostic = Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs index 92c02354b9..f569a34e00 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -83,8 +83,8 @@ pub(crate) fn unnecessary_literal_within_tuple_call( return; } let argument_kind = match argument { - ExprKind::Tuple(_) => "tuple", - ExprKind::List(_) => "list", + Expr::Tuple(_) => "tuple", + Expr::List(_) => "list", _ => return, }; let mut diagnostic = Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs index ebec47d1f1..e6cf53f68d 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::Diagnostic; use ruff_diagnostics::{AutofixKind, Violation}; @@ -93,17 +93,15 @@ pub(crate) fn unnecessary_map( } // Exclude the parent if already matched by other arms - if let Some(parent) = parent { - if let ExprKind::Call(ast::ExprCall { func: f, .. }) = &parent.node { - if let Some(id_parent) = helpers::expr_name(f) { - if id_parent == "dict" || id_parent == "set" || id_parent == "list" { - return; - } + if let Some(Expr::Call(ast::ExprCall { func: f, .. })) = parent { + if let Some(id_parent) = helpers::expr_name(f) { + if id_parent == "dict" || id_parent == "set" || id_parent == "list" { + return; } - }; + } }; - if args.len() == 2 && matches!(&args[0].node, ExprKind::Lambda(_)) { + if args.len() == 2 && matches!(&args[0], Expr::Lambda(_)) { let mut diagnostic = create_diagnostic("generator", expr.range()); if checker.patch(diagnostic.kind.rule()) { #[allow(deprecated)] @@ -125,30 +123,28 @@ pub(crate) fn unnecessary_map( return; } - if let Some(arg) = args.first() { - if let ExprKind::Call(ast::ExprCall { func, args, .. }) = &arg.node { - if args.len() != 2 { - return; - } - let Some(argument) = helpers::first_argument_with_matching_function("map", func, args) else { + if let Some(Expr::Call(ast::ExprCall { func, args, .. })) = args.first() { + if args.len() != 2 { + return; + } + let Some(argument) = helpers::first_argument_with_matching_function("map", func, args) else { return; }; - if let ExprKind::Lambda(_) = argument { - let mut diagnostic = create_diagnostic(id, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| { - fixes::fix_unnecessary_map( - checker.locator, - checker.stylist, - expr, - parent, - id, - ) - }); - } - checker.diagnostics.push(diagnostic); + if let Expr::Lambda(_) = argument { + let mut diagnostic = create_diagnostic(id, expr.range()); + if checker.patch(diagnostic.kind.rule()) { + #[allow(deprecated)] + diagnostic.try_set_fix_from_edit(|| { + fixes::fix_unnecessary_map( + checker.locator, + checker.stylist, + expr, + parent, + id, + ) + }); } + checker.diagnostics.push(diagnostic); } } } @@ -158,12 +154,12 @@ pub(crate) fn unnecessary_map( } if args.len() == 1 { - if let ExprKind::Call(ast::ExprCall { func, args, .. }) = &args[0].node { + if let Expr::Call(ast::ExprCall { func, args, .. }) = &args[0] { let Some(argument) = helpers::first_argument_with_matching_function("map", func, args) else { return; }; - if let ExprKind::Lambda(ast::ExprLambda { body, .. }) = &argument { - if matches!(&body.node, ExprKind::Tuple(ast::ExprTuple { elts, .. }) | ExprKind::List(ast::ExprList { elts, .. } )if elts.len() == 2) + if let Expr::Lambda(ast::ExprLambda { body, .. }) = argument { + if matches!(body.as_ref(), Expr::Tuple(ast::ExprTuple { elts, .. }) | Expr::List(ast::ExprList { elts, .. } ) if elts.len() == 2) { let mut diagnostic = create_diagnostic(id, expr.range()); if checker.patch(diagnostic.kind.rule()) { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_subscript_reversal.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_subscript_reversal.rs index 3a9467ed21..a27628d774 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_subscript_reversal.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_subscript_reversal.rs @@ -1,5 +1,5 @@ use num_bigint::BigInt; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Unaryop}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged, Unaryop}; use crate::checkers::ast::Checker; use ruff_diagnostics::{Diagnostic, Violation}; @@ -60,10 +60,10 @@ pub(crate) fn unnecessary_subscript_reversal( if !checker.ctx.is_builtin(id) { return; } - let ExprKind::Subscript(ast::ExprSubscript { slice, .. }) = &first_arg.node else { + let Expr::Subscript(ast::ExprSubscript { slice, .. }) = first_arg else { return; }; - let ExprKind::Slice(ast::ExprSlice { lower, upper, step }) = &slice.node else { + let Expr::Slice(ast::ExprSlice { lower, upper, step, range: _ }) = slice.as_ref() else { return; }; if lower.is_some() || upper.is_some() { @@ -72,16 +72,17 @@ pub(crate) fn unnecessary_subscript_reversal( let Some(step) = step.as_ref() else { return; }; - let ExprKind::UnaryOp(ast::ExprUnaryOp { + let Expr::UnaryOp(ast::ExprUnaryOp { op: Unaryop::USub, operand, - }) = &step.node else { + range: _, + }) = step.as_ref() else { return; }; - let ExprKind::Constant(ast::ExprConstant { + let Expr::Constant(ast::ExprConstant { value: Constant::Int(val), .. - }) = &operand.node else { + }) = operand.as_ref() else { return; }; if *val != BigInt::from(1) { diff --git a/crates/ruff/src/rules/flake8_datetimez/rules.rs b/crates/ruff/src/rules/flake8_datetimez/rules.rs index 8821d1e876..de3faa826d 100644 --- a/crates/ruff/src/rules/flake8_datetimez/rules.rs +++ b/crates/ruff/src/rules/flake8_datetimez/rules.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -321,10 +321,11 @@ pub(crate) fn call_datetime_strptime_without_zone( } // Does the `strptime` call contain a format string with a timezone specifier? - if let Some(ExprKind::Constant(ast::ExprConstant { + if let Some(Expr::Constant(ast::ExprConstant { value: Constant::Str(format), kind: None, - })) = args.get(1).as_ref().map(|arg| &arg.node) + range: _, + })) = args.get(1).as_ref() { if format.contains("%z") { return; @@ -339,8 +340,8 @@ pub(crate) fn call_datetime_strptime_without_zone( return; }; - if let ExprKind::Call(ast::ExprCall { keywords, .. }) = &grandparent.node { - if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &parent.node { + if let Expr::Call(ast::ExprCall { keywords, .. }) = grandparent { + if let Expr::Attribute(ast::ExprAttribute { attr, .. }) = parent { let attr = attr.as_str(); // Ex) `datetime.strptime(...).astimezone()` if attr == "astimezone" { diff --git a/crates/ruff/src/rules/flake8_debugger/rules.rs b/crates/ruff/src/rules/flake8_debugger/rules.rs index 015e719bfa..22036b1942 100644 --- a/crates/ruff/src/rules/flake8_debugger/rules.rs +++ b/crates/ruff/src/rules/flake8_debugger/rules.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, Stmt}; +use rustpython_parser::ast::{Expr, Ranged, Stmt}; use crate::checkers::ast::Checker; use crate::rules::flake8_debugger::types::DebuggerUsingType; diff --git a/crates/ruff/src/rules/flake8_django/rules/all_with_model_form.rs b/crates/ruff/src/rules/flake8_django/rules/all_with_model_form.rs index 81bb5efa26..410f83fbfa 100644 --- a/crates/ruff/src/rules/flake8_django/rules/all_with_model_form.rs +++ b/crates/ruff/src/rules/flake8_django/rules/all_with_model_form.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -56,27 +56,27 @@ pub(crate) fn all_with_model_form( return None; } for element in body.iter() { - let StmtKind::ClassDef(ast::StmtClassDef { name, body, .. }) = &element.node else { + let Stmt::ClassDef(ast::StmtClassDef { name, body, .. }) = element else { continue; }; if name != "Meta" { continue; } for element in body.iter() { - let StmtKind::Assign(ast::StmtAssign { targets, value, .. }) = &element.node else { + let Stmt::Assign(ast::StmtAssign { targets, value, .. }) = element else { continue; }; for target in targets.iter() { - let ExprKind::Name(ast::ExprName { id, .. }) = &target.node else { + let Expr::Name(ast::ExprName { id, .. }) = target else { continue; }; if id != "fields" { continue; } - let ExprKind::Constant(ast::ExprConstant { value, .. }) = &value.node else { + let Expr::Constant(ast::ExprConstant { value, .. }) = value.as_ref() else { continue; }; - match &value { + match value { Constant::Str(s) => { if s == "__all__" { return Some(Diagnostic::new(DjangoAllWithModelForm, element.range())); diff --git a/crates/ruff/src/rules/flake8_django/rules/exclude_with_model_form.rs b/crates/ruff/src/rules/flake8_django/rules/exclude_with_model_form.rs index e23aeab4ff..bc3ae08909 100644 --- a/crates/ruff/src/rules/flake8_django/rules/exclude_with_model_form.rs +++ b/crates/ruff/src/rules/flake8_django/rules/exclude_with_model_form.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -54,18 +54,18 @@ pub(crate) fn exclude_with_model_form( return None; } for element in body.iter() { - let StmtKind::ClassDef(ast::StmtClassDef { name, body, .. }) = &element.node else { + let Stmt::ClassDef(ast::StmtClassDef { name, body, .. }) = element else { continue; }; if name != "Meta" { continue; } for element in body.iter() { - let StmtKind::Assign(ast::StmtAssign { targets, .. }) = &element.node else { + let Stmt::Assign(ast::StmtAssign { targets, .. }) = element else { continue; }; for target in targets.iter() { - let ExprKind::Name(ast::ExprName { id, .. }) = &target.node else { + let Expr::Name(ast::ExprName { id, .. }) = target else { continue; }; if id == "exclude" { diff --git a/crates/ruff/src/rules/flake8_django/rules/locals_in_render_function.rs b/crates/ruff/src/rules/flake8_django/rules/locals_in_render_function.rs index 03d3bdee1b..5e3aa9a309 100644 --- a/crates/ruff/src/rules/flake8_django/rules/locals_in_render_function.rs +++ b/crates/ruff/src/rules/flake8_django/rules/locals_in_render_function.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -64,17 +64,14 @@ pub(crate) fn locals_in_render_function( return; } &args[2] - } else if let Some(keyword) = keywords.iter().find(|keyword| { - keyword - .node - .arg - .as_ref() - .map_or(false, |arg| arg == "context") - }) { - if !is_locals_call(checker, &keyword.node.value) { + } else if let Some(keyword) = keywords + .iter() + .find(|keyword| keyword.arg.as_ref().map_or(false, |arg| arg == "context")) + { + if !is_locals_call(checker, &keyword.value) { return; } - &keyword.node.value + &keyword.value } else { return; }; @@ -86,7 +83,7 @@ pub(crate) fn locals_in_render_function( } fn is_locals_call(checker: &Checker, expr: &Expr) -> bool { - let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node else { + let Expr::Call(ast::ExprCall { func, .. }) = expr else { return false }; checker diff --git a/crates/ruff/src/rules/flake8_django/rules/model_without_dunder_str.rs b/crates/ruff/src/rules/flake8_django/rules/model_without_dunder_str.rs index 91e1f47ea1..69853ac571 100644 --- a/crates/ruff/src/rules/flake8_django/rules/model_without_dunder_str.rs +++ b/crates/ruff/src/rules/flake8_django/rules/model_without_dunder_str.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -68,8 +68,8 @@ pub(crate) fn model_without_dunder_str( } fn has_dunder_method(body: &[Stmt]) -> bool { - body.iter().any(|val| match &val.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { name, .. }) => { + body.iter().any(|val| match val { + Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) => { if name == "__str__" { return true; } @@ -94,24 +94,24 @@ fn checker_applies(checker: &Checker, bases: &[Expr], body: &[Stmt]) -> bool { /// Check if class is abstract, in terms of Django model inheritance. fn is_model_abstract(body: &[Stmt]) -> bool { for element in body.iter() { - let StmtKind::ClassDef(ast::StmtClassDef {name, body, ..}) = &element.node else { + let Stmt::ClassDef(ast::StmtClassDef {name, body, ..}) = element else { continue }; if name != "Meta" { continue; } for element in body.iter() { - let StmtKind::Assign(ast::StmtAssign {targets, value, ..}) = &element.node else { + let Stmt::Assign(ast::StmtAssign {targets, value, ..}) = element else { continue; }; for target in targets.iter() { - let ExprKind::Name(ast::ExprName {id , ..}) = &target.node else { + let Expr::Name(ast::ExprName {id , ..}) = target else { continue; }; if id != "abstract" { continue; } - let ExprKind::Constant(ast::ExprConstant{value: Constant::Bool(true), ..}) = &value.node else { + let Expr::Constant(ast::ExprConstant{value: Constant::Bool(true), ..}) = value.as_ref() else { continue; }; return true; diff --git a/crates/ruff/src/rules/flake8_django/rules/non_leading_receiver_decorator.rs b/crates/ruff/src/rules/flake8_django/rules/non_leading_receiver_decorator.rs index fb7bb6144b..1500926eca 100644 --- a/crates/ruff/src/rules/flake8_django/rules/non_leading_receiver_decorator.rs +++ b/crates/ruff/src/rules/flake8_django/rules/non_leading_receiver_decorator.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -58,8 +58,8 @@ where let mut diagnostics = vec![]; let mut seen_receiver = false; for (i, decorator) in decorator_list.iter().enumerate() { - let is_receiver = match &decorator.node { - ExprKind::Call(ast::ExprCall { func, .. }) => resolve_call_path(func) + let is_receiver = match decorator { + Expr::Call(ast::ExprCall { func, .. }) => resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["django", "dispatch", "receiver"] }), diff --git a/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs b/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs index c1d44e6e64..e73d323785 100644 --- a/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs +++ b/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs @@ -1,5 +1,5 @@ use rustpython_parser::ast::Constant::Bool; -use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -64,7 +64,7 @@ const NOT_NULL_TRUE_FIELDS: [&str; 6] = [ pub(crate) fn nullable_model_string_field(checker: &Checker, body: &[Stmt]) -> Vec { let mut errors = Vec::new(); for statement in body.iter() { - let StmtKind::Assign(ast::StmtAssign {value, ..}) = &statement.node else { + let Stmt::Assign(ast::StmtAssign {value, ..}) = statement else { continue }; if let Some(field_name) = is_nullable_field(checker, value) { @@ -80,7 +80,7 @@ pub(crate) fn nullable_model_string_field(checker: &Checker, body: &[Stmt]) -> V } fn is_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a str> { - let ExprKind::Call(ast::ExprCall {func, keywords, ..}) = &value.node else { + let Expr::Call(ast::ExprCall {func, keywords, ..}) = value else { return None; }; @@ -96,10 +96,10 @@ fn is_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a st let mut blank_key = false; let mut unique_key = false; for keyword in keywords.iter() { - let ExprKind::Constant(ast::ExprConstant {value: Bool(true), ..}) = &keyword.node.value.node else { + let Expr::Constant(ast::ExprConstant {value: Bool(true), ..}) = &keyword.value else { continue }; - let Some(argument) = &keyword.node.arg else { + let Some(argument) = &keyword.arg else { continue }; match argument.as_str() { diff --git a/crates/ruff/src/rules/flake8_django/rules/unordered_body_content_in_model.rs b/crates/ruff/src/rules/flake8_django/rules/unordered_body_content_in_model.rs index c555b67373..e8a18c27cb 100644 --- a/crates/ruff/src/rules/flake8_django/rules/unordered_body_content_in_model.rs +++ b/crates/ruff/src/rules/flake8_django/rules/unordered_body_content_in_model.rs @@ -1,6 +1,6 @@ use std::fmt; -use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -99,10 +99,10 @@ impl fmt::Display for ContentType { } } -fn get_element_type(checker: &Checker, element: &StmtKind) -> Option { +fn get_element_type(checker: &Checker, element: &Stmt) -> Option { match element { - StmtKind::Assign(ast::StmtAssign { targets, value, .. }) => { - if let ExprKind::Call(ast::ExprCall { func, .. }) = &value.node { + Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { + if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() { if helpers::is_model_field(&checker.ctx, func) { return Some(ContentType::FieldDeclaration); } @@ -110,7 +110,7 @@ fn get_element_type(checker: &Checker, element: &StmtKind) -> Option Option { + Stmt::ClassDef(ast::StmtClassDef { name, .. }) => { if name == "Meta" { Some(ContentType::MetaClass) } else { None } } - StmtKind::FunctionDef(ast::StmtFunctionDef { name, .. }) => match name.as_str() { + Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) => match name.as_str() { "__str__" => Some(ContentType::StrMethod), "save" => Some(ContentType::SaveMethod), "get_absolute_url" => Some(ContentType::GetAbsoluteUrlMethod), @@ -150,7 +150,7 @@ pub(crate) fn unordered_body_content_in_model( } let mut elements_type_found = Vec::new(); for element in body.iter() { - let Some(current_element_type) = get_element_type(checker, &element.node) else { + let Some(current_element_type) = get_element_type(checker, element) else { continue; }; let Some(&element_type) = elements_type_found diff --git a/crates/ruff/src/rules/flake8_errmsg/rules.rs b/crates/ruff/src/rules/flake8_errmsg/rules.rs index 2c0eb793aa..242b9ef902 100644 --- a/crates/ruff/src/rules/flake8_errmsg/rules.rs +++ b/crates/ruff/src/rules/flake8_errmsg/rules.rs @@ -1,8 +1,9 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind}; +use ruff_text_size::TextRange; +use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Ranged, Stmt}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{create_expr, create_stmt, unparse_stmt}; +use ruff_python_ast::helpers::unparse_stmt; use ruff_python_ast::source_code::Stylist; use ruff_python_ast::whitespace; @@ -183,17 +184,18 @@ impl Violation for DotFormatInException { /// `raise` statement. The variable name is `msg`. /// 2. Replace the exception argument with the variable name. fn generate_fix(stylist: &Stylist, stmt: &Stmt, exc_arg: &Expr, indentation: &str) -> Fix { - let assignment = unparse_stmt( - &create_stmt(StmtKind::Assign(ast::StmtAssign { - targets: vec![create_expr(ExprKind::Name(ast::ExprName { - id: "msg".into(), - ctx: ExprContext::Store, - }))], - value: Box::new(exc_arg.clone()), - type_comment: None, - })), - stylist, - ); + let node = Expr::Name(ast::ExprName { + id: "msg".into(), + ctx: ExprContext::Store, + range: TextRange::default(), + }); + let node1 = Stmt::Assign(ast::StmtAssign { + targets: vec![node], + value: Box::new(exc_arg.clone()), + type_comment: None, + range: TextRange::default(), + }); + let assignment = unparse_stmt(&node1, stylist); #[allow(deprecated)] Fix::unspecified_edits( Edit::insertion( @@ -214,11 +216,11 @@ fn generate_fix(stylist: &Stylist, stmt: &Stmt, exc_arg: &Expr, indentation: &st /// EM101, EM102, EM103 pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr) { - if let ExprKind::Call(ast::ExprCall { args, .. }) = &exc.node { + if let Expr::Call(ast::ExprCall { args, .. }) = exc { if let Some(first) = args.first() { - match &first.node { + match first { // Check for string literals - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: Constant::Str(string), .. }) => { @@ -249,7 +251,7 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr } } // Check for f-strings - ExprKind::JoinedStr(_) => { + Expr::JoinedStr(_) => { if checker.settings.rules.enabled(Rule::FStringInException) { let indentation = whitespace::indentation(checker.locator, stmt).and_then( |indentation| { @@ -275,12 +277,12 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr } } // Check for .format() calls - ExprKind::Call(ast::ExprCall { func, .. }) => { + Expr::Call(ast::ExprCall { func, .. }) => { if checker.settings.rules.enabled(Rule::DotFormatInException) { - if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = - &func.node + if let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = + func.as_ref() { - if attr == "format" && matches!(value.node, ExprKind::Constant(_)) { + if attr == "format" && value.is_constant_expr() { let indentation = whitespace::indentation(checker.locator, stmt) .and_then(|indentation| { if checker.ctx.find_binding("msg").is_none() { diff --git a/crates/ruff/src/rules/flake8_future_annotations/rules.rs b/crates/ruff/src/rules/flake8_future_annotations/rules.rs index f7086d2d2c..4828164b3a 100644 --- a/crates/ruff/src/rules/flake8_future_annotations/rules.rs +++ b/crates/ruff/src/rules/flake8_future_annotations/rules.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/flake8_gettext/rules.rs b/crates/ruff/src/rules/flake8_gettext/rules.rs index 9dabace058..a9df874c77 100644 --- a/crates/ruff/src/rules/flake8_gettext/rules.rs +++ b/crates/ruff/src/rules/flake8_gettext/rules.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Operator}; +use rustpython_parser::ast::{self, Constant, Expr, Operator, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -34,7 +34,7 @@ impl Violation for PrintfInGetTextFuncCall { /// Returns true if the [`Expr`] is an internationalization function call. pub(crate) fn is_gettext_func_call(func: &Expr, functions_names: &[String]) -> bool { - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { + if let Expr::Name(ast::ExprName { id, .. }) = func { functions_names.contains(id.as_ref()) } else { false @@ -44,7 +44,7 @@ pub(crate) fn is_gettext_func_call(func: &Expr, functions_names: &[String]) -> b /// INT001 pub(crate) fn f_string_in_gettext_func_call(args: &[Expr]) -> Option { if let Some(first) = args.first() { - if matches!(first.node, ExprKind::JoinedStr(_)) { + if first.is_joined_str_expr() { return Some(Diagnostic::new(FStringInGetTextFuncCall {}, first.range())); } } @@ -54,8 +54,8 @@ pub(crate) fn f_string_in_gettext_func_call(args: &[Expr]) -> Option /// INT002 pub(crate) fn format_in_gettext_func_call(args: &[Expr]) -> Option { if let Some(first) = args.first() { - if let ExprKind::Call(ast::ExprCall { func, .. }) = &first.node { - if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node { + if let Expr::Call(ast::ExprCall { func, .. }) = &first { + if let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func.as_ref() { if attr == "format" { return Some(Diagnostic::new(FormatInGetTextFuncCall {}, first.range())); } @@ -68,16 +68,16 @@ pub(crate) fn format_in_gettext_func_call(args: &[Expr]) -> Option { /// INT003 pub(crate) fn printf_in_gettext_func_call(args: &[Expr]) -> Option { if let Some(first) = args.first() { - if let ExprKind::BinOp(ast::ExprBinOp { + if let Expr::BinOp(ast::ExprBinOp { op: Operator::Mod { .. }, left, .. - }) = &first.node + }) = &first { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(_), .. - }) = left.node + }) = left.as_ref() { return Some(Diagnostic::new(PrintfInGetTextFuncCall {}, first.range())); } diff --git a/crates/ruff/src/rules/flake8_implicit_str_concat/rules.rs b/crates/ruff/src/rules/flake8_implicit_str_concat/rules.rs index 0a1df5b397..49350098c0 100644 --- a/crates/ruff/src/rules/flake8_implicit_str_concat/rules.rs +++ b/crates/ruff/src/rules/flake8_implicit_str_concat/rules.rs @@ -1,6 +1,6 @@ use itertools::Itertools; use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Operator}; +use rustpython_parser::ast::{self, Constant, Expr, Operator, Ranged}; use rustpython_parser::lexer::LexResult; use rustpython_parser::Tok; @@ -153,19 +153,25 @@ pub(crate) fn implicit( /// ISC003 pub(crate) fn explicit(expr: &Expr) -> Option { - if let ExprKind::BinOp(ast::ExprBinOp { left, op, right }) = &expr.node { + if let Expr::BinOp(ast::ExprBinOp { + left, + op, + right, + range: _, + }) = expr + { if matches!(op, Operator::Add) { if matches!( - left.node, - ExprKind::JoinedStr(_) - | ExprKind::Constant(ast::ExprConstant { + left.as_ref(), + Expr::JoinedStr(_) + | Expr::Constant(ast::ExprConstant { value: Constant::Str(..) | Constant::Bytes(..), .. }) ) && matches!( - right.node, - ExprKind::JoinedStr(_) - | ExprKind::Constant(ast::ExprConstant { + right.as_ref(), + Expr::JoinedStr(_) + | Expr::Constant(ast::ExprConstant { value: Constant::Str(..) | Constant::Bytes(..), .. }) diff --git a/crates/ruff/src/rules/flake8_import_conventions/rules/banned_import_alias.rs b/crates/ruff/src/rules/flake8_import_conventions/rules/banned_import_alias.rs index 66f038553a..c22b9db2ec 100644 --- a/crates/ruff/src/rules/flake8_import_conventions/rules/banned_import_alias.rs +++ b/crates/ruff/src/rules/flake8_import_conventions/rules/banned_import_alias.rs @@ -1,5 +1,5 @@ use rustc_hash::FxHashMap; -use rustpython_parser::ast::Stmt; +use rustpython_parser::ast::{Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/flake8_import_conventions/rules/banned_import_from.rs b/crates/ruff/src/rules/flake8_import_conventions/rules/banned_import_from.rs index ebfdc815d4..f410f3b029 100644 --- a/crates/ruff/src/rules/flake8_import_conventions/rules/banned_import_from.rs +++ b/crates/ruff/src/rules/flake8_import_conventions/rules/banned_import_from.rs @@ -1,5 +1,5 @@ use rustc_hash::FxHashSet; -use rustpython_parser::ast::Stmt; +use rustpython_parser::ast::{Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/flake8_import_conventions/rules/conventional_import_alias.rs b/crates/ruff/src/rules/flake8_import_conventions/rules/conventional_import_alias.rs index 7c18d40b50..58ee94eca0 100644 --- a/crates/ruff/src/rules/flake8_import_conventions/rules/conventional_import_alias.rs +++ b/crates/ruff/src/rules/flake8_import_conventions/rules/conventional_import_alias.rs @@ -1,5 +1,5 @@ use rustc_hash::FxHashMap; -use rustpython_parser::ast::Stmt; +use rustpython_parser::ast::{Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/flake8_logging_format/rules.rs b/crates/ruff/src/rules/flake8_logging_format/rules.rs index 835ebf116b..b30870b3e3 100644 --- a/crates/ruff/src/rules/flake8_logging_format/rules.rs +++ b/crates/ruff/src/rules/flake8_logging_format/rules.rs @@ -1,5 +1,5 @@ use ruff_text_size::{TextRange, TextSize}; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword, Operator}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Operator, Ranged}; use ruff_diagnostics::{Diagnostic, Edit, Fix}; use ruff_python_ast::helpers::{find_keyword, SimpleCallArgs}; @@ -40,9 +40,9 @@ const RESERVED_ATTRS: &[&str; 22] = &[ /// Check logging messages for violations. fn check_msg(checker: &mut Checker, msg: &Expr) { - match &msg.node { + match msg { // Check for string concatenation and percent format. - ExprKind::BinOp(ast::ExprBinOp { op, .. }) => match op { + Expr::BinOp(ast::ExprBinOp { op, .. }) => match op { Operator::Add => { if checker.settings.rules.enabled(Rule::LoggingStringConcat) { checker @@ -60,7 +60,7 @@ fn check_msg(checker: &mut Checker, msg: &Expr) { _ => {} }, // Check for f-strings. - ExprKind::JoinedStr(_) => { + Expr::JoinedStr(_) => { if checker.settings.rules.enabled(Rule::LoggingFString) { checker .diagnostics @@ -68,10 +68,10 @@ fn check_msg(checker: &mut Checker, msg: &Expr) { } } // Check for .format() calls. - ExprKind::Call(ast::ExprCall { func, .. }) => { + Expr::Call(ast::ExprCall { func, .. }) => { if checker.settings.rules.enabled(Rule::LoggingStringFormat) { - if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &func.node { - if attr == "format" && matches!(value.node, ExprKind::Constant(_)) { + if let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = func.as_ref() { + if attr == "format" && value.is_constant_expr() { checker .diagnostics .push(Diagnostic::new(LoggingStringFormat, msg.range())); @@ -85,14 +85,14 @@ fn check_msg(checker: &mut Checker, msg: &Expr) { /// Check contents of the `extra` argument to logging calls. fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) { - match &extra.node.value.node { - ExprKind::Dict(ast::ExprDict { keys, .. }) => { + match &extra.value { + Expr::Dict(ast::ExprDict { keys, .. }) => { for key in keys { if let Some(key) = &key { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(string), .. - }) = &key.node + }) = key { if RESERVED_ATTRS.contains(&string.as_str()) { checker.diagnostics.push(Diagnostic::new( @@ -104,14 +104,14 @@ fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) { } } } - ExprKind::Call(ast::ExprCall { func, keywords, .. }) => { + Expr::Call(ast::ExprCall { func, keywords, .. }) => { if checker .ctx .resolve_call_path(func) .map_or(false, |call_path| call_path.as_slice() == ["", "dict"]) { for keyword in keywords { - if let Some(key) = &keyword.node.arg { + if let Some(key) = &keyword.arg { if RESERVED_ATTRS.contains(&key.as_str()) { checker.diagnostics.push(Diagnostic::new( LoggingExtraAttrClash(key.to_string()), @@ -155,7 +155,7 @@ pub(crate) fn logging_call( return; } - if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &func.node { + if let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = func { if let Some(logging_call_type) = LoggingCallType::from_attribute(attr.as_str()) { let call_args = SimpleCallArgs::new(args, keywords); let level_call_range = TextRange::new(value.end() + TextSize::from(1), func.end()); @@ -205,14 +205,12 @@ pub(crate) fn logging_call( // If `exc_info` is `True` or `sys.exc_info()`, it's redundant; but otherwise, // return. if !(matches!( - exc_info.node.value.node, - ExprKind::Constant(ast::ExprConstant { + exc_info.value, + Expr::Constant(ast::ExprConstant { value: Constant::Bool(true), .. }) - ) || if let ExprKind::Call(ast::ExprCall { func, .. }) = - &exc_info.node.value.node - { + ) || if let Expr::Call(ast::ExprCall { func, .. }) = &exc_info.value { checker .ctx .resolve_call_path(func) diff --git a/crates/ruff/src/rules/flake8_pie/rules.rs b/crates/ruff/src/rules/flake8_pie/rules.rs index b31fbcf72c..5dae8ec66d 100644 --- a/crates/ruff/src/rules/flake8_pie/rules.rs +++ b/crates/ruff/src/rules/flake8_pie/rules.rs @@ -3,16 +3,17 @@ use std::iter; use itertools::Either::{Left, Right}; use log::error; +use ruff_text_size::TextRange; use rustc_hash::FxHashSet; use rustpython_parser::ast::{ - self, Boolop, Constant, Expr, ExprContext, ExprKind, Keyword, Stmt, StmtKind, + self, Boolop, Constant, Expr, ExprContext, ExprLambda, Keyword, Ranged, Stmt, }; use ruff_diagnostics::{AlwaysAutofixableViolation, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::comparable::ComparableExpr; -use ruff_python_ast::helpers::{create_expr, trailing_comment_start_offset, unparse_expr}; +use ruff_python_ast::helpers::{trailing_comment_start_offset, unparse_expr}; use ruff_python_ast::types::RefEquality; use ruff_python_stdlib::identifiers::is_identifier; @@ -301,17 +302,17 @@ pub(crate) fn no_unnecessary_pass(checker: &mut Checker, body: &[Stmt]) { // redundant. Consider removing all `pass` statements instead. let docstring_stmt = &body[0]; let pass_stmt = &body[1]; - let StmtKind::Expr(ast::StmtExpr { value } )= &docstring_stmt.node else { + let Stmt::Expr(ast::StmtExpr { value, range: _ } )= docstring_stmt else { return; }; if matches!( - value.node, - ExprKind::Constant(ast::ExprConstant { + value.as_ref(), + Expr::Constant(ast::ExprConstant { value: Constant::Str(..), .. }) ) { - if matches!(pass_stmt.node, StmtKind::Pass) { + if pass_stmt.is_pass_stmt() { let mut diagnostic = Diagnostic::new(UnnecessaryPass, pass_stmt.range()); if checker.patch(diagnostic.kind.rule()) { if let Some(index) = trailing_comment_start_offset(pass_stmt, checker.locator) { @@ -350,19 +351,19 @@ pub(crate) fn duplicate_class_field_definition<'a, 'b>( let mut seen_targets: FxHashSet<&str> = FxHashSet::default(); for stmt in body { // Extract the property name from the assignment statement. - let target = match &stmt.node { - StmtKind::Assign(ast::StmtAssign { targets, .. }) => { + let target = match stmt { + Stmt::Assign(ast::StmtAssign { targets, .. }) => { if targets.len() != 1 { continue; } - if let ExprKind::Name(ast::ExprName { id, .. }) = &targets[0].node { + if let Expr::Name(ast::ExprName { id, .. }) = &targets[0] { id } else { continue; } } - StmtKind::AnnAssign(ast::StmtAnnAssign { target, .. }) => { - if let ExprKind::Name(ast::ExprName { id, .. }) = &target.node { + Stmt::AnnAssign(ast::StmtAnnAssign { target, .. }) => { + if let Expr::Name(ast::ExprName { id, .. }) = target.as_ref() { id } else { continue; @@ -410,7 +411,7 @@ pub(crate) fn non_unique_enums<'a, 'b>( ) where 'b: 'a, { - let StmtKind::ClassDef(ast::StmtClassDef { bases, .. }) = &parent.node else { + let Stmt::ClassDef(ast::StmtClassDef { bases, .. }) = parent else { return; }; @@ -425,11 +426,11 @@ pub(crate) fn non_unique_enums<'a, 'b>( let mut seen_targets: FxHashSet = FxHashSet::default(); for stmt in body { - let StmtKind::Assign(ast::StmtAssign { value, .. }) = &stmt.node else { + let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else { continue; }; - if let ExprKind::Call(ast::ExprCall { func, .. }) = &value.node { + if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() { if checker .ctx .resolve_call_path(func) @@ -457,7 +458,7 @@ pub(crate) fn unnecessary_spread(checker: &mut Checker, keys: &[Option], v if let (None, value) = item { // We only care about when the key is None which indicates a spread `**` // inside a dict. - if let ExprKind::Dict(_) = value.node { + if let Expr::Dict(_) = value { let diagnostic = Diagnostic::new(UnnecessarySpread, value.range()); checker.diagnostics.push(diagnostic); } @@ -467,10 +468,10 @@ pub(crate) fn unnecessary_spread(checker: &mut Checker, keys: &[Option], v /// Return `true` if a key is a valid keyword argument name. fn is_valid_kwarg_name(key: &Expr) -> bool { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(value), .. - }) = &key.node + }) = key { is_identifier(value) } else { @@ -482,8 +483,8 @@ fn is_valid_kwarg_name(key: &Expr) -> bool { pub(crate) fn unnecessary_dict_kwargs(checker: &mut Checker, expr: &Expr, kwargs: &[Keyword]) { for kw in kwargs { // keyword is a spread operator (indicated by None) - if kw.node.arg.is_none() { - if let ExprKind::Dict(ast::ExprDict { keys, .. }) = &kw.node.value.node { + if kw.arg.is_none() { + if let Expr::Dict(ast::ExprDict { keys, .. }) = &kw.value { // ensure foo(**{"bar-bar": 1}) doesn't error if keys.iter().all(|expr| expr.as_ref().map_or(false, is_valid_kwarg_name)) || // handle case of foo(**{**bar}) @@ -499,17 +500,18 @@ pub(crate) fn unnecessary_dict_kwargs(checker: &mut Checker, expr: &Expr, kwargs /// PIE810 pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) { - let ExprKind::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values }) = &expr.node else { + let Expr::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values, range: _ }) = expr else { return; }; let mut duplicates = BTreeMap::new(); for (index, call) in values.iter().enumerate() { - let ExprKind::Call(ast::ExprCall { + let Expr::Call(ast::ExprCall { func, args, keywords, - }) = &call.node else { + range: _ + }) = &call else { continue }; @@ -517,14 +519,14 @@ pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) { continue; } - let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. } )= &func.node else { + let Expr::Attribute(ast::ExprAttribute { value, attr, .. } )= func.as_ref() else { continue }; if attr != "startswith" && attr != "endswith" { continue; } - let ExprKind::Name(ast::ExprName { id: arg_name, .. } )= &value.node else { + let Expr::Name(ast::ExprName { id: arg_name, .. } )= value.as_ref() else { continue }; @@ -548,7 +550,7 @@ pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) { .iter() .map(|index| &values[*index]) .map(|expr| { - let ExprKind::Call(ast::ExprCall { func: _, args, keywords: _}) = &expr.node else { + let Expr::Call(ast::ExprCall { func: _, args, keywords: _, range: _}) = expr else { unreachable!("{}", format!("Indices should only contain `{attr_name}` calls")) }; args.get(0) @@ -556,35 +558,43 @@ pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) { }) .collect(); - let call = create_expr(ExprKind::Call(ast::ExprCall { - func: Box::new(create_expr(ExprKind::Attribute(ast::ExprAttribute { - value: Box::new(create_expr(ExprKind::Name(ast::ExprName { - id: arg_name.into(), - ctx: ExprContext::Load, - }))), - attr: attr_name.into(), - ctx: ExprContext::Load, - }))), - args: vec![create_expr(ExprKind::Tuple(ast::ExprTuple { - elts: words - .iter() - .flat_map(|value| { - if let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &value.node { - Left(elts.iter()) - } else { - Right(iter::once(*value)) - } - }) - .map(Clone::clone) - .collect(), - ctx: ExprContext::Load, - }))], + let node = Expr::Tuple(ast::ExprTuple { + elts: words + .iter() + .flat_map(|value| { + if let Expr::Tuple(ast::ExprTuple { elts, .. }) = value { + Left(elts.iter()) + } else { + Right(iter::once(*value)) + } + }) + .map(Clone::clone) + .collect(), + ctx: ExprContext::Load, + range: TextRange::default(), + }); + let node1 = Expr::Name(ast::ExprName { + id: arg_name.into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }); + let node2 = Expr::Attribute(ast::ExprAttribute { + value: Box::new(node1), + attr: attr_name.into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }); + let node3 = Expr::Call(ast::ExprCall { + func: Box::new(node2), + args: vec![node], keywords: vec![], - })); + range: TextRange::default(), + }); + let call = node3; // Generate the combined `BoolOp`. let mut call = Some(call); - let bool_op = create_expr(ExprKind::BoolOp(ast::ExprBoolOp { + let node = Expr::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values: values .iter() @@ -597,7 +607,9 @@ pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) { } }) .collect(), - })); + range: TextRange::default(), + }); + let bool_op = node; #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( unparse_expr(&bool_op, checker.stylist), @@ -610,17 +622,20 @@ pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) { } /// PIE807 -pub(crate) fn reimplemented_list_builtin(checker: &mut Checker, expr: &Expr) { - let ExprKind::Lambda(ast::ExprLambda { args, body }) = &expr.node else { - panic!("Expected ExprKind::Lambda"); - }; +pub(crate) fn reimplemented_list_builtin(checker: &mut Checker, expr: &ExprLambda) { + let ExprLambda { + args, + body, + range: _, + } = expr; + if args.args.is_empty() && args.kwonlyargs.is_empty() && args.posonlyargs.is_empty() && args.vararg.is_none() && args.kwarg.is_none() { - if let ExprKind::List(ast::ExprList { elts, .. }) = &body.node { + if let Expr::List(ast::ExprList { elts, .. }) = body.as_ref() { if elts.is_empty() { let mut diagnostic = Diagnostic::new(ReimplementedListBuiltin, expr.range()); if checker.patch(diagnostic.kind.rule()) { diff --git a/crates/ruff/src/rules/flake8_print/rules/print_call.rs b/crates/ruff/src/rules/flake8_print/rules/print_call.rs index 828f9c1368..366ce93962 100644 --- a/crates/ruff/src/rules/flake8_print/rules/print_call.rs +++ b/crates/ruff/src/rules/flake8_print/rules/print_call.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -87,16 +87,17 @@ pub(crate) fn print_call(checker: &mut Checker, func: &Expr, keywords: &[Keyword // or `"sys.stderr"`), don't trigger T201. if let Some(keyword) = keywords .iter() - .find(|keyword| keyword.node.arg.as_ref().map_or(false, |arg| arg == "file")) + .find(|keyword| keyword.arg.as_ref().map_or(false, |arg| arg == "file")) { - if !is_const_none(&keyword.node.value) { - if checker.ctx.resolve_call_path(&keyword.node.value).map_or( - true, - |call_path| { + if !is_const_none(&keyword.value) { + if checker + .ctx + .resolve_call_path(&keyword.value) + .map_or(true, |call_path| { call_path.as_slice() != ["sys", "stdout"] && call_path.as_slice() != ["sys", "stderr"] - }, - ) { + }) + { return; } } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/bad_version_info_comparison.rs b/crates/ruff/src/rules/flake8_pyi/rules/bad_version_info_comparison.rs index 6c86a1b4a3..c1afc2f305 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/bad_version_info_comparison.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/bad_version_info_comparison.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Cmpop, Expr}; +use rustpython_parser::ast::{Cmpop, Expr, Ranged}; use crate::checkers::ast::Checker; use ruff_diagnostics::{Diagnostic, Violation}; diff --git a/crates/ruff/src/rules/flake8_pyi/rules/docstring_in_stubs.rs b/crates/ruff/src/rules/flake8_pyi/rules/docstring_in_stubs.rs index 013808e8e1..924baa9c2b 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/docstring_in_stubs.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/docstring_in_stubs.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/flake8_pyi/rules/duplicate_union_member.rs b/crates/ruff/src/rules/flake8_pyi/rules/duplicate_union_member.rs index a4bb984262..1a10df206f 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/duplicate_union_member.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/duplicate_union_member.rs @@ -1,5 +1,5 @@ use rustc_hash::FxHashSet; -use rustpython_parser::ast::{self, Expr, ExprKind, Operator}; +use rustpython_parser::ast::{self, Expr, Operator, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -45,11 +45,12 @@ fn traverse_union<'a>( // // So we have to traverse both branches in order (left, then right), to report duplicates // in the order they appear in the source code. - if let ExprKind::BinOp(ast::ExprBinOp { + if let Expr::BinOp(ast::ExprBinOp { op: Operator::BitOr, left, right, - }) = &expr.node + range: _, + }) = expr { // Traverse left subtree, then the right subtree, propagating the previous node. traverse_union(seen_nodes, checker, left, Some(expr)); @@ -72,7 +73,7 @@ fn traverse_union<'a>( let parent = parent.expect("Parent node must exist"); // SAFETY: Parent node must have been a `BinOp` in order for us to have traversed it. - let ExprKind::BinOp(ast::ExprBinOp { left, right, .. }) = &parent.node else { + let Expr::BinOp(ast::ExprBinOp { left, right, .. }) = parent else { panic!("Parent node must be a BinOp"); }; @@ -80,7 +81,7 @@ fn traverse_union<'a>( #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( unparse_expr( - if expr.node == left.node { right } else { left }, + if expr == left.as_ref() { right } else { left }, checker.stylist, ), parent.range(), diff --git a/crates/ruff/src/rules/flake8_pyi/rules/non_empty_stub_body.rs b/crates/ruff/src/rules/flake8_pyi/rules/non_empty_stub_body.rs index e20a26976f..a347eea129 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/non_empty_stub_body.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/non_empty_stub_body.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -20,8 +20,8 @@ pub(crate) fn non_empty_stub_body(checker: &mut Checker, body: &[Stmt]) { if body.len() != 1 { return; } - if let StmtKind::Expr(ast::StmtExpr { value }) = &body[0].node { - if let ExprKind::Constant(ast::ExprConstant { value, .. }) = &value.node { + if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = &body[0] { + if let Expr::Constant(ast::ExprConstant { value, .. }) = value.as_ref() { if matches!(value, Constant::Ellipsis | Constant::Str(_)) { return; } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/pass_in_class_body.rs b/crates/ruff/src/rules/flake8_pyi/rules/pass_in_class_body.rs index 9abb89d9c7..4518708979 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/pass_in_class_body.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/pass_in_class_body.rs @@ -7,7 +7,7 @@ use ruff_python_ast::types::RefEquality; use crate::checkers::ast::Checker; use crate::registry::AsRule; -use rustpython_parser::ast::{Stmt, StmtKind}; +use rustpython_parser::ast::{Ranged, Stmt}; #[violation] pub struct PassInClassBody; @@ -35,7 +35,7 @@ pub(crate) fn pass_in_class_body<'a>( } for stmt in body { - if matches!(stmt.node, StmtKind::Pass) { + if stmt.is_pass_stmt() { let mut diagnostic = Diagnostic::new(PassInClassBody, stmt.range()); if checker.patch(diagnostic.kind.rule()) { diff --git a/crates/ruff/src/rules/flake8_pyi/rules/pass_statement_stub_body.rs b/crates/ruff/src/rules/flake8_pyi/rules/pass_statement_stub_body.rs index bcb03d497d..118047c9df 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/pass_statement_stub_body.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/pass_statement_stub_body.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Stmt, StmtKind}; +use rustpython_parser::ast::{Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -20,7 +20,7 @@ pub(crate) fn pass_statement_stub_body(checker: &mut Checker, body: &[Stmt]) { if body.len() != 1 { return; } - if matches!(body[0].node, StmtKind::Pass) { + if body[0].is_pass_stmt() { checker .diagnostics .push(Diagnostic::new(PassStatementStubBody, body[0].range())); diff --git a/crates/ruff/src/rules/flake8_pyi/rules/prefix_type_params.rs b/crates/ruff/src/rules/flake8_pyi/rules/prefix_type_params.rs index 4e2048aaaf..358ea50626 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/prefix_type_params.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/prefix_type_params.rs @@ -1,6 +1,6 @@ use std::fmt; -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -63,13 +63,13 @@ pub(crate) fn prefix_type_params(checker: &mut Checker, value: &Expr, targets: & if targets.len() != 1 { return; } - if let ExprKind::Name(ast::ExprName { id, .. }) = &targets[0].node { + if let Expr::Name(ast::ExprName { id, .. }) = &targets[0] { if id.starts_with('_') { return; } }; - if let ExprKind::Call(ast::ExprCall { func, .. }) = &value.node { + if let Expr::Call(ast::ExprCall { func, .. }) = value { let Some(kind) = checker.ctx.resolve_call_path(func).and_then(|call_path| { if checker.ctx.match_typing_call_path(&call_path, "ParamSpec") { Some(VarKind::ParamSpec) diff --git a/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs b/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs index b0446603f9..d1e5313797 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Arguments, Constant, Expr, ExprKind, Operator, Unaryop}; +use rustpython_parser::ast::{self, Arguments, Constant, Expr, Operator, Ranged, Unaryop}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -93,17 +93,21 @@ fn is_valid_default_value_with_annotation( checker: &Checker, allow_container: bool, ) -> bool { - match &default.node { - ExprKind::List(ast::ExprList { elts, .. }) - | ExprKind::Tuple(ast::ExprTuple { elts, .. }) - | ExprKind::Set(ast::ExprSet { elts }) => { + match default { + Expr::List(ast::ExprList { elts, .. }) + | Expr::Tuple(ast::ExprTuple { elts, .. }) + | Expr::Set(ast::ExprSet { elts, range: _ }) => { return allow_container && elts.len() <= 10 && elts .iter() .all(|e| is_valid_default_value_with_annotation(e, checker, false)); } - ExprKind::Dict(ast::ExprDict { keys, values }) => { + Expr::Dict(ast::ExprDict { + keys, + values, + range: _, + }) => { return allow_container && keys.len() <= 10 && keys.iter().zip(values).all(|(k, v)| { @@ -112,29 +116,29 @@ fn is_valid_default_value_with_annotation( }) && is_valid_default_value_with_annotation(v, checker, false) }); } - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: Constant::Ellipsis | Constant::None, .. }) => { return true; } - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: Constant::Str(..), .. }) => return checker.locator.slice(default.range()).len() <= 50, - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: Constant::Bytes(..), .. }) => return checker.locator.slice(default.range()).len() <= 50, // Ex) `123`, `True`, `False`, `3.14` - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: Constant::Int(..) | Constant::Bool(..) | Constant::Float(..), .. }) => { return checker.locator.slice(default.range()).len() <= 10; } // Ex) `2j` - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: Constant::Complex { real, .. }, .. }) => { @@ -142,30 +146,31 @@ fn is_valid_default_value_with_annotation( return checker.locator.slice(default.range()).len() <= 10; } } - ExprKind::UnaryOp(ast::ExprUnaryOp { + Expr::UnaryOp(ast::ExprUnaryOp { op: Unaryop::USub, operand, + range: _, }) => { // Ex) `-1`, `-3.14` - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Int(..) | Constant::Float(..), .. - }) = &operand.node + }) = operand.as_ref() { return checker.locator.slice(operand.range()).len() <= 10; } // Ex) `-2j` - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Complex { real, .. }, .. - }) = &operand.node + }) = operand.as_ref() { if *real == 0.0 { return checker.locator.slice(operand.range()).len() <= 10; } } // Ex) `-math.inf`, `-math.pi`, etc. - if let ExprKind::Attribute(_) = &operand.node { + if let Expr::Attribute(_) = operand.as_ref() { if checker .ctx .resolve_call_path(operand) @@ -180,34 +185,36 @@ fn is_valid_default_value_with_annotation( } } } - ExprKind::BinOp(ast::ExprBinOp { + Expr::BinOp(ast::ExprBinOp { left, op: Operator::Add | Operator::Sub, right, + range: _, }) => { // Ex) `1 + 2j`, `1 - 2j`, `-1 - 2j`, `-1 + 2j` - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Complex { .. }, .. - }) = right.node + }) = right.as_ref() { // Ex) `1 + 2j`, `1 - 2j` - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Int(..) | Constant::Float(..), .. - }) = &left.node + }) = left.as_ref() { return checker.locator.slice(left.range()).len() <= 10; - } else if let ExprKind::UnaryOp(ast::ExprUnaryOp { + } else if let Expr::UnaryOp(ast::ExprUnaryOp { op: Unaryop::USub, operand, - }) = &left.node + range: _, + }) = left.as_ref() { // Ex) `-1 + 2j`, `-1 - 2j` - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Int(..) | Constant::Float(..), .. - }) = &operand.node + }) = operand.as_ref() { return checker.locator.slice(operand.range()).len() <= 10; } @@ -215,7 +222,7 @@ fn is_valid_default_value_with_annotation( } } // Ex) `math.inf`, `sys.stdin`, etc. - ExprKind::Attribute(_) => { + Expr::Attribute(_) => { if checker .ctx .resolve_call_path(default) @@ -236,16 +243,17 @@ fn is_valid_default_value_with_annotation( /// Returns `true` if an [`Expr`] appears to be a valid PEP 604 union. (e.g. `int | None`) fn is_valid_pep_604_union(annotation: &Expr) -> bool { - match &annotation.node { - ExprKind::BinOp(ast::ExprBinOp { + match annotation { + Expr::BinOp(ast::ExprBinOp { left, op: Operator::BitOr, right, + range: _, }) => is_valid_pep_604_union(left) && is_valid_pep_604_union(right), - ExprKind::Name(_) - | ExprKind::Subscript(_) - | ExprKind::Attribute(_) - | ExprKind::Constant(ast::ExprConstant { + Expr::Name(_) + | Expr::Subscript(_) + | Expr::Attribute(_) + | Expr::Constant(ast::ExprConstant { value: Constant::None, .. }) => true, @@ -256,12 +264,12 @@ fn is_valid_pep_604_union(annotation: &Expr) -> bool { /// Returns `true` if an [`Expr`] appears to be a valid default value without an annotation. fn is_valid_default_value_without_annotation(default: &Expr) -> bool { matches!( - &default.node, - ExprKind::Call(_) - | ExprKind::Name(_) - | ExprKind::Attribute(_) - | ExprKind::Subscript(_) - | ExprKind::Constant(ast::ExprConstant { + default, + Expr::Call(_) + | Expr::Name(_) + | Expr::Attribute(_) + | Expr::Subscript(_) + | Expr::Constant(ast::ExprConstant { value: Constant::Ellipsis | Constant::None, .. }) @@ -271,7 +279,7 @@ fn is_valid_default_value_without_annotation(default: &Expr) -> bool { /// Returns `true` if an [`Expr`] appears to be `TypeVar`, `TypeVarTuple`, `NewType`, or `ParamSpec` /// call. fn is_type_var_like_call(context: &Context, expr: &Expr) -> bool { - let ExprKind::Call(ast::ExprCall { func, .. } )= &expr.node else { + let Expr::Call(ast::ExprCall { func, .. } )= expr else { return false; }; context.resolve_call_path(func).map_or(false, |call_path| { @@ -288,7 +296,7 @@ fn is_type_var_like_call(context: &Context, expr: &Expr) -> bool { /// Returns `true` if this is a "special" assignment which must have a value (e.g., an assignment to /// `__all__`). fn is_special_assignment(context: &Context, target: &Expr) -> bool { - if let ExprKind::Name(ast::ExprName { id, .. }) = &target.node { + if let Expr::Name(ast::ExprName { id, .. }) = target { match id.as_str() { "__all__" => context.scope().kind.is_module(), "__match_args__" | "__slots__" => context.scope().kind.is_class(), @@ -323,7 +331,7 @@ pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, args: &Argum .checked_sub(defaults_start) .and_then(|i| args.defaults.get(i)) { - if arg.node.annotation.is_some() { + if arg.annotation.is_some() { if !is_valid_default_value_with_annotation(default, checker, true) { let mut diagnostic = Diagnostic::new(TypedArgumentDefaultInStub, default.range()); @@ -350,7 +358,7 @@ pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, args: &Argum .checked_sub(defaults_start) .and_then(|i| args.kw_defaults.get(i)) { - if kwarg.node.annotation.is_some() { + if kwarg.annotation.is_some() { if !is_valid_default_value_with_annotation(default, checker, true) { let mut diagnostic = Diagnostic::new(TypedArgumentDefaultInStub, default.range()); @@ -380,7 +388,7 @@ pub(crate) fn argument_simple_defaults(checker: &mut Checker, args: &Arguments) .checked_sub(defaults_start) .and_then(|i| args.defaults.get(i)) { - if arg.node.annotation.is_none() { + if arg.annotation.is_none() { if !is_valid_default_value_with_annotation(default, checker, true) { let mut diagnostic = Diagnostic::new(ArgumentDefaultInStub, default.range()); @@ -407,7 +415,7 @@ pub(crate) fn argument_simple_defaults(checker: &mut Checker, args: &Arguments) .checked_sub(defaults_start) .and_then(|i| args.kw_defaults.get(i)) { - if kwarg.node.annotation.is_none() { + if kwarg.annotation.is_none() { if !is_valid_default_value_with_annotation(default, checker, true) { let mut diagnostic = Diagnostic::new(ArgumentDefaultInStub, default.range()); @@ -434,7 +442,7 @@ pub(crate) fn assignment_default_in_stub(checker: &mut Checker, targets: &[Expr] return; } let target = &targets[0]; - if !matches!(target.node, ExprKind::Name(..)) { + if !target.is_name_expr() { return; } if is_special_assignment(&checker.ctx, target) { @@ -502,7 +510,7 @@ pub(crate) fn unannotated_assignment_in_stub( return; } let target = &targets[0]; - let ExprKind::Name(ast::ExprName { id, .. }) = &target.node else { + let Expr::Name(ast::ExprName { id, .. }) = target else { return; }; if is_special_assignment(&checker.ctx, target) { diff --git a/crates/ruff/src/rules/flake8_pyi/rules/type_alias_naming.rs b/crates/ruff/src/rules/flake8_pyi/rules/type_alias_naming.rs index bccb79fe9f..3bd57edfc4 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/type_alias_naming.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/type_alias_naming.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -60,7 +60,7 @@ fn is_t_suffixed_type_alias(name: &str) -> bool { /// PYI042 pub(crate) fn snake_case_type_alias(checker: &mut Checker, target: &Expr) { - if let ExprKind::Name(ast::ExprName { id, .. }) = target.node() { + if let Expr::Name(ast::ExprName { id, range, .. }) = target { if !is_snake_case_type_alias(id) { return; } @@ -69,14 +69,14 @@ pub(crate) fn snake_case_type_alias(checker: &mut Checker, target: &Expr) { SnakeCaseTypeAlias { name: id.to_string(), }, - target.range(), + *range, )); } } /// PYI043 pub(crate) fn t_suffixed_type_alias(checker: &mut Checker, target: &Expr) { - if let ExprKind::Name(ast::ExprName { id, .. }) = target.node() { + if let Expr::Name(ast::ExprName { id, range, .. }) = target { if !is_t_suffixed_type_alias(id) { return; } @@ -85,7 +85,7 @@ pub(crate) fn t_suffixed_type_alias(checker: &mut Checker, target: &Expr) { TSuffixedTypeAlias { name: id.to_string(), }, - target.range(), + *range, )); } } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_platform.rs b/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_platform.rs index ed070e109a..20f4cb0815 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_platform.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_platform.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Cmpop, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Cmpop, Constant, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -125,8 +125,8 @@ pub(crate) fn unrecognized_platform( return; } - match &right.node { - ExprKind::Constant(ast::ExprConstant { + match right { + Expr::Constant(ast::ExprConstant { value: Constant::Str(value), .. }) => { diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs index 271e8cf403..85776c25ee 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs @@ -5,10 +5,7 @@ use libcst_native::{ ParenthesizableWhitespace, ParenthesizedNode, SimpleStatementLine, SimpleWhitespace, SmallStatement, Statement, Suite, TrailingWhitespace, UnaryOp, UnaryOperation, }; -use rustpython_parser::ast::{ - self, Boolop, Excepthandler, ExcepthandlerKind, Expr, ExprKind, Keyword, Stmt, StmtKind, - Unaryop, -}; +use rustpython_parser::ast::{self, Boolop, Excepthandler, Expr, Keyword, Ranged, Stmt, Unaryop}; use std::borrow::Cow; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; @@ -136,8 +133,8 @@ where 'b: 'a, { fn visit_stmt(&mut self, stmt: &'a Stmt) { - match &stmt.node { - StmtKind::Assert(_) => { + match stmt { + Stmt::Assert(_) => { self.current_assert = Some(stmt); visitor::walk_stmt(self, stmt); self.current_assert = None; @@ -147,10 +144,10 @@ where } fn visit_expr(&mut self, expr: &'a Expr) { - match &expr.node { - ExprKind::Name(ast::ExprName { id, .. }) => { + match expr { + Expr::Name(ast::ExprName { id, .. }) => { if let Some(current_assert) = self.current_assert { - if id == self.exception_name { + if id.as_str() == self.exception_name { self.errors.push(Diagnostic::new( PytestAssertInExcept { name: id.to_string(), @@ -182,12 +179,12 @@ pub(crate) fn unittest_assertion( args: &[Expr], keywords: &[Keyword], ) -> Option { - match &func.node { - ExprKind::Attribute(ast::ExprAttribute { attr, .. }) => { + match func { + Expr::Attribute(ast::ExprAttribute { attr, .. }) => { if let Ok(unittest_assert) = UnittestAssert::try_from(attr.as_str()) { // We're converting an expression to a statement, so avoid applying the fix if // the assertion is part of a larger expression. - let fixable = matches!(checker.ctx.stmt().node, StmtKind::Expr(_)) + let fixable = checker.ctx.stmt().is_expr_stmt() && checker.ctx.expr_parent().is_none() && !checker.ctx.scope().kind.is_lambda() && !has_comments_in(expr.range(), checker.locator); @@ -228,11 +225,9 @@ pub(crate) fn assert_falsy(checker: &mut Checker, stmt: &Stmt, test: &Expr) { pub(crate) fn assert_in_exception_handler(handlers: &[Excepthandler]) -> Vec { handlers .iter() - .flat_map(|handler| match &handler.node { - ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { - name, - body, - .. + .flat_map(|handler| match handler { + Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { + name, body, .. }) => { if let Some(name) = name { check_assert_in_except(name, body) @@ -260,26 +255,28 @@ enum CompositionKind { /// For example, `a and b` or `not (a or b)`. The latter is equivalent to /// `not a and not b` by De Morgan's laws. fn is_composite_condition(test: &Expr) -> CompositionKind { - match &test.node { - ExprKind::BoolOp(ast::ExprBoolOp { + match test { + Expr::BoolOp(ast::ExprBoolOp { op: Boolop::And, .. }) => { return CompositionKind::Simple; } - ExprKind::UnaryOp(ast::ExprUnaryOp { + Expr::UnaryOp(ast::ExprUnaryOp { op: Unaryop::Not, operand, + range: _, }) => { - if let ExprKind::BoolOp(ast::ExprBoolOp { + if let Expr::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values, - }) = &operand.node + range: _, + }) = operand.as_ref() { // Only split cases without mixed `and` and `or`. return if values.iter().all(|expr| { !matches!( - expr.node, - ExprKind::BoolOp(ast::ExprBoolOp { + expr, + Expr::BoolOp(ast::ExprBoolOp { op: Boolop::And, .. }) diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/fail.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/fail.rs index cb61c427c0..f634e3be48 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/fail.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/fail.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/fixture.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/fixture.rs index 6a74211473..7df5b1bd08 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/fixture.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/fixture.rs @@ -1,6 +1,6 @@ use anyhow::Result; use ruff_text_size::{TextLen, TextRange, TextSize}; -use rustpython_parser::ast::{self, Arguments, Expr, ExprKind, Keyword, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Arguments, Expr, Keyword, Ranged, Stmt}; use std::fmt; use ruff_diagnostics::{AlwaysAutofixableViolation, Violation}; @@ -207,29 +207,29 @@ where 'b: 'a, { fn visit_stmt(&mut self, stmt: &'b Stmt) { - match &stmt.node { - StmtKind::Return(ast::StmtReturn { value }) => { + match stmt { + Stmt::Return(ast::StmtReturn { value, range: _ }) => { if value.is_some() { self.has_return_with_value = true; } } - StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_) => {} + Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) => {} _ => visitor::walk_stmt(self, stmt), } } fn visit_expr(&mut self, expr: &'b Expr) { - match &expr.node { - ExprKind::YieldFrom(_) => { + match expr { + Expr::YieldFrom(_) => { self.has_yield_from = true; } - ExprKind::Yield(ast::ExprYield { value }) => { + Expr::Yield(ast::ExprYield { value, range: _ }) => { self.yield_statements.push(expr); if value.is_some() { self.has_return_with_value = true; } } - ExprKind::Call(ast::ExprCall { func, .. }) => { + Expr::Call(ast::ExprCall { func, .. }) => { if collect_call_path(func).map_or(false, |call_path| { call_path.as_slice() == ["request", "addfinalizer"] }) { @@ -277,11 +277,12 @@ pub(crate) fn fix_extraneous_scope_function( /// PT001, PT002, PT003 fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &Expr) { - match &decorator.node { - ExprKind::Call(ast::ExprCall { + match decorator { + Expr::Call(ast::ExprCall { func, args, keywords, + range: _, }) => { if checker .settings @@ -323,7 +324,7 @@ fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &E { let scope_keyword = keywords .iter() - .find(|kw| kw.node.arg.as_ref().map_or(false, |arg| arg == "scope")); + .find(|kw| kw.arg.as_ref().map_or(false, |arg| arg == "scope")); if let Some(scope_keyword) = scope_keyword { if keyword_is_literal(scope_keyword, "function") { @@ -414,8 +415,8 @@ fn check_fixture_returns(checker: &mut Checker, stmt: &Stmt, name: &str, body: & .enabled(Rule::PytestUselessYieldFixture) { if let Some(stmt) = body.last() { - if let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node { - if let ExprKind::Yield(_) = value.node { + if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = stmt { + if value.is_yield_expr() { if visitor.yield_statements.len() == 1 { let mut diagnostic = Diagnostic::new( PytestUselessYieldFixture { @@ -441,7 +442,7 @@ fn check_fixture_returns(checker: &mut Checker, stmt: &Stmt, name: &str, body: & /// PT019 fn check_test_function_args(checker: &mut Checker, args: &Arguments) { args.args.iter().chain(&args.kwonlyargs).for_each(|arg| { - let name = &arg.node.arg; + let name = &arg.arg; if name.starts_with('_') { checker.diagnostics.push(Diagnostic::new( PytestFixtureParamWithoutValue { diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/helpers.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/helpers.rs index 4fa1067103..cd6ea32b81 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/helpers.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/helpers.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword}; use ruff_python_ast::call_path::{collect_call_path, CallPath}; use ruff_python_ast::helpers::map_callable; @@ -48,10 +48,10 @@ pub(super) fn is_pytest_parametrize(context: &Context, decorator: &Expr) -> bool } pub(super) fn keyword_is_literal(kw: &Keyword, literal: &str) -> bool { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(string), .. - }) = &kw.node.value.node + }) = &kw.value { string == literal } else { @@ -60,13 +60,13 @@ pub(super) fn keyword_is_literal(kw: &Keyword, literal: &str) -> bool { } pub(super) fn is_empty_or_null_string(expr: &Expr) -> bool { - match &expr.node { - ExprKind::Constant(ast::ExprConstant { + match expr { + Expr::Constant(ast::ExprConstant { value: Constant::Str(string), .. }) => string.is_empty(), - ExprKind::Constant(constant) if constant.value.is_none() => true, - ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => { + Expr::Constant(constant) if constant.value.is_none() => true, + Expr::JoinedStr(ast::ExprJoinedStr { values, range: _ }) => { values.iter().all(is_empty_or_null_string) } _ => false, diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/imports.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/imports.rs index cb4efe4309..e710b9a15c 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/imports.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/imports.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Stmt; +use rustpython_parser::ast::{Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/marks.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/marks.rs index 39de83ec58..d0dc8fea35 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/marks.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/marks.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextSize; -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -73,11 +73,12 @@ fn pytest_mark_parentheses( } fn check_mark_parentheses(checker: &mut Checker, decorator: &Expr, call_path: &CallPath) { - match &decorator.node { - ExprKind::Call(ast::ExprCall { + match decorator { + Expr::Call(ast::ExprCall { func, args, keywords, + range: _, }) => { if !checker.settings.flake8_pytest_style.mark_parentheses && args.is_empty() @@ -105,7 +106,7 @@ fn check_useless_usefixtures(checker: &mut Checker, decorator: &Expr, call_path: let mut has_parameters = false; - if let ExprKind::Call(ast::ExprCall { args, keywords, .. }) = &decorator.node { + if let Expr::Call(ast::ExprCall { args, keywords, .. }) = decorator { if !args.is_empty() || !keywords.is_empty() { has_parameters = true; } diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs index 2d3ef24aab..d996eaf24a 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs @@ -1,10 +1,10 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Constant, Expr, ExprContext, ExprKind}; +use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Ranged}; use rustpython_parser::{lexer, Mode, Tok}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{create_expr, unparse_expr}; +use ruff_python_ast::helpers::unparse_expr; use crate::checkers::ast::Checker; use crate::registry::{AsRule, Rule}; @@ -49,8 +49,8 @@ impl Violation for PytestParametrizeValuesWrongType { fn elts_to_csv(elts: &[Expr], checker: &Checker) -> Option { let all_literals = elts.iter().all(|e| { matches!( - e.node, - ExprKind::Constant(ast::ExprConstant { + e, + Expr::Constant(ast::ExprConstant { value: Constant::Str(_), .. }) @@ -61,25 +61,24 @@ fn elts_to_csv(elts: &[Expr], checker: &Checker) -> Option { return None; } - Some(unparse_expr( - &create_expr(ExprKind::Constant(ast::ExprConstant { - value: Constant::Str(elts.iter().fold(String::new(), |mut acc, elt| { - if let ExprKind::Constant(ast::ExprConstant { - value: Constant::Str(ref s), - .. - }) = elt.node - { - if !acc.is_empty() { - acc.push(','); - } - acc.push_str(s); + let node = Expr::Constant(ast::ExprConstant { + value: Constant::Str(elts.iter().fold(String::new(), |mut acc, elt| { + if let Expr::Constant(ast::ExprConstant { + value: Constant::Str(ref s), + .. + }) = elt + { + if !acc.is_empty() { + acc.push(','); } - acc - })), - kind: None, + acc.push_str(s); + } + acc })), - checker.stylist, - )) + kind: None, + range: TextRange::default(), + }); + Some(unparse_expr(&node, checker.stylist)) } /// Returns the range of the `name` argument of `@pytest.mark.parametrize`. @@ -132,8 +131,8 @@ fn get_parametrize_name_range(checker: &Checker, decorator: &Expr, expr: &Expr) fn check_names(checker: &mut Checker, decorator: &Expr, expr: &Expr) { let names_type = checker.settings.flake8_pytest_style.parametrize_names_type; - match &expr.node { - ExprKind::Constant(ast::ExprConstant { + match expr { + Expr::Constant(ast::ExprConstant { value: Constant::Str(string), .. }) => { @@ -149,28 +148,23 @@ fn check_names(checker: &mut Checker, decorator: &Expr, expr: &Expr) { name_range, ); if checker.patch(diagnostic.kind.rule()) { + let node = Expr::Tuple(ast::ExprTuple { + elts: names + .iter() + .map(|name| { + Expr::Constant(ast::ExprConstant { + value: Constant::Str((*name).to_string()), + kind: None, + range: TextRange::default(), + }) + }) + .collect(), + ctx: ExprContext::Load, + range: TextRange::default(), + }); #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - format!( - "({})", - unparse_expr( - &create_expr(ExprKind::Tuple(ast::ExprTuple { - elts: names - .iter() - .map(|&name| { - create_expr(ExprKind::Constant( - ast::ExprConstant { - value: Constant::Str(name.to_string()), - kind: None, - }, - )) - }) - .collect(), - ctx: ExprContext::Load, - })), - checker.stylist, - ) - ), + format!("({})", unparse_expr(&node, checker.stylist,)), name_range, ))); } @@ -185,23 +179,23 @@ fn check_names(checker: &mut Checker, decorator: &Expr, expr: &Expr) { name_range, ); if checker.patch(diagnostic.kind.rule()) { + let node = Expr::List(ast::ExprList { + elts: names + .iter() + .map(|name| { + Expr::Constant(ast::ExprConstant { + value: Constant::Str((*name).to_string()), + kind: None, + range: TextRange::default(), + }) + }) + .collect(), + ctx: ExprContext::Load, + range: TextRange::default(), + }); #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - unparse_expr( - &create_expr(ExprKind::List(ast::ExprList { - elts: names - .iter() - .map(|&name| { - create_expr(ExprKind::Constant(ast::ExprConstant { - value: Constant::Str(name.to_string()), - kind: None, - })) - }) - .collect(), - ctx: ExprContext::Load, - })), - checker.stylist, - ), + unparse_expr(&node, checker.stylist), name_range, ))); } @@ -211,7 +205,7 @@ fn check_names(checker: &mut Checker, decorator: &Expr, expr: &Expr) { } } } - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + Expr::Tuple(ast::ExprTuple { elts, .. }) => { if elts.len() == 1 { if let Some(first) = elts.first() { handle_single_name(checker, expr, first); @@ -227,15 +221,14 @@ fn check_names(checker: &mut Checker, decorator: &Expr, expr: &Expr) { expr.range(), ); if checker.patch(diagnostic.kind.rule()) { + let node = Expr::List(ast::ExprList { + elts: elts.clone(), + ctx: ExprContext::Load, + range: TextRange::default(), + }); #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - unparse_expr( - &create_expr(ExprKind::List(ast::ExprList { - elts: elts.clone(), - ctx: ExprContext::Load, - })), - checker.stylist, - ), + unparse_expr(&node, checker.stylist), expr.range(), ))); } @@ -262,7 +255,7 @@ fn check_names(checker: &mut Checker, decorator: &Expr, expr: &Expr) { } }; } - ExprKind::List(ast::ExprList { elts, .. }) => { + Expr::List(ast::ExprList { elts, .. }) => { if elts.len() == 1 { if let Some(first) = elts.first() { handle_single_name(checker, expr, first); @@ -278,18 +271,14 @@ fn check_names(checker: &mut Checker, decorator: &Expr, expr: &Expr) { expr.range(), ); if checker.patch(diagnostic.kind.rule()) { + let node = Expr::Tuple(ast::ExprTuple { + elts: elts.clone(), + ctx: ExprContext::Load, + range: TextRange::default(), + }); #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - format!( - "({})", - unparse_expr( - &create_expr(ExprKind::Tuple(ast::ExprTuple { - elts: elts.clone(), - ctx: ExprContext::Load, - })), - checker.stylist, - ) - ), + format!("({})", unparse_expr(&node, checker.stylist,)), expr.range(), ))); } @@ -329,18 +318,18 @@ fn check_values(checker: &mut Checker, names: &Expr, values: &Expr) { .flake8_pytest_style .parametrize_values_row_type; - let is_multi_named = if let ExprKind::Constant(ast::ExprConstant { + let is_multi_named = if let Expr::Constant(ast::ExprConstant { value: Constant::Str(string), .. - }) = &names.node + }) = &names { split_names(string).len() > 1 } else { true }; - match &values.node { - ExprKind::List(ast::ExprList { elts, .. }) => { + match values { + Expr::List(ast::ExprList { elts, .. }) => { if values_type != types::ParametrizeValuesType::List { checker.diagnostics.push(Diagnostic::new( PytestParametrizeValuesWrongType { @@ -354,7 +343,7 @@ fn check_values(checker: &mut Checker, names: &Expr, values: &Expr) { handle_value_rows(checker, elts, values_type, values_row_type); } } - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + Expr::Tuple(ast::ExprTuple { elts, .. }) => { if values_type != types::ParametrizeValuesType::Tuple { checker.diagnostics.push(Diagnostic::new( PytestParametrizeValuesWrongType { @@ -381,9 +370,10 @@ fn handle_single_name(checker: &mut Checker, expr: &Expr, value: &Expr) { ); if checker.patch(diagnostic.kind.rule()) { + let node = value.clone(); #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - unparse_expr(&create_expr(value.node.clone()), checker.stylist), + unparse_expr(&node, checker.stylist), expr.range(), ))); } @@ -397,8 +387,8 @@ fn handle_value_rows( values_row_type: types::ParametrizeValuesRowType, ) { for elt in elts { - match &elt.node { - ExprKind::Tuple(_) => { + match elt { + Expr::Tuple(_) => { if values_row_type != types::ParametrizeValuesRowType::Tuple { checker.diagnostics.push(Diagnostic::new( PytestParametrizeValuesWrongType { @@ -409,7 +399,7 @@ fn handle_value_rows( )); } } - ExprKind::List(_) => { + Expr::List(_) => { if values_row_type != types::ParametrizeValuesRowType::List { checker.diagnostics.push(Diagnostic::new( PytestParametrizeValuesWrongType { @@ -428,7 +418,7 @@ fn handle_value_rows( pub(crate) fn parametrize(checker: &mut Checker, decorators: &[Expr]) { for decorator in decorators { if is_pytest_parametrize(&checker.ctx, decorator) { - if let ExprKind::Call(ast::ExprCall { args, .. }) = &decorator.node { + if let Expr::Call(ast::ExprCall { args, .. }) = decorator { if checker .settings .rules diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/patch.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/patch.rs index 1cef0b5af8..2bc47f6952 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/patch.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/patch.rs @@ -1,5 +1,5 @@ use rustc_hash::FxHashSet; -use rustpython_parser::ast::{self, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -50,8 +50,8 @@ where 'b: 'a, { fn visit_expr(&mut self, expr: &'b Expr) { - match &expr.node { - ExprKind::Name(ast::ExprName { id, .. }) => { + match expr { + Expr::Name(ast::ExprName { id, .. }) => { if self.names.contains(&id.as_str()) { self.uses_args = true; } @@ -72,20 +72,24 @@ fn check_patch_call( return None; } - if let Some(new_arg) = simple_args.argument("new", new_arg_number) { - if let ExprKind::Lambda(ast::ExprLambda { args, body }) = &new_arg.node { - // Walk the lambda body. - let mut visitor = LambdaBodyVisitor { - names: collect_arg_names(args), - uses_args: false, - }; - visitor.visit_expr(body); + if let Some(Expr::Lambda(ast::ExprLambda { + args, + body, + range: _, + })) = simple_args.argument("new", new_arg_number) + { + // Walk the lambda body. + let mut visitor = LambdaBodyVisitor { + names: collect_arg_names(args), + uses_args: false, + }; + visitor.visit_expr(body); - if !visitor.uses_args { - return Some(Diagnostic::new(PytestPatchWithLambda, call.range())); - } + if !visitor.uses_args { + return Some(Diagnostic::new(PytestPatchWithLambda, call.range())); } } + None } diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs index 33d2f6404a..dd541156ae 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Identifier, Keyword, Stmt, StmtKind, Withitem}; +use rustpython_parser::ast::{self, Expr, Identifier, Keyword, Ranged, Stmt, Withitem}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -59,7 +59,7 @@ const fn is_non_trivial_with_body(body: &[Stmt]) -> bool { if body.len() > 1 { true } else if let Some(first_body_stmt) = body.first() { - !matches!(first_body_stmt.node, StmtKind::Pass) + !first_body_stmt.is_pass_stmt() } else { false } @@ -82,11 +82,11 @@ pub(crate) fn raises_call(checker: &mut Checker, func: &Expr, args: &[Expr], key if checker.settings.rules.enabled(Rule::PytestRaisesTooBroad) { let match_keyword = keywords .iter() - .find(|kw| kw.node.arg == Some(Identifier::new("match"))); + .find(|kw| kw.arg == Some(Identifier::new("match"))); if let Some(exception) = args.first() { if let Some(match_keyword) = match_keyword { - if is_empty_or_null_string(&match_keyword.node.value) { + if is_empty_or_null_string(&match_keyword.value) { exception_needs_match(checker, exception); } } else { @@ -105,8 +105,8 @@ pub(crate) fn complex_raises( ) { let mut is_too_complex = false; - let raises_called = items.iter().any(|item| match &item.context_expr.node { - ExprKind::Call(ast::ExprCall { func, .. }) => is_pytest_raises(checker, func), + let raises_called = items.iter().any(|item| match &item.context_expr { + Expr::Call(ast::ExprCall { func, .. }) => is_pytest_raises(checker, func), _ => false, }); @@ -115,20 +115,20 @@ pub(crate) fn complex_raises( if body.len() > 1 { is_too_complex = true; } else if let Some(first_stmt) = body.first() { - match &first_stmt.node { - StmtKind::With(ast::StmtWith { body, .. }) - | StmtKind::AsyncWith(ast::StmtAsyncWith { body, .. }) => { + match first_stmt { + Stmt::With(ast::StmtWith { body, .. }) + | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { if is_non_trivial_with_body(body) { is_too_complex = true; } } - StmtKind::If(_) - | StmtKind::For(_) - | StmtKind::Match(_) - | StmtKind::AsyncFor(_) - | StmtKind::While(_) - | StmtKind::Try(_) - | StmtKind::TryStar(_) => { + Stmt::If(_) + | Stmt::For(_) + | Stmt::Match(_) + | Stmt::AsyncFor(_) + | Stmt::While(_) + | Stmt::Try(_) + | Stmt::TryStar(_) => { is_too_complex = true; } _ => {} diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/unittest_assert.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/unittest_assert.rs index 064586eff0..81b07d166a 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/unittest_assert.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/unittest_assert.rs @@ -1,12 +1,9 @@ use std::hash::BuildHasherDefault; use anyhow::{anyhow, bail, Result}; +use ruff_text_size::TextRange; use rustc_hash::FxHashMap; -use rustpython_parser::ast::{ - self, Cmpop, Constant, Expr, ExprContext, ExprKind, Keyword, Stmt, StmtKind, Unaryop, -}; - -use ruff_python_ast::helpers::{create_expr, create_stmt}; +use rustpython_parser::ast::{self, Cmpop, Constant, Expr, ExprContext, Keyword, Stmt, Unaryop}; /// An enum to represent the different types of assertions present in the /// `unittest` module. Note: any variants that can't be replaced with plain @@ -145,18 +142,20 @@ impl TryFrom<&str> for UnittestAssert { } fn assert(expr: &Expr, msg: Option<&Expr>) -> Stmt { - create_stmt(StmtKind::Assert(ast::StmtAssert { + Stmt::Assert(ast::StmtAssert { test: Box::new(expr.clone()), msg: msg.map(|msg| Box::new(msg.clone())), - })) + range: TextRange::default(), + }) } fn compare(left: &Expr, cmpop: Cmpop, right: &Expr) -> Expr { - create_expr(ExprKind::Compare(ast::ExprCompare { + Expr::Compare(ast::ExprCompare { left: Box::new(left.clone()), ops: vec![cmpop], comparators: vec![right.clone()], - })) + range: TextRange::default(), + }) } impl UnittestAssert { @@ -207,10 +206,8 @@ impl UnittestAssert { keywords: &'a [Keyword], ) -> Result> { // If we have variable-length arguments, abort. - if args - .iter() - .any(|arg| matches!(arg.node, ExprKind::Starred(_))) - || keywords.iter().any(|kw| kw.node.arg.is_none()) + if args.iter().any(|arg| matches!(arg, Expr::Starred(_))) + || keywords.iter().any(|kw| kw.arg.is_none()) { bail!("Variable-length arguments are not supported"); } @@ -219,8 +216,7 @@ impl UnittestAssert { // If any of the keyword arguments are not in the argument spec, abort. if keywords.iter().any(|kw| { - kw.node - .arg + kw.arg .as_ref() .map_or(false, |kwarg_name| !arg_spec.contains(&kwarg_name.as_str())) }) { @@ -242,12 +238,11 @@ impl UnittestAssert { for arg_name in arg_spec.iter().skip(args.len()) { if let Some(value) = keywords.iter().find_map(|keyword| { if keyword - .node .arg .as_ref() .map_or(false, |kwarg_name| &kwarg_name == arg_name) { - Some(&keyword.node.value) + Some(&keyword.value) } else { None } @@ -263,15 +258,18 @@ impl UnittestAssert { let args = self.args_map(args, keywords)?; match self { UnittestAssert::True | UnittestAssert::False => { - let expr = args + let expr = *args .get("expr") .ok_or_else(|| anyhow!("Missing argument `expr`"))?; let msg = args.get("msg").copied(); Ok(if matches!(self, UnittestAssert::False) { - let unary_expr = create_expr(ExprKind::UnaryOp(ast::ExprUnaryOp { + let node = expr.clone(); + let node1 = Expr::UnaryOp(ast::ExprUnaryOp { op: Unaryop::Not, - operand: Box::new(create_expr(expr.node.clone())), - })); + operand: Box::new(node), + range: TextRange::default(), + }); + let unary_expr = node1; assert(&unary_expr, msg) } else { assert(expr, msg) @@ -334,14 +332,12 @@ impl UnittestAssert { } else { Cmpop::IsNot }; - let expr = compare( - expr, - cmpop, - &create_expr(ExprKind::Constant(ast::ExprConstant { - value: Constant::None, - kind: None, - })), - ); + let node = Expr::Constant(ast::ExprConstant { + value: Constant::None, + kind: None, + range: TextRange::default(), + }); + let expr = compare(expr, cmpop, &node); Ok(assert(&expr, msg)) } UnittestAssert::IsInstance | UnittestAssert::NotIsInstance => { @@ -352,21 +348,27 @@ impl UnittestAssert { .get("cls") .ok_or_else(|| anyhow!("Missing argument `cls`"))?; let msg = args.get("msg").copied(); - let isinstance = create_expr(ast::ExprCall { - func: Box::new(create_expr(ast::ExprName { - id: "isinstance".into(), - ctx: ExprContext::Load, - })), + let node = ast::ExprName { + id: "isinstance".into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node1 = ast::ExprCall { + func: Box::new(node.into()), args: vec![(**obj).clone(), (**cls).clone()], keywords: vec![], - }); + range: TextRange::default(), + }; + let isinstance = node1.into(); if matches!(self, UnittestAssert::IsInstance) { Ok(assert(&isinstance, msg)) } else { - let expr = create_expr(ast::ExprUnaryOp { + let node = ast::ExprUnaryOp { op: Unaryop::Not, operand: Box::new(isinstance), - }); + range: TextRange::default(), + }; + let expr = node.into(); Ok(assert(&expr, msg)) } } @@ -381,28 +383,33 @@ impl UnittestAssert { .get("regex") .ok_or_else(|| anyhow!("Missing argument `regex`"))?; let msg = args.get("msg").copied(); - let re_search = create_expr(ast::ExprCall { - func: Box::new(create_expr(ast::ExprAttribute { - value: Box::new(create_expr(ast::ExprName { - id: "re".into(), - ctx: ExprContext::Load, - })), - attr: "search".into(), - ctx: ExprContext::Load, - })), + let node = ast::ExprName { + id: "re".into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node1 = ast::ExprAttribute { + value: Box::new(node.into()), + attr: "search".into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node2 = ast::ExprCall { + func: Box::new(node1.into()), args: vec![(**regex).clone(), (**text).clone()], keywords: vec![], - }); + range: TextRange::default(), + }; + let re_search = node2.into(); if matches!(self, UnittestAssert::Regex | UnittestAssert::RegexpMatches) { Ok(assert(&re_search, msg)) } else { - Ok(assert( - &create_expr(ast::ExprUnaryOp { - op: Unaryop::Not, - operand: Box::new(re_search), - }), - msg, - )) + let node = ast::ExprUnaryOp { + op: Unaryop::Not, + operand: Box::new(re_search), + range: TextRange::default(), + }; + Ok(assert(&node.into(), msg)) } } _ => bail!("Cannot autofix `{self}`"), diff --git a/crates/ruff/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs b/crates/ruff/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs index 1f8aaa8787..a37c60da20 100644 --- a/crates/ruff/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs +++ b/crates/ruff/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -23,11 +23,12 @@ impl AlwaysAutofixableViolation for UnnecessaryParenOnRaiseException { /// RSE102 pub(crate) fn unnecessary_paren_on_raise_exception(checker: &mut Checker, expr: &Expr) { - if let ExprKind::Call(ast::ExprCall { + if let Expr::Call(ast::ExprCall { func, args, keywords, - }) = &expr.node + range: _, + }) = expr { if args.is_empty() && keywords.is_empty() { let range = match_parens(func.end(), checker.locator) diff --git a/crates/ruff/src/rules/flake8_return/helpers.rs b/crates/ruff/src/rules/flake8_return/helpers.rs index 4fd46778f0..1047785e28 100644 --- a/crates/ruff/src/rules/flake8_return/helpers.rs +++ b/crates/ruff/src/rules/flake8_return/helpers.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextSize; -use rustpython_parser::ast::{Expr, ExprKind, Stmt}; +use rustpython_parser::ast::{Expr, Ranged, Stmt}; use ruff_python_ast::newlines::StrExt; use ruff_python_ast::source_code::Locator; @@ -10,8 +10,8 @@ pub(crate) fn result_exists(returns: &[(&Stmt, Option<&Expr>)]) -> bool { returns.iter().any(|(_, expr)| { expr.map(|expr| { !matches!( - expr.node, - ExprKind::Constant(ref constant) if constant.value.is_none() + expr, + Expr::Constant(ref constant) if constant.value.is_none() ) }) .unwrap_or(false) diff --git a/crates/ruff/src/rules/flake8_return/rules.rs b/crates/ruff/src/rules/flake8_return/rules.rs index 0948f5131e..c293df8396 100644 --- a/crates/ruff/src/rules/flake8_return/rules.rs +++ b/crates/ruff/src/rules/flake8_return/rules.rs @@ -1,6 +1,6 @@ use itertools::Itertools; use ruff_text_size::{TextRange, TextSize}; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged, Stmt}; use ruff_diagnostics::{AlwaysAutofixableViolation, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix}; @@ -331,8 +331,8 @@ fn unnecessary_return_none(checker: &mut Checker, stack: &Stack) { continue; }; if !matches!( - expr.node, - ExprKind::Constant(ast::ExprConstant { + expr, + Expr::Constant(ast::ExprConstant { value: Constant::None, .. }) @@ -402,8 +402,8 @@ fn is_noreturn_func(context: &Context, func: &Expr) -> bool { /// RET503 fn implicit_return(checker: &mut Checker, stmt: &Stmt) { - match &stmt.node { - StmtKind::If(ast::StmtIf { body, orelse, .. }) => { + match stmt { + Stmt::If(ast::StmtIf { body, orelse, .. }) => { if let Some(last_stmt) = body.last() { implicit_return(checker, last_stmt); } @@ -427,25 +427,25 @@ fn implicit_return(checker: &mut Checker, stmt: &Stmt) { checker.diagnostics.push(diagnostic); } } - StmtKind::Assert(ast::StmtAssert { test, .. }) + Stmt::Assert(ast::StmtAssert { test, .. }) if matches!( - test.node, - ExprKind::Constant(ast::ExprConstant { + test.as_ref(), + Expr::Constant(ast::ExprConstant { value: Constant::Bool(false), .. }) ) => {} - StmtKind::While(ast::StmtWhile { test, .. }) + Stmt::While(ast::StmtWhile { test, .. }) if matches!( - test.node, - ExprKind::Constant(ast::ExprConstant { + test.as_ref(), + Expr::Constant(ast::ExprConstant { value: Constant::Bool(true), .. }) ) => {} - StmtKind::For(ast::StmtFor { orelse, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { orelse, .. }) - | StmtKind::While(ast::StmtWhile { orelse, .. }) => { + Stmt::For(ast::StmtFor { orelse, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { orelse, .. }) + | Stmt::While(ast::StmtWhile { orelse, .. }) => { if let Some(last_stmt) = orelse.last() { implicit_return(checker, last_stmt); } else { @@ -466,24 +466,24 @@ fn implicit_return(checker: &mut Checker, stmt: &Stmt) { checker.diagnostics.push(diagnostic); } } - StmtKind::Match(ast::StmtMatch { cases, .. }) => { + Stmt::Match(ast::StmtMatch { cases, .. }) => { for case in cases { if let Some(last_stmt) = case.body.last() { implicit_return(checker, last_stmt); } } } - StmtKind::With(ast::StmtWith { body, .. }) - | StmtKind::AsyncWith(ast::StmtAsyncWith { body, .. }) => { + Stmt::With(ast::StmtWith { body, .. }) + | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { if let Some(last_stmt) = body.last() { implicit_return(checker, last_stmt); } } - StmtKind::Return(_) | StmtKind::Raise(_) | StmtKind::Try(_) | StmtKind::TryStar(_) => {} - StmtKind::Expr(ast::StmtExpr { value }) + Stmt::Return(_) | Stmt::Raise(_) | Stmt::Try(_) | Stmt::TryStar(_) => {} + Stmt::Expr(ast::StmtExpr { value, .. }) if matches!( - &value.node, - ExprKind::Call(ast::ExprCall { func, .. }) + value.as_ref(), + Expr::Call(ast::ExprCall { func, .. }) if is_noreturn_func(&checker.ctx, func) ) => {} _ => { @@ -593,7 +593,7 @@ fn has_refs_or_assigns_within_try_or_loop(id: &str, stack: &Stack) -> bool { /// RET504 fn unnecessary_assign(checker: &mut Checker, stack: &Stack, expr: &Expr) { - if let ExprKind::Name(ast::ExprName { id, .. }) = &expr.node { + if let Expr::Name(ast::ExprName { id, .. }) = expr { if !stack.assignments.contains_key(id.as_str()) { return; } @@ -624,11 +624,11 @@ fn unnecessary_assign(checker: &mut Checker, stack: &Stack, expr: &Expr) { /// RET505, RET506, RET507, RET508 fn superfluous_else_node(checker: &mut Checker, stmt: &Stmt, branch: Branch) -> bool { - let StmtKind::If(ast::StmtIf { body, .. }) = &stmt.node else { + let Stmt::If(ast::StmtIf { body, .. }) = stmt else { return false; }; for child in body { - if matches!(child.node, StmtKind::Return(_)) { + if child.is_return_stmt() { let diagnostic = Diagnostic::new( SuperfluousElseReturn { branch }, elif_else_range(stmt, checker.locator).unwrap_or_else(|| stmt.range()), @@ -637,8 +637,7 @@ fn superfluous_else_node(checker: &mut Checker, stmt: &Stmt, branch: Branch) -> checker.diagnostics.push(diagnostic); } return true; - } - if matches!(child.node, StmtKind::Break) { + } else if child.is_break_stmt() { let diagnostic = Diagnostic::new( SuperfluousElseBreak { branch }, elif_else_range(stmt, checker.locator).unwrap_or_else(|| stmt.range()), @@ -647,8 +646,7 @@ fn superfluous_else_node(checker: &mut Checker, stmt: &Stmt, branch: Branch) -> checker.diagnostics.push(diagnostic); } return true; - } - if matches!(child.node, StmtKind::Raise(_)) { + } else if child.is_raise_stmt() { let diagnostic = Diagnostic::new( SuperfluousElseRaise { branch }, elif_else_range(stmt, checker.locator).unwrap_or_else(|| stmt.range()), @@ -657,8 +655,7 @@ fn superfluous_else_node(checker: &mut Checker, stmt: &Stmt, branch: Branch) -> checker.diagnostics.push(diagnostic); } return true; - } - if matches!(child.node, StmtKind::Continue) { + } else if child.is_continue_stmt() { let diagnostic = Diagnostic::new( SuperfluousElseContinue { branch }, elif_else_range(stmt, checker.locator).unwrap_or_else(|| stmt.range()), @@ -695,7 +692,7 @@ pub(crate) fn function(checker: &mut Checker, body: &[Stmt], returns: Option<&Ex }; // Skip functions that consist of a single return statement. - if body.len() == 1 && matches!(last_stmt.node, StmtKind::Return(_)) { + if body.len() == 1 && matches!(last_stmt, Stmt::Return(_)) { return; } diff --git a/crates/ruff/src/rules/flake8_return/visitor.rs b/crates/ruff/src/rules/flake8_return/visitor.rs index c56a22cf46..c7c3657138 100644 --- a/crates/ruff/src/rules/flake8_return/visitor.rs +++ b/crates/ruff/src/rules/flake8_return/visitor.rs @@ -1,6 +1,6 @@ use ruff_text_size::{TextRange, TextSize}; use rustc_hash::{FxHashMap, FxHashSet}; -use rustpython_parser::ast::{self, Expr, ExprKind, Identifier, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Expr, Identifier, Ranged, Stmt}; use ruff_python_ast::visitor; use ruff_python_ast::visitor::Visitor; @@ -26,14 +26,14 @@ pub(crate) struct ReturnVisitor<'a> { impl<'a> ReturnVisitor<'a> { fn visit_assign_target(&mut self, expr: &'a Expr) { - match &expr.node { - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + match expr { + Expr::Tuple(ast::ExprTuple { elts, .. }) => { for elt in elts { self.visit_assign_target(elt); } return; } - ExprKind::Name(ast::ExprName { id, .. }) => { + Expr::Name(ast::ExprName { id, .. }) => { self.stack .assignments .entry(id) @@ -41,7 +41,7 @@ impl<'a> ReturnVisitor<'a> { .push(expr.start()); return; } - ExprKind::Attribute(_) => { + Expr::Attribute(_) => { // Attribute assignments are often side-effects (e.g., `self.property = value`), // so we conservatively treat them as references to every known // variable. @@ -61,20 +61,20 @@ impl<'a> ReturnVisitor<'a> { impl<'a> Visitor<'a> for ReturnVisitor<'a> { fn visit_stmt(&mut self, stmt: &'a Stmt) { - match &stmt.node { - StmtKind::Global(ast::StmtGlobal { names }) - | StmtKind::Nonlocal(ast::StmtNonlocal { names }) => { + match stmt { + Stmt::Global(ast::StmtGlobal { names, range: _ }) + | Stmt::Nonlocal(ast::StmtNonlocal { names, range: _ }) => { self.stack .non_locals .extend(names.iter().map(Identifier::as_str)); } - StmtKind::FunctionDef(ast::StmtFunctionDef { + Stmt::FunctionDef(ast::StmtFunctionDef { decorator_list, args, returns, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { decorator_list, args, returns, @@ -89,7 +89,7 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> { } visitor::walk_arguments(self, args); } - StmtKind::Return(ast::StmtReturn { value }) => { + Stmt::Return(ast::StmtReturn { value, range: _ }) => { self.stack .returns .push((stmt, value.as_ref().map(|expr| &**expr))); @@ -98,9 +98,9 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> { visitor::walk_stmt(self, stmt); self.parents.pop(); } - StmtKind::If(ast::StmtIf { orelse, .. }) => { + Stmt::If(ast::StmtIf { orelse, .. }) => { let is_elif_arm = self.parents.iter().any(|parent| { - if let StmtKind::If(ast::StmtIf { orelse, .. }) = &parent.node { + if let Stmt::If(ast::StmtIf { orelse, .. }) = parent { orelse.len() == 1 && &orelse[0] == stmt } else { false @@ -108,8 +108,8 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> { }); if !is_elif_arm { - let has_elif = orelse.len() == 1 - && matches!(orelse.first().unwrap().node, StmtKind::If(_)); + let has_elif = + orelse.len() == 1 && matches!(orelse.first().unwrap(), Stmt::If(_)); let has_else = !orelse.is_empty(); if has_elif { @@ -125,8 +125,8 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> { visitor::walk_stmt(self, stmt); self.parents.pop(); } - StmtKind::Assign(ast::StmtAssign { targets, value, .. }) => { - if let ExprKind::Name(ast::ExprName { id, .. }) = &value.node { + Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { + if let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() { self.stack .references .entry(id) @@ -138,23 +138,21 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> { if let Some(target) = targets.first() { // Skip unpacking assignments, like `x, y = my_object`. - if matches!(target.node, ExprKind::Tuple(_)) - && !matches!(value.node, ExprKind::Tuple(_)) - { + if matches!(target, Expr::Tuple(_)) && !value.is_tuple_expr() { return; } self.visit_assign_target(target); } } - StmtKind::For(_) | StmtKind::AsyncFor(_) | StmtKind::While(_) => { + Stmt::For(_) | Stmt::AsyncFor(_) | Stmt::While(_) => { self.stack.loops.push(stmt.range()); self.parents.push(stmt); visitor::walk_stmt(self, stmt); self.parents.pop(); } - StmtKind::Try(_) | StmtKind::TryStar(_) => { + Stmt::Try(_) | Stmt::TryStar(_) => { self.stack.tries.push(stmt.range()); self.parents.push(stmt); @@ -170,8 +168,8 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> { } fn visit_expr(&mut self, expr: &'a Expr) { - match &expr.node { - ExprKind::Call(_) => { + match expr { + Expr::Call(_) => { // Arbitrary function calls can have side effects, so we conservatively treat // every function call as a reference to every known variable. for name in self.stack.assignments.keys() { @@ -182,14 +180,14 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> { .push(expr.start()); } } - ExprKind::Name(ast::ExprName { id, .. }) => { + Expr::Name(ast::ExprName { id, .. }) => { self.stack .references .entry(id) .or_insert_with(Vec::new) .push(expr.start()); } - ExprKind::YieldFrom(_) | ExprKind::Yield(_) => { + Expr::YieldFrom(_) | Expr::Yield(_) => { self.stack.yields.push(expr); } _ => visitor::walk_expr(self, expr), diff --git a/crates/ruff/src/rules/flake8_self/rules/private_member_access.rs b/crates/ruff/src/rules/flake8_self/rules/private_member_access.rs index d3feab126e..da01985e1c 100644 --- a/crates/ruff/src/rules/flake8_self/rules/private_member_access.rs +++ b/crates/ruff/src/rules/flake8_self/rules/private_member_access.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -62,7 +62,7 @@ impl Violation for PrivateMemberAccess { /// SLF001 pub(crate) fn private_member_access(checker: &mut Checker, expr: &Expr) { - if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &expr.node { + if let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = expr { if (attr.starts_with("__") && !attr.ends_with("__")) || (attr.starts_with('_') && !attr.starts_with("__")) { @@ -75,7 +75,7 @@ pub(crate) fn private_member_access(checker: &mut Checker, expr: &Expr) { return; } - if let ExprKind::Call(ast::ExprCall { func, .. }) = &value.node { + if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() { // Ignore `super()` calls. if let Some(call_path) = collect_call_path(func) { if call_path.as_slice() == ["super"] { diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs index 6672b01987..85285e00a7 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs @@ -5,14 +5,12 @@ use itertools::Either::{Left, Right}; use itertools::Itertools; use ruff_text_size::TextRange; use rustc_hash::FxHashMap; -use rustpython_parser::ast::{self, Boolop, Cmpop, Expr, ExprContext, ExprKind, Unaryop}; +use rustpython_parser::ast::{self, Boolop, Cmpop, Expr, ExprContext, Ranged, Unaryop}; use ruff_diagnostics::{AlwaysAutofixableViolation, AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::comparable::ComparableExpr; -use ruff_python_ast::helpers::{ - contains_effect, create_expr, has_comments, unparse_expr, Truthiness, -}; +use ruff_python_ast::helpers::{contains_effect, has_comments, unparse_expr, Truthiness}; use ruff_python_ast::source_code::Stylist; use ruff_python_semantic::context::Context; @@ -239,10 +237,8 @@ impl AlwaysAutofixableViolation for ExprAndFalse { /// Return `true` if two `Expr` instances are equivalent names. fn is_same_expr<'a>(a: &'a Expr, b: &'a Expr) -> Option<&'a str> { - if let ( - ExprKind::Name(ast::ExprName { id: a, .. }), - ExprKind::Name(ast::ExprName { id: b, .. }), - ) = (&a.node, &b.node) + if let (Expr::Name(ast::ExprName { id: a, .. }), Expr::Name(ast::ExprName { id: b, .. })) = + (&a, &b) { if a == b { return Some(a); @@ -253,7 +249,7 @@ fn is_same_expr<'a>(a: &'a Expr, b: &'a Expr) -> Option<&'a str> { /// SIM101 pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { - let ExprKind::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values } )= &expr.node else { + let Expr::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values, range: _ } )= expr else { return; }; @@ -262,7 +258,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { let mut duplicates: FxHashMap> = FxHashMap::default(); for (index, call) in values.iter().enumerate() { // Verify that this is an `isinstance` call. - let ExprKind::Call(ast::ExprCall { func, args, keywords }) = &call.node else { + let Expr::Call(ast::ExprCall { func, args, keywords, range: _ }) = &call else { continue; }; if args.len() != 2 { @@ -271,7 +267,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { if !keywords.is_empty() { continue; } - let ExprKind::Name(ast::ExprName { id: func_name, .. }) = &func.node else { + let Expr::Name(ast::ExprName { id: func_name, .. }) = func.as_ref() else { continue; }; if func_name != "isinstance" { @@ -294,16 +290,15 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { if indices.len() > 1 { // Grab the target used in each duplicate `isinstance` call (e.g., `obj` in // `isinstance(obj, int)`). - let target = - if let ExprKind::Call(ast::ExprCall { args, .. }) = &values[indices[0]].node { - args.get(0).expect("`isinstance` should have two arguments") - } else { - unreachable!("Indices should only contain `isinstance` calls") - }; + let target = if let Expr::Call(ast::ExprCall { args, .. }) = &values[indices[0]] { + args.get(0).expect("`isinstance` should have two arguments") + } else { + unreachable!("Indices should only contain `isinstance` calls") + }; let fixable = !contains_effect(target, |id| checker.ctx.is_builtin(id)); let mut diagnostic = Diagnostic::new( DuplicateIsinstanceCall { - name: if let ExprKind::Name(ast::ExprName { id, .. }) = &target.node { + name: if let Expr::Name(ast::ExprName { id, .. }) = target { Some(id.to_string()) } else { None @@ -318,7 +313,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { .iter() .map(|index| &values[*index]) .map(|expr| { - let ExprKind::Call(ast::ExprCall { args, ..}) = &expr.node else { + let Expr::Call(ast::ExprCall { args, ..}) = expr else { unreachable!("Indices should only contain `isinstance` calls") }; args.get(1).expect("`isinstance` should have two arguments") @@ -326,36 +321,37 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { .collect(); // Generate a single `isinstance` call. - let call = create_expr(ast::ExprCall { - func: Box::new(create_expr(ast::ExprName { - id: "isinstance".into(), - ctx: ExprContext::Load, - })), - args: vec![ - target.clone(), - create_expr(ast::ExprTuple { - // Flatten all the types used across the `isinstance` calls. - elts: types - .iter() - .flat_map(|value| { - if let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = - &value.node - { - Left(elts.iter()) - } else { - Right(iter::once(*value)) - } - }) - .map(Clone::clone) - .collect(), - ctx: ExprContext::Load, - }), - ], + let node = ast::ExprTuple { + // Flatten all the types used across the `isinstance` calls. + elts: types + .iter() + .flat_map(|value| { + if let Expr::Tuple(ast::ExprTuple { elts, .. }) = value { + Left(elts.iter()) + } else { + Right(iter::once(*value)) + } + }) + .map(Clone::clone) + .collect(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node1 = ast::ExprName { + id: "isinstance".into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node2 = ast::ExprCall { + func: Box::new(node1.into()), + args: vec![target.clone(), node.into()], keywords: vec![], - }); + range: TextRange::default(), + }; + let call = node2.into(); // Generate the combined `BoolOp`. - let bool_op = create_expr(ast::ExprBoolOp { + let node = ast::ExprBoolOp { op: Boolop::Or, values: iter::once(call) .chain( @@ -366,7 +362,9 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { .map(|(_, elt)| elt.clone()), ) .collect(), - }); + range: TextRange::default(), + }; + let bool_op = node.into(); // Populate the `Fix`. Replace the _entire_ `BoolOp`. Note that if we have // multiple duplicates, the fixes will conflict. @@ -382,7 +380,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { } fn match_eq_target(expr: &Expr) -> Option<(&str, &Expr)> { - let ExprKind::Compare(ast::ExprCompare { left, ops, comparators } )= &expr.node else { + let Expr::Compare(ast::ExprCompare { left, ops, comparators, range: _ } )= expr else { return None; }; if ops.len() != 1 || comparators.len() != 1 { @@ -391,11 +389,11 @@ fn match_eq_target(expr: &Expr) -> Option<(&str, &Expr)> { if !matches!(&ops[0], Cmpop::Eq) { return None; } - let ExprKind::Name(ast::ExprName { id, .. }) = &left.node else { + let Expr::Name(ast::ExprName { id, .. }) = left.as_ref() else { return None; }; let comparator = &comparators[0]; - if !matches!(&comparator.node, ExprKind::Name(_)) { + if !matches!(&comparator, Expr::Name(_)) { return None; } Some((id, comparator)) @@ -403,7 +401,7 @@ fn match_eq_target(expr: &Expr) -> Option<(&str, &Expr)> { /// SIM109 pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) { - let ExprKind::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values }) = &expr.node else { + let Expr::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values, range: _ }) = expr else { return; }; @@ -440,17 +438,23 @@ pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) { } // Create a `x in (a, b)` expression. - let in_expr = create_expr(ast::ExprCompare { - left: Box::new(create_expr(ast::ExprName { - id: id.into(), - ctx: ExprContext::Load, - })), + let node = ast::ExprTuple { + elts: comparators.into_iter().map(Clone::clone).collect(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node1 = ast::ExprName { + id: id.into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node2 = ast::ExprCompare { + left: Box::new(node1.into()), ops: vec![Cmpop::In], - comparators: vec![create_expr(ast::ExprTuple { - elts: comparators.into_iter().map(Clone::clone).collect(), - ctx: ExprContext::Load, - })], - }); + comparators: vec![node.into()], + range: TextRange::default(), + }; + let in_expr = node2.into(); let mut diagnostic = Diagnostic::new( CompareWithTuple { replacement: unparse_expr(&in_expr, checker.stylist), @@ -468,10 +472,12 @@ pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) { in_expr } else { // Wrap in a `x in (a, b) or ...` boolean operation. - create_expr(ast::ExprBoolOp { + let node = ast::ExprBoolOp { op: Boolop::Or, values: iter::once(in_expr).chain(unmatched).collect(), - }) + range: TextRange::default(), + }; + node.into() }; #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( @@ -485,7 +491,7 @@ pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) { /// SIM220 pub(crate) fn expr_and_not_expr(checker: &mut Checker, expr: &Expr) { - let ExprKind::BoolOp(ast::ExprBoolOp { op: Boolop::And, values, }) = &expr.node else { + let Expr::BoolOp(ast::ExprBoolOp { op: Boolop::And, values, range: _, }) = expr else { return; }; if values.len() < 2 { @@ -496,10 +502,11 @@ pub(crate) fn expr_and_not_expr(checker: &mut Checker, expr: &Expr) { let mut negated_expr = vec![]; let mut non_negated_expr = vec![]; for expr in values { - if let ExprKind::UnaryOp(ast::ExprUnaryOp { + if let Expr::UnaryOp(ast::ExprUnaryOp { op: Unaryop::Not, operand, - }) = &expr.node + range: _, + }) = expr { negated_expr.push(operand); } else { @@ -539,7 +546,7 @@ pub(crate) fn expr_and_not_expr(checker: &mut Checker, expr: &Expr) { /// SIM221 pub(crate) fn expr_or_not_expr(checker: &mut Checker, expr: &Expr) { - let ExprKind::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values, }) = &expr.node else { + let Expr::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values, range: _, }) = expr else { return; }; if values.len() < 2 { @@ -550,10 +557,11 @@ pub(crate) fn expr_or_not_expr(checker: &mut Checker, expr: &Expr) { let mut negated_expr = vec![]; let mut non_negated_expr = vec![]; for expr in values { - if let ExprKind::UnaryOp(ast::ExprUnaryOp { + if let Expr::UnaryOp(ast::ExprUnaryOp { op: Unaryop::Not, operand, - }) = &expr.node + range: _, + }) = expr { negated_expr.push(operand); } else { @@ -614,14 +622,14 @@ pub(crate) fn get_short_circuit_edit( fn is_short_circuit( expr: &Expr, - expected_op: &Boolop, + expected_op: Boolop, context: &Context, stylist: &Stylist, ) -> Option<(Edit, ContentAround)> { - let ExprKind::BoolOp(ast::ExprBoolOp { op, values, }) = &expr.node else { + let Expr::BoolOp(ast::ExprBoolOp { op, values, range: _, }) = expr else { return None; }; - if op != expected_op { + if *op != expected_op { return None; } let short_circuit_truthiness = match op { @@ -693,7 +701,7 @@ fn is_short_circuit( /// SIM222 pub(crate) fn expr_or_true(checker: &mut Checker, expr: &Expr) { - if let Some((edit, remove)) = is_short_circuit(expr, &Boolop::Or, &checker.ctx, checker.stylist) + if let Some((edit, remove)) = is_short_circuit(expr, Boolop::Or, &checker.ctx, checker.stylist) { let mut diagnostic = Diagnostic::new( ExprOrTrue { @@ -712,8 +720,7 @@ pub(crate) fn expr_or_true(checker: &mut Checker, expr: &Expr) { /// SIM223 pub(crate) fn expr_and_false(checker: &mut Checker, expr: &Expr) { - if let Some((edit, remove)) = - is_short_circuit(expr, &Boolop::And, &checker.ctx, checker.stylist) + if let Some((edit, remove)) = is_short_circuit(expr, Boolop::And, &checker.ctx, checker.stylist) { let mut diagnostic = Diagnostic::new( ExprAndFalse { diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs index 90740e77ef..399621a6b6 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs @@ -1,8 +1,9 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind}; +use ruff_text_size::TextRange; +use rustpython_parser::ast::{self, Constant, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{create_expr, unparse_expr}; +use ruff_python_ast::helpers::unparse_expr; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -71,19 +72,19 @@ impl AlwaysAutofixableViolation for DictGetWithNoneDefault { /// SIM112 pub(crate) fn use_capital_environment_variables(checker: &mut Checker, expr: &Expr) { // Ex) `os.environ['foo']` - if let ExprKind::Subscript(_) = &expr.node { + if let Expr::Subscript(_) = expr { check_os_environ_subscript(checker, expr); return; } // Ex) `os.environ.get('foo')`, `os.getenv('foo')` - let ExprKind::Call(ast::ExprCall { func, args, .. }) = &expr.node else { + let Expr::Call(ast::ExprCall { func, args, .. }) = expr else { return; }; let Some(arg) = args.get(0) else { return; }; - let ExprKind::Constant(ast::ExprConstant { value: Constant::Str(env_var), .. }) = &arg.node else { + let Expr::Constant(ast::ExprConstant { value: Constant::Str(env_var), .. }) = arg else { return; }; if !checker @@ -112,19 +113,19 @@ pub(crate) fn use_capital_environment_variables(checker: &mut Checker, expr: &Ex } fn check_os_environ_subscript(checker: &mut Checker, expr: &Expr) { - let ExprKind::Subscript(ast::ExprSubscript { value, slice, .. }) = &expr.node else { + let Expr::Subscript(ast::ExprSubscript { value, slice, .. }) = expr else { return; }; - let ExprKind::Attribute(ast::ExprAttribute { value: attr_value, attr, .. }) = &value.node else { + let Expr::Attribute(ast::ExprAttribute { value: attr_value, attr, .. }) = value.as_ref() else { return; }; - let ExprKind::Name(ast::ExprName { id, .. }) = &attr_value.node else { + let Expr::Name(ast::ExprName { id, .. }) = attr_value.as_ref() else { return; }; if id != "os" || attr != "environ" { return; } - let ExprKind::Constant(ast::ExprConstant { value: Constant::Str(env_var), kind }) = &slice.node else { + let Expr::Constant(ast::ExprConstant { value: Constant::Str(env_var), kind, range: _ }) = slice.as_ref() else { return; }; let capital_env_var = env_var.to_ascii_uppercase(); @@ -140,10 +141,12 @@ fn check_os_environ_subscript(checker: &mut Checker, expr: &Expr) { slice.range(), ); if checker.patch(diagnostic.kind.rule()) { - let new_env_var = create_expr(ast::ExprConstant { + let node = ast::ExprConstant { value: capital_env_var.into(), kind: kind.clone(), - }); + range: TextRange::default(), + }; + let new_env_var = node.into(); #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( unparse_expr(&new_env_var, checker.stylist), @@ -155,16 +158,16 @@ fn check_os_environ_subscript(checker: &mut Checker, expr: &Expr) { /// SIM910 pub(crate) fn dict_get_with_none_default(checker: &mut Checker, expr: &Expr) { - let ExprKind::Call(ast::ExprCall { func, args, keywords }) = &expr.node else { + let Expr::Call(ast::ExprCall { func, args, keywords, range: _ }) = expr else { return; }; if !keywords.is_empty() { return; } - let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. } )= &func.node else { + let Expr::Attribute(ast::ExprAttribute { value, attr, .. } )= func.as_ref() else { return; }; - if !matches!(value.node, ExprKind::Dict(_)) { + if !value.is_dict_expr() { return; } if attr != "get" { @@ -173,15 +176,15 @@ pub(crate) fn dict_get_with_none_default(checker: &mut Checker, expr: &Expr) { let Some(key) = args.get(0) else { return; }; - if !matches!(key.node, ExprKind::Constant(_) | ExprKind::Name(_)) { + if !matches!(key, Expr::Constant(_) | Expr::Name(_)) { return; } let Some(default) = args.get(1) else { return; }; if !matches!( - default.node, - ExprKind::Constant(ast::ExprConstant { + default, + Expr::Constant(ast::ExprConstant { value: Constant::None, .. }) diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs index 28f7786a62..2094271f20 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs @@ -1,15 +1,15 @@ use log::error; use ruff_text_size::TextRange; use rustc_hash::FxHashSet; -use rustpython_parser::ast::{self, Cmpop, Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Cmpop, Constant, Expr, ExprContext, Ranged, Stmt}; use unicode_width::UnicodeWidthStr; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::comparable::{ComparableConstant, ComparableExpr, ComparableStmt}; use ruff_python_ast::helpers::{ - any_over_expr, contains_effect, create_expr, create_stmt, first_colon_range, has_comments, - has_comments_in, unparse_expr, unparse_stmt, + any_over_expr, contains_effect, first_colon_range, has_comments, has_comments_in, unparse_expr, + unparse_stmt, }; use ruff_python_ast::newlines::StrExt; use ruff_python_semantic::context::Context; @@ -173,17 +173,17 @@ impl Violation for IfElseBlockInsteadOfDictGet { } fn is_main_check(expr: &Expr) -> bool { - if let ExprKind::Compare(ast::ExprCompare { + if let Expr::Compare(ast::ExprCompare { left, comparators, .. - }) = &expr.node + }) = expr { - if let ExprKind::Name(ast::ExprName { id, .. }) = &left.node { + if let Expr::Name(ast::ExprName { id, .. }) = left.as_ref() { if id == "__name__" { if comparators.len() == 1 { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(value), .. - }) = &comparators[0].node + }) = &comparators[0] { if value == "__main__" { return true; @@ -208,7 +208,7 @@ fn is_main_check(expr: &Expr) -> bool { /// ... /// ``` fn find_last_nested_if(body: &[Stmt]) -> Option<(&Expr, &Stmt)> { - let [Stmt { node: StmtKind::If(ast::StmtIf { test, body: inner_body, orelse }), ..}] = body else { return None }; + let [Stmt::If(ast::StmtIf { test, body: inner_body, orelse, .. })] = body else { return None }; if !orelse.is_empty() { return None; } @@ -230,11 +230,9 @@ pub(crate) fn nested_if_statements( parent: Option<&Stmt>, ) { // If the parent could contain a nested if-statement, abort. - if let Some(parent) = parent { - if let StmtKind::If(ast::StmtIf { body, orelse, .. }) = &parent.node { - if orelse.is_empty() && body.len() == 1 { - return; - } + if let Some(Stmt::If(ast::StmtIf { body, orelse, .. })) = parent { + if orelse.is_empty() && body.len() == 1 { + return; } } @@ -250,8 +248,8 @@ pub(crate) fn nested_if_statements( // Allow `if True:` and `if False:` statements. if matches!( - test.node, - ExprKind::Constant(ast::ExprConstant { + test, + Expr::Constant(ast::ExprConstant { value: Constant::Bool(..), .. }) @@ -323,10 +321,10 @@ fn is_one_line_return_bool(stmts: &[Stmt]) -> Option { if stmts.len() != 1 { return None; } - let StmtKind::Return(ast::StmtReturn { value }) = &stmts[0].node else { + let Stmt::Return(ast::StmtReturn { value, range: _ }) = &stmts[0] else { return None; }; - let Some(ExprKind::Constant(ast::ExprConstant { value, .. })) = value.as_ref().map(|value| &value.node) else { + let Some(Expr::Constant(ast::ExprConstant { value, .. })) = value.as_deref() else { return None; }; let Constant::Bool(value) = value else { @@ -337,7 +335,7 @@ fn is_one_line_return_bool(stmts: &[Stmt]) -> Option { /// SIM103 pub(crate) fn needless_bool(checker: &mut Checker, stmt: &Stmt) { - let StmtKind::If(ast::StmtIf { test, body, orelse }) = &stmt.node else { + let Stmt::If(ast::StmtIf { test, body, orelse, range: _ }) = stmt else { return; }; let (Some(if_return), Some(else_return)) = (is_one_line_return_bool(body), is_one_line_return_bool(orelse)) else { @@ -354,40 +352,42 @@ pub(crate) fn needless_bool(checker: &mut Checker, stmt: &Stmt) { let fixable = matches!(if_return, Bool::True) && matches!(else_return, Bool::False) && !has_comments(stmt, checker.locator) - && (matches!(test.node, ExprKind::Compare(_)) || checker.ctx.is_builtin("bool")); + && (test.is_compare_expr() || checker.ctx.is_builtin("bool")); let mut diagnostic = Diagnostic::new(NeedlessBool { condition }, stmt.range()); if fixable && checker.patch(diagnostic.kind.rule()) { - if matches!(test.node, ExprKind::Compare(_)) { + if test.is_compare_expr() { // If the condition is a comparison, we can replace it with the condition. + let node = ast::StmtReturn { + value: Some(test.clone()), + range: TextRange::default(), + }; #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - unparse_stmt( - &create_stmt(ast::StmtReturn { - value: Some(test.clone()), - }), - checker.stylist, - ), + unparse_stmt(&node.into(), checker.stylist), stmt.range(), ))); } else { // Otherwise, we need to wrap the condition in a call to `bool`. (We've already // verified, above, that `bool` is a builtin.) + let node = ast::ExprName { + id: "bool".into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node1 = ast::ExprCall { + func: Box::new(node.into()), + args: vec![(**test).clone()], + keywords: vec![], + range: TextRange::default(), + }; + let node2 = ast::StmtReturn { + value: Some(Box::new(node1.into())), + range: TextRange::default(), + }; #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - unparse_stmt( - &create_stmt(ast::StmtReturn { - value: Some(Box::new(create_expr(ast::ExprCall { - func: Box::new(create_expr(ast::ExprName { - id: "bool".into(), - ctx: ExprContext::Load, - })), - args: vec![(**test).clone()], - keywords: vec![], - }))), - }), - checker.stylist, - ), + unparse_stmt(&node2.into(), checker.stylist), stmt.range(), ))); }; @@ -396,15 +396,19 @@ pub(crate) fn needless_bool(checker: &mut Checker, stmt: &Stmt) { } fn ternary(target_var: &Expr, body_value: &Expr, test: &Expr, orelse_value: &Expr) -> Stmt { - create_stmt(ast::StmtAssign { + let node = ast::ExprIfExp { + test: Box::new(test.clone()), + body: Box::new(body_value.clone()), + orelse: Box::new(orelse_value.clone()), + range: TextRange::default(), + }; + let node1 = ast::StmtAssign { targets: vec![target_var.clone()], - value: Box::new(create_expr(ast::ExprIfExp { - test: Box::new(test.clone()), - body: Box::new(body_value.clone()), - orelse: Box::new(orelse_value.clone()), - })), + value: Box::new(node.into()), type_comment: None, - }) + range: TextRange::default(), + }; + node1.into() } /// Return `true` if the `Expr` contains a reference to `${module}.${target}`. @@ -417,25 +421,25 @@ fn contains_call_path(ctx: &Context, expr: &Expr, target: &[&str]) -> bool { /// SIM108 pub(crate) fn use_ternary_operator(checker: &mut Checker, stmt: &Stmt, parent: Option<&Stmt>) { - let StmtKind::If(ast::StmtIf { test, body, orelse } )= &stmt.node else { + let Stmt::If(ast::StmtIf { test, body, orelse, range: _ } )= stmt else { return; }; if body.len() != 1 || orelse.len() != 1 { return; } - let StmtKind::Assign(ast::StmtAssign { targets: body_targets, value: body_value, .. } )= &body[0].node else { + let Stmt::Assign(ast::StmtAssign { targets: body_targets, value: body_value, .. } )= &body[0] else { return; }; - let StmtKind::Assign(ast::StmtAssign { targets: orelse_targets, value: orelse_value, .. } )= &orelse[0].node else { + let Stmt::Assign(ast::StmtAssign { targets: orelse_targets, value: orelse_value, .. } )= &orelse[0] else { return; }; if body_targets.len() != 1 || orelse_targets.len() != 1 { return; } - let ExprKind::Name(ast::ExprName { id: body_id, .. } )= &body_targets[0].node else { + let Expr::Name(ast::ExprName { id: body_id, .. } )= &body_targets[0] else { return; }; - let ExprKind::Name(ast::ExprName { id: orelse_id, .. } )= &orelse_targets[0].node else { + let Expr::Name(ast::ExprName { id: orelse_id, .. } )= &orelse_targets[0] else { return; }; if body_id != orelse_id { @@ -455,10 +459,10 @@ pub(crate) fn use_ternary_operator(checker: &mut Checker, stmt: &Stmt, parent: O // It's part of a bigger if-elif block: // https://github.com/MartinThoma/flake8-simplify/issues/115 - if let Some(StmtKind::If(ast::StmtIf { + if let Some(Stmt::If(ast::StmtIf { orelse: parent_orelse, .. - })) = parent.map(|parent| &parent.node) + })) = parent { if parent_orelse.len() == 1 && stmt == &parent_orelse[0] { // TODO(charlie): These two cases have the same AST: @@ -486,14 +490,14 @@ pub(crate) fn use_ternary_operator(checker: &mut Checker, stmt: &Stmt, parent: O // Avoid suggesting ternary for `if (yield ...)`-style checks. // TODO(charlie): Fix precedence handling for yields in generator. if matches!( - body_value.node, - ExprKind::Yield(_) | ExprKind::YieldFrom(_) | ExprKind::Await(_) + body_value.as_ref(), + Expr::Yield(_) | Expr::YieldFrom(_) | Expr::Await(_) ) { return; } if matches!( - orelse_value.node, - ExprKind::Yield(_) | ExprKind::YieldFrom(_) | ExprKind::Await(_) + orelse_value.as_ref(), + Expr::Yield(_) | Expr::YieldFrom(_) | Expr::Await(_) ) { return; } @@ -539,7 +543,7 @@ fn get_if_body_pairs<'a>( if orelse.len() != 1 { break; } - let StmtKind::If(ast::StmtIf { test, body, orelse: orelse_orelse }) = &orelse[0].node else { + let Stmt::If(ast::StmtIf { test, body, orelse: orelse_orelse, range: _ }) = &orelse[0] else { break; }; pairs.push((test, body)); @@ -550,16 +554,16 @@ fn get_if_body_pairs<'a>( /// SIM114 pub(crate) fn if_with_same_arms(checker: &mut Checker, stmt: &Stmt, parent: Option<&Stmt>) { - let StmtKind::If(ast::StmtIf { test, body, orelse }) = &stmt.node else { + let Stmt::If(ast::StmtIf { test, body, orelse, range: _ }) = stmt else { return; }; // It's part of a bigger if-elif block: // https://github.com/MartinThoma/flake8-simplify/issues/115 - if let Some(StmtKind::If(ast::StmtIf { + if let Some(Stmt::If(ast::StmtIf { orelse: parent_orelse, .. - })) = parent.map(|parent| &parent.node) + })) = parent { if parent_orelse.len() == 1 && stmt == &parent_orelse[0] { // TODO(charlie): These two cases have the same AST: @@ -614,14 +618,15 @@ pub(crate) fn manual_dict_lookup( // * Each if-statement's body must consist of a single `return`. // * Each if-statement's orelse must be either another if-statement or empty. // * The final if-statement's orelse must be empty, or a single `return`. - let ExprKind::Compare(ast::ExprCompare { + let Expr::Compare(ast::ExprCompare { left, ops, comparators, - })= &test.node else { + range: _, + })= &test else { return; }; - let ExprKind::Name(ast::ExprName { id: target, .. }) = &left.node else { + let Expr::Name(ast::ExprName { id: target, .. }) = left.as_ref() else { return; }; if body.len() != 1 { @@ -636,10 +641,10 @@ pub(crate) fn manual_dict_lookup( if comparators.len() != 1 { return; } - let ExprKind::Constant(ast::ExprConstant { value: constant, .. }) = &comparators[0].node else { + let Expr::Constant(ast::ExprConstant { value: constant, .. }) = &comparators[0] else { return; }; - let StmtKind::Return(ast::StmtReturn { value }) = &body[0].node else { + let Stmt::Return(ast::StmtReturn { value, range: _ }) = &body[0] else { return; }; if value.as_ref().map_or(false, |value| { @@ -650,10 +655,10 @@ pub(crate) fn manual_dict_lookup( // It's part of a bigger if-elif block: // https://github.com/MartinThoma/flake8-simplify/issues/115 - if let Some(StmtKind::If(ast::StmtIf { + if let Some(Stmt::If(ast::StmtIf { orelse: parent_orelse, .. - })) = parent.map(|parent| &parent.node) + })) = parent { if parent_orelse.len() == 1 && stmt == &parent_orelse[0] { // TODO(charlie): These two cases have the same AST: @@ -683,7 +688,7 @@ pub(crate) fn manual_dict_lookup( let mut child: Option<&Stmt> = orelse.get(0); while let Some(current) = child.take() { - let StmtKind::If(ast::StmtIf { test, body, orelse }) = ¤t.node else { + let Stmt::If(ast::StmtIf { test, body, orelse, range: _ }) = ¤t else { return; }; if body.len() != 1 { @@ -692,14 +697,15 @@ pub(crate) fn manual_dict_lookup( if orelse.len() > 1 { return; } - let ExprKind::Compare(ast::ExprCompare { + let Expr::Compare(ast::ExprCompare { left, ops, comparators, - } )= &test.node else { + range: _ + } )= test.as_ref() else { return; }; - let ExprKind::Name(ast::ExprName { id, .. }) = &left.node else { + let Expr::Name(ast::ExprName { id, .. }) = left.as_ref() else { return; }; if !(id == target && ops.len() == 1 && ops[0] == Cmpop::Eq) { @@ -708,10 +714,10 @@ pub(crate) fn manual_dict_lookup( if comparators.len() != 1 { return; } - let ExprKind::Constant(ast::ExprConstant { value: constant, .. } )= &comparators[0].node else { + let Expr::Constant(ast::ExprConstant { value: constant, .. } )= &comparators[0] else { return; }; - let StmtKind::Return(ast::StmtReturn { value } )= &body[0].node else { + let Stmt::Return(ast::StmtReturn { value, range: _ } )= &body[0] else { return; }; if value.as_ref().map_or(false, |value| { @@ -722,11 +728,11 @@ pub(crate) fn manual_dict_lookup( constants.insert(constant.into()); if let Some(orelse) = orelse.first() { - match &orelse.node { - StmtKind::If(_) => { + match orelse { + Stmt::If(_) => { child = Some(orelse); } - StmtKind::Return(_) => { + Stmt::Return(_) => { child = None; } _ => return, @@ -751,26 +757,26 @@ pub(crate) fn use_dict_get_with_default( checker: &mut Checker, stmt: &Stmt, test: &Expr, - body: &Vec, - orelse: &Vec, + body: &[Stmt], + orelse: &[Stmt], parent: Option<&Stmt>, ) { if body.len() != 1 || orelse.len() != 1 { return; } - let StmtKind::Assign(ast::StmtAssign { targets: body_var, value: body_value, ..}) = &body[0].node else { + let Stmt::Assign(ast::StmtAssign { targets: body_var, value: body_value, ..}) = &body[0] else { return; }; if body_var.len() != 1 { return; }; - let StmtKind::Assign(ast::StmtAssign { targets: orelse_var, value: orelse_value, .. }) = &orelse[0].node else { + let Stmt::Assign(ast::StmtAssign { targets: orelse_var, value: orelse_value, .. }) = &orelse[0] else { return; }; if orelse_var.len() != 1 { return; }; - let ExprKind::Compare(ast::ExprCompare { left: test_key, ops , comparators: test_dict }) = &test.node else { + let Expr::Compare(ast::ExprCompare { left: test_key, ops , comparators: test_dict, range: _ }) = &test else { return; }; if test_dict.len() != 1 { @@ -784,7 +790,7 @@ pub(crate) fn use_dict_get_with_default( } }; let test_dict = &test_dict[0]; - let ExprKind::Subscript(ast::ExprSubscript { value: expected_subscript, slice: expected_slice, .. } ) = &expected_value.node else { + let Expr::Subscript(ast::ExprSubscript { value: expected_subscript, slice: expected_slice, .. } ) = expected_value.as_ref() else { return; }; @@ -804,10 +810,10 @@ pub(crate) fn use_dict_get_with_default( // It's part of a bigger if-elif block: // https://github.com/MartinThoma/flake8-simplify/issues/115 - if let Some(StmtKind::If(ast::StmtIf { + if let Some(Stmt::If(ast::StmtIf { orelse: parent_orelse, .. - })) = parent.map(|parent| &parent.node) + })) = parent { if parent_orelse.len() == 1 && stmt == &parent_orelse[0] { // TODO(charlie): These two cases have the same AST: @@ -832,25 +838,28 @@ pub(crate) fn use_dict_get_with_default( } } - let contents = unparse_stmt( - &create_stmt(ast::StmtAssign { - targets: vec![create_expr(expected_var.node.clone())], - value: Box::new(create_expr(ast::ExprCall { - func: Box::new(create_expr(ast::ExprAttribute { - value: expected_subscript.clone(), - attr: "get".into(), - ctx: ExprContext::Load, - })), - args: vec![ - create_expr(test_key.node.clone()), - create_expr(default_value.node.clone()), - ], - keywords: vec![], - })), - type_comment: None, - }), - checker.stylist, - ); + let node = *default_value.clone(); + let node1 = *test_key.clone(); + let node2 = ast::ExprAttribute { + value: expected_subscript.clone(), + attr: "get".into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node3 = ast::ExprCall { + func: Box::new(node2.into()), + args: vec![node1, node], + keywords: vec![], + range: TextRange::default(), + }; + let node4 = expected_var.clone(); + let node5 = ast::StmtAssign { + targets: vec![node4], + value: Box::new(node3.into()), + type_comment: None, + range: TextRange::default(), + }; + let contents = unparse_stmt(&node5.into(), checker.stylist); // Don't flag if the resulting expression would exceed the maximum line length. let line_start = checker.locator.line_start(stmt.start()); diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs index 115646b22b..185013bf0e 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs @@ -1,8 +1,9 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprContext, ExprKind, Unaryop}; +use ruff_text_size::TextRange; +use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Ranged, Unaryop}; use ruff_diagnostics::{AlwaysAutofixableViolation, AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{create_expr, unparse_expr}; +use ruff_python_ast::helpers::unparse_expr; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -81,13 +82,13 @@ pub(crate) fn explicit_true_false_in_ifexpr( body: &Expr, orelse: &Expr, ) { - let ExprKind::Constant(ast::ExprConstant { value, .. } )= &body.node else { + let Expr::Constant(ast::ExprConstant { value, .. } )= &body else { return; }; if !matches!(value, Constant::Bool(true)) { return; } - let ExprKind::Constant(ast::ExprConstant { value, .. } )= &orelse.node else { + let Expr::Constant(ast::ExprConstant { value, .. } )= &orelse else { return; }; if !matches!(value, Constant::Bool(false)) { @@ -101,26 +102,27 @@ pub(crate) fn explicit_true_false_in_ifexpr( expr.range(), ); if checker.patch(diagnostic.kind.rule()) { - if matches!(test.node, ExprKind::Compare(_)) { + if matches!(test, Expr::Compare(_)) { #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( unparse_expr(&test.clone(), checker.stylist), expr.range(), ))); } else if checker.ctx.is_builtin("bool") { + let node = ast::ExprName { + id: "bool".into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node1 = ast::ExprCall { + func: Box::new(node.into()), + args: vec![test.clone()], + keywords: vec![], + range: TextRange::default(), + }; #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - unparse_expr( - &create_expr(ast::ExprCall { - func: Box::new(create_expr(ast::ExprName { - id: "bool".into(), - ctx: ExprContext::Load, - })), - args: vec![test.clone()], - keywords: vec![], - }), - checker.stylist, - ), + unparse_expr(&node1.into(), checker.stylist), expr.range(), ))); }; @@ -136,13 +138,13 @@ pub(crate) fn explicit_false_true_in_ifexpr( body: &Expr, orelse: &Expr, ) { - let ExprKind::Constant(ast::ExprConstant { value, .. }) = &body.node else { + let Expr::Constant(ast::ExprConstant { value, .. }) = &body else { return; }; if !matches!(value, Constant::Bool(false)) { return; } - let ExprKind::Constant(ast::ExprConstant { value, .. }) = &orelse.node else { + let Expr::Constant(ast::ExprConstant { value, .. }) = &orelse else { return; }; if !matches!(value, Constant::Bool(true)) { @@ -156,15 +158,15 @@ pub(crate) fn explicit_false_true_in_ifexpr( expr.range(), ); if checker.patch(diagnostic.kind.rule()) { + let node = test.clone(); + let node1 = ast::ExprUnaryOp { + op: Unaryop::Not, + operand: Box::new(node), + range: TextRange::default(), + }; #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - unparse_expr( - &create_expr(ast::ExprUnaryOp { - op: Unaryop::Not, - operand: Box::new(create_expr(test.node.clone())), - }), - checker.stylist, - ), + unparse_expr(&node1.into(), checker.stylist), expr.range(), ))); } @@ -179,18 +181,18 @@ pub(crate) fn twisted_arms_in_ifexpr( body: &Expr, orelse: &Expr, ) { - let ExprKind::UnaryOp(ast::ExprUnaryOp { op, operand: test_operand } )= &test.node else { + let Expr::UnaryOp(ast::ExprUnaryOp { op, operand: test_operand, range: _ } )= &test else { return; }; - if !matches!(op, Unaryop::Not) { + if !op.is_not() { return; } // Check if the test operand and else branch use the same variable. - let ExprKind::Name(ast::ExprName { id: test_id, .. } )= &test_operand.node else { + let Expr::Name(ast::ExprName { id: test_id, .. } )= test_operand.as_ref() else { return; }; - let ExprKind::Name(ast::ExprName {id: orelse_id, ..}) = &orelse.node else { + let Expr::Name(ast::ExprName {id: orelse_id, ..}) = orelse else { return; }; if !test_id.eq(orelse_id) { @@ -205,16 +207,18 @@ pub(crate) fn twisted_arms_in_ifexpr( expr.range(), ); if checker.patch(diagnostic.kind.rule()) { + let node = body.clone(); + let node1 = orelse.clone(); + let node2 = orelse.clone(); + let node3 = ast::ExprIfExp { + test: Box::new(node2), + body: Box::new(node1), + orelse: Box::new(node), + range: TextRange::default(), + }; #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - unparse_expr( - &create_expr(ast::ExprIfExp { - test: Box::new(create_expr(orelse.node.clone())), - body: Box::new(create_expr(orelse.node.clone())), - orelse: Box::new(create_expr(body.node.clone())), - }), - checker.stylist, - ), + unparse_expr(&node3.into(), checker.stylist), expr.range(), ))); } diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs index ba68a6a176..c37f564345 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs @@ -1,8 +1,9 @@ -use rustpython_parser::ast::{self, Cmpop, Expr, ExprContext, ExprKind, Stmt, StmtKind, Unaryop}; +use ruff_text_size::TextRange; +use rustpython_parser::ast::{self, Cmpop, Expr, ExprContext, Ranged, Stmt, Unaryop}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{create_expr, unparse_expr}; +use ruff_python_ast::helpers::unparse_expr; use ruff_python_semantic::scope::ScopeKind; use crate::checkers::ast::Checker; @@ -65,13 +66,13 @@ impl AlwaysAutofixableViolation for DoubleNegation { const DUNDER_METHODS: &[&str] = &["__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__"]; fn is_exception_check(stmt: &Stmt) -> bool { - let StmtKind::If(ast::StmtIf {test: _, body, orelse: _ })= &stmt.node else { + let Stmt::If(ast::StmtIf {test: _, body, orelse: _, range: _ })= stmt else { return false; }; if body.len() != 1 { return false; } - if matches!(body[0].node, StmtKind::Raise(_)) { + if matches!(body[0], Stmt::Raise(_)) { return true; } false @@ -81,13 +82,13 @@ fn is_exception_check(stmt: &Stmt) -> bool { pub(crate) fn negation_with_equal_op( checker: &mut Checker, expr: &Expr, - op: &Unaryop, + op: Unaryop, operand: &Expr, ) { if !matches!(op, Unaryop::Not) { return; } - let ExprKind::Compare(ast::ExprCompare { left, ops, comparators}) = &operand.node else { + let Expr::Compare(ast::ExprCompare { left, ops, comparators, range: _}) = operand else { return; }; if !matches!(&ops[..], [Cmpop::Eq]) { @@ -112,16 +113,15 @@ pub(crate) fn negation_with_equal_op( expr.range(), ); if checker.patch(diagnostic.kind.rule()) { + let node = ast::ExprCompare { + left: left.clone(), + ops: vec![Cmpop::NotEq], + comparators: comparators.clone(), + range: TextRange::default(), + }; #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - unparse_expr( - &create_expr(ast::ExprCompare { - left: left.clone(), - ops: vec![Cmpop::NotEq], - comparators: comparators.clone(), - }), - checker.stylist, - ), + unparse_expr(&node.into(), checker.stylist), expr.range(), ))); } @@ -132,13 +132,13 @@ pub(crate) fn negation_with_equal_op( pub(crate) fn negation_with_not_equal_op( checker: &mut Checker, expr: &Expr, - op: &Unaryop, + op: Unaryop, operand: &Expr, ) { if !matches!(op, Unaryop::Not) { return; } - let ExprKind::Compare(ast::ExprCompare { left, ops, comparators}) = &operand.node else { + let Expr::Compare(ast::ExprCompare { left, ops, comparators, range: _}) = operand else { return; }; if !matches!(&ops[..], [Cmpop::NotEq]) { @@ -163,16 +163,15 @@ pub(crate) fn negation_with_not_equal_op( expr.range(), ); if checker.patch(diagnostic.kind.rule()) { + let node = ast::ExprCompare { + left: left.clone(), + ops: vec![Cmpop::Eq], + comparators: comparators.clone(), + range: TextRange::default(), + }; #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - unparse_expr( - &create_expr(ast::ExprCompare { - left: left.clone(), - ops: vec![Cmpop::Eq], - comparators: comparators.clone(), - }), - checker.stylist, - ), + unparse_expr(&node.into(), checker.stylist), expr.range(), ))); } @@ -180,11 +179,11 @@ pub(crate) fn negation_with_not_equal_op( } /// SIM208 -pub(crate) fn double_negation(checker: &mut Checker, expr: &Expr, op: &Unaryop, operand: &Expr) { +pub(crate) fn double_negation(checker: &mut Checker, expr: &Expr, op: Unaryop, operand: &Expr) { if !matches!(op, Unaryop::Not) { return; } - let ExprKind::UnaryOp(ast::ExprUnaryOp { op: operand_op, operand }) = &operand.node else { + let Expr::UnaryOp(ast::ExprUnaryOp { op: operand_op, operand, range: _ }) = operand else { return; }; if !matches!(operand_op, Unaryop::Not) { @@ -205,19 +204,20 @@ pub(crate) fn double_negation(checker: &mut Checker, expr: &Expr, op: &Unaryop, expr.range(), ))); } else if checker.ctx.is_builtin("bool") { + let node = ast::ExprName { + id: "bool".into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node1 = ast::ExprCall { + func: Box::new(node.into()), + args: vec![*operand.clone()], + keywords: vec![], + range: TextRange::default(), + }; #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - unparse_expr( - &create_expr(ast::ExprCall { - func: Box::new(create_expr(ast::ExprName { - id: "bool".into(), - ctx: ExprContext::Load, - })), - args: vec![*operand.clone()], - keywords: vec![], - }), - checker.stylist, - ), + unparse_expr(&node1.into(), checker.stylist), expr.range(), ))); }; diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_with.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_with.rs index 2437b9a29c..fa4cdb0497 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_with.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_with.rs @@ -1,6 +1,6 @@ use log::error; use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Attributed, Stmt, StmtKind, Withitem}; +use rustpython_parser::ast::{self, Ranged, Stmt, Withitem}; use unicode_width::UnicodeWidthStr; use ruff_diagnostics::{AutofixKind, Violation}; @@ -60,8 +60,8 @@ impl Violation for MultipleWithStatements { } } -fn find_last_with(body: &[Stmt]) -> Option<(&Vec, &Vec)> { - let [Attributed { node: StmtKind::With(ast::StmtWith { items, body, .. }), ..}] = body else { return None }; +fn find_last_with(body: &[Stmt]) -> Option<(&[Withitem], &[Stmt])> { + let [Stmt::With(ast::StmtWith { items, body, .. })] = body else { return None }; find_last_with(body).or(Some((items, body))) } @@ -72,11 +72,9 @@ pub(crate) fn multiple_with_statements( with_body: &[Stmt], with_parent: Option<&Stmt>, ) { - if let Some(parent) = with_parent { - if let StmtKind::With(ast::StmtWith { body, .. }) = &parent.node { - if body.len() == 1 { - return; - } + if let Some(Stmt::With(ast::StmtWith { body, .. })) = with_parent { + if body.len() == 1 { + return; } } if let Some((items, body)) = find_last_with(with_body) { diff --git a/crates/ruff/src/rules/flake8_simplify/rules/fix_if.rs b/crates/ruff/src/rules/flake8_simplify/rules/fix_if.rs index 14a808c8ea..b94839db61 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/fix_if.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/fix_if.rs @@ -4,6 +4,7 @@ use libcst_native::{ LeftParen, ParenthesizableWhitespace, ParenthesizedNode, RightParen, SimpleWhitespace, Statement, Suite, }; +use rustpython_parser::ast::Ranged; use std::borrow::Cow; use ruff_diagnostics::Edit; diff --git a/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs b/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs index b81232881d..ba6bc1ebc4 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs @@ -1,5 +1,6 @@ use anyhow::{bail, Result}; use libcst_native::{Codegen, CodegenState, CompoundStatement, Statement, Suite, With}; +use rustpython_parser::ast::Ranged; use ruff_diagnostics::Edit; use ruff_python_ast::source_code::{Locator, Stylist}; diff --git a/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs b/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs index 0e803c1cdb..7158040d67 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs @@ -2,7 +2,7 @@ use anyhow::Result; use libcst_native::{Codegen, CodegenState}; use log::error; use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Cmpop, Expr, ExprKind}; +use rustpython_parser::ast::{self, Cmpop, Expr, Ranged}; use ruff_diagnostics::Edit; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; @@ -54,18 +54,19 @@ fn get_value_content_for_key_in_dict( /// SIM118 fn key_in_dict(checker: &mut Checker, left: &Expr, right: &Expr, range: TextRange) { - let ExprKind::Call(ast::ExprCall { + let Expr::Call(ast::ExprCall { func, args, keywords, - }) = &right.node else { + range: _ + }) = &right else { return; }; if !(args.is_empty() && keywords.is_empty()) { return; } - let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node else { + let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func.as_ref() else { return; }; if attr != "keys" { diff --git a/crates/ruff/src/rules/flake8_simplify/rules/open_file_with_context_handler.rs b/crates/ruff/src/rules/flake8_simplify/rules/open_file_with_context_handler.rs index db06e57b52..9713fac9a2 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/open_file_with_context_handler.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/open_file_with_context_handler.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, StmtKind}; +use rustpython_parser::ast::{self, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -45,22 +45,22 @@ fn match_async_exit_stack(checker: &Checker) -> bool { let Some(expr) = checker.ctx.expr_grandparent() else { return false; }; - let ExprKind::Await(ast::ExprAwait { value }) = &expr.node else { + let Expr::Await(ast::ExprAwait { value, range: _ }) = expr else { return false; }; - let ExprKind::Call(ast::ExprCall { func, .. }) = &value.node else { + let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else { return false; }; - let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node else { + let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func.as_ref() else { return false; }; if attr != "enter_async_context" { return false; } for parent in checker.ctx.parents() { - if let StmtKind::With(ast::StmtWith { items, .. }) = &parent.node { + if let Stmt::With(ast::StmtWith { items, .. }) = parent { for item in items { - if let ExprKind::Call(ast::ExprCall { func, .. }) = &item.context_expr.node { + if let Expr::Call(ast::ExprCall { func, .. }) = &item.context_expr { if checker .ctx .resolve_call_path(func) @@ -83,19 +83,19 @@ fn match_exit_stack(checker: &Checker) -> bool { let Some(expr) = checker.ctx.expr_parent() else { return false; }; - let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node else { + let Expr::Call(ast::ExprCall { func, .. }) = expr else { return false; }; - let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node else { + let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func.as_ref() else { return false; }; if attr != "enter_context" { return false; } for parent in checker.ctx.parents() { - if let StmtKind::With(ast::StmtWith { items, .. }) = &parent.node { + if let Stmt::With(ast::StmtWith { items, .. }) = parent { for item in items { - if let ExprKind::Call(ast::ExprCall { func, .. }) = &item.context_expr.node { + if let Expr::Call(ast::ExprCall { func, .. }) = &item.context_expr { if checker .ctx .resolve_call_path(func) @@ -121,7 +121,7 @@ pub(crate) fn open_file_with_context_handler(checker: &mut Checker, func: &Expr) { if checker.ctx.is_builtin("open") { // Ex) `with open("foo.txt") as f: ...` - if matches!(checker.ctx.stmt().node, StmtKind::With(_)) { + if matches!(checker.ctx.stmt(), Stmt::With(_)) { return; } diff --git a/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs b/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs index a841210afc..587c83d590 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs @@ -1,12 +1,12 @@ use ruff_text_size::{TextRange, TextSize}; use rustpython_parser::ast::{ - self, Cmpop, Comprehension, Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind, Unaryop, + self, Cmpop, Comprehension, Constant, Expr, ExprContext, Ranged, Stmt, Unaryop, }; use unicode_width::UnicodeWidthStr; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{create_expr, create_stmt, unparse_stmt}; +use ruff_python_ast::helpers::unparse_stmt; use ruff_python_ast::source_code::Stylist; use crate::checkers::ast::Checker; @@ -41,15 +41,15 @@ struct Loop<'a> { terminal: TextSize, } -/// Extract the returned boolean values a `StmtKind::For` with an `else` body. +/// Extract the returned boolean values a `Stmt::For` with an `else` body. fn return_values_for_else(stmt: &Stmt) -> Option { - let StmtKind::For(ast::StmtFor { + let Stmt::For(ast::StmtFor { body, target, iter, orelse, .. - }) = &stmt.node else { + }) = stmt else { return None; }; @@ -61,11 +61,11 @@ fn return_values_for_else(stmt: &Stmt) -> Option { if orelse.len() != 1 { return None; } - let StmtKind::If(ast::StmtIf { + let Stmt::If(ast::StmtIf { body: nested_body, test: nested_test, - orelse: nested_orelse, - }) = &body[0].node else { + orelse: nested_orelse, range: _, + }) = &body[0] else { return None; }; if nested_body.len() != 1 { @@ -74,24 +74,24 @@ fn return_values_for_else(stmt: &Stmt) -> Option { if !nested_orelse.is_empty() { return None; } - let StmtKind::Return(ast::StmtReturn { value }) = &nested_body[0].node else { + let Stmt::Return(ast::StmtReturn { value, range: _ }) = &nested_body[0] else { return None; }; let Some(value) = value else { return None; }; - let ExprKind::Constant(ast::ExprConstant { value: Constant::Bool(value), .. }) = &value.node else { + let Expr::Constant(ast::ExprConstant { value: Constant::Bool(value), .. }) = value.as_ref() else { return None; }; // The `else` block has to contain a single `return True` or `return False`. - let StmtKind::Return(ast::StmtReturn { value: next_value }) = &orelse[0].node else { + let Stmt::Return(ast::StmtReturn { value: next_value, range: _ }) = &orelse[0] else { return None; }; let Some(next_value) = next_value else { return None; }; - let ExprKind::Constant(ast::ExprConstant { value: Constant::Bool(next_value), .. }) = &next_value.node else { + let Expr::Constant(ast::ExprConstant { value: Constant::Bool(next_value), .. }) = next_value.as_ref() else { return None; }; @@ -105,16 +105,16 @@ fn return_values_for_else(stmt: &Stmt) -> Option { }) } -/// Extract the returned boolean values from subsequent `StmtKind::For` and -/// `StmtKind::Return` statements, or `None`. +/// Extract the returned boolean values from subsequent `Stmt::For` and +/// `Stmt::Return` statements, or `None`. fn return_values_for_siblings<'a>(stmt: &'a Stmt, sibling: &'a Stmt) -> Option> { - let StmtKind::For(ast::StmtFor { + let Stmt::For(ast::StmtFor { body, target, iter, orelse, .. - }) = &stmt.node else { + }) = stmt else { return None; }; @@ -126,11 +126,11 @@ fn return_values_for_siblings<'a>(stmt: &'a Stmt, sibling: &'a Stmt) -> Option(stmt: &'a Stmt, sibling: &'a Stmt) -> Option(stmt: &'a Stmt, sibling: &'a Stmt) -> Option String { - unparse_stmt( - &create_stmt(ast::StmtReturn { - value: Some(Box::new(create_expr(ast::ExprCall { - func: Box::new(create_expr(ast::ExprName { - id: id.into(), - ctx: ExprContext::Load, - })), - args: vec![create_expr(ast::ExprGeneratorExp { - elt: Box::new(test.clone()), - generators: vec![Comprehension { - target: target.clone(), - iter: iter.clone(), - ifs: vec![], - is_async: false, - }], - })], - keywords: vec![], - }))), - }), - stylist, - ) + let node = ast::ExprGeneratorExp { + elt: Box::new(test.clone()), + generators: vec![Comprehension { + target: target.clone(), + iter: iter.clone(), + ifs: vec![], + is_async: false, + range: TextRange::default(), + }], + range: TextRange::default(), + }; + let node1 = ast::ExprName { + id: id.into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node2 = ast::ExprCall { + func: Box::new(node1.into()), + args: vec![node.into()], + keywords: vec![], + range: TextRange::default(), + }; + let node3 = ast::StmtReturn { + value: Some(Box::new(node2.into())), + range: TextRange::default(), + }; + unparse_stmt(&node3.into(), stylist) } /// SIM110, SIM111 @@ -248,20 +254,22 @@ pub(crate) fn convert_for_loop_to_any_all( if checker.settings.rules.enabled(Rule::ReimplementedBuiltin) { // Invert the condition. let test = { - if let ExprKind::UnaryOp(ast::ExprUnaryOp { + if let Expr::UnaryOp(ast::ExprUnaryOp { op: Unaryop::Not, operand, - }) = &loop_info.test.node + range: _, + }) = &loop_info.test { *operand.clone() - } else if let ExprKind::Compare(ast::ExprCompare { + } else if let Expr::Compare(ast::ExprCompare { left, ops, comparators, - }) = &loop_info.test.node + range: _, + }) = &loop_info.test { - if ops.len() == 1 && comparators.len() == 1 { - let op = match &ops[0] { + if let ([op], [comparator]) = (ops.as_slice(), comparators.as_slice()) { + let op = match op { Cmpop::Eq => Cmpop::NotEq, Cmpop::NotEq => Cmpop::Eq, Cmpop::Lt => Cmpop::GtE, @@ -273,22 +281,28 @@ pub(crate) fn convert_for_loop_to_any_all( Cmpop::In => Cmpop::NotIn, Cmpop::NotIn => Cmpop::In, }; - create_expr(ast::ExprCompare { + let node = ast::ExprCompare { left: left.clone(), ops: vec![op], - comparators: vec![comparators[0].clone()], - }) + comparators: vec![comparator.clone()], + range: TextRange::default(), + }; + node.into() } else { - create_expr(ast::ExprUnaryOp { + let node = ast::ExprUnaryOp { op: Unaryop::Not, operand: Box::new(loop_info.test.clone()), - }) + range: TextRange::default(), + }; + node.into() } } else { - create_expr(ast::ExprUnaryOp { + let node = ast::ExprUnaryOp { op: Unaryop::Not, operand: Box::new(loop_info.test.clone()), - }) + range: TextRange::default(), + }; + node.into() } }; let contents = return_stmt( diff --git a/crates/ruff/src/rules/flake8_simplify/rules/return_in_try_except_finally.rs b/crates/ruff/src/rules/flake8_simplify/rules/return_in_try_except_finally.rs index 664bd40343..eacfa6ddb9 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/return_in_try_except_finally.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/return_in_try_except_finally.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Excepthandler, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -50,9 +50,7 @@ impl Violation for ReturnInTryExceptFinally { } fn find_return(stmts: &[Stmt]) -> Option<&Stmt> { - stmts - .iter() - .find(|stmt| matches!(stmt.node, StmtKind::Return(_))) + stmts.iter().find(|stmt| matches!(stmt, Stmt::Return(_))) } /// SIM107 @@ -64,8 +62,7 @@ pub(crate) fn return_in_try_except_finally( ) { let try_has_return = find_return(body).is_some(); let except_has_return = handlers.iter().any(|handler| { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) = - &handler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) = handler; find_return(body).is_some() }); diff --git a/crates/ruff/src/rules/flake8_simplify/rules/suppressible_exception.rs b/crates/ruff/src/rules/flake8_simplify/rules/suppressible_exception.rs index dbb872cad5..086fdb97c5 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/suppressible_exception.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/suppressible_exception.rs @@ -1,7 +1,5 @@ use ruff_text_size::{TextLen, TextRange}; -use rustpython_parser::ast::{ - self, Attributed, Constant, Excepthandler, ExcepthandlerKind, ExprKind, Stmt, StmtKind, -}; +use rustpython_parser::ast::{self, Constant, Excepthandler, Expr, Ranged, Stmt}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -45,18 +43,15 @@ pub(crate) fn suppressible_exception( ) { if !matches!( try_body, - [Attributed { - node: StmtKind::Delete(_) - | StmtKind::Assign(_) - | StmtKind::AugAssign(_) - | StmtKind::AnnAssign(_) - | StmtKind::Assert(_) - | StmtKind::Import(_) - | StmtKind::ImportFrom(_) - | StmtKind::Expr(_) - | StmtKind::Pass, - .. - }] + [Stmt::Delete(_) + | Stmt::Assign(_) + | Stmt::AugAssign(_) + | Stmt::AnnAssign(_) + | Stmt::Assert(_) + | Stmt::Import(_) + | Stmt::ImportFrom(_) + | Stmt::Expr(_) + | Stmt::Pass(_)] ) || handlers.len() != 1 || !orelse.is_empty() || !finalbody.is_empty() @@ -64,15 +59,14 @@ pub(crate) fn suppressible_exception( return; } let handler = &handlers[0]; - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) = - &handler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) = handler; if body.len() == 1 { - let node = &body[0].node; - if matches!(node, StmtKind::Pass) + let node = &body[0]; + if node.is_pass_stmt() || (matches!( node, - StmtKind::Expr(ast::StmtExpr { value }) - if matches!(**value, Attributed { node: ExprKind::Constant(ast::ExprConstant { value: Constant::Ellipsis, .. }), ..}) + Stmt::Expr(ast::StmtExpr { value, range: _ }) + if matches!(**value, Expr::Constant(ast::ExprConstant { value: Constant::Ellipsis, .. })) )) { let handler_names: Vec = helpers::extract_handled_exceptions(handlers) diff --git a/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs b/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs index 00dd021682..c52b6d12dc 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs @@ -1,6 +1,6 @@ use anyhow::Result; use libcst_native::{Codegen, CodegenState, CompOp}; -use rustpython_parser::ast::{self, Cmpop, Expr, ExprKind, Unaryop}; +use rustpython_parser::ast::{self, Cmpop, Expr, Ranged, Unaryop}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -39,15 +39,16 @@ impl Violation for YodaConditions { /// Return `true` if an [`Expr`] is a constant or a constant-like name. fn is_constant_like(expr: &Expr) -> bool { - match &expr.node { - ExprKind::Attribute(ast::ExprAttribute { attr, .. }) => str::is_upper(attr), - ExprKind::Constant(_) => true, - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => elts.iter().all(is_constant_like), - ExprKind::Name(ast::ExprName { id, .. }) => str::is_upper(id), - ExprKind::UnaryOp(ast::ExprUnaryOp { + match expr { + Expr::Attribute(ast::ExprAttribute { attr, .. }) => str::is_upper(attr), + Expr::Constant(_) => true, + Expr::Tuple(ast::ExprTuple { elts, .. }) => elts.iter().all(is_constant_like), + Expr::Name(ast::ExprName { id, .. }) => str::is_upper(id), + Expr::UnaryOp(ast::ExprUnaryOp { op: Unaryop::UAdd | Unaryop::USub | Unaryop::Invert, operand, - }) => matches!(operand.node, ExprKind::Constant(_)), + range: _, + }) => operand.is_constant_expr(), _ => false, } } diff --git a/crates/ruff/src/rules/flake8_tidy_imports/banned_api.rs b/crates/ruff/src/rules/flake8_tidy_imports/banned_api.rs index 1739f04acc..ca5b4b0cef 100644 --- a/crates/ruff/src/rules/flake8_tidy_imports/banned_api.rs +++ b/crates/ruff/src/rules/flake8_tidy_imports/banned_api.rs @@ -1,5 +1,5 @@ use rustc_hash::FxHashMap; -use rustpython_parser::ast::{Attributed, Expr}; +use rustpython_parser::ast::{Expr, Ranged}; use serde::{Deserialize, Serialize}; use crate::checkers::ast::Checker; @@ -49,7 +49,10 @@ impl Violation for BannedApi { } /// TID251 -pub fn name_is_banned(checker: &mut Checker, name: String, located: &Attributed) { +pub fn name_is_banned(checker: &mut Checker, name: String, located: &T) +where + T: Ranged, +{ let banned_api = &checker.settings.flake8_tidy_imports.banned_api; if let Some(ban) = banned_api.get(&name) { checker.diagnostics.push(Diagnostic::new( @@ -63,7 +66,10 @@ pub fn name_is_banned(checker: &mut Checker, name: String, located: &Attribut } /// TID251 -pub fn name_or_parent_is_banned(checker: &mut Checker, name: &str, located: &Attributed) { +pub fn name_or_parent_is_banned(checker: &mut Checker, name: &str, located: &T) +where + T: Ranged, +{ let banned_api = &checker.settings.flake8_tidy_imports.banned_api; let mut name = name; loop { diff --git a/crates/ruff/src/rules/flake8_tidy_imports/relative_imports.rs b/crates/ruff/src/rules/flake8_tidy_imports/relative_imports.rs index 27ac761de4..9d1b284c31 100644 --- a/crates/ruff/src/rules/flake8_tidy_imports/relative_imports.rs +++ b/crates/ruff/src/rules/flake8_tidy_imports/relative_imports.rs @@ -1,9 +1,10 @@ -use rustpython_parser::ast::{self, Int, Stmt, StmtKind}; +use ruff_text_size::TextRange; +use rustpython_parser::ast::{self, Int, Ranged, Stmt}; use serde::{Deserialize, Serialize}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation, CacheKey}; -use ruff_python_ast::helpers::{create_stmt, resolve_imported_module_path, unparse_stmt}; +use ruff_python_ast::helpers::{resolve_imported_module_path, unparse_stmt}; use ruff_python_ast::source_code::Stylist; use ruff_python_stdlib::identifiers::is_identifier; @@ -102,17 +103,16 @@ fn fix_banned_relative_import( return None; } - let StmtKind::ImportFrom(ast::StmtImportFrom { names, .. }) = &stmt.node else { - panic!("Expected StmtKind::ImportFrom"); + let Stmt::ImportFrom(ast::StmtImportFrom { names, .. }) = stmt else { + panic!("Expected Stmt::ImportFrom"); }; - let content = unparse_stmt( - &create_stmt(ast::StmtImportFrom { - module: Some(module_path.to_string().into()), - names: names.clone(), - level: Some(Int::new(0)), - }), - stylist, - ); + let node = ast::StmtImportFrom { + module: Some(module_path.to_string().into()), + names: names.clone(), + level: Some(Int::new(0)), + range: TextRange::default(), + }; + let content = unparse_stmt(&node.into(), stylist); #[allow(deprecated)] Some(Fix::unspecified(Edit::range_replacement( content, diff --git a/crates/ruff/src/rules/flake8_type_checking/helpers.rs b/crates/ruff/src/rules/flake8_type_checking/helpers.rs index 12b5e67ffc..317ec2f044 100644 --- a/crates/ruff/src/rules/flake8_type_checking/helpers.rs +++ b/crates/ruff/src/rules/flake8_type_checking/helpers.rs @@ -1,5 +1,5 @@ use num_traits::Zero; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Constant, Expr}; use ruff_python_ast::call_path::from_qualified_name; use ruff_python_ast::helpers::map_callable; @@ -11,8 +11,8 @@ use ruff_python_semantic::scope::ScopeKind; pub(crate) fn is_type_checking_block(context: &Context, test: &Expr) -> bool { // Ex) `if False:` if matches!( - test.node, - ExprKind::Constant(ast::ExprConstant { + test, + Expr::Constant(ast::ExprConstant { value: Constant::Bool(false), .. }) @@ -21,10 +21,10 @@ pub(crate) fn is_type_checking_block(context: &Context, test: &Expr) -> bool { } // Ex) `if 0:` - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Int(value), .. - }) = &test.node + }) = &test { if value.is_zero() { return true; diff --git a/crates/ruff/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs b/crates/ruff/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs index 2dbece9459..f78759d651 100644 --- a/crates/ruff/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs +++ b/crates/ruff/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs @@ -1,5 +1,5 @@ use log::error; -use rustpython_parser::ast::{Stmt, StmtKind}; +use rustpython_parser::ast::{Ranged, Stmt}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -55,7 +55,7 @@ pub(crate) fn empty_type_checking_block<'a, 'b>( ) where 'b: 'a, { - if body.len() == 1 && matches!(body[0].node, StmtKind::Pass) { + if body.len() == 1 && body[0].is_pass_stmt() { let mut diagnostic = Diagnostic::new(EmptyTypeCheckingBlock, body[0].range()); // Delete the entire type-checking block. diff --git a/crates/ruff/src/rules/flake8_unused_arguments/helpers.rs b/crates/ruff/src/rules/flake8_unused_arguments/helpers.rs index 4f887fceaa..0669964015 100644 --- a/crates/ruff/src/rules/flake8_unused_arguments/helpers.rs +++ b/crates/ruff/src/rules/flake8_unused_arguments/helpers.rs @@ -1,30 +1,30 @@ -use rustpython_parser::ast::{self, Constant, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Constant, Expr, Stmt}; use ruff_python_ast::helpers::is_docstring_stmt; /// Return `true` if a `Stmt` is a "empty": a `pass`, `...`, `raise /// NotImplementedError`, or `raise NotImplemented` (with or without arguments). fn is_empty_stmt(stmt: &Stmt) -> bool { - match &stmt.node { - StmtKind::Pass => return true, - StmtKind::Expr(ast::StmtExpr { value }) => { + match stmt { + Stmt::Pass(_) => return true, + Stmt::Expr(ast::StmtExpr { value, range: _ }) => { return matches!( - value.node, - ExprKind::Constant(ast::ExprConstant { + value.as_ref(), + Expr::Constant(ast::ExprConstant { value: Constant::Ellipsis, .. }) ) } - StmtKind::Raise(ast::StmtRaise { exc, cause }) => { + Stmt::Raise(ast::StmtRaise { exc, cause, .. }) => { if cause.is_none() { if let Some(exc) = exc { - match &exc.node { - ExprKind::Name(ast::ExprName { id, .. }) => { + match exc.as_ref() { + Expr::Name(ast::ExprName { id, .. }) => { return id == "NotImplementedError" || id == "NotImplemented"; } - ExprKind::Call(ast::ExprCall { func, .. }) => { - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { + Expr::Call(ast::ExprCall { func, .. }) => { + if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { return id == "NotImplementedError" || id == "NotImplemented"; } } @@ -39,7 +39,7 @@ fn is_empty_stmt(stmt: &Stmt) -> bool { } pub(crate) fn is_empty(body: &[Stmt]) -> bool { - match &body { + match body { [] => true, [stmt] => is_docstring_stmt(stmt) || is_empty_stmt(stmt), [docstring, stmt] => is_docstring_stmt(docstring) && is_empty_stmt(stmt), diff --git a/crates/ruff/src/rules/flake8_unused_arguments/rules.rs b/crates/ruff/src/rules/flake8_unused_arguments/rules.rs index d91b55b9de..65a94ebf51 100644 --- a/crates/ruff/src/rules/flake8_unused_arguments/rules.rs +++ b/crates/ruff/src/rules/flake8_unused_arguments/rules.rs @@ -258,16 +258,13 @@ fn call<'a>( ) -> Vec { let mut diagnostics: Vec = vec![]; for arg in args { - if let Some(binding) = values - .get(arg.node.arg.as_str()) - .map(|index| &bindings[*index]) - { + if let Some(binding) = values.get(arg.arg.as_str()).map(|index| &bindings[*index]) { if !binding.used() && binding.kind.is_argument() - && !dummy_variable_rgx.is_match(arg.node.arg.as_str()) + && !dummy_variable_rgx.is_match(arg.arg.as_str()) { diagnostics.push(Diagnostic::new( - argumentable.check_for(arg.node.arg.to_string()), + argumentable.check_for(arg.arg.to_string()), binding.range, )); } diff --git a/crates/ruff/src/rules/flake8_use_pathlib/helpers.rs b/crates/ruff/src/rules/flake8_use_pathlib/helpers.rs index e59596558d..5978d2dfc6 100644 --- a/crates/ruff/src/rules/flake8_use_pathlib/helpers.rs +++ b/crates/ruff/src/rules/flake8_use_pathlib/helpers.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; diff --git a/crates/ruff/src/rules/flynt/helpers.rs b/crates/ruff/src/rules/flynt/helpers.rs index 1420d4f2ee..c2e7f324df 100644 --- a/crates/ruff/src/rules/flynt/helpers.rs +++ b/crates/ruff/src/rules/flynt/helpers.rs @@ -1,32 +1,36 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Int}; - -use ruff_python_ast::helpers::create_expr; +use ruff_text_size::TextRange; +use rustpython_parser::ast::{self, Constant, Expr, Int}; /// Wrap an expression in a `FormattedValue` with no special formatting. fn to_formatted_value_expr(inner: &Expr) -> Expr { - create_expr(ast::ExprFormattedValue { + let node = ast::ExprFormattedValue { value: Box::new(inner.clone()), conversion: Int::new(0), format_spec: None, - }) + range: TextRange::default(), + }; + node.into() } /// Convert a string to a constant string expression. pub(crate) fn to_constant_string(s: &str) -> Expr { - create_expr(ast::ExprConstant { + let node = ast::ExprConstant { value: Constant::Str(s.to_owned()), kind: None, - }) + range: TextRange::default(), + }; + node.into() } /// Figure out if `expr` represents a "simple" call /// (i.e. one that can be safely converted to a formatted value). fn is_simple_call(expr: &Expr) -> bool { - match &expr.node { - ExprKind::Call(ast::ExprCall { + match expr { + Expr::Call(ast::ExprCall { func, args, keywords, + range: _, }) => args.is_empty() && keywords.is_empty() && is_simple_callee(func), _ => false, } @@ -35,32 +39,32 @@ fn is_simple_call(expr: &Expr) -> bool { /// Figure out if `func` represents a "simple" callee (a bare name, or a chain of simple /// attribute accesses). fn is_simple_callee(func: &Expr) -> bool { - match &func.node { - ExprKind::Name(_) => true, - ExprKind::Attribute(ast::ExprAttribute { value, .. }) => is_simple_callee(value), + match func { + Expr::Name(_) => true, + Expr::Attribute(ast::ExprAttribute { value, .. }) => is_simple_callee(value), _ => false, } } /// Convert an expression to a f-string element (if it looks like a good idea). pub(crate) fn to_fstring_elem(expr: &Expr) -> Option { - match &expr.node { + match expr { // These are directly handled by `unparse_fstring_elem`: - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: Constant::Str(_), .. }) - | ExprKind::JoinedStr(_) - | ExprKind::FormattedValue(_) => Some(expr.clone()), + | Expr::JoinedStr(_) + | Expr::FormattedValue(_) => Some(expr.clone()), // These should be pretty safe to wrap in a formatted value. - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: Constant::Int(_) | Constant::Float(_) | Constant::Bool(_) | Constant::Complex { .. }, .. }) - | ExprKind::Name(_) - | ExprKind::Attribute(_) => Some(to_formatted_value_expr(expr)), - ExprKind::Call(_) if is_simple_call(expr) => Some(to_formatted_value_expr(expr)), + | Expr::Name(_) + | Expr::Attribute(_) => Some(to_formatted_value_expr(expr)), + Expr::Call(_) if is_simple_call(expr) => Some(to_formatted_value_expr(expr)), _ => None, } } diff --git a/crates/ruff/src/rules/flynt/rules/static_join_to_fstring.rs b/crates/ruff/src/rules/flynt/rules/static_join_to_fstring.rs index 486120cb7f..b883d03c6b 100644 --- a/crates/ruff/src/rules/flynt/rules/static_join_to_fstring.rs +++ b/crates/ruff/src/rules/flynt/rules/static_join_to_fstring.rs @@ -1,8 +1,9 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use ruff_text_size::TextRange; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{create_expr, unparse_expr}; +use ruff_python_ast::helpers::unparse_expr; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -27,7 +28,7 @@ impl AlwaysAutofixableViolation for StaticJoinToFString { } fn is_static_length(elts: &[Expr]) -> bool { - elts.iter().all(|e| !matches!(e.node, ExprKind::Starred(_))) + elts.iter().all(|e| !matches!(e, Expr::Starred(_))) } fn build_fstring(joiner: &str, joinees: &[Expr]) -> Option { @@ -35,7 +36,7 @@ fn build_fstring(joiner: &str, joinees: &[Expr]) -> Option { let mut first = true; for expr in joinees { - if matches!(expr.node, ExprKind::JoinedStr(_)) { + if matches!(expr, Expr::JoinedStr(_)) { // Oops, already an f-string. We don't know how to handle those // gracefully right now. return None; @@ -46,17 +47,19 @@ fn build_fstring(joiner: &str, joinees: &[Expr]) -> Option { fstring_elems.push(helpers::to_fstring_elem(expr)?); } - Some(create_expr(ast::ExprJoinedStr { + let node = ast::ExprJoinedStr { values: fstring_elems, - })) + range: TextRange::default(), + }; + Some(node.into()) } pub(crate) fn static_join_to_fstring(checker: &mut Checker, expr: &Expr, joiner: &str) { - let ExprKind::Call(ast::ExprCall { + let Expr::Call(ast::ExprCall { args, keywords, .. - })= &expr.node else { + })= expr else { return; }; @@ -67,9 +70,9 @@ pub(crate) fn static_join_to_fstring(checker: &mut Checker, expr: &Expr, joiner: } // Get the elements to join; skip (e.g.) generators, sets, etc. - let joinees = match &args[0].node { - ExprKind::List(ast::ExprList { elts, .. }) if is_static_length(elts) => elts, - ExprKind::Tuple(ast::ExprTuple { elts, .. }) if is_static_length(elts) => elts, + let joinees = match &args[0] { + Expr::List(ast::ExprList { elts, .. }) if is_static_length(elts) => elts, + Expr::Tuple(ast::ExprTuple { elts, .. }) if is_static_length(elts) => elts, _ => return, }; diff --git a/crates/ruff/src/rules/isort/annotate.rs b/crates/ruff/src/rules/isort/annotate.rs index 048d686d64..71168e5121 100644 --- a/crates/ruff/src/rules/isort/annotate.rs +++ b/crates/ruff/src/rules/isort/annotate.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Ranged, Stmt}; use ruff_python_ast::source_code::Locator; @@ -19,19 +19,19 @@ pub(crate) fn annotate_imports<'a>( imports .iter() .map(|import| { - match &import.node { - StmtKind::Import(ast::StmtImport { names }) => { + match import { + Stmt::Import(ast::StmtImport { names, range }) => { // Find comments above. let mut atop = vec![]; while let Some(comment) = - comments_iter.next_if(|comment| comment.start() < import.start()) + comments_iter.next_if(|comment| comment.start() < range.start()) { atop.push(comment); } // Find comments inline. let mut inline = vec![]; - let import_line_end = locator.line_end(import.end()); + let import_line_end = locator.line_end(range.end()); while let Some(comment) = comments_iter.next_if(|comment| comment.end() <= import_line_end) @@ -43,18 +43,19 @@ pub(crate) fn annotate_imports<'a>( names: names .iter() .map(|alias| AliasData { - name: &alias.node.name, - asname: alias.node.asname.as_deref(), + name: &alias.name, + asname: alias.asname.as_deref(), }) .collect(), atop, inline, } } - StmtKind::ImportFrom(ast::StmtImportFrom { + Stmt::ImportFrom(ast::StmtImportFrom { module, names, level, + range: _, }) => { // Find comments above. let mut atop = vec![]; @@ -105,8 +106,8 @@ pub(crate) fn annotate_imports<'a>( } AnnotatedAliasData { - name: &alias.node.name, - asname: alias.node.asname.as_deref(), + name: &alias.name, + asname: alias.asname.as_deref(), atop: alias_atop, inline: alias_inline, } @@ -126,7 +127,7 @@ pub(crate) fn annotate_imports<'a>( inline, } } - _ => panic!("Expected StmtKind::Import | StmtKind::ImportFrom"), + _ => panic!("Expected Stmt::Import | Stmt::ImportFrom"), } }) .collect() diff --git a/crates/ruff/src/rules/isort/categorize.rs b/crates/ruff/src/rules/isort/categorize.rs index 2998f5c48a..3dc3a01b42 100644 --- a/crates/ruff/src/rules/isort/categorize.rs +++ b/crates/ruff/src/rules/isort/categorize.rs @@ -144,7 +144,7 @@ pub(crate) fn categorize_imports<'a>( target_version: PythonVersion, ) -> BTreeMap<&'a ImportSection, ImportBlock<'a>> { let mut block_by_type: BTreeMap<&ImportSection, ImportBlock> = BTreeMap::default(); - // Categorize `StmtKind::Import`. + // Categorize `Stmt::Import`. for (alias, comments) in block.import { let import_type = categorize( &alias.module_name(), @@ -160,7 +160,7 @@ pub(crate) fn categorize_imports<'a>( .import .insert(alias, comments); } - // Categorize `StmtKind::ImportFrom` (without re-export). + // Categorize `Stmt::ImportFrom` (without re-export). for (import_from, aliases) in block.import_from { let classification = categorize( &import_from.module_name(), @@ -176,7 +176,7 @@ pub(crate) fn categorize_imports<'a>( .import_from .insert(import_from, aliases); } - // Categorize `StmtKind::ImportFrom` (with re-export). + // Categorize `Stmt::ImportFrom` (with re-export). for ((import_from, alias), aliases) in block.import_from_as { let classification = categorize( &import_from.module_name(), @@ -192,7 +192,7 @@ pub(crate) fn categorize_imports<'a>( .import_from_as .insert((import_from, alias), aliases); } - // Categorize `StmtKind::ImportFrom` (with star). + // Categorize `Stmt::ImportFrom` (with star). for (import_from, comments) in block.import_from_star { let classification = categorize( &import_from.module_name(), diff --git a/crates/ruff/src/rules/isort/helpers.rs b/crates/ruff/src/rules/isort/helpers.rs index 1a3bae8c5a..4b86854272 100644 --- a/crates/ruff/src/rules/isort/helpers.rs +++ b/crates/ruff/src/rules/isort/helpers.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Stmt; +use rustpython_parser::ast::{Ranged, Stmt}; use rustpython_parser::{lexer, Mode, Tok}; use ruff_python_ast::newlines::StrExt; @@ -6,7 +6,7 @@ use ruff_python_ast::source_code::Locator; use crate::rules::isort::types::TrailingComma; -/// Return `true` if a `StmtKind::ImportFrom` statement ends with a magic +/// Return `true` if a `Stmt::ImportFrom` statement ends with a magic /// trailing comma. pub(crate) fn trailing_comma(stmt: &Stmt, locator: &Locator) -> TrailingComma { let contents = locator.slice(stmt.range()); diff --git a/crates/ruff/src/rules/isort/order.rs b/crates/ruff/src/rules/isort/order.rs index 1f1e786518..1867ebf0de 100644 --- a/crates/ruff/src/rules/isort/order.rs +++ b/crates/ruff/src/rules/isort/order.rs @@ -20,7 +20,7 @@ pub(crate) fn order_imports<'a>( ) -> OrderedImportBlock<'a> { let mut ordered = OrderedImportBlock::default(); - // Sort `StmtKind::Import`. + // Sort `Stmt::Import`. ordered.import.extend( block .import @@ -28,7 +28,7 @@ pub(crate) fn order_imports<'a>( .sorted_by(|(alias1, _), (alias2, _)| cmp_modules(alias1, alias2, force_to_top)), ); - // Sort `StmtKind::ImportFrom`. + // Sort `Stmt::ImportFrom`. ordered.import_from.extend( // Include all non-re-exports. block @@ -54,7 +54,7 @@ pub(crate) fn order_imports<'a>( trailing_comma, }, )| { - // Within each `StmtKind::ImportFrom`, sort the members. + // Within each `Stmt::ImportFrom`, sort the members. ( import_from, comments, diff --git a/crates/ruff/src/rules/isort/rules/add_required_imports.rs b/crates/ruff/src/rules/isort/rules/add_required_imports.rs index 32fa9800be..9658b0c26e 100644 --- a/crates/ruff/src/rules/isort/rules/add_required_imports.rs +++ b/crates/ruff/src/rules/isort/rules/add_required_imports.rs @@ -1,7 +1,7 @@ use log::error; use ruff_text_size::{TextRange, TextSize}; use rustpython_parser as parser; -use rustpython_parser::ast::{self, StmtKind, Suite}; +use rustpython_parser::ast::{self, Stmt, Suite}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -56,29 +56,31 @@ impl AlwaysAutofixableViolation for MissingRequiredImport { fn contains(block: &Block, required_import: &AnyImport) -> bool { block.imports.iter().any(|import| match required_import { AnyImport::Import(required_import) => { - let StmtKind::Import(ast::StmtImport { + let Stmt::Import(ast::StmtImport { names, - }) = &import.node else { + range: _, + }) = &import else { return false; }; names.iter().any(|alias| { - &alias.node.name == required_import.name.name - && alias.node.asname.as_deref() == required_import.name.as_name + &alias.name == required_import.name.name + && alias.asname.as_deref() == required_import.name.as_name }) } AnyImport::ImportFrom(required_import) => { - let StmtKind::ImportFrom(ast::StmtImportFrom { + let Stmt::ImportFrom(ast::StmtImportFrom { module, names, level, - }) = &import.node else { + range: _, + }) = &import else { return false; }; module.as_deref() == required_import.module && level.map(|level| level.to_u32()) == required_import.level && names.iter().any(|alias| { - &alias.node.name == required_import.name.name - && alias.node.asname.as_deref() == required_import.name.as_name + &alias.name == required_import.name.name + && alias.asname.as_deref() == required_import.name.as_name }) } }) @@ -154,11 +156,12 @@ pub(crate) fn add_required_imports( return vec![]; } let stmt = &body[0]; - match &stmt.node { - StmtKind::ImportFrom(ast::StmtImportFrom { + match stmt { + Stmt::ImportFrom(ast::StmtImportFrom { module, names, level, + range: _, }) => names .iter() .filter_map(|name| { @@ -166,8 +169,8 @@ pub(crate) fn add_required_imports( &AnyImport::ImportFrom(ImportFrom { module: module.as_deref(), name: Alias { - name: name.node.name.as_str(), - as_name: name.node.asname.as_deref(), + name: name.name.as_str(), + as_name: name.asname.as_deref(), }, level: level.map(|level| level.to_u32()), }), @@ -180,14 +183,14 @@ pub(crate) fn add_required_imports( ) }) .collect(), - StmtKind::Import(ast::StmtImport { names }) => names + Stmt::Import(ast::StmtImport { names, range: _ }) => names .iter() .filter_map(|name| { add_required_import( &AnyImport::Import(Import { name: Alias { - name: name.node.name.as_str(), - as_name: name.node.asname.as_deref(), + name: name.name.as_str(), + as_name: name.asname.as_deref(), }, }), blocks, diff --git a/crates/ruff/src/rules/isort/rules/organize_imports.rs b/crates/ruff/src/rules/isort/rules/organize_imports.rs index 2d44d0a2b2..15ef0c8d3d 100644 --- a/crates/ruff/src/rules/isort/rules/organize_imports.rs +++ b/crates/ruff/src/rules/isort/rules/organize_imports.rs @@ -2,7 +2,7 @@ use std::path::Path; use itertools::{EitherOrBoth, Itertools}; use ruff_text_size::TextRange; -use rustpython_parser::ast::Stmt; +use rustpython_parser::ast::{Ranged, Stmt}; use textwrap::indent; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; diff --git a/crates/ruff/src/rules/isort/sorting.rs b/crates/ruff/src/rules/isort/sorting.rs index e5280dafde..9ce7d63bb3 100644 --- a/crates/ruff/src/rules/isort/sorting.rs +++ b/crates/ruff/src/rules/isort/sorting.rs @@ -68,7 +68,7 @@ pub(crate) fn cmp_modules( }) } -/// Compare two member imports within `StmtKind::ImportFrom` blocks. +/// Compare two member imports within `Stmt::ImportFrom` blocks. pub(crate) fn cmp_members( alias1: &AliasData, alias2: &AliasData, @@ -110,7 +110,7 @@ pub(crate) fn cmp_levels( } } -/// Compare two `StmtKind::ImportFrom` blocks. +/// Compare two `Stmt::ImportFrom` blocks. pub(crate) fn cmp_import_from( import_from1: &ImportFromData, import_from2: &ImportFromData, diff --git a/crates/ruff/src/rules/isort/track.rs b/crates/ruff/src/rules/isort/track.rs index 9ceb7aa6d5..7757056308 100644 --- a/crates/ruff/src/rules/isort/track.rs +++ b/crates/ruff/src/rules/isort/track.rs @@ -1,5 +1,5 @@ use ruff_text_size::{TextRange, TextSize}; -use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, MatchCase, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Excepthandler, MatchCase, Ranged, Stmt}; use ruff_python_ast::source_code::Locator; use ruff_python_ast::statement_visitor::StatementVisitor; @@ -75,15 +75,15 @@ impl<'a> ImportTracker<'a> { // least one blank line. In that case, we treat it as a regular // sibling (i.e., as if the comment is the next statement, as // opposed to the class or function). - match &stmt.node { - StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_) => { + match stmt { + Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) => { if helpers::has_comment_break(stmt, self.locator) { Trailer::Sibling } else { Trailer::FunctionDef } } - StmtKind::ClassDef(_) => { + Stmt::ClassDef(_) => { if helpers::has_comment_break(stmt, self.locator) { Trailer::Sibling } else { @@ -138,7 +138,7 @@ where } // Track imports. - if matches!(stmt.node, StmtKind::Import(_) | StmtKind::ImportFrom(_)) && !is_excluded { + if matches!(stmt, Stmt::Import(_) | Stmt::ImportFrom(_)) && !is_excluded { self.track_import(stmt); } else { self.finalize(self.trailer_for(stmt)); @@ -147,26 +147,26 @@ where // Track scope. let prev_nested = self.nested; self.nested = true; - match &stmt.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { body, .. }) => { + match stmt { + Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) => { for stmt in body { self.visit_stmt(stmt); } self.finalize(None); } - StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) => { + Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) => { for stmt in body { self.visit_stmt(stmt); } self.finalize(None); } - StmtKind::ClassDef(ast::StmtClassDef { body, .. }) => { + Stmt::ClassDef(ast::StmtClassDef { body, .. }) => { for stmt in body { self.visit_stmt(stmt); } self.finalize(None); } - StmtKind::For(ast::StmtFor { body, orelse, .. }) => { + Stmt::For(ast::StmtFor { body, orelse, .. }) => { for stmt in body { self.visit_stmt(stmt); } @@ -177,7 +177,7 @@ where } self.finalize(None); } - StmtKind::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) => { + Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) => { for stmt in body { self.visit_stmt(stmt); } @@ -188,7 +188,7 @@ where } self.finalize(None); } - StmtKind::While(ast::StmtWhile { body, orelse, .. }) => { + Stmt::While(ast::StmtWhile { body, orelse, .. }) => { for stmt in body { self.visit_stmt(stmt); } @@ -199,7 +199,7 @@ where } self.finalize(None); } - StmtKind::If(ast::StmtIf { body, orelse, .. }) => { + Stmt::If(ast::StmtIf { body, orelse, .. }) => { for stmt in body { self.visit_stmt(stmt); } @@ -210,34 +210,36 @@ where } self.finalize(None); } - StmtKind::With(ast::StmtWith { body, .. }) => { + Stmt::With(ast::StmtWith { body, .. }) => { for stmt in body { self.visit_stmt(stmt); } self.finalize(None); } - StmtKind::AsyncWith(ast::StmtAsyncWith { body, .. }) => { + Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { for stmt in body { self.visit_stmt(stmt); } self.finalize(None); } - StmtKind::Match(ast::StmtMatch { cases, .. }) => { + Stmt::Match(ast::StmtMatch { cases, .. }) => { for match_case in cases { self.visit_match_case(match_case); } } - StmtKind::Try(ast::StmtTry { + Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, + range: _, }) - | StmtKind::TryStar(ast::StmtTryStar { + | Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, finalbody, + range: _, }) => { for excepthandler in handlers { self.visit_excepthandler(excepthandler); @@ -267,8 +269,8 @@ where let prev_nested = self.nested; self.nested = true; - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) = - &excepthandler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) = + excepthandler; for stmt in body { self.visit_stmt(stmt); } diff --git a/crates/ruff/src/rules/mccabe/rules.rs b/crates/ruff/src/rules/mccabe/rules.rs index 73e6057242..9e0599118f 100644 --- a/crates/ruff/src/rules/mccabe/rules.rs +++ b/crates/ruff/src/rules/mccabe/rules.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, ExcepthandlerKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Excepthandler, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -68,44 +68,46 @@ impl Violation for ComplexStructure { fn get_complexity_number(stmts: &[Stmt]) -> usize { let mut complexity = 0; for stmt in stmts { - match &stmt.node { - StmtKind::If(ast::StmtIf { body, orelse, .. }) => { + match stmt { + Stmt::If(ast::StmtIf { body, orelse, .. }) => { complexity += 1; complexity += get_complexity_number(body); complexity += get_complexity_number(orelse); } - StmtKind::For(ast::StmtFor { body, orelse, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) => { + Stmt::For(ast::StmtFor { body, orelse, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) => { complexity += 1; complexity += get_complexity_number(body); complexity += get_complexity_number(orelse); } - StmtKind::With(ast::StmtWith { body, .. }) - | StmtKind::AsyncWith(ast::StmtAsyncWith { body, .. }) => { + Stmt::With(ast::StmtWith { body, .. }) + | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { complexity += get_complexity_number(body); } - StmtKind::While(ast::StmtWhile { body, orelse, .. }) => { + Stmt::While(ast::StmtWhile { body, orelse, .. }) => { complexity += 1; complexity += get_complexity_number(body); complexity += get_complexity_number(orelse); } - StmtKind::Match(ast::StmtMatch { cases, .. }) => { + Stmt::Match(ast::StmtMatch { cases, .. }) => { complexity += 1; for case in cases { complexity += get_complexity_number(&case.body); } } - StmtKind::Try(ast::StmtTry { + Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, + range: _, }) - | StmtKind::TryStar(ast::StmtTryStar { + | Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, finalbody, + range: _, }) => { complexity += get_complexity_number(body); if !orelse.is_empty() { @@ -115,19 +117,18 @@ fn get_complexity_number(stmts: &[Stmt]) -> usize { complexity += get_complexity_number(finalbody); for handler in handlers { complexity += 1; - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { - body, - .. - }) = &handler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { + body, .. + }) = handler; complexity += get_complexity_number(body); } } - StmtKind::FunctionDef(ast::StmtFunctionDef { body, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) => { + Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) => { complexity += 1; complexity += get_complexity_number(body); } - StmtKind::ClassDef(ast::StmtClassDef { body, .. }) => { + Stmt::ClassDef(ast::StmtClassDef { body, .. }) => { complexity += get_complexity_number(body); } _ => {} diff --git a/crates/ruff/src/rules/numpy/rules/deprecated_type_alias.rs b/crates/ruff/src/rules/numpy/rules/deprecated_type_alias.rs index 70ab2c2323..8a136e292f 100644 --- a/crates/ruff/src/rules/numpy/rules/deprecated_type_alias.rs +++ b/crates/ruff/src/rules/numpy/rules/deprecated_type_alias.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/numpy/rules/numpy_legacy_random.rs b/crates/ruff/src/rules/numpy/rules/numpy_legacy_random.rs index 3a8a7b1fa7..d1e5aa055b 100644 --- a/crates/ruff/src/rules/numpy/rules/numpy_legacy_random.rs +++ b/crates/ruff/src/rules/numpy/rules/numpy_legacy_random.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use crate::checkers::ast::Checker; use ruff_diagnostics::{Diagnostic, Violation}; diff --git a/crates/ruff/src/rules/pandas_vet/fixes.rs b/crates/ruff/src/rules/pandas_vet/fixes.rs index 76a43b3b78..a189dbac2a 100644 --- a/crates/ruff/src/rules/pandas_vet/fixes.rs +++ b/crates/ruff/src/rules/pandas_vet/fixes.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Expr, Keyword, Ranged}; use ruff_diagnostics::{Edit, Fix}; use ruff_python_ast::source_code::Locator; @@ -7,9 +7,9 @@ use ruff_python_ast::source_code::Locator; use crate::autofix::actions::remove_argument; fn match_name(expr: &Expr) -> Option<&str> { - if let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node { - if let ExprKind::Attribute(ast::ExprAttribute { value, .. }) = &func.node { - if let ExprKind::Name(ast::ExprName { id, .. }) = &value.node { + if let Expr::Call(ast::ExprCall { func, .. }) = expr { + if let Expr::Attribute(ast::ExprAttribute { value, .. }) = func.as_ref() { + if let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() { return Some(id); } } diff --git a/crates/ruff/src/rules/pandas_vet/helpers.rs b/crates/ruff/src/rules/pandas_vet/helpers.rs index 271f17f6f0..cbe66b476a 100644 --- a/crates/ruff/src/rules/pandas_vet/helpers.rs +++ b/crates/ruff/src/rules/pandas_vet/helpers.rs @@ -1,18 +1,18 @@ -use rustpython_parser::ast::{Expr, ExprKind}; +use rustpython_parser::ast::Expr; /// Return `true` if an `Expr` _could_ be a `DataFrame`. This rules out /// obviously-wrong cases, like constants and literals. pub(crate) const fn is_dataframe_candidate(expr: &Expr) -> bool { !matches!( - expr.node, - ExprKind::Constant(_) - | ExprKind::Tuple(_) - | ExprKind::List(_) - | ExprKind::Set(_) - | ExprKind::Dict(_) - | ExprKind::SetComp(_) - | ExprKind::ListComp(_) - | ExprKind::DictComp(_) - | ExprKind::GeneratorExp(_) + expr, + Expr::Constant(_) + | Expr::Tuple(_) + | Expr::List(_) + | Expr::Set(_) + | Expr::Dict(_) + | Expr::SetComp(_) + | Expr::ListComp(_) + | Expr::DictComp(_) + | Expr::GeneratorExp(_) ) } diff --git a/crates/ruff/src/rules/pandas_vet/rules/assignment_to_df.rs b/crates/ruff/src/rules/pandas_vet/rules/assignment_to_df.rs index 8c0ab99784..6473d4a7a9 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/assignment_to_df.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/assignment_to_df.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -19,7 +19,7 @@ pub(crate) fn assignment_to_df(targets: &[Expr]) -> Option { return None; } let target = &targets[0]; - let ExprKind::Name(ast::ExprName { id, .. }) = &target.node else { + let Expr::Name(ast::ExprName { id, .. }) = target else { return None; }; if id != "df" { diff --git a/crates/ruff/src/rules/pandas_vet/rules/check_attr.rs b/crates/ruff/src/rules/pandas_vet/rules/check_attr.rs index 2df6177cc1..c392a99c78 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/check_attr.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/check_attr.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::Violation; use ruff_diagnostics::{Diagnostic, DiagnosticKind}; @@ -61,7 +61,7 @@ pub(crate) fn check_attr(checker: &mut Checker, attr: &str, value: &Expr, attr_e // Avoid flagging on function calls (e.g., `df.values()`). if let Some(parent) = checker.ctx.expr_parent() { - if matches!(parent.node, ExprKind::Call(_)) { + if matches!(parent, Expr::Call(_)) { return; } } @@ -72,7 +72,7 @@ pub(crate) fn check_attr(checker: &mut Checker, attr: &str, value: &Expr, attr_e // If the target is a named variable, avoid triggering on // irrelevant bindings (like imports). - if let ExprKind::Name(ast::ExprName { id, .. }) = &value.node { + if let Expr::Name(ast::ExprName { id, .. }) = value { if checker.ctx.find_binding(id).map_or(true, |binding| { matches!( binding.kind, diff --git a/crates/ruff/src/rules/pandas_vet/rules/check_call.rs b/crates/ruff/src/rules/pandas_vet/rules/check_call.rs index ee057b80f9..c2aa897cbd 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/check_call.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/check_call.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::Violation; use ruff_diagnostics::{Diagnostic, DiagnosticKind}; @@ -63,7 +63,7 @@ impl Violation for PandasUseOfDotStack { pub(crate) fn check_call(checker: &mut Checker, func: &Expr) { let rules = &checker.settings.rules; - let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. } )= &func.node else {return}; + let Expr::Attribute(ast::ExprAttribute { value, attr, .. } )= func else {return}; let violation: DiagnosticKind = match attr.as_str() { "isnull" if rules.enabled(Rule::PandasUseOfDotIsNull) => PandasUseOfDotIsNull.into(), "notnull" if rules.enabled(Rule::PandasUseOfDotNotNull) => PandasUseOfDotNotNull.into(), @@ -83,7 +83,7 @@ pub(crate) fn check_call(checker: &mut Checker, func: &Expr) { // If the target is a named variable, avoid triggering on // irrelevant bindings (like non-Pandas imports). - if let ExprKind::Name(ast::ExprName { id, .. }) = &value.node { + if let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() { if checker.ctx.find_binding(id).map_or(true, |binding| { if let BindingKind::Importation(Importation { full_name: module, .. diff --git a/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs b/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs index c24fd8888c..40421917bf 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs @@ -1,5 +1,5 @@ use ruff_python_semantic::binding::{BindingKind, Importation}; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword, StmtKind}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged}; use ruff_diagnostics::{AutofixKind, Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -76,13 +76,13 @@ pub(crate) fn inplace_argument( } for keyword in keywords.iter().rev() { - let Some(arg) = &keyword.node.arg else { + let Some(arg) = &keyword.arg else { seen_star = true; continue; }; if arg == "inplace" { - let is_true_literal = match &keyword.node.value.node { - ExprKind::Constant(ast::ExprConstant { + let is_true_literal = match &keyword.value { + Expr::Constant(ast::ExprConstant { value: Constant::Bool(boolean), .. }) => *boolean, @@ -99,7 +99,7 @@ pub(crate) fn inplace_argument( // but we don't currently restore expression stacks when parsing deferred nodes, // and so the parent is lost. let fixable = !seen_star - && matches!(checker.ctx.stmt().node, StmtKind::Expr(_)) + && checker.ctx.stmt().is_expr_stmt() && checker.ctx.expr_parent().is_none() && !checker.ctx.scope().kind.is_lambda(); let mut diagnostic = Diagnostic::new(PandasUseOfInplaceArgument, keyword.range()); diff --git a/crates/ruff/src/rules/pandas_vet/rules/pd_merge.rs b/crates/ruff/src/rules/pandas_vet/rules/pd_merge.rs index 6a01f7a134..b6c4120d7d 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/pd_merge.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/pd_merge.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -18,8 +18,8 @@ impl Violation for PandasUseOfPdMerge { /// PD015 pub(crate) fn use_of_pd_merge(func: &Expr) -> Option { - if let ExprKind::Attribute(ast::ExprAttribute { attr, value, .. }) = &func.node { - if let ExprKind::Name(ast::ExprName { id, .. }) = &value.node { + if let Expr::Attribute(ast::ExprAttribute { attr, value, .. }) = func { + if let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() { if id == "pd" && attr == "merge" { return Some(Diagnostic::new(PandasUseOfPdMerge, func.range())); } diff --git a/crates/ruff/src/rules/pep8_naming/helpers.rs b/crates/ruff/src/rules/pep8_naming/helpers.rs index 1bed2d3014..29b0a803f1 100644 --- a/crates/ruff/src/rules/pep8_naming/helpers.rs +++ b/crates/ruff/src/rules/pep8_naming/helpers.rs @@ -1,6 +1,6 @@ use itertools::Itertools; use ruff_python_semantic::context::Context; -use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Expr, Stmt}; use ruff_python_stdlib::str::{is_lower, is_upper}; @@ -23,10 +23,10 @@ pub(crate) fn is_acronym(name: &str, asname: &str) -> bool { } pub(crate) fn is_named_tuple_assignment(context: &Context, stmt: &Stmt) -> bool { - let StmtKind::Assign(ast::StmtAssign { value, .. }) = &stmt.node else { + let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else { return false; }; - let ExprKind::Call(ast::ExprCall {func, ..}) = &value.node else { + let Expr::Call(ast::ExprCall {func, ..}) = value.as_ref() else { return false; }; context.resolve_call_path(func).map_or(false, |call_path| { @@ -38,10 +38,10 @@ pub(crate) fn is_named_tuple_assignment(context: &Context, stmt: &Stmt) -> bool } pub(crate) fn is_typed_dict_assignment(context: &Context, stmt: &Stmt) -> bool { - let StmtKind::Assign(ast::StmtAssign { value, .. }) = &stmt.node else { + let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else { return false; }; - let ExprKind::Call(ast::ExprCall {func, ..}) = &value.node else { + let Expr::Call(ast::ExprCall {func, ..}) = value.as_ref() else { return false; }; context.resolve_call_path(func).map_or(false, |call_path| { @@ -50,10 +50,10 @@ pub(crate) fn is_typed_dict_assignment(context: &Context, stmt: &Stmt) -> bool { } pub(crate) fn is_type_var_assignment(context: &Context, stmt: &Stmt) -> bool { - let StmtKind::Assign(ast::StmtAssign { value, .. }) = &stmt.node else { + let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else { return false; }; - let ExprKind::Call(ast::ExprCall {func, ..}) = &value.node else { + let Expr::Call(ast::ExprCall {func, ..}) = value.as_ref() else { return false; }; context.resolve_call_path(func).map_or(false, |call_path| { diff --git a/crates/ruff/src/rules/pep8_naming/rules/camelcase_imported_as_acronym.rs b/crates/ruff/src/rules/pep8_naming/rules/camelcase_imported_as_acronym.rs index b416c3235d..a4ceec8d8d 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/camelcase_imported_as_acronym.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/camelcase_imported_as_acronym.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Alias, Stmt}; +use rustpython_parser::ast::{Alias, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pep8_naming/rules/camelcase_imported_as_constant.rs b/crates/ruff/src/rules/pep8_naming/rules/camelcase_imported_as_constant.rs index 98f3c1a2ae..355be20923 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/camelcase_imported_as_constant.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/camelcase_imported_as_constant.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Alias, Stmt}; +use rustpython_parser::ast::{Alias, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pep8_naming/rules/camelcase_imported_as_lowercase.rs b/crates/ruff/src/rules/pep8_naming/rules/camelcase_imported_as_lowercase.rs index 3a6560aa4d..c427e879a5 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/camelcase_imported_as_lowercase.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/camelcase_imported_as_lowercase.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Alias, Stmt}; +use rustpython_parser::ast::{Alias, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pep8_naming/rules/constant_imported_as_non_constant.rs b/crates/ruff/src/rules/pep8_naming/rules/constant_imported_as_non_constant.rs index a5cff55308..79cf3b32af 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/constant_imported_as_non_constant.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/constant_imported_as_non_constant.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Alias, Stmt}; +use rustpython_parser::ast::{Alias, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pep8_naming/rules/error_suffix_on_exception_name.rs b/crates/ruff/src/rules/pep8_naming/rules/error_suffix_on_exception_name.rs index bc99b49af6..c75678682c 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/error_suffix_on_exception_name.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/error_suffix_on_exception_name.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Stmt}; +use rustpython_parser::ast::{self, Expr, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -49,7 +49,7 @@ pub(crate) fn error_suffix_on_exception_name( locator: &Locator, ) -> Option { if !bases.iter().any(|base| { - if let ExprKind::Name(ast::ExprName { id, .. }) = &base.node { + if let Expr::Name(ast::ExprName { id, .. }) = &base { id == "Exception" || id.ends_with("Error") } else { false diff --git a/crates/ruff/src/rules/pep8_naming/rules/invalid_argument_name.rs b/crates/ruff/src/rules/pep8_naming/rules/invalid_argument_name.rs index 517eca1ed0..c2c8fe8d08 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/invalid_argument_name.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/invalid_argument_name.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Arg; +use rustpython_parser::ast::{Arg, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_class_method.rs b/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_class_method.rs index f8390ca5df..010d69dfb4 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_class_method.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_class_method.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Arguments, Expr}; +use rustpython_parser::ast::{Arguments, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -76,7 +76,7 @@ pub(crate) fn invalid_first_argument_name_for_class_method( return None; } if let Some(arg) = args.posonlyargs.first().or_else(|| args.args.first()) { - if &arg.node.arg != "cls" { + if &arg.arg != "cls" { if checker .settings .pep8_naming diff --git a/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_method.rs b/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_method.rs index 757d5a17f5..6a6c786035 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_method.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_method.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Arguments, Expr}; +use rustpython_parser::ast::{Arguments, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -73,7 +73,7 @@ pub(crate) fn invalid_first_argument_name_for_method( return None; } let arg = args.posonlyargs.first().or_else(|| args.args.first())?; - if &arg.node.arg == "self" { + if &arg.arg == "self" { return None; } if checker diff --git a/crates/ruff/src/rules/pep8_naming/rules/lowercase_imported_as_non_lowercase.rs b/crates/ruff/src/rules/pep8_naming/rules/lowercase_imported_as_non_lowercase.rs index 21f3a681cd..5d347f1f9d 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/lowercase_imported_as_non_lowercase.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/lowercase_imported_as_non_lowercase.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Alias, Stmt}; +use rustpython_parser::ast::{Alias, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_class_scope.rs b/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_class_scope.rs index 4e06f21523..6834f0a093 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_class_scope.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_class_scope.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, Stmt}; +use rustpython_parser::ast::{Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_global_scope.rs b/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_global_scope.rs index f2563fc5e0..fcad8aa628 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_global_scope.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_global_scope.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, Stmt}; +use rustpython_parser::ast::{Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pep8_naming/rules/non_lowercase_variable_in_function.rs b/crates/ruff/src/rules/pep8_naming/rules/non_lowercase_variable_in_function.rs index e2c7beb63e..2b7e45286d 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/non_lowercase_variable_in_function.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/non_lowercase_variable_in_function.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, Stmt}; +use rustpython_parser::ast::{Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pycodestyle/helpers.rs b/crates/ruff/src/rules/pycodestyle/helpers.rs index 93e973233d..d3766abd97 100644 --- a/crates/ruff/src/rules/pycodestyle/helpers.rs +++ b/crates/ruff/src/rules/pycodestyle/helpers.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::helpers::{create_expr, unparse_expr}; +use ruff_python_ast::helpers::unparse_expr; use ruff_python_ast::newlines::Line; use ruff_python_ast::source_code::Stylist; use ruff_text_size::{TextLen, TextRange}; @@ -15,14 +15,13 @@ pub(crate) fn compare( comparators: &[Expr], stylist: &Stylist, ) -> String { - unparse_expr( - &create_expr(ast::ExprCompare { - left: Box::new(left.clone()), - ops: ops.to_vec(), - comparators: comparators.to_vec(), - }), - stylist, - ) + let node = ast::ExprCompare { + left: Box::new(left.clone()), + ops: ops.to_vec(), + comparators: comparators.to_vec(), + range: TextRange::default(), + }; + unparse_expr(&node.into(), stylist) } pub(super) fn is_overlong( diff --git a/crates/ruff/src/rules/pycodestyle/rules/bare_except.rs b/crates/ruff/src/rules/pycodestyle/rules/bare_except.rs index 6b22ac8dd3..f2d591e061 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/bare_except.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/bare_except.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Excepthandler, Expr, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Excepthandler, Expr, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -54,7 +54,7 @@ pub(crate) fn bare_except( if type_.is_none() && !body .iter() - .any(|stmt| matches!(stmt.node, StmtKind::Raise(ast::StmtRaise { exc: None, .. }))) + .any(|stmt| matches!(stmt, Stmt::Raise(ast::StmtRaise { exc: None, .. }))) { Some(Diagnostic::new(BareExcept, except_range(handler, locator))) } else { diff --git a/crates/ruff/src/rules/pycodestyle/rules/imports.rs b/crates/ruff/src/rules/pycodestyle/rules/imports.rs index 17262229cd..09cc5fb600 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/imports.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/imports.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Alias, Stmt}; +use rustpython_parser::ast::{Alias, Ranged, Stmt}; use crate::checkers::ast::Checker; use ruff_diagnostics::{Diagnostic, Violation}; diff --git a/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs b/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs index 068836c3e7..5256c2e24c 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs @@ -7,7 +7,7 @@ use ruff_python_ast::whitespace::leading_space; use ruff_python_semantic::context::Context; use ruff_python_semantic::scope::ScopeKind; use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Arg, ArgData, Arguments, Constant, Expr, ExprKind, Stmt}; +use rustpython_parser::ast::{self, Arg, Arguments, Constant, Expr, Ranged, Stmt}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -63,8 +63,8 @@ pub(crate) fn lambda_assignment( annotation: Option<&Expr>, stmt: &Stmt, ) { - if let ExprKind::Name(ast::ExprName { id, .. }) = &target.node { - if let ExprKind::Lambda(ast::ExprLambda { args, body }) = &value.node { + if let Expr::Name(ast::ExprName { id, .. }) = target { + if let Expr::Lambda(ast::ExprLambda { args, body, .. }) = value { // If the assignment is in a class body, it might not be safe // to replace it because the assignment might be // carrying a type annotation that will be used by some @@ -118,10 +118,10 @@ pub(crate) fn lambda_assignment( /// If an ellipsis is used for the argument types, an empty list is returned. /// The returned values are cloned, so they can be used as-is. fn extract_types(ctx: &Context, annotation: &Expr) -> Option<(Vec, Expr)> { - let ExprKind::Subscript(ast::ExprSubscript { value, slice, .. }) = &annotation.node else { + let Expr::Subscript(ast::ExprSubscript { value, slice, .. }) = &annotation else { return None; }; - let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &slice.node else { + let Expr::Tuple(ast::ExprTuple { elts, .. }) = slice.as_ref() else { return None; }; if elts.len() != 2 { @@ -137,9 +137,9 @@ fn extract_types(ctx: &Context, annotation: &Expr) -> Option<(Vec, Expr)> // The first argument to `Callable` must be a list of types, parameter // specification, or ellipsis. - let args = match &elts[0].node { - ExprKind::List(ast::ExprList { elts, .. }) => elts.clone(), - ExprKind::Constant(ast::ExprConstant { + let args = match &elts[0] { + Expr::List(ast::ExprList { elts, .. }) => elts.clone(), + Expr::Constant(ast::ExprConstant { value: Constant::Ellipsis, .. }) => vec![], @@ -160,12 +160,10 @@ fn function( annotation: Option<&Expr>, stylist: &Stylist, ) -> String { - let body = Stmt::new( - TextRange::default(), - ast::StmtReturn { - value: Some(Box::new(body.clone())), - }, - ); + let body = Stmt::Return(ast::StmtReturn { + value: Some(Box::new(body.clone())), + range: TextRange::default(), + }); if let Some(annotation) = annotation { if let Some((arg_types, return_type)) = extract_types(ctx, annotation) { // A `lambda` expression can only have positional and positional-only @@ -174,62 +172,48 @@ fn function( .posonlyargs .iter() .enumerate() - .map(|(idx, arg)| { - Arg::new( - TextRange::default(), - ArgData { - annotation: arg_types - .get(idx) - .map(|arg_type| Box::new(arg_type.clone())), - ..arg.node.clone() - }, - ) + .map(|(idx, arg)| Arg { + annotation: arg_types + .get(idx) + .map(|arg_type| Box::new(arg_type.clone())), + ..arg.clone() }) .collect::>(); let new_args = args .args .iter() .enumerate() - .map(|(idx, arg)| { - Arg::new( - TextRange::default(), - ArgData { - annotation: arg_types - .get(idx + new_posonlyargs.len()) - .map(|arg_type| Box::new(arg_type.clone())), - ..arg.node.clone() - }, - ) + .map(|(idx, arg)| Arg { + annotation: arg_types + .get(idx + new_posonlyargs.len()) + .map(|arg_type| Box::new(arg_type.clone())), + ..arg.clone() }) .collect::>(); - let func = Stmt::new( - TextRange::default(), - ast::StmtFunctionDef { - name: name.into(), - args: Box::new(Arguments { - posonlyargs: new_posonlyargs, - args: new_args, - ..args.clone() - }), - body: vec![body], - decorator_list: vec![], - returns: Some(Box::new(return_type)), - type_comment: None, - }, - ); + let func = Stmt::FunctionDef(ast::StmtFunctionDef { + name: name.into(), + args: Box::new(Arguments { + posonlyargs: new_posonlyargs, + args: new_args, + ..args.clone() + }), + body: vec![body], + decorator_list: vec![], + returns: Some(Box::new(return_type)), + type_comment: None, + range: TextRange::default(), + }); return unparse_stmt(&func, stylist); } } - let func = Stmt::new( - TextRange::default(), - ast::StmtFunctionDef { - name: name.into(), - args: Box::new(args.clone()), - body: vec![body], - decorator_list: vec![], - returns: None, - type_comment: None, - }, - ); + let func = Stmt::FunctionDef(ast::StmtFunctionDef { + name: name.into(), + args: Box::new(args.clone()), + body: vec![body], + decorator_list: vec![], + returns: None, + type_comment: None, + range: TextRange::default(), + }); unparse_stmt(&func, stylist) } diff --git a/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs b/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs index 480ae18380..94a5bfe34f 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs @@ -1,6 +1,6 @@ use itertools::izip; use rustc_hash::FxHashMap; -use rustpython_parser::ast::{self, Cmpop, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Cmpop, Constant, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -156,10 +156,11 @@ pub(crate) fn literal_comparisons( if !helpers::is_constant_non_singleton(next) { if check_none_comparisons && matches!( - comparator.node, - ExprKind::Constant(ast::ExprConstant { + comparator, + Expr::Constant(ast::ExprConstant { value: Constant::None, - kind: None + kind: None, + range: _ }) ) { @@ -180,14 +181,15 @@ pub(crate) fn literal_comparisons( } if check_true_false_comparisons { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Bool(value), kind: None, - }) = comparator.node + range: _, + }) = comparator { if matches!(op, Cmpop::Eq) { let diagnostic = - Diagnostic::new(TrueFalseComparison(value, op.into()), comparator.range()); + Diagnostic::new(TrueFalseComparison(*value, op.into()), comparator.range()); if checker.patch(diagnostic.kind.rule()) { bad_ops.insert(0, Cmpop::Is); } @@ -195,7 +197,7 @@ pub(crate) fn literal_comparisons( } if matches!(op, Cmpop::NotEq) { let diagnostic = - Diagnostic::new(TrueFalseComparison(value, op.into()), comparator.range()); + Diagnostic::new(TrueFalseComparison(*value, op.into()), comparator.range()); if checker.patch(diagnostic.kind.rule()) { bad_ops.insert(0, Cmpop::IsNot); } @@ -214,10 +216,11 @@ pub(crate) fn literal_comparisons( if check_none_comparisons && matches!( - next.node, - ExprKind::Constant(ast::ExprConstant { + next, + Expr::Constant(ast::ExprConstant { value: Constant::None, - kind: None + kind: None, + range: _ }) ) { @@ -238,22 +241,22 @@ pub(crate) fn literal_comparisons( } if check_true_false_comparisons { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Bool(value), kind: None, - }) = next.node + range: _, + }) = next { - if matches!(op, Cmpop::Eq) { + if op.is_eq() { let diagnostic = - Diagnostic::new(TrueFalseComparison(value, op.into()), next.range()); + Diagnostic::new(TrueFalseComparison(*value, op.into()), next.range()); if checker.patch(diagnostic.kind.rule()) { bad_ops.insert(idx, Cmpop::Is); } diagnostics.push(diagnostic); - } - if matches!(op, Cmpop::NotEq) { + } else if op.is_not_eq() { let diagnostic = - Diagnostic::new(TrueFalseComparison(value, op.into()), next.range()); + Diagnostic::new(TrueFalseComparison(*value, op.into()), next.range()); if checker.patch(diagnostic.kind.rule()) { bad_ops.insert(idx, Cmpop::IsNot); } @@ -273,7 +276,7 @@ pub(crate) fn literal_comparisons( .iter() .enumerate() .map(|(idx, op)| bad_ops.get(&idx).unwrap_or(op)) - .cloned() + .copied() .collect::>(); let content = compare(left, &ops, comparators, checker.stylist); for diagnostic in &mut diagnostics { diff --git a/crates/ruff/src/rules/pycodestyle/rules/not_tests.rs b/crates/ruff/src/rules/pycodestyle/rules/not_tests.rs index 685104ef07..971856e9d7 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/not_tests.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/not_tests.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Cmpop, Expr, ExprKind, Unaryop}; +use rustpython_parser::ast::{self, Cmpop, Expr, Ranged, Unaryop}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -77,17 +77,18 @@ impl AlwaysAutofixableViolation for NotIsTest { pub(crate) fn not_tests( checker: &mut Checker, expr: &Expr, - op: &Unaryop, + op: Unaryop, operand: &Expr, check_not_in: bool, check_not_is: bool, ) { if matches!(op, Unaryop::Not) { - if let ExprKind::Compare(ast::ExprCompare { + if let Expr::Compare(ast::ExprCompare { left, ops, comparators, - }) = &operand.node + range: _, + }) = operand { if !matches!(&ops[..], [Cmpop::In | Cmpop::Is]) { return; diff --git a/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs b/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs index 350f47cf26..e4d93a02b3 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs @@ -1,5 +1,5 @@ use itertools::izip; -use rustpython_parser::ast::{self, Cmpop, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Cmpop, Constant, Expr, Ranged}; use crate::checkers::ast::Checker; use ruff_diagnostics::{Diagnostic, Violation}; @@ -47,19 +47,20 @@ pub(crate) fn type_comparison( if !matches!(op, Cmpop::Is | Cmpop::IsNot | Cmpop::Eq | Cmpop::NotEq) { continue; } - match &right.node { - ExprKind::Call(ast::ExprCall { func, args, .. }) => { - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { + match right { + Expr::Call(ast::ExprCall { func, args, .. }) => { + if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { // Ex) `type(False)` if id == "type" && checker.ctx.is_builtin("type") { if let Some(arg) = args.first() { // Allow comparison for types which are not obvious. if !matches!( - arg.node, - ExprKind::Name(_) - | ExprKind::Constant(ast::ExprConstant { + arg, + Expr::Name(_) + | Expr::Constant(ast::ExprConstant { value: Constant::None, - kind: None + kind: None, + range: _ }) ) { checker @@ -70,8 +71,8 @@ pub(crate) fn type_comparison( } } } - ExprKind::Attribute(ast::ExprAttribute { value, .. }) => { - if let ExprKind::Name(ast::ExprName { id, .. }) = &value.node { + Expr::Attribute(ast::ExprAttribute { value, .. }) => { + if let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() { // Ex) `types.NoneType` if id == "types" && checker diff --git a/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_class.rs b/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_class.rs index 61318d8dca..a07bf56ff8 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_class.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_class.rs @@ -3,6 +3,7 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::newlines::{StrExt, UniversalNewlineIterator}; use ruff_python_semantic::definition::{Definition, Member, MemberKind}; use ruff_text_size::{TextLen, TextRange}; +use rustpython_parser::ast::Ranged; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; diff --git a/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_function.rs b/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_function.rs index dd81c317c7..41469ec9d3 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_function.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_function.rs @@ -1,6 +1,7 @@ use once_cell::sync::Lazy; use regex::Regex; use ruff_text_size::{TextLen, TextRange}; +use rustpython_parser::ast::Ranged; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pydocstyle/rules/capitalized.rs b/crates/ruff/src/rules/pydocstyle/rules/capitalized.rs index ad47747d81..7a77ddcd7f 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/capitalized.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/capitalized.rs @@ -1,4 +1,5 @@ use ruff_text_size::{TextLen, TextRange}; +use rustpython_parser::ast::Ranged; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pydocstyle/rules/multi_line_summary_start.rs b/crates/ruff/src/rules/pydocstyle/rules/multi_line_summary_start.rs index 7bcbac89aa..c1ee8cf9a4 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/multi_line_summary_start.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/multi_line_summary_start.rs @@ -1,4 +1,5 @@ use ruff_text_size::{TextRange, TextSize}; +use rustpython_parser::ast::Ranged; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pydocstyle/rules/newline_after_last_paragraph.rs b/crates/ruff/src/rules/pydocstyle/rules/newline_after_last_paragraph.rs index 05adc5ab97..34f3cf1047 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/newline_after_last_paragraph.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/newline_after_last_paragraph.rs @@ -3,6 +3,7 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::newlines::{NewlineWithTrailingNewline, StrExt}; use ruff_python_ast::whitespace; use ruff_text_size::{TextLen, TextSize}; +use rustpython_parser::ast::Ranged; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; diff --git a/crates/ruff/src/rules/pydocstyle/rules/no_signature.rs b/crates/ruff/src/rules/pydocstyle/rules/no_signature.rs index 8abffb86ec..ccfbf599f5 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/no_signature.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/no_signature.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, StmtKind}; +use rustpython_parser::ast::{self, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -27,7 +27,7 @@ pub(crate) fn no_signature(checker: &mut Checker, docstring: &Docstring) { }) = docstring.definition else { return; }; - let StmtKind::FunctionDef(ast::StmtFunctionDef { name, .. }) = &stmt.node else { + let Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) = stmt else { return; }; diff --git a/crates/ruff/src/rules/pydocstyle/rules/sections.rs b/crates/ruff/src/rules/pydocstyle/rules/sections.rs index f5893264ed..2f4b5adc5d 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/sections.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/sections.rs @@ -3,7 +3,7 @@ use once_cell::sync::Lazy; use regex::Regex; use ruff_text_size::{TextLen, TextRange, TextSize}; use rustc_hash::FxHashSet; -use rustpython_parser::ast::{self, StmtKind}; +use rustpython_parser::ast::{self, Stmt}; use ruff_diagnostics::{AlwaysAutofixableViolation, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix}; @@ -739,13 +739,13 @@ fn missing_args(checker: &mut Checker, docstring: &Docstring, docstrings_args: & }; let ( - StmtKind::FunctionDef(ast::StmtFunctionDef { + Stmt::FunctionDef(ast::StmtFunctionDef { args: arguments, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { args: arguments, .. }) - ) = &stmt.node else { + ) = stmt else { return; }; @@ -764,7 +764,7 @@ fn missing_args(checker: &mut Checker, docstring: &Docstring, docstrings_args: & ), ) { - let arg_name = arg.node.arg.as_str(); + let arg_name = arg.arg.as_str(); if !arg_name.starts_with('_') && !docstrings_args.contains(arg_name) { missing_arg_names.insert(arg_name.to_string()); } @@ -773,7 +773,7 @@ fn missing_args(checker: &mut Checker, docstring: &Docstring, docstrings_args: & // Check specifically for `vararg` and `kwarg`, which can be prefixed with a // single or double star, respectively. if let Some(arg) = &arguments.vararg { - let arg_name = arg.node.arg.as_str(); + let arg_name = arg.arg.as_str(); let starred_arg_name = format!("*{arg_name}"); if !arg_name.starts_with('_') && !docstrings_args.contains(arg_name) @@ -783,7 +783,7 @@ fn missing_args(checker: &mut Checker, docstring: &Docstring, docstrings_args: & } } if let Some(arg) = &arguments.kwarg { - let arg_name = arg.node.arg.as_str(); + let arg_name = arg.arg.as_str(); let starred_arg_name = format!("**{arg_name}"); if !arg_name.starts_with('_') && !docstrings_args.contains(arg_name) diff --git a/crates/ruff/src/rules/pyflakes/fixes.rs b/crates/ruff/src/rules/pyflakes/fixes.rs index 8abfffb330..904eba68e7 100644 --- a/crates/ruff/src/rules/pyflakes/fixes.rs +++ b/crates/ruff/src/rules/pyflakes/fixes.rs @@ -1,7 +1,7 @@ use anyhow::{bail, Ok, Result}; use libcst_native::{Codegen, CodegenState, DictElement, Expression}; use ruff_text_size::TextRange; -use rustpython_parser::ast::{Excepthandler, Expr}; +use rustpython_parser::ast::{Excepthandler, Expr, Ranged}; use rustpython_parser::{lexer, Mode, Tok}; use ruff_diagnostics::Edit; diff --git a/crates/ruff/src/rules/pyflakes/rules/assert_tuple.rs b/crates/ruff/src/rules/pyflakes/rules/assert_tuple.rs index fe968945a8..456c18b45f 100644 --- a/crates/ruff/src/rules/pyflakes/rules/assert_tuple.rs +++ b/crates/ruff/src/rules/pyflakes/rules/assert_tuple.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Stmt}; +use rustpython_parser::ast::{self, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -17,7 +17,7 @@ impl Violation for AssertTuple { /// F631 pub(crate) fn assert_tuple(checker: &mut Checker, stmt: &Stmt, test: &Expr) { - if let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &test.node { + if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &test { if !elts.is_empty() { checker .diagnostics diff --git a/crates/ruff/src/rules/pyflakes/rules/break_outside_loop.rs b/crates/ruff/src/rules/pyflakes/rules/break_outside_loop.rs index 11e8567c2d..026a7bfb29 100644 --- a/crates/ruff/src/rules/pyflakes/rules/break_outside_loop.rs +++ b/crates/ruff/src/rules/pyflakes/rules/break_outside_loop.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -21,16 +21,16 @@ pub(crate) fn break_outside_loop<'a>( let mut allowed: bool = false; let mut child = stmt; for parent in parents { - match &parent.node { - StmtKind::For(ast::StmtFor { orelse, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { orelse, .. }) - | StmtKind::While(ast::StmtWhile { orelse, .. }) => { + match parent { + Stmt::For(ast::StmtFor { orelse, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { orelse, .. }) + | Stmt::While(ast::StmtWhile { orelse, .. }) => { if !orelse.contains(child) { allowed = true; break; } } - StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_) | StmtKind::ClassDef(_) => { + Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) | Stmt::ClassDef(_) => { break; } _ => {} diff --git a/crates/ruff/src/rules/pyflakes/rules/continue_outside_loop.rs b/crates/ruff/src/rules/pyflakes/rules/continue_outside_loop.rs index 4b7156e0e1..e483a6496b 100644 --- a/crates/ruff/src/rules/pyflakes/rules/continue_outside_loop.rs +++ b/crates/ruff/src/rules/pyflakes/rules/continue_outside_loop.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -21,16 +21,16 @@ pub(crate) fn continue_outside_loop<'a>( let mut allowed: bool = false; let mut child = stmt; for parent in parents { - match &parent.node { - StmtKind::For(ast::StmtFor { orelse, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { orelse, .. }) - | StmtKind::While(ast::StmtWhile { orelse, .. }) => { + match parent { + Stmt::For(ast::StmtFor { orelse, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { orelse, .. }) + | Stmt::While(ast::StmtWhile { orelse, .. }) => { if !orelse.contains(child) { allowed = true; break; } } - StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_) | StmtKind::ClassDef(_) => { + Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) | Stmt::ClassDef(_) => { break; } _ => {} diff --git a/crates/ruff/src/rules/pyflakes/rules/default_except_not_last.rs b/crates/ruff/src/rules/pyflakes/rules/default_except_not_last.rs index df8c303a59..25981d38c3 100644 --- a/crates/ruff/src/rules/pyflakes/rules/default_except_not_last.rs +++ b/crates/ruff/src/rules/pyflakes/rules/default_except_not_last.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind}; +use rustpython_parser::ast::{self, Excepthandler}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -21,8 +21,7 @@ pub(crate) fn default_except_not_last( locator: &Locator, ) -> Option { for (idx, handler) in handlers.iter().enumerate() { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = - &handler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = handler; if type_.is_none() && idx < handlers.len() - 1 { return Some(Diagnostic::new( DefaultExceptNotLast, diff --git a/crates/ruff/src/rules/pyflakes/rules/f_string_missing_placeholders.rs b/crates/ruff/src/rules/pyflakes/rules/f_string_missing_placeholders.rs index 195e76b265..b8d04af426 100644 --- a/crates/ruff/src/rules/pyflakes/rules/f_string_missing_placeholders.rs +++ b/crates/ruff/src/rules/pyflakes/rules/f_string_missing_placeholders.rs @@ -1,5 +1,5 @@ use ruff_text_size::{TextRange, TextSize}; -use rustpython_parser::ast::{Expr, ExprKind}; +use rustpython_parser::ast::{Expr, Ranged}; use rustpython_parser::{lexer, Mode, StringKind, Tok}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; @@ -101,7 +101,7 @@ fn fix_f_string_missing_placeholders( pub(crate) fn f_string_missing_placeholders(expr: &Expr, values: &[Expr], checker: &mut Checker) { if !values .iter() - .any(|value| matches!(value.node, ExprKind::FormattedValue(_))) + .any(|value| matches!(value, Expr::FormattedValue(_))) { for (prefix_range, tok_range) in find_useless_f_strings(expr, checker.locator) { let mut diagnostic = Diagnostic::new(FStringMissingPlaceholders, tok_range); diff --git a/crates/ruff/src/rules/pyflakes/rules/if_tuple.rs b/crates/ruff/src/rules/pyflakes/rules/if_tuple.rs index 603cbf6ac1..3fcdcf9d21 100644 --- a/crates/ruff/src/rules/pyflakes/rules/if_tuple.rs +++ b/crates/ruff/src/rules/pyflakes/rules/if_tuple.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Stmt}; +use rustpython_parser::ast::{self, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -17,7 +17,7 @@ impl Violation for IfTuple { /// F634 pub(crate) fn if_tuple(checker: &mut Checker, stmt: &Stmt, test: &Expr) { - if let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &test.node { + if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &test { if !elts.is_empty() { checker .diagnostics diff --git a/crates/ruff/src/rules/pyflakes/rules/imports.rs b/crates/ruff/src/rules/pyflakes/rules/imports.rs index 0cc8305b0c..f7651469ab 100644 --- a/crates/ruff/src/rules/pyflakes/rules/imports.rs +++ b/crates/ruff/src/rules/pyflakes/rules/imports.rs @@ -1,5 +1,5 @@ use itertools::Itertools; -use rustpython_parser::ast::Alias; +use rustpython_parser::ast::{Alias, Ranged}; use ruff_diagnostics::Diagnostic; use ruff_diagnostics::{AutofixKind, Violation}; @@ -136,10 +136,10 @@ impl Violation for FutureFeatureNotDefined { } pub(crate) fn future_feature_not_defined(checker: &mut Checker, alias: &Alias) { - if !ALL_FEATURE_NAMES.contains(&alias.node.name.as_str()) { + if !ALL_FEATURE_NAMES.contains(&alias.name.as_str()) { checker.diagnostics.push(Diagnostic::new( FutureFeatureNotDefined { - name: alias.node.name.to_string(), + name: alias.name.to_string(), }, alias.range(), )); diff --git a/crates/ruff/src/rules/pyflakes/rules/invalid_literal_comparisons.rs b/crates/ruff/src/rules/pyflakes/rules/invalid_literal_comparisons.rs index cb415c3ee3..59d4e790be 100644 --- a/crates/ruff/src/rules/pyflakes/rules/invalid_literal_comparisons.rs +++ b/crates/ruff/src/rules/pyflakes/rules/invalid_literal_comparisons.rs @@ -69,8 +69,8 @@ pub(crate) fn invalid_literal_comparison( let mut diagnostic = Diagnostic::new(IsLiteral { cmpop: op.into() }, location); if checker.patch(diagnostic.kind.rule()) { if let Some(located_op) = &located.get(index) { - assert_eq!(&located_op.node, op); - if let Some(content) = match &located_op.node { + assert_eq!(located_op.op, *op); + if let Some(content) = match located_op.op { Cmpop::Is => Some("==".to_string()), Cmpop::IsNot => Some("!=".to_string()), node => { @@ -81,7 +81,7 @@ pub(crate) fn invalid_literal_comparison( #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( content, - located_op.range() + location.start(), + located_op.range + location.start(), ))); } } else { diff --git a/crates/ruff/src/rules/pyflakes/rules/invalid_print_syntax.rs b/crates/ruff/src/rules/pyflakes/rules/invalid_print_syntax.rs index 3539bc6786..7e47e176f6 100644 --- a/crates/ruff/src/rules/pyflakes/rules/invalid_print_syntax.rs +++ b/crates/ruff/src/rules/pyflakes/rules/invalid_print_syntax.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -17,7 +17,7 @@ impl Violation for InvalidPrintSyntax { /// F633 pub(crate) fn invalid_print_syntax(checker: &mut Checker, left: &Expr) { - let ExprKind::Name(ast::ExprName { id, .. }) = &left.node else { + let Expr::Name(ast::ExprName { id, .. }) = &left else { return; }; if id != "print" { diff --git a/crates/ruff/src/rules/pyflakes/rules/raise_not_implemented.rs b/crates/ruff/src/rules/pyflakes/rules/raise_not_implemented.rs index 89f43a0392..d639ffa07c 100644 --- a/crates/ruff/src/rules/pyflakes/rules/raise_not_implemented.rs +++ b/crates/ruff/src/rules/pyflakes/rules/raise_not_implemented.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -21,15 +21,15 @@ impl AlwaysAutofixableViolation for RaiseNotImplemented { } fn match_not_implemented(expr: &Expr) -> Option<&Expr> { - match &expr.node { - ExprKind::Call(ast::ExprCall { func, .. }) => { - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { + match expr { + Expr::Call(ast::ExprCall { func, .. }) => { + if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { if id == "NotImplemented" { return Some(func); } } } - ExprKind::Name(ast::ExprName { id, .. }) => { + Expr::Name(ast::ExprName { id, .. }) => { if id == "NotImplemented" { return Some(expr); } diff --git a/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs b/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs index 1d80f9550d..09e40ab42e 100644 --- a/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs +++ b/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs @@ -1,7 +1,7 @@ use std::hash::{BuildHasherDefault, Hash}; use rustc_hash::{FxHashMap, FxHashSet}; -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -73,11 +73,11 @@ enum DictionaryKey<'a> { } fn into_dictionary_key(expr: &Expr) -> Option { - match &expr.node { - ExprKind::Constant(ast::ExprConstant { value, .. }) => { + match expr { + Expr::Constant(ast::ExprConstant { value, .. }) => { Some(DictionaryKey::Constant(value.into())) } - ExprKind::Name(ast::ExprName { id, .. }) => Some(DictionaryKey::Variable(id)), + Expr::Name(ast::ExprName { id, .. }) => Some(DictionaryKey::Variable(id)), _ => None, } } diff --git a/crates/ruff/src/rules/pyflakes/rules/return_outside_function.rs b/crates/ruff/src/rules/pyflakes/rules/return_outside_function.rs index c67e4b6159..41cecdc571 100644 --- a/crates/ruff/src/rules/pyflakes/rules/return_outside_function.rs +++ b/crates/ruff/src/rules/pyflakes/rules/return_outside_function.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Stmt; +use rustpython_parser::ast::{Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pyflakes/rules/starred_expressions.rs b/crates/ruff/src/rules/pyflakes/rules/starred_expressions.rs index 90ea89588e..8a3fef38dd 100644 --- a/crates/ruff/src/rules/pyflakes/rules/starred_expressions.rs +++ b/crates/ruff/src/rules/pyflakes/rules/starred_expressions.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{Expr, ExprKind}; +use rustpython_parser::ast::Expr; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -34,7 +34,7 @@ pub(crate) fn starred_expressions( let mut has_starred: bool = false; let mut starred_index: Option = None; for (index, elt) in elts.iter().enumerate() { - if matches!(elt.node, ExprKind::Starred(_)) { + if matches!(elt, Expr::Starred(_)) { if has_starred && check_two_starred_expressions { return Some(Diagnostic::new(MultipleStarredExpressions, location)); } diff --git a/crates/ruff/src/rules/pyflakes/rules/strings.rs b/crates/ruff/src/rules/pyflakes/rules/strings.rs index b21bca31fb..f4b8e02b11 100644 --- a/crates/ruff/src/rules/pyflakes/rules/strings.rs +++ b/crates/ruff/src/rules/pyflakes/rules/strings.rs @@ -2,7 +2,7 @@ use ruff_text_size::TextRange; use std::string::ToString; use rustc_hash::FxHashSet; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Identifier, Keyword, KeywordData}; +use rustpython_parser::ast::{self, Constant, Expr, Identifier, Keyword}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -210,14 +210,13 @@ impl Violation for StringDotFormatMixingAutomatic { fn has_star_star_kwargs(keywords: &[Keyword]) -> bool { keywords.iter().any(|k| { - let KeywordData { arg, .. } = &k.node; + let Keyword { arg, .. } = &k; arg.is_none() }) } fn has_star_args(args: &[Expr]) -> bool { - args.iter() - .any(|arg| matches!(&arg.node, ExprKind::Starred(_))) + args.iter().any(|arg| matches!(&arg, Expr::Starred(_))) } /// F502 @@ -229,13 +228,13 @@ pub(crate) fn percent_format_expected_mapping( ) { if !summary.keywords.is_empty() { // Tuple, List, Set (+comprehensions) - match right.node { - ExprKind::List(_) - | ExprKind::Tuple(_) - | ExprKind::Set(_) - | ExprKind::ListComp(_) - | ExprKind::SetComp(_) - | ExprKind::GeneratorExp(_) => checker + match right { + Expr::List(_) + | Expr::Tuple(_) + | Expr::Set(_) + | Expr::ListComp(_) + | Expr::SetComp(_) + | Expr::GeneratorExp(_) => checker .diagnostics .push(Diagnostic::new(PercentFormatExpectedMapping, location)), _ => {} @@ -250,8 +249,7 @@ pub(crate) fn percent_format_expected_sequence( right: &Expr, location: TextRange, ) { - if summary.num_positional > 1 && matches!(right.node, ExprKind::Dict(_) | ExprKind::DictComp(_)) - { + if summary.num_positional > 1 && matches!(right, Expr::Dict(_) | Expr::DictComp(_)) { checker .diagnostics .push(Diagnostic::new(PercentFormatExpectedSequence, location)); @@ -268,7 +266,7 @@ pub(crate) fn percent_format_extra_named_arguments( if summary.num_positional > 0 { return; } - let ExprKind::Dict(ast::ExprDict { keys, .. }) = &right.node else { + let Expr::Dict(ast::ExprDict { keys, .. }) = &right else { return; }; if keys.iter().any(std::option::Option::is_none) { @@ -278,14 +276,10 @@ pub(crate) fn percent_format_extra_named_arguments( let missing: Vec<&str> = keys .iter() .filter_map(|k| match k { - Some(Expr { - node: - ExprKind::Constant(ast::ExprConstant { - value: Constant::Str(value), - .. - }), + Some(Expr::Constant(ast::ExprConstant { + value: Constant::Str(value), .. - }) => { + })) => { if summary.keywords.contains(value) { None } else { @@ -331,15 +325,15 @@ pub(crate) fn percent_format_missing_arguments( return; } - if let ExprKind::Dict(ast::ExprDict { keys, .. }) = &right.node { + if let Expr::Dict(ast::ExprDict { keys, .. }) = &right { if keys.iter().any(std::option::Option::is_none) { return; // contains **x splat } let mut keywords = FxHashSet::default(); for key in keys.iter().flatten() { - match &key.node { - ExprKind::Constant(ast::ExprConstant { + match key { + Expr::Constant(ast::ExprConstant { value: Constant::Str(value), .. }) => { @@ -393,13 +387,13 @@ pub(crate) fn percent_format_positional_count_mismatch( return; } - match &right.node { - ExprKind::List(ast::ExprList { elts, .. }) - | ExprKind::Tuple(ast::ExprTuple { elts, .. }) - | ExprKind::Set(ast::ExprSet { elts }) => { + match right { + Expr::List(ast::ExprList { elts, .. }) + | Expr::Tuple(ast::ExprTuple { elts, .. }) + | Expr::Set(ast::ExprSet { elts, .. }) => { let mut found = 0; for elt in elts { - if let ExprKind::Starred(_) = &elt.node { + if let Expr::Starred(_) = &elt { return; } found += 1; @@ -427,8 +421,8 @@ pub(crate) fn percent_format_star_requires_sequence( location: TextRange, ) { if summary.starred { - match &right.node { - ExprKind::Dict(_) | ExprKind::DictComp(_) => checker + match right { + Expr::Dict(_) | Expr::DictComp(_) => checker .diagnostics .push(Diagnostic::new(PercentFormatStarRequiresSequence, location)), _ => {} @@ -448,7 +442,7 @@ pub(crate) fn string_dot_format_extra_named_arguments( } let keywords = keywords.iter().filter_map(|k| { - let KeywordData { arg, .. } = &k.node; + let Keyword { arg, .. } = &k; arg.as_ref() }); @@ -497,7 +491,7 @@ pub(crate) fn string_dot_format_extra_positional_arguments( .iter() .enumerate() .filter(|(i, arg)| { - !(matches!(arg.node, ExprKind::Starred(_)) + !(matches!(arg, Expr::Starred(_)) || summary.autos.contains(i) || summary.indices.contains(i)) }) @@ -547,7 +541,7 @@ pub(crate) fn string_dot_format_missing_argument( let keywords: FxHashSet<_> = keywords .iter() .filter_map(|k| { - let KeywordData { arg, .. } = &k.node; + let Keyword { arg, .. } = &k; arg.as_ref().map(Identifier::as_str) }) .collect(); diff --git a/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs b/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs index e0f5b54074..29944b1186 100644 --- a/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs +++ b/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs @@ -1,7 +1,7 @@ use itertools::Itertools; use log::error; use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Attributed, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Ranged, Stmt}; use rustpython_parser::{lexer, Mode, Tok}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; @@ -65,9 +65,10 @@ impl Violation for UnusedVariable { /// Return the [`TextRange`] of the token after the next match of /// the predicate, skipping over any bracketed expressions. -fn match_token_after(located: &Attributed, locator: &Locator, f: F) -> TextRange +fn match_token_after(located: &T, locator: &Locator, f: F) -> TextRange where F: Fn(Tok) -> bool, + T: Ranged, { let contents = locator.after(located.start()); @@ -127,9 +128,10 @@ where /// Return the [`TextRange`] of the token matching the predicate, /// skipping over any bracketed expressions. -fn match_token(located: &Attributed, locator: &Locator, f: F) -> TextRange +fn match_token(located: &T, locator: &Locator, f: F) -> TextRange where F: Fn(Tok) -> bool, + T: Ranged, { let contents = locator.after(located.start()); @@ -198,9 +200,9 @@ fn remove_unused_variable( checker: &Checker, ) -> Option<(DeletionKind, Fix)> { // First case: simple assignment (`x = 1`) - if let StmtKind::Assign(ast::StmtAssign { targets, value, .. }) = &stmt.node { + if let Stmt::Assign(ast::StmtAssign { targets, value, .. }) = stmt { if let Some(target) = targets.iter().find(|target| range == target.range()) { - if matches!(target.node, ExprKind::Name(_)) { + if target.is_name_expr() { return if targets.len() > 1 || contains_effect(value, |id| checker.ctx.is_builtin(id)) { @@ -240,13 +242,13 @@ fn remove_unused_variable( } // Second case: simple annotated assignment (`x: int = 1`) - if let StmtKind::AnnAssign(ast::StmtAnnAssign { + if let Stmt::AnnAssign(ast::StmtAnnAssign { target, value: Some(value), .. - }) = &stmt.node + }) = stmt { - if matches!(target.node, ExprKind::Name(_)) { + if target.is_name_expr() { return if contains_effect(value, |id| checker.ctx.is_builtin(id)) { // If the expression is complex (`x = foo()`), remove the assignment, // but preserve the right-hand side. @@ -282,7 +284,7 @@ fn remove_unused_variable( } // Third case: withitem (`with foo() as x:`) - if let StmtKind::With(ast::StmtWith { items, .. }) = &stmt.node { + if let Stmt::With(ast::StmtWith { items, .. }) = stmt { // Find the binding that matches the given `Range`. // TODO(charlie): Store the `Withitem` in the `Binding`. for item in items { diff --git a/crates/ruff/src/rules/pyflakes/rules/yield_outside_function.rs b/crates/ruff/src/rules/pyflakes/rules/yield_outside_function.rs index cf615d5bc5..2fb4291551 100644 --- a/crates/ruff/src/rules/pyflakes/rules/yield_outside_function.rs +++ b/crates/ruff/src/rules/pyflakes/rules/yield_outside_function.rs @@ -1,6 +1,6 @@ use std::fmt; -use rustpython_parser::ast::{Expr, ExprKind}; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -43,11 +43,11 @@ pub(crate) fn yield_outside_function(checker: &mut Checker, expr: &Expr) { checker.ctx.scope().kind, ScopeKind::Class(_) | ScopeKind::Module ) { - let keyword = match expr.node { - ExprKind::Yield(_) => DeferralKeyword::Yield, - ExprKind::YieldFrom(_) => DeferralKeyword::YieldFrom, - ExprKind::Await(_) => DeferralKeyword::Await, - _ => panic!("Expected ExprKind::Yield | ExprKind::YieldFrom | ExprKind::Await"), + let keyword = match expr { + Expr::Yield(_) => DeferralKeyword::Yield, + Expr::YieldFrom(_) => DeferralKeyword::YieldFrom, + Expr::Await(_) => DeferralKeyword::Await, + _ => panic!("Expected Expr::Yield | Expr::YieldFrom | Expr::Await"), }; checker.diagnostics.push(Diagnostic::new( YieldOutsideFunction { keyword }, diff --git a/crates/ruff/src/rules/pygrep_hooks/rules/deprecated_log_warn.rs b/crates/ruff/src/rules/pygrep_hooks/rules/deprecated_log_warn.rs index b49582ebcf..4dfeed38aa 100644 --- a/crates/ruff/src/rules/pygrep_hooks/rules/deprecated_log_warn.rs +++ b/crates/ruff/src/rules/pygrep_hooks/rules/deprecated_log_warn.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pygrep_hooks/rules/invalid_mock_access.rs b/crates/ruff/src/rules/pygrep_hooks/rules/invalid_mock_access.rs index ff0e073cbb..d0b52d3ca8 100644 --- a/crates/ruff/src/rules/pygrep_hooks/rules/invalid_mock_access.rs +++ b/crates/ruff/src/rules/pygrep_hooks/rules/invalid_mock_access.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -49,7 +49,7 @@ impl Violation for InvalidMockAccess { /// PGH005 pub(crate) fn uncalled_mock_method(checker: &mut Checker, expr: &Expr) { - if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &expr.node { + if let Expr::Attribute(ast::ExprAttribute { attr, .. }) = expr { if matches!( attr.as_str(), "assert_any_call" @@ -72,10 +72,10 @@ pub(crate) fn uncalled_mock_method(checker: &mut Checker, expr: &Expr) { /// PGH005 pub(crate) fn non_existent_mock_method(checker: &mut Checker, test: &Expr) { - let attr = match &test.node { - ExprKind::Attribute(ast::ExprAttribute { attr, .. }) => attr, - ExprKind::Call(ast::ExprCall { func, .. }) => match &func.node { - ExprKind::Attribute(ast::ExprAttribute { attr, .. }) => attr, + let attr = match test { + Expr::Attribute(ast::ExprAttribute { attr, .. }) => attr, + Expr::Call(ast::ExprCall { func, .. }) => match func.as_ref() { + Expr::Attribute(ast::ExprAttribute { attr, .. }) => attr, _ => return, }, _ => return, diff --git a/crates/ruff/src/rules/pygrep_hooks/rules/no_eval.rs b/crates/ruff/src/rules/pygrep_hooks/rules/no_eval.rs index 6dcdf7e852..5eaccae08e 100644 --- a/crates/ruff/src/rules/pygrep_hooks/rules/no_eval.rs +++ b/crates/ruff/src/rules/pygrep_hooks/rules/no_eval.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -40,7 +40,7 @@ impl Violation for Eval { /// PGH001 pub(crate) fn no_eval(checker: &mut Checker, func: &Expr) { - let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else { + let Expr::Name(ast::ExprName { id, .. }) = func else { return; }; if id != "eval" { diff --git a/crates/ruff/src/rules/pylint/rules/assert_on_string_literal.rs b/crates/ruff/src/rules/pylint/rules/assert_on_string_literal.rs index 35351db205..a529d9f256 100644 --- a/crates/ruff/src/rules/pylint/rules/assert_on_string_literal.rs +++ b/crates/ruff/src/rules/pylint/rules/assert_on_string_literal.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -43,8 +43,8 @@ impl Violation for AssertOnStringLiteral { /// PLW0129 pub(crate) fn assert_on_string_literal(checker: &mut Checker, test: &Expr) { - match &test.node { - ExprKind::Constant(ast::ExprConstant { value, .. }) => match value { + match test { + Expr::Constant(ast::ExprConstant { value, .. }) => match value { Constant::Str(value, ..) => { checker.diagnostics.push(Diagnostic::new( AssertOnStringLiteral { @@ -71,11 +71,11 @@ pub(crate) fn assert_on_string_literal(checker: &mut Checker, test: &Expr) { } _ => {} }, - ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => { + Expr::JoinedStr(ast::ExprJoinedStr { values, range: _ }) => { checker.diagnostics.push(Diagnostic::new( AssertOnStringLiteral { - kind: if values.iter().all(|value| match &value.node { - ExprKind::Constant(ast::ExprConstant { value, .. }) => match value { + kind: if values.iter().all(|value| match value { + Expr::Constant(ast::ExprConstant { value, .. }) => match value { Constant::Str(value, ..) => value.is_empty(), Constant::Bytes(value) => value.is_empty(), _ => false, @@ -83,8 +83,8 @@ pub(crate) fn assert_on_string_literal(checker: &mut Checker, test: &Expr) { _ => false, }) { Kind::Empty - } else if values.iter().any(|value| match &value.node { - ExprKind::Constant(ast::ExprConstant { value, .. }) => match value { + } else if values.iter().any(|value| match value { + Expr::Constant(ast::ExprConstant { value, .. }) => match value { Constant::Str(value, ..) => !value.is_empty(), Constant::Bytes(value) => !value.is_empty(), _ => false, diff --git a/crates/ruff/src/rules/pylint/rules/await_outside_async.rs b/crates/ruff/src/rules/pylint/rules/await_outside_async.rs index 8da08ff9e5..6419e10a99 100644 --- a/crates/ruff/src/rules/pylint/rules/await_outside_async.rs +++ b/crates/ruff/src/rules/pylint/rules/await_outside_async.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pylint/rules/bad_str_strip_call.rs b/crates/ruff/src/rules/pylint/rules/bad_str_strip_call.rs index 84a2cb1999..4e961f434b 100644 --- a/crates/ruff/src/rules/pylint/rules/bad_str_strip_call.rs +++ b/crates/ruff/src/rules/pylint/rules/bad_str_strip_call.rs @@ -1,7 +1,7 @@ use std::fmt; use rustc_hash::FxHashSet; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -127,20 +127,20 @@ fn has_duplicates(s: &str) -> bool { /// PLE1310 pub(crate) fn bad_str_strip_call(checker: &mut Checker, func: &Expr, args: &[Expr]) { - if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &func.node { + if let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = func { if matches!( - value.node, - ExprKind::Constant(ast::ExprConstant { + value.as_ref(), + Expr::Constant(ast::ExprConstant { value: Constant::Str(_) | Constant::Bytes(_), .. }) ) { if let Some(strip) = StripKind::from_str(attr.as_str()) { if let Some(arg) = args.get(0) { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(value), .. - }) = &arg.node + }) = &arg { if has_duplicates(value) { let removal = if checker.settings.target_version >= PythonVersion::Py39 diff --git a/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs b/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs index 0bc49a1fbb..d141286f0f 100644 --- a/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs +++ b/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs @@ -3,7 +3,7 @@ use std::str::FromStr; use rustc_hash::FxHashMap; use rustpython_format::cformat::{CFormatPart, CFormatSpec, CFormatStrOrBytes, CFormatString}; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Operator}; +use rustpython_parser::ast::{self, Constant, Expr, Operator, Ranged}; use rustpython_parser::{lexer, Mode, Tok}; use ruff_diagnostics::{Diagnostic, Violation}; @@ -49,21 +49,21 @@ enum DataType { impl From<&Expr> for DataType { fn from(expr: &Expr) -> Self { - match &expr.node { - ExprKind::NamedExpr(ast::ExprNamedExpr { value, .. }) => (&**value).into(), - ExprKind::UnaryOp(ast::ExprUnaryOp { operand, .. }) => (&**operand).into(), - ExprKind::Dict(_) => DataType::Object, - ExprKind::Set(_) => DataType::Object, - ExprKind::ListComp(_) => DataType::Object, - ExprKind::SetComp(_) => DataType::Object, - ExprKind::DictComp(_) => DataType::Object, - ExprKind::GeneratorExp(_) => DataType::Object, - ExprKind::JoinedStr(_) => DataType::String, - ExprKind::BinOp(ast::ExprBinOp { left, op, .. }) => { + match expr { + Expr::NamedExpr(ast::ExprNamedExpr { value, .. }) => (&**value).into(), + Expr::UnaryOp(ast::ExprUnaryOp { operand, .. }) => (&**operand).into(), + Expr::Dict(_) => DataType::Object, + Expr::Set(_) => DataType::Object, + Expr::ListComp(_) => DataType::Object, + Expr::SetComp(_) => DataType::Object, + Expr::DictComp(_) => DataType::Object, + Expr::GeneratorExp(_) => DataType::Object, + Expr::JoinedStr(_) => DataType::String, + Expr::BinOp(ast::ExprBinOp { left, op, .. }) => { // Ex) "a" % "b" if matches!( - left.node, - ExprKind::Constant(ast::ExprConstant { + left.as_ref(), + Expr::Constant(ast::ExprConstant { value: Constant::Str(..), .. }) @@ -73,14 +73,14 @@ impl From<&Expr> for DataType { } DataType::Unknown } - ExprKind::Constant(ast::ExprConstant { value, .. }) => match value { + Expr::Constant(ast::ExprConstant { value, .. }) => match value { Constant::Str(_) => DataType::String, Constant::Int(_) => DataType::Integer, Constant::Float(_) => DataType::Float, _ => DataType::Unknown, }, - ExprKind::List(_) => DataType::Object, - ExprKind::Tuple(_) => DataType::Object, + Expr::List(_) => DataType::Object, + Expr::Tuple(_) => DataType::Object, _ => DataType::Unknown, } } @@ -221,10 +221,10 @@ fn is_valid_dict( let Some(key) = key else { return true; }; - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(mapping_key), .. - }) = &key.node + }) = key { let Some(format) = formats_hash.get(mapping_key.as_str()) else { return true; @@ -275,12 +275,14 @@ pub(crate) fn bad_string_format_type(checker: &mut Checker, expr: &Expr, right: } // Parse the parameters. - let is_valid = match &right.node { - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => is_valid_tuple(&format_strings, elts), - ExprKind::Dict(ast::ExprDict { keys, values }) => { - is_valid_dict(&format_strings, keys, values) - } - ExprKind::Constant(_) => is_valid_constant(&format_strings, right), + let is_valid = match right { + Expr::Tuple(ast::ExprTuple { elts, .. }) => is_valid_tuple(&format_strings, elts), + Expr::Dict(ast::ExprDict { + keys, + values, + range: _, + }) => is_valid_dict(&format_strings, keys, values), + Expr::Constant(_) => is_valid_constant(&format_strings, right), _ => true, }; if !is_valid { diff --git a/crates/ruff/src/rules/pylint/rules/binary_op_exception.rs b/crates/ruff/src/rules/pylint/rules/binary_op_exception.rs index e25f277111..70b5e2e264 100644 --- a/crates/ruff/src/rules/pylint/rules/binary_op_exception.rs +++ b/crates/ruff/src/rules/pylint/rules/binary_op_exception.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, ExprKind}; +use rustpython_parser::ast::{self, Excepthandler, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -63,14 +63,13 @@ impl Violation for BinaryOpException { /// PLW0711 pub(crate) fn binary_op_exception(checker: &mut Checker, excepthandler: &Excepthandler) { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = - &excepthandler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = excepthandler; let Some(type_) = type_ else { return; }; - let ExprKind::BoolOp(ast::ExprBoolOp { op, .. }) = &type_.node else { + let Expr::BoolOp(ast::ExprBoolOp { op, .. }) = type_.as_ref() else { return; }; diff --git a/crates/ruff/src/rules/pylint/rules/collapsible_else_if.rs b/crates/ruff/src/rules/pylint/rules/collapsible_else_if.rs index 82eafe5af8..b99de7e37a 100644 --- a/crates/ruff/src/rules/pylint/rules/collapsible_else_if.rs +++ b/crates/ruff/src/rules/pylint/rules/collapsible_else_if.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Stmt, StmtKind}; +use rustpython_parser::ast::{Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -18,7 +18,7 @@ impl Violation for CollapsibleElseIf { pub(crate) fn collapsible_else_if(orelse: &[Stmt], locator: &Locator) -> Option { if orelse.len() == 1 { let first = &orelse[0]; - if matches!(first.node, StmtKind::If(_)) { + if matches!(first, Stmt::If(_)) { // Determine whether this is an `elif`, or an `if` in an `else` block. if locator.slice(first.range()).starts_with("if") { return Some(Diagnostic::new(CollapsibleElseIf, first.range())); diff --git a/crates/ruff/src/rules/pylint/rules/compare_to_empty_string.rs b/crates/ruff/src/rules/pylint/rules/compare_to_empty_string.rs index 8fbcabaa90..7b9cc253b0 100644 --- a/crates/ruff/src/rules/pylint/rules/compare_to_empty_string.rs +++ b/crates/ruff/src/rules/pylint/rules/compare_to_empty_string.rs @@ -1,6 +1,6 @@ use anyhow::bail; use itertools::Itertools; -use rustpython_parser::ast::{self, Cmpop, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Cmpop, Constant, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -100,7 +100,7 @@ pub(crate) fn compare_to_empty_string( // Omit string comparison rules within subscripts. This is mostly commonly used within // DataFrame and np.ndarray indexing. for parent in checker.ctx.expr_ancestors() { - if matches!(parent.node, ExprKind::Subscript(_)) { + if matches!(parent, Expr::Subscript(_)) { return; } } @@ -114,7 +114,7 @@ pub(crate) fn compare_to_empty_string( if let Ok(op) = EmptyStringCmpop::try_from(op) { if std::mem::take(&mut first) { // Check the left-most expression. - if let ExprKind::Constant(ast::ExprConstant { value, .. }) = &lhs.node { + if let Expr::Constant(ast::ExprConstant { value, .. }) = &lhs { if let Constant::Str(s) = value { if s.is_empty() { let constant = unparse_constant(value, checker.stylist); @@ -134,7 +134,7 @@ pub(crate) fn compare_to_empty_string( } // Check all right-hand expressions. - if let ExprKind::Constant(ast::ExprConstant { value, .. }) = &rhs.node { + if let Expr::Constant(ast::ExprConstant { value, .. }) = &rhs { if let Constant::Str(s) = value { if s.is_empty() { let expr = unparse_expr(lhs, checker.stylist); diff --git a/crates/ruff/src/rules/pylint/rules/comparison_of_constant.rs b/crates/ruff/src/rules/pylint/rules/comparison_of_constant.rs index 2bb1f6fa7f..afe30820d9 100644 --- a/crates/ruff/src/rules/pylint/rules/comparison_of_constant.rs +++ b/crates/ruff/src/rules/pylint/rules/comparison_of_constant.rs @@ -1,7 +1,7 @@ use std::fmt; use itertools::Itertools; -use rustpython_parser::ast::{self, Attributed, Cmpop, Expr, ExprKind}; +use rustpython_parser::ast::{self, Cmpop, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -90,19 +90,19 @@ pub(crate) fn comparison_of_constant( ) { for ((left, right), op) in std::iter::once(left) .chain(comparators.iter()) - .tuple_windows::<(&Attributed<_>, &Attributed<_>)>() + .tuple_windows() .zip(ops) { if let ( - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: left_constant, .. }), - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: right_constant, .. }), - ) = (&left.node, &right.node) + ) = (&left, &right) { let diagnostic = Diagnostic::new( ComparisonOfConstant { diff --git a/crates/ruff/src/rules/pylint/rules/continue_in_finally.rs b/crates/ruff/src/rules/pylint/rules/continue_in_finally.rs index 675ec8bf7a..09e6c21793 100644 --- a/crates/ruff/src/rules/pylint/rules/continue_in_finally.rs +++ b/crates/ruff/src/rules/pylint/rules/continue_in_finally.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -44,27 +44,27 @@ impl Violation for ContinueInFinally { fn traverse_body(checker: &mut Checker, body: &[Stmt]) { for stmt in body { - if matches!(stmt.node, StmtKind::Continue) { + if stmt.is_continue_stmt() { checker .diagnostics .push(Diagnostic::new(ContinueInFinally, stmt.range())); } - match &stmt.node { - StmtKind::If(ast::StmtIf { body, orelse, .. }) - | StmtKind::Try(ast::StmtTry { body, orelse, .. }) - | StmtKind::TryStar(ast::StmtTryStar { body, orelse, .. }) => { + match stmt { + Stmt::If(ast::StmtIf { body, orelse, .. }) + | Stmt::Try(ast::StmtTry { body, orelse, .. }) + | Stmt::TryStar(ast::StmtTryStar { body, orelse, .. }) => { traverse_body(checker, body); traverse_body(checker, orelse); } - StmtKind::For(ast::StmtFor { orelse, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { orelse, .. }) - | StmtKind::While(ast::StmtWhile { orelse, .. }) => traverse_body(checker, orelse), - StmtKind::With(ast::StmtWith { body, .. }) - | StmtKind::AsyncWith(ast::StmtAsyncWith { body, .. }) => { + Stmt::For(ast::StmtFor { orelse, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { orelse, .. }) + | Stmt::While(ast::StmtWhile { orelse, .. }) => traverse_body(checker, orelse), + Stmt::With(ast::StmtWith { body, .. }) + | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { traverse_body(checker, body); } - StmtKind::Match(ast::StmtMatch { cases, .. }) => { + Stmt::Match(ast::StmtMatch { cases, .. }) => { for case in cases { traverse_body(checker, &case.body); } diff --git a/crates/ruff/src/rules/pylint/rules/duplicate_bases.rs b/crates/ruff/src/rules/pylint/rules/duplicate_bases.rs index 5cdd54800d..c49517b749 100644 --- a/crates/ruff/src/rules/pylint/rules/duplicate_bases.rs +++ b/crates/ruff/src/rules/pylint/rules/duplicate_bases.rs @@ -1,7 +1,7 @@ use std::hash::BuildHasherDefault; use rustc_hash::FxHashSet; -use rustpython_parser::ast::{self, Expr, ExprKind, Identifier}; +use rustpython_parser::ast::{self, Expr, Identifier, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -27,7 +27,7 @@ pub(crate) fn duplicate_bases(checker: &mut Checker, name: &str, bases: &[Expr]) let mut seen: FxHashSet<&Identifier> = FxHashSet::with_capacity_and_hasher(bases.len(), BuildHasherDefault::default()); for base in bases { - if let ExprKind::Name(ast::ExprName { id, .. }) = &base.node { + if let Expr::Name(ast::ExprName { id, .. }) = base { if !seen.insert(id) { checker.diagnostics.push(Diagnostic::new( DuplicateBases { diff --git a/crates/ruff/src/rules/pylint/rules/global_statement.rs b/crates/ruff/src/rules/pylint/rules/global_statement.rs index 1a8114eaaa..9ec1147331 100644 --- a/crates/ruff/src/rules/pylint/rules/global_statement.rs +++ b/crates/ruff/src/rules/pylint/rules/global_statement.rs @@ -1,5 +1,6 @@ use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use rustpython_parser::ast::Ranged; use crate::checkers::ast::Checker; diff --git a/crates/ruff/src/rules/pylint/rules/import_self.rs b/crates/ruff/src/rules/pylint/rules/import_self.rs index 18a39fdfea..ccf4a2be4c 100644 --- a/crates/ruff/src/rules/pylint/rules/import_self.rs +++ b/crates/ruff/src/rules/pylint/rules/import_self.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Alias; +use rustpython_parser::ast::{Alias, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -23,10 +23,10 @@ pub(crate) fn import_self(alias: &Alias, module_path: Option<&[String]>) -> Opti return None; }; - if alias.node.name.split('.').eq(module_path) { + if alias.name.split('.').eq(module_path) { return Some(Diagnostic::new( ImportSelf { - name: alias.node.name.to_string(), + name: alias.name.to_string(), }, alias.range(), )); @@ -55,11 +55,11 @@ pub(crate) fn import_from_self( { if let Some(alias) = names .iter() - .find(|alias| alias.node.name == module_path[module_path.len() - 1]) + .find(|alias| alias.name == module_path[module_path.len() - 1]) { return Some(Diagnostic::new( ImportSelf { - name: format!("{}.{}", imported_module_path, alias.node.name), + name: format!("{}.{}", imported_module_path, alias.name), }, alias.range(), )); diff --git a/crates/ruff/src/rules/pylint/rules/invalid_all_format.rs b/crates/ruff/src/rules/pylint/rules/invalid_all_format.rs index 79dd758ad2..0a818814ee 100644 --- a/crates/ruff/src/rules/pylint/rules/invalid_all_format.rs +++ b/crates/ruff/src/rules/pylint/rules/invalid_all_format.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pylint/rules/invalid_all_object.rs b/crates/ruff/src/rules/pylint/rules/invalid_all_object.rs index a1f7a3c236..46e05c80e7 100644 --- a/crates/ruff/src/rules/pylint/rules/invalid_all_object.rs +++ b/crates/ruff/src/rules/pylint/rules/invalid_all_object.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pylint/rules/invalid_envvar_default.rs b/crates/ruff/src/rules/pylint/rules/invalid_envvar_default.rs index 975326f5a9..d09d1b35f7 100644 --- a/crates/ruff/src/rules/pylint/rules/invalid_envvar_default.rs +++ b/crates/ruff/src/rules/pylint/rules/invalid_envvar_default.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword, Operator}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Operator, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -39,39 +39,40 @@ impl Violation for InvalidEnvvarDefault { fn is_valid_default(expr: &Expr) -> bool { // We can't infer the types of these defaults, so assume they're valid. if matches!( - expr.node, - ExprKind::Name(_) | ExprKind::Attribute(_) | ExprKind::Subscript(_) | ExprKind::Call(_) + expr, + Expr::Name(_) | Expr::Attribute(_) | Expr::Subscript(_) | Expr::Call(_) ) { return true; } // Allow string concatenation. - if let ExprKind::BinOp(ast::ExprBinOp { + if let Expr::BinOp(ast::ExprBinOp { left, right, op: Operator::Add, - }) = &expr.node + range: _, + }) = expr { return is_valid_default(left) && is_valid_default(right); } // Allow string formatting. - if let ExprKind::BinOp(ast::ExprBinOp { + if let Expr::BinOp(ast::ExprBinOp { left, op: Operator::Mod, .. - }) = &expr.node + }) = expr { return is_valid_default(left); } // Otherwise, the default must be a string or `None`. matches!( - expr.node, - ExprKind::Constant(ast::ExprConstant { + expr, + Expr::Constant(ast::ExprConstant { value: Constant::Str { .. } | Constant::None { .. }, .. - }) | ExprKind::JoinedStr(_) + }) | Expr::JoinedStr(_) ) } @@ -91,8 +92,8 @@ pub(crate) fn invalid_envvar_default( let Some(expr) = args.get(1).or_else(|| { keywords .iter() - .find(|keyword| keyword.node.arg.as_ref().map_or(false, |arg| arg .as_str()== "default")) - .map(|keyword| &keyword.node.value) + .find(|keyword| keyword.arg.as_ref().map_or(false, |arg| arg .as_str()== "default")) + .map(|keyword| &keyword.value) }) else { return; }; diff --git a/crates/ruff/src/rules/pylint/rules/invalid_envvar_value.rs b/crates/ruff/src/rules/pylint/rules/invalid_envvar_value.rs index a701dadadc..a5f853e3bb 100644 --- a/crates/ruff/src/rules/pylint/rules/invalid_envvar_value.rs +++ b/crates/ruff/src/rules/pylint/rules/invalid_envvar_value.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword, Operator}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Operator, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -36,39 +36,40 @@ impl Violation for InvalidEnvvarValue { fn is_valid_key(expr: &Expr) -> bool { // We can't infer the types of these defaults, so assume they're valid. if matches!( - expr.node, - ExprKind::Name(_) | ExprKind::Attribute(_) | ExprKind::Subscript(_) | ExprKind::Call(_) + expr, + Expr::Name(_) | Expr::Attribute(_) | Expr::Subscript(_) | Expr::Call(_) ) { return true; } // Allow string concatenation. - if let ExprKind::BinOp(ast::ExprBinOp { + if let Expr::BinOp(ast::ExprBinOp { left, right, op: Operator::Add, - }) = &expr.node + range: _, + }) = expr { return is_valid_key(left) && is_valid_key(right); } // Allow string formatting. - if let ExprKind::BinOp(ast::ExprBinOp { + if let Expr::BinOp(ast::ExprBinOp { left, op: Operator::Mod, .. - }) = &expr.node + }) = expr { return is_valid_key(left); } // Otherwise, the default must be a string. matches!( - expr.node, - ExprKind::Constant(ast::ExprConstant { + expr, + Expr::Constant(ast::ExprConstant { value: Constant::Str { .. }, .. - }) | ExprKind::JoinedStr(_) + }) | Expr::JoinedStr(_) ) } @@ -88,8 +89,8 @@ pub(crate) fn invalid_envvar_value( let Some(expr) = args.get(0).or_else(|| { keywords .iter() - .find(|keyword| keyword.node.arg.as_ref().map_or(false, |arg| arg == "key")) - .map(|keyword| &keyword.node.value) + .find(|keyword| keyword.arg.as_ref().map_or(false, |arg| arg == "key")) + .map(|keyword| &keyword.value) }) else { return; }; diff --git a/crates/ruff/src/rules/pylint/rules/load_before_global_declaration.rs b/crates/ruff/src/rules/pylint/rules/load_before_global_declaration.rs index 31fd6701a3..025d6384f6 100644 --- a/crates/ruff/src/rules/pylint/rules/load_before_global_declaration.rs +++ b/crates/ruff/src/rules/pylint/rules/load_before_global_declaration.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pylint/rules/logging.rs b/crates/ruff/src/rules/pylint/rules/logging.rs index f101d47e82..65fcf9e64a 100644 --- a/crates/ruff/src/rules/pylint/rules/logging.rs +++ b/crates/ruff/src/rules/pylint/rules/logging.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -93,15 +93,12 @@ pub(crate) fn logging_call( keywords: &[Keyword], ) { // If there are any starred arguments, abort. - if args - .iter() - .any(|arg| matches!(arg.node, ExprKind::Starred(_))) - { + if args.iter().any(|arg| matches!(arg, Expr::Starred(_))) { return; } // If there are any starred keyword arguments, abort. - if keywords.iter().any(|keyword| keyword.node.arg.is_none()) { + if keywords.iter().any(|keyword| keyword.arg.is_none()) { return; } @@ -109,42 +106,40 @@ pub(crate) fn logging_call( return; } - if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node { + if let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func { if LoggingLevel::from_attribute(attr.as_str()).is_some() { let call_args = SimpleCallArgs::new(args, keywords); - if let Some(msg) = call_args.argument("msg", 0) { - if let ExprKind::Constant(ast::ExprConstant { - value: Constant::Str(value), - .. - }) = &msg.node - { - if let Ok(summary) = CFormatSummary::try_from(value.as_str()) { - if summary.starred { - return; - } - if !summary.keywords.is_empty() { - return; - } + if let Some(Expr::Constant(ast::ExprConstant { + value: Constant::Str(value), + .. + })) = call_args.argument("msg", 0) + { + if let Ok(summary) = CFormatSummary::try_from(value.as_str()) { + if summary.starred { + return; + } + if !summary.keywords.is_empty() { + return; + } - let message_args = call_args.args.len() - 1; + let message_args = call_args.args.len() - 1; - if checker.settings.rules.enabled(Rule::LoggingTooManyArgs) { - if summary.num_positional < message_args { - checker - .diagnostics - .push(Diagnostic::new(LoggingTooManyArgs, func.range())); - } + if checker.settings.rules.enabled(Rule::LoggingTooManyArgs) { + if summary.num_positional < message_args { + checker + .diagnostics + .push(Diagnostic::new(LoggingTooManyArgs, func.range())); } + } - if checker.settings.rules.enabled(Rule::LoggingTooFewArgs) { - if message_args > 0 - && call_args.kwargs.is_empty() - && summary.num_positional > message_args - { - checker - .diagnostics - .push(Diagnostic::new(LoggingTooFewArgs, func.range())); - } + if checker.settings.rules.enabled(Rule::LoggingTooFewArgs) { + if message_args > 0 + && call_args.kwargs.is_empty() + && summary.num_positional > message_args + { + checker + .diagnostics + .push(Diagnostic::new(LoggingTooFewArgs, func.range())); } } } diff --git a/crates/ruff/src/rules/pylint/rules/magic_value_comparison.rs b/crates/ruff/src/rules/pylint/rules/magic_value_comparison.rs index 65dad6c06d..b1810498b8 100644 --- a/crates/ruff/src/rules/pylint/rules/magic_value_comparison.rs +++ b/crates/ruff/src/rules/pylint/rules/magic_value_comparison.rs @@ -1,5 +1,5 @@ use itertools::Itertools; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Unaryop}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged, Unaryop}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -25,13 +25,14 @@ impl Violation for MagicValueComparison { /// If an [`Expr`] is a constant (or unary operation on a constant), return the [`Constant`]. fn as_constant(expr: &Expr) -> Option<&Constant> { - match &expr.node { - ExprKind::Constant(ast::ExprConstant { value, .. }) => Some(value), - ExprKind::UnaryOp(ast::ExprUnaryOp { + match expr { + Expr::Constant(ast::ExprConstant { value, .. }) => Some(value), + Expr::UnaryOp(ast::ExprUnaryOp { op: Unaryop::UAdd | Unaryop::USub | Unaryop::Invert, operand, - }) => match &operand.node { - ExprKind::Constant(ast::ExprConstant { value, .. }) => Some(value), + range: _, + }) => match operand.as_ref() { + Expr::Constant(ast::ExprConstant { value, .. }) => Some(value), _ => None, }, _ => None, diff --git a/crates/ruff/src/rules/pylint/rules/manual_import_from.rs b/crates/ruff/src/rules/pylint/rules/manual_import_from.rs index 76fe5d7643..5ff3697228 100644 --- a/crates/ruff/src/rules/pylint/rules/manual_import_from.rs +++ b/crates/ruff/src/rules/pylint/rules/manual_import_from.rs @@ -1,8 +1,9 @@ -use rustpython_parser::ast::{self, Alias, AliasData, Attributed, Int, Stmt}; +use ruff_text_size::TextRange; +use rustpython_parser::ast::{self, Alias, Int, Ranged, Stmt}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{create_stmt, unparse_stmt}; +use ruff_python_ast::helpers::unparse_stmt; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -35,10 +36,10 @@ pub(crate) fn manual_from_import( alias: &Alias, names: &[Alias], ) { - let Some(asname) = &alias.node.asname else { + let Some(asname) = &alias.asname else { return; }; - let Some((module, name)) = alias.node.name.rsplit_once('.') else { + let Some((module, name)) = alias.name.rsplit_once('.') else { return; }; if asname != name { @@ -54,22 +55,19 @@ pub(crate) fn manual_from_import( alias.range(), ); if fixable && checker.patch(diagnostic.kind.rule()) { + let node = ast::StmtImportFrom { + module: Some(module.into()), + names: vec![Alias { + name: asname.clone(), + asname: None, + range: TextRange::default(), + }], + level: Some(Int::new(0)), + range: TextRange::default(), + }; #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - unparse_stmt( - &create_stmt(ast::StmtImportFrom { - module: Some(module.into()), - names: vec![Attributed::new( - stmt.range(), - AliasData { - name: asname.clone(), - asname: None, - }, - )], - level: Some(Int::new(0)), - }), - checker.stylist, - ), + unparse_stmt(&node.into(), checker.stylist), stmt.range(), ))); } diff --git a/crates/ruff/src/rules/pylint/rules/nested_min_max.rs b/crates/ruff/src/rules/pylint/rules/nested_min_max.rs index a2630234cb..68dd74b4e2 100644 --- a/crates/ruff/src/rules/pylint/rules/nested_min_max.rs +++ b/crates/ruff/src/rules/pylint/rules/nested_min_max.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Expr, Keyword, Ranged}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -39,12 +39,12 @@ impl MinMax { if !keywords.is_empty() { return None; } - let ExprKind::Name(ast::ExprName { id, .. }) = func.node() else { + let Expr::Name(ast::ExprName { id, .. }) = func else { return None; }; - if id == "min" && context.is_builtin("min") { + if id.as_str() == "min" && context.is_builtin("min") { Some(MinMax::Min) - } else if id == "max" && context.is_builtin("max") { + } else if id.as_str() == "max" && context.is_builtin("max") { Some(MinMax::Max) } else { None @@ -66,20 +66,19 @@ impl std::fmt::Display for MinMax { fn collect_nested_args(context: &Context, min_max: MinMax, args: &[Expr]) -> Vec { fn inner(context: &Context, min_max: MinMax, args: &[Expr], new_args: &mut Vec) { for arg in args { - if let ExprKind::Call(ast::ExprCall { + if let Expr::Call(ast::ExprCall { func, args, keywords, - }) = arg.node() + range: _, + }) = arg { if args.len() == 1 { - let new_arg = Expr::new( - TextRange::default(), - ast::ExprStarred { - value: Box::new(args[0].clone()), - ctx: ast::ExprContext::Load, - }, - ); + let new_arg = Expr::Starred(ast::ExprStarred { + value: Box::new(args[0].clone()), + ctx: ast::ExprContext::Load, + range: TextRange::default(), + }); new_args.push(new_arg); continue; } @@ -110,22 +109,20 @@ pub(crate) fn nested_min_max( }; if args.iter().any(|arg| { - let ExprKind::Call(ast::ExprCall { func, keywords, ..} )= arg.node() else { + let Expr::Call(ast::ExprCall { func, keywords, ..} )= arg else { return false; }; - MinMax::try_from_call(func, keywords, &checker.ctx) == Some(min_max) + MinMax::try_from_call(func.as_ref(), keywords.as_ref(), &checker.ctx) == Some(min_max) }) { let fixable = !has_comments(expr, checker.locator); let mut diagnostic = Diagnostic::new(NestedMinMax { func: min_max }, expr.range()); if fixable && checker.patch(diagnostic.kind.rule()) { - let flattened_expr = Expr::new( - TextRange::default(), - ast::ExprCall { - func: Box::new(func.clone()), - args: collect_nested_args(&checker.ctx, min_max, args), - keywords: keywords.to_owned(), - }, - ); + let flattened_expr = Expr::Call(ast::ExprCall { + func: Box::new(func.clone()), + args: collect_nested_args(&checker.ctx, min_max, args), + keywords: keywords.to_owned(), + range: TextRange::default(), + }); #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( unparse_expr(&flattened_expr, checker.stylist), diff --git a/crates/ruff/src/rules/pylint/rules/property_with_parameters.rs b/crates/ruff/src/rules/pylint/rules/property_with_parameters.rs index 22431feebe..7d28d1cfb7 100644 --- a/crates/ruff/src/rules/pylint/rules/property_with_parameters.rs +++ b/crates/ruff/src/rules/pylint/rules/property_with_parameters.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Arguments, Expr, ExprKind, Stmt}; +use rustpython_parser::ast::{self, Arguments, Expr, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -25,7 +25,7 @@ pub(crate) fn property_with_parameters( ) { if !decorator_list .iter() - .any(|d| matches!(&d.node, ExprKind::Name(ast::ExprName { id, .. }) if id == "property")) + .any(|d| matches!(&d, Expr::Name(ast::ExprName { id, .. }) if id == "property")) { return; } diff --git a/crates/ruff/src/rules/pylint/rules/redefined_loop_name.rs b/crates/ruff/src/rules/pylint/rules/redefined_loop_name.rs index 333e186536..28a0473799 100644 --- a/crates/ruff/src/rules/pylint/rules/redefined_loop_name.rs +++ b/crates/ruff/src/rules/pylint/rules/redefined_loop_name.rs @@ -1,7 +1,7 @@ use std::{fmt, iter}; use regex::Regex; -use rustpython_parser::ast::{self, Expr, ExprContext, ExprKind, Stmt, StmtKind, Withitem}; +use rustpython_parser::ast::{self, Expr, ExprContext, Ranged, Stmt, Withitem}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -151,10 +151,10 @@ where { fn visit_stmt(&mut self, stmt: &'b Stmt) { // Collect target expressions. - match &stmt.node { + match stmt { // For and async for. - StmtKind::For(ast::StmtFor { target, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { target, .. }) => { + Stmt::For(ast::StmtFor { target, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { target, .. }) => { self.assignment_targets.extend( assignment_targets_from_expr(target, self.dummy_variable_rgx).map(|expr| { ExprWithInnerBindingKind { @@ -165,7 +165,7 @@ where ); } // With. - StmtKind::With(ast::StmtWith { items, .. }) => { + Stmt::With(ast::StmtWith { items, .. }) => { self.assignment_targets.extend( assignment_targets_from_with_items(items, self.dummy_variable_rgx).map( |expr| ExprWithInnerBindingKind { @@ -176,7 +176,7 @@ where ); } // Assignment, augmented assignment, and annotated assignment. - StmtKind::Assign(ast::StmtAssign { targets, value, .. }) => { + Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { // Check for single-target assignments which are of the // form `x = cast(..., x)`. if targets.first().map_or(false, |target| { @@ -193,7 +193,7 @@ where ), ); } - StmtKind::AugAssign(ast::StmtAugAssign { target, .. }) => { + Stmt::AugAssign(ast::StmtAugAssign { target, .. }) => { self.assignment_targets.extend( assignment_targets_from_expr(target, self.dummy_variable_rgx).map(|expr| { ExprWithInnerBindingKind { @@ -203,7 +203,7 @@ where }), ); } - StmtKind::AnnAssign(ast::StmtAnnAssign { target, value, .. }) => { + Stmt::AnnAssign(ast::StmtAnnAssign { target, value, .. }) => { if value.is_none() { return; } @@ -219,10 +219,10 @@ where _ => {} } // Decide whether to recurse. - match &stmt.node { + match stmt { // Don't recurse into blocks that create a new scope. - StmtKind::ClassDef(_) => {} - StmtKind::FunctionDef(_) => {} + Stmt::ClassDef(_) => {} + Stmt::FunctionDef(_) => {} // Otherwise, do recurse. _ => { walk_stmt(self, stmt); @@ -241,16 +241,16 @@ where /// x = cast(int, x) /// ``` fn assignment_is_cast_expr(context: &Context, value: &Expr, target: &Expr) -> bool { - let ExprKind::Call(ast::ExprCall { func, args, .. }) = &value.node else { + let Expr::Call(ast::ExprCall { func, args, .. }) = value else { return false; }; - let ExprKind::Name(ast::ExprName { id: target_id, .. }) = &target.node else { + let Expr::Name(ast::ExprName { id: target_id, .. }) = target else { return false; }; if args.len() != 2 { return false; } - let ExprKind::Name(ast::ExprName { id: arg_id, .. }) = &args[1].node else { + let Expr::Name(ast::ExprName { id: arg_id, .. }) = &args[1] else { return false; }; if arg_id != target_id { @@ -266,22 +266,24 @@ fn assignment_targets_from_expr<'a, U>( // The Box is necessary to ensure the match arms have the same return type - we can't use // a cast to "impl Iterator", since at the time of writing that is only allowed for // return types and argument types. - match &expr.node { - ExprKind::Attribute(ast::ExprAttribute { + match expr { + Expr::Attribute(ast::ExprAttribute { ctx: ExprContext::Store, .. }) => Box::new(iter::once(expr)), - ExprKind::Subscript(ast::ExprSubscript { + Expr::Subscript(ast::ExprSubscript { ctx: ExprContext::Store, .. }) => Box::new(iter::once(expr)), - ExprKind::Starred(ast::ExprStarred { + Expr::Starred(ast::ExprStarred { ctx: ExprContext::Store, value, + range: _, }) => Box::new(iter::once(&**value)), - ExprKind::Name(ast::ExprName { + Expr::Name(ast::ExprName { ctx: ExprContext::Store, id, + range: _, }) => { // Ignore dummy variables. if dummy_variable_rgx.is_match(id) { @@ -290,16 +292,18 @@ fn assignment_targets_from_expr<'a, U>( Box::new(iter::once(expr)) } } - ExprKind::List(ast::ExprList { + Expr::List(ast::ExprList { ctx: ExprContext::Store, elts, + range: _, }) => Box::new( elts.iter() .flat_map(|elt| assignment_targets_from_expr(elt, dummy_variable_rgx)), ), - ExprKind::Tuple(ast::ExprTuple { + Expr::Tuple(ast::ExprTuple { ctx: ExprContext::Store, elts, + range: _, }) => Box::new( elts.iter() .flat_map(|elt| assignment_targets_from_expr(elt, dummy_variable_rgx)), @@ -334,9 +338,9 @@ fn assignment_targets_from_assign_targets<'a, U>( /// PLW2901 pub(crate) fn redefined_loop_name<'a, 'b>(checker: &'a mut Checker<'b>, node: &Node<'b>) { let (outer_assignment_targets, inner_assignment_targets) = match node { - Node::Stmt(stmt) => match &stmt.node { + Node::Stmt(stmt) => match stmt { // With. - StmtKind::With(ast::StmtWith { items, body, .. }) => { + Stmt::With(ast::StmtWith { items, body, .. }) => { let outer_assignment_targets: Vec> = assignment_targets_from_with_items(items, &checker.settings.dummy_variable_rgx) .map(|expr| ExprWithOuterBindingKind { @@ -355,8 +359,8 @@ pub(crate) fn redefined_loop_name<'a, 'b>(checker: &'a mut Checker<'b>, node: &N (outer_assignment_targets, visitor.assignment_targets) } // For and async for. - StmtKind::For(ast::StmtFor { target, body, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { target, body, .. }) => { + Stmt::For(ast::StmtFor { target, body, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { target, body, .. }) => { let outer_assignment_targets: Vec> = assignment_targets_from_expr(target, &checker.settings.dummy_variable_rgx) .map(|expr| ExprWithOuterBindingKind { diff --git a/crates/ruff/src/rules/pylint/rules/repeated_isinstance_calls.rs b/crates/ruff/src/rules/pylint/rules/repeated_isinstance_calls.rs index 3799d4255c..80be763726 100644 --- a/crates/ruff/src/rules/pylint/rules/repeated_isinstance_calls.rs +++ b/crates/ruff/src/rules/pylint/rules/repeated_isinstance_calls.rs @@ -1,6 +1,6 @@ use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; -use rustpython_parser::ast::{self, Boolop, Expr, ExprKind}; +use rustpython_parser::ast::{self, Boolop, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -28,7 +28,7 @@ impl Violation for RepeatedIsinstanceCalls { pub(crate) fn repeated_isinstance_calls( checker: &mut Checker, expr: &Expr, - op: &Boolop, + op: Boolop, values: &[Expr], ) { if !matches!(op, Boolop::Or) || !checker.ctx.is_builtin("isinstance") { @@ -38,10 +38,10 @@ pub(crate) fn repeated_isinstance_calls( let mut obj_to_types: FxHashMap)> = FxHashMap::default(); for value in values { - let ExprKind::Call(ast::ExprCall { func, args, .. }) = &value.node else { + let Expr::Call(ast::ExprCall { func, args, .. }) = value else { continue; }; - if !matches!(&func.node, ExprKind::Name(ast::ExprName { id, .. }) if id == "isinstance") { + if !matches!(func.as_ref(), Expr::Name(ast::ExprName { id, .. }) if id == "isinstance") { continue; } let [obj, types] = &args[..] else { @@ -52,8 +52,8 @@ pub(crate) fn repeated_isinstance_calls( .or_insert_with(|| (0, FxHashSet::default())); *num_calls += 1; - matches.extend(match &types.node { - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + matches.extend(match types { + Expr::Tuple(ast::ExprTuple { elts, .. }) => { elts.iter().map(HashableExpr::from_expr).collect() } _ => { diff --git a/crates/ruff/src/rules/pylint/rules/return_in_init.rs b/crates/ruff/src/rules/pylint/rules/return_in_init.rs index e40b7db8e4..d5f981b545 100644 --- a/crates/ruff/src/rules/pylint/rules/return_in_init.rs +++ b/crates/ruff/src/rules/pylint/rules/return_in_init.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -44,11 +44,11 @@ impl Violation for ReturnInInit { /// PLE0101 pub(crate) fn return_in_init(checker: &mut Checker, stmt: &Stmt) { - if let StmtKind::Return(ast::StmtReturn { value }) = &stmt.node { + if let Stmt::Return(ast::StmtReturn { value, range: _ }) = stmt { if let Some(expr) = value { if matches!( - expr.node, - ExprKind::Constant(ast::ExprConstant { + expr.as_ref(), + Expr::Constant(ast::ExprConstant { value: Constant::None, .. }) diff --git a/crates/ruff/src/rules/pylint/rules/sys_exit_alias.rs b/crates/ruff/src/rules/pylint/rules/sys_exit_alias.rs index 1ff6dc1d12..83eeefa0fb 100644 --- a/crates/ruff/src/rules/pylint/rules/sys_exit_alias.rs +++ b/crates/ruff/src/rules/pylint/rules/sys_exit_alias.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -29,7 +29,7 @@ impl Violation for SysExitAlias { /// PLR1722 pub(crate) fn sys_exit_alias(checker: &mut Checker, func: &Expr) { - let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else { + let Expr::Name(ast::ExprName { id, .. }) = func else { return; }; for name in ["exit", "quit"] { diff --git a/crates/ruff/src/rules/pylint/rules/too_many_arguments.rs b/crates/ruff/src/rules/pylint/rules/too_many_arguments.rs index cf201ec220..8266aa290e 100644 --- a/crates/ruff/src/rules/pylint/rules/too_many_arguments.rs +++ b/crates/ruff/src/rules/pylint/rules/too_many_arguments.rs @@ -27,7 +27,7 @@ pub(crate) fn too_many_arguments(checker: &mut Checker, args: &Arguments, stmt: .iter() .chain(args.kwonlyargs.iter()) .chain(args.posonlyargs.iter()) - .filter(|arg| !checker.settings.dummy_variable_rgx.is_match(&arg.node.arg)) + .filter(|arg| !checker.settings.dummy_variable_rgx.is_match(&arg.arg)) .count(); if num_args > checker.settings.pylint.max_args { checker.diagnostics.push(Diagnostic::new( diff --git a/crates/ruff/src/rules/pylint/rules/too_many_branches.rs b/crates/ruff/src/rules/pylint/rules/too_many_branches.rs index e2532b6258..8edede1586 100644 --- a/crates/ruff/src/rules/pylint/rules/too_many_branches.rs +++ b/crates/ruff/src/rules/pylint/rules/too_many_branches.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, ExcepthandlerKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Excepthandler, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -26,27 +26,27 @@ fn num_branches(stmts: &[Stmt]) -> usize { stmts .iter() .map(|stmt| { - match &stmt.node { - StmtKind::If(ast::StmtIf { body, orelse, .. }) => { + match stmt { + Stmt::If(ast::StmtIf { body, orelse, .. }) => { 1 + num_branches(body) + (if let Some(stmt) = orelse.first() { // `elif:` and `else: if:` have the same AST representation. // Avoid treating `elif:` as two statements. - usize::from(!matches!(stmt.node, StmtKind::If(_))) + usize::from(!matches!(stmt, Stmt::If(_))) } else { 0 }) + num_branches(orelse) } - StmtKind::Match(ast::StmtMatch { cases, .. }) => { + Stmt::Match(ast::StmtMatch { cases, .. }) => { 1 + cases .iter() .map(|case| num_branches(&case.body)) .sum::() } - StmtKind::For(ast::StmtFor { body, orelse, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) - | StmtKind::While(ast::StmtWhile { body, orelse, .. }) => { + Stmt::For(ast::StmtFor { body, orelse, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) + | Stmt::While(ast::StmtWhile { body, orelse, .. }) => { 1 + num_branches(body) + (if orelse.is_empty() { 0 @@ -54,17 +54,19 @@ fn num_branches(stmts: &[Stmt]) -> usize { 1 + num_branches(orelse) }) } - StmtKind::Try(ast::StmtTry { + Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, + range: _, }) - | StmtKind::TryStar(ast::StmtTryStar { + | Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, finalbody, + range: _, }) => { 1 + num_branches(body) + (if orelse.is_empty() { @@ -81,9 +83,9 @@ fn num_branches(stmts: &[Stmt]) -> usize { .iter() .map(|handler| { 1 + { - let ExcepthandlerKind::ExceptHandler( + let Excepthandler::ExceptHandler( ast::ExcepthandlerExceptHandler { body, .. }, - ) = &handler.node; + ) = handler; num_branches(body) } }) diff --git a/crates/ruff/src/rules/pylint/rules/too_many_statements.rs b/crates/ruff/src/rules/pylint/rules/too_many_statements.rs index 774a692875..829f85e471 100644 --- a/crates/ruff/src/rules/pylint/rules/too_many_statements.rs +++ b/crates/ruff/src/rules/pylint/rules/too_many_statements.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, ExcepthandlerKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Excepthandler, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -25,46 +25,48 @@ impl Violation for TooManyStatements { fn num_statements(stmts: &[Stmt]) -> usize { let mut count = 0; for stmt in stmts { - match &stmt.node { - StmtKind::If(ast::StmtIf { body, orelse, .. }) => { + match stmt { + Stmt::If(ast::StmtIf { body, orelse, .. }) => { count += 1; count += num_statements(body); if let Some(stmt) = orelse.first() { // `elif:` and `else: if:` have the same AST representation. // Avoid treating `elif:` as two statements. - if !matches!(stmt.node, StmtKind::If(_)) { + if !matches!(stmt, Stmt::If(_)) { count += 1; } count += num_statements(orelse); } } - StmtKind::For(ast::StmtFor { body, orelse, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) => { + Stmt::For(ast::StmtFor { body, orelse, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) => { count += num_statements(body); count += num_statements(orelse); } - StmtKind::While(ast::StmtWhile { body, orelse, .. }) => { + Stmt::While(ast::StmtWhile { body, orelse, .. }) => { count += 1; count += num_statements(body); count += num_statements(orelse); } - StmtKind::Match(ast::StmtMatch { cases, .. }) => { + Stmt::Match(ast::StmtMatch { cases, .. }) => { count += 1; for case in cases { count += num_statements(&case.body); } } - StmtKind::Try(ast::StmtTry { + Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, + range: _, }) - | StmtKind::TryStar(ast::StmtTryStar { + | Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, finalbody, + range: _, }) => { count += 1; count += num_statements(body); @@ -80,20 +82,19 @@ fn num_statements(stmts: &[Stmt]) -> usize { } for handler in handlers { count += 1; - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { - body, - .. - }) = &handler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { + body, .. + }) = handler; count += num_statements(body); } } - StmtKind::FunctionDef(ast::StmtFunctionDef { body, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) - | StmtKind::With(ast::StmtWith { body, .. }) => { + Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) + | Stmt::With(ast::StmtWith { body, .. }) => { count += 1; count += num_statements(body); } - StmtKind::Return(_) => {} + Stmt::Return(_) => {} _ => { count += 1; } diff --git a/crates/ruff/src/rules/pylint/rules/unnecessary_direct_lambda_call.rs b/crates/ruff/src/rules/pylint/rules/unnecessary_direct_lambda_call.rs index 6306c6e24b..32207ad885 100644 --- a/crates/ruff/src/rules/pylint/rules/unnecessary_direct_lambda_call.rs +++ b/crates/ruff/src/rules/pylint/rules/unnecessary_direct_lambda_call.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Expr, ExprKind}; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -36,7 +36,7 @@ impl Violation for UnnecessaryDirectLambdaCall { /// PLC3002 pub(crate) fn unnecessary_direct_lambda_call(checker: &mut Checker, expr: &Expr, func: &Expr) { - if let ExprKind::Lambda(_) = &func.node { + if let Expr::Lambda(_) = func { checker .diagnostics .push(Diagnostic::new(UnnecessaryDirectLambdaCall, expr.range())); diff --git a/crates/ruff/src/rules/pylint/rules/useless_else_on_loop.rs b/crates/ruff/src/rules/pylint/rules/useless_else_on_loop.rs index 78163fb21c..8d0fa2375b 100644 --- a/crates/ruff/src/rules/pylint/rules/useless_else_on_loop.rs +++ b/crates/ruff/src/rules/pylint/rules/useless_else_on_loop.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, ExcepthandlerKind, MatchCase, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Excepthandler, MatchCase, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -20,41 +20,42 @@ impl Violation for UselessElseOnLoop { } fn loop_exits_early(body: &[Stmt]) -> bool { - body.iter().any(|stmt| match &stmt.node { - StmtKind::If(ast::StmtIf { body, orelse, .. }) => { + body.iter().any(|stmt| match stmt { + Stmt::If(ast::StmtIf { body, orelse, .. }) => { loop_exits_early(body) || loop_exits_early(orelse) } - StmtKind::With(ast::StmtWith { body, .. }) - | StmtKind::AsyncWith(ast::StmtAsyncWith { body, .. }) => loop_exits_early(body), - StmtKind::Match(ast::StmtMatch { cases, .. }) => cases + Stmt::With(ast::StmtWith { body, .. }) + | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => loop_exits_early(body), + Stmt::Match(ast::StmtMatch { cases, .. }) => cases .iter() .any(|MatchCase { body, .. }| loop_exits_early(body)), - StmtKind::Try(ast::StmtTry { + Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, + .. }) - | StmtKind::TryStar(ast::StmtTryStar { + | Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, finalbody, + .. }) => { loop_exits_early(body) || loop_exits_early(orelse) || loop_exits_early(finalbody) - || handlers.iter().any(|handler| match &handler.node { - ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { - body, - .. + || handlers.iter().any(|handler| match handler { + Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { + body, .. }) => loop_exits_early(body), }) } - StmtKind::For(ast::StmtFor { orelse, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { orelse, .. }) - | StmtKind::While(ast::StmtWhile { orelse, .. }) => loop_exits_early(orelse), - StmtKind::Break => true, + Stmt::For(ast::StmtFor { orelse, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { orelse, .. }) + | Stmt::While(ast::StmtWhile { orelse, .. }) => loop_exits_early(orelse), + Stmt::Break(_) => true, _ => false, }) } diff --git a/crates/ruff/src/rules/pylint/rules/useless_import_alias.rs b/crates/ruff/src/rules/pylint/rules/useless_import_alias.rs index acf1e28449..7c657a5840 100644 --- a/crates/ruff/src/rules/pylint/rules/useless_import_alias.rs +++ b/crates/ruff/src/rules/pylint/rules/useless_import_alias.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Alias; +use rustpython_parser::ast::{Alias, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -37,13 +37,13 @@ impl AlwaysAutofixableViolation for UselessImportAlias { /// PLC0414 pub(crate) fn useless_import_alias(checker: &mut Checker, alias: &Alias) { - let Some(asname) = &alias.node.asname else { + let Some(asname) = &alias.asname else { return; }; - if alias.node.name.contains('.') { + if alias.name.contains('.') { return; } - if &alias.node.name != asname { + if &alias.name != asname { return; } diff --git a/crates/ruff/src/rules/pylint/rules/useless_return.rs b/crates/ruff/src/rules/pylint/rules/useless_return.rs index 704ab701e9..2fc8336b2c 100644 --- a/crates/ruff/src/rules/pylint/rules/useless_return.rs +++ b/crates/ruff/src/rules/pylint/rules/useless_return.rs @@ -1,5 +1,5 @@ use log::error; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged, Stmt}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -64,7 +64,7 @@ pub(crate) fn useless_return<'a>( // Find the last statement in the function. let last_stmt = body.last().unwrap(); - if !matches!(last_stmt.node, StmtKind::Return(_)) { + if !matches!(last_stmt, Stmt::Return(_)) { return; } @@ -75,10 +75,10 @@ pub(crate) fn useless_return<'a>( // Skip functions that consist of a docstring and a return statement. if body.len() == 2 { - if let StmtKind::Expr(ast::StmtExpr { value }) = &body[0].node { + if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = &body[0] { if matches!( - value.node, - ExprKind::Constant(ast::ExprConstant { + value.as_ref(), + Expr::Constant(ast::ExprConstant { value: Constant::Str(_), .. }) @@ -89,7 +89,7 @@ pub(crate) fn useless_return<'a>( } // Verify that the last statement is a return statement. - let StmtKind::Return(ast::StmtReturn { value}) = &last_stmt.node else { + let Stmt::Return(ast::StmtReturn { value, range: _}) = &last_stmt else { return; }; diff --git a/crates/ruff/src/rules/pylint/rules/yield_in_init.rs b/crates/ruff/src/rules/pylint/rules/yield_in_init.rs index 00cb177a02..f9f08650d4 100644 --- a/crates/ruff/src/rules/pylint/rules/yield_in_init.rs +++ b/crates/ruff/src/rules/pylint/rules/yield_in_init.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pyupgrade/fixes.rs b/crates/ruff/src/rules/pyupgrade/fixes.rs index 0bc8a66e41..d29555109a 100644 --- a/crates/ruff/src/rules/pyupgrade/fixes.rs +++ b/crates/ruff/src/rules/pyupgrade/fixes.rs @@ -4,7 +4,7 @@ use libcst_native::{ SmallStatement, Statement, Suite, }; use ruff_text_size::{TextRange, TextSize}; -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use rustpython_parser::{lexer, Mode, Tok}; use ruff_diagnostics::Edit; diff --git a/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs b/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs index 177a200cda..744c3e1c7c 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs @@ -1,12 +1,11 @@ use anyhow::{bail, Result}; use log::debug; -use rustpython_parser::ast::{ - self, Constant, Expr, ExprContext, ExprKind, Keyword, Stmt, StmtKind, -}; +use ruff_text_size::TextRange; +use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Keyword, Ranged, Stmt}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{create_expr, create_stmt, unparse_stmt}; +use ruff_python_ast::helpers::unparse_stmt; use ruff_python_ast::source_code::Stylist; use ruff_python_stdlib::identifiers::is_identifier; @@ -41,14 +40,15 @@ fn match_named_tuple_assign<'a>( value: &'a Expr, ) -> Option<(&'a str, &'a [Expr], &'a [Keyword], &'a Expr)> { let target = targets.get(0)?; - let ExprKind::Name(ast::ExprName { id: typename, .. }) = &target.node else { + let Expr::Name(ast::ExprName { id: typename, .. }) = target else { return None; }; - let ExprKind::Call(ast::ExprCall { + let Expr::Call(ast::ExprCall { func, args, keywords, - }) = &value.node else { + range: _, + }) = value else { return None; }; if !checker @@ -63,38 +63,42 @@ fn match_named_tuple_assign<'a>( Some((typename, args, keywords, func)) } -/// Generate a `StmtKind::AnnAssign` representing the provided property +/// Generate a `Stmt::AnnAssign` representing the provided property /// definition. fn create_property_assignment_stmt( property: &str, annotation: &Expr, value: Option<&Expr>, ) -> Stmt { - create_stmt(ast::StmtAnnAssign { - target: Box::new(create_expr(ast::ExprName { - id: property.into(), - ctx: ExprContext::Load, - })), + let node = ast::ExprName { + id: property.into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node1 = ast::StmtAnnAssign { + target: Box::new(node.into()), annotation: Box::new(annotation.clone()), value: value.map(|value| Box::new(value.clone())), simple: true, - }) + range: TextRange::default(), + }; + node1.into() } /// Match the `defaults` keyword in a `NamedTuple(...)` call. fn match_defaults(keywords: &[Keyword]) -> Result<&[Expr]> { let defaults = keywords.iter().find(|keyword| { - if let Some(arg) = &keyword.node.arg { + if let Some(arg) = &keyword.arg { arg == "defaults" } else { false } }); match defaults { - Some(defaults) => match &defaults.node.value.node { - ExprKind::List(ast::ExprList { elts, .. }) => Ok(elts), - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => Ok(elts), - _ => bail!("Expected defaults to be `ExprKind::List` | `ExprKind::Tuple`"), + Some(defaults) => match &defaults.value { + Expr::List(ast::ExprList { elts, .. }) => Ok(elts), + Expr::Tuple(ast::ExprTuple { elts, .. }) => Ok(elts), + _ => bail!("Expected defaults to be `Expr::List` | `Expr::Tuple`"), }, None => Ok(&[]), } @@ -103,13 +107,17 @@ fn match_defaults(keywords: &[Keyword]) -> Result<&[Expr]> { /// Create a list of property assignments from the `NamedTuple` arguments. fn create_properties_from_args(args: &[Expr], defaults: &[Expr]) -> Result> { let Some(fields) = args.get(1) else { - return Ok(vec![create_stmt(StmtKind::Pass)]); + let node = Stmt::Pass(ast::StmtPass { range: TextRange::default()}); + return Ok(vec![node]); }; - let ExprKind::List(ast::ExprList { elts, .. } )= &fields.node else { - bail!("Expected argument to be `ExprKind::List`"); + let Expr::List(ast::ExprList { elts, .. } )= &fields else { + bail!("Expected argument to be `Expr::List`"); }; if elts.is_empty() { - return Ok(vec![create_stmt(StmtKind::Pass)]); + let node = Stmt::Pass(ast::StmtPass { + range: TextRange::default(), + }); + return Ok(vec![node]); } let padded_defaults = if elts.len() >= defaults.len() { std::iter::repeat(None) @@ -121,16 +129,16 @@ fn create_properties_from_args(args: &[Expr], defaults: &[Expr]) -> Result Result, base_class: &Expr) -> Stmt { - create_stmt(ast::StmtClassDef { + let node = ast::StmtClassDef { name: typename.into(), bases: vec![base_class.clone()], keywords: vec![], body, decorator_list: vec![], - }) + range: TextRange::default(), + }; + node.into() } /// Generate a `Fix` to convert a `NamedTuple` assignment to a class definition. diff --git a/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs b/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs index cb43b134c3..36a0728df6 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs @@ -1,12 +1,11 @@ use anyhow::{bail, Result}; use log::debug; -use rustpython_parser::ast::{ - self, Constant, Expr, ExprContext, ExprKind, Keyword, Stmt, StmtKind, -}; +use ruff_text_size::TextRange; +use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Keyword, Ranged, Stmt}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{create_expr, create_stmt, unparse_stmt}; +use ruff_python_ast::helpers::unparse_stmt; use ruff_python_ast::source_code::Stylist; use ruff_python_stdlib::identifiers::is_identifier; @@ -42,14 +41,15 @@ fn match_typed_dict_assign<'a>( value: &'a Expr, ) -> Option<(&'a str, &'a [Expr], &'a [Keyword], &'a Expr)> { let target = targets.get(0)?; - let ExprKind::Name(ast::ExprName { id: class_name, .. }) = &target.node else { + let Expr::Name(ast::ExprName { id: class_name, .. }) = target else { return None; }; - let ExprKind::Call(ast::ExprCall { + let Expr::Call(ast::ExprCall { func, args, keywords, - }) = &value.node else { + range: _ + }) = value else { return None; }; if !checker @@ -64,18 +64,23 @@ fn match_typed_dict_assign<'a>( Some((class_name, args, keywords, func)) } -/// Generate a `StmtKind::AnnAssign` representing the provided property +/// Generate a `Stmt::AnnAssign` representing the provided property /// definition. -fn create_property_assignment_stmt(property: &str, annotation: &ExprKind) -> Stmt { - create_stmt(ast::StmtAnnAssign { - target: Box::new(create_expr(ast::ExprName { - id: property.into(), - ctx: ExprContext::Load, - })), - annotation: Box::new(create_expr(annotation.clone())), +fn create_property_assignment_stmt(property: &str, annotation: &Expr) -> Stmt { + let node = annotation.clone(); + let node1 = ast::ExprName { + id: property.into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node2 = ast::StmtAnnAssign { + target: Box::new(node1.into()), + annotation: Box::new(node), value: None, simple: true, - }) + range: TextRange::default(), + }; + node2.into() } /// Generate a `StmtKind:ClassDef` statement based on the provided body, @@ -90,33 +95,34 @@ fn create_class_def_stmt( Some(keyword) => vec![keyword.clone()], None => vec![], }; - create_stmt(ast::StmtClassDef { + let node = ast::StmtClassDef { name: class_name.into(), bases: vec![base_class.clone()], keywords, body, decorator_list: vec![], - }) + range: TextRange::default(), + }; + node.into() } fn properties_from_dict_literal(keys: &[Option], values: &[Expr]) -> Result> { if keys.is_empty() { - return Ok(vec![create_stmt(StmtKind::Pass)]); + let node = Stmt::Pass(ast::StmtPass { + range: TextRange::default(), + }); + return Ok(vec![node]); } keys.iter() .zip(values.iter()) .map(|(key, value)| match key { - Some(Expr { - node: - ExprKind::Constant(ast::ExprConstant { - value: Constant::Str(property), - .. - }), + Some(Expr::Constant(ast::ExprConstant { + value: Constant::Str(property), .. - }) => { + })) => { if is_identifier(property) { - Ok(create_property_assignment_stmt(property, &value.node)) + Ok(create_property_assignment_stmt(property, value)) } else { bail!("Property name is not valid identifier: {}", property) } @@ -127,14 +133,17 @@ fn properties_from_dict_literal(keys: &[Option], values: &[Expr]) -> Resul } fn properties_from_dict_call(func: &Expr, keywords: &[Keyword]) -> Result> { - let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else { - bail!("Expected `func` to be `ExprKind::Name`") + let Expr::Name(ast::ExprName { id, .. }) = func else { + bail!("Expected `func` to be `Expr::Name`") }; if id != "dict" { bail!("Expected `id` to be `\"dict\"`") } if keywords.is_empty() { - return Ok(vec![create_stmt(StmtKind::Pass)]); + let node = Stmt::Pass(ast::StmtPass { + range: TextRange::default(), + }); + return Ok(vec![node]); } properties_from_keywords(keywords) @@ -143,17 +152,17 @@ fn properties_from_dict_call(func: &Expr, keywords: &[Keyword]) -> Result Result> { if keywords.is_empty() { - return Ok(vec![create_stmt(StmtKind::Pass)]); + let node = Stmt::Pass(ast::StmtPass { + range: TextRange::default(), + }); + return Ok(vec![node]); } keywords .iter() .map(|keyword| { - if let Some(property) = &keyword.node.arg { - Ok(create_property_assignment_stmt( - property, - &keyword.node.value.node, - )) + if let Some(property) = &keyword.arg { + Ok(create_property_assignment_stmt(property, &keyword.value)) } else { bail!("Expected `arg` to be `Some`") } @@ -167,7 +176,7 @@ fn properties_from_keywords(keywords: &[Keyword]) -> Result> { // ``` fn match_total_from_only_keyword(keywords: &[Keyword]) -> Option<&Keyword> { let keyword = keywords.get(0)?; - let arg = &keyword.node.arg.as_ref()?; + let arg = &keyword.arg.as_ref()?; match arg.as_str() { "total" => Some(keyword), _ => None, @@ -185,19 +194,24 @@ fn match_properties_and_total<'a>( // ``` if let Some(dict) = args.get(1) { let total = match_total_from_only_keyword(keywords); - match &dict.node { - ExprKind::Dict(ast::ExprDict { keys, values }) => { - Ok((properties_from_dict_literal(keys, values)?, total)) - } - ExprKind::Call(ast::ExprCall { func, keywords, .. }) => { + match dict { + Expr::Dict(ast::ExprDict { + keys, + values, + range: _, + }) => Ok((properties_from_dict_literal(keys, values)?, total)), + Expr::Call(ast::ExprCall { func, keywords, .. }) => { Ok((properties_from_dict_call(func, keywords)?, total)) } - _ => bail!("Expected `arg` to be `ExprKind::Dict` or `ExprKind::Call`"), + _ => bail!("Expected `arg` to be `Expr::Dict` or `Expr::Call`"), } } else if !keywords.is_empty() { Ok((properties_from_keywords(keywords)?, None)) } else { - Ok((vec![create_stmt(StmtKind::Pass)], None)) + let node = Stmt::Pass(ast::StmtPass { + range: TextRange::default(), + }); + Ok((vec![node], None)) } } diff --git a/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs index 02008f3bac..01055b6ba0 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs index 69ced4a0ac..dddc5b328f 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Attributed, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Ranged, Stmt}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -20,7 +20,10 @@ impl AlwaysAutofixableViolation for DeprecatedCElementTree { } } -fn add_check_for_node(checker: &mut Checker, node: &Attributed) { +fn add_check_for_node(checker: &mut Checker, node: &T) +where + T: Ranged, +{ let mut diagnostic = Diagnostic::new(DeprecatedCElementTree, node.range()); if checker.patch(diagnostic.kind.rule()) { let contents = checker.locator.slice(node.range()); @@ -35,19 +38,20 @@ fn add_check_for_node(checker: &mut Checker, node: &Attributed) { /// UP023 pub(crate) fn deprecated_c_element_tree(checker: &mut Checker, stmt: &Stmt) { - match &stmt.node { - StmtKind::Import(ast::StmtImport { names }) => { + match stmt { + Stmt::Import(ast::StmtImport { names, range: _ }) => { // Ex) `import xml.etree.cElementTree as ET` for name in names { - if &name.node.name == "xml.etree.cElementTree" && name.node.asname.is_some() { + if &name.name == "xml.etree.cElementTree" && name.asname.is_some() { add_check_for_node(checker, name); } } } - StmtKind::ImportFrom(ast::StmtImportFrom { + Stmt::ImportFrom(ast::StmtImportFrom { module, names, level, + range: _, }) => { if level.map_or(false, |level| level.to_u32() > 0) { // Ex) `import .xml.etree.cElementTree as ET` @@ -58,13 +62,13 @@ pub(crate) fn deprecated_c_element_tree(checker: &mut Checker, stmt: &Stmt) { } else if module == "xml.etree" { // Ex) `from xml.etree import cElementTree as ET` for name in names { - if &name.node.name == "cElementTree" && name.node.asname.is_some() { + if &name.name == "cElementTree" && name.asname.is_some() { add_check_for_node(checker, name); } } } } } - _ => panic!("Expected StmtKind::Import | StmtKind::ImportFrom"), + _ => panic!("Expected Stmt::Import | Stmt::ImportFrom"), } } diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs index b163f4d857..f331fcd76d 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs @@ -1,5 +1,5 @@ use itertools::Itertools; -use rustpython_parser::ast::{Alias, AliasData, Stmt}; +use rustpython_parser::ast::{Alias, Ranged, Stmt}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -261,7 +261,7 @@ const TYPING_EXTENSIONS_TO_TYPING_311: &[&str] = &[ struct ImportReplacer<'a> { stmt: &'a Stmt, module: &'a str, - members: &'a [AliasData], + members: &'a [Alias], locator: &'a Locator<'a>, stylist: &'a Stylist<'a>, version: PythonVersion, @@ -271,7 +271,7 @@ impl<'a> ImportReplacer<'a> { const fn new( stmt: &'a Stmt, module: &'a str, - members: &'a [AliasData], + members: &'a [Alias], locator: &'a Locator<'a>, stylist: &'a Stylist<'a>, version: PythonVersion, @@ -475,7 +475,7 @@ impl<'a> ImportReplacer<'a> { } /// Partitions imports into matched and unmatched names. - fn partition_imports(&self, candidates: &[&str]) -> (Vec<&AliasData>, Vec<&AliasData>) { + fn partition_imports(&self, candidates: &[&str]) -> (Vec<&Alias>, Vec<&Alias>) { let mut matched_names = vec![]; let mut unmatched_names = vec![]; for name in self.members { @@ -490,7 +490,7 @@ impl<'a> ImportReplacer<'a> { /// Converts a list of names and a module into an `import from`-style /// import. - fn format_import_from(names: &[&AliasData], module: &str) -> String { + fn format_import_from(names: &[&Alias], module: &str) -> String { // Construct the whitespace strings. // Generate the formatted names. let full_names: String = names @@ -516,7 +516,7 @@ pub(crate) fn deprecated_import( if level.map_or(false, |level| level > 0) { return; } - if names.first().map_or(false, |name| &name.node.name == "*") { + if names.first().map_or(false, |name| &name.name == "*") { return; } let Some(module) = module else { @@ -527,7 +527,7 @@ pub(crate) fn deprecated_import( return; } - let members: Vec = names.iter().map(|alias| alias.node.clone()).collect(); + let members: Vec = names.iter().map(std::clone::Clone::clone).collect(); let fixer = ImportReplacer::new( stmt, module, diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs index f67824d0cf..6745134fd4 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs @@ -4,7 +4,7 @@ use libcst_native::{ ImportAlias, ImportFrom, ImportNames, Name, NameOrAttribute, ParenthesizableWhitespace, }; use log::error; -use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Expr, Ranged, Stmt}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -246,7 +246,7 @@ fn format_import_from( /// UP026 pub(crate) fn deprecated_mock_attribute(checker: &mut Checker, expr: &Expr) { - if let ExprKind::Attribute(ast::ExprAttribute { value, .. }) = &expr.node { + if let Expr::Attribute(ast::ExprAttribute { value, .. }) = expr { if collect_call_path(value) .map_or(false, |call_path| call_path.as_slice() == ["mock", "mock"]) { @@ -270,12 +270,12 @@ pub(crate) fn deprecated_mock_attribute(checker: &mut Checker, expr: &Expr) { /// UP026 pub(crate) fn deprecated_mock_import(checker: &mut Checker, stmt: &Stmt) { - match &stmt.node { - StmtKind::Import(ast::StmtImport { names }) => { + match stmt { + Stmt::Import(ast::StmtImport { names, range: _ }) => { // Find all `mock` imports. if names .iter() - .any(|name| &name.node.name == "mock" || &name.node.name == "mock.mock") + .any(|name| &name.name == "mock" || &name.name == "mock.mock") { // Generate the fix, if needed, which is shared between all `mock` imports. let content = if checker.patch(Rule::DeprecatedMockImport) { @@ -296,7 +296,7 @@ pub(crate) fn deprecated_mock_import(checker: &mut Checker, stmt: &Stmt) { // Add a `Diagnostic` for each `mock` import. for name in names { - if &name.node.name == "mock" || &name.node.name == "mock.mock" { + if &name.name == "mock" || &name.name == "mock.mock" { let mut diagnostic = Diagnostic::new( DeprecatedMockImport { reference_type: MockReference::Import, @@ -315,7 +315,7 @@ pub(crate) fn deprecated_mock_import(checker: &mut Checker, stmt: &Stmt) { } } } - StmtKind::ImportFrom(ast::StmtImportFrom { + Stmt::ImportFrom(ast::StmtImportFrom { module: Some(module), level, .. diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_unittest_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_unittest_alias.rs index a61b790b57..e73b6a1efc 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_unittest_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_unittest_alias.rs @@ -1,6 +1,6 @@ use once_cell::sync::Lazy; use rustc_hash::FxHashMap; -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -49,13 +49,13 @@ static DEPRECATED_ALIASES: Lazy> = Lazy::n /// UP005 pub(crate) fn deprecated_unittest_alias(checker: &mut Checker, expr: &Expr) { - let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &expr.node else { + let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = expr else { return; }; - let Some(&target) = DEPRECATED_ALIASES.get(attr.as_str()) else { + let Some(target) = DEPRECATED_ALIASES.get(attr.as_str()) else { return; }; - let ExprKind::Name(ast::ExprName { id, .. }) = &value.node else { + let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() else { return; }; if id != "self" { @@ -64,7 +64,7 @@ pub(crate) fn deprecated_unittest_alias(checker: &mut Checker, expr: &Expr) { let mut diagnostic = Diagnostic::new( DeprecatedUnittestAlias { alias: attr.to_string(), - target: target.to_string(), + target: (*target).to_string(), }, expr.range(), ); diff --git a/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs b/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs index eefd33cf71..e21bbf0869 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs @@ -3,7 +3,7 @@ use rustc_hash::FxHashMap; use rustpython_format::{ FieldName, FieldNamePart, FieldType, FormatPart, FormatString, FromTemplate, }; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, KeywordData}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -42,7 +42,7 @@ impl<'a> FormatSummaryValues<'a> { fn try_from_expr(checker: &'a Checker, expr: &'a Expr) -> Option { let mut extracted_args: Vec = Vec::new(); let mut extracted_kwargs: FxHashMap<&str, String> = FxHashMap::default(); - if let ExprKind::Call(ast::ExprCall { args, keywords, .. }) = &expr.node { + if let Expr::Call(ast::ExprCall { args, keywords, .. }) = expr { for arg in args { let arg = checker.locator.slice(arg.range()); if contains_invalids(arg) { @@ -51,7 +51,11 @@ impl<'a> FormatSummaryValues<'a> { extracted_args.push(arg.to_string()); } for keyword in keywords { - let KeywordData { arg, value } = &keyword.node; + let Keyword { + arg, + value, + range: _, + } = keyword; if let Some(key) = arg { let kwarg = checker.locator.slice(value.range()); if contains_invalids(kwarg) { @@ -104,15 +108,15 @@ fn contains_invalids(string: &str) -> bool { /// Generate an f-string from an [`Expr`]. fn try_convert_to_f_string(checker: &Checker, expr: &Expr) -> Option { - let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node else { + let Expr::Call(ast::ExprCall { func, .. }) = expr else { return None; }; - let ExprKind::Attribute(ast::ExprAttribute { value, .. }) = &func.node else { + let Expr::Attribute(ast::ExprAttribute { value, .. }) = func.as_ref() else { return None; }; if !matches!( - &value.node, - ExprKind::Constant(ast::ExprConstant { + value.as_ref(), + Expr::Constant(ast::ExprConstant { value: Constant::Str(..), .. }), diff --git a/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs b/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs index 68d27b23b4..802d63d91f 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs @@ -2,7 +2,7 @@ use anyhow::{anyhow, bail, Result}; use libcst_native::{Arg, Codegen, CodegenState, Expression}; use once_cell::sync::Lazy; use regex::Regex; -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs b/crates/ruff/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs index 8e435e35f8..1eb96710d5 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, KeywordData}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -25,11 +25,12 @@ impl AlwaysAutofixableViolation for LRUCacheWithMaxsizeNone { /// UP033 pub(crate) fn lru_cache_with_maxsize_none(checker: &mut Checker, decorator_list: &[Expr]) { for expr in decorator_list.iter() { - let ExprKind::Call(ast::ExprCall { + let Expr::Call(ast::ExprCall { func, args, keywords, - }) = &expr.node else { + range: _, + }) = expr else { continue; }; @@ -43,13 +44,18 @@ pub(crate) fn lru_cache_with_maxsize_none(checker: &mut Checker, decorator_list: call_path.as_slice() == ["functools", "lru_cache"] }) { - let KeywordData { arg, value } = &keywords[0].node; + let Keyword { + arg, + value, + range: _, + } = &keywords[0]; if arg.as_ref().map_or(false, |arg| arg == "maxsize") && matches!( - value.node, - ExprKind::Constant(ast::ExprConstant { + value, + Expr::Constant(ast::ExprConstant { value: Constant::None, kind: None, + range: _, }) ) { diff --git a/crates/ruff/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs b/crates/ruff/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs index dbb07e5607..0da4a40499 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -25,11 +25,12 @@ impl AlwaysAutofixableViolation for LRUCacheWithoutParameters { /// UP011 pub(crate) fn lru_cache_without_parameters(checker: &mut Checker, decorator_list: &[Expr]) { for expr in decorator_list.iter() { - let ExprKind::Call(ast::ExprCall { + let Expr::Call(ast::ExprCall { func, args, keywords, - }) = &expr.node else { + range: _, + }) = expr else { continue; }; diff --git a/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs b/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs index a44324c148..f99f930c0d 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs @@ -1,6 +1,6 @@ use std::fmt; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -50,7 +50,7 @@ pub(crate) fn native_literals( args: &[Expr], keywords: &[Keyword], ) { - let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else { return; }; + let Expr::Name(ast::ExprName { id, .. }) = func else { return; }; if !keywords.is_empty() || args.len() > 1 { return; @@ -88,8 +88,8 @@ pub(crate) fn native_literals( // Look for `str("")`. if id == "str" && !matches!( - &arg.node, - ExprKind::Constant(ast::ExprConstant { + &arg, + Expr::Constant(ast::ExprConstant { value: Constant::Str(_), .. }), @@ -101,8 +101,8 @@ pub(crate) fn native_literals( // Look for `bytes(b"")` if id == "bytes" && !matches!( - &arg.node, - ExprKind::Constant(ast::ExprConstant { + &arg, + Expr::Constant(ast::ExprConstant { value: Constant::Bytes(_), .. }), diff --git a/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs index d12941f087..a7f8372a62 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pyupgrade/rules/os_error_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/os_error_alias.rs index c6c6f6a152..8d11f320ce 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/os_error_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/os_error_alias.rs @@ -1,9 +1,10 @@ -use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind}; +use ruff_text_size::TextRange; +use rustpython_parser::ast::{self, Excepthandler, Expr, ExprContext, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::call_path::compose_call_path; -use ruff_python_ast::helpers::{create_expr, unparse_expr}; +use ruff_python_ast::helpers::unparse_expr; use ruff_python_semantic::context::Context; use crate::checkers::ast::Checker; @@ -54,7 +55,7 @@ fn is_os_error(context: &Context, expr: &Expr) -> bool { .map_or(false, |call_path| call_path.as_slice() == ["", "OSError"]) } -/// Create a [`Diagnostic`] for a single target, like an [`ExprKind::Name`]. +/// Create a [`Diagnostic`] for a single target, like an [`Expr::Name`]. fn atom_diagnostic(checker: &mut Checker, target: &Expr) { let mut diagnostic = Diagnostic::new( OSErrorAlias { @@ -76,8 +77,8 @@ fn atom_diagnostic(checker: &mut Checker, target: &Expr) { fn tuple_diagnostic(checker: &mut Checker, target: &Expr, aliases: &[&Expr]) { let mut diagnostic = Diagnostic::new(OSErrorAlias { name: None }, target.range()); if checker.patch(diagnostic.kind.rule()) { - let ExprKind::Tuple(ast::ExprTuple { elts, ..}) = &target.node else { - panic!("Expected ExprKind::Tuple"); + let Expr::Tuple(ast::ExprTuple { elts, ..}) = target else { + panic!("Expected Expr::Tuple"); }; // Filter out any `OSErrors` aliases. @@ -94,13 +95,12 @@ fn tuple_diagnostic(checker: &mut Checker, target: &Expr, aliases: &[&Expr]) { // If `OSError` itself isn't already in the tuple, add it. if elts.iter().all(|elt| !is_os_error(&checker.ctx, elt)) { - remaining.insert( - 0, - create_expr(ast::ExprName { - id: "OSError".into(), - ctx: ExprContext::Load, - }), - ); + let node = ast::ExprName { + id: "OSError".into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + remaining.insert(0, node.into()); } if remaining.len() == 1 { @@ -110,18 +110,14 @@ fn tuple_diagnostic(checker: &mut Checker, target: &Expr, aliases: &[&Expr]) { target.range(), ))); } else { + let node = ast::ExprTuple { + elts: remaining, + ctx: ExprContext::Load, + range: TextRange::default(), + }; #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( - format!( - "({})", - unparse_expr( - &create_expr(ast::ExprTuple { - elts: remaining, - ctx: ExprContext::Load, - }), - checker.stylist, - ) - ), + format!("({})", unparse_expr(&node.into(), checker.stylist,)), target.range(), ))); } @@ -132,18 +128,17 @@ fn tuple_diagnostic(checker: &mut Checker, target: &Expr, aliases: &[&Expr]) { /// UP024 pub(crate) fn os_error_alias_handlers(checker: &mut Checker, handlers: &[Excepthandler]) { for handler in handlers { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = - &handler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = handler; let Some(expr) = type_.as_ref() else { continue; }; - match &expr.node { - ExprKind::Name(_) | ExprKind::Attribute(_) => { + match expr.as_ref() { + Expr::Name(_) | Expr::Attribute(_) => { if is_alias(&checker.ctx, expr) { atom_diagnostic(checker, expr); } } - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + Expr::Tuple(ast::ExprTuple { elts, .. }) => { // List of aliases to replace with `OSError`. let mut aliases: Vec<&Expr> = vec![]; for elt in elts { @@ -169,7 +164,7 @@ pub(crate) fn os_error_alias_call(checker: &mut Checker, func: &Expr) { /// UP024 pub(crate) fn os_error_alias_raise(checker: &mut Checker, expr: &Expr) { - if matches!(expr.node, ExprKind::Name(_) | ExprKind::Attribute(_)) { + if matches!(expr, Expr::Name(_) | Expr::Attribute(_)) { if is_alias(&checker.ctx, expr) { atom_diagnostic(checker, expr); } diff --git a/crates/ruff/src/rules/pyupgrade/rules/outdated_version_block.rs b/crates/ruff/src/rules/pyupgrade/rules/outdated_version_block.rs index bc3451964e..6419c73ed1 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/outdated_version_block.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/outdated_version_block.rs @@ -3,7 +3,7 @@ use std::cmp::Ordering; use log::error; use num_bigint::{BigInt, Sign}; use ruff_text_size::{TextRange, TextSize}; -use rustpython_parser::ast::{self, Attributed, Cmpop, Constant, Expr, ExprKind, Stmt}; +use rustpython_parser::ast::{self, Cmpop, Constant, Expr, Ranged, Stmt}; use rustpython_parser::{lexer, Mode, Tok}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; @@ -52,7 +52,10 @@ impl BlockMetadata { } } -fn metadata(locator: &Locator, located: &Attributed) -> Option { +fn metadata(locator: &Locator, located: &T) -> Option +where + T: Ranged, +{ indentation(locator, located)?; let line_start = locator.line_start(located.start()); @@ -107,10 +110,10 @@ fn bigint_to_u32(number: &BigInt) -> u32 { fn extract_version(elts: &[Expr]) -> Vec { let mut version: Vec = vec![]; for elt in elts { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Int(item), .. - }) = &elt.node + }) = &elt { let number = bigint_to_u32(item); version.push(number); @@ -148,7 +151,7 @@ fn compare_version(if_version: &[u32], py_version: PythonVersion, or_equal: bool } } -/// Convert a [`StmtKind::If`], retaining the `else`. +/// Convert a [`Stmt::If`], retaining the `else`. fn fix_py2_block( checker: &mut Checker, stmt: &Stmt, @@ -241,7 +244,7 @@ fn fix_py2_block( } } -/// Convert a [`StmtKind::If`], removing the `else` block. +/// Convert a [`Stmt::If`], removing the `else` block. fn fix_py3_block( checker: &mut Checker, stmt: &Stmt, @@ -310,11 +313,12 @@ pub(crate) fn outdated_version_block( body: &[Stmt], orelse: &[Stmt], ) { - let ExprKind::Compare(ast::ExprCompare { + let Expr::Compare(ast::ExprCompare { left, ops, comparators, - }) = &test.node else { + range: _, + }) = &test else { return; }; @@ -329,10 +333,10 @@ pub(crate) fn outdated_version_block( } if ops.len() == 1 && comparators.len() == 1 { - let comparison = &comparators[0].node; + let comparison = &comparators[0]; let op = &ops[0]; match comparison { - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + Expr::Tuple(ast::ExprTuple { elts, .. }) => { let version = extract_version(elts); let target = checker.settings.target_version; if op == &Cmpop::Lt || op == &Cmpop::LtE { @@ -364,7 +368,7 @@ pub(crate) fn outdated_version_block( } } } - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: Constant::Int(number), .. }) => { diff --git a/crates/ruff/src/rules/pyupgrade/rules/printf_string_formatting.rs b/crates/ruff/src/rules/pyupgrade/rules/printf_string_formatting.rs index 201a342d89..08aa5fda1e 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/printf_string_formatting.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/printf_string_formatting.rs @@ -4,7 +4,7 @@ use std::str::FromStr; use rustpython_format::cformat::{ CConversionFlags, CFormatPart, CFormatPrecision, CFormatQuantity, CFormatString, }; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged}; use rustpython_parser::{lexer, Mode, Tok}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; @@ -140,7 +140,7 @@ fn percent_to_format(format_string: &CFormatString) -> String { /// If a tuple has one argument, remove the comma; otherwise, return it as-is. fn clean_params_tuple(checker: &mut Checker, right: &Expr, locator: &Locator) -> String { let mut contents = checker.locator.slice(right.range()).to_string(); - if let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &right.node { + if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &right { if elts.len() == 1 { if !locator.contains_line_break(right.range()) { for (i, character) in contents.chars().rev().enumerate() { @@ -165,17 +165,22 @@ fn clean_params_dictionary( ) -> Option { let is_multi_line = locator.contains_line_break(right.range()); let mut contents = String::new(); - if let ExprKind::Dict(ast::ExprDict { keys, values }) = &right.node { + if let Expr::Dict(ast::ExprDict { + keys, + values, + range: _, + }) = &right + { let mut arguments: Vec = vec![]; let mut seen: Vec<&str> = vec![]; let mut indent = None; for (key, value) in keys.iter().zip(values.iter()) { match key { Some(key) => { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(key_string), .. - }) = &key.node + }) = key { // If the dictionary key is not a valid variable name, abort. if !is_identifier(key_string) { @@ -291,7 +296,7 @@ fn convertible(format_string: &CFormatString, params: &Expr) -> bool { } // All dict substitutions must be named. - if let ExprKind::Dict(_) = ¶ms.node { + if let Expr::Dict(_) = ¶ms { if fmt.mapping_key.is_none() { return false; } @@ -370,11 +375,11 @@ pub(crate) fn printf_string_formatting( } // Parse the parameters. - let params_string = match right.node { - ExprKind::Constant(_) | ExprKind::JoinedStr(_) => { + let params_string = match right { + Expr::Constant(_) | Expr::JoinedStr(_) => { format!("({})", checker.locator.slice(right.range())) } - ExprKind::Name(_) | ExprKind::Attribute(_) | ExprKind::Subscript(_) | ExprKind::Call(_) => { + Expr::Name(_) | Expr::Attribute(_) | Expr::Subscript(_) | Expr::Call(_) => { if num_keyword_arguments > 0 { // If we have _any_ named fields, assume the right-hand side is a mapping. format!("(**{})", checker.locator.slice(right.range())) @@ -395,8 +400,8 @@ pub(crate) fn printf_string_formatting( return; } } - ExprKind::Tuple(_) => clean_params_tuple(checker, right, locator), - ExprKind::Dict(_) => { + Expr::Tuple(_) => clean_params_tuple(checker, right, locator), + Expr::Dict(_) => { if let Some(params_string) = clean_params_dictionary(checker, right, locator) { params_string } else { diff --git a/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs b/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs index bcc04e3aa3..b7afd6a51c 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs @@ -2,7 +2,7 @@ use std::str::FromStr; use anyhow::{anyhow, Result}; use ruff_text_size::TextSize; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged}; use rustpython_parser::{lexer, Mode, Tok}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; @@ -87,13 +87,14 @@ impl OpenMode { } fn match_open(expr: &Expr) -> (Option<&Expr>, Vec) { - if let ExprKind::Call(ast::ExprCall { + if let Expr::Call(ast::ExprCall { func, args, keywords, - }) = &expr.node + range: _, + }) = expr { - if matches!(&func.node, ExprKind::Name(ast::ExprName {id, ..}) if id == OPEN_FUNC_NAME) { + if matches!(func.as_ref(), Expr::Name(ast::ExprName {id, ..}) if id == OPEN_FUNC_NAME) { // Return the "open mode" parameter and keywords. return (args.get(1), keywords.clone()); } @@ -178,15 +179,15 @@ pub(crate) fn redundant_open_modes(checker: &mut Checker, expr: &Expr) { let (mode_param, keywords): (Option<&Expr>, Vec) = match_open(expr); if mode_param.is_none() && !keywords.is_empty() { if let Some(keyword) = find_keyword(&keywords, MODE_KEYWORD_ARGUMENT) { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(mode_param_value), .. - }) = &keyword.node.value.node + }) = &keyword.value { if let Ok(mode) = OpenMode::from_str(mode_param_value.as_str()) { checker.diagnostics.push(create_check( expr, - &keyword.node.value, + &keyword.value, mode.replacement_value(), checker.locator, checker.patch(Rule::RedundantOpenModes), @@ -195,10 +196,10 @@ pub(crate) fn redundant_open_modes(checker: &mut Checker, expr: &Expr) { } } } else if let Some(mode_param) = mode_param { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(mode_param_value), .. - }) = &mode_param.node + }) = &mode_param { if let Ok(mode) = OpenMode::from_str(mode_param_value.as_str()) { checker.diagnostics.push(create_check( diff --git a/crates/ruff/src/rules/pyupgrade/rules/replace_stdout_stderr.rs b/crates/ruff/src/rules/pyupgrade/rules/replace_stdout_stderr.rs index 3a5c4a737c..2c0c42e956 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/replace_stdout_stderr.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/replace_stdout_stderr.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use rustpython_parser::ast::{Expr, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -78,13 +78,13 @@ pub(crate) fn replace_stdout_stderr( // Verify that they're both set to `subprocess.PIPE`. if !checker .ctx - .resolve_call_path(&stdout.node.value) + .resolve_call_path(&stdout.value) .map_or(false, |call_path| { call_path.as_slice() == ["subprocess", "PIPE"] }) || !checker .ctx - .resolve_call_path(&stderr.node.value) + .resolve_call_path(&stderr.value) .map_or(false, |call_path| { call_path.as_slice() == ["subprocess", "PIPE"] }) diff --git a/crates/ruff/src/rules/pyupgrade/rules/replace_universal_newlines.rs b/crates/ruff/src/rules/pyupgrade/rules/replace_universal_newlines.rs index 3fe0913a83..7df30f8b62 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/replace_universal_newlines.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/replace_universal_newlines.rs @@ -1,5 +1,5 @@ use ruff_text_size::{TextLen, TextRange}; -use rustpython_parser::ast::{Expr, Keyword}; +use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs b/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs index 907b792300..9d3fb07fb0 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, ArgData, Expr, ExprKind, StmtKind}; +use rustpython_parser::ast::{self, Arg, Expr, Ranged, Stmt}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -24,7 +24,7 @@ impl AlwaysAutofixableViolation for SuperCallWithParameters { /// Returns `true` if a call is an argumented `super` invocation. fn is_super_call_with_arguments(func: &Expr, args: &[Expr]) -> bool { - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { + if let Expr::Name(ast::ExprName { id, .. }) = func { id == "super" && !args.is_empty() } else { false @@ -60,38 +60,36 @@ pub(crate) fn super_call_with_parameters( }; // Find the enclosing function definition (if any). - let Some(StmtKind::FunctionDef(ast::StmtFunctionDef { + let Some(Stmt::FunctionDef(ast::StmtFunctionDef { args: parent_args, .. })) = parents - .find(|stmt| matches!(stmt.node, StmtKind::FunctionDef ( _))) - .map(|stmt| &stmt.node) else { + .find(|stmt| stmt.is_function_def_stmt()) else { return; }; // Extract the name of the first argument to the enclosing function. - let Some(ArgData { + let Some(Arg { arg: parent_arg, .. - }) = parent_args.args.first().map(|expr| &expr.node) else { + }) = parent_args.args.first() else { return; }; // Find the enclosing class definition (if any). - let Some(StmtKind::ClassDef(ast::StmtClassDef { + let Some(Stmt::ClassDef(ast::StmtClassDef { name: parent_name, .. })) = parents - .find(|stmt| matches!(stmt.node, StmtKind::ClassDef (_))) - .map(|stmt| &stmt.node) else { + .find(|stmt| matches!(stmt, Stmt::ClassDef (_))) else { return; }; let ( - ExprKind::Name(ast::ExprName { + Expr::Name(ast::ExprName { id: first_arg_id, .. }), - ExprKind::Name(ast::ExprName { + Expr::Name(ast::ExprName { id: second_arg_id, .. }), - ) = (&first_arg.node, &second_arg.node) else { + ) = (first_arg, second_arg) else { return; }; diff --git a/crates/ruff/src/rules/pyupgrade/rules/type_of_primitive.rs b/crates/ruff/src/rules/pyupgrade/rules/type_of_primitive.rs index 25601270d1..9c80dd5579 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/type_of_primitive.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/type_of_primitive.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -38,7 +38,7 @@ pub(crate) fn type_of_primitive(checker: &mut Checker, expr: &Expr, func: &Expr, { return; } - let ExprKind::Constant(ast::ExprConstant { value, .. } )= &args[0].node else { + let Expr::Constant(ast::ExprConstant { value, .. } )= &args[0] else { return; }; let Some(primitive) = Primitive::from_constant(value) else { diff --git a/crates/ruff/src/rules/pyupgrade/rules/typing_text_str_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/typing_text_str_alias.rs index 1f47507aab..dd165ca1c6 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/typing_text_str_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/typing_text_str_alias.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pyupgrade/rules/unicode_kind_prefix.rs b/crates/ruff/src/rules/pyupgrade/rules/unicode_kind_prefix.rs index 4d14c743b3..45dbf962d5 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unicode_kind_prefix.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unicode_kind_prefix.rs @@ -1,5 +1,5 @@ use ruff_text_size::{TextRange, TextSize}; -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs index 6c2f1af90d..2f037a1116 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs @@ -1,6 +1,6 @@ use itertools::Itertools; use log::error; -use rustpython_parser::ast::{Alias, AliasData, Attributed, Stmt}; +use rustpython_parser::ast::{Alias, Ranged, Stmt}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -69,7 +69,7 @@ pub(crate) fn unnecessary_builtin_import( checker: &mut Checker, stmt: &Stmt, module: &str, - names: &[Attributed], + names: &[Alias], ) { let deprecated_names = match module { "builtins" => BUILTINS, @@ -82,10 +82,10 @@ pub(crate) fn unnecessary_builtin_import( let mut unused_imports: Vec<&Alias> = vec![]; for alias in names { - if alias.node.asname.is_some() { + if alias.asname.is_some() { continue; } - if deprecated_names.contains(&alias.node.name.as_str()) { + if deprecated_names.contains(&alias.name.as_str()) { unused_imports.push(alias); } } @@ -97,7 +97,7 @@ pub(crate) fn unnecessary_builtin_import( UnnecessaryBuiltinImport { names: unused_imports .iter() - .map(|alias| alias.node.name.to_string()) + .map(|alias| alias.name.to_string()) .sorted() .collect(), }, @@ -110,7 +110,7 @@ pub(crate) fn unnecessary_builtin_import( let defined_in = checker.ctx.stmt_parent(); let unused_imports: Vec = unused_imports .iter() - .map(|alias| format!("{module}.{}", alias.node.name)) + .map(|alias| format!("{module}.{}", alias.name)) .collect(); match autofix::actions::remove_unused_imports( unused_imports.iter().map(String::as_str), diff --git a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs index d777504ec1..9d304c3e04 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged}; use rustpython_parser::{lexer, Mode, Tok}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; @@ -38,11 +38,11 @@ impl AlwaysAutofixableViolation for UnnecessaryEncodeUTF8 { const UTF8_LITERALS: &[&str] = &["utf-8", "utf8", "utf_8", "u8", "utf", "cp65001"]; fn match_encoded_variable(func: &Expr) -> Option<&Expr> { - let ExprKind::Attribute(ast::ExprAttribute { + let Expr::Attribute(ast::ExprAttribute { value: variable, attr, .. - }) = &func.node else { + }) = func else { return None; }; if attr != "encode" { @@ -52,10 +52,10 @@ fn match_encoded_variable(func: &Expr) -> Option<&Expr> { } fn is_utf8_encoding_arg(arg: &Expr) -> bool { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(value), .. - }) = &arg.node + }) = &arg { UTF8_LITERALS.contains(&value.to_lowercase().as_str()) } else { @@ -89,13 +89,8 @@ fn match_encoding_arg<'a>(args: &'a [Expr], kwargs: &'a [Keyword]) -> Option { let kwarg = &kwargs[0]; - if kwarg - .node - .arg - .as_ref() - .map_or(false, |arg| arg == "encoding") - { - if is_utf8_encoding_arg(&kwarg.node.value) { + if kwarg.arg.as_ref().map_or(false, |arg| arg == "encoding") { + if is_utf8_encoding_arg(&kwarg.value) { return Some(EncodingArg::Keyword(kwarg)); } } @@ -144,8 +139,8 @@ pub(crate) fn unnecessary_encode_utf8( let Some(variable) = match_encoded_variable(func) else { return; }; - match &variable.node { - ExprKind::Constant(ast::ExprConstant { + match variable { + Expr::Constant(ast::ExprConstant { value: Constant::Str(literal), .. }) => { @@ -212,7 +207,7 @@ pub(crate) fn unnecessary_encode_utf8( } } // Ex) `f"foo{bar}".encode("utf-8")` - ExprKind::JoinedStr(_) => { + Expr::JoinedStr(_) => { if let Some(encoding_arg) = match_encoding_arg(args, kwargs) { if let EncodingArg::Keyword(kwarg) = encoding_arg { // Ex) Convert `f"unicode text©".encode(encoding="utf-8")` to diff --git a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs index 2915abc688..7924b55b16 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs @@ -1,6 +1,6 @@ use itertools::Itertools; use log::error; -use rustpython_parser::ast::{Alias, AliasData, Attributed, Stmt}; +use rustpython_parser::ast::{Alias, Ranged, Stmt}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -57,18 +57,14 @@ const PY37_PLUS_REMOVE_FUTURES: &[&str] = &[ ]; /// UP010 -pub(crate) fn unnecessary_future_import( - checker: &mut Checker, - stmt: &Stmt, - names: &[Attributed], -) { +pub(crate) fn unnecessary_future_import(checker: &mut Checker, stmt: &Stmt, names: &[Alias]) { let mut unused_imports: Vec<&Alias> = vec![]; for alias in names { - if alias.node.asname.is_some() { + if alias.asname.is_some() { continue; } - if PY33_PLUS_REMOVE_FUTURES.contains(&alias.node.name.as_str()) - || PY37_PLUS_REMOVE_FUTURES.contains(&alias.node.name.as_str()) + if PY33_PLUS_REMOVE_FUTURES.contains(&alias.name.as_str()) + || PY37_PLUS_REMOVE_FUTURES.contains(&alias.name.as_str()) { unused_imports.push(alias); } @@ -81,7 +77,7 @@ pub(crate) fn unnecessary_future_import( UnnecessaryFutureImport { names: unused_imports .iter() - .map(|alias| alias.node.name.to_string()) + .map(|alias| alias.name.to_string()) .sorted() .collect(), }, @@ -94,7 +90,7 @@ pub(crate) fn unnecessary_future_import( let defined_in = checker.ctx.stmt_parent(); let unused_imports: Vec = unused_imports .iter() - .map(|alias| format!("__future__.{}", alias.node.name)) + .map(|alias| format!("__future__.{}", alias.name)) .collect(); match autofix::actions::remove_unused_imports( unused_imports.iter().map(String::as_str), diff --git a/crates/ruff/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs b/crates/ruff/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs index 99df775412..3ff0a14ffb 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -20,53 +20,63 @@ impl AlwaysAutofixableViolation for UnpackedListComprehension { } } -/// Returns `true` if `expr` contains an `ExprKind::Await`. +/// Returns `true` if `expr` contains an `Expr::Await`. fn contains_await(expr: &Expr) -> bool { - match &expr.node { - ExprKind::Await(_) => true, - ExprKind::BoolOp(ast::ExprBoolOp { values, .. }) => values.iter().any(contains_await), - ExprKind::NamedExpr(ast::ExprNamedExpr { target, value }) => { - contains_await(target) || contains_await(value) - } - ExprKind::BinOp(ast::ExprBinOp { left, right, .. }) => { + match expr { + Expr::Await(_) => true, + Expr::BoolOp(ast::ExprBoolOp { values, .. }) => values.iter().any(contains_await), + Expr::NamedExpr(ast::ExprNamedExpr { + target, + value, + range: _, + }) => contains_await(target) || contains_await(value), + Expr::BinOp(ast::ExprBinOp { left, right, .. }) => { contains_await(left) || contains_await(right) } - ExprKind::UnaryOp(ast::ExprUnaryOp { operand, .. }) => contains_await(operand), - ExprKind::Lambda(ast::ExprLambda { body, .. }) => contains_await(body), - ExprKind::IfExp(ast::ExprIfExp { test, body, orelse }) => { - contains_await(test) || contains_await(body) || contains_await(orelse) - } - ExprKind::Dict(ast::ExprDict { keys, values }) => keys + Expr::UnaryOp(ast::ExprUnaryOp { operand, .. }) => contains_await(operand), + Expr::Lambda(ast::ExprLambda { body, .. }) => contains_await(body), + Expr::IfExp(ast::ExprIfExp { + test, + body, + orelse, + range: _, + }) => contains_await(test) || contains_await(body) || contains_await(orelse), + Expr::Dict(ast::ExprDict { + keys, + values, + range: _, + }) => keys .iter() .flatten() .chain(values.iter()) .any(contains_await), - ExprKind::Set(ast::ExprSet { elts }) => elts.iter().any(contains_await), - ExprKind::ListComp(ast::ExprListComp { elt, .. }) => contains_await(elt), - ExprKind::SetComp(ast::ExprSetComp { elt, .. }) => contains_await(elt), - ExprKind::DictComp(ast::ExprDictComp { key, value, .. }) => { + Expr::Set(ast::ExprSet { elts, range: _ }) => elts.iter().any(contains_await), + Expr::ListComp(ast::ExprListComp { elt, .. }) => contains_await(elt), + Expr::SetComp(ast::ExprSetComp { elt, .. }) => contains_await(elt), + Expr::DictComp(ast::ExprDictComp { key, value, .. }) => { contains_await(key) || contains_await(value) } - ExprKind::GeneratorExp(ast::ExprGeneratorExp { elt, .. }) => contains_await(elt), - ExprKind::Yield(ast::ExprYield { value }) => { + Expr::GeneratorExp(ast::ExprGeneratorExp { elt, .. }) => contains_await(elt), + Expr::Yield(ast::ExprYield { value, range: _ }) => { value.as_ref().map_or(false, |value| contains_await(value)) } - ExprKind::YieldFrom(ast::ExprYieldFrom { value }) => contains_await(value), - ExprKind::Compare(ast::ExprCompare { + Expr::YieldFrom(ast::ExprYieldFrom { value, range: _ }) => contains_await(value), + Expr::Compare(ast::ExprCompare { left, comparators, .. }) => contains_await(left) || comparators.iter().any(contains_await), - ExprKind::Call(ast::ExprCall { + Expr::Call(ast::ExprCall { func, args, keywords, + range: _, }) => { contains_await(func) || args.iter().any(contains_await) || keywords .iter() - .any(|keyword| contains_await(&keyword.node.value)) + .any(|keyword| contains_await(&keyword.value)) } - ExprKind::FormattedValue(ast::ExprFormattedValue { + Expr::FormattedValue(ast::ExprFormattedValue { value, format_spec, .. }) => { contains_await(value) @@ -74,17 +84,24 @@ fn contains_await(expr: &Expr) -> bool { .as_ref() .map_or(false, |value| contains_await(value)) } - ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => values.iter().any(contains_await), - ExprKind::Constant(_) => false, - ExprKind::Attribute(ast::ExprAttribute { value, .. }) => contains_await(value), - ExprKind::Subscript(ast::ExprSubscript { value, slice, .. }) => { + Expr::JoinedStr(ast::ExprJoinedStr { values, range: _ }) => { + values.iter().any(contains_await) + } + Expr::Constant(_) => false, + Expr::Attribute(ast::ExprAttribute { value, .. }) => contains_await(value), + Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => { contains_await(value) || contains_await(slice) } - ExprKind::Starred(ast::ExprStarred { value, .. }) => contains_await(value), - ExprKind::Name(_) => false, - ExprKind::List(ast::ExprList { elts, .. }) => elts.iter().any(contains_await), - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => elts.iter().any(contains_await), - ExprKind::Slice(ast::ExprSlice { lower, upper, step }) => { + Expr::Starred(ast::ExprStarred { value, .. }) => contains_await(value), + Expr::Name(_) => false, + Expr::List(ast::ExprList { elts, .. }) => elts.iter().any(contains_await), + Expr::Tuple(ast::ExprTuple { elts, .. }) => elts.iter().any(contains_await), + Expr::Slice(ast::ExprSlice { + lower, + upper, + step, + range: _, + }) => { lower.as_ref().map_or(false, |value| contains_await(value)) || upper.as_ref().map_or(false, |value| contains_await(value)) || step.as_ref().map_or(false, |value| contains_await(value)) @@ -97,8 +114,13 @@ pub(crate) fn unpacked_list_comprehension(checker: &mut Checker, targets: &[Expr let Some(target) = targets.get(0) else { return; }; - if let ExprKind::Tuple(_) = target.node { - if let ExprKind::ListComp(ast::ExprListComp { elt, generators }) = &value.node { + if let Expr::Tuple(_) = target { + if let Expr::ListComp(ast::ExprListComp { + elt, + generators, + range: _, + }) = value + { if generators.iter().any(|generator| generator.is_async) || contains_await(elt) { return; } diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs index 61c89111d8..b216e11e1e 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::Expr; +use rustpython_parser::ast::{Expr, Ranged}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs index e07e7080d2..bc49f03769 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs @@ -1,5 +1,5 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Operator}; +use rustpython_parser::ast::{self, Constant, Expr, Operator, Ranged}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -26,34 +26,28 @@ impl Violation for NonPEP604Annotation { } fn optional(expr: &Expr) -> Expr { - Expr::new( - TextRange::default(), - ast::ExprBinOp { - left: Box::new(expr.clone()), - op: Operator::BitOr, - right: Box::new(Expr::new( - TextRange::default(), - ast::ExprConstant { - value: Constant::None, - kind: None, - }, - )), - }, - ) + Expr::BinOp(ast::ExprBinOp { + left: Box::new(expr.clone()), + op: Operator::BitOr, + right: Box::new(Expr::Constant(ast::ExprConstant { + value: Constant::None, + kind: None, + range: TextRange::default(), + })), + range: TextRange::default(), + }) } fn union(elts: &[Expr]) -> Expr { if elts.len() == 1 { elts[0].clone() } else { - Expr::new( - TextRange::default(), - ast::ExprBinOp { - left: Box::new(union(&elts[..elts.len() - 1])), - op: Operator::BitOr, - right: Box::new(elts[elts.len() - 1].clone()), - }, - ) + Expr::BinOp(ast::ExprBinOp { + left: Box::new(union(&elts[..elts.len() - 1])), + op: Operator::BitOr, + right: Box::new(elts[elts.len() - 1].clone()), + range: TextRange::default(), + }) } } @@ -82,11 +76,11 @@ pub(crate) fn use_pep604_annotation( Pep604Operator::Union => { let mut diagnostic = Diagnostic::new(NonPEP604Annotation, expr.range()); if fixable && checker.patch(diagnostic.kind.rule()) { - match &slice.node { - ExprKind::Slice(_) => { + match slice { + Expr::Slice(_) => { // Invalid type annotation. } - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + Expr::Tuple(ast::ExprTuple { elts, .. }) => { #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( unparse_expr(&union(elts), checker.stylist), diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_isinstance.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_isinstance.rs index 1950fcfb45..fd761afa79 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_isinstance.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_isinstance.rs @@ -1,7 +1,7 @@ use ruff_text_size::TextRange; use std::fmt; -use rustpython_parser::ast::{self, Expr, ExprKind, Operator}; +use rustpython_parser::ast::{self, Expr, Operator, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -55,14 +55,12 @@ fn union(elts: &[Expr]) -> Expr { if elts.len() == 1 { elts[0].clone() } else { - Expr::new( - TextRange::default(), - ast::ExprBinOp { - left: Box::new(union(&elts[..elts.len() - 1])), - op: Operator::BitOr, - right: Box::new(elts[elts.len() - 1].clone()), - }, - ) + Expr::BinOp(ast::ExprBinOp { + left: Box::new(union(&elts[..elts.len() - 1])), + op: Operator::BitOr, + right: Box::new(elts[elts.len() - 1].clone()), + range: TextRange::default(), + }) } } @@ -73,7 +71,7 @@ pub(crate) fn use_pep604_isinstance( func: &Expr, args: &[Expr], ) { - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { + if let Expr::Name(ast::ExprName { id, .. }) = func { let Some(kind) = CallKind::from_name(id) else { return; }; @@ -81,17 +79,14 @@ pub(crate) fn use_pep604_isinstance( return; }; if let Some(types) = args.get(1) { - if let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &types.node { + if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &types { // Ex) `()` if elts.is_empty() { return; } // Ex) `(*args,)` - if elts - .iter() - .any(|elt| matches!(elt.node, ExprKind::Starred(_))) - { + if elts.iter().any(|elt| matches!(elt, Expr::Starred(_))) { return; } diff --git a/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs b/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs index 1167c8f2d7..0bfdca15c6 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs @@ -1,6 +1,6 @@ use log::error; use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Expr, ExprKind, Stmt}; +use rustpython_parser::ast::{self, Expr, Ranged, Stmt}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -28,13 +28,13 @@ fn rule(targets: &[Expr], value: &Expr, location: TextRange) -> Option Option { for expr in bases { - let ExprKind::Name(ast::ExprName { id, .. }) = &expr.node else { + let Expr::Name(ast::ExprName { id, .. }) = expr else { continue; }; if id != "object" { diff --git a/crates/ruff/src/rules/pyupgrade/rules/yield_in_for_loop.rs b/crates/ruff/src/rules/pyupgrade/rules/yield_in_for_loop.rs index 15d342fe48..999df0fd04 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/yield_in_for_loop.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/yield_in_for_loop.rs @@ -1,5 +1,5 @@ use rustc_hash::FxHashMap; -use rustpython_parser::ast::{self, Expr, ExprContext, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Expr, ExprContext, Ranged, Stmt}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -28,14 +28,13 @@ impl AlwaysAutofixableViolation for YieldInForLoop { /// Return `true` if the two expressions are equivalent, and consistent solely /// of tuples and names. fn is_same_expr(a: &Expr, b: &Expr) -> bool { - match (&a.node, &b.node) { + match (&a, &b) { + (Expr::Name(ast::ExprName { id: a, .. }), Expr::Name(ast::ExprName { id: b, .. })) => { + a == b + } ( - ExprKind::Name(ast::ExprName { id: a, .. }), - ExprKind::Name(ast::ExprName { id: b, .. }), - ) => a == b, - ( - ExprKind::Tuple(ast::ExprTuple { elts: a, .. }), - ExprKind::Tuple(ast::ExprTuple { elts: b, .. }), + Expr::Tuple(ast::ExprTuple { elts: a, .. }), + Expr::Tuple(ast::ExprTuple { elts: b, .. }), ) => a.len() == b.len() && a.iter().zip(b).all(|(a, b)| is_same_expr(a, b)), _ => false, } @@ -44,12 +43,10 @@ fn is_same_expr(a: &Expr, b: &Expr) -> bool { /// Collect all named variables in an expression consisting solely of tuples and /// names. fn collect_names(expr: &Expr) -> Vec<&str> { - match &expr.node { - ExprKind::Name(ast::ExprName { id, .. }) => vec![id], - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { - elts.iter().flat_map(collect_names).collect() - } - _ => panic!("Expected: ExprKind::Name | ExprKind::Tuple"), + match expr { + Expr::Name(ast::ExprName { id, .. }) => vec![id], + Expr::Tuple(ast::ExprTuple { elts, .. }) => elts.iter().flat_map(collect_names).collect(), + _ => panic!("Expected: Expr::Name | Expr::Tuple"), } } @@ -68,8 +65,8 @@ struct YieldFromVisitor<'a> { impl<'a> StatementVisitor<'a> for YieldFromVisitor<'a> { fn visit_stmt(&mut self, stmt: &'a Stmt) { - match &stmt.node { - StmtKind::For(ast::StmtFor { + match stmt { + Stmt::For(ast::StmtFor { target, body, orelse, @@ -86,8 +83,12 @@ impl<'a> StatementVisitor<'a> for YieldFromVisitor<'a> { } // If the body is not a yield, don't rewrite. let body = &body[0]; - if let StmtKind::Expr(ast::StmtExpr { value }) = &body.node { - if let ExprKind::Yield(ast::ExprYield { value: Some(value) }) = &value.node { + if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = &body { + if let Expr::Yield(ast::ExprYield { + value: Some(value), + range: _, + }) = value.as_ref() + { if is_same_expr(target, value) { self.yields.push(YieldFrom { stmt, @@ -99,7 +100,7 @@ impl<'a> StatementVisitor<'a> for YieldFromVisitor<'a> { } } } - StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_) | StmtKind::ClassDef(_) => { + Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) | Stmt::ClassDef(_) => { // Don't recurse into anything that defines a new scope. } _ => statement_visitor::walk_stmt(self, stmt), @@ -122,8 +123,8 @@ impl<'a> Visitor<'a> for ReferenceVisitor<'a> { } fn visit_expr(&mut self, expr: &'a Expr) { - match &expr.node { - ExprKind::Name(ast::ExprName { id, ctx }) => { + match expr { + Expr::Name(ast::ExprName { id, ctx, range: _ }) => { if matches!(ctx, ExprContext::Load | ExprContext::Del) { if let Some(parent) = self.parent { self.references @@ -141,7 +142,7 @@ impl<'a> Visitor<'a> for ReferenceVisitor<'a> { /// UP028 pub(crate) fn yield_in_for_loop(checker: &mut Checker, stmt: &Stmt) { // Intentionally omit async functions. - if let StmtKind::FunctionDef(ast::StmtFunctionDef { body, .. }) = &stmt.node { + if let Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) = stmt { let yields = { let mut visitor = YieldFromVisitor::default(); visitor.visit_body(body); diff --git a/crates/ruff/src/rules/ruff/rules/asyncio_dangling_task.rs b/crates/ruff/src/rules/ruff/rules/asyncio_dangling_task.rs index b4831a5336..1171926ee3 100644 --- a/crates/ruff/src/rules/ruff/rules/asyncio_dangling_task.rs +++ b/crates/ruff/src/rules/ruff/rules/asyncio_dangling_task.rs @@ -1,6 +1,6 @@ use std::fmt; -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -85,7 +85,7 @@ pub(crate) fn asyncio_dangling_task<'a, F>( where F: FnOnce(&'a Expr) -> Option>, { - if let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node { + if let Expr::Call(ast::ExprCall { func, .. }) = expr { match resolve_call_path(func).as_deref() { Some(["asyncio", "create_task"]) => Some(Diagnostic::new( AsyncioDanglingTask { diff --git a/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs b/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs index 9fcd7aec5b..e5f6527c11 100644 --- a/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs +++ b/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs @@ -1,8 +1,9 @@ -use rustpython_parser::ast::{self, Expr, ExprContext, ExprKind, Operator}; +use ruff_text_size::TextRange; +use rustpython_parser::ast::{self, Expr, ExprContext, Operator, Ranged}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{create_expr, has_comments, unparse_expr}; +use ruff_python_ast::helpers::{has_comments, unparse_expr}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -33,10 +34,12 @@ fn make_splat_elts( splat_at_left: bool, ) -> Vec { let mut new_elts = other_elements.to_owned(); - let splat = create_expr(ast::ExprStarred { + let node = ast::ExprStarred { value: Box::from(splat_element.clone()), ctx: ExprContext::Load, - }); + range: TextRange::default(), + }; + let splat = node.into(); if splat_at_left { new_elts.insert(0, splat); } else { @@ -55,46 +58,74 @@ enum Kind { /// This suggestion could be unsafe if the non-literal expression in the /// expression has overridden the `__add__` (or `__radd__`) magic methods. pub(crate) fn collection_literal_concatenation(checker: &mut Checker, expr: &Expr) { - let ExprKind::BinOp(ast::ExprBinOp { left, op: Operator::Add, right }) = &expr.node else { + let Expr::BinOp(ast::ExprBinOp { left, op: Operator::Add, right, range: _ }) = expr else { return; }; // Figure out which way the splat is, and what the kind of the collection is. - let (kind, splat_element, other_elements, splat_at_left, ctx) = match (&left.node, &right.node) - { - (ExprKind::List(ast::ExprList { elts: l_elts, ctx }), _) => { - (Kind::List, right, l_elts, false, ctx) - } - (ExprKind::Tuple(ast::ExprTuple { elts: l_elts, ctx }), _) => { - (Kind::Tuple, right, l_elts, false, ctx) - } - (_, ExprKind::List(ast::ExprList { elts: r_elts, ctx })) => { - (Kind::List, left, r_elts, true, ctx) - } - (_, ExprKind::Tuple(ast::ExprTuple { elts: r_elts, ctx })) => { - (Kind::Tuple, left, r_elts, true, ctx) - } - _ => return, - }; + let (kind, splat_element, other_elements, splat_at_left, ctx) = + match (left.as_ref(), right.as_ref()) { + ( + Expr::List(ast::ExprList { + elts: l_elts, + ctx, + range: _, + }), + _, + ) => (Kind::List, right, l_elts, false, ctx), + ( + Expr::Tuple(ast::ExprTuple { + elts: l_elts, + ctx, + range: _, + }), + _, + ) => (Kind::Tuple, right, l_elts, false, ctx), + ( + _, + Expr::List(ast::ExprList { + elts: r_elts, + ctx, + range: _, + }), + ) => (Kind::List, left, r_elts, true, ctx), + ( + _, + Expr::Tuple(ast::ExprTuple { + elts: r_elts, + ctx, + range: _, + }), + ) => (Kind::Tuple, left, r_elts, true, ctx), + _ => return, + }; // We'll be a bit conservative here; only calls, names and attribute accesses // will be considered as splat elements. - if !matches!( - splat_element.node, - ExprKind::Call(_) | ExprKind::Name(_) | ExprKind::Attribute(_) - ) { + if !(splat_element.is_call_expr() + || splat_element.is_name_expr() + || splat_element.is_attribute_expr()) + { return; } let new_expr = match kind { - Kind::List => create_expr(ast::ExprList { - elts: make_splat_elts(splat_element, other_elements, splat_at_left), - ctx: ctx.clone(), - }), - Kind::Tuple => create_expr(ast::ExprTuple { - elts: make_splat_elts(splat_element, other_elements, splat_at_left), - ctx: ctx.clone(), - }), + Kind::List => { + let node = ast::ExprList { + elts: make_splat_elts(splat_element, other_elements, splat_at_left), + ctx: *ctx, + range: TextRange::default(), + }; + node.into() + } + Kind::Tuple => { + let node = ast::ExprTuple { + elts: make_splat_elts(splat_element, other_elements, splat_at_left), + ctx: *ctx, + range: TextRange::default(), + }; + node.into() + } }; let contents = match kind { diff --git a/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs b/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs index 1981e27008..ef5798ba6d 100644 --- a/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs +++ b/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -50,11 +50,12 @@ pub(crate) fn explicit_f_string_type_conversion( return; } - let ExprKind::Call(ast::ExprCall { + let Expr::Call(ast::ExprCall { func, args, keywords, - }) = &formatted_value.node else { + range: _, + }) = formatted_value else { return; }; @@ -63,7 +64,7 @@ pub(crate) fn explicit_f_string_type_conversion( return; } - let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else { + let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() else { return; }; diff --git a/crates/ruff/src/rules/ruff/rules/mutable_defaults_in_dataclass_fields.rs b/crates/ruff/src/rules/ruff/rules/mutable_defaults_in_dataclass_fields.rs index eb2dfb3f84..f478b3e38e 100644 --- a/crates/ruff/src/rules/ruff/rules/mutable_defaults_in_dataclass_fields.rs +++ b/crates/ruff/src/rules/ruff/rules/mutable_defaults_in_dataclass_fields.rs @@ -1,5 +1,5 @@ use ruff_python_ast::call_path::{from_qualified_name, CallPath}; -use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -150,13 +150,13 @@ impl Violation for FunctionCallInDataclassDefaultArgument { fn is_mutable_expr(expr: &Expr) -> bool { matches!( - &expr.node, - ExprKind::List(_) - | ExprKind::Dict(_) - | ExprKind::Set(_) - | ExprKind::ListComp(_) - | ExprKind::DictComp(_) - | ExprKind::SetComp(_) + expr, + Expr::List(_) + | Expr::Dict(_) + | Expr::Set(_) + | Expr::ListComp(_) + | Expr::DictComp(_) + | Expr::SetComp(_) ) } @@ -172,7 +172,7 @@ fn is_allowed_dataclass_function(context: &Context, func: &Expr) -> bool { /// Returns `true` if the given [`Expr`] is a `typing.ClassVar` annotation. fn is_class_var_annotation(context: &Context, annotation: &Expr) -> bool { - let ExprKind::Subscript(ast::ExprSubscript { value, .. }) = &annotation.node else { + let Expr::Subscript(ast::ExprSubscript { value, .. }) = &annotation else { return false; }; context.match_typing_expr(value, "ClassVar") @@ -189,16 +189,16 @@ pub(crate) fn function_call_in_dataclass_defaults(checker: &mut Checker, body: & .collect(); for statement in body { - if let StmtKind::AnnAssign(ast::StmtAnnAssign { + if let Stmt::AnnAssign(ast::StmtAnnAssign { annotation, value: Some(expr), .. - }) = &statement.node + }) = statement { if is_class_var_annotation(&checker.ctx, annotation) { continue; } - if let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node { + if let Expr::Call(ast::ExprCall { func, .. }) = expr.as_ref() { if !is_immutable_func(&checker.ctx, func, &extend_immutable_calls) && !is_allowed_dataclass_function(&checker.ctx, func) { @@ -217,8 +217,8 @@ pub(crate) fn function_call_in_dataclass_defaults(checker: &mut Checker, body: & /// RUF008 pub(crate) fn mutable_dataclass_default(checker: &mut Checker, body: &[Stmt]) { for statement in body { - match &statement.node { - StmtKind::AnnAssign(ast::StmtAnnAssign { + match statement { + Stmt::AnnAssign(ast::StmtAnnAssign { annotation, value: Some(value), .. @@ -232,7 +232,7 @@ pub(crate) fn mutable_dataclass_default(checker: &mut Checker, body: &[Stmt]) { .push(Diagnostic::new(MutableDataclassDefault, value.range())); } } - StmtKind::Assign(ast::StmtAssign { value, .. }) => { + Stmt::Assign(ast::StmtAssign { value, .. }) => { if is_mutable_expr(value) { checker .diagnostics diff --git a/crates/ruff/src/rules/ruff/rules/pairwise_over_zipped.rs b/crates/ruff/src/rules/ruff/rules/pairwise_over_zipped.rs index 61e2290157..d7f7219d58 100644 --- a/crates/ruff/src/rules/ruff/rules/pairwise_over_zipped.rs +++ b/crates/ruff/src/rules/ruff/rules/pairwise_over_zipped.rs @@ -1,5 +1,5 @@ use num_traits::ToPrimitive; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Unaryop}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged, Unaryop}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -33,15 +33,15 @@ impl SliceInfo { /// Return the argument name, lower bound, and upper bound for an expression, if it's a slice. fn match_slice_info(expr: &Expr) -> Option { - let ExprKind::Subscript(ast::ExprSubscript { value, slice, .. }) = &expr.node else { + let Expr::Subscript(ast::ExprSubscript { value, slice, .. }) = expr else { return None; }; - let ExprKind::Name(ast::ExprName { id: arg_id, .. }) = &value.node else { + let Expr::Name(ast::ExprName { id: arg_id, .. }) = value.as_ref() else { return None; }; - let ExprKind::Slice(ast::ExprSlice { lower, step, .. }) = &slice.node else { + let Expr::Slice(ast::ExprSlice { lower, step, .. }) = slice.as_ref() else { return None; }; @@ -63,19 +63,20 @@ fn match_slice_info(expr: &Expr) -> Option { } fn to_bound(expr: &Expr) -> Option { - match &expr.node { - ExprKind::Constant(ast::ExprConstant { + match expr { + Expr::Constant(ast::ExprConstant { value: Constant::Int(value), .. }) => value.to_i64(), - ExprKind::UnaryOp(ast::ExprUnaryOp { + Expr::UnaryOp(ast::ExprUnaryOp { op: Unaryop::USub | Unaryop::Invert, operand, + range: _, }) => { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Int(value), .. - }) = &operand.node + }) = operand.as_ref() { value.to_i64().map(|v| -v) } else { @@ -88,7 +89,7 @@ fn to_bound(expr: &Expr) -> Option { /// RUF007 pub(crate) fn pairwise_over_zipped(checker: &mut Checker, func: &Expr, args: &[Expr]) { - let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else { + let Expr::Name(ast::ExprName { id, .. }) = func else { return; }; @@ -107,7 +108,7 @@ pub(crate) fn pairwise_over_zipped(checker: &mut Checker, func: &Expr, args: &[E // Allow the first argument to be a `Name` or `Subscript`. let Some(first_arg_info) = ({ - if let ExprKind::Name(ast::ExprName { id, .. }) = &args[0].node { + if let Expr::Name(ast::ExprName { id, .. }) = &args[0] { Some(SliceInfo::new(id.to_string(), None)) } else { match_slice_info(&args[0]) @@ -117,7 +118,7 @@ pub(crate) fn pairwise_over_zipped(checker: &mut Checker, func: &Expr, args: &[E }; // Require second argument to be a `Subscript`. - let ExprKind::Subscript (_) = &args[1].node else { + let Expr::Subscript (_) = &args[1] else { return; }; let Some(second_arg_info) = match_slice_info(&args[1]) else { diff --git a/crates/ruff/src/rules/tryceratops/helpers.rs b/crates/ruff/src/rules/tryceratops/helpers.rs index 72954fd9e3..adc856e1ec 100644 --- a/crates/ruff/src/rules/tryceratops/helpers.rs +++ b/crates/ruff/src/rules/tryceratops/helpers.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr}; use ruff_python_ast::visitor; use ruff_python_ast::visitor::Visitor; @@ -25,7 +25,7 @@ where 'b: 'a, { fn visit_expr(&mut self, expr: &'b Expr) { - if let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node { + if let Expr::Call(ast::ExprCall { func, .. }) = expr { if logging::is_logger_candidate(self.context, func) { self.calls.push((expr, func)); } diff --git a/crates/ruff/src/rules/tryceratops/rules/error_instead_of_exception.rs b/crates/ruff/src/rules/tryceratops/rules/error_instead_of_exception.rs index 6bb21e2f6f..646a35ffed 100644 --- a/crates/ruff/src/rules/tryceratops/rules/error_instead_of_exception.rs +++ b/crates/ruff/src/rules/tryceratops/rules/error_instead_of_exception.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, ExprKind}; +use rustpython_parser::ast::{self, Excepthandler, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -55,15 +55,14 @@ impl Violation for ErrorInsteadOfException { /// TRY400 pub(crate) fn error_instead_of_exception(checker: &mut Checker, handlers: &[Excepthandler]) { for handler in handlers { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) = - &handler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) = handler; let calls = { let mut visitor = LoggerCandidateVisitor::new(&checker.ctx); visitor.visit_body(body); visitor.calls }; for (expr, func) in calls { - if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node { + if let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func { if attr == "error" { checker .diagnostics diff --git a/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_args.rs b/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_args.rs index 9bc7cf131b..a4ff800789 100644 --- a/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_args.rs +++ b/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_args.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind}; +use rustpython_parser::ast::{self, Constant, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -53,15 +53,15 @@ fn any_string(expr: &Expr, predicate: F) -> bool where F: (Fn(&str) -> bool) + Copy, { - match &expr.node { - ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => { + match expr { + Expr::JoinedStr(ast::ExprJoinedStr { values, range: _ }) => { for value in values { if any_string(value, predicate) { return true; } } } - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: Constant::Str(val), .. }) => { @@ -77,7 +77,7 @@ where /// TRY003 pub(crate) fn raise_vanilla_args(checker: &mut Checker, expr: &Expr) { - if let ExprKind::Call(ast::ExprCall { args, .. }) = &expr.node { + if let Expr::Call(ast::ExprCall { args, .. }) = expr { if let Some(arg) = args.first() { if any_string(arg, |part| part.chars().any(char::is_whitespace)) { checker diff --git a/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_class.rs b/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_class.rs index 319e38d850..163bb03203 100644 --- a/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_class.rs +++ b/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_class.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -64,13 +64,11 @@ impl Violation for RaiseVanillaClass { pub(crate) fn raise_vanilla_class(checker: &mut Checker, expr: &Expr) { if checker .ctx - .resolve_call_path( - if let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node { - func - } else { - expr - }, - ) + .resolve_call_path(if let Expr::Call(ast::ExprCall { func, .. }) = expr { + func + } else { + expr + }) .map_or(false, |call_path| call_path.as_slice() == ["", "Exception"]) { checker diff --git a/crates/ruff/src/rules/tryceratops/rules/raise_within_try.rs b/crates/ruff/src/rules/tryceratops/rules/raise_within_try.rs index 1e58efdc98..5dcdcc117e 100644 --- a/crates/ruff/src/rules/tryceratops/rules/raise_within_try.rs +++ b/crates/ruff/src/rules/tryceratops/rules/raise_within_try.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{Excepthandler, Stmt, StmtKind}; +use rustpython_parser::ast::{Excepthandler, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -63,9 +63,9 @@ where 'b: 'a, { fn visit_stmt(&mut self, stmt: &'b Stmt) { - match stmt.node { - StmtKind::Raise(_) => self.raises.push(stmt), - StmtKind::Try(_) | StmtKind::TryStar(_) => (), + match stmt { + Stmt::Raise(_) => self.raises.push(stmt), + Stmt::Try(_) | Stmt::TryStar(_) => (), _ => walk_stmt(self, stmt), } } diff --git a/crates/ruff/src/rules/tryceratops/rules/reraise_no_cause.rs b/crates/ruff/src/rules/tryceratops/rules/reraise_no_cause.rs index 3b302b5645..259dfac223 100644 --- a/crates/ruff/src/rules/tryceratops/rules/reraise_no_cause.rs +++ b/crates/ruff/src/rules/tryceratops/rules/reraise_no_cause.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{ExprKind, Stmt}; +use rustpython_parser::ast::Stmt; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -55,9 +55,7 @@ pub(crate) fn reraise_no_cause(checker: &mut Checker, body: &[Stmt]) { }; for (range, exc, cause) in raises { - if exc.map_or(false, |expr| { - matches!(expr.node, ExprKind::Call(_)) && cause.is_none() - }) { + if exc.map_or(false, |expr| expr.is_call_expr() && cause.is_none()) { checker .diagnostics .push(Diagnostic::new(ReraiseNoCause, range)); diff --git a/crates/ruff/src/rules/tryceratops/rules/try_consider_else.rs b/crates/ruff/src/rules/tryceratops/rules/try_consider_else.rs index 205ee46bc5..77ab803bb5 100644 --- a/crates/ruff/src/rules/tryceratops/rules/try_consider_else.rs +++ b/crates/ruff/src/rules/tryceratops/rules/try_consider_else.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Excepthandler, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Excepthandler, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -64,7 +64,7 @@ pub(crate) fn try_consider_else( ) { if body.len() > 1 && orelse.is_empty() && !handler.is_empty() { if let Some(stmt) = body.last() { - if let StmtKind::Return(ast::StmtReturn { value }) = &stmt.node { + if let Stmt::Return(ast::StmtReturn { value, range: _ }) = stmt { if let Some(value) = value { if contains_effect(value, |id| checker.ctx.is_builtin(id)) { return; diff --git a/crates/ruff/src/rules/tryceratops/rules/type_check_without_type_error.rs b/crates/ruff/src/rules/tryceratops/rules/type_check_without_type_error.rs index a2590861fc..5cc964c3a4 100644 --- a/crates/ruff/src/rules/tryceratops/rules/type_check_without_type_error.rs +++ b/crates/ruff/src/rules/tryceratops/rules/type_check_without_type_error.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -55,13 +55,13 @@ where 'b: 'a, { fn visit_stmt(&mut self, stmt: &'b Stmt) { - match &stmt.node { - StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_) | StmtKind::ClassDef(_) => { + match stmt { + Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) | Stmt::ClassDef(_) => { // Don't recurse. } - StmtKind::Return(_) => self.returns.push(stmt), - StmtKind::Break => self.breaks.push(stmt), - StmtKind::Continue => self.continues.push(stmt), + Stmt::Return(_) => self.returns.push(stmt), + Stmt::Break(_) => self.breaks.push(stmt), + Stmt::Continue(_) => self.continues.push(stmt), _ => walk_stmt(self, stmt), } } @@ -88,14 +88,12 @@ fn check_type_check_call(checker: &mut Checker, call: &Expr) -> bool { /// Returns `true` if an [`Expr`] is a test to check types (e.g. via isinstance) fn check_type_check_test(checker: &mut Checker, test: &Expr) -> bool { - match &test.node { - ExprKind::BoolOp(ast::ExprBoolOp { values, .. }) => values + match test { + Expr::BoolOp(ast::ExprBoolOp { values, .. }) => values .iter() .all(|expr| check_type_check_test(checker, expr)), - ExprKind::UnaryOp(ast::ExprUnaryOp { operand, .. }) => { - check_type_check_test(checker, operand) - } - ExprKind::Call(ast::ExprCall { func, .. }) => check_type_check_call(checker, func), + Expr::UnaryOp(ast::ExprUnaryOp { operand, .. }) => check_type_check_test(checker, operand), + Expr::Call(ast::ExprCall { func, .. }) => check_type_check_call(checker, func), _ => false, } } @@ -130,10 +128,10 @@ fn is_builtin_exception(checker: &mut Checker, exc: &Expr) -> bool { /// Returns `true` if an [`Expr`] is a reference to a builtin exception. fn check_raise_type(checker: &mut Checker, exc: &Expr) -> bool { - match &exc.node { - ExprKind::Name(_) => is_builtin_exception(checker, exc), - ExprKind::Call(ast::ExprCall { func, .. }) => { - if let ExprKind::Name(_) = &func.node { + match exc { + Expr::Name(_) => is_builtin_exception(checker, exc), + Expr::Call(ast::ExprCall { func, .. }) => { + if let Expr::Name(_) = func.as_ref() { is_builtin_exception(checker, func) } else { false @@ -157,7 +155,7 @@ fn check_body(checker: &mut Checker, body: &[Stmt]) { if has_control_flow(item) { return; } - if let StmtKind::Raise(ast::StmtRaise { exc: Some(exc), .. }) = &item.node { + if let Stmt::Raise(ast::StmtRaise { exc: Some(exc), .. }) = &item { check_raise(checker, exc, item); } } @@ -169,13 +167,13 @@ fn check_orelse(checker: &mut Checker, body: &[Stmt]) { if has_control_flow(item) { return; } - match &item.node { - StmtKind::If(ast::StmtIf { test, .. }) => { + match item { + Stmt::If(ast::StmtIf { test, .. }) => { if !check_type_check_test(checker, test) { return; } } - StmtKind::Raise(ast::StmtRaise { exc: Some(exc), .. }) => { + Stmt::Raise(ast::StmtRaise { exc: Some(exc), .. }) => { check_raise(checker, exc, item); } _ => {} @@ -191,11 +189,9 @@ pub(crate) fn type_check_without_type_error( orelse: &[Stmt], parent: Option<&Stmt>, ) { - if let Some(parent) = parent { - if let StmtKind::If(ast::StmtIf { test, .. }) = &parent.node { - if !check_type_check_test(checker, test) { - return; - } + if let Some(Stmt::If(ast::StmtIf { test, .. })) = parent { + if !check_type_check_test(checker, test) { + return; } } diff --git a/crates/ruff/src/rules/tryceratops/rules/verbose_log_message.rs b/crates/ruff/src/rules/tryceratops/rules/verbose_log_message.rs index 85029374e1..660fd89f7b 100644 --- a/crates/ruff/src/rules/tryceratops/rules/verbose_log_message.rs +++ b/crates/ruff/src/rules/tryceratops/rules/verbose_log_message.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind}; +use rustpython_parser::ast::{self, Excepthandler, Expr, ExprContext, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -51,12 +51,13 @@ where 'b: 'a, { fn visit_expr(&mut self, expr: &'b Expr) { - match &expr.node { - ExprKind::Name(ast::ExprName { + match expr { + Expr::Name(ast::ExprName { id, ctx: ExprContext::Load, + range: _, }) => self.names.push((id, expr)), - ExprKind::Attribute(_) => {} + Expr::Attribute(_) => {} _ => visitor::walk_expr(self, expr), } } @@ -65,9 +66,8 @@ where /// TRY401 pub(crate) fn verbose_log_message(checker: &mut Checker, handlers: &[Excepthandler]) { for handler in handlers { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { - name, body, .. - }) = &handler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { name, body, .. }) = + handler; let Some(target) = name else { continue; }; @@ -80,10 +80,10 @@ pub(crate) fn verbose_log_message(checker: &mut Checker, handlers: &[Excepthandl }; for (expr, func) in calls { - let ExprKind::Call(ast::ExprCall { args, .. }) = &expr.node else { + let Expr::Call(ast::ExprCall { args, .. }) = expr else { continue; }; - if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node { + if let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func { if attr == "exception" { // Collect all referenced names in the `logging.exception` call. let names: Vec<(&str, &Expr)> = { diff --git a/crates/ruff/src/rules/tryceratops/rules/verbose_raise.rs b/crates/ruff/src/rules/tryceratops/rules/verbose_raise.rs index 28cd57a15b..b740212215 100644 --- a/crates/ruff/src/rules/tryceratops/rules/verbose_raise.rs +++ b/crates/ruff/src/rules/tryceratops/rules/verbose_raise.rs @@ -1,6 +1,4 @@ -use rustpython_parser::ast::{ - self, Excepthandler, ExcepthandlerKind, Expr, ExprKind, Stmt, StmtKind, -}; +use rustpython_parser::ast::{self, Excepthandler, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -52,14 +50,18 @@ where 'b: 'a, { fn visit_stmt(&mut self, stmt: &'b Stmt) { - match &stmt.node { - StmtKind::Raise(ast::StmtRaise { exc, cause }) => { + match stmt { + Stmt::Raise(ast::StmtRaise { + exc, + cause, + range: _, + }) => { self.raises.push((exc.as_deref(), cause.as_deref())); } - StmtKind::Try(ast::StmtTry { + Stmt::Try(ast::StmtTry { body, finalbody, .. }) - | StmtKind::TryStar(ast::StmtTryStar { + | Stmt::TryStar(ast::StmtTryStar { body, finalbody, .. }) => { for stmt in body.iter().chain(finalbody.iter()) { @@ -75,11 +77,11 @@ where pub(crate) fn verbose_raise(checker: &mut Checker, handlers: &[Excepthandler]) { for handler in handlers { // If the handler assigned a name to the exception... - if let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { + if let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { name: Some(exception_name), body, .. - }) = &handler.node + }) = handler { let raises = { let mut visitor = RaiseStatementVisitor::default(); @@ -92,7 +94,7 @@ pub(crate) fn verbose_raise(checker: &mut Checker, handlers: &[Excepthandler]) { } if let Some(exc) = exc { // ...and the raised object is bound to the same name... - if let ExprKind::Name(ast::ExprName { id, .. }) = &exc.node { + if let Expr::Name(ast::ExprName { id, .. }) = exc { if id == exception_name { checker .diagnostics diff --git a/crates/ruff_macros/src/map_codes.rs b/crates/ruff_macros/src/map_codes.rs index 3a9743e550..b20af08ba8 100644 --- a/crates/ruff_macros/src/map_codes.rs +++ b/crates/ruff_macros/src/map_codes.rs @@ -167,7 +167,7 @@ pub(crate) fn map_codes(func: &ItemFn) -> syn::Result { }); #[allow(clippy::type_complexity)] - let mut rule_to_codes: HashMap<&Path, Vec<(&Ident, &str, &Vec)>> = HashMap::new(); + let mut rule_to_codes: HashMap<&Path, Vec<(&Ident, &str, &[Attribute])>> = HashMap::new(); let mut linter_code_for_rule_match_arms = quote!(); for (linter, map) in &linters { diff --git a/crates/ruff_python_ast/src/all.rs b/crates/ruff_python_ast/src/all.rs index 9d0cd2d42e..29a17869f1 100644 --- a/crates/ruff_python_ast/src/all.rs +++ b/crates/ruff_python_ast/src/all.rs @@ -1,5 +1,5 @@ use bitflags::bitflags; -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Constant, Expr, Stmt}; bitflags! { #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] @@ -18,10 +18,10 @@ where { fn add_to_names<'a>(elts: &'a [Expr], names: &mut Vec<&'a str>, flags: &mut AllNamesFlags) { for elt in elts { - if let ExprKind::Constant(ast::ExprConstant { + if let Expr::Constant(ast::ExprConstant { value: Constant::Str(value), .. - }) = &elt.node + }) = elt { names.push(value); } else { @@ -30,44 +30,45 @@ where } } - fn extract_elts(expr: &Expr, is_builtin: F) -> (Option<&Vec>, AllNamesFlags) + fn extract_elts(expr: &Expr, is_builtin: F) -> (Option<&[Expr]>, AllNamesFlags) where F: Fn(&str) -> bool, { - match &expr.node { - ExprKind::List(ast::ExprList { elts, .. }) => { + match expr { + Expr::List(ast::ExprList { elts, .. }) => { return (Some(elts), AllNamesFlags::empty()); } - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + Expr::Tuple(ast::ExprTuple { elts, .. }) => { return (Some(elts), AllNamesFlags::empty()); } - ExprKind::ListComp(_) => { + Expr::ListComp(_) => { // Allow comprehensions, even though we can't statically analyze them. return (None, AllNamesFlags::empty()); } - ExprKind::Call(ast::ExprCall { + Expr::Call(ast::ExprCall { func, args, keywords, + range: _range, }) => { // Allow `tuple()` and `list()` calls. if keywords.is_empty() && args.len() <= 1 { - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { + if let Expr::Name(ast::ExprName { id, .. }) = &**func { let id = id.as_str(); if id == "tuple" || id == "list" { if is_builtin(id) { if args.is_empty() { return (None, AllNamesFlags::empty()); } - match &args[0].node { - ExprKind::List(ast::ExprList { elts, .. }) - | ExprKind::Set(ast::ExprSet { elts }) - | ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + match &args[0] { + Expr::List(ast::ExprList { elts, .. }) + | Expr::Set(ast::ExprSet { elts, .. }) + | Expr::Tuple(ast::ExprTuple { elts, .. }) => { return (Some(elts), AllNamesFlags::empty()); } - ExprKind::ListComp(_) - | ExprKind::SetComp(_) - | ExprKind::GeneratorExp(_) => { + Expr::ListComp(_) + | Expr::SetComp(_) + | Expr::GeneratorExp(_) => { // Allow comprehensions, even though we can't statically analyze // them. return (None, AllNamesFlags::empty()); @@ -87,13 +88,13 @@ where let mut names: Vec<&str> = vec![]; let mut flags = AllNamesFlags::empty(); - if let Some(value) = match &stmt.node { - StmtKind::Assign(ast::StmtAssign { value, .. }) => Some(value), - StmtKind::AnnAssign(ast::StmtAnnAssign { value, .. }) => value.as_ref(), - StmtKind::AugAssign(ast::StmtAugAssign { value, .. }) => Some(value), + if let Some(value) = match stmt { + Stmt::Assign(ast::StmtAssign { value, .. }) => Some(value), + Stmt::AnnAssign(ast::StmtAnnAssign { value, .. }) => value.as_ref(), + Stmt::AugAssign(ast::StmtAugAssign { value, .. }) => Some(value), _ => None, } { - if let ExprKind::BinOp(ast::ExprBinOp { left, right, .. }) = &value.node { + if let Expr::BinOp(ast::ExprBinOp { left, right, .. }) = &**value { let mut current_left = left; let mut current_right = right; loop { @@ -106,7 +107,7 @@ where // Process the left side, which can be a "real" value or the "rest" of the // binary operation. - if let ExprKind::BinOp(ast::ExprBinOp { left, right, .. }) = ¤t_left.node { + if let Expr::BinOp(ast::ExprBinOp { left, right, .. }) = &**current_left { current_left = left; current_right = right; } else { diff --git a/crates/ruff_python_ast/src/call_path.rs b/crates/ruff_python_ast/src/call_path.rs index 4266490e57..eedc2c76a1 100644 --- a/crates/ruff_python_ast/src/call_path.rs +++ b/crates/ruff_python_ast/src/call_path.rs @@ -1,12 +1,12 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr}; use smallvec::smallvec; /// A representation of a qualified name, like `typing.List`. pub type CallPath<'a> = smallvec::SmallVec<[&'a str; 8]>; fn collect_call_path_inner<'a>(expr: &'a Expr, parts: &mut CallPath<'a>) -> bool { - match &expr.node { - ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) => { + match expr { + Expr::Attribute(ast::ExprAttribute { value, attr, .. }) => { if collect_call_path_inner(value, parts) { parts.push(attr.as_str()); true @@ -14,7 +14,7 @@ fn collect_call_path_inner<'a>(expr: &'a Expr, parts: &mut CallPath<'a>) -> bool false } } - ExprKind::Name(ast::ExprName { id, .. }) => { + Expr::Name(ast::ExprName { id, .. }) => { parts.push(id.as_str()); true } diff --git a/crates/ruff_python_ast/src/cast.rs b/crates/ruff_python_ast/src/cast.rs index 527cb6e883..7e75ac4998 100644 --- a/crates/ruff_python_ast/src/cast.rs +++ b/crates/ruff_python_ast/src/cast.rs @@ -1,19 +1,19 @@ -use rustpython_parser::ast::{self, Expr, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Expr, Stmt}; pub fn name(stmt: &Stmt) -> &str { - match &stmt.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { name, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, .. }) => name.as_str(), - _ => panic!("Expected StmtKind::FunctionDef | StmtKind::AsyncFunctionDef"), + match stmt { + Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, .. }) => name.as_str(), + _ => panic!("Expected Stmt::FunctionDef | Stmt::AsyncFunctionDef"), } } -pub fn decorator_list(stmt: &Stmt) -> &Vec { - match &stmt.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { decorator_list, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { decorator_list, .. }) => { +pub fn decorator_list(stmt: &Stmt) -> &[Expr] { + match stmt { + Stmt::FunctionDef(ast::StmtFunctionDef { decorator_list, .. }) + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { decorator_list, .. }) => { decorator_list } - _ => panic!("Expected StmtKind::FunctionDef | StmtKind::AsyncFunctionDef"), + _ => panic!("Expected Stmt::FunctionDef | Stmt::AsyncFunctionDef"), } } diff --git a/crates/ruff_python_ast/src/comparable.rs b/crates/ruff_python_ast/src/comparable.rs index 2a28f3dc81..b6cff49c97 100644 --- a/crates/ruff_python_ast/src/comparable.rs +++ b/crates/ruff_python_ast/src/comparable.rs @@ -3,9 +3,8 @@ use num_bigint::BigInt; use rustpython_parser::ast::{ - self, Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, Excepthandler, - ExcepthandlerKind, Expr, ExprContext, ExprKind, Identifier, Int, Keyword, MatchCase, Operator, - Pattern, PatternKind, Stmt, StmtKind, Unaryop, Withitem, + self, Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, Excepthandler, Expr, + ExprContext, Identifier, Int, Keyword, MatchCase, Operator, Pattern, Stmt, Unaryop, Withitem, }; #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] @@ -136,8 +135,8 @@ pub struct ComparableAlias<'a> { impl<'a> From<&'a Alias> for ComparableAlias<'a> { fn from(alias: &'a Alias) -> Self { Self { - name: alias.node.name.as_str(), - asname: alias.node.asname.as_deref(), + name: alias.name.as_str(), + asname: alias.asname.as_deref(), } } } @@ -194,48 +193,50 @@ pub enum ComparablePattern<'a> { impl<'a> From<&'a Pattern> for ComparablePattern<'a> { fn from(pattern: &'a Pattern) -> Self { - match &pattern.node { - PatternKind::MatchValue(ast::PatternMatchValue { value }) => Self::MatchValue { + match pattern { + Pattern::MatchValue(ast::PatternMatchValue { value, .. }) => Self::MatchValue { value: value.into(), }, - PatternKind::MatchSingleton(ast::PatternMatchSingleton { value }) => { + Pattern::MatchSingleton(ast::PatternMatchSingleton { value, .. }) => { Self::MatchSingleton { value: value.into(), } } - PatternKind::MatchSequence(ast::PatternMatchSequence { patterns }) => { + Pattern::MatchSequence(ast::PatternMatchSequence { patterns, .. }) => { Self::MatchSequence { patterns: patterns.iter().map(Into::into).collect(), } } - PatternKind::MatchMapping(ast::PatternMatchMapping { + Pattern::MatchMapping(ast::PatternMatchMapping { keys, patterns, rest, + .. }) => Self::MatchMapping { keys: keys.iter().map(Into::into).collect(), patterns: patterns.iter().map(Into::into).collect(), rest: rest.as_deref(), }, - PatternKind::MatchClass(ast::PatternMatchClass { + Pattern::MatchClass(ast::PatternMatchClass { cls, patterns, kwd_attrs, kwd_patterns, + .. }) => Self::MatchClass { cls: cls.into(), patterns: patterns.iter().map(Into::into).collect(), kwd_attrs: kwd_attrs.iter().map(Identifier::as_str).collect(), kwd_patterns: kwd_patterns.iter().map(Into::into).collect(), }, - PatternKind::MatchStar(ast::PatternMatchStar { name }) => Self::MatchStar { + Pattern::MatchStar(ast::PatternMatchStar { name, .. }) => Self::MatchStar { name: name.as_deref(), }, - PatternKind::MatchAs(ast::PatternMatchAs { pattern, name }) => Self::MatchAs { + Pattern::MatchAs(ast::PatternMatchAs { pattern, name, .. }) => Self::MatchAs { pattern: pattern.as_ref().map(Into::into), name: name.as_deref(), }, - PatternKind::MatchOr(ast::PatternMatchOr { patterns }) => Self::MatchOr { + Pattern::MatchOr(ast::PatternMatchOr { patterns, .. }) => Self::MatchOr { patterns: patterns.iter().map(Into::into).collect(), }, } @@ -344,9 +345,9 @@ pub struct ComparableArg<'a> { impl<'a> From<&'a Arg> for ComparableArg<'a> { fn from(arg: &'a Arg) -> Self { Self { - arg: arg.node.arg.as_str(), - annotation: arg.node.annotation.as_ref().map(Into::into), - type_comment: arg.node.type_comment.as_deref(), + arg: arg.arg.as_str(), + annotation: arg.annotation.as_ref().map(Into::into), + type_comment: arg.type_comment.as_deref(), } } } @@ -360,8 +361,8 @@ pub struct ComparableKeyword<'a> { impl<'a> From<&'a Keyword> for ComparableKeyword<'a> { fn from(keyword: &'a Keyword) -> Self { Self { - arg: keyword.node.arg.as_ref().map(Identifier::as_str), - value: (&keyword.node.value).into(), + arg: keyword.arg.as_ref().map(Identifier::as_str), + value: (&keyword.value).into(), } } } @@ -396,8 +397,9 @@ pub enum ComparableExcepthandler<'a> { impl<'a> From<&'a Excepthandler> for ComparableExcepthandler<'a> { fn from(excepthandler: &'a Excepthandler) -> Self { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, name, body }) = - &excepthandler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { + type_, name, body, .. + }) = excepthandler; Self::ExceptHandler { type_: type_.as_ref().map(Into::into), name: name.as_deref(), @@ -536,136 +538,230 @@ impl<'a> From<&'a Box> for ComparableExpr<'a> { impl<'a> From<&'a Expr> for ComparableExpr<'a> { fn from(expr: &'a Expr) -> Self { - match &expr.node { - ExprKind::BoolOp(ast::ExprBoolOp { op, values }) => Self::BoolOp { + match expr { + Expr::BoolOp(ast::ExprBoolOp { + op, + values, + range: _range, + }) => Self::BoolOp { op: op.into(), values: values.iter().map(Into::into).collect(), }, - ExprKind::NamedExpr(ast::ExprNamedExpr { target, value }) => Self::NamedExpr { + Expr::NamedExpr(ast::ExprNamedExpr { + target, + value, + range: _range, + }) => Self::NamedExpr { target: target.into(), value: value.into(), }, - ExprKind::BinOp(ast::ExprBinOp { left, op, right }) => Self::BinOp { + Expr::BinOp(ast::ExprBinOp { + left, + op, + right, + range: _range, + }) => Self::BinOp { left: left.into(), op: op.into(), right: right.into(), }, - ExprKind::UnaryOp(ast::ExprUnaryOp { op, operand }) => Self::UnaryOp { + Expr::UnaryOp(ast::ExprUnaryOp { + op, + operand, + range: _range, + }) => Self::UnaryOp { op: op.into(), operand: operand.into(), }, - ExprKind::Lambda(ast::ExprLambda { args, body }) => Self::Lambda { + Expr::Lambda(ast::ExprLambda { + args, + body, + range: _range, + }) => Self::Lambda { args: (&**args).into(), body: body.into(), }, - ExprKind::IfExp(ast::ExprIfExp { test, body, orelse }) => Self::IfExp { + Expr::IfExp(ast::ExprIfExp { + test, + body, + orelse, + range: _range, + }) => Self::IfExp { test: test.into(), body: body.into(), orelse: orelse.into(), }, - ExprKind::Dict(ast::ExprDict { keys, values }) => Self::Dict { + Expr::Dict(ast::ExprDict { + keys, + values, + range: _range, + }) => Self::Dict { keys: keys .iter() .map(|expr| expr.as_ref().map(Into::into)) .collect(), values: values.iter().map(Into::into).collect(), }, - ExprKind::Set(ast::ExprSet { elts }) => Self::Set { + Expr::Set(ast::ExprSet { + elts, + range: _range, + }) => Self::Set { elts: elts.iter().map(Into::into).collect(), }, - ExprKind::ListComp(ast::ExprListComp { elt, generators }) => Self::ListComp { + Expr::ListComp(ast::ExprListComp { + elt, + generators, + range: _range, + }) => Self::ListComp { elt: elt.into(), generators: generators.iter().map(Into::into).collect(), }, - ExprKind::SetComp(ast::ExprSetComp { elt, generators }) => Self::SetComp { + Expr::SetComp(ast::ExprSetComp { + elt, + generators, + range: _range, + }) => Self::SetComp { elt: elt.into(), generators: generators.iter().map(Into::into).collect(), }, - ExprKind::DictComp(ast::ExprDictComp { + Expr::DictComp(ast::ExprDictComp { key, value, generators, + range: _range, }) => Self::DictComp { key: key.into(), value: value.into(), generators: generators.iter().map(Into::into).collect(), }, - ExprKind::GeneratorExp(ast::ExprGeneratorExp { elt, generators }) => { - Self::GeneratorExp { - elt: elt.into(), - generators: generators.iter().map(Into::into).collect(), - } - } - ExprKind::Await(ast::ExprAwait { value }) => Self::Await { + Expr::GeneratorExp(ast::ExprGeneratorExp { + elt, + generators, + range: _range, + }) => Self::GeneratorExp { + elt: elt.into(), + generators: generators.iter().map(Into::into).collect(), + }, + Expr::Await(ast::ExprAwait { + value, + range: _range, + }) => Self::Await { value: value.into(), }, - ExprKind::Yield(ast::ExprYield { value }) => Self::Yield { + Expr::Yield(ast::ExprYield { + value, + range: _range, + }) => Self::Yield { value: value.as_ref().map(Into::into), }, - ExprKind::YieldFrom(ast::ExprYieldFrom { value }) => Self::YieldFrom { + Expr::YieldFrom(ast::ExprYieldFrom { + value, + range: _range, + }) => Self::YieldFrom { value: value.into(), }, - ExprKind::Compare(ast::ExprCompare { + Expr::Compare(ast::ExprCompare { left, ops, comparators, + range: _range, }) => Self::Compare { left: left.into(), ops: ops.iter().map(Into::into).collect(), comparators: comparators.iter().map(Into::into).collect(), }, - ExprKind::Call(ast::ExprCall { + Expr::Call(ast::ExprCall { func, args, keywords, + range: _range, }) => Self::Call { func: func.into(), args: args.iter().map(Into::into).collect(), keywords: keywords.iter().map(Into::into).collect(), }, - ExprKind::FormattedValue(ast::ExprFormattedValue { + Expr::FormattedValue(ast::ExprFormattedValue { value, conversion, format_spec, + range: _range, }) => Self::FormattedValue { value: value.into(), conversion: *conversion, format_spec: format_spec.as_ref().map(Into::into), }, - ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => Self::JoinedStr { + Expr::JoinedStr(ast::ExprJoinedStr { + values, + range: _range, + }) => Self::JoinedStr { values: values.iter().map(Into::into).collect(), }, - ExprKind::Constant(ast::ExprConstant { value, kind }) => Self::Constant { + Expr::Constant(ast::ExprConstant { + value, + kind, + range: _range, + }) => Self::Constant { value: value.into(), kind: kind.as_ref().map(String::as_str), }, - ExprKind::Attribute(ast::ExprAttribute { value, attr, ctx }) => Self::Attribute { + Expr::Attribute(ast::ExprAttribute { + value, + attr, + ctx, + range: _range, + }) => Self::Attribute { value: value.into(), attr: attr.as_str(), ctx: ctx.into(), }, - ExprKind::Subscript(ast::ExprSubscript { value, slice, ctx }) => Self::Subscript { + Expr::Subscript(ast::ExprSubscript { + value, + slice, + ctx, + range: _range, + }) => Self::Subscript { value: value.into(), slice: slice.into(), ctx: ctx.into(), }, - ExprKind::Starred(ast::ExprStarred { value, ctx }) => Self::Starred { + Expr::Starred(ast::ExprStarred { + value, + ctx, + range: _range, + }) => Self::Starred { value: value.into(), ctx: ctx.into(), }, - ExprKind::Name(ast::ExprName { id, ctx }) => Self::Name { + Expr::Name(ast::ExprName { + id, + ctx, + range: _range, + }) => Self::Name { id: id.as_str(), ctx: ctx.into(), }, - ExprKind::List(ast::ExprList { elts, ctx }) => Self::List { + Expr::List(ast::ExprList { + elts, + ctx, + range: _range, + }) => Self::List { elts: elts.iter().map(Into::into).collect(), ctx: ctx.into(), }, - ExprKind::Tuple(ast::ExprTuple { elts, ctx }) => Self::Tuple { + Expr::Tuple(ast::ExprTuple { + elts, + ctx, + range: _range, + }) => Self::Tuple { elts: elts.iter().map(Into::into).collect(), ctx: ctx.into(), }, - ExprKind::Slice(ast::ExprSlice { lower, upper, step }) => Self::Slice { + Expr::Slice(ast::ExprSlice { + lower, + upper, + step, + range: _range, + }) => Self::Slice { lower: lower.as_ref().map(Into::into), upper: upper.as_ref().map(Into::into), step: step.as_ref().map(Into::into), @@ -803,14 +899,15 @@ pub enum ComparableStmt<'a> { impl<'a> From<&'a Stmt> for ComparableStmt<'a> { fn from(stmt: &'a Stmt) -> Self { - match &stmt.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { + match stmt { + Stmt::FunctionDef(ast::StmtFunctionDef { name, args, body, decorator_list, returns, type_comment, + range: _range, }) => Self::FunctionDef { name: name.as_str(), args: args.into(), @@ -819,13 +916,14 @@ impl<'a> From<&'a Stmt> for ComparableStmt<'a> { returns: returns.as_ref().map(Into::into), type_comment: type_comment.as_ref().map(std::string::String::as_str), }, - StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { + Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, args, body, decorator_list, returns, type_comment, + range: _range, }) => Self::AsyncFunctionDef { name: name.as_str(), args: args.into(), @@ -834,12 +932,13 @@ impl<'a> From<&'a Stmt> for ComparableStmt<'a> { returns: returns.as_ref().map(Into::into), type_comment: type_comment.as_ref().map(std::string::String::as_str), }, - StmtKind::ClassDef(ast::StmtClassDef { + Stmt::ClassDef(ast::StmtClassDef { name, bases, keywords, body, decorator_list, + range: _range, }) => Self::ClassDef { name: name.as_str(), bases: bases.iter().map(Into::into).collect(), @@ -847,43 +946,57 @@ impl<'a> From<&'a Stmt> for ComparableStmt<'a> { body: body.iter().map(Into::into).collect(), decorator_list: decorator_list.iter().map(Into::into).collect(), }, - StmtKind::Return(ast::StmtReturn { value }) => Self::Return { + Stmt::Return(ast::StmtReturn { + value, + range: _range, + }) => Self::Return { value: value.as_ref().map(Into::into), }, - StmtKind::Delete(ast::StmtDelete { targets }) => Self::Delete { + Stmt::Delete(ast::StmtDelete { + targets, + range: _range, + }) => Self::Delete { targets: targets.iter().map(Into::into).collect(), }, - StmtKind::Assign(ast::StmtAssign { + Stmt::Assign(ast::StmtAssign { targets, value, type_comment, + range: _range, }) => Self::Assign { targets: targets.iter().map(Into::into).collect(), value: value.into(), type_comment: type_comment.as_ref().map(std::string::String::as_str), }, - StmtKind::AugAssign(ast::StmtAugAssign { target, op, value }) => Self::AugAssign { + Stmt::AugAssign(ast::StmtAugAssign { + target, + op, + value, + range: _range, + }) => Self::AugAssign { target: target.into(), op: op.into(), value: value.into(), }, - StmtKind::AnnAssign(ast::StmtAnnAssign { + Stmt::AnnAssign(ast::StmtAnnAssign { target, annotation, value, simple, + range: _range, }) => Self::AnnAssign { target: target.into(), annotation: annotation.into(), value: value.as_ref().map(Into::into), simple: *simple, }, - StmtKind::For(ast::StmtFor { + Stmt::For(ast::StmtFor { target, iter, body, orelse, type_comment, + range: _range, }) => Self::For { target: target.into(), iter: iter.into(), @@ -891,12 +1004,13 @@ impl<'a> From<&'a Stmt> for ComparableStmt<'a> { orelse: orelse.iter().map(Into::into).collect(), type_comment: type_comment.as_ref().map(String::as_str), }, - StmtKind::AsyncFor(ast::StmtAsyncFor { + Stmt::AsyncFor(ast::StmtAsyncFor { target, iter, body, orelse, type_comment, + range: _range, }) => Self::AsyncFor { target: target.into(), iter: iter.into(), @@ -904,92 +1018,131 @@ impl<'a> From<&'a Stmt> for ComparableStmt<'a> { orelse: orelse.iter().map(Into::into).collect(), type_comment: type_comment.as_ref().map(String::as_str), }, - StmtKind::While(ast::StmtWhile { test, body, orelse }) => Self::While { + Stmt::While(ast::StmtWhile { + test, + body, + orelse, + range: _range, + }) => Self::While { test: test.into(), body: body.iter().map(Into::into).collect(), orelse: orelse.iter().map(Into::into).collect(), }, - StmtKind::If(ast::StmtIf { test, body, orelse }) => Self::If { + Stmt::If(ast::StmtIf { + test, + body, + orelse, + range: _range, + }) => Self::If { test: test.into(), body: body.iter().map(Into::into).collect(), orelse: orelse.iter().map(Into::into).collect(), }, - StmtKind::With(ast::StmtWith { + Stmt::With(ast::StmtWith { items, body, type_comment, + range: _range, }) => Self::With { items: items.iter().map(Into::into).collect(), body: body.iter().map(Into::into).collect(), type_comment: type_comment.as_ref().map(String::as_str), }, - StmtKind::AsyncWith(ast::StmtAsyncWith { + Stmt::AsyncWith(ast::StmtAsyncWith { items, body, type_comment, + range: _range, }) => Self::AsyncWith { items: items.iter().map(Into::into).collect(), body: body.iter().map(Into::into).collect(), type_comment: type_comment.as_ref().map(String::as_str), }, - StmtKind::Match(ast::StmtMatch { subject, cases }) => Self::Match { + Stmt::Match(ast::StmtMatch { + subject, + cases, + range: _range, + }) => Self::Match { subject: subject.into(), cases: cases.iter().map(Into::into).collect(), }, - StmtKind::Raise(ast::StmtRaise { exc, cause }) => Self::Raise { + Stmt::Raise(ast::StmtRaise { + exc, + cause, + range: _range, + }) => Self::Raise { exc: exc.as_ref().map(Into::into), cause: cause.as_ref().map(Into::into), }, - StmtKind::Try(ast::StmtTry { + Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, + range: _range, }) => Self::Try { body: body.iter().map(Into::into).collect(), handlers: handlers.iter().map(Into::into).collect(), orelse: orelse.iter().map(Into::into).collect(), finalbody: finalbody.iter().map(Into::into).collect(), }, - StmtKind::TryStar(ast::StmtTryStar { + Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, finalbody, + range: _range, }) => Self::TryStar { body: body.iter().map(Into::into).collect(), handlers: handlers.iter().map(Into::into).collect(), orelse: orelse.iter().map(Into::into).collect(), finalbody: finalbody.iter().map(Into::into).collect(), }, - StmtKind::Assert(ast::StmtAssert { test, msg }) => Self::Assert { + Stmt::Assert(ast::StmtAssert { + test, + msg, + range: _range, + }) => Self::Assert { test: test.into(), msg: msg.as_ref().map(Into::into), }, - StmtKind::Import(ast::StmtImport { names }) => Self::Import { + Stmt::Import(ast::StmtImport { + names, + range: _range, + }) => Self::Import { names: names.iter().map(Into::into).collect(), }, - StmtKind::ImportFrom(ast::StmtImportFrom { + Stmt::ImportFrom(ast::StmtImportFrom { module, names, level, + range: _range, }) => Self::ImportFrom { module: module.as_deref(), names: names.iter().map(Into::into).collect(), level: *level, }, - StmtKind::Global(ast::StmtGlobal { names }) => Self::Global { + Stmt::Global(ast::StmtGlobal { + names, + range: _range, + }) => Self::Global { names: names.iter().map(Identifier::as_str).collect(), }, - StmtKind::Nonlocal(ast::StmtNonlocal { names }) => Self::Nonlocal { + Stmt::Nonlocal(ast::StmtNonlocal { + names, + range: _range, + }) => Self::Nonlocal { names: names.iter().map(Identifier::as_str).collect(), }, - StmtKind::Expr(ast::StmtExpr { value }) => Self::Expr { + Stmt::Expr(ast::StmtExpr { + value, + range: _range, + }) => Self::Expr { value: value.into(), }, - StmtKind::Pass => Self::Pass, - StmtKind::Break => Self::Break, - StmtKind::Continue => Self::Continue, + Stmt::Pass(_) => Self::Pass, + Stmt::Break(_) => Self::Break, + Stmt::Continue(_) => Self::Continue, } } } diff --git a/crates/ruff_python_ast/src/helpers.rs b/crates/ruff_python_ast/src/helpers.rs index 8338391533..31ff4e7941 100644 --- a/crates/ruff_python_ast/src/helpers.rs +++ b/crates/ruff_python_ast/src/helpers.rs @@ -9,8 +9,8 @@ use regex::Regex; use ruff_text_size::{TextRange, TextSize}; use rustc_hash::{FxHashMap, FxHashSet}; use rustpython_parser::ast::{ - self, Arguments, Attributed, Cmpop, Constant, Excepthandler, ExcepthandlerKind, Expr, ExprKind, - Keyword, KeywordData, MatchCase, Pattern, PatternKind, Stmt, StmtKind, + self, Arguments, Cmpop, Constant, Excepthandler, Expr, Keyword, MatchCase, Pattern, Ranged, + Stmt, }; use rustpython_parser::{lexer, Mode, Tok}; use smallvec::SmallVec; @@ -20,16 +20,6 @@ use crate::newlines::UniversalNewlineIterator; use crate::source_code::{Generator, Indexer, Locator, Stylist}; use crate::statement_visitor::{walk_body, walk_stmt, StatementVisitor}; -/// Create an `Expr` with default location from an `ExprKind`. -pub fn create_expr(node: impl Into) -> Expr { - Expr::new(TextRange::default(), node.into()) -} - -/// Create a `Stmt` with a default location from a `StmtKind`. -pub fn create_stmt(node: impl Into) -> Stmt { - Stmt::new(TextRange::default(), node.into()) -} - /// Generate source code from an [`Expr`]. pub fn unparse_expr(expr: &Expr, stylist: &Stylist) -> String { let mut generator: Generator = stylist.into(); @@ -68,14 +58,15 @@ where { any_over_expr(expr, &|expr| { // Accept empty initializers. - if let ExprKind::Call(ast::ExprCall { + if let Expr::Call(ast::ExprCall { func, args, keywords, - }) = &expr.node + range: _range, + }) = expr { if args.is_empty() && keywords.is_empty() { - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { + if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { if !is_iterable_initializer(id.as_str(), |id| is_builtin(id)) { return true; } @@ -85,32 +76,32 @@ where } // Avoid false positive for overloaded operators. - if let ExprKind::BinOp(ast::ExprBinOp { left, right, .. }) = &expr.node { + if let Expr::BinOp(ast::ExprBinOp { left, right, .. }) = expr { if !matches!( - left.node, - ExprKind::Constant(_) - | ExprKind::JoinedStr(_) - | ExprKind::List(_) - | ExprKind::Tuple(_) - | ExprKind::Set(_) - | ExprKind::Dict(_) - | ExprKind::ListComp(_) - | ExprKind::SetComp(_) - | ExprKind::DictComp(_) + left.as_ref(), + Expr::Constant(_) + | Expr::JoinedStr(_) + | Expr::List(_) + | Expr::Tuple(_) + | Expr::Set(_) + | Expr::Dict(_) + | Expr::ListComp(_) + | Expr::SetComp(_) + | Expr::DictComp(_) ) { return true; } if !matches!( - right.node, - ExprKind::Constant(_) - | ExprKind::JoinedStr(_) - | ExprKind::List(_) - | ExprKind::Tuple(_) - | ExprKind::Set(_) - | ExprKind::Dict(_) - | ExprKind::ListComp(_) - | ExprKind::SetComp(_) - | ExprKind::DictComp(_) + right.as_ref(), + Expr::Constant(_) + | Expr::JoinedStr(_) + | Expr::List(_) + | Expr::Tuple(_) + | Expr::Set(_) + | Expr::Dict(_) + | Expr::ListComp(_) + | Expr::SetComp(_) + | Expr::DictComp(_) ) { return true; } @@ -119,16 +110,16 @@ where // Otherwise, avoid all complex expressions. matches!( - expr.node, - ExprKind::Await(_) - | ExprKind::Call(_) - | ExprKind::DictComp(_) - | ExprKind::GeneratorExp(_) - | ExprKind::ListComp(_) - | ExprKind::SetComp(_) - | ExprKind::Subscript(_) - | ExprKind::Yield(_) - | ExprKind::YieldFrom(_) + expr, + Expr::Await(_) + | Expr::Call(_) + | Expr::DictComp(_) + | Expr::GeneratorExp(_) + | Expr::ListComp(_) + | Expr::SetComp(_) + | Expr::Subscript(_) + | Expr::Yield(_) + | Expr::YieldFrom(_) ) }) } @@ -142,34 +133,69 @@ where if func(expr) { return true; } - match &expr.node { - ExprKind::BoolOp(ast::ExprBoolOp { values, .. }) - | ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => { - values.iter().any(|expr| any_over_expr(expr, func)) - } - ExprKind::NamedExpr(ast::ExprNamedExpr { target, value }) => { - any_over_expr(target, func) || any_over_expr(value, func) - } - ExprKind::BinOp(ast::ExprBinOp { left, right, .. }) => { + match expr { + Expr::BoolOp(ast::ExprBoolOp { + values, + range: _range, + .. + }) + | Expr::JoinedStr(ast::ExprJoinedStr { + values, + range: _range, + }) => values.iter().any(|expr| any_over_expr(expr, func)), + Expr::NamedExpr(ast::ExprNamedExpr { + target, + value, + range: _range, + }) => any_over_expr(target, func) || any_over_expr(value, func), + Expr::BinOp(ast::ExprBinOp { left, right, .. }) => { any_over_expr(left, func) || any_over_expr(right, func) } - ExprKind::UnaryOp(ast::ExprUnaryOp { operand, .. }) => any_over_expr(operand, func), - ExprKind::Lambda(ast::ExprLambda { body, .. }) => any_over_expr(body, func), - ExprKind::IfExp(ast::ExprIfExp { test, body, orelse }) => { - any_over_expr(test, func) || any_over_expr(body, func) || any_over_expr(orelse, func) - } - ExprKind::Dict(ast::ExprDict { keys, values }) => values + Expr::UnaryOp(ast::ExprUnaryOp { operand, .. }) => any_over_expr(operand, func), + Expr::Lambda(ast::ExprLambda { body, .. }) => any_over_expr(body, func), + Expr::IfExp(ast::ExprIfExp { + test, + body, + orelse, + range: _range, + }) => any_over_expr(test, func) || any_over_expr(body, func) || any_over_expr(orelse, func), + Expr::Dict(ast::ExprDict { + keys, + values, + range: _range, + }) => values .iter() .chain(keys.iter().flatten()) .any(|expr| any_over_expr(expr, func)), - ExprKind::Set(ast::ExprSet { elts }) - | ExprKind::List(ast::ExprList { elts, .. }) - | ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { - elts.iter().any(|expr| any_over_expr(expr, func)) - } - ExprKind::ListComp(ast::ExprListComp { elt, generators }) - | ExprKind::SetComp(ast::ExprSetComp { elt, generators }) - | ExprKind::GeneratorExp(ast::ExprGeneratorExp { elt, generators }) => { + Expr::Set(ast::ExprSet { + elts, + range: _range, + }) + | Expr::List(ast::ExprList { + elts, + range: _range, + .. + }) + | Expr::Tuple(ast::ExprTuple { + elts, + range: _range, + .. + }) => elts.iter().any(|expr| any_over_expr(expr, func)), + Expr::ListComp(ast::ExprListComp { + elt, + generators, + range: _range, + }) + | Expr::SetComp(ast::ExprSetComp { + elt, + generators, + range: _range, + }) + | Expr::GeneratorExp(ast::ExprGeneratorExp { + elt, + generators, + range: _range, + }) => { any_over_expr(elt, func) || generators.iter().any(|generator| { any_over_expr(&generator.target, func) @@ -177,10 +203,11 @@ where || generator.ifs.iter().any(|expr| any_over_expr(expr, func)) }) } - ExprKind::DictComp(ast::ExprDictComp { + Expr::DictComp(ast::ExprDictComp { key, value, generators, + range: _range, }) => { any_over_expr(key, func) || any_over_expr(value, func) @@ -190,28 +217,46 @@ where || generator.ifs.iter().any(|expr| any_over_expr(expr, func)) }) } - ExprKind::Await(ast::ExprAwait { value }) - | ExprKind::YieldFrom(ast::ExprYieldFrom { value }) - | ExprKind::Attribute(ast::ExprAttribute { value, .. }) - | ExprKind::Starred(ast::ExprStarred { value, .. }) => any_over_expr(value, func), - ExprKind::Yield(ast::ExprYield { value }) => value + Expr::Await(ast::ExprAwait { + value, + range: _range, + }) + | Expr::YieldFrom(ast::ExprYieldFrom { + value, + range: _range, + }) + | Expr::Attribute(ast::ExprAttribute { + value, + range: _range, + .. + }) + | Expr::Starred(ast::ExprStarred { + value, + range: _range, + .. + }) => any_over_expr(value, func), + Expr::Yield(ast::ExprYield { + value, + range: _range, + }) => value .as_ref() .map_or(false, |value| any_over_expr(value, func)), - ExprKind::Compare(ast::ExprCompare { + Expr::Compare(ast::ExprCompare { left, comparators, .. }) => any_over_expr(left, func) || comparators.iter().any(|expr| any_over_expr(expr, func)), - ExprKind::Call(ast::ExprCall { + Expr::Call(ast::ExprCall { func: call_func, args, keywords, + range: _range, }) => { any_over_expr(call_func, func) || args.iter().any(|expr| any_over_expr(expr, func)) || keywords .iter() - .any(|keyword| any_over_expr(&keyword.node.value, func)) + .any(|keyword| any_over_expr(&keyword.value, func)) } - ExprKind::FormattedValue(ast::ExprFormattedValue { + Expr::FormattedValue(ast::ExprFormattedValue { value, format_spec, .. }) => { any_over_expr(value, func) @@ -219,10 +264,15 @@ where .as_ref() .map_or(false, |value| any_over_expr(value, func)) } - ExprKind::Subscript(ast::ExprSubscript { value, slice, .. }) => { + Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => { any_over_expr(value, func) || any_over_expr(slice, func) } - ExprKind::Slice(ast::ExprSlice { lower, upper, step }) => { + Expr::Slice(ast::ExprSlice { + lower, + upper, + step, + range: _range, + }) => { lower .as_ref() .map_or(false, |value| any_over_expr(value, func)) @@ -233,7 +283,7 @@ where .as_ref() .map_or(false, |value| any_over_expr(value, func)) } - ExprKind::Name(_) | ExprKind::Constant(_) => false, + Expr::Name(_) | Expr::Constant(_) => false, } } @@ -241,19 +291,25 @@ pub fn any_over_pattern(pattern: &Pattern, func: &F) -> bool where F: Fn(&Expr) -> bool, { - match &pattern.node { - PatternKind::MatchValue(ast::PatternMatchValue { value }) => any_over_expr(value, func), - PatternKind::MatchSingleton(_) => false, - PatternKind::MatchSequence(ast::PatternMatchSequence { patterns }) => patterns + match pattern { + Pattern::MatchValue(ast::PatternMatchValue { + value, + range: _range, + }) => any_over_expr(value, func), + Pattern::MatchSingleton(_) => false, + Pattern::MatchSequence(ast::PatternMatchSequence { + patterns, + range: _range, + }) => patterns .iter() .any(|pattern| any_over_pattern(pattern, func)), - PatternKind::MatchMapping(ast::PatternMatchMapping { keys, patterns, .. }) => { + Pattern::MatchMapping(ast::PatternMatchMapping { keys, patterns, .. }) => { keys.iter().any(|key| any_over_expr(key, func)) || patterns .iter() .any(|pattern| any_over_pattern(pattern, func)) } - PatternKind::MatchClass(ast::PatternMatchClass { + Pattern::MatchClass(ast::PatternMatchClass { cls, patterns, kwd_patterns, @@ -267,11 +323,14 @@ where .iter() .any(|pattern| any_over_pattern(pattern, func)) } - PatternKind::MatchStar(_) => false, - PatternKind::MatchAs(ast::PatternMatchAs { pattern, .. }) => pattern + Pattern::MatchStar(_) => false, + Pattern::MatchAs(ast::PatternMatchAs { pattern, .. }) => pattern .as_ref() .map_or(false, |pattern| any_over_pattern(pattern, func)), - PatternKind::MatchOr(ast::PatternMatchOr { patterns }) => patterns + Pattern::MatchOr(ast::PatternMatchOr { + patterns, + range: _range, + }) => patterns .iter() .any(|pattern| any_over_pattern(pattern, func)), } @@ -281,15 +340,15 @@ pub fn any_over_stmt(stmt: &Stmt, func: &F) -> bool where F: Fn(&Expr) -> bool, { - match &stmt.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { + match stmt { + Stmt::FunctionDef(ast::StmtFunctionDef { args, body, decorator_list, returns, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { args, body, decorator_list, @@ -302,32 +361,27 @@ where .iter() .any(|expr| any_over_expr(expr, func)) || args.args.iter().any(|arg| { - arg.node - .annotation + arg.annotation .as_ref() .map_or(false, |expr| any_over_expr(expr, func)) }) || args.kwonlyargs.iter().any(|arg| { - arg.node - .annotation + arg.annotation .as_ref() .map_or(false, |expr| any_over_expr(expr, func)) }) || args.posonlyargs.iter().any(|arg| { - arg.node - .annotation + arg.annotation .as_ref() .map_or(false, |expr| any_over_expr(expr, func)) }) || args.vararg.as_ref().map_or(false, |arg| { - arg.node - .annotation + arg.annotation .as_ref() .map_or(false, |expr| any_over_expr(expr, func)) }) || args.kwarg.as_ref().map_or(false, |arg| { - arg.node - .annotation + arg.annotation .as_ref() .map_or(false, |expr| any_over_expr(expr, func)) }) @@ -337,7 +391,7 @@ where .as_ref() .map_or(false, |value| any_over_expr(value, func)) } - StmtKind::ClassDef(ast::StmtClassDef { + Stmt::ClassDef(ast::StmtClassDef { bases, keywords, body, @@ -347,23 +401,27 @@ where bases.iter().any(|expr| any_over_expr(expr, func)) || keywords .iter() - .any(|keyword| any_over_expr(&keyword.node.value, func)) + .any(|keyword| any_over_expr(&keyword.value, func)) || body.iter().any(|stmt| any_over_stmt(stmt, func)) || decorator_list.iter().any(|expr| any_over_expr(expr, func)) } - StmtKind::Return(ast::StmtReturn { value }) => value + Stmt::Return(ast::StmtReturn { + value, + range: _range, + }) => value .as_ref() .map_or(false, |value| any_over_expr(value, func)), - StmtKind::Delete(ast::StmtDelete { targets }) => { - targets.iter().any(|expr| any_over_expr(expr, func)) - } - StmtKind::Assign(ast::StmtAssign { targets, value, .. }) => { + Stmt::Delete(ast::StmtDelete { + targets, + range: _range, + }) => targets.iter().any(|expr| any_over_expr(expr, func)), + Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { targets.iter().any(|expr| any_over_expr(expr, func)) || any_over_expr(value, func) } - StmtKind::AugAssign(ast::StmtAugAssign { target, value, .. }) => { + Stmt::AugAssign(ast::StmtAugAssign { target, value, .. }) => { any_over_expr(target, func) || any_over_expr(value, func) } - StmtKind::AnnAssign(ast::StmtAnnAssign { + Stmt::AnnAssign(ast::StmtAnnAssign { target, annotation, value, @@ -375,14 +433,14 @@ where .as_ref() .map_or(false, |value| any_over_expr(value, func)) } - StmtKind::For(ast::StmtFor { + Stmt::For(ast::StmtFor { target, iter, body, orelse, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { + | Stmt::AsyncFor(ast::StmtAsyncFor { target, iter, body, @@ -394,14 +452,20 @@ where || any_over_body(body, func) || any_over_body(orelse, func) } - StmtKind::While(ast::StmtWhile { test, body, orelse }) => { - any_over_expr(test, func) || any_over_body(body, func) || any_over_body(orelse, func) - } - StmtKind::If(ast::StmtIf { test, body, orelse }) => { - any_over_expr(test, func) || any_over_body(body, func) || any_over_body(orelse, func) - } - StmtKind::With(ast::StmtWith { items, body, .. }) - | StmtKind::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => { + Stmt::While(ast::StmtWhile { + test, + body, + orelse, + range: _range, + }) => any_over_expr(test, func) || any_over_body(body, func) || any_over_body(orelse, func), + Stmt::If(ast::StmtIf { + test, + body, + orelse, + range: _range, + }) => any_over_expr(test, func) || any_over_body(body, func) || any_over_body(orelse, func), + Stmt::With(ast::StmtWith { items, body, .. }) + | Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => { items.iter().any(|withitem| { any_over_expr(&withitem.context_expr, func) || withitem @@ -410,32 +474,38 @@ where .map_or(false, |expr| any_over_expr(expr, func)) }) || any_over_body(body, func) } - StmtKind::Raise(ast::StmtRaise { exc, cause }) => { + Stmt::Raise(ast::StmtRaise { + exc, + cause, + range: _range, + }) => { exc.as_ref() .map_or(false, |value| any_over_expr(value, func)) || cause .as_ref() .map_or(false, |value| any_over_expr(value, func)) } - StmtKind::Try(ast::StmtTry { + Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, + range: _range, }) - | StmtKind::TryStar(ast::StmtTryStar { + | Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, finalbody, + range: _range, }) => { any_over_body(body, func) || handlers.iter().any(|handler| { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, body, .. - }) = &handler.node; + }) = handler; type_ .as_ref() .map_or(false, |expr| any_over_expr(expr, func)) @@ -444,19 +514,28 @@ where || any_over_body(orelse, func) || any_over_body(finalbody, func) } - StmtKind::Assert(ast::StmtAssert { test, msg }) => { + Stmt::Assert(ast::StmtAssert { + test, + msg, + range: _range, + }) => { any_over_expr(test, func) || msg .as_ref() .map_or(false, |value| any_over_expr(value, func)) } - StmtKind::Match(ast::StmtMatch { subject, cases }) => { + Stmt::Match(ast::StmtMatch { + subject, + cases, + range: _range, + }) => { any_over_expr(subject, func) || cases.iter().any(|case| { let MatchCase { pattern, guard, body, + range: _range, } = case; any_over_pattern(pattern, func) || guard @@ -465,14 +544,15 @@ where || any_over_body(body, func) }) } - StmtKind::Import(_) => false, - StmtKind::ImportFrom(_) => false, - StmtKind::Global(_) => false, - StmtKind::Nonlocal(_) => false, - StmtKind::Expr(ast::StmtExpr { value }) => any_over_expr(value, func), - StmtKind::Pass => false, - StmtKind::Break => false, - StmtKind::Continue => false, + Stmt::Import(_) => false, + Stmt::ImportFrom(_) => false, + Stmt::Global(_) => false, + Stmt::Nonlocal(_) => false, + Stmt::Expr(ast::StmtExpr { + value, + range: _range, + }) => any_over_expr(value, func), + Stmt::Pass(_) | Stmt::Break(_) | Stmt::Continue(_) => false, } } @@ -489,18 +569,18 @@ static DUNDER_REGEX: Lazy = Lazy::new(|| Regex::new(r"__[^\s]+__").unwrap pub fn is_assignment_to_a_dunder(stmt: &Stmt) -> bool { // Check whether it's an assignment to a dunder, with or without a type // annotation. This is what pycodestyle (as of 2.9.1) does. - match &stmt.node { - StmtKind::Assign(ast::StmtAssign { targets, .. }) => { + match stmt { + Stmt::Assign(ast::StmtAssign { targets, .. }) => { if targets.len() != 1 { return false; } - match &targets[0].node { - ExprKind::Name(ast::ExprName { id, .. }) => DUNDER_REGEX.is_match(id.as_str()), + match &targets[0] { + Expr::Name(ast::ExprName { id, .. }) => DUNDER_REGEX.is_match(id.as_str()), _ => false, } } - StmtKind::AnnAssign(ast::StmtAnnAssign { target, .. }) => match &target.node { - ExprKind::Name(ast::ExprName { id, .. }) => DUNDER_REGEX.is_match(id.as_str()), + Stmt::AnnAssign(ast::StmtAnnAssign { target, .. }) => match target.as_ref() { + Expr::Name(ast::ExprName { id, .. }) => DUNDER_REGEX.is_match(id.as_str()), _ => false, }, _ => false, @@ -511,8 +591,8 @@ pub fn is_assignment_to_a_dunder(stmt: &Stmt) -> bool { /// `...`). pub const fn is_singleton(expr: &Expr) -> bool { matches!( - expr.node, - ExprKind::Constant(ast::ExprConstant { + expr, + Expr::Constant(ast::ExprConstant { value: Constant::None | Constant::Bool(_) | Constant::Ellipsis, .. }) @@ -521,9 +601,9 @@ pub const fn is_singleton(expr: &Expr) -> bool { /// Return `true` if the [`Expr`] is a constant or tuple of constants. pub fn is_constant(expr: &Expr) -> bool { - match &expr.node { - ExprKind::Constant(_) => true, - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => elts.iter().all(is_constant), + match expr { + Expr::Constant(_) => true, + Expr::Tuple(ast::ExprTuple { elts, .. }) => elts.iter().all(is_constant), _ => false, } } @@ -537,7 +617,7 @@ pub fn is_constant_non_singleton(expr: &Expr) -> bool { /// [`Keyword`] arguments. pub fn find_keyword<'a>(keywords: &'a [Keyword], keyword_name: &str) -> Option<&'a Keyword> { keywords.iter().find(|keyword| { - let KeywordData { arg, .. } = &keyword.node; + let Keyword { arg, .. } = keyword; arg.as_ref().map_or(false, |arg| arg == keyword_name) }) } @@ -545,10 +625,11 @@ pub fn find_keyword<'a>(keywords: &'a [Keyword], keyword_name: &str) -> Option<& /// Return `true` if an [`Expr`] is `None`. pub const fn is_const_none(expr: &Expr) -> bool { matches!( - &expr.node, - ExprKind::Constant(ast::ExprConstant { + expr, + Expr::Constant(ast::ExprConstant { value: Constant::None, - kind: None + kind: None, + .. }), ) } @@ -556,10 +637,11 @@ pub const fn is_const_none(expr: &Expr) -> bool { /// Return `true` if an [`Expr`] is `True`. pub const fn is_const_true(expr: &Expr) -> bool { matches!( - &expr.node, - ExprKind::Constant(ast::ExprConstant { + expr, + Expr::Constant(ast::ExprConstant { value: Constant::Bool(true), - kind: None + kind: None, + .. }), ) } @@ -567,7 +649,7 @@ pub const fn is_const_true(expr: &Expr) -> bool { /// Return `true` if a keyword argument is present with a non-`None` value. pub fn has_non_none_keyword(keywords: &[Keyword], keyword: &str) -> bool { find_keyword(keywords, keyword).map_or(false, |keyword| { - let KeywordData { value, .. } = &keyword.node; + let Keyword { value, .. } = keyword; !is_const_none(value) }) } @@ -576,10 +658,10 @@ pub fn has_non_none_keyword(keywords: &[Keyword], keyword: &str) -> bool { pub fn extract_handled_exceptions(handlers: &[Excepthandler]) -> Vec<&Expr> { let mut handled_exceptions = Vec::new(); for handler in handlers { - match &handler.node { - ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) => { + match handler { + Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) => { if let Some(type_) = type_ { - if let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &type_.node { + if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &type_.as_ref() { for type_ in elts { handled_exceptions.push(type_); } @@ -597,19 +679,19 @@ pub fn extract_handled_exceptions(handlers: &[Excepthandler]) -> Vec<&Expr> { pub fn collect_arg_names<'a>(arguments: &'a Arguments) -> FxHashSet<&'a str> { let mut arg_names: FxHashSet<&'a str> = FxHashSet::default(); for arg in &arguments.posonlyargs { - arg_names.insert(arg.node.arg.as_str()); + arg_names.insert(arg.arg.as_str()); } for arg in &arguments.args { - arg_names.insert(arg.node.arg.as_str()); + arg_names.insert(arg.arg.as_str()); } if let Some(arg) = &arguments.vararg { - arg_names.insert(arg.node.arg.as_str()); + arg_names.insert(arg.arg.as_str()); } for arg in &arguments.kwonlyargs { - arg_names.insert(arg.node.arg.as_str()); + arg_names.insert(arg.arg.as_str()); } if let Some(arg) = &arguments.kwarg { - arg_names.insert(arg.node.arg.as_str()); + arg_names.insert(arg.arg.as_str()); } arg_names } @@ -618,7 +700,7 @@ pub fn collect_arg_names<'a>(arguments: &'a Arguments) -> FxHashSet<&'a str> { /// be used with or without explicit call syntax), return the underlying /// callable. pub fn map_callable(decorator: &Expr) -> &Expr { - if let ExprKind::Call(ast::ExprCall { func, .. }) = &decorator.node { + if let Expr::Call(ast::ExprCall { func, .. }) = decorator { func } else { decorator @@ -626,7 +708,10 @@ pub fn map_callable(decorator: &Expr) -> &Expr { } /// Returns `true` if a statement or expression includes at least one comment. -pub fn has_comments(located: &Attributed, locator: &Locator) -> bool { +pub fn has_comments(located: &T, locator: &Locator) -> bool +where + T: Ranged, +{ let start = if has_leading_content(located, locator) { located.start() } else { @@ -668,8 +753,8 @@ where F: Fn(&str) -> bool, { any_over_body(body, &|expr| { - if let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node { - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { + if let Expr::Call(ast::ExprCall { func, .. }) = expr { + if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { if matches!(id.as_str(), "locals" | "globals" | "vars" | "exec" | "eval") { if is_builtin(id.as_str()) { return true; @@ -832,11 +917,14 @@ where 'b: 'a, { fn visit_stmt(&mut self, stmt: &'b Stmt) { - match &stmt.node { - StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_) => { + match stmt { + Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) => { // Don't recurse. } - StmtKind::Return(ast::StmtReturn { value }) => self.returns.push(value.as_deref()), + Stmt::Return(ast::StmtReturn { + value, + range: _range, + }) => self.returns.push(value.as_deref()), _ => walk_stmt(self, stmt), } } @@ -853,28 +941,32 @@ where 'b: 'a, { fn visit_stmt(&mut self, stmt: &'b Stmt) { - match &stmt.node { - StmtKind::Raise(ast::StmtRaise { exc, cause }) => { + match stmt { + Stmt::Raise(ast::StmtRaise { + exc, + cause, + range: _range, + }) => { self.raises .push((stmt.range(), exc.as_deref(), cause.as_deref())); } - StmtKind::ClassDef(_) - | StmtKind::FunctionDef(_) - | StmtKind::AsyncFunctionDef(_) - | StmtKind::Try(_) - | StmtKind::TryStar(_) => {} - StmtKind::If(ast::StmtIf { body, orelse, .. }) => { + Stmt::ClassDef(_) + | Stmt::FunctionDef(_) + | Stmt::AsyncFunctionDef(_) + | Stmt::Try(_) + | Stmt::TryStar(_) => {} + Stmt::If(ast::StmtIf { body, orelse, .. }) => { walk_body(self, body); walk_body(self, orelse); } - StmtKind::While(ast::StmtWhile { body, .. }) - | StmtKind::With(ast::StmtWith { body, .. }) - | StmtKind::AsyncWith(ast::StmtAsyncWith { body, .. }) - | StmtKind::For(ast::StmtFor { body, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { body, .. }) => { + Stmt::While(ast::StmtWhile { body, .. }) + | Stmt::With(ast::StmtWith { body, .. }) + | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) + | Stmt::For(ast::StmtFor { body, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { body, .. }) => { walk_body(self, body); } - StmtKind::Match(ast::StmtMatch { cases, .. }) => { + Stmt::Match(ast::StmtMatch { cases, .. }) => { for case in cases { walk_body(self, &case.body); } @@ -891,13 +983,16 @@ struct GlobalStatementVisitor<'a> { impl<'a> StatementVisitor<'a> for GlobalStatementVisitor<'a> { fn visit_stmt(&mut self, stmt: &'a Stmt) { - match &stmt.node { - StmtKind::Global(ast::StmtGlobal { names }) => { + match stmt { + Stmt::Global(ast::StmtGlobal { + names, + range: _range, + }) => { for name in names { self.globals.insert(name.as_str(), stmt); } } - StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_) | StmtKind::ClassDef(_) => { + Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) | Stmt::ClassDef(_) => { // Don't recurse. } _ => walk_stmt(self, stmt), @@ -914,15 +1009,21 @@ pub fn extract_globals(body: &[Stmt]) -> FxHashMap<&str, &Stmt> { visitor.globals } -/// Return `true` if a [`Attributed`] has leading content. -pub fn has_leading_content(located: &Attributed, locator: &Locator) -> bool { +/// Return `true` if a [`Ranged`] has leading content. +pub fn has_leading_content(located: &T, locator: &Locator) -> bool +where + T: Ranged, +{ let line_start = locator.line_start(located.start()); let leading = &locator.contents()[TextRange::new(line_start, located.start())]; leading.chars().any(|char| !char.is_whitespace()) } -/// Return `true` if a [`Attributed`] has trailing content. -pub fn has_trailing_content(located: &Attributed, locator: &Locator) -> bool { +/// Return `true` if a [`Ranged`] has trailing content. +pub fn has_trailing_content(located: &T, locator: &Locator) -> bool +where + T: Ranged, +{ let line_end = locator.line_end(located.end()); let trailing = &locator.contents()[TextRange::new(located.end(), line_end)]; @@ -937,11 +1038,11 @@ pub fn has_trailing_content(located: &Attributed, locator: &Locator) -> bo false } -/// If a [`Attributed`] has a trailing comment, return the index of the hash. -pub fn trailing_comment_start_offset( - located: &Attributed, - locator: &Locator, -) -> Option { +/// If a [`Ranged`] has a trailing comment, return the index of the hash. +pub fn trailing_comment_start_offset(located: &T, locator: &Locator) -> Option +where + T: Ranged, +{ let line_end = locator.line_end(located.end()); let trailing = &locator.contents()[TextRange::new(located.end(), line_end)]; @@ -1007,8 +1108,8 @@ pub fn match_parens(start: TextSize, locator: &Locator) -> Option { /// rather than that of the entire function or class body. pub fn identifier_range(stmt: &Stmt, locator: &Locator) -> TextRange { if matches!( - stmt.node, - StmtKind::ClassDef(_) | StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_) + stmt, + Stmt::ClassDef(_) | Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) ) { let contents = &locator.contents()[stmt.range()]; @@ -1025,9 +1126,12 @@ pub fn identifier_range(stmt: &Stmt, locator: &Locator) -> TextRange { /// Return the ranges of [`Tok::Name`] tokens within a specified node. pub fn find_names<'a, T>( - located: &'a Attributed, + located: &'a T, locator: &'a Locator, -) -> impl Iterator + 'a { +) -> impl Iterator + 'a +where + T: Ranged, +{ let contents = locator.slice(located.range()); lexer::lex_starts_at(contents, Mode::Module, located.start()) @@ -1038,8 +1142,12 @@ pub fn find_names<'a, T>( /// Return the `Range` of `name` in `Excepthandler`. pub fn excepthandler_name_range(handler: &Excepthandler, locator: &Locator) -> Option { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { name, type_, body }) = - &handler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { + name, + type_, + body, + range: _range, + }) = handler; match (name, type_) { (Some(_), Some(type_)) => { @@ -1059,8 +1167,7 @@ pub fn excepthandler_name_range(handler: &Excepthandler, locator: &Locator) -> O /// Return the `Range` of `except` in `Excepthandler`. pub fn except_range(handler: &Excepthandler, locator: &Locator) -> TextRange { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { body, type_, .. }) = - &handler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { body, type_, .. }) = handler; let end = if let Some(type_) = type_ { type_.end() } else { @@ -1077,10 +1184,10 @@ pub fn except_range(handler: &Excepthandler, locator: &Locator) -> TextRange { /// Return the `Range` of `else` in `For`, `AsyncFor`, and `While` statements. pub fn else_range(stmt: &Stmt, locator: &Locator) -> Option { - match &stmt.node { - StmtKind::For(ast::StmtFor { body, orelse, .. }) - | StmtKind::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) - | StmtKind::While(ast::StmtWhile { body, orelse, .. }) + match stmt { + Stmt::For(ast::StmtFor { body, orelse, .. }) + | Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) + | Stmt::While(ast::StmtWhile { body, orelse, .. }) if !orelse.is_empty() => { let body_end = body.last().expect("Expected body to be non-empty").end(); @@ -1111,17 +1218,14 @@ pub fn first_colon_range(range: TextRange, locator: &Locator) -> Option Option { - let StmtKind::If(ast::StmtIf { body, orelse, .. } )= &stmt.node else { + let Stmt::If(ast::StmtIf { body, orelse, .. } )= stmt else { return None; }; let start = body.last().expect("Expected body to be non-empty").end(); let end = match &orelse[..] { - [Stmt { - node: StmtKind::If(ast::StmtIf { test, .. }), - .. - }] => test.start(), + [Stmt::If(ast::StmtIf { test, .. })] => test.start(), [stmt, ..] => stmt.start(), _ => return None, }; @@ -1175,11 +1279,15 @@ pub fn followed_by_multi_statement_line(stmt: &Stmt, locator: &Locator) -> bool } /// Return `true` if a `Stmt` is a docstring. -pub const fn is_docstring_stmt(stmt: &Stmt) -> bool { - if let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node { +pub fn is_docstring_stmt(stmt: &Stmt) -> bool { + if let Stmt::Expr(ast::StmtExpr { + value, + range: _range, + }) = stmt + { matches!( - value.node, - ExprKind::Constant(ast::ExprConstant { + value.as_ref(), + Expr::Constant(ast::ExprConstant { value: Constant::Str { .. }, .. }) @@ -1203,13 +1311,13 @@ impl<'a> SimpleCallArgs<'a> { ) -> Self { let args = args .into_iter() - .take_while(|arg| !matches!(arg.node, ExprKind::Starred(_))) + .take_while(|arg| !matches!(arg, Expr::Starred(_))) .collect(); let kwargs = keywords .into_iter() .filter_map(|keyword| { - let node = &keyword.node; + let node = keyword; node.arg.as_ref().map(|arg| (arg.as_str(), &node.value)) }) .collect(); @@ -1246,14 +1354,15 @@ impl<'a> SimpleCallArgs<'a> { /// Check if a node is parent of a conditional branch. pub fn on_conditional_branch<'a>(parents: &mut impl Iterator) -> bool { parents.any(|parent| { - if matches!( - parent.node, - StmtKind::If(_) | StmtKind::While(_) | StmtKind::Match(_) - ) { + if matches!(parent, Stmt::If(_) | Stmt::While(_) | Stmt::Match(_)) { return true; } - if let StmtKind::Expr(ast::StmtExpr { value }) = &parent.node { - if matches!(value.node, ExprKind::IfExp(_)) { + if let Stmt::Expr(ast::StmtExpr { + value, + range: _range, + }) = parent + { + if matches!(value.as_ref(), Expr::IfExp(_)) { return true; } } @@ -1265,22 +1374,18 @@ pub fn on_conditional_branch<'a>(parents: &mut impl Iterator) - pub fn in_nested_block<'a>(mut parents: impl Iterator) -> bool { parents.any(|parent| { matches!( - parent.node, - StmtKind::Try(_) - | StmtKind::TryStar(_) - | StmtKind::If(_) - | StmtKind::With(_) - | StmtKind::Match(_) + parent, + Stmt::Try(_) | Stmt::TryStar(_) | Stmt::If(_) | Stmt::With(_) | Stmt::Match(_) ) }) } /// Check if a node represents an unpacking assignment. pub fn is_unpacking_assignment(parent: &Stmt, child: &Expr) -> bool { - match &parent.node { - StmtKind::With(ast::StmtWith { items, .. }) => items.iter().any(|item| { + match parent { + Stmt::With(ast::StmtWith { items, .. }) => items.iter().any(|item| { if let Some(optional_vars) = &item.optional_vars { - if matches!(optional_vars.node, ExprKind::Tuple(_)) { + if matches!(optional_vars.as_ref(), Expr::Tuple(_)) { if any_over_expr(optional_vars, &|expr| expr == child) { return true; } @@ -1288,29 +1393,24 @@ pub fn is_unpacking_assignment(parent: &Stmt, child: &Expr) -> bool { } false }), - StmtKind::Assign(ast::StmtAssign { targets, value, .. }) => { + Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { // In `(a, b) = (1, 2)`, `(1, 2)` is the target, and it is a tuple. let value_is_tuple = matches!( - &value.node, - ExprKind::Set(_) | ExprKind::List(_) | ExprKind::Tuple(_) + value.as_ref(), + Expr::Set(_) | Expr::List(_) | Expr::Tuple(_) ); // In `(a, b) = coords = (1, 2)`, `(a, b)` and `coords` are the targets, and // `(a, b)` is a tuple. (We use "tuple" as a placeholder for any // unpackable expression.) - let targets_are_tuples = targets.iter().all(|item| { - matches!( - item.node, - ExprKind::Set(_) | ExprKind::List(_) | ExprKind::Tuple(_) - ) - }); + let targets_are_tuples = targets + .iter() + .all(|item| matches!(item, Expr::Set(_) | Expr::List(_) | Expr::Tuple(_))); // If we're looking at `a` in `(a, b) = coords = (1, 2)`, then we should // identify that the current expression is in a tuple. let child_in_tuple = targets_are_tuples || targets.iter().any(|item| { - matches!( - item.node, - ExprKind::Set(_) | ExprKind::List(_) | ExprKind::Tuple(_) - ) && any_over_expr(item, &|expr| expr == child) + matches!(item, Expr::Set(_) | Expr::List(_) | Expr::Tuple(_)) + && any_over_expr(item, &|expr| expr == child) }); // If our child is a tuple, and value is not, it's always an unpacking @@ -1340,7 +1440,20 @@ pub fn is_unpacking_assignment(parent: &Stmt, child: &Expr) -> bool { } } -pub type AttributedCmpop = Attributed; +#[derive(Clone, PartialEq, Debug)] +pub struct LocatedCmpop { + pub range: TextRange, + pub op: Cmpop, +} + +impl LocatedCmpop { + fn new>(range: T, op: Cmpop) -> Self { + Self { + range: range.into(), + op, + } + } +} /// Extract all [`Cmpop`] operators from a source code snippet, with appropriate /// ranges. @@ -1348,9 +1461,9 @@ pub type AttributedCmpop = Attributed; /// `RustPython` doesn't include line and column information on [`Cmpop`] nodes. /// `CPython` doesn't either. This method iterates over the token stream and /// re-identifies [`Cmpop`] nodes, annotating them with valid ranges. -pub fn locate_cmpops(contents: &str) -> Vec { +pub fn locate_cmpops(contents: &str) -> Vec { let mut tok_iter = lexer::lex(contents, Mode::Module).flatten().peekable(); - let mut ops: Vec = vec![]; + let mut ops: Vec = vec![]; let mut count: usize = 0; loop { let Some((tok, range)) = tok_iter.next() else { @@ -1369,42 +1482,45 @@ pub fn locate_cmpops(contents: &str) -> Vec { if let Some((_, next_range)) = tok_iter.next_if(|(tok, _)| matches!(tok, Tok::In)) { - ops.push(AttributedCmpop::new( - range.start()..next_range.end(), + ops.push(LocatedCmpop::new( + TextRange::new(range.start(), next_range.end()), Cmpop::NotIn, )); } } Tok::In => { - ops.push(AttributedCmpop::new(range, Cmpop::In)); + ops.push(LocatedCmpop::new(range, Cmpop::In)); } Tok::Is => { let op = if let Some((_, next_range)) = tok_iter.next_if(|(tok, _)| matches!(tok, Tok::Not)) { - AttributedCmpop::new(range.start()..next_range.end(), Cmpop::IsNot) + LocatedCmpop::new( + TextRange::new(range.start(), next_range.end()), + Cmpop::IsNot, + ) } else { - AttributedCmpop::new(range, Cmpop::Is) + LocatedCmpop::new(range, Cmpop::Is) }; ops.push(op); } Tok::NotEqual => { - ops.push(AttributedCmpop::new(range, Cmpop::NotEq)); + ops.push(LocatedCmpop::new(range, Cmpop::NotEq)); } Tok::EqEqual => { - ops.push(AttributedCmpop::new(range, Cmpop::Eq)); + ops.push(LocatedCmpop::new(range, Cmpop::Eq)); } Tok::GreaterEqual => { - ops.push(AttributedCmpop::new(range, Cmpop::GtE)); + ops.push(LocatedCmpop::new(range, Cmpop::GtE)); } Tok::Greater => { - ops.push(AttributedCmpop::new(range, Cmpop::Gt)); + ops.push(LocatedCmpop::new(range, Cmpop::Gt)); } Tok::LessEqual => { - ops.push(AttributedCmpop::new(range, Cmpop::LtE)); + ops.push(LocatedCmpop::new(range, Cmpop::LtE)); } Tok::Less => { - ops.push(AttributedCmpop::new(range, Cmpop::Lt)); + ops.push(LocatedCmpop::new(range, Cmpop::Lt)); } _ => {} } @@ -1448,8 +1564,8 @@ impl Truthiness { where F: Fn(&str) -> bool, { - match &expr.node { - ExprKind::Constant(ast::ExprConstant { value, .. }) => match value { + match expr { + Expr::Constant(ast::ExprConstant { value, .. }) => match value { Constant::Bool(value) => Some(*value), Constant::None => Some(false), Constant::Str(string) => Some(!string.is_empty()), @@ -1460,11 +1576,11 @@ impl Truthiness { Constant::Ellipsis => Some(true), Constant::Tuple(elts) => Some(!elts.is_empty()), }, - ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => { + Expr::JoinedStr(ast::ExprJoinedStr { values, range: _range }) => { if values.is_empty() { Some(false) } else if values.iter().any(|value| { - let ExprKind::Constant(ast::ExprConstant { value: Constant::Str(string), .. } )= &value.node else { + let Expr::Constant(ast::ExprConstant { value: Constant::Str(string), .. } )= &value else { return false; }; !string.is_empty() @@ -1474,16 +1590,16 @@ impl Truthiness { None } } - ExprKind::List(ast::ExprList { elts, .. }) - | ExprKind::Set(ast::ExprSet { elts }) - | ExprKind::Tuple(ast::ExprTuple { elts, .. }) => Some(!elts.is_empty()), - ExprKind::Dict(ast::ExprDict { keys, .. }) => Some(!keys.is_empty()), - ExprKind::Call(ast::ExprCall { + Expr::List(ast::ExprList { elts, range: _range, .. }) + | Expr::Set(ast::ExprSet { elts, range: _range }) + | Expr::Tuple(ast::ExprTuple { elts, range: _range,.. }) => Some(!elts.is_empty()), + Expr::Dict(ast::ExprDict { keys, range: _range, .. }) => Some(!keys.is_empty()), + Expr::Call(ast::ExprCall { func, args, - keywords, + keywords, range: _range, }) => { - if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node { + if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { if is_iterable_initializer(id.as_str(), |id| is_builtin(id)) { if args.is_empty() && keywords.is_empty() { Some(false) @@ -1516,7 +1632,7 @@ mod tests { use crate::helpers::{ elif_else_range, else_range, first_colon_range, has_trailing_content, identifier_range, - locate_cmpops, resolve_imported_module_path, AttributedCmpop, + locate_cmpops, resolve_imported_module_path, LocatedCmpop, }; use crate::source_code::Locator; @@ -1736,7 +1852,7 @@ else: fn extract_cmpop_location() { assert_eq!( locate_cmpops("x == 1"), - vec![AttributedCmpop::new( + vec![LocatedCmpop::new( TextSize::from(2)..TextSize::from(4), Cmpop::Eq )] @@ -1744,7 +1860,7 @@ else: assert_eq!( locate_cmpops("x != 1"), - vec![AttributedCmpop::new( + vec![LocatedCmpop::new( TextSize::from(2)..TextSize::from(4), Cmpop::NotEq )] @@ -1752,7 +1868,7 @@ else: assert_eq!( locate_cmpops("x is 1"), - vec![AttributedCmpop::new( + vec![LocatedCmpop::new( TextSize::from(2)..TextSize::from(4), Cmpop::Is )] @@ -1760,7 +1876,7 @@ else: assert_eq!( locate_cmpops("x is not 1"), - vec![AttributedCmpop::new( + vec![LocatedCmpop::new( TextSize::from(2)..TextSize::from(8), Cmpop::IsNot )] @@ -1768,7 +1884,7 @@ else: assert_eq!( locate_cmpops("x in 1"), - vec![AttributedCmpop::new( + vec![LocatedCmpop::new( TextSize::from(2)..TextSize::from(4), Cmpop::In )] @@ -1776,7 +1892,7 @@ else: assert_eq!( locate_cmpops("x not in 1"), - vec![AttributedCmpop::new( + vec![LocatedCmpop::new( TextSize::from(2)..TextSize::from(8), Cmpop::NotIn )] @@ -1784,7 +1900,7 @@ else: assert_eq!( locate_cmpops("x != (1 is not 2)"), - vec![AttributedCmpop::new( + vec![LocatedCmpop::new( TextSize::from(2)..TextSize::from(4), Cmpop::NotEq )] diff --git a/crates/ruff_python_ast/src/relocate.rs b/crates/ruff_python_ast/src/relocate.rs index c4c40eb724..b05b170ec4 100644 --- a/crates/ruff_python_ast/src/relocate.rs +++ b/crates/ruff_python_ast/src/relocate.rs @@ -1,41 +1,61 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::{self, Expr, ExprKind, Keyword}; +use rustpython_parser::ast::{self, Expr, Keyword}; fn relocate_keyword(keyword: &mut Keyword, location: TextRange) { - keyword.range = location; - relocate_expr(&mut keyword.node.value, location); + relocate_expr(&mut keyword.value, location); } /// Change an expression's location (recursively) to match a desired, fixed /// location. pub fn relocate_expr(expr: &mut Expr, location: TextRange) { - expr.range = location; - match &mut expr.node { - ExprKind::BoolOp(ast::ExprBoolOp { values, .. }) => { + match expr { + Expr::BoolOp(ast::ExprBoolOp { values, range, .. }) => { + *range = location; for expr in values { relocate_expr(expr, location); } } - ExprKind::NamedExpr(ast::ExprNamedExpr { target, value }) => { + Expr::NamedExpr(ast::ExprNamedExpr { + target, + value, + range, + }) => { + *range = location; relocate_expr(target, location); relocate_expr(value, location); } - ExprKind::BinOp(ast::ExprBinOp { left, right, .. }) => { + Expr::BinOp(ast::ExprBinOp { + left, right, range, .. + }) => { + *range = location; relocate_expr(left, location); relocate_expr(right, location); } - ExprKind::UnaryOp(ast::ExprUnaryOp { operand, .. }) => { + Expr::UnaryOp(ast::ExprUnaryOp { operand, range, .. }) => { + *range = location; relocate_expr(operand, location); } - ExprKind::Lambda(ast::ExprLambda { body, .. }) => { + Expr::Lambda(ast::ExprLambda { body, range, .. }) => { + *range = location; relocate_expr(body, location); } - ExprKind::IfExp(ast::ExprIfExp { test, body, orelse }) => { + Expr::IfExp(ast::ExprIfExp { + test, + body, + orelse, + range, + }) => { + *range = location; relocate_expr(test, location); relocate_expr(body, location); relocate_expr(orelse, location); } - ExprKind::Dict(ast::ExprDict { keys, values }) => { + Expr::Dict(ast::ExprDict { + keys, + values, + range, + }) => { + *range = location; for expr in keys.iter_mut().flatten() { relocate_expr(expr, location); } @@ -43,44 +63,64 @@ pub fn relocate_expr(expr: &mut Expr, location: TextRange) { relocate_expr(expr, location); } } - ExprKind::Set(ast::ExprSet { elts }) => { + Expr::Set(ast::ExprSet { elts, range }) => { + *range = location; for expr in elts { relocate_expr(expr, location); } } - ExprKind::ListComp(ast::ExprListComp { elt, .. }) => { + Expr::ListComp(ast::ExprListComp { elt, range, .. }) => { + *range = location; relocate_expr(elt, location); } - ExprKind::SetComp(ast::ExprSetComp { elt, .. }) => { + Expr::SetComp(ast::ExprSetComp { elt, range, .. }) => { + *range = location; relocate_expr(elt, location); } - ExprKind::DictComp(ast::ExprDictComp { key, value, .. }) => { + Expr::DictComp(ast::ExprDictComp { + key, value, range, .. + }) => { + *range = location; relocate_expr(key, location); relocate_expr(value, location); } - ExprKind::GeneratorExp(ast::ExprGeneratorExp { elt, .. }) => { + Expr::GeneratorExp(ast::ExprGeneratorExp { elt, range, .. }) => { + *range = location; relocate_expr(elt, location); } - ExprKind::Await(ast::ExprAwait { value }) => relocate_expr(value, location), - ExprKind::Yield(ast::ExprYield { value }) => { + Expr::Await(ast::ExprAwait { value, range }) => { + *range = location; + relocate_expr(value, location); + } + Expr::Yield(ast::ExprYield { value, range }) => { + *range = location; if let Some(expr) = value { relocate_expr(expr, location); } } - ExprKind::YieldFrom(ast::ExprYieldFrom { value }) => relocate_expr(value, location), - ExprKind::Compare(ast::ExprCompare { - left, comparators, .. + Expr::YieldFrom(ast::ExprYieldFrom { value, range }) => { + *range = location; + relocate_expr(value, location); + } + Expr::Compare(ast::ExprCompare { + left, + comparators, + range, + .. }) => { + *range = location; relocate_expr(left, location); for expr in comparators { relocate_expr(expr, location); } } - ExprKind::Call(ast::ExprCall { + Expr::Call(ast::ExprCall { func, args, keywords, + range, }) => { + *range = location; relocate_expr(func, location); for expr in args { relocate_expr(expr, location); @@ -89,42 +129,67 @@ pub fn relocate_expr(expr: &mut Expr, location: TextRange) { relocate_keyword(keyword, location); } } - ExprKind::FormattedValue(ast::ExprFormattedValue { - value, format_spec, .. + Expr::FormattedValue(ast::ExprFormattedValue { + value, + format_spec, + range, + .. }) => { + *range = location; relocate_expr(value, location); if let Some(expr) = format_spec { relocate_expr(expr, location); } } - ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => { + Expr::JoinedStr(ast::ExprJoinedStr { values, range }) => { + *range = location; for expr in values { relocate_expr(expr, location); } } - ExprKind::Constant(_) => {} - ExprKind::Attribute(ast::ExprAttribute { value, .. }) => { + Expr::Constant(ast::ExprConstant { range, .. }) => { + *range = location; + } + Expr::Attribute(ast::ExprAttribute { value, range, .. }) => { + *range = location; relocate_expr(value, location); } - ExprKind::Subscript(ast::ExprSubscript { value, slice, .. }) => { + Expr::Subscript(ast::ExprSubscript { + value, + slice, + range, + .. + }) => { + *range = location; relocate_expr(value, location); relocate_expr(slice, location); } - ExprKind::Starred(ast::ExprStarred { value, .. }) => { + Expr::Starred(ast::ExprStarred { value, range, .. }) => { + *range = location; relocate_expr(value, location); } - ExprKind::Name(_) => {} - ExprKind::List(ast::ExprList { elts, .. }) => { + Expr::Name(ast::ExprName { range, .. }) => { + *range = location; + } + Expr::List(ast::ExprList { elts, range, .. }) => { + *range = location; for expr in elts { relocate_expr(expr, location); } } - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + Expr::Tuple(ast::ExprTuple { elts, range, .. }) => { + *range = location; for expr in elts { relocate_expr(expr, location); } } - ExprKind::Slice(ast::ExprSlice { lower, upper, step }) => { + Expr::Slice(ast::ExprSlice { + lower, + upper, + step, + range, + }) => { + *range = location; if let Some(expr) = lower { relocate_expr(expr, location); } diff --git a/crates/ruff_python_ast/src/source_code/generator.rs b/crates/ruff_python_ast/src/source_code/generator.rs index 5fca7fe87e..83cc4a1ce9 100644 --- a/crates/ruff_python_ast/src/source_code/generator.rs +++ b/crates/ruff_python_ast/src/source_code/generator.rs @@ -5,8 +5,7 @@ use std::ops::Deref; use rustpython_literal::escape::{AsciiEscape, Escape, UnicodeEscape}; use rustpython_parser::ast::{ self, Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, ConversionFlag, - Excepthandler, ExcepthandlerKind, Expr, ExprKind, Identifier, Int, MatchCase, Operator, - Pattern, PatternKind, Stmt, StmtKind, Suite, Withitem, + Excepthandler, Expr, Identifier, Int, MatchCase, Operator, Pattern, Stmt, Suite, Withitem, }; use crate::newlines::LineEnding; @@ -182,8 +181,8 @@ impl<'a> Generator<'a> { }}; } - match &ast.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { + match ast { + Stmt::FunctionDef(ast::StmtFunctionDef { name, args, body, @@ -216,7 +215,7 @@ impl<'a> Generator<'a> { self.newlines(2); } } - StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { + Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, args, body, @@ -248,12 +247,13 @@ impl<'a> Generator<'a> { self.newlines(2); } } - StmtKind::ClassDef(ast::StmtClassDef { + Stmt::ClassDef(ast::StmtClassDef { name, bases, keywords, body, decorator_list, + range: _range, }) => { self.newlines(if self.indent_depth == 0 { 2 } else { 1 }); statement!({ @@ -274,13 +274,13 @@ impl<'a> Generator<'a> { for keyword in keywords { self.p_if(first, "("); self.p_delim(&mut first, ", "); - if let Some(arg) = &keyword.node.arg { + if let Some(arg) = &keyword.arg { self.p_id(arg); self.p("="); } else { self.p("**"); } - self.unparse_expr(&keyword.node.value, precedence::MAX); + self.unparse_expr(&keyword.value, precedence::MAX); } self.p_if(!first, ")"); self.p(":"); @@ -290,7 +290,10 @@ impl<'a> Generator<'a> { self.newlines(2); } } - StmtKind::Return(ast::StmtReturn { value }) => { + Stmt::Return(ast::StmtReturn { + value, + range: _range, + }) => { statement!({ if let Some(expr) = value { self.p("return "); @@ -300,7 +303,10 @@ impl<'a> Generator<'a> { } }); } - StmtKind::Delete(ast::StmtDelete { targets }) => { + Stmt::Delete(ast::StmtDelete { + targets, + range: _range, + }) => { statement!({ self.p("del "); let mut first = true; @@ -310,7 +316,7 @@ impl<'a> Generator<'a> { } }); } - StmtKind::Assign(ast::StmtAssign { targets, value, .. }) => { + Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { statement!({ for target in targets { self.unparse_expr(target, precedence::ASSIGN); @@ -319,7 +325,12 @@ impl<'a> Generator<'a> { self.unparse_expr(value, precedence::ASSIGN); }); } - StmtKind::AugAssign(ast::StmtAugAssign { target, op, value }) => { + Stmt::AugAssign(ast::StmtAugAssign { + target, + op, + value, + range: _range, + }) => { statement!({ self.unparse_expr(target, precedence::AUG_ASSIGN); self.p(" "); @@ -342,14 +353,15 @@ impl<'a> Generator<'a> { self.unparse_expr(value, precedence::AUG_ASSIGN); }); } - StmtKind::AnnAssign(ast::StmtAnnAssign { + Stmt::AnnAssign(ast::StmtAnnAssign { target, annotation, value, simple, + range: _range, }) => { statement!({ - let need_parens = matches!(target.node, ExprKind::Name(_)) && !simple; + let need_parens = matches!(target.as_ref(), Expr::Name(_)) && !simple; self.p_if(need_parens, "("); self.unparse_expr(target, precedence::ANN_ASSIGN); self.p_if(need_parens, ")"); @@ -361,7 +373,7 @@ impl<'a> Generator<'a> { } }); } - StmtKind::For(ast::StmtFor { + Stmt::For(ast::StmtFor { target, iter, body, @@ -383,7 +395,7 @@ impl<'a> Generator<'a> { self.body(orelse); } } - StmtKind::AsyncFor(ast::StmtAsyncFor { + Stmt::AsyncFor(ast::StmtAsyncFor { target, iter, body, @@ -405,7 +417,12 @@ impl<'a> Generator<'a> { self.body(orelse); } } - StmtKind::While(ast::StmtWhile { test, body, orelse }) => { + Stmt::While(ast::StmtWhile { + test, + body, + orelse, + range: _range, + }) => { statement!({ self.p("while "); self.unparse_expr(test, precedence::WHILE); @@ -419,7 +436,12 @@ impl<'a> Generator<'a> { self.body(orelse); } } - StmtKind::If(ast::StmtIf { test, body, orelse }) => { + Stmt::If(ast::StmtIf { + test, + body, + orelse, + range: _range, + }) => { statement!({ self.p("if "); self.unparse_expr(test, precedence::IF); @@ -427,10 +449,16 @@ impl<'a> Generator<'a> { }); self.body(body); - let mut orelse_: &Vec> = orelse; + let mut orelse_: &[Stmt] = orelse; loop { - if orelse_.len() == 1 && matches!(orelse_[0].node, StmtKind::If(_)) { - if let StmtKind::If(ast::StmtIf { body, test, orelse }) = &orelse_[0].node { + if orelse_.len() == 1 && matches!(orelse_[0], Stmt::If(_)) { + if let Stmt::If(ast::StmtIf { + body, + test, + orelse, + range: _range, + }) = &orelse_[0] + { statement!({ self.p("elif "); self.unparse_expr(test, precedence::IF); @@ -450,7 +478,7 @@ impl<'a> Generator<'a> { } } } - StmtKind::With(ast::StmtWith { items, body, .. }) => { + Stmt::With(ast::StmtWith { items, body, .. }) => { statement!({ self.p("with "); let mut first = true; @@ -462,7 +490,7 @@ impl<'a> Generator<'a> { }); self.body(body); } - StmtKind::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => { + Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => { statement!({ self.p("async with "); let mut first = true; @@ -474,7 +502,11 @@ impl<'a> Generator<'a> { }); self.body(body); } - StmtKind::Match(ast::StmtMatch { subject, cases }) => { + Stmt::Match(ast::StmtMatch { + subject, + cases, + range: _range, + }) => { statement!({ self.p("match "); self.unparse_expr(subject, precedence::MAX); @@ -488,7 +520,11 @@ impl<'a> Generator<'a> { self.indent_depth -= 1; } } - StmtKind::Raise(ast::StmtRaise { exc, cause }) => { + Stmt::Raise(ast::StmtRaise { + exc, + cause, + range: _range, + }) => { statement!({ self.p("raise"); if let Some(exc) = exc { @@ -501,11 +537,12 @@ impl<'a> Generator<'a> { } }); } - StmtKind::Try(ast::StmtTry { + Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, + range: _range, }) => { statement!({ self.p("try:"); @@ -531,11 +568,12 @@ impl<'a> Generator<'a> { self.body(finalbody); } } - StmtKind::TryStar(ast::StmtTryStar { + Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, finalbody, + range: _range, }) => { statement!({ self.p("try:"); @@ -561,7 +599,11 @@ impl<'a> Generator<'a> { self.body(finalbody); } } - StmtKind::Assert(ast::StmtAssert { test, msg }) => { + Stmt::Assert(ast::StmtAssert { + test, + msg, + range: _range, + }) => { statement!({ self.p("assert "); self.unparse_expr(test, precedence::ASSERT); @@ -571,7 +613,10 @@ impl<'a> Generator<'a> { } }); } - StmtKind::Import(ast::StmtImport { names }) => { + Stmt::Import(ast::StmtImport { + names, + range: _range, + }) => { statement!({ self.p("import "); let mut first = true; @@ -581,10 +626,11 @@ impl<'a> Generator<'a> { } }); } - StmtKind::ImportFrom(ast::StmtImportFrom { + Stmt::ImportFrom(ast::StmtImportFrom { module, names, level, + range: _range, }) => { statement!({ self.p("from "); @@ -602,7 +648,10 @@ impl<'a> Generator<'a> { } }); } - StmtKind::Global(ast::StmtGlobal { names }) => { + Stmt::Global(ast::StmtGlobal { + names, + range: _range, + }) => { statement!({ self.p("global "); let mut first = true; @@ -612,7 +661,10 @@ impl<'a> Generator<'a> { } }); } - StmtKind::Nonlocal(ast::StmtNonlocal { names }) => { + Stmt::Nonlocal(ast::StmtNonlocal { + names, + range: _range, + }) => { statement!({ self.p("nonlocal "); let mut first = true; @@ -622,22 +674,25 @@ impl<'a> Generator<'a> { } }); } - StmtKind::Expr(ast::StmtExpr { value }) => { + Stmt::Expr(ast::StmtExpr { + value, + range: _range, + }) => { statement!({ self.unparse_expr(value, precedence::EXPR); }); } - StmtKind::Pass => { + Stmt::Pass(_) => { statement!({ self.p("pass"); }); } - StmtKind::Break => { + Stmt::Break(_) => { statement!({ self.p("break"); }); } - StmtKind::Continue => { + Stmt::Continue(_) => { statement!({ self.p("continue"); }); @@ -646,11 +701,12 @@ impl<'a> Generator<'a> { } fn unparse_excepthandler(&mut self, ast: &Excepthandler, star: bool) { - match &ast.node { - ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { + match ast { + Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, name, body, + range: _range, }) => { self.p("except"); if star { @@ -671,14 +727,23 @@ impl<'a> Generator<'a> { } fn unparse_pattern(&mut self, ast: &Pattern) { - match &ast.node { - PatternKind::MatchValue(ast::PatternMatchValue { value }) => { + match ast { + Pattern::MatchValue(ast::PatternMatchValue { + value, + range: _range, + }) => { self.unparse_expr(value, precedence::MAX); } - PatternKind::MatchSingleton(ast::PatternMatchSingleton { value }) => { + Pattern::MatchSingleton(ast::PatternMatchSingleton { + value, + range: _range, + }) => { self.unparse_constant(value); } - PatternKind::MatchSequence(ast::PatternMatchSequence { patterns }) => { + Pattern::MatchSequence(ast::PatternMatchSequence { + patterns, + range: _range, + }) => { self.p("["); let mut first = true; for pattern in patterns { @@ -687,10 +752,11 @@ impl<'a> Generator<'a> { } self.p("]"); } - PatternKind::MatchMapping(ast::PatternMatchMapping { + Pattern::MatchMapping(ast::PatternMatchMapping { keys, patterns, rest, + range: _range, }) => { self.p("{"); let mut first = true; @@ -707,8 +773,11 @@ impl<'a> Generator<'a> { } self.p("}"); } - PatternKind::MatchClass(_) => {} - PatternKind::MatchStar(ast::PatternMatchStar { name }) => { + Pattern::MatchClass(_) => {} + Pattern::MatchStar(ast::PatternMatchStar { + name, + range: _range, + }) => { self.p("*"); if let Some(name) = name { self.p_id(name); @@ -716,7 +785,11 @@ impl<'a> Generator<'a> { self.p("_"); } } - PatternKind::MatchAs(ast::PatternMatchAs { pattern, name }) => { + Pattern::MatchAs(ast::PatternMatchAs { + pattern, + name, + range: _range, + }) => { if let Some(pattern) = pattern { self.unparse_pattern(pattern); self.p(" as "); @@ -727,7 +800,10 @@ impl<'a> Generator<'a> { self.p("_"); } } - PatternKind::MatchOr(ast::PatternMatchOr { patterns }) => { + Pattern::MatchOr(ast::PatternMatchOr { + patterns, + range: _range, + }) => { let mut first = true; for pattern in patterns { self.p_delim(&mut first, " | "); @@ -771,8 +847,12 @@ impl<'a> Generator<'a> { ret }}; } - match &ast.node { - ExprKind::BoolOp(ast::ExprBoolOp { op, values }) => { + match ast { + Expr::BoolOp(ast::ExprBoolOp { + op, + values, + range: _range, + }) => { let (op, prec) = opprec!(bin, op, Boolop, And("and", AND), Or("or", OR)); group_if!(prec, { let mut first = true; @@ -782,14 +862,23 @@ impl<'a> Generator<'a> { } }); } - ExprKind::NamedExpr(ast::ExprNamedExpr { target, value }) => { + Expr::NamedExpr(ast::ExprNamedExpr { + target, + value, + range: _range, + }) => { group_if!(precedence::NAMED_EXPR, { self.unparse_expr(target, precedence::NAMED_EXPR); self.p(" := "); self.unparse_expr(value, precedence::NAMED_EXPR + 1); }); } - ExprKind::BinOp(ast::ExprBinOp { left, op, right }) => { + Expr::BinOp(ast::ExprBinOp { + left, + op, + right, + range: _range, + }) => { let rassoc = matches!(op, Operator::Pow); let (op, prec) = opprec!( bin, @@ -815,7 +904,11 @@ impl<'a> Generator<'a> { self.unparse_expr(right, prec + u8::from(!rassoc)); }); } - ExprKind::UnaryOp(ast::ExprUnaryOp { op, operand }) => { + Expr::UnaryOp(ast::ExprUnaryOp { + op, + operand, + range: _range, + }) => { let (op, prec) = opprec!( un, op, @@ -830,7 +923,11 @@ impl<'a> Generator<'a> { self.unparse_expr(operand, prec); }); } - ExprKind::Lambda(ast::ExprLambda { args, body }) => { + Expr::Lambda(ast::ExprLambda { + args, + body, + range: _range, + }) => { group_if!(precedence::LAMBDA, { let npos = args.args.len() + args.posonlyargs.len(); self.p(if npos > 0 { "lambda " } else { "lambda" }); @@ -839,7 +936,12 @@ impl<'a> Generator<'a> { self.unparse_expr(body, precedence::LAMBDA); }); } - ExprKind::IfExp(ast::ExprIfExp { test, body, orelse }) => { + Expr::IfExp(ast::ExprIfExp { + test, + body, + orelse, + range: _range, + }) => { group_if!(precedence::IF_EXP, { self.unparse_expr(body, precedence::IF_EXP + 1); self.p(" if "); @@ -848,7 +950,11 @@ impl<'a> Generator<'a> { self.unparse_expr(orelse, precedence::IF_EXP); }); } - ExprKind::Dict(ast::ExprDict { keys, values }) => { + Expr::Dict(ast::ExprDict { + keys, + values, + range: _range, + }) => { self.p("{"); let mut first = true; for (k, v) in keys.iter().zip(values) { @@ -864,7 +970,10 @@ impl<'a> Generator<'a> { } self.p("}"); } - ExprKind::Set(ast::ExprSet { elts }) => { + Expr::Set(ast::ExprSet { + elts, + range: _range, + }) => { if elts.is_empty() { self.p("set()"); } else { @@ -877,22 +986,31 @@ impl<'a> Generator<'a> { self.p("}"); } } - ExprKind::ListComp(ast::ExprListComp { elt, generators }) => { + Expr::ListComp(ast::ExprListComp { + elt, + generators, + range: _range, + }) => { self.p("["); self.unparse_expr(elt, precedence::MAX); self.unparse_comp(generators); self.p("]"); } - ExprKind::SetComp(ast::ExprSetComp { elt, generators }) => { + Expr::SetComp(ast::ExprSetComp { + elt, + generators, + range: _range, + }) => { self.p("{"); self.unparse_expr(elt, precedence::MAX); self.unparse_comp(generators); self.p("}"); } - ExprKind::DictComp(ast::ExprDictComp { + Expr::DictComp(ast::ExprDictComp { key, value, generators, + range: _range, }) => { self.p("{"); self.unparse_expr(key, precedence::MAX); @@ -901,19 +1019,29 @@ impl<'a> Generator<'a> { self.unparse_comp(generators); self.p("}"); } - ExprKind::GeneratorExp(ast::ExprGeneratorExp { elt, generators }) => { + Expr::GeneratorExp(ast::ExprGeneratorExp { + elt, + generators, + range: _range, + }) => { self.p("("); self.unparse_expr(elt, precedence::COMMA); self.unparse_comp(generators); self.p(")"); } - ExprKind::Await(ast::ExprAwait { value }) => { + Expr::Await(ast::ExprAwait { + value, + range: _range, + }) => { group_if!(precedence::AWAIT, { self.p("await "); self.unparse_expr(value, precedence::MAX); }); } - ExprKind::Yield(ast::ExprYield { value }) => { + Expr::Yield(ast::ExprYield { + value, + range: _range, + }) => { group_if!(precedence::YIELD, { self.p("yield"); if let Some(value) = value { @@ -922,16 +1050,20 @@ impl<'a> Generator<'a> { } }); } - ExprKind::YieldFrom(ast::ExprYieldFrom { value }) => { + Expr::YieldFrom(ast::ExprYieldFrom { + value, + range: _range, + }) => { group_if!(precedence::YIELD_FROM, { self.p("yield from "); self.unparse_expr(value, precedence::MAX); }); } - ExprKind::Compare(ast::ExprCompare { + Expr::Compare(ast::ExprCompare { left, ops, comparators, + range: _range, }) => { group_if!(precedence::CMP, { let new_lvl = precedence::CMP + 1; @@ -954,18 +1086,20 @@ impl<'a> Generator<'a> { } }); } - ExprKind::Call(ast::ExprCall { + Expr::Call(ast::ExprCall { func, args, keywords, + range: _range, }) => { self.unparse_expr(func, precedence::MAX); self.p("("); if let ( - [Expr { - node: ExprKind::GeneratorExp(ast::ExprGeneratorExp { elt, generators }), - .. - }], + [Expr::GeneratorExp(ast::ExprGeneratorExp { + elt, + generators, + range: _range, + })], [], ) = (&**args, &**keywords) { @@ -980,37 +1114,45 @@ impl<'a> Generator<'a> { } for kw in keywords { self.p_delim(&mut first, ", "); - if let Some(arg) = &kw.node.arg { + if let Some(arg) = &kw.arg { self.p_id(arg); self.p("="); - self.unparse_expr(&kw.node.value, precedence::COMMA); + self.unparse_expr(&kw.value, precedence::COMMA); } else { self.p("**"); - self.unparse_expr(&kw.node.value, precedence::MAX); + self.unparse_expr(&kw.value, precedence::MAX); } } } self.p(")"); } - ExprKind::FormattedValue(ast::ExprFormattedValue { + Expr::FormattedValue(ast::ExprFormattedValue { value, conversion, format_spec, + range: _range, }) => self.unparse_formatted(value, *conversion, format_spec.as_deref()), - ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => { + Expr::JoinedStr(ast::ExprJoinedStr { + values, + range: _range, + }) => { self.unparse_joinedstr(values, false); } - ExprKind::Constant(ast::ExprConstant { value, kind }) => { + Expr::Constant(ast::ExprConstant { + value, + kind, + range: _range, + }) => { if let Some(kind) = kind { self.p(kind); } self.unparse_constant(value); } - ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) => { - if let ExprKind::Constant(ast::ExprConstant { + Expr::Attribute(ast::ExprAttribute { value, attr, .. }) => { + if let Expr::Constant(ast::ExprConstant { value: Constant::Int(_), .. - }) = &value.node + }) = value.as_ref() { self.p("("); self.unparse_expr(value, precedence::MAX); @@ -1021,18 +1163,18 @@ impl<'a> Generator<'a> { }; self.p_id(attr); } - ExprKind::Subscript(ast::ExprSubscript { value, slice, .. }) => { + Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => { self.unparse_expr(value, precedence::MAX); self.p("["); self.unparse_expr(slice, precedence::SUBSCRIPT); self.p("]"); } - ExprKind::Starred(ast::ExprStarred { value, .. }) => { + Expr::Starred(ast::ExprStarred { value, .. }) => { self.p("*"); self.unparse_expr(value, precedence::MAX); } - ExprKind::Name(ast::ExprName { id, .. }) => self.p_id(id), - ExprKind::List(ast::ExprList { elts, .. }) => { + Expr::Name(ast::ExprName { id, .. }) => self.p_id(id), + Expr::List(ast::ExprList { elts, .. }) => { self.p("["); let mut first = true; for elt in elts { @@ -1041,7 +1183,7 @@ impl<'a> Generator<'a> { } self.p("]"); } - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => { + Expr::Tuple(ast::ExprTuple { elts, .. }) => { if elts.is_empty() { self.p("()"); } else { @@ -1055,7 +1197,12 @@ impl<'a> Generator<'a> { }); } } - ExprKind::Slice(ast::ExprSlice { lower, upper, step }) => { + Expr::Slice(ast::ExprSlice { + lower, + upper, + step, + range: _range, + }) => { if let Some(lower) = lower { self.unparse_expr(lower, precedence::SLICE); } @@ -1163,8 +1310,8 @@ impl<'a> Generator<'a> { } fn unparse_arg(&mut self, arg: &Arg) { - self.p_id(&arg.node.arg); - if let Some(ann) = &arg.node.annotation { + self.p_id(&arg.arg); + if let Some(ann) = &arg.annotation { self.p(": "); self.unparse_expr(ann, precedence::COMMA); } @@ -1220,21 +1367,25 @@ impl<'a> Generator<'a> { } fn unparse_fstring_elem(&mut self, expr: &Expr, is_spec: bool) { - match &expr.node { - ExprKind::Constant(ast::ExprConstant { value, .. }) => { + match expr { + Expr::Constant(ast::ExprConstant { value, .. }) => { if let Constant::Str(s) = value { self.unparse_fstring_str(s); } else { unreachable!() } } - ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => { + Expr::JoinedStr(ast::ExprJoinedStr { + values, + range: _range, + }) => { self.unparse_joinedstr(values, is_spec); } - ExprKind::FormattedValue(ast::ExprFormattedValue { + Expr::FormattedValue(ast::ExprFormattedValue { value, conversion, format_spec, + range: _range, }) => self.unparse_formatted(value, *conversion, format_spec.as_deref()), _ => unreachable!(), } @@ -1265,8 +1416,8 @@ impl<'a> Generator<'a> { } fn unparse_alias(&mut self, alias: &Alias) { - self.p_id(&alias.node.name); - if let Some(asname) = &alias.node.asname { + self.p_id(&alias.name); + if let Some(asname) = &alias.asname { self.p(" as "); self.p_id(asname); } diff --git a/crates/ruff_python_ast/src/statement_visitor.rs b/crates/ruff_python_ast/src/statement_visitor.rs index 55121f3cbb..805da33b42 100644 --- a/crates/ruff_python_ast/src/statement_visitor.rs +++ b/crates/ruff_python_ast/src/statement_visitor.rs @@ -1,6 +1,6 @@ //! Specialized AST visitor trait and walk functions that only visit statements. -use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, MatchCase, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Excepthandler, MatchCase, Stmt}; /// A trait for AST visitors that only need to visit statements. pub trait StatementVisitor<'a> { @@ -25,48 +25,49 @@ pub fn walk_body<'a, V: StatementVisitor<'a> + ?Sized>(visitor: &mut V, body: &' } pub fn walk_stmt<'a, V: StatementVisitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { - match &stmt.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { body, .. }) => { + match stmt { + Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) => { visitor.visit_body(body); } - StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) => { + Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) => { visitor.visit_body(body); } - StmtKind::For(ast::StmtFor { body, orelse, .. }) => { + Stmt::For(ast::StmtFor { body, orelse, .. }) => { visitor.visit_body(body); visitor.visit_body(orelse); } - StmtKind::ClassDef(ast::StmtClassDef { body, .. }) => { + Stmt::ClassDef(ast::StmtClassDef { body, .. }) => { visitor.visit_body(body); } - StmtKind::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) => { + Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) => { visitor.visit_body(body); visitor.visit_body(orelse); } - StmtKind::While(ast::StmtWhile { body, orelse, .. }) => { + Stmt::While(ast::StmtWhile { body, orelse, .. }) => { visitor.visit_body(body); visitor.visit_body(orelse); } - StmtKind::If(ast::StmtIf { body, orelse, .. }) => { + Stmt::If(ast::StmtIf { body, orelse, .. }) => { visitor.visit_body(body); visitor.visit_body(orelse); } - StmtKind::With(ast::StmtWith { body, .. }) => { + Stmt::With(ast::StmtWith { body, .. }) => { visitor.visit_body(body); } - StmtKind::AsyncWith(ast::StmtAsyncWith { body, .. }) => { + Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { visitor.visit_body(body); } - StmtKind::Match(ast::StmtMatch { cases, .. }) => { + Stmt::Match(ast::StmtMatch { cases, .. }) => { for match_case in cases { visitor.visit_match_case(match_case); } } - StmtKind::Try(ast::StmtTry { + Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, + range: _range, }) => { visitor.visit_body(body); for excepthandler in handlers { @@ -75,11 +76,12 @@ pub fn walk_stmt<'a, V: StatementVisitor<'a> + ?Sized>(visitor: &mut V, stmt: &' visitor.visit_body(orelse); visitor.visit_body(finalbody); } - StmtKind::TryStar(ast::StmtTryStar { + Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, finalbody, + range: _range, }) => { visitor.visit_body(body); for excepthandler in handlers { @@ -96,8 +98,8 @@ pub fn walk_excepthandler<'a, V: StatementVisitor<'a> + ?Sized>( visitor: &mut V, excepthandler: &'a Excepthandler, ) { - match &excepthandler.node { - ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) => { + match excepthandler { + Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) => { visitor.visit_body(body); } } diff --git a/crates/ruff_python_ast/src/visitor.rs b/crates/ruff_python_ast/src/visitor.rs index caa8ffa3ea..c1a6523b55 100644 --- a/crates/ruff_python_ast/src/visitor.rs +++ b/crates/ruff_python_ast/src/visitor.rs @@ -1,9 +1,8 @@ //! AST visitor trait and walk functions. use rustpython_parser::ast::{ - self, Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, Excepthandler, - ExcepthandlerKind, Expr, ExprContext, ExprKind, Keyword, MatchCase, Operator, Pattern, - PatternKind, Stmt, StmtKind, Unaryop, Withitem, + self, Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, Excepthandler, Expr, + ExprContext, Keyword, MatchCase, Operator, Pattern, Stmt, Unaryop, Withitem, }; /// A trait for AST visitors. Visits all nodes in the AST recursively. @@ -80,8 +79,8 @@ pub fn walk_body<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, body: &'a [Stmt]) } pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { - match &stmt.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { + match stmt { + Stmt::FunctionDef(ast::StmtFunctionDef { args, body, decorator_list, @@ -97,7 +96,7 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { } visitor.visit_body(body); } - StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { + Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { args, body, decorator_list, @@ -113,7 +112,7 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { } visitor.visit_body(body); } - StmtKind::ClassDef(ast::StmtClassDef { + Stmt::ClassDef(ast::StmtClassDef { bases, keywords, body, @@ -131,28 +130,39 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { } visitor.visit_body(body); } - StmtKind::Return(ast::StmtReturn { value }) => { + Stmt::Return(ast::StmtReturn { + value, + range: _range, + }) => { if let Some(expr) = value { visitor.visit_expr(expr); } } - StmtKind::Delete(ast::StmtDelete { targets }) => { + Stmt::Delete(ast::StmtDelete { + targets, + range: _range, + }) => { for expr in targets { visitor.visit_expr(expr); } } - StmtKind::Assign(ast::StmtAssign { targets, value, .. }) => { + Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { visitor.visit_expr(value); for expr in targets { visitor.visit_expr(expr); } } - StmtKind::AugAssign(ast::StmtAugAssign { target, op, value }) => { + Stmt::AugAssign(ast::StmtAugAssign { + target, + op, + value, + range: _range, + }) => { visitor.visit_expr(target); visitor.visit_operator(op); visitor.visit_expr(value); } - StmtKind::AnnAssign(ast::StmtAnnAssign { + Stmt::AnnAssign(ast::StmtAnnAssign { target, annotation, value, @@ -164,7 +174,7 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { } visitor.visit_expr(target); } - StmtKind::For(ast::StmtFor { + Stmt::For(ast::StmtFor { target, iter, body, @@ -176,7 +186,7 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { visitor.visit_body(body); visitor.visit_body(orelse); } - StmtKind::AsyncFor(ast::StmtAsyncFor { + Stmt::AsyncFor(ast::StmtAsyncFor { target, iter, body, @@ -188,35 +198,53 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { visitor.visit_body(body); visitor.visit_body(orelse); } - StmtKind::While(ast::StmtWhile { test, body, orelse }) => { + Stmt::While(ast::StmtWhile { + test, + body, + orelse, + range: _range, + }) => { visitor.visit_expr(test); visitor.visit_body(body); visitor.visit_body(orelse); } - StmtKind::If(ast::StmtIf { test, body, orelse }) => { + Stmt::If(ast::StmtIf { + test, + body, + orelse, + range: _range, + }) => { visitor.visit_expr(test); visitor.visit_body(body); visitor.visit_body(orelse); } - StmtKind::With(ast::StmtWith { items, body, .. }) => { + Stmt::With(ast::StmtWith { items, body, .. }) => { for withitem in items { visitor.visit_withitem(withitem); } visitor.visit_body(body); } - StmtKind::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => { + Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => { for withitem in items { visitor.visit_withitem(withitem); } visitor.visit_body(body); } - StmtKind::Match(ast::StmtMatch { subject, cases }) => { + Stmt::Match(ast::StmtMatch { + subject, + cases, + range: _range, + }) => { visitor.visit_expr(subject); for match_case in cases { visitor.visit_match_case(match_case); } } - StmtKind::Raise(ast::StmtRaise { exc, cause }) => { + Stmt::Raise(ast::StmtRaise { + exc, + cause, + range: _range, + }) => { if let Some(expr) = exc { visitor.visit_expr(expr); }; @@ -224,11 +252,12 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { visitor.visit_expr(expr); }; } - StmtKind::Try(ast::StmtTry { + Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, + range: _range, }) => { visitor.visit_body(body); for excepthandler in handlers { @@ -237,11 +266,12 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { visitor.visit_body(orelse); visitor.visit_body(finalbody); } - StmtKind::TryStar(ast::StmtTryStar { + Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, finalbody, + range: _range, }) => { visitor.visit_body(body); for excepthandler in handlers { @@ -250,62 +280,100 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { visitor.visit_body(orelse); visitor.visit_body(finalbody); } - StmtKind::Assert(ast::StmtAssert { test, msg }) => { + Stmt::Assert(ast::StmtAssert { + test, + msg, + range: _range, + }) => { visitor.visit_expr(test); if let Some(expr) = msg { visitor.visit_expr(expr); } } - StmtKind::Import(ast::StmtImport { names }) => { + Stmt::Import(ast::StmtImport { + names, + range: _range, + }) => { for alias in names { visitor.visit_alias(alias); } } - StmtKind::ImportFrom(ast::StmtImportFrom { names, .. }) => { + Stmt::ImportFrom(ast::StmtImportFrom { names, .. }) => { for alias in names { visitor.visit_alias(alias); } } - StmtKind::Global(_) => {} - StmtKind::Nonlocal(_) => {} - StmtKind::Expr(ast::StmtExpr { value }) => visitor.visit_expr(value), - StmtKind::Pass => {} - StmtKind::Break => {} - StmtKind::Continue => {} + Stmt::Global(_) => {} + Stmt::Nonlocal(_) => {} + Stmt::Expr(ast::StmtExpr { + value, + range: _range, + }) => visitor.visit_expr(value), + Stmt::Pass(_) | Stmt::Break(_) | Stmt::Continue(_) => {} } } pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { - match &expr.node { - ExprKind::BoolOp(ast::ExprBoolOp { op, values }) => { + match expr { + Expr::BoolOp(ast::ExprBoolOp { + op, + values, + range: _range, + }) => { visitor.visit_boolop(op); for expr in values { visitor.visit_expr(expr); } } - ExprKind::NamedExpr(ast::ExprNamedExpr { target, value }) => { + Expr::NamedExpr(ast::ExprNamedExpr { + target, + value, + range: _range, + }) => { visitor.visit_expr(value); visitor.visit_expr(target); } - ExprKind::BinOp(ast::ExprBinOp { left, op, right }) => { + Expr::BinOp(ast::ExprBinOp { + left, + op, + right, + range: _range, + }) => { visitor.visit_expr(left); visitor.visit_operator(op); visitor.visit_expr(right); } - ExprKind::UnaryOp(ast::ExprUnaryOp { op, operand }) => { + Expr::UnaryOp(ast::ExprUnaryOp { + op, + operand, + range: _range, + }) => { visitor.visit_unaryop(op); visitor.visit_expr(operand); } - ExprKind::Lambda(ast::ExprLambda { args, body }) => { + Expr::Lambda(ast::ExprLambda { + args, + body, + range: _range, + }) => { visitor.visit_arguments(args); visitor.visit_expr(body); } - ExprKind::IfExp(ast::ExprIfExp { test, body, orelse }) => { + Expr::IfExp(ast::ExprIfExp { + test, + body, + orelse, + range: _range, + }) => { visitor.visit_expr(test); visitor.visit_expr(body); visitor.visit_expr(orelse); } - ExprKind::Dict(ast::ExprDict { keys, values }) => { + Expr::Dict(ast::ExprDict { + keys, + values, + range: _range, + }) => { for expr in keys.iter().flatten() { visitor.visit_expr(expr); } @@ -313,27 +381,39 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { visitor.visit_expr(expr); } } - ExprKind::Set(ast::ExprSet { elts }) => { + Expr::Set(ast::ExprSet { + elts, + range: _range, + }) => { for expr in elts { visitor.visit_expr(expr); } } - ExprKind::ListComp(ast::ExprListComp { elt, generators }) => { + Expr::ListComp(ast::ExprListComp { + elt, + generators, + range: _range, + }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); } visitor.visit_expr(elt); } - ExprKind::SetComp(ast::ExprSetComp { elt, generators }) => { + Expr::SetComp(ast::ExprSetComp { + elt, + generators, + range: _range, + }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); } visitor.visit_expr(elt); } - ExprKind::DictComp(ast::ExprDictComp { + Expr::DictComp(ast::ExprDictComp { key, value, generators, + range: _range, }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); @@ -341,23 +421,37 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { visitor.visit_expr(key); visitor.visit_expr(value); } - ExprKind::GeneratorExp(ast::ExprGeneratorExp { elt, generators }) => { + Expr::GeneratorExp(ast::ExprGeneratorExp { + elt, + generators, + range: _range, + }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); } visitor.visit_expr(elt); } - ExprKind::Await(ast::ExprAwait { value }) => visitor.visit_expr(value), - ExprKind::Yield(ast::ExprYield { value }) => { + Expr::Await(ast::ExprAwait { + value, + range: _range, + }) => visitor.visit_expr(value), + Expr::Yield(ast::ExprYield { + value, + range: _range, + }) => { if let Some(expr) = value { visitor.visit_expr(expr); } } - ExprKind::YieldFrom(ast::ExprYieldFrom { value }) => visitor.visit_expr(value), - ExprKind::Compare(ast::ExprCompare { + Expr::YieldFrom(ast::ExprYieldFrom { + value, + range: _range, + }) => visitor.visit_expr(value), + Expr::Compare(ast::ExprCompare { left, ops, comparators, + range: _range, }) => { visitor.visit_expr(left); for cmpop in ops { @@ -367,10 +461,11 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { visitor.visit_expr(expr); } } - ExprKind::Call(ast::ExprCall { + Expr::Call(ast::ExprCall { func, args, keywords, + range: _range, }) => { visitor.visit_expr(func); for expr in args { @@ -380,7 +475,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { visitor.visit_keyword(keyword); } } - ExprKind::FormattedValue(ast::ExprFormattedValue { + Expr::FormattedValue(ast::ExprFormattedValue { value, format_spec, .. }) => { visitor.visit_expr(value); @@ -388,41 +483,66 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { visitor.visit_format_spec(expr); } } - ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => { + Expr::JoinedStr(ast::ExprJoinedStr { + values, + range: _range, + }) => { for expr in values { visitor.visit_expr(expr); } } - ExprKind::Constant(ast::ExprConstant { value, .. }) => visitor.visit_constant(value), - ExprKind::Attribute(ast::ExprAttribute { value, ctx, .. }) => { + Expr::Constant(ast::ExprConstant { value, .. }) => visitor.visit_constant(value), + Expr::Attribute(ast::ExprAttribute { value, ctx, .. }) => { visitor.visit_expr(value); visitor.visit_expr_context(ctx); } - ExprKind::Subscript(ast::ExprSubscript { value, slice, ctx }) => { + Expr::Subscript(ast::ExprSubscript { + value, + slice, + ctx, + range: _range, + }) => { visitor.visit_expr(value); visitor.visit_expr(slice); visitor.visit_expr_context(ctx); } - ExprKind::Starred(ast::ExprStarred { value, ctx }) => { + Expr::Starred(ast::ExprStarred { + value, + ctx, + range: _range, + }) => { visitor.visit_expr(value); visitor.visit_expr_context(ctx); } - ExprKind::Name(ast::ExprName { ctx, .. }) => { + Expr::Name(ast::ExprName { ctx, .. }) => { visitor.visit_expr_context(ctx); } - ExprKind::List(ast::ExprList { elts, ctx }) => { + Expr::List(ast::ExprList { + elts, + ctx, + range: _range, + }) => { for expr in elts { visitor.visit_expr(expr); } visitor.visit_expr_context(ctx); } - ExprKind::Tuple(ast::ExprTuple { elts, ctx }) => { + Expr::Tuple(ast::ExprTuple { + elts, + ctx, + range: _range, + }) => { for expr in elts { visitor.visit_expr(expr); } visitor.visit_expr_context(ctx); } - ExprKind::Slice(ast::ExprSlice { lower, upper, step }) => { + Expr::Slice(ast::ExprSlice { + lower, + upper, + step, + range: _range, + }) => { if let Some(expr) = lower { visitor.visit_expr(expr); } @@ -459,10 +579,8 @@ pub fn walk_excepthandler<'a, V: Visitor<'a> + ?Sized>( visitor: &mut V, excepthandler: &'a Excepthandler, ) { - match &excepthandler.node { - ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { - type_, body, .. - }) => { + match excepthandler { + Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, body, .. }) => { if let Some(expr) = type_ { visitor.visit_expr(expr); } @@ -496,13 +614,13 @@ pub fn walk_arguments<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arguments: & } pub fn walk_arg<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arg: &'a Arg) { - if let Some(expr) = &arg.node.annotation { + if let Some(expr) = &arg.annotation { visitor.visit_annotation(expr); } } pub fn walk_keyword<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, keyword: &'a Keyword) { - visitor.visit_expr(&keyword.node.value); + visitor.visit_expr(&keyword.value); } pub fn walk_withitem<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, withitem: &'a Withitem) { @@ -521,17 +639,26 @@ pub fn walk_match_case<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, match_case: } pub fn walk_pattern<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, pattern: &'a Pattern) { - match &pattern.node { - PatternKind::MatchValue(ast::PatternMatchValue { value }) => visitor.visit_expr(value), - PatternKind::MatchSingleton(ast::PatternMatchSingleton { value }) => { + match pattern { + Pattern::MatchValue(ast::PatternMatchValue { + value, + range: _range, + }) => visitor.visit_expr(value), + Pattern::MatchSingleton(ast::PatternMatchSingleton { + value, + range: _range, + }) => { visitor.visit_constant(value); } - PatternKind::MatchSequence(ast::PatternMatchSequence { patterns }) => { + Pattern::MatchSequence(ast::PatternMatchSequence { + patterns, + range: _range, + }) => { for pattern in patterns { visitor.visit_pattern(pattern); } } - PatternKind::MatchMapping(ast::PatternMatchMapping { keys, patterns, .. }) => { + Pattern::MatchMapping(ast::PatternMatchMapping { keys, patterns, .. }) => { for expr in keys { visitor.visit_expr(expr); } @@ -539,7 +666,7 @@ pub fn walk_pattern<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, pattern: &'a P visitor.visit_pattern(pattern); } } - PatternKind::MatchClass(ast::PatternMatchClass { + Pattern::MatchClass(ast::PatternMatchClass { cls, patterns, kwd_patterns, @@ -554,13 +681,16 @@ pub fn walk_pattern<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, pattern: &'a P visitor.visit_pattern(pattern); } } - PatternKind::MatchStar(_) => {} - PatternKind::MatchAs(ast::PatternMatchAs { pattern, .. }) => { + Pattern::MatchStar(_) => {} + Pattern::MatchAs(ast::PatternMatchAs { pattern, .. }) => { if let Some(pattern) = pattern { visitor.visit_pattern(pattern); } } - PatternKind::MatchOr(ast::PatternMatchOr { patterns }) => { + Pattern::MatchOr(ast::PatternMatchOr { + patterns, + range: _range, + }) => { for pattern in patterns { visitor.visit_pattern(pattern); } diff --git a/crates/ruff_python_ast/src/whitespace.rs b/crates/ruff_python_ast/src/whitespace.rs index 4757381d7d..a3ee25c29b 100644 --- a/crates/ruff_python_ast/src/whitespace.rs +++ b/crates/ruff_python_ast/src/whitespace.rs @@ -1,10 +1,13 @@ use ruff_text_size::TextRange; -use rustpython_parser::ast::Attributed; +use rustpython_parser::ast::Ranged; use crate::source_code::Locator; /// Extract the leading indentation from a line. -pub fn indentation<'a, T>(locator: &'a Locator, located: &Attributed) -> Option<&'a str> { +pub fn indentation<'a, T>(locator: &'a Locator, located: &T) -> Option<&'a str> +where + T: Ranged, +{ let line_start = locator.line_start(located.start()); let indentation = &locator.contents()[TextRange::new(line_start, located.start())]; diff --git a/crates/ruff_python_formatter/src/cst/helpers.rs b/crates/ruff_python_formatter/src/cst/helpers.rs index 131a24342a..4c025f9bc0 100644 --- a/crates/ruff_python_formatter/src/cst/helpers.rs +++ b/crates/ruff_python_formatter/src/cst/helpers.rs @@ -1,5 +1,6 @@ use ruff_python_ast::source_code::Locator; use ruff_text_size::{TextLen, TextRange, TextSize}; +use rustpython_parser::ast::Ranged; /// Return `true` if the given string is a radix literal (e.g., `0b101`). pub(crate) fn is_radix_literal(content: &str) -> bool { @@ -127,7 +128,7 @@ pub(crate) fn expand_indented_block( /// Return true if the `orelse` block of an `if` statement is an `elif` statement. pub(crate) fn is_elif(orelse: &[rustpython_parser::ast::Stmt], locator: &Locator) -> bool { - if orelse.len() == 1 && matches!(orelse[0].node, rustpython_parser::ast::StmtKind::If { .. }) { + if orelse.len() == 1 && matches!(orelse[0], rustpython_parser::ast::Stmt::If { .. }) { let contents = locator.after(orelse[0].start()); if contents.starts_with("elif") { return true; diff --git a/crates/ruff_python_formatter/src/cst/mod.rs b/crates/ruff_python_formatter/src/cst/mod.rs index a250f79660..f40292c14d 100644 --- a/crates/ruff_python_formatter/src/cst/mod.rs +++ b/crates/ruff_python_formatter/src/cst/mod.rs @@ -5,7 +5,7 @@ use std::ops::Deref; use itertools::Itertools; use ruff_text_size::{TextRange, TextSize}; -use rustpython_parser::ast::Constant; +use rustpython_parser::ast::{Constant, Ranged}; use rustpython_parser::{ast, Mode}; use ruff_python_ast::source_code::Locator; @@ -575,9 +575,8 @@ impl From<(rustpython_parser::ast::Alias, &Locator<'_>)> for Alias { Alias { range: alias.range(), node: AliasData { - name: alias.node.name.to_string(), + name: alias.name.to_string(), asname: alias - .node .asname .as_ref() .map(rustpython_parser::ast::Identifier::to_string), @@ -601,17 +600,17 @@ impl From<(rustpython_parser::ast::Withitem, &Locator<'_>)> for Withitem { impl From<(rustpython_parser::ast::Excepthandler, &Locator<'_>)> for Excepthandler { fn from((excepthandler, locator): (rustpython_parser::ast::Excepthandler, &Locator)) -> Self { - let rustpython_parser::ast::ExcepthandlerKind::ExceptHandler( - ast::ExcepthandlerExceptHandler { type_, name, body }, - ) = excepthandler.node; + let rustpython_parser::ast::Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { + type_, + name, + body, + range, + }) = excepthandler; // Find the start and end of the `body`. let body = { - let body_range = expand_indented_block( - excepthandler.range.start(), - body.last().unwrap().end(), - locator, - ); + let body_range = + expand_indented_block(range.start(), body.last().unwrap().end(), locator); Body { range: body_range, node: body @@ -624,7 +623,7 @@ impl From<(rustpython_parser::ast::Excepthandler, &Locator<'_>)> for Excepthandl }; Excepthandler { - range: TextRange::new(excepthandler.range.start(), body.end()), + range: TextRange::new(range.start(), body.end()), node: ExcepthandlerKind::ExceptHandler { type_: type_.map(|type_| Box::new((*type_, locator).into())), name: name.map(Into::into), @@ -640,28 +639,29 @@ impl From<(rustpython_parser::ast::Pattern, &Locator<'_>)> for Pattern { fn from((pattern, locator): (rustpython_parser::ast::Pattern, &Locator)) -> Self { Pattern { range: pattern.range(), - node: match pattern.node { - rustpython_parser::ast::PatternKind::MatchValue( - rustpython_parser::ast::PatternMatchValue { value }, + node: match pattern { + rustpython_parser::ast::Pattern::MatchValue( + rustpython_parser::ast::PatternMatchValue { value, range: _ }, ) => PatternKind::MatchValue { value: Box::new((*value, locator).into()), }, - rustpython_parser::ast::PatternKind::MatchSingleton( - rustpython_parser::ast::PatternMatchSingleton { value }, + rustpython_parser::ast::Pattern::MatchSingleton( + rustpython_parser::ast::PatternMatchSingleton { value, range: _ }, ) => PatternKind::MatchSingleton { value }, - rustpython_parser::ast::PatternKind::MatchSequence( - rustpython_parser::ast::PatternMatchSequence { patterns }, + rustpython_parser::ast::Pattern::MatchSequence( + rustpython_parser::ast::PatternMatchSequence { patterns, range: _ }, ) => PatternKind::MatchSequence { patterns: patterns .into_iter() .map(|pattern| (pattern, locator).into()) .collect(), }, - rustpython_parser::ast::PatternKind::MatchMapping( + rustpython_parser::ast::Pattern::MatchMapping( rustpython_parser::ast::PatternMatchMapping { keys, patterns, rest, + range: _, }, ) => PatternKind::MatchMapping { keys: keys.into_iter().map(|key| (key, locator).into()).collect(), @@ -671,12 +671,13 @@ impl From<(rustpython_parser::ast::Pattern, &Locator<'_>)> for Pattern { .collect(), rest: rest.map(Into::into), }, - rustpython_parser::ast::PatternKind::MatchClass( + rustpython_parser::ast::Pattern::MatchClass( rustpython_parser::ast::PatternMatchClass { cls, patterns, kwd_attrs, kwd_patterns, + range: _, }, ) => PatternKind::MatchClass { cls: Box::new((*cls, locator).into()), @@ -690,19 +691,23 @@ impl From<(rustpython_parser::ast::Pattern, &Locator<'_>)> for Pattern { .map(|pattern| (pattern, locator).into()) .collect(), }, - rustpython_parser::ast::PatternKind::MatchStar( - rustpython_parser::ast::PatternMatchStar { name }, + rustpython_parser::ast::Pattern::MatchStar( + rustpython_parser::ast::PatternMatchStar { name, range: _ }, ) => PatternKind::MatchStar { name: name.map(Into::into), }, - rustpython_parser::ast::PatternKind::MatchAs( - rustpython_parser::ast::PatternMatchAs { pattern, name }, + rustpython_parser::ast::Pattern::MatchAs( + rustpython_parser::ast::PatternMatchAs { + pattern, + name, + range: _, + }, ) => PatternKind::MatchAs { pattern: pattern.map(|pattern| Box::new((*pattern, locator).into())), name: name.map(Into::into), }, - rustpython_parser::ast::PatternKind::MatchOr( - rustpython_parser::ast::PatternMatchOr { patterns }, + rustpython_parser::ast::Pattern::MatchOr( + rustpython_parser::ast::PatternMatchOr { patterns, range: _ }, ) => PatternKind::MatchOr { patterns: patterns .into_iter() @@ -749,35 +754,36 @@ impl From<(rustpython_parser::ast::MatchCase, &Locator<'_>)> for MatchCase { impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { fn from((stmt, locator): (rustpython_parser::ast::Stmt, &Locator)) -> Self { - match stmt.node { - rustpython_parser::ast::StmtKind::Expr(ast::StmtExpr { value }) => Stmt { - range: stmt.range, + match stmt { + rustpython_parser::ast::Stmt::Expr(ast::StmtExpr { value, range }) => Stmt { + range, node: StmtKind::Expr { value: Box::new((*value, locator).into()), }, trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::Pass => Stmt { - range: stmt.range, + rustpython_parser::ast::Stmt::Pass(ast::StmtPass { range }) => Stmt { + range, node: StmtKind::Pass, trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::Return(ast::StmtReturn { value }) => Stmt { - range: stmt.range, + rustpython_parser::ast::Stmt::Return(ast::StmtReturn { value, range }) => Stmt { + range, node: StmtKind::Return { value: value.map(|v| (*v, locator).into()), }, trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::Assign(ast::StmtAssign { + rustpython_parser::ast::Stmt::Assign(ast::StmtAssign { targets, value, type_comment, + range, }) => Stmt { - range: stmt.range, + range, node: StmtKind::Assign { targets: targets .into_iter() @@ -789,20 +795,18 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::ClassDef(ast::StmtClassDef { + rustpython_parser::ast::Stmt::ClassDef(ast::StmtClassDef { name, bases, keywords, body, decorator_list, + range, }) => { // Find the start and end of the `body`. let body = { - let body_range = expand_indented_block( - stmt.range.start(), - body.last().unwrap().end(), - locator, - ); + let body_range = + expand_indented_block(range.start(), body.last().unwrap().end(), locator); Body { range: body_range, node: body @@ -815,7 +819,7 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { }; Stmt { - range: TextRange::new(stmt.range.start(), body.end()), + range: TextRange::new(range.start(), body.end()), node: StmtKind::ClassDef { name: name.into(), bases: bases @@ -836,14 +840,16 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { parentheses: Parenthesize::Never, } } - rustpython_parser::ast::StmtKind::If(ast::StmtIf { test, body, orelse }) => { + rustpython_parser::ast::Stmt::If(ast::StmtIf { + test, + body, + orelse, + range, + }) => { // Find the start and end of the `body`. let body = { - let body_range = expand_indented_block( - stmt.range.start(), - body.last().unwrap().end(), - locator, - ); + let body_range = + expand_indented_block(range.start(), body.last().unwrap().end(), locator); Body { range: body_range, node: body @@ -858,7 +864,7 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { if orelse.is_empty() { // No `else` block. Stmt { - range: TextRange::new(stmt.range.start(), body.end()), + range: TextRange::new(range.start(), body.end()), node: StmtKind::If { test: Box::new((*test, locator).into()), body, @@ -872,14 +878,16 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { if is_elif(&orelse, locator) { // Find the start and end of the `elif`. let mut elif: Body = (orelse, locator).into(); - if let StmtKind::If { is_elif, .. } = - &mut elif.node.first_mut().unwrap().node + if let Attributed { + node: StmtKind::If { is_elif, .. }, + .. + } = elif.node.first_mut().unwrap() { *is_elif = true; }; Stmt { - range: TextRange::new(stmt.range.start(), elif.end()), + range: TextRange::new(range.start(), elif.end()), node: StmtKind::If { test: Box::new((*test, locator).into()), body, @@ -907,7 +915,7 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { }; Stmt { - range: TextRange::new(stmt.range.start(), orelse.end()), + range: TextRange::new(range.start(), orelse.end()), node: StmtKind::If { test: Box::new((*test, locator).into()), body, @@ -920,8 +928,8 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { } } } - rustpython_parser::ast::StmtKind::Assert(ast::StmtAssert { test, msg }) => Stmt { - range: stmt.range, + rustpython_parser::ast::Stmt::Assert(ast::StmtAssert { test, msg, range }) => Stmt { + range, node: StmtKind::Assert { test: Box::new((*test, locator).into()), msg: msg.map(|node| Box::new((*node, locator).into())), @@ -929,21 +937,19 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::FunctionDef(ast::StmtFunctionDef { + rustpython_parser::ast::Stmt::FunctionDef(ast::StmtFunctionDef { name, args, body, decorator_list, returns, type_comment, + range, }) => { // Find the start and end of the `body`. let body = { - let body_range = expand_indented_block( - stmt.range.start(), - body.last().unwrap().end(), - locator, - ); + let body_range = + expand_indented_block(range.start(), body.last().unwrap().end(), locator); Body { range: body_range, node: body @@ -959,7 +965,7 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { range: TextRange::new( decorator_list .first() - .map_or(stmt.range.start(), ast::Attributed::start), + .map_or(range.start(), ast::Ranged::start), body.end(), ), node: StmtKind::FunctionDef { @@ -977,21 +983,19 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { parentheses: Parenthesize::Never, } } - rustpython_parser::ast::StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { + rustpython_parser::ast::Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, args, body, decorator_list, returns, type_comment, + range, }) => { // Find the start and end of the `body`. let body = { - let body_range = expand_indented_block( - stmt.range.start(), - body.last().unwrap().end(), - locator, - ); + let body_range = + expand_indented_block(range.start(), body.last().unwrap().end(), locator); Body { range: body_range, node: body @@ -1007,7 +1011,7 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { range: TextRange::new( decorator_list .first() - .map_or(stmt.range.start(), |expr| expr.range.start()), + .map_or(range.start(), |expr| expr.range().start()), body.end(), ), node: StmtKind::AsyncFunctionDef { @@ -1025,8 +1029,8 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { parentheses: Parenthesize::Never, } } - rustpython_parser::ast::StmtKind::Delete(ast::StmtDelete { targets }) => Stmt { - range: stmt.range, + rustpython_parser::ast::Stmt::Delete(ast::StmtDelete { targets, range }) => Stmt { + range, node: StmtKind::Delete { targets: targets .into_iter() @@ -1036,12 +1040,13 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::AugAssign(ast::StmtAugAssign { + rustpython_parser::ast::Stmt::AugAssign(ast::StmtAugAssign { target, op, value, + range, }) => Stmt { - range: stmt.range, + range, node: StmtKind::AugAssign { op: { let target_tok = match &op { @@ -1097,13 +1102,14 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::AnnAssign(ast::StmtAnnAssign { + rustpython_parser::ast::Stmt::AnnAssign(ast::StmtAnnAssign { target, annotation, value, simple, + range, }) => Stmt { - range: stmt.range, + range, node: StmtKind::AnnAssign { target: Box::new((*target, locator).into()), annotation: Box::new((*annotation, locator).into()), @@ -1113,20 +1119,18 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::For(ast::StmtFor { + rustpython_parser::ast::Stmt::For(ast::StmtFor { target, iter, body, orelse, type_comment, + range, }) => { // Find the start and end of the `body`. let body = { - let body_range = expand_indented_block( - stmt.range.start(), - body.last().unwrap().end(), - locator, - ); + let body_range = + expand_indented_block(range.start(), body.last().unwrap().end(), locator); Body { range: body_range, node: body @@ -1154,10 +1158,7 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { }); Stmt { - range: TextRange::new( - stmt.range.start(), - orelse.as_ref().unwrap_or(&body).end(), - ), + range: TextRange::new(range.start(), orelse.as_ref().unwrap_or(&body).end()), node: StmtKind::For { target: Box::new((*target, locator).into()), iter: Box::new((*iter, locator).into()), @@ -1169,20 +1170,18 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { parentheses: Parenthesize::Never, } } - rustpython_parser::ast::StmtKind::AsyncFor(ast::StmtAsyncFor { + rustpython_parser::ast::Stmt::AsyncFor(ast::StmtAsyncFor { target, iter, body, orelse, type_comment, + range, }) => { // Find the start and end of the `body`. let body = { - let body_range = expand_indented_block( - stmt.range.start(), - body.last().unwrap().end(), - locator, - ); + let body_range = + expand_indented_block(range.start(), body.last().unwrap().end(), locator); Body { range: body_range, node: body @@ -1210,10 +1209,7 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { }); Stmt { - range: TextRange::new( - stmt.range.start(), - orelse.as_ref().unwrap_or(&body).end(), - ), + range: TextRange::new(range.start(), orelse.as_ref().unwrap_or(&body).end()), node: StmtKind::AsyncFor { target: Box::new((*target, locator).into()), iter: Box::new((*iter, locator).into()), @@ -1225,14 +1221,16 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { parentheses: Parenthesize::Never, } } - rustpython_parser::ast::StmtKind::While(ast::StmtWhile { test, body, orelse }) => { + rustpython_parser::ast::Stmt::While(ast::StmtWhile { + test, + body, + orelse, + range, + }) => { // Find the start and end of the `body`. let body = { - let body_range = expand_indented_block( - stmt.range.start(), - body.last().unwrap().end(), - locator, - ); + let body_range = + expand_indented_block(range.start(), body.last().unwrap().end(), locator); Body { range: body_range, node: body @@ -1260,10 +1258,7 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { }); Stmt { - range: TextRange::new( - stmt.range.start(), - orelse.as_ref().unwrap_or(&body).end(), - ), + range: TextRange::new(range.start(), orelse.as_ref().unwrap_or(&body).end()), node: StmtKind::While { test: Box::new((*test, locator).into()), body, @@ -1273,18 +1268,16 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { parentheses: Parenthesize::Never, } } - rustpython_parser::ast::StmtKind::With(ast::StmtWith { + rustpython_parser::ast::Stmt::With(ast::StmtWith { items, body, type_comment, + range, }) => { // Find the start and end of the `body`. let body = { - let body_range = expand_indented_block( - stmt.range.start(), - body.last().unwrap().end(), - locator, - ); + let body_range = + expand_indented_block(range.start(), body.last().unwrap().end(), locator); Body { range: body_range, node: body @@ -1297,7 +1290,7 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { }; Stmt { - range: TextRange::new(stmt.range.start(), body.end()), + range: TextRange::new(range.start(), body.end()), node: StmtKind::With { items: items .into_iter() @@ -1310,18 +1303,16 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { parentheses: Parenthesize::Never, } } - rustpython_parser::ast::StmtKind::AsyncWith(ast::StmtAsyncWith { + rustpython_parser::ast::Stmt::AsyncWith(ast::StmtAsyncWith { items, body, type_comment, + range, }) => { // Find the start and end of the `body`. let body = { - let body_range = expand_indented_block( - stmt.range.start(), - body.last().unwrap().end(), - locator, - ); + let body_range = + expand_indented_block(range.start(), body.last().unwrap().end(), locator); Body { range: body_range, node: body @@ -1334,7 +1325,7 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { }; Stmt { - range: TextRange::new(stmt.range.start(), body.end()), + range: TextRange::new(range.start(), body.end()), node: StmtKind::AsyncWith { items: items .into_iter() @@ -1347,8 +1338,12 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { parentheses: Parenthesize::Never, } } - rustpython_parser::ast::StmtKind::Match(ast::StmtMatch { subject, cases }) => Stmt { - range: stmt.range, + rustpython_parser::ast::Stmt::Match(ast::StmtMatch { + subject, + cases, + range, + }) => Stmt { + range, node: StmtKind::Match { subject: Box::new((*subject, locator).into()), cases: cases @@ -1359,8 +1354,8 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::Raise(ast::StmtRaise { exc, cause }) => Stmt { - range: stmt.range, + rustpython_parser::ast::Stmt::Raise(ast::StmtRaise { exc, cause, range }) => Stmt { + range, node: StmtKind::Raise { exc: exc.map(|exc| Box::new((*exc, locator).into())), cause: cause.map(|cause| Box::new((*cause, locator).into())), @@ -1368,19 +1363,17 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::Try(ast::StmtTry { + rustpython_parser::ast::Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, + range, }) => { // Find the start and end of the `body`. let body = { - let body_range = expand_indented_block( - stmt.range.start(), - body.last().unwrap().end(), - locator, - ); + let body_range = + expand_indented_block(range.start(), body.last().unwrap().end(), locator); Body { range: body_range, node: body @@ -1445,7 +1438,7 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { ); Stmt { - range: TextRange::new(stmt.range.start(), end_location), + range: TextRange::new(range.start(), end_location), node: StmtKind::Try { body, handlers, @@ -1456,19 +1449,17 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { parentheses: Parenthesize::Never, } } - rustpython_parser::ast::StmtKind::TryStar(ast::StmtTryStar { + rustpython_parser::ast::Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, finalbody, + range, }) => { // Find the start and end of the `body`. let body = { - let body_range = expand_indented_block( - stmt.range.start(), - body.last().unwrap().end(), - locator, - ); + let body_range = + expand_indented_block(range.start(), body.last().unwrap().end(), locator); Body { range: body_range, node: body @@ -1533,7 +1524,7 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { ); Stmt { - range: TextRange::new(stmt.range.start(), end_location), + range: TextRange::new(range.start(), end_location), node: StmtKind::TryStar { body, handlers, @@ -1544,8 +1535,8 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { parentheses: Parenthesize::Never, } } - rustpython_parser::ast::StmtKind::Import(ast::StmtImport { names }) => Stmt { - range: stmt.range, + rustpython_parser::ast::Stmt::Import(ast::StmtImport { names, range }) => Stmt { + range, node: StmtKind::Import { names: names .into_iter() @@ -1555,12 +1546,13 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::ImportFrom(ast::StmtImportFrom { + rustpython_parser::ast::Stmt::ImportFrom(ast::StmtImportFrom { module, names, level, + range, }) => Stmt { - range: stmt.range, + range, node: StmtKind::ImportFrom { module: module.map(Into::into), names: names @@ -1572,30 +1564,30 @@ impl From<(rustpython_parser::ast::Stmt, &Locator<'_>)> for Stmt { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::Global(ast::StmtGlobal { names }) => Stmt { - range: stmt.range, + rustpython_parser::ast::Stmt::Global(ast::StmtGlobal { names, range }) => Stmt { + range, node: StmtKind::Global { names: names.into_iter().map(Into::into).collect(), }, trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::Nonlocal(ast::StmtNonlocal { names }) => Stmt { - range: stmt.range, + rustpython_parser::ast::Stmt::Nonlocal(ast::StmtNonlocal { names, range }) => Stmt { + range, node: StmtKind::Nonlocal { names: names.into_iter().map(Into::into).collect(), }, trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::Break => Stmt { - range: stmt.range, + rustpython_parser::ast::Stmt::Break(ast::StmtBreak { range }) => Stmt { + range, node: StmtKind::Break, trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::StmtKind::Continue => Stmt { - range: stmt.range, + rustpython_parser::ast::Stmt::Continue(ast::StmtContinue { range }) => Stmt { + range, node: StmtKind::Continue, trivia: vec![], parentheses: Parenthesize::Never, @@ -1609,8 +1601,8 @@ impl From<(rustpython_parser::ast::Keyword, &Locator<'_>)> for Keyword { Keyword { range: keyword.range(), node: KeywordData { - arg: keyword.node.arg.map(Into::into), - value: (keyword.node.value, locator).into(), + arg: keyword.arg.map(Into::into), + value: (keyword.value, locator).into(), }, trivia: vec![], parentheses: Parenthesize::Never, @@ -1623,12 +1615,9 @@ impl From<(rustpython_parser::ast::Arg, &Locator<'_>)> for Arg { Arg { range: arg.range(), node: ArgData { - arg: arg.node.arg.into(), - annotation: arg - .node - .annotation - .map(|node| Box::new((*node, locator).into())), - type_comment: arg.node.type_comment, + arg: arg.arg.into(), + annotation: arg.annotation.map(|node| Box::new((*node, locator).into())), + type_comment: arg.type_comment, }, trivia: vec![], parentheses: Parenthesize::Never, @@ -1691,9 +1680,9 @@ impl From<(rustpython_parser::ast::Comprehension, &Locator<'_>)> for Comprehensi impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { fn from((expr, locator): (rustpython_parser::ast::Expr, &Locator)) -> Self { - match expr.node { - rustpython_parser::ast::ExprKind::Name(ast::ExprName { id, ctx }) => Expr { - range: expr.range, + match expr { + rustpython_parser::ast::Expr::Name(ast::ExprName { id, ctx, range }) => Expr { + range, node: ExprKind::Name { id: id.into(), ctx: ctx.into(), @@ -1701,8 +1690,8 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::BoolOp(ast::ExprBoolOp { op, values }) => Expr { - range: expr.range, + rustpython_parser::ast::Expr::BoolOp(ast::ExprBoolOp { op, values, range }) => Expr { + range, node: ExprKind::BoolOp { ops: values .iter() @@ -1728,19 +1717,26 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::NamedExpr(ast::ExprNamedExpr { target, value }) => { - Expr { - range: expr.range, - node: ExprKind::NamedExpr { - target: Box::new((*target, locator).into()), - value: Box::new((*value, locator).into()), - }, - trivia: vec![], - parentheses: Parenthesize::Never, - } - } - rustpython_parser::ast::ExprKind::BinOp(ast::ExprBinOp { left, op, right }) => Expr { - range: expr.range, + rustpython_parser::ast::Expr::NamedExpr(ast::ExprNamedExpr { + target, + value, + range, + }) => Expr { + range, + node: ExprKind::NamedExpr { + target: Box::new((*target, locator).into()), + value: Box::new((*value, locator).into()), + }, + trivia: vec![], + parentheses: Parenthesize::Never, + }, + rustpython_parser::ast::Expr::BinOp(ast::ExprBinOp { + left, + op, + right, + range, + }) => Expr { + range, node: ExprKind::BinOp { op: { let target_tok = match &op { @@ -1784,32 +1780,38 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::UnaryOp(ast::ExprUnaryOp { op, operand }) => Expr { - range: expr.range, - node: ExprKind::UnaryOp { - op: { - let target_tok = match &op { - rustpython_parser::ast::Unaryop::Invert => { - rustpython_parser::Tok::Tilde - } - rustpython_parser::ast::Unaryop::Not => rustpython_parser::Tok::Not, - rustpython_parser::ast::Unaryop::UAdd => rustpython_parser::Tok::Plus, - rustpython_parser::ast::Unaryop::USub => rustpython_parser::Tok::Minus, - }; - let op_range = find_tok( - TextRange::new(expr.range.start(), operand.start()), - locator, - |tok| tok == target_tok, - ); - UnaryOp::new(op_range, (&op).into()) + rustpython_parser::ast::Expr::UnaryOp(ast::ExprUnaryOp { op, operand, range }) => { + Expr { + range, + node: ExprKind::UnaryOp { + op: { + let target_tok = match &op { + rustpython_parser::ast::Unaryop::Invert => { + rustpython_parser::Tok::Tilde + } + rustpython_parser::ast::Unaryop::Not => rustpython_parser::Tok::Not, + rustpython_parser::ast::Unaryop::UAdd => { + rustpython_parser::Tok::Plus + } + rustpython_parser::ast::Unaryop::USub => { + rustpython_parser::Tok::Minus + } + }; + let op_range = find_tok( + TextRange::new(range.start(), operand.start()), + locator, + |tok| tok == target_tok, + ); + UnaryOp::new(op_range, (&op).into()) + }, + operand: Box::new((*operand, locator).into()), }, - operand: Box::new((*operand, locator).into()), - }, - trivia: vec![], - parentheses: Parenthesize::Never, - }, - rustpython_parser::ast::ExprKind::Lambda(ast::ExprLambda { args, body }) => Expr { - range: expr.range, + trivia: vec![], + parentheses: Parenthesize::Never, + } + } + rustpython_parser::ast::Expr::Lambda(ast::ExprLambda { args, body, range }) => Expr { + range, node: ExprKind::Lambda { args: Box::new((*args, locator).into()), body: Box::new((*body, locator).into()), @@ -1817,20 +1819,27 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::IfExp(ast::ExprIfExp { test, body, orelse }) => { - Expr { - range: expr.range, - node: ExprKind::IfExp { - test: Box::new((*test, locator).into()), - body: Box::new((*body, locator).into()), - orelse: Box::new((*orelse, locator).into()), - }, - trivia: vec![], - parentheses: Parenthesize::Never, - } - } - rustpython_parser::ast::ExprKind::Dict(ast::ExprDict { keys, values }) => Expr { - range: expr.range, + rustpython_parser::ast::Expr::IfExp(ast::ExprIfExp { + test, + body, + orelse, + range, + }) => Expr { + range, + node: ExprKind::IfExp { + test: Box::new((*test, locator).into()), + body: Box::new((*body, locator).into()), + orelse: Box::new((*orelse, locator).into()), + }, + trivia: vec![], + parentheses: Parenthesize::Never, + }, + rustpython_parser::ast::Expr::Dict(ast::ExprDict { + keys, + values, + range, + }) => Expr { + range, node: ExprKind::Dict { keys: keys .into_iter() @@ -1844,8 +1853,8 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::Set(ast::ExprSet { elts }) => Expr { - range: expr.range, + rustpython_parser::ast::Expr::Set(ast::ExprSet { elts, range }) => Expr { + range, node: ExprKind::Set { elts: elts .into_iter() @@ -1855,40 +1864,45 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::ListComp(ast::ExprListComp { elt, generators }) => { - Expr { - range: expr.range, - node: ExprKind::ListComp { - elt: Box::new((*elt, locator).into()), - generators: generators - .into_iter() - .map(|node| (node, locator).into()) - .collect(), - }, - trivia: vec![], - parentheses: Parenthesize::Never, - } - } - rustpython_parser::ast::ExprKind::SetComp(ast::ExprSetComp { elt, generators }) => { - Expr { - range: expr.range, - node: ExprKind::SetComp { - elt: Box::new((*elt, locator).into()), - generators: generators - .into_iter() - .map(|node| (node, locator).into()) - .collect(), - }, - trivia: vec![], - parentheses: Parenthesize::Never, - } - } - rustpython_parser::ast::ExprKind::DictComp(ast::ExprDictComp { + rustpython_parser::ast::Expr::ListComp(ast::ExprListComp { + elt, + generators, + range, + }) => Expr { + range, + node: ExprKind::ListComp { + elt: Box::new((*elt, locator).into()), + generators: generators + .into_iter() + .map(|node| (node, locator).into()) + .collect(), + }, + trivia: vec![], + parentheses: Parenthesize::Never, + }, + rustpython_parser::ast::Expr::SetComp(ast::ExprSetComp { + elt, + generators, + range, + }) => Expr { + range, + node: ExprKind::SetComp { + elt: Box::new((*elt, locator).into()), + generators: generators + .into_iter() + .map(|node| (node, locator).into()) + .collect(), + }, + trivia: vec![], + parentheses: Parenthesize::Never, + }, + rustpython_parser::ast::Expr::DictComp(ast::ExprDictComp { key, value, generators, + range, }) => Expr { - range: expr.range, + range, node: ExprKind::DictComp { key: Box::new((*key, locator).into()), value: Box::new((*value, locator).into()), @@ -1900,11 +1914,12 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::GeneratorExp(ast::ExprGeneratorExp { + rustpython_parser::ast::Expr::GeneratorExp(ast::ExprGeneratorExp { elt, generators, + range, }) => Expr { - range: expr.range, + range, node: ExprKind::GeneratorExp { elt: Box::new((*elt, locator).into()), generators: generators @@ -1915,36 +1930,37 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::Await(ast::ExprAwait { value }) => Expr { - range: expr.range, + rustpython_parser::ast::Expr::Await(ast::ExprAwait { value, range }) => Expr { + range, node: ExprKind::Await { value: Box::new((*value, locator).into()), }, trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::Yield(ast::ExprYield { value }) => Expr { - range: expr.range, + rustpython_parser::ast::Expr::Yield(ast::ExprYield { value, range }) => Expr { + range, node: ExprKind::Yield { value: value.map(|v| Box::new((*v, locator).into())), }, trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::YieldFrom(ast::ExprYieldFrom { value }) => Expr { - range: expr.range, + rustpython_parser::ast::Expr::YieldFrom(ast::ExprYieldFrom { value, range }) => Expr { + range, node: ExprKind::YieldFrom { value: Box::new((*value, locator).into()), }, trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::Compare(ast::ExprCompare { + rustpython_parser::ast::Expr::Compare(ast::ExprCompare { left, ops, comparators, + range, }) => Expr { - range: expr.range, + range, node: ExprKind::Compare { ops: iter::once(left.as_ref()) .chain(comparators.iter()) @@ -1992,12 +2008,13 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::Call(ast::ExprCall { + rustpython_parser::ast::Expr::Call(ast::ExprCall { func, args, keywords, + range, }) => Expr { - range: expr.range, + range, node: ExprKind::Call { func: Box::new((*func, locator).into()), args: args @@ -2012,12 +2029,13 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::FormattedValue(ast::ExprFormattedValue { + rustpython_parser::ast::Expr::FormattedValue(ast::ExprFormattedValue { value, conversion, format_spec, + range, }) => Expr { - range: expr.range, + range, node: ExprKind::FormattedValue { value: Box::new((*value, locator).into()), conversion: conversion.to_usize(), @@ -2026,8 +2044,8 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => Expr { - range: expr.range, + rustpython_parser::ast::Expr::JoinedStr(ast::ExprJoinedStr { values, range }) => Expr { + range, node: ExprKind::JoinedStr { values: values .into_iter() @@ -2037,18 +2055,21 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::Constant(ast::ExprConstant { value, kind }) => Expr { - range: expr.range, - node: ExprKind::Constant { value, kind }, - trivia: vec![], - parentheses: Parenthesize::Never, - }, - rustpython_parser::ast::ExprKind::Attribute(ast::ExprAttribute { + rustpython_parser::ast::Expr::Constant(ast::ExprConstant { value, kind, range }) => { + Expr { + range, + node: ExprKind::Constant { value, kind }, + trivia: vec![], + parentheses: Parenthesize::Never, + } + } + rustpython_parser::ast::Expr::Attribute(ast::ExprAttribute { value, attr, ctx, + range, }) => Expr { - range: expr.range, + range, node: ExprKind::Attribute { value: Box::new((*value, locator).into()), attr: attr.into(), @@ -2057,12 +2078,13 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::Subscript(ast::ExprSubscript { + rustpython_parser::ast::Expr::Subscript(ast::ExprSubscript { value, slice, ctx, + range, }) => Expr { - range: expr.range, + range, node: ExprKind::Subscript { value: Box::new((*value, locator).into()), slice: Box::new((*slice, locator).into()), @@ -2071,8 +2093,8 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::Starred(ast::ExprStarred { value, ctx }) => Expr { - range: expr.range, + rustpython_parser::ast::Expr::Starred(ast::ExprStarred { value, ctx, range }) => Expr { + range, node: ExprKind::Starred { value: Box::new((*value, locator).into()), ctx: ctx.into(), @@ -2080,8 +2102,8 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::List(ast::ExprList { elts, ctx }) => Expr { - range: expr.range, + rustpython_parser::ast::Expr::List(ast::ExprList { elts, ctx, range }) => Expr { + range, node: ExprKind::List { elts: elts .into_iter() @@ -2092,8 +2114,8 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::Tuple(ast::ExprTuple { elts, ctx }) => Expr { - range: expr.range, + rustpython_parser::ast::Expr::Tuple(ast::ExprTuple { elts, ctx, range }) => Expr { + range, node: ExprKind::Tuple { elts: elts .into_iter() @@ -2104,12 +2126,17 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { trivia: vec![], parentheses: Parenthesize::Never, }, - rustpython_parser::ast::ExprKind::Slice(ast::ExprSlice { lower, upper, step }) => { + rustpython_parser::ast::Expr::Slice(ast::ExprSlice { + lower, + upper, + step, + range: expr_range, + }) => { // Locate the colon tokens, which indicate the number of index segments. let tokens = rustpython_parser::lexer::lex_starts_at( - &locator.contents()[expr.range], + &locator.contents()[expr_range], Mode::Module, - expr.range.start(), + expr_range.start(), ); // Find the first and (if it exists) second colon in the slice, avoiding any @@ -2144,7 +2171,7 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { } let lower = SliceIndex::new( - TextRange::new(expr.range.start(), first_colon.unwrap()), + TextRange::new(expr_range.start(), first_colon.unwrap()), lower.map_or(SliceIndexKind::Empty, |node| SliceIndexKind::Index { value: Box::new((*node, locator).into()), }), @@ -2152,7 +2179,7 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { let upper = SliceIndex::new( TextRange::new( first_colon.unwrap(), - second_colon.unwrap_or(expr.range.end()), + second_colon.unwrap_or(expr_range.end()), ), upper.map_or(SliceIndexKind::Empty, |node| SliceIndexKind::Index { value: Box::new((*node, locator).into()), @@ -2160,7 +2187,7 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { ); let step = second_colon.map(|second_colon| { SliceIndex::new( - TextRange::new(second_colon, expr.range.end()), + TextRange::new(second_colon, expr_range.end()), step.map_or(SliceIndexKind::Empty, |node| SliceIndexKind::Index { value: Box::new((*node, locator).into()), }), @@ -2168,7 +2195,7 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr { }); Expr { - range: expr.range, + range: expr_range, node: ExprKind::Slice { lower, upper, step }, trivia: vec![], parentheses: Parenthesize::Never, diff --git a/crates/ruff_python_formatter/src/format/alias.rs b/crates/ruff_python_formatter/src/format/alias.rs index 1feae1610e..a12648f9b2 100644 --- a/crates/ruff_python_formatter/src/format/alias.rs +++ b/crates/ruff_python_formatter/src/format/alias.rs @@ -23,8 +23,8 @@ impl Format for FormatAlias<'_> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { let alias = self.item; - write!(f, [dynamic_text(&alias.node.name, TextSize::default())])?; - if let Some(asname) = &alias.node.asname { + write!(f, [dynamic_text(&alias.name, TextSize::default())])?; + if let Some(asname) = &alias.asname { write!(f, [text(" as ")])?; write!(f, [dynamic_text(asname, TextSize::default())])?; } diff --git a/crates/ruff_python_formatter/src/format/arg.rs b/crates/ruff_python_formatter/src/format/arg.rs index 72ab232c5c..4279d34520 100644 --- a/crates/ruff_python_formatter/src/format/arg.rs +++ b/crates/ruff_python_formatter/src/format/arg.rs @@ -23,8 +23,8 @@ impl Format for FormatArg<'_> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { let arg = self.item; - write!(f, [dynamic_text(&arg.node.arg, TextSize::default())])?; - if let Some(annotation) = &arg.node.annotation { + write!(f, [dynamic_text(&arg.arg, TextSize::default())])?; + if let Some(annotation) = &arg.annotation { write!(f, [text(": ")])?; write!(f, [annotation.format()])?; } diff --git a/crates/ruff_python_formatter/src/format/arguments.rs b/crates/ruff_python_formatter/src/format/arguments.rs index a49220fb0c..d5dd17100d 100644 --- a/crates/ruff_python_formatter/src/format/arguments.rs +++ b/crates/ruff_python_formatter/src/format/arguments.rs @@ -35,7 +35,7 @@ impl Format for FormatArguments<'_> { [group(&format_args![format_with(|f| { write!(f, [arg.format()])?; if let Some(i) = i.checked_sub(defaults_start) { - if arg.node.annotation.is_some() { + if arg.annotation.is_some() { write!(f, [space()])?; write!(f, [text("=")])?; write!(f, [space()])?; @@ -91,7 +91,7 @@ impl Format for FormatArguments<'_> { .checked_sub(defaults_start) .and_then(|i| args.kw_defaults.get(i)) { - if kwarg.node.annotation.is_some() { + if kwarg.annotation.is_some() { write!(f, [space()])?; write!(f, [text("=")])?; write!(f, [space()])?; diff --git a/crates/ruff_python_formatter/src/format/builders.rs b/crates/ruff_python_formatter/src/format/builders.rs index 3d663ddae3..3106eea705 100644 --- a/crates/ruff_python_formatter/src/format/builders.rs +++ b/crates/ruff_python_formatter/src/format/builders.rs @@ -14,7 +14,7 @@ pub(crate) struct Block<'a> { impl Format for Block<'_> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - for (i, stmt) in self.body.node.iter().enumerate() { + for (i, stmt) in self.body.iter().enumerate() { if i > 0 { write!(f, [hard_line_break()])?; } diff --git a/crates/ruff_python_formatter/src/format/keyword.rs b/crates/ruff_python_formatter/src/format/keyword.rs index 5c34acf072..d89cea21ff 100644 --- a/crates/ruff_python_formatter/src/format/keyword.rs +++ b/crates/ruff_python_formatter/src/format/keyword.rs @@ -24,13 +24,13 @@ impl Format for FormatKeyword<'_> { let keyword = self.item; write!(f, [leading_comments(keyword)])?; - if let Some(arg) = &keyword.node.arg { + if let Some(arg) = &keyword.arg { write!(f, [dynamic_text(arg, TextSize::default())])?; write!(f, [text("=")])?; - write!(f, [keyword.node.value.format()])?; + write!(f, [keyword.value.format()])?; } else { write!(f, [text("**")])?; - write!(f, [keyword.node.value.format()])?; + write!(f, [keyword.value.format()])?; } write!(f, [end_of_line_comments(keyword)])?; write!(f, [trailing_comments(keyword)])?; diff --git a/crates/ruff_python_formatter/src/format/pattern.rs b/crates/ruff_python_formatter/src/format/pattern.rs index 99051ba8d9..b6845cbe17 100644 --- a/crates/ruff_python_formatter/src/format/pattern.rs +++ b/crates/ruff_python_formatter/src/format/pattern.rs @@ -127,7 +127,7 @@ impl Format for FormatPattern<'_> { } } PatternKind::MatchStar { name } => { - if let Some(name) = &name { + if let Some(name) = name { write!(f, [text("*"), dynamic_text(name, TextSize::default())])?; } else { write!(f, [text("*_")])?; @@ -140,7 +140,7 @@ impl Format for FormatPattern<'_> { write!(f, [text("as")])?; write!(f, [space()])?; } - if let Some(name) = &name { + if let Some(name) = name { write!(f, [dynamic_text(name, TextSize::default())])?; } else { write!(f, [text("_")])?; diff --git a/crates/ruff_python_semantic/src/analyze/branch_detection.rs b/crates/ruff_python_semantic/src/analyze/branch_detection.rs index c5cf134aff..7d1f1c2284 100644 --- a/crates/ruff_python_semantic/src/analyze/branch_detection.rs +++ b/crates/ruff_python_semantic/src/analyze/branch_detection.rs @@ -1,6 +1,6 @@ use std::cmp::Ordering; -use rustpython_parser::ast::{self, ExcepthandlerKind, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Excepthandler, Stmt}; use crate::node::{NodeId, Nodes}; @@ -41,15 +41,15 @@ fn common_ancestor( /// Return the alternative branches for a given node. fn alternatives(stmt: &Stmt) -> Vec> { - match &stmt.node { - StmtKind::If(ast::StmtIf { body, .. }) => vec![body.iter().collect()], - StmtKind::Try(ast::StmtTry { + match stmt { + Stmt::If(ast::StmtIf { body, .. }) => vec![body.iter().collect()], + Stmt::Try(ast::StmtTry { body, handlers, orelse, .. }) - | StmtKind::TryStar(ast::StmtTryStar { + | Stmt::TryStar(ast::StmtTryStar { body, handlers, orelse, @@ -57,13 +57,12 @@ fn alternatives(stmt: &Stmt) -> Vec> { }) => vec![body.iter().chain(orelse.iter()).collect()] .into_iter() .chain(handlers.iter().map(|handler| { - let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { - body, .. - }) = &handler.node; + let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) = + handler; body.iter().collect() })) .collect(), - StmtKind::Match(ast::StmtMatch { cases, .. }) => cases + Stmt::Match(ast::StmtMatch { cases, .. }) => cases .iter() .map(|case| case.body.iter().collect()) .collect(), diff --git a/crates/ruff_python_semantic/src/analyze/logging.rs b/crates/ruff_python_semantic/src/analyze/logging.rs index efc9ca9474..036c8afb23 100644 --- a/crates/ruff_python_semantic/src/analyze/logging.rs +++ b/crates/ruff_python_semantic/src/analyze/logging.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Expr, ExprKind}; +use rustpython_parser::ast::{self, Expr}; use ruff_python_ast::call_path::collect_call_path; @@ -17,7 +17,7 @@ use crate::context::Context; /// bar.error() /// ``` pub fn is_logger_candidate(context: &Context, func: &Expr) -> bool { - if let ExprKind::Attribute(ast::ExprAttribute { value, .. }) = &func.node { + if let Expr::Attribute(ast::ExprAttribute { value, .. }) = func { let Some(call_path) = (if let Some(call_path) = context.resolve_call_path(value) { if call_path.first().map_or(false, |module| *module == "logging") || call_path.as_slice() == ["flask", "current_app", "logger"] { Some(call_path) diff --git a/crates/ruff_python_semantic/src/analyze/typing.rs b/crates/ruff_python_semantic/src/analyze/typing.rs index 369ff45e0e..4b467de4aa 100644 --- a/crates/ruff_python_semantic/src/analyze/typing.rs +++ b/crates/ruff_python_semantic/src/analyze/typing.rs @@ -1,4 +1,4 @@ -use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Operator}; +use rustpython_parser::ast::{self, Constant, Expr, Operator}; use ruff_python_ast::call_path::{from_unqualified_name, CallPath}; use ruff_python_stdlib::typing::{ @@ -29,7 +29,7 @@ pub fn match_annotated_subscript<'a>( context: &Context, typing_modules: impl Iterator, ) -> Option { - if !matches!(expr.node, ExprKind::Name(_) | ExprKind::Attribute(_)) { + if !matches!(expr, Expr::Name(_) | Expr::Attribute(_)) { return None; } @@ -113,12 +113,12 @@ pub enum Pep604Operator { pub fn to_pep604_operator(value: &Expr, slice: &Expr, context: &Context) -> Option { /// Returns `true` if any argument in the slice is a string. fn any_arg_is_str(slice: &Expr) -> bool { - match &slice.node { - ExprKind::Constant(ast::ExprConstant { + match slice { + Expr::Constant(ast::ExprConstant { value: Constant::Str(_), .. }) => true, - ExprKind::Tuple(ast::ExprTuple { elts, .. }) => elts.iter().any(any_arg_is_str), + Expr::Tuple(ast::ExprTuple { elts, .. }) => elts.iter().any(any_arg_is_str), _ => false, } } @@ -146,8 +146,8 @@ pub fn to_pep604_operator(value: &Expr, slice: &Expr, context: &Context) -> Opti /// Return `true` if `Expr` represents a reference to a type annotation that resolves to an /// immutable type. pub fn is_immutable_annotation(context: &Context, expr: &Expr) -> bool { - match &expr.node { - ExprKind::Name(_) | ExprKind::Attribute(_) => { + match expr { + Expr::Name(_) | Expr::Attribute(_) => { context.resolve_call_path(expr).map_or(false, |call_path| { IMMUTABLE_TYPES .iter() @@ -155,7 +155,7 @@ pub fn is_immutable_annotation(context: &Context, expr: &Expr) -> bool { .any(|target| call_path.as_slice() == *target) }) } - ExprKind::Subscript(ast::ExprSubscript { value, slice, .. }) => { + Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => { context.resolve_call_path(value).map_or(false, |call_path| { if IMMUTABLE_GENERIC_TYPES .iter() @@ -163,7 +163,7 @@ pub fn is_immutable_annotation(context: &Context, expr: &Expr) -> bool { { true } else if call_path.as_slice() == ["typing", "Union"] { - if let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &slice.node { + if let Expr::Tuple(ast::ExprTuple { elts, .. }) = slice.as_ref() { elts.iter().all(|elt| is_immutable_annotation(context, elt)) } else { false @@ -171,7 +171,7 @@ pub fn is_immutable_annotation(context: &Context, expr: &Expr) -> bool { } else if call_path.as_slice() == ["typing", "Optional"] { is_immutable_annotation(context, slice) } else if call_path.as_slice() == ["typing", "Annotated"] { - if let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &slice.node { + if let Expr::Tuple(ast::ExprTuple { elts, .. }) = slice.as_ref() { elts.first() .map_or(false, |elt| is_immutable_annotation(context, elt)) } else { @@ -182,12 +182,13 @@ pub fn is_immutable_annotation(context: &Context, expr: &Expr) -> bool { } }) } - ExprKind::BinOp(ast::ExprBinOp { + Expr::BinOp(ast::ExprBinOp { left, op: Operator::BitOr, right, + range: _range, }) => is_immutable_annotation(context, left) && is_immutable_annotation(context, right), - ExprKind::Constant(ast::ExprConstant { + Expr::Constant(ast::ExprConstant { value: Constant::None, .. }) => true, diff --git a/crates/ruff_python_semantic/src/analyze/visibility.rs b/crates/ruff_python_semantic/src/analyze/visibility.rs index e9d0b2d660..4c2bc6a4bc 100644 --- a/crates/ruff_python_semantic/src/analyze/visibility.rs +++ b/crates/ruff_python_semantic/src/analyze/visibility.rs @@ -1,6 +1,6 @@ use std::path::Path; -use rustpython_parser::ast::{self, Expr, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Expr, Stmt}; use ruff_python_ast::call_path::{collect_call_path, CallPath}; use ruff_python_ast::helpers::map_callable; @@ -164,9 +164,9 @@ impl ModuleSource<'_> { } pub(crate) fn function_visibility(stmt: &Stmt) -> Visibility { - match &stmt.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { name, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, .. }) => { + match stmt { + Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, .. }) => { if name.starts_with('_') { Visibility::Private } else { @@ -178,13 +178,13 @@ pub(crate) fn function_visibility(stmt: &Stmt) -> Visibility { } pub(crate) fn method_visibility(stmt: &Stmt) -> Visibility { - match &stmt.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { + match stmt { + Stmt::FunctionDef(ast::StmtFunctionDef { name, decorator_list, .. }) - | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { + | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, decorator_list, .. @@ -216,8 +216,8 @@ pub(crate) fn method_visibility(stmt: &Stmt) -> Visibility { } pub(crate) fn class_visibility(stmt: &Stmt) -> Visibility { - match &stmt.node { - StmtKind::ClassDef(ast::StmtClassDef { name, .. }) => { + match stmt { + Stmt::ClassDef(ast::StmtClassDef { name, .. }) => { if name.starts_with('_') { Visibility::Private } else { diff --git a/crates/ruff_python_semantic/src/definition.rs b/crates/ruff_python_semantic/src/definition.rs index ceda227587..e9daf9feec 100644 --- a/crates/ruff_python_semantic/src/definition.rs +++ b/crates/ruff_python_semantic/src/definition.rs @@ -5,7 +5,7 @@ use std::fmt::Debug; use std::num::TryFromIntError; use std::ops::{Deref, Index}; -use rustpython_parser::ast::{self, Stmt, StmtKind}; +use rustpython_parser::ast::{self, Stmt}; use crate::analyze::visibility::{ class_visibility, function_visibility, method_visibility, ModuleSource, Visibility, @@ -87,10 +87,10 @@ pub struct Member<'a> { impl<'a> Member<'a> { fn name(&self) -> &'a str { - match &self.stmt.node { - StmtKind::FunctionDef(ast::StmtFunctionDef { name, .. }) => name, - StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, .. }) => name, - StmtKind::ClassDef(ast::StmtClassDef { name, .. }) => name, + match &self.stmt { + Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) => name, + Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, .. }) => name, + Stmt::ClassDef(ast::StmtClassDef { name, .. }) => name, _ => unreachable!("Unexpected member kind: {:?}", self.kind), } } diff --git a/crates/ruff_python_semantic/src/scope.rs b/crates/ruff_python_semantic/src/scope.rs index 28c42b286d..6a9f192619 100644 --- a/crates/ruff_python_semantic/src/scope.rs +++ b/crates/ruff_python_semantic/src/scope.rs @@ -115,7 +115,7 @@ pub enum ScopeKind<'a> { #[derive(Debug)] pub struct FunctionDef<'a> { - // Properties derived from StmtKind::FunctionDef. + // Properties derived from Stmt::FunctionDef. pub name: &'a str, pub args: &'a Arguments, pub body: &'a [Stmt], @@ -130,7 +130,7 @@ pub struct FunctionDef<'a> { #[derive(Debug)] pub struct ClassDef<'a> { - // Properties derived from StmtKind::ClassDef. + // Properties derived from Stmt::ClassDef. pub name: &'a str, pub bases: &'a [Expr], pub keywords: &'a [Keyword],