From 5b6df8b1cc7020c55a5efc1e82b908a0b1d337b1 Mon Sep 17 00:00:00 2001 From: wy Date: Tue, 18 Feb 2025 16:20:14 +0800 Subject: [PATCH] fix #8089 --- htmlreport/cppcheck-htmlreport | 20 +++++++++++++++++--- test/tools/htmlreport/test_htmlreport.py | 13 +++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/htmlreport/cppcheck-htmlreport b/htmlreport/cppcheck-htmlreport index 492ce90e196..1bac04ec74c 100755 --- a/htmlreport/cppcheck-htmlreport +++ b/htmlreport/cppcheck-htmlreport @@ -11,6 +11,7 @@ import os import re import sys import subprocess +import time from collections import Counter from pygments import highlight @@ -470,7 +471,7 @@ 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, author, author_mail, date, add_author, tr_class=None, htmlfile=None, message_class=None): +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): ret = '' if htmlfile: ret += '<%s>%d' % (td_th, htmlfile, line, line, td_th) @@ -485,6 +486,9 @@ def tr_str(td_th, line, id, cwe, severity, message, author, author_mail, date, a message_attribute = '' ret += '<%s%s>%s' % (td_th, message_attribute, html_escape(message), td_th) + if timestamp: + ret += '<%s>%s' % (td_th, timestamp, td_th) + for field in add_author: if field == 'name': ret += '<%s>%s' % (td_th, html_escape(author), td_th) @@ -556,6 +560,7 @@ class CppCheckHandler(XmlContentHandler): self.errors = [] self.version = '1' self.versionCppcheck = '' + self.timestamp = '' def startElement(self, name, attributes): if name == 'results': @@ -579,6 +584,7 @@ class CppCheckHandler(XmlContentHandler): }], 'id': attributes['id'], 'severity': attributes['severity'], + 'timestamp': self.timestamp, 'msg': attributes['msg'] }) @@ -592,6 +598,7 @@ class CppCheckHandler(XmlContentHandler): 'line': 0, 'id': attributes['id'], 'severity': attributes['severity'], + 'timestamp': self.timestamp, 'msg': attributes['msg'], 'verbose': attributes.get('verbose') } @@ -694,6 +701,13 @@ def main() -> None: try: contentHandler = CppCheckHandler() for fname in options.file or [sys.stdin]: + if options.file is not None: + t = os.path.getmtime(fname) + else: + t = time.time() + t_s = time.ctime(t) + if t_s is not None: + contentHandler.timestamp = t_s xml_parse(fname, contentHandler) except (XmlParseException, ValueError) as msg: print('Failed to parse cppcheck xml file: %s' % msg) @@ -865,7 +879,7 @@ def main() -> None: output_file.write('\n ') output_file.write( '\n %s' % - tr_str('th', 'Line', 'Id', 'CWE', 'Severity', 'Message', 'Author', 'Author mail', 'Date (DD/MM/YYYY)', add_author=add_author_information)) + 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('*') @@ -905,7 +919,7 @@ def main() -> None: output_file.write( '\n %s' % - tr_str('td', line, error["id"], cwe_url, error["severity"], error["msg"], + tr_str('td', line, error["id"], cwe_url, error["severity"], 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', diff --git a/test/tools/htmlreport/test_htmlreport.py b/test/tools/htmlreport/test_htmlreport.py index cec5aafea06..6f8713f4f55 100755 --- a/test/tools/htmlreport/test_htmlreport.py +++ b/test/tools/htmlreport/test_htmlreport.py @@ -8,6 +8,7 @@ import tempfile import unittest +import time TEST_TOOLS_DIR = os.path.abspath(os.path.dirname(__file__)) ROOT_DIR = os.path.split(os.path.dirname(os.path.dirname(TEST_TOOLS_DIR)))[0] @@ -94,6 +95,18 @@ def testAddCheckersReport(self): output_directory.cleanup() + def testAddTimestamp(self): + with runCheck( + xml_filename=os.path.join(TEST_TOOLS_DIR, 'example.xml'), + ) as (report, output_directory): + xml_file = os.path.join(TEST_TOOLS_DIR, 'example.xml') + t = os.path.getmtime(xml_file) + t_s = time.ctime(t) + + self.assertIn(t_s, report) + + output_directory.cleanup() + @contextlib.contextmanager def runCheck(source_filename=None, xml_version='1', xml_filename=None, checkers_filename=None):