diff --git a/Cargo.lock b/Cargo.lock index 792a25d92a..2c90148e5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1931,7 +1931,6 @@ dependencies = [ "ruff_macros", "ruff_python", "rustc-hash", - "rustpython-ast", "rustpython-common", "rustpython-parser", "schemars", @@ -1998,7 +1997,6 @@ dependencies = [ "once_cell", "ruff", "ruff_cli", - "rustpython-ast", "rustpython-common", "rustpython-parser", "schemars", @@ -2076,7 +2074,6 @@ version = "0.2.0" source = "git+https://github.com/RustPython/RustPython.git?rev=adc23253e4b58980b407ba2760dbe61681d752fc#adc23253e4b58980b407ba2760dbe61681d752fc" dependencies = [ "num-bigint", - "rustpython-common", "rustpython-compiler-core", ] diff --git a/crates/ruff/Cargo.toml b/crates/ruff/Cargo.toml index f6620afd3e..e0d144c83a 100644 --- a/crates/ruff/Cargo.toml +++ b/crates/ruff/Cargo.toml @@ -42,7 +42,6 @@ regex = { version = "1.6.0" } ruff_macros = { version = "0.0.243", path = "../ruff_macros" } ruff_python = { version = "0.0.243", path = "../ruff_python" } rustc-hash = { version = "1.1.0" } -rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "adc23253e4b58980b407ba2760dbe61681d752fc" } rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "adc23253e4b58980b407ba2760dbe61681d752fc" } rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "adc23253e4b58980b407ba2760dbe61681d752fc" } schemars = { version = "0.8.11" } diff --git a/crates/ruff/src/ast/helpers.rs b/crates/ruff/src/ast/helpers.rs index 6bb7e78e09..f4ac0e5b97 100644 --- a/crates/ruff/src/ast/helpers.rs +++ b/crates/ruff/src/ast/helpers.rs @@ -30,20 +30,27 @@ pub fn create_stmt(node: StmtKind) -> Stmt { Stmt::new(Location::default(), Location::default(), node) } -/// Generate source code from an `Expr`. +/// Generate source code from an [`Expr`]. pub fn unparse_expr(expr: &Expr, stylist: &Stylist) -> String { let mut generator: Generator = stylist.into(); generator.unparse_expr(expr, 0); generator.generate() } -/// Generate source code from an `Stmt`. +/// Generate source code from a [`Stmt`]. pub fn unparse_stmt(stmt: &Stmt, stylist: &Stylist) -> String { let mut generator: Generator = stylist.into(); generator.unparse_stmt(stmt); generator.generate() } +/// Generate source code from an [`Constant`]. +pub fn unparse_constant(constant: &Constant, stylist: &Stylist) -> String { + let mut generator: Generator = stylist.into(); + generator.unparse_constant(constant); + generator.generate() +} + fn collect_call_path_inner<'a>(expr: &'a Expr, parts: &mut CallPath<'a>) -> bool { match &expr.node { ExprKind::Attribute { value, attr, .. } => { diff --git a/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs b/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs index c8a50efacb..ce882ff1c2 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs @@ -1,7 +1,7 @@ use ruff_macros::derive_message_formats; use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword}; -use crate::ast::helpers::SimpleCallArgs; +use crate::ast::helpers::{unparse_constant, SimpleCallArgs}; use crate::ast::types::Range; use crate::checkers::ast::Checker; use crate::define_violation; @@ -46,7 +46,7 @@ pub fn request_without_timeout( ExprKind::Constant { value: value @ Constant::None, .. - } => Some(value.to_string()), + } => Some(unparse_constant(value, checker.stylist)), _ => None, } { checker.diagnostics.push(Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_comprehensions/fixes.rs b/crates/ruff/src/rules/flake8_comprehensions/fixes.rs index 1a5adb70aa..64767eddb9 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/fixes.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/fixes.rs @@ -31,7 +31,7 @@ fn match_arg<'a, 'b>(call: &'a Call<'b>) -> Result<&'a Arg<'b>> { pub fn fix_unnecessary_generator_list( locator: &Locator, stylist: &Stylist, - expr: &rustpython_ast::Expr, + expr: &rustpython_parser::ast::Expr, ) -> Result { // Expr(Call(GeneratorExp)))) -> Expr(ListComp))) let module_text = locator.slice_source_code_range(&Range::from_located(expr)); @@ -77,7 +77,7 @@ pub fn fix_unnecessary_generator_list( pub fn fix_unnecessary_generator_set( locator: &Locator, stylist: &Stylist, - expr: &rustpython_ast::Expr, + expr: &rustpython_parser::ast::Expr, ) -> Result { // Expr(Call(GeneratorExp)))) -> Expr(SetComp))) let module_text = locator.slice_source_code_range(&Range::from_located(expr)); @@ -124,7 +124,7 @@ pub fn fix_unnecessary_generator_set( pub fn fix_unnecessary_generator_dict( locator: &Locator, stylist: &Stylist, - expr: &rustpython_ast::Expr, + expr: &rustpython_parser::ast::Expr, ) -> Result { let module_text = locator.slice_source_code_range(&Range::from_located(expr)); let mut tree = match_module(module_text)?; @@ -186,7 +186,7 @@ pub fn fix_unnecessary_generator_dict( pub fn fix_unnecessary_list_comprehension_set( locator: &Locator, stylist: &Stylist, - expr: &rustpython_ast::Expr, + expr: &rustpython_parser::ast::Expr, ) -> Result { // Expr(Call(ListComp)))) -> // Expr(SetComp))) @@ -232,7 +232,7 @@ pub fn fix_unnecessary_list_comprehension_set( pub fn fix_unnecessary_list_comprehension_dict( locator: &Locator, stylist: &Stylist, - expr: &rustpython_ast::Expr, + expr: &rustpython_parser::ast::Expr, ) -> Result { let module_text = locator.slice_source_code_range(&Range::from_located(expr)); let mut tree = match_module(module_text)?; @@ -330,7 +330,7 @@ fn drop_trailing_comma<'a>( pub fn fix_unnecessary_literal_set( locator: &Locator, stylist: &Stylist, - expr: &rustpython_ast::Expr, + expr: &rustpython_parser::ast::Expr, ) -> Result { // Expr(Call(List|Tuple)))) -> Expr(Set))) let module_text = locator.slice_source_code_range(&Range::from_located(expr)); @@ -381,7 +381,7 @@ pub fn fix_unnecessary_literal_set( pub fn fix_unnecessary_literal_dict( locator: &Locator, stylist: &Stylist, - expr: &rustpython_ast::Expr, + expr: &rustpython_parser::ast::Expr, ) -> Result { // Expr(Call(List|Tuple)))) -> Expr(Dict))) let module_text = locator.slice_source_code_range(&Range::from_located(expr)); @@ -454,7 +454,7 @@ pub fn fix_unnecessary_literal_dict( pub fn fix_unnecessary_collection_call( locator: &Locator, stylist: &Stylist, - expr: &rustpython_ast::Expr, + expr: &rustpython_parser::ast::Expr, ) -> Result { // Expr(Call("list" | "tuple" | "dict")))) -> Expr(List|Tuple|Dict) let module_text = locator.slice_source_code_range(&Range::from_located(expr)); @@ -568,7 +568,7 @@ pub fn fix_unnecessary_collection_call( pub fn fix_unnecessary_literal_within_tuple_call( locator: &Locator, stylist: &Stylist, - expr: &rustpython_ast::Expr, + expr: &rustpython_parser::ast::Expr, ) -> Result { let module_text = locator.slice_source_code_range(&Range::from_located(expr)); let mut tree = match_module(module_text)?; @@ -627,7 +627,7 @@ pub fn fix_unnecessary_literal_within_tuple_call( pub fn fix_unnecessary_literal_within_list_call( locator: &Locator, stylist: &Stylist, - expr: &rustpython_ast::Expr, + expr: &rustpython_parser::ast::Expr, ) -> Result { let module_text = locator.slice_source_code_range(&Range::from_located(expr)); let mut tree = match_module(module_text)?; @@ -688,7 +688,7 @@ pub fn fix_unnecessary_literal_within_list_call( pub fn fix_unnecessary_list_call( locator: &Locator, stylist: &Stylist, - expr: &rustpython_ast::Expr, + expr: &rustpython_parser::ast::Expr, ) -> Result { // Expr(Call(List|Tuple)))) -> Expr(List|Tuple))) let module_text = locator.slice_source_code_range(&Range::from_located(expr)); @@ -719,7 +719,7 @@ pub fn fix_unnecessary_list_call( pub fn fix_unnecessary_call_around_sorted( locator: &Locator, stylist: &Stylist, - expr: &rustpython_ast::Expr, + expr: &rustpython_parser::ast::Expr, ) -> Result { let module_text = locator.slice_source_code_range(&Range::from_located(expr)); let mut tree = match_module(module_text)?; @@ -806,7 +806,7 @@ pub fn fix_unnecessary_call_around_sorted( pub fn fix_unnecessary_comprehension( locator: &Locator, stylist: &Stylist, - expr: &rustpython_ast::Expr, + expr: &rustpython_parser::ast::Expr, ) -> Result { let module_text = locator.slice_source_code_range(&Range::from_located(expr)); let mut tree = match_module(module_text)?; diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs index 82d52d12d7..f8729c5a6b 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs @@ -189,7 +189,7 @@ pub fn double_negation(checker: &mut Checker, expr: &Expr, op: &Unaryop, operand let mut diagnostic = Diagnostic::new( DoubleNegation { - expr: operand.to_string(), + expr: unparse_expr(operand, checker.stylist), }, Range::from_located(expr), ); diff --git a/crates/ruff/src/rules/flake8_simplify/rules/fix_if.rs b/crates/ruff/src/rules/flake8_simplify/rules/fix_if.rs index 1a5eb62953..f551b7a31b 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/fix_if.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/fix_if.rs @@ -31,7 +31,7 @@ fn parenthesize_and_operand(expr: Expression) -> Expression { pub(crate) fn fix_nested_if_statements( locator: &Locator, stylist: &Stylist, - stmt: &rustpython_ast::Stmt, + stmt: &rustpython_parser::ast::Stmt, ) -> Result { // Infer the indentation of the outer block. let Some(outer_indent) = whitespace::indentation(locator, stmt) else { diff --git a/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs b/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs index 34dbb4f367..e1a430d074 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs @@ -12,7 +12,7 @@ use crate::source_code::{Locator, Stylist}; pub(crate) fn fix_multiple_with_statements( locator: &Locator, stylist: &Stylist, - stmt: &rustpython_ast::Stmt, + stmt: &rustpython_parser::ast::Stmt, ) -> Result { // Infer the indentation of the outer block. let Some(outer_indent) = whitespace::indentation(locator, stmt) else { diff --git a/crates/ruff/src/rules/pylint/rules/comparison_of_constant.rs b/crates/ruff/src/rules/pylint/rules/comparison_of_constant.rs index 551a3fa918..f97981314d 100644 --- a/crates/ruff/src/rules/pylint/rules/comparison_of_constant.rs +++ b/crates/ruff/src/rules/pylint/rules/comparison_of_constant.rs @@ -1,5 +1,6 @@ use std::fmt; +use crate::ast::helpers::unparse_constant; use itertools::Itertools; use ruff_macros::derive_message_formats; use rustpython_parser::ast::{Cmpop, Expr, ExprKind, Located}; @@ -108,9 +109,9 @@ pub fn comparison_of_constant( { let diagnostic = Diagnostic::new( ComparisonOfConstant { - left_constant: left_constant.to_string(), + left_constant: unparse_constant(left_constant, checker.stylist), op: op.into(), - right_constant: right_constant.to_string(), + right_constant: unparse_constant(right_constant, checker.stylist), }, Range::from_located(left), ); diff --git a/crates/ruff/src/rules/pylint/rules/magic_value_comparison.rs b/crates/ruff/src/rules/pylint/rules/magic_value_comparison.rs index d6b494c217..d8bf537c2a 100644 --- a/crates/ruff/src/rules/pylint/rules/magic_value_comparison.rs +++ b/crates/ruff/src/rules/pylint/rules/magic_value_comparison.rs @@ -1,3 +1,4 @@ +use crate::ast::helpers::unparse_constant; use itertools::Itertools; use ruff_macros::derive_message_formats; use rustpython_parser::ast::{Constant, Expr, ExprKind}; @@ -65,7 +66,7 @@ pub fn magic_value_comparison(checker: &mut Checker, left: &Expr, comparators: & if is_magic_value(value, &checker.settings.pylint.allow_magic_value_types) { checker.diagnostics.push(Diagnostic::new( MagicValueComparison { - value: value.to_string(), + value: unparse_constant(value, checker.stylist), }, Range::from_located(comparison_expr), )); diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR0133_comparison_of_constant.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR0133_comparison_of_constant.py.snap index d0ceda152a..296c281140 100644 --- a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR0133_comparison_of_constant.py.snap +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR0133_comparison_of_constant.py.snap @@ -1,5 +1,5 @@ --- -source: src/rules/pylint/mod.rs +source: crates/ruff/src/rules/pylint/mod.rs expression: diagnostics --- - kind: @@ -108,9 +108,9 @@ expression: diagnostics parent: ~ - kind: ComparisonOfConstant: - left_constant: "'hello'" + left_constant: "\"hello\"" op: Eq - right_constant: "''" + right_constant: "\"\"" location: row: 51 column: 3 diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__allow_magic_value_types.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__allow_magic_value_types.snap index 7c7bfe0b40..35b9e39e05 100644 --- a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__allow_magic_value_types.snap +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__allow_magic_value_types.snap @@ -1,10 +1,10 @@ --- -source: src/rules/pylint/mod.rs +source: crates/ruff/src/rules/pylint/mod.rs expression: diagnostics --- - kind: MagicValueComparison: - value: "'Hunter2'" + value: "\"Hunter2\"" location: row: 50 column: 21 @@ -26,7 +26,7 @@ expression: diagnostics parent: ~ - kind: MagicValueComparison: - value: "b'something'" + value: "b\"something\"" location: row: 65 column: 17 diff --git a/crates/ruff/src/source_code/generator.rs b/crates/ruff/src/source_code/generator.rs index 8b45ab0d75..68b9cf978a 100644 --- a/crates/ruff/src/source_code/generator.rs +++ b/crates/ruff/src/source_code/generator.rs @@ -644,7 +644,7 @@ impl<'a> Generator<'a> { let (op, prec) = opprec!( un, op, - rustpython_ast::Unaryop, + rustpython_parser::ast::Unaryop, Invert("~", FACTOR), Not("not ", NOT), UAdd("+", FACTOR), @@ -827,23 +827,7 @@ impl<'a> Generator<'a> { if let Some(kind) = kind { self.p(kind); } - assert_eq!(f64::MAX_10_EXP, 308); - let inf_str = "1e309"; - match value { - Constant::Float(f) if f.is_infinite() => self.p(inf_str), - Constant::Complex { real, imag } - if real.is_infinite() || imag.is_infinite() => - { - self.p(&value.to_string().replace("inf", inf_str)); - } - Constant::Bytes(b) => { - self.p(&bytes::repr(b, self.quote.into())); - } - Constant::Str(s) => { - self.p(&format!("{}", str::repr(s, self.quote.into()))); - } - _ => self.p(&format!("{value}")), - } + self.unparse_constant(value); } ExprKind::Attribute { value, attr, .. } => { if let ExprKind::Constant { @@ -919,6 +903,59 @@ impl<'a> Generator<'a> { } } + pub fn unparse_constant(&mut self, constant: &Constant) { + assert_eq!(f64::MAX_10_EXP, 308); + let inf_str = "1e309"; + match constant { + Constant::Bytes(b) => { + self.p(&bytes::repr(b, self.quote.into())); + } + Constant::Str(s) => { + self.p(&format!("{}", str::repr(s, self.quote.into()))); + } + Constant::None => self.p("None"), + Constant::Bool(b) => self.p(if *b { "True" } else { "False" }), + Constant::Int(i) => self.p(&format!("{}", i)), + Constant::Tuple(tup) => { + if let [elt] = &**tup { + self.p("("); + self.unparse_constant(elt); + self.p(","); + self.p(")"); + } else { + self.p("("); + for (i, elt) in tup.iter().enumerate() { + if i != 0 { + self.p(", "); + } + self.unparse_constant(elt); + } + self.p(")"); + } + } + Constant::Float(fp) => { + if fp.is_infinite() { + self.p(inf_str); + } else { + self.p(&rustpython_common::float_ops::to_string(*fp)); + } + } + Constant::Complex { real, imag } => { + let value = if *real == 0.0 { + format!("{imag}j") + } else { + format!("({real}{imag:+}j)") + }; + if real.is_infinite() || imag.is_infinite() { + self.p(&value.replace("inf", inf_str)); + } else { + self.p(&value); + } + } + Constant::Ellipsis => self.p("..."), + } + } + fn unparse_args(&mut self, args: &Arguments) { let mut first = true; let defaults_start = args.posonlyargs.len() + args.args.len() - args.defaults.len(); diff --git a/crates/ruff_dev/Cargo.toml b/crates/ruff_dev/Cargo.toml index b7da271bee..a58f4fa794 100644 --- a/crates/ruff_dev/Cargo.toml +++ b/crates/ruff_dev/Cargo.toml @@ -11,7 +11,6 @@ libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a87 once_cell = { version = "1.16.0" } ruff = { path = "../ruff" } ruff_cli = { path = "../ruff_cli" } -rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "adc23253e4b58980b407ba2760dbe61681d752fc" } rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "adc23253e4b58980b407ba2760dbe61681d752fc" } rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "adc23253e4b58980b407ba2760dbe61681d752fc" } schemars = { version = "0.8.11" }