Re-integrate RustPython parser repository (#4359)

Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
Jeong, YunWon 2023-05-11 16:47:17 +09:00 committed by GitHub
parent 865205d992
commit be6e00ef6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
270 changed files with 3061 additions and 3361 deletions

271
Cargo.lock generated
View file

@ -144,15 +144,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
[[package]]
name = "ascii-canvas"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6"
dependencies = [
"term",
]
[[package]]
name = "assert_cmd"
version = "2.0.11"
@ -200,21 +191,6 @@ dependencies = [
"serde",
]
[[package]]
name = "bit-set"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
dependencies = [
"bit-vec",
]
[[package]]
name = "bit-vec"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
[[package]]
name = "bitflags"
version = "1.3.2"
@ -223,9 +199,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.1.0"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c70beb79cbb5ce9c4f8e20849978f34225931f665bb49efa6982875a4d5facb3"
checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813"
[[package]]
name = "bstr"
@ -700,16 +676,6 @@ dependencies = [
"dirs-sys 0.4.0",
]
[[package]]
name = "dirs-next"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
dependencies = [
"cfg-if",
"dirs-sys-next",
]
[[package]]
name = "dirs-sys"
version = "0.3.7"
@ -732,17 +698,6 @@ dependencies = [
"windows-sys 0.45.0",
]
[[package]]
name = "dirs-sys-next"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "doc-comment"
version = "0.3.3"
@ -767,15 +722,6 @@ version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "ena"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1"
dependencies = [
"log",
]
[[package]]
name = "encode_unicode"
version = "0.3.6"
@ -833,12 +779,6 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "fixedbitset"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flake8-to-ruff"
version = "0.0.265"
@ -1168,37 +1108,11 @@ dependencies = [
"libc",
]
[[package]]
name = "lalrpop"
version = "0.19.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f34313ec00c2eb5c3c87ca6732ea02dcf3af99c3ff7a8fb622ffb99c9d860a87"
dependencies = [
"ascii-canvas",
"bit-set",
"diff",
"ena",
"is-terminal",
"itertools",
"lalrpop-util",
"petgraph",
"pico-args",
"regex",
"regex-syntax 0.6.29",
"string_cache",
"term",
"tiny-keccak",
"unicode-xid",
]
[[package]]
name = "lalrpop-util"
version = "0.19.9"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5c1f7869c94d214466c5fd432dfed12c379fd87786768d36455892d46b18edd"
dependencies = [
"regex",
]
checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d"
[[package]]
name = "lazy_static"
@ -1388,12 +1302,6 @@ version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308d96db8debc727c3fd9744aac51751243420e46edf401010908da7f8d5e57c"
[[package]]
name = "new_debug_unreachable"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
[[package]]
name = "nextest-workspace-hack"
version = "0.1.0"
@ -1525,29 +1433,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
dependencies = [
"cfg-if",
"libc",
"redox_syscall 0.2.16",
"smallvec",
"windows-sys 0.45.0",
]
[[package]]
name = "paste"
version = "1.0.12"
@ -1624,23 +1509,13 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "petgraph"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
dependencies = [
"fixedbitset",
"indexmap",
]
[[package]]
name = "phf"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c"
dependencies = [
"phf_shared 0.11.1",
"phf_shared",
]
[[package]]
@ -1650,7 +1525,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770"
dependencies = [
"phf_generator",
"phf_shared 0.11.1",
"phf_shared",
]
[[package]]
@ -1659,19 +1534,10 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf"
dependencies = [
"phf_shared 0.11.1",
"phf_shared",
"rand",
]
[[package]]
name = "phf_shared"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
dependencies = [
"siphasher",
]
[[package]]
name = "phf_shared"
version = "0.11.1"
@ -1681,12 +1547,6 @@ dependencies = [
"siphasher",
]
[[package]]
name = "pico-args"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468"
[[package]]
name = "pin-project-lite"
version = "0.2.9"
@ -1738,12 +1598,6 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "precomputed-hash"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "predicates"
version = "3.0.3"
@ -1944,7 +1798,7 @@ checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
dependencies = [
"aho-corasick 1.0.1",
"memchr",
"regex-syntax 0.7.1",
"regex-syntax",
]
[[package]]
@ -1953,12 +1807,6 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.7.1"
@ -2008,7 +1856,7 @@ version = "0.0.265"
dependencies = [
"annotate-snippets 0.9.1",
"anyhow",
"bitflags 2.1.0",
"bitflags 2.2.1",
"chrono",
"clap 4.2.4",
"colored",
@ -2101,7 +1949,7 @@ dependencies = [
"assert_cmd",
"atty",
"bincode",
"bitflags 2.1.0",
"bitflags 2.2.1",
"cachedir",
"chrono",
"clap 4.2.4",
@ -2200,7 +2048,7 @@ name = "ruff_python_ast"
version = "0.0.0"
dependencies = [
"anyhow",
"bitflags 2.1.0",
"bitflags 2.2.1",
"is-macro",
"itertools",
"log",
@ -2209,10 +2057,9 @@ dependencies = [
"num-traits",
"once_cell",
"regex",
"ruff_rustpython",
"ruff_text_size",
"rustc-hash",
"rustpython-common",
"rustpython-literal 0.2.0 (git+https://github.com/RustPython/Parser.git?rev=2af98056629fbe75ccc0d90c4ee05dfeb403d666)",
"rustpython-parser",
"serde",
"smallvec",
@ -2234,7 +2081,6 @@ dependencies = [
"ruff_testing_macros",
"ruff_text_size",
"rustc-hash",
"rustpython-common",
"rustpython-parser",
"similar",
"test-case",
@ -2244,7 +2090,7 @@ dependencies = [
name = "ruff_python_semantic"
version = "0.0.0"
dependencies = [
"bitflags 2.1.0",
"bitflags 2.2.1",
"is-macro",
"nohash-hasher",
"ruff_python_ast",
@ -2268,8 +2114,6 @@ name = "ruff_rustpython"
version = "0.0.0"
dependencies = [
"anyhow",
"once_cell",
"rustpython-common",
"rustpython-parser",
]
@ -2286,7 +2130,7 @@ dependencies = [
[[package]]
name = "ruff_text_size"
version = "0.0.0"
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
source = "git+https://github.com/RustPython/Parser.git?rev=2af98056629fbe75ccc0d90c4ee05dfeb403d666#2af98056629fbe75ccc0d90c4ee05dfeb403d666"
dependencies = [
"schemars",
"serde",
@ -2357,75 +2201,92 @@ dependencies = [
[[package]]
name = "rustpython-ast"
version = "0.2.0"
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
source = "git+https://github.com/RustPython/Parser.git?rev=2af98056629fbe75ccc0d90c4ee05dfeb403d666#2af98056629fbe75ccc0d90c4ee05dfeb403d666"
dependencies = [
"num-bigint",
"ruff_text_size",
"rustpython-parser-core",
]
[[package]]
name = "rustpython-common"
version = "0.2.0"
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
source = "git+https://github.com/RustPython/RustPython.git?rev=f3e4d3409253660bd4fa7f3d24d3db747e7dca61#f3e4d3409253660bd4fa7f3d24d3db747e7dca61"
dependencies = [
"ascii",
"bitflags 1.3.2",
"bitflags 2.2.1",
"bstr 0.2.17",
"cfg-if",
"getrandom",
"hexf-parse",
"itertools",
"lexical-parse-float",
"libc",
"lock_api",
"num-bigint",
"num-complex",
"num-traits",
"once_cell",
"radium",
"rand",
"rustpython-literal 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=5b2af304a2baa53598e594097824165d4ac7a119)",
"siphasher",
"unic-ucd-category",
"volatile",
"widestring",
]
[[package]]
name = "rustpython-compiler-core"
name = "rustpython-literal"
version = "0.2.0"
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
source = "git+https://github.com/RustPython/Parser.git?rev=2af98056629fbe75ccc0d90c4ee05dfeb403d666#2af98056629fbe75ccc0d90c4ee05dfeb403d666"
dependencies = [
"bitflags 1.3.2",
"itertools",
"lz4_flex",
"num-bigint",
"num-complex",
"ruff_text_size",
"hexf-parse",
"lexical-parse-float",
"num-traits",
"unic-ucd-category",
]
[[package]]
name = "rustpython-literal"
version = "0.2.0"
source = "git+https://github.com/youknowone/RustPython-parser.git?rev=5b2af304a2baa53598e594097824165d4ac7a119#5b2af304a2baa53598e594097824165d4ac7a119"
dependencies = [
"hexf-parse",
"lexical-parse-float",
"num-traits",
"unic-ucd-category",
]
[[package]]
name = "rustpython-parser"
version = "0.2.0"
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
source = "git+https://github.com/RustPython/Parser.git?rev=2af98056629fbe75ccc0d90c4ee05dfeb403d666#2af98056629fbe75ccc0d90c4ee05dfeb403d666"
dependencies = [
"anyhow",
"itertools",
"lalrpop",
"lalrpop-util",
"log",
"num-bigint",
"num-traits",
"phf",
"phf_codegen",
"ruff_text_size",
"rustc-hash",
"rustpython-ast",
"rustpython-compiler-core",
"rustpython-parser-core",
"tiny-keccak",
"unic-emoji-char",
"unic-ucd-ident",
"unicode_names2",
]
[[package]]
name = "rustpython-parser-core"
version = "0.2.0"
source = "git+https://github.com/RustPython/Parser.git?rev=2af98056629fbe75ccc0d90c4ee05dfeb403d666#2af98056629fbe75ccc0d90c4ee05dfeb403d666"
dependencies = [
"itertools",
"lz4_flex",
"num-bigint",
"num-complex",
"ruff_text_size",
]
[[package]]
name = "rustversion"
version = "1.0.12"
@ -2613,19 +2474,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "string_cache"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
dependencies = [
"new_debug_unreachable",
"once_cell",
"parking_lot",
"phf_shared 0.10.0",
"precomputed-hash",
]
[[package]]
name = "strsim"
version = "0.10.0"
@ -2698,17 +2546,6 @@ dependencies = [
"windows-sys 0.45.0",
]
[[package]]
name = "term"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
dependencies = [
"dirs-next",
"rustversion",
"winapi",
]
[[package]]
name = "termcolor"
version = "1.2.0"
@ -3061,12 +2898,6 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "unicode_names2"
version = "0.6.0"

View file

@ -11,7 +11,7 @@ authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
[workspace.dependencies]
anyhow = { version = "1.0.69" }
bitflags = { version = "2.1.0" }
bitflags = { version = "2.2.1" }
chrono = { version = "0.4.23", default-features = false, features = ["clock"] }
clap = { version = "4.1.8", features = ["derive"] }
colored = { version = "2.0.0" }
@ -30,10 +30,11 @@ path-absolutize = { version = "3.0.14" }
proc-macro2 = { version = "1.0.51" }
quote = { version = "1.0.23" }
regex = { version = "1.7.1" }
ruff_text_size = { git = "https://github.com/charliermarsh/RustPython.git", rev = "c3147d2c1524ebd0e90cf1c2938d770314fd5a5a" }
ruff_text_size = { git = "https://github.com/RustPython/Parser.git", rev = "2af98056629fbe75ccc0d90c4ee05dfeb403d666" }
rustc-hash = { version = "1.1.0" }
rustpython-common = { git = "https://github.com/charliermarsh/RustPython.git", rev = "c3147d2c1524ebd0e90cf1c2938d770314fd5a5a" }
rustpython-parser = { git = "https://github.com/charliermarsh/RustPython.git", rev = "c3147d2c1524ebd0e90cf1c2938d770314fd5a5a" }
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "f3e4d3409253660bd4fa7f3d24d3db747e7dca61" }
rustpython-literal = { git = "https://github.com/RustPython/Parser.git", rev = "2af98056629fbe75ccc0d90c4ee05dfeb403d666" }
rustpython-parser = { git = "https://github.com/RustPython/Parser.git", rev = "2af98056629fbe75ccc0d90c4ee05dfeb403d666" , default-features = false}
schemars = { version = "0.8.12" }
serde = { version = "1.0.152", features = ["derive"] }
serde_json = { version = "1.0.93", features = ["preserve_order"] }

View file

@ -5,7 +5,7 @@ use libcst_native::{
Codegen, CodegenState, ImportNames, ParenthesizableWhitespace, SmallStatement, Statement,
};
use ruff_text_size::{TextLen, TextRange, TextSize};
use rustpython_parser::ast::{ExcepthandlerKind, Expr, Keyword, Stmt, StmtKind};
use rustpython_parser::ast::{self, ExcepthandlerKind, Expr, Keyword, Stmt, StmtKind};
use rustpython_parser::{lexer, Mode, Tok};
use ruff_diagnostics::Edit;
@ -28,21 +28,21 @@ fn has_single_child(body: &[Stmt], deleted: &[&Stmt]) -> bool {
/// Determine if a child is the only statement in its body.
fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result<bool> {
match &parent.node {
StmtKind::FunctionDef { body, .. }
| StmtKind::AsyncFunctionDef { body, .. }
| StmtKind::ClassDef { body, .. }
| StmtKind::With { body, .. }
| StmtKind::AsyncWith { body, .. } => {
StmtKind::FunctionDef(ast::StmtFunctionDef { body, .. })
| StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. })
| StmtKind::ClassDef(ast::StmtClassDef { body, .. })
| StmtKind::With(ast::StmtWith { body, .. })
| StmtKind::AsyncWith(ast::StmtAsyncWith { body, .. }) => {
if body.iter().contains(child) {
Ok(has_single_child(body, deleted))
} else {
bail!("Unable to find child in parent body")
}
}
StmtKind::For { body, orelse, .. }
| StmtKind::AsyncFor { body, orelse, .. }
| StmtKind::While { body, orelse, .. }
| StmtKind::If { body, orelse, .. } => {
StmtKind::For(ast::StmtFor { body, orelse, .. })
| StmtKind::AsyncFor(ast::StmtAsyncFor { body, orelse, .. })
| StmtKind::While(ast::StmtWhile { body, orelse, .. })
| StmtKind::If(ast::StmtIf { body, orelse, .. }) => {
if body.iter().contains(child) {
Ok(has_single_child(body, deleted))
} else if orelse.iter().contains(child) {
@ -51,18 +51,18 @@ fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result<bool>
bail!("Unable to find child in parent body")
}
}
StmtKind::Try {
StmtKind::Try(ast::StmtTry {
body,
handlers,
orelse,
finalbody,
}
| StmtKind::TryStar {
})
| StmtKind::TryStar(ast::StmtTryStar {
body,
handlers,
orelse,
finalbody,
} => {
}) => {
if body.iter().contains(child) {
Ok(has_single_child(body, deleted))
} else if orelse.iter().contains(child) {
@ -70,7 +70,9 @@ fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result<bool>
} else if finalbody.iter().contains(child) {
Ok(has_single_child(finalbody, deleted))
} else if let Some(body) = handlers.iter().find_map(|handler| match &handler.node {
ExcepthandlerKind::ExceptHandler { body, .. } => {
ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler {
body, ..
}) => {
if body.iter().contains(child) {
Some(body)
} else {
@ -83,7 +85,7 @@ fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result<bool>
bail!("Unable to find child in parent body")
}
}
StmtKind::Match { cases, .. } => {
StmtKind::Match(ast::StmtMatch { cases, .. }) => {
if let Some(body) = cases.iter().find_map(|case| {
if case.body.iter().contains(child) {
Some(&case.body)
@ -350,7 +352,7 @@ pub fn remove_argument(
if n_arguments == 1 {
// Case 1: there is only one argument.
let mut count: usize = 0;
for (tok, range) in lexer::lex_located(contents, Mode::Module, call_at).flatten() {
for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, call_at).flatten() {
if matches!(tok, Tok::Lpar) {
if count == 0 {
fix_start = Some(if remove_parentheses {
@ -382,7 +384,7 @@ pub fn remove_argument(
{
// Case 2: argument or keyword is _not_ the last node.
let mut seen_comma = false;
for (tok, range) in lexer::lex_located(contents, Mode::Module, call_at).flatten() {
for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, call_at).flatten() {
if seen_comma {
if matches!(tok, Tok::NonLogicalNewline) {
// Also delete any non-logical newlines after the comma.
@ -405,7 +407,7 @@ pub fn remove_argument(
} else {
// Case 3: argument or keyword is the last node, so we have to find the last
// comma in the stmt.
for (tok, range) in lexer::lex_located(contents, Mode::Module, call_at).flatten() {
for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, call_at).flatten() {
if range.start() == expr_range.start() {
fix_end = Some(expr_range.end());
break;

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
use std::borrow::Cow;
use std::path::Path;
use rustpython_parser::ast::{StmtKind, Suite};
use rustpython_parser::ast::{self, StmtKind, Suite};
use ruff_diagnostics::Diagnostic;
use ruff_python_ast::helpers::to_module_path;
@ -29,20 +29,21 @@ fn extract_import_map(path: &Path, package: Option<&Path>, blocks: &[&Block]) ->
let mut module_imports = Vec::with_capacity(num_imports);
for stmt in blocks.iter().flat_map(|block| &block.imports) {
match &stmt.node {
StmtKind::Import { names } => {
StmtKind::Import(ast::StmtImport { names }) => {
module_imports.extend(
names
.iter()
.map(|name| ModuleImport::new(name.node.name.clone(), stmt.range())),
.map(|name| ModuleImport::new(name.node.name.to_string(), stmt.range())),
);
}
StmtKind::ImportFrom {
StmtKind::ImportFrom(ast::StmtImportFrom {
module,
names,
level,
} => {
let level = level.unwrap_or(0);
}) => {
let level = level.map_or(0, |level| level.to_usize());
let module = if let Some(module) = module {
let module: &String = module.as_ref();
if level == 0 {
Cow::Borrowed(module)
} else {

View file

@ -4,7 +4,7 @@
use std::iter::FusedIterator;
use ruff_text_size::{TextRange, TextSize};
use rustpython_parser::ast::{Constant, ExprKind, Stmt, StmtKind, Suite};
use rustpython_parser::ast::{self, Constant, ExprKind, Stmt, StmtKind, Suite};
use rustpython_parser::lexer::LexResult;
use rustpython_parser::Tok;
@ -76,11 +76,11 @@ struct StringLinesVisitor<'a> {
impl StatementVisitor<'_> for StringLinesVisitor<'_> {
fn visit_stmt(&mut self, stmt: &Stmt) {
if let StmtKind::Expr { value } = &stmt.node {
if let ExprKind::Constant {
if let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node {
if let ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(..),
..
} = &value.node
}) = &value.node
{
for line in UniversalNewlineIterator::with_offset(
self.locator.slice(value.range()),

View file

@ -1,6 +1,6 @@
//! Extract docstrings from an AST.
use rustpython_parser::ast::{Constant, Expr, ExprKind, Stmt, StmtKind};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Stmt, StmtKind};
use ruff_python_semantic::analyze::visibility;
@ -10,16 +10,16 @@ use crate::docstrings::definition::{Definition, DefinitionKind, Documentable};
pub fn docstring_from(suite: &[Stmt]) -> Option<&Expr> {
let stmt = suite.first()?;
// Require the docstring to be a standalone expression.
let StmtKind::Expr { value } = &stmt.node else {
let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node else {
return None;
};
// Only match strings.
if !matches!(
&value.node,
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(_),
..
}
})
) {
return None;
}

View file

@ -3,7 +3,7 @@
use anyhow::Result;
use libcst_native::{Codegen, CodegenState, ImportAlias, Name, NameOrAttribute};
use ruff_text_size::TextSize;
use rustpython_parser::ast::{Stmt, StmtKind, Suite};
use rustpython_parser::ast::{self, Stmt, StmtKind, Suite};
use rustpython_parser::{lexer, Mode, Tok};
use ruff_diagnostics::Edit;
@ -79,13 +79,13 @@ impl<'a> Importer<'a> {
if stmt.start() >= at {
break;
}
if let StmtKind::ImportFrom {
if let StmtKind::ImportFrom(ast::StmtImportFrom {
module: name,
level,
..
} = &stmt.node
}) = &stmt.node
{
if level.map_or(true, |level| level == 0)
if level.map_or(true, |level| level.to_u32() == 0)
&& name.as_ref().map_or(false, |name| name == module)
{
import_from = Some(*stmt);
@ -178,7 +178,8 @@ fn match_docstring_end(body: &[Stmt]) -> Option<TextSize> {
/// along with a trailing newline suffix.
fn end_of_statement_insertion(stmt: &Stmt, locator: &Locator, stylist: &Stylist) -> Insertion {
let location = stmt.end();
let mut tokens = lexer::lex_located(locator.after(location), Mode::Module, location).flatten();
let mut tokens =
lexer::lex_starts_at(locator.after(location), Mode::Module, location).flatten();
if let Some((Tok::Semi, range)) = tokens.next() {
// If the first token after the docstring is a semicolon, insert after the semicolon as an
// inline statement;
@ -211,7 +212,7 @@ fn top_of_file_insertion(body: &[Stmt], locator: &Locator, stylist: &Stylist) ->
let mut location = if let Some(location) = match_docstring_end(body) {
// If the first token after the docstring is a semicolon, insert after the semicolon as an
// inline statement;
let first_token = lexer::lex_located(locator.after(location), Mode::Module, location)
let first_token = lexer::lex_starts_at(locator.after(location), Mode::Module, location)
.flatten()
.next();
if let Some((Tok::Semi, range)) = first_token {
@ -226,7 +227,7 @@ fn top_of_file_insertion(body: &[Stmt], locator: &Locator, stylist: &Stylist) ->
// Skip over any comments and empty lines.
for (tok, range) in
lexer::lex_located(locator.after(location), Mode::Module, location).flatten()
lexer::lex_starts_at(locator.after(location), Mode::Module, location).flatten()
{
if matches!(tok, Tok::Comment(..) | Tok::Newline) {
location = locator.full_line_end(range.end());

View file

@ -145,7 +145,7 @@ impl<'a> DisplayParseError<'a> {
impl Display for DisplayParseError<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let source_location = self.source_code.source_location(self.error.location);
let source_location = self.source_code.source_location(self.error.offset);
write!(
f,

View file

@ -1,5 +1,5 @@
use num_bigint::BigInt;
use rustpython_parser::ast::{Cmpop, Constant, Expr, ExprKind, Located};
use rustpython_parser::ast::{self, Attributed, Cmpop, Constant, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -124,16 +124,15 @@ fn is_sys(checker: &Checker, expr: &Expr, target: &str) -> bool {
pub fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) {
if is_sys(checker, value, "version") {
match &slice.node {
ExprKind::Slice {
ExprKind::Slice(ast::ExprSlice {
lower: None,
upper: Some(upper),
step: None,
..
} => {
if let ExprKind::Constant {
}) => {
if let ExprKind::Constant(ast::ExprConstant {
value: Constant::Int(i),
..
} = &upper.node
}) = &upper.node
{
if *i == BigInt::from(1)
&& checker.settings.rules.enabled(Rule::SysVersionSlice1)
@ -151,10 +150,10 @@ pub fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) {
}
}
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Int(i),
..
} => {
}) => {
if *i == BigInt::from(2) && checker.settings.rules.enabled(Rule::SysVersion2) {
checker
.diagnostics
@ -175,21 +174,23 @@ pub fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) {
/// YTT103, YTT201, YTT203, YTT204, YTT302
pub fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &[Expr]) {
match &left.node {
ExprKind::Subscript { value, slice, .. } if is_sys(checker, value, "version_info") => {
if let ExprKind::Constant {
ExprKind::Subscript(ast::ExprSubscript { value, slice, .. })
if is_sys(checker, value, "version_info") =>
{
if let ExprKind::Constant(ast::ExprConstant {
value: Constant::Int(i),
..
} = &slice.node
}) = &slice.node
{
if *i == BigInt::from(0) {
if let (
[Cmpop::Eq | Cmpop::NotEq],
[Located {
[Attributed {
node:
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Int(n),
..
},
}),
..
}],
) = (ops, comparators)
@ -205,12 +206,12 @@ pub fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &
} else if *i == BigInt::from(1) {
if let (
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE],
[Located {
[Attributed {
node:
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Int(_),
..
},
}),
..
}],
) = (ops, comparators)
@ -225,17 +226,17 @@ pub fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &
}
}
ExprKind::Attribute { value, attr, .. }
ExprKind::Attribute(ast::ExprAttribute { value, attr, .. })
if is_sys(checker, value, "version_info") && attr == "minor" =>
{
if let (
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE],
[Located {
[Attributed {
node:
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Int(_),
..
},
}),
..
}],
) = (ops, comparators)
@ -258,12 +259,12 @@ pub fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &
if is_sys(checker, left, "version") {
if let (
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE],
[Located {
[Attributed {
node:
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(s),
..
},
}),
..
}],
) = (ops, comparators)

View file

@ -13,7 +13,7 @@ pub fn add_return_annotation(locator: &Locator, stmt: &Stmt, annotation: &str) -
let mut seen_lpar = false;
let mut seen_rpar = false;
let mut count: usize = 0;
for (tok, range) in lexer::lex_located(contents, Mode::Module, stmt.start()).flatten() {
for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, stmt.start()).flatten() {
if seen_lpar && seen_rpar {
if matches!(tok, Tok::Colon) {
return Ok(Edit::insertion(format!(" -> {annotation}"), range.start()));

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Arguments, Expr, Stmt, StmtKind};
use rustpython_parser::ast::{self, Arguments, Expr, Stmt, StmtKind};
use ruff_python_ast::cast;
use ruff_python_semantic::analyze::visibility;
@ -8,20 +8,20 @@ use crate::docstrings::definition::{Definition, DefinitionKind};
pub(super) fn match_function_def(stmt: &Stmt) -> (&str, &Arguments, Option<&Expr>, &Vec<Stmt>) {
match &stmt.node {
StmtKind::FunctionDef {
StmtKind::FunctionDef(ast::StmtFunctionDef {
name,
args,
returns,
body,
..
}
| StmtKind::AsyncFunctionDef {
})
| StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef {
name,
args,
returns,
body,
..
} => (name, args, returns.as_ref().map(|expr| &**expr), body),
}) => (name, args, returns.as_ref().map(|expr| &**expr), body),
_ => panic!("Found non-FunctionDef in match_name"),
}
}

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Constant, Expr, ExprKind, Stmt};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Stmt};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -420,10 +420,10 @@ fn is_none_returning(body: &[Stmt]) -> bool {
for expr in visitor.returns.into_iter().flatten() {
if !matches!(
expr.node,
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::None,
..
}
})
) {
return false;
}

View file

@ -1,6 +1,6 @@
use once_cell::sync::Lazy;
use regex::Regex;
use rustpython_parser::ast::{Constant, Expr, ExprKind};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind};
use crate::checkers::ast::Checker;
@ -10,10 +10,10 @@ static PASSWORD_CANDIDATE_REGEX: Lazy<Regex> = Lazy::new(|| {
pub fn string_literal(expr: &Expr) -> Option<&str> {
match &expr.node {
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(string),
..
} => Some(string),
}) => Some(string),
_ => None,
}
}
@ -24,7 +24,7 @@ pub fn matches_password_name(string: &str) -> bool {
pub fn is_untyped_exception(type_: Option<&Expr>, checker: &Checker) -> bool {
type_.map_or(true, |type_| {
if let ExprKind::Tuple { elts, .. } = &type_.node {
if let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &type_.node {
elts.iter().any(|type_| {
checker
.ctx

View file

@ -1,7 +1,7 @@
use num_traits::ToPrimitive;
use once_cell::sync::Lazy;
use rustc_hash::FxHashMap;
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword, Operator};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword, Operator};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -70,14 +70,14 @@ static PYSTAT_MAPPING: Lazy<FxHashMap<&'static str, u16>> = Lazy::new(|| {
fn get_int_value(expr: &Expr) -> Option<u16> {
match &expr.node {
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Int(value),
..
} => value.to_u16(),
ExprKind::Attribute { .. } => {
}) => value.to_u16(),
ExprKind::Attribute(_) => {
compose_call_path(expr).and_then(|path| PYSTAT_MAPPING.get(path.as_str()).copied())
}
ExprKind::BinOp { left, op, right } => {
ExprKind::BinOp(ast::ExprBinOp { left, op, right }) => {
if let (Some(left_value), Some(right_value)) =
(get_int_value(left), get_int_value(right))
{

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind};
use rustpython_parser::ast::{self, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -15,7 +15,7 @@ impl Violation for ExecBuiltin {
/// S102
pub fn exec_used(expr: &Expr, func: &Expr) -> Option<Diagnostic> {
let ExprKind::Name { id, .. } = &func.node else {
let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else {
return None;
};
if id != "exec" {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Constant, Expr, ExprKind};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -24,17 +24,17 @@ impl Violation for HardcodedPasswordString {
fn password_target(target: &Expr) -> Option<&str> {
let target_name = match &target.node {
// variable = "s3cr3t"
ExprKind::Name { id, .. } => id,
ExprKind::Name(ast::ExprName { id, .. }) => id.as_str(),
// d["password"] = "s3cr3t"
ExprKind::Subscript { slice, .. } => match &slice.node {
ExprKind::Constant {
ExprKind::Subscript(ast::ExprSubscript { slice, .. }) => match &slice.node {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(string),
..
} => string,
}) => string,
_ => return None,
},
// obj.password = "s3cr3t"
ExprKind::Attribute { attr, .. } => attr,
ExprKind::Attribute(ast::ExprAttribute { attr, .. }) => attr,
_ => return None,
};

View file

@ -1,6 +1,6 @@
use once_cell::sync::Lazy;
use regex::Regex;
use rustpython_parser::ast::{Expr, ExprKind, Operator};
use rustpython_parser::ast::{self, Expr, ExprKind, Operator};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -56,10 +56,10 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio
match &expr.node {
// "select * from table where val = " + "str" + ...
// "select * from table where val = %s" % ...
ExprKind::BinOp {
ExprKind::BinOp(ast::ExprBinOp {
op: Operator::Add | Operator::Mod,
..
} => {
}) => {
let Some(parent) = checker.ctx.expr_parent() else {
if any_over_expr(expr, &has_string_literal) {
return Some(unparse_expr(expr, checker.stylist));
@ -67,7 +67,7 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio
return None;
};
// Only evaluate the full BinOp, not the nested components.
let ExprKind::BinOp { .. } = &parent.node else {
let ExprKind::BinOp(_ )= &parent.node else {
if any_over_expr(expr, &has_string_literal) {
return Some(unparse_expr(expr, checker.stylist));
}
@ -75,8 +75,8 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio
};
None
}
ExprKind::Call { func, .. } => {
let ExprKind::Attribute{ attr, value, .. } = &func.node else {
ExprKind::Call(ast::ExprCall { func, .. }) => {
let ExprKind::Attribute(ast::ExprAttribute { attr, value, .. }) = &func.node else {
return None;
};
// "select * from table where val = {}".format(...)
@ -86,7 +86,7 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio
None
}
// f"select * from table where val = {val}"
ExprKind::JoinedStr { .. } => Some(unparse_expr(expr, checker.stylist)),
ExprKind::JoinedStr(_) => Some(unparse_expr(expr, checker.stylist)),
_ => None,
}
}

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -27,10 +27,10 @@ fn is_used_for_security(call_args: &SimpleCallArgs) -> bool {
match call_args.keyword_argument("usedforsecurity") {
Some(expr) => !matches!(
&expr.node,
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Bool(false),
..
}
})
),
_ => true,
}

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -47,13 +47,13 @@ pub fn jinja2_autoescape_false(
if let Some(autoescape_arg) = call_args.keyword_argument("autoescape") {
match &autoescape_arg.node {
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Bool(true),
..
} => (),
ExprKind::Call { func, .. } => {
if let ExprKind::Name { id, .. } = &func.node {
if id.as_str() != "select_autoescape" {
}) => (),
ExprKind::Call(ast::ExprCall { func, .. }) => {
if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node {
if id != "select_autoescape" {
checker.diagnostics.push(Diagnostic::new(
Jinja2AutoescapeFalse { value: true },
autoescape_arg.range(),

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -56,10 +56,10 @@ pub fn request_with_no_cert_validation(
}) {
let call_args = SimpleCallArgs::new(args, keywords);
if let Some(verify_arg) = call_args.keyword_argument("verify") {
if let ExprKind::Constant {
if let ExprKind::Constant(ast::ExprConstant {
value: Constant::Bool(false),
..
} = &verify_arg.node
}) = &verify_arg.node
{
checker.diagnostics.push(Diagnostic::new(
RequestWithNoCertValidation {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -45,10 +45,10 @@ pub fn request_without_timeout(
let call_args = SimpleCallArgs::new(args, keywords);
if let Some(timeout_arg) = call_args.keyword_argument("timeout") {
if let Some(timeout) = match &timeout_arg.node {
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: value @ Constant::None,
..
} => Some(unparse_constant(value, checker.stylist)),
}) => Some(unparse_constant(value, checker.stylist)),
_ => None,
} {
checker.diagnostics.push(Diagnostic::new(

View file

@ -2,7 +2,7 @@
use once_cell::sync::Lazy;
use regex::Regex;
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -159,17 +159,17 @@ fn find_shell_keyword<'a>(ctx: &Context, keywords: &'a [Keyword]) -> Option<Shel
fn shell_call_seems_safe(arg: &Expr) -> bool {
matches!(
arg.node,
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(_),
..
}
})
)
}
/// Return the [`Expr`] as a string literal, if it's a string or a list of strings.
fn try_string_literal(expr: &Expr) -> Option<&str> {
match &expr.node {
ExprKind::List { elts, .. } => {
ExprKind::List(ast::ExprList { elts, .. }) => {
if elts.is_empty() {
None
} else {

View file

@ -1,5 +1,5 @@
use num_traits::{One, Zero};
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -33,10 +33,10 @@ pub fn snmp_insecure_version(
{
let call_args = SimpleCallArgs::new(args, keywords);
if let Some(mp_model_arg) = call_args.keyword_argument("mpModel") {
if let ExprKind::Constant {
if let ExprKind::Constant(ast::ExprConstant {
value: Constant::Int(value),
..
} = &mp_model_arg.node
}) = &mp_model_arg.node
{
if value.is_zero() || value.is_one() {
checker

View file

@ -1,7 +1,7 @@
//! Check for calls to suspicious functions, or calls into suspicious modules.
//!
//! See: <https://bandit.readthedocs.io/en/latest/blacklists/blacklist_calls.html>
use rustpython_parser::ast::{Expr, ExprKind};
use rustpython_parser::ast::{self, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, DiagnosticKind, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -466,7 +466,7 @@ const SUSPICIOUS_MODULES: &[SuspiciousModule] = &[
/// S001
pub fn suspicious_function_call(checker: &mut Checker, expr: &Expr) {
let ExprKind::Call { func, .. } = &expr.node else {
let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node else {
return;
};

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -48,8 +48,8 @@ pub fn unsafe_yaml_load(checker: &mut Checker, func: &Expr, args: &[Expr], keywo
})
{
let loader = match &loader_arg.node {
ExprKind::Attribute { attr, .. } => Some(attr.to_string()),
ExprKind::Name { id, .. } => Some(id.to_string()),
ExprKind::Attribute(ast::ExprAttribute { attr, .. }) => Some(attr.to_string()),
ExprKind::Name(ast::ExprName { id, .. }) => Some(id.to_string()),
_ => None,
};
checker.diagnostics.push(Diagnostic::new(

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind};
use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -30,17 +30,17 @@ pub fn blind_except(
let Some(type_) = type_ else {
return;
};
let ExprKind::Name { id, .. } = &type_.node else {
let ExprKind::Name(ast::ExprName { id, .. }) = &type_.node else {
return;
};
for exception in ["BaseException", "Exception"] {
if id == exception && checker.ctx.is_builtin(exception) {
// If the exception is re-raised, don't flag an error.
if body.iter().any(|stmt| {
if let StmtKind::Raise { exc, .. } = &stmt.node {
if let StmtKind::Raise(ast::StmtRaise { exc, .. }) = &stmt.node {
if let Some(exc) = exc {
if let ExprKind::Name { id, .. } = &exc.node {
name.map_or(false, |name| name == id)
if let ExprKind::Name(ast::ExprName { id, .. }) = &exc.node {
name.map_or(false, |name| id == name)
} else {
false
}
@ -56,10 +56,12 @@ pub fn blind_except(
// If the exception is logged, don't flag an error.
if body.iter().any(|stmt| {
if let StmtKind::Expr { value } = &stmt.node {
if let ExprKind::Call { func, keywords, .. } = &value.node {
if let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node {
if let ExprKind::Call(ast::ExprCall { func, keywords, .. }) = &value.node {
if logging::is_logger_candidate(&checker.ctx, func) {
if let ExprKind::Attribute { attr, .. } = &func.node {
if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node
{
let attr = attr.as_str();
if attr == "exception" {
return true;
}

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Arguments, Constant, Expr, ExprKind};
use rustpython_parser::ast::{self, Arguments, Constant, Expr, ExprKind};
use ruff_diagnostics::Violation;
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
@ -67,11 +67,11 @@ const FUNC_DEF_NAME_ALLOWLIST: &[&str] = &["__setitem__"];
/// `true`, the function name must be explicitly allowed, and the argument must
/// be either the first or second argument in the call.
fn allow_boolean_trap(func: &Expr) -> bool {
if let ExprKind::Attribute { attr, .. } = &func.node {
if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node {
return FUNC_CALL_NAME_ALLOWLIST.contains(&attr.as_ref());
}
if let ExprKind::Name { id, .. } = &func.node {
if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node {
return FUNC_CALL_NAME_ALLOWLIST.contains(&id.as_ref());
}
@ -81,10 +81,10 @@ fn allow_boolean_trap(func: &Expr) -> bool {
const fn is_boolean_arg(arg: &Expr) -> bool {
matches!(
&arg.node,
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Bool(_),
..
}
})
)
}
@ -120,11 +120,11 @@ pub fn check_positional_boolean_in_def(
// check for both bool (python class) and 'bool' (string annotation)
let hint = match &expr.node {
ExprKind::Name { id, .. } => id == "bool",
ExprKind::Constant {
ExprKind::Name(ast::ExprName { id, .. }) => id == "bool",
ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(value),
..
} => value == "bool",
}) => value == "bool",
_ => false,
};
if !hint {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword, Stmt, StmtKind};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword, Stmt, StmtKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -57,8 +57,8 @@ fn is_abc_class(context: &Context, bases: &[Expr], keywords: &[Keyword]) -> bool
fn is_empty_body(body: &[Stmt]) -> bool {
body.iter().all(|stmt| match &stmt.node {
StmtKind::Pass => true,
StmtKind::Expr { value } => match &value.node {
ExprKind::Constant { value, .. } => {
StmtKind::Expr(ast::StmtExpr { value }) => match &value.node {
ExprKind::Constant(ast::ExprConstant { value, .. }) => {
matches!(value, Constant::Str(..) | Constant::Ellipsis)
}
_ => false,
@ -88,23 +88,23 @@ pub fn abstract_base_class(
for stmt in body {
// https://github.com/PyCQA/flake8-bugbear/issues/293
// Ignore abc's that declares a class attribute that must be set
if let StmtKind::AnnAssign { .. } | StmtKind::Assign { .. } = &stmt.node {
if let StmtKind::AnnAssign(_) | StmtKind::Assign(_) = &stmt.node {
has_abstract_method = true;
continue;
}
let (
StmtKind::FunctionDef {
StmtKind::FunctionDef(ast::StmtFunctionDef {
decorator_list,
body,
name: method_name,
..
} | StmtKind::AsyncFunctionDef {
}) | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef {
decorator_list,
body,
name: method_name,
..
}
})
) = &stmt.node else {
continue;
};

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextSize;
use rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind};
use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation};
@ -24,20 +24,17 @@ impl AlwaysAutofixableViolation for AssertFalse {
fn assertion_error(msg: Option<&Expr>) -> Stmt {
Stmt::new(
TextSize::default(),
TextSize::default(),
StmtKind::Raise {
TextRange::default(),
StmtKind::Raise(ast::StmtRaise {
exc: Some(Box::new(Expr::new(
TextSize::default(),
TextSize::default(),
ExprKind::Call {
TextRange::default(),
ExprKind::Call(ast::ExprCall {
func: Box::new(Expr::new(
TextSize::default(),
TextSize::default(),
ExprKind::Name {
id: "AssertionError".to_string(),
TextRange::default(),
ExprKind::Name(ast::ExprName {
id: "AssertionError".into(),
ctx: ExprContext::Load,
},
}),
)),
args: if let Some(msg) = msg {
vec![msg.clone()]
@ -45,19 +42,19 @@ fn assertion_error(msg: Option<&Expr>) -> Stmt {
vec![]
},
keywords: vec![],
},
}),
))),
cause: None,
},
}),
)
}
/// B011
pub fn assert_false(checker: &mut Checker, stmt: &Stmt, test: &Expr, msg: Option<&Expr>) {
let ExprKind::Constant {
let ExprKind::Constant(ast::ExprConstant {
value: Constant::Bool(false),
..
} = &test.node else {
} )= &test.node else {
return;
};

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{ExprKind, Stmt, Withitem};
use rustpython_parser::ast::{self, ExprKind, Stmt, Withitem};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -55,7 +55,7 @@ pub fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items: &[With
return;
};
let item_context = &item.context_expr;
let ExprKind::Call { func, args, keywords } = &item_context.node else {
let ExprKind::Call(ast::ExprCall { func, args, keywords }) = &item_context.node else {
return;
};
if args.len() != 1 {
@ -74,7 +74,8 @@ pub fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items: &[With
}
let kind = {
if matches!(&func.node, ExprKind::Attribute { attr, .. } if attr == "assertRaises") {
if matches!(&func.node, ExprKind::Attribute(ast::ExprAttribute { attr, .. }) if attr == "assertRaises")
{
AssertionKind::AssertRaises
} else if checker
.ctx

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind};
use rustpython_parser::ast::{self, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -20,13 +20,13 @@ pub fn assignment_to_os_environ(checker: &mut Checker, targets: &[Expr]) {
return;
}
let target = &targets[0];
let ExprKind::Attribute { value, attr, .. } = &target.node else {
let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &target.node else {
return;
};
if attr != "environ" {
return;
}
let ExprKind::Name { id, .. } = &value.node else {
let ExprKind::Name(ast::ExprName { id, .. } )= &value.node else {
return;
};
if id != "os" {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind};
use rustpython_parser::ast::{self, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -36,7 +36,7 @@ pub fn cached_instance_method(checker: &mut Checker, decorator_list: &[Expr]) {
for decorator in decorator_list {
// TODO(charlie): This should take into account `classmethod-decorators` and
// `staticmethod-decorators`.
if let ExprKind::Name { id, .. } = &decorator.node {
if let ExprKind::Name(ast::ExprName { id, .. }) = &decorator.node {
if id == "classmethod" || id == "staticmethod" {
return;
}
@ -46,7 +46,7 @@ pub fn cached_instance_method(checker: &mut Checker, decorator_list: &[Expr]) {
if is_cache_func(
checker,
match &decorator.node {
ExprKind::Call { func, .. } => func,
ExprKind::Call(ast::ExprCall { func, .. }) => func,
_ => decorator,
},
) {

View file

@ -17,7 +17,7 @@ impl Violation for CannotRaiseLiteral {
/// B016
pub fn cannot_raise_literal(checker: &mut Checker, expr: &Expr) {
let ExprKind::Constant { .. } = &expr.node else {
let ExprKind::Constant ( _) = &expr.node else {
return;
};
checker

View file

@ -1,7 +1,7 @@
use itertools::Itertools;
use ruff_text_size::TextSize;
use ruff_text_size::TextRange;
use rustc_hash::{FxHashMap, FxHashSet};
use rustpython_parser::ast::{Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind};
use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind};
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
use ruff_diagnostics::{Diagnostic, Edit, Fix};
@ -50,9 +50,8 @@ impl AlwaysAutofixableViolation for DuplicateHandlerException {
fn type_pattern(elts: Vec<&Expr>) -> Expr {
Expr::new(
TextSize::default(),
TextSize::default(),
ExprKind::Tuple {
TextRange::default(),
ast::ExprTuple {
elts: elts.into_iter().cloned().collect(),
ctx: ExprContext::Load,
},
@ -117,11 +116,11 @@ pub fn duplicate_exceptions(checker: &mut Checker, handlers: &[Excepthandler]) {
let mut seen: FxHashSet<CallPath> = FxHashSet::default();
let mut duplicates: FxHashMap<CallPath, Vec<&Expr>> = FxHashMap::default();
for handler in handlers {
let ExcepthandlerKind::ExceptHandler { type_: Some(type_), .. } = &handler.node else {
let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_: Some(type_), .. }) = &handler.node else {
continue;
};
match &type_.node {
ExprKind::Attribute { .. } | ExprKind::Name { .. } => {
ExprKind::Attribute(_) | ExprKind::Name(_) => {
if let Some(call_path) = call_path::collect_call_path(type_) {
if seen.contains(&call_path) {
duplicates.entry(call_path).or_default().push(type_);
@ -130,7 +129,7 @@ pub fn duplicate_exceptions(checker: &mut Checker, handlers: &[Excepthandler]) {
}
}
}
ExprKind::Tuple { elts, .. } => {
ExprKind::Tuple(ast::ExprTuple { elts, .. }) => {
for (name, expr) in duplicate_handler_exceptions(checker, type_, elts) {
if seen.contains(&name) {
duplicates.entry(name).or_default().push(expr);

View file

@ -1,5 +1,5 @@
use rustpython_parser::ast::Excepthandler;
use rustpython_parser::ast::{ExcepthandlerKind, ExprKind};
use rustpython_parser::ast::{self, ExcepthandlerKind, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -18,11 +18,12 @@ impl Violation for ExceptWithEmptyTuple {
/// B029
pub fn except_with_empty_tuple(checker: &mut Checker, excepthandler: &Excepthandler) {
let ExcepthandlerKind::ExceptHandler { type_, .. } = &excepthandler.node;
let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) =
&excepthandler.node;
let Some(type_) = type_ else {
return;
};
let ExprKind::Tuple { elts, .. } = &type_.node else {
let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &type_.node else {
return;
};
if elts.is_empty() {

View file

@ -1,6 +1,6 @@
use std::collections::VecDeque;
use rustpython_parser::ast::{Excepthandler, ExcepthandlerKind, Expr, ExprKind};
use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -21,15 +21,16 @@ impl Violation for ExceptWithNonExceptionClasses {
/// This should leave any unstarred iterables alone (subsequently raising a
/// warning for B029).
fn flatten_starred_iterables(expr: &Expr) -> Vec<&Expr> {
let ExprKind::Tuple { elts, .. } = &expr.node else {
let ExprKind::Tuple(ast::ExprTuple { elts, .. } )= &expr.node else {
return vec![expr];
};
let mut flattened_exprs: Vec<&Expr> = Vec::with_capacity(elts.len());
let mut exprs_to_process: VecDeque<&Expr> = elts.iter().collect();
while let Some(expr) = exprs_to_process.pop_front() {
match &expr.node {
ExprKind::Starred { value, .. } => match &value.node {
ExprKind::Tuple { elts, .. } | ExprKind::List { elts, .. } => {
ExprKind::Starred(ast::ExprStarred { value, .. }) => match &value.node {
ExprKind::Tuple(ast::ExprTuple { elts, .. })
| ExprKind::List(ast::ExprList { elts, .. }) => {
exprs_to_process.append(&mut elts.iter().collect());
}
_ => flattened_exprs.push(value),
@ -42,17 +43,15 @@ fn flatten_starred_iterables(expr: &Expr) -> Vec<&Expr> {
/// B030
pub fn except_with_non_exception_classes(checker: &mut Checker, excepthandler: &Excepthandler) {
let ExcepthandlerKind::ExceptHandler { type_, .. } = &excepthandler.node;
let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) =
&excepthandler.node;
let Some(type_) = type_ else {
return;
};
for expr in flatten_starred_iterables(type_) {
if !matches!(
&expr.node,
ExprKind::Subscript { .. }
| ExprKind::Attribute { .. }
| ExprKind::Name { .. }
| ExprKind::Call { .. },
ExprKind::Subscript(_) | ExprKind::Attribute(_) | ExprKind::Name(_) | ExprKind::Call(_),
) {
checker
.diagnostics

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{ExprKind, Stmt, StmtKind};
use rustpython_parser::ast::{self, ExprKind, Stmt, StmtKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -23,10 +23,10 @@ pub fn f_string_docstring(checker: &mut Checker, body: &[Stmt]) {
let Some(stmt) = body.first() else {
return;
};
let StmtKind::Expr { value } = &stmt.node else {
let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node else {
return;
};
let ExprKind::JoinedStr { .. } = value.node else {
let ExprKind::JoinedStr ( _) = value.node else {
return;
};
checker.diagnostics.push(Diagnostic::new(

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextRange;
use rustpython_parser::ast::{Arguments, Constant, Expr, ExprKind};
use rustpython_parser::ast::{self, Arguments, Constant, Expr, ExprKind};
use ruff_diagnostics::Violation;
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
@ -84,7 +84,7 @@ where
{
fn visit_expr(&mut self, expr: &'b Expr) {
match &expr.node {
ExprKind::Call { func, args, .. } => {
ExprKind::Call(ast::ExprCall { func, args, .. }) => {
if !is_mutable_func(self.checker, func)
&& !is_immutable_func(&self.checker.ctx, func, &self.extend_immutable_calls)
&& !is_nan_or_infinity(func, args)
@ -99,14 +99,14 @@ where
}
visitor::walk_expr(self, expr);
}
ExprKind::Lambda { .. } => {}
ExprKind::Lambda(_) => {}
_ => visitor::walk_expr(self, expr),
}
}
}
fn is_nan_or_infinity(expr: &Expr, args: &[Expr]) -> bool {
let ExprKind::Name { id, .. } = &expr.node else {
let ExprKind::Name(ast::ExprName { id, .. }) = &expr.node else {
return false;
};
if id != "float" {
@ -115,10 +115,10 @@ fn is_nan_or_infinity(expr: &Expr, args: &[Expr]) -> bool {
let Some(arg) = args.first() else {
return false;
};
let ExprKind::Constant {
let ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(value),
..
} = &arg.node else {
} )= &arg.node else {
return false;
};
let lowercased = value.to_lowercase();

View file

@ -1,6 +1,6 @@
use ruff_text_size::TextRange;
use rustc_hash::FxHashSet;
use rustpython_parser::ast::{Comprehension, Expr, ExprContext, ExprKind, Stmt, StmtKind};
use rustpython_parser::ast::{self, Comprehension, Expr, ExprContext, ExprKind, Stmt, StmtKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -36,7 +36,7 @@ struct LoadedNamesVisitor<'a> {
impl<'a> Visitor<'a> for LoadedNamesVisitor<'a> {
fn visit_expr(&mut self, expr: &'a Expr) {
match &expr.node {
ExprKind::Name { id, ctx } => match ctx {
ExprKind::Name(ast::ExprName { id, ctx }) => match ctx {
ExprContext::Load => self.loaded.push((id, expr, expr.range())),
ExprContext::Store => self.stored.push((id, expr, expr.range())),
ExprContext::Del => {}
@ -57,8 +57,8 @@ struct SuspiciousVariablesVisitor<'a> {
impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> {
fn visit_stmt(&mut self, stmt: &'a Stmt) {
match &stmt.node {
StmtKind::FunctionDef { args, body, .. }
| StmtKind::AsyncFunctionDef { args, body, .. } => {
StmtKind::FunctionDef(ast::StmtFunctionDef { args, body, .. })
| StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { args, body, .. }) => {
// Collect all loaded variable names.
let mut visitor = LoadedNamesVisitor::default();
visitor.visit_body(body);
@ -76,9 +76,9 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> {
);
return;
}
StmtKind::Return { value: Some(value) } => {
StmtKind::Return(ast::StmtReturn { value: Some(value) }) => {
// Mark `return lambda: x` as safe.
if matches!(value.node, ExprKind::Lambda { .. }) {
if matches!(value.node, ExprKind::Lambda(_)) {
self.safe_functions.push(value);
}
}
@ -89,26 +89,27 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> {
fn visit_expr(&mut self, expr: &'a Expr) {
match &expr.node {
ExprKind::Call {
ExprKind::Call(ast::ExprCall {
func,
args,
keywords,
} => {
if let ExprKind::Name { id, .. } = &func.node {
}) => {
if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node {
let id = id.as_str();
if id == "filter" || id == "reduce" || id == "map" {
for arg in args {
if matches!(arg.node, ExprKind::Lambda { .. }) {
if matches!(arg.node, ExprKind::Lambda(_)) {
self.safe_functions.push(arg);
}
}
}
}
if let ExprKind::Attribute { value, attr, .. } = &func.node {
if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &func.node {
if attr == "reduce" {
if let ExprKind::Name { id, .. } = &value.node {
if let ExprKind::Name(ast::ExprName { id, .. }) = &value.node {
if id == "functools" {
for arg in args {
if matches!(arg.node, ExprKind::Lambda { .. }) {
if matches!(arg.node, ExprKind::Lambda(_)) {
self.safe_functions.push(arg);
}
}
@ -118,13 +119,13 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> {
}
for keyword in keywords {
if keyword.node.arg.as_ref().map_or(false, |arg| arg == "key")
&& matches!(keyword.node.value.node, ExprKind::Lambda { .. })
&& matches!(keyword.node.value.node, ExprKind::Lambda(_))
{
self.safe_functions.push(&keyword.node.value);
}
}
}
ExprKind::Lambda { args, body } => {
ExprKind::Lambda(ast::ExprLambda { args, body }) => {
if !self.safe_functions.contains(&expr) {
// Collect all loaded variable names.
let mut visitor = LoadedNamesVisitor::default();
@ -160,13 +161,14 @@ struct NamesFromAssignmentsVisitor<'a> {
impl<'a> Visitor<'a> for NamesFromAssignmentsVisitor<'a> {
fn visit_expr(&mut self, expr: &'a Expr) {
match &expr.node {
ExprKind::Name { id, .. } => {
ExprKind::Name(ast::ExprName { id, .. }) => {
self.names.insert(id.as_str());
}
ExprKind::Starred { value, .. } => {
ExprKind::Starred(ast::ExprStarred { value, .. }) => {
self.visit_expr(value);
}
ExprKind::List { elts, .. } | ExprKind::Tuple { elts, .. } => {
ExprKind::List(ast::ExprList { elts, .. })
| ExprKind::Tuple(ast::ExprTuple { elts, .. }) => {
for expr in elts {
self.visit_expr(expr);
}
@ -186,24 +188,24 @@ impl<'a> Visitor<'a> for AssignedNamesVisitor<'a> {
fn visit_stmt(&mut self, stmt: &'a Stmt) {
if matches!(
&stmt.node,
StmtKind::FunctionDef { .. } | StmtKind::AsyncFunctionDef { .. }
StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_)
) {
// Don't recurse.
return;
}
match &stmt.node {
StmtKind::Assign { targets, .. } => {
StmtKind::Assign(ast::StmtAssign { targets, .. }) => {
let mut visitor = NamesFromAssignmentsVisitor::default();
for expr in targets {
visitor.visit_expr(expr);
}
self.names.extend(visitor.names);
}
StmtKind::AugAssign { target, .. }
| StmtKind::AnnAssign { target, .. }
| StmtKind::For { target, .. }
| StmtKind::AsyncFor { target, .. } => {
StmtKind::AugAssign(ast::StmtAugAssign { target, .. })
| StmtKind::AnnAssign(ast::StmtAnnAssign { target, .. })
| StmtKind::For(ast::StmtFor { target, .. })
| StmtKind::AsyncFor(ast::StmtAsyncFor { target, .. }) => {
let mut visitor = NamesFromAssignmentsVisitor::default();
visitor.visit_expr(target);
self.names.extend(visitor.names);
@ -215,7 +217,7 @@ impl<'a> Visitor<'a> for AssignedNamesVisitor<'a> {
}
fn visit_expr(&mut self, expr: &'a Expr) {
if matches!(&expr.node, ExprKind::Lambda { .. }) {
if matches!(&expr.node, ExprKind::Lambda(_)) {
// Don't recurse.
return;
}

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextSize;
use rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind};
use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Constant, Expr, ExprContext, ExprKind};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation};
@ -27,11 +27,10 @@ impl AlwaysAutofixableViolation for GetAttrWithConstant {
}
fn attribute(value: &Expr, attr: &str) -> Expr {
Expr::new(
TextSize::default(),
TextSize::default(),
ExprKind::Attribute {
TextRange::default(),
ast::ExprAttribute {
value: Box::new(value.clone()),
attr: attr.to_string(),
attr: attr.into(),
ctx: ExprContext::Load,
},
)
@ -39,7 +38,7 @@ fn attribute(value: &Expr, attr: &str) -> Expr {
/// B009
pub fn getattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
let ExprKind::Name { id, .. } = &func.node else {
let ExprKind::Name(ast::ExprName { id, .. } )= &func.node else {
return;
};
if id != "getattr" {
@ -48,10 +47,10 @@ pub fn getattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, ar
let [obj, arg] = args else {
return;
};
let ExprKind::Constant {
let ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(value),
..
} = &arg.node else {
} )= &arg.node else {
return;
};
if !is_identifier(value) {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Stmt, StmtKind};
use rustpython_parser::ast::{self, Stmt, StmtKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -24,33 +24,34 @@ fn walk_stmt(checker: &mut Checker, body: &[Stmt], f: fn(&Stmt) -> bool) {
checker.diagnostics.push(Diagnostic::new(
JumpStatementInFinally {
name: match &stmt.node {
StmtKind::Break { .. } => "break".to_string(),
StmtKind::Continue { .. } => "continue".to_string(),
StmtKind::Return { .. } => "return".to_string(),
StmtKind::Break => "break",
StmtKind::Continue => "continue",
StmtKind::Return(_) => "return",
_ => unreachable!(
"Expected StmtKind::Break | StmtKind::Continue | StmtKind::Return"
),
},
}
.to_owned(),
},
stmt.range(),
));
}
match &stmt.node {
StmtKind::While { body, .. }
| StmtKind::For { body, .. }
| StmtKind::AsyncFor { body, .. } => {
StmtKind::While(ast::StmtWhile { body, .. })
| StmtKind::For(ast::StmtFor { body, .. })
| StmtKind::AsyncFor(ast::StmtAsyncFor { body, .. }) => {
walk_stmt(checker, body, |stmt| {
matches!(stmt.node, StmtKind::Return { .. })
matches!(stmt.node, StmtKind::Return(_))
});
}
StmtKind::If { body, .. }
| StmtKind::Try { body, .. }
| StmtKind::TryStar { body, .. }
| StmtKind::With { body, .. }
| StmtKind::AsyncWith { body, .. } => {
StmtKind::If(ast::StmtIf { body, .. })
| StmtKind::Try(ast::StmtTry { body, .. })
| StmtKind::TryStar(ast::StmtTryStar { body, .. })
| StmtKind::With(ast::StmtWith { body, .. })
| StmtKind::AsyncWith(ast::StmtAsyncWith { body, .. }) => {
walk_stmt(checker, body, f);
}
StmtKind::Match { cases, .. } => {
StmtKind::Match(ast::StmtMatch { cases, .. }) => {
for case in cases {
walk_stmt(checker, &case.body, f);
}
@ -65,7 +66,7 @@ pub fn jump_statement_in_finally(checker: &mut Checker, finalbody: &[Stmt]) {
walk_stmt(checker, finalbody, |stmt| {
matches!(
stmt.node,
StmtKind::Break | StmtKind::Continue | StmtKind::Return { .. }
StmtKind::Break | StmtKind::Continue | StmtKind::Return(_)
)
});
}

View file

@ -1,5 +1,5 @@
use rustc_hash::FxHashMap;
use rustpython_parser::ast::{Expr, ExprKind};
use rustpython_parser::ast::{self, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -32,18 +32,18 @@ where
{
fn visit_expr(&mut self, expr: &'b Expr) {
match &expr.node {
ExprKind::Name { id, .. } => {
ExprKind::Name(ast::ExprName { id, .. }) => {
self.names.insert(id, expr);
}
ExprKind::ListComp { generators, .. }
| ExprKind::DictComp { generators, .. }
| ExprKind::SetComp { generators, .. }
| ExprKind::GeneratorExp { generators, .. } => {
ExprKind::ListComp(ast::ExprListComp { generators, .. })
| ExprKind::DictComp(ast::ExprDictComp { generators, .. })
| ExprKind::SetComp(ast::ExprSetComp { generators, .. })
| ExprKind::GeneratorExp(ast::ExprGeneratorExp { generators, .. }) => {
for comp in generators {
self.visit_expr(&comp.iter);
}
}
ExprKind::Lambda { args, body } => {
ExprKind::Lambda(ast::ExprLambda { args, body }) => {
visitor::walk_expr(self, body);
for arg in &args.args {
self.names.remove(arg.node.arg.as_str());

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Arguments, Expr, ExprKind};
use rustpython_parser::ast::{self, Arguments, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -38,13 +38,13 @@ pub fn is_mutable_func(checker: &Checker, func: &Expr) -> bool {
fn is_mutable_expr(checker: &Checker, expr: &Expr) -> bool {
match &expr.node {
ExprKind::List { .. }
| ExprKind::Dict { .. }
| ExprKind::Set { .. }
| ExprKind::ListComp { .. }
| ExprKind::DictComp { .. }
| ExprKind::SetComp { .. } => true,
ExprKind::Call { func, .. } => is_mutable_func(checker, func),
ExprKind::List(_)
| ExprKind::Dict(_)
| ExprKind::Set(_)
| ExprKind::ListComp(_)
| ExprKind::DictComp(_)
| ExprKind::SetComp(_) => true,
ExprKind::Call(ast::ExprCall { func, .. }) => is_mutable_func(checker, func),
_ => false,
}
}

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{ExprKind, Stmt};
use rustpython_parser::ast::{self, ExprKind, Stmt};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -33,7 +33,7 @@ pub fn raise_without_from_inside_except(checker: &mut Checker, body: &[Stmt]) {
if cause.is_none() {
if let Some(exc) = exc {
match &exc.node {
ExprKind::Name { id, .. } if is_lower(id) => {}
ExprKind::Name(ast::ExprName { id, .. }) if is_lower(id) => {}
_ => {
checker
.diagnostics

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Excepthandler, ExcepthandlerKind, ExprKind};
use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, ExprKind};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation};
@ -31,10 +31,10 @@ impl AlwaysAutofixableViolation for RedundantTupleInExceptionHandler {
/// B013
pub fn redundant_tuple_in_exception_handler(checker: &mut Checker, handlers: &[Excepthandler]) {
for handler in handlers {
let ExcepthandlerKind::ExceptHandler { type_: Some(type_), .. } = &handler.node else {
let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_: Some(type_), .. }) = &handler.node else {
continue;
};
let ExprKind::Tuple { elts, .. } = &type_.node else {
let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &type_.node else {
continue;
};
let [elt] = &elts[..] else {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Comprehension, Expr, ExprKind, Stmt, StmtKind};
use rustpython_parser::ast::{self, Comprehension, Expr, ExprKind, Stmt, StmtKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -84,7 +84,7 @@ impl<'a> GroupNameFinder<'a> {
}
fn name_matches(&self, expr: &Expr) -> bool {
if let ExprKind::Name { id, .. } = &expr.node {
if let ExprKind::Name(ast::ExprName { id, .. }) = &expr.node {
id == self.group_name
} else {
false
@ -113,9 +113,9 @@ where
return;
}
match &stmt.node {
StmtKind::For {
StmtKind::For(ast::StmtFor {
target, iter, body, ..
} => {
}) => {
if self.name_matches(target) {
self.overridden = true;
} else {
@ -138,15 +138,15 @@ where
self.nested = false;
}
}
StmtKind::While { body, .. } => {
StmtKind::While(ast::StmtWhile { body, .. }) => {
self.nested = true;
visitor::walk_body(self, body);
self.nested = false;
}
StmtKind::If { test, body, orelse } => {
StmtKind::If(ast::StmtIf { test, body, orelse }) => {
// Determine whether we're on an `if` arm (as opposed to an `elif`).
let is_if_arm = !self.parent_ifs.iter().any(|parent| {
if let StmtKind::If { orelse, .. } = &parent.node {
if let StmtKind::If(ast::StmtIf { orelse, .. }) = &parent.node {
orelse.len() == 1 && &orelse[0] == stmt
} else {
false
@ -166,7 +166,7 @@ where
let has_else = orelse
.first()
.map_or(false, |expr| !matches!(expr.node, StmtKind::If { .. }));
.map_or(false, |expr| !matches!(expr.node, StmtKind::If(_)));
self.parent_ifs.push(stmt);
if has_else {
@ -193,7 +193,7 @@ where
}
}
}
StmtKind::Match { subject, cases } => {
StmtKind::Match(ast::StmtMatch { subject, cases }) => {
self.counter_stack.push(Vec::with_capacity(cases.len()));
self.visit_expr(subject);
for match_case in cases {
@ -207,14 +207,14 @@ where
self.increment_usage_count(max_count);
}
}
StmtKind::Assign { targets, value, .. } => {
StmtKind::Assign(ast::StmtAssign { targets, value, .. }) => {
if targets.iter().any(|target| self.name_matches(target)) {
self.overridden = true;
} else {
self.visit_expr(value);
}
}
StmtKind::AnnAssign { target, value, .. } => {
StmtKind::AnnAssign(ast::StmtAnnAssign { target, value, .. }) => {
if self.name_matches(target) {
self.overridden = true;
} else if let Some(expr) = value {
@ -241,7 +241,7 @@ where
}
fn visit_expr(&mut self, expr: &'a Expr) {
if let ExprKind::NamedExpr { target, .. } = &expr.node {
if let ExprKind::NamedExpr(ast::ExprNamedExpr { target, .. }) = &expr.node {
if self.name_matches(target) {
self.overridden = true;
}
@ -251,7 +251,8 @@ where
}
match &expr.node {
ExprKind::ListComp { elt, generators } | ExprKind::SetComp { elt, generators } => {
ExprKind::ListComp(ast::ExprListComp { elt, generators })
| ExprKind::SetComp(ast::ExprSetComp { elt, generators }) => {
for comprehension in generators {
self.visit_comprehension(comprehension);
}
@ -261,11 +262,11 @@ where
self.nested = false;
}
}
ExprKind::DictComp {
ExprKind::DictComp(ast::ExprDictComp {
key,
value,
generators,
} => {
}) => {
for comprehension in generators {
self.visit_comprehension(comprehension);
}
@ -307,10 +308,10 @@ pub fn reuse_of_groupby_generator(
body: &[Stmt],
iter: &Expr,
) {
let ExprKind::Call { func, .. } = &iter.node else {
let ExprKind::Call(ast::ExprCall { func, .. }) = &iter.node else {
return;
};
let ExprKind::Tuple { elts, .. } = &target.node else {
let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &target.node else {
// Ignore any `groupby()` invocation that isn't unpacked
return;
};
@ -318,7 +319,7 @@ pub fn reuse_of_groupby_generator(
return;
}
// We have an invocation of groupby which is a simple unpacking
let ExprKind::Name { id: group_name, .. } = &elts[1].node else {
let ExprKind::Name(ast::ExprName { id: group_name, .. }) = &elts[1].node else {
return;
};
// Check if the function call is `itertools.groupby`

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextSize;
use rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind};
use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation};
@ -29,28 +29,26 @@ impl AlwaysAutofixableViolation for SetAttrWithConstant {
fn assignment(obj: &Expr, name: &str, value: &Expr, stylist: &Stylist) -> String {
let stmt = Stmt::new(
TextSize::default(),
TextSize::default(),
StmtKind::Assign {
TextRange::default(),
StmtKind::Assign(ast::StmtAssign {
targets: vec![Expr::new(
TextSize::default(),
TextSize::default(),
ExprKind::Attribute {
TextRange::default(),
ExprKind::Attribute(ast::ExprAttribute {
value: Box::new(obj.clone()),
attr: name.to_string(),
attr: name.into(),
ctx: ExprContext::Store,
},
}),
)],
value: Box::new(value.clone()),
type_comment: None,
},
}),
);
unparse_stmt(&stmt, stylist)
}
/// B010
pub fn setattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
let ExprKind::Name { id, .. } = &func.node else {
let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else {
return;
};
if id != "setattr" {
@ -59,10 +57,10 @@ pub fn setattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, ar
let [obj, name, value] = args else {
return;
};
let ExprKind::Constant {
let ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(name),
..
} = &name.node else {
} )= &name.node else {
return;
};
if !is_identifier(name) {
@ -74,7 +72,7 @@ pub fn setattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, ar
// We can only replace a `setattr` call (which is an `Expr`) with an assignment
// (which is a `Stmt`) if the `Expr` is already being used as a `Stmt`
// (i.e., it's directly within an `StmtKind::Expr`).
if let StmtKind::Expr { value: child } = &checker.ctx.stmt().node {
if let StmtKind::Expr(ast::StmtExpr { value: child }) = &checker.ctx.stmt().node {
if expr == child.as_ref() {
let mut diagnostic = Diagnostic::new(SetAttrWithConstant, expr.range());

View file

@ -34,7 +34,7 @@ pub fn star_arg_unpacking_after_keyword_arg(
return;
};
for arg in args {
let ExprKind::Starred { .. } = arg.node else {
let ExprKind::Starred (_) = arg.node else {
continue;
};
if arg.start() <= keyword.start() {

View file

@ -1,5 +1,5 @@
use itertools::Itertools;
use rustpython_parser::ast::{Constant, Expr, ExprKind};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -18,7 +18,7 @@ impl Violation for StripWithMultiCharacters {
/// B005
pub fn strip_with_multi_characters(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
let ExprKind::Attribute { attr, .. } = &func.node else {
let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node else {
return;
};
if !matches!(attr.as_str(), "strip" | "lstrip" | "rstrip") {
@ -28,10 +28,10 @@ pub fn strip_with_multi_characters(checker: &mut Checker, expr: &Expr, func: &Ex
return;
}
let ExprKind::Constant {
let ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(value),
..
} = &args[0].node else {
} )= &args[0].node else {
return;
};

View file

@ -17,7 +17,7 @@
//! n += 1
//! ```
use rustpython_parser::ast::{Expr, ExprKind, Unaryop};
use rustpython_parser::ast::{self, Expr, ExprKind, Unaryop};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -39,7 +39,7 @@ pub fn unary_prefix_increment(checker: &mut Checker, expr: &Expr, op: &Unaryop,
if !matches!(op, Unaryop::UAdd) {
return;
}
let ExprKind::UnaryOp { op, .. } = &operand.node else {
let ExprKind::UnaryOp(ast::ExprUnaryOp { op, .. })= &operand.node else {
return;
};
if !matches!(op, Unaryop::UAdd) {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind, Stmt};
use rustpython_parser::ast::{self, Expr, ExprKind, Stmt};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -44,15 +44,15 @@ pub fn unintentional_type_annotation(
return;
}
match &target.node {
ExprKind::Subscript { value, .. } => {
if matches!(&value.node, ExprKind::Name { .. }) {
ExprKind::Subscript(ast::ExprSubscript { value, .. }) => {
if matches!(&value.node, ExprKind::Name(_)) {
checker
.diagnostics
.push(Diagnostic::new(UnintentionalTypeAnnotation, stmt.range()));
}
}
ExprKind::Attribute { value, .. } => {
if let ExprKind::Name { id, .. } = &value.node {
ExprKind::Attribute(ast::ExprAttribute { value, .. }) => {
if let ExprKind::Name(ast::ExprName { id, .. }) = &value.node {
if id != "self" {
checker
.diagnostics

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Constant, Expr, ExprKind};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -20,7 +20,7 @@ impl Violation for UnreliableCallableCheck {
/// B004
pub fn unreliable_callable_check(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
let ExprKind::Name { id, .. } = &func.node else {
let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else {
return;
};
if id != "getattr" && id != "hasattr" {
@ -29,10 +29,10 @@ pub fn unreliable_callable_check(checker: &mut Checker, expr: &Expr, func: &Expr
if args.len() < 2 {
return;
};
let ExprKind::Constant {
let ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(s),
..
} = &args[1].node else
}) = &args[1].node else
{
return;
};

View file

@ -19,7 +19,7 @@
//! ```
use rustc_hash::FxHashMap;
use rustpython_parser::ast::{Expr, ExprKind, Stmt};
use rustpython_parser::ast::{self, Expr, ExprKind, Stmt};
use serde::{Deserialize, Serialize};
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
@ -93,7 +93,7 @@ where
'b: 'a,
{
fn visit_expr(&mut self, expr: &'a Expr) {
if let ExprKind::Name { id, .. } = &expr.node {
if let ExprKind::Name(ast::ExprName { id, .. }) = &expr.node {
self.names.insert(id, expr);
}
visitor::walk_expr(self, expr);

View file

@ -20,7 +20,7 @@ impl Violation for UselessComparison {
/// B015
pub fn useless_comparison(checker: &mut Checker, expr: &Expr) {
if matches!(expr.node, ExprKind::Compare { .. }) {
if matches!(expr.node, ExprKind::Compare(_)) {
checker
.diagnostics
.push(Diagnostic::new(UselessComparison, expr.range()));

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Constant, Expr, ExprKind};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -36,18 +36,18 @@ impl Violation for UselessExpression {
/// B018
pub fn useless_expression(checker: &mut Checker, value: &Expr) {
// Ignore comparisons, as they're handled by `useless_comparison`.
if matches!(value.node, ExprKind::Compare { .. }) {
if matches!(value.node, ExprKind::Compare(_)) {
return;
}
// Ignore strings, to avoid false positives with docstrings.
if matches!(
value.node,
ExprKind::JoinedStr { .. }
| ExprKind::Constant {
ExprKind::JoinedStr(_)
| ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(..) | Constant::Ellipsis,
..
}
})
) {
return;
}
@ -56,7 +56,7 @@ pub fn useless_expression(checker: &mut Checker, value: &Expr) {
if contains_effect(value, |id| checker.ctx.is_builtin(id)) {
// Flag attributes as useless expressions, even if they're attached to calls or other
// expressions.
if matches!(value.node, ExprKind::Attribute { .. }) {
if matches!(value.node, ExprKind::Attribute(_)) {
checker.diagnostics.push(Diagnostic::new(
UselessExpression {
kind: Kind::Attribute,

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
use crate::checkers::ast::Checker;
use ruff_diagnostics::{Diagnostic, Violation};
@ -21,7 +21,7 @@ pub fn zip_without_explicit_strict(
func: &Expr,
kwargs: &[Keyword],
) {
if let ExprKind::Name { id, .. } = &func.node {
if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node {
if id == "zip"
&& checker.ctx.is_builtin("zip")
&& !kwargs.iter().any(|keyword| {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::Located;
use rustpython_parser::ast::Attributed;
use ruff_diagnostics::Violation;
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
@ -170,7 +170,7 @@ impl Violation for BuiltinAttributeShadowing {
/// Check builtin name shadowing.
pub fn builtin_shadowing<T>(
name: &str,
located: &Located<T>,
located: &Attributed<T>,
node_type: ShadowingType,
ignorelist: &[String],
) -> Option<Diagnostic> {

View file

@ -116,7 +116,7 @@ pub fn fix_unnecessary_generator_set(
// If the expression is embedded in an f-string, surround it with spaces to avoid
// syntax errors.
if let Some(parent_element) = parent {
if let &rustpython_parser::ast::ExprKind::FormattedValue { .. } = &parent_element.node {
if let &rustpython_parser::ast::ExprKind::FormattedValue(_) = &parent_element.node {
content = format!(" {content} ");
}
}
@ -186,7 +186,7 @@ pub fn fix_unnecessary_generator_dict(
// If the expression is embedded in an f-string, surround it with spaces to avoid
// syntax errors.
if let Some(parent_element) = parent {
if let &rustpython_parser::ast::ExprKind::FormattedValue { .. } = &parent_element.node {
if let &rustpython_parser::ast::ExprKind::FormattedValue(_) = &parent_element.node {
content = format!(" {content} ");
}
}
@ -1101,9 +1101,7 @@ pub fn fix_unnecessary_map(
// syntax errors.
if kind == "set" || kind == "dict" {
if let Some(parent_element) = parent {
if let &rustpython_parser::ast::ExprKind::FormattedValue { .. } =
&parent_element.node
{
if let &rustpython_parser::ast::ExprKind::FormattedValue(_) = &parent_element.node {
content = format!(" {content} ");
}
}

View file

@ -1,7 +1,7 @@
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
pub fn expr_name(func: &Expr) -> Option<&str> {
if let ExprKind::Name { id, .. } = &func.node {
if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node {
Some(id)
} else {
None

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind};
use rustpython_parser::ast::{self, Expr, ExprKind};
use crate::checkers::ast::Checker;
use crate::registry::AsRule;
@ -65,7 +65,7 @@ pub fn unnecessary_call_around_sorted(
let Some(arg) = args.first() else {
return;
};
let ExprKind::Call { func, .. } = &arg.node else {
let ExprKind::Call(ast::ExprCall { func, .. }) = &arg.node else {
return;
};
let Some(inner) = helpers::expr_name(func) else {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Comprehension, Expr, ExprKind};
use rustpython_parser::ast::{self, Comprehension, Expr, ExprKind};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
use ruff_macros::{derive_message_formats, violation};
@ -51,9 +51,9 @@ impl AlwaysAutofixableViolation for UnnecessaryComprehension {
/// Add diagnostic for C416 based on the expression node id.
fn add_diagnostic(checker: &mut Checker, expr: &Expr) {
let id = match &expr.node {
ExprKind::ListComp { .. } => "list",
ExprKind::SetComp { .. } => "set",
ExprKind::DictComp { .. } => "dict",
ExprKind::ListComp(_) => "list",
ExprKind::SetComp(_) => "set",
ExprKind::DictComp(_) => "dict",
_ => return,
};
if !checker.ctx.is_builtin(id) {
@ -86,7 +86,7 @@ pub fn unnecessary_dict_comprehension(
return;
}
let generator = &generators[0];
if !(generator.ifs.is_empty() && generator.is_async == 0) {
if !generator.ifs.is_empty() || generator.is_async {
return;
}
let Some(key_id) = helpers::expr_name(key) else {
@ -95,7 +95,7 @@ pub fn unnecessary_dict_comprehension(
let Some(value_id) = helpers::expr_name(value) else {
return;
};
let ExprKind::Tuple { elts, .. } = &generator.target.node else {
let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &generator.target.node else {
return;
};
if elts.len() != 2 {
@ -127,7 +127,7 @@ pub fn unnecessary_list_set_comprehension(
return;
}
let generator = &generators[0];
if !(generator.ifs.is_empty() && generator.is_async == 0) {
if !generator.ifs.is_empty() || generator.is_async {
return;
}
let Some(elt_id) = helpers::expr_name(elt) else {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
use ruff_diagnostics::Violation;
use ruff_diagnostics::{AutofixKind, Diagnostic};
@ -66,11 +66,11 @@ pub fn unnecessary_comprehension_any_all(
if !keywords.is_empty() {
return;
}
let ExprKind::Name { id, .. } = &func.node else {
let ExprKind::Name(ast::ExprName { id, .. } )= &func.node else {
return;
};
if (matches!(id.as_str(), "all" | "any")) && args.len() == 1 {
let (ExprKind::ListComp { elt, .. } | ExprKind::SetComp { elt, .. }) = &args[0].node else {
let (ExprKind::ListComp(ast::ExprListComp { elt, .. } )| ExprKind::SetComp(ast::ExprSetComp { elt, .. })) = &args[0].node else {
return;
};
if is_async_generator(elt) {
@ -92,5 +92,5 @@ pub fn unnecessary_comprehension_any_all(
/// Return `true` if the `Expr` contains an `await` expression.
fn is_async_generator(expr: &Expr) -> bool {
any_over_expr(expr, &|expr| matches!(expr.node, ExprKind::Await { .. }))
any_over_expr(expr, &|expr| matches!(expr.node, ExprKind::Await(_)))
}

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind};
use rustpython_parser::ast::{self, Expr, ExprKind};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
use ruff_macros::{derive_message_formats, violation};
@ -84,7 +84,7 @@ pub fn unnecessary_double_cast_or_process(
let Some(arg) = args.first() else {
return;
};
let ExprKind::Call { func, ..} = &arg.node else {
let ExprKind::Call(ast::ExprCall { func, ..} )= &arg.node else {
return;
};
let Some(inner) = helpers::expr_name(func) else {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
use ruff_macros::{derive_message_formats, violation};
@ -53,9 +53,9 @@ pub fn unnecessary_generator_dict(
let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
return;
};
if let ExprKind::GeneratorExp { elt, .. } = argument {
if let ExprKind::GeneratorExp(ast::ExprGeneratorExp { elt, .. }) = argument {
match &elt.node {
ExprKind::Tuple { elts, .. } if elts.len() == 2 => {
ExprKind::Tuple(ast::ExprTuple { elts, .. }) if elts.len() == 2 => {
let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorDict, expr.range());
if checker.patch(diagnostic.kind.rule()) {
#[allow(deprecated)]

View file

@ -55,7 +55,7 @@ pub fn unnecessary_generator_list(
if !checker.ctx.is_builtin("list") {
return;
}
if let ExprKind::GeneratorExp { .. } = argument {
if let ExprKind::GeneratorExp(_) = argument {
let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorList, expr.range());
if checker.patch(diagnostic.kind.rule()) {
#[allow(deprecated)]

View file

@ -56,7 +56,7 @@ pub fn unnecessary_generator_set(
if !checker.ctx.is_builtin("set") {
return;
}
if let ExprKind::GeneratorExp { .. } = argument {
if let ExprKind::GeneratorExp(_) = argument {
let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorSet, expr.range());
if checker.patch(diagnostic.kind.rule()) {
#[allow(deprecated)]

View file

@ -45,7 +45,7 @@ pub fn unnecessary_list_call(checker: &mut Checker, expr: &Expr, func: &Expr, ar
if !checker.ctx.is_builtin("list") {
return;
}
if !matches!(argument, ExprKind::ListComp { .. }) {
if !matches!(argument, ExprKind::ListComp(_)) {
return;
}
let mut diagnostic = Diagnostic::new(UnnecessaryListCall, expr.range());

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
use crate::checkers::ast::Checker;
use crate::registry::AsRule;
@ -52,10 +52,10 @@ pub fn unnecessary_list_comprehension_dict(
if !checker.ctx.is_builtin("dict") {
return;
}
let ExprKind::ListComp { elt, .. } = &argument else {
let ExprKind::ListComp(ast::ExprListComp { elt, .. }) = &argument else {
return;
};
let ExprKind::Tuple { elts, .. } = &elt.node else {
let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &elt.node else {
return;
};
if elts.len() != 2 {

View file

@ -53,7 +53,7 @@ pub fn unnecessary_list_comprehension_set(
if !checker.ctx.is_builtin("set") {
return;
}
if let ExprKind::ListComp { .. } = &argument {
if let ExprKind::ListComp(_) = &argument {
let mut diagnostic = Diagnostic::new(UnnecessaryListComprehensionSet, expr.range());
if checker.patch(diagnostic.kind.rule()) {
#[allow(deprecated)]

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
use crate::checkers::ast::Checker;
use crate::registry::AsRule;
@ -60,15 +60,14 @@ pub fn unnecessary_literal_dict(
return;
}
let (kind, elts) = match argument {
ExprKind::Tuple { elts, .. } => ("tuple", elts),
ExprKind::List { elts, .. } => ("list", elts),
ExprKind::Tuple(ast::ExprTuple { elts, .. }) => ("tuple", elts),
ExprKind::List(ast::ExprList { elts, .. }) => ("list", elts),
_ => return,
};
// Accept `dict((1, 2), ...))` `dict([(1, 2), ...])`.
if !elts
.iter()
.all(|elt| matches!(&elt.node, ExprKind::Tuple { elts, .. } if elts.len() == 2))
{
if !elts.iter().all(
|elt| matches!(&elt.node, ExprKind::Tuple(ast::ExprTuple { elts, .. } )if elts.len() == 2),
) {
return;
}
let mut diagnostic = Diagnostic::new(

View file

@ -61,8 +61,8 @@ pub fn unnecessary_literal_set(
return;
}
let kind = match argument {
ExprKind::List { .. } => "list",
ExprKind::Tuple { .. } => "tuple",
ExprKind::List(_) => "list",
ExprKind::Tuple(_) => "tuple",
_ => return,
};
let mut diagnostic = Diagnostic::new(

View file

@ -79,8 +79,8 @@ pub fn unnecessary_literal_within_dict_call(
return;
}
let argument_kind = match argument {
ExprKind::DictComp { .. } => DictKind::Comprehension,
ExprKind::Dict { .. } => DictKind::Literal,
ExprKind::DictComp(_) => DictKind::Comprehension,
ExprKind::Dict(_) => DictKind::Literal,
_ => return,
};
let mut diagnostic = Diagnostic::new(

View file

@ -82,8 +82,8 @@ pub fn unnecessary_literal_within_list_call(
return;
}
let argument_kind = match argument {
ExprKind::Tuple { .. } => "tuple",
ExprKind::List { .. } => "list",
ExprKind::Tuple(_) => "tuple",
ExprKind::List(_) => "list",
_ => return,
};
let mut diagnostic = Diagnostic::new(

View file

@ -83,8 +83,8 @@ pub fn unnecessary_literal_within_tuple_call(
return;
}
let argument_kind = match argument {
ExprKind::Tuple { .. } => "tuple",
ExprKind::List { .. } => "list",
ExprKind::Tuple(_) => "tuple",
ExprKind::List(_) => "list",
_ => return,
};
let mut diagnostic = Diagnostic::new(

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextRange;
use rustpython_parser::ast::{Expr, ExprKind};
use rustpython_parser::ast::{self, Expr, ExprKind};
use ruff_diagnostics::Diagnostic;
use ruff_diagnostics::{AutofixKind, Violation};
@ -94,7 +94,7 @@ pub fn unnecessary_map(
// Exclude the parent if already matched by other arms
if let Some(parent) = parent {
if let ExprKind::Call { func: f, .. } = &parent.node {
if let ExprKind::Call(ast::ExprCall { func: f, .. }) = &parent.node {
if let Some(id_parent) = helpers::expr_name(f) {
if id_parent == "dict" || id_parent == "set" || id_parent == "list" {
return;
@ -103,7 +103,7 @@ pub fn unnecessary_map(
};
};
if args.len() == 2 && matches!(&args[0].node, ExprKind::Lambda { .. }) {
if args.len() == 2 && matches!(&args[0].node, ExprKind::Lambda(_)) {
let mut diagnostic = create_diagnostic("generator", expr.range());
if checker.patch(diagnostic.kind.rule()) {
#[allow(deprecated)]
@ -126,14 +126,14 @@ pub fn unnecessary_map(
}
if let Some(arg) = args.first() {
if let ExprKind::Call { func, args, .. } = &arg.node {
if let ExprKind::Call(ast::ExprCall { func, args, .. }) = &arg.node {
if args.len() != 2 {
return;
}
let Some(argument) = helpers::first_argument_with_matching_function("map", func, args) else {
return;
};
if let ExprKind::Lambda { .. } = argument {
if let ExprKind::Lambda(_) = argument {
let mut diagnostic = create_diagnostic(id, expr.range());
if checker.patch(diagnostic.kind.rule()) {
#[allow(deprecated)]
@ -158,12 +158,12 @@ pub fn unnecessary_map(
}
if args.len() == 1 {
if let ExprKind::Call { func, args, .. } = &args[0].node {
if let ExprKind::Call(ast::ExprCall { func, args, .. }) = &args[0].node {
let Some(argument) = helpers::first_argument_with_matching_function("map", func, args) else {
return;
};
if let ExprKind::Lambda { body, .. } = &argument {
if matches!(&body.node, ExprKind::Tuple { elts, .. } | ExprKind::List { elts, .. } if elts.len() == 2)
if let ExprKind::Lambda(ast::ExprLambda { body, .. }) = &argument {
if matches!(&body.node, ExprKind::Tuple(ast::ExprTuple { elts, .. }) | ExprKind::List(ast::ExprList { elts, .. } )if elts.len() == 2)
{
let mut diagnostic = create_diagnostic(id, expr.range());
if checker.patch(diagnostic.kind.rule()) {

View file

@ -1,5 +1,5 @@
use num_bigint::BigInt;
use rustpython_parser::ast::{Constant, Expr, ExprKind, Unaryop};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Unaryop};
use crate::checkers::ast::Checker;
use ruff_diagnostics::{Diagnostic, Violation};
@ -60,10 +60,10 @@ pub fn unnecessary_subscript_reversal(
if !checker.ctx.is_builtin(id) {
return;
}
let ExprKind::Subscript { slice, .. } = &first_arg.node else {
let ExprKind::Subscript(ast::ExprSubscript { slice, .. }) = &first_arg.node else {
return;
};
let ExprKind::Slice { lower, upper, step } = &slice.node else {
let ExprKind::Slice(ast::ExprSlice { lower, upper, step }) = &slice.node else {
return;
};
if lower.is_some() || upper.is_some() {
@ -72,16 +72,16 @@ pub fn unnecessary_subscript_reversal(
let Some(step) = step.as_ref() else {
return;
};
let ExprKind::UnaryOp {
let ExprKind::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::USub,
operand,
} = &step.node else {
}) = &step.node else {
return;
};
let ExprKind::Constant {
let ExprKind::Constant(ast::ExprConstant {
value: Constant::Int(val),
..
} = &operand.node else {
}) = &operand.node else {
return;
};
if *val != BigInt::from(1) {

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextRange;
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -317,10 +317,10 @@ pub fn call_datetime_strptime_without_zone(
}
// Does the `strptime` call contain a format string with a timezone specifier?
if let Some(ExprKind::Constant {
if let Some(ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(format),
kind: None,
}) = args.get(1).as_ref().map(|arg| &arg.node)
})) = args.get(1).as_ref().map(|arg| &arg.node)
{
if format.contains("%z") {
return;
@ -335,8 +335,9 @@ pub fn call_datetime_strptime_without_zone(
return;
};
if let ExprKind::Call { keywords, .. } = &grandparent.node {
if let ExprKind::Attribute { attr, .. } = &parent.node {
if let ExprKind::Call(ast::ExprCall { keywords, .. }) = &grandparent.node {
if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &parent.node {
let attr = attr.as_str();
// Ex) `datetime.strptime(...).astimezone()`
if attr == "astimezone" {
return;

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Constant, Expr, ExprKind, Stmt, StmtKind};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Stmt, StmtKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -52,24 +52,24 @@ pub fn all_with_model_form(checker: &Checker, bases: &[Expr], body: &[Stmt]) ->
return None;
}
for element in body.iter() {
let StmtKind::ClassDef { name, body, .. } = &element.node else {
let StmtKind::ClassDef(ast::StmtClassDef { name, body, .. }) = &element.node else {
continue;
};
if name != "Meta" {
continue;
}
for element in body.iter() {
let StmtKind::Assign { targets, value, .. } = &element.node else {
let StmtKind::Assign(ast::StmtAssign { targets, value, .. }) = &element.node else {
continue;
};
for target in targets.iter() {
let ExprKind::Name { id, .. } = &target.node else {
let ExprKind::Name(ast::ExprName { id, .. }) = &target.node else {
continue;
};
if id != "fields" {
continue;
}
let ExprKind::Constant { value, .. } = &value.node else {
let ExprKind::Constant(ast::ExprConstant { value, .. }) = &value.node else {
continue;
};
match &value {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind};
use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -54,18 +54,18 @@ pub fn exclude_with_model_form(
return None;
}
for element in body.iter() {
let StmtKind::ClassDef { name, body, .. } = &element.node else {
let StmtKind::ClassDef(ast::StmtClassDef { name, body, .. }) = &element.node else {
continue;
};
if name != "Meta" {
continue;
}
for element in body.iter() {
let StmtKind::Assign { targets, .. } = &element.node else {
let StmtKind::Assign(ast::StmtAssign { targets, .. }) = &element.node else {
continue;
};
for target in targets.iter() {
let ExprKind::Name { id, .. } = &target.node else {
let ExprKind::Name(ast::ExprName { id, .. }) = &target.node else {
continue;
};
if id == "exclude" {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -86,7 +86,7 @@ pub fn locals_in_render_function(
}
fn is_locals_call(checker: &Checker, expr: &Expr) -> bool {
let ExprKind::Call { func, .. } = &expr.node else {
let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node else {
return false
};
checker

View file

@ -1,5 +1,4 @@
use rustpython_parser::ast::{Constant, Expr, StmtKind};
use rustpython_parser::ast::{ExprKind, Stmt};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Stmt, StmtKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -70,7 +69,7 @@ pub fn model_without_dunder_str(
fn has_dunder_method(body: &[Stmt]) -> bool {
body.iter().any(|val| match &val.node {
StmtKind::FunctionDef { name, .. } => {
StmtKind::FunctionDef(ast::StmtFunctionDef { name, .. }) => {
if name == "__str__" {
return true;
}
@ -95,24 +94,24 @@ fn checker_applies(checker: &Checker, bases: &[Expr], body: &[Stmt]) -> bool {
/// Check if class is abstract, in terms of Django model inheritance.
fn is_model_abstract(body: &[Stmt]) -> bool {
for element in body.iter() {
let StmtKind::ClassDef {name, body, ..} = &element.node else {
let StmtKind::ClassDef(ast::StmtClassDef {name, body, ..}) = &element.node else {
continue
};
if name != "Meta" {
continue;
}
for element in body.iter() {
let StmtKind::Assign {targets, value, ..} = &element.node else {
let StmtKind::Assign(ast::StmtAssign {targets, value, ..}) = &element.node else {
continue;
};
for target in targets.iter() {
let ExprKind::Name {id , ..} = &target.node else {
let ExprKind::Name(ast::ExprName {id , ..}) = &target.node else {
continue;
};
if id != "abstract" {
continue;
}
let ExprKind::Constant{value: Constant::Bool(true), ..} = &value.node else {
let ExprKind::Constant(ast::ExprConstant{value: Constant::Bool(true), ..}) = &value.node else {
continue;
};
return true;

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind};
use rustpython_parser::ast::{self, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -59,9 +59,10 @@ where
let mut seen_receiver = false;
for (i, decorator) in decorator_list.iter().enumerate() {
let is_receiver = match &decorator.node {
ExprKind::Call { func, .. } => resolve_call_path(func).map_or(false, |call_path| {
call_path.as_slice() == ["django", "dispatch", "receiver"]
}),
ExprKind::Call(ast::ExprCall { func, .. }) => resolve_call_path(func)
.map_or(false, |call_path| {
call_path.as_slice() == ["django", "dispatch", "receiver"]
}),
_ => false,
};
if i > 0 && is_receiver && !seen_receiver {

View file

@ -1,5 +1,5 @@
use rustpython_parser::ast::Constant::Bool;
use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind};
use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -64,7 +64,7 @@ const NOT_NULL_TRUE_FIELDS: [&str; 6] = [
pub fn nullable_model_string_field(checker: &Checker, body: &[Stmt]) -> Vec<Diagnostic> {
let mut errors = Vec::new();
for statement in body.iter() {
let StmtKind::Assign {value, ..} = &statement.node else {
let StmtKind::Assign(ast::StmtAssign {value, ..}) = &statement.node else {
continue
};
if let Some(field_name) = is_nullable_field(checker, value) {
@ -80,7 +80,7 @@ pub fn nullable_model_string_field(checker: &Checker, body: &[Stmt]) -> Vec<Diag
}
fn is_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a str> {
let ExprKind::Call {func, keywords, ..} = &value.node else {
let ExprKind::Call(ast::ExprCall {func, keywords, ..}) = &value.node else {
return None;
};
@ -96,7 +96,7 @@ fn is_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a st
let mut blank_key = false;
let mut unique_key = false;
for keyword in keywords.iter() {
let ExprKind::Constant {value: Bool(true), ..} = &keyword.node.value.node else {
let ExprKind::Constant(ast::ExprConstant {value: Bool(true), ..}) = &keyword.node.value.node else {
continue
};
let Some(argument) = &keyword.node.arg else {

View file

@ -1,6 +1,6 @@
use std::fmt;
use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind};
use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -101,8 +101,8 @@ impl fmt::Display for ContentType {
fn get_element_type(checker: &Checker, element: &StmtKind) -> Option<ContentType> {
match element {
StmtKind::Assign { targets, value, .. } => {
if let ExprKind::Call { func, .. } = &value.node {
StmtKind::Assign(ast::StmtAssign { targets, value, .. }) => {
if let ExprKind::Call(ast::ExprCall { func, .. }) = &value.node {
if helpers::is_model_field(&checker.ctx, func) {
return Some(ContentType::FieldDeclaration);
}
@ -110,7 +110,7 @@ fn get_element_type(checker: &Checker, element: &StmtKind) -> Option<ContentType
let Some(expr) = targets.first() else {
return None;
};
let ExprKind::Name { id, .. } = &expr.node else {
let ExprKind::Name(ast::ExprName { id, .. }) = &expr.node else {
return None;
};
if id == "objects" {
@ -119,14 +119,14 @@ fn get_element_type(checker: &Checker, element: &StmtKind) -> Option<ContentType
None
}
}
StmtKind::ClassDef { name, .. } => {
StmtKind::ClassDef(ast::StmtClassDef { name, .. }) => {
if name == "Meta" {
Some(ContentType::MetaClass)
} else {
None
}
}
StmtKind::FunctionDef { name, .. } => match name.as_str() {
StmtKind::FunctionDef(ast::StmtFunctionDef { name, .. }) => match name.as_str() {
"__str__" => Some(ContentType::StrMethod),
"save" => Some(ContentType::SaveMethod),
"get_absolute_url" => Some(ContentType::GetAbsoluteUrlMethod),

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind};
use rustpython_parser::ast::{self, Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind};
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -184,14 +184,14 @@ impl Violation for DotFormatInException {
/// 2. Replace the exception argument with the variable name.
fn generate_fix(stylist: &Stylist, stmt: &Stmt, exc_arg: &Expr, indentation: &str) -> Fix {
let assignment = unparse_stmt(
&create_stmt(StmtKind::Assign {
targets: vec![create_expr(ExprKind::Name {
id: String::from("msg"),
&create_stmt(StmtKind::Assign(ast::StmtAssign {
targets: vec![create_expr(ExprKind::Name(ast::ExprName {
id: "msg".into(),
ctx: ExprContext::Store,
})],
}))],
value: Box::new(exc_arg.clone()),
type_comment: None,
}),
})),
stylist,
);
#[allow(deprecated)]
@ -214,14 +214,14 @@ fn generate_fix(stylist: &Stylist, stmt: &Stmt, exc_arg: &Expr, indentation: &st
/// EM101, EM102, EM103
pub fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr) {
if let ExprKind::Call { args, .. } = &exc.node {
if let ExprKind::Call(ast::ExprCall { args, .. }) = &exc.node {
if let Some(first) = args.first() {
match &first.node {
// Check for string literals
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(string),
..
} => {
}) => {
if checker.settings.rules.enabled(Rule::RawStringInException) {
if string.len() > checker.settings.flake8_errmsg.max_string_length {
let indentation = whitespace::indentation(checker.locator, stmt)
@ -249,7 +249,7 @@ pub fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr) {
}
}
// Check for f-strings
ExprKind::JoinedStr { .. } => {
ExprKind::JoinedStr(_) => {
if checker.settings.rules.enabled(Rule::FStringInException) {
let indentation = whitespace::indentation(checker.locator, stmt).and_then(
|indentation| {
@ -275,10 +275,12 @@ pub fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr) {
}
}
// Check for .format() calls
ExprKind::Call { func, .. } => {
ExprKind::Call(ast::ExprCall { func, .. }) => {
if checker.settings.rules.enabled(Rule::DotFormatInException) {
if let ExprKind::Attribute { value, attr, .. } = &func.node {
if attr == "format" && matches!(value.node, ExprKind::Constant { .. }) {
if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) =
&func.node
{
if attr == "format" && matches!(value.node, ExprKind::Constant(_)) {
let indentation = whitespace::indentation(checker.locator, stmt)
.and_then(|indentation| {
if checker.ctx.find_binding("msg").is_none() {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Constant, Expr, ExprKind, Operator};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Operator};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -34,8 +34,8 @@ impl Violation for PrintfInGetTextFuncCall {
/// Returns true if the [`Expr`] is an internationalization function call.
pub fn is_gettext_func_call(func: &Expr, functions_names: &[String]) -> bool {
if let ExprKind::Name { id, .. } = &func.node {
functions_names.contains(id)
if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node {
functions_names.contains(id.as_ref())
} else {
false
}
@ -44,7 +44,7 @@ pub fn is_gettext_func_call(func: &Expr, functions_names: &[String]) -> bool {
/// INT001
pub fn f_string_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> {
if let Some(first) = args.first() {
if matches!(first.node, ExprKind::JoinedStr { .. }) {
if matches!(first.node, ExprKind::JoinedStr(_)) {
return Some(Diagnostic::new(FStringInGetTextFuncCall {}, first.range()));
}
}
@ -54,8 +54,8 @@ pub fn f_string_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> {
/// INT002
pub fn format_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> {
if let Some(first) = args.first() {
if let ExprKind::Call { func, .. } = &first.node {
if let ExprKind::Attribute { attr, .. } = &func.node {
if let ExprKind::Call(ast::ExprCall { func, .. }) = &first.node {
if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node {
if attr == "format" {
return Some(Diagnostic::new(FormatInGetTextFuncCall {}, first.range()));
}
@ -68,16 +68,16 @@ pub fn format_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> {
/// INT003
pub fn printf_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> {
if let Some(first) = args.first() {
if let ExprKind::BinOp {
if let ExprKind::BinOp(ast::ExprBinOp {
op: Operator::Mod { .. },
left,
..
} = &first.node
}) = &first.node
{
if let ExprKind::Constant {
if let ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(_),
..
} = left.node
}) = left.node
{
return Some(Diagnostic::new(PrintfInGetTextFuncCall {}, first.range()));
}

View file

@ -1,6 +1,6 @@
use itertools::Itertools;
use ruff_text_size::TextRange;
use rustpython_parser::ast::{Constant, Expr, ExprKind, Operator};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Operator};
use rustpython_parser::lexer::LexResult;
use rustpython_parser::Tok;
@ -149,22 +149,22 @@ pub fn implicit(tokens: &[LexResult], settings: &Settings, locator: &Locator) ->
/// ISC003
pub fn explicit(expr: &Expr) -> Option<Diagnostic> {
if let ExprKind::BinOp { left, op, right } = &expr.node {
if let ExprKind::BinOp(ast::ExprBinOp { left, op, right }) = &expr.node {
if matches!(op, Operator::Add) {
if matches!(
left.node,
ExprKind::JoinedStr { .. }
| ExprKind::Constant {
ExprKind::JoinedStr(_)
| ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(..) | Constant::Bytes(..),
..
}
})
) && matches!(
right.node,
ExprKind::JoinedStr { .. }
| ExprKind::Constant {
ExprKind::JoinedStr(_)
| ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(..) | Constant::Bytes(..),
..
}
})
) {
return Some(Diagnostic::new(ExplicitStringConcatenation, expr.range()));
}

View file

@ -1,6 +1,5 @@
use ruff_text_size::{TextRange, TextSize};
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword, Operator};
use std::ops::Add;
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword, Operator};
use ruff_diagnostics::{Diagnostic, Edit, Fix};
use ruff_python_ast::helpers::{find_keyword, SimpleCallArgs};
@ -43,7 +42,7 @@ const RESERVED_ATTRS: &[&str; 22] = &[
fn check_msg(checker: &mut Checker, msg: &Expr) {
match &msg.node {
// Check for string concatenation and percent format.
ExprKind::BinOp { op, .. } => match op {
ExprKind::BinOp(ast::ExprBinOp { op, .. }) => match op {
Operator::Add => {
if checker.settings.rules.enabled(Rule::LoggingStringConcat) {
checker
@ -61,7 +60,7 @@ fn check_msg(checker: &mut Checker, msg: &Expr) {
_ => {}
},
// Check for f-strings.
ExprKind::JoinedStr { .. } => {
ExprKind::JoinedStr(_) => {
if checker.settings.rules.enabled(Rule::LoggingFString) {
checker
.diagnostics
@ -69,10 +68,10 @@ fn check_msg(checker: &mut Checker, msg: &Expr) {
}
}
// Check for .format() calls.
ExprKind::Call { func, .. } => {
ExprKind::Call(ast::ExprCall { func, .. }) => {
if checker.settings.rules.enabled(Rule::LoggingStringFormat) {
if let ExprKind::Attribute { value, attr, .. } = &func.node {
if attr == "format" && matches!(value.node, ExprKind::Constant { .. }) {
if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &func.node {
if attr == "format" && matches!(value.node, ExprKind::Constant(_)) {
checker
.diagnostics
.push(Diagnostic::new(LoggingStringFormat, msg.range()));
@ -87,13 +86,13 @@ fn check_msg(checker: &mut Checker, msg: &Expr) {
/// Check contents of the `extra` argument to logging calls.
fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) {
match &extra.node.value.node {
ExprKind::Dict { keys, .. } => {
ExprKind::Dict(ast::ExprDict { keys, .. }) => {
for key in keys {
if let Some(key) = &key {
if let ExprKind::Constant {
if let ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(string),
..
} = &key.node
}) = &key.node
{
if RESERVED_ATTRS.contains(&string.as_str()) {
checker.diagnostics.push(Diagnostic::new(
@ -105,7 +104,7 @@ fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) {
}
}
}
ExprKind::Call { func, keywords, .. } => {
ExprKind::Call(ast::ExprCall { func, keywords, .. }) => {
if checker
.ctx
.resolve_call_path(func)
@ -151,10 +150,10 @@ pub fn logging_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords:
return;
}
if let ExprKind::Attribute { value, attr, .. } = &func.node {
if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &func.node {
if let Some(logging_call_type) = LoggingCallType::from_attribute(attr.as_str()) {
let call_args = SimpleCallArgs::new(args, keywords);
let level_call_range = TextRange::new(value.end().add(TextSize::from(1)), func.end());
let level_call_range = TextRange::new(value.end() + TextSize::from(1), func.end());
// G001 - G004
let msg_pos = usize::from(matches!(logging_call_type, LoggingCallType::LogCall));
@ -202,11 +201,13 @@ pub fn logging_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords:
// return.
if !(matches!(
exc_info.node.value.node,
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Bool(true),
..
}
) || if let ExprKind::Call { func, .. } = &exc_info.node.value.node {
})
) || if let ExprKind::Call(ast::ExprCall { func, .. }) =
&exc_info.node.value.node
{
checker
.ctx
.resolve_call_path(func)

View file

@ -5,7 +5,7 @@ use itertools::Either::{Left, Right};
use log::error;
use rustc_hash::FxHashSet;
use rustpython_parser::ast::{
Boolop, Constant, Expr, ExprContext, ExprKind, Keyword, Stmt, StmtKind,
self, Boolop, Constant, Expr, ExprContext, ExprKind, Keyword, Stmt, StmtKind,
};
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
@ -301,15 +301,15 @@ pub fn no_unnecessary_pass(checker: &mut Checker, body: &[Stmt]) {
// redundant. Consider removing all `pass` statements instead.
let docstring_stmt = &body[0];
let pass_stmt = &body[1];
let StmtKind::Expr { value } = &docstring_stmt.node else {
let StmtKind::Expr(ast::StmtExpr { value } )= &docstring_stmt.node else {
return;
};
if matches!(
value.node,
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(..),
..
}
})
) {
if matches!(pass_stmt.node, StmtKind::Pass) {
let mut diagnostic = Diagnostic::new(UnnecessaryPass, pass_stmt.range());
@ -351,18 +351,18 @@ pub fn duplicate_class_field_definition<'a, 'b>(
for stmt in body {
// Extract the property name from the assignment statement.
let target = match &stmt.node {
StmtKind::Assign { targets, .. } => {
StmtKind::Assign(ast::StmtAssign { targets, .. }) => {
if targets.len() != 1 {
continue;
}
if let ExprKind::Name { id, .. } = &targets[0].node {
if let ExprKind::Name(ast::ExprName { id, .. }) = &targets[0].node {
id
} else {
continue;
}
}
StmtKind::AnnAssign { target, .. } => {
if let ExprKind::Name { id, .. } = &target.node {
StmtKind::AnnAssign(ast::StmtAnnAssign { target, .. }) => {
if let ExprKind::Name(ast::ExprName { id, .. }) = &target.node {
id
} else {
continue;
@ -407,7 +407,7 @@ pub fn non_unique_enums<'a, 'b>(checker: &mut Checker<'a>, parent: &'b Stmt, bod
where
'b: 'a,
{
let StmtKind::ClassDef { bases, .. } = &parent.node else {
let StmtKind::ClassDef(ast::StmtClassDef { bases, .. }) = &parent.node else {
return;
};
@ -422,11 +422,11 @@ where
let mut seen_targets: FxHashSet<ComparableExpr> = FxHashSet::default();
for stmt in body {
let StmtKind::Assign { value, .. } = &stmt.node else {
let StmtKind::Assign(ast::StmtAssign { value, .. }) = &stmt.node else {
continue;
};
if let ExprKind::Call { func, .. } = &value.node {
if let ExprKind::Call(ast::ExprCall { func, .. }) = &value.node {
if checker
.ctx
.resolve_call_path(func)
@ -454,7 +454,7 @@ pub fn unnecessary_spread(checker: &mut Checker, keys: &[Option<Expr>], values:
if let (None, value) = item {
// We only care about when the key is None which indicates a spread `**`
// inside a dict.
if let ExprKind::Dict { .. } = value.node {
if let ExprKind::Dict(_) = value.node {
let diagnostic = Diagnostic::new(UnnecessarySpread, value.range());
checker.diagnostics.push(diagnostic);
}
@ -464,10 +464,10 @@ pub fn unnecessary_spread(checker: &mut Checker, keys: &[Option<Expr>], values:
/// Return `true` if a key is a valid keyword argument name.
fn is_valid_kwarg_name(key: &Expr) -> bool {
if let ExprKind::Constant {
if let ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(value),
..
} = &key.node
}) = &key.node
{
is_identifier(value)
} else {
@ -480,7 +480,7 @@ pub fn unnecessary_dict_kwargs(checker: &mut Checker, expr: &Expr, kwargs: &[Key
for kw in kwargs {
// keyword is a spread operator (indicated by None)
if kw.node.arg.is_none() {
if let ExprKind::Dict { keys, .. } = &kw.node.value.node {
if let ExprKind::Dict(ast::ExprDict { keys, .. }) = &kw.node.value.node {
// ensure foo(**{"bar-bar": 1}) doesn't error
if keys.iter().all(|expr| expr.as_ref().map_or(false, is_valid_kwarg_name)) ||
// handle case of foo(**{**bar})
@ -496,18 +496,17 @@ pub fn unnecessary_dict_kwargs(checker: &mut Checker, expr: &Expr, kwargs: &[Key
/// PIE810
pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
let ExprKind::BoolOp { op: Boolop::Or, values } = &expr.node else {
let ExprKind::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values }) = &expr.node else {
return;
};
let mut duplicates = BTreeMap::new();
for (index, call) in values.iter().enumerate() {
let ExprKind::Call {
let ExprKind::Call(ast::ExprCall {
func,
args,
keywords,
..
} = &call.node else {
}) = &call.node else {
continue
};
@ -515,15 +514,14 @@ pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
continue;
}
let ExprKind::Attribute { value, attr, .. } = &func.node else {
let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. } )= &func.node else {
continue
};
if attr != "startswith" && attr != "endswith" {
continue;
}
let ExprKind::Name { id: arg_name, .. } = &value.node else {
let ExprKind::Name(ast::ExprName { id: arg_name, .. } )= &value.node else {
continue
};
@ -547,7 +545,7 @@ pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
.iter()
.map(|index| &values[*index])
.map(|expr| {
let ExprKind::Call { func: _, args, keywords: _} = &expr.node else {
let ExprKind::Call(ast::ExprCall { func: _, args, keywords: _}) = &expr.node else {
unreachable!("{}", format!("Indices should only contain `{attr_name}` calls"))
};
args.get(0)
@ -555,20 +553,20 @@ pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
})
.collect();
let call = create_expr(ExprKind::Call {
func: Box::new(create_expr(ExprKind::Attribute {
value: Box::new(create_expr(ExprKind::Name {
id: arg_name.to_string(),
let call = create_expr(ExprKind::Call(ast::ExprCall {
func: Box::new(create_expr(ExprKind::Attribute(ast::ExprAttribute {
value: Box::new(create_expr(ExprKind::Name(ast::ExprName {
id: arg_name.into(),
ctx: ExprContext::Load,
})),
attr: attr_name.to_string(),
}))),
attr: attr_name.into(),
ctx: ExprContext::Load,
})),
args: vec![create_expr(ExprKind::Tuple {
}))),
args: vec![create_expr(ExprKind::Tuple(ast::ExprTuple {
elts: words
.iter()
.flat_map(|value| {
if let ExprKind::Tuple { elts, .. } = &value.node {
if let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &value.node {
Left(elts.iter())
} else {
Right(iter::once(*value))
@ -577,13 +575,13 @@ pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
.map(Clone::clone)
.collect(),
ctx: ExprContext::Load,
})],
}))],
keywords: vec![],
});
}));
// Generate the combined `BoolOp`.
let mut call = Some(call);
let bool_op = create_expr(ExprKind::BoolOp {
let bool_op = create_expr(ExprKind::BoolOp(ast::ExprBoolOp {
op: Boolop::Or,
values: values
.iter()
@ -596,7 +594,7 @@ pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
}
})
.collect(),
});
}));
#[allow(deprecated)]
diagnostic.set_fix(Fix::unspecified(Edit::range_replacement(
unparse_expr(&bool_op, checker.stylist),
@ -610,7 +608,7 @@ pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
/// PIE807
pub fn reimplemented_list_builtin(checker: &mut Checker, expr: &Expr) {
let ExprKind::Lambda { args, body } = &expr.node else {
let ExprKind::Lambda(ast::ExprLambda { args, body }) = &expr.node else {
panic!("Expected ExprKind::Lambda");
};
if args.args.is_empty()
@ -619,7 +617,7 @@ pub fn reimplemented_list_builtin(checker: &mut Checker, expr: &Expr) {
&& args.vararg.is_none()
&& args.kwarg.is_none()
{
if let ExprKind::List { elts, .. } = &body.node {
if let ExprKind::List(ast::ExprList { elts, .. }) = &body.node {
if elts.is_empty() {
let mut diagnostic = Diagnostic::new(ReimplementedListBuiltin, expr.range());
if checker.patch(diagnostic.kind.rule()) {

View file

@ -1,5 +1,5 @@
use rustc_hash::FxHashSet;
use rustpython_parser::ast::{Expr, ExprKind, Operator};
use rustpython_parser::ast::{self, Expr, ExprKind, Operator};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation};
@ -45,11 +45,11 @@ fn traverse_union<'a>(
//
// So we have to traverse both branches in order (left, then right), to report duplicates
// in the order they appear in the source code.
if let ExprKind::BinOp {
if let ExprKind::BinOp(ast::ExprBinOp {
op: Operator::BitOr,
left,
right,
} = &expr.node
}) = &expr.node
{
// Traverse left subtree, then the right subtree, propagating the previous node.
traverse_union(seen_nodes, checker, left, Some(expr));
@ -72,7 +72,7 @@ fn traverse_union<'a>(
let parent = parent.expect("Parent node must exist");
// SAFETY: Parent node must have been a `BinOp` in order for us to have traversed it.
let ExprKind::BinOp { left, right, .. } = &parent.node else {
let ExprKind::BinOp(ast::ExprBinOp { left, right, .. }) = &parent.node else {
panic!("Parent node must be a BinOp");
};

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Constant, ExprKind, Stmt, StmtKind};
use rustpython_parser::ast::{self, Constant, ExprKind, Stmt, StmtKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -20,8 +20,8 @@ pub fn non_empty_stub_body(checker: &mut Checker, body: &[Stmt]) {
if body.len() != 1 {
return;
}
if let StmtKind::Expr { value } = &body[0].node {
if let ExprKind::Constant { value, .. } = &value.node {
if let StmtKind::Expr(ast::StmtExpr { value }) = &body[0].node {
if let ExprKind::Constant(ast::ExprConstant { value, .. }) = &value.node {
if matches!(value, Constant::Ellipsis | Constant::Str(_)) {
return;
}

View file

@ -1,6 +1,6 @@
use std::fmt;
use rustpython_parser::ast::{Expr, ExprKind};
use rustpython_parser::ast::{self, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -63,13 +63,13 @@ pub fn prefix_type_params(checker: &mut Checker, value: &Expr, targets: &[Expr])
if targets.len() != 1 {
return;
}
if let ExprKind::Name { id, .. } = &targets[0].node {
if let ExprKind::Name(ast::ExprName { id, .. }) = &targets[0].node {
if id.starts_with('_') {
return;
}
};
if let ExprKind::Call { func, .. } = &value.node {
if let ExprKind::Call(ast::ExprCall { func, .. }) = &value.node {
let Some(kind) = checker.ctx.resolve_call_path(func).and_then(|call_path| {
if checker.ctx.match_typing_call_path(&call_path, "ParamSpec") {
Some(VarKind::ParamSpec)

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Arguments, Constant, Expr, ExprKind, Operator, Unaryop};
use rustpython_parser::ast::{self, Arguments, Constant, Expr, ExprKind, Operator, Unaryop};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation};
@ -80,14 +80,16 @@ fn is_valid_default_value_with_annotation(
allow_container: bool,
) -> bool {
match &default.node {
ExprKind::List { elts, .. } | ExprKind::Tuple { elts, .. } | ExprKind::Set { elts, .. } => {
ExprKind::List(ast::ExprList { elts, .. })
| ExprKind::Tuple(ast::ExprTuple { elts, .. })
| ExprKind::Set(ast::ExprSet { elts }) => {
return allow_container
&& elts.len() <= 10
&& elts
.iter()
.all(|e| is_valid_default_value_with_annotation(e, checker, false));
}
ExprKind::Dict { keys, values, .. } => {
ExprKind::Dict(ast::ExprDict { keys, values }) => {
return allow_container
&& keys.len() <= 10
&& keys.iter().zip(values).all(|(k, v)| {
@ -96,60 +98,60 @@ fn is_valid_default_value_with_annotation(
}) && is_valid_default_value_with_annotation(v, checker, false)
});
}
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Ellipsis | Constant::None,
..
} => {
}) => {
return true;
}
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(..),
..
} => return checker.locator.slice(default.range()).len() <= 50,
ExprKind::Constant {
}) => return checker.locator.slice(default.range()).len() <= 50,
ExprKind::Constant(ast::ExprConstant {
value: Constant::Bytes(..),
..
} => return checker.locator.slice(default.range()).len() <= 50,
}) => return checker.locator.slice(default.range()).len() <= 50,
// Ex) `123`, `True`, `False`, `3.14`
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Int(..) | Constant::Bool(..) | Constant::Float(..),
..
} => {
}) => {
return checker.locator.slice(default.range()).len() <= 10;
}
// Ex) `2j`
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Complex { real, .. },
..
} => {
}) => {
if *real == 0.0 {
return checker.locator.slice(default.range()).len() <= 10;
}
}
ExprKind::UnaryOp {
ExprKind::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::USub,
operand,
} => {
}) => {
// Ex) `-1`, `-3.14`
if let ExprKind::Constant {
if let ExprKind::Constant(ast::ExprConstant {
value: Constant::Int(..) | Constant::Float(..),
..
} = &operand.node
}) = &operand.node
{
return checker.locator.slice(operand.range()).len() <= 10;
}
// Ex) `-2j`
if let ExprKind::Constant {
if let ExprKind::Constant(ast::ExprConstant {
value: Constant::Complex { real, .. },
..
} = &operand.node
}) = &operand.node
{
if *real == 0.0 {
return checker.locator.slice(operand.range()).len() <= 10;
}
}
// Ex) `-math.inf`, `-math.pi`, etc.
if let ExprKind::Attribute { .. } = &operand.node {
if let ExprKind::Attribute(_) = &operand.node {
if checker
.ctx
.resolve_call_path(operand)
@ -164,34 +166,34 @@ fn is_valid_default_value_with_annotation(
}
}
}
ExprKind::BinOp {
ExprKind::BinOp(ast::ExprBinOp {
left,
op: Operator::Add | Operator::Sub,
right,
} => {
}) => {
// Ex) `1 + 2j`, `1 - 2j`, `-1 - 2j`, `-1 + 2j`
if let ExprKind::Constant {
if let ExprKind::Constant(ast::ExprConstant {
value: Constant::Complex { .. },
..
} = right.node
}) = right.node
{
// Ex) `1 + 2j`, `1 - 2j`
if let ExprKind::Constant {
if let ExprKind::Constant(ast::ExprConstant {
value: Constant::Int(..) | Constant::Float(..),
..
} = &left.node
}) = &left.node
{
return checker.locator.slice(left.range()).len() <= 10;
} else if let ExprKind::UnaryOp {
} else if let ExprKind::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::USub,
operand,
} = &left.node
}) = &left.node
{
// Ex) `-1 + 2j`, `-1 - 2j`
if let ExprKind::Constant {
if let ExprKind::Constant(ast::ExprConstant {
value: Constant::Int(..) | Constant::Float(..),
..
} = &operand.node
}) = &operand.node
{
return checker.locator.slice(operand.range()).len() <= 10;
}
@ -199,7 +201,7 @@ fn is_valid_default_value_with_annotation(
}
}
// Ex) `math.inf`, `sys.stdin`, etc.
ExprKind::Attribute { .. } => {
ExprKind::Attribute(_) => {
if checker
.ctx
.resolve_call_path(default)
@ -221,18 +223,18 @@ fn is_valid_default_value_with_annotation(
/// Returns `true` if an [`Expr`] appears to be a valid PEP 604 union. (e.g. `int | None`)
fn is_valid_pep_604_union(annotation: &Expr) -> bool {
match &annotation.node {
ExprKind::BinOp {
ExprKind::BinOp(ast::ExprBinOp {
left,
op: Operator::BitOr,
right,
} => is_valid_pep_604_union(left) && is_valid_pep_604_union(right),
ExprKind::Name { .. }
| ExprKind::Subscript { .. }
| ExprKind::Attribute { .. }
| ExprKind::Constant {
}) => is_valid_pep_604_union(left) && is_valid_pep_604_union(right),
ExprKind::Name(_)
| ExprKind::Subscript(_)
| ExprKind::Attribute(_)
| ExprKind::Constant(ast::ExprConstant {
value: Constant::None,
..
} => true,
}) => true,
_ => false,
}
}
@ -241,21 +243,21 @@ fn is_valid_pep_604_union(annotation: &Expr) -> bool {
fn is_valid_default_value_without_annotation(default: &Expr) -> bool {
matches!(
&default.node,
ExprKind::Call { .. }
| ExprKind::Name { .. }
| ExprKind::Attribute { .. }
| ExprKind::Subscript { .. }
| ExprKind::Constant {
ExprKind::Call(_)
| ExprKind::Name(_)
| ExprKind::Attribute(_)
| ExprKind::Subscript(_)
| ExprKind::Constant(ast::ExprConstant {
value: Constant::Ellipsis | Constant::None,
..
}
})
) || is_valid_pep_604_union(default)
}
/// Returns `true` if an [`Expr`] appears to be `TypeVar`, `TypeVarTuple`, `NewType`, or `ParamSpec`
/// call.
fn is_type_var_like_call(context: &Context, expr: &Expr) -> bool {
let ExprKind::Call { func, .. } = &expr.node else {
let ExprKind::Call(ast::ExprCall { func, .. } )= &expr.node else {
return false;
};
context.resolve_call_path(func).map_or(false, |call_path| {
@ -272,7 +274,7 @@ fn is_type_var_like_call(context: &Context, expr: &Expr) -> bool {
/// Returns `true` if this is a "special" assignment which must have a value (e.g., an assignment to
/// `__all__`).
fn is_special_assignment(context: &Context, target: &Expr) -> bool {
if let ExprKind::Name { id, .. } = &target.node {
if let ExprKind::Name(ast::ExprName { id, .. }) = &target.node {
match id.as_str() {
"__all__" => context.scope().kind.is_module(),
"__match_args__" | "__slots__" => context.scope().kind.is_class(),

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Expr, ExprKind};
use rustpython_parser::ast::{self, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -60,7 +60,7 @@ fn is_t_suffixed_type_alias(name: &str) -> bool {
/// PYI042
pub fn snake_case_type_alias(checker: &mut Checker, target: &Expr) {
if let ExprKind::Name { id, .. } = target.node() {
if let ExprKind::Name(ast::ExprName { id, .. }) = target.node() {
if !is_snake_case_type_alias(id) {
return;
}
@ -76,7 +76,7 @@ pub fn snake_case_type_alias(checker: &mut Checker, target: &Expr) {
/// PYI043
pub fn t_suffixed_type_alias(checker: &mut Checker, target: &Expr) {
if let ExprKind::Name { id, .. } = target.node() {
if let ExprKind::Name(ast::ExprName { id, .. }) = target.node() {
if !is_t_suffixed_type_alias(id) {
return;
}

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Cmpop, Constant, Expr, ExprKind};
use rustpython_parser::ast::{self, Cmpop, Constant, Expr, ExprKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -126,10 +126,10 @@ pub fn unrecognized_platform(
}
match &right.node {
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(value),
..
} => {
}) => {
// Other values are possible but we don't need them right now.
// This protects against typos.
if !["linux", "win32", "cygwin", "darwin"].contains(&value.as_str())

View file

@ -6,7 +6,8 @@ use libcst_native::{
SmallStatement, Statement, Suite, TrailingWhitespace, UnaryOp, UnaryOperation,
};
use rustpython_parser::ast::{
Boolop, Excepthandler, ExcepthandlerKind, Expr, ExprKind, Keyword, Stmt, StmtKind, Unaryop,
self, Boolop, Excepthandler, ExcepthandlerKind, Expr, ExprKind, Keyword, Stmt, StmtKind,
Unaryop,
};
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
@ -135,7 +136,7 @@ where
{
fn visit_stmt(&mut self, stmt: &'a Stmt) {
match &stmt.node {
StmtKind::Assert { .. } => {
StmtKind::Assert(_) => {
self.current_assert = Some(stmt);
visitor::walk_stmt(self, stmt);
self.current_assert = None;
@ -146,9 +147,9 @@ where
fn visit_expr(&mut self, expr: &'a Expr) {
match &expr.node {
ExprKind::Name { id, .. } => {
ExprKind::Name(ast::ExprName { id, .. }) => {
if let Some(current_assert) = self.current_assert {
if id.as_str() == self.exception_name {
if id == self.exception_name {
self.errors.push(Diagnostic::new(
PytestAssertInExcept {
name: id.to_string(),
@ -181,11 +182,11 @@ pub fn unittest_assertion(
keywords: &[Keyword],
) -> Option<Diagnostic> {
match &func.node {
ExprKind::Attribute { attr, .. } => {
ExprKind::Attribute(ast::ExprAttribute { attr, .. }) => {
if let Ok(unittest_assert) = UnittestAssert::try_from(attr.as_str()) {
// We're converting an expression to a statement, so avoid applying the fix if
// the assertion is part of a larger expression.
let fixable = matches!(checker.ctx.stmt().node, StmtKind::Expr { .. })
let fixable = matches!(checker.ctx.stmt().node, StmtKind::Expr(_))
&& checker.ctx.expr_parent().is_none()
&& !checker.ctx.scope().kind.is_lambda()
&& !has_comments_in(expr.range(), checker.locator);
@ -227,7 +228,11 @@ pub fn assert_in_exception_handler(handlers: &[Excepthandler]) -> Vec<Diagnostic
handlers
.iter()
.flat_map(|handler| match &handler.node {
ExcepthandlerKind::ExceptHandler { name, body, .. } => {
ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler {
name,
body,
..
}) => {
if let Some(name) = name {
check_assert_in_except(name, body)
} else {
@ -255,28 +260,28 @@ enum CompositionKind {
/// `not a and not b` by De Morgan's laws.
fn is_composite_condition(test: &Expr) -> CompositionKind {
match &test.node {
ExprKind::BoolOp {
ExprKind::BoolOp(ast::ExprBoolOp {
op: Boolop::And, ..
} => {
}) => {
return CompositionKind::Simple;
}
ExprKind::UnaryOp {
ExprKind::UnaryOp(ast::ExprUnaryOp {
op: Unaryop::Not,
operand,
} => {
if let ExprKind::BoolOp {
}) => {
if let ExprKind::BoolOp(ast::ExprBoolOp {
op: Boolop::Or,
values,
} = &operand.node
}) = &operand.node
{
// Only split cases without mixed `and` and `or`.
return if values.iter().all(|expr| {
!matches!(
expr.node,
ExprKind::BoolOp {
ExprKind::BoolOp(ast::ExprBoolOp {
op: Boolop::And,
..
}
})
)
}) {
CompositionKind::Simple

View file

@ -1,6 +1,6 @@
use anyhow::Result;
use ruff_text_size::{TextLen, TextRange, TextSize};
use rustpython_parser::ast::{Arguments, Expr, ExprKind, Keyword, Stmt, StmtKind};
use rustpython_parser::ast::{self, Arguments, Expr, ExprKind, Keyword, Stmt, StmtKind};
use std::fmt;
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
@ -208,28 +208,28 @@ where
{
fn visit_stmt(&mut self, stmt: &'b Stmt) {
match &stmt.node {
StmtKind::Return { value, .. } => {
StmtKind::Return(ast::StmtReturn { value }) => {
if value.is_some() {
self.has_return_with_value = true;
}
}
StmtKind::FunctionDef { .. } | StmtKind::AsyncFunctionDef { .. } => {}
StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_) => {}
_ => visitor::walk_stmt(self, stmt),
}
}
fn visit_expr(&mut self, expr: &'b Expr) {
match &expr.node {
ExprKind::YieldFrom { .. } => {
ExprKind::YieldFrom(_) => {
self.has_yield_from = true;
}
ExprKind::Yield { value, .. } => {
ExprKind::Yield(ast::ExprYield { value }) => {
self.yield_statements.push(expr);
if value.is_some() {
self.has_return_with_value = true;
}
}
ExprKind::Call { func, .. } => {
ExprKind::Call(ast::ExprCall { func, .. }) => {
if collect_call_path(func).map_or(false, |call_path| {
call_path.as_slice() == ["request", "addfinalizer"]
}) {
@ -278,12 +278,11 @@ pub fn fix_extraneous_scope_function(
/// PT001, PT002, PT003
fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &Expr) {
match &decorator.node {
ExprKind::Call {
ExprKind::Call(ast::ExprCall {
func,
args,
keywords,
..
} => {
}) => {
if checker
.settings
.rules
@ -415,8 +414,8 @@ fn check_fixture_returns(checker: &mut Checker, stmt: &Stmt, name: &str, body: &
.enabled(Rule::PytestUselessYieldFixture)
{
if let Some(stmt) = body.last() {
if let StmtKind::Expr { value, .. } = &stmt.node {
if let ExprKind::Yield { .. } = value.node {
if let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node {
if let ExprKind::Yield(_) = value.node {
if visitor.yield_statements.len() == 1 {
let mut diagnostic = Diagnostic::new(
PytestUselessYieldFixture {

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
use ruff_python_ast::call_path::{collect_call_path, CallPath};
use ruff_python_ast::helpers::map_callable;
@ -48,10 +48,10 @@ pub(super) fn is_pytest_parametrize(context: &Context, decorator: &Expr) -> bool
}
pub(super) fn keyword_is_literal(kw: &Keyword, literal: &str) -> bool {
if let ExprKind::Constant {
if let ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(string),
..
} = &kw.node.value.node
}) = &kw.node.value.node
{
string == literal
} else {
@ -61,15 +61,17 @@ pub(super) fn keyword_is_literal(kw: &Keyword, literal: &str) -> bool {
pub(super) fn is_empty_or_null_string(expr: &Expr) -> bool {
match &expr.node {
ExprKind::Constant {
ExprKind::Constant(ast::ExprConstant {
value: Constant::Str(string),
..
} => string.is_empty(),
ExprKind::Constant {
}) => string.is_empty(),
ExprKind::Constant(ast::ExprConstant {
value: Constant::None,
..
} => true,
ExprKind::JoinedStr { values } => values.iter().all(is_empty_or_null_string),
}) => true,
ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => {
values.iter().all(is_empty_or_null_string)
}
_ => false,
}
}

View file

@ -36,7 +36,7 @@ pub fn import(import_from: &Stmt, name: &str, asname: Option<&str>) -> Option<Di
pub fn import_from(
import_from: &Stmt,
module: Option<&str>,
level: Option<usize>,
level: Option<u32>,
) -> Option<Diagnostic> {
// If level is not zero or module is none, return
if let Some(level) = level {

Some files were not shown because too many files have changed in this diff Show more