From 2551f9346a3b377dd02f2c256264734997fcea18 Mon Sep 17 00:00:00 2001 From: Felipe cruz Date: Fri, 14 Sep 2012 21:21:28 -0300 Subject: [PATCH] add `Function.if_nest_level()` returning max nesting level --- README.markdown | 39 +++++++++++++++++++++++++ qc/domain.py | 31 ++++++++++++++++++++ qc/tests/test_qc_parser.py | 58 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) diff --git a/README.markdown b/README.markdown index e026e22..a535224 100644 --- a/README.markdown +++ b/README.markdown @@ -15,6 +15,45 @@ data = analyze("tests/test_file1.c") [func.name for func in data.functions if func.it_calls("read")] ``` +Get max if nest level: + +```python +from qc.parser import analyze +code = """ + int main (int argc, char *argv[]) { + char *space; + space = malloc(sizeof(char) * 10); + if (space == NULL) { + if (1 > 2) { + if (3 == 4) { + return -1; + } + } else { + if (1 == 1) { + return -1; + } else { + if (1 == 2) { + return -1; + } else { + if (1 == 2) { + return -1; + } else { + return -1; + } + } + } + } + return -1; + } + return 0; + } +""" + +parsed_content = parse(code, "") +main = parsed_content.functions[0] +assert 5 == main.if_nest_level() +``` + ## Testing ```sh diff --git a/qc/domain.py b/qc/domain.py index 2e94b2b..cdecda1 100644 --- a/qc/domain.py +++ b/qc/domain.py @@ -16,5 +16,36 @@ def it_calls(self, inner_function_name): isinstance(call.rvalue, c_ast.FuncCall) and call.rvalue.name.name == inner_function_name)]) + def if_nest_level(self): + def nest_meter(if_statement): + values = [] + if hasattr(if_statement, 'iftrue') and if_statement.iftrue and \ + len(if_statement.iftrue.block_items): + nested_ifs = [if_stm for if_stm + in if_statement.iftrue.block_items + if isinstance(if_stm, c_ast.If)] + for nested_if in nested_ifs: + values.append(1 + nest_meter(nested_if)) + if hasattr(if_statement, 'iffalse') and if_statement.iffalse and \ + len(if_statement.iffalse.block_items): + nested_ifs = [if_stm for if_stm + in if_statement.iffalse.block_items + if isinstance(if_stm, c_ast.If)] + for nested_if in nested_ifs: + values.append(1 + nest_meter(nested_if)) + + if not values: + return 1 + + return max(values) + + values = [] + for block in self.blocks: + if isinstance(block, c_ast.If): + values.append(nest_meter(block)) + + return max(values) + + def __str__(self): return str(self.node) diff --git a/qc/tests/test_qc_parser.py b/qc/tests/test_qc_parser.py index 5c5783d..58d4c1f 100644 --- a/qc/tests/test_qc_parser.py +++ b/qc/tests/test_qc_parser.py @@ -43,3 +43,61 @@ def test_parse_check_functions_calling_malloc(): assert "main" == [function.name for function in parsed_content.functions if function.it_calls("malloc")][0] + +def test_parse_check_if_nest_level(): + code = """ + int main (int argc, char *argv[]) { + char *space; + space = malloc(sizeof(char) * 10); + if (space == NULL) { + if (1 > 2) { + if (3 == 4) { + return -1; + } + } + return -1; + } + return 0; + } + """ + parsed_content = parse(code, "") + assert parsed_content + assert 1 == len(parsed_content.functions) + assert "main" == parsed_content.functions[0].name + assert 3 == parsed_content.functions[0].if_nest_level() + +def test_parse_check_if_else_nest_level(): + code = """ + int main (int argc, char *argv[]) { + char *space; + space = malloc(sizeof(char) * 10); + if (space == NULL) { + if (1 > 2) { + if (3 == 4) { + return -1; + } + } else { + if (1 == 1) { + return -1; + } else { + if (1 == 2) { + return -1; + } else { + if (1 == 2) { + return -1; + } else { + return -1; + } + } + } + } + return -1; + } + return 0; + } + """ + parsed_content = parse(code, "") + assert parsed_content + assert 1 == len(parsed_content.functions) + assert "main" == parsed_content.functions[0].name + assert 5 == parsed_content.functions[0].if_nest_level()