Failed Conditions
Pull Request — master (#1182)
by Lasse
01:41
created

bears.c_languages.clang_available()   A

Complexity

Conditions 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 2
dl 0
loc 12
rs 9.4286
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 clang.cindex import Index, LibclangError
6
from coalib.results.SourceRange import SourceRange
7
from coalib.settings.Setting import typed_list
8
9
10
def clang_available(cls):
11
    """
12
    Checks if Clang is available and ready to use. This method is intended to
13
    be assigned to the check_prerequisites method of a bear.
14
15
    :return: True if Clang is available, a description of the error else.
16
    """
17
    try:
18
        Index.create()
19
        return True
20
    except LibclangError as error:  # pragma: no cover
21
        return str(error)
22
23
24
class ClangBear(LocalBear):
25
    def run(self, filename, file, clang_cli_options: typed_list(str)=None):
26
        """
27
        Runs Clang over the given files and raises/fixes any upcoming issues.
28
29
        :param clang_cli_options: Any options that will be passed through to
30
                                  Clang.
31
        """
32
        index = Index.create()
33
        diagnostics = index.parse(
34
            filename,
35
            args=clang_cli_options,
36
            unsaved_files=[(filename, ''.join(file))]).diagnostics
37
        for diag in diagnostics:
38
            severity = {0: RESULT_SEVERITY.INFO,
39
                        1: RESULT_SEVERITY.INFO,
40
                        2: RESULT_SEVERITY.NORMAL,
41
                        3: RESULT_SEVERITY.MAJOR,
42
                        4: RESULT_SEVERITY.MAJOR}.get(diag.severity)
43
            affected_code = tuple(SourceRange.from_clang_range(range)
44
                                  for range in diag.ranges)
45
46
            diffs = None
47
            fixits = list(diag.fixits)
48
            if len(fixits) > 0:
49
                # FIXME: coala doesn't support choice of diffs, for now
50
                # append first one only, often there's only one anyway
51
                diffs = {filename: Diff.from_clang_fixit(fixits[0], file)}
52
53
                # No affected code yet? Let's derive it from the fix!
54
                if len(affected_code) == 0:
55
                    affected_code = diffs[filename].affected_code(filename)
56
57
            # Still no affected code? Position is the best we can get...
58
            if len(affected_code) == 0:
59
                affected_code = (SourceRange.from_values(
60
                    diag.location.file.name,
61
                    diag.location.line,
62
                    diag.location.column),)
63
64
            yield Result(
65
                self,
66
                diag.spelling,
67
                severity=severity,
68
                affected_code=affected_code,
69
                diffs=diffs)
70
71
    check_prerequisites = classmethod(clang_available)
72