Skip to content

Commit c7d23c8

Browse files
fix: make max_conditional iterative (#258)
context: #243 User ran into `RecursionError: maximum recursion depth exceeded` running `_get_max_nested_conditional`. By removing the recursion from the function we hopefully fix this issue. So now it's using text-book definition of BFS to go about finding the max depth. Notice we do have to go through all nodes of the function because we don't know if a node that is not of type conditional doesn't have another conditional inside of it (think block nodes, for example). And we only increase the level when we pass through one conditional, not when we go to the next child. close #243
1 parent 711b01f commit c7d23c8

File tree

3 files changed

+85
-6
lines changed

3 files changed

+85
-6
lines changed

codecov_cli/services/staticanalysis/analyzers/general.py

+21-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import hashlib
2+
from collections import deque
23

34

45
class BaseAnalyzer(object):
@@ -16,10 +17,26 @@ def _count_elements(self, node, types):
1617
count += 1
1718
return count
1819

19-
def _get_max_nested_conditional(self, node):
20-
return (1 if node.type in self.condition_statements else 0) + max(
21-
(self._get_max_nested_conditional(x) for x in node.children), default=0
22-
)
20+
def _get_max_nested_conditional(self, head):
21+
"""Iterates over all nodes in a function body and returns the max nested conditional depth.
22+
Uses BFS to avoid recursion calls (so we don't throw RecursionError)
23+
"""
24+
nodes_to_visit = deque()
25+
nodes_to_visit.append([head, int(head.type in self.condition_statements)])
26+
max_nested_depth = 0
27+
28+
while nodes_to_visit:
29+
curr_node, curr_depth = nodes_to_visit.popleft()
30+
max_nested_depth = max(max_nested_depth, curr_depth)
31+
# Here is where the depth might change
32+
# If the current node is a conditional
33+
is_curr_conditional = curr_node.type in self.condition_statements
34+
35+
# Enqueue all child nodes of the curr_node
36+
for child in curr_node.children:
37+
nodes_to_visit.append([child, curr_depth + is_curr_conditional])
38+
39+
return max_nested_depth
2340

2441
def _get_complexity_metrics(self, body_node):
2542
number_conditions = self._count_elements(

samples/inputs/sample_002.py

+6
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,9 @@ def single_line_minecraft(bb):
2727
c = 0
2828
while c < 1:
2929
print("b")
30+
31+
def nested_conditionals(val):
32+
if val > 10:
33+
if val > 100:
34+
if val > 1000:
35+
return 'large value'

samples/outputs/sample_002.json

+58-2
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,22 @@
4545
"returns": 0,
4646
"max_nested_conditional": 0
4747
}
48+
},
49+
{
50+
"identifier": "nested_conditionals",
51+
"start_line": 31,
52+
"end_line": 35,
53+
"code_hash": "9ee2ce7f737ad1adf8e8e6be70be534b",
54+
"complexity_metrics": {
55+
"conditions": 3,
56+
"max_nested_conditional": 3,
57+
"mccabe_cyclomatic_complexity": 4,
58+
"returns": 1
59+
}
4860
}
4961
],
50-
"hash": "97be1c2949c8f328b8ba5673eba21a84",
51-
"number_lines": 30,
62+
"hash": "9fb6bbc43350a18531adfb399f5cc0ae",
63+
"number_lines": 35,
5264
"statements": [
5365
[
5466
9,
@@ -199,6 +211,46 @@
199211
"len": 0,
200212
"extra_connected_lines": []
201213
}
214+
],
215+
[
216+
32,
217+
{
218+
"extra_connected_lines": [],
219+
"len": 3,
220+
"line_hash": "9ee2ce7f737ad1adf8e8e6be70be534b",
221+
"line_surety_ancestorship": null,
222+
"start_column": 4
223+
}
224+
],
225+
[
226+
33,
227+
{
228+
"extra_connected_lines": [],
229+
"len": 2,
230+
"line_hash": "3d1fa1be2935c716122a2a63eb0070f3",
231+
"line_surety_ancestorship": 32,
232+
"start_column": 8
233+
}
234+
],
235+
[
236+
34,
237+
{
238+
"extra_connected_lines": [],
239+
"len": 1,
240+
"line_hash": "20a6f68248783caeab8abb2ccda43cb3",
241+
"line_surety_ancestorship": 33,
242+
"start_column": 12
243+
}
244+
],
245+
[
246+
35,
247+
{
248+
"extra_connected_lines": [],
249+
"len": 0,
250+
"line_hash": "6c92ccd39eaa87eb873f2de3e475db82",
251+
"line_surety_ancestorship": 34,
252+
"start_column": 16
253+
}
202254
]
203255
],
204256
"definition_lines": [
@@ -213,6 +265,10 @@
213265
[
214266
17,
215267
1
268+
],
269+
[
270+
31,
271+
4
216272
]
217273
],
218274
"import_lines": [

0 commit comments

Comments
 (0)