Exemple #1
0
    def _create_diag(message, fmap, files):
        """
        Creates a new plist diagnostic from a single clang-tidy message.
        """

        diag = {
            'location': PListConverter._create_location(message, fmap),
            'check_name': message.checker,
            'description': message.message,
            'category': PListConverter._get_checker_category(message.checker),
            'type': 'clang-tidy',
            'path': []
        }

        PListConverter._add_fixits(diag, message, fmap)
        PListConverter._add_notes(diag, message, fmap)

        # The original message should be the last part of the path. This is
        # displayed by quick check, and this is the main event displayed by
        # the web interface. FIXME: notes and fixits should not be events.
        diag['path'].append(
            PListConverter._create_event_from_note(message, fmap))

        source_file = files[diag['location']['file']]
        diag['issue_hash_content_of_line_in_context'] \
            = get_report_hash(diag, source_file, HashType.PATH_SENSITIVE)

        return diag
    def _add_report_hash(self, plist_obj):
        """ Generate report hash for the given plist data. """
        files = plist_obj['files']
        for diag in plist_obj['diagnostics']:
            report_hash = get_report_hash(diag,
                                          files[diag['location']['file']],
                                          HashType.CONTEXT_FREE)

            diag['issue_hash_content_of_line_in_context'] = report_hash
    def _add_report_hash(self, plist_data):
        """ Generate report hash for the given plist data

        It will generate a context free hash for each diagnostics.
        """
        files = plist_data['files']
        for diag in plist_data['diagnostics']:
            report_hash = diag.get('issue_hash_content_of_line_in_context')
            if not report_hash or report_hash == '0':
                report_hash = get_report_hash(diag,
                                              files[diag['location']['file']],
                                              HashType.CONTEXT_FREE)

                diag['issue_hash_content_of_line_in_context'] = report_hash
Exemple #4
0
    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')
        plist = plistlib.readPlist(test_plist)

        expected_report_hash = {
            'f48840093ef89e291fb68a95a5181612':
                'c2a2856f566ed67ed1c3596ad06d42db',
            'e4907182b363faf2ec905fc32cc5a4ab':
                '5a92e13f07c81c6d3197e7d910827e6e'}

        files = plist['files']
        for diag in plist['diagnostics']:
            file_path = files[diag['location']['file']]
            report_hash = get_report_hash(diag, file_path,
                                          HashType.CONTEXT_FREE)
            actual_report_hash = diag['issue_hash_content_of_line_in_context']
            self.assertEqual(report_hash,
                             expected_report_hash[actual_report_hash])
Exemple #5
0
    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')
        plist = plistlib.readPlist(test_plist)

        expected_report_hash = {
            'f48840093ef89e291fb68a95a5181612':
                'fdf11db1183dba2da4cd188e70d142e5',
            'e4907182b363faf2ec905fc32cc5a4ab':
                '774799eb31f5fb8514988a7f6736b33e'}

        files = plist['files']
        for diag in plist['diagnostics']:
            file_path = files[diag['location']['file']]
            report_hash = get_report_hash(diag, file_path,
                                          HashType.PATH_SENSITIVE)
            actual_report_hash = diag['issue_hash_content_of_line_in_context']
            self.assertEqual(report_hash,
                             expected_report_hash[actual_report_hash])
Exemple #6
0
def parse_plist_file(path, source_root=None, allow_plist_update=True):
    """
    Parse the reports from a plist file.
    One plist file can contain multiple reports.
    """
    LOG.debug("Parsing plist: %s", path)

    reports = []
    files = []
    try:
        plist = None
        with open(path, 'rb') as plist_file_obj:
            plist = parse_plist(plist_file_obj)

        if not plist:
            LOG.error("Failed to parse plist %s", path)
            return files, reports

        files = plist['files']

        diag_changed = False
        for diag in plist['diagnostics']:

            available_keys = list(diag.keys())

            main_section = {}
            for key in available_keys:
                # Skip path it is handled separately.
                if key != 'path':
                    main_section.update({key: diag[key]})

            # We need to extend information for plist files generated
            # by older clang version (before 3.7).
            main_section['check_name'] = get_checker_name(diag, path)

            # We need to extend information for plist files generated
            # by older clang version (before 3.8).
            file_path = files[diag['location']['file']]
            if source_root:
                file_path = os.path.join(source_root, file_path.lstrip('/'))

            report_hash = diag.get('issue_hash_content_of_line_in_context')

            if not report_hash:
                # Generate hash value if it is missing from the report.
                report_hash = get_report_hash(diag, file_path,
                                              HashType.PATH_SENSITIVE)

                main_section['issue_hash_content_of_line_in_context'] = \
                    report_hash

            if 'issue_hash_content_of_line_in_context' not in diag:
                # If the report hash was not in the plist, we set it in the
                # diagnostic section for later update.
                diag['issue_hash_content_of_line_in_context'] = report_hash
                diag_changed = True

            bug_path_items = [item for item in diag['path']]

            report = Report(main_section, bug_path_items, files)
            reports.append(report)

        if diag_changed and allow_plist_update:
            # If the diagnostic section has changed we update the plist file.
            # This way the client will always send a plist file where the
            # report hash field is filled.
            plistlib.dump(plist, path)
    except IndexError as iex:
        LOG.warning('Indexing error during processing plist file %s', 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',
                    path)
        traceback.print_exc()
        LOG.warning(type(ex))
        LOG.warning(ex)
    finally:
        return files, reports
def parse_plist_file(path: str,
                     allow_plist_update=True) \
                             -> Tuple[Dict[int, str], List[Report]]:
    """
    Parse the reports from a plist file.
    One plist file can contain multiple reports.
    """
    LOG.debug("Parsing plist: %s", path)

    reports = []
    source_files = {}

    try:
        plist = None
        with open(path, 'rb') as plist_file_obj:
            plist = parse_plist(plist_file_obj)

        if not plist:
            LOG.error("Failed to parse plist %s", path)
            return {}, []

        metadata = plist.get('metadata')

        mentioned_files = plist.get('files', [])

        # file index to filepath that bugpath events refer to
        source_files = \
            {i: filepath for i, filepath in enumerate(mentioned_files)}
        diag_changed = False
        for diag in plist.get('diagnostics', []):

            available_keys = list(diag.keys())

            main_section = {}
            for key in available_keys:
                # Skip path it is handled separately.
                if key != 'path':
                    main_section.update({key: diag[key]})

            # We need to extend information for plist files generated
            # by older clang version (before 3.7).
            main_section['check_name'] = get_checker_name(diag, path)

            report_hash = diag.get('issue_hash_content_of_line_in_context')

            if not report_hash:
                file_path = mentioned_files[diag['location']['file']]

                # Generate hash value if it is missing from the report.
                report_hash = get_report_hash(diag, file_path,
                                              HashType.PATH_SENSITIVE)

                main_section['issue_hash_content_of_line_in_context'] = \
                    report_hash

            if 'issue_hash_content_of_line_in_context' not in diag:
                # If the report hash was not in the plist, we set it in the
                # diagnostic section for later update.
                diag['issue_hash_content_of_line_in_context'] = report_hash
                diag_changed = True

            bug_path_items = [item for item in diag['path']]
            reports.append(
                Report(main_section, bug_path_items, source_files, metadata))

        if diag_changed and allow_plist_update:
            # If the diagnostic section has changed we update the plist file.
            # This way the client will always send a plist file where the
            # report hash field is filled.
            with open(path, 'wb') as plist_file:
                plistlib.dump(plist, plist_file)
    except IndexError as iex:
        LOG.warning('Indexing error during processing plist file %s', 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',
                    path)
        traceback.print_exc()
        LOG.warning(type(ex))
        LOG.warning(ex)
    finally:
        return source_files, reports