diff --git a/crates/ruff_linter/resources/test/fixtures/flake8_annotations/annotation_presence.py b/crates/ruff_linter/resources/test/fixtures/flake8_annotations/annotation_presence.py index b84ec16576854..4ef4e2220bb93 100644 --- a/crates/ruff_linter/resources/test/fixtures/flake8_annotations/annotation_presence.py +++ b/crates/ruff_linter/resources/test/fixtures/flake8_annotations/annotation_presence.py @@ -71,7 +71,7 @@ class Foo: def foo(self: "Foo", a: int, b: int) -> int: pass - # ANN101 + # OK def foo(self, a: int, b: int) -> int: pass @@ -125,12 +125,12 @@ def foo(self: "Foo", a: int, *params: str, **options: Any) -> int: def foo(cls: Type["Foo"], a: int, b: int) -> int: pass - # ANN102 + # OK @classmethod def foo(cls, a: int, b: int) -> int: pass - # ANN101 + # OK def foo(self, /, a: int, b: int) -> int: pass diff --git a/crates/ruff_linter/src/checkers/ast/analyze/definitions.rs b/crates/ruff_linter/src/checkers/ast/analyze/definitions.rs index 689b5c416e4e1..4580d23a644d8 100644 --- a/crates/ruff_linter/src/checkers/ast/analyze/definitions.rs +++ b/crates/ruff_linter/src/checkers/ast/analyze/definitions.rs @@ -27,10 +27,8 @@ pub(crate) fn definitions(checker: &mut Checker) { Rule::MissingReturnTypeStaticMethod, Rule::MissingReturnTypeUndocumentedPublicFunction, Rule::MissingTypeArgs, - Rule::MissingTypeCls, Rule::MissingTypeFunctionArgument, Rule::MissingTypeKwargs, - Rule::MissingTypeSelf, ]); let enforce_stubs = checker.source_type.is_stub() && checker.enabled(Rule::DocstringInStub); let enforce_stubs_and_runtime = checker.enabled(Rule::IterMethodReturnIterable); diff --git a/crates/ruff_linter/src/codes.rs b/crates/ruff_linter/src/codes.rs index 4405757aa3b63..edd6bcce4da9d 100644 --- a/crates/ruff_linter/src/codes.rs +++ b/crates/ruff_linter/src/codes.rs @@ -428,8 +428,10 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Flake8Annotations, "001") => (RuleGroup::Stable, rules::flake8_annotations::rules::MissingTypeFunctionArgument), (Flake8Annotations, "002") => (RuleGroup::Stable, rules::flake8_annotations::rules::MissingTypeArgs), (Flake8Annotations, "003") => (RuleGroup::Stable, rules::flake8_annotations::rules::MissingTypeKwargs), - (Flake8Annotations, "101") => (RuleGroup::Deprecated, rules::flake8_annotations::rules::MissingTypeSelf), - (Flake8Annotations, "102") => (RuleGroup::Deprecated, rules::flake8_annotations::rules::MissingTypeCls), + #[allow(deprecated)] + (Flake8Annotations, "101") => (RuleGroup::Removed, rules::flake8_annotations::rules::MissingTypeSelf), + #[allow(deprecated)] + (Flake8Annotations, "102") => (RuleGroup::Removed, rules::flake8_annotations::rules::MissingTypeCls), (Flake8Annotations, "201") => (RuleGroup::Stable, rules::flake8_annotations::rules::MissingReturnTypeUndocumentedPublicFunction), (Flake8Annotations, "202") => (RuleGroup::Stable, rules::flake8_annotations::rules::MissingReturnTypePrivateFunction), (Flake8Annotations, "204") => (RuleGroup::Stable, rules::flake8_annotations::rules::MissingReturnTypeSpecialMethod), diff --git a/crates/ruff_linter/src/rules/flake8_annotations/mod.rs b/crates/ruff_linter/src/rules/flake8_annotations/mod.rs index 859f8588c5311..57d866ec2c93c 100644 --- a/crates/ruff_linter/src/rules/flake8_annotations/mod.rs +++ b/crates/ruff_linter/src/rules/flake8_annotations/mod.rs @@ -24,8 +24,6 @@ mod tests { Rule::MissingTypeFunctionArgument, Rule::MissingTypeArgs, Rule::MissingTypeKwargs, - Rule::MissingTypeSelf, - Rule::MissingTypeCls, Rule::MissingReturnTypeUndocumentedPublicFunction, Rule::MissingReturnTypePrivateFunction, Rule::MissingReturnTypeSpecialMethod, @@ -52,8 +50,6 @@ mod tests { Rule::MissingTypeFunctionArgument, Rule::MissingTypeArgs, Rule::MissingTypeKwargs, - Rule::MissingTypeSelf, - Rule::MissingTypeCls, Rule::MissingReturnTypeUndocumentedPublicFunction, Rule::MissingReturnTypePrivateFunction, Rule::MissingReturnTypeSpecialMethod, @@ -80,8 +76,6 @@ mod tests { Rule::MissingTypeFunctionArgument, Rule::MissingTypeArgs, Rule::MissingTypeKwargs, - Rule::MissingTypeSelf, - Rule::MissingTypeCls, ]) }, )?; @@ -161,8 +155,6 @@ mod tests { Rule::MissingTypeFunctionArgument, Rule::MissingTypeArgs, Rule::MissingTypeKwargs, - Rule::MissingTypeSelf, - Rule::MissingTypeCls, Rule::MissingReturnTypeUndocumentedPublicFunction, Rule::MissingReturnTypePrivateFunction, Rule::MissingReturnTypeSpecialMethod, diff --git a/crates/ruff_linter/src/rules/flake8_annotations/rules/definition.rs b/crates/ruff_linter/src/rules/flake8_annotations/rules/definition.rs index 9f94b29cc53cd..aed85eb102832 100644 --- a/crates/ruff_linter/src/rules/flake8_annotations/rules/definition.rs +++ b/crates/ruff_linter/src/rules/flake8_annotations/rules/definition.rs @@ -110,9 +110,8 @@ impl Violation for MissingTypeKwargs { } } -/// ## Deprecation -/// This rule is commonly disabled because type checkers can infer this type without annotation. -/// It will be removed in a future release. +/// ## Removed +/// This rule has been removed because type checkers can infer this type without annotation. /// /// ## What it does /// Checks that instance method `self` arguments have type annotations. @@ -139,21 +138,22 @@ impl Violation for MissingTypeKwargs { /// def bar(self: "Foo"): ... /// ``` #[violation] -pub struct MissingTypeSelf { - name: String, -} +#[deprecated(note = "ANN101 has been removed")] +pub struct MissingTypeSelf; +#[allow(deprecated)] impl Violation for MissingTypeSelf { - #[derive_message_formats] fn message(&self) -> String { - let Self { name } = self; - format!("Missing type annotation for `{name}` in method") + unreachable!("ANN101 has been removed"); + } + + fn message_formats() -> &'static [&'static str] { + &["Missing type annotation for `{name}` in method"] } } -/// ## Deprecation -/// This rule is commonly disabled because type checkers can infer this type without annotation. -/// It will be removed in a future release. +/// ## Removed +/// This rule has been removed because type checkers can infer this type without annotation. /// /// ## What it does /// Checks that class method `cls` arguments have type annotations. @@ -182,15 +182,17 @@ impl Violation for MissingTypeSelf { /// def bar(cls: Type["Foo"]): ... /// ``` #[violation] -pub struct MissingTypeCls { - name: String, -} +#[deprecated(note = "ANN102 has been removed")] +pub struct MissingTypeCls; +#[allow(deprecated)] impl Violation for MissingTypeCls { - #[derive_message_formats] fn message(&self) -> String { - let Self { name } = self; - format!("Missing type annotation for `{name}` in classmethod") + unreachable!("ANN102 has been removed") + } + + fn message_formats() -> &'static [&'static str] { + &["Missing type annotation for `{name}` in classmethod"] } } @@ -594,7 +596,6 @@ pub(crate) fn definition( // Keep track of whether we've seen any typed arguments or return values. let mut has_any_typed_arg = false; // Any argument has been typed? let mut has_typed_return = false; // Return value has been typed? - let mut has_typed_self_or_cls = false; // Has a typed `self` or `cls` argument? // Temporary storage for diagnostics; we emit them at the end // unless configured to suppress ANN* for declarations that are fully untyped. @@ -697,43 +698,6 @@ pub(crate) fn definition( } } - // ANN101, ANN102 - if is_method && !visibility::is_staticmethod(decorator_list, checker.semantic()) { - if let Some(ParameterWithDefault { - parameter, - default: _, - range: _, - }) = parameters - .posonlyargs - .first() - .or_else(|| parameters.args.first()) - { - if parameter.annotation.is_none() { - if visibility::is_classmethod(decorator_list, checker.semantic()) { - if checker.enabled(Rule::MissingTypeCls) { - diagnostics.push(Diagnostic::new( - MissingTypeCls { - name: parameter.name.to_string(), - }, - parameter.range(), - )); - } - } else { - if checker.enabled(Rule::MissingTypeSelf) { - diagnostics.push(Diagnostic::new( - MissingTypeSelf { - name: parameter.name.to_string(), - }, - parameter.range(), - )); - } - } - } else { - has_typed_self_or_cls = true; - } - } - } - // ANN201, ANN202, ANN401 if let Some(expr) = &returns { has_typed_return = true; @@ -927,13 +891,25 @@ pub(crate) fn definition( } } } + + if !checker.settings.flake8_annotations.ignore_fully_untyped { + return diagnostics; + } + // If settings say so, don't report any of the // diagnostics gathered here if there were no type annotations at all. - if checker.settings.flake8_annotations.ignore_fully_untyped - && !(has_any_typed_arg || has_typed_self_or_cls || has_typed_return) + if has_any_typed_arg + || has_typed_return + || (is_method + && !visibility::is_staticmethod(decorator_list, checker.semantic()) + && parameters + .posonlyargs + .first() + .or_else(|| parameters.args.first()) + .is_some_and(|first_param| first_param.parameter.annotation.is_some())) { - vec![] - } else { diagnostics + } else { + vec![] } } diff --git a/crates/ruff_linter/src/rules/flake8_annotations/snapshots/ruff_linter__rules__flake8_annotations__tests__defaults.snap b/crates/ruff_linter/src/rules/flake8_annotations/snapshots/ruff_linter__rules__flake8_annotations__tests__defaults.snap index dedf99ff7cd35..d3837dec75837 100644 --- a/crates/ruff_linter/src/rules/flake8_annotations/snapshots/ruff_linter__rules__flake8_annotations__tests__defaults.snap +++ b/crates/ruff_linter/src/rules/flake8_annotations/snapshots/ruff_linter__rules__flake8_annotations__tests__defaults.snap @@ -1,6 +1,5 @@ --- source: crates/ruff_linter/src/rules/flake8_annotations/mod.rs -snapshot_kind: text --- annotation_presence.py:5:5: ANN201 [*] Missing return type annotation for public function `foo` | @@ -158,14 +157,6 @@ annotation_presence.py:65:39: ANN401 Dynamically typed expressions (typing.Any) 66 | pass | -annotation_presence.py:75:13: ANN101 Missing type annotation for `self` in method - | -74 | # ANN101 -75 | def foo(self, a: int, b: int) -> int: - | ^^^^ ANN101 -76 | pass - | - annotation_presence.py:79:29: ANN401 Dynamically typed expressions (typing.Any) are disallowed in `a` | 78 | # ANN401 @@ -214,23 +205,6 @@ annotation_presence.py:95:59: ANN401 Dynamically typed expressions (typing.Any) 96 | pass | -annotation_presence.py:130:13: ANN102 Missing type annotation for `cls` in classmethod - | -128 | # ANN102 -129 | @classmethod -130 | def foo(cls, a: int, b: int) -> int: - | ^^^ ANN102 -131 | pass - | - -annotation_presence.py:134:13: ANN101 Missing type annotation for `self` in method - | -133 | # ANN101 -134 | def foo(self, /, a: int, b: int) -> int: - | ^^^^ ANN101 -135 | pass - | - annotation_presence.py:149:10: ANN401 Dynamically typed expressions (typing.Any) are disallowed in `a` | 148 | # ANN401 @@ -324,12 +298,3 @@ annotation_presence.py:165:9: ANN204 [*] Missing return type annotation for spec 165 |- def __init__(self): 165 |+ def __init__(self) -> None: 166 166 | print(f"{self.attr=}") - -annotation_presence.py:165:18: ANN101 Missing type annotation for `self` in method - | -163 | # Regression test for: https://github.com/astral-sh/ruff/issues/7711 -164 | class Class: -165 | def __init__(self): - | ^^^^ ANN101 -166 | print(f"{self.attr=}") - | diff --git a/crates/ruff_macros/src/violation.rs b/crates/ruff_macros/src/violation.rs index 028a5e5a41330..93a9efa5bd7be 100644 --- a/crates/ruff_macros/src/violation.rs +++ b/crates/ruff_macros/src/violation.rs @@ -53,6 +53,7 @@ pub(crate) fn violation(violation: &ItemStruct) -> Result { #[derive(Debug, PartialEq, Eq)] #violation + #[allow(deprecated)] #[automatically_derived] impl From<#ident> for ruff_diagnostics::DiagnosticKind { fn from(value: #ident) -> Self { @@ -71,12 +72,15 @@ pub(crate) fn violation(violation: &ItemStruct) -> Result { #[derive(Debug, PartialEq, Eq)] #violation + #[automatically_derived] + #[allow(deprecated)] impl #ident { pub fn explanation() -> Option<&'static str> { Some(#explanation) } } + #[allow(deprecated)] #[automatically_derived] impl From<#ident> for ruff_diagnostics::DiagnosticKind { fn from(value: #ident) -> Self { diff --git a/ruff.schema.json b/ruff.schema.json index 856b434f0547a..263ab678efac1 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -2798,10 +2798,6 @@ "ANN001", "ANN002", "ANN003", - "ANN1", - "ANN10", - "ANN101", - "ANN102", "ANN2", "ANN20", "ANN201",