mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 06:11:43 +00:00
1149 lines
34 KiB
Rust
1149 lines
34 KiB
Rust
//! An equivalent object hierarchy to the [`Expr`] hierarchy, but with the
|
|
//! ability to compare expressions for equality (via [`Eq`] and [`Hash`]).
|
|
|
|
use num_bigint::BigInt;
|
|
use rustpython_parser::ast::{
|
|
self, Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, ConversionFlag,
|
|
Excepthandler, Expr, ExprContext, Identifier, Int, Keyword, MatchCase, Operator, Pattern, Stmt,
|
|
Unaryop, Withitem,
|
|
};
|
|
|
|
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
|
pub enum ComparableExprContext {
|
|
Load,
|
|
Store,
|
|
Del,
|
|
}
|
|
|
|
impl From<&ExprContext> for ComparableExprContext {
|
|
fn from(ctx: &ExprContext) -> Self {
|
|
match ctx {
|
|
ExprContext::Load => Self::Load,
|
|
ExprContext::Store => Self::Store,
|
|
ExprContext::Del => Self::Del,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
|
pub enum ComparableBoolop {
|
|
And,
|
|
Or,
|
|
}
|
|
|
|
impl From<&Boolop> for ComparableBoolop {
|
|
fn from(op: &Boolop) -> Self {
|
|
match op {
|
|
Boolop::And => Self::And,
|
|
Boolop::Or => Self::Or,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
|
pub enum ComparableOperator {
|
|
Add,
|
|
Sub,
|
|
Mult,
|
|
MatMult,
|
|
Div,
|
|
Mod,
|
|
Pow,
|
|
LShift,
|
|
RShift,
|
|
BitOr,
|
|
BitXor,
|
|
BitAnd,
|
|
FloorDiv,
|
|
}
|
|
|
|
impl From<&Operator> for ComparableOperator {
|
|
fn from(op: &Operator) -> Self {
|
|
match op {
|
|
Operator::Add => Self::Add,
|
|
Operator::Sub => Self::Sub,
|
|
Operator::Mult => Self::Mult,
|
|
Operator::MatMult => Self::MatMult,
|
|
Operator::Div => Self::Div,
|
|
Operator::Mod => Self::Mod,
|
|
Operator::Pow => Self::Pow,
|
|
Operator::LShift => Self::LShift,
|
|
Operator::RShift => Self::RShift,
|
|
Operator::BitOr => Self::BitOr,
|
|
Operator::BitXor => Self::BitXor,
|
|
Operator::BitAnd => Self::BitAnd,
|
|
Operator::FloorDiv => Self::FloorDiv,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
|
pub enum ComparableUnaryop {
|
|
Invert,
|
|
Not,
|
|
UAdd,
|
|
USub,
|
|
}
|
|
|
|
impl From<&Unaryop> for ComparableUnaryop {
|
|
fn from(op: &Unaryop) -> Self {
|
|
match op {
|
|
Unaryop::Invert => Self::Invert,
|
|
Unaryop::Not => Self::Not,
|
|
Unaryop::UAdd => Self::UAdd,
|
|
Unaryop::USub => Self::USub,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
|
pub enum ComparableCmpop {
|
|
Eq,
|
|
NotEq,
|
|
Lt,
|
|
LtE,
|
|
Gt,
|
|
GtE,
|
|
Is,
|
|
IsNot,
|
|
In,
|
|
NotIn,
|
|
}
|
|
|
|
impl From<&Cmpop> for ComparableCmpop {
|
|
fn from(op: &Cmpop) -> Self {
|
|
match op {
|
|
Cmpop::Eq => Self::Eq,
|
|
Cmpop::NotEq => Self::NotEq,
|
|
Cmpop::Lt => Self::Lt,
|
|
Cmpop::LtE => Self::LtE,
|
|
Cmpop::Gt => Self::Gt,
|
|
Cmpop::GtE => Self::GtE,
|
|
Cmpop::Is => Self::Is,
|
|
Cmpop::IsNot => Self::IsNot,
|
|
Cmpop::In => Self::In,
|
|
Cmpop::NotIn => Self::NotIn,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[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.name.as_str(),
|
|
asname: alias.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),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[allow(clippy::enum_variant_names)]
|
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
|
pub enum ComparablePattern<'a> {
|
|
MatchValue {
|
|
value: ComparableExpr<'a>,
|
|
},
|
|
MatchSingleton {
|
|
value: ComparableConstant<'a>,
|
|
},
|
|
MatchSequence {
|
|
patterns: Vec<ComparablePattern<'a>>,
|
|
},
|
|
MatchMapping {
|
|
keys: Vec<ComparableExpr<'a>>,
|
|
patterns: Vec<ComparablePattern<'a>>,
|
|
rest: Option<&'a str>,
|
|
},
|
|
MatchClass {
|
|
cls: ComparableExpr<'a>,
|
|
patterns: Vec<ComparablePattern<'a>>,
|
|
kwd_attrs: Vec<&'a str>,
|
|
kwd_patterns: Vec<ComparablePattern<'a>>,
|
|
},
|
|
MatchStar {
|
|
name: Option<&'a str>,
|
|
},
|
|
MatchAs {
|
|
pattern: Option<Box<ComparablePattern<'a>>>,
|
|
name: Option<&'a str>,
|
|
},
|
|
MatchOr {
|
|
patterns: Vec<ComparablePattern<'a>>,
|
|
},
|
|
}
|
|
|
|
impl<'a> From<&'a Pattern> for ComparablePattern<'a> {
|
|
fn from(pattern: &'a Pattern) -> Self {
|
|
match pattern {
|
|
Pattern::MatchValue(ast::PatternMatchValue { value, .. }) => Self::MatchValue {
|
|
value: value.into(),
|
|
},
|
|
Pattern::MatchSingleton(ast::PatternMatchSingleton { value, .. }) => {
|
|
Self::MatchSingleton {
|
|
value: value.into(),
|
|
}
|
|
}
|
|
Pattern::MatchSequence(ast::PatternMatchSequence { patterns, .. }) => {
|
|
Self::MatchSequence {
|
|
patterns: patterns.iter().map(Into::into).collect(),
|
|
}
|
|
}
|
|
Pattern::MatchMapping(ast::PatternMatchMapping {
|
|
keys,
|
|
patterns,
|
|
rest,
|
|
..
|
|
}) => Self::MatchMapping {
|
|
keys: keys.iter().map(Into::into).collect(),
|
|
patterns: patterns.iter().map(Into::into).collect(),
|
|
rest: rest.as_deref(),
|
|
},
|
|
Pattern::MatchClass(ast::PatternMatchClass {
|
|
cls,
|
|
patterns,
|
|
kwd_attrs,
|
|
kwd_patterns,
|
|
..
|
|
}) => Self::MatchClass {
|
|
cls: cls.into(),
|
|
patterns: patterns.iter().map(Into::into).collect(),
|
|
kwd_attrs: kwd_attrs.iter().map(Identifier::as_str).collect(),
|
|
kwd_patterns: kwd_patterns.iter().map(Into::into).collect(),
|
|
},
|
|
Pattern::MatchStar(ast::PatternMatchStar { name, .. }) => Self::MatchStar {
|
|
name: name.as_deref(),
|
|
},
|
|
Pattern::MatchAs(ast::PatternMatchAs { pattern, name, .. }) => Self::MatchAs {
|
|
pattern: pattern.as_ref().map(Into::into),
|
|
name: name.as_deref(),
|
|
},
|
|
Pattern::MatchOr(ast::PatternMatchOr { patterns, .. }) => Self::MatchOr {
|
|
patterns: patterns.iter().map(Into::into).collect(),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> From<&'a Box<Pattern>> for Box<ComparablePattern<'a>> {
|
|
fn from(pattern: &'a Box<Pattern>) -> Self {
|
|
Box::new((&**pattern).into())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
|
pub struct ComparableMatchCase<'a> {
|
|
pub pattern: ComparablePattern<'a>,
|
|
pub guard: Option<ComparableExpr<'a>>,
|
|
pub body: Vec<ComparableStmt<'a>>,
|
|
}
|
|
|
|
impl<'a> From<&'a MatchCase> for ComparableMatchCase<'a> {
|
|
fn from(match_case: &'a MatchCase) -> Self {
|
|
Self {
|
|
pattern: (&match_case.pattern).into(),
|
|
guard: match_case.guard.as_ref().map(Into::into),
|
|
body: match_case.body.iter().map(Into::into).collect(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
|
pub enum ComparableConstant<'a> {
|
|
None,
|
|
Bool(&'a bool),
|
|
Str(&'a str),
|
|
Bytes(&'a [u8]),
|
|
Int(&'a BigInt),
|
|
Tuple(Vec<ComparableConstant<'a>>),
|
|
Float(u64),
|
|
Complex { real: u64, imag: u64 },
|
|
Ellipsis,
|
|
}
|
|
|
|
impl<'a> From<&'a Constant> for ComparableConstant<'a> {
|
|
fn from(constant: &'a Constant) -> Self {
|
|
match constant {
|
|
Constant::None => Self::None,
|
|
Constant::Bool(value) => Self::Bool(value),
|
|
Constant::Str(value) => Self::Str(value),
|
|
Constant::Bytes(value) => Self::Bytes(value),
|
|
Constant::Int(value) => Self::Int(value),
|
|
Constant::Tuple(value) => Self::Tuple(value.iter().map(Into::into).collect()),
|
|
Constant::Float(value) => Self::Float(value.to_bits()),
|
|
Constant::Complex { real, imag } => Self::Complex {
|
|
real: real.to_bits(),
|
|
imag: imag.to_bits(),
|
|
},
|
|
Constant::Ellipsis => Self::Ellipsis,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
|
pub struct ComparableArguments<'a> {
|
|
pub posonlyargs: Vec<ComparableArg<'a>>,
|
|
pub args: Vec<ComparableArg<'a>>,
|
|
pub vararg: Option<ComparableArg<'a>>,
|
|
pub kwonlyargs: Vec<ComparableArg<'a>>,
|
|
pub kw_defaults: Vec<ComparableExpr<'a>>,
|
|
pub kwarg: Option<ComparableArg<'a>>,
|
|
pub defaults: Vec<ComparableExpr<'a>>,
|
|
}
|
|
|
|
impl<'a> From<&'a Arguments> for ComparableArguments<'a> {
|
|
fn from(arguments: &'a Arguments) -> Self {
|
|
Self {
|
|
posonlyargs: arguments.posonlyargs.iter().map(Into::into).collect(),
|
|
args: arguments.args.iter().map(Into::into).collect(),
|
|
vararg: arguments.vararg.as_ref().map(Into::into),
|
|
kwonlyargs: arguments.kwonlyargs.iter().map(Into::into).collect(),
|
|
kw_defaults: arguments.kw_defaults.iter().map(Into::into).collect(),
|
|
kwarg: arguments.vararg.as_ref().map(Into::into),
|
|
defaults: arguments.defaults.iter().map(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> {
|
|
fn from(arg: &'a Box<Arg>) -> Self {
|
|
(&**arg).into()
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
|
pub struct ComparableArg<'a> {
|
|
pub arg: &'a str,
|
|
pub annotation: Option<Box<ComparableExpr<'a>>>,
|
|
pub type_comment: Option<&'a str>,
|
|
}
|
|
|
|
impl<'a> From<&'a Arg> for ComparableArg<'a> {
|
|
fn from(arg: &'a Arg) -> Self {
|
|
Self {
|
|
arg: arg.arg.as_str(),
|
|
annotation: arg.annotation.as_ref().map(Into::into),
|
|
type_comment: arg.type_comment.as_deref(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
|
pub struct ComparableKeyword<'a> {
|
|
pub arg: Option<&'a str>,
|
|
pub value: ComparableExpr<'a>,
|
|
}
|
|
|
|
impl<'a> From<&'a Keyword> for ComparableKeyword<'a> {
|
|
fn from(keyword: &'a Keyword) -> Self {
|
|
Self {
|
|
arg: keyword.arg.as_ref().map(Identifier::as_str),
|
|
value: (&keyword.value).into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
|
pub struct ComparableComprehension<'a> {
|
|
pub target: ComparableExpr<'a>,
|
|
pub iter: ComparableExpr<'a>,
|
|
pub ifs: Vec<ComparableExpr<'a>>,
|
|
pub is_async: bool,
|
|
}
|
|
|
|
impl<'a> From<&'a Comprehension> for ComparableComprehension<'a> {
|
|
fn from(comprehension: &'a Comprehension) -> Self {
|
|
Self {
|
|
target: (&comprehension.target).into(),
|
|
iter: (&comprehension.iter).into(),
|
|
ifs: comprehension.ifs.iter().map(Into::into).collect(),
|
|
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 Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler {
|
|
type_, name, body, ..
|
|
}) = excepthandler;
|
|
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)]
|
|
pub enum ComparableExpr<'a> {
|
|
BoolOp {
|
|
op: ComparableBoolop,
|
|
values: Vec<ComparableExpr<'a>>,
|
|
},
|
|
NamedExpr {
|
|
target: Box<ComparableExpr<'a>>,
|
|
value: Box<ComparableExpr<'a>>,
|
|
},
|
|
BinOp {
|
|
left: Box<ComparableExpr<'a>>,
|
|
op: ComparableOperator,
|
|
right: Box<ComparableExpr<'a>>,
|
|
},
|
|
UnaryOp {
|
|
op: ComparableUnaryop,
|
|
operand: Box<ComparableExpr<'a>>,
|
|
},
|
|
Lambda {
|
|
args: ComparableArguments<'a>,
|
|
body: Box<ComparableExpr<'a>>,
|
|
},
|
|
IfExp {
|
|
test: Box<ComparableExpr<'a>>,
|
|
body: Box<ComparableExpr<'a>>,
|
|
orelse: Box<ComparableExpr<'a>>,
|
|
},
|
|
Dict {
|
|
keys: Vec<Option<ComparableExpr<'a>>>,
|
|
values: Vec<ComparableExpr<'a>>,
|
|
},
|
|
Set {
|
|
elts: Vec<ComparableExpr<'a>>,
|
|
},
|
|
ListComp {
|
|
elt: Box<ComparableExpr<'a>>,
|
|
generators: Vec<ComparableComprehension<'a>>,
|
|
},
|
|
SetComp {
|
|
elt: Box<ComparableExpr<'a>>,
|
|
generators: Vec<ComparableComprehension<'a>>,
|
|
},
|
|
DictComp {
|
|
key: Box<ComparableExpr<'a>>,
|
|
value: Box<ComparableExpr<'a>>,
|
|
generators: Vec<ComparableComprehension<'a>>,
|
|
},
|
|
GeneratorExp {
|
|
elt: Box<ComparableExpr<'a>>,
|
|
generators: Vec<ComparableComprehension<'a>>,
|
|
},
|
|
Await {
|
|
value: Box<ComparableExpr<'a>>,
|
|
},
|
|
Yield {
|
|
value: Option<Box<ComparableExpr<'a>>>,
|
|
},
|
|
YieldFrom {
|
|
value: Box<ComparableExpr<'a>>,
|
|
},
|
|
Compare {
|
|
left: Box<ComparableExpr<'a>>,
|
|
ops: Vec<ComparableCmpop>,
|
|
comparators: Vec<ComparableExpr<'a>>,
|
|
},
|
|
Call {
|
|
func: Box<ComparableExpr<'a>>,
|
|
args: Vec<ComparableExpr<'a>>,
|
|
keywords: Vec<ComparableKeyword<'a>>,
|
|
},
|
|
FormattedValue {
|
|
value: Box<ComparableExpr<'a>>,
|
|
conversion: ConversionFlag,
|
|
format_spec: Option<Box<ComparableExpr<'a>>>,
|
|
},
|
|
JoinedStr {
|
|
values: Vec<ComparableExpr<'a>>,
|
|
},
|
|
Constant {
|
|
value: ComparableConstant<'a>,
|
|
kind: Option<&'a str>,
|
|
},
|
|
Attribute {
|
|
value: Box<ComparableExpr<'a>>,
|
|
attr: &'a str,
|
|
ctx: ComparableExprContext,
|
|
},
|
|
Subscript {
|
|
value: Box<ComparableExpr<'a>>,
|
|
slice: Box<ComparableExpr<'a>>,
|
|
ctx: ComparableExprContext,
|
|
},
|
|
Starred {
|
|
value: Box<ComparableExpr<'a>>,
|
|
ctx: ComparableExprContext,
|
|
},
|
|
Name {
|
|
id: &'a str,
|
|
ctx: ComparableExprContext,
|
|
},
|
|
List {
|
|
elts: Vec<ComparableExpr<'a>>,
|
|
ctx: ComparableExprContext,
|
|
},
|
|
Tuple {
|
|
elts: Vec<ComparableExpr<'a>>,
|
|
ctx: ComparableExprContext,
|
|
},
|
|
Slice {
|
|
lower: Option<Box<ComparableExpr<'a>>>,
|
|
upper: Option<Box<ComparableExpr<'a>>>,
|
|
step: Option<Box<ComparableExpr<'a>>>,
|
|
},
|
|
}
|
|
|
|
impl<'a> From<&'a Box<Expr>> for Box<ComparableExpr<'a>> {
|
|
fn from(expr: &'a Box<Expr>) -> Self {
|
|
Box::new((&**expr).into())
|
|
}
|
|
}
|
|
|
|
impl<'a> From<&'a Box<Expr>> for ComparableExpr<'a> {
|
|
fn from(expr: &'a Box<Expr>) -> Self {
|
|
(&**expr).into()
|
|
}
|
|
}
|
|
|
|
impl<'a> From<&'a Expr> for ComparableExpr<'a> {
|
|
fn from(expr: &'a Expr) -> Self {
|
|
match expr {
|
|
Expr::BoolOp(ast::ExprBoolOp {
|
|
op,
|
|
values,
|
|
range: _range,
|
|
}) => Self::BoolOp {
|
|
op: op.into(),
|
|
values: values.iter().map(Into::into).collect(),
|
|
},
|
|
Expr::NamedExpr(ast::ExprNamedExpr {
|
|
target,
|
|
value,
|
|
range: _range,
|
|
}) => Self::NamedExpr {
|
|
target: target.into(),
|
|
value: value.into(),
|
|
},
|
|
Expr::BinOp(ast::ExprBinOp {
|
|
left,
|
|
op,
|
|
right,
|
|
range: _range,
|
|
}) => Self::BinOp {
|
|
left: left.into(),
|
|
op: op.into(),
|
|
right: right.into(),
|
|
},
|
|
Expr::UnaryOp(ast::ExprUnaryOp {
|
|
op,
|
|
operand,
|
|
range: _range,
|
|
}) => Self::UnaryOp {
|
|
op: op.into(),
|
|
operand: operand.into(),
|
|
},
|
|
Expr::Lambda(ast::ExprLambda {
|
|
args,
|
|
body,
|
|
range: _range,
|
|
}) => Self::Lambda {
|
|
args: (&**args).into(),
|
|
body: body.into(),
|
|
},
|
|
Expr::IfExp(ast::ExprIfExp {
|
|
test,
|
|
body,
|
|
orelse,
|
|
range: _range,
|
|
}) => Self::IfExp {
|
|
test: test.into(),
|
|
body: body.into(),
|
|
orelse: orelse.into(),
|
|
},
|
|
Expr::Dict(ast::ExprDict {
|
|
keys,
|
|
values,
|
|
range: _range,
|
|
}) => Self::Dict {
|
|
keys: keys
|
|
.iter()
|
|
.map(|expr| expr.as_ref().map(Into::into))
|
|
.collect(),
|
|
values: values.iter().map(Into::into).collect(),
|
|
},
|
|
Expr::Set(ast::ExprSet {
|
|
elts,
|
|
range: _range,
|
|
}) => Self::Set {
|
|
elts: elts.iter().map(Into::into).collect(),
|
|
},
|
|
Expr::ListComp(ast::ExprListComp {
|
|
elt,
|
|
generators,
|
|
range: _range,
|
|
}) => Self::ListComp {
|
|
elt: elt.into(),
|
|
generators: generators.iter().map(Into::into).collect(),
|
|
},
|
|
Expr::SetComp(ast::ExprSetComp {
|
|
elt,
|
|
generators,
|
|
range: _range,
|
|
}) => Self::SetComp {
|
|
elt: elt.into(),
|
|
generators: generators.iter().map(Into::into).collect(),
|
|
},
|
|
Expr::DictComp(ast::ExprDictComp {
|
|
key,
|
|
value,
|
|
generators,
|
|
range: _range,
|
|
}) => Self::DictComp {
|
|
key: key.into(),
|
|
value: value.into(),
|
|
generators: generators.iter().map(Into::into).collect(),
|
|
},
|
|
Expr::GeneratorExp(ast::ExprGeneratorExp {
|
|
elt,
|
|
generators,
|
|
range: _range,
|
|
}) => Self::GeneratorExp {
|
|
elt: elt.into(),
|
|
generators: generators.iter().map(Into::into).collect(),
|
|
},
|
|
Expr::Await(ast::ExprAwait {
|
|
value,
|
|
range: _range,
|
|
}) => Self::Await {
|
|
value: value.into(),
|
|
},
|
|
Expr::Yield(ast::ExprYield {
|
|
value,
|
|
range: _range,
|
|
}) => Self::Yield {
|
|
value: value.as_ref().map(Into::into),
|
|
},
|
|
Expr::YieldFrom(ast::ExprYieldFrom {
|
|
value,
|
|
range: _range,
|
|
}) => Self::YieldFrom {
|
|
value: value.into(),
|
|
},
|
|
Expr::Compare(ast::ExprCompare {
|
|
left,
|
|
ops,
|
|
comparators,
|
|
range: _range,
|
|
}) => Self::Compare {
|
|
left: left.into(),
|
|
ops: ops.iter().map(Into::into).collect(),
|
|
comparators: comparators.iter().map(Into::into).collect(),
|
|
},
|
|
Expr::Call(ast::ExprCall {
|
|
func,
|
|
args,
|
|
keywords,
|
|
range: _range,
|
|
}) => Self::Call {
|
|
func: func.into(),
|
|
args: args.iter().map(Into::into).collect(),
|
|
keywords: keywords.iter().map(Into::into).collect(),
|
|
},
|
|
Expr::FormattedValue(ast::ExprFormattedValue {
|
|
value,
|
|
conversion,
|
|
format_spec,
|
|
range: _range,
|
|
}) => Self::FormattedValue {
|
|
value: value.into(),
|
|
conversion: *conversion,
|
|
format_spec: format_spec.as_ref().map(Into::into),
|
|
},
|
|
Expr::JoinedStr(ast::ExprJoinedStr {
|
|
values,
|
|
range: _range,
|
|
}) => Self::JoinedStr {
|
|
values: values.iter().map(Into::into).collect(),
|
|
},
|
|
Expr::Constant(ast::ExprConstant {
|
|
value,
|
|
kind,
|
|
range: _range,
|
|
}) => Self::Constant {
|
|
value: value.into(),
|
|
kind: kind.as_ref().map(String::as_str),
|
|
},
|
|
Expr::Attribute(ast::ExprAttribute {
|
|
value,
|
|
attr,
|
|
ctx,
|
|
range: _range,
|
|
}) => Self::Attribute {
|
|
value: value.into(),
|
|
attr: attr.as_str(),
|
|
ctx: ctx.into(),
|
|
},
|
|
Expr::Subscript(ast::ExprSubscript {
|
|
value,
|
|
slice,
|
|
ctx,
|
|
range: _range,
|
|
}) => Self::Subscript {
|
|
value: value.into(),
|
|
slice: slice.into(),
|
|
ctx: ctx.into(),
|
|
},
|
|
Expr::Starred(ast::ExprStarred {
|
|
value,
|
|
ctx,
|
|
range: _range,
|
|
}) => Self::Starred {
|
|
value: value.into(),
|
|
ctx: ctx.into(),
|
|
},
|
|
Expr::Name(ast::ExprName {
|
|
id,
|
|
ctx,
|
|
range: _range,
|
|
}) => Self::Name {
|
|
id: id.as_str(),
|
|
ctx: ctx.into(),
|
|
},
|
|
Expr::List(ast::ExprList {
|
|
elts,
|
|
ctx,
|
|
range: _range,
|
|
}) => Self::List {
|
|
elts: elts.iter().map(Into::into).collect(),
|
|
ctx: ctx.into(),
|
|
},
|
|
Expr::Tuple(ast::ExprTuple {
|
|
elts,
|
|
ctx,
|
|
range: _range,
|
|
}) => Self::Tuple {
|
|
elts: elts.iter().map(Into::into).collect(),
|
|
ctx: ctx.into(),
|
|
},
|
|
Expr::Slice(ast::ExprSlice {
|
|
lower,
|
|
upper,
|
|
step,
|
|
range: _range,
|
|
}) => Self::Slice {
|
|
lower: lower.as_ref().map(Into::into),
|
|
upper: upper.as_ref().map(Into::into),
|
|
step: step.as_ref().map(Into::into),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
#[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: bool,
|
|
},
|
|
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>,
|
|
},
|
|
Match {
|
|
subject: ComparableExpr<'a>,
|
|
cases: Vec<ComparableMatchCase<'a>>,
|
|
},
|
|
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>>,
|
|
},
|
|
TryStar {
|
|
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<Int>,
|
|
},
|
|
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 {
|
|
Stmt::FunctionDef(ast::StmtFunctionDef {
|
|
name,
|
|
args,
|
|
body,
|
|
decorator_list,
|
|
returns,
|
|
type_comment,
|
|
range: _range,
|
|
}) => Self::FunctionDef {
|
|
name: name.as_str(),
|
|
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(String::as_str),
|
|
},
|
|
Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef {
|
|
name,
|
|
args,
|
|
body,
|
|
decorator_list,
|
|
returns,
|
|
type_comment,
|
|
range: _range,
|
|
}) => Self::AsyncFunctionDef {
|
|
name: name.as_str(),
|
|
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(String::as_str),
|
|
},
|
|
Stmt::ClassDef(ast::StmtClassDef {
|
|
name,
|
|
bases,
|
|
keywords,
|
|
body,
|
|
decorator_list,
|
|
range: _range,
|
|
}) => Self::ClassDef {
|
|
name: name.as_str(),
|
|
bases: bases.iter().map(Into::into).collect(),
|
|
keywords: keywords.iter().map(Into::into).collect(),
|
|
body: body.iter().map(Into::into).collect(),
|
|
decorator_list: decorator_list.iter().map(Into::into).collect(),
|
|
},
|
|
Stmt::Return(ast::StmtReturn {
|
|
value,
|
|
range: _range,
|
|
}) => Self::Return {
|
|
value: value.as_ref().map(Into::into),
|
|
},
|
|
Stmt::Delete(ast::StmtDelete {
|
|
targets,
|
|
range: _range,
|
|
}) => Self::Delete {
|
|
targets: targets.iter().map(Into::into).collect(),
|
|
},
|
|
Stmt::Assign(ast::StmtAssign {
|
|
targets,
|
|
value,
|
|
type_comment,
|
|
range: _range,
|
|
}) => Self::Assign {
|
|
targets: targets.iter().map(Into::into).collect(),
|
|
value: value.into(),
|
|
type_comment: type_comment.as_ref().map(String::as_str),
|
|
},
|
|
Stmt::AugAssign(ast::StmtAugAssign {
|
|
target,
|
|
op,
|
|
value,
|
|
range: _range,
|
|
}) => Self::AugAssign {
|
|
target: target.into(),
|
|
op: op.into(),
|
|
value: value.into(),
|
|
},
|
|
Stmt::AnnAssign(ast::StmtAnnAssign {
|
|
target,
|
|
annotation,
|
|
value,
|
|
simple,
|
|
range: _range,
|
|
}) => Self::AnnAssign {
|
|
target: target.into(),
|
|
annotation: annotation.into(),
|
|
value: value.as_ref().map(Into::into),
|
|
simple: *simple,
|
|
},
|
|
Stmt::For(ast::StmtFor {
|
|
target,
|
|
iter,
|
|
body,
|
|
orelse,
|
|
type_comment,
|
|
range: _range,
|
|
}) => 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),
|
|
},
|
|
Stmt::AsyncFor(ast::StmtAsyncFor {
|
|
target,
|
|
iter,
|
|
body,
|
|
orelse,
|
|
type_comment,
|
|
range: _range,
|
|
}) => 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),
|
|
},
|
|
Stmt::While(ast::StmtWhile {
|
|
test,
|
|
body,
|
|
orelse,
|
|
range: _range,
|
|
}) => Self::While {
|
|
test: test.into(),
|
|
body: body.iter().map(Into::into).collect(),
|
|
orelse: orelse.iter().map(Into::into).collect(),
|
|
},
|
|
Stmt::If(ast::StmtIf {
|
|
test,
|
|
body,
|
|
orelse,
|
|
range: _range,
|
|
}) => Self::If {
|
|
test: test.into(),
|
|
body: body.iter().map(Into::into).collect(),
|
|
orelse: orelse.iter().map(Into::into).collect(),
|
|
},
|
|
Stmt::With(ast::StmtWith {
|
|
items,
|
|
body,
|
|
type_comment,
|
|
range: _range,
|
|
}) => Self::With {
|
|
items: items.iter().map(Into::into).collect(),
|
|
body: body.iter().map(Into::into).collect(),
|
|
type_comment: type_comment.as_ref().map(String::as_str),
|
|
},
|
|
Stmt::AsyncWith(ast::StmtAsyncWith {
|
|
items,
|
|
body,
|
|
type_comment,
|
|
range: _range,
|
|
}) => Self::AsyncWith {
|
|
items: items.iter().map(Into::into).collect(),
|
|
body: body.iter().map(Into::into).collect(),
|
|
type_comment: type_comment.as_ref().map(String::as_str),
|
|
},
|
|
Stmt::Match(ast::StmtMatch {
|
|
subject,
|
|
cases,
|
|
range: _range,
|
|
}) => Self::Match {
|
|
subject: subject.into(),
|
|
cases: cases.iter().map(Into::into).collect(),
|
|
},
|
|
Stmt::Raise(ast::StmtRaise {
|
|
exc,
|
|
cause,
|
|
range: _range,
|
|
}) => Self::Raise {
|
|
exc: exc.as_ref().map(Into::into),
|
|
cause: cause.as_ref().map(Into::into),
|
|
},
|
|
Stmt::Try(ast::StmtTry {
|
|
body,
|
|
handlers,
|
|
orelse,
|
|
finalbody,
|
|
range: _range,
|
|
}) => Self::Try {
|
|
body: body.iter().map(Into::into).collect(),
|
|
handlers: handlers.iter().map(Into::into).collect(),
|
|
orelse: orelse.iter().map(Into::into).collect(),
|
|
finalbody: finalbody.iter().map(Into::into).collect(),
|
|
},
|
|
Stmt::TryStar(ast::StmtTryStar {
|
|
body,
|
|
handlers,
|
|
orelse,
|
|
finalbody,
|
|
range: _range,
|
|
}) => Self::TryStar {
|
|
body: body.iter().map(Into::into).collect(),
|
|
handlers: handlers.iter().map(Into::into).collect(),
|
|
orelse: orelse.iter().map(Into::into).collect(),
|
|
finalbody: finalbody.iter().map(Into::into).collect(),
|
|
},
|
|
Stmt::Assert(ast::StmtAssert {
|
|
test,
|
|
msg,
|
|
range: _range,
|
|
}) => Self::Assert {
|
|
test: test.into(),
|
|
msg: msg.as_ref().map(Into::into),
|
|
},
|
|
Stmt::Import(ast::StmtImport {
|
|
names,
|
|
range: _range,
|
|
}) => Self::Import {
|
|
names: names.iter().map(Into::into).collect(),
|
|
},
|
|
Stmt::ImportFrom(ast::StmtImportFrom {
|
|
module,
|
|
names,
|
|
level,
|
|
range: _range,
|
|
}) => Self::ImportFrom {
|
|
module: module.as_deref(),
|
|
names: names.iter().map(Into::into).collect(),
|
|
level: *level,
|
|
},
|
|
Stmt::Global(ast::StmtGlobal {
|
|
names,
|
|
range: _range,
|
|
}) => Self::Global {
|
|
names: names.iter().map(Identifier::as_str).collect(),
|
|
},
|
|
Stmt::Nonlocal(ast::StmtNonlocal {
|
|
names,
|
|
range: _range,
|
|
}) => Self::Nonlocal {
|
|
names: names.iter().map(Identifier::as_str).collect(),
|
|
},
|
|
Stmt::Expr(ast::StmtExpr {
|
|
value,
|
|
range: _range,
|
|
}) => Self::Expr {
|
|
value: value.into(),
|
|
},
|
|
Stmt::Pass(_) => Self::Pass,
|
|
Stmt::Break(_) => Self::Break,
|
|
Stmt::Continue(_) => Self::Continue,
|
|
}
|
|
}
|
|
}
|