Skip to content

Commit 1efa2e0

Browse files
Avoid match statement misidentification in token rules (#3129)
1 parent df3932f commit 1efa2e0

File tree

25 files changed

+128
-66
lines changed

25 files changed

+128
-66
lines changed

Cargo.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a87
1313
once_cell = { version = "1.16.0" }
1414
regex = { version = "1.6.0" }
1515
rustc-hash = { version = "1.1.0" }
16-
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "ddf497623ae56d21aa4166ff1c0725a7db67e955" }
17-
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "ddf497623ae56d21aa4166ff1c0725a7db67e955" }
16+
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "6d5bbd913c7c46518f4ed8b1b378ffb0df72f505" }
17+
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "6d5bbd913c7c46518f4ed8b1b378ffb0df72f505" }
1818
schemars = { version = "0.8.11" }
1919
serde = { version = "1.0.147", features = ["derive"] }
2020
serde_json = { version = "1.0.87" }

crates/ruff/resources/test/fixtures/pycodestyle/E70.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,6 @@ class C: ...; ...
5757
#: E701:2:12
5858
match *0, 1, *2:
5959
case 0,: y = 0
60+
#:
61+
class Foo:
62+
match: Optional[Match] = None

crates/ruff/src/ast/helpers.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rustpython_parser::ast::{
1111
};
1212
use rustpython_parser::lexer;
1313
use rustpython_parser::lexer::Tok;
14+
use rustpython_parser::mode::Mode;
1415
use rustpython_parser::token::StringKind;
1516
use smallvec::{smallvec, SmallVec};
1617

@@ -655,7 +656,7 @@ pub fn has_comments<T>(located: &Located<T>, locator: &Locator) -> bool {
655656

656657
/// Returns `true` if a [`Range`] includes at least one comment.
657658
pub fn has_comments_in(range: Range, locator: &Locator) -> bool {
658-
for tok in lexer::make_tokenizer(locator.slice(&range)) {
659+
for tok in lexer::make_tokenizer_located(locator.slice(&range), Mode::Module, range.location) {
659660
match tok {
660661
Ok((_, tok, _)) => {
661662
if matches!(tok, Tok::Comment(..)) {
@@ -870,7 +871,8 @@ pub fn match_parens(start: Location, locator: &Locator) -> Option<Range> {
870871
let mut fix_start = None;
871872
let mut fix_end = None;
872873
let mut count: usize = 0;
873-
for (start, tok, end) in lexer::make_tokenizer_located(contents, start).flatten() {
874+
for (start, tok, end) in lexer::make_tokenizer_located(contents, Mode::Module, start).flatten()
875+
{
874876
if matches!(tok, Tok::Lpar) {
875877
if count == 0 {
876878
fix_start = Some(start);
@@ -902,7 +904,9 @@ pub fn identifier_range(stmt: &Stmt, locator: &Locator) -> Range {
902904
| StmtKind::AsyncFunctionDef { .. }
903905
) {
904906
let contents = locator.slice(&Range::from_located(stmt));
905-
for (start, tok, end) in lexer::make_tokenizer_located(contents, stmt.location).flatten() {
907+
for (start, tok, end) in
908+
lexer::make_tokenizer_located(contents, Mode::Module, stmt.location).flatten()
909+
{
906910
if matches!(tok, Tok::Name { .. }) {
907911
return Range::new(start, end);
908912
}
@@ -933,7 +937,7 @@ pub fn find_names<'a, T, U>(
933937
locator: &'a Locator,
934938
) -> impl Iterator<Item = Range> + 'a {
935939
let contents = locator.slice(&Range::from_located(located));
936-
lexer::make_tokenizer_located(contents, located.location)
940+
lexer::make_tokenizer_located(contents, Mode::Module, located.location)
937941
.flatten()
938942
.filter(|(_, tok, _)| matches!(tok, Tok::Name { .. }))
939943
.map(|(start, _, end)| Range {
@@ -951,7 +955,7 @@ pub fn excepthandler_name_range(handler: &Excepthandler, locator: &Locator) -> O
951955
(Some(_), Some(type_)) => {
952956
let type_end_location = type_.end_location.unwrap();
953957
let contents = locator.slice(&Range::new(type_end_location, body[0].location));
954-
let range = lexer::make_tokenizer_located(contents, type_end_location)
958+
let range = lexer::make_tokenizer_located(contents, Mode::Module, type_end_location)
955959
.flatten()
956960
.tuple_windows()
957961
.find(|(tok, next_tok)| {
@@ -978,7 +982,7 @@ pub fn except_range(handler: &Excepthandler, locator: &Locator) -> Range {
978982
location: handler.location,
979983
end_location: end,
980984
});
981-
let range = lexer::make_tokenizer_located(contents, handler.location)
985+
let range = lexer::make_tokenizer_located(contents, Mode::Module, handler.location)
982986
.flatten()
983987
.find(|(_, kind, _)| matches!(kind, Tok::Except { .. }))
984988
.map(|(location, _, end_location)| Range {
@@ -992,7 +996,7 @@ pub fn except_range(handler: &Excepthandler, locator: &Locator) -> Range {
992996
/// Find f-strings that don't contain any formatted values in a `JoinedStr`.
993997
pub fn find_useless_f_strings(expr: &Expr, locator: &Locator) -> Vec<(Range, Range)> {
994998
let contents = locator.slice(&Range::from_located(expr));
995-
lexer::make_tokenizer_located(contents, expr.location)
999+
lexer::make_tokenizer_located(contents, Mode::Module, expr.location)
9961000
.flatten()
9971001
.filter_map(|(location, tok, end_location)| match tok {
9981002
Tok::String {
@@ -1046,7 +1050,7 @@ pub fn else_range(stmt: &Stmt, locator: &Locator) -> Option<Range> {
10461050
.expect("Expected orelse to be non-empty")
10471051
.location,
10481052
});
1049-
let range = lexer::make_tokenizer_located(contents, body_end)
1053+
let range = lexer::make_tokenizer_located(contents, Mode::Module, body_end)
10501054
.flatten()
10511055
.find(|(_, kind, _)| matches!(kind, Tok::Else))
10521056
.map(|(location, _, end_location)| Range {
@@ -1062,7 +1066,7 @@ pub fn else_range(stmt: &Stmt, locator: &Locator) -> Option<Range> {
10621066
/// Return the `Range` of the first `Tok::Colon` token in a `Range`.
10631067
pub fn first_colon_range(range: Range, locator: &Locator) -> Option<Range> {
10641068
let contents = locator.slice(&range);
1065-
let range = lexer::make_tokenizer_located(contents, range.location)
1069+
let range = lexer::make_tokenizer_located(contents, Mode::Module, range.location)
10661070
.flatten()
10671071
.find(|(_, kind, _)| matches!(kind, Tok::Colon))
10681072
.map(|(location, _, end_location)| Range {
@@ -1092,7 +1096,7 @@ pub fn elif_else_range(stmt: &Stmt, locator: &Locator) -> Option<Range> {
10921096
_ => return None,
10931097
};
10941098
let contents = locator.slice(&Range::new(start, end));
1095-
let range = lexer::make_tokenizer_located(contents, start)
1099+
let range = lexer::make_tokenizer_located(contents, Mode::Module, start)
10961100
.flatten()
10971101
.find(|(_, kind, _)| matches!(kind, Tok::Elif | Tok::Else))
10981102
.map(|(location, _, end_location)| Range {

crates/ruff/src/ast/operations.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use rustc_hash::FxHashMap;
33
use rustpython_parser::ast::{Cmpop, Constant, Expr, ExprKind, Located, Stmt, StmtKind};
44
use rustpython_parser::lexer;
55
use rustpython_parser::lexer::Tok;
6+
use rustpython_parser::mode::Mode;
67

78
use crate::ast::helpers::any_over_expr;
89
use crate::ast::types::{BindingKind, Scope};
@@ -283,7 +284,9 @@ pub type LocatedCmpop<U = ()> = Located<Cmpop, U>;
283284
/// `CPython` doesn't either. This method iterates over the token stream and
284285
/// re-identifies [`Cmpop`] nodes, annotating them with valid ranges.
285286
pub fn locate_cmpops(contents: &str) -> Vec<LocatedCmpop> {
286-
let mut tok_iter = lexer::make_tokenizer(contents).flatten().peekable();
287+
let mut tok_iter = lexer::make_tokenizer(contents, Mode::Module)
288+
.flatten()
289+
.peekable();
287290
let mut ops: Vec<LocatedCmpop> = vec![];
288291
let mut count: usize = 0;
289292
loop {

crates/ruff/src/autofix/helpers.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use libcst_native::{
66
use rustpython_parser::ast::{ExcepthandlerKind, Expr, Keyword, Location, Stmt, StmtKind};
77
use rustpython_parser::lexer;
88
use rustpython_parser::lexer::Tok;
9+
use rustpython_parser::mode::Mode;
910

1011
use crate::ast::helpers;
1112
use crate::ast::helpers::to_absolute;
@@ -371,7 +372,9 @@ pub fn remove_argument(
371372
if n_arguments == 1 {
372373
// Case 1: there is only one argument.
373374
let mut count: usize = 0;
374-
for (start, tok, end) in lexer::make_tokenizer_located(contents, stmt_at).flatten() {
375+
for (start, tok, end) in
376+
lexer::make_tokenizer_located(contents, Mode::Module, stmt_at).flatten()
377+
{
375378
if matches!(tok, Tok::Lpar) {
376379
if count == 0 {
377380
fix_start = Some(if remove_parentheses {
@@ -403,7 +406,9 @@ pub fn remove_argument(
403406
{
404407
// Case 2: argument or keyword is _not_ the last node.
405408
let mut seen_comma = false;
406-
for (start, tok, end) in lexer::make_tokenizer_located(contents, stmt_at).flatten() {
409+
for (start, tok, end) in
410+
lexer::make_tokenizer_located(contents, Mode::Module, stmt_at).flatten()
411+
{
407412
if seen_comma {
408413
if matches!(tok, Tok::NonLogicalNewline) {
409414
// Also delete any non-logical newlines after the comma.
@@ -426,7 +431,9 @@ pub fn remove_argument(
426431
} else {
427432
// Case 3: argument or keyword is the last node, so we have to find the last
428433
// comma in the stmt.
429-
for (start, tok, _) in lexer::make_tokenizer_located(contents, stmt_at).flatten() {
434+
for (start, tok, _) in
435+
lexer::make_tokenizer_located(contents, Mode::Module, stmt_at).flatten()
436+
{
430437
if start == expr_at {
431438
fix_end = Some(expr_end);
432439
break;

crates/ruff/src/checkers/logical_lines.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ pub fn check_logical_lines(
154154
mod tests {
155155
use rustpython_parser::lexer;
156156
use rustpython_parser::lexer::LexResult;
157+
use rustpython_parser::mode::Mode;
157158

158159
use crate::checkers::logical_lines::iter_logical_lines;
159160
use crate::source_code::Locator;
@@ -164,7 +165,7 @@ mod tests {
164165
x = 1
165166
y = 2
166167
z = x + 1"#;
167-
let lxr: Vec<LexResult> = lexer::make_tokenizer(contents).collect();
168+
let lxr: Vec<LexResult> = lexer::make_tokenizer(contents, Mode::Module).collect();
168169
let locator = Locator::new(contents);
169170
let actual: Vec<String> = iter_logical_lines(&lxr, &locator)
170171
.into_iter()
@@ -185,7 +186,7 @@ x = [
185186
]
186187
y = 2
187188
z = x + 1"#;
188-
let lxr: Vec<LexResult> = lexer::make_tokenizer(contents).collect();
189+
let lxr: Vec<LexResult> = lexer::make_tokenizer(contents, Mode::Module).collect();
189190
let locator = Locator::new(contents);
190191
let actual: Vec<String> = iter_logical_lines(&lxr, &locator)
191192
.into_iter()
@@ -199,7 +200,7 @@ z = x + 1"#;
199200
assert_eq!(actual, expected);
200201

201202
let contents = "x = 'abc'";
202-
let lxr: Vec<LexResult> = lexer::make_tokenizer(contents).collect();
203+
let lxr: Vec<LexResult> = lexer::make_tokenizer(contents, Mode::Module).collect();
203204
let locator = Locator::new(contents);
204205
let actual: Vec<String> = iter_logical_lines(&lxr, &locator)
205206
.into_iter()
@@ -212,7 +213,7 @@ z = x + 1"#;
212213
def f():
213214
x = 1
214215
f()"#;
215-
let lxr: Vec<LexResult> = lexer::make_tokenizer(contents).collect();
216+
let lxr: Vec<LexResult> = lexer::make_tokenizer(contents, Mode::Module).collect();
216217
let locator = Locator::new(contents);
217218
let actual: Vec<String> = iter_logical_lines(&lxr, &locator)
218219
.into_iter()
@@ -227,7 +228,7 @@ def f():
227228
# Comment goes here.
228229
x = 1
229230
f()"#;
230-
let lxr: Vec<LexResult> = lexer::make_tokenizer(contents).collect();
231+
let lxr: Vec<LexResult> = lexer::make_tokenizer(contents, Mode::Module).collect();
231232
let locator = Locator::new(contents);
232233
let actual: Vec<String> = iter_logical_lines(&lxr, &locator)
233234
.into_iter()

0 commit comments

Comments
 (0)