[pylint] Add duplicate-bases rule (#4411)

This commit is contained in:
alm
2023-05-13 17:28:03 +03:00
committed by GitHub
parent 2f53781a77
commit 0a68636de3
9 changed files with 89 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
###
# Errors.
###
class A:
...
class B(A, A):
...
###
# Non-errors.
###
class C:
...
class D(C):
...
class E(A, C):
...

View File

@@ -761,6 +761,10 @@ where
if self.settings.rules.enabled(Rule::BuiltinVariableShadowing) {
flake8_builtins::rules::builtin_variable_shadowing(self, name, stmt);
}
if self.settings.rules.enabled(Rule::DuplicateBases) {
pylint::rules::duplicate_bases(self, name, bases);
}
}
StmtKind::Import(ast::StmtImport { names }) => {
if self.settings.rules.enabled(Rule::MultipleImportsOnOneLine) {

View File

@@ -213,6 +213,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<Rule> {
(Pylint, "W2901") => Rule::RedefinedLoopName,
(Pylint, "E0302") => Rule::UnexpectedSpecialMethodSignature,
(Pylint, "W3301") => Rule::NestedMinMax,
(Pylint, "E0241") => Rule::DuplicateBases,
// flake8-builtins
(Flake8Builtins, "001") => Rule::BuiltinVariableShadowing,

View File

@@ -190,6 +190,7 @@ ruff_macros::register_rules!(
rules::pylint::rules::LoggingTooManyArgs,
rules::pylint::rules::UnexpectedSpecialMethodSignature,
rules::pylint::rules::NestedMinMax,
rules::pylint::rules::DuplicateBases,
// flake8-builtins
rules::flake8_builtins::rules::BuiltinVariableShadowing,
rules::flake8_builtins::rules::BuiltinArgumentShadowing,

View File

@@ -46,6 +46,7 @@ mod tests {
#[test_case(Rule::ImportSelf, Path::new("import_self/module.py"); "PLW0406")]
#[test_case(Rule::InvalidAllFormat, Path::new("invalid_all_format.py"); "PLE0605")]
#[test_case(Rule::InvalidAllObject, Path::new("invalid_all_object.py"); "PLE0604")]
#[test_case(Rule::DuplicateBases, Path::new("duplicate_bases.py"); "PLE0241")]
#[test_case(Rule::InvalidCharacterBackspace, Path::new("invalid_characters.py"); "PLE2510")]
#[test_case(Rule::InvalidCharacterEsc, Path::new("invalid_characters.py"); "PLE2513")]
#[test_case(Rule::InvalidCharacterNul, Path::new("invalid_characters.py"); "PLE2514")]

View File

@@ -0,0 +1,42 @@
use std::hash::BuildHasherDefault;
use rustc_hash::FxHashSet;
use rustpython_parser::ast::{self, Expr, ExprKind, Identifier};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use crate::checkers::ast::Checker;
#[violation]
pub struct DuplicateBases {
base: String,
class: String,
}
impl Violation for DuplicateBases {
#[derive_message_formats]
fn message(&self) -> String {
let DuplicateBases { base, class } = self;
format!("Duplicate base `{base}` for class `{class}`")
}
}
/// PLE0241
pub(crate) fn duplicate_bases(checker: &mut Checker, name: &str, bases: &[Expr]) {
let mut seen: FxHashSet<&Identifier> =
FxHashSet::with_capacity_and_hasher(bases.len(), BuildHasherDefault::default());
for base in bases {
if let ExprKind::Name(ast::ExprName { id, .. }) = &base.node {
if !seen.insert(id) {
checker.diagnostics.push(Diagnostic::new(
DuplicateBases {
base: id.to_string(),
class: name.to_string(),
},
base.range(),
));
}
}
}
}

View File

@@ -8,6 +8,7 @@ pub(crate) use collapsible_else_if::{collapsible_else_if, CollapsibleElseIf};
pub(crate) use compare_to_empty_string::{compare_to_empty_string, CompareToEmptyString};
pub(crate) use comparison_of_constant::{comparison_of_constant, ComparisonOfConstant};
pub(crate) use continue_in_finally::{continue_in_finally, ContinueInFinally};
pub(crate) use duplicate_bases::{duplicate_bases, DuplicateBases};
pub(crate) use global_statement::{global_statement, GlobalStatement};
pub(crate) use global_variable_not_assigned::GlobalVariableNotAssigned;
pub(crate) use import_self::{import_from_self, import_self, ImportSelf};
@@ -57,6 +58,7 @@ mod collapsible_else_if;
mod compare_to_empty_string;
mod comparison_of_constant;
mod continue_in_finally;
mod duplicate_bases;
mod global_statement;
mod global_variable_not_assigned;
mod import_self;

View File

@@ -0,0 +1,11 @@
---
source: crates/ruff/src/rules/pylint/mod.rs
---
duplicate_bases.py:8:12: PLE0241 Duplicate base `A` for class `B`
|
8 | class B(A, A):
| ^ PLE0241
9 | ...
|

3
ruff.schema.json generated
View File

@@ -1959,6 +1959,9 @@
"PLE0116",
"PLE0117",
"PLE0118",
"PLE02",
"PLE024",
"PLE0241",
"PLE03",
"PLE030",
"PLE0302",