mirror of https://github.com/astral-sh/ruff
Implement `ComparableStmt` (#2826)
This commit is contained in:
parent
0e53ddc2b3
commit
5a34504149
|
|
@ -1,4 +1,4 @@
|
||||||
# These SHOULD change
|
# Errors
|
||||||
if a:
|
if a:
|
||||||
b
|
b
|
||||||
elif c:
|
elif c:
|
||||||
|
|
@ -52,9 +52,23 @@ if (
|
||||||
and k == 14
|
and k == 14
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
elif 1 == 2: pass
|
elif 1 == 2:
|
||||||
|
pass
|
||||||
|
|
||||||
# These SHOULD NOT change
|
failures = errors = skipped = disabled = 0
|
||||||
|
if result.eofs == "O":
|
||||||
|
pass
|
||||||
|
elif result.eofs == "S":
|
||||||
|
skipped = 1
|
||||||
|
elif result.eofs == "F":
|
||||||
|
failures = 1
|
||||||
|
elif result.eofs == "E":
|
||||||
|
errors = 1
|
||||||
|
else:
|
||||||
|
errors = 1
|
||||||
|
|
||||||
|
|
||||||
|
# OK
|
||||||
def complicated_calc(*arg, **kwargs):
|
def complicated_calc(*arg, **kwargs):
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@
|
||||||
|
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
use rustpython_parser::ast::{
|
use rustpython_parser::ast::{
|
||||||
Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, Expr, ExprContext, ExprKind, Keyword,
|
Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, Excepthandler,
|
||||||
Operator, Unaryop,
|
ExcepthandlerKind, Expr, ExprContext, ExprKind, Keyword, Operator, Stmt, StmtKind, Unaryop,
|
||||||
|
Withitem,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
|
|
@ -126,6 +127,36 @@ impl From<&Cmpop> for ComparableCmpop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct ComparableAlias<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
|
pub asname: Option<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a Alias> for ComparableAlias<'a> {
|
||||||
|
fn from(alias: &'a Alias) -> Self {
|
||||||
|
Self {
|
||||||
|
name: &alias.node.name,
|
||||||
|
asname: alias.node.asname.as_deref(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct ComparableWithitem<'a> {
|
||||||
|
pub context_expr: ComparableExpr<'a>,
|
||||||
|
pub optional_vars: Option<ComparableExpr<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a Withitem> for ComparableWithitem<'a> {
|
||||||
|
fn from(withitem: &'a Withitem) -> Self {
|
||||||
|
Self {
|
||||||
|
context_expr: (&withitem.context_expr).into(),
|
||||||
|
optional_vars: withitem.optional_vars.as_ref().map(Into::into),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum ComparableConstant<'a> {
|
pub enum ComparableConstant<'a> {
|
||||||
None,
|
None,
|
||||||
|
|
@ -147,9 +178,7 @@ impl<'a> From<&'a Constant> for ComparableConstant<'a> {
|
||||||
Constant::Str(value) => Self::Str(value),
|
Constant::Str(value) => Self::Str(value),
|
||||||
Constant::Bytes(value) => Self::Bytes(value),
|
Constant::Bytes(value) => Self::Bytes(value),
|
||||||
Constant::Int(value) => Self::Int(value),
|
Constant::Int(value) => Self::Int(value),
|
||||||
Constant::Tuple(value) => {
|
Constant::Tuple(value) => Self::Tuple(value.iter().map(Into::into).collect()),
|
||||||
Self::Tuple(value.iter().map(std::convert::Into::into).collect())
|
|
||||||
}
|
|
||||||
Constant::Float(value) => Self::Float(value.to_bits()),
|
Constant::Float(value) => Self::Float(value.to_bits()),
|
||||||
Constant::Complex { real, imag } => Self::Complex {
|
Constant::Complex { real, imag } => Self::Complex {
|
||||||
real: real.to_bits(),
|
real: real.to_bits(),
|
||||||
|
|
@ -174,37 +203,23 @@ pub struct ComparableArguments<'a> {
|
||||||
impl<'a> From<&'a Arguments> for ComparableArguments<'a> {
|
impl<'a> From<&'a Arguments> for ComparableArguments<'a> {
|
||||||
fn from(arguments: &'a Arguments) -> Self {
|
fn from(arguments: &'a Arguments) -> Self {
|
||||||
Self {
|
Self {
|
||||||
posonlyargs: arguments
|
posonlyargs: arguments.posonlyargs.iter().map(Into::into).collect(),
|
||||||
.posonlyargs
|
args: arguments.args.iter().map(Into::into).collect(),
|
||||||
.iter()
|
vararg: arguments.vararg.as_ref().map(Into::into),
|
||||||
.map(std::convert::Into::into)
|
kwonlyargs: arguments.kwonlyargs.iter().map(Into::into).collect(),
|
||||||
.collect(),
|
kw_defaults: arguments.kw_defaults.iter().map(Into::into).collect(),
|
||||||
args: arguments
|
kwarg: arguments.vararg.as_ref().map(Into::into),
|
||||||
.args
|
defaults: arguments.defaults.iter().map(Into::into).collect(),
|
||||||
.iter()
|
|
||||||
.map(std::convert::Into::into)
|
|
||||||
.collect(),
|
|
||||||
vararg: arguments.vararg.as_ref().map(std::convert::Into::into),
|
|
||||||
kwonlyargs: arguments
|
|
||||||
.kwonlyargs
|
|
||||||
.iter()
|
|
||||||
.map(std::convert::Into::into)
|
|
||||||
.collect(),
|
|
||||||
kw_defaults: arguments
|
|
||||||
.kw_defaults
|
|
||||||
.iter()
|
|
||||||
.map(std::convert::Into::into)
|
|
||||||
.collect(),
|
|
||||||
kwarg: arguments.vararg.as_ref().map(std::convert::Into::into),
|
|
||||||
defaults: arguments
|
|
||||||
.defaults
|
|
||||||
.iter()
|
|
||||||
.map(std::convert::Into::into)
|
|
||||||
.collect(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a Box<Arguments>> for ComparableArguments<'a> {
|
||||||
|
fn from(arguments: &'a Box<Arguments>) -> Self {
|
||||||
|
(&**arguments).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a Box<Arg>> for ComparableArg<'a> {
|
impl<'a> From<&'a Box<Arg>> for ComparableArg<'a> {
|
||||||
fn from(arg: &'a Box<Arg>) -> Self {
|
fn from(arg: &'a Box<Arg>) -> Self {
|
||||||
(&**arg).into()
|
(&**arg).into()
|
||||||
|
|
@ -222,7 +237,7 @@ impl<'a> From<&'a Arg> for ComparableArg<'a> {
|
||||||
fn from(arg: &'a Arg) -> Self {
|
fn from(arg: &'a Arg) -> Self {
|
||||||
Self {
|
Self {
|
||||||
arg: &arg.node.arg,
|
arg: &arg.node.arg,
|
||||||
annotation: arg.node.annotation.as_ref().map(std::convert::Into::into),
|
annotation: arg.node.annotation.as_ref().map(Into::into),
|
||||||
type_comment: arg.node.type_comment.as_deref(),
|
type_comment: arg.node.type_comment.as_deref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -256,16 +271,32 @@ impl<'a> From<&'a Comprehension> for ComparableComprehension<'a> {
|
||||||
Self {
|
Self {
|
||||||
target: (&comprehension.target).into(),
|
target: (&comprehension.target).into(),
|
||||||
iter: (&comprehension.iter).into(),
|
iter: (&comprehension.iter).into(),
|
||||||
ifs: comprehension
|
ifs: comprehension.ifs.iter().map(Into::into).collect(),
|
||||||
.ifs
|
|
||||||
.iter()
|
|
||||||
.map(std::convert::Into::into)
|
|
||||||
.collect(),
|
|
||||||
is_async: &comprehension.is_async,
|
is_async: &comprehension.is_async,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum ComparableExcepthandler<'a> {
|
||||||
|
ExceptHandler {
|
||||||
|
type_: Option<ComparableExpr<'a>>,
|
||||||
|
name: Option<&'a str>,
|
||||||
|
body: Vec<ComparableStmt<'a>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a Excepthandler> for ComparableExcepthandler<'a> {
|
||||||
|
fn from(excepthandler: &'a Excepthandler) -> Self {
|
||||||
|
let ExcepthandlerKind::ExceptHandler { type_, name, body } = &excepthandler.node;
|
||||||
|
Self::ExceptHandler {
|
||||||
|
type_: type_.as_ref().map(Into::into),
|
||||||
|
name: name.as_deref(),
|
||||||
|
body: body.iter().map(Into::into).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum ComparableExpr<'a> {
|
pub enum ComparableExpr<'a> {
|
||||||
BoolOp {
|
BoolOp {
|
||||||
|
|
@ -399,7 +430,7 @@ impl<'a> From<&'a Expr> for ComparableExpr<'a> {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::BoolOp { op, values } => Self::BoolOp {
|
ExprKind::BoolOp { op, values } => Self::BoolOp {
|
||||||
op: op.into(),
|
op: op.into(),
|
||||||
values: values.iter().map(std::convert::Into::into).collect(),
|
values: values.iter().map(Into::into).collect(),
|
||||||
},
|
},
|
||||||
ExprKind::NamedExpr { target, value } => Self::NamedExpr {
|
ExprKind::NamedExpr { target, value } => Self::NamedExpr {
|
||||||
target: target.into(),
|
target: target.into(),
|
||||||
|
|
@ -426,20 +457,20 @@ impl<'a> From<&'a Expr> for ComparableExpr<'a> {
|
||||||
ExprKind::Dict { keys, values } => Self::Dict {
|
ExprKind::Dict { keys, values } => Self::Dict {
|
||||||
keys: keys
|
keys: keys
|
||||||
.iter()
|
.iter()
|
||||||
.map(|expr| expr.as_ref().map(std::convert::Into::into))
|
.map(|expr| expr.as_ref().map(Into::into))
|
||||||
.collect(),
|
.collect(),
|
||||||
values: values.iter().map(std::convert::Into::into).collect(),
|
values: values.iter().map(Into::into).collect(),
|
||||||
},
|
},
|
||||||
ExprKind::Set { elts } => Self::Set {
|
ExprKind::Set { elts } => Self::Set {
|
||||||
elts: elts.iter().map(std::convert::Into::into).collect(),
|
elts: elts.iter().map(Into::into).collect(),
|
||||||
},
|
},
|
||||||
ExprKind::ListComp { elt, generators } => Self::ListComp {
|
ExprKind::ListComp { elt, generators } => Self::ListComp {
|
||||||
elt: elt.into(),
|
elt: elt.into(),
|
||||||
generators: generators.iter().map(std::convert::Into::into).collect(),
|
generators: generators.iter().map(Into::into).collect(),
|
||||||
},
|
},
|
||||||
ExprKind::SetComp { elt, generators } => Self::SetComp {
|
ExprKind::SetComp { elt, generators } => Self::SetComp {
|
||||||
elt: elt.into(),
|
elt: elt.into(),
|
||||||
generators: generators.iter().map(std::convert::Into::into).collect(),
|
generators: generators.iter().map(Into::into).collect(),
|
||||||
},
|
},
|
||||||
ExprKind::DictComp {
|
ExprKind::DictComp {
|
||||||
key,
|
key,
|
||||||
|
|
@ -448,17 +479,17 @@ impl<'a> From<&'a Expr> for ComparableExpr<'a> {
|
||||||
} => Self::DictComp {
|
} => Self::DictComp {
|
||||||
key: key.into(),
|
key: key.into(),
|
||||||
value: value.into(),
|
value: value.into(),
|
||||||
generators: generators.iter().map(std::convert::Into::into).collect(),
|
generators: generators.iter().map(Into::into).collect(),
|
||||||
},
|
},
|
||||||
ExprKind::GeneratorExp { elt, generators } => Self::GeneratorExp {
|
ExprKind::GeneratorExp { elt, generators } => Self::GeneratorExp {
|
||||||
elt: elt.into(),
|
elt: elt.into(),
|
||||||
generators: generators.iter().map(std::convert::Into::into).collect(),
|
generators: generators.iter().map(Into::into).collect(),
|
||||||
},
|
},
|
||||||
ExprKind::Await { value } => Self::Await {
|
ExprKind::Await { value } => Self::Await {
|
||||||
value: value.into(),
|
value: value.into(),
|
||||||
},
|
},
|
||||||
ExprKind::Yield { value } => Self::Yield {
|
ExprKind::Yield { value } => Self::Yield {
|
||||||
value: value.as_ref().map(std::convert::Into::into),
|
value: value.as_ref().map(Into::into),
|
||||||
},
|
},
|
||||||
ExprKind::YieldFrom { value } => Self::YieldFrom {
|
ExprKind::YieldFrom { value } => Self::YieldFrom {
|
||||||
value: value.into(),
|
value: value.into(),
|
||||||
|
|
@ -469,8 +500,8 @@ impl<'a> From<&'a Expr> for ComparableExpr<'a> {
|
||||||
comparators,
|
comparators,
|
||||||
} => Self::Compare {
|
} => Self::Compare {
|
||||||
left: left.into(),
|
left: left.into(),
|
||||||
ops: ops.iter().map(std::convert::Into::into).collect(),
|
ops: ops.iter().map(Into::into).collect(),
|
||||||
comparators: comparators.iter().map(std::convert::Into::into).collect(),
|
comparators: comparators.iter().map(Into::into).collect(),
|
||||||
},
|
},
|
||||||
ExprKind::Call {
|
ExprKind::Call {
|
||||||
func,
|
func,
|
||||||
|
|
@ -478,8 +509,8 @@ impl<'a> From<&'a Expr> for ComparableExpr<'a> {
|
||||||
keywords,
|
keywords,
|
||||||
} => Self::Call {
|
} => Self::Call {
|
||||||
func: func.into(),
|
func: func.into(),
|
||||||
args: args.iter().map(std::convert::Into::into).collect(),
|
args: args.iter().map(Into::into).collect(),
|
||||||
keywords: keywords.iter().map(std::convert::Into::into).collect(),
|
keywords: keywords.iter().map(Into::into).collect(),
|
||||||
},
|
},
|
||||||
ExprKind::FormattedValue {
|
ExprKind::FormattedValue {
|
||||||
value,
|
value,
|
||||||
|
|
@ -488,10 +519,10 @@ impl<'a> From<&'a Expr> for ComparableExpr<'a> {
|
||||||
} => Self::FormattedValue {
|
} => Self::FormattedValue {
|
||||||
value: value.into(),
|
value: value.into(),
|
||||||
conversion,
|
conversion,
|
||||||
format_spec: format_spec.as_ref().map(std::convert::Into::into),
|
format_spec: format_spec.as_ref().map(Into::into),
|
||||||
},
|
},
|
||||||
ExprKind::JoinedStr { values } => Self::JoinedStr {
|
ExprKind::JoinedStr { values } => Self::JoinedStr {
|
||||||
values: values.iter().map(std::convert::Into::into).collect(),
|
values: values.iter().map(Into::into).collect(),
|
||||||
},
|
},
|
||||||
ExprKind::Constant { value, kind } => Self::Constant {
|
ExprKind::Constant { value, kind } => Self::Constant {
|
||||||
value: value.into(),
|
value: value.into(),
|
||||||
|
|
@ -516,18 +547,314 @@ impl<'a> From<&'a Expr> for ComparableExpr<'a> {
|
||||||
ctx: ctx.into(),
|
ctx: ctx.into(),
|
||||||
},
|
},
|
||||||
ExprKind::List { elts, ctx } => Self::List {
|
ExprKind::List { elts, ctx } => Self::List {
|
||||||
elts: elts.iter().map(std::convert::Into::into).collect(),
|
elts: elts.iter().map(Into::into).collect(),
|
||||||
ctx: ctx.into(),
|
ctx: ctx.into(),
|
||||||
},
|
},
|
||||||
ExprKind::Tuple { elts, ctx } => Self::Tuple {
|
ExprKind::Tuple { elts, ctx } => Self::Tuple {
|
||||||
elts: elts.iter().map(std::convert::Into::into).collect(),
|
elts: elts.iter().map(Into::into).collect(),
|
||||||
ctx: ctx.into(),
|
ctx: ctx.into(),
|
||||||
},
|
},
|
||||||
ExprKind::Slice { lower, upper, step } => Self::Slice {
|
ExprKind::Slice { lower, upper, step } => Self::Slice {
|
||||||
lower: lower.as_ref().map(std::convert::Into::into),
|
lower: lower.as_ref().map(Into::into),
|
||||||
upper: upper.as_ref().map(std::convert::Into::into),
|
upper: upper.as_ref().map(Into::into),
|
||||||
step: step.as_ref().map(std::convert::Into::into),
|
step: step.as_ref().map(Into::into),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum ComparableStmt<'a> {
|
||||||
|
FunctionDef {
|
||||||
|
name: &'a str,
|
||||||
|
args: ComparableArguments<'a>,
|
||||||
|
body: Vec<ComparableStmt<'a>>,
|
||||||
|
decorator_list: Vec<ComparableExpr<'a>>,
|
||||||
|
returns: Option<ComparableExpr<'a>>,
|
||||||
|
type_comment: Option<&'a str>,
|
||||||
|
},
|
||||||
|
AsyncFunctionDef {
|
||||||
|
name: &'a str,
|
||||||
|
args: ComparableArguments<'a>,
|
||||||
|
body: Vec<ComparableStmt<'a>>,
|
||||||
|
decorator_list: Vec<ComparableExpr<'a>>,
|
||||||
|
returns: Option<ComparableExpr<'a>>,
|
||||||
|
type_comment: Option<&'a str>,
|
||||||
|
},
|
||||||
|
ClassDef {
|
||||||
|
name: &'a str,
|
||||||
|
bases: Vec<ComparableExpr<'a>>,
|
||||||
|
keywords: Vec<ComparableKeyword<'a>>,
|
||||||
|
body: Vec<ComparableStmt<'a>>,
|
||||||
|
decorator_list: Vec<ComparableExpr<'a>>,
|
||||||
|
},
|
||||||
|
Return {
|
||||||
|
value: Option<ComparableExpr<'a>>,
|
||||||
|
},
|
||||||
|
Delete {
|
||||||
|
targets: Vec<ComparableExpr<'a>>,
|
||||||
|
},
|
||||||
|
Assign {
|
||||||
|
targets: Vec<ComparableExpr<'a>>,
|
||||||
|
value: ComparableExpr<'a>,
|
||||||
|
type_comment: Option<&'a str>,
|
||||||
|
},
|
||||||
|
AugAssign {
|
||||||
|
target: ComparableExpr<'a>,
|
||||||
|
op: ComparableOperator,
|
||||||
|
value: ComparableExpr<'a>,
|
||||||
|
},
|
||||||
|
AnnAssign {
|
||||||
|
target: ComparableExpr<'a>,
|
||||||
|
annotation: ComparableExpr<'a>,
|
||||||
|
value: Option<ComparableExpr<'a>>,
|
||||||
|
simple: usize,
|
||||||
|
},
|
||||||
|
For {
|
||||||
|
target: ComparableExpr<'a>,
|
||||||
|
iter: ComparableExpr<'a>,
|
||||||
|
body: Vec<ComparableStmt<'a>>,
|
||||||
|
orelse: Vec<ComparableStmt<'a>>,
|
||||||
|
type_comment: Option<&'a str>,
|
||||||
|
},
|
||||||
|
AsyncFor {
|
||||||
|
target: ComparableExpr<'a>,
|
||||||
|
iter: ComparableExpr<'a>,
|
||||||
|
body: Vec<ComparableStmt<'a>>,
|
||||||
|
orelse: Vec<ComparableStmt<'a>>,
|
||||||
|
type_comment: Option<&'a str>,
|
||||||
|
},
|
||||||
|
While {
|
||||||
|
test: ComparableExpr<'a>,
|
||||||
|
body: Vec<ComparableStmt<'a>>,
|
||||||
|
orelse: Vec<ComparableStmt<'a>>,
|
||||||
|
},
|
||||||
|
If {
|
||||||
|
test: ComparableExpr<'a>,
|
||||||
|
body: Vec<ComparableStmt<'a>>,
|
||||||
|
orelse: Vec<ComparableStmt<'a>>,
|
||||||
|
},
|
||||||
|
With {
|
||||||
|
items: Vec<ComparableWithitem<'a>>,
|
||||||
|
body: Vec<ComparableStmt<'a>>,
|
||||||
|
type_comment: Option<&'a str>,
|
||||||
|
},
|
||||||
|
AsyncWith {
|
||||||
|
items: Vec<ComparableWithitem<'a>>,
|
||||||
|
body: Vec<ComparableStmt<'a>>,
|
||||||
|
type_comment: Option<&'a str>,
|
||||||
|
},
|
||||||
|
Raise {
|
||||||
|
exc: Option<ComparableExpr<'a>>,
|
||||||
|
cause: Option<ComparableExpr<'a>>,
|
||||||
|
},
|
||||||
|
Try {
|
||||||
|
body: Vec<ComparableStmt<'a>>,
|
||||||
|
handlers: Vec<ComparableExcepthandler<'a>>,
|
||||||
|
orelse: Vec<ComparableStmt<'a>>,
|
||||||
|
finalbody: Vec<ComparableStmt<'a>>,
|
||||||
|
},
|
||||||
|
Assert {
|
||||||
|
test: ComparableExpr<'a>,
|
||||||
|
msg: Option<ComparableExpr<'a>>,
|
||||||
|
},
|
||||||
|
Import {
|
||||||
|
names: Vec<ComparableAlias<'a>>,
|
||||||
|
},
|
||||||
|
ImportFrom {
|
||||||
|
module: Option<&'a str>,
|
||||||
|
names: Vec<ComparableAlias<'a>>,
|
||||||
|
level: Option<usize>,
|
||||||
|
},
|
||||||
|
Global {
|
||||||
|
names: Vec<&'a str>,
|
||||||
|
},
|
||||||
|
Nonlocal {
|
||||||
|
names: Vec<&'a str>,
|
||||||
|
},
|
||||||
|
Expr {
|
||||||
|
value: ComparableExpr<'a>,
|
||||||
|
},
|
||||||
|
Pass,
|
||||||
|
Break,
|
||||||
|
Continue,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a Stmt> for ComparableStmt<'a> {
|
||||||
|
fn from(stmt: &'a Stmt) -> Self {
|
||||||
|
match &stmt.node {
|
||||||
|
StmtKind::FunctionDef {
|
||||||
|
name,
|
||||||
|
args,
|
||||||
|
body,
|
||||||
|
decorator_list,
|
||||||
|
returns,
|
||||||
|
type_comment,
|
||||||
|
} => Self::FunctionDef {
|
||||||
|
name,
|
||||||
|
args: args.into(),
|
||||||
|
body: body.iter().map(Into::into).collect(),
|
||||||
|
decorator_list: decorator_list.iter().map(Into::into).collect(),
|
||||||
|
returns: returns.as_ref().map(Into::into),
|
||||||
|
type_comment: type_comment.as_ref().map(std::string::String::as_str),
|
||||||
|
},
|
||||||
|
StmtKind::AsyncFunctionDef {
|
||||||
|
name,
|
||||||
|
args,
|
||||||
|
body,
|
||||||
|
decorator_list,
|
||||||
|
returns,
|
||||||
|
type_comment,
|
||||||
|
} => Self::AsyncFunctionDef {
|
||||||
|
name,
|
||||||
|
args: args.into(),
|
||||||
|
body: body.iter().map(Into::into).collect(),
|
||||||
|
decorator_list: decorator_list.iter().map(Into::into).collect(),
|
||||||
|
returns: returns.as_ref().map(Into::into),
|
||||||
|
type_comment: type_comment.as_ref().map(std::string::String::as_str),
|
||||||
|
},
|
||||||
|
StmtKind::ClassDef {
|
||||||
|
name,
|
||||||
|
bases,
|
||||||
|
keywords,
|
||||||
|
body,
|
||||||
|
decorator_list,
|
||||||
|
} => Self::ClassDef {
|
||||||
|
name,
|
||||||
|
bases: bases.iter().map(Into::into).collect(),
|
||||||
|
keywords: keywords.iter().map(Into::into).collect(),
|
||||||
|
body: body.iter().map(Into::into).collect(),
|
||||||
|
decorator_list: decorator_list.iter().map(Into::into).collect(),
|
||||||
|
},
|
||||||
|
StmtKind::Return { value } => Self::Return {
|
||||||
|
value: value.as_ref().map(Into::into),
|
||||||
|
},
|
||||||
|
StmtKind::Delete { targets } => Self::Delete {
|
||||||
|
targets: targets.iter().map(Into::into).collect(),
|
||||||
|
},
|
||||||
|
StmtKind::Assign {
|
||||||
|
targets,
|
||||||
|
value,
|
||||||
|
type_comment,
|
||||||
|
} => Self::Assign {
|
||||||
|
targets: targets.iter().map(Into::into).collect(),
|
||||||
|
value: value.into(),
|
||||||
|
type_comment: type_comment.as_ref().map(std::string::String::as_str),
|
||||||
|
},
|
||||||
|
StmtKind::AugAssign { target, op, value } => Self::AugAssign {
|
||||||
|
target: target.into(),
|
||||||
|
op: op.into(),
|
||||||
|
value: value.into(),
|
||||||
|
},
|
||||||
|
StmtKind::AnnAssign {
|
||||||
|
target,
|
||||||
|
annotation,
|
||||||
|
value,
|
||||||
|
simple,
|
||||||
|
} => Self::AnnAssign {
|
||||||
|
target: target.into(),
|
||||||
|
annotation: annotation.into(),
|
||||||
|
value: value.as_ref().map(Into::into),
|
||||||
|
simple: *simple,
|
||||||
|
},
|
||||||
|
StmtKind::For {
|
||||||
|
target,
|
||||||
|
iter,
|
||||||
|
body,
|
||||||
|
orelse,
|
||||||
|
type_comment,
|
||||||
|
} => Self::For {
|
||||||
|
target: target.into(),
|
||||||
|
iter: iter.into(),
|
||||||
|
body: body.iter().map(Into::into).collect(),
|
||||||
|
orelse: orelse.iter().map(Into::into).collect(),
|
||||||
|
type_comment: type_comment.as_ref().map(String::as_str),
|
||||||
|
},
|
||||||
|
StmtKind::AsyncFor {
|
||||||
|
target,
|
||||||
|
iter,
|
||||||
|
body,
|
||||||
|
orelse,
|
||||||
|
type_comment,
|
||||||
|
} => Self::AsyncFor {
|
||||||
|
target: target.into(),
|
||||||
|
iter: iter.into(),
|
||||||
|
body: body.iter().map(Into::into).collect(),
|
||||||
|
orelse: orelse.iter().map(Into::into).collect(),
|
||||||
|
type_comment: type_comment.as_ref().map(String::as_str),
|
||||||
|
},
|
||||||
|
StmtKind::While { test, body, orelse } => Self::While {
|
||||||
|
test: test.into(),
|
||||||
|
body: body.iter().map(Into::into).collect(),
|
||||||
|
orelse: orelse.iter().map(Into::into).collect(),
|
||||||
|
},
|
||||||
|
StmtKind::If { test, body, orelse } => Self::If {
|
||||||
|
test: test.into(),
|
||||||
|
body: body.iter().map(Into::into).collect(),
|
||||||
|
orelse: orelse.iter().map(Into::into).collect(),
|
||||||
|
},
|
||||||
|
StmtKind::With {
|
||||||
|
items,
|
||||||
|
body,
|
||||||
|
type_comment,
|
||||||
|
} => Self::With {
|
||||||
|
items: items.iter().map(Into::into).collect(),
|
||||||
|
body: body.iter().map(Into::into).collect(),
|
||||||
|
type_comment: type_comment.as_ref().map(String::as_str),
|
||||||
|
},
|
||||||
|
StmtKind::AsyncWith {
|
||||||
|
items,
|
||||||
|
body,
|
||||||
|
type_comment,
|
||||||
|
} => Self::AsyncWith {
|
||||||
|
items: items.iter().map(Into::into).collect(),
|
||||||
|
body: body.iter().map(Into::into).collect(),
|
||||||
|
type_comment: type_comment.as_ref().map(String::as_str),
|
||||||
|
},
|
||||||
|
StmtKind::Match { .. } => unreachable!("StmtKind::Match is not supported"),
|
||||||
|
StmtKind::Raise { exc, cause } => Self::Raise {
|
||||||
|
exc: exc.as_ref().map(Into::into),
|
||||||
|
cause: cause.as_ref().map(Into::into),
|
||||||
|
},
|
||||||
|
StmtKind::Try {
|
||||||
|
body,
|
||||||
|
handlers,
|
||||||
|
orelse,
|
||||||
|
finalbody,
|
||||||
|
} => Self::Try {
|
||||||
|
body: body.iter().map(Into::into).collect(),
|
||||||
|
handlers: handlers.iter().map(Into::into).collect(),
|
||||||
|
orelse: orelse.iter().map(Into::into).collect(),
|
||||||
|
finalbody: finalbody.iter().map(Into::into).collect(),
|
||||||
|
},
|
||||||
|
StmtKind::Assert { test, msg } => Self::Assert {
|
||||||
|
test: test.into(),
|
||||||
|
msg: msg.as_ref().map(Into::into),
|
||||||
|
},
|
||||||
|
StmtKind::Import { names } => Self::Import {
|
||||||
|
names: names.iter().map(Into::into).collect(),
|
||||||
|
},
|
||||||
|
StmtKind::ImportFrom {
|
||||||
|
module,
|
||||||
|
names,
|
||||||
|
level,
|
||||||
|
} => Self::ImportFrom {
|
||||||
|
module: module.as_ref().map(String::as_str),
|
||||||
|
names: names.iter().map(Into::into).collect(),
|
||||||
|
level: *level,
|
||||||
|
},
|
||||||
|
StmtKind::Global { names } => Self::Global {
|
||||||
|
names: names.iter().map(String::as_str).collect(),
|
||||||
|
},
|
||||||
|
StmtKind::Nonlocal { names } => Self::Nonlocal {
|
||||||
|
names: names.iter().map(String::as_str).collect(),
|
||||||
|
},
|
||||||
|
StmtKind::Expr { value } => Self::Expr {
|
||||||
|
value: value.into(),
|
||||||
|
},
|
||||||
|
StmtKind::Pass => Self::Pass,
|
||||||
|
StmtKind::Break => Self::Break,
|
||||||
|
StmtKind::Continue => Self::Continue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
use log::error;
|
use log::error;
|
||||||
use rustpython_parser::ast::{Cmpop, Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{Cmpop, Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind};
|
||||||
use rustpython_parser::lexer;
|
|
||||||
use rustpython_parser::lexer::Tok;
|
|
||||||
|
|
||||||
use ruff_macros::{define_violation, derive_message_formats};
|
use ruff_macros::{define_violation, derive_message_formats};
|
||||||
|
|
||||||
use crate::ast::comparable::ComparableExpr;
|
use crate::ast::comparable::{ComparableExpr, ComparableStmt};
|
||||||
use crate::ast::helpers::{
|
use crate::ast::helpers::{
|
||||||
contains_call_path, contains_effect, create_expr, create_stmt, first_colon_range, has_comments,
|
contains_call_path, contains_effect, create_expr, create_stmt, first_colon_range, has_comments,
|
||||||
has_comments_in, unparse_expr, unparse_stmt,
|
has_comments_in, unparse_expr, unparse_stmt,
|
||||||
|
|
@ -15,9 +13,26 @@ use crate::checkers::ast::Checker;
|
||||||
use crate::fix::Fix;
|
use crate::fix::Fix;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::rules::flake8_simplify::rules::fix_if;
|
use crate::rules::flake8_simplify::rules::fix_if;
|
||||||
use crate::source_code::Locator;
|
|
||||||
use crate::violation::{AutofixKind, Availability, Violation};
|
use crate::violation::{AutofixKind, Availability, Violation};
|
||||||
|
|
||||||
|
fn compare_expr(expr1: &ComparableExpr, expr2: &ComparableExpr) -> bool {
|
||||||
|
expr1.eq(expr2)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_stmt(stmt1: &ComparableStmt, stmt2: &ComparableStmt) -> bool {
|
||||||
|
stmt1.eq(stmt2)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_body(body1: &[Stmt], body2: &[Stmt]) -> bool {
|
||||||
|
if body1.len() != body2.len() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
body1
|
||||||
|
.iter()
|
||||||
|
.zip(body2.iter())
|
||||||
|
.all(|(stmt1, stmt2)| compare_stmt(&stmt1.into(), &stmt2.into()))
|
||||||
|
}
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
pub struct CollapsibleIf {
|
pub struct CollapsibleIf {
|
||||||
pub fixable: bool,
|
pub fixable: bool,
|
||||||
|
|
@ -482,10 +497,6 @@ pub fn use_ternary_operator(checker: &mut Checker, stmt: &Stmt, parent: Option<&
|
||||||
checker.diagnostics.push(diagnostic);
|
checker.diagnostics.push(diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compare_expr(expr1: &ComparableExpr, expr2: &ComparableExpr) -> bool {
|
|
||||||
expr1.eq(expr2)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_if_body_pairs(orelse: &[Stmt], result: &mut Vec<Vec<Stmt>>) {
|
fn get_if_body_pairs(orelse: &[Stmt], result: &mut Vec<Vec<Stmt>>) {
|
||||||
if orelse.is_empty() {
|
if orelse.is_empty() {
|
||||||
return;
|
return;
|
||||||
|
|
@ -515,28 +526,6 @@ fn get_if_body_pairs(orelse: &[Stmt], result: &mut Vec<Vec<Stmt>>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_equal(locator: &Locator, stmts1: &[Stmt], stmts2: &[Stmt]) -> bool {
|
|
||||||
if stmts1.len() != stmts2.len() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (stmt1, stmt2) in stmts1.iter().zip(stmts2.iter()) {
|
|
||||||
let text1 = locator.slice_source_code_range(&Range::from_located(stmt1));
|
|
||||||
let text2 = locator.slice_source_code_range(&Range::from_located(stmt2));
|
|
||||||
let lexer1: Vec<Tok> = lexer::make_tokenizer(text1)
|
|
||||||
.flatten()
|
|
||||||
.map(|(_, tok, _)| tok)
|
|
||||||
.collect();
|
|
||||||
let lexer2: Vec<Tok> = lexer::make_tokenizer(text2)
|
|
||||||
.flatten()
|
|
||||||
.map(|(_, tok, _)| tok)
|
|
||||||
.collect();
|
|
||||||
if lexer1 != lexer2 {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
/// SIM114
|
/// SIM114
|
||||||
pub fn if_with_same_arms(checker: &mut Checker, body: &[Stmt], orelse: &[Stmt]) {
|
pub fn if_with_same_arms(checker: &mut Checker, body: &[Stmt], orelse: &[Stmt]) {
|
||||||
if orelse.is_empty() {
|
if orelse.is_empty() {
|
||||||
|
|
@ -553,7 +542,7 @@ pub fn if_with_same_arms(checker: &mut Checker, body: &[Stmt], orelse: &[Stmt])
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..(if_statements - 1) {
|
for i in 0..(if_statements - 1) {
|
||||||
if is_equal(checker.locator, &final_stmts[i], &final_stmts[i + 1]) {
|
if compare_body(&final_stmts[i], &final_stmts[i + 1]) {
|
||||||
let first = &final_stmts[i].first().unwrap();
|
let first = &final_stmts[i].first().unwrap();
|
||||||
let last = &final_stmts[i].last().unwrap();
|
let last = &final_stmts[i].last().unwrap();
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
|
|
|
||||||
|
|
@ -72,4 +72,44 @@ expression: diagnostics
|
||||||
column: 8
|
column: 8
|
||||||
fix: ~
|
fix: ~
|
||||||
parent: ~
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
IfWithSameArms: ~
|
||||||
|
location:
|
||||||
|
row: 66
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 66
|
||||||
|
column: 14
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
IfWithSameArms: ~
|
||||||
|
location:
|
||||||
|
row: 66
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 66
|
||||||
|
column: 14
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
IfWithSameArms: ~
|
||||||
|
location:
|
||||||
|
row: 66
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 66
|
||||||
|
column: 14
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
IfWithSameArms: ~
|
||||||
|
location:
|
||||||
|
row: 66
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 66
|
||||||
|
column: 14
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue