Avoid used-prior-global-declaration false-positives in f-strings (#1314)

This commit is contained in:
Charlie Marsh 2022-12-21 14:34:09 -05:00 committed by GitHub
parent ce1663d302
commit de767cc026
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 11 deletions

View File

@ -109,6 +109,11 @@ def f():
del x del x
def f():
print(f"{x=}")
global x
### ###
# Non-errors. # Non-errors.
### ###
@ -146,3 +151,8 @@ def f():
global x, y global x, y
del x del x
def f():
global x
print(f"{x=}")

View File

@ -156,19 +156,14 @@ impl<'a> Checker<'a> {
} }
/// Add a `Check` to the `Checker`. /// Add a `Check` to the `Checker`.
pub(crate) fn add_check(&mut self, check: Check) { pub(crate) fn add_check(&mut self, mut check: Check) {
// If we're in an f-string, override the location. RustPython doesn't produce // If we're in an f-string, override the location. RustPython doesn't produce
// reliable locations for expressions within f-strings, so we use the // reliable locations for expressions within f-strings, so we use the
// span of the f-string itself as a best-effort default. // span of the f-string itself as a best-effort default.
let check = if let Some(range) = self.in_f_string { if let Some(range) = self.in_f_string {
Check { check.location = range.location;
location: range.location, check.end_location = range.end_location;
end_location: range.end_location,
..check
} }
} else {
check
};
self.checks.push(check); self.checks.push(check);
} }
@ -189,6 +184,13 @@ impl<'a> Checker<'a> {
&& self.settings.fixable.contains(code) && self.settings.fixable.contains(code)
} }
/// Return the amended `Range` from a `Located`.
pub fn range_for<T>(&self, located: &Located<T>) -> Range {
// If we're in an f-string, override the location.
self.in_f_string
.unwrap_or_else(|| Range::from_located(located))
}
/// Return `true` if the `Expr` is a reference to `typing.${target}`. /// Return `true` if the `Expr` is a reference to `typing.${target}`.
pub fn match_typing_expr(&self, expr: &Expr, target: &str) -> bool { pub fn match_typing_expr(&self, expr: &Expr, target: &str) -> bool {
let call_path = dealias_call_path(collect_call_paths(expr), &self.import_aliases); let call_path = dealias_call_path(collect_call_paths(expr), &self.import_aliases);

View File

@ -13,7 +13,7 @@ pub fn used_prior_global_declaration(checker: &mut Checker, name: &str, expr: &E
_ => return, _ => return,
}; };
if let Some(stmt) = globals.get(name) { if let Some(stmt) = globals.get(name) {
if expr.location < stmt.location { if checker.range_for(expr).location < stmt.location {
checker.add_check(Check::new( checker.add_check(Check::new(
CheckKind::UsedPriorGlobalDeclaration(name.to_string(), stmt.location.row()), CheckKind::UsedPriorGlobalDeclaration(name.to_string(), stmt.location.row()),
Range::from_located(expr), Range::from_located(expr),

View File

@ -134,4 +134,15 @@ expression: checks
row: 105 row: 105
column: 9 column: 9
fix: ~ fix: ~
- kind:
UsedPriorGlobalDeclaration:
- x
- 114
location:
row: 113
column: 10
end_location:
row: 113
column: 17
fix: ~