Avoid parsing f-strings in type annotations (#3699)

This commit is contained in:
Charlie Marsh 2023-03-23 18:51:44 -04:00 committed by GitHub
parent ba43d6bd0b
commit 028329854b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 38 additions and 2 deletions

View file

@ -0,0 +1,7 @@
"""Test case: f-strings in type annotations."""
from typing import List
x = 1
x: List[f"i{x}nt"] = []

View file

@ -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"] = []

View file

@ -2130,7 +2130,8 @@ where
} }
fn visit_expr(&mut self, expr: &'b Expr) { 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_deferred_string_type_definition.is_none()
&& self.ctx.in_type_definition && self.ctx.in_type_definition
&& self.ctx.annotations_future_enabled && self.ctx.annotations_future_enabled
@ -3283,7 +3284,7 @@ where
value: Constant::Str(value), value: Constant::Str(value),
kind, 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(( self.deferred.string_type_definitions.push((
Range::from(expr), Range::from(expr),
value, value,
@ -3624,7 +3625,10 @@ where
self.ctx.in_subscript = prev_in_subscript; self.ctx.in_subscript = prev_in_subscript;
} }
ExprKind::JoinedStr { .. } => { ExprKind::JoinedStr { .. } => {
let prev_in_f_string = self.ctx.in_f_string;
self.ctx.in_f_string = true;
visitor::walk_expr(self, expr); visitor::walk_expr(self, expr);
self.ctx.in_f_string = prev_in_f_string;
} }
_ => visitor::walk_expr(self, expr), _ => visitor::walk_expr(self, expr),
} }

View file

@ -108,6 +108,8 @@ mod tests {
#[test_case(Rule::UndefinedName, Path::new("F821_11.py"); "F821_11")] #[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_12.py"); "F821_12")]
#[test_case(Rule::UndefinedName, Path::new("F821_13.py"); "F821_13")] #[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_0.py"); "F822_0")]
#[test_case(Rule::UndefinedExport, Path::new("F822_1.py"); "F822_1")] #[test_case(Rule::UndefinedExport, Path::new("F822_1.py"); "F822_1")]
#[test_case(Rule::UndefinedExport, Path::new("F822_2.py"); "F822_2")] #[test_case(Rule::UndefinedExport, Path::new("F822_2.py"); "F822_2")]

View file

@ -0,0 +1,6 @@
---
source: crates/ruff/src/rules/pyflakes/mod.rs
expression: diagnostics
---
[]

View file

@ -0,0 +1,6 @@
---
source: crates/ruff/src/rules/pyflakes/mod.rs
expression: diagnostics
---
[]

View file

@ -45,6 +45,7 @@ pub struct Context<'a> {
pub in_deferred_string_type_definition: Option<AnnotationKind>, pub in_deferred_string_type_definition: Option<AnnotationKind>,
pub in_deferred_type_definition: bool, pub in_deferred_type_definition: bool,
pub in_exception_handler: bool, pub in_exception_handler: bool,
pub in_f_string: bool,
pub in_literal: bool, pub in_literal: bool,
pub in_subscript: bool, pub in_subscript: bool,
pub in_type_checking_block: bool, pub in_type_checking_block: bool,
@ -83,6 +84,7 @@ impl<'a> Context<'a> {
in_deferred_string_type_definition: None, in_deferred_string_type_definition: None,
in_deferred_type_definition: false, in_deferred_type_definition: false,
in_exception_handler: false, in_exception_handler: false,
in_f_string: false,
in_literal: false, in_literal: false,
in_subscript: false, in_subscript: false,
in_type_checking_block: false, in_type_checking_block: false,