1//===- unittests/Interpreter/CodeCompletionTest.cpp -----------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include "InterpreterTestFixture.h"
10
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"
19
20#include "gmock/gmock.h"
21#include "gtest/gtest.h"
22
23using namespace clang;
24namespace {
25auto CB = clang::IncrementalCompilerBuilder();
26
27class CodeCompletionTest : public InterpreterTestBase {
28public:
29 std::unique_ptr<clang::Interpreter> Interp;
30
31 void SetUp() override {
32 if (!HostSupportsJIT())
33 GTEST_SKIP();
34 std::unique_ptr<CompilerInstance> CI = cantFail(ValOrErr: CB.CreateCpp());
35 this->Interp = cantFail(ValOrErr: clang::Interpreter::create(CI: std::move(CI)));
36 }
37
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);
42 return {};
43 }
44
45 auto ComplInterp = clang::Interpreter::create(CI: std::move(*ComplCI));
46 if (auto Err = ComplInterp.takeError()) {
47 ErrR = std::move(Err);
48 return {};
49 }
50
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(InterpCI: MainCI, Content: Input, /* Lines */ Line: 1, Col: Input.size() + 1, ParentCI,
57 CCResults&: Results);
58
59 for (auto Res : Results)
60 if (Res.find(str: CC.Prefix) == 0)
61 Comps.push_back(x: Res);
62 return Comps;
63 }
64};
65
66TEST_F(CodeCompletionTest, Sanity) {
67 cantFail(ValOrErr: Interp->Parse(Code: "int foo = 12;"));
68 auto Err = llvm::Error::success();
69 auto comps = runComp(Input: "f", ErrR&: 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);
74}
75
76TEST_F(CodeCompletionTest, SanityNoneValid) {
77 cantFail(ValOrErr: Interp->Parse(Code: "int foo = 12;"));
78 auto Err = llvm::Error::success();
79 auto comps = runComp(Input: "babanana", ErrR&: Err);
80 EXPECT_EQ((size_t)0, comps.size()); // foo and float
81 EXPECT_EQ((bool)Err, false);
82}
83
84TEST_F(CodeCompletionTest, TwoDecls) {
85 cantFail(ValOrErr: Interp->Parse(Code: "int application = 12;"));
86 cantFail(ValOrErr: Interp->Parse(Code: "int apple = 12;"));
87 auto Err = llvm::Error::success();
88 auto comps = runComp(Input: "app", ErrR&: Err);
89 EXPECT_EQ((size_t)2, comps.size());
90 EXPECT_EQ((bool)Err, false);
91}
92
93TEST_F(CodeCompletionTest, CompFunDeclsNoError) {
94 auto Err = llvm::Error::success();
95 auto comps = runComp(Input: "void app(", ErrR&: Err);
96 EXPECT_EQ((bool)Err, false);
97}
98
99TEST_F(CodeCompletionTest, TypedDirected) {
100 cantFail(ValOrErr: Interp->Parse(Code: "int application = 12;"));
101 cantFail(ValOrErr: Interp->Parse(Code: "char apple = '2';"));
102 cantFail(ValOrErr: Interp->Parse(Code: "void add(int &SomeInt){}"));
103 {
104 auto Err = llvm::Error::success();
105 auto comps = runComp(Input: std::string("add("), ErrR&: Err);
106 EXPECT_EQ((size_t)1, comps.size());
107 EXPECT_EQ((bool)Err, false);
108 }
109
110 cantFail(ValOrErr: Interp->Parse(Code: "int banana = 42;"));
111
112 {
113 auto Err = llvm::Error::success();
114 auto comps = runComp(Input: std::string("add("), ErrR&: 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);
119 }
120
121 {
122 auto Err = llvm::Error::success();
123 auto comps = runComp(Input: std::string("add(b"), ErrR&: Err);
124 EXPECT_EQ((size_t)1, comps.size());
125 EXPECT_EQ(comps[0], "banana");
126 EXPECT_EQ((bool)Err, false);
127 }
128}
129
130TEST_F(CodeCompletionTest, SanityClasses) {
131 cantFail(ValOrErr: Interp->Parse(Code: "struct Apple{};"));
132 cantFail(ValOrErr: Interp->Parse(Code: "void takeApple(Apple &a1){}"));
133 cantFail(ValOrErr: Interp->Parse(Code: "Apple a1;"));
134 cantFail(ValOrErr: Interp->Parse(Code: "void takeAppleCopy(Apple a1){}"));
135
136 {
137 auto Err = llvm::Error::success();
138 auto comps = runComp(Input: "takeApple(", ErrR&: 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 auto Err = llvm::Error::success();
145 auto comps = runComp(Input: std::string("takeAppleCopy("), ErrR&: Err);
146 EXPECT_EQ((size_t)1, comps.size());
147 EXPECT_EQ(comps[0], std::string("a1"));
148 EXPECT_EQ((bool)Err, false);
149 }
150}
151
152TEST_F(CodeCompletionTest, SubClassing) {
153 cantFail(ValOrErr: Interp->Parse(Code: "struct Fruit {};"));
154 cantFail(ValOrErr: Interp->Parse(Code: "struct Apple : Fruit{};"));
155 cantFail(ValOrErr: Interp->Parse(Code: "void takeFruit(Fruit &f){}"));
156 cantFail(ValOrErr: Interp->Parse(Code: "Apple a1;"));
157 cantFail(ValOrErr: Interp->Parse(Code: "Fruit f1;"));
158 auto Err = llvm::Error::success();
159 auto comps = runComp(Input: std::string("takeFruit("), ErrR&: 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);
164}
165
166TEST_F(CodeCompletionTest, MultipleArguments) {
167 cantFail(ValOrErr: Interp->Parse(Code: "int foo = 42;"));
168 cantFail(ValOrErr: Interp->Parse(Code: "char fowl = 'A';"));
169 cantFail(ValOrErr: Interp->Parse(Code: "void takeTwo(int &a, char b){}"));
170 auto Err = llvm::Error::success();
171 auto comps = runComp(Input: std::string("takeTwo(foo, "), ErrR&: Err);
172 EXPECT_EQ((size_t)1, comps.size());
173 EXPECT_EQ(comps[0], std::string("fowl"));
174 EXPECT_EQ((bool)Err, false);
175}
176
177TEST_F(CodeCompletionTest, Methods) {
178 cantFail(ValOrErr: Interp->Parse(
179 Code: "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
180 cantFail(ValOrErr: Interp->Parse(Code: "Foo f1;"));
181
182 auto Err = llvm::Error::success();
183 auto comps = runComp(Input: std::string("f1."), ErrR&: 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);
188}
189
190TEST_F(CodeCompletionTest, MethodsInvocations) {
191 cantFail(ValOrErr: Interp->Parse(
192 Code: "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
193 cantFail(ValOrErr: Interp->Parse(Code: "Foo f1;"));
194 cantFail(ValOrErr: Interp->Parse(Code: "int a = 84;"));
195
196 auto Err = llvm::Error::success();
197 auto comps = runComp(Input: std::string("f1.add("), ErrR&: Err);
198 EXPECT_EQ((size_t)1, comps.size());
199 EXPECT_EQ(comps[0], std::string("a"));
200 EXPECT_EQ((bool)Err, false);
201}
202
203TEST_F(CodeCompletionTest, NestedInvocations) {
204 cantFail(ValOrErr: Interp->Parse(
205 Code: "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};"));
206 cantFail(ValOrErr: Interp->Parse(Code: "Foo f1;"));
207 cantFail(ValOrErr: Interp->Parse(Code: "int a = 84;"));
208 cantFail(ValOrErr: Interp->Parse(Code: "int plus(int a, int b) { return a + b; }"));
209
210 auto Err = llvm::Error::success();
211 auto comps = runComp(Input: std::string("plus(42, f1.add("), ErrR&: Err);
212 EXPECT_EQ((size_t)1, comps.size());
213 EXPECT_EQ(comps[0], std::string("a"));
214 EXPECT_EQ((bool)Err, false);
215}
216
217TEST_F(CodeCompletionTest, TemplateFunctions) {
218 cantFail(
219 ValOrErr: Interp->Parse(Code: "template <typename T> T id(T a) { return a;} "));
220 cantFail(ValOrErr: Interp->Parse(Code: "int apple = 84;"));
221 {
222 auto Err = llvm::Error::success();
223 auto comps = runComp(Input: std::string("id<int>("), ErrR&: Err);
224 EXPECT_EQ((size_t)1, comps.size());
225 EXPECT_EQ(comps[0], std::string("apple"));
226 EXPECT_EQ((bool)Err, false);
227 }
228
229 cantFail(ValOrErr: Interp->Parse(
230 Code: "template <typename T> T pickFirst(T a, T b) { return a;} "));
231 cantFail(ValOrErr: Interp->Parse(Code: "char pear = '4';"));
232 {
233 auto Err = llvm::Error::success();
234 auto comps = runComp(Input: std::string("pickFirst(apple, "), ErrR&: Err);
235 EXPECT_EQ((size_t)1, comps.size());
236 EXPECT_EQ(comps[0], std::string("apple"));
237 EXPECT_EQ((bool)Err, false);
238 }
239}
240
241} // anonymous namespace
242

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang/unittests/Interpreter/CodeCompletionTest.cpp