Skip to content

Commit

Permalink
Add unreachable code rule (#5384)
Browse files Browse the repository at this point in the history
Co-authored-by: Thomas de Zeeuw <[email protected]>
Co-authored-by: Micha Reiser <[email protected]>
  • Loading branch information
3 people authored Jul 4, 2023
1 parent 937de12 commit 0b963dd
Show file tree
Hide file tree
Showing 30 changed files with 4,688 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ crates/ruff/resources/test/fixtures/isort/line_ending_crlf.py text eol=crlf
crates/ruff/resources/test/fixtures/pycodestyle/W605_1.py text eol=crlf

ruff.schema.json linguist-generated=true text=auto eol=lf
*.md.snap linguist-language=Markdown
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions crates/ruff/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ name = "ruff"
[dependencies]
ruff_cache = { path = "../ruff_cache" }
ruff_diagnostics = { path = "../ruff_diagnostics", features = ["serde"] }
ruff_index = { path = "../ruff_index" }
ruff_macros = { path = "../ruff_macros" }
ruff_python_whitespace = { path = "../ruff_python_whitespace" }
ruff_python_ast = { path = "../ruff_python_ast", features = ["serde"] }
Expand Down Expand Up @@ -88,3 +89,5 @@ colored = { workspace = true, features = ["no-color"] }
[features]
default = []
schemars = ["dep:schemars"]
# Enables the UnreachableCode rule
unreachable-code = []
11 changes: 11 additions & 0 deletions crates/ruff/resources/test/fixtures/control-flow-graph/assert.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
def func():
assert True

def func():
assert False

def func():
assert True, "oops"

def func():
assert False, "oops"
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
def func():
async for i in range(5):
print(i)

def func():
async for i in range(20):
print(i)
else:
return 0

def func():
async for i in range(10):
if i == 5:
return 1
return 0

def func():
async for i in range(111):
if i == 5:
return 1
else:
return 0
return 2

def func():
async for i in range(12):
continue

def func():
async for i in range(1110):
if True:
continue

def func():
async for i in range(13):
break

def func():
async for i in range(1110):
if True:
break
41 changes: 41 additions & 0 deletions crates/ruff/resources/test/fixtures/control-flow-graph/for.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
def func():
for i in range(5):
print(i)

def func():
for i in range(20):
print(i)
else:
return 0

def func():
for i in range(10):
if i == 5:
return 1
return 0

def func():
for i in range(111):
if i == 5:
return 1
else:
return 0
return 2

def func():
for i in range(12):
continue

def func():
for i in range(1110):
if True:
continue

def func():
for i in range(13):
break

def func():
for i in range(1110):
if True:
break
108 changes: 108 additions & 0 deletions crates/ruff/resources/test/fixtures/control-flow-graph/if.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
def func():
if False:
return 0
return 1

def func():
if True:
return 1
return 0

def func():
if False:
return 0
else:
return 1

def func():
if True:
return 1
else:
return 0

def func():
if False:
return 0
else:
return 1
return "unreachable"

def func():
if True:
return 1
else:
return 0
return "unreachable"

def func():
if True:
if True:
return 1
return 2
else:
return 3
return "unreachable2"

def func():
if False:
return 0

def func():
if True:
return 1

def func():
if True:
return 1
elif False:
return 2
else:
return 0

def func():
if False:
return 1
elif True:
return 2
else:
return 0

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

def func():
if False:
return "unreached"
elif False:
return "also unreached"
return "reached"

# Test case found in the Bokeh repository that trigger a false positive.
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
131 changes: 131 additions & 0 deletions crates/ruff/resources/test/fixtures/control-flow-graph/match.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
def func(status):
match status:
case _:
return 0
return "unreachable"

def func(status):
match status:
case 1:
return 1
return 0

def func(status):
match status:
case 1:
return 1
case _:
return 0

def func(status):
match status:
case 1 | 2 | 3:
return 5
return 6

def func(status):
match status:
case 1 | 2 | 3:
return 5
case _:
return 10
return 0

def func(status):
match status:
case 0:
return 0
case 1:
return 1
case 1:
return "1 again"
case _:
return 3

def func(status):
i = 0
match status, i:
case _, _:
return 0

def func(status):
i = 0
match status, i:
case _, 0:
return 0
case _, 2:
return 0

def func(point):
match point:
case (0, 0):
print("Origin")
case _:
raise ValueError("oops")

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")

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")

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")

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")

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 :(")
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
def func():
raise Exception

def func():
raise "a glass!"
23 changes: 23 additions & 0 deletions crates/ruff/resources/test/fixtures/control-flow-graph/simple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
def func():
pass

def func():
pass

def func():
return

def func():
return 1

def func():
return 1
return "unreachable"

def func():
i = 0

def func():
i = 0
i += 2
return i
Loading

0 comments on commit 0b963dd

Please sign in to comment.