Skip all bracketed expressions when locating comparison ops (#7740)

Closes https://github.com/astral-sh/ruff/issues/7737.
This commit is contained in:
Charlie Marsh 2023-10-01 10:57:40 -04:00 committed by GitHub
parent 1cf3b5676f
commit 2838f7af98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 114 additions and 52 deletions

View file

@ -25,3 +25,7 @@ not ''}
{2 is
not ''}
# Regression test for
if values[1is not None ] is not '-':
pass

View file

@ -171,6 +171,8 @@ F632.py:26:2: F632 [*] Use `!=` to compare constant literals
| __^
27 | | not ''}
| |_______^ F632
28 |
29 | # Regression test for
|
= help: Replace `is not` with `!=`
@ -181,5 +183,42 @@ F632.py:26:2: F632 [*] Use `!=` to compare constant literals
26 |-{2 is
27 |- not ''}
26 |+{2 != ''}
28 27 |
29 28 | # Regression test for
30 29 | if values[1is not None ] is not '-':
F632.py:30:4: F632 [*] Use `!=` to compare constant literals
|
29 | # Regression test for
30 | if values[1is not None ] is not '-':
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ F632
31 | pass
|
= help: Replace `is not` with `!=`
Fix
27 27 | not ''}
28 28 |
29 29 | # Regression test for
30 |-if values[1is not None ] is not '-':
30 |+if values[1is not None ] != '-':
31 31 | pass
F632.py:30:11: F632 [*] Use `!=` to compare constant literals
|
29 | # Regression test for
30 | if values[1is not None ] is not '-':
| ^^^^^^^^^^^^ F632
31 | pass
|
= help: Replace `is not` with `!=`
Fix
27 27 | not ''}
28 28 |
29 29 | # Regression test for
30 |-if values[1is not None ] is not '-':
30 |+if values[1!= None ] is not '-':
31 31 | pass

View file

@ -180,24 +180,46 @@ pub fn locate_cmp_ops(expr: &Expr, source: &str) -> Vec<LocatedCmpOp> {
.peekable();
let mut ops: Vec<LocatedCmpOp> = vec![];
let mut count = 0u32;
// Track the bracket depth.
let mut par_count = 0u32;
let mut sqb_count = 0u32;
let mut brace_count = 0u32;
loop {
let Some((tok, range)) = tok_iter.next() else {
break;
};
if matches!(tok, Tok::Lpar) {
count = count.saturating_add(1);
continue;
} else if matches!(tok, Tok::Rpar) {
count = count.saturating_sub(1);
match tok {
Tok::Lpar => {
par_count = par_count.saturating_add(1);
}
Tok::Rpar => {
par_count = par_count.saturating_sub(1);
}
Tok::Lsqb => {
sqb_count = sqb_count.saturating_add(1);
}
Tok::Rsqb => {
sqb_count = sqb_count.saturating_sub(1);
}
Tok::Lbrace => {
brace_count = brace_count.saturating_add(1);
}
Tok::Rbrace => {
brace_count = brace_count.saturating_sub(1);
}
_ => {}
}
if par_count > 0 || sqb_count > 0 || brace_count > 0 {
continue;
}
if count == 0 {
match tok {
Tok::Not => {
if let Some((_, next_range)) =
tok_iter.next_if(|(tok, _)| matches!(tok, Tok::In))
{
if let Some((_, next_range)) = tok_iter.next_if(|(tok, _)| tok.is_in()) {
ops.push(LocatedCmpOp::new(
TextRange::new(range.start(), next_range.end()),
CmpOp::NotIn,
@ -208,9 +230,7 @@ pub fn locate_cmp_ops(expr: &Expr, source: &str) -> Vec<LocatedCmpOp> {
ops.push(LocatedCmpOp::new(range, CmpOp::In));
}
Tok::Is => {
let op = if let Some((_, next_range)) =
tok_iter.next_if(|(tok, _)| matches!(tok, Tok::Not))
{
let op = if let Some((_, next_range)) = tok_iter.next_if(|(tok, _)| tok.is_not()) {
LocatedCmpOp::new(
TextRange::new(range.start(), next_range.end()),
CmpOp::IsNot,
@ -241,7 +261,6 @@ pub fn locate_cmp_ops(expr: &Expr, source: &str) -> Vec<LocatedCmpOp> {
_ => {}
}
}
}
ops
}