1a871470aSStefan Gränitz //===- unittests/Interpreter/CodeCompletionTest.cpp -----------------------===// 2a871470aSStefan Gränitz // 3a871470aSStefan Gränitz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a871470aSStefan Gränitz // See https://llvm.org/LICENSE.txt for license information. 5a871470aSStefan Gränitz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a871470aSStefan Gränitz // 7a871470aSStefan Gränitz //===----------------------------------------------------------------------===// 8a871470aSStefan Gränitz 9a871470aSStefan Gränitz #include "InterpreterTestFixture.h" 10a871470aSStefan Gränitz 1179af92bbSFred Fu #include "clang/Interpreter/CodeCompletion.h" 1279af92bbSFred Fu #include "clang/Frontend/CompilerInstance.h" 1379af92bbSFred Fu #include "clang/Interpreter/Interpreter.h" 1435b366acSFred Fu #include "clang/Lex/Preprocessor.h" 1579af92bbSFred Fu #include "clang/Sema/CodeCompleteConsumer.h" 1635b366acSFred Fu #include "clang/Sema/Sema.h" 1779af92bbSFred Fu #include "llvm/LineEditor/LineEditor.h" 1879af92bbSFred Fu #include "llvm/Support/raw_ostream.h" 1979af92bbSFred Fu 2079af92bbSFred Fu #include "gmock/gmock.h" 2179af92bbSFred Fu #include "gtest/gtest.h" 2279af92bbSFred Fu 2379af92bbSFred Fu using namespace clang; 2479af92bbSFred Fu namespace { 2579af92bbSFred Fu auto CB = clang::IncrementalCompilerBuilder(); 2679af92bbSFred Fu 27a871470aSStefan Gränitz class CodeCompletionTest : public InterpreterTestBase { 28a871470aSStefan Gränitz public: 29*a72d7eeaSVassil Vassilev std::unique_ptr<clang::Interpreter> Interp; 3079af92bbSFred Fu 31647d2728SStefan Gränitz void SetUp() override { 32647d2728SStefan Gränitz if (!HostSupportsJIT()) 33647d2728SStefan Gränitz GTEST_SKIP(); 34647d2728SStefan Gränitz std::unique_ptr<CompilerInstance> CI = cantFail(CB.CreateCpp()); 35647d2728SStefan Gränitz this->Interp = cantFail(clang::Interpreter::create(std::move(CI))); 36647d2728SStefan Gränitz } 37a871470aSStefan Gränitz 38a871470aSStefan Gränitz std::vector<std::string> runComp(llvm::StringRef Input, llvm::Error &ErrR) { 39a871470aSStefan Gränitz auto ComplCI = CB.CreateCpp(); 40a871470aSStefan Gränitz if (auto Err = ComplCI.takeError()) { 4179af92bbSFred Fu ErrR = std::move(Err); 4279af92bbSFred Fu return {}; 4379af92bbSFred Fu } 4479af92bbSFred Fu 45a871470aSStefan Gränitz auto ComplInterp = clang::Interpreter::create(std::move(*ComplCI)); 46a871470aSStefan Gränitz if (auto Err = ComplInterp.takeError()) { 4779af92bbSFred Fu ErrR = std::move(Err); 4879af92bbSFred Fu return {}; 4979af92bbSFred Fu } 5079af92bbSFred Fu 5179af92bbSFred Fu std::vector<std::string> Results; 5279af92bbSFred Fu std::vector<std::string> Comps; 53a871470aSStefan Gränitz auto *ParentCI = this->Interp->getCompilerInstance(); 54a871470aSStefan Gränitz auto *MainCI = (*ComplInterp)->getCompilerInstance(); 5535b366acSFred Fu auto CC = ReplCodeCompleter(); 56a871470aSStefan Gränitz CC.codeComplete(MainCI, Input, /* Lines */ 1, Input.size() + 1, ParentCI, 57a871470aSStefan Gränitz Results); 5879af92bbSFred Fu 5979af92bbSFred Fu for (auto Res : Results) 6035b366acSFred Fu if (Res.find(CC.Prefix) == 0) 6179af92bbSFred Fu Comps.push_back(Res); 6279af92bbSFred Fu return Comps; 6379af92bbSFred Fu } 64a871470aSStefan Gränitz }; 6579af92bbSFred Fu 66a871470aSStefan Gränitz TEST_F(CodeCompletionTest, Sanity) { 677022a247SVladimir Vereschaka cantFail(Interp->Parse("int foo = 12;")); 6879af92bbSFred Fu auto Err = llvm::Error::success(); 69a871470aSStefan Gränitz auto comps = runComp("f", Err); 7035b366acSFred Fu EXPECT_EQ((size_t)2, comps.size()); // float and foo 7135b366acSFred Fu EXPECT_EQ(comps[0], std::string("float")); 7235b366acSFred Fu EXPECT_EQ(comps[1], std::string("foo")); 7379af92bbSFred Fu EXPECT_EQ((bool)Err, false); 7479af92bbSFred Fu } 7579af92bbSFred Fu 76a871470aSStefan Gränitz TEST_F(CodeCompletionTest, SanityNoneValid) { 777022a247SVladimir Vereschaka cantFail(Interp->Parse("int foo = 12;")); 7879af92bbSFred Fu auto Err = llvm::Error::success(); 79a871470aSStefan Gränitz auto comps = runComp("babanana", Err); 8079af92bbSFred Fu EXPECT_EQ((size_t)0, comps.size()); // foo and float 8179af92bbSFred Fu EXPECT_EQ((bool)Err, false); 8279af92bbSFred Fu } 8379af92bbSFred Fu 84a871470aSStefan Gränitz TEST_F(CodeCompletionTest, TwoDecls) { 857022a247SVladimir Vereschaka cantFail(Interp->Parse("int application = 12;")); 867022a247SVladimir Vereschaka cantFail(Interp->Parse("int apple = 12;")); 8779af92bbSFred Fu auto Err = llvm::Error::success(); 88a871470aSStefan Gränitz auto comps = runComp("app", Err); 8979af92bbSFred Fu EXPECT_EQ((size_t)2, comps.size()); 9079af92bbSFred Fu EXPECT_EQ((bool)Err, false); 9179af92bbSFred Fu } 9279af92bbSFred Fu 93a871470aSStefan Gränitz TEST_F(CodeCompletionTest, CompFunDeclsNoError) { 9479af92bbSFred Fu auto Err = llvm::Error::success(); 95a871470aSStefan Gränitz auto comps = runComp("void app(", Err); 9679af92bbSFred Fu EXPECT_EQ((bool)Err, false); 9779af92bbSFred Fu } 9879af92bbSFred Fu 99a871470aSStefan Gränitz TEST_F(CodeCompletionTest, TypedDirected) { 1007022a247SVladimir Vereschaka cantFail(Interp->Parse("int application = 12;")); 1017022a247SVladimir Vereschaka cantFail(Interp->Parse("char apple = '2';")); 1027022a247SVladimir Vereschaka cantFail(Interp->Parse("void add(int &SomeInt){}")); 10335b366acSFred Fu { 10435b366acSFred Fu auto Err = llvm::Error::success(); 105a871470aSStefan Gränitz auto comps = runComp(std::string("add("), Err); 10635b366acSFred Fu EXPECT_EQ((size_t)1, comps.size()); 10735b366acSFred Fu EXPECT_EQ((bool)Err, false); 10835b366acSFred Fu } 10935b366acSFred Fu 1107022a247SVladimir Vereschaka cantFail(Interp->Parse("int banana = 42;")); 11135b366acSFred Fu 11235b366acSFred Fu { 11335b366acSFred Fu auto Err = llvm::Error::success(); 114a871470aSStefan Gränitz auto comps = runComp(std::string("add("), Err); 11535b366acSFred Fu EXPECT_EQ((size_t)2, comps.size()); 11635b366acSFred Fu EXPECT_EQ(comps[0], "application"); 11735b366acSFred Fu EXPECT_EQ(comps[1], "banana"); 11835b366acSFred Fu EXPECT_EQ((bool)Err, false); 11935b366acSFred Fu } 12035b366acSFred Fu 12135b366acSFred Fu { 12235b366acSFred Fu auto Err = llvm::Error::success(); 123a871470aSStefan Gränitz auto comps = runComp(std::string("add(b"), Err); 12435b366acSFred Fu EXPECT_EQ((size_t)1, comps.size()); 12535b366acSFred Fu EXPECT_EQ(comps[0], "banana"); 12635b366acSFred Fu EXPECT_EQ((bool)Err, false); 12735b366acSFred Fu } 12835b366acSFred Fu } 12935b366acSFred Fu 130a871470aSStefan Gränitz TEST_F(CodeCompletionTest, SanityClasses) { 1317022a247SVladimir Vereschaka cantFail(Interp->Parse("struct Apple{};")); 1327022a247SVladimir Vereschaka cantFail(Interp->Parse("void takeApple(Apple &a1){}")); 1337022a247SVladimir Vereschaka cantFail(Interp->Parse("Apple a1;")); 1347022a247SVladimir Vereschaka cantFail(Interp->Parse("void takeAppleCopy(Apple a1){}")); 13535b366acSFred Fu 13635b366acSFred Fu { 13735b366acSFred Fu auto Err = llvm::Error::success(); 138a871470aSStefan Gränitz auto comps = runComp("takeApple(", Err); 13935b366acSFred Fu EXPECT_EQ((size_t)1, comps.size()); 14035b366acSFred Fu EXPECT_EQ(comps[0], std::string("a1")); 14135b366acSFred Fu EXPECT_EQ((bool)Err, false); 14235b366acSFred Fu } 14335b366acSFred Fu { 14435b366acSFred Fu auto Err = llvm::Error::success(); 145a871470aSStefan Gränitz auto comps = runComp(std::string("takeAppleCopy("), Err); 14635b366acSFred Fu EXPECT_EQ((size_t)1, comps.size()); 14735b366acSFred Fu EXPECT_EQ(comps[0], std::string("a1")); 14835b366acSFred Fu EXPECT_EQ((bool)Err, false); 14935b366acSFred Fu } 15035b366acSFred Fu } 15135b366acSFred Fu 152a871470aSStefan Gränitz TEST_F(CodeCompletionTest, SubClassing) { 1537022a247SVladimir Vereschaka cantFail(Interp->Parse("struct Fruit {};")); 1547022a247SVladimir Vereschaka cantFail(Interp->Parse("struct Apple : Fruit{};")); 1557022a247SVladimir Vereschaka cantFail(Interp->Parse("void takeFruit(Fruit &f){}")); 1567022a247SVladimir Vereschaka cantFail(Interp->Parse("Apple a1;")); 1577022a247SVladimir Vereschaka cantFail(Interp->Parse("Fruit f1;")); 15835b366acSFred Fu auto Err = llvm::Error::success(); 159a871470aSStefan Gränitz auto comps = runComp(std::string("takeFruit("), Err); 16035b366acSFred Fu EXPECT_EQ((size_t)2, comps.size()); 16135b366acSFred Fu EXPECT_EQ(comps[0], std::string("a1")); 16235b366acSFred Fu EXPECT_EQ(comps[1], std::string("f1")); 16335b366acSFred Fu EXPECT_EQ((bool)Err, false); 16435b366acSFred Fu } 16535b366acSFred Fu 166a871470aSStefan Gränitz TEST_F(CodeCompletionTest, MultipleArguments) { 1677022a247SVladimir Vereschaka cantFail(Interp->Parse("int foo = 42;")); 1687022a247SVladimir Vereschaka cantFail(Interp->Parse("char fowl = 'A';")); 1697022a247SVladimir Vereschaka cantFail(Interp->Parse("void takeTwo(int &a, char b){}")); 17035b366acSFred Fu auto Err = llvm::Error::success(); 171a871470aSStefan Gränitz auto comps = runComp(std::string("takeTwo(foo, "), Err); 17235b366acSFred Fu EXPECT_EQ((size_t)1, comps.size()); 17335b366acSFred Fu EXPECT_EQ(comps[0], std::string("fowl")); 17435b366acSFred Fu EXPECT_EQ((bool)Err, false); 17535b366acSFred Fu } 17635b366acSFred Fu 177a871470aSStefan Gränitz TEST_F(CodeCompletionTest, Methods) { 1787022a247SVladimir Vereschaka cantFail(Interp->Parse( 17935b366acSFred Fu "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};")); 1807022a247SVladimir Vereschaka cantFail(Interp->Parse("Foo f1;")); 18135b366acSFred Fu 18235b366acSFred Fu auto Err = llvm::Error::success(); 183a871470aSStefan Gränitz auto comps = runComp(std::string("f1."), Err); 18435b366acSFred Fu EXPECT_EQ((size_t)2, comps.size()); 18535b366acSFred Fu EXPECT_EQ(comps[0], std::string("add")); 18635b366acSFred Fu EXPECT_EQ(comps[1], std::string("par")); 18735b366acSFred Fu EXPECT_EQ((bool)Err, false); 18835b366acSFred Fu } 18935b366acSFred Fu 190a871470aSStefan Gränitz TEST_F(CodeCompletionTest, MethodsInvocations) { 1917022a247SVladimir Vereschaka cantFail(Interp->Parse( 19235b366acSFred Fu "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};")); 1937022a247SVladimir Vereschaka cantFail(Interp->Parse("Foo f1;")); 1947022a247SVladimir Vereschaka cantFail(Interp->Parse("int a = 84;")); 19535b366acSFred Fu 19635b366acSFred Fu auto Err = llvm::Error::success(); 197a871470aSStefan Gränitz auto comps = runComp(std::string("f1.add("), Err); 19835b366acSFred Fu EXPECT_EQ((size_t)1, comps.size()); 19935b366acSFred Fu EXPECT_EQ(comps[0], std::string("a")); 20035b366acSFred Fu EXPECT_EQ((bool)Err, false); 20135b366acSFred Fu } 20235b366acSFred Fu 203a871470aSStefan Gränitz TEST_F(CodeCompletionTest, NestedInvocations) { 2047022a247SVladimir Vereschaka cantFail(Interp->Parse( 20535b366acSFred Fu "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};")); 2067022a247SVladimir Vereschaka cantFail(Interp->Parse("Foo f1;")); 2077022a247SVladimir Vereschaka cantFail(Interp->Parse("int a = 84;")); 2087022a247SVladimir Vereschaka cantFail(Interp->Parse("int plus(int a, int b) { return a + b; }")); 20935b366acSFred Fu 21035b366acSFred Fu auto Err = llvm::Error::success(); 211a871470aSStefan Gränitz auto comps = runComp(std::string("plus(42, f1.add("), Err); 21235b366acSFred Fu EXPECT_EQ((size_t)1, comps.size()); 21335b366acSFred Fu EXPECT_EQ(comps[0], std::string("a")); 21435b366acSFred Fu EXPECT_EQ((bool)Err, false); 21535b366acSFred Fu } 21635b366acSFred Fu 217a871470aSStefan Gränitz TEST_F(CodeCompletionTest, TemplateFunctions) { 21835b366acSFred Fu cantFail( 2197022a247SVladimir Vereschaka Interp->Parse("template <typename T> T id(T a) { return a;} ")); 2207022a247SVladimir Vereschaka cantFail(Interp->Parse("int apple = 84;")); 22135b366acSFred Fu { 22235b366acSFred Fu auto Err = llvm::Error::success(); 223a871470aSStefan Gränitz auto comps = runComp(std::string("id<int>("), Err); 22435b366acSFred Fu EXPECT_EQ((size_t)1, comps.size()); 22535b366acSFred Fu EXPECT_EQ(comps[0], std::string("apple")); 22635b366acSFred Fu EXPECT_EQ((bool)Err, false); 22735b366acSFred Fu } 22835b366acSFred Fu 2297022a247SVladimir Vereschaka cantFail(Interp->Parse( 23035b366acSFred Fu "template <typename T> T pickFirst(T a, T b) { return a;} ")); 2317022a247SVladimir Vereschaka cantFail(Interp->Parse("char pear = '4';")); 23235b366acSFred Fu { 23335b366acSFred Fu auto Err = llvm::Error::success(); 234a871470aSStefan Gränitz auto comps = runComp(std::string("pickFirst(apple, "), Err); 23535b366acSFred Fu EXPECT_EQ((size_t)1, comps.size()); 23635b366acSFred Fu EXPECT_EQ(comps[0], std::string("apple")); 23735b366acSFred Fu EXPECT_EQ((bool)Err, false); 23835b366acSFred Fu } 23935b366acSFred Fu } 24035b366acSFred Fu 24179af92bbSFred Fu } // anonymous namespace 242