diff --git a/crates/ruff/resources/test/fixtures/ruff/RUF017.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP100.py similarity index 81% rename from crates/ruff/resources/test/fixtures/ruff/RUF017.py rename to crates/ruff/resources/test/fixtures/pyupgrade/UP100.py index 99034d0ab0901f..72bc9f565f4eff 100644 --- a/crates/ruff/resources/test/fixtures/ruff/RUF017.py +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP100.py @@ -1,12 +1,12 @@ import typing from typing import TypeAlias -# RUF017 +# UP100 x: typing.TypeAlias = int x: TypeAlias = int -# RUF017 with generics (todo) +# UP100 with generics (todo) T = typing.TypeVar["T"] x: typing.TypeAlias = list[T] diff --git a/crates/ruff/src/checkers/ast/analyze/statement.rs b/crates/ruff/src/checkers/ast/analyze/statement.rs index 6addff17bc54c9..bfa5cda1975575 100644 --- a/crates/ruff/src/checkers/ast/analyze/statement.rs +++ b/crates/ruff/src/checkers/ast/analyze/statement.rs @@ -1376,8 +1376,8 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { stmt, ); } - if checker.enabled(Rule::TypeAliasAnnotation) { - ruff::rules::type_alias_annotation(checker, assign_stmt); + if checker.enabled(Rule::NonPEP695TypeAlias) { + pyupgrade::rules::non_pep695_type_alias(checker, assign_stmt); } if checker.is_stub { if let Some(value) = value { diff --git a/crates/ruff/src/codes.rs b/crates/ruff/src/codes.rs index 85d00f04a99267..a581e26ccf532b 100644 --- a/crates/ruff/src/codes.rs +++ b/crates/ruff/src/codes.rs @@ -438,6 +438,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Pyupgrade, "037") => (RuleGroup::Unspecified, rules::pyupgrade::rules::QuotedAnnotation), (Pyupgrade, "038") => (RuleGroup::Unspecified, rules::pyupgrade::rules::NonPEP604Isinstance), (Pyupgrade, "039") => (RuleGroup::Unspecified, rules::pyupgrade::rules::UnnecessaryClassParentheses), + (Pyupgrade, "100") => (RuleGroup::Unspecified, rules::pyupgrade::rules::NonPEP695TypeAlias), // pydocstyle (Pydocstyle, "100") => (RuleGroup::Unspecified, rules::pydocstyle::rules::UndocumentedPublicModule), @@ -807,7 +808,6 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Ruff, "014") => (RuleGroup::Nursery, rules::ruff::rules::UnreachableCode), (Ruff, "015") => (RuleGroup::Unspecified, rules::ruff::rules::UnnecessaryIterableAllocationForFirstElement), (Ruff, "016") => (RuleGroup::Unspecified, rules::ruff::rules::InvalidIndexType), - (Ruff, "017") => (RuleGroup::Unspecified, rules::ruff::rules::TypeAliasAnnotation), (Ruff, "100") => (RuleGroup::Unspecified, rules::ruff::rules::UnusedNOQA), (Ruff, "200") => (RuleGroup::Unspecified, rules::ruff::rules::InvalidPyprojectToml), diff --git a/crates/ruff/src/rules/pyflakes/mod.rs b/crates/ruff/src/rules/pyflakes/mod.rs index 7eb0434f31ef6e..b37f23c7b54627 100644 --- a/crates/ruff/src/rules/pyflakes/mod.rs +++ b/crates/ruff/src/rules/pyflakes/mod.rs @@ -3422,7 +3422,7 @@ mod tests { } #[test] - fn type_alias_annotations() { + fn use_pep695_type_aliass() { flakes( r#" from typing_extensions import TypeAlias diff --git a/crates/ruff/src/rules/pyupgrade/mod.rs b/crates/ruff/src/rules/pyupgrade/mod.rs index 0ec3c25e4b7db9..0d5360bfc87b37 100644 --- a/crates/ruff/src/rules/pyupgrade/mod.rs +++ b/crates/ruff/src/rules/pyupgrade/mod.rs @@ -88,6 +88,32 @@ mod tests { Ok(()) } + #[test] + fn non_pep695_type_alias_not_applied_py311() -> Result<()> { + let diagnostics = test_path( + Path::new("pyupgrade/UP100.py"), + &settings::Settings { + target_version: PythonVersion::Py311, + ..settings::Settings::for_rule(Rule::NonPEP695TypeAlias) + }, + )?; + assert_messages!(diagnostics); + Ok(()) + } + + #[test] + fn non_pep695_type_alias_py312() -> Result<()> { + let diagnostics = test_path( + Path::new("pyupgrade/UP100.py"), + &settings::Settings { + target_version: PythonVersion::Py312, + ..settings::Settings::for_rule(Rule::NonPEP695TypeAlias) + }, + )?; + assert_messages!(diagnostics); + Ok(()) + } + #[test] fn future_annotations_keep_runtime_typing_p37() -> Result<()> { let diagnostics = test_path( diff --git a/crates/ruff/src/rules/pyupgrade/rules/mod.rs b/crates/ruff/src/rules/pyupgrade/rules/mod.rs index 16ca52a57b49ba..0a924c145120d8 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/mod.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/mod.rs @@ -32,6 +32,7 @@ pub(crate) use unpacked_list_comprehension::*; pub(crate) use use_pep585_annotation::*; pub(crate) use use_pep604_annotation::*; pub(crate) use use_pep604_isinstance::*; +pub(crate) use use_pep695_type_alias::*; pub(crate) use useless_metaclass_type::*; pub(crate) use useless_object_inheritance::*; pub(crate) use yield_in_for_loop::*; @@ -70,6 +71,7 @@ mod unpacked_list_comprehension; mod use_pep585_annotation; mod use_pep604_annotation; mod use_pep604_isinstance; +mod use_pep695_type_alias; mod useless_metaclass_type; mod useless_object_inheritance; mod yield_in_for_loop; diff --git a/crates/ruff/src/rules/ruff/rules/type_alias_annotation.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep695_type_alias.rs similarity index 82% rename from crates/ruff/src/rules/ruff/rules/type_alias_annotation.rs rename to crates/ruff/src/rules/pyupgrade/rules/use_pep695_type_alias.rs index aec298fb9ea9e4..1aa2e3a0b5f6dd 100644 --- a/crates/ruff/src/rules/ruff/rules/type_alias_annotation.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep695_type_alias.rs @@ -24,26 +24,26 @@ use crate::checkers::ast::Checker; /// type ListOfInt = list[int] /// ``` #[violation] -pub struct TypeAliasAnnotation { +pub struct NonPEP695TypeAlias { name: String, } -impl Violation for TypeAliasAnnotation { +impl Violation for NonPEP695TypeAlias { const AUTOFIX: AutofixKind = AutofixKind::Always; #[derive_message_formats] fn message(&self) -> String { - let TypeAliasAnnotation { name } = self; - format!("Type alias `{name}` uses `TypeAlias` annotation instead of the `type` keyword.") + let NonPEP695TypeAlias { name } = self; + format!("Type alias `{name}` uses `TypeAlias` annotation instead of the `type` keyword") } fn autofix_title(&self) -> Option { - Some("Use the `type` keyword instead".to_string()) + Some("Replace with the `type` keyword".to_string()) } } -/// RUF017 -pub(crate) fn type_alias_annotation(checker: &mut Checker, stmt: &StmtAnnAssign) { +/// UP100 +pub(crate) fn non_pep695_type_alias(checker: &mut Checker, stmt: &StmtAnnAssign) { let StmtAnnAssign { target, annotation, @@ -71,9 +71,9 @@ pub(crate) fn type_alias_annotation(checker: &mut Checker, stmt: &StmtAnnAssign) return; }; - // todo(zanie): We should check for generic type variables used in the value and define them + // TODO(zanie): We should check for generic type variables used in the value and define them // as type params instead - let mut diagnostic = Diagnostic::new(TypeAliasAnnotation { name: name.clone() }, stmt.range()); + let mut diagnostic = Diagnostic::new(NonPEP695TypeAlias { name: name.clone() }, stmt.range()); if checker.patch(diagnostic.kind.rule()) { diagnostic.set_fix(Fix::automatic(Edit::range_replacement( checker.generator().stmt(&Stmt::from(StmtTypeAlias { diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__non_pep695_type_alias_not_applied_py311.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__non_pep695_type_alias_not_applied_py311.snap new file mode 100644 index 00000000000000..870ad3bf5d6254 --- /dev/null +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__non_pep695_type_alias_not_applied_py311.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff/src/rules/pyupgrade/mod.rs +--- + diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__non_pep695_type_alias_py312.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__non_pep695_type_alias_py312.snap new file mode 100644 index 00000000000000..b0e5752888cb9b --- /dev/null +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__non_pep695_type_alias_py312.snap @@ -0,0 +1,61 @@ +--- +source: crates/ruff/src/rules/pyupgrade/mod.rs +--- +UP100.py:5:1: UP100 [*] Type alias `x` uses `TypeAlias` annotation instead of the `type` keyword + | +4 | # UP100 +5 | x: typing.TypeAlias = int + | ^^^^^^^^^^^^^^^^^^^^^^^^^ UP100 +6 | x: TypeAlias = int + | + = help: Replace with the `type` keyword + +ℹ Fix +2 2 | from typing import TypeAlias +3 3 | +4 4 | # UP100 +5 |-x: typing.TypeAlias = int + 5 |+type x = int +6 6 | x: TypeAlias = int +7 7 | +8 8 | + +UP100.py:6:1: UP100 [*] Type alias `x` uses `TypeAlias` annotation instead of the `type` keyword + | +4 | # UP100 +5 | x: typing.TypeAlias = int +6 | x: TypeAlias = int + | ^^^^^^^^^^^^^^^^^^ UP100 + | + = help: Replace with the `type` keyword + +ℹ Fix +3 3 | +4 4 | # UP100 +5 5 | x: typing.TypeAlias = int +6 |-x: TypeAlias = int + 6 |+type x = int +7 7 | +8 8 | +9 9 | # UP100 with generics (todo) + +UP100.py:11:1: UP100 [*] Type alias `x` uses `TypeAlias` annotation instead of the `type` keyword + | + 9 | # UP100 with generics (todo) +10 | T = typing.TypeVar["T"] +11 | x: typing.TypeAlias = list[T] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP100 + | + = help: Replace with the `type` keyword + +ℹ Fix +8 8 | +9 9 | # UP100 with generics (todo) +10 10 | T = typing.TypeVar["T"] +11 |-x: typing.TypeAlias = list[T] + 11 |+type x = list[T] +12 12 | +13 13 | +14 14 | # OK + + diff --git a/crates/ruff/src/rules/ruff/mod.rs b/crates/ruff/src/rules/ruff/mod.rs index 98b2cc5133fbf6..42350547abd151 100644 --- a/crates/ruff/src/rules/ruff/mod.rs +++ b/crates/ruff/src/rules/ruff/mod.rs @@ -36,7 +36,6 @@ mod tests { Path::new("RUF015.py") )] #[test_case(Rule::InvalidIndexType, Path::new("RUF016.py"))] - #[test_case(Rule::TypeAliasAnnotation, Path::new("RUF017.py"))] #[cfg_attr( feature = "unreachable-code", test_case(Rule::UnreachableCode, Path::new("RUF014.py")) diff --git a/crates/ruff/src/rules/ruff/rules/mod.rs b/crates/ruff/src/rules/ruff/rules/mod.rs index 2db41a251b575a..e4d39feefd825f 100644 --- a/crates/ruff/src/rules/ruff/rules/mod.rs +++ b/crates/ruff/src/rules/ruff/rules/mod.rs @@ -10,7 +10,6 @@ pub(crate) use mutable_class_default::*; pub(crate) use mutable_dataclass_default::*; pub(crate) use pairwise_over_zipped::*; pub(crate) use static_key_dict_comprehension::*; -pub(crate) use type_alias_annotation::*; pub(crate) use unnecessary_iterable_allocation_for_first_element::*; #[cfg(feature = "unreachable-code")] pub(crate) use unreachable::*; @@ -30,7 +29,6 @@ mod mutable_class_default; mod mutable_dataclass_default; mod pairwise_over_zipped; mod static_key_dict_comprehension; -mod type_alias_annotation; mod unnecessary_iterable_allocation_for_first_element; #[cfg(feature = "unreachable-code")] pub(crate) mod unreachable; diff --git a/ruff.schema.json b/ruff.schema.json index f419e9454dded0..b6357ceb6705b8 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -2453,7 +2453,6 @@ "RUF013", "RUF015", "RUF016", - "RUF017", "RUF1", "RUF10", "RUF100", @@ -2667,6 +2666,8 @@ "UP037", "UP038", "UP039", + "UP1", + "UP100", "W", "W1", "W19",