[refurb] Make fix unsafe if it deletes comments (FURB136) (#22680)

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan

<!-- How was it tested? -->
This commit is contained in:
chiri
2026-01-19 18:17:24 +03:00
committed by GitHub
parent 2bc4756716
commit bffc95873d
3 changed files with 52 additions and 4 deletions

View File

@@ -23,3 +23,11 @@ x if (
x
> y
) else y # FURB136
highest_score = (
x
# text
if x > y
else y
)

View File

@@ -1,3 +1,4 @@
use ruff_diagnostics::Applicability;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::comparable::ComparableExpr;
use ruff_python_ast::{self as ast, CmpOp, Expr};
@@ -19,14 +20,21 @@ use crate::{Edit, Fix, FixAvailability, Violation};
///
/// ## Example
/// ```python
/// score1, score2 = 4, 5
///
/// highest_score = score1 if score1 > score2 else score2
/// ```
///
/// Use instead:
/// ```python
/// score1, score2 = 4, 5
///
/// highest_score = max(score2, score1)
/// ```
///
/// ## Fix safety
/// This rule's fix is marked as safe, unless the expression contains comments.
///
/// ## References
/// - [Python documentation: `min`](https://docs.python.org/3.11/library/functions.html#min)
/// - [Python documentation: `max`](https://docs.python.org/3.11/library/functions.html#max)
@@ -141,10 +149,16 @@ pub(crate) fn if_expr_min_max(checker: &Checker, if_exp: &ast::ExprIf) {
);
if checker.semantic().has_builtin_binding(min_max.as_str()) {
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
replacement,
if_exp.range(),
)));
let applicability = if checker.comment_ranges().intersects(if_exp.range()) {
Applicability::Unsafe
} else {
Applicability::Safe
};
diagnostic.set_fix(Fix::applicable_edit(
Edit::range_replacement(replacement, if_exp.range()),
applicability,
));
}
}

View File

@@ -181,3 +181,29 @@ help: Replace with `max(y, x)`
- > y
- ) else y # FURB136
22 + max(y, x) # FURB136
23 |
24 |
25 | highest_score = (
FURB136 [*] Replace `if` expression with `max(y, x)`
--> FURB136.py:29:5
|
28 | highest_score = (
29 | / x
30 | | # text
31 | | if x > y
32 | | else y
| |__________^
33 | )
|
help: Replace with `max(y, x)`
26 |
27 |
28 | highest_score = (
- x
- # text
- if x > y
- else y
29 + max(y, x)
30 | )
note: This is an unsafe fix and may change runtime behavior