-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Summary add `potential-index-error` rule (`PLE0643`) See: #970 ## Test Plan `cargo test`
- Loading branch information
1 parent
866bea6
commit 49a445a
Showing
8 changed files
with
131 additions
and
0 deletions.
There are no files selected for viewing
9 changes: 9 additions & 0 deletions
9
crates/ruff_linter/resources/test/fixtures/pylint/potential_index_error.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
print([1, 2, 3][3]) # PLE0643 | ||
print([1, 2, 3][-4]) # PLE0643 | ||
print([1, 2, 3][999999999999999999999999999999999999999999]) # PLE0643 | ||
print([1, 2, 3][-999999999999999999999999999999999999999999]) # PLE0643 | ||
|
||
print([1, 2, 3][2]) # OK | ||
print([1, 2, 3][0]) # OK | ||
print([1, 2, 3][-3]) # OK | ||
print([1, 2, 3][3:]) # OK |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
crates/ruff_linter/src/rules/pylint/rules/potential_index_error.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
use ruff_diagnostics::{Diagnostic, Violation}; | ||
use ruff_macros::{derive_message_formats, violation}; | ||
use ruff_python_ast::{self as ast, Expr}; | ||
use ruff_text_size::Ranged; | ||
|
||
use crate::checkers::ast::Checker; | ||
|
||
/// ## What it does | ||
/// Checks for hard-coded sequence accesses that are known to be out of bounds. | ||
/// | ||
/// ## Why is this bad? | ||
/// Attempting to access a sequence with an out-of-bounds index will cause an | ||
/// `IndexError` to be raised at runtime. When the sequence and index are | ||
/// defined statically (e.g., subscripts on `list` and `tuple` literals, with | ||
/// integer indexes), such errors can be detected ahead of time. | ||
/// | ||
/// ## Example | ||
/// ```python | ||
/// print([0, 1, 2][3]) | ||
/// ``` | ||
#[violation] | ||
pub struct PotentialIndexError; | ||
|
||
impl Violation for PotentialIndexError { | ||
#[derive_message_formats] | ||
fn message(&self) -> String { | ||
format!("Potential IndexError") | ||
} | ||
} | ||
|
||
/// PLE0643 | ||
pub(crate) fn potential_index_error(checker: &mut Checker, value: &Expr, slice: &Expr) { | ||
// Determine the length of the sequence. | ||
let length = match value { | ||
Expr::Tuple(ast::ExprTuple { elts, .. }) | Expr::List(ast::ExprList { elts, .. }) => { | ||
match i64::try_from(elts.len()) { | ||
Ok(length) => length, | ||
Err(_) => return, | ||
} | ||
} | ||
_ => { | ||
return; | ||
} | ||
}; | ||
|
||
// Determine the index value. | ||
let index = match slice { | ||
Expr::NumberLiteral(ast::ExprNumberLiteral { | ||
value: ast::Number::Int(number_value), | ||
.. | ||
}) => number_value.as_i64(), | ||
Expr::UnaryOp(ast::ExprUnaryOp { | ||
op: ast::UnaryOp::USub, | ||
operand, | ||
.. | ||
}) => match operand.as_ref() { | ||
Expr::NumberLiteral(ast::ExprNumberLiteral { | ||
value: ast::Number::Int(number_value), | ||
.. | ||
}) => number_value.as_i64().map(|number| -number), | ||
_ => return, | ||
}, | ||
_ => return, | ||
}; | ||
|
||
// Emit a diagnostic if the index is out of bounds. If the index can't be represented as an | ||
// `i64`, but the length _can_, then the index is definitely out of bounds. | ||
if index.map_or(true, |index| index >= length || index < -length) { | ||
checker | ||
.diagnostics | ||
.push(Diagnostic::new(PotentialIndexError, slice.range())); | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
...pylint/snapshots/ruff_linter__rules__pylint__tests__PLE0643_potential_index_error.py.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
--- | ||
source: crates/ruff_linter/src/rules/pylint/mod.rs | ||
--- | ||
potential_index_error.py:1:17: PLE0643 Potential IndexError | ||
| | ||
1 | print([1, 2, 3][3]) # PLE0643 | ||
| ^ PLE0643 | ||
2 | print([1, 2, 3][-4]) # PLE0643 | ||
3 | print([1, 2, 3][999999999999999999999999999999999999999999]) # PLE0643 | ||
| | ||
|
||
potential_index_error.py:2:17: PLE0643 Potential IndexError | ||
| | ||
1 | print([1, 2, 3][3]) # PLE0643 | ||
2 | print([1, 2, 3][-4]) # PLE0643 | ||
| ^^ PLE0643 | ||
3 | print([1, 2, 3][999999999999999999999999999999999999999999]) # PLE0643 | ||
4 | print([1, 2, 3][-999999999999999999999999999999999999999999]) # PLE0643 | ||
| | ||
|
||
potential_index_error.py:3:17: PLE0643 Potential IndexError | ||
| | ||
1 | print([1, 2, 3][3]) # PLE0643 | ||
2 | print([1, 2, 3][-4]) # PLE0643 | ||
3 | print([1, 2, 3][999999999999999999999999999999999999999999]) # PLE0643 | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLE0643 | ||
4 | print([1, 2, 3][-999999999999999999999999999999999999999999]) # PLE0643 | ||
| | ||
|
||
potential_index_error.py:4:17: PLE0643 Potential IndexError | ||
| | ||
2 | print([1, 2, 3][-4]) # PLE0643 | ||
3 | print([1, 2, 3][999999999999999999999999999999999999999999]) # PLE0643 | ||
4 | print([1, 2, 3][-999999999999999999999999999999999999999999]) # PLE0643 | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLE0643 | ||
5 | | ||
6 | print([1, 2, 3][2]) # OK | ||
| | ||
|
||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.