def test_from_clang_range(self): # Simulating a clang SourceRange is easier than setting one up without # actually parsing a complete C file. ClangRange = namedtuple("ClangRange", "start end") ClangPosition = namedtuple("ClangPosition", "file line column") ClangFile = namedtuple("ClangFile", "name") file = ClangFile("t.c".encode()) start = ClangPosition(file, 1, 2) end = ClangPosition(file, 3, 4) uut = SourceRange.from_clang_range(ClangRange(start, end)) compare = SourceRange.from_values("t.c", 1, 2, 3, 4) self.assertEqual(uut, compare)
def test_from_clang_range(self): # Simulating a clang SourceRange is easier than setting one up without # actually parsing a complete C file. ClangRange = namedtuple("ClangRange", "start end") ClangPosition = namedtuple("ClangPosition", "file line column") ClangFile = namedtuple("ClangFile", "name") file = ClangFile("t.c") start = ClangPosition(file, 1, 2) end = ClangPosition(file, 3, 4) uut = SourceRange.from_clang_range(ClangRange(start, end)) compare = SourceRange.from_values("t.c", 1, 2, 3, 4) self.assertEqual(uut, compare)
def test_from_clang_range(self): # Simulating a clang SourceRange is easier than setting one up without # actually parsing a complete C file. ClangRange = namedtuple('ClangRange', 'start end') ClangPosition = namedtuple('ClangPosition', 'file line column') ClangFile = namedtuple('ClangFile', 'name') file = ClangFile('t.c') start = ClangPosition(file, 1, 2) end = ClangPosition(file, 3, 4) uut = SourceRange.from_clang_range(ClangRange(start, end)) compare = SourceRange.from_values('t.c', 1, 2, 3, 4) self.assertEqual(uut, compare)
def run(self, filename, file, clang_cli_options: typed_list(str)=None): """ Check code for syntactical or semantical problems using Clang. This bear supports automatic fixes. :param clang_cli_options: Any options that will be passed through to Clang. """ index = Index.create() diagnostics = index.parse( filename, args=clang_cli_options, unsaved_files=[(filename, ''.join(file))]).diagnostics for diag in diagnostics: severity = {0: RESULT_SEVERITY.INFO, 1: RESULT_SEVERITY.INFO, 2: RESULT_SEVERITY.NORMAL, 3: RESULT_SEVERITY.MAJOR, 4: RESULT_SEVERITY.MAJOR}.get(diag.severity) affected_code = tuple(SourceRange.from_clang_range(range) for range in diag.ranges) diffs = None fixits = list(diag.fixits) if len(fixits) > 0: # FIXME: coala doesn't support choice of diffs, for now # append first one only, often there's only one anyway diffs = {filename: Diff.from_clang_fixit(fixits[0], file)} # No affected code yet? Let's derive it from the fix! if len(affected_code) == 0: affected_code = diffs[filename].affected_code(filename) # Still no affected code? Position is the best we can get... if len(affected_code) == 0 and diag.location.file is not None: affected_code = (SourceRange.from_values( diag.location.file.name, diag.location.line, diag.location.column),) yield Result( self, diag.spelling, severity=severity, affected_code=affected_code, diffs=diffs)
def run(self, filename, file, cyclomatic_complexity: int = 8, ): """ Check for all functions if they are too complicated using the cyclomatic complexity metric. You can read more about this metric at <https://www.wikiwand.com/en/Cyclomatic_complexity>. :param cyclomatic_complexity: Maximum cyclomatic complexity that is considered to be normal. The value of 10 had received substantial corroborating evidence. But the general recommendation: "For each module, either limit cyclomatic complexity to [the agreed-upon limit] or provide a written explanation of why the limit was exceeded." """ root = Index.create().parse(filename).cursor for cursor, complexity in self.complexities(root, filename): if complexity > cyclomatic_complexity: affected_code = (SourceRange.from_clang_range(cursor.extent),) yield Result( self, "The function '{function}' should be simplified. Its " 'cyclomatic complexity is {complexity} which exceeds ' 'maximal recommended value ' 'of {rec_value}.'.format( function=cursor.displayname, complexity=complexity, rec_value=cyclomatic_complexity), affected_code=affected_code, additional_info=( 'The cyclomatic complexity is a metric that measures ' 'how complicated a function is by counting branches ' 'and exits of each function.\n\n' 'Your function seems to be complicated and should be ' 'refactored so that it can be understood by other ' 'people easily.\n\nSee ' '<http://www.wikiwand.com/en/Cyclomatic_complexity>' ' for more information.'))
def run(self, filename, file, max_complexity: int = 8): """ Check for all functions if they are too complicated using the cyclomatic complexity metric. You can read more about this metric at <https://www.wikiwand.com/en/Cyclomatic_complexity>. :param max_complexity: Maximum cyclomatic complexity that is considered to be normal. The value of 10 had received substantial corroborating evidence. But the general recommendation: "For each module, either limit cyclomatic complexity to [the agreed-upon limit] or provide a written explanation of why the limit was exceeded." """ root = Index.create().parse(filename).cursor for cursor, complexity in self.complexities(root, filename): if complexity > max_complexity: affected_code = (SourceRange.from_clang_range(cursor.extent),) yield Result( self, "The function '{function}' should be simplified. Its " "cyclomatic complexity is {complexity} which exceeds " "maximal recommended value " "of {rec_value}.".format( function=cursor.displayname, complexity=complexity, rec_value=max_complexity ), affected_code=affected_code, additional_info=( "The cyclomatic complexity is a metric that measures " "how complicated a function is by counting branches " "and exits of each function.\n\n" "Your function seems to be complicated and should be " "refactored so that it can be understood by other " "people easily.\n\nSee " "<http://www.wikiwand.com/en/Cyclomatic_complexity>" " for more information." ), )