mirror of
https://github.com/astral-sh/ruff
synced 2026-01-21 05:20:49 -05:00
PIE794: Detect duplicated declared class fields (#22717)
This commit is contained in:
@@ -50,3 +50,8 @@ class Person:
|
||||
name: str = "Foo"
|
||||
name: str = name + " Bar"
|
||||
name: str = "Bar" # PIE794
|
||||
|
||||
|
||||
class TextEdit:
|
||||
start_line: int
|
||||
start_line: int # PIE794
|
||||
|
||||
@@ -58,17 +58,17 @@ pub(crate) fn duplicate_class_field_definition(checker: &Checker, body: &[Stmt])
|
||||
let mut seen_targets: FxHashSet<&str> = FxHashSet::default();
|
||||
for stmt in body {
|
||||
// Extract the property name from the assignment statement.
|
||||
let target = match stmt {
|
||||
Stmt::Assign(ast::StmtAssign { targets, .. }) => {
|
||||
if let [Expr::Name(id)] = targets.as_slice() {
|
||||
id
|
||||
} else {
|
||||
let (target, value) = match stmt {
|
||||
Stmt::Assign(ast::StmtAssign { targets, value, .. }) => {
|
||||
let [Expr::Name(target)] = targets.as_slice() else {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
(target, Some(&**value))
|
||||
}
|
||||
Stmt::AnnAssign(ast::StmtAnnAssign { target, .. }) => {
|
||||
Stmt::AnnAssign(ast::StmtAnnAssign { target, value, .. }) => {
|
||||
if let Expr::Name(id) = target.as_ref() {
|
||||
id
|
||||
(id, value.as_deref())
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
@@ -77,24 +77,12 @@ pub(crate) fn duplicate_class_field_definition(checker: &Checker, body: &[Stmt])
|
||||
};
|
||||
|
||||
// If this is an unrolled augmented assignment (e.g., `x = x + 1`), skip it.
|
||||
match stmt {
|
||||
Stmt::Assign(ast::StmtAssign { value, .. }) => {
|
||||
if any_over_expr(value.as_ref(), &|expr| {
|
||||
expr.as_name_expr().is_some_and(|name| name.id == target.id)
|
||||
}) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Stmt::AnnAssign(ast::StmtAnnAssign {
|
||||
value: Some(value), ..
|
||||
}) => {
|
||||
if any_over_expr(value.as_ref(), &|expr| {
|
||||
expr.as_name_expr().is_some_and(|name| name.id == target.id)
|
||||
}) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
if let Some(value) = value
|
||||
&& any_over_expr(value, &|expr| {
|
||||
expr.as_name_expr().is_some_and(|name| name.id == target.id)
|
||||
})
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if !seen_targets.insert(target.id.as_str()) {
|
||||
|
||||
@@ -108,4 +108,22 @@ help: Remove duplicate field definition for `name`
|
||||
50 | name: str = "Foo"
|
||||
51 | name: str = name + " Bar"
|
||||
- name: str = "Bar" # PIE794
|
||||
52 |
|
||||
53 |
|
||||
54 | class TextEdit:
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
PIE794 [*] Class field `start_line` is defined multiple times
|
||||
--> PIE794.py:57:5
|
||||
|
|
||||
55 | class TextEdit:
|
||||
56 | start_line: int
|
||||
57 | start_line: int # PIE794
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: Remove duplicate field definition for `start_line`
|
||||
54 |
|
||||
55 | class TextEdit:
|
||||
56 | start_line: int
|
||||
- start_line: int # PIE794
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
Reference in New Issue
Block a user