diff --git a/crates/ruff/src/autofix/codemods.rs b/crates/ruff/src/autofix/codemods.rs index 389107f787f192..6d290d81a08145 100644 --- a/crates/ruff/src/autofix/codemods.rs +++ b/crates/ruff/src/autofix/codemods.rs @@ -11,6 +11,23 @@ use ruff_python_ast::source_code::{Locator, Stylist}; use crate::cst::helpers::compose_module_path; use crate::cst::matchers::match_statement; +/// Glue code to make libcst codegen work with ruff's Stylist +pub(crate) trait CodegenStylist<'a>: Codegen<'a> { + fn codegen_stylist(&self, stylist: &'a Stylist) -> String; +} + +impl<'a, T: Codegen<'a>> CodegenStylist<'a> for T { + fn codegen_stylist(&self, stylist: &'a Stylist) -> String { + let mut state = CodegenState { + default_newline: stylist.line_ending().as_str(), + default_indent: stylist.indentation(), + ..Default::default() + }; + self.codegen(&mut state); + state.to_string() + } +} + /// Given an import statement, remove any imports that are specified in the `imports` iterator. /// /// Returns `Ok(None)` if the statement is empty after removing the imports. @@ -114,14 +131,7 @@ pub(crate) fn remove_imports<'a>( return Ok(None); } - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Some(state.to_string())) + Ok(Some(tree.codegen_stylist(stylist))) } /// Given an import statement, remove any imports that are not specified in the `imports` slice. @@ -200,11 +210,5 @@ pub(crate) fn retain_imports( } } - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - Ok(state.to_string()) + Ok(tree.codegen_stylist(stylist)) } diff --git a/crates/ruff/src/importer/mod.rs b/crates/ruff/src/importer/mod.rs index ca05d6b958d90e..9df741641fde77 100644 --- a/crates/ruff/src/importer/mod.rs +++ b/crates/ruff/src/importer/mod.rs @@ -3,11 +3,12 @@ use std::error::Error; use anyhow::Result; -use libcst_native::{Codegen, CodegenState, ImportAlias, Name, NameOrAttribute}; +use libcst_native::{ImportAlias, Name, NameOrAttribute}; use ruff_text_size::TextSize; use rustpython_parser::ast::{self, Ranged, Stmt, Suite}; use crate::autofix; +use crate::autofix::codemods::CodegenStylist; use ruff_diagnostics::Edit; use ruff_python_ast::imports::{AnyImport, Import, ImportFrom}; use ruff_python_ast::source_code::{Locator, Stylist}; @@ -324,13 +325,10 @@ impl<'a> Importer<'a> { asname: None, comma: aliases.last().and_then(|alias| alias.comma.clone()), }); - let mut state = CodegenState { - default_newline: &self.stylist.line_ending(), - default_indent: self.stylist.indentation(), - ..CodegenState::default() - }; - statement.codegen(&mut state); - Ok(Edit::range_replacement(state.to_string(), stmt.range())) + Ok(Edit::range_replacement( + statement.codegen_stylist(self.stylist), + stmt.range(), + )) } /// Add a `TYPE_CHECKING` block to the given module. diff --git a/crates/ruff/src/rules/flake8_comprehensions/fixes.rs b/crates/ruff/src/rules/flake8_comprehensions/fixes.rs index dcd062187cf7b4..b10156a39ae529 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/fixes.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/fixes.rs @@ -1,14 +1,15 @@ use anyhow::{bail, Result}; use itertools::Itertools; use libcst_native::{ - Arg, AssignEqual, AssignTargetExpression, Call, Codegen, CodegenState, Comment, CompFor, Dict, - DictComp, DictElement, Element, EmptyLine, Expression, GeneratorExp, LeftCurlyBrace, LeftParen, - LeftSquareBracket, List, ListComp, Name, ParenthesizableWhitespace, ParenthesizedWhitespace, - RightCurlyBrace, RightParen, RightSquareBracket, Set, SetComp, SimpleString, SimpleWhitespace, + Arg, AssignEqual, AssignTargetExpression, Call, Comment, CompFor, Dict, DictComp, DictElement, + Element, EmptyLine, Expression, GeneratorExp, LeftCurlyBrace, LeftParen, LeftSquareBracket, + List, ListComp, Name, ParenthesizableWhitespace, ParenthesizedWhitespace, RightCurlyBrace, + RightParen, RightSquareBracket, Set, SetComp, SimpleString, SimpleWhitespace, TrailingWhitespace, Tuple, }; use rustpython_parser::ast::Ranged; +use crate::autofix::codemods::CodegenStylist; use ruff_diagnostics::{Edit, Fix}; use ruff_python_ast::source_code::{Locator, Stylist}; @@ -44,14 +45,10 @@ pub(crate) fn fix_unnecessary_generator_list( rpar: generator_exp.rpar.clone(), })); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), expr.range())) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + expr.range(), + )) } /// (C401) Convert `set(x for x in y)` to `{x for x in y}`. @@ -82,14 +79,7 @@ pub(crate) fn fix_unnecessary_generator_set( rpar: generator_exp.rpar.clone(), })); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - let mut content = state.to_string(); + let mut content = tree.codegen_stylist(stylist); // If the expression is embedded in an f-string, surround it with spaces to avoid // syntax errors. @@ -136,14 +126,7 @@ pub(crate) fn fix_unnecessary_generator_dict( whitespace_after_colon: ParenthesizableWhitespace::SimpleWhitespace(SimpleWhitespace(" ")), })); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - let mut content = state.to_string(); + let mut content = tree.codegen_stylist(stylist); // If the expression is embedded in an f-string, surround it with spaces to avoid // syntax errors. @@ -182,14 +165,10 @@ pub(crate) fn fix_unnecessary_list_comprehension_set( rpar: list_comp.rpar.clone(), })); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), expr.range())) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + expr.range(), + )) } /// (C404) Convert `dict([(i, i) for i in range(3)])` to `{i: i for i in @@ -229,14 +208,10 @@ pub(crate) fn fix_unnecessary_list_comprehension_dict( rpar: list_comp.rpar.clone(), })); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), expr.range())) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + expr.range(), + )) } /// Drop a trailing comma from a list of tuple elements. @@ -318,14 +293,10 @@ pub(crate) fn fix_unnecessary_literal_set( })); } - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), expr.range())) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + expr.range(), + )) } /// (C406) Convert `dict([(1, 2)])` to `{1: 2}`. @@ -386,14 +357,10 @@ pub(crate) fn fix_unnecessary_literal_dict( rpar: vec![], })); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), expr.range())) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + expr.range(), + )) } /// (C408) @@ -495,14 +462,10 @@ pub(crate) fn fix_unnecessary_collection_call( } }; - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), expr.range())) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + expr.range(), + )) } /// (C409) Convert `tuple([1, 2])` to `tuple(1, 2)` @@ -549,14 +512,10 @@ pub(crate) fn fix_unnecessary_literal_within_tuple_call( }], })); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), expr.range())) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + expr.range(), + )) } /// (C410) Convert `list([1, 2])` to `[1, 2]` @@ -605,14 +564,10 @@ pub(crate) fn fix_unnecessary_literal_within_list_call( rpar: vec![], })); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), expr.range())) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + expr.range(), + )) } /// (C411) Convert `list([i * i for i in x])` to `[i * i for i in x]`. @@ -629,14 +584,10 @@ pub(crate) fn fix_unnecessary_list_call( tree = arg.value.clone(); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), expr.range())) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + expr.range(), + )) } /// (C413) Convert `list(sorted([2, 3, 1]))` to `sorted([2, 3, 1])`. @@ -747,14 +698,10 @@ pub(crate) fn fix_unnecessary_call_around_sorted( } } - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), expr.range())) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + expr.range(), + )) } /// (C414) Convert `sorted(list(foo))` to `sorted(foo)` @@ -781,14 +728,10 @@ pub(crate) fn fix_unnecessary_double_cast_or_process( None => bail!("Expected at least one argument in outer function call"), }; - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), expr.range())) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + expr.range(), + )) } /// (C416) Convert `[i for i in x]` to `list(x)`. @@ -872,14 +815,10 @@ pub(crate) fn fix_unnecessary_comprehension( } } - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), expr.range())) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + expr.range(), + )) } /// (C417) Convert `map(lambda x: x * 2, bar)` to `(x * 2 for x in bar)`. @@ -1018,14 +957,7 @@ pub(crate) fn fix_unnecessary_map( } } - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - let mut content = state.to_string(); + let mut content = tree.codegen_stylist(stylist); // If the expression is embedded in an f-string, surround it with spaces to avoid // syntax errors. @@ -1054,14 +986,10 @@ pub(crate) fn fix_unnecessary_literal_within_dict_call( tree = arg.value.clone(); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), expr.range())) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + expr.range(), + )) } /// (C419) Convert `[i for i in a]` into `i for i in a` @@ -1231,15 +1159,8 @@ pub(crate) fn fix_unnecessary_comprehension_any_all( _ => whitespace_after_arg, }; - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - Ok(Fix::suggested(Edit::range_replacement( - state.to_string(), + tree.codegen_stylist(stylist), expr.range(), ))) } diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs index aa59cf845d8709..ee2f4f7c1033c2 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs @@ -3,12 +3,13 @@ use std::borrow::Cow; use anyhow::bail; use anyhow::Result; use libcst_native::{ - Assert, BooleanOp, Codegen, CodegenState, CompoundStatement, Expression, - ParenthesizableWhitespace, ParenthesizedNode, SimpleStatementLine, SimpleWhitespace, - SmallStatement, Statement, TrailingWhitespace, UnaryOp, UnaryOperation, + Assert, BooleanOp, CompoundStatement, Expression, ParenthesizableWhitespace, ParenthesizedNode, + SimpleStatementLine, SimpleWhitespace, SmallStatement, Statement, TrailingWhitespace, UnaryOp, + UnaryOperation, }; use rustpython_parser::ast::{self, Boolop, Excepthandler, Expr, Keyword, Ranged, Stmt, Unaryop}; +use crate::autofix::codemods::CodegenStylist; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::helpers::{has_comments_in, Truthiness}; @@ -410,15 +411,8 @@ fn fix_composite_condition(stmt: &Stmt, locator: &Locator, stylist: &Stylist) -> })); } - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - // Reconstruct and reformat the code. - let module_text = state.to_string(); + let module_text = tree.codegen_stylist(stylist); let contents = if outer_indent.is_empty() { module_text } else { 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 4a58149ff8f33e..a36364dedf7660 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/fix_if.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/fix_if.rs @@ -2,12 +2,12 @@ use std::borrow::Cow; use anyhow::{bail, Result}; use libcst_native::{ - BooleanOp, BooleanOperation, Codegen, CodegenState, CompoundStatement, Expression, If, - LeftParen, ParenthesizableWhitespace, ParenthesizedNode, RightParen, SimpleWhitespace, - Statement, Suite, + BooleanOp, BooleanOperation, CompoundStatement, Expression, If, LeftParen, + ParenthesizableWhitespace, ParenthesizedNode, RightParen, SimpleWhitespace, Statement, Suite, }; use rustpython_parser::ast::Ranged; +use crate::autofix::codemods::CodegenStylist; use ruff_diagnostics::Edit; use ruff_python_ast::source_code::{Locator, Stylist}; use ruff_python_ast::whitespace; @@ -111,15 +111,8 @@ pub(crate) fn fix_nested_if_statements( })); outer_if.body = inner_if.body.clone(); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..Default::default() - }; - tree.codegen(&mut state); - // Reconstruct and reformat the code. - let module_text = state.to_string(); + let module_text = tree.codegen_stylist(stylist); let module_text = if outer_indent.is_empty() { &module_text } 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 eaae0f85755c61..b3636cabbc9fc7 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs @@ -1,7 +1,8 @@ use anyhow::{bail, Result}; -use libcst_native::{Codegen, CodegenState, CompoundStatement, Statement, Suite, With}; +use libcst_native::{CompoundStatement, Statement, Suite, With}; use rustpython_parser::ast::Ranged; +use crate::autofix::codemods::CodegenStylist; use ruff_diagnostics::Edit; use ruff_python_ast::source_code::{Locator, Stylist}; use ruff_python_ast::whitespace; @@ -70,15 +71,8 @@ pub(crate) fn fix_multiple_with_statements( } outer_with.body = inner_with.body.clone(); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - // Reconstruct and reformat the code. - let module_text = state.to_string(); + let module_text = tree.codegen_stylist(stylist); let contents = if outer_indent.is_empty() { module_text } else { diff --git a/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs b/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs index e63827a35263c8..8463476e960ba1 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs @@ -1,9 +1,10 @@ use anyhow::Result; -use libcst_native::{Codegen, CodegenState}; + use log::error; use ruff_text_size::TextRange; use rustpython_parser::ast::{self, Cmpop, Expr, Ranged}; +use crate::autofix::codemods::CodegenStylist; use ruff_diagnostics::Edit; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -42,14 +43,7 @@ fn get_value_content_for_key_in_dict( let call = match_call_mut(&mut expression)?; let attribute = match_attribute(&mut call.func)?; - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - attribute.value.codegen(&mut state); - - Ok(state.to_string()) + Ok(attribute.value.codegen_stylist(stylist)) } /// SIM118 diff --git a/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs b/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs index e21b586f901ea7..b7900195764998 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs @@ -1,7 +1,8 @@ use anyhow::Result; -use libcst_native::{Codegen, CodegenState, CompOp}; +use libcst_native::CompOp; use rustpython_parser::ast::{self, Cmpop, Expr, Ranged, Unaryop}; +use crate::autofix::codemods::CodegenStylist; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::source_code::{Locator, Stylist}; @@ -117,13 +118,7 @@ fn reverse_comparison(expr: &Expr, locator: &Locator, stylist: &Stylist) -> Resu _ => panic!("Expected comparison operator"), }; - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - expression.codegen(&mut state); - Ok(state.to_string()) + Ok(expression.codegen_stylist(stylist)) } /// SIM300 diff --git a/crates/ruff/src/rules/pyflakes/fixes.rs b/crates/ruff/src/rules/pyflakes/fixes.rs index 7a695132988209..83cdc6130beb56 100644 --- a/crates/ruff/src/rules/pyflakes/fixes.rs +++ b/crates/ruff/src/rules/pyflakes/fixes.rs @@ -1,5 +1,5 @@ use anyhow::{anyhow, bail, Ok, Result}; -use libcst_native::{Codegen, CodegenState, DictElement, Expression}; +use libcst_native::{DictElement, Expression}; use ruff_text_size::TextRange; use rustpython_format::{ FieldName, FieldNamePart, FieldType, FormatPart, FormatString, FromTemplate, @@ -7,6 +7,7 @@ use rustpython_format::{ use rustpython_parser::ast::{Excepthandler, Expr, Ranged}; use rustpython_parser::{lexer, Mode, Tok}; +use crate::autofix::codemods::CodegenStylist; use ruff_diagnostics::Edit; use ruff_python_ast::source_code::{Locator, Stylist}; use ruff_python_ast::str::{leading_quote, raw_contents, trailing_quote}; @@ -33,14 +34,10 @@ pub(crate) fn remove_unused_format_arguments_from_dict( } if raw_contents(name.value).map_or(false, |name| unused_arguments.contains(&name))) }); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), stmt.range())) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + stmt.range(), + )) } /// Generate a [`Edit`] to remove unused keyword arguments from a `format` call. @@ -57,14 +54,10 @@ pub(crate) fn remove_unused_keyword_arguments_from_format_call( call.args .retain(|e| !matches!(&e.keyword, Some(kw) if unused_arguments.contains(&kw.value))); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), location)) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + location, + )) } fn unparse_format_part(format_part: FormatPart) -> String { @@ -193,14 +186,10 @@ pub(crate) fn remove_unused_positional_arguments_from_format_call( simple_string.value = new_format_string.as_str(); } - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Ok(Edit::range_replacement(state.to_string(), location)) + Ok(Edit::range_replacement( + tree.codegen_stylist(stylist), + location, + )) } /// Generate a [`Edit`] to remove the binding from an exception handler. diff --git a/crates/ruff/src/rules/pyupgrade/fixes.rs b/crates/ruff/src/rules/pyupgrade/fixes.rs index ce242175f1b8fb..5f37034a2d169a 100644 --- a/crates/ruff/src/rules/pyupgrade/fixes.rs +++ b/crates/ruff/src/rules/pyupgrade/fixes.rs @@ -1,9 +1,10 @@ use anyhow::Result; -use libcst_native::{Codegen, CodegenState, ParenthesizableWhitespace}; +use libcst_native::ParenthesizableWhitespace; use ruff_text_size::{TextRange, TextSize}; use rustpython_parser::ast::{Expr, Ranged}; use rustpython_parser::{lexer, Mode, Tok}; +use crate::autofix::codemods::CodegenStylist; use ruff_diagnostics::Edit; use ruff_python_ast::source_code::{Locator, Stylist}; @@ -29,14 +30,7 @@ pub(crate) fn adjust_indentation( let indented_block = match_indented_block(&mut embedding.body)?; indented_block.indent = Some(indentation); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..Default::default() - }; - indented_block.codegen(&mut state); - - let module_text = state.to_string(); + let module_text = indented_block.codegen_stylist(stylist); let module_text = module_text .strip_prefix(stylist.line_ending().as_str()) .unwrap() @@ -61,14 +55,10 @@ pub(crate) fn remove_super_arguments( body.whitespace_before_args = ParenthesizableWhitespace::default(); body.whitespace_after_func = ParenthesizableWhitespace::default(); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - Some(Edit::range_replacement(state.to_string(), range)) + Some(Edit::range_replacement( + tree.codegen_stylist(stylist), + range, + )) } /// Remove any imports matching `members` from an import-from statement. diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs index f13f8b98251d47..9680aa8998a131 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs @@ -1,11 +1,12 @@ use anyhow::Result; use libcst_native::{ - AsName, AssignTargetExpression, Attribute, Codegen, CodegenState, Dot, Expression, Import, - ImportAlias, ImportFrom, ImportNames, Name, NameOrAttribute, ParenthesizableWhitespace, + AsName, AssignTargetExpression, Attribute, Dot, Expression, Import, ImportAlias, ImportFrom, + ImportNames, Name, NameOrAttribute, ParenthesizableWhitespace, }; use log::error; use rustpython_parser::ast::{self, Expr, Ranged, Stmt}; +use crate::autofix::codemods::CodegenStylist; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::call_path::collect_call_path; @@ -137,14 +138,7 @@ fn format_import( } else { import.names = clean_aliases; - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - let mut content = state.to_string(); + let mut content = tree.codegen_stylist(stylist); content.push_str(&stylist.line_ending()); content.push_str(indent); content.push_str(&format_mocks(mock_aliases, indent, stylist)); @@ -187,13 +181,7 @@ fn format_import_from( lpar: vec![], rpar: vec![], }))); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - Ok(state.to_string()) + Ok(tree.codegen_stylist(stylist)) } else if let ImportFrom { names: ImportNames::Aliases(aliases), .. @@ -224,14 +212,7 @@ fn format_import_from( rpar: vec![], }))); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - tree.codegen(&mut state); - - let mut content = state.to_string(); + let mut content = tree.codegen_stylist(stylist); if !mock_aliases.is_empty() { content.push_str(&stylist.line_ending()); content.push_str(indent); diff --git a/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs b/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs index 83e7f4d83934cc..0918d050788e83 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs @@ -1,9 +1,10 @@ use anyhow::{anyhow, bail, Result}; -use libcst_native::{Arg, Codegen, CodegenState}; +use libcst_native::Arg; use once_cell::sync::Lazy; use regex::Regex; use rustpython_parser::ast::{Expr, Ranged}; +use crate::autofix::codemods::CodegenStylist; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::source_code::{Locator, Stylist}; @@ -99,27 +100,16 @@ fn generate_call( // Fix the string itself. let item = match_attribute(&mut call.func)?; - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - item.codegen(&mut state); - let cleaned = remove_specifiers(&state.to_string()); + let cleaned = remove_specifiers(&item.codegen_stylist(stylist)); call.func = Box::new(match_expression(&cleaned)?); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - expression.codegen(&mut state); - if module_text == state.to_string() { + let state = expression.codegen_stylist(stylist); + if module_text == state { // Ex) `'{' '0}'.format(1)` bail!("Failed to generate call expression for: {module_text}") } - Ok(state.to_string()) + Ok(state) } /// UP030 diff --git a/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs b/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs index a9b6d989b0b8d2..9ed8091258bebb 100644 --- a/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs +++ b/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs @@ -1,7 +1,7 @@ use anyhow::{bail, Result}; -use libcst_native::{Codegen, CodegenState}; use rustpython_parser::ast::{self, Expr, Ranged}; +use crate::autofix::codemods::CodegenStylist; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::source_code::{Locator, Stylist}; @@ -77,15 +77,8 @@ fn fix_explicit_f_string_type_conversion( } formatted_string_expression.expression = call.args[0].value.clone(); - let mut state = CodegenState { - default_newline: &stylist.line_ending(), - default_indent: stylist.indentation(), - ..CodegenState::default() - }; - expression.codegen(&mut state); - Ok(Fix::automatic(Edit::range_replacement( - state.to_string(), + expression.codegen_stylist(stylist), range, ))) }