Skip to content

Commit

Permalink
Extends B002 to detect unary prefix decrement operators (#5998)
Browse files Browse the repository at this point in the history
## Summary

Extends `B002` to detect unary decrement prefix operators.

Closes #5992.

## Test Plan

`cargo test`
  • Loading branch information
tjkuson authored Jul 23, 2023
1 parent 1776cbd commit e7f5121
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 74 deletions.
12 changes: 8 additions & 4 deletions crates/ruff/resources/test/fixtures/flake8_bugbear/B002.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
"""
Should emit:
B002 - on lines 15 and 20
B002 - on lines 18, 19, and 24
"""


def this_is_all_fine(n):
x = n + 1
y = 1 + n
z = +x + y
return +z
a = n - 1
b = 1 - n
c = -a - b
return +z, -c


def this_is_buggy(n):
x = ++n
return x
y = --n
return x, y


def this_is_buggy_too(n):
return ++n
return ++n, --n
6 changes: 4 additions & 2 deletions crates/ruff/src/checkers/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3302,8 +3302,10 @@ where
check_not_is,
);
}
if self.enabled(Rule::UnaryPrefixIncrement) {
flake8_bugbear::rules::unary_prefix_increment(self, expr, *op, operand);
if self.enabled(Rule::UnaryPrefixIncrementDecrement) {
flake8_bugbear::rules::unary_prefix_increment_decrement(
self, expr, *op, operand,
);
}
if self.enabled(Rule::NegateEqualOp) {
flake8_simplify::rules::negation_with_equal_op(self, expr, *op, operand);
Expand Down
2 changes: 1 addition & 1 deletion crates/ruff/src/codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
(Flake8Builtins, "003") => (RuleGroup::Unspecified, rules::flake8_builtins::rules::BuiltinAttributeShadowing),

// flake8-bugbear
(Flake8Bugbear, "002") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::UnaryPrefixIncrement),
(Flake8Bugbear, "002") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::UnaryPrefixIncrementDecrement),
(Flake8Bugbear, "003") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::AssignmentToOsEnviron),
(Flake8Bugbear, "004") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::UnreliableCallableCheck),
(Flake8Bugbear, "005") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::StripWithMultiCharacters),
Expand Down
2 changes: 1 addition & 1 deletion crates/ruff/src/rules/flake8_bugbear/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ mod tests {
#[test_case(Rule::SetAttrWithConstant, Path::new("B009_B010.py"))]
#[test_case(Rule::StarArgUnpackingAfterKeywordArg, Path::new("B026.py"))]
#[test_case(Rule::StripWithMultiCharacters, Path::new("B005.py"))]
#[test_case(Rule::UnaryPrefixIncrement, Path::new("B002.py"))]
#[test_case(Rule::UnaryPrefixIncrementDecrement, Path::new("B002.py"))]
#[test_case(Rule::UnintentionalTypeAnnotation, Path::new("B032.py"))]
#[test_case(Rule::UnreliableCallableCheck, Path::new("B004.py"))]
#[test_case(Rule::UnusedLoopControlVariable, Path::new("B007.py"))]
Expand Down
4 changes: 2 additions & 2 deletions crates/ruff/src/rules/flake8_bugbear/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub(crate) use reuse_of_groupby_generator::*;
pub(crate) use setattr_with_constant::*;
pub(crate) use star_arg_unpacking_after_keyword_arg::*;
pub(crate) use strip_with_multi_characters::*;
pub(crate) use unary_prefix_increment::*;
pub(crate) use unary_prefix_increment_decrement::*;
pub(crate) use unintentional_type_annotation::*;
pub(crate) use unreliable_callable_check::*;
pub(crate) use unused_loop_control_variable::*;
Expand Down Expand Up @@ -57,7 +57,7 @@ mod reuse_of_groupby_generator;
mod setattr_with_constant;
mod star_arg_unpacking_after_keyword_arg;
mod strip_with_multi_characters;
mod unary_prefix_increment;
mod unary_prefix_increment_decrement;
mod unintentional_type_annotation;
mod unreliable_callable_check;
mod unused_loop_control_variable;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use rustpython_parser::ast::{self, Expr, Ranged, UnaryOp};

use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};

use crate::checkers::ast::Checker;

/// ## What it does
/// Checks for the attempted use of the unary prefix increment (`++`) or
/// decrement operator (`--`).
///
/// ## Why is this bad?
/// Python does not support the unary prefix increment or decrement operator.
/// Writing `++n` is equivalent to `+(+(n))` and writing `--n` is equivalent to
/// `-(-(n))`. In both cases, it is equivalent to `n`.
///
/// ## Example
/// ```python
/// ++x
/// --y
/// ```
///
/// Use instead:
/// ```python
/// x += 1
/// y -= 1
/// ```
///
/// ## References
/// - [Python documentation: Unary arithmetic and bitwise operations](https://docs.python.org/3/reference/expressions.html#unary-arithmetic-and-bitwise-operations)
/// - [Python documentation: Augmented assignment statements](https://docs.python.org/3/reference/simple_stmts.html#augmented-assignment-statements)
#[violation]
pub struct UnaryPrefixIncrementDecrement {
operator: UnaryPrefixOperatorType,
}

impl Violation for UnaryPrefixIncrementDecrement {
#[derive_message_formats]
fn message(&self) -> String {
let UnaryPrefixIncrementDecrement { operator } = self;
match operator {
UnaryPrefixOperatorType::Increment => {
format!("Python does not support the unary prefix increment operator (`++`)")
}
UnaryPrefixOperatorType::Decrement => {
format!("Python does not support the unary prefix decrement operator (`--`)")
}
}
}
}

/// B002
pub(crate) fn unary_prefix_increment_decrement(
checker: &mut Checker,
expr: &Expr,
op: UnaryOp,
operand: &Expr,
) {
let Expr::UnaryOp(ast::ExprUnaryOp { op: nested_op, .. }) = operand else {
return;
};
match (op, nested_op) {
(UnaryOp::UAdd, UnaryOp::UAdd) => {
checker.diagnostics.push(Diagnostic::new(
UnaryPrefixIncrementDecrement {
operator: UnaryPrefixOperatorType::Increment,
},
expr.range(),
));
}
(UnaryOp::USub, UnaryOp::USub) => {
checker.diagnostics.push(Diagnostic::new(
UnaryPrefixIncrementDecrement {
operator: UnaryPrefixOperatorType::Decrement,
},
expr.range(),
));
}
_ => {}
}
}

#[derive(Debug, PartialEq, Eq, Copy, Clone)]
enum UnaryPrefixOperatorType {
Increment,
Decrement,
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
---
source: crates/ruff/src/rules/flake8_bugbear/mod.rs
---
B002.py:15:9: B002 Python does not support the unary prefix increment
B002.py:18:9: B002 Python does not support the unary prefix increment operator (`++`)
|
14 | def this_is_buggy(n):
15 | x = ++n
17 | def this_is_buggy(n):
18 | x = ++n
| ^^^ B002
16 | return x
19 | y = --n
20 | return x, y
|

B002.py:20:12: B002 Python does not support the unary prefix increment
B002.py:19:9: B002 Python does not support the unary prefix decrement operator (`--`)
|
19 | def this_is_buggy_too(n):
20 | return ++n
17 | def this_is_buggy(n):
18 | x = ++n
19 | y = --n
| ^^^ B002
20 | return x, y
|

B002.py:24:12: B002 Python does not support the unary prefix increment operator (`++`)
|
23 | def this_is_buggy_too(n):
24 | return ++n, --n
| ^^^ B002
|

B002.py:24:17: B002 Python does not support the unary prefix decrement operator (`--`)
|
23 | def this_is_buggy_too(n):
24 | return ++n, --n
| ^^^ B002
|


0 comments on commit e7f5121

Please sign in to comment.