Completed
Pull Request — master (#1106)
by Lasse
02:11
created

bears.c_languages.ClangBear   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 47
Duplicated Lines 0 %
Metric Value
dl 0
loc 47
rs 10
wmc 6

1 Method

Rating   Name   Duplication   Size   Complexity  
B run() 0 46 6
1
from coalib.bears.LocalBear import LocalBear
2
from coalib.results.RESULT_SEVERITY import RESULT_SEVERITY
3
from coalib.results.Result import Result
4
from coalib.results.Diff import Diff
5
from coalib.bearlib.parsing.clang.cindex import Index
6
from coalib.results.SourceRange import SourceRange
7
from coalib.settings.Setting import typed_list
8
9
10
class ClangBear(LocalBear):
11
    def run(self, filename, file, clang_cli_options: typed_list(str)=None):
12
        """
13
        Runs Clang over the given files and raises/fixes any upcoming issues.
14
15
        :param clang_cli_options: Any options that will be passed through to
16
                                  Clang.
17
        """
18
        index = Index.create()
19
        diagnostics = index.parse(
20
            filename,
21
            args=clang_cli_options,
22
            unsaved_files=[(filename.encode(),
23
                            ''.join(file).encode())]).diagnostics
24
        for diag in diagnostics:
25
            severity = {0: RESULT_SEVERITY.INFO,
26
                        1: RESULT_SEVERITY.INFO,
27
                        2: RESULT_SEVERITY.NORMAL,
28
                        3: RESULT_SEVERITY.MAJOR,
29
                        4: RESULT_SEVERITY.MAJOR}.get(diag.severity)
30
            affected_code = tuple(SourceRange.from_clang_range(range)
31
                                  for range in diag.ranges)
32
33
            diffs = None
34
            fixits = list(diag.fixits)
35
            if len(fixits) > 0:
36
                # FIXME: coala doesn't support choice of diffs, for now
37
                # append first one only, often there's only one anyway
38
                diffs = {filename: Diff.from_clang_fixit(fixits[0], file)}
39
40
                # No affected code yet? Let's derive it from the fix!
41
                if len(affected_code) == 0:
42
                    affected_code = diffs[filename].affected_code(filename)
43
44
            # Still no affected code? Position is the best we can get...
45
            if len(affected_code) == 0:
46
                affected_code = (SourceRange.from_values(
47
                    diag.location.file.name.decode(),
48
                    diag.location.line,
49
                    diag.location.column),)
50
51
            yield Result(
52
                self,
53
                diag.spelling.decode(),
54
                severity=severity,
55
                affected_code=affected_code,
56
                diffs=diffs)
57