def postprocess_result(self, skip_handler: Optional[SkipListHandler]): """ Generate analyzer result output file which can be parsed and stored into the database. """ LOG.debug_analyzer(self.analyzer_stdout) tidy_stdout = self.analyzer_stdout.splitlines() reports = Parser().get_reports_from_iter(tidy_stdout) reports = [r for r in reports if not r.skip(skip_handler)] # In the earlier versions of CodeChecker Clang Tidy never used context # free hash even if we enabled it with '--report-hash context-free' # when calling the analyze command. To do not break every hash # automatically when using this option we introduced a new choice for # --report-hash option ('context-free-v2') and we still do not use # context free hash for 'context-free' choice. hash_type = HashType.PATH_SENSITIVE if self.report_hash_type == 'context-free-v2': hash_type = HashType.CONTEXT_FREE elif self.report_hash_type == 'diagnostic-message': hash_type = HashType.DIAGNOSTIC_MESSAGE for report in reports: report.report_hash = get_report_hash(report, hash_type) report_file.create(self.analyzer_result_file, reports, self.checker_labels, self.analyzer_info)
def get_reports(self, analyzer_result_file_path: str, source_dir_path: Optional[str] = None) -> List[Report]: """ Get reports from the given analyzer result file. """ reports: List[Report] = [] if not source_dir_path: source_dir_path = os.path.dirname(analyzer_result_file_path) try: with open(analyzer_result_file_path, 'rb') as fp: plist = parse(fp) if not plist: return reports metadata = plist.get('metadata') files = get_file_index_map(plist, source_dir_path, self._file_cache) for diag in plist.get('diagnostics', []): report = self.__create_report(analyzer_result_file_path, diag, files, metadata) if report.report_hash is None: report.report_hash = get_report_hash( report, HashType.PATH_SENSITIVE) reports.append(report) except KeyError as ex: LOG.warning( "Failed to get file path id! Found files: %s. " "KeyError: %s", files, ex) except IndexError as iex: LOG.warning("Indexing error during processing plist file %s", analyzer_result_file_path) LOG.warning(type(iex)) LOG.warning(repr(iex)) _, _, exc_traceback = sys.exc_info() traceback.print_tb(exc_traceback, limit=1, file=sys.stdout) except Exception as ex: LOG.warning( "Error during processing reports from the plist " "file: %s", analyzer_result_file_path) traceback.print_exc() LOG.warning(type(ex)) LOG.warning(ex) finally: return reports
def replace_report_hash( self, plist_file_path: str, hash_type=HashType.CONTEXT_FREE ): """ Override hash in the given file by using the given version hash. """ try: with open(plist_file_path, 'rb+') as f: plist = plistlib.load(f) f.seek(0) f.truncate() metadata = plist.get('metadata') analyzer_result_dir_path = os.path.dirname(plist_file_path) file_cache: Dict[str, File] = {} files = get_file_index_map( plist, analyzer_result_dir_path, file_cache) for diag in plist['diagnostics']: report = self.__create_report( plist_file_path, diag, files, metadata) diag['issue_hash_content_of_line_in_context'] = \ get_report_hash(report, hash_type) plistlib.dump(plist, f) except (TypeError, AttributeError, plistlib.InvalidFileException) as err: LOG.warning('Failed to process plist file: %s wrong file format?', plist_file_path) LOG.warning(err) except IndexError as iex: LOG.warning('Indexing error during processing plist file %s', plist_file_path) LOG.warning(type(iex)) LOG.warning(repr(iex)) _, _, exc_traceback = sys.exc_info() traceback.print_tb(exc_traceback, limit=1, file=sys.stdout) except Exception as ex: LOG.warning('Error during processing reports from the plist ' 'file: %s', plist_file_path) traceback.print_exc() LOG.warning(type(ex)) LOG.warning(ex)
def test_gen_report_hash_context_free(self): """ Test context free hash generation for multi errors. """ test_plist = os.path.join(self.test_file_dir, 'cpp', 'multi_error.plist') expected_report_hash = { 'f48840093ef89e291fb68a95a5181612': 'c2a2856f566ed67ed1c3596ad06d42db', 'e4907182b363faf2ec905fc32cc5a4ab': '5a92e13f07c81c6d3197e7d910827e6e' } reports = get_reports(test_plist) for report in reports: report_hash = get_report_hash(report, HashType.CONTEXT_FREE) self.assertEqual(report_hash, expected_report_hash[report.report_hash])
def test_gen_report_hash_path_sensitive(self): """ Test path sensitive report hash generation for multiple errors. """ test_plist = os.path.join(self.test_file_dir, 'cpp', 'multi_error.plist') expected_report_hash = { 'f48840093ef89e291fb68a95a5181612': 'fdf11db1183dba2da4cd188e70d142e5', 'e4907182b363faf2ec905fc32cc5a4ab': '774799eb31f5fb8514988a7f6736b33e' } reports = get_reports(test_plist) for report in reports: report_hash = get_report_hash(report, HashType.PATH_SENSITIVE) self.assertEqual(report_hash, expected_report_hash[report.report_hash])
def test_gen_report_hash_diag_messages(self): """ Test diagnostic message hash generation for multi errors. """ test_plist = os.path.join(self.test_file_dir, 'cpp', 'multi_error.plist') expected_report_hash = { 'f48840093ef89e291fb68a95a5181612': 'c137804816bf2d5a67b6c067cd2ab5e8', 'e4907182b363faf2ec905fc32cc5a4ab': 'd08c2f8c5c4d8533e1de3fa88241f813' } reports = get_reports(test_plist) for report in reports: report_hash = get_report_hash(report, HashType.DIAGNOSTIC_MESSAGE) self.assertEqual(report_hash, expected_report_hash[report.report_hash])
def postprocess_result(self, skip_handler: Optional[SkipListHandler]): """ Generate analyzer result output file which can be parsed and stored into the database. """ if os.path.exists(self.analyzer_result_file): reports = report_file.get_reports(self.analyzer_result_file, self.checker_labels) reports = [r for r in reports if not r.skip(skip_handler)] hash_type = None if self.report_hash_type in ['context-free', 'context-free-v2']: hash_type = HashType.CONTEXT_FREE elif self.report_hash_type == 'diagnostic-message': hash_type = HashType.DIAGNOSTIC_MESSAGE if hash_type is not None: for report in reports: report.report_hash = get_report_hash(report, hash_type) report_file.create(self.analyzer_result_file, reports, self.checker_labels, self.analyzer_info)
def _add_report_hash(self, report: Report): """ Generate report hash for the given plist data. """ report.report_hash = get_report_hash(report, HashType.CONTEXT_FREE)