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