diff --git a/crates/ruff/resources/test/fixtures/pyflakes/F821_14.py b/crates/ruff/resources/test/fixtures/pyflakes/F821_14.py new file mode 100644 index 0000000000..a7c56c0b14 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pyflakes/F821_14.py @@ -0,0 +1,7 @@ +"""Test case: f-strings in type annotations.""" + +from typing import List + +x = 1 + +x: List[f"i{x}nt"] = [] diff --git a/crates/ruff/resources/test/fixtures/pyflakes/F821_15.py b/crates/ruff/resources/test/fixtures/pyflakes/F821_15.py new file mode 100644 index 0000000000..0194ab5c10 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pyflakes/F821_15.py @@ -0,0 +1,9 @@ +"""Test case: f-strings in future type annotations.""" + +from __future__ import annotations + +from typing import List + +x = 1 + +x: List[f"i{x}nt"] = [] diff --git a/crates/ruff/src/checkers/ast/mod.rs b/crates/ruff/src/checkers/ast/mod.rs index 574525f502..c9c795e91b 100644 --- a/crates/ruff/src/checkers/ast/mod.rs +++ b/crates/ruff/src/checkers/ast/mod.rs @@ -2130,7 +2130,8 @@ where } fn visit_expr(&mut self, expr: &'b Expr) { - if !self.ctx.in_deferred_type_definition + if !self.ctx.in_f_string + && !self.ctx.in_deferred_type_definition && self.ctx.in_deferred_string_type_definition.is_none() && self.ctx.in_type_definition && self.ctx.annotations_future_enabled @@ -3283,7 +3284,7 @@ where value: Constant::Str(value), kind, } => { - if self.ctx.in_type_definition && !self.ctx.in_literal { + if self.ctx.in_type_definition && !self.ctx.in_literal && !self.ctx.in_f_string { self.deferred.string_type_definitions.push(( Range::from(expr), value, @@ -3624,7 +3625,10 @@ where self.ctx.in_subscript = prev_in_subscript; } ExprKind::JoinedStr { .. } => { + let prev_in_f_string = self.ctx.in_f_string; + self.ctx.in_f_string = true; visitor::walk_expr(self, expr); + self.ctx.in_f_string = prev_in_f_string; } _ => visitor::walk_expr(self, expr), } diff --git a/crates/ruff/src/rules/pyflakes/mod.rs b/crates/ruff/src/rules/pyflakes/mod.rs index d591866d7c..0e4fc33e76 100644 --- a/crates/ruff/src/rules/pyflakes/mod.rs +++ b/crates/ruff/src/rules/pyflakes/mod.rs @@ -108,6 +108,8 @@ mod tests { #[test_case(Rule::UndefinedName, Path::new("F821_11.py"); "F821_11")] #[test_case(Rule::UndefinedName, Path::new("F821_12.py"); "F821_12")] #[test_case(Rule::UndefinedName, Path::new("F821_13.py"); "F821_13")] + #[test_case(Rule::UndefinedName, Path::new("F821_14.py"); "F821_14")] + #[test_case(Rule::UndefinedName, Path::new("F821_15.py"); "F821_15")] #[test_case(Rule::UndefinedExport, Path::new("F822_0.py"); "F822_0")] #[test_case(Rule::UndefinedExport, Path::new("F822_1.py"); "F822_1")] #[test_case(Rule::UndefinedExport, Path::new("F822_2.py"); "F822_2")] diff --git a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F821_F821_14.py.snap b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F821_F821_14.py.snap new file mode 100644 index 0000000000..bd5537b631 --- /dev/null +++ b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F821_F821_14.py.snap @@ -0,0 +1,6 @@ +--- +source: crates/ruff/src/rules/pyflakes/mod.rs +expression: diagnostics +--- +[] + diff --git a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F821_F821_15.py.snap b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F821_F821_15.py.snap new file mode 100644 index 0000000000..bd5537b631 --- /dev/null +++ b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F821_F821_15.py.snap @@ -0,0 +1,6 @@ +--- +source: crates/ruff/src/rules/pyflakes/mod.rs +expression: diagnostics +--- +[] + diff --git a/crates/ruff_python_ast/src/context.rs b/crates/ruff_python_ast/src/context.rs index 741104c27d..bff83be6c1 100644 --- a/crates/ruff_python_ast/src/context.rs +++ b/crates/ruff_python_ast/src/context.rs @@ -45,6 +45,7 @@ pub struct Context<'a> { pub in_deferred_string_type_definition: Option, pub in_deferred_type_definition: bool, pub in_exception_handler: bool, + pub in_f_string: bool, pub in_literal: bool, pub in_subscript: bool, pub in_type_checking_block: bool, @@ -83,6 +84,7 @@ impl<'a> Context<'a> { in_deferred_string_type_definition: None, in_deferred_type_definition: false, in_exception_handler: false, + in_f_string: false, in_literal: false, in_subscript: false, in_type_checking_block: false,