diff --git a/crates/ruff_linter/resources/test/fixtures/flake8_return/RET505.py b/crates/ruff_linter/resources/test/fixtures/flake8_return/RET505.py index ad6fe46c7e..6110e891c1 100644 --- a/crates/ruff_linter/resources/test/fixtures/flake8_return/RET505.py +++ b/crates/ruff_linter/resources/test/fixtures/flake8_return/RET505.py @@ -238,3 +238,9 @@ def indent(x, y, w, z): # comment c = 3 return z + +def f(): + if True: + return True + else: + return False diff --git a/crates/ruff_linter/src/fix/edits.rs b/crates/ruff_linter/src/fix/edits.rs index 161425b4a7..5cadc38c87 100644 --- a/crates/ruff_linter/src/fix/edits.rs +++ b/crates/ruff_linter/src/fix/edits.rs @@ -300,11 +300,25 @@ pub(crate) fn adjust_indentation( indexer: &Indexer, stylist: &Stylist, ) -> Result { + let contents = locator.slice(range); + // If the range includes a multi-line string, use LibCST to ensure that we don't adjust the // whitespace _within_ the string. - if indexer.multiline_ranges().intersects(range) || indexer.fstring_ranges().intersects(range) { - let contents = locator.slice(range); + let contains_multiline_string = + indexer.multiline_ranges().intersects(range) || indexer.fstring_ranges().intersects(range); + // If the range has mixed indentation, we will use LibCST as well. + let mixed_indentation = contents.universal_newlines().any(|line| { + let trimmed = line.trim_whitespace_start(); + if trimmed.is_empty() { + return false; + } + + let line_indentation: &str = &line[..line.len() - trimmed.len()]; + line_indentation.contains('\t') && line_indentation.contains(' ') + }); + + if contains_multiline_string || mixed_indentation { let module_text = format!("def f():{}{contents}", stylist.line_ending().as_str()); let mut tree = match_statement(&module_text)?; @@ -322,7 +336,6 @@ pub(crate) fn adjust_indentation( Ok(module_text) } else { // Otherwise, we can do a simple adjustment ourselves. - let contents = locator.slice(range); Ok(dedent_to(contents, indentation)) } } diff --git a/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET505_RET505.py.snap b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET505_RET505.py.snap index c3fd9c8b12..4cfdb04431 100644 --- a/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET505_RET505.py.snap +++ b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET505_RET505.py.snap @@ -215,4 +215,12 @@ RET505.py:237:5: RET505 Unnecessary `else` after `return` statement | = help: Remove unnecessary `else` - +RET505.py:245:2: RET505 Unnecessary `else` after `return` statement + | +243 | if True: +244 | return True +245 | else: + | ^^^^ RET505 +246 | return False + | + = help: Remove unnecessary `else` diff --git a/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__preview__RET505_RET505.py.snap b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__preview__RET505_RET505.py.snap index 21a3d2efc6..3c60fc51f8 100644 --- a/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__preview__RET505_RET505.py.snap +++ b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__preview__RET505_RET505.py.snap @@ -460,5 +460,24 @@ RET505.py:237:5: RET505 [*] Unnecessary `else` after `return` statement 240 |- return z 238 |+ c = 3 239 |+ return z +241 240 | +242 241 | def f(): +243 242 | if True: +RET505.py:245:2: RET505 [*] Unnecessary `else` after `return` statement + | +243 | if True: +244 | return True +245 | else: + | ^^^^ RET505 +246 | return False + | + = help: Remove unnecessary `else` +ℹ Safe fix +242 242 | def f(): +243 243 | if True: +244 244 | return True +245 |- else: +246 |- return False + 245 |+ return False