def test_multiple_checker_name_comments(self):
        """
        Check multiple comment where same checker name are given for multiple
        source code comment.
        """

        bug_line = 43
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_3)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(
            bug_line)
        self.assertEqual(len(source_line_comments), 2)

        expected = [{
                        'checkers': {'my.checker_1'},
                        'message': 'intentional comment',
                        'status': 'intentional'
                    },
                    {
                        'checkers': {'my.checker_2', 'my.checker_1'},
                        'message': 'some comment',
                        'status': 'false_positive'
                    }]

        self.assertDictEqual(expected[0], source_line_comments[0])
        self.assertDictEqual(expected[1], source_line_comments[1])

        current_line_comments = \
            sc_handler.filter_source_line_comments(bug_line,
                                                   'my.checker_1')
        self.assertEqual(len(current_line_comments), 2)
    def test_cstyle_comment_multi_nomsg(self):
        """
        Multi line C style comment.
        /* codechecker_suppress [ my_checker_1 ]
        */
        """

        bug_line = 89
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(
            bug_line)

        for l in source_line_comments:
            print(l)

        self.assertEqual(len(source_line_comments), 1)

        expected = [{
                        'checkers': {'my_checker_1'},
                        'message': 'WARNING! source code comment is missing',
                        'status': 'false_positive'
                    }]

        self.assertDictEqual(expected[0], source_line_comments[0])
    def test_cstyle_comment(self):
        """
        C style comment in one line.
        /* codechecker_suppress [ my_checker_1 ] suppress comment */
        """

        bug_line = 76
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(
            bug_line)

        for l in source_line_comments:
            print(l)

        self.assertEqual(len(source_line_comments), 1)

        expected = [{
                        'checkers': {'my_checker_1'},
                        'message': 'suppress comment',
                        'status': 'false_positive'
                    }]

        self.assertDictEqual(expected[0], source_line_comments[0])
    def test_cstyle_comment_multi_line_mismatch(self):
        """
        Multi line C style comment start '/*' is in a different line
        from the codechecker review status comment.

        /*
          codechecker_suppress [ my_checker_1 ]
          multi line
          comment
          again
         */
        """

        bug_line = 108
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(
            bug_line)

        for l in source_line_comments:
            print('-======')
            print(l)

        self.assertEqual(len(source_line_comments), 1)

        expected = [{
                        'checkers': {'my_checker_1'},
                        'message': 'multi line comment again',
                        'status': 'false_positive'
                    }]

        self.assertDictEqual(expected[0], source_line_comments[0])
    def get_suppressed_reports(reports):
        """
        Returns suppressed reports.
        """
        suppressed_in_code = []
        for rep in reports:
            bughash = rep.report_hash
            source_file = rep.main['location']['file_name']
            bug_line = rep.main['location']['line']
            checker_name = rep.main['check_name']

            sc_handler = SourceCodeCommentHandler(source_file)
            src_comment_data = sc_handler.filter_source_line_comments(
                bug_line,
                checker_name)

            if len(src_comment_data) == 1:
                suppressed_in_code.append(bughash)
                LOG.debug("Bug %s is suppressed in code. file: %s Line %s",
                          bughash, source_file, bug_line)
            elif len(src_comment_data) > 1:
                LOG.warning(
                    "Multiple source code comment can be found "
                    "for '%s' checker in '%s' at line %s. "
                    "This bug will not be suppressed!",
                    checker_name, source_file, bug_line)
        return suppressed_in_code
    def test_malformed_commment_format(self):
        """Check malformed comment."""
        bug_line = 1
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_2)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertFalse(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 0)
    def test_multi_liner_some_checkers(self):
        """There is source code comment above the bug line."""
        bug_line = 50
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertFalse(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 0)
    def test_src_comment_first_line(self):
        """Bug is reported for the first line."""
        bug_line = 3
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertFalse(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 0)
    def test_no_comment(self):
        """There is no comment above the bug line."""
        bug_line = 9
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertFalse(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 0)
Beispiel #10
0
    def collect_file_hashes_from_plist(plist_file):
        """
        Collects file content hashes and last modification times for the
        source files which can be found in the given plist file.

        :returns List of file paths which are in the processed plist file but
        missing from the user's disk and the source file modification times
        for the still available source files.

        """
        source_file_mod_times = {}
        missing_files = []
        sc_handler = SourceCodeCommentHandler()

        try:
            files, reports = plist_parser.parse_plist_file(plist_file)

            # CppCheck generates a '0' value for the bug hash.
            # In case all of the reports in a plist file contain only
            # a hash with '0' value oeverwrite the hash values in the
            # plist report files with a context free hash value.
            rep_hash = [rep.report_hash == '0' for rep in reports]
            if all(rep_hash):
                common_report.use_context_free_hashes(plist_file)

            for f in files:
                if not os.path.isfile(f):
                    missing_files.append(f)
                    missing_source_files.add(f)
                    continue

                content_hash = get_file_content_hash(f)
                hash_to_file[content_hash] = f
                file_to_hash[f] = content_hash
                source_file_mod_times[f] = util.get_last_mod_time(f)

            # Get file hashes which contain source code comments.
            for report in reports:
                last_report_event = report.bug_path[-1]
                file_path = files[last_report_event['location']['file']]
                if not os.path.isfile(file_path):
                    continue

                file_hash = file_to_hash[file_path]
                if file_hash in file_hash_with_review_status:
                    continue

                report_line = last_report_event['location']['line']
                if sc_handler.has_source_line_comments(file_path, report_line):
                    file_hash_with_review_status.add(file_hash)

            return missing_files, source_file_mod_times
        except Exception as ex:
            LOG.error('Parsing the plist failed: %s', str(ex))
Beispiel #11
0
    def test_multi_liner_some_checkers(self):
        """There is source code comment above the bug line."""
        bug_line = 50
        sc_handler = SourceCodeCommentHandler()
        res = sc_handler.has_source_line_comments(self.__tmp_srcfile_1,
                                                  bug_line)
        self.assertFalse(res)

        source_line_comments = \
            sc_handler.get_source_line_comments(self.__tmp_srcfile_1, bug_line)
        self.assertEqual(len(source_line_comments), 0)
Beispiel #12
0
    def test_no_comment(self):
        """There is no comment above the bug line."""
        bug_line = 9
        sc_handler = SourceCodeCommentHandler()
        res = sc_handler.has_source_line_comments(self.__tmp_srcfile_1,
                                                  bug_line)
        self.assertFalse(res)

        source_line_comments = \
            sc_handler.get_source_line_comments(self.__tmp_srcfile_1, bug_line)
        self.assertEqual(len(source_line_comments), 0)
Beispiel #13
0
    def test_src_comment_first_line(self):
        """Bug is reported for the first line."""
        bug_line = 3
        sc_handler = SourceCodeCommentHandler()
        res = sc_handler.has_source_line_comments(self.__tmp_srcfile_1,
                                                  bug_line)
        self.assertFalse(res)

        source_line_comments = \
            sc_handler.get_source_line_comments(self.__tmp_srcfile_1, bug_line)
        self.assertEqual(len(source_line_comments), 0)
Beispiel #14
0
def skip_report(report_hash,
                source_file,
                report_line,
                checker_name,
                src_comment_handler=None,
                src_comment_status_filter=None):
    """
    Returns a tuple where the first value will be True if the report was
    suppressed in the source code, otherwise False. The second value will be
    the list of available source code comments.
    """
    bug = {'hash_value': report_hash, 'file_path': source_file}
    if src_comment_handler and src_comment_handler.get_suppressed(bug):
        LOG.debug("Suppressed by suppress file: %s:%s [%s] %s", source_file,
                  report_line, checker_name, report_hash)
        return True, []

    sc_handler = SourceCodeCommentHandler()

    src_comment_data = []
    # Check for source code comment.
    with open(source_file, encoding='utf-8', errors='ignore') as sf:
        try:
            src_comment_data = sc_handler.filter_source_line_comments(
                sf, report_line, checker_name)
        except SpellException as ex:
            LOG.warning("%s contains %s", os.path.basename(source_file),
                        str(ex))

    if not src_comment_data:
        skip = True if src_comment_status_filter and \
            'unreviewed' not in src_comment_status_filter else False
        return skip, src_comment_data
    elif len(src_comment_data) == 1:
        status = src_comment_data[0]['status']

        LOG.debug("Suppressed by source code comment.")
        if src_comment_handler:
            file_name = os.path.basename(source_file)
            message = src_comment_data[0]['message']
            src_comment_handler.store_suppress_bug_id(report_hash, file_name,
                                                      message, status)

        if src_comment_status_filter and \
                status not in src_comment_status_filter:
            return True, src_comment_data

    elif len(src_comment_data) > 1:
        LOG.warning(
            "Multiple source code comment can be found "
            "for '%s' checker in '%s' at line %d. "
            "This bug will not be suppressed!", checker_name, source_file,
            report_line)
    return False, src_comment_data
Beispiel #15
0
    def test_malformed_commment_format(self):
        """Check malformed comment."""
        bug_line = 1
        sc_handler = SourceCodeCommentHandler()
        res = sc_handler.has_source_line_comments(self.__tmp_srcfile_2,
                                                  bug_line)
        self.assertFalse(res)

        source_line_comments = \
            sc_handler.get_source_line_comments(self.__tmp_srcfile_2, bug_line)
        self.assertEqual(len(source_line_comments), 0)
    def test_no_src_comment_comment(self):
        """There is no source comment above the bug line."""
        bug_line = 16
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {'checkers': {'all'},
                    'message': 'some comment',
                    'status': 'false_positive'}
        self.assertDictEqual(expected, source_line_comments[0])
    def test_comment_characters(self):
        """Check for different special comment characters."""
        bug_line = 57
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {'checkers': {'my.checker_1', 'my.checker_2'},
                    'message': "i/';0 (*&^%$#@!)",
                    'status': 'false_positive'}
        self.assertDictEqual(expected, source_line_comments[0])
    def test_fancy_comment_characters(self):
        """Check fancy comment."""
        bug_line = 64
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {'checkers': {'my_checker_1'},
                    'message': u"áúőóüöáé ▬▬▬▬▬▬▬▬▬▬ஜ۩۞۩ஜ▬▬▬▬▬▬▬▬▬▬",
                    'status': 'false_positive'}
        self.assertDictEqual(expected, source_line_comments[0])
    def test_no_fancy_comment(self):
        """Check no fancy comment."""
        bug_line = 70
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {'checkers': {'my_checker_1'},
                    'message': 'WARNING! source code comment is missing',
                    'status': 'false_positive'}
        self.assertDictEqual(expected, source_line_comments[0])
    def test_confirmed_comment(self):
        """Check Confirmed comment."""
        bug_line = 17
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_3)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {'checkers': {'all'},
                    'message': 'some comment',
                    'status': 'confirmed'}
        self.assertDictEqual(expected, source_line_comments[0])
    def test_multi_liner_all_2(self):
        """There is source code comment above the bug line."""
        bug_line = 36
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {'checkers': {'my.checker_1', 'my.checker_2'},
                    'message': 'some really long comment',
                    'status': 'false_positive'}
        self.assertDictEqual(expected, source_line_comments[0])
    def test_fancy_comment_characters(self):
        """Check fancy comment."""
        bug_line = 64
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {
            'checkers': {'my_checker_1'},
            'message': u"áúőóüöáé ▬▬▬▬▬▬▬▬▬▬ஜ۩۞۩ஜ▬▬▬▬▬▬▬▬▬▬",
            'status': 'false_positive'
        }
        self.assertDictEqual(expected, source_line_comments[0])
Beispiel #23
0
def parse_codechecker_review_comment(source_file_name: str, report_line: int,
                                     checker_name: str) -> SourceLineComments:
    """Parse the CodeChecker review comments from a source file at a given
    position.  Returns an empty list if there are no comments.
    """
    src_comment_data = []
    with open(source_file_name, encoding='utf-8', errors='ignore') as f:
        if contains_codechecker_comment(f):
            sc_handler = SourceCodeCommentHandler()
            try:
                src_comment_data = sc_handler.filter_source_line_comments(
                    f, report_line, checker_name)
            except SpellException as ex:
                LOG.warning("File %s contains %s", source_file_name, ex)

    return src_comment_data
    def test_confirmed_comment(self):
        """Check Confirmed comment."""
        bug_line = 17
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_3)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {
            'checkers': {'all'},
            'message': 'some comment',
            'status': 'confirmed'
        }
        self.assertDictEqual(expected, source_line_comments[0])
    def test_no_fancy_comment(self):
        """Check no fancy comment."""
        bug_line = 70
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {
            'checkers': {'my_checker_1'},
            'message': 'WARNING! source code comment is missing',
            'status': 'false_positive'
        }
        self.assertDictEqual(expected, source_line_comments[0])
    def test_comment_characters(self):
        """Check for different special comment characters."""
        bug_line = 57
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {
            'checkers': {'my.checker_1', 'my.checker_2'},
            'message': "i/';0 (*&^%$#@!)",
            'status': 'false_positive'
        }
        self.assertDictEqual(expected, source_line_comments[0])
    def test_one_liner_all(self):
        """There is source code comment above the bug line."""
        bug_line = 29
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_1)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {
            'checkers': {'my_checker_1', 'my_checker_2'},
            'message': 'some comment',
            'status': 'false_positive'
        }
        self.assertDictEqual(expected, source_line_comments[0])
    def test_no_src_comment_comment(self):
        """There is no source comment above the bug line."""
        bug_line = 16
        sc_handler = SourceCodeCommentHandler()
        res = sc_handler.has_source_line_comments(self.__tmp_srcfile_1,
                                                  bug_line)
        self.assertTrue(res)

        source_line_comments = \
            sc_handler.get_source_line_comments(self.__tmp_srcfile_1, bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {'checkers': {'all'},
                    'message': 'some comment',
                    'status': 'false_positive',
                    'line': '// codechecker_suppress [all] some comment\n'}
        self.assertDictEqual(expected, source_line_comments[0])
Beispiel #29
0
    def collect_file_hashes_from_plist(plist_file):
        """
        Collects file content hashes and last modification times for the
        source files which can be found in the given plist file.

        :returns List of file paths which are in the processed plist file but
        missing from the user's disk and the source file modification times
        for the still available source files.

        """
        source_file_mod_times = {}
        missing_files = []
        try:
            files, reports = plist_parser.parse_plist(plist_file)

            for f in files:
                if not os.path.isfile(f):
                    missing_files.append(f)
                    missing_source_files.add(f)
                    continue

                content_hash = get_file_content_hash(f)
                hash_to_file[content_hash] = f
                file_to_hash[f] = content_hash
                source_file_mod_times[f] = util.get_last_mod_time(f)

            # Get file hashes which contain source code comments.
            for report in reports:
                last_report_event = report.bug_path[-1]
                file_path = files[last_report_event['location']['file']]
                if not os.path.isfile(file_path):
                    continue

                file_hash = file_to_hash[file_path]
                if file_hash in file_hash_with_review_status:
                    continue

                report_line = last_report_event['location']['line']
                sc_handler = SourceCodeCommentHandler(file_path)
                if sc_handler.has_source_line_comments(report_line):
                    file_hash_with_review_status.add(file_hash)

            return missing_files, source_file_mod_times
        except Exception as ex:
            LOG.error('Parsing the plist failed: %s', str(ex))
Beispiel #30
0
def scan_for_review_comment(job):
    """Scan a file for review comments returns
    all the found review comments.
    """
    file_path, lines = job
    sc_handler = SourceCodeCommentHandler()
    comments = []
    with open(file_path, mode='r', encoding='utf-8', errors='ignore') as sf:
        comments, misspelled_comments = \
                sc_handler.scan_source_line_comments(sf, lines)

        if misspelled_comments:
            LOG.warning("There are misspelled review status comments in %s",
                        file_path)
        for mc in misspelled_comments:
            LOG.warning(mc)

    return comments
    def test_false_positive_comment(self):
        """Check False positive comment."""
        bug_line = 7
        sc_handler = SourceCodeCommentHandler()
        res = sc_handler.has_source_line_comments(self.__tmp_srcfile_3,
                                                  bug_line)
        self.assertTrue(res)

        source_line_comments = \
            sc_handler.get_source_line_comments(self.__tmp_srcfile_3, bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {'checkers': {'all'},
                    'message': 'some comment',
                    'status': 'false_positive',
                    'line': '// codechecker_false_positive [ all ] '
                            'some comment\n'}
        self.assertDictEqual(expected, source_line_comments[0])
    def test_multi_liner_all_2(self):
        """There is source code comment above the bug line."""
        bug_line = 36
        sc_handler = SourceCodeCommentHandler()
        res = sc_handler.has_source_line_comments(self.__tmp_srcfile_1,
                                                  bug_line)
        self.assertTrue(res)

        source_line_comments = \
            sc_handler.get_source_line_comments(self.__tmp_srcfile_1, bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {'checkers': {'my.checker_1', 'my.checker_2'},
                    'message': 'some really long comment',
                    'status': 'false_positive',
                    'line': '// codechecker_suppress [my.checker_1 '
                            'my.checker_2] some really\n // long comment\n'}
        self.assertDictEqual(expected, source_line_comments[0])
Beispiel #33
0
    def test_intentional_comment(self):
        """Check Intentional comment."""
        bug_line = 12
        sc_handler = SourceCodeCommentHandler()
        res = sc_handler.has_source_line_comments(self.__tmp_srcfile_3,
                                                  bug_line)
        self.assertTrue(res)

        source_line_comments = \
            sc_handler.get_source_line_comments(self.__tmp_srcfile_3, bug_line)
        self.assertEqual(len(source_line_comments), 1)

        expected = {
            'checkers': {'all'},
            'message': 'some comment',
            'status': 'intentional'
        }
        self.assertDictEqual(expected, source_line_comments[0])
Beispiel #34
0
    def test_multiple_checker_name_comments(self):
        """
        Check multiple comment where same checker name are given for multiple
        source code comment.
        """

        bug_line = 43
        sc_handler = SourceCodeCommentHandler()
        res = sc_handler.has_source_line_comments(self.__tmp_srcfile_3,
                                                  bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(
            self.__tmp_srcfile_3, bug_line)
        self.assertEqual(len(source_line_comments), 2)

        expected = [{
            'checkers': {'my.checker_1'},
            'message':
            'intentional comment',
            'status':
            'intentional',
            'line':
            '// codechecker_intentional [ my.checker_1 ] '
            'intentional comment\n'
        }, {
            'checkers': {'my.checker_2', 'my.checker_1'},
            'message':
            'some comment',
            'status':
            'false_positive',
            'line':
            '// codechecker_false_positive [ '
            'my.checker_2, my.checker_1 ] some comment\n'
        }]

        self.assertDictEqual(expected[0], source_line_comments[0])
        self.assertDictEqual(expected[1], source_line_comments[1])

        current_line_comments = \
            sc_handler.filter_source_line_comments(self.__tmp_srcfile_3,
                                                   bug_line,
                                                   'my.checker_1')
        self.assertEqual(len(current_line_comments), 2)
    def test_cstyle_multi_comment_multi_line(self):
        """
        Multi line C style comment with multiple review status comment.

        /* codechecker_false_positive [ my.checker_2, my.checker_1 ] comment
        codechecker_intentional [ my.checker_1 ] intentional comment */

        """

        bug_line = 49
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_3)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)

        for l in source_line_comments:
            print(l)

        self.assertEqual(len(source_line_comments), 2)

        expected = [{
            'checkers': {'my.checker_1'},
            'message': 'intentional comment',
            'status': 'intentional'
        }, {
            'checkers': {'my.checker_1', 'my.checker_2'},
            'message': 'some comment',
            'status': 'false_positive'
        }]

        self.assertDictEqual(expected[0], source_line_comments[0])
        self.assertDictEqual(expected[1], source_line_comments[1])

        current_line_comments = \
            sc_handler.filter_source_line_comments(bug_line, 'my.checker_1')
        self.assertEqual(len(current_line_comments), 2)
        self.assertEqual(current_line_comments[0]['message'],
                         expected[0]['message'])
        self.assertEqual(current_line_comments[0]['status'],
                         expected[0]['status'])
        self.assertEqual(current_line_comments[1]['message'],
                         expected[1]['message'])
        self.assertEqual(current_line_comments[1]['status'],
                         expected[1]['status'])

        current_line_comments = \
            sc_handler.filter_source_line_comments(bug_line, 'my.checker_2')
        self.assertEqual(len(current_line_comments), 1)

        self.assertEqual(current_line_comments[0]['message'],
                         expected[1]['message'])
        self.assertEqual(current_line_comments[0]['status'],
                         expected[1]['status'])

        current_line_comments = \
            sc_handler.filter_source_line_comments(bug_line, 'my.dummy')
        self.assertEqual(len(current_line_comments), 0)
Beispiel #36
0
    def test_multiple_all_comments(self):
        """Check multiple comment."""
        bug_line = 37
        sc_handler = SourceCodeCommentHandler()
        res = sc_handler.has_source_line_comments(self.__tmp_srcfile_3,
                                                  bug_line)
        self.assertTrue(res)

        source_line_comments = \
            sc_handler.get_source_line_comments(self.__tmp_srcfile_3, bug_line)
        self.assertEqual(len(source_line_comments), 2)

        expected = [{
            'checkers': {'my.checker_1'},
            'message': 'intentional comment',
            'status': 'intentional'
        }, {
            'checkers': {'all'},
            'message': 'some comment',
            'status': 'false_positive'
        }]

        self.assertDictEqual(expected[0], source_line_comments[0])
        self.assertDictEqual(expected[1], source_line_comments[1])

        current_line_comments = \
            sc_handler.filter_source_line_comments(self.__tmp_srcfile_3,
                                                   bug_line,
                                                   'my.checker_1')
        self.assertEqual(len(current_line_comments), 1)

        self.assertEqual(current_line_comments[0]['message'],
                         expected[0]['message'])
        self.assertEqual(current_line_comments[0]['status'],
                         expected[0]['status'])

        current_line_comments = \
            sc_handler.filter_source_line_comments(self.__tmp_srcfile_3,
                                                   bug_line,
                                                   '')
        self.assertEqual(len(current_line_comments), 1)
        self.assertEqual(current_line_comments[0]['message'],
                         expected[1]['message'])
        self.assertEqual(current_line_comments[0]['status'],
                         expected[1]['status'])

        current_line_comments = \
            sc_handler.filter_source_line_comments(self.__tmp_srcfile_3,
                                                   bug_line,
                                                   'my.dummy')
        self.assertEqual(len(current_line_comments), 1)

        self.assertEqual(len(current_line_comments), 1)
        self.assertEqual(current_line_comments[0]['message'],
                         expected[1]['message'])
        self.assertEqual(current_line_comments[0]['status'],
                         expected[1]['status'])
Beispiel #37
0
    def collect_file_hashes_from_plist(plist_file):
        """
        Collects file content hashes and last modification times of files which
        can be found in the given plist file.

        :returns List of file paths which are in the processed plist file but
        missing from the user's disk.
        """
        missing_files = []
        try:
            files, reports = plist_parser.parse_plist(plist_file)

            for f in files:
                if not os.path.isfile(f):
                    missing_files.append(f)
                    missing_source_files.add(f)
                    continue

                content_hash = util.get_file_content_hash(f)
                hash_to_file[content_hash] = f
                file_to_hash[f] = content_hash
                file_to_mtime[f] = util.get_last_mod_time(f)

            # Get file hashes which contain source code comments.
            for report in reports:
                last_report_event = report.bug_path[-1]
                file_path = files[last_report_event['location']['file']]
                if not os.path.isfile(file_path):
                    continue

                file_hash = file_to_hash[file_path]
                if file_hash in file_hash_with_review_status:
                    continue

                report_line = last_report_event['location']['line']
                sc_handler = SourceCodeCommentHandler(file_path)
                if sc_handler.has_source_line_comments(report_line):
                    file_hash_with_review_status.add(file_hash)

            return missing_files
        except Exception as ex:
            LOG.error('Parsing the plist failed: %s', str(ex))
Beispiel #38
0
def skip_report(report_hash, source_file, report_line, checker_name,
                src_comment_handler=None):
    """
    Returns True if the report was suppressed in the source code, otherwise
    False.
    """
    bug = {'hash_value': report_hash, 'file_path': source_file}
    if src_comment_handler and src_comment_handler.get_suppressed(bug):
        LOG.debug("Suppressed by suppress file: %s:%s [%s] %s", source_file,
                  report_line, checker_name, report_hash)
        return True

    sc_handler = SourceCodeCommentHandler()

    # Check for source code comment.
    src_comment_data = sc_handler.filter_source_line_comments(
        source_file,
        report_line,
        checker_name)

    if len(src_comment_data) == 1:
        status = src_comment_data[0]['status']

        LOG.debug("Suppressed by source code comment.")
        if src_comment_handler:
            file_name = os.path.basename(source_file)
            message = src_comment_data[0]['message']
            src_comment_handler.store_suppress_bug_id(
                report_hash,
                file_name,
                message,
                status)

        if skip_suppress_status(status):
            return True

    elif len(src_comment_data) > 1:
        LOG.warning("Multiple source code comment can be found "
                    "for '%s' checker in '%s' at line %d. "
                    "This bug will not be suppressed!",
                    checker_name, source_file, report_line)
    return False
Beispiel #39
0
def skip_report(report_hash, source_file, report_line, checker_name,
                src_comment_handler=None):
    """
    Returns True if the report was suppressed in the source code, otherwise
    False.
    """
    bug = {'hash_value': report_hash, 'file_path': source_file}
    if src_comment_handler and src_comment_handler.get_suppressed(bug):
        LOG.debug("Suppressed by suppress file: %s:%s [%s] %s", source_file,
                  report_line, checker_name, report_hash)
        return True

    sc_handler = SourceCodeCommentHandler(source_file)

    # Check for source code comment.
    src_comment_data = sc_handler.filter_source_line_comments(
        report_line,
        checker_name)

    if len(src_comment_data) == 1:
        status = src_comment_data[0]['status']

        LOG.debug("Suppressed by source code comment.")
        if src_comment_handler:
            file_name = os.path.basename(source_file)
            message = src_comment_data[0]['message']
            src_comment_handler.store_suppress_bug_id(
                report_hash,
                file_name,
                message,
                status)

        if skip_suppress_status(status):
            return True

    elif len(src_comment_data) > 1:
        LOG.warning("Multiple source code comment can be found "
                    "for '%s' checker in '%s' at line %d. "
                    "This bug will not be suppressed!",
                    checker_name, source_file, report_line)
    return False
    def test_multiple_comments(self):
        """Check multiple comment."""
        bug_line = 23
        sc_handler = SourceCodeCommentHandler()
        res = sc_handler.has_source_line_comments(self.__tmp_srcfile_3,
                                                  bug_line)
        self.assertTrue(res)

        source_line_comments = \
            sc_handler.get_source_line_comments(self.__tmp_srcfile_3, bug_line)
        self.assertEqual(len(source_line_comments), 2)

        expected = [{
                        'checkers': {'my.checker_1'},
                        'message': 'intentional comment',
                        'status': 'intentional',
                        'line': '// codechecker_intentional [ my.checker_1 ] '
                                'intentional comment\n'},
                    {
                        'checkers': {'my.checker_2'},
                        'message': 'confirmed bug',
                        'status': 'confirmed',
                        'line': '// codechecker_confirmed  [ my.checker_2 ] '
                                'confirmed bug\n'
                    }]

        self.assertDictEqual(expected[0], source_line_comments[0])
        self.assertDictEqual(expected[1], source_line_comments[1])

        current_line_comments = \
            sc_handler.filter_source_line_comments(self.__tmp_srcfile_3,
                                                   bug_line,
                                                   'my.checker_1')
        self.assertEqual(len(current_line_comments), 1)
        self.assertEqual(current_line_comments[0]['message'],
                         expected[0]['message'])
        self.assertEqual(current_line_comments[0]['status'],
                         expected[0]['status'])

        current_line_comments = \
            sc_handler.filter_source_line_comments(self.__tmp_srcfile_3,
                                                   bug_line,
                                                   'my.checker_2')
        self.assertEqual(len(current_line_comments), 1)

        self.assertEqual(current_line_comments[0]['message'],
                         expected[1]['message'])
        self.assertEqual(current_line_comments[0]['status'],
                         expected[1]['status'])

        current_line_comments = \
            sc_handler.filter_source_line_comments(self.__tmp_srcfile_3,
                                                   bug_line,
                                                   'my.dummy')
        self.assertEqual(len(current_line_comments), 0)
Beispiel #41
0
    def test_cstyle_comment_multi_line_mismatch(self):
        """
        Multi line C style comment start '/*' is in a different line
        from the codechecker review status comment.

        /*
          codechecker_suppress [ my_checker_1 ]
          multi line
          comment
          again
         */
        """

        bug_line = 108
        sc_handler = SourceCodeCommentHandler()
        res = sc_handler.has_source_line_comments(self.__tmp_srcfile_1,
                                                  bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(
            self.__tmp_srcfile_1, bug_line)

        for line in source_line_comments:
            print('-======')
            print(line)

        self.assertEqual(len(source_line_comments), 1)

        expected = {
            'checkers': {'my_checker_1'},
            'message':
            'multi line comment again',
            'status':
            'false_positive',
            'line':
            '  codechecker_suppress [ my_checker_1 ]\n   '
            'multi line\n   comment\n   again\n  */\n'
        }

        self.assertDictEqual(expected, source_line_comments[0])
    def test_multiple_multi_line_comments(self):
        """Check multi line long line comments."""
        bug_line = 31
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_3)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 2)

        expected = [{
                        'checkers': {'my.checker_1'},
                        'message': 'long intentional bug comment',
                        'status': 'intentional'},
                    {
                        'checkers': {'my.checker_2'},
                        'message': 'long confirmed bug comment',
                        'status': 'confirmed'
                    }]

        self.assertDictEqual(expected[0], source_line_comments[0])
        self.assertDictEqual(expected[1], source_line_comments[1])
    def test_multiple_multi_line_comments(self):
        """Check multi line long line comments."""
        bug_line = 31
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_3)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 2)

        expected = [{
            'checkers': {'my.checker_1'},
            'message': 'long intentional bug comment',
            'status': 'intentional'
        }, {
            'checkers': {'my.checker_2'},
            'message': 'long confirmed bug comment',
            'status': 'confirmed'
        }]

        self.assertDictEqual(expected[0], source_line_comments[0])
        self.assertDictEqual(expected[1], source_line_comments[1])
    def test_cstyle_multi_comment_multi_line(self):
        """
        Multi line C style comment with multiple review status comment.

        /* codechecker_false_positive [ my.checker_2, my.checker_1 ] comment
        codechecker_intentional [ my.checker_1 ] intentional comment */

        """

        bug_line = 49
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_3)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(
            bug_line)

        for l in source_line_comments:
            print(l)

        self.assertEqual(len(source_line_comments), 2)

        expected = [{
                        'checkers': {'my.checker_1'},
                        'message': 'intentional comment',
                        'status': 'intentional'},
                    {
                        'checkers': {'my.checker_1', 'my.checker_2'},
                        'message': 'some comment',
                        'status': 'false_positive'
                    }]

        self.assertDictEqual(expected[0], source_line_comments[0])
        self.assertDictEqual(expected[1], source_line_comments[1])

        current_line_comments = \
            sc_handler.filter_source_line_comments(bug_line, 'my.checker_1')
        self.assertEqual(len(current_line_comments), 2)
        self.assertEqual(current_line_comments[0]['message'],
                         expected[0]['message'])
        self.assertEqual(current_line_comments[0]['status'],
                         expected[0]['status'])
        self.assertEqual(current_line_comments[1]['message'],
                         expected[1]['message'])
        self.assertEqual(current_line_comments[1]['status'],
                         expected[1]['status'])

        current_line_comments = \
            sc_handler.filter_source_line_comments(bug_line, 'my.checker_2')
        self.assertEqual(len(current_line_comments), 1)

        self.assertEqual(current_line_comments[0]['message'],
                         expected[1]['message'])
        self.assertEqual(current_line_comments[0]['status'],
                         expected[1]['status'])

        current_line_comments = \
            sc_handler.filter_source_line_comments(bug_line, 'my.dummy')
        self.assertEqual(len(current_line_comments), 0)
Beispiel #45
0
    def test_cstyle_comment_multi_star(self):
        """
        Multi line C style comment.

        /* codechecker_suppress [ my_checker_1 ]
         * multi line
         * comment
         * again
         */
        """

        bug_line = 98
        sc_handler = SourceCodeCommentHandler()
        res = sc_handler.has_source_line_comments(self.__tmp_srcfile_1,
                                                  bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(
            self.__tmp_srcfile_1, bug_line)

        for line in source_line_comments:
            print('-======')
            print(line)

        self.assertEqual(len(source_line_comments), 1)

        expected = {
            'checkers': {'my_checker_1'},
            'message':
            'multi line comment again',
            'status':
            'false_positive',
            'line':
            "/* codechecker_suppress [ my_checker_1 ]\n  * "
            "multi line\n  * comment\n  * again\n  */\n"
        }

        self.assertDictEqual(expected, source_line_comments[0])
    def test_multiple_all_comments(self):
        """Check multiple comment."""
        bug_line = 37
        sc_handler = SourceCodeCommentHandler(self.__tmp_srcfile_3)
        res = sc_handler.has_source_line_comments(bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(bug_line)
        self.assertEqual(len(source_line_comments), 2)

        expected = [{
                        'checkers': {'my.checker_1'},
                        'message': 'intentional comment',
                        'status': 'intentional'},
                    {
                        'checkers': {'all'},
                        'message': 'some comment',
                        'status': 'false_positive'
                    }]

        self.assertDictEqual(expected[0], source_line_comments[0])
        self.assertDictEqual(expected[1], source_line_comments[1])

        current_line_comments = \
            sc_handler.filter_source_line_comments(bug_line, 'my.checker_1')
        self.assertEqual(len(current_line_comments), 1)

        self.assertEqual(current_line_comments[0]['message'],
                         expected[0]['message'])
        self.assertEqual(current_line_comments[0]['status'],
                         expected[0]['status'])

        current_line_comments = \
            sc_handler.filter_source_line_comments(bug_line, '')
        self.assertEqual(len(current_line_comments), 1)
        self.assertEqual(current_line_comments[0]['message'],
                         expected[1]['message'])
        self.assertEqual(current_line_comments[0]['status'],
                         expected[1]['status'])

        current_line_comments = \
            sc_handler.filter_source_line_comments(bug_line, 'my.dummy')
        self.assertEqual(len(current_line_comments), 1)

        self.assertEqual(len(current_line_comments), 1)
        self.assertEqual(current_line_comments[0]['message'],
                         expected[1]['message'])
        self.assertEqual(current_line_comments[0]['status'],
                         expected[1]['status'])
Beispiel #47
0
class Report:
    """Represents an analyzer report.

    The main section is where the analyzer reported the issue.
    The bugpath contains additional locations (and messages) which lead to
    the main section.
    """

    def __init__(self,
                 main: Dict,
                 bugpath: Dict,
                 files: Dict[int, str],
                 metadata: Dict[str, str]):

        # Dictionary containing checker name, report hash,
        # main report position, report message ...
        self.__main = main

        # Dictionary containing bug path related data
        # with control, event ... sections.
        self.__bug_path = bugpath

        # Dictionary fileid to filepath that bugpath events refer to
        self.__files = files

        # Can contain the source line where the main section was reported.
        self.__source_line = ""

        # Dictionary containing metadata information (analyzer name, version).
        self.__metadata = metadata

        self.__source_code_comments = None
        self.__sc_handler = SourceCodeCommentHandler()

    @property
    def line(self) -> int:
        return self.__main['location']['line']

    @property
    def col(self) -> int:
        return self.__main['location']['col']

    @property
    def description(self) -> str:
        return self.__main['description']

    @property
    def main(self) -> Dict:
        return self.__main

    @property
    def report_hash(self) -> str:
        return self.__main['issue_hash_content_of_line_in_context']

    @property
    def check_name(self) -> str:
        return self.__main['check_name']

    @property
    def bug_path(self) -> Dict:
        return self.__bug_path

    @property
    def notes(self) -> List[str]:
        return self.__main.get('notes', [])

    @property
    def macro_expansions(self) -> List[str]:
        return self.__main.get('macro_expansions', [])

    @property
    def files(self) -> Dict[int, str]:
        return self.__files

    @property
    def file_path(self) -> str:
        """ Get the filepath for the main report location. """
        return self.files[self.__main['location']['file']]

    @property
    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

    @source_line.setter
    def source_line(self, sl):
        self.__source_line = sl

    @property
    def metadata(self) -> Dict:
        return self.__metadata

    @property
    def source_code_comments(self):
        """
        Get source code comments for the report.
        It will read the source file only once.
        """
        if self.__source_code_comments is not None:
            return self.__source_code_comments

        self.__source_code_comments = []

        if not os.path.exists(self.file_path):
            return self.__source_code_comments

        with open(self.file_path, encoding='utf-8', errors='ignore') as sf:
            try:
                self.__source_code_comments = \
                    self.__sc_handler.filter_source_line_comments(
                        sf, self.line, self.check_name)
            except SpellException as ex:
                LOG.warning("%s contains %s", os.path.basename(self.file_path),
                            str(ex))

        if len(self.__source_code_comments) == 1:
            LOG.debug("Report %s is suppressed in code. file: %s Line %s",
                      self.report_hash, self.file_path, self.line)
        elif len(self.__source_code_comments) > 1:
            LOG.warning(
                "Multiple source code comment can be found "
                "for '%s' checker in '%s' at line %s. "
                "This bug will not be suppressed!",
                self.check_name, self.file_path, self.line)

        return self.__source_code_comments

    def check_source_code_comments(self, comment_types: List[str]):
        """
        True if it doesn't have a source code comment or if every comments have
        specified comment types.
        """
        if not self.source_code_comments:
            return True

        return all(c['status'] in comment_types
                   for c in self.source_code_comments)

    def __str__(self):
        msg = json.dumps(self.__main, sort_keys=True, indent=2)
        msg += str(self.__files)
        return msg

    def trim_path_prefixes(self, path_prefixes=None):
        """ Removes the longest matching leading path from the file paths. """
        self.__files = {i: util.trim_path_prefixes(file_path, path_prefixes)
                        for i, file_path in self.__files.items()}

    def to_json(self):
        """Converts to a special json format.

        This format is used by the parse command when the reports are printed
        to the stdout in json format."""
        ret = self.__main
        ret["path"] = self.bug_path
        ret["files"] = self.files.values()

        return ret
Beispiel #48
0
    def test_cstyle_multi_comment_multi_line_long(self):
        """
        Multi line C style comment with multiple review status comment.

        /* codechecker_false_positive [ my.checker_2, my.checker_1 ] comment
        which
        is
        long
        codechecker_intentional [ my.checker_1 ] intentional comment
        long
        again */

        """

        bug_line = 60
        sc_handler = SourceCodeCommentHandler()
        res = sc_handler.has_source_line_comments(self.__tmp_srcfile_3,
                                                  bug_line)
        self.assertTrue(res)

        source_line_comments = sc_handler.get_source_line_comments(
            self.__tmp_srcfile_3, bug_line)

        for line in source_line_comments:
            print(line)

        self.assertEqual(len(source_line_comments), 2)

        expected = [{
            'checkers': {'my.checker_1'},
            'message':
            'intentional comment long again',
            'status':
            'intentional',
            'line':
            'codechecker_intentional [ my.checker_1 ] '
            'intentional comment\n long\n again */\n'
        }, {
            'checkers': {'my.checker_1', 'my.checker_2'},
            'message':
            'comment which is long',
            'status':
            'false_positive',
            'line':
            '/* codechecker_false_positive [ '
            'my.checker_2, my.checker_1 ] comment\n '
            'which\n is\n long\n'
        }]

        self.assertDictEqual(expected[0], source_line_comments[0])
        self.assertDictEqual(expected[1], source_line_comments[1])

        current_line_comments = \
            sc_handler.filter_source_line_comments(self.__tmp_srcfile_3,
                                                   bug_line,
                                                   'my.checker_1')
        self.assertEqual(len(current_line_comments), 2)
        self.assertEqual(current_line_comments[0]['message'],
                         expected[0]['message'])
        self.assertEqual(current_line_comments[0]['status'],
                         expected[0]['status'])
        self.assertEqual(current_line_comments[1]['message'],
                         expected[1]['message'])
        self.assertEqual(current_line_comments[1]['status'],
                         expected[1]['status'])

        current_line_comments = \
            sc_handler.filter_source_line_comments(self.__tmp_srcfile_3,
                                                   bug_line,
                                                   'my.checker_2')
        self.assertEqual(len(current_line_comments), 1)

        self.assertEqual(current_line_comments[0]['message'],
                         expected[1]['message'])
        self.assertEqual(current_line_comments[0]['status'],
                         expected[1]['status'])

        current_line_comments = \
            sc_handler.filter_source_line_comments(self.__tmp_srcfile_3,
                                                   bug_line,
                                                   'my.dummy')
        self.assertEqual(len(current_line_comments), 0)