diff --git a/crates/ruff_linter/resources/test/fixtures/pylint/E1519.py b/crates/ruff_linter/resources/test/fixtures/pylint/E1519.py new file mode 100644 index 00000000000000..f12911540e2d58 --- /dev/null +++ b/crates/ruff_linter/resources/test/fixtures/pylint/E1519.py @@ -0,0 +1,8 @@ +from functools import singledispatch + + +class Board: + @singledispatch # [singledispatch-method] + @classmethod + def convert_position(cls, position): + pass diff --git a/crates/ruff_linter/src/checkers/ast/analyze/deferred_scopes.rs b/crates/ruff_linter/src/checkers/ast/analyze/deferred_scopes.rs index e070ae5adbc0b0..a74a170c017754 100644 --- a/crates/ruff_linter/src/checkers/ast/analyze/deferred_scopes.rs +++ b/crates/ruff_linter/src/checkers/ast/analyze/deferred_scopes.rs @@ -40,6 +40,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) { Rule::UnusedPrivateTypedDict, Rule::UnusedStaticMethodArgument, Rule::UnusedVariable, + Rule::SingleDispatchMethod, ]) { return; } @@ -389,6 +390,10 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) { if checker.enabled(Rule::TooManyLocals) { pylint::rules::too_many_locals(checker, scope, &mut diagnostics); } + + if checker.enabled(Rule::SingleDispatchMethod) { + pylint::rules::single_dispatch_method(checker, scope_id, &mut diagnostics); + } } } checker.diagnostics.extend(diagnostics); diff --git a/crates/ruff_linter/src/codes.rs b/crates/ruff_linter/src/codes.rs index 5cf0293d1292ef..e55fe0812a9380 100644 --- a/crates/ruff_linter/src/codes.rs +++ b/crates/ruff_linter/src/codes.rs @@ -252,6 +252,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Pylint, "E1307") => (RuleGroup::Stable, rules::pylint::rules::BadStringFormatType), (Pylint, "E1310") => (RuleGroup::Stable, rules::pylint::rules::BadStrStripCall), (Pylint, "E1507") => (RuleGroup::Stable, rules::pylint::rules::InvalidEnvvarValue), + (Pylint, "E1519") => (RuleGroup::Preview, rules::pylint::rules::SingleDispatchMethod), (Pylint, "E1700") => (RuleGroup::Stable, rules::pylint::rules::YieldFromInAsyncFunction), (Pylint, "E2502") => (RuleGroup::Stable, rules::pylint::rules::BidirectionalUnicode), (Pylint, "E2510") => (RuleGroup::Stable, rules::pylint::rules::InvalidCharacterBackspace), diff --git a/crates/ruff_linter/src/rules/pylint/mod.rs b/crates/ruff_linter/src/rules/pylint/mod.rs index e9599b963aa705..c93dd1544c1a3f 100644 --- a/crates/ruff_linter/src/rules/pylint/mod.rs +++ b/crates/ruff_linter/src/rules/pylint/mod.rs @@ -20,6 +20,7 @@ mod tests { use crate::settings::LinterSettings; use crate::test::test_path; + #[test_case(Rule::SingleDispatchMethod, Path::new("E1519.py"))] #[test_case(Rule::AssertOnStringLiteral, Path::new("assert_on_string_literal.py"))] #[test_case(Rule::AwaitOutsideAsync, Path::new("await_outside_async.py"))] #[test_case(Rule::BadOpenMode, Path::new("bad_open_mode.py"))] diff --git a/crates/ruff_linter/src/rules/pylint/rules/mod.rs b/crates/ruff_linter/src/rules/pylint/rules/mod.rs index 9963339844a848..806633d58aa1ee 100644 --- a/crates/ruff_linter/src/rules/pylint/rules/mod.rs +++ b/crates/ruff_linter/src/rules/pylint/rules/mod.rs @@ -53,6 +53,7 @@ pub(crate) use repeated_isinstance_calls::*; pub(crate) use repeated_keyword_argument::*; pub(crate) use return_in_init::*; pub(crate) use self_assigning_variable::*; +pub(crate) use single_dispatch_method::*; pub(crate) use single_string_slots::*; pub(crate) use subprocess_popen_preexec_fn::*; pub(crate) use subprocess_run_without_check::*; @@ -139,6 +140,7 @@ mod repeated_isinstance_calls; mod repeated_keyword_argument; mod return_in_init; mod self_assigning_variable; +mod single_dispatch_method; mod single_string_slots; mod subprocess_popen_preexec_fn; mod subprocess_run_without_check; diff --git a/crates/ruff_linter/src/rules/pylint/rules/single_dispatch_method.rs b/crates/ruff_linter/src/rules/pylint/rules/single_dispatch_method.rs new file mode 100644 index 00000000000000..deadbc9251b833 --- /dev/null +++ b/crates/ruff_linter/src/rules/pylint/rules/single_dispatch_method.rs @@ -0,0 +1,22 @@ +use ruff_diagnostics::{Diagnostic, FixAvailability, Violation}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_python_semantic::ScopeId; + +use ruff_source_file::SourceRow; + +use crate::checkers::ast::Checker; + +#[violation] +pub struct SingleDispatchMethod {} + +impl Violation for SingleDispatchMethod { + const FIX_AVAILABILITY: FixAvailability = FixAvailability::None; + + #[derive_message_formats] + fn message(&self) -> String { + format!("") + } +} + +/// E1519 +pub(crate) fn single_dispatch_method(checker: &Checker, diagnostics: &mut Vec) {} diff --git a/ruff.schema.json b/ruff.schema.json index 674003ed05df23..0743fea9dcc5b3 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -3231,6 +3231,8 @@ "PLE15", "PLE150", "PLE1507", + "PLE151", + "PLE1519", "PLE17", "PLE170", "PLE1700",