Skip to content

Commit 6abf716

Browse files
Avoid syntax errors when fixing parenthesized unused variables (#1919)
Closes #1917.
1 parent c0845a8 commit 6abf716

File tree

3 files changed

+74
-3
lines changed

3 files changed

+74
-3
lines changed

resources/test/fixtures/pyflakes/F841_3.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,14 @@ def f():
4444
1 / 0
4545
except (ValueError, ZeroDivisionError) as x2:
4646
pass
47+
48+
49+
def f(a, b):
50+
x = (
51+
a
52+
if a is not None
53+
else b
54+
)
55+
56+
y = \
57+
a if a is not None else b

src/rules/pyflakes/rules/unused_variable.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1+
use itertools::Itertools;
12
use log::error;
2-
use rustpython_ast::{Expr, ExprKind, Stmt, StmtKind};
3+
use rustpython_ast::{Expr, ExprKind, Location, Stmt, StmtKind};
4+
use rustpython_parser::lexer;
5+
use rustpython_parser::lexer::Tok;
36

47
use crate::ast::types::{BindingKind, Range, RefEquality, ScopeKind};
58
use crate::autofix::helpers::delete_stmt;
69
use crate::checkers::ast::Checker;
710
use crate::fix::Fix;
811
use crate::registry::{Diagnostic, RuleCode};
12+
use crate::source_code::Locator;
913
use crate::violations;
1014

1115
fn is_literal_or_name(expr: &Expr, checker: &Checker) -> bool {
@@ -43,6 +47,22 @@ fn is_literal_or_name(expr: &Expr, checker: &Checker) -> bool {
4347
false
4448
}
4549

50+
fn match_token_after<F>(stmt: &Stmt, locator: &Locator, f: F) -> Location
51+
where
52+
F: Fn(Tok) -> bool,
53+
{
54+
let contents = locator.slice_source_code_range(&Range::from_located(stmt));
55+
for ((_, tok, _), (start, ..)) in lexer::make_tokenizer_located(&contents, stmt.location)
56+
.flatten()
57+
.tuple_windows()
58+
{
59+
if f(tok) {
60+
return start;
61+
}
62+
}
63+
unreachable!("No token after matched");
64+
}
65+
4666
enum DeletionKind {
4767
Whole,
4868
Partial,
@@ -83,7 +103,10 @@ fn remove_unused_variable(
83103
// but preserve the right-hand side.
84104
Some((
85105
DeletionKind::Partial,
86-
Fix::deletion(stmt.location, value.location),
106+
Fix::deletion(
107+
stmt.location,
108+
match_token_after(stmt, checker.locator, |tok| tok == Tok::Equal),
109+
),
87110
))
88111
};
89112
}
@@ -122,7 +145,10 @@ fn remove_unused_variable(
122145
// but preserve the right-hand side.
123146
Some((
124147
DeletionKind::Partial,
125-
Fix::deletion(stmt.location, value.location),
148+
Fix::deletion(
149+
stmt.location,
150+
match_token_after(stmt, checker.locator, |tok| tok == Tok::Equal),
151+
),
126152
))
127153
};
128154
}

src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F841_F841_3.py.snap

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,4 +212,38 @@ expression: diagnostics
212212
row: 45
213213
column: 48
214214
parent: ~
215+
- kind:
216+
UnusedVariable: x
217+
location:
218+
row: 50
219+
column: 4
220+
end_location:
221+
row: 50
222+
column: 5
223+
fix:
224+
content: ""
225+
location:
226+
row: 50
227+
column: 4
228+
end_location:
229+
row: 50
230+
column: 8
231+
parent: ~
232+
- kind:
233+
UnusedVariable: y
234+
location:
235+
row: 56
236+
column: 4
237+
end_location:
238+
row: 56
239+
column: 5
240+
fix:
241+
content: ""
242+
location:
243+
row: 56
244+
column: 4
245+
end_location:
246+
row: 57
247+
column: 8
248+
parent: ~
215249

0 commit comments

Comments
 (0)