mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 10:48:32 +00:00
Control flow: return
and raise
(#17121)
We add support for `return` and `raise` statements in the control flow graph: we simply add an edge to the terminal block, push the statements to the current block, and proceed. This implementation will have to be modified somewhat once we add support for `try` statements - then we will need to check whether to _defer_ the jump. But for now this will do! Also in this PR: We fix the `unreachable` diagnostic range so that it lumps together consecutive unreachable blocks.
This commit is contained in:
parent
755ece0c36
commit
d401a5440e
7 changed files with 194 additions and 14 deletions
|
@ -12,3 +12,19 @@ def no_control_flow_reachable():
|
|||
del c
|
||||
def foo():
|
||||
return
|
||||
|
||||
def after_return():
|
||||
return 1
|
||||
print("unreachable")
|
||||
print("and this")
|
||||
|
||||
def after_raise():
|
||||
raise ValueError
|
||||
print("unreachable")
|
||||
print("and this")
|
||||
|
||||
def multiple_returns():
|
||||
return 1
|
||||
print("unreachable")
|
||||
return 2
|
||||
print("unreachable range should include above return")
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::collections::HashSet;
|
|||
use itertools::Itertools;
|
||||
use ruff_python_ast::{Identifier, Stmt};
|
||||
use ruff_python_semantic::cfg::graph::{build_cfg, BlockId, Condition, ControlFlowGraph};
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
use ruff_text_size::TextRange;
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
||||
|
@ -46,19 +46,24 @@ pub(crate) fn in_function(checker: &Checker, name: &Identifier, body: &[Stmt]) {
|
|||
let cfg = build_cfg(body);
|
||||
let reachable = reachable(&cfg);
|
||||
|
||||
let mut unreachable = (0..cfg.num_blocks())
|
||||
let mut blocks = (0..cfg.num_blocks())
|
||||
.map(BlockId::from_usize)
|
||||
.filter(|block| !reachable.contains(block) && !cfg.stmts(*block).is_empty())
|
||||
.map(|block| cfg.range(block))
|
||||
.sorted_by_key(ruff_text_size::Ranged::start)
|
||||
.filter(|block| !cfg.stmts(*block).is_empty())
|
||||
.sorted_by_key(|block| cfg.range(*block).start())
|
||||
.peekable();
|
||||
|
||||
while let Some(block_range) = unreachable.next() {
|
||||
let start = block_range.start();
|
||||
let mut end = block_range.end();
|
||||
while let Some(next_block) = unreachable.next_if(|nxt| nxt.start() <= end) {
|
||||
end = next_block.end();
|
||||
// Advance past leading reachable blocks
|
||||
while blocks.next_if(|block| reachable.contains(block)).is_some() {}
|
||||
|
||||
while let Some(start_block) = blocks.next() {
|
||||
// Advance to next reachable block
|
||||
let mut end_block = start_block;
|
||||
while let Some(next_block) = blocks.next_if(|block| !reachable.contains(block)) {
|
||||
end_block = next_block;
|
||||
}
|
||||
let start = cfg.range(start_block).start();
|
||||
let end = cfg.range(end_block).end();
|
||||
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
UnreachableCode {
|
||||
name: name.to_string(),
|
||||
|
|
|
@ -1,4 +1,34 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pylint/mod.rs
|
||||
---
|
||||
unreachable.py:18:5: PLW0101 Unreachable code in `after_return`
|
||||
|
|
||||
16 | def after_return():
|
||||
17 | return 1
|
||||
18 | / print("unreachable")
|
||||
19 | | print("and this")
|
||||
| |_____________________^ PLW0101
|
||||
20 |
|
||||
21 | def after_raise():
|
||||
|
|
||||
|
||||
unreachable.py:23:5: PLW0101 Unreachable code in `after_raise`
|
||||
|
|
||||
21 | def after_raise():
|
||||
22 | raise ValueError
|
||||
23 | / print("unreachable")
|
||||
24 | | print("and this")
|
||||
| |_____________________^ PLW0101
|
||||
25 |
|
||||
26 | def multiple_returns():
|
||||
|
|
||||
|
||||
unreachable.py:28:5: PLW0101 Unreachable code in `multiple_returns`
|
||||
|
|
||||
26 | def multiple_returns():
|
||||
27 | return 1
|
||||
28 | / print("unreachable")
|
||||
29 | | return 2
|
||||
30 | | print("unreachable range should include above return")
|
||||
| |__________________________________________________________^ PLW0101
|
||||
|
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue