Example #1
0
    def __format_location(event, source_file):
        loc = event['location']
        line = util.get_line(source_file, loc['line'])
        if line == '':
            return line

        marker_line = line[0:(loc['col'] - 1)]
        marker_line = ' ' * (len(marker_line) + marker_line.count('\t'))
        return '%s%s^' % (line.replace('\t', '  '), marker_line)
Example #2
0
    def __format_location(event, source_file):
        loc = event['location']
        line = util.get_line(source_file, loc['line'])
        if line == '':
            return line

        marker_line = line[0:(loc['col'] - 1)]
        marker_line = ' ' * (len(marker_line) + marker_line.count('\t'))
        return '%s%s^' % (line.replace('\t', '  '), marker_line)
Example #3
0
    def source_line(self) -> str:
        """Get the source line for the main location.

        If the source line is already set returns that
        if not tries to read it from the disk.
        """
        if not self.__source_line:
            self.__source_line = util.get_line(self.file_path, self.line)

        return self.__source_line
Example #4
0
def generate_report_hash_no_bugpath(main_section, source_file):
    """
    !!! NOT Compatible with the old hash generation method

    High level overview of the hash content:
     * file_name from the main diag section
     * checker message
     * line content from the source file if can be read up
     * column numbers from the main diag sections location
     * all the whitespaces from the source content are removed

    """

    try:
        m_loc = main_section.get('location')
        source_line = m_loc.get('line')

        from_col = m_loc.get('col')
        until_col = m_loc.get('col')

        # WARNING!!! Changing the error handling type for encoding errors
        # can influence the hash content!
        line_content = get_line(source_file, source_line, errors='ignore')

        # Remove whitespaces so the hash will be independet of the
        # source code indentation.
        line_content, new_col = \
            remove_whitespace(line_content, from_col)
        # Update the column number in sync with the
        # removed whitespaces.
        until_col = until_col - (from_col - new_col)
        from_col = new_col

        if line_content == '' and not os.path.isfile(source_file):
            LOG.error("Failed to include soruce line in the report hash.")
            LOG.error('%s does not exists!', source_file)

        file_name = os.path.basename(source_file)
        msg = main_section.get('description')

        hash_content = [
            file_name, msg, line_content,
            str(from_col),
            str(until_col)
        ]

        string_to_hash = '|||'.join(hash_content)
        return hashlib.md5(string_to_hash.encode()).hexdigest()

    except Exception as ex:
        LOG.error("Hash generation failed")
        LOG.error(ex)
        return ''
Example #5
0
def generate_report_hash_no_bugpath(main_section, source_file):
    """
    !!! NOT Compatible with the old hash generation method

    High level overview of the hash content:
     * file_name from the main diag section
     * checker message
     * line content from the source file if can be read up
     * column numbers from the main diag sections location
     * whitespaces from the beginning of the source content are removed

    """

    try:
        m_loc = main_section.get('location')
        source_line = m_loc.get('line')

        from_col = m_loc.get('col')
        until_col = m_loc.get('col')

        # WARNING!!! Changing the error handling type for encoding errors
        # can influence the hash content!
        line_content = get_line(source_file, source_line, errors='ignore')

        # Remove whitespaces so the hash will be independet of the
        # source code indentation.
        line_content, new_col = \
            remove_whitespace(line_content, from_col)
        # Update the column number in sync with the
        # removed whitespaces.
        until_col = until_col - (from_col-new_col)
        from_col = new_col

        if line_content == '' and not os.path.isfile(source_file):
            LOG.error("Failed to include soruce line in the report hash.")
            LOG.error('%s does not exists!', source_file)

        file_name = os.path.basename(source_file)
        msg = main_section.get('description')

        hash_content = [file_name,
                        msg,
                        line_content,
                        str(from_col),
                        str(until_col)]

        string_to_hash = '|||'.join(hash_content)
        return hashlib.md5(string_to_hash.encode()).hexdigest()

    except Exception as ex:
        LOG.error("Hash generation failed")
        LOG.error(ex)
        return ''
    def test_util_getline(self):
        """
        Lines in files with carriage return character
        should be handled as separate lines.
        """
        test_file_path = os.path.dirname(os.path.realpath(__file__))
        file_to_process = os.path.join(test_file_path, 'newline')

        line1 = get_line(file_to_process, 1)
        self.assertEqual(line1, 'line1\n')

        line2 = get_line(file_to_process, 2)
        self.assertEqual(line2, 'line2\n')

        line4 = get_line(file_to_process, 4)
        self.assertEqual(line4, 'line4\n')

        line5 = get_line(file_to_process, 5)
        self.assertEqual(line5, 'line5\n')

        line6 = get_line(file_to_process, 6)
        self.assertEqual(line6, 'line6\n')
    def test_util_getline(self):
        """
        Lines in files with carriage return character
        should be handled as separate lines.
        """
        test_file_path = os.path.dirname(os.path.realpath(__file__))
        file_to_process = os.path.join(test_file_path, 'newline')

        line1 = get_line(file_to_process, 1)
        self.assertEqual(line1, 'line1\n')

        line2 = get_line(file_to_process, 2)
        self.assertEqual(line2, 'line2\n')

        line4 = get_line(file_to_process, 4)
        self.assertEqual(line4, 'line4\n')

        line5 = get_line(file_to_process, 5)
        self.assertEqual(line5, 'line5\n')

        line6 = get_line(file_to_process, 6)
        self.assertEqual(line6, 'line6\n')
    def get_source_line_comments(self, source_file, bug_line):
        """
        This function returns the available preprocessed source code comments
        for a bug line.
        """
        LOG.debug(
            "Checking for source code comments in the source file '%s'"
            " at line %s", source_file, bug_line)

        previous_line_num = bug_line - 1

        # No more line.
        if previous_line_num < 1:
            return []

        source_line_comments = []
        curr_suppress_comment = []

        # Iterate over lines while it has comments or we reached
        # the top of the file.
        cstyle_end_found = False

        while True:

            source_line = util.get_line(source_file, previous_line_num)

            # cpp style comment
            is_comment = \
                SourceCodeCommentHandler.__check_if_comment(source_line)

            # cstyle commment
            cstyle_start, cstyle_end = \
                SourceCodeCommentHandler.__check_if_cstyle_comment(source_line)

            if not is_comment and not cstyle_start and not cstyle_end:
                if not cstyle_end_found:
                    # Not a comment
                    break

            if not cstyle_end_found and cstyle_end:
                cstyle_end_found = True

            curr_suppress_comment.append(source_line)
            has_any_marker = any(
                marker in source_line
                for marker in self.source_code_comment_markers)

            # It is a comment.
            if has_any_marker:
                rev = list(reversed(curr_suppress_comment))

                orig_review_comment = ' '.join(rev)

                if rev[0].strip().startswith('//'):
                    review_comment = orig_review_comment.replace('//', '')
                else:
                    r_comment = []
                    for comment in rev:
                        comment = comment.strip()
                        comment = comment.replace('/*', '').replace('*/', '')
                        if comment.startswith('*'):
                            r_comment.append(comment[1:])
                        else:
                            r_comment.append(comment)

                    review_comment = ' '.join(r_comment).strip()

                comment = \
                    self.__process_source_line_comment(review_comment)

                if comment:
                    comment['line'] = orig_review_comment
                    source_line_comments.append(comment)
                else:
                    _, file_name = os.path.split(source_file)
                    LOG.warning(
                        "Misspelled review status comment in %s@%d: %s",
                        file_name, previous_line_num,
                        orig_review_comment.strip())

                curr_suppress_comment = []

            if previous_line_num > 0:
                previous_line_num -= 1
            else:
                break

            if cstyle_start:
                break

        return source_line_comments
Example #9
0
def generate_report_hash(path, source_file, check_name):
    """
    !!! Compatible with the old hash before v6.0

    Keep this until needed for transformation tools from the old
    hash to the new hash.

    Hash generation algoritm for older plist versions where no
    issue hash was generated or for the plists generated
    from clang-tidy where the issue hash generation feature
    is still missing.

    As the main diagnositc section the last element from the
    bug path is used.

    High level overview of the hash content:
     * file_name from the main diag section.
     * checker name
     * checker message
     * line content from the source file if can be read up
     * column numbers from the main diag section
     * range column numbers only from the control diag sections if
       column number in the range is not the same as the previous
       control diag section number in the bug path. If there are no control
       sections event section column numbers are used.

    """
    def compare_ctrl_sections(curr, prev):
        """
        Compare two sections and return column numbers which
        should be included in the path hash or None if the
        two compared sections ranges are identical.
        """
        curr_edges = curr['edges']
        curr_start_range_begin = curr_edges[0]['start'][0]
        curr_start_range_end = curr_edges[0]['start'][1]

        prev_edges = prev['edges']
        prev_end_range_begin = prev_edges[0]['end'][0]
        prev_end_range_end = prev_edges[0]['end'][1]

        if curr_start_range_begin != prev_end_range_begin and \
                curr_start_range_end != prev_end_range_end:
            return (curr_start_range_begin['col'], curr_start_range_end['col'])

        return None

    # The last diag section from the bug path used as a main
    # diagnostic section.
    try:
        ctrl_sections = [x for x in path if x.get('kind') == 'control']

        main_section = path[-1]

        m_loc = main_section.get('location')
        source_line = m_loc.get('line')

        from_col = m_loc.get('col')
        until_col = m_loc.get('col')

        # WARNING!!! Changing the error handling type for encoding errors
        # can influence the hash content!
        line_content = get_line(source_file, source_line, errors='ignore')

        if line_content == '' and not os.path.isfile(source_file):
            LOG.error("Failed to generate report hash.")
            LOG.error('%s does not exists!', source_file)

        file_name = os.path.basename(source_file)
        msg = main_section.get('message')

        hash_content = [
            file_name, check_name, msg, line_content,
            str(from_col),
            str(until_col)
        ]

        hash_from_ctrl_section = True
        for i, section in enumerate(ctrl_sections):
            edges = section['edges']

            try:
                start_range_begin = edges[0]['start'][0]
                start_range_end = edges[0]['start'][1]

                end_range_begin = edges[0]['end'][0]
                end_range_end = edges[0]['end'][1]

                if i > 0:
                    prev = ctrl_sections[i - 1]
                    col_to_append = compare_ctrl_sections(section, prev)
                    if col_to_append:
                        begin_col, end_col = col_to_append
                        hash_content.append(str(begin_col))
                        hash_content.append(str(end_col))
                else:
                    hash_content.append(str(start_range_begin['col']))
                    hash_content.append(str(start_range_end['col']))

                hash_content.append(str(end_range_begin['col']))
                hash_content.append(str(end_range_end['col']))
            except IndexError:
                # Edges might be empty.
                hash_from_ctrl_section = False

        # Hash generation from the control sections failed for some reason
        # use event section positions for hash generation.
        if not hash_from_ctrl_section:
            event_sections = [x for x in path if x.get('kind') == 'event']

            for i, section in enumerate(event_sections):
                loc = section['location']
                col_num = loc['col']
                hash_content.append(str(col_num))

        return str_to_hash('|||'.join(hash_content))

    except Exception as ex:
        LOG.error("Hash generation failed")
        LOG.error(ex)
        return ''
Example #10
0
def generate_report_hash(path, source_file, check_name):
    """
    !!! Compatible with the old hash before v6.0

    Keep this until needed for transformation tools from the old
    hash to the new hash.

    Hash generation algoritm for older plist versions where no
    issue hash was generated or for the plists generated
    from clang-tidy where the issue hash generation feature
    is still missing.

    As the main diagnositc section the last element from the
    bug path is used.

    High level overview of the hash content:
     * file_name from the main diag section.
     * checker name
     * checker message
     * line content from the source file if can be read up
     * column numbers from the main diag section
     * range column numbers only from the control diag sections if
       column number in the range is not the same as the previous
       control diag section number in the bug path. If there are no control
       sections event section column numbers are used.

    """

    def compare_ctrl_sections(curr, prev):
        """
        Compare two sections and return column numbers which
        should be included in the path hash or None if the
        two compared sections ranges are identical.
        """
        curr_edges = curr['edges']
        curr_start_range_begin = curr_edges[0]['start'][0]
        curr_start_range_end = curr_edges[0]['start'][1]

        prev_edges = prev['edges']
        prev_end_range_begin = prev_edges[0]['end'][0]
        prev_end_range_end = prev_edges[0]['end'][1]

        if curr_start_range_begin != prev_end_range_begin and \
                curr_start_range_end != prev_end_range_end:
            return (curr_start_range_begin['col'],
                    curr_start_range_end['col'])

        return None

    # The last diag section from the bug path used as a main
    # diagnostic section.
    try:
        ctrl_sections = [x for x in path if x.get('kind') == 'control']

        main_section = path[-1]

        m_loc = main_section.get('location')
        source_line = m_loc.get('line')

        from_col = m_loc.get('col')
        until_col = m_loc.get('col')

        # WARNING!!! Changing the error handling type for encoding errors
        # can influence the hash content!
        line_content = get_line(source_file, source_line, errors='ignore')

        if line_content == '' and not os.path.isfile(source_file):
            LOG.error("Failed to generate report hash.")
            LOG.error('%s does not exists!', source_file)

        file_name = os.path.basename(source_file)
        msg = main_section.get('message')

        hash_content = [file_name,
                        check_name,
                        msg,
                        line_content,
                        str(from_col),
                        str(until_col)]

        hash_from_ctrl_section = True
        for i, section in enumerate(ctrl_sections):
            edges = section['edges']

            try:
                start_range_begin = edges[0]['start'][0]
                start_range_end = edges[0]['start'][1]

                end_range_begin = edges[0]['end'][0]
                end_range_end = edges[0]['end'][1]

                if i > 0:
                    prev = ctrl_sections[i-1]
                    col_to_append = compare_ctrl_sections(section, prev)
                    if col_to_append:
                        begin_col, end_col = col_to_append
                        hash_content.append(str(begin_col))
                        hash_content.append(str(end_col))
                else:
                    hash_content.append(str(start_range_begin['col']))
                    hash_content.append(str(start_range_end['col']))

                hash_content.append(str(end_range_begin['col']))
                hash_content.append(str(end_range_end['col']))
            except IndexError:
                # Edges might be empty.
                hash_from_ctrl_section = False

        # Hash generation from the control sections failed for some reason
        # use event section positions for hash generation.
        if not hash_from_ctrl_section:
            event_sections = [x for x in path if x.get('kind') == 'event']

            for i, section in enumerate(event_sections):
                loc = section['location']
                col_num = loc['col']
                hash_content.append(str(col_num))

        string_to_hash = '|||'.join(hash_content)
        return hashlib.md5(string_to_hash.encode()).hexdigest()

    except Exception as ex:
        LOG.error("Hash generation failed")
        LOG.error(ex)
        return ''