From 8f6cb9dfb53449d1e0ef9e2940763592a5728a56 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Thu, 7 Mar 2024 16:51:54 -0800 Subject: [PATCH] Treat `typing.Annotated` subscripts as type definitions (#10285) ## Summary I think this code has existed since the start of `typing.Annotated` support (https://github.com/astral-sh/ruff/pull/333), and was then overlooked over a series of refactors. Closes https://github.com/astral-sh/ruff/issues/10279. --- .../test/fixtures/pyflakes/F401_23.py | 7 +++++++ crates/ruff_linter/src/checkers/ast/mod.rs | 2 +- crates/ruff_linter/src/rules/pyflakes/mod.rs | 1 + ...les__pyflakes__tests__F401_F401_23.py.snap | 20 +++++++++++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 crates/ruff_linter/resources/test/fixtures/pyflakes/F401_23.py create mode 100644 crates/ruff_linter/src/rules/pyflakes/snapshots/ruff_linter__rules__pyflakes__tests__F401_F401_23.py.snap diff --git a/crates/ruff_linter/resources/test/fixtures/pyflakes/F401_23.py b/crates/ruff_linter/resources/test/fixtures/pyflakes/F401_23.py new file mode 100644 index 0000000000000..d398b238f145d --- /dev/null +++ b/crates/ruff_linter/resources/test/fixtures/pyflakes/F401_23.py @@ -0,0 +1,7 @@ +"""Test: ensure that we treat strings in `typing.Annotation` as type definitions.""" + +from pathlib import Path +from re import RegexFlag +from typing import Annotated + +p: Annotated["Path", int] = 1 diff --git a/crates/ruff_linter/src/checkers/ast/mod.rs b/crates/ruff_linter/src/checkers/ast/mod.rs index ad320819e550b..62ee66842b46d 100644 --- a/crates/ruff_linter/src/checkers/ast/mod.rs +++ b/crates/ruff_linter/src/checkers/ast/mod.rs @@ -1348,7 +1348,7 @@ impl<'a> Visitor<'a> for Checker<'a> { { let mut iter = elts.iter(); if let Some(expr) = iter.next() { - self.visit_expr(expr); + self.visit_type_definition(expr); } for expr in iter { self.visit_non_type_definition(expr); diff --git a/crates/ruff_linter/src/rules/pyflakes/mod.rs b/crates/ruff_linter/src/rules/pyflakes/mod.rs index 00cdfda23ee44..bd3adf28ecaea 100644 --- a/crates/ruff_linter/src/rules/pyflakes/mod.rs +++ b/crates/ruff_linter/src/rules/pyflakes/mod.rs @@ -55,6 +55,7 @@ mod tests { #[test_case(Rule::UnusedImport, Path::new("F401_20.py"))] #[test_case(Rule::UnusedImport, Path::new("F401_21.py"))] #[test_case(Rule::UnusedImport, Path::new("F401_22.py"))] + #[test_case(Rule::UnusedImport, Path::new("F401_23.py"))] #[test_case(Rule::ImportShadowedByLoopVar, Path::new("F402.py"))] #[test_case(Rule::ImportShadowedByLoopVar, Path::new("F402.ipynb"))] #[test_case(Rule::UndefinedLocalWithImportStar, Path::new("F403.py"))] diff --git a/crates/ruff_linter/src/rules/pyflakes/snapshots/ruff_linter__rules__pyflakes__tests__F401_F401_23.py.snap b/crates/ruff_linter/src/rules/pyflakes/snapshots/ruff_linter__rules__pyflakes__tests__F401_F401_23.py.snap new file mode 100644 index 0000000000000..afde9e550a87d --- /dev/null +++ b/crates/ruff_linter/src/rules/pyflakes/snapshots/ruff_linter__rules__pyflakes__tests__F401_F401_23.py.snap @@ -0,0 +1,20 @@ +--- +source: crates/ruff_linter/src/rules/pyflakes/mod.rs +--- +F401_23.py:4:16: F401 [*] `re.RegexFlag` imported but unused + | +3 | from pathlib import Path +4 | from re import RegexFlag + | ^^^^^^^^^ F401 +5 | from typing import Annotated + | + = help: Remove unused import: `re.RegexFlag` + +ℹ Safe fix +1 1 | """Test: ensure that we treat strings in `typing.Annotation` as type definitions.""" +2 2 | +3 3 | from pathlib import Path +4 |-from re import RegexFlag +5 4 | from typing import Annotated +6 5 | +7 6 | p: Annotated["Path", int] = 1