diff --git a/crates/ruff_linter/resources/test/fixtures/refurb/FURB181.py b/crates/ruff_linter/resources/test/fixtures/refurb/FURB181.py index 559f67ee30..5c178cdcd3 100644 --- a/crates/ruff_linter/resources/test/fixtures/refurb/FURB181.py +++ b/crates/ruff_linter/resources/test/fixtures/refurb/FURB181.py @@ -55,3 +55,12 @@ class Hash: Hash().digest().hex() + + +hashed = ( + sha512(b"some data") + .digest( + # text + ) + .hex() +) \ No newline at end of file diff --git a/crates/ruff_linter/src/rules/refurb/rules/hashlib_digest_hex.rs b/crates/ruff_linter/src/rules/refurb/rules/hashlib_digest_hex.rs index deac83a9d0..4365053279 100644 --- a/crates/ruff_linter/src/rules/refurb/rules/hashlib_digest_hex.rs +++ b/crates/ruff_linter/src/rules/refurb/rules/hashlib_digest_hex.rs @@ -1,3 +1,4 @@ +use ruff_diagnostics::Applicability; use ruff_macros::{ViolationMetadata, derive_message_formats}; use ruff_python_ast::{Expr, ExprAttribute, ExprCall}; use ruff_python_semantic::Modules; @@ -28,6 +29,9 @@ use crate::{Edit, Fix, FixAvailability, Violation}; /// hashed = sha512(b"some data").hexdigest() /// ``` /// +/// ## Fix safety +/// This rule's fix is marked as safe, unless the expression contains comments. +/// /// ## References /// - [Python documentation: `hashlib`](https://docs.python.org/3/library/hashlib.html) #[derive(ViolationMetadata)] @@ -112,10 +116,18 @@ pub(crate) fn hashlib_digest_hex(checker: &Checker, call: &ExprCall) { { let mut diagnostic = checker.report_diagnostic(HashlibDigestHex, call.range()); if arguments.is_empty() { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - ".hexdigest".to_string(), - TextRange::new(value.end(), call.func.end()), - ))); + let replacement_range = TextRange::new(value.end(), call.func.end()); + + let applicability = if checker.comment_ranges().intersects(replacement_range) { + Applicability::Unsafe + } else { + Applicability::Safe + }; + + diagnostic.set_fix(Fix::applicable_edit( + Edit::range_replacement(".hexdigest".to_string(), replacement_range), + applicability, + )); } } } diff --git a/crates/ruff_linter/src/rules/refurb/snapshots/ruff_linter__rules__refurb__tests__FURB181_FURB181.py.snap b/crates/ruff_linter/src/rules/refurb/snapshots/ruff_linter__rules__refurb__tests__FURB181_FURB181.py.snap index d437b1ae07..384a5f8359 100644 --- a/crates/ruff_linter/src/rules/refurb/snapshots/ruff_linter__rules__refurb__tests__FURB181_FURB181.py.snap +++ b/crates/ruff_linter/src/rules/refurb/snapshots/ruff_linter__rules__refurb__tests__FURB181_FURB181.py.snap @@ -322,3 +322,28 @@ help: Replace with `.hexdigest()` 39 | 40 | # not yet supported 41 | h = sha256() + +FURB181 [*] Use of hashlib's `.digest().hex()` + --> FURB181.py:61:5 + | +60 | hashed = ( +61 | / sha512(b"some data") +62 | | .digest( +63 | | # text +64 | | ) +65 | | .hex() + | |__________^ +66 | ) + | +help: Replace with `.hexdigest()` +58 | +59 | +60 | hashed = ( + - sha512(b"some data") + - .digest( + - # text + - ) + - .hex() +61 + sha512(b"some data").hexdigest() +62 | ) +note: This is an unsafe fix and may change runtime behavior