xref: /llvm-project/clang/unittests/Interpreter/CodeCompletionTest.cpp (revision a72d7eea5413444249670579fecea6823fb3c564)
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