xref: /llvm-project/clang/unittests/Interpreter/CodeCompletionTest.cpp (revision 6a47315a3cb2c6d381809f0ba5c89bd8dcdbcaa0)
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/ExecutionEngine/Orc/LLJIT.h"
8 #include "llvm/LineEditor/LineEditor.h"
9 #include "llvm/Support/Error.h"
10 #include "llvm/Support/raw_ostream.h"
11 
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14 
15 #if defined(_AIX) || defined(__MVS__)
16 #define CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
17 #endif
18 
19 using namespace clang;
20 namespace {
21 auto CB = clang::IncrementalCompilerBuilder();
22 
23 static std::unique_ptr<Interpreter> createInterpreter() {
24   auto CI = cantFail(CB.CreateCpp());
25   return cantFail(clang::Interpreter::create(std::move(CI)));
26 }
27 
28 static std::vector<std::string> runComp(clang::Interpreter &MainInterp,
29                                         llvm::StringRef Input,
30                                         llvm::Error &ErrR) {
31   auto CI = CB.CreateCpp();
32   if (auto Err = CI.takeError()) {
33     ErrR = std::move(Err);
34     return {};
35   }
36 
37   auto Interp = clang::Interpreter::create(std::move(*CI));
38   if (auto Err = Interp.takeError()) {
39     // log the error and returns an empty vector;
40     ErrR = std::move(Err);
41 
42     return {};
43   }
44 
45   std::vector<std::string> Results;
46   std::vector<std::string> Comps;
47   auto *MainCI = (*Interp)->getCompilerInstance();
48   auto CC = ReplCodeCompleter();
49   CC.codeComplete(MainCI, Input, /* Lines */ 1, Input.size() + 1,
50                   MainInterp.getCompilerInstance(), Results);
51 
52   for (auto Res : Results)
53     if (Res.find(CC.Prefix) == 0)
54       Comps.push_back(Res);
55   return Comps;
56 }
57 
58 static bool HostSupportsJit() {
59   auto J = llvm::orc::LLJITBuilder().create();
60   if (J)
61     return true;
62   LLVMConsumeError(llvm::wrap(J.takeError()));
63   return false;
64 }
65 
66 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
67 TEST(CodeCompletionTest, DISABLED_Sanity) {
68 #else
69 TEST(CodeCompletionTest, Sanity) {
70 #endif
71   if (!HostSupportsJit())
72     GTEST_SKIP();
73   auto Interp = createInterpreter();
74   cantFail(Interp->Parse("int foo = 12;"));
75   auto Err = llvm::Error::success();
76   auto comps = runComp(*Interp, "f", Err);
77   EXPECT_EQ((size_t)2, comps.size()); // float and foo
78   EXPECT_EQ(comps[0], std::string("float"));
79   EXPECT_EQ(comps[1], std::string("foo"));
80   EXPECT_EQ((bool)Err, false);
81 }
82 
83 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
84 TEST(CodeCompletionTest, DISABLED_SanityNoneValid) {
85 #else
86 TEST(CodeCompletionTest, SanityNoneValid) {
87 #endif
88   if (!HostSupportsJit())
89     GTEST_SKIP();
90   auto Interp = createInterpreter();
91   cantFail(Interp->Parse("int foo = 12;"));
92   auto Err = llvm::Error::success();
93   auto comps = runComp(*Interp, "babanana", Err);
94   EXPECT_EQ((size_t)0, comps.size()); // foo and float
95   EXPECT_EQ((bool)Err, false);
96 }
97 
98 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
99 TEST(CodeCompletionTest, DISABLED_TwoDecls) {
100 #else
101 TEST(CodeCompletionTest, TwoDecls) {
102 #endif
103   if (!HostSupportsJit())
104     GTEST_SKIP();
105   auto Interp = createInterpreter();
106   cantFail(Interp->Parse("int application = 12;"));
107   cantFail(Interp->Parse("int apple = 12;"));
108   auto Err = llvm::Error::success();
109   auto comps = runComp(*Interp, "app", Err);
110   EXPECT_EQ((size_t)2, comps.size());
111   EXPECT_EQ((bool)Err, false);
112 }
113 
114 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
115 TEST(CodeCompletionTest, DISABLED_CompFunDeclsNoError) {
116 #else
117 TEST(CodeCompletionTest, CompFunDeclsNoError) {
118 #endif
119   if (!HostSupportsJit())
120     GTEST_SKIP();
121   auto Interp = createInterpreter();
122   auto Err = llvm::Error::success();
123   auto comps = runComp(*Interp, "void app(", Err);
124   EXPECT_EQ((bool)Err, false);
125 }
126 
127 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
128 TEST(CodeCompletionTest, DISABLED_TypedDirected) {
129 #else
130 TEST(CodeCompletionTest, TypedDirected) {
131 #endif
132   if (!HostSupportsJit())
133     GTEST_SKIP();
134   auto Interp = createInterpreter();
135   cantFail(Interp->Parse("int application = 12;"));
136   cantFail(Interp->Parse("char apple = '2';"));
137   cantFail(Interp->Parse("void add(int &SomeInt){}"));
138   {
139     auto Err = llvm::Error::success();
140     auto comps = runComp(*Interp, std::string("add("), Err);
141     EXPECT_EQ((size_t)1, comps.size());
142     EXPECT_EQ((bool)Err, false);
143   }
144 
145   cantFail(Interp->Parse("int banana = 42;"));
146 
147   {
148     auto Err = llvm::Error::success();
149     auto comps = runComp(*Interp, std::string("add("), Err);
150     EXPECT_EQ((size_t)2, comps.size());
151     EXPECT_EQ(comps[0], "application");
152     EXPECT_EQ(comps[1], "banana");
153     EXPECT_EQ((bool)Err, false);
154   }
155 
156   {
157     auto Err = llvm::Error::success();
158     auto comps = runComp(*Interp, std::string("add(b"), Err);
159     EXPECT_EQ((size_t)1, comps.size());
160     EXPECT_EQ(comps[0], "banana");
161     EXPECT_EQ((bool)Err, false);
162   }
163 }
164 
165 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
166 TEST(CodeCompletionTest, DISABLED_SanityClasses) {
167 #else
168 TEST(CodeCompletionTest, SanityClasses) {
169 #endif
170   if (!HostSupportsJit())
171     GTEST_SKIP();
172   auto Interp = createInterpreter();
173   cantFail(Interp->Parse("struct Apple{};"));
174   cantFail(Interp->Parse("void takeApple(Apple &a1){}"));
175   cantFail(Interp->Parse("Apple a1;"));
176   cantFail(Interp->Parse("void takeAppleCopy(Apple a1){}"));
177 
178   {
179     auto Err = llvm::Error::success();
180     auto comps = runComp(*Interp, "takeApple(", Err);
181     EXPECT_EQ((size_t)1, comps.size());
182     EXPECT_EQ(comps[0], std::string("a1"));
183     EXPECT_EQ((bool)Err, false);
184   }
185   {
186     auto Err = llvm::Error::success();
187     auto comps = runComp(*Interp, std::string("takeAppleCopy("), Err);
188     EXPECT_EQ((size_t)1, comps.size());
189     EXPECT_EQ(comps[0], std::string("a1"));
190     EXPECT_EQ((bool)Err, false);
191   }
192 }
193 
194 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
195 TEST(CodeCompletionTest, DISABLED_SubClassing) {
196 #else
197 TEST(CodeCompletionTest, SubClassing) {
198 #endif
199   if (!HostSupportsJit())
200     GTEST_SKIP();
201   auto Interp = createInterpreter();
202   cantFail(Interp->Parse("struct Fruit {};"));
203   cantFail(Interp->Parse("struct Apple : Fruit{};"));
204   cantFail(Interp->Parse("void takeFruit(Fruit &f){}"));
205   cantFail(Interp->Parse("Apple a1;"));
206   cantFail(Interp->Parse("Fruit f1;"));
207   auto Err = llvm::Error::success();
208   auto comps = runComp(*Interp, std::string("takeFruit("), Err);
209   EXPECT_EQ((size_t)2, comps.size());
210   EXPECT_EQ(comps[0], std::string("a1"));
211   EXPECT_EQ(comps[1], std::string("f1"));
212   EXPECT_EQ((bool)Err, false);
213 }
214 
215 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
216 TEST(CodeCompletionTest, DISABLED_MultipleArguments) {
217 #else
218 TEST(CodeCompletionTest, MultipleArguments) {
219 #endif
220   if (!HostSupportsJit())
221     GTEST_SKIP();
222   auto Interp = createInterpreter();
223   cantFail(Interp->Parse("int foo = 42;"));
224   cantFail(Interp->Parse("char fowl = 'A';"));
225   cantFail(Interp->Parse("void takeTwo(int &a, char b){}"));
226   auto Err = llvm::Error::success();
227   auto comps = runComp(*Interp, std::string("takeTwo(foo,  "), Err);
228   EXPECT_EQ((size_t)1, comps.size());
229   EXPECT_EQ(comps[0], std::string("fowl"));
230   EXPECT_EQ((bool)Err, false);
231 }
232 
233 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
234 TEST(CodeCompletionTest, DISABLED_Methods) {
235 #else
236 TEST(CodeCompletionTest, Methods) {
237 #endif
238   if (!HostSupportsJit())
239     GTEST_SKIP();
240   auto Interp = createInterpreter();
241   cantFail(Interp->Parse(
242       "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
243   cantFail(Interp->Parse("Foo f1;"));
244 
245   auto Err = llvm::Error::success();
246   auto comps = runComp(*Interp, std::string("f1."), Err);
247   EXPECT_EQ((size_t)2, comps.size());
248   EXPECT_EQ(comps[0], std::string("add"));
249   EXPECT_EQ(comps[1], std::string("par"));
250   EXPECT_EQ((bool)Err, false);
251 }
252 
253 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
254 TEST(CodeCompletionTest, DISABLED_MethodsInvocations) {
255 #else
256 TEST(CodeCompletionTest, MethodsInvocations) {
257 #endif
258   if (!HostSupportsJit())
259     GTEST_SKIP();
260   auto Interp = createInterpreter();
261   cantFail(Interp->Parse(
262       "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
263   cantFail(Interp->Parse("Foo f1;"));
264   cantFail(Interp->Parse("int a = 84;"));
265 
266   auto Err = llvm::Error::success();
267   auto comps = runComp(*Interp, std::string("f1.add("), Err);
268   EXPECT_EQ((size_t)1, comps.size());
269   EXPECT_EQ(comps[0], std::string("a"));
270   EXPECT_EQ((bool)Err, false);
271 }
272 
273 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
274 TEST(CodeCompletionTest, DISABLED_NestedInvocations) {
275 #else
276 TEST(CodeCompletionTest, NestedInvocations) {
277 #endif
278   if (!HostSupportsJit())
279     GTEST_SKIP();
280   auto Interp = createInterpreter();
281   cantFail(Interp->Parse(
282       "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
283   cantFail(Interp->Parse("Foo f1;"));
284   cantFail(Interp->Parse("int a = 84;"));
285   cantFail(Interp->Parse("int plus(int a, int b) { return a + b; }"));
286 
287   auto Err = llvm::Error::success();
288   auto comps = runComp(*Interp, std::string("plus(42, f1.add("), Err);
289   EXPECT_EQ((size_t)1, comps.size());
290   EXPECT_EQ(comps[0], std::string("a"));
291   EXPECT_EQ((bool)Err, false);
292 }
293 
294 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
295 TEST(CodeCompletionTest, DISABLED_TemplateFunctions) {
296 #else
297 TEST(CodeCompletionTest, TemplateFunctions) {
298 #endif
299   if (!HostSupportsJit())
300     GTEST_SKIP();
301   auto Interp = createInterpreter();
302   cantFail(
303       Interp->Parse("template <typename T> T id(T a) { return a;} "));
304   cantFail(Interp->Parse("int apple = 84;"));
305   {
306     auto Err = llvm::Error::success();
307     auto comps = runComp(*Interp, std::string("id<int>("), Err);
308     EXPECT_EQ((size_t)1, comps.size());
309     EXPECT_EQ(comps[0], std::string("apple"));
310     EXPECT_EQ((bool)Err, false);
311   }
312 
313   cantFail(Interp->Parse(
314       "template <typename T> T pickFirst(T a, T b) { return a;} "));
315   cantFail(Interp->Parse("char pear = '4';"));
316   {
317     auto Err = llvm::Error::success();
318     auto comps = runComp(*Interp, std::string("pickFirst(apple, "), Err);
319     EXPECT_EQ((size_t)1, comps.size());
320     EXPECT_EQ(comps[0], std::string("apple"));
321     EXPECT_EQ((bool)Err, false);
322   }
323 }
324 
325 } // anonymous namespace
326