Remove `BackwardsTokenizer` based `parenthesized_range` references in `ruff_linter` (#21836)

Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
Denys Zhak 2025-12-11 13:04:57 +01:00 committed by GitHub
parent 71540c03b6
commit 27912d46b1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
63 changed files with 263 additions and 529 deletions

View File

@ -437,6 +437,15 @@ impl<'a> Checker<'a> {
} }
} }
/// Returns the [`Tokens`] for the parsed source file.
///
///
/// Unlike [`Self::tokens`], this method always returns
/// the tokens for the current file, even when within a parsed type annotation.
pub(crate) fn source_tokens(&self) -> &'a Tokens {
self.parsed.tokens()
}
/// The [`Locator`] for the current file, which enables extraction of source code from byte /// The [`Locator`] for the current file, which enables extraction of source code from byte
/// offsets. /// offsets.
pub(crate) const fn locator(&self) -> &'a Locator<'a> { pub(crate) const fn locator(&self) -> &'a Locator<'a> {

View File

@ -3,14 +3,13 @@
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use ruff_python_ast::AnyNodeRef; use ruff_python_ast::AnyNodeRef;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::{self, Tokens, parenthesized_range};
use ruff_python_ast::{self as ast, Arguments, ExceptHandler, Expr, ExprList, Parameters, Stmt}; use ruff_python_ast::{self as ast, Arguments, ExceptHandler, Expr, ExprList, Parameters, Stmt};
use ruff_python_codegen::Stylist; use ruff_python_codegen::Stylist;
use ruff_python_index::Indexer; use ruff_python_index::Indexer;
use ruff_python_trivia::textwrap::dedent_to; use ruff_python_trivia::textwrap::dedent_to;
use ruff_python_trivia::{ use ruff_python_trivia::{
CommentRanges, PythonWhitespace, SimpleTokenKind, SimpleTokenizer, has_leading_content, PythonWhitespace, SimpleTokenKind, SimpleTokenizer, has_leading_content, is_python_whitespace,
is_python_whitespace,
}; };
use ruff_source_file::{LineRanges, NewlineWithTrailingNewline, UniversalNewlines}; use ruff_source_file::{LineRanges, NewlineWithTrailingNewline, UniversalNewlines};
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize}; use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
@ -209,7 +208,7 @@ pub(crate) fn remove_argument<T: Ranged>(
arguments: &Arguments, arguments: &Arguments,
parentheses: Parentheses, parentheses: Parentheses,
source: &str, source: &str,
comment_ranges: &CommentRanges, tokens: &Tokens,
) -> Result<Edit> { ) -> Result<Edit> {
// Partition into arguments before and after the argument to remove. // Partition into arguments before and after the argument to remove.
let (before, after): (Vec<_>, Vec<_>) = arguments let (before, after): (Vec<_>, Vec<_>) = arguments
@ -224,7 +223,7 @@ pub(crate) fn remove_argument<T: Ranged>(
.context("Unable to find argument")?; .context("Unable to find argument")?;
let parenthesized_range = let parenthesized_range =
parenthesized_range(arg.value().into(), arguments.into(), comment_ranges, source) token::parenthesized_range(arg.value().into(), arguments.into(), tokens)
.unwrap_or(arg.range()); .unwrap_or(arg.range());
if !after.is_empty() { if !after.is_empty() {
@ -270,24 +269,13 @@ pub(crate) fn remove_argument<T: Ranged>(
/// ///
/// The new argument will be inserted before the first existing keyword argument in `arguments`, if /// The new argument will be inserted before the first existing keyword argument in `arguments`, if
/// there are any present. Otherwise, the new argument is added to the end of the argument list. /// there are any present. Otherwise, the new argument is added to the end of the argument list.
pub(crate) fn add_argument( pub(crate) fn add_argument(argument: &str, arguments: &Arguments, tokens: &Tokens) -> Edit {
argument: &str,
arguments: &Arguments,
comment_ranges: &CommentRanges,
source: &str,
) -> Edit {
if let Some(ast::Keyword { range, value, .. }) = arguments.keywords.first() { if let Some(ast::Keyword { range, value, .. }) = arguments.keywords.first() {
let keyword = parenthesized_range(value.into(), arguments.into(), comment_ranges, source) let keyword = parenthesized_range(value.into(), arguments.into(), tokens).unwrap_or(*range);
.unwrap_or(*range);
Edit::insertion(format!("{argument}, "), keyword.start()) Edit::insertion(format!("{argument}, "), keyword.start())
} else if let Some(last) = arguments.arguments_source_order().last() { } else if let Some(last) = arguments.arguments_source_order().last() {
// Case 1: existing arguments, so append after the last argument. // Case 1: existing arguments, so append after the last argument.
let last = parenthesized_range( let last = parenthesized_range(last.value().into(), arguments.into(), tokens)
last.value().into(),
arguments.into(),
comment_ranges,
source,
)
.unwrap_or(last.range()); .unwrap_or(last.range());
Edit::insertion(format!(", {argument}"), last.end()) Edit::insertion(format!(", {argument}"), last.end())
} else { } else {

View File

@ -91,8 +91,8 @@ pub(crate) fn fastapi_redundant_response_model(checker: &Checker, function_def:
response_model_arg, response_model_arg,
&call.arguments, &call.arguments,
Parentheses::Preserve, Parentheses::Preserve,
checker.locator().contents(), checker.source(),
checker.comment_ranges(), checker.tokens(),
) )
.map(Fix::unsafe_edit) .map(Fix::unsafe_edit)
}); });

View File

@ -74,12 +74,7 @@ pub(crate) fn map_without_explicit_strict(checker: &Checker, call: &ast::ExprCal
checker checker
.report_diagnostic(MapWithoutExplicitStrict, call.range()) .report_diagnostic(MapWithoutExplicitStrict, call.range())
.set_fix(Fix::applicable_edit( .set_fix(Fix::applicable_edit(
add_argument( add_argument("strict=False", &call.arguments, checker.tokens()),
"strict=False",
&call.arguments,
checker.comment_ranges(),
checker.locator().contents(),
),
Applicability::Unsafe, Applicability::Unsafe,
)); ));
} }

View File

@ -3,7 +3,7 @@ use std::fmt::Write;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::is_docstring_stmt; use ruff_python_ast::helpers::is_docstring_stmt;
use ruff_python_ast::name::QualifiedName; use ruff_python_ast::name::QualifiedName;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{self as ast, Expr, ParameterWithDefault}; use ruff_python_ast::{self as ast, Expr, ParameterWithDefault};
use ruff_python_semantic::SemanticModel; use ruff_python_semantic::SemanticModel;
use ruff_python_semantic::analyze::function_type::is_stub; use ruff_python_semantic::analyze::function_type::is_stub;
@ -166,12 +166,7 @@ fn move_initialization(
return None; return None;
} }
let range = match parenthesized_range( let range = match parenthesized_range(default.into(), parameter.into(), checker.tokens()) {
default.into(),
parameter.into(),
checker.comment_ranges(),
checker.source(),
) {
Some(range) => range, Some(range) => range,
None => default.range(), None => default.range(),
}; };
@ -194,12 +189,7 @@ fn move_initialization(
"{} = {}", "{} = {}",
parameter.parameter.name(), parameter.parameter.name(),
locator.slice( locator.slice(
parenthesized_range( parenthesized_range(default.into(), parameter.into(), checker.tokens())
default.into(),
parameter.into(),
checker.comment_ranges(),
checker.source()
)
.unwrap_or(default.range()) .unwrap_or(default.range())
) )
); );

View File

@ -92,12 +92,7 @@ pub(crate) fn no_explicit_stacklevel(checker: &Checker, call: &ast::ExprCall) {
} }
let mut diagnostic = checker.report_diagnostic(NoExplicitStacklevel, call.func.range()); let mut diagnostic = checker.report_diagnostic(NoExplicitStacklevel, call.func.range());
let edit = add_argument( let edit = add_argument("stacklevel=2", &call.arguments, checker.tokens());
"stacklevel=2",
&call.arguments,
checker.comment_ranges(),
checker.locator().contents(),
);
diagnostic.set_fix(Fix::unsafe_edit(edit)); diagnostic.set_fix(Fix::unsafe_edit(edit));
} }

View File

@ -70,12 +70,7 @@ pub(crate) fn zip_without_explicit_strict(checker: &Checker, call: &ast::ExprCal
checker checker
.report_diagnostic(ZipWithoutExplicitStrict, call.range()) .report_diagnostic(ZipWithoutExplicitStrict, call.range())
.set_fix(Fix::applicable_edit( .set_fix(Fix::applicable_edit(
add_argument( add_argument("strict=False", &call.arguments, checker.tokens()),
"strict=False",
&call.arguments,
checker.comment_ranges(),
checker.locator().contents(),
),
Applicability::Unsafe, Applicability::Unsafe,
)); ));
} }

View File

@ -2,8 +2,8 @@ use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast; use ruff_python_ast as ast;
use ruff_python_ast::ExprGenerator; use ruff_python_ast::ExprGenerator;
use ruff_python_ast::comparable::ComparableExpr; use ruff_python_ast::comparable::ComparableExpr;
use ruff_python_ast::parenthesize::parenthesized_range;
use ruff_python_ast::token::TokenKind; use ruff_python_ast::token::TokenKind;
use ruff_python_ast::token::parenthesized_range;
use ruff_text_size::{Ranged, TextRange, TextSize}; use ruff_text_size::{Ranged, TextRange, TextSize};
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -142,12 +142,8 @@ pub(crate) fn unnecessary_generator_list(checker: &Checker, call: &ast::ExprCall
if *parenthesized { if *parenthesized {
// The generator's range will include the innermost parentheses, but it could be // The generator's range will include the innermost parentheses, but it could be
// surrounded by additional parentheses. // surrounded by additional parentheses.
let range = parenthesized_range( let range =
argument.into(), parenthesized_range(argument.into(), (&call.arguments).into(), checker.tokens())
(&call.arguments).into(),
checker.comment_ranges(),
checker.locator().contents(),
)
.unwrap_or(argument.range()); .unwrap_or(argument.range());
// The generator always parenthesizes the expression; trim the parentheses. // The generator always parenthesizes the expression; trim the parentheses.

View File

@ -2,8 +2,8 @@ use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast; use ruff_python_ast as ast;
use ruff_python_ast::ExprGenerator; use ruff_python_ast::ExprGenerator;
use ruff_python_ast::comparable::ComparableExpr; use ruff_python_ast::comparable::ComparableExpr;
use ruff_python_ast::parenthesize::parenthesized_range;
use ruff_python_ast::token::TokenKind; use ruff_python_ast::token::TokenKind;
use ruff_python_ast::token::parenthesized_range;
use ruff_text_size::{Ranged, TextRange, TextSize}; use ruff_text_size::{Ranged, TextRange, TextSize};
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -147,12 +147,8 @@ pub(crate) fn unnecessary_generator_set(checker: &Checker, call: &ast::ExprCall)
if *parenthesized { if *parenthesized {
// The generator's range will include the innermost parentheses, but it could be // The generator's range will include the innermost parentheses, but it could be
// surrounded by additional parentheses. // surrounded by additional parentheses.
let range = parenthesized_range( let range =
argument.into(), parenthesized_range(argument.into(), (&call.arguments).into(), checker.tokens())
(&call.arguments).into(),
checker.comment_ranges(),
checker.locator().contents(),
)
.unwrap_or(argument.range()); .unwrap_or(argument.range());
// The generator always parenthesizes the expression; trim the parentheses. // The generator always parenthesizes the expression; trim the parentheses.

View File

@ -1,7 +1,7 @@
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast; use ruff_python_ast as ast;
use ruff_python_ast::parenthesize::parenthesized_range;
use ruff_python_ast::token::TokenKind; use ruff_python_ast::token::TokenKind;
use ruff_python_ast::token::parenthesized_range;
use ruff_text_size::{Ranged, TextRange, TextSize}; use ruff_text_size::{Ranged, TextRange, TextSize};
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -89,12 +89,8 @@ pub(crate) fn unnecessary_list_comprehension_set(checker: &Checker, call: &ast::
// If the list comprehension is parenthesized, remove the parentheses in addition to // If the list comprehension is parenthesized, remove the parentheses in addition to
// removing the brackets. // removing the brackets.
let replacement_range = parenthesized_range( let replacement_range =
argument.into(), parenthesized_range(argument.into(), (&call.arguments).into(), checker.tokens())
(&call.arguments).into(),
checker.comment_ranges(),
checker.locator().contents(),
)
.unwrap_or_else(|| argument.range()); .unwrap_or_else(|| argument.range());
let span = argument.range().add_start(one).sub_end(one); let span = argument.range().add_start(one).sub_end(one);

View File

@ -1,5 +1,5 @@
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{self as ast, Expr, Operator}; use ruff_python_ast::{self as ast, Expr, Operator};
use ruff_python_trivia::is_python_whitespace; use ruff_python_trivia::is_python_whitespace;
use ruff_source_file::LineRanges; use ruff_source_file::LineRanges;
@ -88,13 +88,7 @@ pub(crate) fn explicit(checker: &Checker, expr: &Expr) {
checker.report_diagnostic(ExplicitStringConcatenation, expr.range()); checker.report_diagnostic(ExplicitStringConcatenation, expr.range());
let is_parenthesized = |expr: &Expr| { let is_parenthesized = |expr: &Expr| {
parenthesized_range( parenthesized_range(expr.into(), bin_op.into(), checker.tokens()).is_some()
expr.into(),
bin_op.into(),
checker.comment_ranges(),
checker.source(),
)
.is_some()
}; };
// If either `left` or `right` is parenthesized, generating // If either `left` or `right` is parenthesized, generating
// a fix would be too involved. Just report the diagnostic. // a fix would be too involved. Just report the diagnostic.

View File

@ -111,7 +111,6 @@ pub(crate) fn exc_info_outside_except_handler(checker: &Checker, call: &ExprCall
} }
let arguments = &call.arguments; let arguments = &call.arguments;
let source = checker.source();
let mut diagnostic = checker.report_diagnostic(ExcInfoOutsideExceptHandler, exc_info.range); let mut diagnostic = checker.report_diagnostic(ExcInfoOutsideExceptHandler, exc_info.range);
@ -120,8 +119,8 @@ pub(crate) fn exc_info_outside_except_handler(checker: &Checker, call: &ExprCall
exc_info, exc_info,
arguments, arguments,
Parentheses::Preserve, Parentheses::Preserve,
source, checker.source(),
checker.comment_ranges(), checker.tokens(),
)?; )?;
Ok(Fix::unsafe_edit(edit)) Ok(Fix::unsafe_edit(edit))
}); });

View File

@ -2,7 +2,7 @@ use itertools::Itertools;
use rustc_hash::{FxBuildHasher, FxHashSet}; use rustc_hash::{FxBuildHasher, FxHashSet};
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{self as ast, Expr}; use ruff_python_ast::{self as ast, Expr};
use ruff_python_stdlib::identifiers::is_identifier; use ruff_python_stdlib::identifiers::is_identifier;
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
@ -129,8 +129,8 @@ pub(crate) fn unnecessary_dict_kwargs(checker: &Checker, call: &ast::ExprCall) {
keyword, keyword,
&call.arguments, &call.arguments,
Parentheses::Preserve, Parentheses::Preserve,
checker.locator().contents(), checker.source(),
checker.comment_ranges(), checker.tokens(),
) )
.map(Fix::safe_edit) .map(Fix::safe_edit)
}); });
@ -158,8 +158,7 @@ pub(crate) fn unnecessary_dict_kwargs(checker: &Checker, call: &ast::ExprCall) {
parenthesized_range( parenthesized_range(
value.into(), value.into(),
dict.into(), dict.into(),
checker.comment_ranges(), checker.tokens()
checker.locator().contents(),
) )
.unwrap_or(value.range()) .unwrap_or(value.range())
) )

View File

@ -73,11 +73,11 @@ pub(crate) fn unnecessary_range_start(checker: &Checker, call: &ast::ExprCall) {
let mut diagnostic = checker.report_diagnostic(UnnecessaryRangeStart, start.range()); let mut diagnostic = checker.report_diagnostic(UnnecessaryRangeStart, start.range());
diagnostic.try_set_fix(|| { diagnostic.try_set_fix(|| {
remove_argument( remove_argument(
&start, start,
&call.arguments, &call.arguments,
Parentheses::Preserve, Parentheses::Preserve,
checker.locator().contents(), checker.source(),
checker.comment_ranges(), checker.tokens(),
) )
.map(Fix::safe_edit) .map(Fix::safe_edit)
}); });

View File

@ -160,20 +160,16 @@ fn generate_fix(
) -> anyhow::Result<Fix> { ) -> anyhow::Result<Fix> {
let locator = checker.locator(); let locator = checker.locator();
let source = locator.contents(); let source = locator.contents();
let tokens = checker.tokens();
let deletion = remove_argument( let deletion = remove_argument(
generic_base, generic_base,
arguments, arguments,
Parentheses::Preserve, Parentheses::Preserve,
source, source,
checker.comment_ranges(), tokens,
)?; )?;
let insertion = add_argument( let insertion = add_argument(locator.slice(generic_base), arguments, tokens);
locator.slice(generic_base),
arguments,
checker.comment_ranges(),
source,
);
Ok(Fix::unsafe_edits(deletion, [insertion])) Ok(Fix::unsafe_edits(deletion, [insertion]))
} }

View File

@ -5,7 +5,7 @@ use ruff_python_ast::{
helpers::{pep_604_union, typing_optional}, helpers::{pep_604_union, typing_optional},
name::Name, name::Name,
operator_precedence::OperatorPrecedence, operator_precedence::OperatorPrecedence,
parenthesize::parenthesized_range, token::{Tokens, parenthesized_range},
}; };
use ruff_python_semantic::analyze::typing::{traverse_literal, traverse_union}; use ruff_python_semantic::analyze::typing::{traverse_literal, traverse_union};
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
@ -243,12 +243,8 @@ fn create_fix(
let union_expr = pep_604_union(&[new_literal_expr, none_expr]); let union_expr = pep_604_union(&[new_literal_expr, none_expr]);
// Check if we need parentheses to preserve operator precedence // Check if we need parentheses to preserve operator precedence
let content = if needs_parentheses_for_precedence( let content =
semantic, if needs_parentheses_for_precedence(semantic, literal_expr, checker.tokens()) {
literal_expr,
checker.comment_ranges(),
checker.source(),
) {
format!("({})", checker.generator().expr(&union_expr)) format!("({})", checker.generator().expr(&union_expr))
} else { } else {
checker.generator().expr(&union_expr) checker.generator().expr(&union_expr)
@ -278,8 +274,7 @@ enum UnionKind {
fn needs_parentheses_for_precedence( fn needs_parentheses_for_precedence(
semantic: &ruff_python_semantic::SemanticModel, semantic: &ruff_python_semantic::SemanticModel,
literal_expr: &Expr, literal_expr: &Expr,
comment_ranges: &ruff_python_trivia::CommentRanges, tokens: &Tokens,
source: &str,
) -> bool { ) -> bool {
// Get the parent expression to check if we're in a context that needs parentheses // Get the parent expression to check if we're in a context that needs parentheses
let Some(parent_expr) = semantic.current_expression_parent() else { let Some(parent_expr) = semantic.current_expression_parent() else {
@ -287,14 +282,7 @@ fn needs_parentheses_for_precedence(
}; };
// Check if the literal expression is already parenthesized // Check if the literal expression is already parenthesized
if parenthesized_range( if parenthesized_range(literal_expr.into(), parent_expr.into(), tokens).is_some() {
literal_expr.into(),
parent_expr.into(),
comment_ranges,
source,
)
.is_some()
{
return false; // Already parenthesized, don't add more return false; // Already parenthesized, don't add more
} }

View File

@ -10,7 +10,7 @@ use libcst_native::{
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::Truthiness; use ruff_python_ast::helpers::Truthiness;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::visitor::Visitor; use ruff_python_ast::visitor::Visitor;
use ruff_python_ast::{ use ruff_python_ast::{
self as ast, AnyNodeRef, Arguments, BoolOp, ExceptHandler, Expr, Keyword, Stmt, UnaryOp, self as ast, AnyNodeRef, Arguments, BoolOp, ExceptHandler, Expr, Keyword, Stmt, UnaryOp,
@ -303,8 +303,7 @@ pub(crate) fn unittest_assertion(
parenthesized_range( parenthesized_range(
expr.into(), expr.into(),
checker.semantic().current_statement().into(), checker.semantic().current_statement().into(),
checker.comment_ranges(), checker.tokens(),
checker.locator().contents(),
) )
.unwrap_or(expr.range()), .unwrap_or(expr.range()),
))); )));

View File

@ -768,8 +768,8 @@ fn check_fixture_decorator(checker: &Checker, func_name: &str, decorator: &Decor
keyword, keyword,
arguments, arguments,
edits::Parentheses::Preserve, edits::Parentheses::Preserve,
checker.locator().contents(), checker.source(),
checker.comment_ranges(), checker.tokens(),
) )
.map(Fix::unsafe_edit) .map(Fix::unsafe_edit)
}); });

View File

@ -2,10 +2,9 @@ use rustc_hash::{FxBuildHasher, FxHashMap};
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::comparable::ComparableExpr; use ruff_python_ast::comparable::ComparableExpr;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::{Tokens, parenthesized_range};
use ruff_python_ast::{self as ast, Expr, ExprCall, ExprContext, StringLiteralFlags}; use ruff_python_ast::{self as ast, Expr, ExprCall, ExprContext, StringLiteralFlags};
use ruff_python_codegen::Generator; use ruff_python_codegen::Generator;
use ruff_python_trivia::CommentRanges;
use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
use ruff_text_size::{Ranged, TextRange, TextSize}; use ruff_text_size::{Ranged, TextRange, TextSize};
@ -322,18 +321,8 @@ fn elts_to_csv(elts: &[Expr], generator: Generator, flags: StringLiteralFlags) -
/// ``` /// ```
/// ///
/// This method assumes that the first argument is a string. /// This method assumes that the first argument is a string.
fn get_parametrize_name_range( fn get_parametrize_name_range(call: &ExprCall, expr: &Expr, tokens: &Tokens) -> Option<TextRange> {
call: &ExprCall, parenthesized_range(expr.into(), (&call.arguments).into(), tokens)
expr: &Expr,
comment_ranges: &CommentRanges,
source: &str,
) -> Option<TextRange> {
parenthesized_range(
expr.into(),
(&call.arguments).into(),
comment_ranges,
source,
)
} }
/// PT006 /// PT006
@ -349,12 +338,7 @@ fn check_names(checker: &Checker, call: &ExprCall, expr: &Expr, argvalues: &Expr
if names.len() > 1 { if names.len() > 1 {
match names_type { match names_type {
types::ParametrizeNameType::Tuple => { types::ParametrizeNameType::Tuple => {
let name_range = get_parametrize_name_range( let name_range = get_parametrize_name_range(call, expr, checker.tokens())
call,
expr,
checker.comment_ranges(),
checker.locator().contents(),
)
.unwrap_or(expr.range()); .unwrap_or(expr.range());
let mut diagnostic = checker.report_diagnostic( let mut diagnostic = checker.report_diagnostic(
PytestParametrizeNamesWrongType { PytestParametrizeNamesWrongType {
@ -386,12 +370,7 @@ fn check_names(checker: &Checker, call: &ExprCall, expr: &Expr, argvalues: &Expr
))); )));
} }
types::ParametrizeNameType::List => { types::ParametrizeNameType::List => {
let name_range = get_parametrize_name_range( let name_range = get_parametrize_name_range(call, expr, checker.tokens())
call,
expr,
checker.comment_ranges(),
checker.locator().contents(),
)
.unwrap_or(expr.range()); .unwrap_or(expr.range());
let mut diagnostic = checker.report_diagnostic( let mut diagnostic = checker.report_diagnostic(
PytestParametrizeNamesWrongType { PytestParametrizeNamesWrongType {

View File

@ -10,7 +10,7 @@ use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::comparable::ComparableExpr; use ruff_python_ast::comparable::ComparableExpr;
use ruff_python_ast::helpers::{Truthiness, contains_effect}; use ruff_python_ast::helpers::{Truthiness, contains_effect};
use ruff_python_ast::name::Name; use ruff_python_ast::name::Name;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_codegen::Generator; use ruff_python_codegen::Generator;
use ruff_python_semantic::SemanticModel; use ruff_python_semantic::SemanticModel;
@ -800,12 +800,7 @@ fn is_short_circuit(
edit = Some(get_short_circuit_edit( edit = Some(get_short_circuit_edit(
value, value,
TextRange::new( TextRange::new(
parenthesized_range( parenthesized_range(furthest.into(), expr.into(), checker.tokens())
furthest.into(),
expr.into(),
checker.comment_ranges(),
checker.locator().contents(),
)
.unwrap_or(furthest.range()) .unwrap_or(furthest.range())
.start(), .start(),
expr.end(), expr.end(),
@ -828,12 +823,7 @@ fn is_short_circuit(
edit = Some(get_short_circuit_edit( edit = Some(get_short_circuit_edit(
next_value, next_value,
TextRange::new( TextRange::new(
parenthesized_range( parenthesized_range(furthest.into(), expr.into(), checker.tokens())
furthest.into(),
expr.into(),
checker.comment_ranges(),
checker.locator().contents(),
)
.unwrap_or(furthest.range()) .unwrap_or(furthest.range())
.start(), .start(),
expr.end(), expr.end(),

View File

@ -4,7 +4,7 @@ use ruff_text_size::{Ranged, TextRange};
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::{is_const_false, is_const_true}; use ruff_python_ast::helpers::{is_const_false, is_const_true};
use ruff_python_ast::name::Name; use ruff_python_ast::name::Name;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
use crate::{AlwaysFixableViolation, Edit, Fix, FixAvailability, Violation}; use crate::{AlwaysFixableViolation, Edit, Fix, FixAvailability, Violation};
@ -171,12 +171,7 @@ pub(crate) fn if_expr_with_true_false(
checker checker
.locator() .locator()
.slice( .slice(
parenthesized_range( parenthesized_range(test.into(), expr.into(), checker.tokens())
test.into(),
expr.into(),
checker.comment_ranges(),
checker.locator().contents(),
)
.unwrap_or(test.range()), .unwrap_or(test.range()),
) )
.to_string(), .to_string(),

View File

@ -4,10 +4,10 @@ use anyhow::Result;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::comparable::ComparableStmt; use ruff_python_ast::comparable::ComparableStmt;
use ruff_python_ast::parenthesize::parenthesized_range;
use ruff_python_ast::stmt_if::{IfElifBranch, if_elif_branches}; use ruff_python_ast::stmt_if::{IfElifBranch, if_elif_branches};
use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{self as ast, Expr}; use ruff_python_ast::{self as ast, Expr};
use ruff_python_trivia::{CommentRanges, SimpleTokenKind, SimpleTokenizer}; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
use ruff_source_file::LineRanges; use ruff_source_file::LineRanges;
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
@ -99,7 +99,7 @@ pub(crate) fn if_with_same_arms(checker: &Checker, stmt_if: &ast::StmtIf) {
&current_branch, &current_branch,
following_branch, following_branch,
checker.locator(), checker.locator(),
checker.comment_ranges(), checker.tokens(),
) )
}); });
} }
@ -111,7 +111,7 @@ fn merge_branches(
current_branch: &IfElifBranch, current_branch: &IfElifBranch,
following_branch: &IfElifBranch, following_branch: &IfElifBranch,
locator: &Locator, locator: &Locator,
comment_ranges: &CommentRanges, tokens: &ruff_python_ast::token::Tokens,
) -> Result<Fix> { ) -> Result<Fix> {
// Identify the colon (`:`) at the end of the current branch's test. // Identify the colon (`:`) at the end of the current branch's test.
let Some(current_branch_colon) = let Some(current_branch_colon) =
@ -127,12 +127,9 @@ fn merge_branches(
); );
// If the following test isn't parenthesized, consider parenthesizing it. // If the following test isn't parenthesized, consider parenthesizing it.
let following_branch_test = if let Some(range) = parenthesized_range( let following_branch_test = if let Some(range) =
following_branch.test.into(), parenthesized_range(following_branch.test.into(), stmt_if.into(), tokens)
stmt_if.into(), {
comment_ranges,
locator.contents(),
) {
Cow::Borrowed(locator.slice(range)) Cow::Borrowed(locator.slice(range))
} else if matches!( } else if matches!(
following_branch.test, following_branch.test,
@ -153,16 +150,11 @@ fn merge_branches(
// //
// For example, if the current test is `x if x else y`, we should parenthesize it to // For example, if the current test is `x if x else y`, we should parenthesize it to
// `(x if x else y) or ...`. // `(x if x else y) or ...`.
let parenthesize_edit = if matches!( let parenthesize_edit =
if matches!(
current_branch.test, current_branch.test,
Expr::Lambda(_) | Expr::Named(_) | Expr::If(_) Expr::Lambda(_) | Expr::Named(_) | Expr::If(_)
) && parenthesized_range( ) && parenthesized_range(current_branch.test.into(), stmt_if.into(), tokens).is_none()
current_branch.test.into(),
stmt_if.into(),
comment_ranges,
locator.contents(),
)
.is_none()
{ {
Some(Edit::range_replacement( Some(Edit::range_replacement(
format!("({})", locator.slice(current_branch.test)), format!("({})", locator.slice(current_branch.test)),

View File

@ -1,6 +1,6 @@
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::AnyNodeRef; use ruff_python_ast::AnyNodeRef;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{self as ast, Arguments, CmpOp, Comprehension, Expr}; use ruff_python_ast::{self as ast, Arguments, CmpOp, Comprehension, Expr};
use ruff_python_semantic::analyze::typing; use ruff_python_semantic::analyze::typing;
use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
@ -90,20 +90,10 @@ fn key_in_dict(checker: &Checker, left: &Expr, right: &Expr, operator: CmpOp, pa
} }
// Extract the exact range of the left and right expressions. // Extract the exact range of the left and right expressions.
let left_range = parenthesized_range( let left_range =
left.into(), parenthesized_range(left.into(), parent, checker.tokens()).unwrap_or(left.range());
parent, let right_range =
checker.comment_ranges(), parenthesized_range(right.into(), parent, checker.tokens()).unwrap_or(right.range());
checker.locator().contents(),
)
.unwrap_or(left.range());
let right_range = parenthesized_range(
right.into(),
parent,
checker.comment_ranges(),
checker.locator().contents(),
)
.unwrap_or(right.range());
let mut diagnostic = checker.report_diagnostic( let mut diagnostic = checker.report_diagnostic(
InDictKeys { InDictKeys {

View File

@ -11,7 +11,7 @@ use crate::registry::Rule;
use crate::rules::flake8_type_checking::helpers::quote_type_expression; use crate::rules::flake8_type_checking::helpers::quote_type_expression;
use crate::{AlwaysFixableViolation, Edit, Fix, FixAvailability, Violation}; use crate::{AlwaysFixableViolation, Edit, Fix, FixAvailability, Violation};
use ruff_python_ast::PythonVersion; use ruff_python_ast::PythonVersion;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
/// ## What it does /// ## What it does
/// Checks if [PEP 613] explicit type aliases contain references to /// Checks if [PEP 613] explicit type aliases contain references to
@ -295,21 +295,20 @@ pub(crate) fn quoted_type_alias(
let range = annotation_expr.range(); let range = annotation_expr.range();
let mut diagnostic = checker.report_diagnostic(QuotedTypeAlias, range); let mut diagnostic = checker.report_diagnostic(QuotedTypeAlias, range);
let fix_string = annotation_expr.value.to_string(); let fix_string = annotation_expr.value.to_string();
let fix_string = if (fix_string.contains('\n') || fix_string.contains('\r')) let fix_string = if (fix_string.contains('\n') || fix_string.contains('\r'))
&& parenthesized_range( && parenthesized_range(
// Check for parenthesis outside string ("""...""") // Check for parentheses outside the string ("""...""")
annotation_expr.into(), annotation_expr.into(),
checker.semantic().current_statement().into(), checker.semantic().current_statement().into(),
checker.comment_ranges(), checker.source_tokens(),
checker.locator().contents(),
) )
.is_none() .is_none()
&& parenthesized_range( && parenthesized_range(
// Check for parenthesis inside string """(...)""" // Check for parentheses inside the string """(...)"""
expr.into(), expr.into(),
annotation_expr.into(), annotation_expr.into(),
checker.comment_ranges(), checker.tokens(),
checker.locator().contents(),
) )
.is_none() .is_none()
{ {

View File

@ -1,10 +1,9 @@
use std::ops::Range; use std::ops::Range;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{Expr, ExprBinOp, ExprCall, Operator}; use ruff_python_ast::{Expr, ExprBinOp, ExprCall, Operator};
use ruff_python_semantic::SemanticModel; use ruff_python_semantic::SemanticModel;
use ruff_python_trivia::CommentRanges;
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -89,11 +88,7 @@ pub(crate) fn path_constructor_current_directory(
let mut diagnostic = checker.report_diagnostic(PathConstructorCurrentDirectory, arg.range()); let mut diagnostic = checker.report_diagnostic(PathConstructorCurrentDirectory, arg.range());
match parent_and_next_path_fragment_range( match parent_and_next_path_fragment_range(checker.semantic(), checker.tokens()) {
checker.semantic(),
checker.comment_ranges(),
checker.source(),
) {
Some((parent_range, next_fragment_range)) => { Some((parent_range, next_fragment_range)) => {
let next_fragment_expr = checker.locator().slice(next_fragment_range); let next_fragment_expr = checker.locator().slice(next_fragment_range);
let call_expr = checker.locator().slice(call.range()); let call_expr = checker.locator().slice(call.range());
@ -116,7 +111,7 @@ pub(crate) fn path_constructor_current_directory(
arguments, arguments,
Parentheses::Preserve, Parentheses::Preserve,
checker.source(), checker.source(),
checker.comment_ranges(), checker.tokens(),
)?; )?;
Ok(Fix::applicable_edit(edit, applicability(call.range()))) Ok(Fix::applicable_edit(edit, applicability(call.range())))
}), }),
@ -125,8 +120,7 @@ pub(crate) fn path_constructor_current_directory(
fn parent_and_next_path_fragment_range( fn parent_and_next_path_fragment_range(
semantic: &SemanticModel, semantic: &SemanticModel,
comment_ranges: &CommentRanges, tokens: &ruff_python_ast::token::Tokens,
source: &str,
) -> Option<(TextRange, TextRange)> { ) -> Option<(TextRange, TextRange)> {
let parent = semantic.current_expression_parent()?; let parent = semantic.current_expression_parent()?;
@ -142,6 +136,6 @@ fn parent_and_next_path_fragment_range(
Some(( Some((
parent.range(), parent.range(),
parenthesized_range(right.into(), parent.into(), comment_ranges, source).unwrap_or(range), parenthesized_range(right.into(), parent.into(), tokens).unwrap_or(range),
)) ))
} }

View File

@ -1,8 +1,7 @@
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::is_const_true; use ruff_python_ast::helpers::is_const_true;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::{Tokens, parenthesized_range};
use ruff_python_ast::{self as ast, Keyword, Stmt}; use ruff_python_ast::{self as ast, Keyword, Stmt};
use ruff_python_trivia::CommentRanges;
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
use crate::Locator; use crate::Locator;
@ -91,7 +90,7 @@ pub(crate) fn inplace_argument(checker: &Checker, call: &ast::ExprCall) {
call, call,
keyword, keyword,
statement, statement,
checker.comment_ranges(), checker.tokens(),
checker.locator(), checker.locator(),
) { ) {
diagnostic.set_fix(fix); diagnostic.set_fix(fix);
@ -111,19 +110,14 @@ fn convert_inplace_argument_to_assignment(
call: &ast::ExprCall, call: &ast::ExprCall,
keyword: &Keyword, keyword: &Keyword,
statement: &Stmt, statement: &Stmt,
comment_ranges: &CommentRanges, tokens: &Tokens,
locator: &Locator, locator: &Locator,
) -> Option<Fix> { ) -> Option<Fix> {
// Add the assignment. // Add the assignment.
let attr = call.func.as_attribute_expr()?; let attr = call.func.as_attribute_expr()?;
let insert_assignment = Edit::insertion( let insert_assignment = Edit::insertion(
format!("{name} = ", name = locator.slice(attr.value.range())), format!("{name} = ", name = locator.slice(attr.value.range())),
parenthesized_range( parenthesized_range(call.into(), statement.into(), tokens)
call.into(),
statement.into(),
comment_ranges,
locator.contents(),
)
.unwrap_or(call.range()) .unwrap_or(call.range())
.start(), .start(),
); );
@ -134,7 +128,7 @@ fn convert_inplace_argument_to_assignment(
&call.arguments, &call.arguments,
Parentheses::Preserve, Parentheses::Preserve,
locator.contents(), locator.contents(),
comment_ranges, tokens,
) )
.ok()?; .ok()?;

View File

@ -1,5 +1,5 @@
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{ use ruff_python_ast::{
self as ast, Expr, ExprEllipsisLiteral, ExprLambda, Identifier, Parameter, self as ast, Expr, ExprEllipsisLiteral, ExprLambda, Identifier, Parameter,
ParameterWithDefault, Parameters, Stmt, ParameterWithDefault, Parameters, Stmt,
@ -265,25 +265,15 @@ fn replace_trailing_ellipsis_with_original_expr(
stmt: &Stmt, stmt: &Stmt,
checker: &Checker, checker: &Checker,
) -> String { ) -> String {
let original_expr_range = parenthesized_range( let original_expr_range =
(&lambda.body).into(), parenthesized_range((&lambda.body).into(), lambda.into(), checker.tokens())
lambda.into(),
checker.comment_ranges(),
checker.source(),
)
.unwrap_or(lambda.body.range()); .unwrap_or(lambda.body.range());
// This prevents the autofix of introducing a syntax error if the lambda's body is an // This prevents the autofix of introducing a syntax error if the lambda's body is an
// expression spanned across multiple lines. To avoid the syntax error we preserve // expression spanned across multiple lines. To avoid the syntax error we preserve
// the parenthesis around the body. // the parenthesis around the body.
let original_expr_in_source = if parenthesized_range( let original_expr_in_source =
lambda.into(), if parenthesized_range(lambda.into(), stmt.into(), checker.tokens()).is_some() {
stmt.into(),
checker.comment_ranges(),
checker.source(),
)
.is_some()
{
format!("({})", checker.locator().slice(original_expr_range)) format!("({})", checker.locator().slice(original_expr_range))
} else { } else {
checker.locator().slice(original_expr_range).to_string() checker.locator().slice(original_expr_range).to_string()

View File

@ -1,4 +1,4 @@
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::{Tokens, parenthesized_range};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
@ -179,14 +179,13 @@ fn is_redundant_boolean_comparison(op: CmpOp, comparator: &Expr) -> Option<bool>
fn generate_redundant_comparison( fn generate_redundant_comparison(
compare: &ast::ExprCompare, compare: &ast::ExprCompare,
comment_ranges: &ruff_python_trivia::CommentRanges, tokens: &Tokens,
source: &str, source: &str,
comparator: &Expr, comparator: &Expr,
kind: bool, kind: bool,
needs_wrap: bool, needs_wrap: bool,
) -> String { ) -> String {
let comparator_range = let comparator_range = parenthesized_range(comparator.into(), compare.into(), tokens)
parenthesized_range(comparator.into(), compare.into(), comment_ranges, source)
.unwrap_or(comparator.range()); .unwrap_or(comparator.range());
let comparator_str = &source[comparator_range]; let comparator_str = &source[comparator_range];
@ -379,7 +378,7 @@ pub(crate) fn literal_comparisons(checker: &Checker, compare: &ast::ExprCompare)
.copied() .copied()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let comment_ranges = checker.comment_ranges(); let tokens = checker.tokens();
let source = checker.source(); let source = checker.source();
let content = match (&*compare.ops, &*compare.comparators) { let content = match (&*compare.ops, &*compare.comparators) {
@ -387,18 +386,13 @@ pub(crate) fn literal_comparisons(checker: &Checker, compare: &ast::ExprCompare)
if let Some(kind) = is_redundant_boolean_comparison(*op, &compare.left) { if let Some(kind) = is_redundant_boolean_comparison(*op, &compare.left) {
let needs_wrap = compare.left.range().start() != compare.range().start(); let needs_wrap = compare.left.range().start() != compare.range().start();
generate_redundant_comparison( generate_redundant_comparison(
compare, compare, tokens, source, comparator, kind, needs_wrap,
comment_ranges,
source,
comparator,
kind,
needs_wrap,
) )
} else if let Some(kind) = is_redundant_boolean_comparison(*op, comparator) { } else if let Some(kind) = is_redundant_boolean_comparison(*op, comparator) {
let needs_wrap = comparator.range().end() != compare.range().end(); let needs_wrap = comparator.range().end() != compare.range().end();
generate_redundant_comparison( generate_redundant_comparison(
compare, compare,
comment_ranges, tokens,
source, source,
&compare.left, &compare.left,
kind, kind,
@ -410,7 +404,7 @@ pub(crate) fn literal_comparisons(checker: &Checker, compare: &ast::ExprCompare)
&ops, &ops,
&compare.comparators, &compare.comparators,
compare.into(), compare.into(),
comment_ranges, tokens,
source, source,
) )
} }
@ -420,7 +414,7 @@ pub(crate) fn literal_comparisons(checker: &Checker, compare: &ast::ExprCompare)
&ops, &ops,
&compare.comparators, &compare.comparators,
compare.into(), compare.into(),
comment_ranges, tokens,
source, source,
), ),
}; };

View File

@ -107,7 +107,7 @@ pub(crate) fn not_tests(checker: &Checker, unary_op: &ast::ExprUnaryOp) {
&[CmpOp::NotIn], &[CmpOp::NotIn],
comparators, comparators,
unary_op.into(), unary_op.into(),
checker.comment_ranges(), checker.tokens(),
checker.source(), checker.source(),
), ),
unary_op.range(), unary_op.range(),
@ -127,7 +127,7 @@ pub(crate) fn not_tests(checker: &Checker, unary_op: &ast::ExprUnaryOp) {
&[CmpOp::IsNot], &[CmpOp::IsNot],
comparators, comparators,
unary_op.into(), unary_op.into(),
checker.comment_ranges(), checker.tokens(),
checker.source(), checker.source(),
), ),
unary_op.range(), unary_op.range(),

View File

@ -3,7 +3,7 @@ use std::collections::hash_map::Entry;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::comparable::{ComparableExpr, HashableExpr}; use ruff_python_ast::comparable::{ComparableExpr, HashableExpr};
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{self as ast, Expr}; use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
@ -193,16 +193,14 @@ pub(crate) fn repeated_keys(checker: &Checker, dict: &ast::ExprDict) {
parenthesized_range( parenthesized_range(
dict.value(i - 1).into(), dict.value(i - 1).into(),
dict.into(), dict.into(),
checker.comment_ranges(), checker.tokens(),
checker.locator().contents(),
) )
.unwrap_or_else(|| dict.value(i - 1).range()) .unwrap_or_else(|| dict.value(i - 1).range())
.end(), .end(),
parenthesized_range( parenthesized_range(
dict.value(i).into(), dict.value(i).into(),
dict.into(), dict.into(),
checker.comment_ranges(), checker.tokens(),
checker.locator().contents(),
) )
.unwrap_or_else(|| dict.value(i).range()) .unwrap_or_else(|| dict.value(i).range())
.end(), .end(),
@ -224,16 +222,14 @@ pub(crate) fn repeated_keys(checker: &Checker, dict: &ast::ExprDict) {
parenthesized_range( parenthesized_range(
dict.value(i - 1).into(), dict.value(i - 1).into(),
dict.into(), dict.into(),
checker.comment_ranges(), checker.tokens(),
checker.locator().contents(),
) )
.unwrap_or_else(|| dict.value(i - 1).range()) .unwrap_or_else(|| dict.value(i - 1).range())
.end(), .end(),
parenthesized_range( parenthesized_range(
dict.value(i).into(), dict.value(i).into(),
dict.into(), dict.into(),
checker.comment_ranges(), checker.tokens(),
checker.locator().contents(),
) )
.unwrap_or_else(|| dict.value(i).range()) .unwrap_or_else(|| dict.value(i).range())
.end(), .end(),

View File

@ -2,7 +2,7 @@ use itertools::Itertools;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::contains_effect; use ruff_python_ast::helpers::contains_effect;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::token::{TokenKind, Tokens}; use ruff_python_ast::token::{TokenKind, Tokens};
use ruff_python_ast::{self as ast, Stmt}; use ruff_python_ast::{self as ast, Stmt};
use ruff_python_semantic::Binding; use ruff_python_semantic::Binding;
@ -172,12 +172,8 @@ fn remove_unused_variable(binding: &Binding, checker: &Checker) -> Option<Fix> {
{ {
// If the expression is complex (`x = foo()`), remove the assignment, // If the expression is complex (`x = foo()`), remove the assignment,
// but preserve the right-hand side. // but preserve the right-hand side.
let start = parenthesized_range( let start =
target.into(), parenthesized_range(target.into(), statement.into(), checker.tokens())
statement.into(),
checker.comment_ranges(),
checker.locator().contents(),
)
.unwrap_or(target.range()) .unwrap_or(target.range())
.start(); .start();
let end = match_token_after(checker.tokens(), target.end(), |token| { let end = match_token_after(checker.tokens(), target.end(), |token| {

View File

@ -2,7 +2,7 @@ use itertools::Itertools;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{ use ruff_python_ast::{
BoolOp, CmpOp, Expr, ExprBoolOp, ExprCompare, BoolOp, CmpOp, Expr, ExprBoolOp, ExprCompare,
parenthesize::{parentheses_iterator, parenthesized_range}, token::{parentheses_iterator, parenthesized_range},
}; };
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
@ -62,7 +62,7 @@ pub(crate) fn boolean_chained_comparison(checker: &Checker, expr_bool_op: &ExprB
} }
let locator = checker.locator(); let locator = checker.locator();
let comment_ranges = checker.comment_ranges(); let tokens = checker.tokens();
// retrieve all compare expressions from boolean expression // retrieve all compare expressions from boolean expression
let compare_expressions = expr_bool_op let compare_expressions = expr_bool_op
@ -89,39 +89,21 @@ pub(crate) fn boolean_chained_comparison(checker: &Checker, expr_bool_op: &ExprB
continue; continue;
} }
let left_paren_count = parentheses_iterator( let left_paren_count =
left_compare.into(), parentheses_iterator(left_compare.into(), Some(expr_bool_op.into()), tokens).count();
Some(expr_bool_op.into()),
comment_ranges,
locator.contents(),
)
.count();
let right_paren_count = parentheses_iterator( let right_paren_count =
right_compare.into(), parentheses_iterator(right_compare.into(), Some(expr_bool_op.into()), tokens).count();
Some(expr_bool_op.into()),
comment_ranges,
locator.contents(),
)
.count();
// Create the edit that removes the comparison operator // Create the edit that removes the comparison operator
// In `a<(b) and ((b))<c`, we need to handle the // In `a<(b) and ((b))<c`, we need to handle the
// parentheses when specifying the fix range. // parentheses when specifying the fix range.
let left_compare_right_range = parenthesized_range( let left_compare_right_range =
left_compare_right.into(), parenthesized_range(left_compare_right.into(), left_compare.into(), tokens)
left_compare.into(),
comment_ranges,
locator.contents(),
)
.unwrap_or(left_compare_right.range()); .unwrap_or(left_compare_right.range());
let right_compare_left_range = parenthesized_range( let right_compare_left_range =
right_compare_left.into(), parenthesized_range(right_compare_left.into(), right_compare.into(), tokens)
right_compare.into(),
comment_ranges,
locator.contents(),
)
.unwrap_or(right_compare_left.range()); .unwrap_or(right_compare_left.range());
let edit = Edit::range_replacement( let edit = Edit::range_replacement(
locator.slice(left_compare_right_range).to_string(), locator.slice(left_compare_right_range).to_string(),

View File

@ -99,7 +99,7 @@ pub(crate) fn duplicate_bases(checker: &Checker, name: &str, arguments: Option<&
arguments, arguments,
Parentheses::Remove, Parentheses::Remove,
checker.locator().contents(), checker.locator().contents(),
checker.comment_ranges(), checker.tokens(),
) )
.map(|edit| { .map(|edit| {
Fix::applicable_edit( Fix::applicable_edit(

View File

@ -1,6 +1,6 @@
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::comparable::ComparableExpr; use ruff_python_ast::comparable::ComparableExpr;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{self as ast, CmpOp, Stmt}; use ruff_python_ast::{self as ast, CmpOp, Stmt};
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
@ -166,12 +166,7 @@ pub(crate) fn if_stmt_min_max(checker: &Checker, stmt_if: &ast::StmtIf) {
let replacement = format!( let replacement = format!(
"{} = {min_max}({}, {})", "{} = {min_max}({}, {})",
checker.locator().slice( checker.locator().slice(
parenthesized_range( parenthesized_range(body_target.into(), body.into(), checker.tokens())
body_target.into(),
body.into(),
checker.comment_ranges(),
checker.locator().contents()
)
.unwrap_or(body_target.range()) .unwrap_or(body_target.range())
), ),
checker.locator().slice(arg1), checker.locator().slice(arg1),

View File

@ -174,12 +174,8 @@ pub(crate) fn missing_maxsplit_arg(checker: &Checker, value: &Expr, slice: &Expr
SliceBoundary::Last => "rsplit", SliceBoundary::Last => "rsplit",
}; };
let maxsplit_argument_edit = fix::edits::add_argument( let maxsplit_argument_edit =
"maxsplit=1", fix::edits::add_argument("maxsplit=1", arguments, checker.tokens());
arguments,
checker.comment_ranges(),
checker.locator().contents(),
);
// Only change `actual_split_type` if it doesn't match `suggested_split_type` // Only change `actual_split_type` if it doesn't match `suggested_split_type`
let split_type_edit: Option<Edit> = if actual_split_type == suggested_split_type { let split_type_edit: Option<Edit> = if actual_split_type == suggested_split_type {

View File

@ -2,7 +2,7 @@ use ast::Expr;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast; use ruff_python_ast as ast;
use ruff_python_ast::comparable::ComparableExpr; use ruff_python_ast::comparable::ComparableExpr;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{ExprBinOp, ExprRef, Operator}; use ruff_python_ast::{ExprBinOp, ExprRef, Operator};
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
@ -150,12 +150,10 @@ fn augmented_assignment(
let right_operand_ref = ExprRef::from(right_operand); let right_operand_ref = ExprRef::from(right_operand);
let parent = original_expr.into(); let parent = original_expr.into();
let comment_ranges = checker.comment_ranges(); let tokens = checker.tokens();
let source = checker.source();
let right_operand_range = let right_operand_range =
parenthesized_range(right_operand_ref, parent, comment_ranges, source) parenthesized_range(right_operand_ref, parent, tokens).unwrap_or(right_operand.range());
.unwrap_or(right_operand.range());
let right_operand_expr = locator.slice(right_operand_range); let right_operand_expr = locator.slice(right_operand_range);
let target_expr = locator.slice(target); let target_expr = locator.slice(target);

View File

@ -75,12 +75,7 @@ pub(crate) fn subprocess_run_without_check(checker: &Checker, call: &ast::ExprCa
let mut diagnostic = let mut diagnostic =
checker.report_diagnostic(SubprocessRunWithoutCheck, call.func.range()); checker.report_diagnostic(SubprocessRunWithoutCheck, call.func.range());
diagnostic.set_fix(Fix::applicable_edit( diagnostic.set_fix(Fix::applicable_edit(
add_argument( add_argument("check=False", &call.arguments, checker.tokens()),
"check=False",
&call.arguments,
checker.comment_ranges(),
checker.locator().contents(),
),
// If the function call contains `**kwargs`, mark the fix as unsafe. // If the function call contains `**kwargs`, mark the fix as unsafe.
if call if call
.arguments .arguments

View File

@ -1,8 +1,7 @@
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::name::QualifiedName; use ruff_python_ast::{self as ast, Expr, name::QualifiedName};
use ruff_python_ast::{self as ast, Expr};
use ruff_python_semantic::SemanticModel; use ruff_python_semantic::SemanticModel;
use ruff_python_semantic::analyze::typing; use ruff_python_semantic::analyze::typing;
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
@ -193,8 +192,7 @@ fn generate_keyword_fix(checker: &Checker, call: &ast::ExprCall) -> Fix {
})) }))
), ),
&call.arguments, &call.arguments,
checker.comment_ranges(), checker.tokens(),
checker.locator().contents(),
)) ))
} }

View File

@ -204,7 +204,7 @@ pub(crate) fn non_pep695_generic_class(checker: &Checker, class_def: &StmtClassD
arguments, arguments,
Parentheses::Remove, Parentheses::Remove,
checker.source(), checker.source(),
checker.comment_ranges(), checker.tokens(),
)?; )?;
Ok(Fix::unsafe_edits( Ok(Fix::unsafe_edits(
Edit::insertion(type_params.to_string(), name.end()), Edit::insertion(type_params.to_string(), name.end()),

View File

@ -2,7 +2,7 @@ use itertools::Itertools;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::name::Name; use ruff_python_ast::name::Name;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::visitor::Visitor; use ruff_python_ast::visitor::Visitor;
use ruff_python_ast::{Expr, ExprCall, ExprName, Keyword, StmtAnnAssign, StmtAssign, StmtRef}; use ruff_python_ast::{Expr, ExprCall, ExprName, Keyword, StmtAnnAssign, StmtAssign, StmtRef};
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
@ -261,11 +261,11 @@ fn create_diagnostic(
type_alias_kind: TypeAliasKind, type_alias_kind: TypeAliasKind,
) { ) {
let source = checker.source(); let source = checker.source();
let tokens = checker.tokens();
let comment_ranges = checker.comment_ranges(); let comment_ranges = checker.comment_ranges();
let range_with_parentheses = let range_with_parentheses =
parenthesized_range(value.into(), stmt.into(), comment_ranges, source) parenthesized_range(value.into(), stmt.into(), tokens).unwrap_or(value.range());
.unwrap_or(value.range());
let content = format!( let content = format!(
"type {name}{type_params} = {value}", "type {name}{type_params} = {value}",

View File

@ -1,9 +1,8 @@
use anyhow::Result; use anyhow::Result;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Keyword}; use ruff_python_ast::{self as ast, Keyword, token::Tokens};
use ruff_python_semantic::Modules; use ruff_python_semantic::Modules;
use ruff_python_trivia::CommentRanges;
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -104,7 +103,7 @@ pub(crate) fn replace_stdout_stderr(checker: &Checker, call: &ast::ExprCall) {
stderr, stderr,
call, call,
checker.locator().contents(), checker.locator().contents(),
checker.comment_ranges(), checker.tokens(),
) )
}); });
} }
@ -117,7 +116,7 @@ fn generate_fix(
stderr: &Keyword, stderr: &Keyword,
call: &ast::ExprCall, call: &ast::ExprCall,
source: &str, source: &str,
comment_ranges: &CommentRanges, tokens: &Tokens,
) -> Result<Fix> { ) -> Result<Fix> {
let (first, second) = if stdout.start() < stderr.start() { let (first, second) = if stdout.start() < stderr.start() {
(stdout, stderr) (stdout, stderr)
@ -132,7 +131,7 @@ fn generate_fix(
&call.arguments, &call.arguments,
Parentheses::Preserve, Parentheses::Preserve,
source, source,
comment_ranges, tokens,
)?], )?],
)) ))
} }

View File

@ -78,7 +78,7 @@ pub(crate) fn replace_universal_newlines(checker: &Checker, call: &ast::ExprCall
&call.arguments, &call.arguments,
Parentheses::Preserve, Parentheses::Preserve,
checker.locator().contents(), checker.locator().contents(),
checker.comment_ranges(), checker.tokens(),
) )
.map(Fix::safe_edit) .map(Fix::safe_edit)
}); });

View File

@ -188,7 +188,7 @@ pub(crate) fn unnecessary_encode_utf8(checker: &Checker, call: &ast::ExprCall) {
&call.arguments, &call.arguments,
Parentheses::Preserve, Parentheses::Preserve,
checker.locator().contents(), checker.locator().contents(),
checker.comment_ranges(), checker.tokens(),
) )
.map(Fix::safe_edit) .map(Fix::safe_edit)
}); });
@ -206,7 +206,7 @@ pub(crate) fn unnecessary_encode_utf8(checker: &Checker, call: &ast::ExprCall) {
&call.arguments, &call.arguments,
Parentheses::Preserve, Parentheses::Preserve,
checker.locator().contents(), checker.locator().contents(),
checker.comment_ranges(), checker.tokens(),
) )
.map(Fix::safe_edit) .map(Fix::safe_edit)
}); });
@ -231,7 +231,7 @@ pub(crate) fn unnecessary_encode_utf8(checker: &Checker, call: &ast::ExprCall) {
&call.arguments, &call.arguments,
Parentheses::Preserve, Parentheses::Preserve,
checker.locator().contents(), checker.locator().contents(),
checker.comment_ranges(), checker.tokens(),
) )
.map(Fix::safe_edit) .map(Fix::safe_edit)
}); });
@ -249,7 +249,7 @@ pub(crate) fn unnecessary_encode_utf8(checker: &Checker, call: &ast::ExprCall) {
&call.arguments, &call.arguments,
Parentheses::Preserve, Parentheses::Preserve,
checker.locator().contents(), checker.locator().contents(),
checker.comment_ranges(), checker.tokens(),
) )
.map(Fix::safe_edit) .map(Fix::safe_edit)
}); });

View File

@ -70,7 +70,7 @@ pub(crate) fn useless_class_metaclass_type(checker: &Checker, class_def: &StmtCl
arguments, arguments,
Parentheses::Remove, Parentheses::Remove,
checker.locator().contents(), checker.locator().contents(),
checker.comment_ranges(), checker.tokens(),
)?; )?;
let range = edit.range(); let range = edit.range();

View File

@ -73,7 +73,7 @@ pub(crate) fn useless_object_inheritance(checker: &Checker, class_def: &ast::Stm
arguments, arguments,
Parentheses::Remove, Parentheses::Remove,
checker.locator().contents(), checker.locator().contents(),
checker.comment_ranges(), checker.tokens(),
)?; )?;
let range = edit.range(); let range = edit.range();

View File

@ -1,5 +1,5 @@
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{self as ast, Expr, Stmt}; use ruff_python_ast::{self as ast, Expr, Stmt};
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
@ -139,12 +139,7 @@ pub(crate) fn yield_in_for_loop(checker: &Checker, stmt_for: &ast::StmtFor) {
let mut diagnostic = checker.report_diagnostic(YieldInForLoop, stmt_for.range()); let mut diagnostic = checker.report_diagnostic(YieldInForLoop, stmt_for.range());
let contents = checker.locator().slice( let contents = checker.locator().slice(
parenthesized_range( parenthesized_range(iter.as_ref().into(), stmt_for.into(), checker.tokens())
iter.as_ref().into(),
stmt_for.into(),
checker.comment_ranges(),
checker.locator().contents(),
)
.unwrap_or(iter.range()), .unwrap_or(iter.range()),
); );
let contents = if iter.as_tuple_expr().is_some_and(|it| !it.parenthesized) { let contents = if iter.as_tuple_expr().is_some_and(|it| !it.parenthesized) {

View File

@ -1,7 +1,7 @@
use std::borrow::Cow; use std::borrow::Cow;
use ruff_python_ast::PythonVersion; use ruff_python_ast::PythonVersion;
use ruff_python_ast::{self as ast, Expr, name::Name, parenthesize::parenthesized_range}; use ruff_python_ast::{self as ast, Expr, name::Name, token::parenthesized_range};
use ruff_python_codegen::Generator; use ruff_python_codegen::Generator;
use ruff_python_semantic::{BindingId, ResolvedReference, SemanticModel}; use ruff_python_semantic::{BindingId, ResolvedReference, SemanticModel};
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
@ -330,12 +330,8 @@ pub(super) fn parenthesize_loop_iter_if_necessary<'a>(
let locator = checker.locator(); let locator = checker.locator();
let iter = for_stmt.iter.as_ref(); let iter = for_stmt.iter.as_ref();
let original_parenthesized_range = parenthesized_range( let original_parenthesized_range =
iter.into(), parenthesized_range(iter.into(), for_stmt.into(), checker.tokens());
for_stmt.into(),
checker.comment_ranges(),
checker.source(),
);
if let Some(range) = original_parenthesized_range { if let Some(range) = original_parenthesized_range {
return Cow::Borrowed(locator.slice(range)); return Cow::Borrowed(locator.slice(range));

View File

@ -1,5 +1,5 @@
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{ use ruff_python_ast::{
Expr, ExprAttribute, ExprBinOp, ExprCall, ExprStringLiteral, ExprSubscript, ExprUnaryOp, Expr, ExprAttribute, ExprBinOp, ExprCall, ExprStringLiteral, ExprSubscript, ExprUnaryOp,
Number, Operator, PythonVersion, UnaryOp, Number, Operator, PythonVersion, UnaryOp,
@ -112,8 +112,7 @@ pub(crate) fn fromisoformat_replace_z(checker: &Checker, call: &ExprCall) {
let value_full_range = parenthesized_range( let value_full_range = parenthesized_range(
replace_time_zone.date.into(), replace_time_zone.date.into(),
replace_time_zone.parent.into(), replace_time_zone.parent.into(),
checker.comment_ranges(), checker.tokens(),
checker.source(),
) )
.unwrap_or(replace_time_zone.date.range()); .unwrap_or(replace_time_zone.date.range());

View File

@ -5,8 +5,7 @@ use ruff_python_ast as ast;
use ruff_python_ast::Expr; use ruff_python_ast::Expr;
use ruff_python_ast::comparable::ComparableExpr; use ruff_python_ast::comparable::ComparableExpr;
use ruff_python_ast::helpers::contains_effect; use ruff_python_ast::helpers::contains_effect;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::{Tokens, parenthesized_range};
use ruff_python_trivia::CommentRanges;
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
use crate::Locator; use crate::Locator;
@ -76,8 +75,8 @@ pub(crate) fn if_exp_instead_of_or_operator(checker: &Checker, if_expr: &ast::Ex
Edit::range_replacement( Edit::range_replacement(
format!( format!(
"{} or {}", "{} or {}",
parenthesize_test(test, if_expr, checker.comment_ranges(), checker.locator()), parenthesize_test(test, if_expr, checker.tokens(), checker.locator()),
parenthesize_test(orelse, if_expr, checker.comment_ranges(), checker.locator()), parenthesize_test(orelse, if_expr, checker.tokens(), checker.locator()),
), ),
if_expr.range(), if_expr.range(),
), ),
@ -99,15 +98,10 @@ pub(crate) fn if_exp_instead_of_or_operator(checker: &Checker, if_expr: &ast::Ex
fn parenthesize_test<'a>( fn parenthesize_test<'a>(
expr: &Expr, expr: &Expr,
if_expr: &ast::ExprIf, if_expr: &ast::ExprIf,
comment_ranges: &CommentRanges, tokens: &Tokens,
locator: &Locator<'a>, locator: &Locator<'a>,
) -> Cow<'a, str> { ) -> Cow<'a, str> {
if let Some(range) = parenthesized_range( if let Some(range) = parenthesized_range(expr.into(), if_expr.into(), tokens) {
expr.into(),
if_expr.into(),
comment_ranges,
locator.contents(),
) {
Cow::Borrowed(locator.slice(range)) Cow::Borrowed(locator.slice(range))
} else if matches!(expr, Expr::If(_) | Expr::Lambda(_) | Expr::Named(_)) { } else if matches!(expr, Expr::If(_) | Expr::Lambda(_) | Expr::Named(_)) {
Cow::Owned(format!("({})", locator.slice(expr.range()))) Cow::Owned(format!("({})", locator.slice(expr.range())))

View File

@ -1,6 +1,6 @@
use ruff_diagnostics::Applicability; use ruff_diagnostics::Applicability;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{Comprehension, Expr, StmtFor}; use ruff_python_ast::{Comprehension, Expr, StmtFor};
use ruff_python_semantic::analyze::typing; use ruff_python_semantic::analyze::typing;
use ruff_python_semantic::analyze::typing::is_io_base_expr; use ruff_python_semantic::analyze::typing::is_io_base_expr;
@ -104,8 +104,7 @@ fn readlines_in_iter(checker: &Checker, iter_expr: &Expr) {
let deletion_range = if let Some(parenthesized_range) = parenthesized_range( let deletion_range = if let Some(parenthesized_range) = parenthesized_range(
expr_attr.value.as_ref().into(), expr_attr.value.as_ref().into(),
expr_attr.into(), expr_attr.into(),
checker.comment_ranges(), checker.tokens(),
checker.source(),
) { ) {
expr_call.range().add_start(parenthesized_range.len()) expr_call.range().add_start(parenthesized_range.len())
} else { } else {

View File

@ -1,7 +1,7 @@
use anyhow::Result; use anyhow::Result;
use ruff_diagnostics::Applicability; use ruff_diagnostics::Applicability;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{self as ast, Expr, Number}; use ruff_python_ast::{self as ast, Expr, Number};
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
@ -152,13 +152,8 @@ fn generate_fix(checker: &Checker, call: &ast::ExprCall, base: Base, arg: &Expr)
checker.semantic(), checker.semantic(),
)?; )?;
let arg_range = parenthesized_range( let arg_range =
arg.into(), parenthesized_range(arg.into(), call.into(), checker.tokens()).unwrap_or(arg.range());
call.into(),
checker.comment_ranges(),
checker.source(),
)
.unwrap_or(arg.range());
let arg_str = checker.locator().slice(arg_range); let arg_str = checker.locator().slice(arg_range);
Ok(Fix::applicable_edits( Ok(Fix::applicable_edits(

View File

@ -95,7 +95,7 @@ pub(crate) fn single_item_membership_test(
&[membership_test.replacement_op()], &[membership_test.replacement_op()],
std::slice::from_ref(item), std::slice::from_ref(item),
expr.into(), expr.into(),
checker.comment_ranges(), checker.tokens(),
checker.source(), checker.source(),
), ),
expr.range(), expr.range(),

View File

@ -163,7 +163,7 @@ fn convert_type_vars(
class_arguments, class_arguments,
Parentheses::Remove, Parentheses::Remove,
source, source,
checker.comment_ranges(), checker.tokens(),
)?; )?;
let replace_type_params = let replace_type_params =
Edit::range_replacement(new_type_params.to_string(), type_params.range); Edit::range_replacement(new_type_params.to_string(), type_params.range);

View File

@ -3,8 +3,8 @@ use anyhow::Result;
use ast::Keyword; use ast::Keyword;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::is_constant; use ruff_python_ast::helpers::is_constant;
use ruff_python_ast::token::Tokens;
use ruff_python_ast::{self as ast, Expr}; use ruff_python_ast::{self as ast, Expr};
use ruff_python_trivia::CommentRanges;
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
use crate::Locator; use crate::Locator;
@ -108,9 +108,8 @@ pub(crate) fn default_factory_kwarg(checker: &Checker, call: &ast::ExprCall) {
}, },
call.range(), call.range(),
); );
diagnostic.try_set_fix(|| { diagnostic
convert_to_positional(call, keyword, checker.locator(), checker.comment_ranges()) .try_set_fix(|| convert_to_positional(call, keyword, checker.locator(), checker.tokens()));
});
} }
/// Returns `true` if a value is definitively not callable (e.g., `1` or `[]`). /// Returns `true` if a value is definitively not callable (e.g., `1` or `[]`).
@ -136,7 +135,7 @@ fn convert_to_positional(
call: &ast::ExprCall, call: &ast::ExprCall,
default_factory: &Keyword, default_factory: &Keyword,
locator: &Locator, locator: &Locator,
comment_ranges: &CommentRanges, tokens: &Tokens,
) -> Result<Fix> { ) -> Result<Fix> {
if call.arguments.len() == 1 { if call.arguments.len() == 1 {
// Ex) `defaultdict(default_factory=list)` // Ex) `defaultdict(default_factory=list)`
@ -153,7 +152,7 @@ fn convert_to_positional(
&call.arguments, &call.arguments,
Parentheses::Preserve, Parentheses::Preserve,
locator.contents(), locator.contents(),
comment_ranges, tokens,
)?; )?;
// Second, insert the value as the first positional argument. // Second, insert the value as the first positional argument.

View File

@ -128,7 +128,7 @@ pub(crate) fn falsy_dict_get_fallback(checker: &Checker, expr: &Expr) {
&call.arguments, &call.arguments,
Parentheses::Preserve, Parentheses::Preserve,
checker.locator().contents(), checker.locator().contents(),
checker.comment_ranges(), checker.tokens(),
) )
.map(|edit| Fix::applicable_edit(edit, applicability)) .map(|edit| Fix::applicable_edit(edit, applicability))
}); });

View File

@ -1,6 +1,6 @@
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast; use ruff_python_ast as ast;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -77,14 +77,7 @@ pub(crate) fn parenthesize_chained_logical_operators(checker: &Checker, expr: &a
) => { ) => {
let locator = checker.locator(); let locator = checker.locator();
let source_range = bool_op.range(); let source_range = bool_op.range();
if parenthesized_range( if parenthesized_range(bool_op.into(), expr.into(), checker.tokens()).is_none() {
bool_op.into(),
expr.into(),
checker.comment_ranges(),
locator.contents(),
)
.is_none()
{
let new_source = format!("({})", locator.slice(source_range)); let new_source = format!("({})", locator.slice(source_range));
let edit = Edit::range_replacement(new_source, source_range); let edit = Edit::range_replacement(new_source, source_range);
checker checker

View File

@ -2,7 +2,7 @@ use anyhow::Context;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast; use ruff_python_ast as ast;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_semantic::{Scope, ScopeKind}; use ruff_python_semantic::{Scope, ScopeKind};
use ruff_python_trivia::{indentation_at_offset, textwrap}; use ruff_python_trivia::{indentation_at_offset, textwrap};
use ruff_source_file::LineRanges; use ruff_source_file::LineRanges;
@ -159,8 +159,7 @@ fn use_initvar(
let default_loc = parenthesized_range( let default_loc = parenthesized_range(
default.into(), default.into(),
parameter_with_default.into(), parameter_with_default.into(),
checker.comment_ranges(), checker.tokens(),
checker.source(),
) )
.unwrap_or(default.range()); .unwrap_or(default.range());

View File

@ -2,7 +2,7 @@ use anyhow::Result;
use itertools::Itertools; use itertools::Itertools;
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{self as ast, Arguments, Expr}; use ruff_python_ast::{self as ast, Arguments, Expr};
use ruff_python_semantic::SemanticModel; use ruff_python_semantic::SemanticModel;
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
@ -116,12 +116,7 @@ fn convert_to_reduce(iterable: &Expr, call: &ast::ExprCall, checker: &Checker) -
)?; )?;
let iterable = checker.locator().slice( let iterable = checker.locator().slice(
parenthesized_range( parenthesized_range(iterable.into(), (&call.arguments).into(), checker.tokens())
iterable.into(),
(&call.arguments).into(),
checker.comment_ranges(),
checker.locator().contents(),
)
.unwrap_or(iterable.range()), .unwrap_or(iterable.range()),
); );

View File

@ -1,7 +1,7 @@
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::PythonVersion; use ruff_python_ast::PythonVersion;
use ruff_python_ast::token::TokenKind; use ruff_python_ast::token::TokenKind;
use ruff_python_ast::{Expr, ExprCall, parenthesize::parenthesized_range}; use ruff_python_ast::{Expr, ExprCall, token::parenthesized_range};
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -124,13 +124,8 @@ fn replace_with_map(starmap: &ExprCall, zip: &ExprCall, checker: &Checker) -> Op
let mut remove_zip = vec![]; let mut remove_zip = vec![];
let full_zip_range = parenthesized_range( let full_zip_range =
zip.into(), parenthesized_range(zip.into(), starmap.into(), checker.tokens()).unwrap_or(zip.range());
starmap.into(),
checker.comment_ranges(),
checker.source(),
)
.unwrap_or(zip.range());
// Delete any parentheses around the `zip` call to prevent that the argument turns into a tuple. // Delete any parentheses around the `zip` call to prevent that the argument turns into a tuple.
remove_zip.push(Edit::range_deletion(TextRange::new( remove_zip.push(Edit::range_deletion(TextRange::new(
@ -138,12 +133,7 @@ fn replace_with_map(starmap: &ExprCall, zip: &ExprCall, checker: &Checker) -> Op
zip.start(), zip.start(),
))); )));
let full_zip_func_range = parenthesized_range( let full_zip_func_range = parenthesized_range((&zip.func).into(), zip.into(), checker.tokens())
(&zip.func).into(),
zip.into(),
checker.comment_ranges(),
checker.source(),
)
.unwrap_or(zip.func.range()); .unwrap_or(zip.func.range());
// Delete the `zip` callee // Delete the `zip` callee

View File

@ -1,5 +1,5 @@
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::{Tokens, parenthesized_range};
use ruff_python_ast::{Arguments, Expr, ExprCall}; use ruff_python_ast::{Arguments, Expr, ExprCall};
use ruff_python_semantic::SemanticModel; use ruff_python_semantic::SemanticModel;
use ruff_python_semantic::analyze::type_inference::{NumberLike, PythonType, ResolvedPythonType}; use ruff_python_semantic::analyze::type_inference::{NumberLike, PythonType, ResolvedPythonType};
@ -86,6 +86,7 @@ pub(crate) fn unnecessary_cast_to_int(checker: &Checker, call: &ExprCall) {
applicability, applicability,
checker.semantic(), checker.semantic(),
checker.locator(), checker.locator(),
checker.tokens(),
checker.comment_ranges(), checker.comment_ranges(),
checker.source(), checker.source(),
); );
@ -95,27 +96,26 @@ pub(crate) fn unnecessary_cast_to_int(checker: &Checker, call: &ExprCall) {
} }
/// Creates a fix that replaces `int(expression)` with `expression`. /// Creates a fix that replaces `int(expression)` with `expression`.
#[allow(clippy::too_many_arguments)]
fn unwrap_int_expression( fn unwrap_int_expression(
call: &ExprCall, call: &ExprCall,
argument: &Expr, argument: &Expr,
applicability: Applicability, applicability: Applicability,
semantic: &SemanticModel, semantic: &SemanticModel,
locator: &Locator, locator: &Locator,
tokens: &Tokens,
comment_ranges: &CommentRanges, comment_ranges: &CommentRanges,
source: &str, source: &str,
) -> Fix { ) -> Fix {
let content = if let Some(range) = parenthesized_range( let content = if let Some(range) =
argument.into(), parenthesized_range(argument.into(), (&call.arguments).into(), tokens)
(&call.arguments).into(), {
comment_ranges,
source,
) {
locator.slice(range).to_string() locator.slice(range).to_string()
} else { } else {
let parenthesize = semantic.current_expression_parent().is_some() let parenthesize = semantic.current_expression_parent().is_some()
|| argument.is_named_expr() || argument.is_named_expr()
|| locator.count_lines(argument.range()) > 0; || locator.count_lines(argument.range()) > 0;
if parenthesize && !has_own_parentheses(argument, comment_ranges, source) { if parenthesize && !has_own_parentheses(argument, tokens, source) {
format!("({})", locator.slice(argument.range())) format!("({})", locator.slice(argument.range()))
} else { } else {
locator.slice(argument.range()).to_string() locator.slice(argument.range()).to_string()
@ -255,7 +255,7 @@ fn round_applicability(arguments: &Arguments, semantic: &SemanticModel) -> Optio
} }
/// Returns `true` if the given [`Expr`] has its own parentheses (e.g., `()`, `[]`, `{}`). /// Returns `true` if the given [`Expr`] has its own parentheses (e.g., `()`, `[]`, `{}`).
fn has_own_parentheses(expr: &Expr, comment_ranges: &CommentRanges, source: &str) -> bool { fn has_own_parentheses(expr: &Expr, tokens: &Tokens, source: &str) -> bool {
match expr { match expr {
Expr::ListComp(_) Expr::ListComp(_)
| Expr::SetComp(_) | Expr::SetComp(_)
@ -276,12 +276,8 @@ fn has_own_parentheses(expr: &Expr, comment_ranges: &CommentRanges, source: &str
// f // f
// (10) // (10)
// ``` // ```
let func_end = parenthesized_range( let func_end =
call_expr.func.as_ref().into(), parenthesized_range(call_expr.func.as_ref().into(), call_expr.into(), tokens)
call_expr.into(),
comment_ranges,
source,
)
.unwrap_or(call_expr.func.range()) .unwrap_or(call_expr.func.range())
.end(); .end();
lines_after_ignoring_trivia(func_end, source) == 0 lines_after_ignoring_trivia(func_end, source) == 0
@ -291,8 +287,7 @@ fn has_own_parentheses(expr: &Expr, comment_ranges: &CommentRanges, source: &str
let subscript_end = parenthesized_range( let subscript_end = parenthesized_range(
subscript_expr.value.as_ref().into(), subscript_expr.value.as_ref().into(),
subscript_expr.into(), subscript_expr.into(),
comment_ranges, tokens,
source,
) )
.unwrap_or(subscript_expr.value.range()) .unwrap_or(subscript_expr.value.range())
.end(); .end();

View File

@ -3,7 +3,7 @@ use ruff_python_ast::{self as ast, BoolOp, CmpOp, Expr};
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::contains_effect; use ruff_python_ast::helpers::contains_effect;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -108,21 +108,11 @@ pub(crate) fn unnecessary_key_check(checker: &Checker, expr: &Expr) {
format!( format!(
"{}.get({})", "{}.get({})",
checker.locator().slice( checker.locator().slice(
parenthesized_range( parenthesized_range(obj_right.into(), right.into(), checker.tokens(),)
obj_right.into(),
right.into(),
checker.comment_ranges(),
checker.locator().contents(),
)
.unwrap_or(obj_right.range()) .unwrap_or(obj_right.range())
), ),
checker.locator().slice( checker.locator().slice(
parenthesized_range( parenthesized_range(key_right.into(), right.into(), checker.tokens(),)
key_right.into(),
right.into(),
checker.comment_ranges(),
checker.locator().contents(),
)
.unwrap_or(key_right.range()) .unwrap_or(key_right.range())
), ),
), ),

View File

@ -2,7 +2,7 @@ use ruff_diagnostics::{Applicability, Edit};
use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::is_empty_f_string; use ruff_python_ast::helpers::is_empty_f_string;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::token::parenthesized_range;
use ruff_python_ast::{self as ast, Expr}; use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
@ -140,31 +140,19 @@ fn fix_unnecessary_literal_in_deque(
// call. otherwise, we only delete the `iterable` argument and leave the others untouched. // call. otherwise, we only delete the `iterable` argument and leave the others untouched.
let edit = if let Some(maxlen) = maxlen { let edit = if let Some(maxlen) = maxlen {
let deque_name = checker.locator().slice( let deque_name = checker.locator().slice(
parenthesized_range( parenthesized_range(deque.func.as_ref().into(), deque.into(), checker.tokens())
deque.func.as_ref().into(),
deque.into(),
checker.comment_ranges(),
checker.source(),
)
.unwrap_or(deque.func.range()), .unwrap_or(deque.func.range()),
); );
let len_str = checker.locator().slice(maxlen); let len_str = checker.locator().slice(maxlen);
let deque_str = format!("{deque_name}(maxlen={len_str})"); let deque_str = format!("{deque_name}(maxlen={len_str})");
Edit::range_replacement(deque_str, deque.range) Edit::range_replacement(deque_str, deque.range)
} else { } else {
let range = parenthesized_range(
iterable.value().into(),
(&deque.arguments).into(),
checker.comment_ranges(),
checker.source(),
)
.unwrap_or(iterable.range());
remove_argument( remove_argument(
&range, &iterable,
&deque.arguments, &deque.arguments,
Parentheses::Preserve, Parentheses::Preserve,
checker.source(), checker.source(),
checker.comment_ranges(), checker.tokens(),
)? )?
}; };
let has_comments = checker.comment_ranges().intersects(edit.range()); let has_comments = checker.comment_ranges().intersects(edit.range());

View File

@ -3,13 +3,14 @@ use std::path::Path;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use ruff_python_trivia::{CommentRanges, SimpleTokenKind, SimpleTokenizer, indentation_at_offset}; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer, indentation_at_offset};
use ruff_source_file::LineRanges; use ruff_source_file::LineRanges;
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize}; use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
use crate::name::{Name, QualifiedName, QualifiedNameBuilder}; use crate::name::{Name, QualifiedName, QualifiedNameBuilder};
use crate::parenthesize::parenthesized_range;
use crate::statement_visitor::StatementVisitor; use crate::statement_visitor::StatementVisitor;
use crate::token::Tokens;
use crate::token::parenthesized_range;
use crate::visitor::Visitor; use crate::visitor::Visitor;
use crate::{ use crate::{
self as ast, Arguments, AtomicNodeIndex, CmpOp, DictItem, ExceptHandler, Expr, ExprNoneLiteral, self as ast, Arguments, AtomicNodeIndex, CmpOp, DictItem, ExceptHandler, Expr, ExprNoneLiteral,
@ -1474,7 +1475,7 @@ pub fn generate_comparison(
ops: &[CmpOp], ops: &[CmpOp],
comparators: &[Expr], comparators: &[Expr],
parent: AnyNodeRef, parent: AnyNodeRef,
comment_ranges: &CommentRanges, tokens: &Tokens,
source: &str, source: &str,
) -> String { ) -> String {
let start = left.start(); let start = left.start();
@ -1483,8 +1484,7 @@ pub fn generate_comparison(
// Add the left side of the comparison. // Add the left side of the comparison.
contents.push_str( contents.push_str(
&source[parenthesized_range(left.into(), parent, comment_ranges, source) &source[parenthesized_range(left.into(), parent, tokens).unwrap_or(left.range())],
.unwrap_or(left.range())],
); );
for (op, comparator) in ops.iter().zip(comparators) { for (op, comparator) in ops.iter().zip(comparators) {
@ -1504,7 +1504,7 @@ pub fn generate_comparison(
// Add the right side of the comparison. // Add the right side of the comparison.
contents.push_str( contents.push_str(
&source[parenthesized_range(comparator.into(), parent, comment_ranges, source) &source[parenthesized_range(comparator.into(), parent, tokens)
.unwrap_or(comparator.range())], .unwrap_or(comparator.range())],
); );
} }