aboutsummaryrefslogtreecommitdiff
path: root/clang/bindings/python/tests/cindex/test_diagnostics.py
blob: ee7d37c896d70daf5356725097a4a5fb2b4d7a7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import os

from clang.cindex import Config, Diagnostic

if "CLANG_LIBRARY_PATH" in os.environ:
    Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

import unittest

from .util import get_tu

# FIXME: We need support for invalid translation units to test better.


class TestDiagnostics(unittest.TestCase):
    def test_diagnostic_warning(self):
        tu = get_tu("int f0() {}\n")
        self.assertEqual(len(tu.diagnostics), 1)
        self.assertEqual(tu.diagnostics[0].severity, Diagnostic.Warning)
        self.assertEqual(tu.diagnostics[0].location.line, 1)
        self.assertEqual(tu.diagnostics[0].location.column, 11)
        self.assertEqual(
            tu.diagnostics[0].spelling, "non-void function does not return a value"
        )

    def test_diagnostic_note(self):
        # FIXME: We aren't getting notes here for some reason.
        tu = get_tu("#define A x\nvoid *A = 1;\n")
        self.assertEqual(len(tu.diagnostics), 1)
        self.assertEqual(tu.diagnostics[0].severity, Diagnostic.Error)
        self.assertEqual(tu.diagnostics[0].location.line, 2)
        self.assertEqual(tu.diagnostics[0].location.column, 7)
        self.assertIn("incompatible", tu.diagnostics[0].spelling)

    #       self.assertEqual(tu.diagnostics[1].severity, Diagnostic.Note)
    #       self.assertEqual(tu.diagnostics[1].location.line, 1)
    #       self.assertEqual(tu.diagnostics[1].location.column, 11)
    #       self.assertEqual(tu.diagnostics[1].spelling, 'instantiated from')

    def test_diagnostic_fixit(self):
        tu = get_tu("struct { int f0; } x = { f0 : 1 };")
        self.assertEqual(len(tu.diagnostics), 1)
        self.assertEqual(tu.diagnostics[0].severity, Diagnostic.Warning)
        self.assertEqual(tu.diagnostics[0].location.line, 1)
        self.assertEqual(tu.diagnostics[0].location.column, 26)
        self.assertRegex(tu.diagnostics[0].spelling, "use of GNU old-style.*")
        self.assertEqual(len(tu.diagnostics[0].fixits), 1)
        with self.assertRaises(IndexError):
            tu.diagnostics[0].fixits[1]
        self.assertEqual(tu.diagnostics[0].fixits[0].range.start.line, 1)
        self.assertEqual(tu.diagnostics[0].fixits[0].range.start.column, 26)
        self.assertEqual(tu.diagnostics[0].fixits[0].range.end.line, 1)
        self.assertEqual(tu.diagnostics[0].fixits[0].range.end.column, 30)
        self.assertEqual(tu.diagnostics[0].fixits[0].value, ".f0 = ")

    def test_diagnostic_range(self):
        tu = get_tu('void f() { int i = "a"; }')
        self.assertEqual(len(tu.diagnostics), 1)
        self.assertEqual(tu.diagnostics[0].severity, Diagnostic.Error)
        self.assertEqual(tu.diagnostics[0].location.line, 1)
        self.assertEqual(tu.diagnostics[0].location.column, 16)
        self.assertRegex(tu.diagnostics[0].spelling, "incompatible pointer to.*")
        self.assertEqual(len(tu.diagnostics[0].fixits), 0)
        self.assertEqual(len(tu.diagnostics[0].ranges), 1)
        self.assertEqual(tu.diagnostics[0].ranges[0].start.line, 1)
        self.assertEqual(tu.diagnostics[0].ranges[0].start.column, 20)
        self.assertEqual(tu.diagnostics[0].ranges[0].end.line, 1)
        self.assertEqual(tu.diagnostics[0].ranges[0].end.column, 23)
        with self.assertRaises(IndexError):
            tu.diagnostics[0].ranges[1].start.line

    def test_diagnostic_category(self):
        """Ensure that category properties work."""
        tu = get_tu("int f(int i) { return 7; }", all_warnings=True)
        self.assertEqual(len(tu.diagnostics), 1)
        d = tu.diagnostics[0]

        self.assertEqual(d.severity, Diagnostic.Warning)
        self.assertEqual(d.location.line, 1)
        self.assertEqual(d.location.column, 11)

        self.assertEqual(d.category_number, 3)
        self.assertEqual(d.category_name, "Semantic Issue")

    def test_diagnostic_option(self):
        """Ensure that category option properties work."""
        tu = get_tu("int f(int i) { return 7; }", all_warnings=True)
        self.assertEqual(len(tu.diagnostics), 1)
        d = tu.diagnostics[0]

        self.assertEqual(d.option, "-Wunused-parameter")
        self.assertEqual(d.disable_option, "-Wno-unused-parameter")

    def test_diagnostic_children(self):
        tu = get_tu("void f(int x) {} void g() { f(); }")
        self.assertEqual(len(tu.diagnostics), 1)
        d = tu.diagnostics[0]

        children = d.children
        self.assertEqual(len(children), 1)
        with self.assertRaises(IndexError):
            children[1]
        self.assertEqual(children[0].severity, Diagnostic.Note)
        self.assertRegex(children[0].spelling, ".*declared here")
        self.assertEqual(children[0].location.line, 1)
        self.assertEqual(children[0].location.column, 6)

    def test_diagnostic_string_repr(self):
        tu = get_tu("struct MissingSemicolon{}")
        self.assertEqual(len(tu.diagnostics), 1)
        d = tu.diagnostics[0]

        self.assertEqual(
            repr(d),
            "<Diagnostic severity 3, location <SourceLocation file 't.c', line 1, column 26>, spelling \"expected ';' after struct\">",
        )

    def test_diagnostic_string_format(self):
        tu = get_tu("struct MissingSemicolon{}")
        self.assertEqual(len(tu.diagnostics), 1)
        d = tu.diagnostics[0]

        self.assertEqual(str(d), "t.c:1:26: error: expected ';' after struct")
        self.assertEqual(
            d.format(0b111111),
            "t.c:1:26: error: expected ';' after struct [2, Parse Issue]",
        )
        with self.assertRaises(ValueError):
            d.format(0b1000000)