htmlreport: show statistics; top 10 files with the most findings for each severity (style, error, warning, portability etc). Partly addresses #1019.

This commit is contained in:
Matthias Krüger 2015-04-20 09:17:45 +02:00
parent 74564e3256
commit 2681b0e56e
1 changed files with 60 additions and 3 deletions

View File

@ -6,8 +6,9 @@ import io
import sys import sys
import optparse import optparse
import os import os
from collections import Counter import operator
from collections import Counter
from pygments import highlight from pygments import highlight
from pygments.lexers import guess_lexer_for_filename from pygments.lexers import guess_lexer_for_filename
from pygments.formatters import HtmlFormatter from pygments.formatters import HtmlFormatter
@ -15,7 +16,6 @@ from xml.sax import parse as xml_parse
from xml.sax import SAXParseException as XmlParseException from xml.sax import SAXParseException as XmlParseException
from xml.sax.handler import ContentHandler as XmlContentHandler from xml.sax.handler import ContentHandler as XmlContentHandler
from xml.sax.saxutils import escape from xml.sax.saxutils import escape
""" """
Turns a cppcheck xml file into a browsable html report along Turns a cppcheck xml file into a browsable html report along
with syntax highlighted source code. with syntax highlighted source code.
@ -425,6 +425,7 @@ if __name__ == '__main__':
# Generate a HTML file with syntax highlighted source code for each # Generate a HTML file with syntax highlighted source code for each
# file that contains one or more errors. # file that contains one or more errors.
print('Processing errors') print('Processing errors')
decode_errors = [] decode_errors = []
for filename, data in sorted(files.items()): for filename, data in sorted(files.items()):
htmlfile = data['htmlfile'] htmlfile = data['htmlfile']
@ -525,7 +526,7 @@ if __name__ == '__main__':
stat_html.append(" " + str(dict(Counter(stats).most_common())[_id]) + " " + str(_id) + "<br/>\n") stat_html.append(" " + str(dict(Counter(stats).most_common())[_id]) + " " + str(_id) + "<br/>\n")
output_file.write(HTML_HEAD.replace('id="menu" dir="rtl"', 'id="menu_index"', 1).replace("Defects:", "Defect summary;", 1) % (options.title, '', options.title, '', '')) output_file.write(HTML_HEAD.replace('id="menu" dir="rtl"', 'id="menu_index"', 1).replace("Defects:", "Defect summary;", 1) % (options.title, '', options.title, '', ''))
output_file.write(' <p>\n' + ' ' + str(stats_count) + ' total<br/><br/>\n' + ''.join(stat_html) + ' </p>') output_file.write(' <p>\n' + ' ' + str(stats_count) + ' total<br/><br/>\n' + ''.join(stat_html) + '<br/><br/><a href="stats.html">Statistics</a></p>')
output_file.write(HTML_HEAD_END.replace("content", "content_index", 1)) output_file.write(HTML_HEAD_END.replace("content", "content_index", 1))
output_file.write(' <table>\n') output_file.write(' <table>\n')
output_file.write( output_file.write(
@ -583,4 +584,60 @@ if __name__ == '__main__':
'w') as css_file: 'w') as css_file:
css_file.write(STYLE_FILE) css_file.write(STYLE_FILE)
print("Creating stats.html (statistics)\n")
stats_countlist={}
for filename, data in sorted(files.items()):
if (filename == ''):
continue
stats_tmplist=[]
for error in sorted(data['errors'], key=lambda k: k['line']):
stats_tmplist.append(error['severity'])
stats_countlist[filename] = dict(Counter(stats_tmplist))
# get top ten for each severity
SEVERITIES = "error", "warning", "portability", "performance", "style", "unusedFunction", "information", "missingInclude", "internal"
with io.open(os.path.join(options.report_dir, 'stats.html'), 'w') as stats_file:
stats_file.write(HTML_HEAD.replace('id="menu" dir="rtl"', 'id="menu_index"', 1).replace("Defects:", "Back to summary", 1) % (options.title, '', options.title, 'Statistics', ''))
stats_file.write(HTML_HEAD_END.replace("content", "content_index", 1))
for sev in SEVERITIES:
_sum = 0
stats_templist={}
try: # if the we have an style warning but we are checking for portability, we have to skip it to prevent KeyError
for filename in stats_countlist:
try: # also bail out if we have a file with no sev-results
_sum += stats_countlist[filename][sev]
stats_templist[filename] = (int)(stats_countlist[filename][sev]) # file : amount,
except KeyError:
continue
if (_sum == 0): # don't print "0 style" etc, if no style warnings were found
break
except KeyError:
continue
stats_file.write("<p>Top 10 files for " + sev + " severity, total findings: " + str(_sum) + "</br>\n")
# sort, so that the file with the most severities per type is first
stats_list_sorted = sorted(stats_templist.items(), key=operator.itemgetter(1,0), reverse=True)
it = 0
LENGTH = 0
for i in stats_list_sorted: # printing loop
# for aesthetics: if it's the first iteration of the loop, get the max length of the number string
if (it == 0):
LENGTH = len(str(i[1])) # <- length of longest number, now get the difference and try to make other numbers align to it
stats_file.write("&#160;"*3 + str(i[1]) + "&#160;"*(1 + LENGTH - len(str(i[1]))) + "<a href=\"" + files[i[0]]['htmlfile'] + "\"> " + i[0] + "</a></br>\n")
it += 1
if (it == 10): # print only the top 10
break
stats_file.write("</p>\n")
print("\nOpen '" + options.report_dir + "/index.html' to see the results.") print("\nOpen '" + options.report_dir + "/index.html' to see the results.")