mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-27 04:19:18 +00:00
Avoid RUF008
if field annotation is immutable (#4039)
This commit is contained in:
parent
7fd44a3e12
commit
ba98149022
6 changed files with 147 additions and 132 deletions
|
@ -1,7 +1,10 @@
|
|||
use rustpython_parser::ast::{Expr, ExprKind};
|
||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Operator};
|
||||
|
||||
use ruff_python_ast::call_path::{from_unqualified_name, CallPath};
|
||||
use ruff_python_stdlib::typing::{PEP_585_BUILTINS_ELIGIBLE, PEP_593_SUBSCRIPTS, SUBSCRIPTS};
|
||||
use ruff_python_stdlib::typing::{
|
||||
IMMUTABLE_GENERIC_TYPES, IMMUTABLE_TYPES, PEP_585_BUILTINS_ELIGIBLE, PEP_593_SUBSCRIPTS,
|
||||
SUBSCRIPTS,
|
||||
};
|
||||
|
||||
use crate::context::Context;
|
||||
|
||||
|
@ -68,3 +71,53 @@ pub fn is_pep585_builtin(expr: &Expr, context: &Context) -> bool {
|
|||
PEP_585_BUILTINS_ELIGIBLE.contains(&call_path.as_slice())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_immutable_annotation(context: &Context, expr: &Expr) -> bool {
|
||||
match &expr.node {
|
||||
ExprKind::Name { .. } | ExprKind::Attribute { .. } => {
|
||||
context.resolve_call_path(expr).map_or(false, |call_path| {
|
||||
IMMUTABLE_TYPES
|
||||
.iter()
|
||||
.chain(IMMUTABLE_GENERIC_TYPES)
|
||||
.any(|target| call_path.as_slice() == *target)
|
||||
})
|
||||
}
|
||||
ExprKind::Subscript { value, slice, .. } => {
|
||||
context.resolve_call_path(value).map_or(false, |call_path| {
|
||||
if IMMUTABLE_GENERIC_TYPES
|
||||
.iter()
|
||||
.any(|target| call_path.as_slice() == *target)
|
||||
{
|
||||
true
|
||||
} else if call_path.as_slice() == ["typing", "Union"] {
|
||||
if let ExprKind::Tuple { elts, .. } = &slice.node {
|
||||
elts.iter().all(|elt| is_immutable_annotation(context, elt))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else if call_path.as_slice() == ["typing", "Optional"] {
|
||||
is_immutable_annotation(context, slice)
|
||||
} else if call_path.as_slice() == ["typing", "Annotated"] {
|
||||
if let ExprKind::Tuple { elts, .. } = &slice.node {
|
||||
elts.first()
|
||||
.map_or(false, |elt| is_immutable_annotation(context, elt))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
ExprKind::BinOp {
|
||||
left,
|
||||
op: Operator::BitOr,
|
||||
right,
|
||||
} => is_immutable_annotation(context, left) && is_immutable_annotation(context, right),
|
||||
ExprKind::Constant {
|
||||
value: Constant::None,
|
||||
..
|
||||
} => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue