From 157d3be27bdaf96b22dadea52e5cbe92937eb02d Mon Sep 17 00:00:00 2001 From: Grigoris Pavlakis <grigpavl@ece.auth.gr> Date: Sat, 23 Mar 2019 01:01:03 +0200 Subject: [PATCH] Clean up MISRA scripts according to review comments Change variable and function names to be more pythonic Replace the ugly ANSI escapes with more readable, reusable strings Pad the resulting strings for readability Close the file after reading its lines Delete a redundant loop in the parser code, credits to @dimst23 Fix comments to foolow Python conventions Comment fixing vol. 2 Encapsulate the 2 functions into a class Fix various blunders with the class encapsulation --- ci/cppcheck-misra.sh | 12 ++--- ci/summarizer.py | 110 ++++++++++++++++++++++++------------------- 2 files changed, 64 insertions(+), 58 deletions(-) diff --git a/ci/cppcheck-misra.sh b/ci/cppcheck-misra.sh index 96e0c9cd..529f96ae 100755 --- a/ci/cppcheck-misra.sh +++ b/ci/cppcheck-misra.sh @@ -14,17 +14,11 @@ curl https://raw.githubusercontent.com/danmar/cppcheck/f4b5b156d720c712f6ce99f6e # generate dump files (XML representations of AST etc.) for all headers, source files etc. echo -e "\u001b[34;1mGenerating dump files...\u001b[0m" -for file in $(find inc/ src/ -type f \( -iname "*.cpp" -or -iname "*.hpp" \)) -do - cppcheck --dump $file -done +find inc/ src/ -type f \( -iname "*.cpp" -or -iname "*.hpp" \) | xargs cppcheck --dump # run the MISRA checks against the dumps and send the results to a file echo -e "\u001b[34;1mRunning MISRA C(2012) rule compliance tests...\u001b[0m" -for file in $(find inc/ src/ -type f -name "*.dump") -do - python ci/misra.py $file >> ci/report.msr 2>&1 -done +find inc/ src/ -type f -name "*.dump" | xargs python3 ci/misra.py >> ci/report.msr 2>&1 # pre-process the generated report to remove all useless strings echo -e "\u001b[34;1mPre-processing report...\u001b[0m" @@ -32,4 +26,4 @@ sed -i -r 's/(.*Script.*)|(.*Checking.*)|(.*MISRA.*)//gm; /(^$)/d; s/(\s\(.*\)\s # run the summarizer for a nice, clean summary of errors echo -e "\u001b[34;1mSummarizing results...\u001b[0m" -python ci/summarizer.py ci/report.msr +python3 ci/summarizer.py ci/report.msr diff --git a/ci/summarizer.py b/ci/summarizer.py index 60090ef3..b7a3aa17 100755 --- a/ci/summarizer.py +++ b/ci/summarizer.py @@ -1,68 +1,80 @@ -#!/bin/env python +#!/bin/env python3 from sys import argv from sys import exit from collections import Counter -''' +""" Naive parser and pretty printer for the MISRA reports by cppcheck -''' +""" -script, reportfile = argv -def analyze(): - ''' - A really dumb parser for the pre-processed report generated by cppcheck - ''' - errorsMap = {} # keys: filenames, values: list of tuples containing rule violated and line - file = open(reportfile, 'r') - fileLines = file.readlines() - cppcheckNumOfErrors = len(fileLines) # number of errors in the original report (most of these are duplicates) - linesSeen = set() # contains the unique lines from the file +red = "\033[91m" +yellow = "\033[93m" +green = "\033[92m" +bold = "\033[1m" +end = "\033[0m" + +class Summarizer(object): + def __init__(self, report_name): + with open(report_name, 'r') as f: + self.file_lines = f.readlines() + f.close() + + def analyze(self): + """ + A really dumb parser for the pre-processed report generated by cppcheck + """ + + errors_map = {} # dictionary containing filenames, rule violations and line where the violation occurred - if len(fileLines) == 0: - print("\033[1m\033[92mStatic analysis for MISRA compliance complete. No errors found.") - return 0 - else: - for line in fileLines: # remove duplicate lines - if line not in linesSeen: - linesSeen.add(line) + lines_seen = set() # contains the unique lines from the file + + if len(self.file_lines) == 0: + print(bold + green + "Static analysis for MISRA compliance complete. No errors found." + end) + return 0 + else: + for line in self.file_lines: # remove duplicate lines + if line not in lines_seen: + lines_seen.add(line) - for line in linesSeen: # after cleaning up the duplicates, split the line into parts - lineContents = line.split(':') - fileName = lineContents[0] # first part is the filename (index 0) - error = (lineContents[1], lineContents[2].strip('\n')) # index 1: line number, index 2: number of violated rule + line_contents = line.split(':') + file_name = line_contents[0] # first part is the filename (index 0) + error = (line_contents[1], line_contents[2].strip('\n')) # index 1 is the line number, index 2 is the number of violated rule - if fileName not in errorsMap.keys(): - errorsMap[fileName] = list() # create a new list for the new filename and append the tuple in it - errorsMap[fileName].append(error) - else: - errorsMap[fileName].append(error) # do not append if it already exists + if file_name not in errors_map.keys(): + errors_map[file_name] = list() # create a new list for the new filename and append the tuple in it + errors_map[file_name].append(error) + else: + errors_map[file_name].append(error) # do not append if it already exists - return errorsMap # return the completed error dictionary + return errors_map # return the completed error dictionary + + + def pretty_print(self, errors): + """ + Pretty-prints the contents of the error dictionary with colors and stuff + """ + print(bold + red + "=================================================\n" + end) + print(bold + red + " Static analysis results: Error Summary \n" + end) + for key in errors: + for error in errors[key]: + name_string = f"{bold}{red}File {yellow}{key}{red}" + rule_violated_string = f"violates rule {yellow}#{error[1]}{red} of the MISRA C 2012 standard" + line_number_string = f"at line {yellow}{error[0]}{end}" -def prettyprint(errors): - ''' - Prettyprints the contents of the error dictionary with colors and stuff - ''' - print("\033[1m\033[91m=================================================\n") - print("\033[1m Static analysis results: Error Summary \n") - for key in errors: - for error in errors[key]: - print("\033[1mFile \033[93m{0}\033[91m violates rule \033[93m#{1}\033[91m of the MISRA C 2012 standard at line \033[93m{2}\033[91m".format(key, error[1], error[0])) - print "" - print "" - print("\033[1m=================================================\033[0m\n") + print(f"{name_string.ljust(75)} {rule_violated_string} {line_number_string}") + print("") + print("") + print(bold + red +"=================================================" + end) -def run(): - errors = analyze() + +if __name__ == "__main__": + s = Summarizer(argv[1]) + errors = s.analyze() if isinstance(errors, dict): - prettyprint(errors) + s.pretty_print(errors) exit(127) elif isinstance(errors, int) and errors == 0: exit(0) - - -if __name__ == "__main__": - run() -- GitLab