xref: /llvm-project/clang/unittests/Interpreter/CodeCompletionTest.cpp (revision 7022a24771c8404f847abb226735a3ae21794426)
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 
14 using namespace clang;
15 namespace {
16 auto CB = clang::IncrementalCompilerBuilder();
17 
18 static std::unique_ptr<Interpreter> createInterpreter() {
19   auto CI = cantFail(CB.CreateCpp());
20   return cantFail(clang::Interpreter::create(std::move(CI)));
21 }
22 
23 static 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(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(MainCI, Input, /* Lines */ 1, Input.size() + 1,
45                   MainInterp.getCompilerInstance(), Results);
46 
47   for (auto Res : Results)
48     if (Res.find(CC.Prefix) == 0)
49       Comps.push_back(Res);
50   return Comps;
51 }
52 
53 TEST(CodeCompletionTest, Sanity) {
54   auto Interp = createInterpreter();
55   cantFail(Interp->Parse("int foo = 12;"));
56   auto Err = llvm::Error::success();
57   auto comps = runComp(*Interp, "f", 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 
64 TEST(CodeCompletionTest, SanityNoneValid) {
65   auto Interp = createInterpreter();
66   cantFail(Interp->Parse("int foo = 12;"));
67   auto Err = llvm::Error::success();
68   auto comps = runComp(*Interp, "babanana", Err);
69   EXPECT_EQ((size_t)0, comps.size()); // foo and float
70   EXPECT_EQ((bool)Err, false);
71 }
72 
73 TEST(CodeCompletionTest, TwoDecls) {
74   auto Interp = createInterpreter();
75   cantFail(Interp->Parse("int application = 12;"));
76   cantFail(Interp->Parse("int apple = 12;"));
77   auto Err = llvm::Error::success();
78   auto comps = runComp(*Interp, "app", Err);
79   EXPECT_EQ((size_t)2, comps.size());
80   EXPECT_EQ((bool)Err, false);
81 }
82 
83 TEST(CodeCompletionTest, CompFunDeclsNoError) {
84   auto Interp = createInterpreter();
85   auto Err = llvm::Error::success();
86   auto comps = runComp(*Interp, "void app(", Err);
87   EXPECT_EQ((bool)Err, false);
88 }
89 
90 TEST(CodeCompletionTest, TypedDirected) {
91   auto Interp = createInterpreter();
92   cantFail(Interp->Parse("int application = 12;"));
93   cantFail(Interp->Parse("char apple = '2';"));
94   cantFail(Interp->Parse("void add(int &SomeInt){}"));
95   {
96     auto Err = llvm::Error::success();
97     auto comps = runComp(*Interp, std::string("add("), Err);
98     EXPECT_EQ((size_t)1, comps.size());
99     EXPECT_EQ((bool)Err, false);
100   }
101 
102   cantFail(Interp->Parse("int banana = 42;"));
103 
104   {
105     auto Err = llvm::Error::success();
106     auto comps = runComp(*Interp, std::string("add("), 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(*Interp, std::string("add(b"), Err);
116     EXPECT_EQ((size_t)1, comps.size());
117     EXPECT_EQ(comps[0], "banana");
118     EXPECT_EQ((bool)Err, false);
119   }
120 }
121 
122 TEST(CodeCompletionTest, SanityClasses) {
123   auto Interp = createInterpreter();
124   cantFail(Interp->Parse("struct Apple{};"));
125   cantFail(Interp->Parse("void takeApple(Apple &a1){}"));
126   cantFail(Interp->Parse("Apple a1;"));
127   cantFail(Interp->Parse("void takeAppleCopy(Apple a1){}"));
128 
129   {
130     auto Err = llvm::Error::success();
131     auto comps = runComp(*Interp, "takeApple(", 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(*Interp, std::string("takeAppleCopy("), 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 
145 TEST(CodeCompletionTest, SubClassing) {
146   auto Interp = createInterpreter();
147   cantFail(Interp->Parse("struct Fruit {};"));
148   cantFail(Interp->Parse("struct Apple : Fruit{};"));
149   cantFail(Interp->Parse("void takeFruit(Fruit &f){}"));
150   cantFail(Interp->Parse("Apple a1;"));
151   cantFail(Interp->Parse("Fruit f1;"));
152   auto Err = llvm::Error::success();
153   auto comps = runComp(*Interp, std::string("takeFruit("), 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 
160 TEST(CodeCompletionTest, MultipleArguments) {
161   auto Interp = createInterpreter();
162   cantFail(Interp->Parse("int foo = 42;"));
163   cantFail(Interp->Parse("char fowl = 'A';"));
164   cantFail(Interp->Parse("void takeTwo(int &a, char b){}"));
165   auto Err = llvm::Error::success();
166   auto comps = runComp(*Interp, std::string("takeTwo(foo,  "), 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 
172 TEST(CodeCompletionTest, Methods) {
173   auto Interp = createInterpreter();
174   cantFail(Interp->Parse(
175       "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
176   cantFail(Interp->Parse("Foo f1;"));
177 
178   auto Err = llvm::Error::success();
179   auto comps = runComp(*Interp, std::string("f1."), 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 
186 TEST(CodeCompletionTest, MethodsInvocations) {
187   auto Interp = createInterpreter();
188   cantFail(Interp->Parse(
189       "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
190   cantFail(Interp->Parse("Foo f1;"));
191   cantFail(Interp->Parse("int a = 84;"));
192 
193   auto Err = llvm::Error::success();
194   auto comps = runComp(*Interp, std::string("f1.add("), 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 
200 TEST(CodeCompletionTest, NestedInvocations) {
201   auto Interp = createInterpreter();
202   cantFail(Interp->Parse(
203       "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
204   cantFail(Interp->Parse("Foo f1;"));
205   cantFail(Interp->Parse("int a = 84;"));
206   cantFail(Interp->Parse("int plus(int a, int b) { return a + b; }"));
207 
208   auto Err = llvm::Error::success();
209   auto comps = runComp(*Interp, std::string("plus(42, f1.add("), 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 
215 TEST(CodeCompletionTest, TemplateFunctions) {
216   auto Interp = createInterpreter();
217   cantFail(
218       Interp->Parse("template <typename T> T id(T a) { return a;} "));
219   cantFail(Interp->Parse("int apple = 84;"));
220   {
221     auto Err = llvm::Error::success();
222     auto comps = runComp(*Interp, std::string("id<int>("), 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(Interp->Parse(
229       "template <typename T> T pickFirst(T a, T b) { return a;} "));
230   cantFail(Interp->Parse("char pear = '4';"));
231   {
232     auto Err = llvm::Error::success();
233     auto comps = runComp(*Interp, std::string("pickFirst(apple, "), 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