From 9d71df0452974b32adb9d0bbe6f1623f4a498f0c Mon Sep 17 00:00:00 2001 From: AfonsoSantos96 Date: Tue, 10 Oct 2023 10:19:40 +0100 Subject: [PATCH] feat(HIS): add function calls metric check to script Signed-off-by: Afonso Santos --- docker/Dockerfile | 1 + his_checker.py | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 530ebf4..eb9082a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -27,6 +27,7 @@ RUN apt-get update && apt-get install -y \ clang-tidy-$CLANG_VERSION \ nodejs \ npm \ + cflow \ enchant-2 && \ pip3 install gitlint && \ pip3 install license-expression && \ diff --git a/his_checker.py b/his_checker.py index 2ec03e9..115785d 100755 --- a/his_checker.py +++ b/his_checker.py @@ -9,16 +9,61 @@ import sys import argparse +import os +import re + +CALL_THRESHOLD = 7 + +def process_calls(files): + + """Process the number of calls inside a function.""" + + metric_fail = 0 + cflow = "cflow -l --depth=2" + print("Checking the number of called functions") + for file in files.files: + lines = os.popen(f"{cflow} {file}").read().split('\n') + call_counter = 0 + for line in lines: + if not line: + continue + depth = int(line.split('}')[0].strip('{ ').strip()) + if depth == 0: + if call_counter > CALL_THRESHOLD: + print(f"{function_info} calls {call_counter} functions." + f" The maximum are {CALL_THRESHOLD} calls") + metric_fail += 1 + match = re.match( + r'\{\s*(\d+)\}\s+(.*?)\(\) <.*?at (.*?):(\d+)>', line) + if match: + depth, function_name, file_path, line_number = \ + match.groups() + function_info = ( + f"At {file_path} ({line_number}): {function_name}") + call_counter = 0 + elif depth >= 1: + call_counter += 1 + if call_counter > CALL_THRESHOLD: + print(f"{function_info} calls {call_counter} functions. " + f"The maximum are {CALL_THRESHOLD} calls") + metric_fail += 1 + print(f"Check done with {metric_fail} error(s)\n") + return metric_fail if __name__ == "__main__": - METRICS_LIST = [] + METRICS_LIST = [process_calls] CHECK_FAIL = 0 PARSER = argparse.ArgumentParser() PARSER.add_argument("files", nargs="+", help="The files to process") ARGS = PARSER.parse_args() + NULL_FD = os.open('/dev/null', os.O_WRONLY) + os.dup2(NULL_FD, 2) # Redirect tools' stderr messages + for metric in METRICS_LIST: CHECK_FAIL += metric(ARGS) + os.close(NULL_FD) + if CHECK_FAIL: sys.exit(-1)