Upgrade RustPython (#5192)

## Summary

This PR upgrade RustPython to pull in the changes to `Arguments` (zip
defaults with their identifiers) and all the renames to `CmpOp` and
friends.
This commit is contained in:
Charlie Marsh 2023-06-19 17:09:53 -04:00 committed by GitHub
parent ddfdc3bb01
commit 36e01ad6eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
103 changed files with 1291 additions and 1165 deletions

13
Cargo.lock generated
View file

@ -2105,7 +2105,7 @@ dependencies = [
[[package]] [[package]]
name = "ruff_text_size" name = "ruff_text_size"
version = "0.0.0" version = "0.0.0"
source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=0dc8fdf52d146698c5bcf0b842fddc9e398ad8db#0dc8fdf52d146698c5bcf0b842fddc9e398ad8db" source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8d74eee75031b68d2204219963fae54a3f31a394#8d74eee75031b68d2204219963fae54a3f31a394"
dependencies = [ dependencies = [
"schemars", "schemars",
"serde", "serde",
@ -2183,7 +2183,7 @@ dependencies = [
[[package]] [[package]]
name = "rustpython-ast" name = "rustpython-ast"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=0dc8fdf52d146698c5bcf0b842fddc9e398ad8db#0dc8fdf52d146698c5bcf0b842fddc9e398ad8db" source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8d74eee75031b68d2204219963fae54a3f31a394#8d74eee75031b68d2204219963fae54a3f31a394"
dependencies = [ dependencies = [
"is-macro", "is-macro",
"num-bigint", "num-bigint",
@ -2194,7 +2194,7 @@ dependencies = [
[[package]] [[package]]
name = "rustpython-format" name = "rustpython-format"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=0dc8fdf52d146698c5bcf0b842fddc9e398ad8db#0dc8fdf52d146698c5bcf0b842fddc9e398ad8db" source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8d74eee75031b68d2204219963fae54a3f31a394#8d74eee75031b68d2204219963fae54a3f31a394"
dependencies = [ dependencies = [
"bitflags 2.3.1", "bitflags 2.3.1",
"itertools", "itertools",
@ -2206,7 +2206,7 @@ dependencies = [
[[package]] [[package]]
name = "rustpython-literal" name = "rustpython-literal"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=0dc8fdf52d146698c5bcf0b842fddc9e398ad8db#0dc8fdf52d146698c5bcf0b842fddc9e398ad8db" source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8d74eee75031b68d2204219963fae54a3f31a394#8d74eee75031b68d2204219963fae54a3f31a394"
dependencies = [ dependencies = [
"hexf-parse", "hexf-parse",
"is-macro", "is-macro",
@ -2218,7 +2218,7 @@ dependencies = [
[[package]] [[package]]
name = "rustpython-parser" name = "rustpython-parser"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=0dc8fdf52d146698c5bcf0b842fddc9e398ad8db#0dc8fdf52d146698c5bcf0b842fddc9e398ad8db" source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8d74eee75031b68d2204219963fae54a3f31a394#8d74eee75031b68d2204219963fae54a3f31a394"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"is-macro", "is-macro",
@ -2241,9 +2241,10 @@ dependencies = [
[[package]] [[package]]
name = "rustpython-parser-core" name = "rustpython-parser-core"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=0dc8fdf52d146698c5bcf0b842fddc9e398ad8db#0dc8fdf52d146698c5bcf0b842fddc9e398ad8db" source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8d74eee75031b68d2204219963fae54a3f31a394#8d74eee75031b68d2204219963fae54a3f31a394"
dependencies = [ dependencies = [
"is-macro", "is-macro",
"memchr",
"ruff_text_size", "ruff_text_size",
] ]

View file

@ -36,11 +36,11 @@ proc-macro2 = { version = "1.0.51" }
quote = { version = "1.0.23" } quote = { version = "1.0.23" }
regex = { version = "1.7.1" } regex = { version = "1.7.1" }
rustc-hash = { version = "1.1.0" } rustc-hash = { version = "1.1.0" }
ruff_text_size = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "0dc8fdf52d146698c5bcf0b842fddc9e398ad8db" } ruff_text_size = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8d74eee75031b68d2204219963fae54a3f31a394" }
rustpython-ast = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "0dc8fdf52d146698c5bcf0b842fddc9e398ad8db", default-features = false, features = ["all-nodes-with-ranges"]} rustpython-ast = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8d74eee75031b68d2204219963fae54a3f31a394" , default-features = false, features = ["all-nodes-with-ranges", "num-bigint"]}
rustpython-format = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "0dc8fdf52d146698c5bcf0b842fddc9e398ad8db" } rustpython-format = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8d74eee75031b68d2204219963fae54a3f31a394", default-features = false, features = ["num-bigint"] }
rustpython-literal = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "0dc8fdf52d146698c5bcf0b842fddc9e398ad8db" } rustpython-literal = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8d74eee75031b68d2204219963fae54a3f31a394" }
rustpython-parser = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "0dc8fdf52d146698c5bcf0b842fddc9e398ad8db", default-features = false, features = ["full-lexer", "all-nodes-with-ranges"] } rustpython-parser = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8d74eee75031b68d2204219963fae54a3f31a394" , default-features = false, features = ["full-lexer", "all-nodes-with-ranges", "num-bigint"] }
schemars = { version = "0.8.12" } schemars = { version = "0.8.12" }
serde = { version = "1.0.152", features = ["derive"] } serde = { version = "1.0.152", features = ["derive"] }
serde_json = { version = "1.0.93" } serde_json = { version = "1.0.93" }

View file

@ -1,7 +1,7 @@
//! Interface for generating autofix edits from higher-level actions (e.g., "remove an argument"). //! Interface for generating autofix edits from higher-level actions (e.g., "remove an argument").
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use ruff_text_size::{TextLen, TextRange, TextSize}; use ruff_text_size::{TextLen, TextRange, TextSize};
use rustpython_parser::ast::{self, Excepthandler, Expr, Keyword, Ranged, Stmt}; use rustpython_parser::ast::{self, ExceptHandler, Expr, Keyword, Ranged, Stmt};
use rustpython_parser::{lexer, Mode, Tok}; use rustpython_parser::{lexer, Mode, Tok};
use ruff_diagnostics::Edit; use ruff_diagnostics::Edit;
@ -218,7 +218,7 @@ fn is_lone_child(child: &Stmt, parent: &Stmt) -> bool {
|| is_only(orelse, child) || is_only(orelse, child)
|| is_only(finalbody, child) || is_only(finalbody, child)
|| handlers.iter().any(|handler| match handler { || handlers.iter().any(|handler| match handler {
Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
body, .. body, ..
}) => is_only(body, child), }) => is_only(body, child),
}) })

View file

@ -5,8 +5,8 @@ use log::error;
use ruff_text_size::{TextRange, TextSize}; use ruff_text_size::{TextRange, TextSize};
use rustpython_format::cformat::{CFormatError, CFormatErrorType}; use rustpython_format::cformat::{CFormatError, CFormatErrorType};
use rustpython_parser::ast::{ use rustpython_parser::ast::{
self, Arg, Arguments, Comprehension, Constant, Excepthandler, Expr, ExprContext, Keyword, self, Arg, ArgWithDefault, Arguments, Comprehension, Constant, ExceptHandler, Expr,
Operator, Pattern, Ranged, Stmt, Suite, Unaryop, ExprContext, Keyword, Operator, Pattern, Ranged, Stmt, Suite, UnaryOp,
}; };
use ruff_diagnostics::{Diagnostic, Fix, IsolationLevel}; use ruff_diagnostics::{Diagnostic, Fix, IsolationLevel};
@ -17,7 +17,7 @@ use ruff_python_ast::source_code::{Generator, Indexer, Locator, Quote, Stylist};
use ruff_python_ast::str::trailing_quote; use ruff_python_ast::str::trailing_quote;
use ruff_python_ast::types::Node; use ruff_python_ast::types::Node;
use ruff_python_ast::typing::{parse_type_annotation, AnnotationKind}; use ruff_python_ast::typing::{parse_type_annotation, AnnotationKind};
use ruff_python_ast::visitor::{walk_excepthandler, walk_pattern, Visitor}; use ruff_python_ast::visitor::{walk_except_handler, walk_pattern, Visitor};
use ruff_python_ast::{cast, helpers, identifier, str, visitor}; use ruff_python_ast::{cast, helpers, identifier, str, visitor};
use ruff_python_semantic::analyze::{branch_detection, typing, visibility}; use ruff_python_semantic::analyze::{branch_detection, typing, visibility};
use ruff_python_semantic::{ use ruff_python_semantic::{
@ -1759,22 +1759,21 @@ where
// are enabled. // are enabled.
let runtime_annotation = !self.semantic.future_annotations(); let runtime_annotation = !self.semantic.future_annotations();
for arg in &args.posonlyargs { for arg_with_default in args
if let Some(expr) = &arg.annotation { .posonlyargs
.iter()
.chain(&args.args)
.chain(&args.kwonlyargs)
{
if let Some(expr) = &arg_with_default.def.annotation {
if runtime_annotation { if runtime_annotation {
self.visit_type_definition(expr); self.visit_type_definition(expr);
} else { } else {
self.visit_annotation(expr); self.visit_annotation(expr);
}; };
} }
} if let Some(expr) = &arg_with_default.default {
for arg in &args.args { self.visit_expr(expr);
if let Some(expr) = &arg.annotation {
if runtime_annotation {
self.visit_type_definition(expr);
} else {
self.visit_annotation(expr);
};
} }
} }
if let Some(arg) = &args.vararg { if let Some(arg) = &args.vararg {
@ -1786,15 +1785,6 @@ where
}; };
} }
} }
for arg in &args.kwonlyargs {
if let Some(expr) = &arg.annotation {
if runtime_annotation {
self.visit_type_definition(expr);
} else {
self.visit_annotation(expr);
};
}
}
if let Some(arg) = &args.kwarg { if let Some(arg) = &args.kwarg {
if let Some(expr) = &arg.annotation { if let Some(expr) = &arg.annotation {
if runtime_annotation { if runtime_annotation {
@ -1811,12 +1801,6 @@ where
self.visit_annotation(expr); self.visit_annotation(expr);
}; };
} }
for expr in &args.kw_defaults {
self.visit_expr(expr);
}
for expr in &args.defaults {
self.visit_expr(expr);
}
self.add_binding( self.add_binding(
name, name,
@ -1929,8 +1913,8 @@ where
self.semantic.handled_exceptions.pop(); self.semantic.handled_exceptions.pop();
self.semantic.flags |= SemanticModelFlags::EXCEPTION_HANDLER; self.semantic.flags |= SemanticModelFlags::EXCEPTION_HANDLER;
for excepthandler in handlers { for except_handler in handlers {
self.visit_excepthandler(excepthandler); self.visit_except_handler(except_handler);
} }
self.visit_body(orelse); self.visit_body(orelse);
@ -2100,7 +2084,7 @@ where
expr, expr,
Expr::BoolOp(_) Expr::BoolOp(_)
| Expr::UnaryOp(ast::ExprUnaryOp { | Expr::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::Not, op: UnaryOp::Not,
.. ..
}) })
) { ) {
@ -3301,12 +3285,21 @@ where
} }
// Visit the default arguments, but avoid the body, which will be deferred. // Visit the default arguments, but avoid the body, which will be deferred.
for expr in &args.kw_defaults { for ArgWithDefault {
self.visit_expr(expr); default,
} def: _,
for expr in &args.defaults { range: _,
self.visit_expr(expr); } in args
.posonlyargs
.iter()
.chain(&args.args)
.chain(&args.kwonlyargs)
{
if let Some(expr) = &default {
self.visit_expr(expr);
}
} }
self.semantic.push_scope(ScopeKind::Lambda(lambda)); self.semantic.push_scope(ScopeKind::Lambda(lambda));
} }
Expr::IfExp(ast::ExprIfExp { Expr::IfExp(ast::ExprIfExp {
@ -3794,9 +3787,9 @@ where
self.semantic.pop_expr(); self.semantic.pop_expr();
} }
fn visit_excepthandler(&mut self, excepthandler: &'b Excepthandler) { fn visit_except_handler(&mut self, except_handler: &'b ExceptHandler) {
match excepthandler { match except_handler {
Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
type_, type_,
name, name,
body, body,
@ -3807,7 +3800,7 @@ where
if let Some(diagnostic) = pycodestyle::rules::bare_except( if let Some(diagnostic) = pycodestyle::rules::bare_except(
type_.as_deref(), type_.as_deref(),
body, body,
excepthandler, except_handler,
self.locator, self.locator,
) { ) {
self.diagnostics.push(diagnostic); self.diagnostics.push(diagnostic);
@ -3822,7 +3815,7 @@ where
if self.enabled(Rule::TryExceptPass) { if self.enabled(Rule::TryExceptPass) {
flake8_bandit::rules::try_except_pass( flake8_bandit::rules::try_except_pass(
self, self,
excepthandler, except_handler,
type_.as_deref(), type_.as_deref(),
name, name,
body, body,
@ -3832,7 +3825,7 @@ where
if self.enabled(Rule::TryExceptContinue) { if self.enabled(Rule::TryExceptContinue) {
flake8_bandit::rules::try_except_continue( flake8_bandit::rules::try_except_continue(
self, self,
excepthandler, except_handler,
type_.as_deref(), type_.as_deref(),
name, name,
body, body,
@ -3840,20 +3833,20 @@ where
); );
} }
if self.enabled(Rule::ExceptWithEmptyTuple) { if self.enabled(Rule::ExceptWithEmptyTuple) {
flake8_bugbear::rules::except_with_empty_tuple(self, excepthandler); flake8_bugbear::rules::except_with_empty_tuple(self, except_handler);
} }
if self.enabled(Rule::ExceptWithNonExceptionClasses) { if self.enabled(Rule::ExceptWithNonExceptionClasses) {
flake8_bugbear::rules::except_with_non_exception_classes(self, excepthandler); flake8_bugbear::rules::except_with_non_exception_classes(self, except_handler);
} }
if self.enabled(Rule::ReraiseNoCause) { if self.enabled(Rule::ReraiseNoCause) {
tryceratops::rules::reraise_no_cause(self, body); tryceratops::rules::reraise_no_cause(self, body);
} }
if self.enabled(Rule::BinaryOpException) { if self.enabled(Rule::BinaryOpException) {
pylint::rules::binary_op_exception(self, excepthandler); pylint::rules::binary_op_exception(self, except_handler);
} }
match name { match name {
Some(name) => { Some(name) => {
let range = excepthandler.try_identifier(self.locator).unwrap(); let range = except_handler.try_identifier(self.locator).unwrap();
if self.enabled(Rule::AmbiguousVariableName) { if self.enabled(Rule::AmbiguousVariableName) {
if let Some(diagnostic) = if let Some(diagnostic) =
@ -3866,7 +3859,7 @@ where
flake8_builtins::rules::builtin_variable_shadowing( flake8_builtins::rules::builtin_variable_shadowing(
self, self,
name, name,
AnyShadowing::from(excepthandler), AnyShadowing::from(except_handler),
); );
} }
@ -3878,7 +3871,7 @@ where
BindingFlags::empty(), BindingFlags::empty(),
); );
walk_excepthandler(self, excepthandler); walk_except_handler(self, except_handler);
// Remove it from the scope immediately after. // Remove it from the scope immediately after.
self.add_binding( self.add_binding(
@ -3898,7 +3891,7 @@ where
if self.patch(Rule::UnusedVariable) { if self.patch(Rule::UnusedVariable) {
diagnostic.try_set_fix(|| { diagnostic.try_set_fix(|| {
pyflakes::fixes::remove_exception_handler_assignment( pyflakes::fixes::remove_exception_handler_assignment(
excepthandler, except_handler,
self.locator, self.locator,
) )
.map(Fix::automatic) .map(Fix::automatic)
@ -3908,7 +3901,7 @@ where
} }
} }
} }
None => walk_excepthandler(self, excepthandler), None => walk_except_handler(self, except_handler),
} }
} }
} }
@ -3946,17 +3939,17 @@ where
// Bind, but intentionally avoid walking default expressions, as we handle them // Bind, but intentionally avoid walking default expressions, as we handle them
// upstream. // upstream.
for arg in &arguments.posonlyargs { for arg_with_default in &arguments.posonlyargs {
self.visit_arg(arg); self.visit_arg(&arg_with_default.def);
} }
for arg in &arguments.args { for arg_with_default in &arguments.args {
self.visit_arg(arg); self.visit_arg(&arg_with_default.def);
} }
if let Some(arg) = &arguments.vararg { if let Some(arg) = &arguments.vararg {
self.visit_arg(arg); self.visit_arg(arg);
} }
for arg in &arguments.kwonlyargs { for arg_with_default in &arguments.kwonlyargs {
self.visit_arg(arg); self.visit_arg(&arg_with_default.def);
} }
if let Some(arg) = &arguments.kwarg { if let Some(arg) = &arguments.kwarg {
self.visit_arg(arg); self.visit_arg(arg);

View file

@ -1,5 +1,5 @@
use num_bigint::BigInt; use num_bigint::BigInt;
use rustpython_parser::ast::{self, Cmpop, Constant, Expr, Ranged}; use rustpython_parser::ast::{self, CmpOp, Constant, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -66,7 +66,7 @@ impl Violation for SysVersionCmpStr10 {
} }
/// YTT103, YTT201, YTT203, YTT204, YTT302 /// YTT103, YTT201, YTT203, YTT204, YTT302
pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &[Expr]) { pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[CmpOp], comparators: &[Expr]) {
match left { match left {
Expr::Subscript(ast::ExprSubscript { value, slice, .. }) Expr::Subscript(ast::ExprSubscript { value, slice, .. })
if is_sys(value, "version_info", checker.semantic()) => if is_sys(value, "version_info", checker.semantic()) =>
@ -78,7 +78,7 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara
{ {
if *i == BigInt::from(0) { if *i == BigInt::from(0) {
if let ( if let (
[Cmpop::Eq | Cmpop::NotEq], [CmpOp::Eq | CmpOp::NotEq],
[Expr::Constant(ast::ExprConstant { [Expr::Constant(ast::ExprConstant {
value: Constant::Int(n), value: Constant::Int(n),
.. ..
@ -93,7 +93,7 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara
} }
} else if *i == BigInt::from(1) { } else if *i == BigInt::from(1) {
if let ( if let (
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE], [CmpOp::Lt | CmpOp::LtE | CmpOp::Gt | CmpOp::GtE],
[Expr::Constant(ast::ExprConstant { [Expr::Constant(ast::ExprConstant {
value: Constant::Int(_), value: Constant::Int(_),
.. ..
@ -114,7 +114,7 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara
if is_sys(value, "version_info", checker.semantic()) && attr == "minor" => if is_sys(value, "version_info", checker.semantic()) && attr == "minor" =>
{ {
if let ( if let (
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE], [CmpOp::Lt | CmpOp::LtE | CmpOp::Gt | CmpOp::GtE],
[Expr::Constant(ast::ExprConstant { [Expr::Constant(ast::ExprConstant {
value: Constant::Int(_), value: Constant::Int(_),
.. ..
@ -134,7 +134,7 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara
if is_sys(left, "version", checker.semantic()) { if is_sys(left, "version", checker.semantic()) {
if let ( if let (
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE], [CmpOp::Lt | CmpOp::LtE | CmpOp::Gt | CmpOp::GtE],
[Expr::Constant(ast::ExprConstant { [Expr::Constant(ast::ExprConstant {
value: Constant::Str(s), value: Constant::Str(s),
.. ..

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, Ranged, Stmt}; use rustpython_parser::ast::{ArgWithDefault, Expr, Ranged, Stmt};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix, Violation}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -471,7 +471,7 @@ pub(crate) fn definition(
_ => return vec![], _ => return vec![],
}; };
let (name, args, returns, body, decorator_list) = match_function_def(stmt); let (name, arguments, returns, body, decorator_list) = match_function_def(stmt);
// Keep track of whether we've seen any typed arguments or return values. // Keep track of whether we've seen any typed arguments or return values.
let mut has_any_typed_arg = false; // Any argument has been typed? let mut has_any_typed_arg = false; // Any argument has been typed?
let mut has_typed_return = false; // Return value has been typed? let mut has_typed_return = false; // Return value has been typed?
@ -484,11 +484,15 @@ pub(crate) fn definition(
let is_overridden = visibility::is_override(decorator_list, checker.semantic()); let is_overridden = visibility::is_override(decorator_list, checker.semantic());
// ANN001, ANN401 // ANN001, ANN401
for arg in args for ArgWithDefault {
def,
default: _,
range: _,
} in arguments
.posonlyargs .posonlyargs
.iter() .iter()
.chain(args.args.iter()) .chain(&arguments.args)
.chain(args.kwonlyargs.iter()) .chain(&arguments.kwonlyargs)
.skip( .skip(
// If this is a non-static method, skip `cls` or `self`. // If this is a non-static method, skip `cls` or `self`.
usize::from( usize::from(
@ -498,12 +502,12 @@ pub(crate) fn definition(
) )
{ {
// ANN401 for dynamically typed arguments // ANN401 for dynamically typed arguments
if let Some(annotation) = &arg.annotation { if let Some(annotation) = &def.annotation {
has_any_typed_arg = true; has_any_typed_arg = true;
if checker.enabled(Rule::AnyType) { if checker.enabled(Rule::AnyType) {
check_dynamically_typed( check_dynamically_typed(
annotation, annotation,
|| arg.arg.to_string(), || def.arg.to_string(),
&mut diagnostics, &mut diagnostics,
is_overridden, is_overridden,
checker.semantic(), checker.semantic(),
@ -511,14 +515,14 @@ pub(crate) fn definition(
} }
} else { } else {
if !(checker.settings.flake8_annotations.suppress_dummy_args if !(checker.settings.flake8_annotations.suppress_dummy_args
&& checker.settings.dummy_variable_rgx.is_match(&arg.arg)) && checker.settings.dummy_variable_rgx.is_match(&def.arg))
{ {
if checker.enabled(Rule::MissingTypeFunctionArgument) { if checker.enabled(Rule::MissingTypeFunctionArgument) {
diagnostics.push(Diagnostic::new( diagnostics.push(Diagnostic::new(
MissingTypeFunctionArgument { MissingTypeFunctionArgument {
name: arg.arg.to_string(), name: def.arg.to_string(),
}, },
arg.range(), def.range(),
)); ));
} }
} }
@ -526,7 +530,7 @@ pub(crate) fn definition(
} }
// ANN002, ANN401 // ANN002, ANN401
if let Some(arg) = &args.vararg { if let Some(arg) = &arguments.vararg {
if let Some(expr) = &arg.annotation { if let Some(expr) = &arg.annotation {
has_any_typed_arg = true; has_any_typed_arg = true;
if !checker.settings.flake8_annotations.allow_star_arg_any { if !checker.settings.flake8_annotations.allow_star_arg_any {
@ -558,7 +562,7 @@ pub(crate) fn definition(
} }
// ANN003, ANN401 // ANN003, ANN401
if let Some(arg) = &args.kwarg { if let Some(arg) = &arguments.kwarg {
if let Some(expr) = &arg.annotation { if let Some(expr) = &arg.annotation {
has_any_typed_arg = true; has_any_typed_arg = true;
if !checker.settings.flake8_annotations.allow_star_arg_any { if !checker.settings.flake8_annotations.allow_star_arg_any {
@ -591,24 +595,32 @@ pub(crate) fn definition(
// ANN101, ANN102 // ANN101, ANN102
if is_method && !visibility::is_staticmethod(cast::decorator_list(stmt), checker.semantic()) { if is_method && !visibility::is_staticmethod(cast::decorator_list(stmt), checker.semantic()) {
if let Some(arg) = args.posonlyargs.first().or_else(|| args.args.first()) { if let Some(ArgWithDefault {
if arg.annotation.is_none() { def,
default: _,
range: _,
}) = arguments
.posonlyargs
.first()
.or_else(|| arguments.args.first())
{
if def.annotation.is_none() {
if visibility::is_classmethod(cast::decorator_list(stmt), checker.semantic()) { if visibility::is_classmethod(cast::decorator_list(stmt), checker.semantic()) {
if checker.enabled(Rule::MissingTypeCls) { if checker.enabled(Rule::MissingTypeCls) {
diagnostics.push(Diagnostic::new( diagnostics.push(Diagnostic::new(
MissingTypeCls { MissingTypeCls {
name: arg.arg.to_string(), name: def.arg.to_string(),
}, },
arg.range(), def.range(),
)); ));
} }
} else { } else {
if checker.enabled(Rule::MissingTypeSelf) { if checker.enabled(Rule::MissingTypeSelf) {
diagnostics.push(Diagnostic::new( diagnostics.push(Diagnostic::new(
MissingTypeSelf { MissingTypeSelf {
name: arg.arg.to_string(), name: def.arg.to_string(),
}, },
arg.range(), def.range(),
)); ));
} }
} }

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Arg, Arguments, Expr, Ranged}; use rustpython_parser::ast::{Arg, ArgWithDefault, Arguments, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -39,29 +39,21 @@ fn check_password_kwarg(arg: &Arg, default: &Expr) -> Option<Diagnostic> {
pub(crate) fn hardcoded_password_default(arguments: &Arguments) -> Vec<Diagnostic> { pub(crate) fn hardcoded_password_default(arguments: &Arguments) -> Vec<Diagnostic> {
let mut diagnostics: Vec<Diagnostic> = Vec::new(); let mut diagnostics: Vec<Diagnostic> = Vec::new();
let defaults_start = for ArgWithDefault {
arguments.posonlyargs.len() + arguments.args.len() - arguments.defaults.len(); def,
for (i, arg) in arguments default,
range: _,
} in arguments
.posonlyargs .posonlyargs
.iter() .iter()
.chain(&arguments.args) .chain(&arguments.args)
.enumerate() .chain(&arguments.kwonlyargs)
{ {
if let Some(i) = i.checked_sub(defaults_start) { let Some(default) = default else {
let default = &arguments.defaults[i]; continue;
if let Some(diagnostic) = check_password_kwarg(arg, default) { };
diagnostics.push(diagnostic); if let Some(diagnostic) = check_password_kwarg(def, default) {
} diagnostics.push(diagnostic);
}
}
let defaults_start = arguments.kwonlyargs.len() - arguments.kw_defaults.len();
for (i, kwarg) in arguments.kwonlyargs.iter().enumerate() {
if let Some(i) = i.checked_sub(defaults_start) {
let default = &arguments.kw_defaults[i];
if let Some(diagnostic) = check_password_kwarg(kwarg, default) {
diagnostics.push(diagnostic);
}
} }
} }

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Excepthandler, Expr, Ranged, Stmt}; use rustpython_parser::ast::{ExceptHandler, Expr, Ranged, Stmt};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -19,7 +19,7 @@ impl Violation for TryExceptContinue {
/// S112 /// S112
pub(crate) fn try_except_continue( pub(crate) fn try_except_continue(
checker: &mut Checker, checker: &mut Checker,
excepthandler: &Excepthandler, except_handler: &ExceptHandler,
type_: Option<&Expr>, type_: Option<&Expr>,
_name: Option<&str>, _name: Option<&str>,
body: &[Stmt], body: &[Stmt],
@ -31,6 +31,6 @@ pub(crate) fn try_except_continue(
{ {
checker checker
.diagnostics .diagnostics
.push(Diagnostic::new(TryExceptContinue, excepthandler.range())); .push(Diagnostic::new(TryExceptContinue, except_handler.range()));
} }
} }

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Excepthandler, Expr, Ranged, Stmt}; use rustpython_parser::ast::{ExceptHandler, Expr, Ranged, Stmt};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -19,7 +19,7 @@ impl Violation for TryExceptPass {
/// S110 /// S110
pub(crate) fn try_except_pass( pub(crate) fn try_except_pass(
checker: &mut Checker, checker: &mut Checker,
excepthandler: &Excepthandler, except_handler: &ExceptHandler,
type_: Option<&Expr>, type_: Option<&Expr>,
_name: Option<&str>, _name: Option<&str>,
body: &[Stmt], body: &[Stmt],
@ -31,6 +31,6 @@ pub(crate) fn try_except_pass(
{ {
checker checker
.diagnostics .diagnostics
.push(Diagnostic::new(TryExceptPass, excepthandler.range())); .push(Diagnostic::new(TryExceptPass, except_handler.range()));
} }
} }

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Arguments, Decorator}; use rustpython_parser::ast::{ArgWithDefault, Arguments, Decorator};
use ruff_diagnostics::Violation; use ruff_diagnostics::Violation;
@ -75,7 +75,19 @@ pub(crate) fn check_boolean_default_value_in_function_definition(
return; return;
} }
for arg in &arguments.defaults { for ArgWithDefault {
add_if_boolean(checker, arg, BooleanDefaultValueInFunctionDefinition.into()); def: _,
default,
range: _,
} in arguments.args.iter().chain(&arguments.posonlyargs)
{
let Some(default) = default else {
continue;
};
add_if_boolean(
checker,
default,
BooleanDefaultValueInFunctionDefinition.into(),
);
} }
} }

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Arguments, Constant, Decorator, Expr, Ranged}; use rustpython_parser::ast::{self, ArgWithDefault, Arguments, Constant, Decorator, Expr, Ranged};
use ruff_diagnostics::Diagnostic; use ruff_diagnostics::Diagnostic;
use ruff_diagnostics::Violation; use ruff_diagnostics::Violation;
@ -93,11 +93,16 @@ pub(crate) fn check_positional_boolean_in_def(
return; return;
} }
for arg in arguments.posonlyargs.iter().chain(arguments.args.iter()) { for ArgWithDefault {
if arg.annotation.is_none() { def,
default: _,
range: _,
} in arguments.posonlyargs.iter().chain(&arguments.args)
{
if def.annotation.is_none() {
continue; continue;
} }
let Some(expr) = &arg.annotation else { let Some(expr) = &def.annotation else {
continue; continue;
}; };
@ -115,7 +120,7 @@ pub(crate) fn check_positional_boolean_in_def(
} }
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
BooleanPositionalArgInFunctionDefinition, BooleanPositionalArgInFunctionDefinition,
arg.range(), def.range(),
)); ));
} }
} }

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Expr, Ranged, Stmt, Withitem}; use rustpython_parser::ast::{self, Expr, Ranged, Stmt, WithItem};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -50,7 +50,7 @@ impl Violation for AssertRaisesException {
} }
/// B017 /// B017
pub(crate) fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items: &[Withitem]) { pub(crate) fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items: &[WithItem]) {
let Some(item) = items.first() else { let Some(item) = items.first() else {
return; return;
}; };

View file

@ -1,7 +1,7 @@
use itertools::Itertools; use itertools::Itertools;
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use rustpython_parser::ast::{self, Excepthandler, Expr, ExprContext, Ranged}; use rustpython_parser::ast::{self, ExceptHandler, Expr, ExprContext, Ranged};
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation}; use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
use ruff_diagnostics::{Diagnostic, Edit, Fix}; use ruff_diagnostics::{Diagnostic, Edit, Fix};
@ -105,11 +105,11 @@ fn duplicate_handler_exceptions<'a>(
seen seen
} }
pub(crate) fn duplicate_exceptions(checker: &mut Checker, handlers: &[Excepthandler]) { pub(crate) fn duplicate_exceptions(checker: &mut Checker, handlers: &[ExceptHandler]) {
let mut seen: FxHashSet<CallPath> = FxHashSet::default(); let mut seen: FxHashSet<CallPath> = FxHashSet::default();
let mut duplicates: FxHashMap<CallPath, Vec<&Expr>> = FxHashMap::default(); let mut duplicates: FxHashMap<CallPath, Vec<&Expr>> = FxHashMap::default();
for handler in handlers { for handler in handlers {
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_: Some(type_), .. }) = handler else { let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_: Some(type_), .. }) = handler else {
continue; continue;
}; };
match type_.as_ref() { match type_.as_ref() {

View file

@ -1,5 +1,5 @@
use rustpython_parser::ast::{self, Ranged}; use rustpython_parser::ast::{self, Ranged};
use rustpython_parser::ast::{Excepthandler, Expr}; use rustpython_parser::ast::{ExceptHandler, Expr};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -17,8 +17,9 @@ impl Violation for ExceptWithEmptyTuple {
} }
/// B029 /// B029
pub(crate) fn except_with_empty_tuple(checker: &mut Checker, excepthandler: &Excepthandler) { pub(crate) fn except_with_empty_tuple(checker: &mut Checker, except_handler: &ExceptHandler) {
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = excepthandler; let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, .. }) =
except_handler;
let Some(type_) = type_ else { let Some(type_) = type_ else {
return; return;
}; };
@ -26,8 +27,9 @@ pub(crate) fn except_with_empty_tuple(checker: &mut Checker, excepthandler: &Exc
return; return;
}; };
if elts.is_empty() { if elts.is_empty() {
checker checker.diagnostics.push(Diagnostic::new(
.diagnostics ExceptWithEmptyTuple,
.push(Diagnostic::new(ExceptWithEmptyTuple, excepthandler.range())); except_handler.range(),
));
} }
} }

View file

@ -1,6 +1,6 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use rustpython_parser::ast::{self, Excepthandler, Expr, Ranged}; use rustpython_parser::ast::{self, ExceptHandler, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -44,9 +44,10 @@ fn flatten_starred_iterables(expr: &Expr) -> Vec<&Expr> {
/// B030 /// B030
pub(crate) fn except_with_non_exception_classes( pub(crate) fn except_with_non_exception_classes(
checker: &mut Checker, checker: &mut Checker,
excepthandler: &Excepthandler, except_handler: &ExceptHandler,
) { ) {
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = excepthandler; let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, .. }) =
except_handler;
let Some(type_) = type_ else { let Some(type_) = type_ else {
return; return;
}; };

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Arguments, Expr, Ranged}; use rustpython_parser::ast::{self, ArgWithDefault, Arguments, Expr, Ranged};
use ruff_diagnostics::Violation; use ruff_diagnostics::Violation;
use ruff_diagnostics::{Diagnostic, DiagnosticKind}; use ruff_diagnostics::{Diagnostic, DiagnosticKind};
@ -114,12 +114,19 @@ pub(crate) fn function_call_argument_default(checker: &mut Checker, arguments: &
.collect(); .collect();
let diagnostics = { let diagnostics = {
let mut visitor = ArgumentDefaultVisitor::new(checker.semantic(), extend_immutable_calls); let mut visitor = ArgumentDefaultVisitor::new(checker.semantic(), extend_immutable_calls);
for expr in arguments for ArgWithDefault {
.defaults default,
def: _,
range: _,
} in arguments
.posonlyargs
.iter() .iter()
.chain(arguments.kw_defaults.iter()) .chain(&arguments.args)
.chain(&arguments.kwonlyargs)
{ {
visitor.visit_expr(expr); if let Some(expr) = &default {
visitor.visit_expr(expr);
}
} }
visitor.diagnostics visitor.diagnostics
}; };

View file

@ -1,5 +1,5 @@
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use rustpython_parser::ast::{self, Expr, Ranged}; use rustpython_parser::ast::{self, ArgWithDefault, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -49,8 +49,17 @@ where
range: _, range: _,
}) => { }) => {
visitor::walk_expr(self, body); visitor::walk_expr(self, body);
for arg in &args.args { for ArgWithDefault {
self.names.remove(arg.arg.as_str()); def,
default: _,
range: _,
} in args
.posonlyargs
.iter()
.chain(&args.args)
.chain(&args.kwonlyargs)
{
self.names.remove(def.arg.as_str());
} }
} }
_ => visitor::walk_expr(self, expr), _ => visitor::walk_expr(self, expr),

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Arguments, Ranged}; use rustpython_parser::ast::{ArgWithDefault, Arguments, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -19,22 +19,22 @@ impl Violation for MutableArgumentDefault {
/// B006 /// B006
pub(crate) fn mutable_argument_default(checker: &mut Checker, arguments: &Arguments) { pub(crate) fn mutable_argument_default(checker: &mut Checker, arguments: &Arguments) {
// Scan in reverse order to right-align zip(). // Scan in reverse order to right-align zip().
for (arg, default) in arguments for ArgWithDefault {
.kwonlyargs def,
default,
range: _,
} in arguments
.posonlyargs
.iter() .iter()
.rev() .chain(&arguments.args)
.zip(arguments.kw_defaults.iter().rev()) .chain(&arguments.kwonlyargs)
.chain(
arguments
.args
.iter()
.rev()
.chain(arguments.posonlyargs.iter().rev())
.zip(arguments.defaults.iter().rev()),
)
{ {
let Some(default)= default else {
continue;
};
if is_mutable_expr(default, checker.semantic()) if is_mutable_expr(default, checker.semantic())
&& !arg.annotation.as_ref().map_or(false, |expr| { && !def.annotation.as_ref().map_or(false, |expr| {
is_immutable_annotation(expr, checker.semantic()) is_immutable_annotation(expr, checker.semantic())
}) })
{ {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Excepthandler, Expr, Ranged}; use rustpython_parser::ast::{self, ExceptHandler, Expr, Ranged};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -30,10 +30,10 @@ impl AlwaysAutofixableViolation for RedundantTupleInExceptionHandler {
/// B013 /// B013
pub(crate) fn redundant_tuple_in_exception_handler( pub(crate) fn redundant_tuple_in_exception_handler(
checker: &mut Checker, checker: &mut Checker,
handlers: &[Excepthandler], handlers: &[ExceptHandler],
) { ) {
for handler in handlers { for handler in handlers {
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_: Some(type_), .. }) = handler else { let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_: Some(type_), .. }) = handler else {
continue; continue;
}; };
let Expr::Tuple(ast::ExprTuple { elts, .. }) = type_.as_ref() else { let Expr::Tuple(ast::ExprTuple { elts, .. }) = type_.as_ref() else {

View file

@ -17,7 +17,7 @@
//! n += 1 //! n += 1
//! ``` //! ```
use rustpython_parser::ast::{self, Expr, Ranged, Unaryop}; use rustpython_parser::ast::{self, Expr, Ranged, UnaryOp};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -38,16 +38,16 @@ impl Violation for UnaryPrefixIncrement {
pub(crate) fn unary_prefix_increment( pub(crate) fn unary_prefix_increment(
checker: &mut Checker, checker: &mut Checker,
expr: &Expr, expr: &Expr,
op: Unaryop, op: UnaryOp,
operand: &Expr, operand: &Expr,
) { ) {
if !matches!(op, Unaryop::UAdd) { if !matches!(op, UnaryOp::UAdd) {
return; return;
} }
let Expr::UnaryOp(ast::ExprUnaryOp { op, .. })= operand else { let Expr::UnaryOp(ast::ExprUnaryOp { op, .. })= operand else {
return; return;
}; };
if !matches!(op, Unaryop::UAdd) { if !matches!(op, UnaryOp::UAdd) {
return; return;
} }
checker checker

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{Excepthandler, Expr, Ranged, Stmt}; use rustpython_parser::ast::{ExceptHandler, Expr, Ranged, Stmt};
use ruff_python_ast::identifier::Identifier; use ruff_python_ast::identifier::Identifier;
use ruff_python_ast::source_code::Locator; use ruff_python_ast::source_code::Locator;
@ -13,7 +13,7 @@ pub(super) fn shadows_builtin(name: &str, ignorelist: &[String]) -> bool {
pub(crate) enum AnyShadowing<'a> { pub(crate) enum AnyShadowing<'a> {
Expression(&'a Expr), Expression(&'a Expr),
Statement(&'a Stmt), Statement(&'a Stmt),
ExceptHandler(&'a Excepthandler), ExceptHandler(&'a ExceptHandler),
} }
impl AnyShadowing<'_> { impl AnyShadowing<'_> {
@ -38,8 +38,8 @@ impl<'a> From<&'a Expr> for AnyShadowing<'a> {
} }
} }
impl<'a> From<&'a Excepthandler> for AnyShadowing<'a> { impl<'a> From<&'a ExceptHandler> for AnyShadowing<'a> {
fn from(value: &'a Excepthandler) -> Self { fn from(value: &'a ExceptHandler) -> Self {
AnyShadowing::ExceptHandler(value) AnyShadowing::ExceptHandler(value)
} }
} }

View file

@ -1,5 +1,5 @@
use num_bigint::BigInt; use num_bigint::BigInt;
use rustpython_parser::ast::{self, Constant, Expr, Ranged, Unaryop}; use rustpython_parser::ast::{self, Constant, Expr, Ranged, UnaryOp};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -74,7 +74,7 @@ pub(crate) fn unnecessary_subscript_reversal(
return; return;
}; };
let Expr::UnaryOp(ast::ExprUnaryOp { let Expr::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::USub, op: UnaryOp::USub,
operand, operand,
range: _, range: _,
}) = step.as_ref() else { }) = step.as_ref() else {

View file

@ -5,7 +5,7 @@ use itertools::Either::{Left, Right};
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Boolop, Expr, ExprContext, Ranged}; use rustpython_parser::ast::{self, BoolOp, Expr, ExprContext, Ranged};
use ruff_diagnostics::AlwaysAutofixableViolation; use ruff_diagnostics::AlwaysAutofixableViolation;
use ruff_diagnostics::{Diagnostic, Edit, Fix}; use ruff_diagnostics::{Diagnostic, Edit, Fix};
@ -60,7 +60,7 @@ impl AlwaysAutofixableViolation for MultipleStartsEndsWith {
/// PIE810 /// PIE810
pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) { pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
let Expr::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values, range: _ }) = expr else { let Expr::BoolOp(ast::ExprBoolOp { op: BoolOp::Or, values, range: _ }) = expr else {
return; return;
}; };
@ -155,7 +155,7 @@ pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
// Generate the combined `BoolOp`. // Generate the combined `BoolOp`.
let mut call = Some(call); let mut call = Some(call);
let node = Expr::BoolOp(ast::ExprBoolOp { let node = Expr::BoolOp(ast::ExprBoolOp {
op: Boolop::Or, op: BoolOp::Or,
values: values values: values
.iter() .iter()
.enumerate() .enumerate()

View file

@ -62,7 +62,7 @@ pub(crate) fn any_eq_ne_annotation(checker: &mut Checker, name: &str, args: &Arg
return; return;
} }
let Some(annotation) = &args.args[1].annotation else { let Some(annotation) = &args.args[1].def.annotation else {
return; return;
}; };

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Cmpop, Expr, Ranged}; use rustpython_parser::ast::{CmpOp, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -61,7 +61,7 @@ pub(crate) fn bad_version_info_comparison(
checker: &mut Checker, checker: &mut Checker,
expr: &Expr, expr: &Expr,
left: &Expr, left: &Expr,
ops: &[Cmpop], ops: &[CmpOp],
comparators: &[Expr], comparators: &[Expr],
) { ) {
let ([op], [_right]) = (ops, comparators) else { let ([op], [_right]) = (ops, comparators) else {
@ -78,7 +78,7 @@ pub(crate) fn bad_version_info_comparison(
return; return;
} }
if !matches!(op, Cmpop::Lt | Cmpop::GtE) { if !matches!(op, CmpOp::Lt | CmpOp::GtE) {
let diagnostic = Diagnostic::new(BadVersionInfoComparison, expr.range()); let diagnostic = Diagnostic::new(BadVersionInfoComparison, expr.range());
checker.diagnostics.push(diagnostic); checker.diagnostics.push(diagnostic);
} }

View file

@ -1,6 +1,5 @@
use std::fmt; use std::fmt;
use itertools::chain;
use rustpython_parser::ast::Ranged; use rustpython_parser::ast::Ranged;
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
@ -49,12 +48,12 @@ impl Violation for NoReturnArgumentAnnotationInStub {
/// PYI050 /// PYI050
pub(crate) fn no_return_argument_annotation(checker: &mut Checker, args: &Arguments) { pub(crate) fn no_return_argument_annotation(checker: &mut Checker, args: &Arguments) {
for annotation in chain!( for annotation in args
args.args.iter(), .posonlyargs
args.posonlyargs.iter(), .iter()
args.kwonlyargs.iter() .chain(&args.args)
) .chain(&args.kwonlyargs)
.filter_map(|arg| arg.annotation.as_ref()) .filter_map(|arg| arg.def.annotation.as_ref())
{ {
if checker.semantic().match_typing_expr(annotation, "NoReturn") { if checker.semantic().match_typing_expr(annotation, "NoReturn") {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(

View file

@ -1,4 +1,6 @@
use rustpython_parser::ast::{self, Arguments, Constant, Expr, Operator, Ranged, Stmt, Unaryop}; use rustpython_parser::ast::{
self, ArgWithDefault, Arguments, Constant, Expr, Operator, Ranged, Stmt, UnaryOp,
};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -156,7 +158,7 @@ fn is_valid_default_value_with_annotation(
}); });
} }
Expr::UnaryOp(ast::ExprUnaryOp { Expr::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::USub, op: UnaryOp::USub,
operand, operand,
range: _, range: _,
}) => { }) => {
@ -199,7 +201,7 @@ fn is_valid_default_value_with_annotation(
{ {
return locator.slice(left.range()).len() <= 10; return locator.slice(left.range()).len() <= 10;
} else if let Expr::UnaryOp(ast::ExprUnaryOp { } else if let Expr::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::USub, op: UnaryOp::USub,
operand, operand,
range: _, range: _,
}) = left.as_ref() }) = left.as_ref()
@ -312,130 +314,74 @@ fn is_enum(bases: &[Expr], semantic: &SemanticModel) -> bool {
} }
/// PYI011 /// PYI011
pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, args: &Arguments) { pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, arguments: &Arguments) {
if !args.defaults.is_empty() { for ArgWithDefault {
let defaults_start = args.posonlyargs.len() + args.args.len() - args.defaults.len(); def,
for (i, arg) in args.posonlyargs.iter().chain(&args.args).enumerate() { default,
if let Some(default) = i range: _,
.checked_sub(defaults_start) } in arguments
.and_then(|i| args.defaults.get(i)) .posonlyargs
{ .iter()
if arg.annotation.is_some() { .chain(&arguments.args)
if !is_valid_default_value_with_annotation( .chain(&arguments.kwonlyargs)
default, {
true, let Some(default) = default else {
checker.locator, continue;
checker.semantic(), };
) { if def.annotation.is_some() {
let mut diagnostic = if !is_valid_default_value_with_annotation(
Diagnostic::new(TypedArgumentDefaultInStub, default.range()); default,
true,
checker.locator,
checker.semantic(),
) {
let mut diagnostic = Diagnostic::new(TypedArgumentDefaultInStub, default.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
diagnostic.set_fix(Fix::suggested(Edit::range_replacement( diagnostic.set_fix(Fix::suggested(Edit::range_replacement(
"...".to_string(), "...".to_string(),
default.range(), default.range(),
))); )));
}
checker.diagnostics.push(diagnostic);
}
} }
}
}
}
if !args.kw_defaults.is_empty() { checker.diagnostics.push(diagnostic);
let defaults_start = args.kwonlyargs.len() - args.kw_defaults.len();
for (i, kwarg) in args.kwonlyargs.iter().enumerate() {
if let Some(default) = i
.checked_sub(defaults_start)
.and_then(|i| args.kw_defaults.get(i))
{
if kwarg.annotation.is_some() {
if !is_valid_default_value_with_annotation(
default,
true,
checker.locator,
checker.semantic(),
) {
let mut diagnostic =
Diagnostic::new(TypedArgumentDefaultInStub, default.range());
if checker.patch(diagnostic.kind.rule()) {
diagnostic.set_fix(Fix::suggested(Edit::range_replacement(
"...".to_string(),
default.range(),
)));
}
checker.diagnostics.push(diagnostic);
}
}
} }
} }
} }
} }
/// PYI014 /// PYI014
pub(crate) fn argument_simple_defaults(checker: &mut Checker, args: &Arguments) { pub(crate) fn argument_simple_defaults(checker: &mut Checker, arguments: &Arguments) {
if !args.defaults.is_empty() { for ArgWithDefault {
let defaults_start = args.posonlyargs.len() + args.args.len() - args.defaults.len(); def,
for (i, arg) in args.posonlyargs.iter().chain(&args.args).enumerate() { default,
if let Some(default) = i range: _,
.checked_sub(defaults_start) } in arguments
.and_then(|i| args.defaults.get(i)) .posonlyargs
{ .iter()
if arg.annotation.is_none() { .chain(&arguments.args)
if !is_valid_default_value_with_annotation( .chain(&arguments.kwonlyargs)
default, {
true, let Some(default) = default else {
checker.locator, continue;
checker.semantic(), };
) { if def.annotation.is_none() {
let mut diagnostic = if !is_valid_default_value_with_annotation(
Diagnostic::new(ArgumentDefaultInStub, default.range()); default,
true,
checker.locator,
checker.semantic(),
) {
let mut diagnostic = Diagnostic::new(ArgumentDefaultInStub, default.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
diagnostic.set_fix(Fix::suggested(Edit::range_replacement( diagnostic.set_fix(Fix::suggested(Edit::range_replacement(
"...".to_string(), "...".to_string(),
default.range(), default.range(),
))); )));
}
checker.diagnostics.push(diagnostic);
}
} }
}
}
}
if !args.kw_defaults.is_empty() { checker.diagnostics.push(diagnostic);
let defaults_start = args.kwonlyargs.len() - args.kw_defaults.len();
for (i, kwarg) in args.kwonlyargs.iter().enumerate() {
if let Some(default) = i
.checked_sub(defaults_start)
.and_then(|i| args.kw_defaults.get(i))
{
if kwarg.annotation.is_none() {
if !is_valid_default_value_with_annotation(
default,
true,
checker.locator,
checker.semantic(),
) {
let mut diagnostic =
Diagnostic::new(ArgumentDefaultInStub, default.range());
if checker.patch(diagnostic.kind.rule()) {
diagnostic.set_fix(Fix::suggested(Edit::range_replacement(
"...".to_string(),
default.range(),
)));
}
checker.diagnostics.push(diagnostic);
}
}
} }
} }
} }

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Cmpop, Constant, Expr, Ranged}; use rustpython_parser::ast::{self, CmpOp, Constant, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -93,7 +93,7 @@ pub(crate) fn unrecognized_platform(
checker: &mut Checker, checker: &mut Checker,
expr: &Expr, expr: &Expr,
left: &Expr, left: &Expr,
ops: &[Cmpop], ops: &[CmpOp],
comparators: &[Expr], comparators: &[Expr],
) { ) {
let ([op], [right]) = (ops, comparators) else { let ([op], [right]) = (ops, comparators) else {
@ -113,7 +113,7 @@ pub(crate) fn unrecognized_platform(
} }
// "in" might also make sense but we don't currently have one. // "in" might also make sense but we don't currently have one.
if !matches!(op, Cmpop::Eq | Cmpop::NotEq) && checker.enabled(Rule::UnrecognizedPlatformCheck) { if !matches!(op, CmpOp::Eq | CmpOp::NotEq) && checker.enabled(Rule::UnrecognizedPlatformCheck) {
checker checker
.diagnostics .diagnostics
.push(diagnostic_unrecognized_platform_check); .push(diagnostic_unrecognized_platform_check);

View file

@ -3,11 +3,11 @@ use std::borrow::Cow;
use anyhow::bail; use anyhow::bail;
use anyhow::Result; use anyhow::Result;
use libcst_native::{ use libcst_native::{
Assert, BooleanOp, CompoundStatement, Expression, ParenthesizableWhitespace, ParenthesizedNode, self, Assert, BooleanOp, CompoundStatement, Expression, ParenthesizableWhitespace,
SimpleStatementLine, SimpleWhitespace, SmallStatement, Statement, TrailingWhitespace, UnaryOp, ParenthesizedNode, SimpleStatementLine, SimpleWhitespace, SmallStatement, Statement,
UnaryOperation, TrailingWhitespace, UnaryOperation,
}; };
use rustpython_parser::ast::{self, Boolop, Excepthandler, Expr, Keyword, Ranged, Stmt, Unaryop}; use rustpython_parser::ast::{self, BoolOp, ExceptHandler, Expr, Keyword, Ranged, Stmt, UnaryOp};
use crate::autofix::codemods::CodegenStylist; use crate::autofix::codemods::CodegenStylist;
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
@ -227,11 +227,11 @@ pub(crate) fn assert_falsy(checker: &mut Checker, stmt: &Stmt, test: &Expr) {
} }
/// PT017 /// PT017
pub(crate) fn assert_in_exception_handler(handlers: &[Excepthandler]) -> Vec<Diagnostic> { pub(crate) fn assert_in_exception_handler(handlers: &[ExceptHandler]) -> Vec<Diagnostic> {
handlers handlers
.iter() .iter()
.flat_map(|handler| match handler { .flat_map(|handler| match handler {
Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
name, body, .. name, body, ..
}) => { }) => {
if let Some(name) = name { if let Some(name) = name {
@ -262,17 +262,17 @@ enum CompositionKind {
fn is_composite_condition(test: &Expr) -> CompositionKind { fn is_composite_condition(test: &Expr) -> CompositionKind {
match test { match test {
Expr::BoolOp(ast::ExprBoolOp { Expr::BoolOp(ast::ExprBoolOp {
op: Boolop::And, .. op: BoolOp::And, ..
}) => { }) => {
return CompositionKind::Simple; return CompositionKind::Simple;
} }
Expr::UnaryOp(ast::ExprUnaryOp { Expr::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::Not, op: UnaryOp::Not,
operand, operand,
range: _, range: _,
}) => { }) => {
if let Expr::BoolOp(ast::ExprBoolOp { if let Expr::BoolOp(ast::ExprBoolOp {
op: Boolop::Or, op: BoolOp::Or,
values, values,
range: _, range: _,
}) = operand.as_ref() }) = operand.as_ref()
@ -282,7 +282,7 @@ fn is_composite_condition(test: &Expr) -> CompositionKind {
!matches!( !matches!(
expr, expr,
Expr::BoolOp(ast::ExprBoolOp { Expr::BoolOp(ast::ExprBoolOp {
op: Boolop::And, op: BoolOp::And,
.. ..
}) })
) )
@ -301,12 +301,12 @@ fn is_composite_condition(test: &Expr) -> CompositionKind {
/// Negate a condition, i.e., `a` => `not a` and `not a` => `a`. /// Negate a condition, i.e., `a` => `not a` and `not a` => `a`.
fn negate<'a>(expression: &Expression<'a>) -> Expression<'a> { fn negate<'a>(expression: &Expression<'a>) -> Expression<'a> {
if let Expression::UnaryOperation(ref expression) = expression { if let Expression::UnaryOperation(ref expression) = expression {
if matches!(expression.operator, UnaryOp::Not { .. }) { if matches!(expression.operator, libcst_native::UnaryOp::Not { .. }) {
return *expression.expression.clone(); return *expression.expression.clone();
} }
} }
Expression::UnaryOperation(Box::new(UnaryOperation { Expression::UnaryOperation(Box::new(UnaryOperation {
operator: UnaryOp::Not { operator: libcst_native::UnaryOp::Not {
whitespace_after: ParenthesizableWhitespace::SimpleWhitespace(SimpleWhitespace(" ")), whitespace_after: ParenthesizableWhitespace::SimpleWhitespace(SimpleWhitespace(" ")),
}, },
expression: Box::new(expression.clone()), expression: Box::new(expression.clone()),
@ -371,7 +371,7 @@ fn fix_composite_condition(stmt: &Stmt, locator: &Locator, stylist: &Stylist) ->
let mut conditions: Vec<Expression> = Vec::with_capacity(2); let mut conditions: Vec<Expression> = Vec::with_capacity(2);
match &assert_statement.test { match &assert_statement.test {
Expression::UnaryOperation(op) => { Expression::UnaryOperation(op) => {
if matches!(op.operator, UnaryOp::Not { .. }) { if matches!(op.operator, libcst_native::UnaryOp::Not { .. }) {
if let Expression::BooleanOperation(op) = &*op.expression { if let Expression::BooleanOperation(op) = &*op.expression {
if matches!(op.operator, BooleanOp::Or { .. }) { if matches!(op.operator, BooleanOp::Or { .. }) {
conditions.push(negate(&op.left)); conditions.push(negate(&op.left));

View file

@ -2,7 +2,7 @@ use std::fmt;
use anyhow::Result; use anyhow::Result;
use ruff_text_size::{TextLen, TextRange, TextSize}; use ruff_text_size::{TextLen, TextRange, TextSize};
use rustpython_parser::ast::{self, Arguments, Expr, Keyword, Ranged, Stmt}; use rustpython_parser::ast::{self, ArgWithDefault, Arguments, Expr, Keyword, Ranged, Stmt};
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation}; use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
use ruff_diagnostics::{Diagnostic, Edit, Fix}; use ruff_diagnostics::{Diagnostic, Edit, Fix};
@ -421,18 +421,29 @@ fn check_fixture_returns(checker: &mut Checker, stmt: &Stmt, name: &str, body: &
} }
/// PT019 /// PT019
fn check_test_function_args(checker: &mut Checker, args: &Arguments) { fn check_test_function_args(checker: &mut Checker, arguments: &Arguments) {
args.args.iter().chain(&args.kwonlyargs).for_each(|arg| { arguments
let name = &arg.arg; .posonlyargs
if name.starts_with('_') { .iter()
checker.diagnostics.push(Diagnostic::new( .chain(&arguments.args)
PytestFixtureParamWithoutValue { .chain(&arguments.kwonlyargs)
name: name.to_string(), .for_each(
}, |ArgWithDefault {
arg.range(), def,
)); default: _,
} range: _,
}); }| {
let name = &def.arg;
if name.starts_with('_') {
checker.diagnostics.push(Diagnostic::new(
PytestFixtureParamWithoutValue {
name: name.to_string(),
},
def.range(),
));
}
},
);
} }
/// PT020 /// PT020

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Expr, Identifier, Keyword, Ranged, Stmt, Withitem}; use rustpython_parser::ast::{self, Expr, Identifier, Keyword, Ranged, Stmt, WithItem};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -94,7 +94,7 @@ pub(crate) fn raises_call(checker: &mut Checker, func: &Expr, args: &[Expr], key
pub(crate) fn complex_raises( pub(crate) fn complex_raises(
checker: &mut Checker, checker: &mut Checker,
stmt: &Stmt, stmt: &Stmt,
items: &[Withitem], items: &[WithItem],
body: &[Stmt], body: &[Stmt],
) { ) {
let mut is_too_complex = false; let mut is_too_complex = false;

View file

@ -3,7 +3,7 @@ use std::hash::BuildHasherDefault;
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Result};
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use rustpython_parser::ast::{self, Cmpop, Constant, Expr, ExprContext, Keyword, Stmt, Unaryop}; use rustpython_parser::ast::{self, CmpOp, Constant, Expr, ExprContext, Keyword, Stmt, UnaryOp};
/// An enum to represent the different types of assertions present in the /// An enum to represent the different types of assertions present in the
/// `unittest` module. Note: any variants that can't be replaced with plain /// `unittest` module. Note: any variants that can't be replaced with plain
@ -149,10 +149,10 @@ fn assert(expr: &Expr, msg: Option<&Expr>) -> Stmt {
}) })
} }
fn compare(left: &Expr, cmpop: Cmpop, right: &Expr) -> Expr { fn compare(left: &Expr, cmp_op: CmpOp, right: &Expr) -> Expr {
Expr::Compare(ast::ExprCompare { Expr::Compare(ast::ExprCompare {
left: Box::new(left.clone()), left: Box::new(left.clone()),
ops: vec![cmpop], ops: vec![cmp_op],
comparators: vec![right.clone()], comparators: vec![right.clone()],
range: TextRange::default(), range: TextRange::default(),
}) })
@ -263,7 +263,7 @@ impl UnittestAssert {
Ok(if matches!(self, UnittestAssert::False) { Ok(if matches!(self, UnittestAssert::False) {
assert( assert(
&Expr::UnaryOp(ast::ExprUnaryOp { &Expr::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::Not, op: UnaryOp::Not,
operand: Box::new(expr.clone()), operand: Box::new(expr.clone()),
range: TextRange::default(), range: TextRange::default(),
}), }),
@ -290,18 +290,18 @@ impl UnittestAssert {
.get("second") .get("second")
.ok_or_else(|| anyhow!("Missing argument `second`"))?; .ok_or_else(|| anyhow!("Missing argument `second`"))?;
let msg = args.get("msg").copied(); let msg = args.get("msg").copied();
let cmpop = match self { let cmp_op = match self {
UnittestAssert::Equal | UnittestAssert::Equals => Cmpop::Eq, UnittestAssert::Equal | UnittestAssert::Equals => CmpOp::Eq,
UnittestAssert::NotEqual | UnittestAssert::NotEquals => Cmpop::NotEq, UnittestAssert::NotEqual | UnittestAssert::NotEquals => CmpOp::NotEq,
UnittestAssert::Greater => Cmpop::Gt, UnittestAssert::Greater => CmpOp::Gt,
UnittestAssert::GreaterEqual => Cmpop::GtE, UnittestAssert::GreaterEqual => CmpOp::GtE,
UnittestAssert::Less => Cmpop::Lt, UnittestAssert::Less => CmpOp::Lt,
UnittestAssert::LessEqual => Cmpop::LtE, UnittestAssert::LessEqual => CmpOp::LtE,
UnittestAssert::Is => Cmpop::Is, UnittestAssert::Is => CmpOp::Is,
UnittestAssert::IsNot => Cmpop::IsNot, UnittestAssert::IsNot => CmpOp::IsNot,
_ => unreachable!(), _ => unreachable!(),
}; };
let expr = compare(first, cmpop, second); let expr = compare(first, cmp_op, second);
Ok(assert(&expr, msg)) Ok(assert(&expr, msg))
} }
UnittestAssert::In | UnittestAssert::NotIn => { UnittestAssert::In | UnittestAssert::NotIn => {
@ -312,12 +312,12 @@ impl UnittestAssert {
.get("container") .get("container")
.ok_or_else(|| anyhow!("Missing argument `container`"))?; .ok_or_else(|| anyhow!("Missing argument `container`"))?;
let msg = args.get("msg").copied(); let msg = args.get("msg").copied();
let cmpop = if matches!(self, UnittestAssert::In) { let cmp_op = if matches!(self, UnittestAssert::In) {
Cmpop::In CmpOp::In
} else { } else {
Cmpop::NotIn CmpOp::NotIn
}; };
let expr = compare(member, cmpop, container); let expr = compare(member, cmp_op, container);
Ok(assert(&expr, msg)) Ok(assert(&expr, msg))
} }
UnittestAssert::IsNone | UnittestAssert::IsNotNone => { UnittestAssert::IsNone | UnittestAssert::IsNotNone => {
@ -325,17 +325,17 @@ impl UnittestAssert {
.get("expr") .get("expr")
.ok_or_else(|| anyhow!("Missing argument `expr`"))?; .ok_or_else(|| anyhow!("Missing argument `expr`"))?;
let msg = args.get("msg").copied(); let msg = args.get("msg").copied();
let cmpop = if matches!(self, UnittestAssert::IsNone) { let cmp_op = if matches!(self, UnittestAssert::IsNone) {
Cmpop::Is CmpOp::Is
} else { } else {
Cmpop::IsNot CmpOp::IsNot
}; };
let node = Expr::Constant(ast::ExprConstant { let node = Expr::Constant(ast::ExprConstant {
value: Constant::None, value: Constant::None,
kind: None, kind: None,
range: TextRange::default(), range: TextRange::default(),
}); });
let expr = compare(expr, cmpop, &node); let expr = compare(expr, cmp_op, &node);
Ok(assert(&expr, msg)) Ok(assert(&expr, msg))
} }
UnittestAssert::IsInstance | UnittestAssert::NotIsInstance => { UnittestAssert::IsInstance | UnittestAssert::NotIsInstance => {
@ -362,7 +362,7 @@ impl UnittestAssert {
Ok(assert(&isinstance, msg)) Ok(assert(&isinstance, msg))
} else { } else {
let node = ast::ExprUnaryOp { let node = ast::ExprUnaryOp {
op: Unaryop::Not, op: UnaryOp::Not,
operand: Box::new(isinstance), operand: Box::new(isinstance),
range: TextRange::default(), range: TextRange::default(),
}; };
@ -403,7 +403,7 @@ impl UnittestAssert {
Ok(assert(&re_search, msg)) Ok(assert(&re_search, msg))
} else { } else {
let node = ast::ExprUnaryOp { let node = ast::ExprUnaryOp {
op: Unaryop::Not, op: UnaryOp::Not,
operand: Box::new(re_search), operand: Box::new(re_search),
range: TextRange::default(), range: TextRange::default(),
}; };

View file

@ -5,7 +5,7 @@ use itertools::Either::{Left, Right};
use itertools::Itertools; use itertools::Itertools;
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use rustpython_parser::ast::{self, Boolop, Cmpop, Expr, ExprContext, Ranged, Unaryop}; use rustpython_parser::ast::{self, BoolOp, CmpOp, Expr, ExprContext, Ranged, UnaryOp};
use ruff_diagnostics::{AlwaysAutofixableViolation, AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AlwaysAutofixableViolation, AutofixKind, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -299,7 +299,7 @@ fn is_same_expr<'a>(a: &'a Expr, b: &'a Expr) -> Option<&'a str> {
/// SIM101 /// SIM101
pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) {
let Expr::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values, range: _ } )= expr else { let Expr::BoolOp(ast::ExprBoolOp { op: BoolOp::Or, values, range: _ } )= expr else {
return; return;
}; };
@ -402,7 +402,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) {
// Generate the combined `BoolOp`. // Generate the combined `BoolOp`.
let node = ast::ExprBoolOp { let node = ast::ExprBoolOp {
op: Boolop::Or, op: BoolOp::Or,
values: iter::once(call) values: iter::once(call)
.chain( .chain(
values values
@ -437,7 +437,7 @@ fn match_eq_target(expr: &Expr) -> Option<(&str, &Expr)> {
if ops.len() != 1 || comparators.len() != 1 { if ops.len() != 1 || comparators.len() != 1 {
return None; return None;
} }
if !matches!(&ops[0], Cmpop::Eq) { if !matches!(&ops[0], CmpOp::Eq) {
return None; return None;
} }
let Expr::Name(ast::ExprName { id, .. }) = left.as_ref() else { let Expr::Name(ast::ExprName { id, .. }) = left.as_ref() else {
@ -452,7 +452,7 @@ fn match_eq_target(expr: &Expr) -> Option<(&str, &Expr)> {
/// SIM109 /// SIM109
pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) { pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) {
let Expr::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values, range: _ }) = expr else { let Expr::BoolOp(ast::ExprBoolOp { op: BoolOp::Or, values, range: _ }) = expr else {
return; return;
}; };
@ -501,7 +501,7 @@ pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) {
}; };
let node2 = ast::ExprCompare { let node2 = ast::ExprCompare {
left: Box::new(node1.into()), left: Box::new(node1.into()),
ops: vec![Cmpop::In], ops: vec![CmpOp::In],
comparators: vec![node.into()], comparators: vec![node.into()],
range: TextRange::default(), range: TextRange::default(),
}; };
@ -524,7 +524,7 @@ pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) {
} else { } else {
// Wrap in a `x in (a, b) or ...` boolean operation. // Wrap in a `x in (a, b) or ...` boolean operation.
let node = ast::ExprBoolOp { let node = ast::ExprBoolOp {
op: Boolop::Or, op: BoolOp::Or,
values: iter::once(in_expr).chain(unmatched).collect(), values: iter::once(in_expr).chain(unmatched).collect(),
range: TextRange::default(), range: TextRange::default(),
}; };
@ -542,7 +542,7 @@ pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) {
/// SIM220 /// SIM220
pub(crate) fn expr_and_not_expr(checker: &mut Checker, expr: &Expr) { pub(crate) fn expr_and_not_expr(checker: &mut Checker, expr: &Expr) {
let Expr::BoolOp(ast::ExprBoolOp { op: Boolop::And, values, range: _, }) = expr else { let Expr::BoolOp(ast::ExprBoolOp { op: BoolOp::And, values, range: _, }) = expr else {
return; return;
}; };
if values.len() < 2 { if values.len() < 2 {
@ -554,7 +554,7 @@ pub(crate) fn expr_and_not_expr(checker: &mut Checker, expr: &Expr) {
let mut non_negated_expr = vec![]; let mut non_negated_expr = vec![];
for expr in values { for expr in values {
if let Expr::UnaryOp(ast::ExprUnaryOp { if let Expr::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::Not, op: UnaryOp::Not,
operand, operand,
range: _, range: _,
}) = expr }) = expr
@ -597,7 +597,7 @@ pub(crate) fn expr_and_not_expr(checker: &mut Checker, expr: &Expr) {
/// SIM221 /// SIM221
pub(crate) fn expr_or_not_expr(checker: &mut Checker, expr: &Expr) { pub(crate) fn expr_or_not_expr(checker: &mut Checker, expr: &Expr) {
let Expr::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values, range: _, }) = expr else { let Expr::BoolOp(ast::ExprBoolOp { op: BoolOp::Or, values, range: _, }) = expr else {
return; return;
}; };
if values.len() < 2 { if values.len() < 2 {
@ -609,7 +609,7 @@ pub(crate) fn expr_or_not_expr(checker: &mut Checker, expr: &Expr) {
let mut non_negated_expr = vec![]; let mut non_negated_expr = vec![];
for expr in values { for expr in values {
if let Expr::UnaryOp(ast::ExprUnaryOp { if let Expr::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::Not, op: UnaryOp::Not,
operand, operand,
range: _, range: _,
}) = expr }) = expr
@ -673,7 +673,7 @@ pub(crate) fn get_short_circuit_edit(
fn is_short_circuit( fn is_short_circuit(
expr: &Expr, expr: &Expr,
expected_op: Boolop, expected_op: BoolOp,
checker: &Checker, checker: &Checker,
) -> Option<(Edit, ContentAround)> { ) -> Option<(Edit, ContentAround)> {
let Expr::BoolOp(ast::ExprBoolOp { op, values, range: _, }) = expr else { let Expr::BoolOp(ast::ExprBoolOp { op, values, range: _, }) = expr else {
@ -683,8 +683,8 @@ fn is_short_circuit(
return None; return None;
} }
let short_circuit_truthiness = match op { let short_circuit_truthiness = match op {
Boolop::And => Truthiness::Falsey, BoolOp::And => Truthiness::Falsey,
Boolop::Or => Truthiness::Truthy, BoolOp::Or => Truthiness::Truthy,
}; };
let mut location = expr.start(); let mut location = expr.start();
@ -753,7 +753,7 @@ fn is_short_circuit(
/// SIM222 /// SIM222
pub(crate) fn expr_or_true(checker: &mut Checker, expr: &Expr) { pub(crate) fn expr_or_true(checker: &mut Checker, expr: &Expr) {
if let Some((edit, remove)) = is_short_circuit(expr, Boolop::Or, checker) { if let Some((edit, remove)) = is_short_circuit(expr, BoolOp::Or, checker) {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
ExprOrTrue { ExprOrTrue {
expr: edit.content().unwrap_or_default().to_string(), expr: edit.content().unwrap_or_default().to_string(),
@ -771,7 +771,7 @@ pub(crate) fn expr_or_true(checker: &mut Checker, expr: &Expr) {
/// SIM223 /// SIM223
pub(crate) fn expr_and_false(checker: &mut Checker, expr: &Expr) { pub(crate) fn expr_and_false(checker: &mut Checker, expr: &Expr) {
if let Some((edit, remove)) = is_short_circuit(expr, Boolop::And, checker) { if let Some((edit, remove)) = is_short_circuit(expr, BoolOp::And, checker) {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
ExprAndFalse { ExprAndFalse {
expr: edit.content().unwrap_or_default().to_string(), expr: edit.content().unwrap_or_default().to_string(),

View file

@ -1,7 +1,7 @@
use log::error; use log::error;
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use rustpython_parser::ast::{self, Cmpop, Constant, Expr, ExprContext, Ranged, Stmt}; use rustpython_parser::ast::{self, CmpOp, Constant, Expr, ExprContext, Ranged, Stmt};
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -734,7 +734,7 @@ pub(crate) fn manual_dict_lookup(
if orelse.len() != 1 { if orelse.len() != 1 {
return; return;
} }
if !(ops.len() == 1 && ops[0] == Cmpop::Eq) { if !(ops.len() == 1 && ops[0] == CmpOp::Eq) {
return; return;
} }
if comparators.len() != 1 { if comparators.len() != 1 {
@ -807,7 +807,7 @@ pub(crate) fn manual_dict_lookup(
let Expr::Name(ast::ExprName { id, .. }) = left.as_ref() else { let Expr::Name(ast::ExprName { id, .. }) = left.as_ref() else {
return; return;
}; };
if !(id == target && ops.len() == 1 && ops[0] == Cmpop::Eq) { if !(id == target && ops.len() == 1 && ops[0] == CmpOp::Eq) {
return; return;
} }
if comparators.len() != 1 { if comparators.len() != 1 {
@ -882,8 +882,8 @@ pub(crate) fn use_dict_get_with_default(
return; return;
} }
let (expected_var, expected_value, default_var, default_value) = match ops[..] { let (expected_var, expected_value, default_var, default_value) = match ops[..] {
[Cmpop::In] => (&body_var[0], body_value, &orelse_var[0], orelse_value), [CmpOp::In] => (&body_var[0], body_value, &orelse_var[0], orelse_value),
[Cmpop::NotIn] => (&orelse_var[0], orelse_value, &body_var[0], body_value), [CmpOp::NotIn] => (&orelse_var[0], orelse_value, &body_var[0], body_value),
_ => { _ => {
return; return;
} }

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Ranged, Unaryop}; use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Ranged, UnaryOp};
use ruff_diagnostics::{AlwaysAutofixableViolation, AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AlwaysAutofixableViolation, AutofixKind, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -219,7 +219,7 @@ pub(crate) fn explicit_false_true_in_ifexpr(
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
let node = test.clone(); let node = test.clone();
let node1 = ast::ExprUnaryOp { let node1 = ast::ExprUnaryOp {
op: Unaryop::Not, op: UnaryOp::Not,
operand: Box::new(node), operand: Box::new(node),
range: TextRange::default(), range: TextRange::default(),
}; };

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Cmpop, Expr, ExprContext, Ranged, Stmt, Unaryop}; use rustpython_parser::ast::{self, CmpOp, Expr, ExprContext, Ranged, Stmt, UnaryOp};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -138,16 +138,16 @@ fn is_exception_check(stmt: &Stmt) -> bool {
pub(crate) fn negation_with_equal_op( pub(crate) fn negation_with_equal_op(
checker: &mut Checker, checker: &mut Checker,
expr: &Expr, expr: &Expr,
op: Unaryop, op: UnaryOp,
operand: &Expr, operand: &Expr,
) { ) {
if !matches!(op, Unaryop::Not) { if !matches!(op, UnaryOp::Not) {
return; return;
} }
let Expr::Compare(ast::ExprCompare { left, ops, comparators, range: _}) = operand else { let Expr::Compare(ast::ExprCompare { left, ops, comparators, range: _}) = operand else {
return; return;
}; };
if !matches!(&ops[..], [Cmpop::Eq]) { if !matches!(&ops[..], [CmpOp::Eq]) {
return; return;
} }
if is_exception_check(checker.semantic().stmt()) { if is_exception_check(checker.semantic().stmt()) {
@ -174,7 +174,7 @@ pub(crate) fn negation_with_equal_op(
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
let node = ast::ExprCompare { let node = ast::ExprCompare {
left: left.clone(), left: left.clone(),
ops: vec![Cmpop::NotEq], ops: vec![CmpOp::NotEq],
comparators: comparators.clone(), comparators: comparators.clone(),
range: TextRange::default(), range: TextRange::default(),
}; };
@ -191,16 +191,16 @@ pub(crate) fn negation_with_equal_op(
pub(crate) fn negation_with_not_equal_op( pub(crate) fn negation_with_not_equal_op(
checker: &mut Checker, checker: &mut Checker,
expr: &Expr, expr: &Expr,
op: Unaryop, op: UnaryOp,
operand: &Expr, operand: &Expr,
) { ) {
if !matches!(op, Unaryop::Not) { if !matches!(op, UnaryOp::Not) {
return; return;
} }
let Expr::Compare(ast::ExprCompare { left, ops, comparators, range: _}) = operand else { let Expr::Compare(ast::ExprCompare { left, ops, comparators, range: _}) = operand else {
return; return;
}; };
if !matches!(&ops[..], [Cmpop::NotEq]) { if !matches!(&ops[..], [CmpOp::NotEq]) {
return; return;
} }
if is_exception_check(checker.semantic().stmt()) { if is_exception_check(checker.semantic().stmt()) {
@ -227,7 +227,7 @@ pub(crate) fn negation_with_not_equal_op(
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
let node = ast::ExprCompare { let node = ast::ExprCompare {
left: left.clone(), left: left.clone(),
ops: vec![Cmpop::Eq], ops: vec![CmpOp::Eq],
comparators: comparators.clone(), comparators: comparators.clone(),
range: TextRange::default(), range: TextRange::default(),
}; };
@ -241,14 +241,14 @@ pub(crate) fn negation_with_not_equal_op(
} }
/// SIM208 /// 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) { if !matches!(op, UnaryOp::Not) {
return; return;
} }
let Expr::UnaryOp(ast::ExprUnaryOp { op: operand_op, operand, range: _ }) = operand else { let Expr::UnaryOp(ast::ExprUnaryOp { op: operand_op, operand, range: _ }) = operand else {
return; return;
}; };
if !matches!(operand_op, Unaryop::Not) { if !matches!(operand_op, UnaryOp::Not) {
return; return;
} }

View file

@ -1,6 +1,6 @@
use log::error; use log::error;
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Ranged, Stmt, Withitem}; use rustpython_parser::ast::{self, Ranged, Stmt, WithItem};
use ruff_diagnostics::{AutofixKind, Violation}; use ruff_diagnostics::{AutofixKind, Violation};
use ruff_diagnostics::{Diagnostic, Fix}; use ruff_diagnostics::{Diagnostic, Fix};
@ -62,7 +62,7 @@ impl Violation for MultipleWithStatements {
/// Returns a boolean indicating whether it's an async with statement, the items /// Returns a boolean indicating whether it's an async with statement, the items
/// and body. /// and body.
fn next_with(body: &[Stmt]) -> Option<(bool, &[Withitem], &[Stmt])> { fn next_with(body: &[Stmt]) -> Option<(bool, &[WithItem], &[Stmt])> {
match body { match body {
[Stmt::With(ast::StmtWith { items, body, .. })] => Some((false, items, body)), [Stmt::With(ast::StmtWith { items, body, .. })] => Some((false, items, body)),
[Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. })] => Some((true, items, body)), [Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. })] => Some((true, items, body)),

View file

@ -1,7 +1,7 @@
use anyhow::Result; use anyhow::Result;
use log::error; use log::error;
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Cmpop, Expr, Ranged}; use rustpython_parser::ast::{self, CmpOp, Expr, Ranged};
use ruff_diagnostics::Edit; use ruff_diagnostics::Edit;
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix};
@ -128,10 +128,10 @@ pub(crate) fn key_in_dict_compare(
checker: &mut Checker, checker: &mut Checker,
expr: &Expr, expr: &Expr,
left: &Expr, left: &Expr,
ops: &[Cmpop], ops: &[CmpOp],
comparators: &[Expr], comparators: &[Expr],
) { ) {
if !matches!(ops[..], [Cmpop::In]) { if !matches!(ops[..], [CmpOp::In]) {
return; return;
} }

View file

@ -1,6 +1,6 @@
use ruff_text_size::{TextRange, TextSize}; use ruff_text_size::{TextRange, TextSize};
use rustpython_parser::ast::{ use rustpython_parser::ast::{
self, Cmpop, Comprehension, Constant, Expr, ExprContext, Ranged, Stmt, Unaryop, self, CmpOp, Comprehension, Constant, Expr, ExprContext, Ranged, Stmt, UnaryOp,
}; };
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
@ -117,7 +117,7 @@ pub(crate) fn convert_for_loop_to_any_all(
// Invert the condition. // Invert the condition.
let test = { let test = {
if let Expr::UnaryOp(ast::ExprUnaryOp { if let Expr::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::Not, op: UnaryOp::Not,
operand, operand,
range: _, range: _,
}) = &loop_info.test }) = &loop_info.test
@ -132,16 +132,16 @@ pub(crate) fn convert_for_loop_to_any_all(
{ {
if let ([op], [comparator]) = (ops.as_slice(), comparators.as_slice()) { if let ([op], [comparator]) = (ops.as_slice(), comparators.as_slice()) {
let op = match op { let op = match op {
Cmpop::Eq => Cmpop::NotEq, CmpOp::Eq => CmpOp::NotEq,
Cmpop::NotEq => Cmpop::Eq, CmpOp::NotEq => CmpOp::Eq,
Cmpop::Lt => Cmpop::GtE, CmpOp::Lt => CmpOp::GtE,
Cmpop::LtE => Cmpop::Gt, CmpOp::LtE => CmpOp::Gt,
Cmpop::Gt => Cmpop::LtE, CmpOp::Gt => CmpOp::LtE,
Cmpop::GtE => Cmpop::Lt, CmpOp::GtE => CmpOp::Lt,
Cmpop::Is => Cmpop::IsNot, CmpOp::Is => CmpOp::IsNot,
Cmpop::IsNot => Cmpop::Is, CmpOp::IsNot => CmpOp::Is,
Cmpop::In => Cmpop::NotIn, CmpOp::In => CmpOp::NotIn,
Cmpop::NotIn => Cmpop::In, CmpOp::NotIn => CmpOp::In,
}; };
let node = ast::ExprCompare { let node = ast::ExprCompare {
left: left.clone(), left: left.clone(),
@ -152,7 +152,7 @@ pub(crate) fn convert_for_loop_to_any_all(
node.into() node.into()
} else { } else {
let node = ast::ExprUnaryOp { let node = ast::ExprUnaryOp {
op: Unaryop::Not, op: UnaryOp::Not,
operand: Box::new(loop_info.test.clone()), operand: Box::new(loop_info.test.clone()),
range: TextRange::default(), range: TextRange::default(),
}; };
@ -160,7 +160,7 @@ pub(crate) fn convert_for_loop_to_any_all(
} }
} else { } else {
let node = ast::ExprUnaryOp { let node = ast::ExprUnaryOp {
op: Unaryop::Not, op: UnaryOp::Not,
operand: Box::new(loop_info.test.clone()), operand: Box::new(loop_info.test.clone()),
range: TextRange::default(), range: TextRange::default(),
}; };

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Excepthandler, Ranged, Stmt}; use rustpython_parser::ast::{self, ExceptHandler, Ranged, Stmt};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -57,12 +57,12 @@ fn find_return(stmts: &[Stmt]) -> Option<&Stmt> {
pub(crate) fn return_in_try_except_finally( pub(crate) fn return_in_try_except_finally(
checker: &mut Checker, checker: &mut Checker,
body: &[Stmt], body: &[Stmt],
handlers: &[Excepthandler], handlers: &[ExceptHandler],
finalbody: &[Stmt], finalbody: &[Stmt],
) { ) {
let try_has_return = find_return(body).is_some(); let try_has_return = find_return(body).is_some();
let except_has_return = handlers.iter().any(|handler| { let except_has_return = handlers.iter().any(|handler| {
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) = handler; let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { body, .. }) = handler;
find_return(body).is_some() find_return(body).is_some()
}); });

View file

@ -1,5 +1,5 @@
use ruff_text_size::{TextLen, TextRange}; use ruff_text_size::{TextLen, TextRange};
use rustpython_parser::ast::{self, Constant, Excepthandler, Expr, Ranged, Stmt}; use rustpython_parser::ast::{self, Constant, ExceptHandler, Expr, Ranged, Stmt};
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -68,7 +68,7 @@ pub(crate) fn suppressible_exception(
checker: &mut Checker, checker: &mut Checker,
stmt: &Stmt, stmt: &Stmt,
try_body: &[Stmt], try_body: &[Stmt],
handlers: &[Excepthandler], handlers: &[ExceptHandler],
orelse: &[Stmt], orelse: &[Stmt],
finalbody: &[Stmt], finalbody: &[Stmt],
) { ) {
@ -90,7 +90,7 @@ pub(crate) fn suppressible_exception(
return; return;
} }
let handler = &handlers[0]; let handler = &handlers[0];
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) = handler; let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { body, .. }) = handler;
if body.len() == 1 { if body.len() == 1 {
let node = &body[0]; let node = &body[0];
if node.is_pass_stmt() if node.is_pass_stmt()

View file

@ -1,6 +1,6 @@
use anyhow::Result; use anyhow::Result;
use libcst_native::CompOp; use libcst_native::CompOp;
use rustpython_parser::ast::{self, Cmpop, Expr, Ranged, Unaryop}; use rustpython_parser::ast::{self, CmpOp, Expr, Ranged, UnaryOp};
use crate::autofix::codemods::CodegenStylist; use crate::autofix::codemods::CodegenStylist;
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
@ -76,7 +76,7 @@ fn is_constant_like(expr: &Expr) -> bool {
Expr::Tuple(ast::ExprTuple { elts, .. }) => elts.iter().all(is_constant_like), Expr::Tuple(ast::ExprTuple { elts, .. }) => elts.iter().all(is_constant_like),
Expr::Name(ast::ExprName { id, .. }) => str::is_cased_uppercase(id), Expr::Name(ast::ExprName { id, .. }) => str::is_cased_uppercase(id),
Expr::UnaryOp(ast::ExprUnaryOp { Expr::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::UAdd | Unaryop::USub | Unaryop::Invert, op: UnaryOp::UAdd | UnaryOp::USub | UnaryOp::Invert,
operand, operand,
range: _, range: _,
}) => operand.is_constant_expr(), }) => operand.is_constant_expr(),
@ -156,7 +156,7 @@ pub(crate) fn yoda_conditions(
checker: &mut Checker, checker: &mut Checker,
expr: &Expr, expr: &Expr,
left: &Expr, left: &Expr,
ops: &[Cmpop], ops: &[CmpOp],
comparators: &[Expr], comparators: &[Expr],
) { ) {
let ([op], [right]) = (ops, comparators) else { let ([op], [right]) = (ops, comparators) else {
@ -165,7 +165,7 @@ pub(crate) fn yoda_conditions(
if !matches!( if !matches!(
op, op,
Cmpop::Eq | Cmpop::NotEq | Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE, CmpOp::Eq | CmpOp::NotEq | CmpOp::Lt | CmpOp::LtE | CmpOp::Gt | CmpOp::GtE,
) { ) {
return; return;
} }

View file

@ -225,8 +225,9 @@ fn function(
let args = args let args = args
.posonlyargs .posonlyargs
.iter() .iter()
.chain(args.args.iter()) .chain(&args.args)
.chain(args.kwonlyargs.iter()) .chain(&args.kwonlyargs)
.map(|arg_with_default| &arg_with_default.def)
.chain( .chain(
iter::once::<Option<&Arg>>(args.vararg.as_deref()) iter::once::<Option<&Arg>>(args.vararg.as_deref())
.flatten() .flatten()
@ -252,9 +253,10 @@ fn method(
let args = args let args = args
.posonlyargs .posonlyargs
.iter() .iter()
.chain(args.args.iter()) .chain(&args.args)
.chain(&args.kwonlyargs)
.skip(1) .skip(1)
.chain(args.kwonlyargs.iter()) .map(|arg_with_default| &arg_with_default.def)
.chain( .chain(
iter::once::<Option<&Arg>>(args.vararg.as_deref()) iter::once::<Option<&Arg>>(args.vararg.as_deref())
.flatten() .flatten()

View file

@ -1,5 +1,5 @@
use ruff_text_size::{TextRange, TextSize}; use ruff_text_size::{TextRange, TextSize};
use rustpython_parser::ast::{self, Excepthandler, MatchCase, Ranged, Stmt}; use rustpython_parser::ast::{self, ExceptHandler, MatchCase, Ranged, Stmt};
use ruff_python_ast::source_code::Locator; use ruff_python_ast::source_code::Locator;
use ruff_python_ast::statement_visitor::StatementVisitor; use ruff_python_ast::statement_visitor::StatementVisitor;
@ -267,8 +267,8 @@ where
finalbody, finalbody,
range: _, range: _,
}) => { }) => {
for excepthandler in handlers { for except_handler in handlers {
self.visit_excepthandler(excepthandler); self.visit_except_handler(except_handler);
} }
for stmt in body { for stmt in body {
@ -291,12 +291,12 @@ where
self.nested = prev_nested; self.nested = prev_nested;
} }
fn visit_excepthandler(&mut self, excepthandler: &'b Excepthandler) { fn visit_except_handler(&mut self, except_handler: &'b ExceptHandler) {
let prev_nested = self.nested; let prev_nested = self.nested;
self.nested = true; self.nested = true;
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) = let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { body, .. }) =
excepthandler; except_handler;
for stmt in body { for stmt in body {
self.visit_stmt(stmt); self.visit_stmt(stmt);
} }

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Excepthandler, Stmt}; use rustpython_parser::ast::{self, ExceptHandler, Stmt};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -117,7 +117,7 @@ fn get_complexity_number(stmts: &[Stmt]) -> usize {
complexity += get_complexity_number(finalbody); complexity += get_complexity_number(finalbody);
for handler in handlers { for handler in handlers {
complexity += 1; complexity += 1;
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
body, .. body, ..
}) = handler; }) = handler;
complexity += get_complexity_number(body); complexity += get_complexity_number(body);

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Arguments, Decorator, Ranged}; use rustpython_parser::ast::{ArgWithDefault, Arguments, Decorator, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -74,8 +74,13 @@ pub(crate) fn invalid_first_argument_name_for_class_method(
) { ) {
return None; return None;
} }
if let Some(arg) = args.posonlyargs.first().or_else(|| args.args.first()) { if let Some(ArgWithDefault {
if &arg.arg != "cls" { def,
default: _,
range: _,
}) = args.posonlyargs.first().or_else(|| args.args.first())
{
if &def.arg != "cls" {
if checker if checker
.settings .settings
.pep8_naming .pep8_naming
@ -87,7 +92,7 @@ pub(crate) fn invalid_first_argument_name_for_class_method(
} }
return Some(Diagnostic::new( return Some(Diagnostic::new(
InvalidFirstArgumentNameForClassMethod, InvalidFirstArgumentNameForClassMethod,
arg.range(), def.range(),
)); ));
} }
} }

View file

@ -73,7 +73,7 @@ pub(crate) fn invalid_first_argument_name_for_method(
return None; return None;
} }
let arg = args.posonlyargs.first().or_else(|| args.args.first())?; let arg = args.posonlyargs.first().or_else(|| args.args.first())?;
if &arg.arg == "self" { if &arg.def.arg == "self" {
return None; return None;
} }
if checker if checker
@ -87,6 +87,6 @@ pub(crate) fn invalid_first_argument_name_for_method(
} }
Some(Diagnostic::new( Some(Diagnostic::new(
InvalidFirstArgumentNameForMethod, InvalidFirstArgumentNameForMethod,
arg.range(), arg.def.range(),
)) ))
} }

View file

@ -1,5 +1,5 @@
use ruff_text_size::{TextLen, TextRange}; use ruff_text_size::{TextLen, TextRange};
use rustpython_parser::ast::{self, Cmpop, Expr}; use rustpython_parser::ast::{self, CmpOp, Expr};
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use ruff_python_ast::source_code::Generator; use ruff_python_ast::source_code::Generator;
@ -13,7 +13,7 @@ pub(crate) fn is_ambiguous_name(name: &str) -> bool {
pub(crate) fn compare( pub(crate) fn compare(
left: &Expr, left: &Expr,
ops: &[Cmpop], ops: &[CmpOp],
comparators: &[Expr], comparators: &[Expr],
generator: Generator, generator: Generator,
) -> String { ) -> String {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Excepthandler, Expr, Stmt}; use rustpython_parser::ast::{self, ExceptHandler, Expr, Stmt};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -58,7 +58,7 @@ impl Violation for BareExcept {
pub(crate) fn bare_except( pub(crate) fn bare_except(
type_: Option<&Expr>, type_: Option<&Expr>,
body: &[Stmt], body: &[Stmt],
handler: &Excepthandler, handler: &ExceptHandler,
locator: &Locator, locator: &Locator,
) -> Option<Diagnostic> { ) -> Option<Diagnostic> {
if type_.is_none() if type_.is_none()

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Arg, Arguments, Constant, Expr, Ranged, Stmt}; use rustpython_parser::ast::{self, Arg, ArgWithDefault, Arguments, Constant, Expr, Ranged, Stmt};
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -176,22 +176,28 @@ fn function(
.posonlyargs .posonlyargs
.iter() .iter()
.enumerate() .enumerate()
.map(|(idx, arg)| Arg { .map(|(idx, arg_with_default)| ArgWithDefault {
annotation: arg_types def: Arg {
.get(idx) annotation: arg_types
.map(|arg_type| Box::new(arg_type.clone())), .get(idx)
..arg.clone() .map(|arg_type| Box::new(arg_type.clone())),
..arg_with_default.def.clone()
},
..arg_with_default.clone()
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let new_args = args let new_args = args
.args .args
.iter() .iter()
.enumerate() .enumerate()
.map(|(idx, arg)| Arg { .map(|(idx, arg_with_default)| ArgWithDefault {
annotation: arg_types def: Arg {
.get(idx + new_posonlyargs.len()) annotation: arg_types
.map(|arg_type| Box::new(arg_type.clone())), .get(idx + new_posonlyargs.len())
..arg.clone() .map(|arg_type| Box::new(arg_type.clone())),
..arg_with_default.def.clone()
},
..arg_with_default.clone()
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let func = Stmt::FunctionDef(ast::StmtFunctionDef { let func = Stmt::FunctionDef(ast::StmtFunctionDef {

View file

@ -1,6 +1,6 @@
use itertools::izip; use itertools::izip;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use rustpython_parser::ast::{self, Cmpop, Constant, Expr, Ranged}; use rustpython_parser::ast::{self, CmpOp, Constant, Expr, Ranged};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -12,16 +12,16 @@ use crate::registry::AsRule;
use crate::rules::pycodestyle::helpers::compare; use crate::rules::pycodestyle::helpers::compare;
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
enum EqCmpop { enum EqCmpOp {
Eq, Eq,
NotEq, NotEq,
} }
impl EqCmpop { impl EqCmpOp {
fn try_from(value: Cmpop) -> Option<EqCmpop> { fn try_from(value: CmpOp) -> Option<EqCmpOp> {
match value { match value {
Cmpop::Eq => Some(EqCmpop::Eq), CmpOp::Eq => Some(EqCmpOp::Eq),
Cmpop::NotEq => Some(EqCmpop::NotEq), CmpOp::NotEq => Some(EqCmpOp::NotEq),
_ => None, _ => None,
} }
} }
@ -50,23 +50,23 @@ impl EqCmpop {
/// ///
/// [PEP 8]: https://peps.python.org/pep-0008/#programming-recommendations /// [PEP 8]: https://peps.python.org/pep-0008/#programming-recommendations
#[violation] #[violation]
pub struct NoneComparison(EqCmpop); pub struct NoneComparison(EqCmpOp);
impl AlwaysAutofixableViolation for NoneComparison { impl AlwaysAutofixableViolation for NoneComparison {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
let NoneComparison(op) = self; let NoneComparison(op) = self;
match op { match op {
EqCmpop::Eq => format!("Comparison to `None` should be `cond is None`"), EqCmpOp::Eq => format!("Comparison to `None` should be `cond is None`"),
EqCmpop::NotEq => format!("Comparison to `None` should be `cond is not None`"), EqCmpOp::NotEq => format!("Comparison to `None` should be `cond is not None`"),
} }
} }
fn autofix_title(&self) -> String { fn autofix_title(&self) -> String {
let NoneComparison(op) = self; let NoneComparison(op) = self;
match op { match op {
EqCmpop::Eq => "Replace with `cond is None`".to_string(), EqCmpOp::Eq => "Replace with `cond is None`".to_string(),
EqCmpop::NotEq => "Replace with `cond is not None`".to_string(), EqCmpOp::NotEq => "Replace with `cond is not None`".to_string(),
} }
} }
} }
@ -96,23 +96,23 @@ impl AlwaysAutofixableViolation for NoneComparison {
/// ///
/// [PEP 8]: https://peps.python.org/pep-0008/#programming-recommendations /// [PEP 8]: https://peps.python.org/pep-0008/#programming-recommendations
#[violation] #[violation]
pub struct TrueFalseComparison(bool, EqCmpop); pub struct TrueFalseComparison(bool, EqCmpOp);
impl AlwaysAutofixableViolation for TrueFalseComparison { impl AlwaysAutofixableViolation for TrueFalseComparison {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
let TrueFalseComparison(value, op) = self; let TrueFalseComparison(value, op) = self;
match (value, op) { match (value, op) {
(true, EqCmpop::Eq) => { (true, EqCmpOp::Eq) => {
format!("Comparison to `True` should be `cond is True` or `if cond:`") format!("Comparison to `True` should be `cond is True` or `if cond:`")
} }
(true, EqCmpop::NotEq) => { (true, EqCmpOp::NotEq) => {
format!("Comparison to `True` should be `cond is not True` or `if not cond:`") format!("Comparison to `True` should be `cond is not True` or `if not cond:`")
} }
(false, EqCmpop::Eq) => { (false, EqCmpOp::Eq) => {
format!("Comparison to `False` should be `cond is False` or `if not cond:`") format!("Comparison to `False` should be `cond is False` or `if not cond:`")
} }
(false, EqCmpop::NotEq) => { (false, EqCmpOp::NotEq) => {
format!("Comparison to `False` should be `cond is not False` or `if cond:`") format!("Comparison to `False` should be `cond is not False` or `if cond:`")
} }
} }
@ -121,10 +121,10 @@ impl AlwaysAutofixableViolation for TrueFalseComparison {
fn autofix_title(&self) -> String { fn autofix_title(&self) -> String {
let TrueFalseComparison(value, op) = self; let TrueFalseComparison(value, op) = self;
match (value, op) { match (value, op) {
(true, EqCmpop::Eq) => "Replace with `cond is True`".to_string(), (true, EqCmpOp::Eq) => "Replace with `cond is True`".to_string(),
(true, EqCmpop::NotEq) => "Replace with `cond is not True`".to_string(), (true, EqCmpOp::NotEq) => "Replace with `cond is not True`".to_string(),
(false, EqCmpop::Eq) => "Replace with `cond is False`".to_string(), (false, EqCmpOp::Eq) => "Replace with `cond is False`".to_string(),
(false, EqCmpop::NotEq) => "Replace with `cond is not False`".to_string(), (false, EqCmpOp::NotEq) => "Replace with `cond is not False`".to_string(),
} }
} }
} }
@ -134,7 +134,7 @@ pub(crate) fn literal_comparisons(
checker: &mut Checker, checker: &mut Checker,
expr: &Expr, expr: &Expr,
left: &Expr, left: &Expr,
ops: &[Cmpop], ops: &[CmpOp],
comparators: &[Expr], comparators: &[Expr],
check_none_comparisons: bool, check_none_comparisons: bool,
check_true_false_comparisons: bool, check_true_false_comparisons: bool,
@ -143,7 +143,7 @@ pub(crate) fn literal_comparisons(
// through the list of operators, we apply "dummy" fixes for each error, // through the list of operators, we apply "dummy" fixes for each error,
// then replace the entire expression at the end with one "real" fix, to // then replace the entire expression at the end with one "real" fix, to
// avoid conflicts. // avoid conflicts.
let mut bad_ops: FxHashMap<usize, Cmpop> = FxHashMap::default(); let mut bad_ops: FxHashMap<usize, CmpOp> = FxHashMap::default();
let mut diagnostics: Vec<Diagnostic> = vec![]; let mut diagnostics: Vec<Diagnostic> = vec![];
let op = ops.first().unwrap(); let op = ops.first().unwrap();
@ -153,20 +153,20 @@ pub(crate) fn literal_comparisons(
let next = &comparators[0]; let next = &comparators[0];
if !helpers::is_constant_non_singleton(next) { if !helpers::is_constant_non_singleton(next) {
if let Some(op) = EqCmpop::try_from(*op) { if let Some(op) = EqCmpOp::try_from(*op) {
if check_none_comparisons && is_const_none(comparator) { if check_none_comparisons && is_const_none(comparator) {
match op { match op {
EqCmpop::Eq => { EqCmpOp::Eq => {
let diagnostic = Diagnostic::new(NoneComparison(op), comparator.range()); let diagnostic = Diagnostic::new(NoneComparison(op), comparator.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
bad_ops.insert(0, Cmpop::Is); bad_ops.insert(0, CmpOp::Is);
} }
diagnostics.push(diagnostic); diagnostics.push(diagnostic);
} }
EqCmpop::NotEq => { EqCmpOp::NotEq => {
let diagnostic = Diagnostic::new(NoneComparison(op), comparator.range()); let diagnostic = Diagnostic::new(NoneComparison(op), comparator.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
bad_ops.insert(0, Cmpop::IsNot); bad_ops.insert(0, CmpOp::IsNot);
} }
diagnostics.push(diagnostic); diagnostics.push(diagnostic);
} }
@ -181,23 +181,23 @@ pub(crate) fn literal_comparisons(
}) = comparator }) = comparator
{ {
match op { match op {
EqCmpop::Eq => { EqCmpOp::Eq => {
let diagnostic = Diagnostic::new( let diagnostic = Diagnostic::new(
TrueFalseComparison(*value, op), TrueFalseComparison(*value, op),
comparator.range(), comparator.range(),
); );
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
bad_ops.insert(0, Cmpop::Is); bad_ops.insert(0, CmpOp::Is);
} }
diagnostics.push(diagnostic); diagnostics.push(diagnostic);
} }
EqCmpop::NotEq => { EqCmpOp::NotEq => {
let diagnostic = Diagnostic::new( let diagnostic = Diagnostic::new(
TrueFalseComparison(*value, op), TrueFalseComparison(*value, op),
comparator.range(), comparator.range(),
); );
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
bad_ops.insert(0, Cmpop::IsNot); bad_ops.insert(0, CmpOp::IsNot);
} }
diagnostics.push(diagnostic); diagnostics.push(diagnostic);
} }
@ -214,20 +214,20 @@ pub(crate) fn literal_comparisons(
continue; continue;
} }
if let Some(op) = EqCmpop::try_from(*op) { if let Some(op) = EqCmpOp::try_from(*op) {
if check_none_comparisons && is_const_none(next) { if check_none_comparisons && is_const_none(next) {
match op { match op {
EqCmpop::Eq => { EqCmpOp::Eq => {
let diagnostic = Diagnostic::new(NoneComparison(op), next.range()); let diagnostic = Diagnostic::new(NoneComparison(op), next.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
bad_ops.insert(idx, Cmpop::Is); bad_ops.insert(idx, CmpOp::Is);
} }
diagnostics.push(diagnostic); diagnostics.push(diagnostic);
} }
EqCmpop::NotEq => { EqCmpOp::NotEq => {
let diagnostic = Diagnostic::new(NoneComparison(op), next.range()); let diagnostic = Diagnostic::new(NoneComparison(op), next.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
bad_ops.insert(idx, Cmpop::IsNot); bad_ops.insert(idx, CmpOp::IsNot);
} }
diagnostics.push(diagnostic); diagnostics.push(diagnostic);
} }
@ -242,19 +242,19 @@ pub(crate) fn literal_comparisons(
}) = next }) = next
{ {
match op { match op {
EqCmpop::Eq => { EqCmpOp::Eq => {
let diagnostic = let diagnostic =
Diagnostic::new(TrueFalseComparison(*value, op), next.range()); Diagnostic::new(TrueFalseComparison(*value, op), next.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
bad_ops.insert(idx, Cmpop::Is); bad_ops.insert(idx, CmpOp::Is);
} }
diagnostics.push(diagnostic); diagnostics.push(diagnostic);
} }
EqCmpop::NotEq => { EqCmpOp::NotEq => {
let diagnostic = let diagnostic =
Diagnostic::new(TrueFalseComparison(*value, op), next.range()); Diagnostic::new(TrueFalseComparison(*value, op), next.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
bad_ops.insert(idx, Cmpop::IsNot); bad_ops.insert(idx, CmpOp::IsNot);
} }
diagnostics.push(diagnostic); diagnostics.push(diagnostic);
} }

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Cmpop, Expr, Ranged, Unaryop}; use rustpython_parser::ast::{self, CmpOp, Expr, Ranged, UnaryOp};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -77,12 +77,12 @@ impl AlwaysAutofixableViolation for NotIsTest {
pub(crate) fn not_tests( pub(crate) fn not_tests(
checker: &mut Checker, checker: &mut Checker,
expr: &Expr, expr: &Expr,
op: Unaryop, op: UnaryOp,
operand: &Expr, operand: &Expr,
check_not_in: bool, check_not_in: bool,
check_not_is: bool, check_not_is: bool,
) { ) {
if matches!(op, Unaryop::Not) { if matches!(op, UnaryOp::Not) {
if let Expr::Compare(ast::ExprCompare { if let Expr::Compare(ast::ExprCompare {
left, left,
ops, ops,
@ -90,19 +90,19 @@ pub(crate) fn not_tests(
range: _, range: _,
}) = operand }) = operand
{ {
if !matches!(&ops[..], [Cmpop::In | Cmpop::Is]) { if !matches!(&ops[..], [CmpOp::In | CmpOp::Is]) {
return; return;
} }
for op in ops.iter() { for op in ops.iter() {
match op { match op {
Cmpop::In => { CmpOp::In => {
if check_not_in { if check_not_in {
let mut diagnostic = Diagnostic::new(NotInTest, operand.range()); let mut diagnostic = Diagnostic::new(NotInTest, operand.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
diagnostic.set_fix(Fix::automatic(Edit::range_replacement( diagnostic.set_fix(Fix::automatic(Edit::range_replacement(
compare( compare(
left, left,
&[Cmpop::NotIn], &[CmpOp::NotIn],
comparators, comparators,
checker.generator(), checker.generator(),
), ),
@ -112,14 +112,14 @@ pub(crate) fn not_tests(
checker.diagnostics.push(diagnostic); checker.diagnostics.push(diagnostic);
} }
} }
Cmpop::Is => { CmpOp::Is => {
if check_not_is { if check_not_is {
let mut diagnostic = Diagnostic::new(NotIsTest, operand.range()); let mut diagnostic = Diagnostic::new(NotIsTest, operand.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
diagnostic.set_fix(Fix::automatic(Edit::range_replacement( diagnostic.set_fix(Fix::automatic(Edit::range_replacement(
compare( compare(
left, left,
&[Cmpop::IsNot], &[CmpOp::IsNot],
comparators, comparators,
checker.generator(), checker.generator(),
), ),

View file

@ -1,5 +1,5 @@
use itertools::izip; use itertools::izip;
use rustpython_parser::ast::{self, Cmpop, Constant, Expr, Ranged}; use rustpython_parser::ast::{self, CmpOp, Constant, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -41,11 +41,11 @@ impl Violation for TypeComparison {
pub(crate) fn type_comparison( pub(crate) fn type_comparison(
checker: &mut Checker, checker: &mut Checker,
expr: &Expr, expr: &Expr,
ops: &[Cmpop], ops: &[CmpOp],
comparators: &[Expr], comparators: &[Expr],
) { ) {
for (op, right) in izip!(ops, comparators) { for (op, right) in izip!(ops, comparators) {
if !matches!(op, Cmpop::Is | Cmpop::IsNot | Cmpop::Eq | Cmpop::NotEq) { if !matches!(op, CmpOp::Is | CmpOp::IsNot | CmpOp::Eq | CmpOp::NotEq) {
continue; continue;
} }
match right { match right {

View file

@ -3,7 +3,7 @@ use once_cell::sync::Lazy;
use regex::Regex; use regex::Regex;
use ruff_text_size::{TextLen, TextRange, TextSize}; use ruff_text_size::{TextLen, TextRange, TextSize};
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use rustpython_parser::ast::{self, Stmt}; use rustpython_parser::ast::{self, ArgWithDefault, Stmt};
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation}; use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
use ruff_diagnostics::{Diagnostic, Edit, Fix}; use ruff_diagnostics::{Diagnostic, Edit, Fix};
@ -713,11 +713,15 @@ fn missing_args(checker: &mut Checker, docstring: &Docstring, docstrings_args: &
// Look for arguments that weren't included in the docstring. // Look for arguments that weren't included in the docstring.
let mut missing_arg_names: FxHashSet<String> = FxHashSet::default(); let mut missing_arg_names: FxHashSet<String> = FxHashSet::default();
for arg in arguments for ArgWithDefault {
def,
default: _,
range: _,
} in arguments
.posonlyargs .posonlyargs
.iter() .iter()
.chain(arguments.args.iter()) .chain(&arguments.args)
.chain(arguments.kwonlyargs.iter()) .chain(&arguments.kwonlyargs)
.skip( .skip(
// If this is a non-static method, skip `cls` or `self`. // If this is a non-static method, skip `cls` or `self`.
usize::from( usize::from(
@ -726,7 +730,7 @@ fn missing_args(checker: &mut Checker, docstring: &Docstring, docstrings_args: &
), ),
) )
{ {
let arg_name = arg.arg.as_str(); let arg_name = def.arg.as_str();
if !arg_name.starts_with('_') && !docstrings_args.contains(arg_name) { if !arg_name.starts_with('_') && !docstrings_args.contains(arg_name) {
missing_arg_names.insert(arg_name.to_string()); missing_arg_names.insert(arg_name.to_string());
} }

View file

@ -1,6 +1,6 @@
use anyhow::{bail, Ok, Result}; use anyhow::{bail, Ok, Result};
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{Excepthandler, Expr, Ranged}; use rustpython_parser::ast::{ExceptHandler, Expr, Ranged};
use rustpython_parser::{lexer, Mode, Tok}; use rustpython_parser::{lexer, Mode, Tok};
use ruff_diagnostics::Edit; use ruff_diagnostics::Edit;
@ -90,17 +90,17 @@ pub(crate) fn remove_unused_positional_arguments_from_format_call(
/// Generate a [`Edit`] to remove the binding from an exception handler. /// Generate a [`Edit`] to remove the binding from an exception handler.
pub(crate) fn remove_exception_handler_assignment( pub(crate) fn remove_exception_handler_assignment(
excepthandler: &Excepthandler, except_handler: &ExceptHandler,
locator: &Locator, locator: &Locator,
) -> Result<Edit> { ) -> Result<Edit> {
let contents = locator.slice(excepthandler.range()); let contents = locator.slice(except_handler.range());
let mut fix_start = None; let mut fix_start = None;
let mut fix_end = None; let mut fix_end = None;
// End of the token just before the `as` to the semicolon. // End of the token just before the `as` to the semicolon.
let mut prev = None; let mut prev = None;
for (tok, range) in for (tok, range) in
lexer::lex_starts_at(contents, Mode::Module, excepthandler.start()).flatten() lexer::lex_starts_at(contents, Mode::Module, except_handler.start()).flatten()
{ {
if matches!(tok, Tok::As) { if matches!(tok, Tok::As) {
fix_start = prev; fix_start = prev;

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Excepthandler}; use rustpython_parser::ast::{self, ExceptHandler};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -55,11 +55,11 @@ impl Violation for DefaultExceptNotLast {
/// F707 /// F707
pub(crate) fn default_except_not_last( pub(crate) fn default_except_not_last(
handlers: &[Excepthandler], handlers: &[ExceptHandler],
locator: &Locator, locator: &Locator,
) -> Option<Diagnostic> { ) -> Option<Diagnostic> {
for (idx, handler) in handlers.iter().enumerate() { for (idx, handler) in handlers.iter().enumerate() {
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = handler; let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, .. }) = handler;
if type_.is_none() && idx < handlers.len() - 1 { if type_.is_none() && idx < handlers.len() - 1 {
return Some(Diagnostic::new( return Some(Diagnostic::new(
DefaultExceptNotLast, DefaultExceptNotLast,

View file

@ -1,7 +1,7 @@
use itertools::izip; use itertools::izip;
use log::error; use log::error;
use once_cell::unsync::Lazy; use once_cell::unsync::Lazy;
use rustpython_parser::ast::{Cmpop, Expr, Ranged}; use rustpython_parser::ast::{CmpOp, Expr, Ranged};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -47,24 +47,24 @@ use crate::registry::AsRule;
/// - [_Why does Python log a SyntaxWarning for is with literals?_ by Adam Johnson](https://adamj.eu/tech/2020/01/21/why-does-python-3-8-syntaxwarning-for-is-literal/) /// - [_Why does Python log a SyntaxWarning for is with literals?_ by Adam Johnson](https://adamj.eu/tech/2020/01/21/why-does-python-3-8-syntaxwarning-for-is-literal/)
#[violation] #[violation]
pub struct IsLiteral { pub struct IsLiteral {
cmpop: IsCmpop, cmp_op: IsCmpOp,
} }
impl AlwaysAutofixableViolation for IsLiteral { impl AlwaysAutofixableViolation for IsLiteral {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
let IsLiteral { cmpop } = self; let IsLiteral { cmp_op } = self;
match cmpop { match cmp_op {
IsCmpop::Is => format!("Use `==` to compare constant literals"), IsCmpOp::Is => format!("Use `==` to compare constant literals"),
IsCmpop::IsNot => format!("Use `!=` to compare constant literals"), IsCmpOp::IsNot => format!("Use `!=` to compare constant literals"),
} }
} }
fn autofix_title(&self) -> String { fn autofix_title(&self) -> String {
let IsLiteral { cmpop } = self; let IsLiteral { cmp_op } = self;
match cmpop { match cmp_op {
IsCmpop::Is => "Replace `is` with `==`".to_string(), IsCmpOp::Is => "Replace `is` with `==`".to_string(),
IsCmpop::IsNot => "Replace `is not` with `!=`".to_string(), IsCmpOp::IsNot => "Replace `is not` with `!=`".to_string(),
} }
} }
} }
@ -73,24 +73,24 @@ impl AlwaysAutofixableViolation for IsLiteral {
pub(crate) fn invalid_literal_comparison( pub(crate) fn invalid_literal_comparison(
checker: &mut Checker, checker: &mut Checker,
left: &Expr, left: &Expr,
ops: &[Cmpop], ops: &[CmpOp],
comparators: &[Expr], comparators: &[Expr],
expr: &Expr, expr: &Expr,
) { ) {
let located = Lazy::new(|| helpers::locate_cmpops(expr, checker.locator)); let located = Lazy::new(|| helpers::locate_cmp_ops(expr, checker.locator));
let mut left = left; let mut left = left;
for (index, (op, right)) in izip!(ops, comparators).enumerate() { for (index, (op, right)) in izip!(ops, comparators).enumerate() {
if matches!(op, Cmpop::Is | Cmpop::IsNot) if matches!(op, CmpOp::Is | CmpOp::IsNot)
&& (helpers::is_constant_non_singleton(left) && (helpers::is_constant_non_singleton(left)
|| helpers::is_constant_non_singleton(right)) || helpers::is_constant_non_singleton(right))
{ {
let mut diagnostic = Diagnostic::new(IsLiteral { cmpop: op.into() }, expr.range()); let mut diagnostic = Diagnostic::new(IsLiteral { cmp_op: op.into() }, expr.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
if let Some(located_op) = &located.get(index) { if let Some(located_op) = &located.get(index) {
assert_eq!(located_op.op, *op); assert_eq!(located_op.op, *op);
if let Some(content) = match located_op.op { if let Some(content) = match located_op.op {
Cmpop::Is => Some("==".to_string()), CmpOp::Is => Some("==".to_string()),
Cmpop::IsNot => Some("!=".to_string()), CmpOp::IsNot => Some("!=".to_string()),
node => { node => {
error!("Failed to fix invalid comparison: {node:?}"); error!("Failed to fix invalid comparison: {node:?}");
None None
@ -112,17 +112,17 @@ pub(crate) fn invalid_literal_comparison(
} }
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
enum IsCmpop { enum IsCmpOp {
Is, Is,
IsNot, IsNot,
} }
impl From<&Cmpop> for IsCmpop { impl From<&CmpOp> for IsCmpOp {
fn from(cmpop: &Cmpop) -> Self { fn from(cmp_op: &CmpOp) -> Self {
match cmpop { match cmp_op {
Cmpop::Is => IsCmpop::Is, CmpOp::Is => IsCmpOp::Is,
Cmpop::IsNot => IsCmpop::IsNot, CmpOp::IsNot => IsCmpOp::IsNot,
_ => panic!("Expected Cmpop::Is | Cmpop::IsNot"), _ => panic!("Expected CmpOp::Is | CmpOp::IsNot"),
} }
} }
} }

View file

@ -253,10 +253,10 @@ fn remove_unused_variable(
} }
} }
// Third case: withitem (`with foo() as x:`) // Third case: with_item (`with foo() as x:`)
if let Stmt::With(ast::StmtWith { items, .. }) = stmt { if let Stmt::With(ast::StmtWith { items, .. }) = stmt {
// Find the binding that matches the given `Range`. // Find the binding that matches the given `Range`.
// TODO(charlie): Store the `Withitem` in the `Binding`. // TODO(charlie): Store the `WithItem` in the `Binding`.
for item in items { for item in items {
if let Some(optional_vars) = &item.optional_vars { if let Some(optional_vars) = &item.optional_vars {
if optional_vars.range() == range { if optional_vars.range() == range {

View file

@ -1,7 +1,7 @@
use std::fmt; use std::fmt;
use rustpython_parser::ast; use rustpython_parser::ast;
use rustpython_parser::ast::Cmpop; use rustpython_parser::ast::CmpOp;
use ruff_python_semantic::analyze::function_type; use ruff_python_semantic::analyze::function_type;
use ruff_python_semantic::{ScopeKind, SemanticModel}; use ruff_python_semantic::{ScopeKind, SemanticModel};
@ -47,29 +47,29 @@ pub(super) fn in_dunder_init(semantic: &SemanticModel, settings: &Settings) -> b
true true
} }
/// A wrapper around [`Cmpop`] that implements `Display`. /// A wrapper around [`CmpOp`] that implements `Display`.
#[derive(Debug)] #[derive(Debug)]
pub(super) struct CmpopExt(Cmpop); pub(super) struct CmpOpExt(CmpOp);
impl From<&Cmpop> for CmpopExt { impl From<&CmpOp> for CmpOpExt {
fn from(cmpop: &Cmpop) -> Self { fn from(cmp_op: &CmpOp) -> Self {
CmpopExt(*cmpop) CmpOpExt(*cmp_op)
} }
} }
impl fmt::Display for CmpopExt { impl fmt::Display for CmpOpExt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let representation = match self.0 { let representation = match self.0 {
Cmpop::Eq => "==", CmpOp::Eq => "==",
Cmpop::NotEq => "!=", CmpOp::NotEq => "!=",
Cmpop::Lt => "<", CmpOp::Lt => "<",
Cmpop::LtE => "<=", CmpOp::LtE => "<=",
Cmpop::Gt => ">", CmpOp::Gt => ">",
Cmpop::GtE => ">=", CmpOp::GtE => ">=",
Cmpop::Is => "is", CmpOp::Is => "is",
Cmpop::IsNot => "is not", CmpOp::IsNot => "is not",
Cmpop::In => "in", CmpOp::In => "in",
Cmpop::NotIn => "not in", CmpOp::NotIn => "not in",
}; };
write!(f, "{representation}") write!(f, "{representation}")
} }

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Excepthandler, Expr, Ranged}; use rustpython_parser::ast::{self, ExceptHandler, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -6,16 +6,16 @@ use ruff_macros::{derive_message_formats, violation};
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
enum Boolop { enum BoolOp {
And, And,
Or, Or,
} }
impl From<&ast::Boolop> for Boolop { impl From<&ast::BoolOp> for BoolOp {
fn from(op: &ast::Boolop) -> Self { fn from(op: &ast::BoolOp) -> Self {
match op { match op {
ast::Boolop::And => Boolop::And, ast::BoolOp::And => BoolOp::And,
ast::Boolop::Or => Boolop::Or, ast::BoolOp::Or => BoolOp::Or,
} }
} }
} }
@ -47,7 +47,7 @@ impl From<&ast::Boolop> for Boolop {
/// ``` /// ```
#[violation] #[violation]
pub struct BinaryOpException { pub struct BinaryOpException {
op: Boolop, op: BoolOp,
} }
impl Violation for BinaryOpException { impl Violation for BinaryOpException {
@ -55,15 +55,16 @@ impl Violation for BinaryOpException {
fn message(&self) -> String { fn message(&self) -> String {
let BinaryOpException { op } = self; let BinaryOpException { op } = self;
match op { match op {
Boolop::And => format!("Exception to catch is the result of a binary `and` operation"), BoolOp::And => format!("Exception to catch is the result of a binary `and` operation"),
Boolop::Or => format!("Exception to catch is the result of a binary `or` operation"), BoolOp::Or => format!("Exception to catch is the result of a binary `or` operation"),
} }
} }
} }
/// PLW0711 /// PLW0711
pub(crate) fn binary_op_exception(checker: &mut Checker, excepthandler: &Excepthandler) { pub(crate) fn binary_op_exception(checker: &mut Checker, except_handler: &ExceptHandler) {
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = excepthandler; let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, .. }) =
except_handler;
let Some(type_) = type_ else { let Some(type_) = type_ else {
return; return;

View file

@ -1,6 +1,6 @@
use anyhow::bail; use anyhow::bail;
use itertools::Itertools; use itertools::Itertools;
use rustpython_parser::ast::{self, Cmpop, Constant, Expr, Ranged}; use rustpython_parser::ast::{self, CmpOp, Constant, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -8,28 +8,28 @@ use ruff_macros::{derive_message_formats, violation};
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub(crate) enum EmptyStringCmpop { pub(crate) enum EmptyStringCmpOp {
Is, Is,
IsNot, IsNot,
Eq, Eq,
NotEq, NotEq,
} }
impl TryFrom<&Cmpop> for EmptyStringCmpop { impl TryFrom<&CmpOp> for EmptyStringCmpOp {
type Error = anyhow::Error; type Error = anyhow::Error;
fn try_from(value: &Cmpop) -> Result<Self, Self::Error> { fn try_from(value: &CmpOp) -> Result<Self, Self::Error> {
match value { match value {
Cmpop::Is => Ok(Self::Is), CmpOp::Is => Ok(Self::Is),
Cmpop::IsNot => Ok(Self::IsNot), CmpOp::IsNot => Ok(Self::IsNot),
Cmpop::Eq => Ok(Self::Eq), CmpOp::Eq => Ok(Self::Eq),
Cmpop::NotEq => Ok(Self::NotEq), CmpOp::NotEq => Ok(Self::NotEq),
_ => bail!("{value:?} cannot be converted to EmptyStringCmpop"), _ => bail!("{value:?} cannot be converted to EmptyStringCmpOp"),
} }
} }
} }
impl EmptyStringCmpop { impl EmptyStringCmpOp {
pub(crate) fn into_unary(self) -> &'static str { pub(crate) fn into_unary(self) -> &'static str {
match self { match self {
Self::Is | Self::Eq => "not ", Self::Is | Self::Eq => "not ",
@ -38,7 +38,7 @@ impl EmptyStringCmpop {
} }
} }
impl std::fmt::Display for EmptyStringCmpop { impl std::fmt::Display for EmptyStringCmpOp {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let repr = match self { let repr = match self {
Self::Is => "is", Self::Is => "is",
@ -93,7 +93,7 @@ impl Violation for CompareToEmptyString {
pub(crate) fn compare_to_empty_string( pub(crate) fn compare_to_empty_string(
checker: &mut Checker, checker: &mut Checker,
left: &Expr, left: &Expr,
ops: &[Cmpop], ops: &[CmpOp],
comparators: &[Expr], comparators: &[Expr],
) { ) {
// Omit string comparison rules within subscripts. This is mostly commonly used within // Omit string comparison rules within subscripts. This is mostly commonly used within
@ -110,7 +110,7 @@ pub(crate) fn compare_to_empty_string(
.tuple_windows::<(&Expr<_>, &Expr<_>)>() .tuple_windows::<(&Expr<_>, &Expr<_>)>()
.zip(ops) .zip(ops)
{ {
if let Ok(op) = EmptyStringCmpop::try_from(op) { if let Ok(op) = EmptyStringCmpOp::try_from(op) {
if std::mem::take(&mut first) { if std::mem::take(&mut first) {
// Check the left-most expression. // Check the left-most expression.
if let Expr::Constant(ast::ExprConstant { value, .. }) = &lhs { if let Expr::Constant(ast::ExprConstant { value, .. }) = &lhs {

View file

@ -1,11 +1,11 @@
use itertools::Itertools; use itertools::Itertools;
use rustpython_parser::ast::{self, Cmpop, Expr, Ranged}; use rustpython_parser::ast::{self, CmpOp, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
use crate::rules::pylint::helpers::CmpopExt; use crate::rules::pylint::helpers::CmpOpExt;
/// ## What it does /// ## What it does
/// Checks for comparisons between constants. /// Checks for comparisons between constants.
@ -30,7 +30,7 @@ use crate::rules::pylint::helpers::CmpopExt;
#[violation] #[violation]
pub struct ComparisonOfConstant { pub struct ComparisonOfConstant {
left_constant: String, left_constant: String,
op: Cmpop, op: CmpOp,
right_constant: String, right_constant: String,
} }
@ -45,7 +45,7 @@ impl Violation for ComparisonOfConstant {
format!( format!(
"Two constants compared in a comparison, consider replacing `{left_constant} {} {right_constant}`", "Two constants compared in a comparison, consider replacing `{left_constant} {} {right_constant}`",
CmpopExt::from(op) CmpOpExt::from(op)
) )
} }
} }
@ -54,7 +54,7 @@ impl Violation for ComparisonOfConstant {
pub(crate) fn comparison_of_constant( pub(crate) fn comparison_of_constant(
checker: &mut Checker, checker: &mut Checker,
left: &Expr, left: &Expr,
ops: &[Cmpop], ops: &[CmpOp],
comparators: &[Expr], comparators: &[Expr],
) { ) {
for ((left, right), op) in std::iter::once(left) for ((left, right), op) in std::iter::once(left)

View file

@ -1,11 +1,11 @@
use itertools::Itertools; use itertools::Itertools;
use rustpython_parser::ast::{Cmpop, Expr, Ranged}; use rustpython_parser::ast::{CmpOp, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
use crate::rules::pylint::helpers::CmpopExt; use crate::rules::pylint::helpers::CmpOpExt;
/// ## What it does /// ## What it does
/// Checks for operations that compare a name to itself. /// Checks for operations that compare a name to itself.
@ -24,7 +24,7 @@ use crate::rules::pylint::helpers::CmpopExt;
#[violation] #[violation]
pub struct ComparisonWithItself { pub struct ComparisonWithItself {
left: String, left: String,
op: Cmpop, op: CmpOp,
right: String, right: String,
} }
@ -34,7 +34,7 @@ impl Violation for ComparisonWithItself {
let ComparisonWithItself { left, op, right } = self; let ComparisonWithItself { left, op, right } = self;
format!( format!(
"Name compared with itself, consider replacing `{left} {} {right}`", "Name compared with itself, consider replacing `{left} {} {right}`",
CmpopExt::from(op) CmpOpExt::from(op)
) )
} }
} }
@ -43,7 +43,7 @@ impl Violation for ComparisonWithItself {
pub(crate) fn comparison_with_itself( pub(crate) fn comparison_with_itself(
checker: &mut Checker, checker: &mut Checker,
left: &Expr, left: &Expr,
ops: &[Cmpop], ops: &[CmpOp],
comparators: &[Expr], comparators: &[Expr],
) { ) {
for ((left, right), op) in std::iter::once(left) for ((left, right), op) in std::iter::once(left)

View file

@ -1,5 +1,5 @@
use itertools::Itertools; use itertools::Itertools;
use rustpython_parser::ast::{self, Constant, Expr, Ranged, Unaryop}; use rustpython_parser::ast::{self, Constant, Expr, Ranged, UnaryOp};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -55,7 +55,7 @@ fn as_constant(expr: &Expr) -> Option<&Constant> {
match expr { match expr {
Expr::Constant(ast::ExprConstant { value, .. }) => Some(value), Expr::Constant(ast::ExprConstant { value, .. }) => Some(value),
Expr::UnaryOp(ast::ExprUnaryOp { Expr::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::UAdd | Unaryop::USub | Unaryop::Invert, op: UnaryOp::UAdd | UnaryOp::USub | UnaryOp::Invert,
operand, operand,
range: _, range: _,
}) => match operand.as_ref() { }) => match operand.as_ref() {

View file

@ -59,14 +59,14 @@ pub(crate) fn property_with_parameters(
{ {
return; return;
} }
if checker.semantic().is_builtin("property") if args
&& args .posonlyargs
.args .iter()
.iter() .chain(&args.args)
.chain(args.posonlyargs.iter()) .chain(&args.kwonlyargs)
.chain(args.kwonlyargs.iter()) .count()
.count() > 1
> 1 && checker.semantic().is_builtin("property")
{ {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
PropertyWithParameters, PropertyWithParameters,

View file

@ -1,7 +1,7 @@
use std::{fmt, iter}; use std::{fmt, iter};
use regex::Regex; use regex::Regex;
use rustpython_parser::ast::{self, Expr, ExprContext, Ranged, Stmt, Withitem}; use rustpython_parser::ast::{self, Expr, ExprContext, Ranged, Stmt, WithItem};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -308,7 +308,7 @@ fn assignment_targets_from_expr<'a>(
} }
fn assignment_targets_from_with_items<'a>( fn assignment_targets_from_with_items<'a>(
items: &'a [Withitem], items: &'a [WithItem],
dummy_variable_rgx: &'a Regex, dummy_variable_rgx: &'a Regex,
) -> impl Iterator<Item = &'a Expr> + 'a { ) -> impl Iterator<Item = &'a Expr> + 'a {
items items

View file

@ -1,6 +1,6 @@
use itertools::Itertools; use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use rustpython_parser::ast::{self, Boolop, Expr, Ranged}; use rustpython_parser::ast::{self, BoolOp, Expr, Ranged};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -63,7 +63,7 @@ impl AlwaysAutofixableViolation for RepeatedIsinstanceCalls {
pub(crate) fn repeated_isinstance_calls( pub(crate) fn repeated_isinstance_calls(
checker: &mut Checker, checker: &mut Checker,
expr: &Expr, expr: &Expr,
op: Boolop, op: BoolOp,
values: &[Expr], values: &[Expr],
) { ) {
if !op.is_or() { if !op.is_or() {

View file

@ -58,18 +58,18 @@ impl Violation for TooManyArguments {
} }
/// PLR0913 /// PLR0913
pub(crate) fn too_many_arguments(checker: &mut Checker, args: &Arguments, stmt: &Stmt) { pub(crate) fn too_many_arguments(checker: &mut Checker, arguments: &Arguments, stmt: &Stmt) {
let num_args = args let num_arguments = arguments
.args .args
.iter() .iter()
.chain(args.kwonlyargs.iter()) .chain(&arguments.kwonlyargs)
.chain(args.posonlyargs.iter()) .chain(&arguments.posonlyargs)
.filter(|arg| !checker.settings.dummy_variable_rgx.is_match(&arg.arg)) .filter(|arg| !checker.settings.dummy_variable_rgx.is_match(&arg.def.arg))
.count(); .count();
if num_args > checker.settings.pylint.max_args { if num_arguments > checker.settings.pylint.max_args {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
TooManyArguments { TooManyArguments {
c_args: num_args, c_args: num_arguments,
max_args: checker.settings.pylint.max_args, max_args: checker.settings.pylint.max_args,
}, },
stmt.identifier(checker.locator), stmt.identifier(checker.locator),

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Excepthandler, Stmt}; use rustpython_parser::ast::{self, ExceptHandler, Stmt};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -147,8 +147,8 @@ fn num_branches(stmts: &[Stmt]) -> usize {
.iter() .iter()
.map(|handler| { .map(|handler| {
1 + { 1 + {
let Excepthandler::ExceptHandler( let ExceptHandler::ExceptHandler(
ast::ExcepthandlerExceptHandler { body, .. }, ast::ExceptHandlerExceptHandler { body, .. },
) = handler; ) = handler;
num_branches(body) num_branches(body)
} }

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Excepthandler, Stmt}; use rustpython_parser::ast::{self, ExceptHandler, Stmt};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -123,7 +123,7 @@ fn num_statements(stmts: &[Stmt]) -> usize {
} }
for handler in handlers { for handler in handlers {
count += 1; count += 1;
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
body, .. body, ..
}) = handler; }) = handler;
count += num_statements(body); count += num_statements(body);

View file

@ -160,8 +160,7 @@ pub(crate) fn unexpected_special_method_signature(
} }
let actual_params = args.args.len(); let actual_params = args.args.len();
let optional_params = args.defaults.len(); let mandatory_params = args.args.iter().filter(|arg| arg.default.is_none()).count();
let mandatory_params = actual_params - optional_params;
let Some(expected_params) = ExpectedParams::from_method(name, is_staticmethod(decorator_list, checker.semantic())) else { let Some(expected_params) = ExpectedParams::from_method(name, is_staticmethod(decorator_list, checker.semantic())) else {
return; return;

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Excepthandler, MatchCase, Stmt}; use rustpython_parser::ast::{self, ExceptHandler, MatchCase, Stmt};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -79,7 +79,7 @@ fn loop_exits_early(body: &[Stmt]) -> bool {
|| loop_exits_early(orelse) || loop_exits_early(orelse)
|| loop_exits_early(finalbody) || loop_exits_early(finalbody)
|| handlers.iter().any(|handler| match handler { || handlers.iter().any(|handler| match handler {
Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
body, .. body, ..
}) => loop_exits_early(body), }) => loop_exits_early(body),
}) })

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Excepthandler, Expr, ExprContext, Ranged}; use rustpython_parser::ast::{self, ExceptHandler, Expr, ExprContext, Ranged};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -151,9 +151,9 @@ fn tuple_diagnostic(checker: &mut Checker, target: &Expr, aliases: &[&Expr]) {
} }
/// UP024 /// UP024
pub(crate) fn os_error_alias_handlers(checker: &mut Checker, handlers: &[Excepthandler]) { pub(crate) fn os_error_alias_handlers(checker: &mut Checker, handlers: &[ExceptHandler]) {
for handler in handlers { for handler in handlers {
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) = handler; let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, .. }) = handler;
let Some(expr) = type_.as_ref() else { let Some(expr) = type_.as_ref() else {
continue; continue;
}; };

View file

@ -2,7 +2,7 @@ use std::cmp::Ordering;
use num_bigint::{BigInt, Sign}; use num_bigint::{BigInt, Sign};
use ruff_text_size::{TextRange, TextSize}; use ruff_text_size::{TextRange, TextSize};
use rustpython_parser::ast::{self, Cmpop, Constant, Expr, Ranged, Stmt}; use rustpython_parser::ast::{self, CmpOp, Constant, Expr, Ranged, Stmt};
use rustpython_parser::{lexer, Mode, Tok}; use rustpython_parser::{lexer, Mode, Tok};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
@ -370,8 +370,8 @@ pub(crate) fn outdated_version_block(
Expr::Tuple(ast::ExprTuple { elts, .. }) => { Expr::Tuple(ast::ExprTuple { elts, .. }) => {
let version = extract_version(elts); let version = extract_version(elts);
let target = checker.settings.target_version; let target = checker.settings.target_version;
if op == &Cmpop::Lt || op == &Cmpop::LtE { if op == &CmpOp::Lt || op == &CmpOp::LtE {
if compare_version(&version, target, op == &Cmpop::LtE) { if compare_version(&version, target, op == &CmpOp::LtE) {
let mut diagnostic = Diagnostic::new(OutdatedVersionBlock, stmt.range()); let mut diagnostic = Diagnostic::new(OutdatedVersionBlock, stmt.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
if let Some(block) = metadata(checker.locator, stmt, body) { if let Some(block) = metadata(checker.locator, stmt, body) {
@ -382,8 +382,8 @@ pub(crate) fn outdated_version_block(
} }
checker.diagnostics.push(diagnostic); checker.diagnostics.push(diagnostic);
} }
} else if op == &Cmpop::Gt || op == &Cmpop::GtE { } else if op == &CmpOp::Gt || op == &CmpOp::GtE {
if compare_version(&version, target, op == &Cmpop::GtE) { if compare_version(&version, target, op == &CmpOp::GtE) {
let mut diagnostic = Diagnostic::new(OutdatedVersionBlock, stmt.range()); let mut diagnostic = Diagnostic::new(OutdatedVersionBlock, stmt.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
if let Some(block) = metadata(checker.locator, stmt, body) { if let Some(block) = metadata(checker.locator, stmt, body) {
@ -402,7 +402,7 @@ pub(crate) fn outdated_version_block(
.. ..
}) => { }) => {
let version_number = bigint_to_u32(number); let version_number = bigint_to_u32(number);
if version_number == 2 && op == &Cmpop::Eq { if version_number == 2 && op == &CmpOp::Eq {
let mut diagnostic = Diagnostic::new(OutdatedVersionBlock, stmt.range()); let mut diagnostic = Diagnostic::new(OutdatedVersionBlock, stmt.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
if let Some(block) = metadata(checker.locator, stmt, body) { if let Some(block) = metadata(checker.locator, stmt, body) {
@ -412,7 +412,7 @@ pub(crate) fn outdated_version_block(
} }
} }
checker.diagnostics.push(diagnostic); checker.diagnostics.push(diagnostic);
} else if version_number == 3 && op == &Cmpop::Eq { } else if version_number == 3 && op == &CmpOp::Eq {
let mut diagnostic = Diagnostic::new(OutdatedVersionBlock, stmt.range()); let mut diagnostic = Diagnostic::new(OutdatedVersionBlock, stmt.range());
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
if let Some(block) = metadata(checker.locator, stmt, body) { if let Some(block) = metadata(checker.locator, stmt, body) {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Arg, Expr, Ranged, Stmt}; use rustpython_parser::ast::{self, Arg, ArgWithDefault, Expr, Ranged, Stmt};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -104,8 +104,9 @@ pub(crate) fn super_call_with_parameters(
}; };
// Extract the name of the first argument to the enclosing function. // Extract the name of the first argument to the enclosing function.
let Some(Arg { let Some(ArgWithDefault {
arg: parent_arg, .. def: Arg { arg: parent_arg, .. },
..
}) = parent_args.args.first() else { }) = parent_args.args.first() else {
return; return;
}; };

View file

@ -1,13 +1,13 @@
use std::fmt; use std::fmt;
use anyhow::Result; use anyhow::Result;
use rustpython_parser::ast::{self, Arguments, Constant, Expr, Operator, Ranged}; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, ArgWithDefault, Arguments, Constant, Expr, Operator, Ranged};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::is_const_none; use ruff_python_ast::helpers::is_const_none;
use ruff_python_semantic::SemanticModel; use ruff_python_semantic::SemanticModel;
use ruff_text_size::TextRange;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
use crate::importer::ImportRequest; use crate::importer::ImportRequest;
@ -307,24 +307,23 @@ fn generate_fix(checker: &Checker, conversion_type: ConversionType, expr: &Expr)
/// RUF011 /// RUF011
pub(crate) fn implicit_optional(checker: &mut Checker, arguments: &Arguments) { pub(crate) fn implicit_optional(checker: &mut Checker, arguments: &Arguments) {
let arguments_with_defaults = arguments for ArgWithDefault {
.kwonlyargs def,
default,
range: _,
} in arguments
.posonlyargs
.iter() .iter()
.rev() .chain(&arguments.args)
.zip(arguments.kw_defaults.iter().rev()) .chain(&arguments.kwonlyargs)
.chain( {
arguments let Some(default) = default else {
.args continue
.iter() };
.rev()
.chain(arguments.posonlyargs.iter().rev())
.zip(arguments.defaults.iter().rev()),
);
for (arg, default) in arguments_with_defaults {
if !is_const_none(default) { if !is_const_none(default) {
continue; continue;
} }
let Some(annotation) = &arg.annotation else { let Some(annotation) = &def.annotation else {
continue continue
}; };
let Some(expr) = type_hint_explicitly_allows_none(annotation, checker.semantic()) else { let Some(expr) = type_hint_explicitly_allows_none(annotation, checker.semantic()) else {

View file

@ -1,5 +1,5 @@
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
use rustpython_parser::ast::{self, Constant, Expr, Ranged, Unaryop}; use rustpython_parser::ast::{self, Constant, Expr, Ranged, UnaryOp};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -69,7 +69,7 @@ fn to_bound(expr: &Expr) -> Option<i64> {
.. ..
}) => value.to_i64(), }) => value.to_i64(),
Expr::UnaryOp(ast::ExprUnaryOp { Expr::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::USub | Unaryop::Invert, op: UnaryOp::USub | UnaryOp::Invert,
operand, operand,
range: _, range: _,
}) => { }) => {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Excepthandler, Expr, Ranged}; use rustpython_parser::ast::{self, ExceptHandler, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -54,9 +54,9 @@ impl Violation for ErrorInsteadOfException {
} }
/// TRY400 /// TRY400
pub(crate) fn error_instead_of_exception(checker: &mut Checker, handlers: &[Excepthandler]) { pub(crate) fn error_instead_of_exception(checker: &mut Checker, handlers: &[ExceptHandler]) {
for handler in handlers { for handler in handlers {
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) = handler; let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { body, .. }) = handler;
let calls = { let calls = {
let mut visitor = LoggerCandidateVisitor::new(checker.semantic()); let mut visitor = LoggerCandidateVisitor::new(checker.semantic());
visitor.visit_body(body); visitor.visit_body(body);

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Excepthandler, Ranged, Stmt}; use rustpython_parser::ast::{ExceptHandler, Ranged, Stmt};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -72,7 +72,7 @@ where
} }
/// TRY301 /// TRY301
pub(crate) fn raise_within_try(checker: &mut Checker, body: &[Stmt], handlers: &[Excepthandler]) { pub(crate) fn raise_within_try(checker: &mut Checker, body: &[Stmt], handlers: &[ExceptHandler]) {
if handlers.is_empty() { if handlers.is_empty() {
return; return;
} }

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Excepthandler, Ranged, Stmt}; use rustpython_parser::ast::{self, ExceptHandler, Ranged, Stmt};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -60,7 +60,7 @@ pub(crate) fn try_consider_else(
checker: &mut Checker, checker: &mut Checker,
body: &[Stmt], body: &[Stmt],
orelse: &[Stmt], orelse: &[Stmt],
handler: &[Excepthandler], handler: &[ExceptHandler],
) { ) {
if body.len() > 1 && orelse.is_empty() && !handler.is_empty() { if body.len() > 1 && orelse.is_empty() && !handler.is_empty() {
if let Some(stmt) = body.last() { if let Some(stmt) = body.last() {

View file

@ -1,5 +1,4 @@
use rustpython_parser::ast::Excepthandler::ExceptHandler; use rustpython_parser::ast::{self, ExceptHandler, ExceptHandlerExceptHandler, Expr, Ranged, Stmt};
use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerExceptHandler, Expr, Ranged, Stmt};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -39,11 +38,12 @@ impl Violation for UselessTryExcept {
} }
/// TRY302 /// TRY302
pub(crate) fn useless_try_except(checker: &mut Checker, handlers: &[Excepthandler]) { pub(crate) fn useless_try_except(checker: &mut Checker, handlers: &[ExceptHandler]) {
if let Some(diagnostics) = handlers if let Some(diagnostics) = handlers
.iter() .iter()
.map(|handler| { .map(|handler| {
let ExceptHandler(ExcepthandlerExceptHandler { name, body, .. }) = handler; let ExceptHandler::ExceptHandler(ExceptHandlerExceptHandler { name, body, .. }) =
handler;
let Some(Stmt::Raise(ast::StmtRaise { exc, cause: None, .. })) = &body.first() else { let Some(Stmt::Raise(ast::StmtRaise { exc, cause: None, .. })) = &body.first() else {
return None; return None;
}; };

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Excepthandler, Expr, Ranged}; use rustpython_parser::ast::{self, ExceptHandler, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -57,9 +57,9 @@ impl<'a> Visitor<'a> for NameVisitor<'a> {
} }
/// TRY401 /// TRY401
pub(crate) fn verbose_log_message(checker: &mut Checker, handlers: &[Excepthandler]) { pub(crate) fn verbose_log_message(checker: &mut Checker, handlers: &[ExceptHandler]) {
for handler in handlers { for handler in handlers {
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { name, body, .. }) = let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { name, body, .. }) =
handler; handler;
let Some(target) = name else { let Some(target) = name else {
continue; continue;

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Excepthandler, Expr, Ranged, Stmt}; use rustpython_parser::ast::{self, ExceptHandler, Expr, Ranged, Stmt};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -74,10 +74,10 @@ where
} }
/// TRY201 /// TRY201
pub(crate) fn verbose_raise(checker: &mut Checker, handlers: &[Excepthandler]) { pub(crate) fn verbose_raise(checker: &mut Checker, handlers: &[ExceptHandler]) {
for handler in handlers { for handler in handlers {
// If the handler assigned a name to the exception... // If the handler assigned a name to the exception...
if let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { if let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
name: Some(exception_name), name: Some(exception_name),
body, body,
.. ..

View file

@ -22,16 +22,16 @@ impl From<&ast::ExprContext> for ComparableExprContext {
} }
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum ComparableBoolop { pub enum ComparableBoolOp {
And, And,
Or, Or,
} }
impl From<ast::Boolop> for ComparableBoolop { impl From<ast::BoolOp> for ComparableBoolOp {
fn from(op: ast::Boolop) -> Self { fn from(op: ast::BoolOp) -> Self {
match op { match op {
ast::Boolop::And => Self::And, ast::BoolOp::And => Self::And,
ast::Boolop::Or => Self::Or, ast::BoolOp::Or => Self::Or,
} }
} }
} }
@ -74,26 +74,26 @@ impl From<ast::Operator> for ComparableOperator {
} }
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum ComparableUnaryop { pub enum ComparableUnaryOp {
Invert, Invert,
Not, Not,
UAdd, UAdd,
USub, USub,
} }
impl From<ast::Unaryop> for ComparableUnaryop { impl From<ast::UnaryOp> for ComparableUnaryOp {
fn from(op: ast::Unaryop) -> Self { fn from(op: ast::UnaryOp) -> Self {
match op { match op {
ast::Unaryop::Invert => Self::Invert, ast::UnaryOp::Invert => Self::Invert,
ast::Unaryop::Not => Self::Not, ast::UnaryOp::Not => Self::Not,
ast::Unaryop::UAdd => Self::UAdd, ast::UnaryOp::UAdd => Self::UAdd,
ast::Unaryop::USub => Self::USub, ast::UnaryOp::USub => Self::USub,
} }
} }
} }
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum ComparableCmpop { pub enum ComparableCmpOp {
Eq, Eq,
NotEq, NotEq,
Lt, Lt,
@ -106,19 +106,19 @@ pub enum ComparableCmpop {
NotIn, NotIn,
} }
impl From<ast::Cmpop> for ComparableCmpop { impl From<ast::CmpOp> for ComparableCmpOp {
fn from(op: ast::Cmpop) -> Self { fn from(op: ast::CmpOp) -> Self {
match op { match op {
ast::Cmpop::Eq => Self::Eq, ast::CmpOp::Eq => Self::Eq,
ast::Cmpop::NotEq => Self::NotEq, ast::CmpOp::NotEq => Self::NotEq,
ast::Cmpop::Lt => Self::Lt, ast::CmpOp::Lt => Self::Lt,
ast::Cmpop::LtE => Self::LtE, ast::CmpOp::LtE => Self::LtE,
ast::Cmpop::Gt => Self::Gt, ast::CmpOp::Gt => Self::Gt,
ast::Cmpop::GtE => Self::GtE, ast::CmpOp::GtE => Self::GtE,
ast::Cmpop::Is => Self::Is, ast::CmpOp::Is => Self::Is,
ast::Cmpop::IsNot => Self::IsNot, ast::CmpOp::IsNot => Self::IsNot,
ast::Cmpop::In => Self::In, ast::CmpOp::In => Self::In,
ast::Cmpop::NotIn => Self::NotIn, ast::CmpOp::NotIn => Self::NotIn,
} }
} }
} }
@ -139,16 +139,16 @@ impl<'a> From<&'a ast::Alias> for ComparableAlias<'a> {
} }
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableWithitem<'a> { pub struct ComparableWithItem<'a> {
context_expr: ComparableExpr<'a>, context_expr: ComparableExpr<'a>,
optional_vars: Option<ComparableExpr<'a>>, optional_vars: Option<ComparableExpr<'a>>,
} }
impl<'a> From<&'a ast::Withitem> for ComparableWithitem<'a> { impl<'a> From<&'a ast::WithItem> for ComparableWithItem<'a> {
fn from(withitem: &'a ast::Withitem) -> Self { fn from(with_item: &'a ast::WithItem) -> Self {
Self { Self {
context_expr: (&withitem.context_expr).into(), context_expr: (&with_item.context_expr).into(),
optional_vars: withitem.optional_vars.as_ref().map(Into::into), optional_vars: with_item.optional_vars.as_ref().map(Into::into),
} }
} }
} }
@ -342,13 +342,11 @@ impl<'a> From<&'a ast::Constant> for ComparableConstant<'a> {
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableArguments<'a> { pub struct ComparableArguments<'a> {
posonlyargs: Vec<ComparableArg<'a>>, posonlyargs: Vec<ComparableArgWithDefault<'a>>,
args: Vec<ComparableArg<'a>>, args: Vec<ComparableArgWithDefault<'a>>,
vararg: Option<ComparableArg<'a>>, vararg: Option<ComparableArg<'a>>,
kwonlyargs: Vec<ComparableArg<'a>>, kwonlyargs: Vec<ComparableArgWithDefault<'a>>,
kw_defaults: Vec<ComparableExpr<'a>>,
kwarg: Option<ComparableArg<'a>>, kwarg: Option<ComparableArg<'a>>,
defaults: Vec<ComparableExpr<'a>>,
} }
impl<'a> From<&'a ast::Arguments> for ComparableArguments<'a> { impl<'a> From<&'a ast::Arguments> for ComparableArguments<'a> {
@ -358,9 +356,7 @@ impl<'a> From<&'a ast::Arguments> for ComparableArguments<'a> {
args: arguments.args.iter().map(Into::into).collect(), args: arguments.args.iter().map(Into::into).collect(),
vararg: arguments.vararg.as_ref().map(Into::into), vararg: arguments.vararg.as_ref().map(Into::into),
kwonlyargs: arguments.kwonlyargs.iter().map(Into::into).collect(), kwonlyargs: arguments.kwonlyargs.iter().map(Into::into).collect(),
kw_defaults: arguments.kw_defaults.iter().map(Into::into).collect(),
kwarg: arguments.kwarg.as_ref().map(Into::into), kwarg: arguments.kwarg.as_ref().map(Into::into),
defaults: arguments.defaults.iter().map(Into::into).collect(),
} }
} }
} }
@ -394,6 +390,21 @@ impl<'a> From<&'a ast::Arg> for ComparableArg<'a> {
} }
} }
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableArgWithDefault<'a> {
def: ComparableArg<'a>,
default: Option<ComparableExpr<'a>>,
}
impl<'a> From<&'a ast::ArgWithDefault> for ComparableArgWithDefault<'a> {
fn from(arg: &'a ast::ArgWithDefault) -> Self {
Self {
def: (&arg.def).into(),
default: arg.default.as_ref().map(Into::into),
}
}
}
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableKeyword<'a> { pub struct ComparableKeyword<'a> {
arg: Option<&'a str>, arg: Option<&'a str>,
@ -429,26 +440,26 @@ impl<'a> From<&'a ast::Comprehension> for ComparableComprehension<'a> {
} }
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExcepthandlerExceptHandler<'a> { pub struct ExceptHandlerExceptHandler<'a> {
type_: Option<Box<ComparableExpr<'a>>>, type_: Option<Box<ComparableExpr<'a>>>,
name: Option<&'a str>, name: Option<&'a str>,
body: Vec<ComparableStmt<'a>>, body: Vec<ComparableStmt<'a>>,
} }
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
pub enum ComparableExcepthandler<'a> { pub enum ComparableExceptHandler<'a> {
ExceptHandler(ExcepthandlerExceptHandler<'a>), ExceptHandler(ExceptHandlerExceptHandler<'a>),
} }
impl<'a> From<&'a ast::Excepthandler> for ComparableExcepthandler<'a> { impl<'a> From<&'a ast::ExceptHandler> for ComparableExceptHandler<'a> {
fn from(excepthandler: &'a ast::Excepthandler) -> Self { fn from(except_handler: &'a ast::ExceptHandler) -> Self {
let ast::Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { let ast::ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
type_, type_,
name, name,
body, body,
.. ..
}) = excepthandler; }) = except_handler;
Self::ExceptHandler(ExcepthandlerExceptHandler { Self::ExceptHandler(ExceptHandlerExceptHandler {
type_: type_.as_ref().map(Into::into), type_: type_.as_ref().map(Into::into),
name: name.as_deref(), name: name.as_deref(),
body: body.iter().map(Into::into).collect(), body: body.iter().map(Into::into).collect(),
@ -458,7 +469,7 @@ impl<'a> From<&'a ast::Excepthandler> for ComparableExcepthandler<'a> {
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprBoolOp<'a> { pub struct ExprBoolOp<'a> {
op: ComparableBoolop, op: ComparableBoolOp,
values: Vec<ComparableExpr<'a>>, values: Vec<ComparableExpr<'a>>,
} }
@ -477,7 +488,7 @@ pub struct ExprBinOp<'a> {
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprUnaryOp<'a> { pub struct ExprUnaryOp<'a> {
op: ComparableUnaryop, op: ComparableUnaryOp,
operand: Box<ComparableExpr<'a>>, operand: Box<ComparableExpr<'a>>,
} }
@ -548,7 +559,7 @@ pub struct ExprYieldFrom<'a> {
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprCompare<'a> { pub struct ExprCompare<'a> {
left: Box<ComparableExpr<'a>>, left: Box<ComparableExpr<'a>>,
ops: Vec<ComparableCmpop>, ops: Vec<ComparableCmpOp>,
comparators: Vec<ComparableExpr<'a>>, comparators: Vec<ComparableExpr<'a>>,
} }
@ -994,14 +1005,14 @@ pub struct StmtIf<'a> {
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtWith<'a> { pub struct StmtWith<'a> {
items: Vec<ComparableWithitem<'a>>, items: Vec<ComparableWithItem<'a>>,
body: Vec<ComparableStmt<'a>>, body: Vec<ComparableStmt<'a>>,
type_comment: Option<&'a str>, type_comment: Option<&'a str>,
} }
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtAsyncWith<'a> { pub struct StmtAsyncWith<'a> {
items: Vec<ComparableWithitem<'a>>, items: Vec<ComparableWithItem<'a>>,
body: Vec<ComparableStmt<'a>>, body: Vec<ComparableStmt<'a>>,
type_comment: Option<&'a str>, type_comment: Option<&'a str>,
} }
@ -1021,7 +1032,7 @@ pub struct StmtRaise<'a> {
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtTry<'a> { pub struct StmtTry<'a> {
body: Vec<ComparableStmt<'a>>, body: Vec<ComparableStmt<'a>>,
handlers: Vec<ComparableExcepthandler<'a>>, handlers: Vec<ComparableExceptHandler<'a>>,
orelse: Vec<ComparableStmt<'a>>, orelse: Vec<ComparableStmt<'a>>,
finalbody: Vec<ComparableStmt<'a>>, finalbody: Vec<ComparableStmt<'a>>,
} }
@ -1029,7 +1040,7 @@ pub struct StmtTry<'a> {
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtTryStar<'a> { pub struct StmtTryStar<'a> {
body: Vec<ComparableStmt<'a>>, body: Vec<ComparableStmt<'a>>,
handlers: Vec<ComparableExcepthandler<'a>>, handlers: Vec<ComparableExceptHandler<'a>>,
orelse: Vec<ComparableStmt<'a>>, orelse: Vec<ComparableStmt<'a>>,
finalbody: Vec<ComparableStmt<'a>>, finalbody: Vec<ComparableStmt<'a>>,
} }

View file

@ -5,9 +5,9 @@ use std::path::Path;
use num_traits::Zero; use num_traits::Zero;
use ruff_text_size::{TextRange, TextSize}; use ruff_text_size::{TextRange, TextSize};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use rustpython_ast::Cmpop; use rustpython_ast::CmpOp;
use rustpython_parser::ast::{ use rustpython_parser::ast::{
self, Arguments, Constant, Excepthandler, Expr, Keyword, MatchCase, Pattern, Ranged, Stmt, self, Arguments, Constant, ExceptHandler, Expr, Keyword, MatchCase, Pattern, Ranged, Stmt,
}; };
use rustpython_parser::{lexer, Mode, Tok}; use rustpython_parser::{lexer, Mode, Tok};
use smallvec::SmallVec; use smallvec::SmallVec;
@ -333,25 +333,19 @@ where
returns, returns,
.. ..
}) => { }) => {
args.defaults.iter().any(|expr| any_over_expr(expr, func)) args.posonlyargs
|| args .iter()
.kw_defaults .chain(args.args.iter().chain(args.kwonlyargs.iter()))
.iter() .any(|arg_with_default| {
.any(|expr| any_over_expr(expr, func)) arg_with_default
|| args.args.iter().any(|arg| { .default
arg.annotation
.as_ref()
.map_or(false, |expr| any_over_expr(expr, func))
})
|| args.kwonlyargs.iter().any(|arg| {
arg.annotation
.as_ref()
.map_or(false, |expr| any_over_expr(expr, func))
})
|| args.posonlyargs.iter().any(|arg| {
arg.annotation
.as_ref() .as_ref()
.map_or(false, |expr| any_over_expr(expr, func)) .map_or(false, |expr| any_over_expr(expr, func))
|| arg_with_default
.def
.annotation
.as_ref()
.map_or(false, |expr| any_over_expr(expr, func))
}) })
|| args.vararg.as_ref().map_or(false, |arg| { || args.vararg.as_ref().map_or(false, |arg| {
arg.annotation arg.annotation
@ -448,9 +442,9 @@ where
}) => any_over_expr(test, func) || any_over_body(body, func) || any_over_body(orelse, func), }) => any_over_expr(test, func) || any_over_body(body, func) || any_over_body(orelse, func),
Stmt::With(ast::StmtWith { items, body, .. }) Stmt::With(ast::StmtWith { items, body, .. })
| Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => { | Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => {
items.iter().any(|withitem| { items.iter().any(|with_item| {
any_over_expr(&withitem.context_expr, func) any_over_expr(&with_item.context_expr, func)
|| withitem || with_item
.optional_vars .optional_vars
.as_ref() .as_ref()
.map_or(false, |expr| any_over_expr(expr, func)) .map_or(false, |expr| any_over_expr(expr, func))
@ -483,7 +477,7 @@ where
}) => { }) => {
any_over_body(body, func) any_over_body(body, func)
|| handlers.iter().any(|handler| { || handlers.iter().any(|handler| {
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
type_, type_,
body, body,
.. ..
@ -655,11 +649,11 @@ pub fn has_non_none_keyword(keywords: &[Keyword], keyword: &str) -> bool {
} }
/// Extract the names of all handled exceptions. /// Extract the names of all handled exceptions.
pub fn extract_handled_exceptions(handlers: &[Excepthandler]) -> Vec<&Expr> { pub fn extract_handled_exceptions(handlers: &[ExceptHandler]) -> Vec<&Expr> {
let mut handled_exceptions = Vec::new(); let mut handled_exceptions = Vec::new();
for handler in handlers { for handler in handlers {
match handler { match handler {
Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) => { ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, .. }) => {
if let Some(type_) = type_ { if let Some(type_) = type_ {
if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &type_.as_ref() { if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &type_.as_ref() {
for type_ in elts { for type_ in elts {
@ -678,17 +672,17 @@ pub fn extract_handled_exceptions(handlers: &[Excepthandler]) -> Vec<&Expr> {
/// Return the set of all bound argument names. /// Return the set of all bound argument names.
pub fn collect_arg_names<'a>(arguments: &'a Arguments) -> FxHashSet<&'a str> { pub fn collect_arg_names<'a>(arguments: &'a Arguments) -> FxHashSet<&'a str> {
let mut arg_names: FxHashSet<&'a str> = FxHashSet::default(); let mut arg_names: FxHashSet<&'a str> = FxHashSet::default();
for arg in &arguments.posonlyargs { for arg_with_default in &arguments.posonlyargs {
arg_names.insert(arg.arg.as_str()); arg_names.insert(arg_with_default.def.arg.as_str());
} }
for arg in &arguments.args { for arg_with_default in &arguments.args {
arg_names.insert(arg.arg.as_str()); arg_names.insert(arg_with_default.def.arg.as_str());
} }
if let Some(arg) = &arguments.vararg { if let Some(arg) = &arguments.vararg {
arg_names.insert(arg.arg.as_str()); arg_names.insert(arg.arg.as_str());
} }
for arg in &arguments.kwonlyargs { for arg_with_default in &arguments.kwonlyargs {
arg_names.insert(arg.arg.as_str()); arg_names.insert(arg_with_default.def.arg.as_str());
} }
if let Some(arg) = &arguments.kwarg { if let Some(arg) = &arguments.kwarg {
arg_names.insert(arg.arg.as_str()); arg_names.insert(arg.arg.as_str());
@ -1409,13 +1403,13 @@ impl Truthiness {
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct LocatedCmpop { pub struct LocatedCmpOp {
pub range: TextRange, pub range: TextRange,
pub op: Cmpop, pub op: CmpOp,
} }
impl LocatedCmpop { impl LocatedCmpOp {
fn new<T: Into<TextRange>>(range: T, op: Cmpop) -> Self { fn new<T: Into<TextRange>>(range: T, op: CmpOp) -> Self {
Self { Self {
range: range.into(), range: range.into(),
op, op,
@ -1423,13 +1417,13 @@ impl LocatedCmpop {
} }
} }
/// Extract all [`Cmpop`] operators from an expression snippet, with appropriate /// Extract all [`CmpOp`] operators from an expression snippet, with appropriate
/// ranges. /// ranges.
/// ///
/// `RustPython` doesn't include line and column information on [`Cmpop`] nodes. /// `RustPython` doesn't include line and column information on [`CmpOp`] nodes.
/// `CPython` doesn't either. This method iterates over the token stream and /// `CPython` doesn't either. This method iterates over the token stream and
/// re-identifies [`Cmpop`] nodes, annotating them with valid ranges. /// re-identifies [`CmpOp`] nodes, annotating them with valid ranges.
pub fn locate_cmpops(expr: &Expr, locator: &Locator) -> Vec<LocatedCmpop> { pub fn locate_cmp_ops(expr: &Expr, locator: &Locator) -> Vec<LocatedCmpOp> {
// If `Expr` is a multi-line expression, we need to parenthesize it to // If `Expr` is a multi-line expression, we need to parenthesize it to
// ensure that it's lexed correctly. // ensure that it's lexed correctly.
let contents = locator.slice(expr.range()); let contents = locator.slice(expr.range());
@ -1441,7 +1435,7 @@ pub fn locate_cmpops(expr: &Expr, locator: &Locator) -> Vec<LocatedCmpop> {
.filter(|(tok, _)| !matches!(tok, Tok::NonLogicalNewline | Tok::Comment(_))) .filter(|(tok, _)| !matches!(tok, Tok::NonLogicalNewline | Tok::Comment(_)))
.peekable(); .peekable();
let mut ops: Vec<LocatedCmpop> = vec![]; let mut ops: Vec<LocatedCmpOp> = vec![];
let mut count = 0u32; let mut count = 0u32;
loop { loop {
let Some((tok, range)) = tok_iter.next() else { let Some((tok, range)) = tok_iter.next() else {
@ -1460,45 +1454,45 @@ pub fn locate_cmpops(expr: &Expr, locator: &Locator) -> Vec<LocatedCmpop> {
if let Some((_, next_range)) = if let Some((_, next_range)) =
tok_iter.next_if(|(tok, _)| matches!(tok, Tok::In)) tok_iter.next_if(|(tok, _)| matches!(tok, Tok::In))
{ {
ops.push(LocatedCmpop::new( ops.push(LocatedCmpOp::new(
TextRange::new(range.start(), next_range.end()), TextRange::new(range.start(), next_range.end()),
Cmpop::NotIn, CmpOp::NotIn,
)); ));
} }
} }
Tok::In => { Tok::In => {
ops.push(LocatedCmpop::new(range, Cmpop::In)); ops.push(LocatedCmpOp::new(range, CmpOp::In));
} }
Tok::Is => { Tok::Is => {
let op = if let Some((_, next_range)) = let op = if let Some((_, next_range)) =
tok_iter.next_if(|(tok, _)| matches!(tok, Tok::Not)) tok_iter.next_if(|(tok, _)| matches!(tok, Tok::Not))
{ {
LocatedCmpop::new( LocatedCmpOp::new(
TextRange::new(range.start(), next_range.end()), TextRange::new(range.start(), next_range.end()),
Cmpop::IsNot, CmpOp::IsNot,
) )
} else { } else {
LocatedCmpop::new(range, Cmpop::Is) LocatedCmpOp::new(range, CmpOp::Is)
}; };
ops.push(op); ops.push(op);
} }
Tok::NotEqual => { Tok::NotEqual => {
ops.push(LocatedCmpop::new(range, Cmpop::NotEq)); ops.push(LocatedCmpOp::new(range, CmpOp::NotEq));
} }
Tok::EqEqual => { Tok::EqEqual => {
ops.push(LocatedCmpop::new(range, Cmpop::Eq)); ops.push(LocatedCmpOp::new(range, CmpOp::Eq));
} }
Tok::GreaterEqual => { Tok::GreaterEqual => {
ops.push(LocatedCmpop::new(range, Cmpop::GtE)); ops.push(LocatedCmpOp::new(range, CmpOp::GtE));
} }
Tok::Greater => { Tok::Greater => {
ops.push(LocatedCmpop::new(range, Cmpop::Gt)); ops.push(LocatedCmpOp::new(range, CmpOp::Gt));
} }
Tok::LessEqual => { Tok::LessEqual => {
ops.push(LocatedCmpop::new(range, Cmpop::LtE)); ops.push(LocatedCmpOp::new(range, CmpOp::LtE));
} }
Tok::Less => { Tok::Less => {
ops.push(LocatedCmpop::new(range, Cmpop::Lt)); ops.push(LocatedCmpOp::new(range, CmpOp::Lt));
} }
_ => {} _ => {}
} }
@ -1513,13 +1507,13 @@ mod tests {
use anyhow::Result; use anyhow::Result;
use ruff_text_size::{TextLen, TextRange, TextSize}; use ruff_text_size::{TextLen, TextRange, TextSize};
use rustpython_ast::{Cmpop, Expr, Stmt}; use rustpython_ast::{CmpOp, Expr, Stmt};
use rustpython_parser::ast::Suite; use rustpython_parser::ast::Suite;
use rustpython_parser::Parse; use rustpython_parser::Parse;
use crate::helpers::{ use crate::helpers::{
elif_else_range, first_colon_range, has_trailing_content, locate_cmpops, elif_else_range, first_colon_range, has_trailing_content, locate_cmp_ops,
resolve_imported_module_path, LocatedCmpop, resolve_imported_module_path, LocatedCmpOp,
}; };
use crate::source_code::Locator; use crate::source_code::Locator;
@ -1642,15 +1636,15 @@ else:
} }
#[test] #[test]
fn extract_cmpop_location() -> Result<()> { fn extract_cmp_op_location() -> Result<()> {
let contents = "x == 1"; let contents = "x == 1";
let expr = Expr::parse(contents, "<filename>")?; let expr = Expr::parse(contents, "<filename>")?;
let locator = Locator::new(contents); let locator = Locator::new(contents);
assert_eq!( assert_eq!(
locate_cmpops(&expr, &locator), locate_cmp_ops(&expr, &locator),
vec![LocatedCmpop::new( vec![LocatedCmpOp::new(
TextSize::from(2)..TextSize::from(4), TextSize::from(2)..TextSize::from(4),
Cmpop::Eq CmpOp::Eq
)] )]
); );
@ -1658,10 +1652,10 @@ else:
let expr = Expr::parse(contents, "<filename>")?; let expr = Expr::parse(contents, "<filename>")?;
let locator = Locator::new(contents); let locator = Locator::new(contents);
assert_eq!( assert_eq!(
locate_cmpops(&expr, &locator), locate_cmp_ops(&expr, &locator),
vec![LocatedCmpop::new( vec![LocatedCmpOp::new(
TextSize::from(2)..TextSize::from(4), TextSize::from(2)..TextSize::from(4),
Cmpop::NotEq CmpOp::NotEq
)] )]
); );
@ -1669,10 +1663,10 @@ else:
let expr = Expr::parse(contents, "<filename>")?; let expr = Expr::parse(contents, "<filename>")?;
let locator = Locator::new(contents); let locator = Locator::new(contents);
assert_eq!( assert_eq!(
locate_cmpops(&expr, &locator), locate_cmp_ops(&expr, &locator),
vec![LocatedCmpop::new( vec![LocatedCmpOp::new(
TextSize::from(2)..TextSize::from(4), TextSize::from(2)..TextSize::from(4),
Cmpop::Is CmpOp::Is
)] )]
); );
@ -1680,10 +1674,10 @@ else:
let expr = Expr::parse(contents, "<filename>")?; let expr = Expr::parse(contents, "<filename>")?;
let locator = Locator::new(contents); let locator = Locator::new(contents);
assert_eq!( assert_eq!(
locate_cmpops(&expr, &locator), locate_cmp_ops(&expr, &locator),
vec![LocatedCmpop::new( vec![LocatedCmpOp::new(
TextSize::from(2)..TextSize::from(8), TextSize::from(2)..TextSize::from(8),
Cmpop::IsNot CmpOp::IsNot
)] )]
); );
@ -1691,10 +1685,10 @@ else:
let expr = Expr::parse(contents, "<filename>")?; let expr = Expr::parse(contents, "<filename>")?;
let locator = Locator::new(contents); let locator = Locator::new(contents);
assert_eq!( assert_eq!(
locate_cmpops(&expr, &locator), locate_cmp_ops(&expr, &locator),
vec![LocatedCmpop::new( vec![LocatedCmpOp::new(
TextSize::from(2)..TextSize::from(4), TextSize::from(2)..TextSize::from(4),
Cmpop::In CmpOp::In
)] )]
); );
@ -1702,10 +1696,10 @@ else:
let expr = Expr::parse(contents, "<filename>")?; let expr = Expr::parse(contents, "<filename>")?;
let locator = Locator::new(contents); let locator = Locator::new(contents);
assert_eq!( assert_eq!(
locate_cmpops(&expr, &locator), locate_cmp_ops(&expr, &locator),
vec![LocatedCmpop::new( vec![LocatedCmpOp::new(
TextSize::from(2)..TextSize::from(8), TextSize::from(2)..TextSize::from(8),
Cmpop::NotIn CmpOp::NotIn
)] )]
); );
@ -1713,10 +1707,10 @@ else:
let expr = Expr::parse(contents, "<filename>")?; let expr = Expr::parse(contents, "<filename>")?;
let locator = Locator::new(contents); let locator = Locator::new(contents);
assert_eq!( assert_eq!(
locate_cmpops(&expr, &locator), locate_cmp_ops(&expr, &locator),
vec![LocatedCmpop::new( vec![LocatedCmpOp::new(
TextSize::from(2)..TextSize::from(4), TextSize::from(2)..TextSize::from(4),
Cmpop::NotEq CmpOp::NotEq
)] )]
); );

View file

@ -20,8 +20,8 @@ use std::ops::{Add, Sub};
use std::str::Chars; use std::str::Chars;
use ruff_text_size::{TextLen, TextRange, TextSize}; use ruff_text_size::{TextLen, TextRange, TextSize};
use rustpython_ast::{Alias, Arg, Pattern}; use rustpython_ast::{Alias, Arg, ArgWithDefault, Pattern};
use rustpython_parser::ast::{self, Excepthandler, Ranged, Stmt}; use rustpython_parser::ast::{self, ExceptHandler, Ranged, Stmt};
use ruff_python_whitespace::is_python_whitespace; use ruff_python_whitespace::is_python_whitespace;
@ -94,7 +94,7 @@ impl Identifier for Arg {
/// ///
/// For example, return the range of `x` in: /// For example, return the range of `x` in:
/// ```python /// ```python
/// def f(x: int = 0): /// def f(x: int):
/// ... /// ...
/// ``` /// ```
fn identifier(&self, locator: &Locator) -> TextRange { fn identifier(&self, locator: &Locator) -> TextRange {
@ -104,6 +104,19 @@ impl Identifier for Arg {
} }
} }
impl Identifier for ArgWithDefault {
/// Return the [`TextRange`] for the identifier defining an [`ArgWithDefault`].
///
/// For example, return the range of `x` in:
/// ```python
/// def f(x: int = 0):
/// ...
/// ```
fn identifier(&self, locator: &Locator) -> TextRange {
self.def.identifier(locator)
}
}
impl Identifier for Alias { impl Identifier for Alias {
/// Return the [`TextRange`] for the identifier defining an [`Alias`]. /// Return the [`TextRange`] for the identifier defining an [`Alias`].
/// ///
@ -239,8 +252,8 @@ impl TryIdentifier for Pattern {
} }
} }
impl TryIdentifier for Excepthandler { impl TryIdentifier for ExceptHandler {
/// Return the [`TextRange`] of a named exception in an [`Excepthandler`]. /// Return the [`TextRange`] of a named exception in an [`ExceptHandler`].
/// ///
/// For example, return the range of `e` in: /// For example, return the range of `e` in:
/// ```python /// ```python
@ -250,7 +263,7 @@ impl TryIdentifier for Excepthandler {
/// ... /// ...
/// ``` /// ```
fn try_identifier(&self, locator: &Locator) -> Option<TextRange> { fn try_identifier(&self, locator: &Locator) -> Option<TextRange> {
let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, name, .. }) = let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, name, .. }) =
self; self;
if name.is_none() { if name.is_none() {
@ -284,11 +297,11 @@ pub fn names<'a>(stmt: &Stmt, locator: &'a Locator<'a>) -> impl Iterator<Item =
IdentifierTokenizer::new(locator.contents(), stmt.range()).skip(1) IdentifierTokenizer::new(locator.contents(), stmt.range()).skip(1)
} }
/// Return the [`TextRange`] of the `except` token in an [`Excepthandler`]. /// Return the [`TextRange`] of the `except` token in an [`ExceptHandler`].
pub fn except(handler: &Excepthandler, locator: &Locator) -> TextRange { pub fn except(handler: &ExceptHandler, locator: &Locator) -> TextRange {
IdentifierTokenizer::new(locator.contents(), handler.range()) IdentifierTokenizer::new(locator.contents(), handler.range())
.next() .next()
.expect("Failed to find `except` token in `Excepthandler`") .expect("Failed to find `except` token in `ExceptHandler`")
} }
/// Return the [`TextRange`] of the `else` token in a `For`, `AsyncFor`, or `While` statement. /// Return the [`TextRange`] of the `else` token in a `For`, `AsyncFor`, or `While` statement.

View file

@ -75,7 +75,7 @@ pub enum AnyNode {
ExprList(ExprList<TextRange>), ExprList(ExprList<TextRange>),
ExprTuple(ExprTuple<TextRange>), ExprTuple(ExprTuple<TextRange>),
ExprSlice(ExprSlice<TextRange>), ExprSlice(ExprSlice<TextRange>),
ExcepthandlerExceptHandler(ExcepthandlerExceptHandler<TextRange>), ExceptHandlerExceptHandler(ExceptHandlerExceptHandler<TextRange>),
PatternMatchValue(PatternMatchValue<TextRange>), PatternMatchValue(PatternMatchValue<TextRange>),
PatternMatchSingleton(PatternMatchSingleton<TextRange>), PatternMatchSingleton(PatternMatchSingleton<TextRange>),
PatternMatchSequence(PatternMatchSequence<TextRange>), PatternMatchSequence(PatternMatchSequence<TextRange>),
@ -88,9 +88,10 @@ pub enum AnyNode {
Comprehension(Comprehension<TextRange>), Comprehension(Comprehension<TextRange>),
Arguments(Arguments<TextRange>), Arguments(Arguments<TextRange>),
Arg(Arg<TextRange>), Arg(Arg<TextRange>),
ArgWithDefault(ArgWithDefault<TextRange>),
Keyword(Keyword<TextRange>), Keyword(Keyword<TextRange>),
Alias(Alias<TextRange>), Alias(Alias<TextRange>),
Withitem(Withitem<TextRange>), WithItem(WithItem<TextRange>),
MatchCase(MatchCase<TextRange>), MatchCase(MatchCase<TextRange>),
Decorator(Decorator<TextRange>), Decorator(Decorator<TextRange>),
} }
@ -157,7 +158,7 @@ impl AnyNode {
| AnyNode::ExprList(_) | AnyNode::ExprList(_)
| AnyNode::ExprTuple(_) | AnyNode::ExprTuple(_)
| AnyNode::ExprSlice(_) | AnyNode::ExprSlice(_)
| AnyNode::ExcepthandlerExceptHandler(_) | AnyNode::ExceptHandlerExceptHandler(_)
| AnyNode::PatternMatchValue(_) | AnyNode::PatternMatchValue(_)
| AnyNode::PatternMatchSingleton(_) | AnyNode::PatternMatchSingleton(_)
| AnyNode::PatternMatchSequence(_) | AnyNode::PatternMatchSequence(_)
@ -170,9 +171,10 @@ impl AnyNode {
| AnyNode::Comprehension(_) | AnyNode::Comprehension(_)
| AnyNode::Arguments(_) | AnyNode::Arguments(_)
| AnyNode::Arg(_) | AnyNode::Arg(_)
| AnyNode::ArgWithDefault(_)
| AnyNode::Keyword(_) | AnyNode::Keyword(_)
| AnyNode::Alias(_) | AnyNode::Alias(_)
| AnyNode::Withitem(_) | AnyNode::WithItem(_)
| AnyNode::MatchCase(_) | AnyNode::MatchCase(_)
| AnyNode::Decorator(_) => None, | AnyNode::Decorator(_) => None,
} }
@ -239,7 +241,7 @@ impl AnyNode {
| AnyNode::StmtPass(_) | AnyNode::StmtPass(_)
| AnyNode::StmtBreak(_) | AnyNode::StmtBreak(_)
| AnyNode::StmtContinue(_) | AnyNode::StmtContinue(_)
| AnyNode::ExcepthandlerExceptHandler(_) | AnyNode::ExceptHandlerExceptHandler(_)
| AnyNode::PatternMatchValue(_) | AnyNode::PatternMatchValue(_)
| AnyNode::PatternMatchSingleton(_) | AnyNode::PatternMatchSingleton(_)
| AnyNode::PatternMatchSequence(_) | AnyNode::PatternMatchSequence(_)
@ -252,9 +254,10 @@ impl AnyNode {
| AnyNode::Comprehension(_) | AnyNode::Comprehension(_)
| AnyNode::Arguments(_) | AnyNode::Arguments(_)
| AnyNode::Arg(_) | AnyNode::Arg(_)
| AnyNode::ArgWithDefault(_)
| AnyNode::Keyword(_) | AnyNode::Keyword(_)
| AnyNode::Alias(_) | AnyNode::Alias(_)
| AnyNode::Withitem(_) | AnyNode::WithItem(_)
| AnyNode::MatchCase(_) | AnyNode::MatchCase(_)
| AnyNode::Decorator(_) => None, | AnyNode::Decorator(_) => None,
} }
@ -321,7 +324,7 @@ impl AnyNode {
| AnyNode::ExprList(_) | AnyNode::ExprList(_)
| AnyNode::ExprTuple(_) | AnyNode::ExprTuple(_)
| AnyNode::ExprSlice(_) | AnyNode::ExprSlice(_)
| AnyNode::ExcepthandlerExceptHandler(_) | AnyNode::ExceptHandlerExceptHandler(_)
| AnyNode::PatternMatchValue(_) | AnyNode::PatternMatchValue(_)
| AnyNode::PatternMatchSingleton(_) | AnyNode::PatternMatchSingleton(_)
| AnyNode::PatternMatchSequence(_) | AnyNode::PatternMatchSequence(_)
@ -334,9 +337,10 @@ impl AnyNode {
| AnyNode::Comprehension(_) | AnyNode::Comprehension(_)
| AnyNode::Arguments(_) | AnyNode::Arguments(_)
| AnyNode::Arg(_) | AnyNode::Arg(_)
| AnyNode::ArgWithDefault(_)
| AnyNode::Keyword(_) | AnyNode::Keyword(_)
| AnyNode::Alias(_) | AnyNode::Alias(_)
| AnyNode::Withitem(_) | AnyNode::WithItem(_)
| AnyNode::MatchCase(_) | AnyNode::MatchCase(_)
| AnyNode::Decorator(_) => None, | AnyNode::Decorator(_) => None,
} }
@ -411,22 +415,23 @@ impl AnyNode {
| AnyNode::ExprList(_) | AnyNode::ExprList(_)
| AnyNode::ExprTuple(_) | AnyNode::ExprTuple(_)
| AnyNode::ExprSlice(_) | AnyNode::ExprSlice(_)
| AnyNode::ExcepthandlerExceptHandler(_) | AnyNode::ExceptHandlerExceptHandler(_)
| AnyNode::TypeIgnoreTypeIgnore(_) | AnyNode::TypeIgnoreTypeIgnore(_)
| AnyNode::Comprehension(_) | AnyNode::Comprehension(_)
| AnyNode::Arguments(_) | AnyNode::Arguments(_)
| AnyNode::Arg(_) | AnyNode::Arg(_)
| AnyNode::ArgWithDefault(_)
| AnyNode::Keyword(_) | AnyNode::Keyword(_)
| AnyNode::Alias(_) | AnyNode::Alias(_)
| AnyNode::Withitem(_) | AnyNode::WithItem(_)
| AnyNode::MatchCase(_) | AnyNode::MatchCase(_)
| AnyNode::Decorator(_) => None, | AnyNode::Decorator(_) => None,
} }
} }
pub fn except_handler(self) -> Option<Excepthandler> { pub fn except_handler(self) -> Option<ExceptHandler> {
match self { match self {
AnyNode::ExcepthandlerExceptHandler(node) => Some(Excepthandler::ExceptHandler(node)), AnyNode::ExceptHandlerExceptHandler(node) => Some(ExceptHandler::ExceptHandler(node)),
AnyNode::ModModule(_) AnyNode::ModModule(_)
| AnyNode::ModInteractive(_) | AnyNode::ModInteractive(_)
@ -498,9 +503,10 @@ impl AnyNode {
| AnyNode::Comprehension(_) | AnyNode::Comprehension(_)
| AnyNode::Arguments(_) | AnyNode::Arguments(_)
| AnyNode::Arg(_) | AnyNode::Arg(_)
| AnyNode::ArgWithDefault(_)
| AnyNode::Keyword(_) | AnyNode::Keyword(_)
| AnyNode::Alias(_) | AnyNode::Alias(_)
| AnyNode::Withitem(_) | AnyNode::WithItem(_)
| AnyNode::MatchCase(_) | AnyNode::MatchCase(_)
| AnyNode::Decorator(_) => None, | AnyNode::Decorator(_) => None,
} }
@ -576,13 +582,14 @@ impl AnyNode {
| AnyNode::PatternMatchStar(_) | AnyNode::PatternMatchStar(_)
| AnyNode::PatternMatchAs(_) | AnyNode::PatternMatchAs(_)
| AnyNode::PatternMatchOr(_) | AnyNode::PatternMatchOr(_)
| AnyNode::ExcepthandlerExceptHandler(_) | AnyNode::ExceptHandlerExceptHandler(_)
| AnyNode::Comprehension(_) | AnyNode::Comprehension(_)
| AnyNode::Arguments(_) | AnyNode::Arguments(_)
| AnyNode::Arg(_) | AnyNode::Arg(_)
| AnyNode::ArgWithDefault(_)
| AnyNode::Keyword(_) | AnyNode::Keyword(_)
| AnyNode::Alias(_) | AnyNode::Alias(_)
| AnyNode::Withitem(_) | AnyNode::WithItem(_)
| AnyNode::MatchCase(_) | AnyNode::MatchCase(_)
| AnyNode::Decorator(_) => None, | AnyNode::Decorator(_) => None,
} }
@ -672,7 +679,7 @@ impl AnyNode {
Self::ExprList(node) => AnyNodeRef::ExprList(node), Self::ExprList(node) => AnyNodeRef::ExprList(node),
Self::ExprTuple(node) => AnyNodeRef::ExprTuple(node), Self::ExprTuple(node) => AnyNodeRef::ExprTuple(node),
Self::ExprSlice(node) => AnyNodeRef::ExprSlice(node), Self::ExprSlice(node) => AnyNodeRef::ExprSlice(node),
Self::ExcepthandlerExceptHandler(node) => AnyNodeRef::ExcepthandlerExceptHandler(node), Self::ExceptHandlerExceptHandler(node) => AnyNodeRef::ExceptHandlerExceptHandler(node),
Self::PatternMatchValue(node) => AnyNodeRef::PatternMatchValue(node), Self::PatternMatchValue(node) => AnyNodeRef::PatternMatchValue(node),
Self::PatternMatchSingleton(node) => AnyNodeRef::PatternMatchSingleton(node), Self::PatternMatchSingleton(node) => AnyNodeRef::PatternMatchSingleton(node),
Self::PatternMatchSequence(node) => AnyNodeRef::PatternMatchSequence(node), Self::PatternMatchSequence(node) => AnyNodeRef::PatternMatchSequence(node),
@ -685,9 +692,10 @@ impl AnyNode {
Self::Comprehension(node) => AnyNodeRef::Comprehension(node), Self::Comprehension(node) => AnyNodeRef::Comprehension(node),
Self::Arguments(node) => AnyNodeRef::Arguments(node), Self::Arguments(node) => AnyNodeRef::Arguments(node),
Self::Arg(node) => AnyNodeRef::Arg(node), Self::Arg(node) => AnyNodeRef::Arg(node),
Self::ArgWithDefault(node) => AnyNodeRef::ArgWithDefault(node),
Self::Keyword(node) => AnyNodeRef::Keyword(node), Self::Keyword(node) => AnyNodeRef::Keyword(node),
Self::Alias(node) => AnyNodeRef::Alias(node), Self::Alias(node) => AnyNodeRef::Alias(node),
Self::Withitem(node) => AnyNodeRef::Withitem(node), Self::WithItem(node) => AnyNodeRef::WithItem(node),
Self::MatchCase(node) => AnyNodeRef::MatchCase(node), Self::MatchCase(node) => AnyNodeRef::MatchCase(node),
Self::Decorator(node) => AnyNodeRef::Decorator(node), Self::Decorator(node) => AnyNodeRef::Decorator(node),
} }
@ -2323,12 +2331,12 @@ impl AstNode for ExprSlice<TextRange> {
AnyNode::from(self) AnyNode::from(self)
} }
} }
impl AstNode for ExcepthandlerExceptHandler<TextRange> { impl AstNode for ExceptHandlerExceptHandler<TextRange> {
fn cast(kind: AnyNode) -> Option<Self> fn cast(kind: AnyNode) -> Option<Self>
where where
Self: Sized, Self: Sized,
{ {
if let AnyNode::ExcepthandlerExceptHandler(node) = kind { if let AnyNode::ExceptHandlerExceptHandler(node) = kind {
Some(node) Some(node)
} else { } else {
None None
@ -2336,7 +2344,7 @@ impl AstNode for ExcepthandlerExceptHandler<TextRange> {
} }
fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { fn cast_ref(kind: AnyNodeRef) -> Option<&Self> {
if let AnyNodeRef::ExcepthandlerExceptHandler(node) = kind { if let AnyNodeRef::ExceptHandlerExceptHandler(node) = kind {
Some(node) Some(node)
} else { } else {
None None
@ -2688,6 +2696,34 @@ impl AstNode for Arg<TextRange> {
AnyNode::from(self) AnyNode::from(self)
} }
} }
impl AstNode for ArgWithDefault<TextRange> {
fn cast(kind: AnyNode) -> Option<Self>
where
Self: Sized,
{
if let AnyNode::ArgWithDefault(node) = kind {
Some(node)
} else {
None
}
}
fn cast_ref(kind: AnyNodeRef) -> Option<&Self> {
if let AnyNodeRef::ArgWithDefault(node) = kind {
Some(node)
} else {
None
}
}
fn as_any_node_ref(&self) -> AnyNodeRef {
AnyNodeRef::from(self)
}
fn into_any_node(self) -> AnyNode {
AnyNode::from(self)
}
}
impl AstNode for Keyword<TextRange> { impl AstNode for Keyword<TextRange> {
fn cast(kind: AnyNode) -> Option<Self> fn cast(kind: AnyNode) -> Option<Self>
where where
@ -2744,12 +2780,12 @@ impl AstNode for Alias<TextRange> {
AnyNode::from(self) AnyNode::from(self)
} }
} }
impl AstNode for Withitem<TextRange> { impl AstNode for WithItem<TextRange> {
fn cast(kind: AnyNode) -> Option<Self> fn cast(kind: AnyNode) -> Option<Self>
where where
Self: Sized, Self: Sized,
{ {
if let AnyNode::Withitem(node) = kind { if let AnyNode::WithItem(node) = kind {
Some(node) Some(node)
} else { } else {
None None
@ -2757,7 +2793,7 @@ impl AstNode for Withitem<TextRange> {
} }
fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { fn cast_ref(kind: AnyNodeRef) -> Option<&Self> {
if let AnyNodeRef::Withitem(node) = kind { if let AnyNodeRef::WithItem(node) = kind {
Some(node) Some(node)
} else { } else {
None None
@ -2924,10 +2960,10 @@ impl From<Pattern> for AnyNode {
} }
} }
impl From<Excepthandler> for AnyNode { impl From<ExceptHandler> for AnyNode {
fn from(handler: Excepthandler) -> Self { fn from(handler: ExceptHandler) -> Self {
match handler { match handler {
Excepthandler::ExceptHandler(handler) => AnyNode::ExcepthandlerExceptHandler(handler), ExceptHandler::ExceptHandler(handler) => AnyNode::ExceptHandlerExceptHandler(handler),
} }
} }
} }
@ -3288,9 +3324,9 @@ impl From<ExprSlice> for AnyNode {
} }
} }
impl From<ExcepthandlerExceptHandler> for AnyNode { impl From<ExceptHandlerExceptHandler> for AnyNode {
fn from(node: ExcepthandlerExceptHandler) -> Self { fn from(node: ExceptHandlerExceptHandler) -> Self {
AnyNode::ExcepthandlerExceptHandler(node) AnyNode::ExceptHandlerExceptHandler(node)
} }
} }
@ -3363,6 +3399,11 @@ impl From<Arg> for AnyNode {
AnyNode::Arg(node) AnyNode::Arg(node)
} }
} }
impl From<ArgWithDefault> for AnyNode {
fn from(node: ArgWithDefault) -> Self {
AnyNode::ArgWithDefault(node)
}
}
impl From<Keyword> for AnyNode { impl From<Keyword> for AnyNode {
fn from(node: Keyword) -> Self { fn from(node: Keyword) -> Self {
AnyNode::Keyword(node) AnyNode::Keyword(node)
@ -3373,9 +3414,9 @@ impl From<Alias> for AnyNode {
AnyNode::Alias(node) AnyNode::Alias(node)
} }
} }
impl From<Withitem> for AnyNode { impl From<WithItem> for AnyNode {
fn from(node: Withitem) -> Self { fn from(node: WithItem) -> Self {
AnyNode::Withitem(node) AnyNode::WithItem(node)
} }
} }
impl From<MatchCase> for AnyNode { impl From<MatchCase> for AnyNode {
@ -3450,7 +3491,7 @@ impl Ranged for AnyNode {
AnyNode::ExprList(node) => node.range(), AnyNode::ExprList(node) => node.range(),
AnyNode::ExprTuple(node) => node.range(), AnyNode::ExprTuple(node) => node.range(),
AnyNode::ExprSlice(node) => node.range(), AnyNode::ExprSlice(node) => node.range(),
AnyNode::ExcepthandlerExceptHandler(node) => node.range(), AnyNode::ExceptHandlerExceptHandler(node) => node.range(),
AnyNode::PatternMatchValue(node) => node.range(), AnyNode::PatternMatchValue(node) => node.range(),
AnyNode::PatternMatchSingleton(node) => node.range(), AnyNode::PatternMatchSingleton(node) => node.range(),
AnyNode::PatternMatchSequence(node) => node.range(), AnyNode::PatternMatchSequence(node) => node.range(),
@ -3463,9 +3504,10 @@ impl Ranged for AnyNode {
AnyNode::Comprehension(node) => node.range(), AnyNode::Comprehension(node) => node.range(),
AnyNode::Arguments(node) => node.range(), AnyNode::Arguments(node) => node.range(),
AnyNode::Arg(node) => node.range(), AnyNode::Arg(node) => node.range(),
AnyNode::ArgWithDefault(node) => node.range(),
AnyNode::Keyword(node) => node.range(), AnyNode::Keyword(node) => node.range(),
AnyNode::Alias(node) => node.range(), AnyNode::Alias(node) => node.range(),
AnyNode::Withitem(node) => node.range(), AnyNode::WithItem(node) => node.range(),
AnyNode::MatchCase(node) => node.range(), AnyNode::MatchCase(node) => node.range(),
AnyNode::Decorator(node) => node.range(), AnyNode::Decorator(node) => node.range(),
} }
@ -3532,7 +3574,7 @@ pub enum AnyNodeRef<'a> {
ExprList(&'a ExprList<TextRange>), ExprList(&'a ExprList<TextRange>),
ExprTuple(&'a ExprTuple<TextRange>), ExprTuple(&'a ExprTuple<TextRange>),
ExprSlice(&'a ExprSlice<TextRange>), ExprSlice(&'a ExprSlice<TextRange>),
ExcepthandlerExceptHandler(&'a ExcepthandlerExceptHandler<TextRange>), ExceptHandlerExceptHandler(&'a ExceptHandlerExceptHandler<TextRange>),
PatternMatchValue(&'a PatternMatchValue<TextRange>), PatternMatchValue(&'a PatternMatchValue<TextRange>),
PatternMatchSingleton(&'a PatternMatchSingleton<TextRange>), PatternMatchSingleton(&'a PatternMatchSingleton<TextRange>),
PatternMatchSequence(&'a PatternMatchSequence<TextRange>), PatternMatchSequence(&'a PatternMatchSequence<TextRange>),
@ -3545,9 +3587,10 @@ pub enum AnyNodeRef<'a> {
Comprehension(&'a Comprehension<TextRange>), Comprehension(&'a Comprehension<TextRange>),
Arguments(&'a Arguments<TextRange>), Arguments(&'a Arguments<TextRange>),
Arg(&'a Arg<TextRange>), Arg(&'a Arg<TextRange>),
ArgWithDefault(&'a ArgWithDefault<TextRange>),
Keyword(&'a Keyword<TextRange>), Keyword(&'a Keyword<TextRange>),
Alias(&'a Alias<TextRange>), Alias(&'a Alias<TextRange>),
Withitem(&'a Withitem<TextRange>), WithItem(&'a WithItem<TextRange>),
MatchCase(&'a MatchCase<TextRange>), MatchCase(&'a MatchCase<TextRange>),
Decorator(&'a Decorator<TextRange>), Decorator(&'a Decorator<TextRange>),
} }
@ -3613,7 +3656,7 @@ impl AnyNodeRef<'_> {
AnyNodeRef::ExprList(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprList(node) => NonNull::from(*node).cast(),
AnyNodeRef::ExprTuple(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprTuple(node) => NonNull::from(*node).cast(),
AnyNodeRef::ExprSlice(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprSlice(node) => NonNull::from(*node).cast(),
AnyNodeRef::ExcepthandlerExceptHandler(node) => NonNull::from(*node).cast(), AnyNodeRef::ExceptHandlerExceptHandler(node) => NonNull::from(*node).cast(),
AnyNodeRef::PatternMatchValue(node) => NonNull::from(*node).cast(), AnyNodeRef::PatternMatchValue(node) => NonNull::from(*node).cast(),
AnyNodeRef::PatternMatchSingleton(node) => NonNull::from(*node).cast(), AnyNodeRef::PatternMatchSingleton(node) => NonNull::from(*node).cast(),
AnyNodeRef::PatternMatchSequence(node) => NonNull::from(*node).cast(), AnyNodeRef::PatternMatchSequence(node) => NonNull::from(*node).cast(),
@ -3626,9 +3669,10 @@ impl AnyNodeRef<'_> {
AnyNodeRef::Comprehension(node) => NonNull::from(*node).cast(), AnyNodeRef::Comprehension(node) => NonNull::from(*node).cast(),
AnyNodeRef::Arguments(node) => NonNull::from(*node).cast(), AnyNodeRef::Arguments(node) => NonNull::from(*node).cast(),
AnyNodeRef::Arg(node) => NonNull::from(*node).cast(), AnyNodeRef::Arg(node) => NonNull::from(*node).cast(),
AnyNodeRef::ArgWithDefault(node) => NonNull::from(*node).cast(),
AnyNodeRef::Keyword(node) => NonNull::from(*node).cast(), AnyNodeRef::Keyword(node) => NonNull::from(*node).cast(),
AnyNodeRef::Alias(node) => NonNull::from(*node).cast(), AnyNodeRef::Alias(node) => NonNull::from(*node).cast(),
AnyNodeRef::Withitem(node) => NonNull::from(*node).cast(), AnyNodeRef::WithItem(node) => NonNull::from(*node).cast(),
AnyNodeRef::MatchCase(node) => NonNull::from(*node).cast(), AnyNodeRef::MatchCase(node) => NonNull::from(*node).cast(),
AnyNodeRef::Decorator(node) => NonNull::from(*node).cast(), AnyNodeRef::Decorator(node) => NonNull::from(*node).cast(),
} }
@ -3700,7 +3744,7 @@ impl AnyNodeRef<'_> {
AnyNodeRef::ExprList(_) => NodeKind::ExprList, AnyNodeRef::ExprList(_) => NodeKind::ExprList,
AnyNodeRef::ExprTuple(_) => NodeKind::ExprTuple, AnyNodeRef::ExprTuple(_) => NodeKind::ExprTuple,
AnyNodeRef::ExprSlice(_) => NodeKind::ExprSlice, AnyNodeRef::ExprSlice(_) => NodeKind::ExprSlice,
AnyNodeRef::ExcepthandlerExceptHandler(_) => NodeKind::ExcepthandlerExceptHandler, AnyNodeRef::ExceptHandlerExceptHandler(_) => NodeKind::ExceptHandlerExceptHandler,
AnyNodeRef::PatternMatchValue(_) => NodeKind::PatternMatchValue, AnyNodeRef::PatternMatchValue(_) => NodeKind::PatternMatchValue,
AnyNodeRef::PatternMatchSingleton(_) => NodeKind::PatternMatchSingleton, AnyNodeRef::PatternMatchSingleton(_) => NodeKind::PatternMatchSingleton,
AnyNodeRef::PatternMatchSequence(_) => NodeKind::PatternMatchSequence, AnyNodeRef::PatternMatchSequence(_) => NodeKind::PatternMatchSequence,
@ -3713,9 +3757,10 @@ impl AnyNodeRef<'_> {
AnyNodeRef::Comprehension(_) => NodeKind::Comprehension, AnyNodeRef::Comprehension(_) => NodeKind::Comprehension,
AnyNodeRef::Arguments(_) => NodeKind::Arguments, AnyNodeRef::Arguments(_) => NodeKind::Arguments,
AnyNodeRef::Arg(_) => NodeKind::Arg, AnyNodeRef::Arg(_) => NodeKind::Arg,
AnyNodeRef::ArgWithDefault(_) => NodeKind::ArgWithDefault,
AnyNodeRef::Keyword(_) => NodeKind::Keyword, AnyNodeRef::Keyword(_) => NodeKind::Keyword,
AnyNodeRef::Alias(_) => NodeKind::Alias, AnyNodeRef::Alias(_) => NodeKind::Alias,
AnyNodeRef::Withitem(_) => NodeKind::Withitem, AnyNodeRef::WithItem(_) => NodeKind::WithItem,
AnyNodeRef::MatchCase(_) => NodeKind::MatchCase, AnyNodeRef::MatchCase(_) => NodeKind::MatchCase,
AnyNodeRef::Decorator(_) => NodeKind::Decorator, AnyNodeRef::Decorator(_) => NodeKind::Decorator,
} }
@ -3782,7 +3827,7 @@ impl AnyNodeRef<'_> {
| AnyNodeRef::ExprList(_) | AnyNodeRef::ExprList(_)
| AnyNodeRef::ExprTuple(_) | AnyNodeRef::ExprTuple(_)
| AnyNodeRef::ExprSlice(_) | AnyNodeRef::ExprSlice(_)
| AnyNodeRef::ExcepthandlerExceptHandler(_) | AnyNodeRef::ExceptHandlerExceptHandler(_)
| AnyNodeRef::PatternMatchValue(_) | AnyNodeRef::PatternMatchValue(_)
| AnyNodeRef::PatternMatchSingleton(_) | AnyNodeRef::PatternMatchSingleton(_)
| AnyNodeRef::PatternMatchSequence(_) | AnyNodeRef::PatternMatchSequence(_)
@ -3795,9 +3840,10 @@ impl AnyNodeRef<'_> {
| AnyNodeRef::Comprehension(_) | AnyNodeRef::Comprehension(_)
| AnyNodeRef::Arguments(_) | AnyNodeRef::Arguments(_)
| AnyNodeRef::Arg(_) | AnyNodeRef::Arg(_)
| AnyNodeRef::ArgWithDefault(_)
| AnyNodeRef::Keyword(_) | AnyNodeRef::Keyword(_)
| AnyNodeRef::Alias(_) | AnyNodeRef::Alias(_)
| AnyNodeRef::Withitem(_) | AnyNodeRef::WithItem(_)
| AnyNodeRef::MatchCase(_) | AnyNodeRef::MatchCase(_)
| AnyNodeRef::Decorator(_) => false, | AnyNodeRef::Decorator(_) => false,
} }
@ -3864,7 +3910,7 @@ impl AnyNodeRef<'_> {
| AnyNodeRef::StmtPass(_) | AnyNodeRef::StmtPass(_)
| AnyNodeRef::StmtBreak(_) | AnyNodeRef::StmtBreak(_)
| AnyNodeRef::StmtContinue(_) | AnyNodeRef::StmtContinue(_)
| AnyNodeRef::ExcepthandlerExceptHandler(_) | AnyNodeRef::ExceptHandlerExceptHandler(_)
| AnyNodeRef::PatternMatchValue(_) | AnyNodeRef::PatternMatchValue(_)
| AnyNodeRef::PatternMatchSingleton(_) | AnyNodeRef::PatternMatchSingleton(_)
| AnyNodeRef::PatternMatchSequence(_) | AnyNodeRef::PatternMatchSequence(_)
@ -3877,9 +3923,10 @@ impl AnyNodeRef<'_> {
| AnyNodeRef::Comprehension(_) | AnyNodeRef::Comprehension(_)
| AnyNodeRef::Arguments(_) | AnyNodeRef::Arguments(_)
| AnyNodeRef::Arg(_) | AnyNodeRef::Arg(_)
| AnyNodeRef::ArgWithDefault(_)
| AnyNodeRef::Keyword(_) | AnyNodeRef::Keyword(_)
| AnyNodeRef::Alias(_) | AnyNodeRef::Alias(_)
| AnyNodeRef::Withitem(_) | AnyNodeRef::WithItem(_)
| AnyNodeRef::MatchCase(_) | AnyNodeRef::MatchCase(_)
| AnyNodeRef::Decorator(_) => false, | AnyNodeRef::Decorator(_) => false,
} }
@ -3946,7 +3993,7 @@ impl AnyNodeRef<'_> {
| AnyNodeRef::ExprList(_) | AnyNodeRef::ExprList(_)
| AnyNodeRef::ExprTuple(_) | AnyNodeRef::ExprTuple(_)
| AnyNodeRef::ExprSlice(_) | AnyNodeRef::ExprSlice(_)
| AnyNodeRef::ExcepthandlerExceptHandler(_) | AnyNodeRef::ExceptHandlerExceptHandler(_)
| AnyNodeRef::PatternMatchValue(_) | AnyNodeRef::PatternMatchValue(_)
| AnyNodeRef::PatternMatchSingleton(_) | AnyNodeRef::PatternMatchSingleton(_)
| AnyNodeRef::PatternMatchSequence(_) | AnyNodeRef::PatternMatchSequence(_)
@ -3959,9 +4006,10 @@ impl AnyNodeRef<'_> {
| AnyNodeRef::Comprehension(_) | AnyNodeRef::Comprehension(_)
| AnyNodeRef::Arguments(_) | AnyNodeRef::Arguments(_)
| AnyNodeRef::Arg(_) | AnyNodeRef::Arg(_)
| AnyNodeRef::ArgWithDefault(_)
| AnyNodeRef::Keyword(_) | AnyNodeRef::Keyword(_)
| AnyNodeRef::Alias(_) | AnyNodeRef::Alias(_)
| AnyNodeRef::Withitem(_) | AnyNodeRef::WithItem(_)
| AnyNodeRef::MatchCase(_) | AnyNodeRef::MatchCase(_)
| AnyNodeRef::Decorator(_) => false, | AnyNodeRef::Decorator(_) => false,
} }
@ -4036,14 +4084,15 @@ impl AnyNodeRef<'_> {
| AnyNodeRef::ExprList(_) | AnyNodeRef::ExprList(_)
| AnyNodeRef::ExprTuple(_) | AnyNodeRef::ExprTuple(_)
| AnyNodeRef::ExprSlice(_) | AnyNodeRef::ExprSlice(_)
| AnyNodeRef::ExcepthandlerExceptHandler(_) | AnyNodeRef::ExceptHandlerExceptHandler(_)
| AnyNodeRef::TypeIgnoreTypeIgnore(_) | AnyNodeRef::TypeIgnoreTypeIgnore(_)
| AnyNodeRef::Comprehension(_) | AnyNodeRef::Comprehension(_)
| AnyNodeRef::Arguments(_) | AnyNodeRef::Arguments(_)
| AnyNodeRef::Arg(_) | AnyNodeRef::Arg(_)
| AnyNodeRef::ArgWithDefault(_)
| AnyNodeRef::Keyword(_) | AnyNodeRef::Keyword(_)
| AnyNodeRef::Alias(_) | AnyNodeRef::Alias(_)
| AnyNodeRef::Withitem(_) | AnyNodeRef::WithItem(_)
| AnyNodeRef::MatchCase(_) | AnyNodeRef::MatchCase(_)
| AnyNodeRef::Decorator(_) => false, | AnyNodeRef::Decorator(_) => false,
} }
@ -4051,7 +4100,7 @@ impl AnyNodeRef<'_> {
pub const fn is_except_handler(self) -> bool { pub const fn is_except_handler(self) -> bool {
match self { match self {
AnyNodeRef::ExcepthandlerExceptHandler(_) => true, AnyNodeRef::ExceptHandlerExceptHandler(_) => true,
AnyNodeRef::ModModule(_) AnyNodeRef::ModModule(_)
| AnyNodeRef::ModInteractive(_) | AnyNodeRef::ModInteractive(_)
@ -4123,9 +4172,10 @@ impl AnyNodeRef<'_> {
| AnyNodeRef::Comprehension(_) | AnyNodeRef::Comprehension(_)
| AnyNodeRef::Arguments(_) | AnyNodeRef::Arguments(_)
| AnyNodeRef::Arg(_) | AnyNodeRef::Arg(_)
| AnyNodeRef::ArgWithDefault(_)
| AnyNodeRef::Keyword(_) | AnyNodeRef::Keyword(_)
| AnyNodeRef::Alias(_) | AnyNodeRef::Alias(_)
| AnyNodeRef::Withitem(_) | AnyNodeRef::WithItem(_)
| AnyNodeRef::MatchCase(_) | AnyNodeRef::MatchCase(_)
| AnyNodeRef::Decorator(_) => false, | AnyNodeRef::Decorator(_) => false,
} }
@ -4201,13 +4251,14 @@ impl AnyNodeRef<'_> {
| AnyNodeRef::PatternMatchStar(_) | AnyNodeRef::PatternMatchStar(_)
| AnyNodeRef::PatternMatchAs(_) | AnyNodeRef::PatternMatchAs(_)
| AnyNodeRef::PatternMatchOr(_) | AnyNodeRef::PatternMatchOr(_)
| AnyNodeRef::ExcepthandlerExceptHandler(_) | AnyNodeRef::ExceptHandlerExceptHandler(_)
| AnyNodeRef::Comprehension(_) | AnyNodeRef::Comprehension(_)
| AnyNodeRef::Arguments(_) | AnyNodeRef::Arguments(_)
| AnyNodeRef::Arg(_) | AnyNodeRef::Arg(_)
| AnyNodeRef::ArgWithDefault(_)
| AnyNodeRef::Keyword(_) | AnyNodeRef::Keyword(_)
| AnyNodeRef::Alias(_) | AnyNodeRef::Alias(_)
| AnyNodeRef::Withitem(_) | AnyNodeRef::WithItem(_)
| AnyNodeRef::MatchCase(_) | AnyNodeRef::MatchCase(_)
| AnyNodeRef::Decorator(_) => false, | AnyNodeRef::Decorator(_) => false,
} }
@ -4578,9 +4629,9 @@ impl<'a> From<&'a ExprSlice> for AnyNodeRef<'a> {
} }
} }
impl<'a> From<&'a ExcepthandlerExceptHandler> for AnyNodeRef<'a> { impl<'a> From<&'a ExceptHandlerExceptHandler> for AnyNodeRef<'a> {
fn from(node: &'a ExcepthandlerExceptHandler) -> Self { fn from(node: &'a ExceptHandlerExceptHandler) -> Self {
AnyNodeRef::ExcepthandlerExceptHandler(node) AnyNodeRef::ExceptHandlerExceptHandler(node)
} }
} }
@ -4738,11 +4789,11 @@ impl<'a> From<&'a Pattern> for AnyNodeRef<'a> {
} }
} }
impl<'a> From<&'a Excepthandler> for AnyNodeRef<'a> { impl<'a> From<&'a ExceptHandler> for AnyNodeRef<'a> {
fn from(handler: &'a Excepthandler) -> Self { fn from(handler: &'a ExceptHandler) -> Self {
match handler { match handler {
Excepthandler::ExceptHandler(handler) => { ExceptHandler::ExceptHandler(handler) => {
AnyNodeRef::ExcepthandlerExceptHandler(handler) AnyNodeRef::ExceptHandlerExceptHandler(handler)
} }
} }
} }
@ -4771,6 +4822,11 @@ impl<'a> From<&'a Arg> for AnyNodeRef<'a> {
AnyNodeRef::Arg(node) AnyNodeRef::Arg(node)
} }
} }
impl<'a> From<&'a ArgWithDefault> for AnyNodeRef<'a> {
fn from(node: &'a ArgWithDefault) -> Self {
AnyNodeRef::ArgWithDefault(node)
}
}
impl<'a> From<&'a Keyword> for AnyNodeRef<'a> { impl<'a> From<&'a Keyword> for AnyNodeRef<'a> {
fn from(node: &'a Keyword) -> Self { fn from(node: &'a Keyword) -> Self {
AnyNodeRef::Keyword(node) AnyNodeRef::Keyword(node)
@ -4781,9 +4837,9 @@ impl<'a> From<&'a Alias> for AnyNodeRef<'a> {
AnyNodeRef::Alias(node) AnyNodeRef::Alias(node)
} }
} }
impl<'a> From<&'a Withitem> for AnyNodeRef<'a> { impl<'a> From<&'a WithItem> for AnyNodeRef<'a> {
fn from(node: &'a Withitem) -> Self { fn from(node: &'a WithItem) -> Self {
AnyNodeRef::Withitem(node) AnyNodeRef::WithItem(node)
} }
} }
impl<'a> From<&'a MatchCase> for AnyNodeRef<'a> { impl<'a> From<&'a MatchCase> for AnyNodeRef<'a> {
@ -4853,7 +4909,7 @@ impl Ranged for AnyNodeRef<'_> {
AnyNodeRef::ExprList(node) => node.range(), AnyNodeRef::ExprList(node) => node.range(),
AnyNodeRef::ExprTuple(node) => node.range(), AnyNodeRef::ExprTuple(node) => node.range(),
AnyNodeRef::ExprSlice(node) => node.range(), AnyNodeRef::ExprSlice(node) => node.range(),
AnyNodeRef::ExcepthandlerExceptHandler(node) => node.range(), AnyNodeRef::ExceptHandlerExceptHandler(node) => node.range(),
AnyNodeRef::PatternMatchValue(node) => node.range(), AnyNodeRef::PatternMatchValue(node) => node.range(),
AnyNodeRef::PatternMatchSingleton(node) => node.range(), AnyNodeRef::PatternMatchSingleton(node) => node.range(),
AnyNodeRef::PatternMatchSequence(node) => node.range(), AnyNodeRef::PatternMatchSequence(node) => node.range(),
@ -4866,9 +4922,10 @@ impl Ranged for AnyNodeRef<'_> {
AnyNodeRef::Comprehension(node) => node.range(), AnyNodeRef::Comprehension(node) => node.range(),
AnyNodeRef::Arguments(node) => node.range(), AnyNodeRef::Arguments(node) => node.range(),
AnyNodeRef::Arg(node) => node.range(), AnyNodeRef::Arg(node) => node.range(),
AnyNodeRef::ArgWithDefault(node) => node.range(),
AnyNodeRef::Keyword(node) => node.range(), AnyNodeRef::Keyword(node) => node.range(),
AnyNodeRef::Alias(node) => node.range(), AnyNodeRef::Alias(node) => node.range(),
AnyNodeRef::Withitem(node) => node.range(), AnyNodeRef::WithItem(node) => node.range(),
AnyNodeRef::MatchCase(node) => node.range(), AnyNodeRef::MatchCase(node) => node.range(),
AnyNodeRef::Decorator(node) => node.range(), AnyNodeRef::Decorator(node) => node.range(),
} }
@ -4935,7 +4992,7 @@ pub enum NodeKind {
ExprList, ExprList,
ExprTuple, ExprTuple,
ExprSlice, ExprSlice,
ExcepthandlerExceptHandler, ExceptHandlerExceptHandler,
PatternMatchValue, PatternMatchValue,
PatternMatchSingleton, PatternMatchSingleton,
PatternMatchSequence, PatternMatchSequence,
@ -4948,9 +5005,10 @@ pub enum NodeKind {
Comprehension, Comprehension,
Arguments, Arguments,
Arg, Arg,
ArgWithDefault,
Keyword, Keyword,
Alias, Alias,
Withitem, WithItem,
MatchCase, MatchCase,
Decorator, Decorator,
} }

View file

@ -1,11 +1,12 @@
//! Generate Python source code from an abstract syntax tree (AST). //! Generate Python source code from an abstract syntax tree (AST).
use rustpython_ast::ArgWithDefault;
use std::ops::Deref; use std::ops::Deref;
use rustpython_literal::escape::{AsciiEscape, Escape, UnicodeEscape}; use rustpython_literal::escape::{AsciiEscape, Escape, UnicodeEscape};
use rustpython_parser::ast::{ use rustpython_parser::ast::{
self, Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, ConversionFlag, self, Alias, Arg, Arguments, BoolOp, CmpOp, Comprehension, Constant, ConversionFlag,
Excepthandler, Expr, Identifier, MatchCase, Operator, Pattern, Stmt, Suite, Withitem, ExceptHandler, Expr, Identifier, MatchCase, Operator, Pattern, Stmt, Suite, WithItem,
}; };
use ruff_python_whitespace::LineEnding; use ruff_python_whitespace::LineEnding;
@ -501,7 +502,7 @@ impl<'a> Generator<'a> {
let mut first = true; let mut first = true;
for item in items { for item in items {
self.p_delim(&mut first, ", "); self.p_delim(&mut first, ", ");
self.unparse_withitem(item); self.unparse_with_item(item);
} }
self.p(":"); self.p(":");
}); });
@ -513,7 +514,7 @@ impl<'a> Generator<'a> {
let mut first = true; let mut first = true;
for item in items { for item in items {
self.p_delim(&mut first, ", "); self.p_delim(&mut first, ", ");
self.unparse_withitem(item); self.unparse_with_item(item);
} }
self.p(":"); self.p(":");
}); });
@ -568,7 +569,7 @@ impl<'a> Generator<'a> {
for handler in handlers { for handler in handlers {
statement!({ statement!({
self.unparse_excepthandler(handler, false); self.unparse_except_handler(handler, false);
}); });
} }
@ -599,7 +600,7 @@ impl<'a> Generator<'a> {
for handler in handlers { for handler in handlers {
statement!({ statement!({
self.unparse_excepthandler(handler, true); self.unparse_except_handler(handler, true);
}); });
} }
@ -717,9 +718,9 @@ impl<'a> Generator<'a> {
} }
} }
fn unparse_excepthandler<U>(&mut self, ast: &Excepthandler<U>, star: bool) { fn unparse_except_handler<U>(&mut self, ast: &ExceptHandler<U>, star: bool) {
match ast { match ast {
Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
type_, type_,
name, name,
body, body,
@ -870,7 +871,7 @@ impl<'a> Generator<'a> {
values, values,
range: _range, range: _range,
}) => { }) => {
let (op, prec) = opprec!(bin, op, Boolop, And("and", AND), Or("or", OR)); let (op, prec) = opprec!(bin, op, BoolOp, And("and", AND), Or("or", OR));
group_if!(prec, { group_if!(prec, {
let mut first = true; let mut first = true;
for val in values { for val in values {
@ -929,7 +930,7 @@ impl<'a> Generator<'a> {
let (op, prec) = opprec!( let (op, prec) = opprec!(
un, un,
op, op,
rustpython_parser::ast::Unaryop, rustpython_parser::ast::UnaryOp,
Invert("~", INVERT), Invert("~", INVERT),
Not("not ", NOT), Not("not ", NOT),
UAdd("+", UADD), UAdd("+", UADD),
@ -1087,16 +1088,16 @@ impl<'a> Generator<'a> {
self.unparse_expr(left, new_lvl); self.unparse_expr(left, new_lvl);
for (op, cmp) in ops.iter().zip(comparators) { for (op, cmp) in ops.iter().zip(comparators) {
let op = match op { let op = match op {
Cmpop::Eq => " == ", CmpOp::Eq => " == ",
Cmpop::NotEq => " != ", CmpOp::NotEq => " != ",
Cmpop::Lt => " < ", CmpOp::Lt => " < ",
Cmpop::LtE => " <= ", CmpOp::LtE => " <= ",
Cmpop::Gt => " > ", CmpOp::Gt => " > ",
Cmpop::GtE => " >= ", CmpOp::GtE => " >= ",
Cmpop::Is => " is ", CmpOp::Is => " is ",
Cmpop::IsNot => " is not ", CmpOp::IsNot => " is not ",
Cmpop::In => " in ", CmpOp::In => " in ",
Cmpop::NotIn => " not in ", CmpOp::NotIn => " not in ",
}; };
self.p(op); self.p(op);
self.unparse_expr(cmp, new_lvl); self.unparse_expr(cmp, new_lvl);
@ -1290,14 +1291,9 @@ impl<'a> Generator<'a> {
fn unparse_args<U>(&mut self, args: &Arguments<U>) { fn unparse_args<U>(&mut self, args: &Arguments<U>) {
let mut first = true; let mut first = true;
let defaults_start = args.posonlyargs.len() + args.args.len() - args.defaults.len(); for (i, arg_with_default) in args.posonlyargs.iter().chain(&args.args).enumerate() {
for (i, arg) in args.posonlyargs.iter().chain(&args.args).enumerate() {
self.p_delim(&mut first, ", "); self.p_delim(&mut first, ", ");
self.unparse_arg(arg); self.unparse_arg_with_default(arg_with_default);
if let Some(i) = i.checked_sub(defaults_start) {
self.p("=");
self.unparse_expr(&args.defaults[i], precedence::COMMA);
}
self.p_if(i + 1 == args.posonlyargs.len(), ", /"); self.p_if(i + 1 == args.posonlyargs.len(), ", /");
} }
if args.vararg.is_some() || !args.kwonlyargs.is_empty() { if args.vararg.is_some() || !args.kwonlyargs.is_empty() {
@ -1307,17 +1303,9 @@ impl<'a> Generator<'a> {
if let Some(vararg) = &args.vararg { if let Some(vararg) = &args.vararg {
self.unparse_arg(vararg); self.unparse_arg(vararg);
} }
let defaults_start = args.kwonlyargs.len() - args.kw_defaults.len(); for kwarg in &args.kwonlyargs {
for (i, kwarg) in args.kwonlyargs.iter().enumerate() {
self.p_delim(&mut first, ", "); self.p_delim(&mut first, ", ");
self.unparse_arg(kwarg); self.unparse_arg_with_default(kwarg);
if let Some(default) = i
.checked_sub(defaults_start)
.and_then(|i| args.kw_defaults.get(i))
{
self.p("=");
self.unparse_expr(default, precedence::COMMA);
}
} }
if let Some(kwarg) = &args.kwarg { if let Some(kwarg) = &args.kwarg {
self.p_delim(&mut first, ", "); self.p_delim(&mut first, ", ");
@ -1334,6 +1322,14 @@ impl<'a> Generator<'a> {
} }
} }
fn unparse_arg_with_default<U>(&mut self, arg_with_default: &ArgWithDefault<U>) {
self.unparse_arg(&arg_with_default.def);
if let Some(default) = &arg_with_default.default {
self.p("=");
self.unparse_expr(default, precedence::COMMA);
}
}
fn unparse_comp<U>(&mut self, generators: &[Comprehension<U>]) { fn unparse_comp<U>(&mut self, generators: &[Comprehension<U>]) {
for comp in generators { for comp in generators {
self.p(if comp.is_async { self.p(if comp.is_async {
@ -1445,9 +1441,9 @@ impl<'a> Generator<'a> {
} }
} }
fn unparse_withitem<U>(&mut self, withitem: &Withitem<U>) { fn unparse_with_item<U>(&mut self, with_item: &WithItem<U>) {
self.unparse_expr(&withitem.context_expr, precedence::MAX); self.unparse_expr(&with_item.context_expr, precedence::MAX);
if let Some(optional_vars) = &withitem.optional_vars { if let Some(optional_vars) = &with_item.optional_vars {
self.p(" as "); self.p(" as ");
self.unparse_expr(optional_vars, precedence::MAX); self.unparse_expr(optional_vars, precedence::MAX);
} }

View file

@ -1,6 +1,6 @@
//! Specialized AST visitor trait and walk functions that only visit statements. //! Specialized AST visitor trait and walk functions that only visit statements.
use rustpython_parser::ast::{self, Excepthandler, MatchCase, Stmt}; use rustpython_parser::ast::{self, ExceptHandler, MatchCase, Stmt};
/// A trait for AST visitors that only need to visit statements. /// A trait for AST visitors that only need to visit statements.
pub trait StatementVisitor<'a> { pub trait StatementVisitor<'a> {
@ -10,8 +10,8 @@ pub trait StatementVisitor<'a> {
fn visit_stmt(&mut self, stmt: &'a Stmt) { fn visit_stmt(&mut self, stmt: &'a Stmt) {
walk_stmt(self, stmt); walk_stmt(self, stmt);
} }
fn visit_excepthandler(&mut self, excepthandler: &'a Excepthandler) { fn visit_except_handler(&mut self, except_handler: &'a ExceptHandler) {
walk_excepthandler(self, excepthandler); walk_except_handler(self, except_handler);
} }
fn visit_match_case(&mut self, match_case: &'a MatchCase) { fn visit_match_case(&mut self, match_case: &'a MatchCase) {
walk_match_case(self, match_case); walk_match_case(self, match_case);
@ -70,8 +70,8 @@ pub fn walk_stmt<'a, V: StatementVisitor<'a> + ?Sized>(visitor: &mut V, stmt: &'
range: _range, range: _range,
}) => { }) => {
visitor.visit_body(body); visitor.visit_body(body);
for excepthandler in handlers { for except_handler in handlers {
visitor.visit_excepthandler(excepthandler); visitor.visit_except_handler(except_handler);
} }
visitor.visit_body(orelse); visitor.visit_body(orelse);
visitor.visit_body(finalbody); visitor.visit_body(finalbody);
@ -84,8 +84,8 @@ pub fn walk_stmt<'a, V: StatementVisitor<'a> + ?Sized>(visitor: &mut V, stmt: &'
range: _range, range: _range,
}) => { }) => {
visitor.visit_body(body); visitor.visit_body(body);
for excepthandler in handlers { for except_handler in handlers {
visitor.visit_excepthandler(excepthandler); visitor.visit_except_handler(except_handler);
} }
visitor.visit_body(orelse); visitor.visit_body(orelse);
visitor.visit_body(finalbody); visitor.visit_body(finalbody);
@ -94,12 +94,12 @@ pub fn walk_stmt<'a, V: StatementVisitor<'a> + ?Sized>(visitor: &mut V, stmt: &'
} }
} }
pub fn walk_excepthandler<'a, V: StatementVisitor<'a> + ?Sized>( pub fn walk_except_handler<'a, V: StatementVisitor<'a> + ?Sized>(
visitor: &mut V, visitor: &mut V,
excepthandler: &'a Excepthandler, except_handler: &'a ExceptHandler,
) { ) {
match excepthandler { match except_handler {
Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) => { ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { body, .. }) => {
visitor.visit_body(body); visitor.visit_body(body);
} }
} }

View file

@ -2,10 +2,10 @@
pub mod preorder; pub mod preorder;
use rustpython_ast::Decorator; use rustpython_ast::{ArgWithDefault, Decorator};
use rustpython_parser::ast::{ use rustpython_parser::ast::{
self, Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, Excepthandler, Expr, self, Alias, Arg, Arguments, BoolOp, CmpOp, Comprehension, Constant, ExceptHandler, Expr,
ExprContext, Keyword, MatchCase, Operator, Pattern, Stmt, Unaryop, Withitem, ExprContext, Keyword, MatchCase, Operator, Pattern, Stmt, UnaryOp, WithItem,
}; };
/// A trait for AST visitors. Visits all nodes in the AST recursively in evaluation-order. /// A trait for AST visitors. Visits all nodes in the AST recursively in evaluation-order.
@ -34,23 +34,23 @@ pub trait Visitor<'a> {
fn visit_expr_context(&mut self, expr_context: &'a ExprContext) { fn visit_expr_context(&mut self, expr_context: &'a ExprContext) {
walk_expr_context(self, expr_context); walk_expr_context(self, expr_context);
} }
fn visit_boolop(&mut self, boolop: &'a Boolop) { fn visit_bool_op(&mut self, bool_op: &'a BoolOp) {
walk_boolop(self, boolop); walk_bool_op(self, bool_op);
} }
fn visit_operator(&mut self, operator: &'a Operator) { fn visit_operator(&mut self, operator: &'a Operator) {
walk_operator(self, operator); walk_operator(self, operator);
} }
fn visit_unaryop(&mut self, unaryop: &'a Unaryop) { fn visit_unary_op(&mut self, unary_op: &'a UnaryOp) {
walk_unaryop(self, unaryop); walk_unary_op(self, unary_op);
} }
fn visit_cmpop(&mut self, cmpop: &'a Cmpop) { fn visit_cmp_op(&mut self, cmp_op: &'a CmpOp) {
walk_cmpop(self, cmpop); walk_cmp_op(self, cmp_op);
} }
fn visit_comprehension(&mut self, comprehension: &'a Comprehension) { fn visit_comprehension(&mut self, comprehension: &'a Comprehension) {
walk_comprehension(self, comprehension); walk_comprehension(self, comprehension);
} }
fn visit_excepthandler(&mut self, excepthandler: &'a Excepthandler) { fn visit_except_handler(&mut self, except_handler: &'a ExceptHandler) {
walk_excepthandler(self, excepthandler); walk_except_handler(self, except_handler);
} }
fn visit_format_spec(&mut self, format_spec: &'a Expr) { fn visit_format_spec(&mut self, format_spec: &'a Expr) {
walk_expr(self, format_spec); walk_expr(self, format_spec);
@ -61,14 +61,17 @@ pub trait Visitor<'a> {
fn visit_arg(&mut self, arg: &'a Arg) { fn visit_arg(&mut self, arg: &'a Arg) {
walk_arg(self, arg); walk_arg(self, arg);
} }
fn visit_arg_with_default(&mut self, arg_with_default: &'a ArgWithDefault) {
walk_arg_with_default(self, arg_with_default);
}
fn visit_keyword(&mut self, keyword: &'a Keyword) { fn visit_keyword(&mut self, keyword: &'a Keyword) {
walk_keyword(self, keyword); walk_keyword(self, keyword);
} }
fn visit_alias(&mut self, alias: &'a Alias) { fn visit_alias(&mut self, alias: &'a Alias) {
walk_alias(self, alias); walk_alias(self, alias);
} }
fn visit_withitem(&mut self, withitem: &'a Withitem) { fn visit_with_item(&mut self, with_item: &'a WithItem) {
walk_withitem(self, withitem); walk_with_item(self, with_item);
} }
fn visit_match_case(&mut self, match_case: &'a MatchCase) { fn visit_match_case(&mut self, match_case: &'a MatchCase) {
walk_match_case(self, match_case); walk_match_case(self, match_case);
@ -228,14 +231,14 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
visitor.visit_body(orelse); visitor.visit_body(orelse);
} }
Stmt::With(ast::StmtWith { items, body, .. }) => { Stmt::With(ast::StmtWith { items, body, .. }) => {
for withitem in items { for with_item in items {
visitor.visit_withitem(withitem); visitor.visit_with_item(with_item);
} }
visitor.visit_body(body); visitor.visit_body(body);
} }
Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => { Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => {
for withitem in items { for with_item in items {
visitor.visit_withitem(withitem); visitor.visit_with_item(with_item);
} }
visitor.visit_body(body); visitor.visit_body(body);
} }
@ -269,8 +272,8 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
range: _range, range: _range,
}) => { }) => {
visitor.visit_body(body); visitor.visit_body(body);
for excepthandler in handlers { for except_handler in handlers {
visitor.visit_excepthandler(excepthandler); visitor.visit_except_handler(except_handler);
} }
visitor.visit_body(orelse); visitor.visit_body(orelse);
visitor.visit_body(finalbody); visitor.visit_body(finalbody);
@ -283,8 +286,8 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
range: _range, range: _range,
}) => { }) => {
visitor.visit_body(body); visitor.visit_body(body);
for excepthandler in handlers { for except_handler in handlers {
visitor.visit_excepthandler(excepthandler); visitor.visit_except_handler(except_handler);
} }
visitor.visit_body(orelse); visitor.visit_body(orelse);
visitor.visit_body(finalbody); visitor.visit_body(finalbody);
@ -333,7 +336,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
values, values,
range: _range, range: _range,
}) => { }) => {
visitor.visit_boolop(op); visitor.visit_bool_op(op);
for expr in values { for expr in values {
visitor.visit_expr(expr); visitor.visit_expr(expr);
} }
@ -361,7 +364,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
operand, operand,
range: _range, range: _range,
}) => { }) => {
visitor.visit_unaryop(op); visitor.visit_unary_op(op);
visitor.visit_expr(operand); visitor.visit_expr(operand);
} }
Expr::Lambda(ast::ExprLambda { Expr::Lambda(ast::ExprLambda {
@ -467,8 +470,8 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
range: _range, range: _range,
}) => { }) => {
visitor.visit_expr(left); visitor.visit_expr(left);
for cmpop in ops { for cmp_op in ops {
visitor.visit_cmpop(cmpop); visitor.visit_cmp_op(cmp_op);
} }
for expr in comparators { for expr in comparators {
visitor.visit_expr(expr); visitor.visit_expr(expr);
@ -588,12 +591,12 @@ pub fn walk_comprehension<'a, V: Visitor<'a> + ?Sized>(
} }
} }
pub fn walk_excepthandler<'a, V: Visitor<'a> + ?Sized>( pub fn walk_except_handler<'a, V: Visitor<'a> + ?Sized>(
visitor: &mut V, visitor: &mut V,
excepthandler: &'a Excepthandler, except_handler: &'a ExceptHandler,
) { ) {
match excepthandler { match except_handler {
Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, body, .. }) => { ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, body, .. }) => {
if let Some(expr) = type_ { if let Some(expr) = type_ {
visitor.visit_expr(expr); visitor.visit_expr(expr);
} }
@ -604,26 +607,20 @@ pub fn walk_excepthandler<'a, V: Visitor<'a> + ?Sized>(
pub fn walk_arguments<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arguments: &'a Arguments) { pub fn walk_arguments<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arguments: &'a Arguments) {
for arg in &arguments.posonlyargs { for arg in &arguments.posonlyargs {
visitor.visit_arg(arg); visitor.visit_arg_with_default(arg);
} }
for arg in &arguments.args { for arg in &arguments.args {
visitor.visit_arg(arg); visitor.visit_arg_with_default(arg);
} }
if let Some(arg) = &arguments.vararg { if let Some(arg) = &arguments.vararg {
visitor.visit_arg(arg); visitor.visit_arg(arg);
} }
for arg in &arguments.kwonlyargs { for arg in &arguments.kwonlyargs {
visitor.visit_arg(arg); visitor.visit_arg_with_default(arg);
}
for expr in &arguments.kw_defaults {
visitor.visit_expr(expr);
} }
if let Some(arg) = &arguments.kwarg { if let Some(arg) = &arguments.kwarg {
visitor.visit_arg(arg); visitor.visit_arg(arg);
} }
for expr in &arguments.defaults {
visitor.visit_expr(expr);
}
} }
pub fn walk_arg<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arg: &'a Arg) { pub fn walk_arg<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arg: &'a Arg) {
@ -632,13 +629,23 @@ pub fn walk_arg<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arg: &'a Arg) {
} }
} }
pub fn walk_arg_with_default<'a, V: Visitor<'a> + ?Sized>(
visitor: &mut V,
arg_with_default: &'a ArgWithDefault,
) {
visitor.visit_arg(&arg_with_default.def);
if let Some(expr) = &arg_with_default.default {
visitor.visit_expr(expr);
}
}
pub fn walk_keyword<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, keyword: &'a Keyword) { pub fn walk_keyword<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, keyword: &'a Keyword) {
visitor.visit_expr(&keyword.value); visitor.visit_expr(&keyword.value);
} }
pub fn walk_withitem<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, withitem: &'a Withitem) { pub fn walk_with_item<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, with_item: &'a WithItem) {
visitor.visit_expr(&withitem.context_expr); visitor.visit_expr(&with_item.context_expr);
if let Some(expr) = &withitem.optional_vars { if let Some(expr) = &with_item.optional_vars {
visitor.visit_expr(expr); visitor.visit_expr(expr);
} }
} }
@ -719,16 +726,16 @@ pub fn walk_expr_context<'a, V: Visitor<'a> + ?Sized>(
} }
#[allow(unused_variables)] #[allow(unused_variables)]
pub fn walk_boolop<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, boolop: &'a Boolop) {} pub fn walk_bool_op<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, bool_op: &'a BoolOp) {}
#[allow(unused_variables)] #[allow(unused_variables)]
pub fn walk_operator<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, operator: &'a Operator) {} pub fn walk_operator<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, operator: &'a Operator) {}
#[allow(unused_variables)] #[allow(unused_variables)]
pub fn walk_unaryop<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, unaryop: &'a Unaryop) {} pub fn walk_unary_op<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, unary_op: &'a UnaryOp) {}
#[allow(unused_variables)] #[allow(unused_variables)]
pub fn walk_cmpop<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, cmpop: &'a Cmpop) {} pub fn walk_cmp_op<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, cmp_op: &'a CmpOp) {}
#[allow(unused_variables)] #[allow(unused_variables)]
pub fn walk_alias<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, alias: &'a Alias) {} pub fn walk_alias<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, alias: &'a Alias) {}

View file

@ -26,28 +26,28 @@ pub trait PreorderVisitor<'a> {
walk_constant(self, constant); walk_constant(self, constant);
} }
fn visit_boolop(&mut self, boolop: &'a Boolop) { fn visit_bool_op(&mut self, bool_op: &'a BoolOp) {
walk_boolop(self, boolop); walk_bool_op(self, bool_op);
} }
fn visit_operator(&mut self, operator: &'a Operator) { fn visit_operator(&mut self, operator: &'a Operator) {
walk_operator(self, operator); walk_operator(self, operator);
} }
fn visit_unaryop(&mut self, unaryop: &'a Unaryop) { fn visit_unary_op(&mut self, unary_op: &'a UnaryOp) {
walk_unaryop(self, unaryop); walk_unary_op(self, unary_op);
} }
fn visit_cmpop(&mut self, cmpop: &'a Cmpop) { fn visit_cmp_op(&mut self, cmp_op: &'a CmpOp) {
walk_cmpop(self, cmpop); walk_cmp_op(self, cmp_op);
} }
fn visit_comprehension(&mut self, comprehension: &'a Comprehension) { fn visit_comprehension(&mut self, comprehension: &'a Comprehension) {
walk_comprehension(self, comprehension); walk_comprehension(self, comprehension);
} }
fn visit_excepthandler(&mut self, excepthandler: &'a Excepthandler) { fn visit_except_handler(&mut self, except_handler: &'a ExceptHandler) {
walk_excepthandler(self, excepthandler); walk_except_handler(self, except_handler);
} }
fn visit_format_spec(&mut self, format_spec: &'a Expr) { fn visit_format_spec(&mut self, format_spec: &'a Expr) {
@ -62,6 +62,10 @@ pub trait PreorderVisitor<'a> {
walk_arg(self, arg); walk_arg(self, arg);
} }
fn visit_arg_with_default(&mut self, arg_with_default: &'a ArgWithDefault) {
walk_arg_with_default(self, arg_with_default);
}
fn visit_keyword(&mut self, keyword: &'a Keyword) { fn visit_keyword(&mut self, keyword: &'a Keyword) {
walk_keyword(self, keyword); walk_keyword(self, keyword);
} }
@ -70,8 +74,8 @@ pub trait PreorderVisitor<'a> {
walk_alias(self, alias); walk_alias(self, alias);
} }
fn visit_withitem(&mut self, withitem: &'a Withitem) { fn visit_with_item(&mut self, with_item: &'a WithItem) {
walk_withitem(self, withitem); walk_with_item(self, with_item);
} }
fn visit_match_case(&mut self, match_case: &'a MatchCase) { fn visit_match_case(&mut self, match_case: &'a MatchCase) {
@ -300,8 +304,8 @@ where
type_comment: _, type_comment: _,
range: _, range: _,
}) => { }) => {
for withitem in items { for with_item in items {
visitor.visit_withitem(withitem); visitor.visit_with_item(with_item);
} }
visitor.visit_body(body); visitor.visit_body(body);
} }
@ -345,8 +349,8 @@ where
range: _range, range: _range,
}) => { }) => {
visitor.visit_body(body); visitor.visit_body(body);
for excepthandler in handlers { for except_handler in handlers {
visitor.visit_excepthandler(excepthandler); visitor.visit_except_handler(except_handler);
} }
visitor.visit_body(orelse); visitor.visit_body(orelse);
visitor.visit_body(finalbody); visitor.visit_body(finalbody);
@ -410,13 +414,13 @@ where
}) => match values.as_slice() { }) => match values.as_slice() {
[left, rest @ ..] => { [left, rest @ ..] => {
visitor.visit_expr(left); visitor.visit_expr(left);
visitor.visit_boolop(op); visitor.visit_bool_op(op);
for expr in rest { for expr in rest {
visitor.visit_expr(expr); visitor.visit_expr(expr);
} }
} }
[] => { [] => {
visitor.visit_boolop(op); visitor.visit_bool_op(op);
} }
}, },
@ -445,7 +449,7 @@ where
operand, operand,
range: _range, range: _range,
}) => { }) => {
visitor.visit_unaryop(op); visitor.visit_unary_op(op);
visitor.visit_expr(operand); visitor.visit_expr(operand);
} }
@ -565,7 +569,7 @@ where
visitor.visit_expr(left); visitor.visit_expr(left);
for (op, comparator) in ops.iter().zip(comparators) { for (op, comparator) in ops.iter().zip(comparators) {
visitor.visit_cmpop(op); visitor.visit_cmp_op(op);
visitor.visit_expr(comparator); visitor.visit_expr(comparator);
} }
} }
@ -703,12 +707,12 @@ where
} }
} }
pub fn walk_excepthandler<'a, V>(visitor: &mut V, excepthandler: &'a Excepthandler) pub fn walk_except_handler<'a, V>(visitor: &mut V, except_handler: &'a ExceptHandler)
where where
V: PreorderVisitor<'a> + ?Sized, V: PreorderVisitor<'a> + ?Sized,
{ {
match excepthandler { match except_handler {
Excepthandler::ExceptHandler(ExcepthandlerExceptHandler { ExceptHandler::ExceptHandler(ExceptHandlerExceptHandler {
range: _, range: _,
type_, type_,
name: _, name: _,
@ -726,34 +730,16 @@ pub fn walk_arguments<'a, V>(visitor: &mut V, arguments: &'a Arguments)
where where
V: PreorderVisitor<'a> + ?Sized, V: PreorderVisitor<'a> + ?Sized,
{ {
let non_default_args_len = for arg in arguments.posonlyargs.iter().chain(&arguments.args) {
arguments.posonlyargs.len() + arguments.args.len() - arguments.defaults.len(); visitor.visit_arg_with_default(arg);
let mut args_iter = arguments.posonlyargs.iter().chain(&arguments.args);
for _ in 0..non_default_args_len {
visitor.visit_arg(args_iter.next().unwrap());
}
for (arg, default) in args_iter.zip(&arguments.defaults) {
visitor.visit_arg(arg);
visitor.visit_expr(default);
} }
if let Some(arg) = &arguments.vararg { if let Some(arg) = &arguments.vararg {
visitor.visit_arg(arg); visitor.visit_arg(arg);
} }
let non_default_kwargs_len = arguments.kwonlyargs.len() - arguments.kw_defaults.len(); for arg in &arguments.kwonlyargs {
let mut kwargsonly_iter = arguments.kwonlyargs.iter(); visitor.visit_arg_with_default(arg);
for _ in 0..non_default_kwargs_len {
visitor.visit_arg(kwargsonly_iter.next().unwrap());
}
for (arg, default) in kwargsonly_iter.zip(&arguments.kw_defaults) {
visitor.visit_arg(arg);
visitor.visit_expr(default);
} }
if let Some(arg) = &arguments.kwarg { if let Some(arg) = &arguments.kwarg {
@ -770,6 +756,16 @@ where
} }
} }
pub fn walk_arg_with_default<'a, V>(visitor: &mut V, arg_with_default: &'a ArgWithDefault)
where
V: PreorderVisitor<'a> + ?Sized,
{
visitor.visit_arg(&arg_with_default.def);
if let Some(expr) = &arg_with_default.default {
visitor.visit_expr(expr);
}
}
#[inline] #[inline]
pub fn walk_keyword<'a, V>(visitor: &mut V, keyword: &'a Keyword) pub fn walk_keyword<'a, V>(visitor: &mut V, keyword: &'a Keyword)
where where
@ -778,13 +774,13 @@ where
visitor.visit_expr(&keyword.value); visitor.visit_expr(&keyword.value);
} }
pub fn walk_withitem<'a, V>(visitor: &mut V, withitem: &'a Withitem) pub fn walk_with_item<'a, V>(visitor: &mut V, with_item: &'a WithItem)
where where
V: PreorderVisitor<'a> + ?Sized, V: PreorderVisitor<'a> + ?Sized,
{ {
visitor.visit_expr(&withitem.context_expr); visitor.visit_expr(&with_item.context_expr);
if let Some(expr) = &withitem.optional_vars { if let Some(expr) = &with_item.optional_vars {
visitor.visit_expr(expr); visitor.visit_expr(expr);
} }
} }
@ -885,7 +881,7 @@ where
{ {
} }
pub fn walk_boolop<'a, V>(_visitor: &mut V, _boolop: &'a Boolop) pub fn walk_bool_op<'a, V>(_visitor: &mut V, _bool_op: &'a BoolOp)
where where
V: PreorderVisitor<'a> + ?Sized, V: PreorderVisitor<'a> + ?Sized,
{ {
@ -899,14 +895,14 @@ where
} }
#[inline] #[inline]
pub fn walk_unaryop<'a, V>(_visitor: &mut V, _unaryop: &'a Unaryop) pub fn walk_unary_op<'a, V>(_visitor: &mut V, _unary_op: &'a UnaryOp)
where where
V: PreorderVisitor<'a> + ?Sized, V: PreorderVisitor<'a> + ?Sized,
{ {
} }
#[inline] #[inline]
pub fn walk_cmpop<'a, V>(_visitor: &mut V, _cmpop: &'a Cmpop) pub fn walk_cmp_op<'a, V>(_visitor: &mut V, _cmp_op: &'a CmpOp)
where where
V: PreorderVisitor<'a> + ?Sized, V: PreorderVisitor<'a> + ?Sized,
{ {
@ -923,11 +919,11 @@ where
mod tests { mod tests {
use crate::node::AnyNodeRef; use crate::node::AnyNodeRef;
use crate::visitor::preorder::{ use crate::visitor::preorder::{
walk_alias, walk_arg, walk_arguments, walk_comprehension, walk_excepthandler, walk_expr, walk_alias, walk_arg, walk_arguments, walk_comprehension, walk_except_handler, walk_expr,
walk_keyword, walk_match_case, walk_module, walk_pattern, walk_stmt, walk_type_ignore, walk_keyword, walk_match_case, walk_module, walk_pattern, walk_stmt, walk_type_ignore,
walk_withitem, Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, walk_with_item, Alias, Arg, Arguments, BoolOp, CmpOp, Comprehension, Constant,
Excepthandler, Expr, Keyword, MatchCase, Mod, Operator, Pattern, PreorderVisitor, Stmt, ExceptHandler, Expr, Keyword, MatchCase, Mod, Operator, Pattern, PreorderVisitor, Stmt,
String, TypeIgnore, Unaryop, Withitem, String, TypeIgnore, UnaryOp, WithItem,
}; };
use insta::assert_snapshot; use insta::assert_snapshot;
use rustpython_parser::lexer::lex; use rustpython_parser::lexer::lex;
@ -1089,20 +1085,20 @@ class A:
self.emit(&constant); self.emit(&constant);
} }
fn visit_boolop(&mut self, boolop: &Boolop) { fn visit_bool_op(&mut self, bool_op: &BoolOp) {
self.emit(&boolop); self.emit(&bool_op);
} }
fn visit_operator(&mut self, operator: &Operator) { fn visit_operator(&mut self, operator: &Operator) {
self.emit(&operator); self.emit(&operator);
} }
fn visit_unaryop(&mut self, unaryop: &Unaryop) { fn visit_unary_op(&mut self, unary_op: &UnaryOp) {
self.emit(&unaryop); self.emit(&unary_op);
} }
fn visit_cmpop(&mut self, cmpop: &Cmpop) { fn visit_cmp_op(&mut self, cmp_op: &CmpOp) {
self.emit(&cmpop); self.emit(&cmp_op);
} }
fn visit_comprehension(&mut self, comprehension: &Comprehension) { fn visit_comprehension(&mut self, comprehension: &Comprehension) {
@ -1111,9 +1107,9 @@ class A:
self.exit_node(); self.exit_node();
} }
fn visit_excepthandler(&mut self, excepthandler: &Excepthandler) { fn visit_except_handler(&mut self, except_handler: &ExceptHandler) {
self.enter_node(excepthandler); self.enter_node(except_handler);
walk_excepthandler(self, excepthandler); walk_except_handler(self, except_handler);
self.exit_node(); self.exit_node();
} }
@ -1147,9 +1143,9 @@ class A:
self.exit_node(); self.exit_node();
} }
fn visit_withitem(&mut self, withitem: &Withitem) { fn visit_with_item(&mut self, with_item: &WithItem) {
self.enter_node(withitem); self.enter_node(with_item);
walk_withitem(self, withitem); walk_with_item(self, with_item);
self.exit_node(); self.exit_node();
} }

View file

@ -14,21 +14,21 @@ pub(super) fn place_comment<'a>(
comment: DecoratedComment<'a>, comment: DecoratedComment<'a>,
locator: &Locator, locator: &Locator,
) -> CommentPlacement<'a> { ) -> CommentPlacement<'a> {
handle_in_between_excepthandlers_or_except_handler_and_else_or_finally_comment(comment, locator) handle_in_between_except_handlers_or_except_handler_and_else_or_finally_comment(
.or_else(|comment| handle_match_comment(comment, locator)) comment, locator,
.or_else(|comment| handle_in_between_bodies_own_line_comment(comment, locator)) )
.or_else(|comment| handle_in_between_bodies_end_of_line_comment(comment, locator)) .or_else(|comment| handle_match_comment(comment, locator))
.or_else(|comment| handle_trailing_body_comment(comment, locator)) .or_else(|comment| handle_in_between_bodies_own_line_comment(comment, locator))
.or_else(handle_trailing_end_of_line_body_comment) .or_else(|comment| handle_in_between_bodies_end_of_line_comment(comment, locator))
.or_else(|comment| handle_trailing_end_of_line_condition_comment(comment, locator)) .or_else(|comment| handle_trailing_body_comment(comment, locator))
.or_else(|comment| { .or_else(handle_trailing_end_of_line_body_comment)
handle_module_level_own_line_comment_before_class_or_function_comment(comment, locator) .or_else(|comment| handle_trailing_end_of_line_condition_comment(comment, locator))
}) .or_else(|comment| {
.or_else(|comment| handle_positional_only_arguments_separator_comment(comment, locator)) handle_module_level_own_line_comment_before_class_or_function_comment(comment, locator)
.or_else(|comment| { })
handle_trailing_binary_expression_left_or_operator_comment(comment, locator) .or_else(|comment| handle_positional_only_arguments_separator_comment(comment, locator))
}) .or_else(|comment| handle_trailing_binary_expression_left_or_operator_comment(comment, locator))
.or_else(handle_leading_function_with_decorators_comment) .or_else(handle_leading_function_with_decorators_comment)
} }
/// Handles leading comments in front of a match case or a trailing comment of the `match` statement. /// Handles leading comments in front of a match case or a trailing comment of the `match` statement.
@ -138,8 +138,8 @@ fn handle_match_comment<'a>(
} }
} }
/// Handles comments between excepthandlers and between the last except handler and any following `else` or `finally` block. /// Handles comments between except handlers and between the last except handler and any following `else` or `finally` block.
fn handle_in_between_excepthandlers_or_except_handler_and_else_or_finally_comment<'a>( fn handle_in_between_except_handlers_or_except_handler_and_else_or_finally_comment<'a>(
comment: DecoratedComment<'a>, comment: DecoratedComment<'a>,
locator: &Locator, locator: &Locator,
) -> CommentPlacement<'a> { ) -> CommentPlacement<'a> {
@ -147,7 +147,7 @@ fn handle_in_between_excepthandlers_or_except_handler_and_else_or_finally_commen
return CommentPlacement::Default(comment); return CommentPlacement::Default(comment);
} }
if let Some(AnyNodeRef::ExcepthandlerExceptHandler(except_handler)) = comment.preceding_node() { if let Some(AnyNodeRef::ExceptHandlerExceptHandler(except_handler)) = comment.preceding_node() {
// it now depends on the indentation level of the comment if it is a leading comment for e.g. // it now depends on the indentation level of the comment if it is a leading comment for e.g.
// the following `elif` or indeed a trailing comment of the previous body's last statement. // the following `elif` or indeed a trailing comment of the previous body's last statement.
let comment_indentation = let comment_indentation =
@ -627,11 +627,8 @@ fn handle_positional_only_arguments_separator_comment<'a>(
// ```python // ```python
// def test(a=10, /, b): pass // def test(a=10, /, b): pass
// ``` // ```
|| arguments || are_same_optional(last_argument_or_default, arguments
.defaults .posonlyargs.last().and_then(|arg| arg.default.as_deref()));
.iter()
.position(|default| AnyNodeRef::from(default).ptr_eq(last_argument_or_default))
== Some(arguments.posonlyargs.len().saturating_sub(1));
if !is_last_positional_argument { if !is_last_positional_argument {
return CommentPlacement::Default(comment); return CommentPlacement::Default(comment);
@ -906,7 +903,7 @@ fn last_child_in_body(node: AnyNodeRef) -> Option<AnyNodeRef> {
| AnyNodeRef::StmtWith(StmtWith { body, .. }) | AnyNodeRef::StmtWith(StmtWith { body, .. })
| AnyNodeRef::StmtAsyncWith(StmtAsyncWith { body, .. }) | AnyNodeRef::StmtAsyncWith(StmtAsyncWith { body, .. })
| AnyNodeRef::MatchCase(MatchCase { body, .. }) | AnyNodeRef::MatchCase(MatchCase { body, .. })
| AnyNodeRef::ExcepthandlerExceptHandler(ExcepthandlerExceptHandler { body, .. }) => body, | AnyNodeRef::ExceptHandlerExceptHandler(ExceptHandlerExceptHandler { body, .. }) => body,
AnyNodeRef::StmtIf(StmtIf { body, orelse, .. }) AnyNodeRef::StmtIf(StmtIf { body, orelse, .. })
| AnyNodeRef::StmtFor(StmtFor { body, orelse, .. }) | AnyNodeRef::StmtFor(StmtFor { body, orelse, .. })
@ -988,7 +985,7 @@ fn is_first_statement_in_enclosing_alternate_body(
}) => { }) => {
are_same_optional(following, handlers.first()) are_same_optional(following, handlers.first())
// Comments between the handlers and the `else`, or comments between the `handlers` and the `finally` // Comments between the handlers and the `else`, or comments between the `handlers` and the `finally`
// are already handled by `handle_in_between_excepthandlers_or_except_handler_and_else_or_finally_comment` // are already handled by `handle_in_between_except_handlers_or_except_handler_and_else_or_finally_comment`
|| handlers.is_empty() && are_same_optional(following, orelse.first()) || handlers.is_empty() && are_same_optional(following, orelse.first())
|| (handlers.is_empty() || !orelse.is_empty()) || (handlers.is_empty() || !orelse.is_empty())
&& are_same_optional(following, finalbody.first()) && are_same_optional(following, finalbody.first())

View file

@ -34,7 +34,7 @@ expression: comments.debug(test_case.source_code)
], ],
}, },
Node { Node {
kind: ExcepthandlerExceptHandler, kind: ExceptHandlerExceptHandler,
range: 100..136, range: 100..136,
source: `except Exception as ex:⏎`, source: `except Exception as ex:⏎`,
}: { }: {

View file

@ -39,7 +39,7 @@ expression: comments.debug(test_case.source_code)
], ],
}, },
Node { Node {
kind: ExcepthandlerExceptHandler, kind: ExceptHandlerExceptHandler,
range: 68..100, range: 68..100,
source: `except Exception as ex:⏎`, source: `except Exception as ex:⏎`,
}: { }: {

View file

@ -208,11 +208,11 @@ impl<'ast> PreorderVisitor<'ast> for CommentsVisitor<'ast> {
self.finish_node(comprehension); self.finish_node(comprehension);
} }
fn visit_excepthandler(&mut self, excepthandler: &'ast Excepthandler) { fn visit_except_handler(&mut self, except_handler: &'ast ExceptHandler) {
if self.start_node(excepthandler).is_traverse() { if self.start_node(except_handler).is_traverse() {
walk_excepthandler(self, excepthandler); walk_except_handler(self, except_handler);
} }
self.finish_node(excepthandler); self.finish_node(except_handler);
} }
fn visit_format_spec(&mut self, format_spec: &'ast Expr) { fn visit_format_spec(&mut self, format_spec: &'ast Expr) {
@ -250,12 +250,12 @@ impl<'ast> PreorderVisitor<'ast> for CommentsVisitor<'ast> {
self.finish_node(alias); self.finish_node(alias);
} }
fn visit_withitem(&mut self, withitem: &'ast Withitem) { fn visit_with_item(&mut self, with_item: &'ast WithItem) {
if self.start_node(withitem).is_traverse() { if self.start_node(with_item).is_traverse() {
walk_withitem(self, withitem); walk_with_item(self, with_item);
} }
self.finish_node(withitem); self.finish_node(with_item);
} }
fn visit_match_case(&mut self, match_case: &'ast MatchCase) { fn visit_match_case(&mut self, match_case: &'ast MatchCase) {

View file

@ -10,7 +10,7 @@ use ruff_formatter::{
}; };
use ruff_python_ast::node::AstNode; use ruff_python_ast::node::AstNode;
use rustpython_parser::ast::{ use rustpython_parser::ast::{
Constant, Expr, ExprAttribute, ExprBinOp, ExprConstant, ExprUnaryOp, Operator, Unaryop, Constant, Expr, ExprAttribute, ExprBinOp, ExprConstant, ExprUnaryOp, Operator, UnaryOp,
}; };
#[derive(Default)] #[derive(Default)]
@ -116,7 +116,7 @@ const fn is_simple_power_expression(expr: &ExprBinOp) -> bool {
const fn is_simple_power_operand(expr: &Expr) -> bool { const fn is_simple_power_operand(expr: &Expr) -> bool {
match expr { match expr {
Expr::UnaryOp(ExprUnaryOp { Expr::UnaryOp(ExprUnaryOp {
op: Unaryop::Not, .. op: UnaryOp::Not, ..
}) => false, }) => false,
Expr::Constant(ExprConstant { Expr::Constant(ExprConstant {
value: Constant::Complex { .. } | Constant::Float(_) | Constant::Int(_), value: Constant::Complex { .. } | Constant::Float(_) | Constant::Int(_),

View file

@ -2253,42 +2253,44 @@ impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::ExprSlice {
} }
} }
impl FormatRule<ast::ExcepthandlerExceptHandler, PyFormatContext<'_>> impl FormatRule<ast::ExceptHandlerExceptHandler, PyFormatContext<'_>>
for crate::other::excepthandler_except_handler::FormatExcepthandlerExceptHandler for crate::other::except_handler_except_handler::FormatExceptHandlerExceptHandler
{ {
#[inline] #[inline]
fn fmt( fn fmt(
&self, &self,
node: &ast::ExcepthandlerExceptHandler, node: &ast::ExceptHandlerExceptHandler,
f: &mut Formatter<PyFormatContext<'_>>, f: &mut Formatter<PyFormatContext<'_>>,
) -> FormatResult<()> { ) -> FormatResult<()> {
FormatNodeRule::<ast::ExcepthandlerExceptHandler>::fmt(self, node, f) FormatNodeRule::<ast::ExceptHandlerExceptHandler>::fmt(self, node, f)
} }
} }
impl<'ast> AsFormat<PyFormatContext<'ast>> for ast::ExcepthandlerExceptHandler { impl<'ast> AsFormat<PyFormatContext<'ast>> for ast::ExceptHandlerExceptHandler {
type Format<'a> = FormatRefWithRule< type Format<'a> = FormatRefWithRule<
'a, 'a,
ast::ExcepthandlerExceptHandler, ast::ExceptHandlerExceptHandler,
crate::other::excepthandler_except_handler::FormatExcepthandlerExceptHandler, crate::other::except_handler_except_handler::FormatExceptHandlerExceptHandler,
PyFormatContext<'ast>, PyFormatContext<'ast>,
>; >;
fn format(&self) -> Self::Format<'_> { fn format(&self) -> Self::Format<'_> {
FormatRefWithRule::new( FormatRefWithRule::new(
self, self,
crate::other::excepthandler_except_handler::FormatExcepthandlerExceptHandler::default(), crate::other::except_handler_except_handler::FormatExceptHandlerExceptHandler::default(
),
) )
} }
} }
impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::ExcepthandlerExceptHandler { impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::ExceptHandlerExceptHandler {
type Format = FormatOwnedWithRule< type Format = FormatOwnedWithRule<
ast::ExcepthandlerExceptHandler, ast::ExceptHandlerExceptHandler,
crate::other::excepthandler_except_handler::FormatExcepthandlerExceptHandler, crate::other::except_handler_except_handler::FormatExceptHandlerExceptHandler,
PyFormatContext<'ast>, PyFormatContext<'ast>,
>; >;
fn into_format(self) -> Self::Format { fn into_format(self) -> Self::Format {
FormatOwnedWithRule::new( FormatOwnedWithRule::new(
self, self,
crate::other::excepthandler_except_handler::FormatExcepthandlerExceptHandler::default(), crate::other::except_handler_except_handler::FormatExceptHandlerExceptHandler::default(
),
) )
} }
} }
@ -2746,6 +2748,46 @@ impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::Arg {
} }
} }
impl FormatRule<ast::ArgWithDefault, PyFormatContext<'_>>
for crate::other::arg_with_default::FormatArgWithDefault
{
#[inline]
fn fmt(
&self,
node: &ast::ArgWithDefault,
f: &mut Formatter<PyFormatContext<'_>>,
) -> FormatResult<()> {
FormatNodeRule::<ast::ArgWithDefault>::fmt(self, node, f)
}
}
impl<'ast> AsFormat<PyFormatContext<'ast>> for ast::ArgWithDefault {
type Format<'a> = FormatRefWithRule<
'a,
ast::ArgWithDefault,
crate::other::arg_with_default::FormatArgWithDefault,
PyFormatContext<'ast>,
>;
fn format(&self) -> Self::Format<'_> {
FormatRefWithRule::new(
self,
crate::other::arg_with_default::FormatArgWithDefault::default(),
)
}
}
impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::ArgWithDefault {
type Format = FormatOwnedWithRule<
ast::ArgWithDefault,
crate::other::arg_with_default::FormatArgWithDefault,
PyFormatContext<'ast>,
>;
fn into_format(self) -> Self::Format {
FormatOwnedWithRule::new(
self,
crate::other::arg_with_default::FormatArgWithDefault::default(),
)
}
}
impl FormatRule<ast::Keyword, PyFormatContext<'_>> for crate::other::keyword::FormatKeyword { impl FormatRule<ast::Keyword, PyFormatContext<'_>> for crate::other::keyword::FormatKeyword {
#[inline] #[inline]
fn fmt(&self, node: &ast::Keyword, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> { fn fmt(&self, node: &ast::Keyword, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
@ -2795,35 +2837,35 @@ impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::Alias {
} }
} }
impl FormatRule<ast::Withitem, PyFormatContext<'_>> for crate::other::withitem::FormatWithitem { impl FormatRule<ast::WithItem, PyFormatContext<'_>> for crate::other::with_item::FormatWithItem {
#[inline] #[inline]
fn fmt( fn fmt(
&self, &self,
node: &ast::Withitem, node: &ast::WithItem,
f: &mut Formatter<PyFormatContext<'_>>, f: &mut Formatter<PyFormatContext<'_>>,
) -> FormatResult<()> { ) -> FormatResult<()> {
FormatNodeRule::<ast::Withitem>::fmt(self, node, f) FormatNodeRule::<ast::WithItem>::fmt(self, node, f)
} }
} }
impl<'ast> AsFormat<PyFormatContext<'ast>> for ast::Withitem { impl<'ast> AsFormat<PyFormatContext<'ast>> for ast::WithItem {
type Format<'a> = FormatRefWithRule< type Format<'a> = FormatRefWithRule<
'a, 'a,
ast::Withitem, ast::WithItem,
crate::other::withitem::FormatWithitem, crate::other::with_item::FormatWithItem,
PyFormatContext<'ast>, PyFormatContext<'ast>,
>; >;
fn format(&self) -> Self::Format<'_> { fn format(&self) -> Self::Format<'_> {
FormatRefWithRule::new(self, crate::other::withitem::FormatWithitem::default()) FormatRefWithRule::new(self, crate::other::with_item::FormatWithItem::default())
} }
} }
impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::Withitem { impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::WithItem {
type Format = FormatOwnedWithRule< type Format = FormatOwnedWithRule<
ast::Withitem, ast::WithItem,
crate::other::withitem::FormatWithitem, crate::other::with_item::FormatWithItem,
PyFormatContext<'ast>, PyFormatContext<'ast>,
>; >;
fn into_format(self) -> Self::Format { fn into_format(self) -> Self::Format {
FormatOwnedWithRule::new(self, crate::other::withitem::FormatWithitem::default()) FormatOwnedWithRule::new(self, crate::other::with_item::FormatWithItem::default())
} }
} }

View file

@ -0,0 +1,28 @@
use rustpython_parser::ast::ArgWithDefault;
use ruff_formatter::write;
use crate::prelude::*;
use crate::FormatNodeRule;
#[derive(Default)]
pub struct FormatArgWithDefault;
impl FormatNodeRule<ArgWithDefault> for FormatArgWithDefault {
fn fmt_fields(&self, item: &ArgWithDefault, f: &mut PyFormatter) -> FormatResult<()> {
let ArgWithDefault {
range: _,
def,
default,
} = item;
write!(f, [def.format()])?;
if let Some(default) = default {
let space = def.annotation.is_some().then_some(space());
write!(f, [space, text("="), space, default.format()])?;
}
Ok(())
}
}

View file

@ -1,12 +1,15 @@
use std::usize;
use rustpython_parser::ast::{Arguments, Ranged};
use ruff_formatter::{format_args, write};
use ruff_python_ast::node::{AnyNodeRef, AstNode};
use crate::comments::{dangling_node_comments, leading_node_comments}; use crate::comments::{dangling_node_comments, leading_node_comments};
use crate::context::NodeLevel; use crate::context::NodeLevel;
use crate::prelude::*; use crate::prelude::*;
use crate::trivia::{first_non_trivia_token, SimpleTokenizer, Token, TokenKind}; use crate::trivia::{first_non_trivia_token, SimpleTokenizer, Token, TokenKind};
use crate::FormatNodeRule; use crate::FormatNodeRule;
use ruff_formatter::{format_args, write, FormatError};
use ruff_python_ast::node::{AnyNodeRef, AstNode};
use rustpython_parser::ast::{Arg, Arguments, Expr, Ranged};
use std::usize;
#[derive(Default)] #[derive(Default)]
pub struct FormatArguments; pub struct FormatArguments;
@ -17,10 +20,8 @@ impl FormatNodeRule<Arguments> for FormatArguments {
range: _, range: _,
posonlyargs, posonlyargs,
args, args,
defaults,
vararg, vararg,
kwonlyargs, kwonlyargs,
kw_defaults,
kwarg, kwarg,
} = item; } = item;
@ -32,30 +33,30 @@ impl FormatNodeRule<Arguments> for FormatArguments {
let mut joiner = f.join_with(separator); let mut joiner = f.join_with(separator);
let mut last_node: Option<AnyNodeRef> = None; let mut last_node: Option<AnyNodeRef> = None;
let mut defaults = std::iter::repeat(None) for arg_with_default in posonlyargs {
.take(posonlyargs.len() + args.len() - defaults.len()) joiner.entry(&arg_with_default.into_format());
.chain(defaults.iter().map(Some));
for positional in posonlyargs { last_node = Some(
let default = defaults.next().ok_or(FormatError::SyntaxError)?; arg_with_default
joiner.entry(&ArgumentWithDefault { .default
argument: positional, .as_deref()
default, .map_or_else(|| (&arg_with_default.def).into(), AnyNodeRef::from),
}); );
last_node = Some(default.map_or_else(|| positional.into(), AnyNodeRef::from));
} }
if !posonlyargs.is_empty() { if !posonlyargs.is_empty() {
joiner.entry(&text("/")); joiner.entry(&text("/"));
} }
for argument in args { for arg_with_default in args {
let default = defaults.next().ok_or(FormatError::SyntaxError)?; joiner.entry(&arg_with_default.into_format());
joiner.entry(&ArgumentWithDefault { argument, default }); last_node = Some(
arg_with_default
last_node = Some(default.map_or_else(|| argument.into(), AnyNodeRef::from)); .default
.as_deref()
.map_or_else(|| (&arg_with_default.def).into(), AnyNodeRef::from),
);
} }
// kw only args need either a `*args` ahead of them capturing all var args or a `*` // kw only args need either a `*args` ahead of them capturing all var args or a `*`
@ -72,24 +73,17 @@ impl FormatNodeRule<Arguments> for FormatArguments {
joiner.entry(&text("*")); joiner.entry(&text("*"));
} }
debug_assert!(defaults.next().is_none()); for arg_with_default in kwonlyargs {
joiner.entry(&arg_with_default.into_format());
let mut defaults = std::iter::repeat(None) last_node = Some(
.take(kwonlyargs.len() - kw_defaults.len()) arg_with_default
.chain(kw_defaults.iter().map(Some)); .default
.as_deref()
for keyword_argument in kwonlyargs { .map_or_else(|| (&arg_with_default.def).into(), AnyNodeRef::from),
let default = defaults.next().ok_or(FormatError::SyntaxError)?; );
joiner.entry(&ArgumentWithDefault {
argument: keyword_argument,
default,
});
last_node = Some(default.map_or_else(|| keyword_argument.into(), AnyNodeRef::from));
} }
debug_assert!(defaults.next().is_none());
if let Some(kwarg) = kwarg { if let Some(kwarg) = kwarg {
joiner.entry(&format_args![ joiner.entry(&format_args![
leading_node_comments(kwarg.as_ref()), leading_node_comments(kwarg.as_ref()),
@ -173,21 +167,3 @@ impl FormatNodeRule<Arguments> for FormatArguments {
Ok(()) Ok(())
} }
} }
struct ArgumentWithDefault<'a> {
argument: &'a Arg,
default: Option<&'a Expr>,
}
impl Format<PyFormatContext<'_>> for ArgumentWithDefault<'_> {
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
write!(f, [self.argument.format()])?;
if let Some(default) = self.default {
let space = self.argument.annotation.is_some().then_some(space());
write!(f, [space, text("="), space, default.format()])?;
}
Ok(())
}
}

View file

@ -1,14 +1,14 @@
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
use ruff_formatter::{write, Buffer, FormatResult}; use ruff_formatter::{write, Buffer, FormatResult};
use rustpython_parser::ast::ExcepthandlerExceptHandler; use rustpython_parser::ast::ExceptHandlerExceptHandler;
#[derive(Default)] #[derive(Default)]
pub struct FormatExcepthandlerExceptHandler; pub struct FormatExceptHandlerExceptHandler;
impl FormatNodeRule<ExcepthandlerExceptHandler> for FormatExcepthandlerExceptHandler { impl FormatNodeRule<ExceptHandlerExceptHandler> for FormatExceptHandlerExceptHandler {
fn fmt_fields( fn fmt_fields(
&self, &self,
item: &ExcepthandlerExceptHandler, item: &ExceptHandlerExceptHandler,
f: &mut PyFormatter, f: &mut PyFormatter,
) -> FormatResult<()> { ) -> FormatResult<()> {
write!(f, [not_yet_implemented(item)]) write!(f, [not_yet_implemented(item)])

Some files were not shown because too many files have changed in this diff Show more