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 #ifdef _AIX 54 TEST(CodeCompletionTest, DISABLED_Sanity) { 55 #else 56 TEST(CodeCompletionTest, Sanity) { 57 #endif 58 auto Interp = createInterpreter(); 59 if (auto R = Interp->ParseAndExecute("int foo = 12;")) { 60 consumeError(std::move(R)); 61 return; 62 } 63 auto Err = llvm::Error::success(); 64 auto comps = runComp(*Interp, "f", Err); 65 EXPECT_EQ((size_t)2, comps.size()); // float and foo 66 EXPECT_EQ(comps[0], std::string("float")); 67 EXPECT_EQ(comps[1], std::string("foo")); 68 EXPECT_EQ((bool)Err, false); 69 } 70 71 #ifdef _AIX 72 TEST(CodeCompletionTest, DISABLED_SanityNoneValid) { 73 #else 74 TEST(CodeCompletionTest, SanityNoneValid) { 75 #endif 76 auto Interp = createInterpreter(); 77 if (auto R = Interp->ParseAndExecute("int foo = 12;")) { 78 consumeError(std::move(R)); 79 return; 80 } 81 auto Err = llvm::Error::success(); 82 auto comps = runComp(*Interp, "babanana", Err); 83 EXPECT_EQ((size_t)0, comps.size()); // foo and float 84 EXPECT_EQ((bool)Err, false); 85 } 86 87 #ifdef _AIX 88 TEST(CodeCompletionTest, DISABLED_TwoDecls) { 89 #else 90 TEST(CodeCompletionTest, TwoDecls) { 91 #endif 92 auto Interp = createInterpreter(); 93 if (auto R = Interp->ParseAndExecute("int application = 12;")) { 94 consumeError(std::move(R)); 95 return; 96 } 97 if (auto R = Interp->ParseAndExecute("int apple = 12;")) { 98 consumeError(std::move(R)); 99 return; 100 } 101 auto Err = llvm::Error::success(); 102 auto comps = runComp(*Interp, "app", Err); 103 EXPECT_EQ((size_t)2, comps.size()); 104 EXPECT_EQ((bool)Err, false); 105 } 106 107 TEST(CodeCompletionTest, CompFunDeclsNoError) { 108 auto Interp = createInterpreter(); 109 auto Err = llvm::Error::success(); 110 auto comps = runComp(*Interp, "void app(", Err); 111 EXPECT_EQ((bool)Err, false); 112 } 113 114 TEST(CodeCompletionTest, TypedDirected) { 115 auto Interp = createInterpreter(); 116 if (auto R = Interp->ParseAndExecute("int application = 12;")) { 117 consumeError(std::move(R)); 118 return; 119 } 120 if (auto R = Interp->ParseAndExecute("char apple = '2';")) { 121 consumeError(std::move(R)); 122 return; 123 } 124 if (auto R = Interp->ParseAndExecute("void add(int &SomeInt){}")) { 125 consumeError(std::move(R)); 126 return; 127 } 128 { 129 auto Err = llvm::Error::success(); 130 auto comps = runComp(*Interp, std::string("add("), Err); 131 EXPECT_EQ((size_t)1, comps.size()); 132 EXPECT_EQ((bool)Err, false); 133 } 134 135 if (auto R = Interp->ParseAndExecute("int banana = 42;")) { 136 consumeError(std::move(R)); 137 return; 138 } 139 140 { 141 auto Err = llvm::Error::success(); 142 auto comps = runComp(*Interp, std::string("add("), Err); 143 EXPECT_EQ((size_t)2, comps.size()); 144 EXPECT_EQ(comps[0], "application"); 145 EXPECT_EQ(comps[1], "banana"); 146 EXPECT_EQ((bool)Err, false); 147 } 148 149 { 150 auto Err = llvm::Error::success(); 151 auto comps = runComp(*Interp, std::string("add(b"), Err); 152 EXPECT_EQ((size_t)1, comps.size()); 153 EXPECT_EQ(comps[0], "banana"); 154 EXPECT_EQ((bool)Err, false); 155 } 156 } 157 158 TEST(CodeCompletionTest, SanityClasses) { 159 auto Interp = createInterpreter(); 160 if (auto R = Interp->ParseAndExecute("struct Apple{};")) { 161 consumeError(std::move(R)); 162 return; 163 } 164 if (auto R = Interp->ParseAndExecute("void takeApple(Apple &a1){}")) { 165 consumeError(std::move(R)); 166 return; 167 } 168 if (auto R = Interp->ParseAndExecute("Apple a1;")) { 169 consumeError(std::move(R)); 170 return; 171 } 172 if (auto R = Interp->ParseAndExecute("void takeAppleCopy(Apple a1){}")) { 173 consumeError(std::move(R)); 174 return; 175 } 176 177 { 178 auto Err = llvm::Error::success(); 179 auto comps = runComp(*Interp, "takeApple(", Err); 180 EXPECT_EQ((size_t)1, comps.size()); 181 EXPECT_EQ(comps[0], std::string("a1")); 182 EXPECT_EQ((bool)Err, false); 183 } 184 { 185 auto Err = llvm::Error::success(); 186 auto comps = runComp(*Interp, std::string("takeAppleCopy("), Err); 187 EXPECT_EQ((size_t)1, comps.size()); 188 EXPECT_EQ(comps[0], std::string("a1")); 189 EXPECT_EQ((bool)Err, false); 190 } 191 } 192 193 TEST(CodeCompletionTest, SubClassing) { 194 auto Interp = createInterpreter(); 195 if (auto R = Interp->ParseAndExecute("struct Fruit {};")) { 196 consumeError(std::move(R)); 197 return; 198 } 199 if (auto R = Interp->ParseAndExecute("struct Apple : Fruit{};")) { 200 consumeError(std::move(R)); 201 return; 202 } 203 if (auto R = Interp->ParseAndExecute("void takeFruit(Fruit &f){}")) { 204 consumeError(std::move(R)); 205 return; 206 } 207 if (auto R = Interp->ParseAndExecute("Apple a1;")) { 208 consumeError(std::move(R)); 209 return; 210 } 211 if (auto R = Interp->ParseAndExecute("Fruit f1;")) { 212 consumeError(std::move(R)); 213 return; 214 } 215 auto Err = llvm::Error::success(); 216 auto comps = runComp(*Interp, std::string("takeFruit("), Err); 217 EXPECT_EQ((size_t)2, comps.size()); 218 EXPECT_EQ(comps[0], std::string("a1")); 219 EXPECT_EQ(comps[1], std::string("f1")); 220 EXPECT_EQ((bool)Err, false); 221 } 222 223 TEST(CodeCompletionTest, MultipleArguments) { 224 auto Interp = createInterpreter(); 225 if (auto R = Interp->ParseAndExecute("int foo = 42;")) { 226 consumeError(std::move(R)); 227 return; 228 } 229 if (auto R = Interp->ParseAndExecute("char fowl = 'A';")) { 230 consumeError(std::move(R)); 231 return; 232 } 233 if (auto R = Interp->ParseAndExecute("void takeTwo(int &a, char b){}")) { 234 consumeError(std::move(R)); 235 return; 236 } 237 auto Err = llvm::Error::success(); 238 auto comps = runComp(*Interp, std::string("takeTwo(foo, "), Err); 239 EXPECT_EQ((size_t)1, comps.size()); 240 EXPECT_EQ(comps[0], std::string("fowl")); 241 EXPECT_EQ((bool)Err, false); 242 } 243 244 TEST(CodeCompletionTest, Methods) { 245 auto Interp = createInterpreter(); 246 cantFail(Interp->ParseAndExecute( 247 "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};")); 248 cantFail(Interp->ParseAndExecute("Foo f1;")); 249 250 auto Err = llvm::Error::success(); 251 auto comps = runComp(*Interp, std::string("f1."), Err); 252 EXPECT_EQ((size_t)2, comps.size()); 253 EXPECT_EQ(comps[0], std::string("add")); 254 EXPECT_EQ(comps[1], std::string("par")); 255 EXPECT_EQ((bool)Err, false); 256 } 257 258 TEST(CodeCompletionTest, MethodsInvocations) { 259 auto Interp = createInterpreter(); 260 cantFail(Interp->ParseAndExecute( 261 "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};")); 262 cantFail(Interp->ParseAndExecute("Foo f1;")); 263 cantFail(Interp->ParseAndExecute("int a = 84;")); 264 265 auto Err = llvm::Error::success(); 266 auto comps = runComp(*Interp, std::string("f1.add("), Err); 267 EXPECT_EQ((size_t)1, comps.size()); 268 EXPECT_EQ(comps[0], std::string("a")); 269 EXPECT_EQ((bool)Err, false); 270 } 271 272 TEST(CodeCompletionTest, NestedInvocations) { 273 auto Interp = createInterpreter(); 274 cantFail(Interp->ParseAndExecute( 275 "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};")); 276 cantFail(Interp->ParseAndExecute("Foo f1;")); 277 cantFail(Interp->ParseAndExecute("int a = 84;")); 278 cantFail(Interp->ParseAndExecute("int plus(int a, int b) { return a + b; }")); 279 280 auto Err = llvm::Error::success(); 281 auto comps = runComp(*Interp, std::string("plus(42, f1.add("), Err); 282 EXPECT_EQ((size_t)1, comps.size()); 283 EXPECT_EQ(comps[0], std::string("a")); 284 EXPECT_EQ((bool)Err, false); 285 } 286 287 TEST(CodeCompletionTest, TemplateFunctions) { 288 auto Interp = createInterpreter(); 289 cantFail( 290 Interp->ParseAndExecute("template <typename T> T id(T a) { return a;} ")); 291 cantFail(Interp->ParseAndExecute("int apple = 84;")); 292 { 293 auto Err = llvm::Error::success(); 294 auto comps = runComp(*Interp, std::string("id<int>("), Err); 295 EXPECT_EQ((size_t)1, comps.size()); 296 EXPECT_EQ(comps[0], std::string("apple")); 297 EXPECT_EQ((bool)Err, false); 298 } 299 300 cantFail(Interp->ParseAndExecute( 301 "template <typename T> T pickFirst(T a, T b) { return a;} ")); 302 cantFail(Interp->ParseAndExecute("char pear = '4';")); 303 { 304 auto Err = llvm::Error::success(); 305 auto comps = runComp(*Interp, std::string("pickFirst(apple, "), Err); 306 EXPECT_EQ((size_t)1, comps.size()); 307 EXPECT_EQ(comps[0], std::string("apple")); 308 EXPECT_EQ((bool)Err, false); 309 } 310 } 311 312 } // anonymous namespace 313