ruff/crates/ruff_python_semantic/src/cfg/mod.rs
Dylan d401a5440e
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.
2025-04-03 08:30:29 -05:00

62 lines
1.8 KiB
Rust

pub mod graph;
pub mod visualize;
#[cfg(test)]
mod tests {
use std::fmt::Write;
use std::fs;
use std::path::PathBuf;
use crate::cfg::graph::build_cfg;
use crate::cfg::visualize::draw_cfg;
use insta;
use ruff_python_parser::parse_module;
use ruff_text_size::Ranged;
use test_case::test_case;
#[test_case("no_flow.py")]
#[test_case("jumps.py")]
fn control_flow_graph(filename: &str) {
let path = PathBuf::from("resources/test/fixtures/cfg").join(filename);
let source = fs::read_to_string(path).expect("failed to read file");
let stmts = parse_module(&source)
.unwrap_or_else(|err| panic!("failed to parse source: '{source}': {err}"))
.into_suite();
let mut output = String::new();
for (i, stmt) in stmts.into_iter().enumerate() {
let func = stmt.as_function_def_stmt().expect(
"Snapshot test for control flow graph should consist only of function definitions",
);
let cfg = build_cfg(&func.body);
let mermaid_graph = draw_cfg(cfg, &source);
writeln!(
output,
"## Function {}\n\
### Source\n\
```python\n\
{}\n\
```\n\n\
### Control Flow Graph\n\
```mermaid\n\
{}\n\
```\n",
i,
&source[func.range()],
mermaid_graph,
)
.unwrap();
}
insta::with_settings!({
omit_expression => true,
input_file => filename,
description => "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
}, {
insta::assert_snapshot!(format!("{filename}.md"), output);
});
}
}