mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 21:05:08 +00:00
[ruff
] Needless else
clause (RUF047
) (#15051)
Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
parent
4cfa355519
commit
c616650dfa
14 changed files with 876 additions and 7 deletions
49
crates/ruff_linter/resources/test/fixtures/ruff/RUF047_for.py
vendored
Normal file
49
crates/ruff_linter/resources/test/fixtures/ruff/RUF047_for.py
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
### Errors
|
||||
|
||||
for _ in range(0):
|
||||
loop_body_is_not_checked()
|
||||
break
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
for this in comment:
|
||||
belongs_to() # `for`
|
||||
else:
|
||||
...
|
||||
|
||||
|
||||
for of in course():
|
||||
this()
|
||||
else:
|
||||
...
|
||||
# this comment does not belong to the else
|
||||
|
||||
|
||||
### No errors
|
||||
|
||||
for this in second_comment:
|
||||
belongs() # to
|
||||
# `else`
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
for _and in so:
|
||||
does()
|
||||
# this
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
for of in course():
|
||||
this()
|
||||
else:
|
||||
... # too
|
||||
|
||||
|
||||
for of in course():
|
||||
this()
|
||||
else:
|
||||
...
|
||||
# too
|
84
crates/ruff_linter/resources/test/fixtures/ruff/RUF047_if.py
vendored
Normal file
84
crates/ruff_linter/resources/test/fixtures/ruff/RUF047_if.py
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
### Errors
|
||||
|
||||
if False:
|
||||
condition_is_not_evaluated()
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
if this_comment():
|
||||
belongs_to() # `if`
|
||||
else:
|
||||
...
|
||||
|
||||
|
||||
if elif_is():
|
||||
treated()
|
||||
elif the_same():
|
||||
as_if()
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
if this_second_comment():
|
||||
belongs() # to
|
||||
# `if`
|
||||
else:
|
||||
pass
|
||||
|
||||
if this_second_comment():
|
||||
belongs() # to
|
||||
# `if`
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
if of_course():
|
||||
this()
|
||||
else:
|
||||
...
|
||||
# this comment doesn't belong to the if
|
||||
|
||||
|
||||
if of_course: this()
|
||||
else: ...
|
||||
|
||||
|
||||
if of_course:
|
||||
this() # comment
|
||||
else: ...
|
||||
|
||||
|
||||
def nested():
|
||||
if a:
|
||||
b()
|
||||
else:
|
||||
...
|
||||
|
||||
|
||||
### No errors
|
||||
|
||||
|
||||
if this_second_comment():
|
||||
belongs() # to
|
||||
# `else`
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
if of_course():
|
||||
this()
|
||||
else:
|
||||
... # too
|
||||
|
||||
|
||||
if of_course():
|
||||
this()
|
||||
else:
|
||||
...
|
||||
# comment
|
||||
|
||||
|
||||
if of_course:
|
||||
this() # comment
|
||||
else: ... # trailing
|
76
crates/ruff_linter/resources/test/fixtures/ruff/RUF047_try.py
vendored
Normal file
76
crates/ruff_linter/resources/test/fixtures/ruff/RUF047_try.py
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
### Errors
|
||||
|
||||
try:
|
||||
raise try_body_is_not_checked()
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
this()
|
||||
except comment:
|
||||
belongs()
|
||||
except:
|
||||
to() # `except`
|
||||
else:
|
||||
...
|
||||
|
||||
|
||||
try:
|
||||
of_course()
|
||||
except:
|
||||
this()
|
||||
else:
|
||||
...
|
||||
# This comment belongs to finally
|
||||
finally:
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
of_course()
|
||||
except:
|
||||
this()
|
||||
else:
|
||||
...
|
||||
# This comment belongs to the statement coming after the else
|
||||
|
||||
|
||||
### No errors
|
||||
|
||||
try:
|
||||
this()
|
||||
except (second, comment):
|
||||
belongs() # to
|
||||
# `else`
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
and_so()
|
||||
except:
|
||||
does()
|
||||
# this
|
||||
else:
|
||||
...
|
||||
|
||||
|
||||
try:
|
||||
of_course()
|
||||
except:
|
||||
this()
|
||||
else:
|
||||
... # too
|
||||
|
||||
try:
|
||||
of_course()
|
||||
except:
|
||||
this()
|
||||
else:
|
||||
...
|
||||
# This comment belongs to else
|
||||
finally:
|
||||
pass
|
49
crates/ruff_linter/resources/test/fixtures/ruff/RUF047_while.py
vendored
Normal file
49
crates/ruff_linter/resources/test/fixtures/ruff/RUF047_while.py
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
### No errors
|
||||
|
||||
while True:
|
||||
loop_body_is_not_checked()
|
||||
break
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
while this_comment:
|
||||
belongs_to() # `for`
|
||||
else:
|
||||
...
|
||||
|
||||
|
||||
while of_course():
|
||||
this()
|
||||
else:
|
||||
...
|
||||
# this comment belongs to the statement coming after the else
|
||||
|
||||
|
||||
### No errors
|
||||
|
||||
while this_second_comment:
|
||||
belongs() # to
|
||||
# `else`
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
while and_so:
|
||||
does()
|
||||
# this
|
||||
else:
|
||||
...
|
||||
|
||||
|
||||
while of_course():
|
||||
this()
|
||||
else:
|
||||
... # too
|
||||
|
||||
while of_course():
|
||||
this()
|
||||
else:
|
||||
...
|
||||
# this comment belongs to the else
|
||||
|
|
@ -1240,6 +1240,9 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
if checker.enabled(Rule::IfKeyInDictDel) {
|
||||
ruff::rules::if_key_in_dict_del(checker, if_);
|
||||
}
|
||||
if checker.enabled(Rule::NeedlessElse) {
|
||||
ruff::rules::needless_else(checker, if_.into());
|
||||
}
|
||||
}
|
||||
Stmt::Assert(
|
||||
assert_stmt @ ast::StmtAssert {
|
||||
|
@ -1349,6 +1352,9 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
if checker.enabled(Rule::AsyncBusyWait) {
|
||||
flake8_async::rules::async_busy_wait(checker, while_stmt);
|
||||
}
|
||||
if checker.enabled(Rule::NeedlessElse) {
|
||||
ruff::rules::needless_else(checker, while_stmt.into());
|
||||
}
|
||||
}
|
||||
Stmt::For(
|
||||
for_stmt @ ast::StmtFor {
|
||||
|
@ -1438,14 +1444,19 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
refurb::rules::for_loop_writes(checker, for_stmt);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::NeedlessElse) {
|
||||
ruff::rules::needless_else(checker, for_stmt.into());
|
||||
}
|
||||
Stmt::Try(ast::StmtTry {
|
||||
}
|
||||
Stmt::Try(
|
||||
try_stmt @ ast::StmtTry {
|
||||
body,
|
||||
handlers,
|
||||
orelse,
|
||||
finalbody,
|
||||
..
|
||||
}) => {
|
||||
},
|
||||
) => {
|
||||
if checker.enabled(Rule::TooManyNestedBlocks) {
|
||||
pylint::rules::too_many_nested_blocks(checker, stmt);
|
||||
}
|
||||
|
@ -1512,6 +1523,9 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
if checker.enabled(Rule::ErrorInsteadOfException) {
|
||||
tryceratops::rules::error_instead_of_exception(checker, handlers);
|
||||
}
|
||||
if checker.enabled(Rule::NeedlessElse) {
|
||||
ruff::rules::needless_else(checker, try_stmt.into());
|
||||
}
|
||||
}
|
||||
Stmt::Assign(assign @ ast::StmtAssign { targets, value, .. }) => {
|
||||
if checker.enabled(Rule::SelfOrClsAssignment) {
|
||||
|
|
|
@ -997,6 +997,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
|||
(Ruff, "041") => (RuleGroup::Preview, rules::ruff::rules::UnnecessaryNestedLiteral),
|
||||
(Ruff, "043") => (RuleGroup::Preview, rules::ruff::rules::PytestRaisesAmbiguousPattern),
|
||||
(Ruff, "046") => (RuleGroup::Preview, rules::ruff::rules::UnnecessaryCastToInt),
|
||||
(Ruff, "047") => (RuleGroup::Preview, rules::ruff::rules::NeedlessElse),
|
||||
(Ruff, "048") => (RuleGroup::Preview, rules::ruff::rules::MapIntVersionParsing),
|
||||
(Ruff, "049") => (RuleGroup::Preview, rules::ruff::rules::DataclassEnum),
|
||||
(Ruff, "051") => (RuleGroup::Preview, rules::ruff::rules::IfKeyInDictDel),
|
||||
|
|
|
@ -79,6 +79,10 @@ mod tests {
|
|||
#[test_case(Rule::InvalidAssertMessageLiteralArgument, Path::new("RUF040.py"))]
|
||||
#[test_case(Rule::UnnecessaryNestedLiteral, Path::new("RUF041.py"))]
|
||||
#[test_case(Rule::UnnecessaryNestedLiteral, Path::new("RUF041.pyi"))]
|
||||
#[test_case(Rule::NeedlessElse, Path::new("RUF047_if.py"))]
|
||||
#[test_case(Rule::NeedlessElse, Path::new("RUF047_for.py"))]
|
||||
#[test_case(Rule::NeedlessElse, Path::new("RUF047_while.py"))]
|
||||
#[test_case(Rule::NeedlessElse, Path::new("RUF047_try.py"))]
|
||||
#[test_case(Rule::IfKeyInDictDel, Path::new("RUF051.py"))]
|
||||
#[test_case(Rule::UsedDummyVariable, Path::new("RUF052.py"))]
|
||||
#[test_case(Rule::FalsyDictGetFallback, Path::new("RUF056.py"))]
|
||||
|
|
|
@ -21,6 +21,7 @@ pub(crate) use missing_fstring_syntax::*;
|
|||
pub(crate) use mutable_class_default::*;
|
||||
pub(crate) use mutable_dataclass_default::*;
|
||||
pub(crate) use mutable_fromkeys_value::*;
|
||||
pub(crate) use needless_else::*;
|
||||
pub(crate) use never_union::*;
|
||||
pub(crate) use none_not_at_end_of_union::*;
|
||||
pub(crate) use parenthesize_chained_operators::*;
|
||||
|
@ -75,6 +76,7 @@ mod missing_fstring_syntax;
|
|||
mod mutable_class_default;
|
||||
mod mutable_dataclass_default;
|
||||
mod mutable_fromkeys_value;
|
||||
mod needless_else;
|
||||
mod never_union;
|
||||
mod none_not_at_end_of_union;
|
||||
mod parenthesize_chained_operators;
|
||||
|
|
304
crates/ruff_linter/src/rules/ruff/rules/needless_else.rs
Normal file
304
crates/ruff_linter/src/rules/ruff/rules/needless_else.rs
Normal file
|
@ -0,0 +1,304 @@
|
|||
use std::cmp::Ordering;
|
||||
|
||||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
||||
use ruff_python_ast::helpers::comment_indentation_after;
|
||||
use ruff_python_ast::whitespace::indentation;
|
||||
use ruff_python_ast::{Stmt, StmtExpr, StmtFor, StmtIf, StmtTry, StmtWhile};
|
||||
use ruff_python_parser::{TokenKind, Tokens};
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `else` clauses that only contains `pass` and `...` statements.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Such an else clause does nothing and can be removed.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// if foo:
|
||||
/// bar()
|
||||
/// else:
|
||||
/// pass
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// if foo:
|
||||
/// bar()
|
||||
/// ```
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct NeedlessElse;
|
||||
|
||||
impl AlwaysFixableViolation for NeedlessElse {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"Empty `else` clause".to_string()
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> String {
|
||||
"Remove the `else` clause".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// RUF047
|
||||
pub(crate) fn needless_else(checker: &mut Checker, stmt: AnyNodeWithOrElse) {
|
||||
let source = checker.source();
|
||||
let tokens = checker.tokens();
|
||||
|
||||
let else_body = stmt.else_body();
|
||||
|
||||
if !body_is_no_op(else_body) {
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(else_range) = stmt.else_range(tokens) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if else_contains_comments(stmt, else_range, checker) {
|
||||
return;
|
||||
}
|
||||
|
||||
let else_line_start = source.line_start(else_range.start());
|
||||
let else_full_end = source.full_line_end(else_range.end());
|
||||
let remove_range = TextRange::new(else_line_start, else_full_end);
|
||||
|
||||
let edit = Edit::range_deletion(remove_range);
|
||||
let fix = Fix::safe_edit(edit);
|
||||
|
||||
let diagnostic = Diagnostic::new(NeedlessElse, else_range);
|
||||
|
||||
checker.diagnostics.push(diagnostic.with_fix(fix));
|
||||
}
|
||||
|
||||
/// Whether `body` contains only one `pass` or `...` statement.
|
||||
fn body_is_no_op(body: &[Stmt]) -> bool {
|
||||
match body {
|
||||
[Stmt::Pass(_)] => true,
|
||||
[Stmt::Expr(StmtExpr { value, .. })] => value.is_ellipsis_literal_expr(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn else_contains_comments(
|
||||
stmt: AnyNodeWithOrElse,
|
||||
else_range: TextRange,
|
||||
checker: &Checker,
|
||||
) -> bool {
|
||||
let else_full_end = checker.source().full_line_end(else_range.end());
|
||||
let commentable_range = TextRange::new(else_range.start(), else_full_end);
|
||||
|
||||
// A comment after the `else` keyword or after the dummy statement.
|
||||
//
|
||||
// ```python
|
||||
// if ...:
|
||||
// ...
|
||||
// else: # comment
|
||||
// pass # comment
|
||||
// ```
|
||||
if checker.comment_ranges().intersects(commentable_range) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let Some(preceding_stmt) = stmt.body_before_else().last() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let Some(else_last_stmt) = stmt.else_body().last() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
else_branch_has_preceding_comment(preceding_stmt, else_range, checker)
|
||||
|| else_branch_has_trailing_comment(else_last_stmt, else_full_end, checker)
|
||||
}
|
||||
|
||||
/// Returns `true` if the `else` clause header has a leading own-line comment.
|
||||
///
|
||||
/// ```python
|
||||
/// if ...:
|
||||
/// ...
|
||||
/// # some comment
|
||||
/// else:
|
||||
/// pass
|
||||
/// ```
|
||||
fn else_branch_has_preceding_comment(
|
||||
preceding_stmt: &Stmt,
|
||||
else_range: TextRange,
|
||||
checker: &Checker,
|
||||
) -> bool {
|
||||
let (tokens, source) = (checker.tokens(), checker.source());
|
||||
|
||||
let before_else_full_end = source.full_line_end(preceding_stmt.end());
|
||||
|
||||
let preceding_indentation = indentation(source, &preceding_stmt)
|
||||
.unwrap_or_default()
|
||||
.text_len();
|
||||
|
||||
for token in tokens.in_range(TextRange::new(before_else_full_end, else_range.start())) {
|
||||
if token.kind() != TokenKind::Comment {
|
||||
continue;
|
||||
}
|
||||
|
||||
let comment_indentation =
|
||||
comment_indentation_after(preceding_stmt.into(), token.range(), source);
|
||||
|
||||
match comment_indentation.cmp(&preceding_indentation) {
|
||||
// Comment belongs to preceding statement.
|
||||
Ordering::Greater | Ordering::Equal => continue,
|
||||
Ordering::Less => return true,
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns `true` if the `else` branch has a trailing own line comment:
|
||||
///
|
||||
/// ```python
|
||||
/// if ...:
|
||||
/// ...
|
||||
/// else:
|
||||
/// pass
|
||||
/// # some comment
|
||||
/// ```
|
||||
fn else_branch_has_trailing_comment(
|
||||
last_else_stmt: &Stmt,
|
||||
else_full_end: TextSize,
|
||||
checker: &Checker,
|
||||
) -> bool {
|
||||
let (tokens, source) = (checker.tokens(), checker.source());
|
||||
|
||||
let preceding_indentation = indentation(source, &last_else_stmt)
|
||||
.unwrap_or_default()
|
||||
.text_len();
|
||||
|
||||
for token in tokens.after(else_full_end) {
|
||||
match token.kind() {
|
||||
TokenKind::Comment => {
|
||||
let comment_indentation =
|
||||
comment_indentation_after(last_else_stmt.into(), token.range(), source);
|
||||
|
||||
match comment_indentation.cmp(&preceding_indentation) {
|
||||
Ordering::Greater | Ordering::Equal => return true,
|
||||
Ordering::Less => break,
|
||||
}
|
||||
}
|
||||
|
||||
TokenKind::NonLogicalNewline
|
||||
| TokenKind::Newline
|
||||
| TokenKind::Indent
|
||||
| TokenKind::Dedent => {}
|
||||
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) enum AnyNodeWithOrElse<'a> {
|
||||
While(&'a StmtWhile),
|
||||
For(&'a StmtFor),
|
||||
Try(&'a StmtTry),
|
||||
If(&'a StmtIf),
|
||||
}
|
||||
|
||||
impl<'a> AnyNodeWithOrElse<'a> {
|
||||
/// Returns the range from the `else` keyword to the last statement in its block.
|
||||
fn else_range(self, tokens: &Tokens) -> Option<TextRange> {
|
||||
match self {
|
||||
Self::For(_) | Self::While(_) | Self::Try(_) => {
|
||||
let before_else = self.body_before_else();
|
||||
|
||||
let else_body = self.else_body();
|
||||
let end = else_body.last()?.end();
|
||||
|
||||
let start = tokens
|
||||
.in_range(TextRange::new(before_else.last()?.end(), end))
|
||||
.iter()
|
||||
.find(|token| token.kind() == TokenKind::Else)?
|
||||
.start();
|
||||
|
||||
Some(TextRange::new(start, end))
|
||||
}
|
||||
|
||||
Self::If(StmtIf {
|
||||
elif_else_clauses, ..
|
||||
}) => elif_else_clauses
|
||||
.last()
|
||||
.filter(|clause| clause.test.is_none())
|
||||
.map(Ranged::range),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the suite before the else block.
|
||||
fn body_before_else(self) -> &'a [Stmt] {
|
||||
match self {
|
||||
Self::Try(StmtTry { body, handlers, .. }) => handlers
|
||||
.last()
|
||||
.and_then(|handler| handler.as_except_handler())
|
||||
.map(|handler| &handler.body)
|
||||
.unwrap_or(body),
|
||||
|
||||
Self::While(StmtWhile { body, .. }) | Self::For(StmtFor { body, .. }) => body,
|
||||
|
||||
Self::If(StmtIf {
|
||||
body,
|
||||
elif_else_clauses,
|
||||
..
|
||||
}) => elif_else_clauses
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|clause| clause.test.is_some())
|
||||
.map(|clause| &*clause.body)
|
||||
.unwrap_or(body),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `else` suite.
|
||||
/// Defaults to an empty suite if the statement has no `else` block.
|
||||
fn else_body(self) -> &'a [Stmt] {
|
||||
match self {
|
||||
Self::While(StmtWhile { orelse, .. })
|
||||
| Self::For(StmtFor { orelse, .. })
|
||||
| Self::Try(StmtTry { orelse, .. }) => orelse,
|
||||
|
||||
Self::If(StmtIf {
|
||||
elif_else_clauses, ..
|
||||
}) => elif_else_clauses
|
||||
.last()
|
||||
.filter(|clause| clause.test.is_none())
|
||||
.map(|clause| &*clause.body)
|
||||
.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a StmtFor> for AnyNodeWithOrElse<'a> {
|
||||
fn from(value: &'a StmtFor) -> Self {
|
||||
Self::For(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a StmtWhile> for AnyNodeWithOrElse<'a> {
|
||||
fn from(value: &'a StmtWhile) -> Self {
|
||||
Self::While(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a StmtIf> for AnyNodeWithOrElse<'a> {
|
||||
fn from(value: &'a StmtIf) -> Self {
|
||||
Self::If(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a StmtTry> for AnyNodeWithOrElse<'a> {
|
||||
fn from(value: &'a StmtTry) -> Self {
|
||||
Self::Try(value)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/ruff/mod.rs
|
||||
---
|
||||
RUF047_for.py:6:1: RUF047 [*] Empty `else` clause
|
||||
|
|
||||
4 | loop_body_is_not_checked()
|
||||
5 | break
|
||||
6 | / else:
|
||||
7 | | pass
|
||||
| |________^ RUF047
|
||||
|
|
||||
= help: Remove the `else` clause
|
||||
|
||||
ℹ Safe fix
|
||||
3 3 | for _ in range(0):
|
||||
4 4 | loop_body_is_not_checked()
|
||||
5 5 | break
|
||||
6 |-else:
|
||||
7 |- pass
|
||||
8 6 |
|
||||
9 7 |
|
||||
10 8 | for this in comment:
|
||||
|
||||
RUF047_for.py:12:1: RUF047 [*] Empty `else` clause
|
||||
|
|
||||
10 | for this in comment:
|
||||
11 | belongs_to() # `for`
|
||||
12 | / else:
|
||||
13 | | ...
|
||||
| |_______^ RUF047
|
||||
|
|
||||
= help: Remove the `else` clause
|
||||
|
||||
ℹ Safe fix
|
||||
9 9 |
|
||||
10 10 | for this in comment:
|
||||
11 11 | belongs_to() # `for`
|
||||
12 |-else:
|
||||
13 |- ...
|
||||
14 12 |
|
||||
15 13 |
|
||||
16 14 | for of in course():
|
|
@ -0,0 +1,159 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/ruff/mod.rs
|
||||
---
|
||||
RUF047_if.py:5:1: RUF047 [*] Empty `else` clause
|
||||
|
|
||||
3 | if False:
|
||||
4 | condition_is_not_evaluated()
|
||||
5 | / else:
|
||||
6 | | pass
|
||||
| |________^ RUF047
|
||||
|
|
||||
= help: Remove the `else` clause
|
||||
|
||||
ℹ Safe fix
|
||||
2 2 |
|
||||
3 3 | if False:
|
||||
4 4 | condition_is_not_evaluated()
|
||||
5 |-else:
|
||||
6 |- pass
|
||||
7 5 |
|
||||
8 6 |
|
||||
9 7 | if this_comment():
|
||||
|
||||
RUF047_if.py:11:1: RUF047 [*] Empty `else` clause
|
||||
|
|
||||
9 | if this_comment():
|
||||
10 | belongs_to() # `if`
|
||||
11 | / else:
|
||||
12 | | ...
|
||||
| |_______^ RUF047
|
||||
|
|
||||
= help: Remove the `else` clause
|
||||
|
||||
ℹ Safe fix
|
||||
8 8 |
|
||||
9 9 | if this_comment():
|
||||
10 10 | belongs_to() # `if`
|
||||
11 |-else:
|
||||
12 |- ...
|
||||
13 11 |
|
||||
14 12 |
|
||||
15 13 | if elif_is():
|
||||
|
||||
RUF047_if.py:19:1: RUF047 [*] Empty `else` clause
|
||||
|
|
||||
17 | elif the_same():
|
||||
18 | as_if()
|
||||
19 | / else:
|
||||
20 | | pass
|
||||
| |________^ RUF047
|
||||
|
|
||||
= help: Remove the `else` clause
|
||||
|
||||
ℹ Safe fix
|
||||
16 16 | treated()
|
||||
17 17 | elif the_same():
|
||||
18 18 | as_if()
|
||||
19 |-else:
|
||||
20 |- pass
|
||||
21 19 |
|
||||
22 20 |
|
||||
23 21 | if this_second_comment():
|
||||
|
||||
RUF047_if.py:26:1: RUF047 [*] Empty `else` clause
|
||||
|
|
||||
24 | belongs() # to
|
||||
25 | # `if`
|
||||
26 | / else:
|
||||
27 | | pass
|
||||
| |________^ RUF047
|
||||
28 |
|
||||
29 | if this_second_comment():
|
||||
|
|
||||
= help: Remove the `else` clause
|
||||
|
||||
ℹ Safe fix
|
||||
23 23 | if this_second_comment():
|
||||
24 24 | belongs() # to
|
||||
25 25 | # `if`
|
||||
26 |-else:
|
||||
27 |- pass
|
||||
28 26 |
|
||||
29 27 | if this_second_comment():
|
||||
30 28 | belongs() # to
|
||||
|
||||
RUF047_if.py:32:1: RUF047 [*] Empty `else` clause
|
||||
|
|
||||
30 | belongs() # to
|
||||
31 | # `if`
|
||||
32 | / else:
|
||||
33 | | pass
|
||||
| |________^ RUF047
|
||||
|
|
||||
= help: Remove the `else` clause
|
||||
|
||||
ℹ Safe fix
|
||||
29 29 | if this_second_comment():
|
||||
30 30 | belongs() # to
|
||||
31 31 | # `if`
|
||||
32 |-else:
|
||||
33 |- pass
|
||||
34 32 |
|
||||
35 33 |
|
||||
36 34 | if of_course():
|
||||
|
||||
RUF047_if.py:44:1: RUF047 [*] Empty `else` clause
|
||||
|
|
||||
43 | if of_course: this()
|
||||
44 | else: ...
|
||||
| ^^^^^^^^^ RUF047
|
||||
|
|
||||
= help: Remove the `else` clause
|
||||
|
||||
ℹ Safe fix
|
||||
41 41 |
|
||||
42 42 |
|
||||
43 43 | if of_course: this()
|
||||
44 |-else: ...
|
||||
45 44 |
|
||||
46 45 |
|
||||
47 46 | if of_course:
|
||||
|
||||
RUF047_if.py:49:1: RUF047 [*] Empty `else` clause
|
||||
|
|
||||
47 | if of_course:
|
||||
48 | this() # comment
|
||||
49 | else: ...
|
||||
| ^^^^^^^^^ RUF047
|
||||
|
|
||||
= help: Remove the `else` clause
|
||||
|
||||
ℹ Safe fix
|
||||
46 46 |
|
||||
47 47 | if of_course:
|
||||
48 48 | this() # comment
|
||||
49 |-else: ...
|
||||
50 49 |
|
||||
51 50 |
|
||||
52 51 | def nested():
|
||||
|
||||
RUF047_if.py:55:5: RUF047 [*] Empty `else` clause
|
||||
|
|
||||
53 | if a:
|
||||
54 | b()
|
||||
55 | / else:
|
||||
56 | | ...
|
||||
| |___________^ RUF047
|
||||
|
|
||||
= help: Remove the `else` clause
|
||||
|
||||
ℹ Safe fix
|
||||
52 52 | def nested():
|
||||
53 53 | if a:
|
||||
54 54 | b()
|
||||
55 |- else:
|
||||
56 |- ...
|
||||
57 55 |
|
||||
58 56 |
|
||||
59 57 | ### No errors
|
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/ruff/mod.rs
|
||||
---
|
||||
RUF047_try.py:7:1: RUF047 [*] Empty `else` clause
|
||||
|
|
||||
5 | except:
|
||||
6 | pass
|
||||
7 | / else:
|
||||
8 | | pass
|
||||
| |________^ RUF047
|
||||
|
|
||||
= help: Remove the `else` clause
|
||||
|
||||
ℹ Safe fix
|
||||
4 4 | raise try_body_is_not_checked()
|
||||
5 5 | except:
|
||||
6 6 | pass
|
||||
7 |-else:
|
||||
8 |- pass
|
||||
9 7 |
|
||||
10 8 |
|
||||
11 9 | try:
|
||||
|
||||
RUF047_try.py:17:1: RUF047 [*] Empty `else` clause
|
||||
|
|
||||
15 | except:
|
||||
16 | to() # `except`
|
||||
17 | / else:
|
||||
18 | | ...
|
||||
| |_______^ RUF047
|
||||
|
|
||||
= help: Remove the `else` clause
|
||||
|
||||
ℹ Safe fix
|
||||
14 14 | belongs()
|
||||
15 15 | except:
|
||||
16 16 | to() # `except`
|
||||
17 |-else:
|
||||
18 |- ...
|
||||
19 17 |
|
||||
20 18 |
|
||||
21 19 | try:
|
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/ruff/mod.rs
|
||||
---
|
||||
RUF047_while.py:6:1: RUF047 [*] Empty `else` clause
|
||||
|
|
||||
4 | loop_body_is_not_checked()
|
||||
5 | break
|
||||
6 | / else:
|
||||
7 | | pass
|
||||
| |________^ RUF047
|
||||
|
|
||||
= help: Remove the `else` clause
|
||||
|
||||
ℹ Safe fix
|
||||
3 3 | while True:
|
||||
4 4 | loop_body_is_not_checked()
|
||||
5 5 | break
|
||||
6 |-else:
|
||||
7 |- pass
|
||||
8 6 |
|
||||
9 7 |
|
||||
10 8 | while this_comment:
|
||||
|
||||
RUF047_while.py:12:1: RUF047 [*] Empty `else` clause
|
||||
|
|
||||
10 | while this_comment:
|
||||
11 | belongs_to() # `for`
|
||||
12 | / else:
|
||||
13 | | ...
|
||||
| |_______^ RUF047
|
||||
|
|
||||
= help: Remove the `else` clause
|
||||
|
||||
ℹ Safe fix
|
||||
9 9 |
|
||||
10 10 | while this_comment:
|
||||
11 11 | belongs_to() # `for`
|
||||
12 |-else:
|
||||
13 |- ...
|
||||
14 12 |
|
||||
15 13 |
|
||||
16 14 | while of_course():
|
1
ruff.schema.json
generated
1
ruff.schema.json
generated
|
@ -3921,6 +3921,7 @@
|
|||
"RUF041",
|
||||
"RUF043",
|
||||
"RUF046",
|
||||
"RUF047",
|
||||
"RUF048",
|
||||
"RUF049",
|
||||
"RUF05",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue