xref: /llvm-project/clang/bindings/python/tests/cindex/test_code_completion.py (revision 71cfa381ef8c4fe659c67e8b2901d767e10f2aff)
1import os
2
3from clang.cindex import Config, TranslationUnit
4
5if "CLANG_LIBRARY_PATH" in os.environ:
6    Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])
7
8import unittest
9from pathlib import Path
10
11
12class TestCodeCompletion(unittest.TestCase):
13    def check_completion_results(self, cr, expected):
14        self.assertIsNotNone(cr)
15        self.assertEqual(len(cr.diagnostics), 0)
16
17        completions = [str(c) for c in cr.results]
18
19        for c in expected:
20            self.assertIn(c, completions)
21
22    def test_code_complete(self):
23        files = [
24            (
25                "fake.c",
26                """
27/// Aaa.
28int test1;
29
30/// Bbb.
31void test2(void);
32
33void f() {
34
35}
36""",
37            )
38        ]
39
40        tu = TranslationUnit.from_source(
41            "fake.c",
42            ["-std=c99"],
43            unsaved_files=files,
44            options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION,
45        )
46
47        cr = tu.codeComplete(
48            "fake.c", 9, 1, unsaved_files=files, include_brief_comments=True
49        )
50
51        expected = [
52            "{'int', ResultType} | {'test1', TypedText} || Priority: 50 || Availability: Available || Brief comment: Aaa.",
53            "{'void', ResultType} | {'test2', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 50 || Availability: Available || Brief comment: Bbb.",
54            "{'return', TypedText} | {';', SemiColon} || Priority: 40 || Availability: Available || Brief comment: ",
55        ]
56        self.check_completion_results(cr, expected)
57
58    def test_code_complete_pathlike(self):
59        files = [
60            (
61                Path("fake.c"),
62                """
63/// Aaa.
64int test1;
65
66/// Bbb.
67void test2(void);
68
69void f() {
70
71}
72""",
73            )
74        ]
75
76        tu = TranslationUnit.from_source(
77            Path("fake.c"),
78            ["-std=c99"],
79            unsaved_files=files,
80            options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION,
81        )
82
83        cr = tu.codeComplete(
84            Path("fake.c"),
85            9,
86            1,
87            unsaved_files=files,
88            include_brief_comments=True,
89        )
90
91        expected = [
92            "{'int', ResultType} | {'test1', TypedText} || Priority: 50 || Availability: Available || Brief comment: Aaa.",
93            "{'void', ResultType} | {'test2', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 50 || Availability: Available || Brief comment: Bbb.",
94            "{'return', TypedText} | {';', SemiColon} || Priority: 40 || Availability: Available || Brief comment: ",
95        ]
96        self.check_completion_results(cr, expected)
97
98    def test_code_complete_availability(self):
99        files = [
100            (
101                "fake.cpp",
102                """
103class P {
104protected:
105  int member;
106};
107
108class Q : public P {
109public:
110  using P::member;
111};
112
113void f(P x, Q y) {
114  x.; // member is inaccessible
115  y.; // member is accessible
116}
117""",
118            )
119        ]
120
121        tu = TranslationUnit.from_source(
122            "fake.cpp", ["-std=c++98"], unsaved_files=files
123        )
124
125        cr = tu.codeComplete("fake.cpp", 12, 5, unsaved_files=files)
126
127        expected = [
128            "{'const', TypedText} || Priority: 50 || Availability: Available || Brief comment: ",
129            "{'volatile', TypedText} || Priority: 50 || Availability: Available || Brief comment: ",
130            "{'operator', TypedText} || Priority: 40 || Availability: Available || Brief comment: ",
131            "{'P', TypedText} || Priority: 50 || Availability: Available || Brief comment: ",
132            "{'Q', TypedText} || Priority: 50 || Availability: Available || Brief comment: ",
133        ]
134        self.check_completion_results(cr, expected)
135
136        cr = tu.codeComplete("fake.cpp", 13, 5, unsaved_files=files)
137        expected = [
138            "{'P', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: ",
139            "{'P &', ResultType} | {'operator=', TypedText} | {'(', LeftParen} | {'const P &', Placeholder} | {')', RightParen} || Priority: 79 || Availability: Available || Brief comment: ",
140            "{'int', ResultType} | {'member', TypedText} || Priority: 35 || Availability: NotAccessible || Brief comment: ",
141            "{'void', ResultType} | {'~P', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 79 || Availability: Available || Brief comment: ",
142        ]
143        self.check_completion_results(cr, expected)
144