Control flow graph: setup (#17064)

This PR contains the scaffolding for a new control flow graph
implementation, along with its application to the `unreachable` rule. At
the moment, the implementation is a maximal over-approximation: no
control flow is modeled and all statements are counted as reachable.
With each additional statement type we support, this approximation will
improve.

So this PR just contains:
- A `ControlFlowGraph` struct and builder
- Support for printing the flow graph as a Mermaid graph
- Snapshot tests for the actual graphs
- (a very bad!) reimplementation of `unreachable` using the new structs
- Snapshot tests for `unreachable`

# Instructions for Viewing Mermaid snapshots
Unfortunately I don't know how to convince GitHub to render the Mermaid
graphs in the snapshots. However, you can view these locally in VSCode
if you install an extension that supports Mermaid graphs in Markdown,
and then add this to your `settings.json`:

```json
  "files.associations": {
"*.md.snap": "markdown",
  }
  ```
This commit is contained in:
Dylan 2025-04-01 05:53:42 -05:00 committed by GitHub
parent 0073fd4945
commit aa93005d8d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 775 additions and 6244 deletions

View file

@ -16,7 +16,6 @@ license = { workspace = true }
ruff_annotate_snippets = { workspace = true }
ruff_cache = { workspace = true }
ruff_diagnostics = { workspace = true, features = ["serde"] }
ruff_index = { workspace = true }
ruff_notebook = { workspace = true }
ruff_macros = { workspace = true }
ruff_python_ast = { workspace = true, features = ["serde", "cache"] }

View file

@ -1,263 +1,14 @@
def after_return():
return "reachable"
return "unreachable"
def empty_statement_reachable(): ...
async def also_works_on_async_functions():
return "reachable"
return "unreachable"
def pass_statement_reachable():
pass
def if_always_true():
if True:
return "reachable"
return "unreachable"
def if_always_false():
if False:
return "unreachable"
return "reachable"
def if_elif_always_false():
if False:
return "unreachable"
elif False:
return "also unreachable"
return "reachable"
def if_elif_always_true():
if False:
return "unreachable"
elif True:
return "reachable"
return "also unreachable"
def ends_with_if():
if False:
return "unreachable"
else:
return "reachable"
def infinite_loop():
while True:
continue
return "unreachable"
''' TODO: we could determine these, but we don't yet.
def for_range_return():
for i in range(10):
if i == 5:
return "reachable"
return "unreachable"
def for_range_else():
for i in range(111):
if i == 5:
return "reachable"
else:
return "unreachable"
return "also unreachable"
def for_range_break():
for i in range(13):
return "reachable"
return "unreachable"
def for_range_if_break():
for i in range(1110):
if True:
return "reachable"
return "unreachable"
'''
def match_wildcard(status):
match status:
case _:
return "reachable"
return "unreachable"
def match_case_and_wildcard(status):
match status:
case 1:
return "reachable"
case _:
return "reachable"
return "unreachable"
def raise_exception():
raise Exception
return "unreachable"
def while_false():
while False:
return "unreachable"
return "reachable"
def while_false_else():
while False:
return "unreachable"
else:
return "reachable"
def while_false_else_return():
while False:
return "unreachable"
else:
return "reachable"
return "also unreachable"
def while_true():
while True:
return "reachable"
return "unreachable"
def while_true_else():
while True:
return "reachable"
else:
return "unreachable"
def while_true_else_return():
while True:
return "reachable"
else:
return "unreachable"
return "also unreachable"
def while_false_var_i():
i = 0
while False:
i += 1
return i
def while_true_var_i():
i = 0
while True:
i += 1
return i
def while_infinite():
while True:
pass
return "unreachable"
def while_if_true():
while True:
if True:
return "reachable"
return "unreachable"
def while_break():
while True:
print("reachable")
break
print("unreachable")
return "reachable"
# Test case found in the Bokeh repository that triggered a false positive.
def bokeh1(self, obj: BytesRep) -> bytes:
data = obj["data"]
if isinstance(data, str):
return base64.b64decode(data)
elif isinstance(data, Buffer):
buffer = data
else:
id = data["id"]
if id in self._buffers:
buffer = self._buffers[id]
else:
self.error(f"can't resolve buffer '{id}'")
return buffer.data
# Test case found in the Bokeh repository that triggered a false positive.
def bokeh2(self, host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> None:
self.stop_serving = False
while True:
try:
self.server = HTTPServer((host, port), HtmlOnlyHandler)
self.host = host
self.port = port
break
except OSError:
log.debug(f"port {port} is in use, trying to next one")
port += 1
self.thread = threading.Thread(target=self._run_web_server)
# Test case found in the pandas repository that triggered a false positive.
def _check_basic_constructor(self, empty):
# mat: 2d matrix with shape (3, 2) to input. empty - makes sized
# objects
mat = empty((2, 3), dtype=float)
# 2-D input
frame = DataFrame(mat, columns=["A", "B", "C"], index=[1, 2])
assert len(frame.index) == 2
assert len(frame.columns) == 3
# 1-D input
frame = DataFrame(empty((3,)), columns=["A"], index=[1, 2, 3])
assert len(frame.index) == 3
assert len(frame.columns) == 1
if empty is not np.ones:
msg = r"Cannot convert non-finite values \(NA or inf\) to integer"
with pytest.raises(IntCastingNaNError, match=msg):
DataFrame(mat, columns=["A", "B", "C"], index=[1, 2], dtype=np.int64)
def no_control_flow_reachable():
x = 1
x = 2
class C:
a = 2
c = C()
del c
def foo():
return
else:
frame = DataFrame(
mat, columns=["A", "B", "C"], index=[1, 2], dtype=np.int64
)
assert frame.values.dtype == np.int64
# wrong size axis labels
msg = r"Shape of passed values is \(2, 3\), indices imply \(1, 3\)"
with pytest.raises(ValueError, match=msg):
DataFrame(mat, columns=["A", "B", "C"], index=[1])
msg = r"Shape of passed values is \(2, 3\), indices imply \(2, 2\)"
with pytest.raises(ValueError, match=msg):
DataFrame(mat, columns=["A", "B"], index=[1, 2])
# higher dim raise exception
with pytest.raises(ValueError, match="Must pass 2-d input"):
DataFrame(empty((3, 3, 3)), columns=["A", "B", "C"], index=[1])
# automatic labeling
frame = DataFrame(mat)
tm.assert_index_equal(frame.index, Index(range(2)), exact=True)
tm.assert_index_equal(frame.columns, Index(range(3)), exact=True)
frame = DataFrame(mat, index=[1, 2])
tm.assert_index_equal(frame.columns, Index(range(3)), exact=True)
frame = DataFrame(mat, columns=["A", "B", "C"])
tm.assert_index_equal(frame.index, Index(range(2)), exact=True)
# 0-length axis
frame = DataFrame(empty((0, 3)))
assert len(frame.index) == 0
frame = DataFrame(empty((3, 0)))
assert len(frame.columns) == 0
def after_return():
return "reachable"
print("unreachable")
print("unreachable")
print("unreachable")
print("unreachable")
print("unreachable")
def check_if_url_exists(url: str) -> bool: # type: ignore[return]
return True # uncomment to check URLs
response = requests.head(url, allow_redirects=True)
if response.status_code == 200:
return True
if response.status_code == 404:
return False
console.print(f"[red]Unexpected error received: {response.status_code}[/]")
response.raise_for_status()

View file

@ -349,7 +349,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
}
#[cfg(any(feature = "test-rules", test))]
if checker.enabled(Rule::UnreachableCode) {
checker.report_diagnostics(pylint::rules::in_function(name, body));
pylint::rules::in_function(checker, name, body);
}
if checker.enabled(Rule::ReimplementedOperator) {
refurb::rules::reimplemented_operator(checker, &function_def.into());

View file

@ -1,244 +0,0 @@
---
source: crates/ruff_linter/src/rules/pylint/rules/unreachable.rs
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
---
## Function 0
### Source
```python
def func():
assert True
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Exception raised"]]
block2["assert True\n"]
start --> block2
block2 -- "True" --> block0
block2 -- "else" --> block1
block1 --> return
block0 --> return
```
## Function 1
### Source
```python
def func():
assert False
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Exception raised"]]
block2["assert False\n"]
start --> block2
block2 -- "False" --> block0
block2 -- "else" --> block1
block1 --> return
block0 --> return
```
## Function 2
### Source
```python
def func():
assert True, "oops"
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Exception raised"]]
block2["assert True, #quot;oops#quot;\n"]
start --> block2
block2 -- "True" --> block0
block2 -- "else" --> block1
block1 --> return
block0 --> return
```
## Function 3
### Source
```python
def func():
assert False, "oops"
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Exception raised"]]
block2["assert False, #quot;oops#quot;\n"]
start --> block2
block2 -- "False" --> block0
block2 -- "else" --> block1
block1 --> return
block0 --> return
```
## Function 4
### Source
```python
def func():
y = 2
assert y == 2
assert y > 1
assert y < 3
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Exception raised"]]
block2["assert y < 3\n"]
block3[["Exception raised"]]
block4["assert y > 1\n"]
block5[["Exception raised"]]
block6["y = 2\nassert y == 2\n"]
start --> block6
block6 -- "y == 2" --> block4
block6 -- "else" --> block5
block5 --> return
block4 -- "y > 1" --> block2
block4 -- "else" --> block3
block3 --> return
block2 -- "y < 3" --> block0
block2 -- "else" --> block1
block1 --> return
block0 --> return
```
## Function 5
### Source
```python
def func():
for i in range(3):
assert i < x
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2[["Exception raised"]]
block3["assert i < x\n"]
block4["for i in range(3):
assert i < x\n"]
start --> block4
block4 -- "range(3)" --> block3
block4 -- "else" --> block0
block3 -- "i < x" --> block1
block3 -- "else" --> block2
block2 --> return
block1 --> block4
block0 --> return
```
## Function 6
### Source
```python
def func():
for j in range(3):
x = 2
else:
assert False
return 1
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 1\n"]
block1[["Exception raised"]]
block2["assert False\n"]
block3[["Loop continue"]]
block4["x = 2\n"]
block5["for j in range(3):
x = 2
else:
assert False\n"]
start --> block5
block5 -- "range(3)" --> block4
block5 -- "else" --> block2
block4 --> block3
block3 --> block5
block2 -- "False" --> block0
block2 -- "else" --> block1
block1 --> return
block0 --> return
```
## Function 7
### Source
```python
def func():
for j in range(3):
if j == 2:
print('yay')
break
else:
assert False
return 1
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 1\n"]
block1[["Exception raised"]]
block2["assert False\n"]
block3[["Loop continue"]]
block4["print('yay')\nbreak\n"]
block5["if j == 2:
print('yay')
break\n"]
block6["for j in range(3):
if j == 2:
print('yay')
break
else:
assert False\n"]
start --> block6
block6 -- "range(3)" --> block5
block6 -- "else" --> block2
block5 -- "j == 2" --> block4
block5 -- "else" --> block3
block4 --> block0
block3 --> block6
block2 -- "False" --> block0
block2 -- "else" --> block1
block1 --> return
block0 --> return
```

View file

@ -1,257 +0,0 @@
---
source: crates/ruff_linter/src/rules/pylint/rules/unreachable.rs
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
---
## Function 0
### Source
```python
def func():
async for i in range(5):
print(i)
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["print(i)\n"]
block3["async for i in range(5):
print(i)\n"]
start --> block3
block3 -- "range(5)" --> block2
block3 -- "else" --> block0
block2 --> block1
block1 --> block3
block0 --> return
```
## Function 1
### Source
```python
def func():
async for i in range(20):
print(i)
else:
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 0\n"]
block2[["Loop continue"]]
block3["print(i)\n"]
block4["async for i in range(20):
print(i)
else:
return 0\n"]
start --> block4
block4 -- "range(20)" --> block3
block4 -- "else" --> block1
block3 --> block2
block2 --> block4
block1 --> return
block0 --> return
```
## Function 2
### Source
```python
def func():
async for i in range(10):
if i == 5:
return 1
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 0\n"]
block1[["Loop continue"]]
block2["return 1\n"]
block3["if i == 5:
return 1\n"]
block4["async for i in range(10):
if i == 5:
return 1\n"]
start --> block4
block4 -- "range(10)" --> block3
block4 -- "else" --> block0
block3 -- "i == 5" --> block2
block3 -- "else" --> block1
block2 --> return
block1 --> block4
block0 --> return
```
## Function 3
### Source
```python
def func():
async for i in range(111):
if i == 5:
return 1
else:
return 0
return 2
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 2\n"]
block1["return 0\n"]
block2[["Loop continue"]]
block3["return 1\n"]
block4["if i == 5:
return 1\n"]
block5["async for i in range(111):
if i == 5:
return 1
else:
return 0\n"]
start --> block5
block5 -- "range(111)" --> block4
block5 -- "else" --> block1
block4 -- "i == 5" --> block3
block4 -- "else" --> block2
block3 --> return
block2 --> block5
block1 --> return
block0 --> return
```
## Function 4
### Source
```python
def func():
async for i in range(12):
continue
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["continue\n"]
block3["async for i in range(12):
continue\n"]
start --> block3
block3 -- "range(12)" --> block2
block3 -- "else" --> block0
block2 --> block3
block1 --> block3
block0 --> return
```
## Function 5
### Source
```python
def func():
async for i in range(1110):
if True:
continue
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["continue\n"]
block3["if True:
continue\n"]
block4["async for i in range(1110):
if True:
continue\n"]
start --> block4
block4 -- "range(1110)" --> block3
block4 -- "else" --> block0
block3 -- "True" --> block2
block3 -- "else" --> block1
block2 --> block4
block1 --> block4
block0 --> return
```
## Function 6
### Source
```python
def func():
async for i in range(13):
break
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["break\n"]
block3["async for i in range(13):
break\n"]
start --> block3
block3 -- "range(13)" --> block2
block3 -- "else" --> block0
block2 --> return
block1 --> block3
block0 --> return
```
## Function 7
### Source
```python
def func():
async for i in range(1110):
if True:
break
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["break\n"]
block3["if True:
break\n"]
block4["async for i in range(1110):
if True:
break\n"]
start --> block4
block4 -- "range(1110)" --> block3
block4 -- "else" --> block0
block3 -- "True" --> block2
block3 -- "else" --> block1
block2 --> return
block1 --> block4
block0 --> return
```

View file

@ -1,590 +0,0 @@
---
source: crates/ruff_linter/src/rules/pylint/rules/unreachable.rs
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
---
## Function 0
### Source
```python
def func():
for i in range(5):
print(i)
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["print(i)\n"]
block3["for i in range(5):
print(i)\n"]
start --> block3
block3 -- "range(5)" --> block2
block3 -- "else" --> block0
block2 --> block1
block1 --> block3
block0 --> return
```
## Function 1
### Source
```python
def func():
for i in range(20):
print(i)
else:
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 0\n"]
block2[["Loop continue"]]
block3["print(i)\n"]
block4["for i in range(20):
print(i)
else:
return 0\n"]
start --> block4
block4 -- "range(20)" --> block3
block4 -- "else" --> block1
block3 --> block2
block2 --> block4
block1 --> return
block0 --> return
```
## Function 2
### Source
```python
def func():
for i in range(10):
if i == 5:
return 1
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 0\n"]
block1[["Loop continue"]]
block2["return 1\n"]
block3["if i == 5:
return 1\n"]
block4["for i in range(10):
if i == 5:
return 1\n"]
start --> block4
block4 -- "range(10)" --> block3
block4 -- "else" --> block0
block3 -- "i == 5" --> block2
block3 -- "else" --> block1
block2 --> return
block1 --> block4
block0 --> return
```
## Function 3
### Source
```python
def func():
for i in range(111):
if i == 5:
return 1
else:
return 0
return 2
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 2\n"]
block1["return 0\n"]
block2[["Loop continue"]]
block3["return 1\n"]
block4["if i == 5:
return 1\n"]
block5["for i in range(111):
if i == 5:
return 1
else:
return 0\n"]
start --> block5
block5 -- "range(111)" --> block4
block5 -- "else" --> block1
block4 -- "i == 5" --> block3
block4 -- "else" --> block2
block3 --> return
block2 --> block5
block1 --> return
block0 --> return
```
## Function 4
### Source
```python
def func():
for i in range(12):
continue
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["continue\n"]
block3["for i in range(12):
continue\n"]
start --> block3
block3 -- "range(12)" --> block2
block3 -- "else" --> block0
block2 --> block3
block1 --> block3
block0 --> return
```
## Function 5
### Source
```python
def func():
for i in range(1110):
if True:
continue
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["continue\n"]
block3["if True:
continue\n"]
block4["for i in range(1110):
if True:
continue\n"]
start --> block4
block4 -- "range(1110)" --> block3
block4 -- "else" --> block0
block3 -- "True" --> block2
block3 -- "else" --> block1
block2 --> block4
block1 --> block4
block0 --> return
```
## Function 6
### Source
```python
def func():
for i in range(13):
break
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["break\n"]
block3["for i in range(13):
break\n"]
start --> block3
block3 -- "range(13)" --> block2
block3 -- "else" --> block0
block2 --> return
block1 --> block3
block0 --> return
```
## Function 7
### Source
```python
def func():
for i in range(1110):
if True:
break
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["break\n"]
block3["if True:
break\n"]
block4["for i in range(1110):
if True:
break\n"]
start --> block4
block4 -- "range(1110)" --> block3
block4 -- "else" --> block0
block3 -- "True" --> block2
block3 -- "else" --> block1
block2 --> return
block1 --> block4
block0 --> return
```
## Function 8
### Source
```python
def func():
for i in range(5):
pass
else:
return 1
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 1\n"]
block2[["Loop continue"]]
block3["pass\n"]
block4["for i in range(5):
pass
else:
return 1\n"]
start --> block4
block4 -- "range(5)" --> block3
block4 -- "else" --> block1
block3 --> block2
block2 --> block4
block1 --> return
block0 --> return
```
## Function 9
### Source
```python
def func():
for i in range(5):
pass
else:
return 1
x = 1
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["x = 1\n"]
block1["return 1\n"]
block2[["Loop continue"]]
block3["pass\n"]
block4["for i in range(5):
pass
else:
return 1\n"]
start --> block4
block4 -- "range(5)" --> block3
block4 -- "else" --> block1
block3 --> block2
block2 --> block4
block1 --> return
block0 --> return
```
## Function 10
### Source
```python
def func():
for i in range(5):
pass
else:
pass
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["pass\n"]
block2[["Loop continue"]]
block3["pass\n"]
block4["for i in range(5):
pass
else:
pass\n"]
start --> block4
block4 -- "range(5)" --> block3
block4 -- "else" --> block1
block3 --> block2
block2 --> block4
block1 --> block0
block0 --> return
```
## Function 11
### Source
```python
def func():
for i in range(3):
if i == 2:
assert i is not None
break
else:
raise Exception()
x = 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["x = 0\n"]
block1[["Exception raised"]]
block2["raise Exception()\n"]
block3[["Loop continue"]]
block4["break\n"]
block5[["Exception raised"]]
block6["assert i is not None\n"]
block7["if i == 2:
assert i is not None
break\n"]
block8["for i in range(3):
if i == 2:
assert i is not None
break
else:
raise Exception()\n"]
start --> block8
block8 -- "range(3)" --> block7
block8 -- "else" --> block2
block7 -- "i == 2" --> block6
block7 -- "else" --> block3
block6 -- "i is not None" --> block4
block6 -- "else" --> block5
block5 --> return
block4 --> block0
block3 --> block8
block2 --> block1
block1 --> return
block0 --> return
```
## Function 12
### Source
```python
def func():
for i in range(13):
for i in range(12):
x = 2
if True:
break
x = 3
if True:
break
print('hello')
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["print('hello')\n"]
block1[["Loop continue"]]
block2["break\n"]
block3["x = 3\nif True:
break\n"]
block4[["Loop continue"]]
block5["break\n"]
block6["x = 2\nif True:
break\n"]
block7["for i in range(12):
x = 2
if True:
break\n"]
block8["for i in range(13):
for i in range(12):
x = 2
if True:
break
x = 3
if True:
break\n"]
start --> block8
block8 -- "range(13)" --> block7
block8 -- "else" --> block0
block7 -- "range(12)" --> block6
block7 -- "else" --> block3
block6 -- "True" --> block5
block6 -- "else" --> block4
block5 --> block3
block4 --> block7
block3 -- "True" --> block2
block3 -- "else" --> block1
block2 --> block0
block1 --> block8
block0 --> return
```
## Function 13
### Source
```python
def func():
for i in range(13):
for i in range(12):
x = 2
if True:
continue
x = 3
if True:
break
print('hello')
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["print('hello')\n"]
block1[["Loop continue"]]
block2["break\n"]
block3["x = 3\nif True:
break\n"]
block4[["Loop continue"]]
block5["continue\n"]
block6["x = 2\nif True:
continue\n"]
block7["for i in range(12):
x = 2
if True:
continue\n"]
block8["for i in range(13):
for i in range(12):
x = 2
if True:
continue
x = 3
if True:
break\n"]
start --> block8
block8 -- "range(13)" --> block7
block8 -- "else" --> block0
block7 -- "range(12)" --> block6
block7 -- "else" --> block3
block6 -- "True" --> block5
block6 -- "else" --> block4
block5 --> block7
block4 --> block7
block3 -- "True" --> block2
block3 -- "else" --> block1
block2 --> block0
block1 --> block8
block0 --> return
```
## Function 14
### Source
```python
def func():
for i in range(13):
for i in range(12):
x = 2
if True:
break
x = 3
if True:
continue
print('hello')
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["print('hello')\n"]
block1[["Loop continue"]]
block2["continue\n"]
block3["x = 3\nif True:
continue\n"]
block4[["Loop continue"]]
block5["break\n"]
block6["x = 2\nif True:
break\n"]
block7["for i in range(12):
x = 2
if True:
break\n"]
block8["for i in range(13):
for i in range(12):
x = 2
if True:
break
x = 3
if True:
continue\n"]
start --> block8
block8 -- "range(13)" --> block7
block8 -- "else" --> block0
block7 -- "range(12)" --> block6
block7 -- "else" --> block3
block6 -- "True" --> block5
block6 -- "else" --> block4
block5 --> block3
block4 --> block7
block3 -- "True" --> block2
block3 -- "else" --> block1
block2 --> block8
block1 --> block8
block0 --> return
```

View file

@ -1,720 +0,0 @@
---
source: crates/ruff_linter/src/rules/pylint/rules/unreachable.rs
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
---
## Function 0
### Source
```python
def func():
if False:
return 0
return 1
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 1\n"]
block1["return 0\n"]
block2["if False:
return 0\n"]
start --> block2
block2 -- "False" --> block1
block2 -- "else" --> block0
block1 --> return
block0 --> return
```
## Function 1
### Source
```python
def func():
if True:
return 1
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 0\n"]
block1["return 1\n"]
block2["if True:
return 1\n"]
start --> block2
block2 -- "True" --> block1
block2 -- "else" --> block0
block1 --> return
block0 --> return
```
## Function 2
### Source
```python
def func():
if False:
return 0
else:
return 1
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 0\n"]
block2["return 1\n"]
block3["if False:
return 0
else:
return 1\n"]
start --> block3
block3 -- "False" --> block1
block3 -- "else" --> block2
block2 --> return
block1 --> return
block0 --> return
```
## Function 3
### Source
```python
def func():
if True:
return 1
else:
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 1\n"]
block2["return 0\n"]
block3["if True:
return 1
else:
return 0\n"]
start --> block3
block3 -- "True" --> block1
block3 -- "else" --> block2
block2 --> return
block1 --> return
block0 --> return
```
## Function 4
### Source
```python
def func():
if False:
return 0
else:
return 1
return "unreachable"
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return #quot;unreachable#quot;\n"]
block1["return 0\n"]
block2["return 1\n"]
block3["if False:
return 0
else:
return 1\n"]
start --> block3
block3 -- "False" --> block1
block3 -- "else" --> block2
block2 --> return
block1 --> return
block0 --> return
```
## Function 5
### Source
```python
def func():
if True:
return 1
else:
return 0
return "unreachable"
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return #quot;unreachable#quot;\n"]
block1["return 1\n"]
block2["return 0\n"]
block3["if True:
return 1
else:
return 0\n"]
start --> block3
block3 -- "True" --> block1
block3 -- "else" --> block2
block2 --> return
block1 --> return
block0 --> return
```
## Function 6
### Source
```python
def func():
if True:
if True:
return 1
return 2
else:
return 3
return "unreachable2"
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return #quot;unreachable2#quot;\n"]
block1["return 2\n"]
block2["return 1\n"]
block3["if True:
return 1\n"]
block4["return 3\n"]
block5["if True:
if True:
return 1
return 2
else:
return 3\n"]
start --> block5
block5 -- "True" --> block3
block5 -- "else" --> block4
block4 --> return
block3 -- "True" --> block2
block3 -- "else" --> block1
block2 --> return
block1 --> return
block0 --> return
```
## Function 7
### Source
```python
def func():
if False:
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 0\n"]
block2["if False:
return 0\n"]
start --> block2
block2 -- "False" --> block1
block2 -- "else" --> block0
block1 --> return
block0 --> return
```
## Function 8
### Source
```python
def func():
if True:
return 1
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 1\n"]
block2["if True:
return 1\n"]
start --> block2
block2 -- "True" --> block1
block2 -- "else" --> block0
block1 --> return
block0 --> return
```
## Function 9
### Source
```python
def func():
if True:
return 1
elif False:
return 2
else:
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 1\n"]
block2["return 0\n"]
block3["return 2\n"]
block4["if True:
return 1
elif False:
return 2
else:
return 0\n"]
block5["if True:
return 1
elif False:
return 2
else:
return 0\n"]
start --> block5
block5 -- "True" --> block1
block5 -- "else" --> block4
block4 -- "False" --> block3
block4 -- "else" --> block2
block3 --> return
block2 --> return
block1 --> return
block0 --> return
```
## Function 10
### Source
```python
def func():
if False:
return 1
elif True:
return 2
else:
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 1\n"]
block2["return 0\n"]
block3["return 2\n"]
block4["if False:
return 1
elif True:
return 2
else:
return 0\n"]
block5["if False:
return 1
elif True:
return 2
else:
return 0\n"]
start --> block5
block5 -- "False" --> block1
block5 -- "else" --> block4
block4 -- "True" --> block3
block4 -- "else" --> block2
block3 --> return
block2 --> return
block1 --> return
block0 --> return
```
## Function 11
### Source
```python
def func():
if True:
if False:
return 0
elif True:
return 1
else:
return 2
return 3
elif True:
return 4
else:
return 5
return 6
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 6\n"]
block1["return 3\n"]
block2["return 0\n"]
block3["return 2\n"]
block4["return 1\n"]
block5["if False:
return 0
elif True:
return 1
else:
return 2\n"]
block6["if False:
return 0
elif True:
return 1
else:
return 2\n"]
block7["return 5\n"]
block8["return 4\n"]
block9["if True:
if False:
return 0
elif True:
return 1
else:
return 2
return 3
elif True:
return 4
else:
return 5\n"]
block10["if True:
if False:
return 0
elif True:
return 1
else:
return 2
return 3
elif True:
return 4
else:
return 5\n"]
start --> block10
block10 -- "True" --> block6
block10 -- "else" --> block9
block9 -- "True" --> block8
block9 -- "else" --> block7
block8 --> return
block7 --> return
block6 -- "False" --> block2
block6 -- "else" --> block5
block5 -- "True" --> block4
block5 -- "else" --> block3
block4 --> return
block3 --> return
block2 --> return
block1 --> return
block0 --> return
```
## Function 12
### Source
```python
def func():
if False:
return "unreached"
elif False:
return "also unreached"
return "reached"
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return #quot;reached#quot;\n"]
block1["return #quot;unreached#quot;\n"]
block2["return #quot;also unreached#quot;\n"]
block3["if False:
return #quot;unreached#quot;
elif False:
return #quot;also unreached#quot;\n"]
block4["if False:
return #quot;unreached#quot;
elif False:
return #quot;also unreached#quot;\n"]
start --> block4
block4 -- "False" --> block1
block4 -- "else" --> block3
block3 -- "False" --> block2
block3 -- "else" --> block0
block2 --> return
block1 --> return
block0 --> return
```
## Function 13
### Source
```python
def func(self, obj: BytesRep) -> bytes:
data = obj["data"]
if isinstance(data, str):
return base64.b64decode(data)
elif isinstance(data, Buffer):
buffer = data
else:
id = data["id"]
if id in self._buffers:
buffer = self._buffers[id]
else:
self.error(f"can't resolve buffer '{id}'")
return buffer.data
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return buffer.data\n"]
block1["return base64.b64decode(data)\n"]
block2["buffer = self._buffers[id]\n"]
block3["self.error(f#quot;can't resolve buffer '{id}'#quot;)\n"]
block4["id = data[#quot;id#quot;]\nif id in self._buffers:
buffer = self._buffers[id]
else:
self.error(f#quot;can't resolve buffer '{id}'#quot;)\n"]
block5["buffer = data\n"]
block6["if isinstance(data, str):
return base64.b64decode(data)
elif isinstance(data, Buffer):
buffer = data
else:
id = data[#quot;id#quot;]
if id in self._buffers:
buffer = self._buffers[id]
else:
self.error(f#quot;can't resolve buffer '{id}'#quot;)\n"]
block7["data = obj[#quot;data#quot;]\nif isinstance(data, str):
return base64.b64decode(data)
elif isinstance(data, Buffer):
buffer = data
else:
id = data[#quot;id#quot;]
if id in self._buffers:
buffer = self._buffers[id]
else:
self.error(f#quot;can't resolve buffer '{id}'#quot;)\n"]
start --> block7
block7 -- "isinstance(data, str)" --> block1
block7 -- "else" --> block6
block6 -- "isinstance(data, Buffer)" --> block5
block6 -- "else" --> block4
block5 --> block0
block4 -- "id in self._buffers" --> block2
block4 -- "else" --> block3
block3 --> block0
block2 --> block0
block1 --> return
block0 --> return
```
## Function 14
### Source
```python
def func(x):
if x == 1:
return 1
elif False:
return 2
elif x == 3:
return 3
elif True:
return 4
elif x == 5:
return 5
elif x == 6:
return 6
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 1\n"]
block2["return 6\n"]
block3["if x == 1:
return 1
elif False:
return 2
elif x == 3:
return 3
elif True:
return 4
elif x == 5:
return 5
elif x == 6:
return 6\n"]
block4["return 5\n"]
block5["if x == 1:
return 1
elif False:
return 2
elif x == 3:
return 3
elif True:
return 4
elif x == 5:
return 5
elif x == 6:
return 6\n"]
block6["return 4\n"]
block7["if x == 1:
return 1
elif False:
return 2
elif x == 3:
return 3
elif True:
return 4
elif x == 5:
return 5
elif x == 6:
return 6\n"]
block8["return 3\n"]
block9["if x == 1:
return 1
elif False:
return 2
elif x == 3:
return 3
elif True:
return 4
elif x == 5:
return 5
elif x == 6:
return 6\n"]
block10["return 2\n"]
block11["if x == 1:
return 1
elif False:
return 2
elif x == 3:
return 3
elif True:
return 4
elif x == 5:
return 5
elif x == 6:
return 6\n"]
block12["if x == 1:
return 1
elif False:
return 2
elif x == 3:
return 3
elif True:
return 4
elif x == 5:
return 5
elif x == 6:
return 6\n"]
start --> block12
block12 -- "x == 1" --> block1
block12 -- "else" --> block11
block11 -- "False" --> block10
block11 -- "else" --> block9
block10 --> return
block9 -- "x == 3" --> block8
block9 -- "else" --> block7
block8 --> return
block7 -- "True" --> block6
block7 -- "else" --> block5
block6 --> return
block5 -- "x == 5" --> block4
block5 -- "else" --> block3
block4 --> return
block3 -- "x == 6" --> block2
block3 -- "else" --> block0
block2 --> return
block1 --> return
block0 --> return
```
## Function 15
### Source
```python
def func():
if x:
return
else:
assert x
print('pop')
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["print('pop')\n"]
block1["return\n"]
block2[["Exception raised"]]
block3["assert x\n"]
block4["if x:
return
else:
assert x\n"]
start --> block4
block4 -- "x" --> block1
block4 -- "else" --> block3
block3 -- "x" --> block0
block3 -- "else" --> block2
block2 --> return
block1 --> return
block0 --> return
```

View file

@ -1,823 +0,0 @@
---
source: crates/ruff_linter/src/rules/pylint/rules/unreachable.rs
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
---
## Function 0
### Source
```python
def func(status):
match status:
case _:
return 0
return "unreachable"
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return #quot;unreachable#quot;\n"]
block1["return 0\n"]
block2["match status:
case _:
return 0\n"]
start --> block2
block2 --> block1
block1 --> return
block0 --> return
```
## Function 1
### Source
```python
def func(status):
match status:
case 1:
return 1
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 0\n"]
block1["return 1\n"]
block2["match status:
case 1:
return 1\n"]
start --> block2
block2 -- "case 1" --> block1
block2 -- "else" --> block0
block1 --> return
block0 --> return
```
## Function 2
### Source
```python
def func(status):
match status:
case 1:
return 1
case _:
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 0\n"]
block2["match status:
case 1:
return 1
case _:
return 0\n"]
block3["return 1\n"]
block4["match status:
case 1:
return 1
case _:
return 0\n"]
start --> block4
block4 -- "case 1" --> block3
block4 -- "else" --> block2
block3 --> return
block2 --> block1
block1 --> return
block0 --> return
```
## Function 3
### Source
```python
def func(status):
match status:
case 1 | 2 | 3:
return 5
return 6
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 6\n"]
block1["return 5\n"]
block2["match status:
case 1 | 2 | 3:
return 5\n"]
start --> block2
block2 -- "case 1 | 2 | 3" --> block1
block2 -- "else" --> block0
block1 --> return
block0 --> return
```
## Function 4
### Source
```python
def func(status):
match status:
case 1 | 2 | 3:
return 5
case _:
return 10
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 0\n"]
block1["return 10\n"]
block2["match status:
case 1 | 2 | 3:
return 5
case _:
return 10\n"]
block3["return 5\n"]
block4["match status:
case 1 | 2 | 3:
return 5
case _:
return 10\n"]
start --> block4
block4 -- "case 1 | 2 | 3" --> block3
block4 -- "else" --> block2
block3 --> return
block2 --> block1
block1 --> return
block0 --> return
```
## Function 5
### Source
```python
def func(status):
match status:
case 0:
return 0
case 1:
return 1
case 1:
return "1 again"
case _:
return 3
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 3\n"]
block2["match status:
case 0:
return 0
case 1:
return 1
case 1:
return #quot;1 again#quot;
case _:
return 3\n"]
block3["return #quot;1 again#quot;\n"]
block4["match status:
case 0:
return 0
case 1:
return 1
case 1:
return #quot;1 again#quot;
case _:
return 3\n"]
block5["return 1\n"]
block6["match status:
case 0:
return 0
case 1:
return 1
case 1:
return #quot;1 again#quot;
case _:
return 3\n"]
block7["return 0\n"]
block8["match status:
case 0:
return 0
case 1:
return 1
case 1:
return #quot;1 again#quot;
case _:
return 3\n"]
start --> block8
block8 -- "case 0" --> block7
block8 -- "else" --> block6
block7 --> return
block6 -- "case 1" --> block5
block6 -- "else" --> block4
block5 --> return
block4 -- "case 1" --> block3
block4 -- "else" --> block2
block3 --> return
block2 --> block1
block1 --> return
block0 --> return
```
## Function 6
### Source
```python
def func(status):
i = 0
match status, i:
case _, _:
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 0\n"]
block2["match status, i:
case _, _:
return 0\n"]
block3["i = 0\n"]
start --> block3
block3 --> block2
block2 -- "case _, _" --> block1
block2 -- "else" --> block0
block1 --> return
block0 --> return
```
## Function 7
### Source
```python
def func(status):
i = 0
match status, i:
case _, 0:
return 0
case _, 2:
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 0\n"]
block2["match status, i:
case _, 0:
return 0
case _, 2:
return 0\n"]
block3["return 0\n"]
block4["match status, i:
case _, 0:
return 0
case _, 2:
return 0\n"]
block5["i = 0\n"]
start --> block5
block5 --> block4
block4 -- "case _, 0" --> block3
block4 -- "else" --> block2
block3 --> return
block2 -- "case _, 2" --> block1
block2 -- "else" --> block0
block1 --> return
block0 --> return
```
## Function 8
### Source
```python
def func(point):
match point:
case (0, 0):
print("Origin")
case _:
raise ValueError("oops")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Exception raised"]]
block2["raise ValueError(#quot;oops#quot;)\n"]
block3["match point:
case (0, 0):
print(#quot;Origin#quot;)
case _:
raise ValueError(#quot;oops#quot;)\n"]
block4["print(#quot;Origin#quot;)\n"]
block5["match point:
case (0, 0):
print(#quot;Origin#quot;)
case _:
raise ValueError(#quot;oops#quot;)\n"]
start --> block5
block5 -- "case (0, 0)" --> block4
block5 -- "else" --> block3
block4 --> block0
block3 --> block2
block2 --> block1
block1 --> return
block0 --> return
```
## Function 9
### Source
```python
def func(point):
match point:
case (0, 0):
print("Origin")
case (0, y):
print(f"Y={y}")
case (x, 0):
print(f"X={x}")
case (x, y):
print(f"X={x}, Y={y}")
case _:
raise ValueError("Not a point")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Exception raised"]]
block2["raise ValueError(#quot;Not a point#quot;)\n"]
block3["match point:
case (0, 0):
print(#quot;Origin#quot;)
case (0, y):
print(f#quot;Y={y}#quot;)
case (x, 0):
print(f#quot;X={x}#quot;)
case (x, y):
print(f#quot;X={x}, Y={y}#quot;)
case _:
raise ValueError(#quot;Not a point#quot;)\n"]
block4["print(f#quot;X={x}, Y={y}#quot;)\n"]
block5["match point:
case (0, 0):
print(#quot;Origin#quot;)
case (0, y):
print(f#quot;Y={y}#quot;)
case (x, 0):
print(f#quot;X={x}#quot;)
case (x, y):
print(f#quot;X={x}, Y={y}#quot;)
case _:
raise ValueError(#quot;Not a point#quot;)\n"]
block6["print(f#quot;X={x}#quot;)\n"]
block7["match point:
case (0, 0):
print(#quot;Origin#quot;)
case (0, y):
print(f#quot;Y={y}#quot;)
case (x, 0):
print(f#quot;X={x}#quot;)
case (x, y):
print(f#quot;X={x}, Y={y}#quot;)
case _:
raise ValueError(#quot;Not a point#quot;)\n"]
block8["print(f#quot;Y={y}#quot;)\n"]
block9["match point:
case (0, 0):
print(#quot;Origin#quot;)
case (0, y):
print(f#quot;Y={y}#quot;)
case (x, 0):
print(f#quot;X={x}#quot;)
case (x, y):
print(f#quot;X={x}, Y={y}#quot;)
case _:
raise ValueError(#quot;Not a point#quot;)\n"]
block10["print(#quot;Origin#quot;)\n"]
block11["match point:
case (0, 0):
print(#quot;Origin#quot;)
case (0, y):
print(f#quot;Y={y}#quot;)
case (x, 0):
print(f#quot;X={x}#quot;)
case (x, y):
print(f#quot;X={x}, Y={y}#quot;)
case _:
raise ValueError(#quot;Not a point#quot;)\n"]
start --> block11
block11 -- "case (0, 0)" --> block10
block11 -- "else" --> block9
block10 --> block0
block9 -- "case (0, y)" --> block8
block9 -- "else" --> block7
block8 --> block0
block7 -- "case (x, 0)" --> block6
block7 -- "else" --> block5
block6 --> block0
block5 -- "case (x, y)" --> block4
block5 -- "else" --> block3
block4 --> block0
block3 --> block2
block2 --> block1
block1 --> return
block0 --> return
```
## Function 10
### Source
```python
def where_is(point):
class Point:
x: int
y: int
match point:
case Point(x=0, y=0):
print("Origin")
case Point(x=0, y=y):
print(f"Y={y}")
case Point(x=x, y=0):
print(f"X={x}")
case Point():
print("Somewhere else")
case _:
print("Not a point")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["print(#quot;Not a point#quot;)\n"]
block2["match point:
case Point(x=0, y=0):
print(#quot;Origin#quot;)
case Point(x=0, y=y):
print(f#quot;Y={y}#quot;)
case Point(x=x, y=0):
print(f#quot;X={x}#quot;)
case Point():
print(#quot;Somewhere else#quot;)
case _:
print(#quot;Not a point#quot;)\n"]
block3["print(#quot;Somewhere else#quot;)\n"]
block4["match point:
case Point(x=0, y=0):
print(#quot;Origin#quot;)
case Point(x=0, y=y):
print(f#quot;Y={y}#quot;)
case Point(x=x, y=0):
print(f#quot;X={x}#quot;)
case Point():
print(#quot;Somewhere else#quot;)
case _:
print(#quot;Not a point#quot;)\n"]
block5["print(f#quot;X={x}#quot;)\n"]
block6["match point:
case Point(x=0, y=0):
print(#quot;Origin#quot;)
case Point(x=0, y=y):
print(f#quot;Y={y}#quot;)
case Point(x=x, y=0):
print(f#quot;X={x}#quot;)
case Point():
print(#quot;Somewhere else#quot;)
case _:
print(#quot;Not a point#quot;)\n"]
block7["print(f#quot;Y={y}#quot;)\n"]
block8["match point:
case Point(x=0, y=0):
print(#quot;Origin#quot;)
case Point(x=0, y=y):
print(f#quot;Y={y}#quot;)
case Point(x=x, y=0):
print(f#quot;X={x}#quot;)
case Point():
print(#quot;Somewhere else#quot;)
case _:
print(#quot;Not a point#quot;)\n"]
block9["print(#quot;Origin#quot;)\n"]
block10["match point:
case Point(x=0, y=0):
print(#quot;Origin#quot;)
case Point(x=0, y=y):
print(f#quot;Y={y}#quot;)
case Point(x=x, y=0):
print(f#quot;X={x}#quot;)
case Point():
print(#quot;Somewhere else#quot;)
case _:
print(#quot;Not a point#quot;)\n"]
block11["class Point:
x: int
y: int\n"]
start --> block11
block11 --> block10
block10 -- "case Point(x=0, y=0)" --> block9
block10 -- "else" --> block8
block9 --> block0
block8 -- "case Point(x=0, y=y)" --> block7
block8 -- "else" --> block6
block7 --> block0
block6 -- "case Point(x=x, y=0)" --> block5
block6 -- "else" --> block4
block5 --> block0
block4 -- "case Point()" --> block3
block4 -- "else" --> block2
block3 --> block0
block2 --> block1
block1 --> block0
block0 --> return
```
## Function 11
### Source
```python
def func(points):
match points:
case []:
print("No points")
case [Point(0, 0)]:
print("The origin")
case [Point(x, y)]:
print(f"Single point {x}, {y}")
case [Point(0, y1), Point(0, y2)]:
print(f"Two on the Y axis at {y1}, {y2}")
case _:
print("Something else")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["print(#quot;Something else#quot;)\n"]
block2["match points:
case []:
print(#quot;No points#quot;)
case [Point(0, 0)]:
print(#quot;The origin#quot;)
case [Point(x, y)]:
print(f#quot;Single point {x}, {y}#quot;)
case [Point(0, y1), Point(0, y2)]:
print(f#quot;Two on the Y axis at {y1}, {y2}#quot;)
case _:
print(#quot;Something else#quot;)\n"]
block3["print(f#quot;Two on the Y axis at {y1}, {y2}#quot;)\n"]
block4["match points:
case []:
print(#quot;No points#quot;)
case [Point(0, 0)]:
print(#quot;The origin#quot;)
case [Point(x, y)]:
print(f#quot;Single point {x}, {y}#quot;)
case [Point(0, y1), Point(0, y2)]:
print(f#quot;Two on the Y axis at {y1}, {y2}#quot;)
case _:
print(#quot;Something else#quot;)\n"]
block5["print(f#quot;Single point {x}, {y}#quot;)\n"]
block6["match points:
case []:
print(#quot;No points#quot;)
case [Point(0, 0)]:
print(#quot;The origin#quot;)
case [Point(x, y)]:
print(f#quot;Single point {x}, {y}#quot;)
case [Point(0, y1), Point(0, y2)]:
print(f#quot;Two on the Y axis at {y1}, {y2}#quot;)
case _:
print(#quot;Something else#quot;)\n"]
block7["print(#quot;The origin#quot;)\n"]
block8["match points:
case []:
print(#quot;No points#quot;)
case [Point(0, 0)]:
print(#quot;The origin#quot;)
case [Point(x, y)]:
print(f#quot;Single point {x}, {y}#quot;)
case [Point(0, y1), Point(0, y2)]:
print(f#quot;Two on the Y axis at {y1}, {y2}#quot;)
case _:
print(#quot;Something else#quot;)\n"]
block9["print(#quot;No points#quot;)\n"]
block10["match points:
case []:
print(#quot;No points#quot;)
case [Point(0, 0)]:
print(#quot;The origin#quot;)
case [Point(x, y)]:
print(f#quot;Single point {x}, {y}#quot;)
case [Point(0, y1), Point(0, y2)]:
print(f#quot;Two on the Y axis at {y1}, {y2}#quot;)
case _:
print(#quot;Something else#quot;)\n"]
start --> block10
block10 -- "case []" --> block9
block10 -- "else" --> block8
block9 --> block0
block8 -- "case [Point(0, 0)]" --> block7
block8 -- "else" --> block6
block7 --> block0
block6 -- "case [Point(x, y)]" --> block5
block6 -- "else" --> block4
block5 --> block0
block4 -- "case [Point(0, y1), Point(0, y2)]" --> block3
block4 -- "else" --> block2
block3 --> block0
block2 --> block1
block1 --> block0
block0 --> return
```
## Function 12
### Source
```python
def func(point):
match point:
case Point(x, y) if x == y:
print(f"Y=X at {x}")
case Point(x, y):
print(f"Not on the diagonal")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["print(f#quot;Not on the diagonal#quot;)\n"]
block2["match point:
case Point(x, y) if x == y:
print(f#quot;Y=X at {x}#quot;)
case Point(x, y):
print(f#quot;Not on the diagonal#quot;)\n"]
block3["print(f#quot;Y=X at {x}#quot;)\n"]
block4["match point:
case Point(x, y) if x == y:
print(f#quot;Y=X at {x}#quot;)
case Point(x, y):
print(f#quot;Not on the diagonal#quot;)\n"]
start --> block4
block4 -- "case Point(x, y) if x == y" --> block3
block4 -- "else" --> block2
block3 --> block0
block2 -- "case Point(x, y)" --> block1
block2 -- "else" --> block0
block1 --> block0
block0 --> return
```
## Function 13
### Source
```python
def func():
from enum import Enum
class Color(Enum):
RED = 'red'
GREEN = 'green'
BLUE = 'blue'
color = Color(input("Enter your choice of 'red', 'blue' or 'green': "))
match color:
case Color.RED:
print("I see red!")
case Color.GREEN:
print("Grass is green")
case Color.BLUE:
print("I'm feeling the blues :(")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["print(#quot;I'm feeling the blues :(#quot;)\n"]
block2["match color:
case Color.RED:
print(#quot;I see red!#quot;)
case Color.GREEN:
print(#quot;Grass is green#quot;)
case Color.BLUE:
print(#quot;I'm feeling the blues :(#quot;)\n"]
block3["print(#quot;Grass is green#quot;)\n"]
block4["match color:
case Color.RED:
print(#quot;I see red!#quot;)
case Color.GREEN:
print(#quot;Grass is green#quot;)
case Color.BLUE:
print(#quot;I'm feeling the blues :(#quot;)\n"]
block5["print(#quot;I see red!#quot;)\n"]
block6["match color:
case Color.RED:
print(#quot;I see red!#quot;)
case Color.GREEN:
print(#quot;Grass is green#quot;)
case Color.BLUE:
print(#quot;I'm feeling the blues :(#quot;)\n"]
block7["from enum import Enum\nclass Color(Enum):
RED = 'red'
GREEN = 'green'
BLUE = 'blue'\ncolor = Color(input(#quot;Enter your choice of 'red', 'blue' or 'green': #quot;))\n"]
start --> block7
block7 --> block6
block6 -- "case Color.RED" --> block5
block6 -- "else" --> block4
block5 --> block0
block4 -- "case Color.GREEN" --> block3
block4 -- "else" --> block2
block3 --> block0
block2 -- "case Color.BLUE" --> block1
block2 -- "else" --> block0
block1 --> block0
block0 --> return
```
## Function 14
### Source
```python
def func(point):
match point:
case (0, 0):
print("Origin")
case foo:
raise ValueError("oops")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Exception raised"]]
block2["raise ValueError(#quot;oops#quot;)\n"]
block3["match point:
case (0, 0):
print(#quot;Origin#quot;)
case foo:
raise ValueError(#quot;oops#quot;)\n"]
block4["print(#quot;Origin#quot;)\n"]
block5["match point:
case (0, 0):
print(#quot;Origin#quot;)
case foo:
raise ValueError(#quot;oops#quot;)\n"]
start --> block5
block5 -- "case (0, 0)" --> block4
block5 -- "else" --> block3
block4 --> block0
block3 --> block2
block2 --> block1
block1 --> return
block0 --> return
```

View file

@ -1,43 +0,0 @@
---
source: crates/ruff_linter/src/rules/pylint/rules/unreachable.rs
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
---
## Function 0
### Source
```python
def func():
raise Exception
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["Exception raised"]]
block1["raise Exception\n"]
start --> block1
block1 --> block0
block0 --> return
```
## Function 1
### Source
```python
def func():
raise "a glass!"
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["Exception raised"]]
block1["raise #quot;a glass!#quot;\n"]
start --> block1
block1 --> block0
block0 --> return
```

View file

@ -1,188 +0,0 @@
---
source: crates/ruff_linter/src/rules/pylint/rules/unreachable.rs
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
---
## Function 0
### Source
```python
def func():
pass
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["pass\n"]
start --> block0
block0 --> return
```
## Function 1
### Source
```python
def func():
pass
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["pass\n"]
start --> block0
block0 --> return
```
## Function 2
### Source
```python
def func():
return
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return\n"]
start --> block0
block0 --> return
```
## Function 3
### Source
```python
def func():
return 1
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 1\n"]
start --> block0
block0 --> return
```
## Function 4
### Source
```python
def func():
return 1
return "unreachable"
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return #quot;unreachable#quot;\n"]
block1["return 1\n"]
start --> block1
block1 --> return
block0 --> return
```
## Function 5
### Source
```python
def func():
i = 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["i = 0\n"]
start --> block0
block0 --> return
```
## Function 6
### Source
```python
def func():
i = 0
i += 2
return i
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["i = 0\ni += 2\nreturn i\n"]
start --> block0
block0 --> return
```
## Function 7
### Source
```python
def func():
with x:
i = 0
i = 1
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["i = 1\n"]
block1["i = 0\n"]
block2["with x:
i = 0\n"]
start --> block2
block2 -- "Exception raised" --> block0
block2 -- "else" --> block1
block1 --> block0
block0 --> return
```
## Function 8
### Source
```python
def func():
with x:
i = 0
return 1
i = 1
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["i = 1\n"]
block1["i = 0\nreturn 1\n"]
block2["with x:
i = 0
return 1\n"]
start --> block2
block2 -- "Exception raised" --> block0
block2 -- "else" --> block1
block1 --> return
block0 --> return
```

View file

@ -1,63 +0,0 @@
---
source: crates/ruff_linter/src/rules/pylint/rules/unreachable.rs
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
---
## Function 0
### Source
```python
def l():
while T:
try:
while ():
if 3:
break
finally:
return
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["return\n"]
block3[["Loop continue"]]
block4["break\n"]
block5["if 3:
break\n"]
block6["while ():
if 3:
break\n"]
block7[["Exception raised"]]
block8["try:
while ():
if 3:
break
finally:
return\n"]
block9["while T:
try:
while ():
if 3:
break
finally:
return\n"]
start --> block9
block9 -- "T" --> block8
block9 -- "else" --> block0
block8 -- "Exception raised" --> block7
block8 -- "else" --> block6
block7 --> block2
block6 -- "()" --> block5
block6 -- "else" --> block2
block5 -- "3" --> block4
block5 -- "else" --> block3
block4 --> block2
block3 --> block6
block2 --> return
block1 --> block9
block0 --> return
```

View file

@ -1,783 +0,0 @@
---
source: crates/ruff_linter/src/rules/pylint/rules/unreachable.rs
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
---
## Function 0
### Source
```python
def func():
try:
print("try")
except Exception:
print("Exception")
except OtherException as e:
print("OtherException")
else:
print("else")
finally:
print("finally")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["print(#quot;finally#quot;)\n"]
block2["print(#quot;else#quot;)\n"]
block3["print(#quot;try#quot;)\n"]
block4[["Exception raised"]]
block5["print(#quot;OtherException#quot;)\n"]
block6["try:
print(#quot;try#quot;)
except Exception:
print(#quot;Exception#quot;)
except OtherException as e:
print(#quot;OtherException#quot;)
else:
print(#quot;else#quot;)
finally:
print(#quot;finally#quot;)\n"]
block7["print(#quot;Exception#quot;)\n"]
block8["try:
print(#quot;try#quot;)
except Exception:
print(#quot;Exception#quot;)
except OtherException as e:
print(#quot;OtherException#quot;)
else:
print(#quot;else#quot;)
finally:
print(#quot;finally#quot;)\n"]
block9["try:
print(#quot;try#quot;)
except Exception:
print(#quot;Exception#quot;)
except OtherException as e:
print(#quot;OtherException#quot;)
else:
print(#quot;else#quot;)
finally:
print(#quot;finally#quot;)\n"]
start --> block9
block9 -- "Exception raised" --> block8
block9 -- "else" --> block3
block8 -- "Exception" --> block7
block8 -- "else" --> block6
block7 --> block1
block6 -- "OtherException" --> block5
block6 -- "else" --> block4
block5 --> block1
block4 --> block1
block3 --> block2
block2 --> block1
block1 --> block0
block0 --> return
```
## Function 1
### Source
```python
def func():
try:
print("try")
except:
print("Exception")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["print(#quot;try#quot;)\n"]
block2[["Exception raised"]]
block3["print(#quot;Exception#quot;)\n"]
block4["try:
print(#quot;try#quot;)
except:
print(#quot;Exception#quot;)\n"]
start --> block4
block4 -- "Exception raised" --> block3
block4 -- "else" --> block1
block3 --> block0
block2 --> return
block1 --> block0
block0 --> return
```
## Function 2
### Source
```python
def func():
try:
print("try")
except:
print("Exception")
except OtherException as e:
print("OtherException")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["print(#quot;try#quot;)\n"]
block2[["Exception raised"]]
block3["print(#quot;OtherException#quot;)\n"]
block4["try:
print(#quot;try#quot;)
except:
print(#quot;Exception#quot;)
except OtherException as e:
print(#quot;OtherException#quot;)\n"]
block5["print(#quot;Exception#quot;)\n"]
block6["try:
print(#quot;try#quot;)
except:
print(#quot;Exception#quot;)
except OtherException as e:
print(#quot;OtherException#quot;)\n"]
start --> block6
block6 -- "Exception raised" --> block5
block6 -- "else" --> block1
block5 --> block0
block4 -- "OtherException" --> block3
block4 -- "else" --> block2
block3 --> block0
block2 --> return
block1 --> block0
block0 --> return
```
## Function 3
### Source
```python
def func():
try:
print("try")
except Exception:
print("Exception")
except OtherException as e:
print("OtherException")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["print(#quot;try#quot;)\n"]
block2[["Exception raised"]]
block3["print(#quot;OtherException#quot;)\n"]
block4["try:
print(#quot;try#quot;)
except Exception:
print(#quot;Exception#quot;)
except OtherException as e:
print(#quot;OtherException#quot;)\n"]
block5["print(#quot;Exception#quot;)\n"]
block6["try:
print(#quot;try#quot;)
except Exception:
print(#quot;Exception#quot;)
except OtherException as e:
print(#quot;OtherException#quot;)\n"]
block7["try:
print(#quot;try#quot;)
except Exception:
print(#quot;Exception#quot;)
except OtherException as e:
print(#quot;OtherException#quot;)\n"]
start --> block7
block7 -- "Exception raised" --> block6
block7 -- "else" --> block1
block6 -- "Exception" --> block5
block6 -- "else" --> block4
block5 --> block0
block4 -- "OtherException" --> block3
block4 -- "else" --> block2
block3 --> block0
block2 --> return
block1 --> block0
block0 --> return
```
## Function 4
### Source
```python
def func():
try:
print("try")
except Exception:
print("Exception")
except OtherException as e:
print("OtherException")
else:
print("else")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["print(#quot;else#quot;)\n"]
block2["print(#quot;try#quot;)\n"]
block3[["Exception raised"]]
block4["print(#quot;OtherException#quot;)\n"]
block5["try:
print(#quot;try#quot;)
except Exception:
print(#quot;Exception#quot;)
except OtherException as e:
print(#quot;OtherException#quot;)
else:
print(#quot;else#quot;)\n"]
block6["print(#quot;Exception#quot;)\n"]
block7["try:
print(#quot;try#quot;)
except Exception:
print(#quot;Exception#quot;)
except OtherException as e:
print(#quot;OtherException#quot;)
else:
print(#quot;else#quot;)\n"]
block8["try:
print(#quot;try#quot;)
except Exception:
print(#quot;Exception#quot;)
except OtherException as e:
print(#quot;OtherException#quot;)
else:
print(#quot;else#quot;)\n"]
start --> block8
block8 -- "Exception raised" --> block7
block8 -- "else" --> block2
block7 -- "Exception" --> block6
block7 -- "else" --> block5
block6 --> block0
block5 -- "OtherException" --> block4
block5 -- "else" --> block3
block4 --> block0
block3 --> return
block2 --> block1
block1 --> block0
block0 --> return
```
## Function 5
### Source
```python
def func():
try:
print("try")
finally:
print("finally")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["print(#quot;finally#quot;)\n"]
block2["print(#quot;try#quot;)\n"]
block3[["Exception raised"]]
block4["try:
print(#quot;try#quot;)
finally:
print(#quot;finally#quot;)\n"]
start --> block4
block4 -- "Exception raised" --> block3
block4 -- "else" --> block2
block3 --> block1
block2 --> block1
block1 --> block0
block0 --> return
```
## Function 6
### Source
```python
def func():
try:
return 0
except:
return 1
finally:
return 2
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 2\n"]
block2["return 0\n"]
block3[["Exception raised"]]
block4["return 1\n"]
block5["try:
return 0
except:
return 1
finally:
return 2\n"]
start --> block5
block5 -- "Exception raised" --> block4
block5 -- "else" --> block2
block4 --> block1
block3 --> block1
block2 --> block1
block1 --> return
block0 --> return
```
## Function 7
### Source
```python
def func():
try:
raise Exception()
except:
print("reached")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Exception raised"]]
block2["raise Exception()\n"]
block3[["Exception raised"]]
block4["print(#quot;reached#quot;)\n"]
block5["try:
raise Exception()
except:
print(#quot;reached#quot;)\n"]
start --> block5
block5 -- "Exception raised" --> block4
block5 -- "else" --> block2
block4 --> block0
block3 --> return
block2 --> block4
block1 --> return
block0 --> return
```
## Function 8
### Source
```python
def func():
try:
assert False
print("unreachable")
except:
print("reached")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["print(#quot;unreachable#quot;)\n"]
block2[["Exception raised"]]
block3["assert False\n"]
block4[["Exception raised"]]
block5["print(#quot;reached#quot;)\n"]
block6["try:
assert False
print(#quot;unreachable#quot;)
except:
print(#quot;reached#quot;)\n"]
start --> block6
block6 -- "Exception raised" --> block5
block6 -- "else" --> block3
block5 --> block0
block4 --> return
block3 -- "False" --> block1
block3 -- "else" --> block5
block2 --> return
block1 --> block0
block0 --> return
```
## Function 9
### Source
```python
def func():
try:
raise Exception()
finally:
print('reached')
return 2
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["print('reached')\nreturn 2\n"]
block2[["Exception raised"]]
block3["raise Exception()\n"]
block4[["Exception raised"]]
block5["try:
raise Exception()
finally:
print('reached')
return 2\n"]
start --> block5
block5 -- "Exception raised" --> block4
block5 -- "else" --> block3
block4 --> block1
block3 --> block1
block2 --> return
block1 --> return
block0 --> return
```
## Function 10
### Source
```python
def func():
try:
assert False
print("unreachable")
finally:
print("reached")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["print(#quot;reached#quot;)\n"]
block2["print(#quot;unreachable#quot;)\n"]
block3[["Exception raised"]]
block4["assert False\n"]
block5[["Exception raised"]]
block6["try:
assert False
print(#quot;unreachable#quot;)
finally:
print(#quot;reached#quot;)\n"]
start --> block6
block6 -- "Exception raised" --> block5
block6 -- "else" --> block4
block5 --> block1
block4 -- "False" --> block2
block4 -- "else" --> block1
block3 --> return
block2 --> block1
block1 --> block0
block0 --> return
```
## Function 11
### Source
```python
def func():
try:
if catalog is not None:
try:
x = 0
except PySparkParseException:
x = 1
try:
x = 2
except PySparkParseException:
x = 3
x = 8
finally:
if catalog is not None:
try:
x = 4
except PySparkParseException:
x = 5
try:
x = 6
except PySparkParseException:
x = 7
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["x = 6\n"]
block2[["Exception raised"]]
block3["x = 7\n"]
block4["try:
x = 6
except PySparkParseException:
x = 7\n"]
block5["try:
x = 6
except PySparkParseException:
x = 7\n"]
block6["x = 4\n"]
block7[["Exception raised"]]
block8["x = 5\n"]
block9["try:
x = 4
except PySparkParseException:
x = 5\n"]
block10["try:
x = 4
except PySparkParseException:
x = 5\n"]
block11["if catalog is not None:
try:
x = 4
except PySparkParseException:
x = 5\n"]
block12["x = 8\n"]
block13["x = 2\n"]
block14[["Exception raised"]]
block15["x = 3\n"]
block16["try:
x = 2
except PySparkParseException:
x = 3\n"]
block17["try:
x = 2
except PySparkParseException:
x = 3\n"]
block18["x = 0\n"]
block19[["Exception raised"]]
block20["x = 1\n"]
block21["try:
x = 0
except PySparkParseException:
x = 1\n"]
block22["try:
x = 0
except PySparkParseException:
x = 1\n"]
block23["if catalog is not None:
try:
x = 0
except PySparkParseException:
x = 1\n"]
block24[["Exception raised"]]
block25["try:
if catalog is not None:
try:
x = 0
except PySparkParseException:
x = 1
try:
x = 2
except PySparkParseException:
x = 3
x = 8
finally:
if catalog is not None:
try:
x = 4
except PySparkParseException:
x = 5
try:
x = 6
except PySparkParseException:
x = 7\n"]
start --> block25
block25 -- "Exception raised" --> block24
block25 -- "else" --> block23
block24 --> block11
block23 -- "catalog is not None" --> block22
block23 -- "else" --> block17
block22 -- "Exception raised" --> block21
block22 -- "else" --> block18
block21 -- "PySparkParseException" --> block20
block21 -- "else" --> block19
block20 --> block17
block19 --> block11
block18 --> block17
block17 -- "Exception raised" --> block16
block17 -- "else" --> block13
block16 -- "PySparkParseException" --> block15
block16 -- "else" --> block14
block15 --> block12
block14 --> block11
block13 --> block12
block12 --> block11
block11 -- "catalog is not None" --> block10
block11 -- "else" --> block5
block10 -- "Exception raised" --> block9
block10 -- "else" --> block6
block9 -- "PySparkParseException" --> block8
block9 -- "else" --> block7
block8 --> block5
block7 --> return
block6 --> block5
block5 -- "Exception raised" --> block4
block5 -- "else" --> block1
block4 -- "PySparkParseException" --> block3
block4 -- "else" --> block2
block3 --> block0
block2 --> return
block1 --> block0
block0 --> return
```
## Function 12
### Source
```python
def func():
try:
assert False
except ex:
raise ex
finally:
raise Exception("other")
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Exception raised"]]
block2["raise Exception(#quot;other#quot;)\n"]
block3[["Exception raised"]]
block4["assert False\n"]
block5[["Exception raised"]]
block6[["Exception raised"]]
block7["raise ex\n"]
block8["try:
assert False
except ex:
raise ex
finally:
raise Exception(#quot;other#quot;)\n"]
block9["try:
assert False
except ex:
raise ex
finally:
raise Exception(#quot;other#quot;)\n"]
start --> block9
block9 -- "Exception raised" --> block8
block9 -- "else" --> block4
block8 -- "ex" --> block7
block8 -- "else" --> block5
block7 --> block2
block6 --> return
block5 --> block2
block4 -- "False" --> block2
block4 -- "else" --> block8
block3 --> return
block2 --> block1
block1 --> return
block0 --> return
```
## Function 13
### Source
```python
def func():
for i in():
try:
try:
while r:
if t:break
finally:()
return
except:l
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["return\n"]
block3["()\n"]
block4[["Loop continue"]]
block5["break\n"]
block6["if t:break\n"]
block7["while r:
if t:break\n"]
block8[["Exception raised"]]
block9["try:
while r:
if t:break
finally:()\n"]
block10[["Exception raised"]]
block11["l\n"]
block12["try:
try:
while r:
if t:break
finally:()
return
except:l\n"]
block13["for i in():
try:
try:
while r:
if t:break
finally:()
return
except:l\n"]
start --> block13
block13 -- "()" --> block12
block13 -- "else" --> block0
block12 -- "Exception raised" --> block11
block12 -- "else" --> block9
block11 --> block1
block10 --> return
block9 -- "Exception raised" --> block8
block9 -- "else" --> block7
block8 --> block3
block7 -- "r" --> block6
block7 -- "else" --> block3
block6 -- "t" --> block5
block6 -- "else" --> block4
block5 --> block3
block4 --> block7
block3 --> block2
block2 --> return
block1 --> block13
block0 --> return
```

View file

@ -1,839 +0,0 @@
---
source: crates/ruff_linter/src/rules/pylint/rules/unreachable.rs
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
---
## Function 0
### Source
```python
def func():
while False:
return "unreachable"
return 1
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 1\n"]
block1[["Loop continue"]]
block2["return #quot;unreachable#quot;\n"]
block3["while False:
return #quot;unreachable#quot;\n"]
start --> block3
block3 -- "False" --> block2
block3 -- "else" --> block0
block2 --> return
block1 --> block3
block0 --> return
```
## Function 1
### Source
```python
def func():
while False:
return "unreachable"
else:
return 1
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return 1\n"]
block2[["Loop continue"]]
block3["return #quot;unreachable#quot;\n"]
block4["while False:
return #quot;unreachable#quot;
else:
return 1\n"]
start --> block4
block4 -- "False" --> block3
block4 -- "else" --> block1
block3 --> return
block2 --> block4
block1 --> return
block0 --> return
```
## Function 2
### Source
```python
def func():
while False:
return "unreachable"
else:
return 1
return "also unreachable"
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return #quot;also unreachable#quot;\n"]
block1["return 1\n"]
block2[["Loop continue"]]
block3["return #quot;unreachable#quot;\n"]
block4["while False:
return #quot;unreachable#quot;
else:
return 1\n"]
start --> block4
block4 -- "False" --> block3
block4 -- "else" --> block1
block3 --> return
block2 --> block4
block1 --> return
block0 --> return
```
## Function 3
### Source
```python
def func():
while True:
return 1
return "unreachable"
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return #quot;unreachable#quot;\n"]
block1[["Loop continue"]]
block2["return 1\n"]
block3["while True:
return 1\n"]
start --> block3
block3 -- "True" --> block2
block3 -- "else" --> block0
block2 --> return
block1 --> block3
block0 --> return
```
## Function 4
### Source
```python
def func():
while True:
return 1
else:
return "unreachable"
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1["return #quot;unreachable#quot;\n"]
block2[["Loop continue"]]
block3["return 1\n"]
block4["while True:
return 1
else:
return #quot;unreachable#quot;\n"]
start --> block4
block4 -- "True" --> block3
block4 -- "else" --> block1
block3 --> return
block2 --> block4
block1 --> return
block0 --> return
```
## Function 5
### Source
```python
def func():
while True:
return 1
else:
return "unreachable"
return "also unreachable"
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return #quot;also unreachable#quot;\n"]
block1["return #quot;unreachable#quot;\n"]
block2[["Loop continue"]]
block3["return 1\n"]
block4["while True:
return 1
else:
return #quot;unreachable#quot;\n"]
start --> block4
block4 -- "True" --> block3
block4 -- "else" --> block1
block3 --> return
block2 --> block4
block1 --> return
block0 --> return
```
## Function 6
### Source
```python
def func():
i = 0
while False:
i += 1
return i
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return i\n"]
block1[["Loop continue"]]
block2["i += 1\n"]
block3["i = 0\nwhile False:
i += 1\n"]
start --> block3
block3 -- "False" --> block2
block3 -- "else" --> block0
block2 --> block1
block1 --> block3
block0 --> return
```
## Function 7
### Source
```python
def func():
i = 0
while True:
i += 1
return i
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return i\n"]
block1[["Loop continue"]]
block2["i += 1\n"]
block3["i = 0\nwhile True:
i += 1\n"]
start --> block3
block3 -- "True" --> block2
block3 -- "else" --> block0
block2 --> block1
block1 --> block3
block0 --> return
```
## Function 8
### Source
```python
def func():
while True:
pass
return 1
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 1\n"]
block1[["Loop continue"]]
block2["pass\n"]
block3["while True:
pass\n"]
start --> block3
block3 -- "True" --> block2
block3 -- "else" --> block0
block2 --> block1
block1 --> block3
block0 --> return
```
## Function 9
### Source
```python
def func():
i = 0
while True:
if True:
print("ok")
i += 1
return i
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return i\n"]
block1[["Loop continue"]]
block2["i += 1\n"]
block3["print(#quot;ok#quot;)\n"]
block4["if True:
print(#quot;ok#quot;)\n"]
block5["i = 0\nwhile True:
if True:
print(#quot;ok#quot;)
i += 1\n"]
start --> block5
block5 -- "True" --> block4
block5 -- "else" --> block0
block4 -- "True" --> block3
block4 -- "else" --> block2
block3 --> block2
block2 --> block1
block1 --> block5
block0 --> return
```
## Function 10
### Source
```python
def func():
i = 0
while True:
if False:
print("ok")
i += 1
return i
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return i\n"]
block1[["Loop continue"]]
block2["i += 1\n"]
block3["print(#quot;ok#quot;)\n"]
block4["if False:
print(#quot;ok#quot;)\n"]
block5["i = 0\nwhile True:
if False:
print(#quot;ok#quot;)
i += 1\n"]
start --> block5
block5 -- "True" --> block4
block5 -- "else" --> block0
block4 -- "False" --> block3
block4 -- "else" --> block2
block3 --> block2
block2 --> block1
block1 --> block5
block0 --> return
```
## Function 11
### Source
```python
def func():
while True:
if True:
return 1
return 0
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["return 0\n"]
block1[["Loop continue"]]
block2["return 1\n"]
block3["if True:
return 1\n"]
block4["while True:
if True:
return 1\n"]
start --> block4
block4 -- "True" --> block3
block4 -- "else" --> block0
block3 -- "True" --> block2
block3 -- "else" --> block1
block2 --> return
block1 --> block4
block0 --> return
```
## Function 12
### Source
```python
def func():
while True:
continue
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["continue\n"]
block3["while True:
continue\n"]
start --> block3
block3 -- "True" --> block2
block3 -- "else" --> block0
block2 --> block3
block1 --> block3
block0 --> return
```
## Function 13
### Source
```python
def func():
while False:
continue
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["continue\n"]
block3["while False:
continue\n"]
start --> block3
block3 -- "False" --> block2
block3 -- "else" --> block0
block2 --> block3
block1 --> block3
block0 --> return
```
## Function 14
### Source
```python
def func():
while True:
break
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["break\n"]
block3["while True:
break\n"]
start --> block3
block3 -- "True" --> block2
block3 -- "else" --> block0
block2 --> return
block1 --> block3
block0 --> return
```
## Function 15
### Source
```python
def func():
while False:
break
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["break\n"]
block3["while False:
break\n"]
start --> block3
block3 -- "False" --> block2
block3 -- "else" --> block0
block2 --> return
block1 --> block3
block0 --> return
```
## Function 16
### Source
```python
def func():
while True:
if True:
continue
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["continue\n"]
block3["if True:
continue\n"]
block4["while True:
if True:
continue\n"]
start --> block4
block4 -- "True" --> block3
block4 -- "else" --> block0
block3 -- "True" --> block2
block3 -- "else" --> block1
block2 --> block4
block1 --> block4
block0 --> return
```
## Function 17
### Source
```python
def func():
while True:
if True:
break
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["break\n"]
block3["if True:
break\n"]
block4["while True:
if True:
break\n"]
start --> block4
block4 -- "True" --> block3
block4 -- "else" --> block0
block3 -- "True" --> block2
block3 -- "else" --> block1
block2 --> return
block1 --> block4
block0 --> return
```
## Function 18
### Source
```python
def func():
while True:
x = 0
x = 1
break
x = 2
x = 3
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["x = 3\n"]
block1[["Loop continue"]]
block2["x = 2\n"]
block3["x = 0\nx = 1\nbreak\n"]
block4["while True:
x = 0
x = 1
break
x = 2\n"]
start --> block4
block4 -- "True" --> block3
block4 -- "else" --> block0
block3 --> block0
block2 --> block1
block1 --> block4
block0 --> return
```
## Function 19
### Source
```python
def func():
while True:
x = 0
x = 1
continue
x = 2
x = 3
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["x = 3\n"]
block1[["Loop continue"]]
block2["x = 2\n"]
block3["x = 0\nx = 1\ncontinue\n"]
block4["while True:
x = 0
x = 1
continue
x = 2\n"]
start --> block4
block4 -- "True" --> block3
block4 -- "else" --> block0
block3 --> block4
block2 --> block1
block1 --> block4
block0 --> return
```
## Function 20
### Source
```python
def func():
while True:
x = 0
x = 1
return
x = 2
x = 3
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["x = 3\n"]
block1[["Loop continue"]]
block2["x = 2\n"]
block3["x = 0\nx = 1\nreturn\n"]
block4["while True:
x = 0
x = 1
return
x = 2\n"]
start --> block4
block4 -- "True" --> block3
block4 -- "else" --> block0
block3 --> return
block2 --> block1
block1 --> block4
block0 --> return
```
## Function 21
### Source
```python
def func():
while True:
x = 0
x = 1
raise Exception
x = 2
x = 3
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["x = 3\n"]
block1[["Loop continue"]]
block2["x = 2\n"]
block3[["Exception raised"]]
block4["x = 0\nx = 1\nraise Exception\n"]
block5["while True:
x = 0
x = 1
raise Exception
x = 2\n"]
start --> block5
block5 -- "True" --> block4
block5 -- "else" --> block0
block4 --> block3
block3 --> return
block2 --> block1
block1 --> block5
block0 --> return
```
## Function 22
### Source
```python
def bokeh2(self, host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> None:
self.stop_serving = False
while True:
try:
self.server = HTTPServer((host, port), HtmlOnlyHandler)
self.host = host
self.port = port
break
except OSError:
log.debug(f"port {port} is in use, trying to next one")
port += 1
self.thread = threading.Thread(target=self._run_web_server)
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0["self.thread = threading.Thread(target=self._run_web_server)\n"]
block1[["Loop continue"]]
block2["self.server = HTTPServer((host, port), HtmlOnlyHandler)\nself.host = host\nself.port = port\nbreak\n"]
block3[["Exception raised"]]
block4["log.debug(f#quot;port {port} is in use, trying to next one#quot;)\nport += 1\n"]
block5["try:
self.server = HTTPServer((host, port), HtmlOnlyHandler)
self.host = host
self.port = port
break
except OSError:
log.debug(f#quot;port {port} is in use, trying to next one#quot;)
port += 1\n"]
block6["try:
self.server = HTTPServer((host, port), HtmlOnlyHandler)
self.host = host
self.port = port
break
except OSError:
log.debug(f#quot;port {port} is in use, trying to next one#quot;)
port += 1\n"]
block7["self.stop_serving = False\nwhile True:
try:
self.server = HTTPServer((host, port), HtmlOnlyHandler)
self.host = host
self.port = port
break
except OSError:
log.debug(f#quot;port {port} is in use, trying to next one#quot;)
port += 1\n"]
start --> block7
block7 -- "True" --> block6
block7 -- "else" --> block0
block6 -- "Exception raised" --> block5
block6 -- "else" --> block2
block5 -- "OSError" --> block4
block5 -- "else" --> block3
block4 --> block1
block3 --> return
block2 --> block0
block1 --> block7
block0 --> return
```
## Function 23
### Source
```python
def func():
while T:
try:
while():
if 3:
break
finally:
return
```
### Control Flow Graph
```mermaid
flowchart TD
start(("Start"))
return(("End"))
block0[["`*(empty)*`"]]
block1[["Loop continue"]]
block2["return\n"]
block3[["Loop continue"]]
block4["break\n"]
block5["if 3:
break\n"]
block6["while():
if 3:
break\n"]
block7[["Exception raised"]]
block8["try:
while():
if 3:
break
finally:
return\n"]
block9["while T:
try:
while():
if 3:
break
finally:
return\n"]
start --> block9
block9 -- "T" --> block8
block9 -- "else" --> block0
block8 -- "Exception raised" --> block7
block8 -- "else" --> block6
block7 --> block2
block6 -- "()" --> block5
block6 -- "else" --> block2
block5 -- "3" --> block4
block5 -- "else" --> block3
block4 --> block2
block3 --> block6
block2 --> return
block1 --> block9
block0 --> return
```

File diff suppressed because it is too large Load diff

View file

@ -1,266 +1,4 @@
---
source: crates/ruff_linter/src/rules/pylint/mod.rs
---
unreachable.py:3:5: PLW0101 Unreachable code in `after_return`
|
1 | def after_return():
2 | return "reachable"
3 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
4 |
5 | async def also_works_on_async_functions():
|
unreachable.py:7:5: PLW0101 Unreachable code in `also_works_on_async_functions`
|
5 | async def also_works_on_async_functions():
6 | return "reachable"
7 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
8 |
9 | def if_always_true():
|
unreachable.py:12:5: PLW0101 Unreachable code in `if_always_true`
|
10 | if True:
11 | return "reachable"
12 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
13 |
14 | def if_always_false():
|
unreachable.py:16:9: PLW0101 Unreachable code in `if_always_false`
|
14 | def if_always_false():
15 | if False:
16 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
17 | return "reachable"
|
unreachable.py:21:9: PLW0101 Unreachable code in `if_elif_always_false`
|
19 | def if_elif_always_false():
20 | if False:
21 | / return "unreachable"
22 | | elif False:
23 | | return "also unreachable"
| |_________________________________^ PLW0101
24 | return "reachable"
|
unreachable.py:28:9: PLW0101 Unreachable code in `if_elif_always_true`
|
26 | def if_elif_always_true():
27 | if False:
28 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
29 | elif True:
30 | return "reachable"
|
unreachable.py:31:5: PLW0101 Unreachable code in `if_elif_always_true`
|
29 | elif True:
30 | return "reachable"
31 | return "also unreachable"
| ^^^^^^^^^^^^^^^^^^^^^^^^^ PLW0101
32 |
33 | def ends_with_if():
|
unreachable.py:35:9: PLW0101 Unreachable code in `ends_with_if`
|
33 | def ends_with_if():
34 | if False:
35 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
36 | else:
37 | return "reachable"
|
unreachable.py:42:5: PLW0101 Unreachable code in `infinite_loop`
|
40 | while True:
41 | continue
42 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
43 |
44 | ''' TODO: we could determine these, but we don't yet.
|
unreachable.py:75:5: PLW0101 Unreachable code in `match_wildcard`
|
73 | case _:
74 | return "reachable"
75 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
76 |
77 | def match_case_and_wildcard(status):
|
unreachable.py:83:5: PLW0101 Unreachable code in `match_case_and_wildcard`
|
81 | case _:
82 | return "reachable"
83 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
84 |
85 | def raise_exception():
|
unreachable.py:87:5: PLW0101 Unreachable code in `raise_exception`
|
85 | def raise_exception():
86 | raise Exception
87 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
88 |
89 | def while_false():
|
unreachable.py:91:9: PLW0101 Unreachable code in `while_false`
|
89 | def while_false():
90 | while False:
91 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
92 | return "reachable"
|
unreachable.py:96:9: PLW0101 Unreachable code in `while_false_else`
|
94 | def while_false_else():
95 | while False:
96 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
97 | else:
98 | return "reachable"
|
unreachable.py:102:9: PLW0101 Unreachable code in `while_false_else_return`
|
100 | def while_false_else_return():
101 | while False:
102 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
103 | else:
104 | return "reachable"
|
unreachable.py:105:5: PLW0101 Unreachable code in `while_false_else_return`
|
103 | else:
104 | return "reachable"
105 | return "also unreachable"
| ^^^^^^^^^^^^^^^^^^^^^^^^^ PLW0101
106 |
107 | def while_true():
|
unreachable.py:110:5: PLW0101 Unreachable code in `while_true`
|
108 | while True:
109 | return "reachable"
110 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
111 |
112 | def while_true_else():
|
unreachable.py:116:9: PLW0101 Unreachable code in `while_true_else`
|
114 | return "reachable"
115 | else:
116 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
117 |
118 | def while_true_else_return():
|
unreachable.py:122:9: PLW0101 Unreachable code in `while_true_else_return`
|
120 | return "reachable"
121 | else:
122 | / return "unreachable"
123 | | return "also unreachable"
| |_____________________________^ PLW0101
124 |
125 | def while_false_var_i():
|
unreachable.py:128:9: PLW0101 Unreachable code in `while_false_var_i`
|
126 | i = 0
127 | while False:
128 | i += 1
| ^^^^^^ PLW0101
129 | return i
|
unreachable.py:135:5: PLW0101 Unreachable code in `while_true_var_i`
|
133 | while True:
134 | i += 1
135 | return i
| ^^^^^^^^ PLW0101
136 |
137 | def while_infinite():
|
unreachable.py:140:5: PLW0101 Unreachable code in `while_infinite`
|
138 | while True:
139 | pass
140 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
141 |
142 | def while_if_true():
|
unreachable.py:146:5: PLW0101 Unreachable code in `while_if_true`
|
144 | if True:
145 | return "reachable"
146 | return "unreachable"
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
147 |
148 | def while_break():
|
unreachable.py:152:9: PLW0101 Unreachable code in `while_break`
|
150 | print("reachable")
151 | break
152 | print("unreachable")
| ^^^^^^^^^^^^^^^^^^^^ PLW0101
153 | return "reachable"
|
unreachable.py:248:5: PLW0101 Unreachable code in `after_return`
|
246 | def after_return():
247 | return "reachable"
248 | / print("unreachable")
249 | | print("unreachable")
250 | | print("unreachable")
251 | | print("unreachable")
252 | | print("unreachable")
| |________________________^ PLW0101
|
unreachable.py:257:5: PLW0101 Unreachable code in `check_if_url_exists`
|
255 | def check_if_url_exists(url: str) -> bool: # type: ignore[return]
256 | return True # uncomment to check URLs
257 | / response = requests.head(url, allow_redirects=True)
258 | | if response.status_code == 200:
259 | | return True
260 | | if response.status_code == 404:
261 | | return False
262 | | console.print(f"[red]Unexpected error received: {response.status_code}[/]")
263 | | response.raise_for_status()
| |_______________________________^ PLW0101
|

View file

@ -27,6 +27,8 @@ serde = { workspace = true, optional = true }
smallvec = { workspace = true }
[dev-dependencies]
insta = { workspace = true, features = ["filters", "json", "redactions"] }
test-case = { workspace = true }
ruff_python_parser = { workspace = true }
[lints]

View file

@ -0,0 +1,24 @@
def func(): ...
def func():
pass
def func():
x = 1
x = 2
def func():
foo()
def func():
from foo import bar
class C:
a = 1
c = C()
del c

View file

@ -0,0 +1,293 @@
use ruff_index::{newtype_index, IndexVec};
use ruff_python_ast::Stmt;
use ruff_text_size::{Ranged, TextRange};
use smallvec::{smallvec, SmallVec};
/// Returns the control flow graph associated to an array of statements
pub fn build_cfg(stmts: &[Stmt]) -> ControlFlowGraph<'_> {
let mut builder = CFGBuilder::with_capacity(stmts.len());
builder.process_stmts(stmts);
builder.finish()
}
/// Control flow graph
#[derive(Debug)]
pub struct ControlFlowGraph<'stmt> {
/// Basic blocks - the nodes of the control flow graph
blocks: IndexVec<BlockId, BlockData<'stmt>>,
/// Entry point to the control flow graph
initial: BlockId,
/// Terminal block - will always be empty
terminal: BlockId,
}
impl<'stmt> ControlFlowGraph<'stmt> {
/// Index of entry point to the control flow graph
pub fn initial(&self) -> BlockId {
self.initial
}
/// Index of terminal block
pub fn terminal(&self) -> BlockId {
self.terminal
}
/// Number of basic blocks, or nodes, in the graph
pub fn num_blocks(&self) -> usize {
self.blocks.len()
}
/// Returns the statements comprising the basic block at the given index
pub fn stmts(&self, block: BlockId) -> &'stmt [Stmt] {
self.blocks[block].stmts
}
/// Returns the range of the statements comprising the basic block at the given index
pub fn range(&self, block: BlockId) -> TextRange {
self.blocks[block].range()
}
/// Returns the [`Edges`] going out of the basic block at the given index
pub fn outgoing(&self, block: BlockId) -> &Edges {
&self.blocks[block].out
}
/// Returns an iterator over the indices of the direct predecessors of the block at the given index
pub fn predecessors(&self, block: BlockId) -> impl ExactSizeIterator<Item = BlockId> + '_ {
self.blocks[block].parents.iter().copied()
}
/// Returns the [`BlockKind`] of the block at the given index
pub(crate) fn kind(&self, block: BlockId) -> BlockKind {
self.blocks[block].kind
}
}
#[newtype_index]
pub struct BlockId;
/// Holds the data of a basic block. A basic block consists of a collection of
/// [`Stmt`]s, together with outgoing edges to other basic blocks.
#[derive(Debug, Default)]
struct BlockData<'stmt> {
kind: BlockKind,
/// Slice of statements regarded as executing unconditionally in order
stmts: &'stmt [Stmt],
/// Outgoing edges, indicating possible paths of execution after the
/// block has concluded
out: Edges,
/// Collection of indices for basic blocks having the current
/// block as the target of an edge
parents: SmallVec<[BlockId; 2]>,
}
impl Ranged for BlockData<'_> {
fn range(&self) -> TextRange {
let Some(first) = self.stmts.first() else {
return TextRange::default();
};
let Some(last) = self.stmts.last() else {
return TextRange::default();
};
TextRange::new(first.start(), last.end())
}
}
#[derive(Debug, Default, Clone, Copy)]
pub(crate) enum BlockKind {
#[default]
Generic,
/// Entry point of the control flow graph
Start,
/// Terminal block for the control flow graph
Terminal,
}
/// Holds a collection of edges. Each edge is determined by:
/// - a [`Condition`] for traversing the edge, and
/// - a target block, specified by its [`BlockId`].
///
/// The conditions and targets are kept in two separate
/// vectors which must always be kept the same length.
#[derive(Debug, Default, Clone)]
pub struct Edges {
conditions: SmallVec<[Condition; 4]>,
targets: SmallVec<[BlockId; 4]>,
}
impl Edges {
/// Creates an unconditional edge to the target block
fn always(target: BlockId) -> Self {
Self {
conditions: smallvec![Condition::Always],
targets: smallvec![target],
}
}
/// Returns iterator over indices of blocks targeted by given edges
pub fn targets(&self) -> impl ExactSizeIterator<Item = BlockId> + '_ {
self.targets.iter().copied()
}
/// Returns iterator over [`Condition`]s which must be satisfied to traverse corresponding edge
pub fn conditions(&self) -> impl ExactSizeIterator<Item = &Condition> {
self.conditions.iter()
}
fn is_empty(&self) -> bool {
self.targets.is_empty()
}
pub fn filter_targets_by_conditions<'a, T: FnMut(&Condition) -> bool + 'a>(
&'a self,
mut predicate: T,
) -> impl Iterator<Item = BlockId> + 'a {
self.conditions()
.zip(self.targets())
.filter(move |(cond, _)| predicate(cond))
.map(|(_, block)| block)
}
}
/// Represents a condition to be tested in a multi-way branch
#[derive(Debug, Clone)]
pub enum Condition {
/// Unconditional edge
Always,
}
struct CFGBuilder<'stmt> {
/// Control flow graph under construction
cfg: ControlFlowGraph<'stmt>,
/// Current basic block index
current: BlockId,
/// Exit block index for current control flow
exit: BlockId,
}
impl<'stmt> CFGBuilder<'stmt> {
/// Returns [`CFGBuilder`] with vector of blocks initialized at given capacity and with both initial and terminal blocks populated.
fn with_capacity(capacity: usize) -> Self {
let mut blocks = IndexVec::with_capacity(capacity);
let initial = blocks.push(BlockData {
kind: BlockKind::Start,
..BlockData::default()
});
let terminal = blocks.push(BlockData {
kind: BlockKind::Terminal,
..BlockData::default()
});
Self {
cfg: ControlFlowGraph {
blocks,
initial,
terminal,
},
current: initial,
exit: terminal,
}
}
/// Runs the core logic for the builder.
fn process_stmts(&mut self, stmts: &'stmt [Stmt]) {
let start = 0;
for stmt in stmts {
let cache_exit = self.exit();
match stmt {
Stmt::FunctionDef(_)
| Stmt::ClassDef(_)
| Stmt::Assign(_)
| Stmt::AugAssign(_)
| Stmt::AnnAssign(_)
| Stmt::TypeAlias(_)
| Stmt::Import(_)
| Stmt::ImportFrom(_)
| Stmt::Global(_)
| Stmt::Nonlocal(_)
| Stmt::Expr(_)
| Stmt::Pass(_)
| Stmt::Delete(_)
| Stmt::IpyEscapeCommand(_) => {}
// Loops
Stmt::While(_) => {}
Stmt::For(_) => {}
// Switch statements
Stmt::If(_) => {}
Stmt::Match(_) => {}
// Exception handling statements
Stmt::Try(_) => {}
Stmt::With(_) => {}
// Jumps
Stmt::Return(_) => {}
Stmt::Break(_) => {}
Stmt::Continue(_) => {}
Stmt::Raise(_) => {}
// An `assert` is a mixture of a switch and a jump.
Stmt::Assert(_) => {}
}
// Restore exit
self.update_exit(cache_exit);
}
// It can happen that we have statements left over
// and not yet occupying a block. In that case,
// `self.current` should be pointing to an empty block
// and we push the remaining statements to it here.
if start < stmts.len() {
self.set_current_block_stmts(&stmts[start..]);
}
// Add edge to exit if not already present
if self.cfg.blocks[self.current].out.is_empty() {
let edges = Edges::always(self.exit());
self.set_current_block_edges(edges);
}
self.move_to(self.exit());
}
/// Returns finished control flow graph
fn finish(self) -> ControlFlowGraph<'stmt> {
self.cfg
}
/// Current exit block, which may change during construction
fn exit(&self) -> BlockId {
self.exit
}
/// Point the current exit to block at provided index
fn update_exit(&mut self, new_exit: BlockId) {
self.exit = new_exit;
}
/// Moves current block to provided index
fn move_to(&mut self, block: BlockId) {
self.current = block;
}
/// Populates the current basic block with the given set of statements.
///
/// This should only be called once on any given block.
fn set_current_block_stmts(&mut self, stmts: &'stmt [Stmt]) {
debug_assert!(
self.cfg.blocks[self.current].stmts.is_empty(),
"Attempting to set statements on an already populated basic block."
);
self.cfg.blocks[self.current].stmts = stmts;
}
/// Draws provided edges out of the current basic block.
///
/// This should only be called once on any given block.
fn set_current_block_edges(&mut self, edges: Edges) {
debug_assert!(
self.cfg.blocks[self.current].out.is_empty(),
"Attempting to set edges on a basic block that already has an outgoing edge."
);
self.cfg.blocks[self.current].out = edges;
}
}

View file

@ -0,0 +1,61 @@
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")]
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);
});
}
}

View file

@ -0,0 +1,89 @@
---
source: crates/ruff_python_semantic/src/cfg/mod.rs
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
---
## Function 0
### Source
```python
def func(): ...
```
### Control Flow Graph
```mermaid
flowchart TD
node0["..."]
node1((("EXIT")))
node0==>node1
```
## Function 1
### Source
```python
def func():
pass
```
### Control Flow Graph
```mermaid
flowchart TD
node0["pass"]
node1((("EXIT")))
node0==>node1
```
## Function 2
### Source
```python
def func():
x = 1
x = 2
```
### Control Flow Graph
```mermaid
flowchart TD
node0["x = 1
x = 2"]
node1((("EXIT")))
node0==>node1
```
## Function 3
### Source
```python
def func():
foo()
```
### Control Flow Graph
```mermaid
flowchart TD
node0["foo()"]
node1((("EXIT")))
node0==>node1
```
## Function 4
### Source
```python
def func():
from foo import bar
class C:
a = 1
c = C()
del c
```
### Control Flow Graph
```mermaid
flowchart TD
node0["from foo import bar
class C:
a = 1
c = C()
del c"]
node1((("EXIT")))
node0==>node1
```

View file

@ -0,0 +1,244 @@
//! Heavily inspired by rustc data structures
use ruff_index::Idx;
use ruff_text_size::Ranged;
use std::fmt::{self, Display};
use crate::cfg::graph::{BlockId, BlockKind, Condition, ControlFlowGraph};
/// Returns control flow graph in Mermaid syntax.
pub fn draw_cfg(graph: ControlFlowGraph, source: &str) -> String {
CFGWithSource::new(graph, source).draw_graph()
}
trait MermaidGraph<'a>: DirectedGraph<'a> {
fn draw_node(&self, node: Self::Node) -> MermaidNode;
fn draw_edges(&self, node: Self::Node) -> impl Iterator<Item = (Self::Node, MermaidEdge)>;
fn draw_graph(&self) -> String {
let mut graph = Vec::new();
// Begin mermaid graph.
graph.push("flowchart TD".to_string());
// Draw nodes
let num_nodes = self.num_nodes();
for idx in 0..num_nodes {
let node = Self::Node::new(idx);
graph.push(format!("\tnode{}{}", idx, &self.draw_node(node)));
}
// Draw edges
for idx in 0..num_nodes {
graph.extend(
self.draw_edges(Self::Node::new(idx))
.map(|(end_idx, edge)| format!("\tnode{}{}node{}", idx, edge, end_idx.index())),
);
}
graph.join("\n")
}
}
pub struct MermaidNode {
shape: MermaidNodeShape,
content: String,
}
impl MermaidNode {
pub fn with_content(content: String) -> Self {
Self {
shape: MermaidNodeShape::default(),
content,
}
}
fn mermaid_write_quoted_str(f: &mut fmt::Formatter<'_>, value: &str) -> fmt::Result {
let mut parts = value.split('"');
if let Some(v) = parts.next() {
write!(f, "{v}")?;
}
for v in parts {
write!(f, "#quot;{v}")?;
}
Ok(())
}
}
impl Display for MermaidNode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let (open, close) = self.shape.open_close();
write!(f, "{open}\"")?;
if self.content.is_empty() {
write!(f, "empty")?;
} else {
MermaidNode::mermaid_write_quoted_str(f, &self.content)?;
}
write!(f, "\"{close}")
}
}
#[derive(Debug, Default)]
pub enum MermaidNodeShape {
#[default]
Rectangle,
DoubleRectangle,
RoundedRectangle,
Stadium,
Circle,
DoubleCircle,
Asymmetric,
Rhombus,
Hexagon,
Parallelogram,
Trapezoid,
}
impl MermaidNodeShape {
fn open_close(&self) -> (&'static str, &'static str) {
match self {
Self::Rectangle => ("[", "]"),
Self::DoubleRectangle => ("[[", "]]"),
Self::RoundedRectangle => ("(", ")"),
Self::Stadium => ("([", "])"),
Self::Circle => ("((", "))"),
Self::DoubleCircle => ("(((", ")))"),
Self::Asymmetric => (">", "]"),
Self::Rhombus => ("{", "}"),
Self::Hexagon => ("{{", "}}"),
Self::Parallelogram => ("[/", "/]"),
Self::Trapezoid => ("[/", "\\]"),
}
}
}
#[derive(Debug, Default)]
pub struct MermaidEdge {
kind: MermaidEdgeKind,
content: String,
}
impl Display for MermaidEdge {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.content.is_empty() {
write!(f, "{}", self.kind)
} else {
write!(f, "{}|\"{}\"|", self.kind, self.content)
}
}
}
#[derive(Debug, Default)]
pub enum MermaidEdgeKind {
#[default]
Arrow,
DottedArrow,
ThickArrow,
BidirectionalArrow,
}
impl Display for MermaidEdgeKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MermaidEdgeKind::Arrow => write!(f, "-->"),
MermaidEdgeKind::DottedArrow => write!(f, "-..->"),
MermaidEdgeKind::ThickArrow => write!(f, "==>"),
MermaidEdgeKind::BidirectionalArrow => write!(f, "<-->"),
}
}
}
pub trait DirectedGraph<'a> {
type Node: Idx;
fn num_nodes(&self) -> usize;
fn start_node(&self) -> Self::Node;
fn successors(&self, node: Self::Node) -> impl ExactSizeIterator<Item = Self::Node> + '_;
}
struct CFGWithSource<'stmt> {
cfg: ControlFlowGraph<'stmt>,
source: &'stmt str,
}
impl<'stmt> CFGWithSource<'stmt> {
fn new(cfg: ControlFlowGraph<'stmt>, source: &'stmt str) -> Self {
Self { cfg, source }
}
}
impl<'stmt> DirectedGraph<'stmt> for CFGWithSource<'stmt> {
type Node = BlockId;
fn num_nodes(&self) -> usize {
self.cfg.num_blocks()
}
fn start_node(&self) -> Self::Node {
self.cfg.initial()
}
fn successors(&self, node: Self::Node) -> impl ExactSizeIterator<Item = Self::Node> + '_ {
self.cfg.outgoing(node).targets()
}
}
impl<'stmt> MermaidGraph<'stmt> for CFGWithSource<'stmt> {
fn draw_node(&self, node: Self::Node) -> MermaidNode {
let statements: Vec<String> = self
.cfg
.stmts(node)
.iter()
.map(|stmt| self.source[stmt.range()].to_string())
.collect();
let content = match self.cfg.kind(node) {
BlockKind::Generic => {
if statements.is_empty() {
"EMPTY".to_string()
} else {
statements.join("\n")
}
}
BlockKind::Start => {
if statements.is_empty() {
"START".to_string()
} else {
statements.join("\n")
}
}
BlockKind::Terminal => {
return MermaidNode {
content: "EXIT".to_string(),
shape: MermaidNodeShape::DoubleCircle,
}
}
};
MermaidNode::with_content(content)
}
fn draw_edges(&self, node: Self::Node) -> impl Iterator<Item = (Self::Node, MermaidEdge)> {
let edge_data = self.cfg.outgoing(node);
edge_data
.targets()
.zip(edge_data.conditions())
.map(|(target, condition)| {
let edge = match condition {
Condition::Always => {
if target == self.cfg.terminal() {
MermaidEdge {
kind: MermaidEdgeKind::ThickArrow,
content: String::new(),
}
} else {
MermaidEdge {
kind: MermaidEdgeKind::Arrow,
content: String::new(),
}
}
}
};
(target, edge)
})
.collect::<Vec<_>>()
.into_iter()
}
}

View file

@ -1,6 +1,7 @@
pub mod analyze;
mod binding;
mod branches;
pub mod cfg;
mod context;
mod definition;
mod globals;