Upgrade RustPython to access ranged names (#5194)

## Summary

In https://github.com/astral-sh/RustPython-Parser/pull/8, we modified
RustPython to include ranges for any identifiers that aren't
`Expr::Name` (which already has an identifier).

For example, the `e` in `except ValueError as e` was previously
un-ranged. To extract its range, we had to do some lexing of our own.
This change should improve performance and let us remove a bunch of
code.

## Test Plan

`cargo test`
This commit is contained in:
Charlie Marsh 2023-06-20 11:43:38 -04:00 committed by GitHub
parent 17f1ecd56e
commit 6331598511
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 86 additions and 57 deletions

12
Cargo.lock generated
View file

@ -2105,7 +2105,7 @@ dependencies = [
[[package]] [[package]]
name = "ruff_text_size" name = "ruff_text_size"
version = "0.0.0" version = "0.0.0"
source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8d74eee75031b68d2204219963fae54a3f31a394#8d74eee75031b68d2204219963fae54a3f31a394" source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=ed3b4eb72b6e497bbdb4d19dec6621074d724130#ed3b4eb72b6e497bbdb4d19dec6621074d724130"
dependencies = [ dependencies = [
"schemars", "schemars",
"serde", "serde",
@ -2183,7 +2183,7 @@ dependencies = [
[[package]] [[package]]
name = "rustpython-ast" name = "rustpython-ast"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8d74eee75031b68d2204219963fae54a3f31a394#8d74eee75031b68d2204219963fae54a3f31a394" source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=ed3b4eb72b6e497bbdb4d19dec6621074d724130#ed3b4eb72b6e497bbdb4d19dec6621074d724130"
dependencies = [ dependencies = [
"is-macro", "is-macro",
"num-bigint", "num-bigint",
@ -2194,7 +2194,7 @@ dependencies = [
[[package]] [[package]]
name = "rustpython-format" name = "rustpython-format"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8d74eee75031b68d2204219963fae54a3f31a394#8d74eee75031b68d2204219963fae54a3f31a394" source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=ed3b4eb72b6e497bbdb4d19dec6621074d724130#ed3b4eb72b6e497bbdb4d19dec6621074d724130"
dependencies = [ dependencies = [
"bitflags 2.3.1", "bitflags 2.3.1",
"itertools", "itertools",
@ -2206,7 +2206,7 @@ dependencies = [
[[package]] [[package]]
name = "rustpython-literal" name = "rustpython-literal"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8d74eee75031b68d2204219963fae54a3f31a394#8d74eee75031b68d2204219963fae54a3f31a394" source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=ed3b4eb72b6e497bbdb4d19dec6621074d724130#ed3b4eb72b6e497bbdb4d19dec6621074d724130"
dependencies = [ dependencies = [
"hexf-parse", "hexf-parse",
"is-macro", "is-macro",
@ -2218,7 +2218,7 @@ dependencies = [
[[package]] [[package]]
name = "rustpython-parser" name = "rustpython-parser"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8d74eee75031b68d2204219963fae54a3f31a394#8d74eee75031b68d2204219963fae54a3f31a394" source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=ed3b4eb72b6e497bbdb4d19dec6621074d724130#ed3b4eb72b6e497bbdb4d19dec6621074d724130"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"is-macro", "is-macro",
@ -2241,7 +2241,7 @@ dependencies = [
[[package]] [[package]]
name = "rustpython-parser-core" name = "rustpython-parser-core"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8d74eee75031b68d2204219963fae54a3f31a394#8d74eee75031b68d2204219963fae54a3f31a394" source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=ed3b4eb72b6e497bbdb4d19dec6621074d724130#ed3b4eb72b6e497bbdb4d19dec6621074d724130"
dependencies = [ dependencies = [
"is-macro", "is-macro",
"memchr", "memchr",

View file

@ -24,7 +24,6 @@ ignore = { version = "0.4.20" }
insta = { version = "1.28.0" } insta = { version = "1.28.0" }
is-macro = { version = "0.2.2" } is-macro = { version = "0.2.2" }
itertools = { version = "0.10.5" } itertools = { version = "0.10.5" }
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "80e4c1399f95e5beb532fdd1e209ad2dbb470438" }
log = { version = "0.4.17" } log = { version = "0.4.17" }
memchr = "2.5.0" memchr = "2.5.0"
nohash-hasher = { version = "0.2.0" } nohash-hasher = { version = "0.2.0" }
@ -36,11 +35,6 @@ proc-macro2 = { version = "1.0.51" }
quote = { version = "1.0.23" } quote = { version = "1.0.23" }
regex = { version = "1.7.1" } regex = { version = "1.7.1" }
rustc-hash = { version = "1.1.0" } rustc-hash = { version = "1.1.0" }
ruff_text_size = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8d74eee75031b68d2204219963fae54a3f31a394" }
rustpython-ast = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8d74eee75031b68d2204219963fae54a3f31a394" , default-features = false, features = ["all-nodes-with-ranges", "num-bigint"]}
rustpython-format = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8d74eee75031b68d2204219963fae54a3f31a394", default-features = false, features = ["num-bigint"] }
rustpython-literal = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8d74eee75031b68d2204219963fae54a3f31a394" }
rustpython-parser = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8d74eee75031b68d2204219963fae54a3f31a394" , default-features = false, features = ["full-lexer", "all-nodes-with-ranges", "num-bigint"] }
schemars = { version = "0.8.12" } schemars = { version = "0.8.12" }
serde = { version = "1.0.152", features = ["derive"] } serde = { version = "1.0.152", features = ["derive"] }
serde_json = { version = "1.0.93" } serde_json = { version = "1.0.93" }
@ -53,6 +47,19 @@ syn = { version = "2.0.15" }
test-case = { version = "3.0.0" } test-case = { version = "3.0.0" }
toml = { version = "0.7.2" } toml = { version = "0.7.2" }
# v0.0.1
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "80e4c1399f95e5beb532fdd1e209ad2dbb470438" }
# v0.0.3
ruff_text_size = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "ed3b4eb72b6e497bbdb4d19dec6621074d724130" }
# v0.0.3
rustpython-ast = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "ed3b4eb72b6e497bbdb4d19dec6621074d724130" , default-features = false, features = ["all-nodes-with-ranges", "num-bigint"]}
# v0.0.3
rustpython-format = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "ed3b4eb72b6e497bbdb4d19dec6621074d724130", default-features = false, features = ["num-bigint"] }
# v0.0.3
rustpython-literal = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "ed3b4eb72b6e497bbdb4d19dec6621074d724130", default-features = false }
# v0.0.3
rustpython-parser = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "ed3b4eb72b6e497bbdb4d19dec6621074d724130" , default-features = false, features = ["full-lexer", "all-nodes-with-ranges", "num-bigint"] }
[profile.release] [profile.release]
lto = "fat" lto = "fat"
codegen-units = 1 codegen-units = 1

View file

@ -825,7 +825,7 @@ where
if alias if alias
.asname .asname
.as_ref() .as_ref()
.map_or(false, |asname| asname == &alias.name) .map_or(false, |asname| asname.as_str() == alias.name.as_str())
{ {
flags |= BindingFlags::EXPLICIT_EXPORT; flags |= BindingFlags::EXPLICIT_EXPORT;
} }
@ -1110,7 +1110,7 @@ where
if alias if alias
.asname .asname
.as_ref() .as_ref()
.map_or(false, |asname| asname == &alias.name) .map_or(false, |asname| asname.as_str() == alias.name.as_str())
{ {
flags |= BindingFlags::EXPLICIT_EXPORT; flags |= BindingFlags::EXPLICIT_EXPORT;
} }

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Ranged}; use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Identifier, Ranged};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -27,7 +27,7 @@ impl AlwaysAutofixableViolation for GetAttrWithConstant {
fn attribute(value: &Expr, attr: &str) -> Expr { fn attribute(value: &Expr, attr: &str) -> Expr {
ast::ExprAttribute { ast::ExprAttribute {
value: Box::new(value.clone()), value: Box::new(value.clone()),
attr: attr.into(), attr: Identifier::new(attr.to_string(), TextRange::default()),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
} }

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Ranged, Stmt}; use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Identifier, Ranged, Stmt};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -30,7 +30,7 @@ fn assignment(obj: &Expr, name: &str, value: &Expr, generator: Generator) -> Str
let stmt = Stmt::Assign(ast::StmtAssign { let stmt = Stmt::Assign(ast::StmtAssign {
targets: vec![Expr::Attribute(ast::ExprAttribute { targets: vec![Expr::Attribute(ast::ExprAttribute {
value: Box::new(obj.clone()), value: Box::new(obj.clone()),
attr: name.into(), attr: Identifier::new(name.to_string(), TextRange::default()),
ctx: ExprContext::Store, ctx: ExprContext::Store,
range: TextRange::default(), range: TextRange::default(),
})], })],

View file

@ -3,7 +3,7 @@ use rustpython_parser::ast::{self, Expr};
/// Returns true if the [`Expr`] is an internationalization function call. /// Returns true if the [`Expr`] is an internationalization function call.
pub(crate) fn is_gettext_func_call(func: &Expr, functions_names: &[String]) -> bool { pub(crate) fn is_gettext_func_call(func: &Expr, functions_names: &[String]) -> bool {
if let Expr::Name(ast::ExprName { id, .. }) = func { if let Expr::Name(ast::ExprName { id, .. }) = func {
functions_names.contains(id.as_ref()) functions_names.contains(id)
} else { } else {
false false
} }

View file

@ -5,7 +5,7 @@ use itertools::Either::{Left, Right};
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, BoolOp, Expr, ExprContext, Ranged}; use rustpython_parser::ast::{self, BoolOp, Expr, ExprContext, Identifier, Ranged};
use ruff_diagnostics::AlwaysAutofixableViolation; use ruff_diagnostics::AlwaysAutofixableViolation;
use ruff_diagnostics::{Diagnostic, Edit, Fix}; use ruff_diagnostics::{Diagnostic, Edit, Fix};
@ -140,7 +140,7 @@ pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
}); });
let node2 = Expr::Attribute(ast::ExprAttribute { let node2 = Expr::Attribute(ast::ExprAttribute {
value: Box::new(node1), value: Box::new(node1),
attr: attr_name.into(), attr: Identifier::new(attr_name.to_string(), TextRange::default()),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}); });

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{self, Expr, Identifier, Keyword, Ranged, Stmt, WithItem}; use rustpython_parser::ast::{self, Expr, Keyword, Ranged, Stmt, WithItem};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -74,9 +74,12 @@ pub(crate) fn raises_call(checker: &mut Checker, func: &Expr, args: &[Expr], key
} }
if checker.enabled(Rule::PytestRaisesTooBroad) { if checker.enabled(Rule::PytestRaisesTooBroad) {
let match_keyword = keywords let match_keyword = keywords.iter().find(|keyword| {
.iter() keyword
.find(|kw| kw.arg == Some(Identifier::new("match"))); .arg
.as_ref()
.map_or(false, |arg| arg.as_str() == "match")
});
if let Some(exception) = args.first() { if let Some(exception) = args.first() {
if let Some(match_keyword) = match_keyword { if let Some(match_keyword) = match_keyword {

View file

@ -3,7 +3,9 @@ use std::hash::BuildHasherDefault;
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Result};
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use rustpython_parser::ast::{self, CmpOp, Constant, Expr, ExprContext, Keyword, Stmt, UnaryOp}; use rustpython_parser::ast::{
self, CmpOp, Constant, Expr, ExprContext, Identifier, Keyword, Stmt, UnaryOp,
};
/// An enum to represent the different types of assertions present in the /// An enum to represent the different types of assertions present in the
/// `unittest` module. Note: any variants that can't be replaced with plain /// `unittest` module. Note: any variants that can't be replaced with plain
@ -388,7 +390,7 @@ impl UnittestAssert {
}; };
let node1 = ast::ExprAttribute { let node1 = ast::ExprAttribute {
value: Box::new(node.into()), value: Box::new(node.into()),
attr: "search".into(), attr: Identifier::new("search".to_string(), TextRange::default()),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };

View file

@ -1,7 +1,7 @@
use log::error; use log::error;
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use rustpython_parser::ast::{self, CmpOp, Constant, Expr, ExprContext, Ranged, Stmt}; use rustpython_parser::ast::{self, CmpOp, Constant, Expr, ExprContext, Identifier, Ranged, Stmt};
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -941,7 +941,7 @@ pub(crate) fn use_dict_get_with_default(
let node1 = *test_key.clone(); let node1 = *test_key.clone();
let node2 = ast::ExprAttribute { let node2 = ast::ExprAttribute {
value: expected_subscript.clone(), value: expected_subscript.clone(),
attr: "get".into(), attr: Identifier::new("get".to_string(), TextRange::default()),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Int, Ranged, Stmt}; use rustpython_parser::ast::{self, Identifier, Int, Ranged, Stmt};
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -94,7 +94,10 @@ fn fix_banned_relative_import(
panic!("Expected Stmt::ImportFrom"); panic!("Expected Stmt::ImportFrom");
}; };
let node = ast::StmtImportFrom { let node = ast::StmtImportFrom {
module: Some(module_path.to_string().into()), module: Some(Identifier::new(
module_path.to_string(),
TextRange::default(),
)),
names: names.clone(), names: names.clone(),
level: Some(Int::new(0)), level: Some(Int::new(0)),
range: TextRange::default(), range: TextRange::default(),

View file

@ -1,5 +1,7 @@
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Arg, ArgWithDefault, Arguments, Constant, Expr, Ranged, Stmt}; use rustpython_parser::ast::{
self, Arg, ArgWithDefault, Arguments, Constant, Expr, Identifier, Ranged, Stmt,
};
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -201,7 +203,7 @@ fn function(
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let func = Stmt::FunctionDef(ast::StmtFunctionDef { let func = Stmt::FunctionDef(ast::StmtFunctionDef {
name: name.into(), name: Identifier::new(name.to_string(), TextRange::default()),
args: Box::new(Arguments { args: Box::new(Arguments {
posonlyargs: new_posonlyargs, posonlyargs: new_posonlyargs,
args: new_args, args: new_args,
@ -217,7 +219,7 @@ fn function(
} }
} }
let func = Stmt::FunctionDef(ast::StmtFunctionDef { let func = Stmt::FunctionDef(ast::StmtFunctionDef {
name: name.into(), name: Identifier::new(name.to_string(), TextRange::default()),
args: Box::new(args.clone()), args: Box::new(args.clone()),
body: vec![body], body: vec![body],
decorator_list: vec![], decorator_list: vec![],

View file

@ -1,7 +1,7 @@
use std::hash::BuildHasherDefault; use std::hash::BuildHasherDefault;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use rustpython_parser::ast::{self, Expr, Identifier, Ranged}; use rustpython_parser::ast::{self, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -52,7 +52,7 @@ impl Violation for DuplicateBases {
/// PLE0241 /// PLE0241
pub(crate) fn duplicate_bases(checker: &mut Checker, name: &str, bases: &[Expr]) { pub(crate) fn duplicate_bases(checker: &mut Checker, name: &str, bases: &[Expr]) {
let mut seen: FxHashSet<&Identifier> = let mut seen: FxHashSet<&str> =
FxHashSet::with_capacity_and_hasher(bases.len(), BuildHasherDefault::default()); FxHashSet::with_capacity_and_hasher(bases.len(), BuildHasherDefault::default());
for base in bases { for base in bases {
if let Expr::Name(ast::ExprName { id, .. }) = base { if let Expr::Name(ast::ExprName { id, .. }) = base {

View file

@ -1,5 +1,5 @@
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Alias, Int, Ranged, Stmt}; use rustpython_parser::ast::{self, Alias, Identifier, Int, Ranged, Stmt};
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -74,7 +74,7 @@ pub(crate) fn manual_from_import(
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
if names.len() == 1 { if names.len() == 1 {
let node = ast::StmtImportFrom { let node = ast::StmtImportFrom {
module: Some(module.into()), module: Some(Identifier::new(module.to_string(), TextRange::default())),
names: vec![Alias { names: vec![Alias {
name: asname.clone(), name: asname.clone(),
asname: None, asname: None,

View file

@ -43,7 +43,7 @@ pub(crate) fn useless_import_alias(checker: &mut Checker, alias: &Alias) {
if alias.name.contains('.') { if alias.name.contains('.') {
return; return;
} }
if &alias.name != asname { if alias.name.as_str() != asname.as_str() {
return; return;
} }

View file

@ -1,7 +1,9 @@
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use log::debug; use log::debug;
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Keyword, Ranged, Stmt}; use rustpython_parser::ast::{
self, Constant, Expr, ExprContext, Identifier, Keyword, Ranged, Stmt,
};
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -185,7 +187,7 @@ fn create_properties_from_args(args: &[Expr], defaults: &[Expr]) -> Result<Vec<S
/// keywords. /// keywords.
fn create_class_def_stmt(typename: &str, body: Vec<Stmt>, base_class: &Expr) -> Stmt { fn create_class_def_stmt(typename: &str, body: Vec<Stmt>, base_class: &Expr) -> Stmt {
ast::StmtClassDef { ast::StmtClassDef {
name: typename.into(), name: Identifier::new(typename.to_string(), TextRange::default()),
bases: vec![base_class.clone()], bases: vec![base_class.clone()],
keywords: vec![], keywords: vec![],
body, body,

View file

@ -1,7 +1,9 @@
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use log::debug; use log::debug;
use ruff_text_size::TextRange; use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, Constant, Expr, ExprContext, Keyword, Ranged, Stmt}; use rustpython_parser::ast::{
self, Constant, Expr, ExprContext, Identifier, Keyword, Ranged, Stmt,
};
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -120,7 +122,7 @@ fn create_class_def_stmt(
None => vec![], None => vec![],
}; };
ast::StmtClassDef { ast::StmtClassDef {
name: class_name.into(), name: Identifier::new(class_name.to_string(), TextRange::default()),
bases: vec![base_class.clone()], bases: vec![base_class.clone()],
keywords, keywords,
body, body,

View file

@ -129,7 +129,7 @@ pub(crate) fn super_call_with_parameters(
return; return;
}; };
if !(first_arg_id == parent_name && second_arg_id == parent_arg) { if !(first_arg_id == parent_name.as_str() && second_arg_id == parent_arg.as_str()) {
return; return;
} }

View file

@ -289,7 +289,7 @@ fn generate_fix(checker: &Checker, conversion_type: ConversionType, expr: &Expr)
let new_expr = Expr::Subscript(ast::ExprSubscript { let new_expr = Expr::Subscript(ast::ExprSubscript {
range: TextRange::default(), range: TextRange::default(),
value: Box::new(Expr::Name(ast::ExprName { value: Box::new(Expr::Name(ast::ExprName {
id: binding.into(), id: binding,
ctx: ast::ExprContext::Store, ctx: ast::ExprContext::Store,
range: TextRange::default(), range: TextRange::default(),
})), })),

View file

@ -50,7 +50,7 @@ pub(crate) fn useless_try_except(checker: &mut Checker, handlers: &[ExceptHandle
if let Some(expr) = exc { if let Some(expr) = exc {
// E.g., `except ... as e: raise e` // E.g., `except ... as e: raise e`
if let Expr::Name(ast::ExprName { id, .. }) = expr.as_ref() { if let Expr::Name(ast::ExprName { id, .. }) = expr.as_ref() {
if Some(id) == name.as_ref() { if name.as_ref().map_or(false, |name| name.as_str() == id) {
return Some(Diagnostic::new(UselessTryExcept, handler.range())); return Some(Diagnostic::new(UselessTryExcept, handler.range()));
} }
} }

View file

@ -86,7 +86,7 @@ pub(crate) fn verbose_log_message(checker: &mut Checker, handlers: &[ExceptHandl
names names
}; };
for expr in names { for expr in names {
if expr.id == *target { if expr.id == target.as_str() {
checker checker
.diagnostics .diagnostics
.push(Diagnostic::new(VerboseLogMessage, expr.range())); .push(Diagnostic::new(VerboseLogMessage, expr.range()));

View file

@ -95,7 +95,7 @@ pub(crate) fn verbose_raise(checker: &mut Checker, handlers: &[ExceptHandler]) {
if let Some(exc) = exc { if let Some(exc) = exc {
// ...and the raised object is bound to the same name... // ...and the raised object is bound to the same name...
if let Expr::Name(ast::ExprName { id, .. }) = exc { if let Expr::Name(ast::ExprName { id, .. }) = exc {
if id == exception_name { if id == exception_name.as_str() {
checker checker
.diagnostics .diagnostics
.push(Diagnostic::new(VerboseRaise, exc.range())); .push(Diagnostic::new(VerboseRaise, exc.range()));

View file

@ -1191,7 +1191,7 @@ impl<'a> Generator<'a> {
self.p("*"); self.p("*");
self.unparse_expr(value, precedence::MAX); self.unparse_expr(value, precedence::MAX);
} }
Expr::Name(ast::ExprName { id, .. }) => self.p_id(id), Expr::Name(ast::ExprName { id, .. }) => self.p(id.as_str()),
Expr::List(ast::ExprList { elts, .. }) => { Expr::List(ast::ExprList { elts, .. }) => {
self.p("["); self.p("[");
let mut first = true; let mut first = true;

View file

@ -1,13 +1,16 @@
use crate::comments::visitor::{CommentPlacement, DecoratedComment}; use std::cmp::Ordering;
use crate::comments::CommentTextPosition;
use crate::trivia::{SimpleTokenizer, Token, TokenKind}; use ruff_text_size::{TextRange, TextSize};
use rustpython_parser::ast::Ranged;
use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::node::AnyNodeRef;
use ruff_python_ast::source_code::Locator; use ruff_python_ast::source_code::Locator;
use ruff_python_ast::whitespace; use ruff_python_ast::whitespace;
use ruff_python_whitespace::{PythonWhitespace, UniversalNewlines}; use ruff_python_whitespace::{PythonWhitespace, UniversalNewlines};
use ruff_text_size::{TextRange, TextSize};
use rustpython_parser::ast::Ranged; use crate::comments::visitor::{CommentPlacement, DecoratedComment};
use std::cmp::Ordering; use crate::comments::CommentTextPosition;
use crate::trivia::{SimpleTokenizer, Token, TokenKind};
/// Implements the custom comment placement logic. /// Implements the custom comment placement logic.
pub(super) fn place_comment<'a>( pub(super) fn place_comment<'a>(
@ -623,8 +626,13 @@ fn handle_positional_only_arguments_separator_comment<'a>(
return CommentPlacement::Default(comment); return CommentPlacement::Default(comment);
}; };
let is_last_positional_argument = are_same_optional(last_argument_or_default, arguments.posonlyargs.last()) let is_last_positional_argument =
// If the preceding node is the default for the last positional argument // If the preceding node is the identifier for the last positional argument (`a`).
// ```python
// def test(a, /, b): pass
// ```
are_same_optional(last_argument_or_default, arguments.posonlyargs.last().map(|arg| &arg.def))
// If the preceding node is the default for the last positional argument (`10`).
// ```python // ```python
// def test(a=10, /, b): pass // def test(a=10, /, b): pass
// ``` // ```