1 //===- unittests/Interpreter/CodeCompletionTest.cpp -----------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "InterpreterTestFixture.h"
11 #include "clang/Interpreter/CodeCompletion.h"
12 #include "clang/Frontend/CompilerInstance.h"
13 #include "clang/Interpreter/Interpreter.h"
14 #include "clang/Lex/Preprocessor.h"
15 #include "clang/Sema/CodeCompleteConsumer.h"
16 #include "clang/Sema/Sema.h"
17 #include "llvm/LineEditor/LineEditor.h"
18 #include "llvm/Support/raw_ostream.h"
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
23 using namespace clang
;
25 auto CB
= clang::IncrementalCompilerBuilder();
27 class CodeCompletionTest
: public InterpreterTestBase
{
29 std::unique_ptr
<clang::Interpreter
> Interp
;
31 void SetUp() override
{
32 if (!HostSupportsJIT())
34 std::unique_ptr
<CompilerInstance
> CI
= cantFail(CB
.CreateCpp());
35 this->Interp
= cantFail(clang::Interpreter::create(std::move(CI
)));
38 std::vector
<std::string
> runComp(llvm::StringRef Input
, llvm::Error
&ErrR
) {
39 auto ComplCI
= CB
.CreateCpp();
40 if (auto Err
= ComplCI
.takeError()) {
41 ErrR
= std::move(Err
);
45 auto ComplInterp
= clang::Interpreter::create(std::move(*ComplCI
));
46 if (auto Err
= ComplInterp
.takeError()) {
47 ErrR
= std::move(Err
);
51 std::vector
<std::string
> Results
;
52 std::vector
<std::string
> Comps
;
53 auto *ParentCI
= this->Interp
->getCompilerInstance();
54 auto *MainCI
= (*ComplInterp
)->getCompilerInstance();
55 auto CC
= ReplCodeCompleter();
56 CC
.codeComplete(MainCI
, Input
, /* Lines */ 1, Input
.size() + 1, ParentCI
,
59 for (auto Res
: Results
)
60 if (Res
.find(CC
.Prefix
) == 0)
66 TEST_F(CodeCompletionTest
, Sanity
) {
67 cantFail(Interp
->Parse("int foo = 12;"));
68 auto Err
= llvm::Error::success();
69 auto comps
= runComp("f", Err
);
70 EXPECT_EQ((size_t)2, comps
.size()); // float and foo
71 EXPECT_EQ(comps
[0], std::string("float"));
72 EXPECT_EQ(comps
[1], std::string("foo"));
73 EXPECT_EQ((bool)Err
, false);
76 TEST_F(CodeCompletionTest
, SanityNoneValid
) {
77 cantFail(Interp
->Parse("int foo = 12;"));
78 auto Err
= llvm::Error::success();
79 auto comps
= runComp("babanana", Err
);
80 EXPECT_EQ((size_t)0, comps
.size()); // foo and float
81 EXPECT_EQ((bool)Err
, false);
84 TEST_F(CodeCompletionTest
, TwoDecls
) {
85 cantFail(Interp
->Parse("int application = 12;"));
86 cantFail(Interp
->Parse("int apple = 12;"));
87 auto Err
= llvm::Error::success();
88 auto comps
= runComp("app", Err
);
89 EXPECT_EQ((size_t)2, comps
.size());
90 EXPECT_EQ((bool)Err
, false);
93 TEST_F(CodeCompletionTest
, CompFunDeclsNoError
) {
94 auto Err
= llvm::Error::success();
95 auto comps
= runComp("void app(", Err
);
96 EXPECT_EQ((bool)Err
, false);
99 TEST_F(CodeCompletionTest
, TypedDirected
) {
100 cantFail(Interp
->Parse("int application = 12;"));
101 cantFail(Interp
->Parse("char apple = '2';"));
102 cantFail(Interp
->Parse("void add(int &SomeInt){}"));
104 auto Err
= llvm::Error::success();
105 auto comps
= runComp(std::string("add("), Err
);
106 EXPECT_EQ((size_t)1, comps
.size());
107 EXPECT_EQ((bool)Err
, false);
110 cantFail(Interp
->Parse("int banana = 42;"));
113 auto Err
= llvm::Error::success();
114 auto comps
= runComp(std::string("add("), Err
);
115 EXPECT_EQ((size_t)2, comps
.size());
116 EXPECT_EQ(comps
[0], "application");
117 EXPECT_EQ(comps
[1], "banana");
118 EXPECT_EQ((bool)Err
, false);
122 auto Err
= llvm::Error::success();
123 auto comps
= runComp(std::string("add(b"), Err
);
124 EXPECT_EQ((size_t)1, comps
.size());
125 EXPECT_EQ(comps
[0], "banana");
126 EXPECT_EQ((bool)Err
, false);
130 TEST_F(CodeCompletionTest
, SanityClasses
) {
131 cantFail(Interp
->Parse("struct Apple{};"));
132 cantFail(Interp
->Parse("void takeApple(Apple &a1){}"));
133 cantFail(Interp
->Parse("Apple a1;"));
134 cantFail(Interp
->Parse("void takeAppleCopy(Apple a1){}"));
137 auto Err
= llvm::Error::success();
138 auto comps
= runComp("takeApple(", Err
);
139 EXPECT_EQ((size_t)1, comps
.size());
140 EXPECT_EQ(comps
[0], std::string("a1"));
141 EXPECT_EQ((bool)Err
, false);
144 auto Err
= llvm::Error::success();
145 auto comps
= runComp(std::string("takeAppleCopy("), Err
);
146 EXPECT_EQ((size_t)1, comps
.size());
147 EXPECT_EQ(comps
[0], std::string("a1"));
148 EXPECT_EQ((bool)Err
, false);
152 TEST_F(CodeCompletionTest
, SubClassing
) {
153 cantFail(Interp
->Parse("struct Fruit {};"));
154 cantFail(Interp
->Parse("struct Apple : Fruit{};"));
155 cantFail(Interp
->Parse("void takeFruit(Fruit &f){}"));
156 cantFail(Interp
->Parse("Apple a1;"));
157 cantFail(Interp
->Parse("Fruit f1;"));
158 auto Err
= llvm::Error::success();
159 auto comps
= runComp(std::string("takeFruit("), Err
);
160 EXPECT_EQ((size_t)2, comps
.size());
161 EXPECT_EQ(comps
[0], std::string("a1"));
162 EXPECT_EQ(comps
[1], std::string("f1"));
163 EXPECT_EQ((bool)Err
, false);
166 TEST_F(CodeCompletionTest
, MultipleArguments
) {
167 cantFail(Interp
->Parse("int foo = 42;"));
168 cantFail(Interp
->Parse("char fowl = 'A';"));
169 cantFail(Interp
->Parse("void takeTwo(int &a, char b){}"));
170 auto Err
= llvm::Error::success();
171 auto comps
= runComp(std::string("takeTwo(foo, "), Err
);
172 EXPECT_EQ((size_t)1, comps
.size());
173 EXPECT_EQ(comps
[0], std::string("fowl"));
174 EXPECT_EQ((bool)Err
, false);
177 TEST_F(CodeCompletionTest
, Methods
) {
178 cantFail(Interp
->Parse(
179 "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
180 cantFail(Interp
->Parse("Foo f1;"));
182 auto Err
= llvm::Error::success();
183 auto comps
= runComp(std::string("f1."), Err
);
184 EXPECT_EQ((size_t)2, comps
.size());
185 EXPECT_EQ(comps
[0], std::string("add"));
186 EXPECT_EQ(comps
[1], std::string("par"));
187 EXPECT_EQ((bool)Err
, false);
190 TEST_F(CodeCompletionTest
, MethodsInvocations
) {
191 cantFail(Interp
->Parse(
192 "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
193 cantFail(Interp
->Parse("Foo f1;"));
194 cantFail(Interp
->Parse("int a = 84;"));
196 auto Err
= llvm::Error::success();
197 auto comps
= runComp(std::string("f1.add("), Err
);
198 EXPECT_EQ((size_t)1, comps
.size());
199 EXPECT_EQ(comps
[0], std::string("a"));
200 EXPECT_EQ((bool)Err
, false);
203 TEST_F(CodeCompletionTest
, NestedInvocations
) {
204 cantFail(Interp
->Parse(
205 "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
206 cantFail(Interp
->Parse("Foo f1;"));
207 cantFail(Interp
->Parse("int a = 84;"));
208 cantFail(Interp
->Parse("int plus(int a, int b) { return a + b; }"));
210 auto Err
= llvm::Error::success();
211 auto comps
= runComp(std::string("plus(42, f1.add("), Err
);
212 EXPECT_EQ((size_t)1, comps
.size());
213 EXPECT_EQ(comps
[0], std::string("a"));
214 EXPECT_EQ((bool)Err
, false);
217 TEST_F(CodeCompletionTest
, TemplateFunctions
) {
219 Interp
->Parse("template <typename T> T id(T a) { return a;} "));
220 cantFail(Interp
->Parse("int apple = 84;"));
222 auto Err
= llvm::Error::success();
223 auto comps
= runComp(std::string("id<int>("), Err
);
224 EXPECT_EQ((size_t)1, comps
.size());
225 EXPECT_EQ(comps
[0], std::string("apple"));
226 EXPECT_EQ((bool)Err
, false);
229 cantFail(Interp
->Parse(
230 "template <typename T> T pickFirst(T a, T b) { return a;} "));
231 cantFail(Interp
->Parse("char pear = '4';"));
233 auto Err
= llvm::Error::success();
234 auto comps
= runComp(std::string("pickFirst(apple, "), Err
);
235 EXPECT_EQ((size_t)1, comps
.size());
236 EXPECT_EQ(comps
[0], std::string("apple"));
237 EXPECT_EQ((bool)Err
, false);
241 } // anonymous namespace