1#include "clang/Interpreter/CodeCompletion.h"
2#include "clang/Frontend/CompilerInstance.h"
3#include "clang/Interpreter/Interpreter.h"
4#include "clang/Lex/Preprocessor.h"
5#include "clang/Sema/CodeCompleteConsumer.h"
6#include "clang/Sema/Sema.h"
7#include "llvm/LineEditor/LineEditor.h"
8#include "llvm/Support/Error.h"
9#include "llvm/Support/raw_ostream.h"
10
11#include "gmock/gmock.h"
12#include "gtest/gtest.h"
13
14using namespace clang;
15namespace {
16auto CB = clang::IncrementalCompilerBuilder();
17
18static std::unique_ptr<Interpreter> createInterpreter() {
19 auto CI = cantFail(ValOrErr: CB.CreateCpp());
20 return cantFail(ValOrErr: clang::Interpreter::create(CI: std::move(CI)));
21}
22
23static std::vector<std::string> runComp(clang::Interpreter &MainInterp,
24 llvm::StringRef Input,
25 llvm::Error &ErrR) {
26 auto CI = CB.CreateCpp();
27 if (auto Err = CI.takeError()) {
28 ErrR = std::move(Err);
29 return {};
30 }
31
32 auto Interp = clang::Interpreter::create(CI: std::move(*CI));
33 if (auto Err = Interp.takeError()) {
34 // log the error and returns an empty vector;
35 ErrR = std::move(Err);
36
37 return {};
38 }
39
40 std::vector<std::string> Results;
41 std::vector<std::string> Comps;
42 auto *MainCI = (*Interp)->getCompilerInstance();
43 auto CC = ReplCodeCompleter();
44 CC.codeComplete(InterpCI: MainCI, Content: Input, /* Lines */ Line: 1, Col: Input.size() + 1,
45 ParentCI: MainInterp.getCompilerInstance(), CCResults&: Results);
46
47 for (auto Res : Results)
48 if (Res.find(str: CC.Prefix) == 0)
49 Comps.push_back(x: Res);
50 return Comps;
51}
52
53TEST(CodeCompletionTest, Sanity) {
54 auto Interp = createInterpreter();
55 cantFail(ValOrErr: Interp->Parse(Code: "int foo = 12;"));
56 auto Err = llvm::Error::success();
57 auto comps = runComp(MainInterp&: *Interp, Input: "f", ErrR&: Err);
58 EXPECT_EQ((size_t)2, comps.size()); // float and foo
59 EXPECT_EQ(comps[0], std::string("float"));
60 EXPECT_EQ(comps[1], std::string("foo"));
61 EXPECT_EQ((bool)Err, false);
62}
63
64TEST(CodeCompletionTest, SanityNoneValid) {
65 auto Interp = createInterpreter();
66 cantFail(ValOrErr: Interp->Parse(Code: "int foo = 12;"));
67 auto Err = llvm::Error::success();
68 auto comps = runComp(MainInterp&: *Interp, Input: "babanana", ErrR&: Err);
69 EXPECT_EQ((size_t)0, comps.size()); // foo and float
70 EXPECT_EQ((bool)Err, false);
71}
72
73TEST(CodeCompletionTest, TwoDecls) {
74 auto Interp = createInterpreter();
75 cantFail(ValOrErr: Interp->Parse(Code: "int application = 12;"));
76 cantFail(ValOrErr: Interp->Parse(Code: "int apple = 12;"));
77 auto Err = llvm::Error::success();
78 auto comps = runComp(MainInterp&: *Interp, Input: "app", ErrR&: Err);
79 EXPECT_EQ((size_t)2, comps.size());
80 EXPECT_EQ((bool)Err, false);
81}
82
83TEST(CodeCompletionTest, CompFunDeclsNoError) {
84 auto Interp = createInterpreter();
85 auto Err = llvm::Error::success();
86 auto comps = runComp(MainInterp&: *Interp, Input: "void app(", ErrR&: Err);
87 EXPECT_EQ((bool)Err, false);
88}
89
90TEST(CodeCompletionTest, TypedDirected) {
91 auto Interp = createInterpreter();
92 cantFail(ValOrErr: Interp->Parse(Code: "int application = 12;"));
93 cantFail(ValOrErr: Interp->Parse(Code: "char apple = '2';"));
94 cantFail(ValOrErr: Interp->Parse(Code: "void add(int &SomeInt){}"));
95 {
96 auto Err = llvm::Error::success();
97 auto comps = runComp(MainInterp&: *Interp, Input: std::string("add("), ErrR&: Err);
98 EXPECT_EQ((size_t)1, comps.size());
99 EXPECT_EQ((bool)Err, false);
100 }
101
102 cantFail(ValOrErr: Interp->Parse(Code: "int banana = 42;"));
103
104 {
105 auto Err = llvm::Error::success();
106 auto comps = runComp(MainInterp&: *Interp, Input: std::string("add("), ErrR&: Err);
107 EXPECT_EQ((size_t)2, comps.size());
108 EXPECT_EQ(comps[0], "application");
109 EXPECT_EQ(comps[1], "banana");
110 EXPECT_EQ((bool)Err, false);
111 }
112
113 {
114 auto Err = llvm::Error::success();
115 auto comps = runComp(MainInterp&: *Interp, Input: std::string("add(b"), ErrR&: Err);
116 EXPECT_EQ((size_t)1, comps.size());
117 EXPECT_EQ(comps[0], "banana");
118 EXPECT_EQ((bool)Err, false);
119 }
120}
121
122TEST(CodeCompletionTest, SanityClasses) {
123 auto Interp = createInterpreter();
124 cantFail(ValOrErr: Interp->Parse(Code: "struct Apple{};"));
125 cantFail(ValOrErr: Interp->Parse(Code: "void takeApple(Apple &a1){}"));
126 cantFail(ValOrErr: Interp->Parse(Code: "Apple a1;"));
127 cantFail(ValOrErr: Interp->Parse(Code: "void takeAppleCopy(Apple a1){}"));
128
129 {
130 auto Err = llvm::Error::success();
131 auto comps = runComp(MainInterp&: *Interp, Input: "takeApple(", ErrR&: Err);
132 EXPECT_EQ((size_t)1, comps.size());
133 EXPECT_EQ(comps[0], std::string("a1"));
134 EXPECT_EQ((bool)Err, false);
135 }
136 {
137 auto Err = llvm::Error::success();
138 auto comps = runComp(MainInterp&: *Interp, Input: std::string("takeAppleCopy("), ErrR&: Err);
139 EXPECT_EQ((size_t)1, comps.size());
140 EXPECT_EQ(comps[0], std::string("a1"));
141 EXPECT_EQ((bool)Err, false);
142 }
143}
144
145TEST(CodeCompletionTest, SubClassing) {
146 auto Interp = createInterpreter();
147 cantFail(ValOrErr: Interp->Parse(Code: "struct Fruit {};"));
148 cantFail(ValOrErr: Interp->Parse(Code: "struct Apple : Fruit{};"));
149 cantFail(ValOrErr: Interp->Parse(Code: "void takeFruit(Fruit &f){}"));
150 cantFail(ValOrErr: Interp->Parse(Code: "Apple a1;"));
151 cantFail(ValOrErr: Interp->Parse(Code: "Fruit f1;"));
152 auto Err = llvm::Error::success();
153 auto comps = runComp(MainInterp&: *Interp, Input: std::string("takeFruit("), ErrR&: Err);
154 EXPECT_EQ((size_t)2, comps.size());
155 EXPECT_EQ(comps[0], std::string("a1"));
156 EXPECT_EQ(comps[1], std::string("f1"));
157 EXPECT_EQ((bool)Err, false);
158}
159
160TEST(CodeCompletionTest, MultipleArguments) {
161 auto Interp = createInterpreter();
162 cantFail(ValOrErr: Interp->Parse(Code: "int foo = 42;"));
163 cantFail(ValOrErr: Interp->Parse(Code: "char fowl = 'A';"));
164 cantFail(ValOrErr: Interp->Parse(Code: "void takeTwo(int &a, char b){}"));
165 auto Err = llvm::Error::success();
166 auto comps = runComp(MainInterp&: *Interp, Input: std::string("takeTwo(foo, "), ErrR&: Err);
167 EXPECT_EQ((size_t)1, comps.size());
168 EXPECT_EQ(comps[0], std::string("fowl"));
169 EXPECT_EQ((bool)Err, false);
170}
171
172TEST(CodeCompletionTest, Methods) {
173 auto Interp = createInterpreter();
174 cantFail(ValOrErr: Interp->Parse(
175 Code: "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
176 cantFail(ValOrErr: Interp->Parse(Code: "Foo f1;"));
177
178 auto Err = llvm::Error::success();
179 auto comps = runComp(MainInterp&: *Interp, Input: std::string("f1."), ErrR&: Err);
180 EXPECT_EQ((size_t)2, comps.size());
181 EXPECT_EQ(comps[0], std::string("add"));
182 EXPECT_EQ(comps[1], std::string("par"));
183 EXPECT_EQ((bool)Err, false);
184}
185
186TEST(CodeCompletionTest, MethodsInvocations) {
187 auto Interp = createInterpreter();
188 cantFail(ValOrErr: Interp->Parse(
189 Code: "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
190 cantFail(ValOrErr: Interp->Parse(Code: "Foo f1;"));
191 cantFail(ValOrErr: Interp->Parse(Code: "int a = 84;"));
192
193 auto Err = llvm::Error::success();
194 auto comps = runComp(MainInterp&: *Interp, Input: std::string("f1.add("), ErrR&: Err);
195 EXPECT_EQ((size_t)1, comps.size());
196 EXPECT_EQ(comps[0], std::string("a"));
197 EXPECT_EQ((bool)Err, false);
198}
199
200TEST(CodeCompletionTest, NestedInvocations) {
201 auto Interp = createInterpreter();
202 cantFail(ValOrErr: Interp->Parse(
203 Code: "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
204 cantFail(ValOrErr: Interp->Parse(Code: "Foo f1;"));
205 cantFail(ValOrErr: Interp->Parse(Code: "int a = 84;"));
206 cantFail(ValOrErr: Interp->Parse(Code: "int plus(int a, int b) { return a + b; }"));
207
208 auto Err = llvm::Error::success();
209 auto comps = runComp(MainInterp&: *Interp, Input: std::string("plus(42, f1.add("), ErrR&: Err);
210 EXPECT_EQ((size_t)1, comps.size());
211 EXPECT_EQ(comps[0], std::string("a"));
212 EXPECT_EQ((bool)Err, false);
213}
214
215TEST(CodeCompletionTest, TemplateFunctions) {
216 auto Interp = createInterpreter();
217 cantFail(
218 ValOrErr: Interp->Parse(Code: "template <typename T> T id(T a) { return a;} "));
219 cantFail(ValOrErr: Interp->Parse(Code: "int apple = 84;"));
220 {
221 auto Err = llvm::Error::success();
222 auto comps = runComp(MainInterp&: *Interp, Input: std::string("id<int>("), ErrR&: Err);
223 EXPECT_EQ((size_t)1, comps.size());
224 EXPECT_EQ(comps[0], std::string("apple"));
225 EXPECT_EQ((bool)Err, false);
226 }
227
228 cantFail(ValOrErr: Interp->Parse(
229 Code: "template <typename T> T pickFirst(T a, T b) { return a;} "));
230 cantFail(ValOrErr: Interp->Parse(Code: "char pear = '4';"));
231 {
232 auto Err = llvm::Error::success();
233 auto comps = runComp(MainInterp&: *Interp, Input: std::string("pickFirst(apple, "), ErrR&: Err);
234 EXPECT_EQ((size_t)1, comps.size());
235 EXPECT_EQ(comps[0], std::string("apple"));
236 EXPECT_EQ((bool)Err, false);
237 }
238}
239
240} // anonymous namespace
241

source code of clang/unittests/Interpreter/CodeCompletionTest.cpp