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 8f5d07fe51b48..a222c5055b683 100644 --- a/crates/ruff_linter/resources/test/fixtures/flake8_return/RET505.py +++ b/crates/ruff_linter/resources/test/fixtures/flake8_return/RET505.py @@ -131,6 +131,37 @@ def bar3(x, y, z): return None +def bar4(x): + if True: + return + else: + # comment + pass + + +def bar5(): + if True: + return + else: # comment + pass + + +def bar6(): + if True: + return + else\ + :\ + # comment + pass + + +def bar7(): + if True: + return + else\ + : # comment + pass + x = 0 if x == 1: diff --git a/crates/ruff_linter/src/rules/flake8_return/mod.rs b/crates/ruff_linter/src/rules/flake8_return/mod.rs index bfad9cf6ba09c..2c9400dd49abd 100644 --- a/crates/ruff_linter/src/rules/flake8_return/mod.rs +++ b/crates/ruff_linter/src/rules/flake8_return/mod.rs @@ -11,10 +11,11 @@ mod tests { use anyhow::Result; use test_case::test_case; - use crate::assert_messages; use crate::registry::Rule; + use crate::settings::types::PreviewMode; use crate::settings::LinterSettings; use crate::test::test_path; + use crate::{assert_messages, settings}; #[test_case(Rule::UnnecessaryReturnNone, Path::new("RET501.py"))] #[test_case(Rule::ImplicitReturnValue, Path::new("RET502.py"))] @@ -33,4 +34,25 @@ mod tests { assert_messages!(snapshot, diagnostics); Ok(()) } + + #[test_case(Rule::SuperfluousElseReturn, Path::new("RET505.py"))] + #[test_case(Rule::SuperfluousElseRaise, Path::new("RET506.py"))] + #[test_case(Rule::SuperfluousElseContinue, Path::new("RET507.py"))] + #[test_case(Rule::SuperfluousElseBreak, Path::new("RET508.py"))] + fn preview_rules(rule_code: Rule, path: &Path) -> Result<()> { + let snapshot = format!( + "preview__{}_{}", + rule_code.noqa_code(), + path.to_string_lossy() + ); + let diagnostics = test_path( + Path::new("flake8_return").join(path).as_path(), + &settings::LinterSettings { + preview: PreviewMode::Enabled, + ..settings::LinterSettings::for_rule(rule_code) + }, + )?; + assert_messages!(snapshot, diagnostics); + Ok(()) + } } diff --git a/crates/ruff_linter/src/rules/flake8_return/rules/function.rs b/crates/ruff_linter/src/rules/flake8_return/rules/function.rs index d7bbd7b107421..36dc832dc6fb2 100644 --- a/crates/ruff_linter/src/rules/flake8_return/rules/function.rs +++ b/crates/ruff_linter/src/rules/flake8_return/rules/function.rs @@ -1,9 +1,10 @@ +use anyhow::Result; use std::ops::Add; use ruff_python_ast::{self as ast, ElifElseClause, Expr, Stmt}; use ruff_text_size::{Ranged, TextRange, TextSize}; -use ruff_diagnostics::{AlwaysFixableViolation, Violation}; +use ruff_diagnostics::{AlwaysFixableViolation, FixAvailability, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -12,12 +13,13 @@ use ruff_python_ast::stmt_if::elif_else_range; use ruff_python_ast::visitor::Visitor; use ruff_python_ast::whitespace::indentation; use ruff_python_semantic::SemanticModel; -use ruff_python_trivia::is_python_whitespace; +use ruff_python_trivia::{is_python_whitespace, SimpleTokenKind, SimpleTokenizer}; use crate::checkers::ast::Checker; use crate::fix::edits; use crate::registry::{AsRule, Rule}; use crate::rules::flake8_return::helpers::end_of_last_statement; +use crate::rules::pyupgrade::fixes::adjust_indentation; use super::super::branch::Branch; use super::super::helpers::result_exists; @@ -210,11 +212,17 @@ pub struct SuperfluousElseReturn { } impl Violation for SuperfluousElseReturn { + const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes; #[derive_message_formats] fn message(&self) -> String { let SuperfluousElseReturn { branch } = self; format!("Unnecessary `{branch}` after `return` statement") } + + fn fix_title(&self) -> Option { + let SuperfluousElseReturn { branch } = self; + Some(format!("Remove unnecessary `{branch}`")) + } } /// ## What it does @@ -248,11 +256,17 @@ pub struct SuperfluousElseRaise { } impl Violation for SuperfluousElseRaise { + const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes; #[derive_message_formats] fn message(&self) -> String { let SuperfluousElseRaise { branch } = self; format!("Unnecessary `{branch}` after `raise` statement") } + + fn fix_title(&self) -> Option { + let SuperfluousElseRaise { branch } = self; + Some(format!("Remove unnecessary `{branch}`")) + } } /// ## What it does @@ -288,11 +302,17 @@ pub struct SuperfluousElseContinue { } impl Violation for SuperfluousElseContinue { + const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes; #[derive_message_formats] fn message(&self) -> String { let SuperfluousElseContinue { branch } = self; format!("Unnecessary `{branch}` after `continue` statement") } + + fn fix_title(&self) -> Option { + let SuperfluousElseContinue { branch } = self; + Some(format!("Remove unnecessary `{branch}`")) + } } /// ## What it does @@ -328,11 +348,17 @@ pub struct SuperfluousElseBreak { } impl Violation for SuperfluousElseBreak { + const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes; #[derive_message_formats] fn message(&self) -> String { let SuperfluousElseBreak { branch } = self; format!("Unnecessary `{branch}` after `break` statement") } + + fn fix_title(&self) -> Option { + let SuperfluousElseBreak { branch } = self; + Some(format!("Remove unnecessary `{branch}`")) + } } /// RET501 @@ -602,42 +628,54 @@ fn superfluous_else_node( }; for child in if_elif_body { if child.is_return_stmt() { - let diagnostic = Diagnostic::new( + let mut diagnostic = Diagnostic::new( SuperfluousElseReturn { branch }, elif_else_range(elif_else, checker.locator().contents()) .unwrap_or_else(|| elif_else.range()), ); if checker.enabled(diagnostic.kind.rule()) { + if checker.settings.preview.is_enabled() { + diagnostic.try_set_fix(|| remove_else(checker, elif_else)); + } checker.diagnostics.push(diagnostic); } return true; } else if child.is_break_stmt() { - let diagnostic = Diagnostic::new( + let mut diagnostic = Diagnostic::new( SuperfluousElseBreak { branch }, elif_else_range(elif_else, checker.locator().contents()) .unwrap_or_else(|| elif_else.range()), ); if checker.enabled(diagnostic.kind.rule()) { + if checker.settings.preview.is_enabled() { + diagnostic.try_set_fix(|| remove_else(checker, elif_else)); + } checker.diagnostics.push(diagnostic); } return true; } else if child.is_raise_stmt() { - let diagnostic = Diagnostic::new( + let mut diagnostic = Diagnostic::new( SuperfluousElseRaise { branch }, elif_else_range(elif_else, checker.locator().contents()) .unwrap_or_else(|| elif_else.range()), ); if checker.enabled(diagnostic.kind.rule()) { + if checker.settings.preview.is_enabled() { + diagnostic.try_set_fix(|| remove_else(checker, elif_else)); + } checker.diagnostics.push(diagnostic); } return true; } else if child.is_continue_stmt() { - let diagnostic = Diagnostic::new( + let mut diagnostic = Diagnostic::new( SuperfluousElseContinue { branch }, elif_else_range(elif_else, checker.locator().contents()) .unwrap_or_else(|| elif_else.range()), ); if checker.enabled(diagnostic.kind.rule()) { + if checker.settings.preview.is_enabled() { + diagnostic.try_set_fix(|| remove_else(checker, elif_else)); + } checker.diagnostics.push(diagnostic); } return true; @@ -715,3 +753,67 @@ pub(crate) fn function(checker: &mut Checker, body: &[Stmt], returns: Option<&Ex } } } + +fn remove_else(checker: &mut Checker, elif_else: &ElifElseClause) -> Result { + if elif_else.test.is_some() { + // it's an elif, so we can just make it an if + + // delete "el" from "elif" + Ok(Fix::safe_edit(Edit::deletion( + elif_else.start(), + elif_else.start() + TextSize::from(2), + ))) + } else { + // the start of the line where the `else`` is + let else_line_start = checker.locator().line_start(elif_else.start()); + + // making a tokenizer to find the Colon for the `else`, not always on the same line! + let mut else_line_tokenizer = + SimpleTokenizer::starts_at(elif_else.start(), checker.locator().contents()); + + // find the Colon for the `else` + let Some(else_colon) = + else_line_tokenizer.find(|token| token.kind == SimpleTokenKind::Colon) + else { + return Err(anyhow::anyhow!("Cannot find `:` in `else` statement")); + }; + + // get the indentation of the `else`, since that is the indent level we want to end with + let Some(desired_indentation) = indentation(checker.locator(), elif_else) else { + return Err(anyhow::anyhow!("Compound statement cannot be inlined")); + }; + + // we're deleting the `else`, and it's Colon, and the rest of the line(s) they're on, + // so here we get the last position of the line the Colon is on + let else_colon_end = checker.locator().full_line_end(else_colon.end()); + + // if there is a comment on the same line as the Colon, let's keep it + // and give it the proper indentation once we unindent it + let else_comment_after_colon = else_line_tokenizer + .find(|token| token.kind.is_comment()) + .and_then(|token| { + if token.kind == SimpleTokenKind::Comment && token.start() < else_colon_end { + return Some(format!( + "{desired_indentation}{}{}", + checker.locator().slice(token), + checker.stylist().line_ending().as_str(), + )); + } + None + }) + .unwrap_or(String::new()); + + let indented = adjust_indentation( + TextRange::new(else_colon_end, elif_else.end()), + desired_indentation, + checker.locator(), + checker.stylist(), + )?; + + Ok(Fix::safe_edit(Edit::replacement( + format!("{else_comment_after_colon}{indented}"), + else_line_start, + elif_else.end(), + ))) + } +} 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 6a694dcadc1fc..e3ecd603fa652 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 @@ -10,6 +10,7 @@ RET505.py:8:5: RET505 Unnecessary `elif` after `return` statement 9 | b = 2 10 | return w | + = help: Remove unnecessary `elif` RET505.py:23:5: RET505 Unnecessary `elif` after `return` statement | @@ -20,6 +21,7 @@ RET505.py:23:5: RET505 Unnecessary `elif` after `return` statement 24 | c = 2 25 | else: | + = help: Remove unnecessary `elif` RET505.py:41:5: RET505 Unnecessary `elif` after `return` statement | @@ -30,6 +32,7 @@ RET505.py:41:5: RET505 Unnecessary `elif` after `return` statement 42 | b = 2 43 | return w | + = help: Remove unnecessary `elif` RET505.py:53:5: RET505 Unnecessary `else` after `return` statement | @@ -40,6 +43,7 @@ RET505.py:53:5: RET505 Unnecessary `else` after `return` statement 54 | b = 2 55 | return z | + = help: Remove unnecessary `else` RET505.py:64:9: RET505 Unnecessary `else` after `return` statement | @@ -50,6 +54,7 @@ RET505.py:64:9: RET505 Unnecessary `else` after `return` statement 65 | c = 3 66 | return x | + = help: Remove unnecessary `else` RET505.py:79:5: RET505 Unnecessary `else` after `return` statement | @@ -60,6 +65,7 @@ RET505.py:79:5: RET505 Unnecessary `else` after `return` statement 80 | c = 3 81 | return | + = help: Remove unnecessary `else` RET505.py:89:9: RET505 Unnecessary `else` after `return` statement | @@ -70,6 +76,7 @@ RET505.py:89:9: RET505 Unnecessary `else` after `return` statement 90 | b = 2 91 | else: | + = help: Remove unnecessary `else` RET505.py:99:5: RET505 Unnecessary `else` after `return` statement | @@ -80,5 +87,49 @@ RET505.py:99:5: RET505 Unnecessary `else` after `return` statement 100 | try: 101 | return False | + = help: Remove unnecessary `else` + +RET505.py:137:5: RET505 Unnecessary `else` after `return` statement + | +135 | if True: +136 | return +137 | else: + | ^^^^ RET505 +138 | # comment +139 | pass + | + = help: Remove unnecessary `else` + +RET505.py:145:5: RET505 Unnecessary `else` after `return` statement + | +143 | if True: +144 | return +145 | else: # comment + | ^^^^ RET505 +146 | pass + | + = help: Remove unnecessary `else` + +RET505.py:152:5: RET505 Unnecessary `else` after `return` statement + | +150 | if True: +151 | return +152 | else\ + | ^^^^ RET505 +153 | :\ +154 | # comment + | + = help: Remove unnecessary `else` + +RET505.py:161:5: RET505 Unnecessary `else` after `return` statement + | +159 | if True: +160 | return +161 | else\ + | ^^^^ RET505 +162 | : # comment +163 | pass + | + = help: Remove unnecessary `else` diff --git a/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET506_RET506.py.snap b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET506_RET506.py.snap index cc9b6eafa9551..339d699edbaf5 100644 --- a/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET506_RET506.py.snap +++ b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET506_RET506.py.snap @@ -10,6 +10,7 @@ RET506.py:8:5: RET506 Unnecessary `elif` after `raise` statement 9 | b = 2 10 | raise Exception(w) | + = help: Remove unnecessary `elif` RET506.py:23:5: RET506 Unnecessary `elif` after `raise` statement | @@ -20,6 +21,7 @@ RET506.py:23:5: RET506 Unnecessary `elif` after `raise` statement 24 | raise Exception(y) 25 | else: | + = help: Remove unnecessary `elif` RET506.py:34:5: RET506 Unnecessary `else` after `raise` statement | @@ -30,6 +32,7 @@ RET506.py:34:5: RET506 Unnecessary `else` after `raise` statement 35 | b = 2 36 | raise Exception(z) | + = help: Remove unnecessary `else` RET506.py:45:9: RET506 Unnecessary `else` after `raise` statement | @@ -40,6 +43,7 @@ RET506.py:45:9: RET506 Unnecessary `else` after `raise` statement 46 | c = 3 47 | raise Exception(x) | + = help: Remove unnecessary `else` RET506.py:60:5: RET506 Unnecessary `else` after `raise` statement | @@ -50,6 +54,7 @@ RET506.py:60:5: RET506 Unnecessary `else` after `raise` statement 61 | c = 3 62 | raise Exception(y) | + = help: Remove unnecessary `else` RET506.py:70:9: RET506 Unnecessary `else` after `raise` statement | @@ -60,6 +65,7 @@ RET506.py:70:9: RET506 Unnecessary `else` after `raise` statement 71 | b = 2 72 | else: | + = help: Remove unnecessary `else` RET506.py:80:5: RET506 Unnecessary `else` after `raise` statement | @@ -70,5 +76,6 @@ RET506.py:80:5: RET506 Unnecessary `else` after `raise` statement 81 | try: 82 | raise Exception(False) | + = help: Remove unnecessary `else` diff --git a/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET507_RET507.py.snap b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET507_RET507.py.snap index 5776623e37821..bec73ac728298 100644 --- a/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET507_RET507.py.snap +++ b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET507_RET507.py.snap @@ -10,6 +10,7 @@ RET507.py:8:9: RET507 Unnecessary `elif` after `continue` statement 9 | continue 10 | else: | + = help: Remove unnecessary `elif` RET507.py:22:9: RET507 Unnecessary `elif` after `continue` statement | @@ -20,6 +21,7 @@ RET507.py:22:9: RET507 Unnecessary `elif` after `continue` statement 23 | c = 2 24 | else: | + = help: Remove unnecessary `elif` RET507.py:36:9: RET507 Unnecessary `else` after `continue` statement | @@ -29,6 +31,7 @@ RET507.py:36:9: RET507 Unnecessary `else` after `continue` statement | ^^^^ RET507 37 | a = z | + = help: Remove unnecessary `else` RET507.py:47:13: RET507 Unnecessary `else` after `continue` statement | @@ -39,6 +42,7 @@ RET507.py:47:13: RET507 Unnecessary `else` after `continue` statement 48 | c = 3 49 | continue | + = help: Remove unnecessary `else` RET507.py:63:9: RET507 Unnecessary `else` after `continue` statement | @@ -49,6 +53,7 @@ RET507.py:63:9: RET507 Unnecessary `else` after `continue` statement 64 | c = 3 65 | continue | + = help: Remove unnecessary `else` RET507.py:74:13: RET507 Unnecessary `else` after `continue` statement | @@ -59,6 +64,7 @@ RET507.py:74:13: RET507 Unnecessary `else` after `continue` statement 75 | b = 2 76 | else: | + = help: Remove unnecessary `else` RET507.py:85:9: RET507 Unnecessary `else` after `continue` statement | @@ -69,5 +75,6 @@ RET507.py:85:9: RET507 Unnecessary `else` after `continue` statement 86 | try: 87 | return | + = help: Remove unnecessary `else` diff --git a/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET508_RET508.py.snap b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET508_RET508.py.snap index c5255d93d9fae..986a08bbfaf89 100644 --- a/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET508_RET508.py.snap +++ b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__RET508_RET508.py.snap @@ -10,6 +10,7 @@ RET508.py:8:9: RET508 Unnecessary `elif` after `break` statement 9 | break 10 | else: | + = help: Remove unnecessary `elif` RET508.py:22:9: RET508 Unnecessary `elif` after `break` statement | @@ -20,6 +21,7 @@ RET508.py:22:9: RET508 Unnecessary `elif` after `break` statement 23 | c = 2 24 | else: | + = help: Remove unnecessary `elif` RET508.py:33:9: RET508 Unnecessary `else` after `break` statement | @@ -29,6 +31,7 @@ RET508.py:33:9: RET508 Unnecessary `else` after `break` statement | ^^^^ RET508 34 | a = z | + = help: Remove unnecessary `else` RET508.py:44:13: RET508 Unnecessary `else` after `break` statement | @@ -39,6 +42,7 @@ RET508.py:44:13: RET508 Unnecessary `else` after `break` statement 45 | c = 3 46 | break | + = help: Remove unnecessary `else` RET508.py:60:9: RET508 Unnecessary `else` after `break` statement | @@ -49,6 +53,7 @@ RET508.py:60:9: RET508 Unnecessary `else` after `break` statement 61 | c = 3 62 | break | + = help: Remove unnecessary `else` RET508.py:71:13: RET508 Unnecessary `else` after `break` statement | @@ -59,6 +64,7 @@ RET508.py:71:13: RET508 Unnecessary `else` after `break` statement 72 | b = 2 73 | else: | + = help: Remove unnecessary `else` RET508.py:82:9: RET508 Unnecessary `else` after `break` statement | @@ -69,6 +75,7 @@ RET508.py:82:9: RET508 Unnecessary `else` after `break` statement 83 | try: 84 | return | + = help: Remove unnecessary `else` RET508.py:158:13: RET508 Unnecessary `else` after `break` statement | @@ -78,5 +85,6 @@ RET508.py:158:13: RET508 Unnecessary `else` after `break` statement | ^^^^ RET508 159 | a = z | + = 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 new file mode 100644 index 0000000000000..2291503080edc --- /dev/null +++ b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__preview__RET505_RET505.py.snap @@ -0,0 +1,282 @@ +--- +source: crates/ruff_linter/src/rules/flake8_return/mod.rs +--- +RET505.py:8:5: RET505 [*] Unnecessary `elif` after `return` statement + | + 6 | a = 1 + 7 | return y + 8 | elif z: + | ^^^^ RET505 + 9 | b = 2 +10 | return w + | + = help: Remove unnecessary `elif` + +ℹ Safe fix +5 5 | if x: # [no-else-return] +6 6 | a = 1 +7 7 | return y +8 |- elif z: + 8 |+ if z: +9 9 | b = 2 +10 10 | return w +11 11 | else: + +RET505.py:23:5: RET505 [*] Unnecessary `elif` after `return` statement + | +21 | b = 2 +22 | return +23 | elif z: + | ^^^^ RET505 +24 | c = 2 +25 | else: + | + = help: Remove unnecessary `elif` + +ℹ Safe fix +20 20 | else: +21 21 | b = 2 +22 22 | return +23 |- elif z: + 23 |+ if z: +24 24 | c = 2 +25 25 | else: +26 26 | c = 3 + +RET505.py:41:5: RET505 [*] Unnecessary `elif` after `return` statement + | +39 | a = 1 +40 | return y +41 | elif z: + | ^^^^ RET505 +42 | b = 2 +43 | return w + | + = help: Remove unnecessary `elif` + +ℹ Safe fix +38 38 | if x: # [no-else-return] +39 39 | a = 1 +40 40 | return y +41 |- elif z: + 41 |+ if z: +42 42 | b = 2 +43 43 | return w +44 44 | else: + +RET505.py:53:5: RET505 [*] Unnecessary `else` after `return` statement + | +51 | a = 1 +52 | return y +53 | else: + | ^^^^ RET505 +54 | b = 2 +55 | return z + | + = help: Remove unnecessary `else` + +ℹ Safe fix +50 50 | if x: # [no-else-return] +51 51 | a = 1 +52 52 | return y +53 |- else: +54 |- b = 2 +55 |- return z + 53 |+ b = 2 + 54 |+ return z +56 55 | +57 56 | +58 57 | def foo3(x, y, z): + +RET505.py:64:9: RET505 [*] Unnecessary `else` after `return` statement + | +62 | b = 2 +63 | return y +64 | else: + | ^^^^ RET505 +65 | c = 3 +66 | return x + | + = help: Remove unnecessary `else` + +ℹ Safe fix +61 61 | if y: # [no-else-return] +62 62 | b = 2 +63 63 | return y +64 |- else: +65 |- c = 3 +66 |- return x + 64 |+ c = 3 + 65 |+ return x +67 66 | else: +68 67 | d = 4 +69 68 | return z + +RET505.py:79:5: RET505 [*] Unnecessary `else` after `return` statement + | +77 | b = 2 +78 | return +79 | else: + | ^^^^ RET505 +80 | c = 3 +81 | return + | + = help: Remove unnecessary `else` + +ℹ Safe fix +76 76 | else: +77 77 | b = 2 +78 78 | return +79 |- else: +80 |- c = 3 + 79 |+ c = 3 +81 80 | return +82 81 | +83 82 | + +RET505.py:89:9: RET505 [*] Unnecessary `else` after `return` statement + | +87 | a = 4 +88 | return +89 | else: + | ^^^^ RET505 +90 | b = 2 +91 | else: + | + = help: Remove unnecessary `else` + +ℹ Safe fix +86 86 | if y: # [no-else-return] +87 87 | a = 4 +88 88 | return +89 |- else: +90 |- b = 2 + 89 |+ b = 2 +91 90 | else: +92 91 | c = 3 +93 92 | return + +RET505.py:99:5: RET505 [*] Unnecessary `else` after `return` statement + | + 97 | if x: # [no-else-return] + 98 | return True + 99 | else: + | ^^^^ RET505 +100 | try: +101 | return False + | + = help: Remove unnecessary `else` + +ℹ Safe fix +96 96 | def bar4(x): +97 97 | if x: # [no-else-return] +98 98 | return True +99 |- else: +100 |- try: +101 |- return False +102 |- except ValueError: +103 |- return None + 99 |+ try: + 100 |+ return False + 101 |+ except ValueError: + 102 |+ return None +104 103 | +105 104 | +106 105 | ### + +RET505.py:137:5: RET505 [*] Unnecessary `else` after `return` statement + | +135 | if True: +136 | return +137 | else: + | ^^^^ RET505 +138 | # comment +139 | pass + | + = help: Remove unnecessary `else` + +ℹ Safe fix +134 134 | def bar4(x): +135 135 | if True: +136 136 | return +137 |- else: +138 |- # comment +139 |- pass + 137 |+ # comment + 138 |+ pass +140 139 | +141 140 | +142 141 | def bar5(): + +RET505.py:145:5: RET505 [*] Unnecessary `else` after `return` statement + | +143 | if True: +144 | return +145 | else: # comment + | ^^^^ RET505 +146 | pass + | + = help: Remove unnecessary `else` + +ℹ Safe fix +142 142 | def bar5(): +143 143 | if True: +144 144 | return +145 |- else: # comment +146 |- pass + 145 |+ # comment + 146 |+ pass +147 147 | +148 148 | +149 149 | def bar6(): + +RET505.py:152:5: RET505 [*] Unnecessary `else` after `return` statement + | +150 | if True: +151 | return +152 | else\ + | ^^^^ RET505 +153 | :\ +154 | # comment + | + = help: Remove unnecessary `else` + +ℹ Safe fix +149 149 | def bar6(): +150 150 | if True: +151 151 | return +152 |- else\ +153 |- :\ +154 |- # comment +155 |- pass + 152 |+ # comment + 153 |+ pass +156 154 | +157 155 | +158 156 | def bar7(): + +RET505.py:161:5: RET505 [*] Unnecessary `else` after `return` statement + | +159 | if True: +160 | return +161 | else\ + | ^^^^ RET505 +162 | : # comment +163 | pass + | + = help: Remove unnecessary `else` + +ℹ Safe fix +158 158 | def bar7(): +159 159 | if True: +160 160 | return +161 |- else\ +162 |- : # comment +163 |- pass + 161 |+ # comment + 162 |+ pass +164 163 | +165 164 | x = 0 +166 165 | + + diff --git a/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__preview__RET506_RET506.py.snap b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__preview__RET506_RET506.py.snap new file mode 100644 index 0000000000000..549850ee8d25b --- /dev/null +++ b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__preview__RET506_RET506.py.snap @@ -0,0 +1,166 @@ +--- +source: crates/ruff_linter/src/rules/flake8_return/mod.rs +--- +RET506.py:8:5: RET506 [*] Unnecessary `elif` after `raise` statement + | + 6 | a = 1 + 7 | raise Exception(y) + 8 | elif z: + | ^^^^ RET506 + 9 | b = 2 +10 | raise Exception(w) + | + = help: Remove unnecessary `elif` + +ℹ Safe fix +5 5 | if x: # [no-else-raise] +6 6 | a = 1 +7 7 | raise Exception(y) +8 |- elif z: + 8 |+ if z: +9 9 | b = 2 +10 10 | raise Exception(w) +11 11 | else: + +RET506.py:23:5: RET506 [*] Unnecessary `elif` after `raise` statement + | +21 | b = 2 +22 | raise Exception(x) +23 | elif z: + | ^^^^ RET506 +24 | raise Exception(y) +25 | else: + | + = help: Remove unnecessary `elif` + +ℹ Safe fix +20 20 | else: +21 21 | b = 2 +22 22 | raise Exception(x) +23 |- elif z: + 23 |+ if z: +24 24 | raise Exception(y) +25 25 | else: +26 26 | c = 3 + +RET506.py:34:5: RET506 [*] Unnecessary `else` after `raise` statement + | +32 | a = 1 +33 | raise Exception(y) +34 | else: + | ^^^^ RET506 +35 | b = 2 +36 | raise Exception(z) + | + = help: Remove unnecessary `else` + +ℹ Safe fix +31 31 | if x: # [no-else-raise] +32 32 | a = 1 +33 33 | raise Exception(y) +34 |- else: +35 |- b = 2 +36 |- raise Exception(z) + 34 |+ b = 2 + 35 |+ raise Exception(z) +37 36 | +38 37 | +39 38 | def foo3(x, y, z): + +RET506.py:45:9: RET506 [*] Unnecessary `else` after `raise` statement + | +43 | b = 2 +44 | raise Exception(y) +45 | else: + | ^^^^ RET506 +46 | c = 3 +47 | raise Exception(x) + | + = help: Remove unnecessary `else` + +ℹ Safe fix +42 42 | if y: # [no-else-raise] +43 43 | b = 2 +44 44 | raise Exception(y) +45 |- else: +46 |- c = 3 +47 |- raise Exception(x) + 45 |+ c = 3 + 46 |+ raise Exception(x) +48 47 | else: +49 48 | d = 4 +50 49 | raise Exception(z) + +RET506.py:60:5: RET506 [*] Unnecessary `else` after `raise` statement + | +58 | b = 2 +59 | raise Exception(x) +60 | else: + | ^^^^ RET506 +61 | c = 3 +62 | raise Exception(y) + | + = help: Remove unnecessary `else` + +ℹ Safe fix +57 57 | else: +58 58 | b = 2 +59 59 | raise Exception(x) +60 |- else: +61 |- c = 3 + 60 |+ c = 3 +62 61 | raise Exception(y) +63 62 | +64 63 | + +RET506.py:70:9: RET506 [*] Unnecessary `else` after `raise` statement + | +68 | a = 4 +69 | raise Exception(x) +70 | else: + | ^^^^ RET506 +71 | b = 2 +72 | else: + | + = help: Remove unnecessary `else` + +ℹ Safe fix +67 67 | if y: # [no-else-raise] +68 68 | a = 4 +69 69 | raise Exception(x) +70 |- else: +71 |- b = 2 + 70 |+ b = 2 +72 71 | else: +73 72 | c = 3 +74 73 | raise Exception(y) + +RET506.py:80:5: RET506 [*] Unnecessary `else` after `raise` statement + | +78 | if x: # [no-else-raise] +79 | raise Exception(True) +80 | else: + | ^^^^ RET506 +81 | try: +82 | raise Exception(False) + | + = help: Remove unnecessary `else` + +ℹ Safe fix +77 77 | def bar4(x): +78 78 | if x: # [no-else-raise] +79 79 | raise Exception(True) +80 |- else: +81 |- try: +82 |- raise Exception(False) +83 |- except ValueError: +84 |- raise Exception(None) + 80 |+ try: + 81 |+ raise Exception(False) + 82 |+ except ValueError: + 83 |+ raise Exception(None) +85 84 | +86 85 | +87 86 | ### + + diff --git a/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__preview__RET507_RET507.py.snap b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__preview__RET507_RET507.py.snap new file mode 100644 index 0000000000000..1a745fc2f576f --- /dev/null +++ b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__preview__RET507_RET507.py.snap @@ -0,0 +1,163 @@ +--- +source: crates/ruff_linter/src/rules/flake8_return/mod.rs +--- +RET507.py:8:9: RET507 [*] Unnecessary `elif` after `continue` statement + | + 6 | if i < y: # [no-else-continue] + 7 | continue + 8 | elif i < w: + | ^^^^ RET507 + 9 | continue +10 | else: + | + = help: Remove unnecessary `elif` + +ℹ Safe fix +5 5 | for i in x: +6 6 | if i < y: # [no-else-continue] +7 7 | continue +8 |- elif i < w: + 8 |+ if i < w: +9 9 | continue +10 10 | else: +11 11 | a = z + +RET507.py:22:9: RET507 [*] Unnecessary `elif` after `continue` statement + | +20 | b = 2 +21 | continue +22 | elif z: + | ^^^^ RET507 +23 | c = 2 +24 | else: + | + = help: Remove unnecessary `elif` + +ℹ Safe fix +19 19 | else: +20 20 | b = 2 +21 21 | continue +22 |- elif z: + 22 |+ if z: +23 23 | c = 2 +24 24 | else: +25 25 | c = 3 + +RET507.py:36:9: RET507 [*] Unnecessary `else` after `continue` statement + | +34 | if i < y: # [no-else-continue] +35 | continue +36 | else: + | ^^^^ RET507 +37 | a = z + | + = help: Remove unnecessary `else` + +ℹ Safe fix +33 33 | for i in x: +34 34 | if i < y: # [no-else-continue] +35 35 | continue +36 |- else: +37 |- a = z + 36 |+ a = z +38 37 | +39 38 | +40 39 | def foo3(x, y, z): + +RET507.py:47:13: RET507 [*] Unnecessary `else` after `continue` statement + | +45 | b = 2 +46 | continue +47 | else: + | ^^^^ RET507 +48 | c = 3 +49 | continue + | + = help: Remove unnecessary `else` + +ℹ Safe fix +44 44 | if z: # [no-else-continue] +45 45 | b = 2 +46 46 | continue +47 |- else: +48 |- c = 3 +49 |- continue + 47 |+ c = 3 + 48 |+ continue +50 49 | else: +51 50 | d = 4 +52 51 | continue + +RET507.py:63:9: RET507 [*] Unnecessary `else` after `continue` statement + | +61 | b = 2 +62 | continue +63 | else: + | ^^^^ RET507 +64 | c = 3 +65 | continue + | + = help: Remove unnecessary `else` + +ℹ Safe fix +60 60 | else: +61 61 | b = 2 +62 62 | continue +63 |- else: +64 |- c = 3 + 63 |+ c = 3 +65 64 | continue +66 65 | +67 66 | + +RET507.py:74:13: RET507 [*] Unnecessary `else` after `continue` statement + | +72 | a = 4 +73 | continue +74 | else: + | ^^^^ RET507 +75 | b = 2 +76 | else: + | + = help: Remove unnecessary `else` + +ℹ Safe fix +71 71 | if y: # [no-else-continue] +72 72 | a = 4 +73 73 | continue +74 |- else: +75 |- b = 2 + 74 |+ b = 2 +76 75 | else: +77 76 | c = 3 +78 77 | continue + +RET507.py:85:9: RET507 [*] Unnecessary `else` after `continue` statement + | +83 | if x: # [no-else-continue] +84 | continue +85 | else: + | ^^^^ RET507 +86 | try: +87 | return + | + = help: Remove unnecessary `else` + +ℹ Safe fix +82 82 | for i in range(10): +83 83 | if x: # [no-else-continue] +84 84 | continue +85 |- else: +86 |- try: +87 |- return +88 |- except ValueError: +89 |- continue + 85 |+ try: + 86 |+ return + 87 |+ except ValueError: + 88 |+ continue +90 89 | +91 90 | +92 91 | def bar1(x, y, z): + + diff --git a/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__preview__RET508_RET508.py.snap b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__preview__RET508_RET508.py.snap new file mode 100644 index 0000000000000..f35bda0f4e39e --- /dev/null +++ b/crates/ruff_linter/src/rules/flake8_return/snapshots/ruff_linter__rules__flake8_return__tests__preview__RET508_RET508.py.snap @@ -0,0 +1,181 @@ +--- +source: crates/ruff_linter/src/rules/flake8_return/mod.rs +--- +RET508.py:8:9: RET508 [*] Unnecessary `elif` after `break` statement + | + 6 | if i > y: # [no-else-break] + 7 | break + 8 | elif i > w: + | ^^^^ RET508 + 9 | break +10 | else: + | + = help: Remove unnecessary `elif` + +ℹ Safe fix +5 5 | for i in x: +6 6 | if i > y: # [no-else-break] +7 7 | break +8 |- elif i > w: + 8 |+ if i > w: +9 9 | break +10 10 | else: +11 11 | a = z + +RET508.py:22:9: RET508 [*] Unnecessary `elif` after `break` statement + | +20 | b = 2 +21 | break +22 | elif z: + | ^^^^ RET508 +23 | c = 2 +24 | else: + | + = help: Remove unnecessary `elif` + +ℹ Safe fix +19 19 | else: +20 20 | b = 2 +21 21 | break +22 |- elif z: + 22 |+ if z: +23 23 | c = 2 +24 24 | else: +25 25 | c = 3 + +RET508.py:33:9: RET508 [*] Unnecessary `else` after `break` statement + | +31 | if i > y: # [no-else-break] +32 | break +33 | else: + | ^^^^ RET508 +34 | a = z + | + = help: Remove unnecessary `else` + +ℹ Safe fix +30 30 | for i in x: +31 31 | if i > y: # [no-else-break] +32 32 | break +33 |- else: +34 |- a = z + 33 |+ a = z +35 34 | +36 35 | +37 36 | def foo3(x, y, z): + +RET508.py:44:13: RET508 [*] Unnecessary `else` after `break` statement + | +42 | b = 2 +43 | break +44 | else: + | ^^^^ RET508 +45 | c = 3 +46 | break + | + = help: Remove unnecessary `else` + +ℹ Safe fix +41 41 | if z: # [no-else-break] +42 42 | b = 2 +43 43 | break +44 |- else: +45 |- c = 3 +46 |- break + 44 |+ c = 3 + 45 |+ break +47 46 | else: +48 47 | d = 4 +49 48 | break + +RET508.py:60:9: RET508 [*] Unnecessary `else` after `break` statement + | +58 | b = 2 +59 | break +60 | else: + | ^^^^ RET508 +61 | c = 3 +62 | break + | + = help: Remove unnecessary `else` + +ℹ Safe fix +57 57 | else: +58 58 | b = 2 +59 59 | break +60 |- else: +61 |- c = 3 + 60 |+ c = 3 +62 61 | break +63 62 | +64 63 | + +RET508.py:71:13: RET508 [*] Unnecessary `else` after `break` statement + | +69 | a = 4 +70 | break +71 | else: + | ^^^^ RET508 +72 | b = 2 +73 | else: + | + = help: Remove unnecessary `else` + +ℹ Safe fix +68 68 | if y: # [no-else-break] +69 69 | a = 4 +70 70 | break +71 |- else: +72 |- b = 2 + 71 |+ b = 2 +73 72 | else: +74 73 | c = 3 +75 74 | break + +RET508.py:82:9: RET508 [*] Unnecessary `else` after `break` statement + | +80 | if x: # [no-else-break] +81 | break +82 | else: + | ^^^^ RET508 +83 | try: +84 | return + | + = help: Remove unnecessary `else` + +ℹ Safe fix +79 79 | for i in range(10): +80 80 | if x: # [no-else-break] +81 81 | break +82 |- else: +83 |- try: +84 |- return +85 |- except ValueError: +86 |- break + 82 |+ try: + 83 |+ return + 84 |+ except ValueError: + 85 |+ break +87 86 | +88 87 | +89 88 | ### + +RET508.py:158:13: RET508 [*] Unnecessary `else` after `break` statement + | +156 | if i > w: +157 | break +158 | else: + | ^^^^ RET508 +159 | a = z + | + = help: Remove unnecessary `else` + +ℹ Safe fix +155 155 | else: +156 156 | if i > w: +157 157 | break +158 |- else: +159 |- a = z + 158 |+ a = z + +