diff --git a/htmlreport/cppcheck-htmlreport b/htmlreport/cppcheck-htmlreport
index c26a137a4ad..a70fbdb4c83 100755
--- a/htmlreport/cppcheck-htmlreport
+++ b/htmlreport/cppcheck-htmlreport
@@ -139,7 +139,7 @@ label.checkBtn > input {
table.summaryTable td { padding: 0 5px 0 5px; }
-.statHeader, .severityHeader {
+.statHeader, .severityHeader, .classificationHeader {
font-weight: bold;
}
@@ -201,7 +201,7 @@ table.summaryTable td { padding: 0 5px 0 5px; }
padding-right: 6px;
}
-.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered {
+.id-filtered, .severity-filtered, .classification-filtered, .file-filtered, .tool-filtered, .text-filtered {
visibility: collapse;
}
"""
@@ -278,7 +278,18 @@ HTML_HEAD = """
updateFileRows();
}
+
+ function toggleClassification(cb) {
+ cb.parentElement.classList.toggle("unchecked", !cb.checked);
+ var elements = document.querySelectorAll(".class_" + cb.id);
+
+ for (var i = 0, len = elements.length; i < len; i++) {
+ elements[i].classList.toggle("classification-filtered", !cb.checked);
+ }
+ updateFileRows();
+ }
+
function toggleTool(cb) {
cb.parentElement.classList.toggle("unchecked", !cb.checked);
@@ -340,7 +351,7 @@ HTML_HEAD = """
var elements = document.querySelectorAll(".fileEntry");
for (var i = 0, len = elements.length; i < len; i++) {
- var visible = elements[i].querySelector(".issue:not(.id-filtered):not(.severity-filtered):not(.tool-filtered):not(.text-filtered)");
+ var visible = elements[i].querySelector(".issue:not(.id-filtered):not(.severity-filtered):not(.classification-filtered):not(.tool-filtered):not(.text-filtered)");
elements[i].classList.toggle("file-filtered", !visible);
}
}
@@ -399,20 +410,27 @@ def html_escape(text):
def filter_button(enabled_filters, id, function):
enabled = enabled_filters.get(id, False)
+ if not id:
+ id = 'None'
return '\n '\
% (' disabled' if not enabled else '', function, id, 'checked' if enabled else 'disabled', id)
def filter_bar(enabled):
+ severity_bar = ''.join([filter_button(enabled, severity, 'toggleSeverity') for severity in ['error', 'warning', 'portability', 'performance', 'style', 'information']]) + '\n | '
+ classification_bar = ''.join([filter_button(enabled, _class, 'toggleClassification') for _class in ['Mandatory', 'Required', 'Advisory', 'Document', 'Disapplied', 'L1','L2','L3','']]) + '\n | '
+ if "checked/>" not in severity_bar:
+ severity_bar = ''
+ if "checked/>" not in classification_bar:
+ classification_bar = ''
return ''.join([
'
\n'
- ,''.join([filter_button(enabled, severity, 'toggleSeverity') for severity in ['error', 'warning', 'portability', 'performance', 'style', 'information']])
- ,'\n | '
+ ,severity_bar
+ , classification_bar
,''.join([filter_button(enabled, tool, 'toggleTool') for tool in ['cppcheck', 'clang-tidy']])
,'\n | '
,'\n '
,'\n '
,'\n
\n'])
-
def git_blame(errors, path, file, blame_options):
last_line= errors[-1]['line']
if last_line == 0:
@@ -471,14 +489,20 @@ def blame_lookup(blame_data, line):
return next((data for start, end, data in blame_data if line >= start and line < end), {})
-def tr_str(td_th, line, id, cwe, severity, message, timestamp, author, author_mail, date, add_author, tr_class=None, htmlfile=None, message_class=None):
+def tr_str(td_th, line, id, cwe, severity, classification, guideline, message, timestamp, author, author_mail, date, add_author, tr_class=None, htmlfile=None, message_class=None):
ret = ''
+ items = [id, cwe]
+ if severity:
+ items.append(severity)
+ if classification:
+ items.extend([classification, guideline])
if htmlfile:
ret += '<%s>%d%s>' % (td_th, htmlfile, line, line, td_th)
- for item in (id, cwe, severity):
+ for item in items:
ret += '<%s>%s%s>' % (td_th, item, td_th)
else:
- for item in (line, id, cwe, severity):
+ items.insert(0,line)
+ for item in items:
ret += '<%s>%s%s>' % (td_th, item, td_th)
if message_class:
message_attribute = ' class="%s"' % message_class
@@ -561,6 +585,7 @@ class CppCheckHandler(XmlContentHandler):
self.version = '1'
self.versionCppcheck = ''
self.timestamp = ''
+ self.report_type = False
def startElement(self, name, attributes):
if name == 'results':
@@ -574,7 +599,10 @@ class CppCheckHandler(XmlContentHandler):
def handleVersion1(self, name, attributes):
if name != 'error':
return
-
+ att_class = attributes.get('classification', '')
+ att_guide = attributes.get('guideline', '')
+ if att_class and not self.report_type:
+ self.report_type = True
self.errors.append({
'file': attributes.get('file', ''),
'line': int(attributes.get('line', 0)),
@@ -584,6 +612,8 @@ class CppCheckHandler(XmlContentHandler):
}],
'id': attributes['id'],
'severity': attributes['severity'],
+ 'classification': att_class,
+ 'guideline': att_guide,
'timestamp': self.timestamp,
'msg': attributes['msg']
})
@@ -592,12 +622,18 @@ class CppCheckHandler(XmlContentHandler):
if name == 'cppcheck':
self.versionCppcheck = attributes['version']
if name == 'error':
+ att_class = attributes.get('classification', '')
+ att_guide = attributes.get('guideline', '')
+ if att_class and not self.report_type:
+ self.report_type = True
error = {
'locations': [],
'file': '',
'line': 0,
'id': attributes['id'],
+ 'classification': att_class,
'severity': attributes['severity'],
+ 'guideline': att_guide,
'timestamp': self.timestamp,
'msg': attributes['msg'],
'verbose': attributes.get('verbose')
@@ -623,7 +659,6 @@ class CppCheckHandler(XmlContentHandler):
'line': line,
'info': attributes.get('info')
})
-
def main() -> None:
# Configure all the options this little utility is using.
parser = argparse.ArgumentParser()
@@ -751,6 +786,8 @@ def main() -> None:
if location.get('info'):
newError['msg'] = location['info']
newError['severity'] = 'information'
+ newError['classification'] = ''
+ newError['guideline'] = ''
del newError['verbose']
errors.append(newError)
@@ -832,7 +869,12 @@ def main() -> None:
for filename, data in sorted(files.items()):
for error in data['errors']:
stats.append(error['id']) # get the stats
- filter_enabled[error['severity']] = True
+ if contentHandler.report_type:
+ filter_enabled[error['severity']] = False
+ filter_enabled[error['classification']] = True
+ else:
+ filter_enabled[error['severity']] = True
+ filter_enabled[error['classification']] = False
filter_enabled['clang-tidy' if error['id'].startswith('clang-tidy-') else 'cppcheck'] = True
stats_count += 1
@@ -877,9 +919,15 @@ def main() -> None:
output_file.write(HTML_MENU_END.replace("content", "content_index", 1))
output_file.write('\n ')
- output_file.write(
- '\n %s' %
- tr_str('th', 'Line', 'Id', 'CWE', 'Severity', 'Message', 'Timestamp', 'Author', 'Author mail', 'Date (DD/MM/YYYY)', add_author=add_author_information))
+ if contentHandler.report_type:
+ output_file.write(
+ '\n %s' %
+ tr_str('th', 'Line', 'Id', 'CWE', '', 'Classification', 'Guideline', 'Message', 'Timestamp',
+ 'Author', 'Author mail', 'Date (DD/MM/YYYY)', add_author=add_author_information))
+ else:
+ output_file.write(
+ '\n %s' %
+ tr_str('th', 'Line', 'Id', 'CWE', 'Severity', '', '', 'Message', 'Timestamp', 'Author', 'Author mail', 'Date (DD/MM/YYYY)', add_author=add_author_information))
for filename, data in sorted(files.items()):
file_error = filename in decode_errors or filename.endswith('*')
@@ -916,13 +964,20 @@ def main() -> None:
message_class = error['severity']
line = error["line"] if is_file else ""
-
+ _severity = error.get('severity', '')
+ _classification = error.get('classification', '')
+ _guideline = error.get('guideline', '')
+ if contentHandler.report_type:
+ _severity = ''
+ if not _classification:
+ _classification = 'None'
+ _guideline = 'None'
output_file.write(
'\n %s' %
- tr_str('td', line, error["id"], cwe_url, error["severity"], error["msg"], error["timestamp"],
+ tr_str('td', line, error["id"], cwe_url, _severity, _classification, _guideline, error["msg"], error["timestamp"],
git_blame_dict.get('author', 'Unknown'), git_blame_dict.get('author-mail', '---'),
git_blame_dict.get('author-time', '---'),
- tr_class=to_css_selector(error["id"]) + ' sev_' + error["severity"] + ' issue',
+ tr_class=to_css_selector(error["id"]) + ' sev_' + _severity +' class_' + _classification + ' issue',
message_class=message_class,
add_author=add_author_information,
htmlfile=htmlfile))