blob: 4133f946ff57ea7e3abeee3c239d287d690d4f0e [file] [log] [blame]
Sam McCall9aad25f2017-12-05 07:20:26 +00001//===-- CodeCompleteTests.cpp -----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Eric Liu6f648df2017-12-19 16:50:37 +00009
Sam McCall328cbdb2017-12-20 16:06:05 +000010#include "Annotations.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000011#include "ClangdServer.h"
Sam McCall328cbdb2017-12-20 16:06:05 +000012#include "CodeComplete.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000013#include "Compiler.h"
Ilya Biryukov5a85b8e2017-12-13 12:53:16 +000014#include "Matchers.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000015#include "Protocol.h"
Sam McCallb536a2a2017-12-19 12:23:48 +000016#include "SourceCode.h"
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000017#include "SyncAPI.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000018#include "TestFS.h"
Eric Liu6f648df2017-12-19 16:50:37 +000019#include "index/MemIndex.h"
Sam McCallf6ae3232017-12-05 20:11:29 +000020#include "gmock/gmock.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000021#include "gtest/gtest.h"
22
23namespace clang {
24namespace clangd {
Sam McCallf6ae3232017-12-05 20:11:29 +000025
Sam McCall9aad25f2017-12-05 07:20:26 +000026namespace {
27using namespace llvm;
Sam McCallf6ae3232017-12-05 20:11:29 +000028using ::testing::AllOf;
29using ::testing::Contains;
Ilya Biryukov5a5e1ca2017-12-29 14:59:22 +000030using ::testing::Each;
Sam McCallf6ae3232017-12-05 20:11:29 +000031using ::testing::ElementsAre;
Ilya Biryukov71028b82018-03-12 15:28:22 +000032using ::testing::Field;
Sam McCallf6ae3232017-12-05 20:11:29 +000033using ::testing::Not;
Sam McCall3d139c52018-01-12 18:30:08 +000034using ::testing::UnorderedElementsAre;
Sam McCall9aad25f2017-12-05 07:20:26 +000035
36class IgnoreDiagnostics : public DiagnosticsConsumer {
Ilya Biryukov71028b82018-03-12 15:28:22 +000037 void onDiagnosticsReady(PathRef File,
Sam McCalla7bb0cc2018-03-12 23:22:35 +000038 std::vector<Diag> Diagnostics) override {}
Sam McCall9aad25f2017-12-05 07:20:26 +000039};
40
Sam McCallf6ae3232017-12-05 20:11:29 +000041// GMock helpers for matching completion items.
42MATCHER_P(Named, Name, "") { return arg.insertText == Name; }
Sam McCall44fdcec22017-12-08 15:00:59 +000043MATCHER_P(Labeled, Label, "") { return arg.label == Label; }
44MATCHER_P(Kind, K, "") { return arg.kind == K; }
Eric Liu6f648df2017-12-19 16:50:37 +000045MATCHER_P(Filter, F, "") { return arg.filterText == F; }
Eric Liu76f6b442018-01-09 17:32:00 +000046MATCHER_P(Doc, D, "") { return arg.documentation == D; }
47MATCHER_P(Detail, D, "") { return arg.detail == D; }
Eric Liu63f419a2018-05-15 15:29:32 +000048MATCHER_P(InsertInclude, IncludeHeader, "") {
49 if (arg.additionalTextEdits.size() != 1)
50 return false;
51 const auto &Edit = arg.additionalTextEdits[0];
52 if (Edit.range.start != Edit.range.end)
53 return false;
54 SmallVector<StringRef, 2> Matches;
55 llvm::Regex RE(R"(#include[ ]*(["<][^">]*[">]))");
56 return RE.match(Edit.newText, &Matches) && Matches[1] == IncludeHeader;
57}
Sam McCall44fdcec22017-12-08 15:00:59 +000058MATCHER_P(PlainText, Text, "") {
59 return arg.insertTextFormat == clangd::InsertTextFormat::PlainText &&
60 arg.insertText == Text;
61}
62MATCHER_P(Snippet, Text, "") {
63 return arg.insertTextFormat == clangd::InsertTextFormat::Snippet &&
64 arg.insertText == Text;
65}
Sam McCall545a20d2018-01-19 14:34:02 +000066MATCHER(NameContainsFilter, "") {
Ilya Biryukov5a5e1ca2017-12-29 14:59:22 +000067 if (arg.filterText.empty())
68 return true;
69 return llvm::StringRef(arg.insertText).contains(arg.filterText);
70}
Eric Liu63f419a2018-05-15 15:29:32 +000071MATCHER(HasAdditionalEdits, "") { return !arg.additionalTextEdits.empty(); }
72
Sam McCallf6ae3232017-12-05 20:11:29 +000073// Shorthand for Contains(Named(Name)).
74Matcher<const std::vector<CompletionItem> &> Has(std::string Name) {
75 return Contains(Named(std::move(Name)));
76}
Sam McCall44fdcec22017-12-08 15:00:59 +000077Matcher<const std::vector<CompletionItem> &> Has(std::string Name,
78 CompletionItemKind K) {
79 return Contains(AllOf(Named(std::move(Name)), Kind(K)));
Sam McCallf6ae3232017-12-05 20:11:29 +000080}
Sam McCall44fdcec22017-12-08 15:00:59 +000081MATCHER(IsDocumented, "") { return !arg.documentation.empty(); }
Sam McCall9aad25f2017-12-05 07:20:26 +000082
Sam McCalla15c2d62018-01-18 09:27:56 +000083std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol> Symbols) {
84 SymbolSlab::Builder Slab;
85 for (const auto &Sym : Symbols)
86 Slab.insert(Sym);
87 return MemIndex::build(std::move(Slab).build());
88}
89
Eric Liu63f419a2018-05-15 15:29:32 +000090CompletionList completions(ClangdServer &Server, StringRef Text,
Sam McCalla15c2d62018-01-18 09:27:56 +000091 std::vector<Symbol> IndexSymbols = {},
Sam McCallf6ae3232017-12-05 20:11:29 +000092 clangd::CodeCompleteOptions Opts = {}) {
Sam McCalla15c2d62018-01-18 09:27:56 +000093 std::unique_ptr<SymbolIndex> OverrideIndex;
94 if (!IndexSymbols.empty()) {
95 assert(!Opts.Index && "both Index and IndexSymbols given!");
96 OverrideIndex = memIndex(std::move(IndexSymbols));
97 Opts.Index = OverrideIndex.get();
98 }
99
Sam McCallc1568062018-02-16 09:41:43 +0000100 auto File = testPath("foo.cpp");
Sam McCall328cbdb2017-12-20 16:06:05 +0000101 Annotations Test(Text);
Sam McCall7363a2f2018-03-05 17:28:54 +0000102 runAddDocument(Server, File, Test.code());
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000103 auto CompletionList =
104 cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Ilya Biryukov5a5e1ca2017-12-29 14:59:22 +0000105 // Sanity-check that filterText is valid.
Sam McCall545a20d2018-01-19 14:34:02 +0000106 EXPECT_THAT(CompletionList.items, Each(NameContainsFilter()));
Ilya Biryukov5a5e1ca2017-12-29 14:59:22 +0000107 return CompletionList;
Sam McCall9aad25f2017-12-05 07:20:26 +0000108}
109
Eric Liu63f419a2018-05-15 15:29:32 +0000110// Builds a server and runs code completion.
111// If IndexSymbols is non-empty, an index will be built and passed to opts.
112CompletionList completions(StringRef Text,
113 std::vector<Symbol> IndexSymbols = {},
114 clangd::CodeCompleteOptions Opts = {}) {
115 MockFSProvider FS;
116 MockCompilationDatabase CDB;
117 IgnoreDiagnostics DiagConsumer;
118 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
119 return completions(Server, Text, std::move(IndexSymbols), std::move(Opts));
120}
121
Sam McCall545a20d2018-01-19 14:34:02 +0000122std::string replace(StringRef Haystack, StringRef Needle, StringRef Repl) {
123 std::string Result;
124 raw_string_ostream OS(Result);
125 std::pair<StringRef, StringRef> Split;
126 for (Split = Haystack.split(Needle); !Split.second.empty();
127 Split = Split.first.split(Needle))
128 OS << Split.first << Repl;
129 Result += Split.first;
130 OS.flush();
131 return Result;
132}
133
Sam McCalla15c2d62018-01-18 09:27:56 +0000134// Helpers to produce fake index symbols for memIndex() or completions().
Sam McCall545a20d2018-01-19 14:34:02 +0000135// USRFormat is a regex replacement string for the unqualified part of the USR.
136Symbol sym(StringRef QName, index::SymbolKind Kind, StringRef USRFormat) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000137 Symbol Sym;
Sam McCall545a20d2018-01-19 14:34:02 +0000138 std::string USR = "c:"; // We synthesize a few simple cases of USRs by hand!
Sam McCalla15c2d62018-01-18 09:27:56 +0000139 size_t Pos = QName.rfind("::");
140 if (Pos == llvm::StringRef::npos) {
141 Sym.Name = QName;
142 Sym.Scope = "";
143 } else {
144 Sym.Name = QName.substr(Pos + 2);
Sam McCall8b2faee2018-01-19 22:18:21 +0000145 Sym.Scope = QName.substr(0, Pos + 2);
146 USR += "@N@" + replace(QName.substr(0, Pos), "::", "@N@"); // ns:: -> @N@ns
Sam McCalla15c2d62018-01-18 09:27:56 +0000147 }
Sam McCall545a20d2018-01-19 14:34:02 +0000148 USR += Regex("^.*$").sub(USRFormat, Sym.Name); // e.g. func -> @F@func#
149 Sym.ID = SymbolID(USR);
Sam McCalla15c2d62018-01-18 09:27:56 +0000150 Sym.CompletionPlainInsertText = Sym.Name;
Sam McCall545a20d2018-01-19 14:34:02 +0000151 Sym.CompletionSnippetInsertText = Sym.Name;
Sam McCalla15c2d62018-01-18 09:27:56 +0000152 Sym.CompletionLabel = Sym.Name;
153 Sym.SymInfo.Kind = Kind;
154 return Sym;
155}
Sam McCall545a20d2018-01-19 14:34:02 +0000156Symbol func(StringRef Name) { // Assumes the function has no args.
157 return sym(Name, index::SymbolKind::Function, "@F@\\0#"); // no args
158}
159Symbol cls(StringRef Name) {
160 return sym(Name, index::SymbolKind::Class, "@S@\\0@S@\\0");
161}
162Symbol var(StringRef Name) {
163 return sym(Name, index::SymbolKind::Variable, "@\\0");
164}
Sam McCalldc8abc42018-05-03 14:53:02 +0000165Symbol ns(StringRef Name) {
166 return sym(Name, index::SymbolKind::Namespace, "@N@\\0");
167}
168Symbol withReferences(int N, Symbol S) {
169 S.References = N;
170 return S;
171}
Sam McCalla15c2d62018-01-18 09:27:56 +0000172
Sam McCallf6ae3232017-12-05 20:11:29 +0000173TEST(CompletionTest, Limit) {
174 clangd::CodeCompleteOptions Opts;
175 Opts.Limit = 2;
176 auto Results = completions(R"cpp(
Sam McCall9aad25f2017-12-05 07:20:26 +0000177struct ClassWithMembers {
178 int AAA();
179 int BBB();
180 int CCC();
181}
Sam McCallf6ae3232017-12-05 20:11:29 +0000182int main() { ClassWithMembers().^ }
Sam McCall9aad25f2017-12-05 07:20:26 +0000183 )cpp",
Sam McCalla15c2d62018-01-18 09:27:56 +0000184 /*IndexSymbols=*/{}, Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000185
186 EXPECT_TRUE(Results.isIncomplete);
Sam McCallf6ae3232017-12-05 20:11:29 +0000187 EXPECT_THAT(Results.items, ElementsAre(Named("AAA"), Named("BBB")));
Sam McCall9aad25f2017-12-05 07:20:26 +0000188}
189
Sam McCallf6ae3232017-12-05 20:11:29 +0000190TEST(CompletionTest, Filter) {
191 std::string Body = R"cpp(
Sam McCall9aad25f2017-12-05 07:20:26 +0000192 int Abracadabra;
193 int Alakazam;
194 struct S {
195 int FooBar;
196 int FooBaz;
197 int Qux;
198 };
199 )cpp";
Sam McCallf6ae3232017-12-05 20:11:29 +0000200 EXPECT_THAT(completions(Body + "int main() { S().Foba^ }").items,
201 AllOf(Has("FooBar"), Has("FooBaz"), Not(Has("Qux"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000202
Sam McCallf6ae3232017-12-05 20:11:29 +0000203 EXPECT_THAT(completions(Body + "int main() { S().FR^ }").items,
204 AllOf(Has("FooBar"), Not(Has("FooBaz")), Not(Has("Qux"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000205
Sam McCallf6ae3232017-12-05 20:11:29 +0000206 EXPECT_THAT(completions(Body + "int main() { S().opr^ }").items,
207 Has("operator="));
Sam McCall9aad25f2017-12-05 07:20:26 +0000208
Sam McCallf6ae3232017-12-05 20:11:29 +0000209 EXPECT_THAT(completions(Body + "int main() { aaa^ }").items,
210 AllOf(Has("Abracadabra"), Has("Alakazam")));
Sam McCall9aad25f2017-12-05 07:20:26 +0000211
Sam McCallf6ae3232017-12-05 20:11:29 +0000212 EXPECT_THAT(completions(Body + "int main() { _a^ }").items,
213 AllOf(Has("static_cast"), Not(Has("Abracadabra"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000214}
215
Sam McCallf6ae3232017-12-05 20:11:29 +0000216void TestAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000217 auto Results = completions(
218 R"cpp(
219 #define MACRO X
Sam McCall9aad25f2017-12-05 07:20:26 +0000220
Sam McCall44fdcec22017-12-08 15:00:59 +0000221 int global_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000222
Sam McCall44fdcec22017-12-08 15:00:59 +0000223 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000224
Sam McCall44fdcec22017-12-08 15:00:59 +0000225 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000226
Sam McCall44fdcec22017-12-08 15:00:59 +0000227 struct ClassWithMembers {
228 /// Doc for method.
229 int method();
Sam McCall9aad25f2017-12-05 07:20:26 +0000230
Sam McCall44fdcec22017-12-08 15:00:59 +0000231 int field;
232 private:
233 int private_field;
234 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000235
Sam McCall44fdcec22017-12-08 15:00:59 +0000236 int test() {
237 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000238
Sam McCall44fdcec22017-12-08 15:00:59 +0000239 /// Doc for local_var.
240 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000241
Sam McCall44fdcec22017-12-08 15:00:59 +0000242 ClassWithMembers().^
243 }
244 )cpp",
Sam McCall545a20d2018-01-19 14:34:02 +0000245 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000246
Sam McCallf6ae3232017-12-05 20:11:29 +0000247 // Class members. The only items that must be present in after-dot
248 // completion.
Sam McCall44fdcec22017-12-08 15:00:59 +0000249 EXPECT_THAT(
250 Results.items,
251 AllOf(Has(Opts.EnableSnippets ? "method()" : "method"), Has("field")));
252 EXPECT_IFF(Opts.IncludeIneligibleResults, Results.items,
253 Has("private_field"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000254 // Global items.
Sam McCall545a20d2018-01-19 14:34:02 +0000255 EXPECT_THAT(
256 Results.items,
257 Not(AnyOf(Has("global_var"), Has("index_var"), Has("global_func"),
258 Has("global_func()"), Has("index_func"), Has("GlobalClass"),
259 Has("IndexClass"), Has("MACRO"), Has("LocalClass"))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000260 // There should be no code patterns (aka snippets) in after-dot
261 // completion. At least there aren't any we're aware of.
Sam McCall44fdcec22017-12-08 15:00:59 +0000262 EXPECT_THAT(Results.items, Not(Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000263 // Check documentation.
Ilya Biryukov43714502018-05-16 12:32:44 +0000264 EXPECT_IFF(Opts.IncludeComments, Results.items, Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000265}
Sam McCall9aad25f2017-12-05 07:20:26 +0000266
Sam McCallf6ae3232017-12-05 20:11:29 +0000267void TestGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000268 auto Results = completions(
269 R"cpp(
270 #define MACRO X
Sam McCall9aad25f2017-12-05 07:20:26 +0000271
Sam McCall44fdcec22017-12-08 15:00:59 +0000272 int global_var;
273 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000274
Sam McCall44fdcec22017-12-08 15:00:59 +0000275 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000276
Sam McCall44fdcec22017-12-08 15:00:59 +0000277 struct ClassWithMembers {
278 /// Doc for method.
279 int method();
280 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000281
Sam McCall44fdcec22017-12-08 15:00:59 +0000282 int test() {
283 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000284
Sam McCall44fdcec22017-12-08 15:00:59 +0000285 /// Doc for local_var.
286 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000287
Sam McCall44fdcec22017-12-08 15:00:59 +0000288 ^
289 }
290 )cpp",
Sam McCall545a20d2018-01-19 14:34:02 +0000291 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
Sam McCallf6ae3232017-12-05 20:11:29 +0000292
293 // Class members. Should never be present in global completions.
Sam McCall44fdcec22017-12-08 15:00:59 +0000294 EXPECT_THAT(Results.items,
Sam McCallf6ae3232017-12-05 20:11:29 +0000295 Not(AnyOf(Has("method"), Has("method()"), Has("field"))));
296 // Global items.
Sam McCalld8169a82018-01-18 15:31:30 +0000297 EXPECT_THAT(Results.items,
Sam McCall545a20d2018-01-19 14:34:02 +0000298 AllOf(Has("global_var"), Has("index_var"),
Sam McCalld8169a82018-01-18 15:31:30 +0000299 Has(Opts.EnableSnippets ? "global_func()" : "global_func"),
Sam McCall545a20d2018-01-19 14:34:02 +0000300 Has("index_func" /* our fake symbol doesn't include () */),
301 Has("GlobalClass"), Has("IndexClass")));
Sam McCallf6ae3232017-12-05 20:11:29 +0000302 // A macro.
Sam McCall44fdcec22017-12-08 15:00:59 +0000303 EXPECT_IFF(Opts.IncludeMacros, Results.items, Has("MACRO"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000304 // Local items. Must be present always.
Ilya Biryukov9b5ffc22017-12-12 12:56:46 +0000305 EXPECT_THAT(Results.items,
306 AllOf(Has("local_var"), Has("LocalClass"),
307 Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000308 // Check documentation.
Ilya Biryukov43714502018-05-16 12:32:44 +0000309 EXPECT_IFF(Opts.IncludeComments, Results.items, Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000310}
311
312TEST(CompletionTest, CompletionOptions) {
Sam McCall2c3849a2018-01-16 12:21:24 +0000313 auto Test = [&](const clangd::CodeCompleteOptions &Opts) {
314 TestAfterDotCompletion(Opts);
315 TestGlobalScopeCompletion(Opts);
316 };
317 // We used to test every combination of options, but that got too slow (2^N).
318 auto Flags = {
Ilya Biryukov71028b82018-03-12 15:28:22 +0000319 &clangd::CodeCompleteOptions::IncludeMacros,
Ilya Biryukov43714502018-05-16 12:32:44 +0000320 &clangd::CodeCompleteOptions::IncludeComments,
Ilya Biryukov71028b82018-03-12 15:28:22 +0000321 &clangd::CodeCompleteOptions::EnableSnippets,
322 &clangd::CodeCompleteOptions::IncludeCodePatterns,
323 &clangd::CodeCompleteOptions::IncludeIneligibleResults,
Sam McCall2c3849a2018-01-16 12:21:24 +0000324 };
325 // Test default options.
326 Test({});
327 // Test with one flag flipped.
328 for (auto &F : Flags) {
329 clangd::CodeCompleteOptions O;
330 O.*F ^= true;
331 Test(O);
Sam McCall9aad25f2017-12-05 07:20:26 +0000332 }
333}
334
Sam McCall44fdcec22017-12-08 15:00:59 +0000335TEST(CompletionTest, Priorities) {
336 auto Internal = completions(R"cpp(
337 class Foo {
338 public: void pub();
339 protected: void prot();
340 private: void priv();
341 };
342 void Foo::pub() { this->^ }
343 )cpp");
344 EXPECT_THAT(Internal.items,
345 HasSubsequence(Named("priv"), Named("prot"), Named("pub")));
346
347 auto External = completions(R"cpp(
348 class Foo {
349 public: void pub();
350 protected: void prot();
351 private: void priv();
352 };
353 void test() {
354 Foo F;
355 F.^
356 }
357 )cpp");
358 EXPECT_THAT(External.items,
359 AllOf(Has("pub"), Not(Has("prot")), Not(Has("priv"))));
360}
361
362TEST(CompletionTest, Qualifiers) {
363 auto Results = completions(R"cpp(
364 class Foo {
365 public: int foo() const;
366 int bar() const;
367 };
368 class Bar : public Foo {
369 int foo() const;
370 };
371 void test() { Bar().^ }
372 )cpp");
373 EXPECT_THAT(Results.items, HasSubsequence(Labeled("bar() const"),
374 Labeled("Foo::foo() const")));
375 EXPECT_THAT(Results.items, Not(Contains(Labeled("foo() const")))); // private
376}
377
378TEST(CompletionTest, Snippets) {
379 clangd::CodeCompleteOptions Opts;
380 Opts.EnableSnippets = true;
381 auto Results = completions(
382 R"cpp(
383 struct fake {
384 int a;
385 int f(int i, const float f) const;
386 };
387 int main() {
388 fake f;
389 f.^
390 }
391 )cpp",
Sam McCalla15c2d62018-01-18 09:27:56 +0000392 /*IndexSymbols=*/{}, Opts);
Sam McCall44fdcec22017-12-08 15:00:59 +0000393 EXPECT_THAT(Results.items,
Eric Liu63696e12017-12-20 17:24:31 +0000394 HasSubsequence(Snippet("a"),
Sam McCall44fdcec22017-12-08 15:00:59 +0000395 Snippet("f(${1:int i}, ${2:const float f})")));
396}
397
398TEST(CompletionTest, Kinds) {
Sam McCall545a20d2018-01-19 14:34:02 +0000399 auto Results = completions(
400 R"cpp(
401 #define MACRO X
402 int variable;
403 struct Struct {};
404 int function();
405 int X = ^
406 )cpp",
407 {func("indexFunction"), var("indexVariable"), cls("indexClass")});
408 EXPECT_THAT(Results.items,
409 AllOf(Has("function", CompletionItemKind::Function),
410 Has("variable", CompletionItemKind::Variable),
411 Has("int", CompletionItemKind::Keyword),
412 Has("Struct", CompletionItemKind::Class),
413 Has("MACRO", CompletionItemKind::Text),
414 Has("indexFunction", CompletionItemKind::Function),
415 Has("indexVariable", CompletionItemKind::Variable),
416 Has("indexClass", CompletionItemKind::Class)));
Sam McCall44fdcec22017-12-08 15:00:59 +0000417
Sam McCall44fdcec22017-12-08 15:00:59 +0000418 Results = completions("nam^");
419 EXPECT_THAT(Results.items, Has("namespace", CompletionItemKind::Snippet));
420}
421
Sam McCall84652cc2018-01-12 16:16:09 +0000422TEST(CompletionTest, NoDuplicates) {
Sam McCall545a20d2018-01-19 14:34:02 +0000423 auto Results = completions(
424 R"cpp(
425 class Adapter {
426 void method();
427 };
Sam McCall84652cc2018-01-12 16:16:09 +0000428
Sam McCall545a20d2018-01-19 14:34:02 +0000429 void Adapter::method() {
430 Adapter^
431 }
432 )cpp",
433 {cls("Adapter")});
Sam McCall84652cc2018-01-12 16:16:09 +0000434
435 // Make sure there are no duplicate entries of 'Adapter'.
Sam McCalld2a95922018-01-22 21:05:00 +0000436 EXPECT_THAT(Results.items, ElementsAre(Named("Adapter")));
Sam McCall84652cc2018-01-12 16:16:09 +0000437}
438
Sam McCall545a20d2018-01-19 14:34:02 +0000439TEST(CompletionTest, ScopedNoIndex) {
440 auto Results = completions(
441 R"cpp(
442 namespace fake { int BigBang, Babble, Ball; };
443 int main() { fake::bb^ }
444 ")cpp");
Sam McCall84652cc2018-01-12 16:16:09 +0000445 // BigBang is a better match than Babble. Ball doesn't match at all.
Sam McCall545a20d2018-01-19 14:34:02 +0000446 EXPECT_THAT(Results.items, ElementsAre(Named("BigBang"), Named("Babble")));
Sam McCall84652cc2018-01-12 16:16:09 +0000447}
448
Sam McCall545a20d2018-01-19 14:34:02 +0000449TEST(CompletionTest, Scoped) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000450 auto Results = completions(
451 R"cpp(
Sam McCall545a20d2018-01-19 14:34:02 +0000452 namespace fake { int Babble, Ball; };
453 int main() { fake::bb^ }
454 ")cpp",
455 {var("fake::BigBang")});
456 EXPECT_THAT(Results.items, ElementsAre(Named("BigBang"), Named("Babble")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000457}
458
Sam McCall545a20d2018-01-19 14:34:02 +0000459TEST(CompletionTest, ScopedWithFilter) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000460 auto Results = completions(
461 R"cpp(
462 void f() { ns::x^ }
463 )cpp",
464 {cls("ns::XYZ"), func("ns::foo")});
465 EXPECT_THAT(Results.items,
466 UnorderedElementsAre(AllOf(Named("XYZ"), Filter("XYZ"))));
467}
468
Sam McCalldc8abc42018-05-03 14:53:02 +0000469TEST(CompletionTest, ReferencesAffectRanking) {
470 auto Results = completions("int main() { abs^ }", {ns("absl"), func("abs")});
471 EXPECT_THAT(Results.items, HasSubsequence(Named("abs"), Named("absl")));
472 Results = completions("int main() { abs^ }",
473 {withReferences(10000, ns("absl")), func("abs")});
474 EXPECT_THAT(Results.items, HasSubsequence(Named("absl"), Named("abs")));
475}
476
Sam McCall545a20d2018-01-19 14:34:02 +0000477TEST(CompletionTest, GlobalQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000478 auto Results = completions(
479 R"cpp(
480 void f() { ::^ }
481 )cpp",
482 {cls("XYZ")});
483 EXPECT_THAT(Results.items, AllOf(Has("XYZ", CompletionItemKind::Class),
484 Has("f", CompletionItemKind::Function)));
485}
486
Sam McCall545a20d2018-01-19 14:34:02 +0000487TEST(CompletionTest, FullyQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000488 auto Results = completions(
489 R"cpp(
Sam McCall545a20d2018-01-19 14:34:02 +0000490 namespace ns { void bar(); }
Sam McCalla15c2d62018-01-18 09:27:56 +0000491 void f() { ::ns::^ }
492 )cpp",
493 {cls("ns::XYZ")});
Sam McCall545a20d2018-01-19 14:34:02 +0000494 EXPECT_THAT(Results.items, AllOf(Has("XYZ", CompletionItemKind::Class),
495 Has("bar", CompletionItemKind::Function)));
496}
497
498TEST(CompletionTest, SemaIndexMerge) {
499 auto Results = completions(
500 R"cpp(
501 namespace ns { int local; void both(); }
502 void f() { ::ns::^ }
503 )cpp",
504 {func("ns::both"), cls("ns::Index")});
505 // We get results from both index and sema, with no duplicates.
506 EXPECT_THAT(
507 Results.items,
508 UnorderedElementsAre(Named("local"), Named("Index"), Named("both")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000509}
510
Haojian Wu48b48652018-01-25 09:20:09 +0000511TEST(CompletionTest, SemaIndexMergeWithLimit) {
512 clangd::CodeCompleteOptions Opts;
513 Opts.Limit = 1;
514 auto Results = completions(
515 R"cpp(
516 namespace ns { int local; void both(); }
517 void f() { ::ns::^ }
518 )cpp",
519 {func("ns::both"), cls("ns::Index")}, Opts);
520 EXPECT_EQ(Results.items.size(), Opts.Limit);
521 EXPECT_TRUE(Results.isIncomplete);
522}
523
Eric Liu63f419a2018-05-15 15:29:32 +0000524TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
525 MockFSProvider FS;
526 MockCompilationDatabase CDB;
527 std::string Subdir = testPath("sub");
528 std::string SearchDirArg = (llvm::Twine("-I") + Subdir).str();
529 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
530 std::string BarHeader = testPath("sub/bar.h");
531 FS.Files[BarHeader] = "";
532
533 IgnoreDiagnostics DiagConsumer;
534 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
535 Symbol::Details Scratch;
536 auto BarURI = URI::createFile(BarHeader).toString();
537 Symbol Sym = cls("ns::X");
538 Sym.CanonicalDeclaration.FileURI = BarURI;
539 Scratch.IncludeHeader = BarURI;
540 Sym.Detail = &Scratch;
541 // Shoten include path based on search dirctory and insert.
542 auto Results = completions(Server,
543 R"cpp(
544 int main() { ns::^ }
545 )cpp",
546 {Sym});
547 EXPECT_THAT(Results.items,
548 ElementsAre(AllOf(Named("X"), InsertInclude("\"bar.h\""))));
549 // Duplicate based on inclusions in preamble.
550 Results = completions(Server,
551 R"cpp(
552 #include "sub/bar.h" // not shortest, so should only match resolved.
553 int main() { ns::^ }
554 )cpp",
555 {Sym});
556 EXPECT_THAT(Results.items,
557 ElementsAre(AllOf(Named("X"), Not(HasAdditionalEdits()))));
558}
559
Sam McCalla15c2d62018-01-18 09:27:56 +0000560TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
561 MockFSProvider FS;
562 MockCompilationDatabase CDB;
563 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000564 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Sam McCalla15c2d62018-01-18 09:27:56 +0000565
Sam McCallc1568062018-02-16 09:41:43 +0000566 FS.Files[testPath("bar.h")] =
Sam McCalld5ea3e32018-01-24 17:53:32 +0000567 R"cpp(namespace ns { struct preamble { int member; }; })cpp";
Sam McCallc1568062018-02-16 09:41:43 +0000568 auto File = testPath("foo.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000569 Annotations Test(R"cpp(
570 #include "bar.h"
571 namespace ns { int local; }
Sam McCalld5ea3e32018-01-24 17:53:32 +0000572 void f() { ns::^; }
573 void f() { ns::preamble().$2^; }
Sam McCalla15c2d62018-01-18 09:27:56 +0000574 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000575 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000576 clangd::CodeCompleteOptions Opts = {};
577
Sam McCalla15c2d62018-01-18 09:27:56 +0000578 auto I = memIndex({var("ns::index")});
579 Opts.Index = I.get();
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000580 auto WithIndex = cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Sam McCalla15c2d62018-01-18 09:27:56 +0000581 EXPECT_THAT(WithIndex.items,
582 UnorderedElementsAre(Named("local"), Named("index")));
Sam McCalld5ea3e32018-01-24 17:53:32 +0000583 auto ClassFromPreamble =
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000584 cantFail(runCodeComplete(Server, File, Test.point("2"), Opts));
Sam McCalld5ea3e32018-01-24 17:53:32 +0000585 EXPECT_THAT(ClassFromPreamble.items, Contains(Named("member")));
Sam McCall0bb24cd2018-02-13 08:59:23 +0000586
587 Opts.Index = nullptr;
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000588 auto WithoutIndex =
589 cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Sam McCall0bb24cd2018-02-13 08:59:23 +0000590 EXPECT_THAT(WithoutIndex.items,
591 UnorderedElementsAre(Named("local"), Named("preamble")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000592}
593
594TEST(CompletionTest, DynamicIndexMultiFile) {
595 MockFSProvider FS;
596 MockCompilationDatabase CDB;
597 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000598 auto Opts = ClangdServer::optsForTest();
599 Opts.BuildDynamicSymbolIndex = true;
600 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
Sam McCalla15c2d62018-01-18 09:27:56 +0000601
Eric Liu709bde82018-02-19 18:48:44 +0000602 FS.Files[testPath("foo.h")] = R"cpp(
Sam McCalla15c2d62018-01-18 09:27:56 +0000603 namespace ns { class XYZ {}; void foo(int x) {} }
Eric Liu709bde82018-02-19 18:48:44 +0000604 )cpp";
Sam McCall7363a2f2018-03-05 17:28:54 +0000605 runAddDocument(Server, testPath("foo.cpp"), R"cpp(
Eric Liu709bde82018-02-19 18:48:44 +0000606 #include "foo.h"
Sam McCall0bb24cd2018-02-13 08:59:23 +0000607 )cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000608
Sam McCallc1568062018-02-16 09:41:43 +0000609 auto File = testPath("bar.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000610 Annotations Test(R"cpp(
611 namespace ns {
612 class XXX {};
613 /// Doooc
614 void fooooo() {}
615 }
616 void f() { ns::^ }
617 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000618 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000619
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000620 auto Results = cantFail(runCodeComplete(Server, File, Test.point(), {}));
Sam McCalla15c2d62018-01-18 09:27:56 +0000621 // "XYZ" and "foo" are not included in the file being completed but are still
622 // visible through the index.
623 EXPECT_THAT(Results.items, Has("XYZ", CompletionItemKind::Class));
624 EXPECT_THAT(Results.items, Has("foo", CompletionItemKind::Function));
625 EXPECT_THAT(Results.items, Has("XXX", CompletionItemKind::Class));
626 EXPECT_THAT(Results.items, Contains(AllOf(Named("fooooo"), Filter("fooooo"),
627 Kind(CompletionItemKind::Function),
628 Doc("Doooc"), Detail("void"))));
629}
630
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000631TEST(CompletionTest, Documentation) {
632 auto Results = completions(
633 R"cpp(
634 // Non-doxygen comment.
635 int foo();
636 /// Doxygen comment.
637 /// \param int a
638 int bar(int a);
639 /* Multi-line
640 block comment
641 */
642 int baz();
643
644 int x = ^
645 )cpp");
646 EXPECT_THAT(Results.items,
647 Contains(AllOf(Named("foo"), Doc("Non-doxygen comment."))));
648 EXPECT_THAT(
649 Results.items,
650 Contains(AllOf(Named("bar"), Doc("Doxygen comment.\n\\param int a"))));
651 EXPECT_THAT(Results.items,
652 Contains(AllOf(Named("baz"), Doc("Multi-line\nblock comment"))));
653}
654
Haojian Wu58d208d2018-01-25 09:44:06 +0000655TEST(CodeCompleteTest, DisableTypoCorrection) {
656 auto Results = completions(R"cpp(
657 namespace clang { int v; }
658 void f() { clangd::^
659 )cpp");
660 EXPECT_TRUE(Results.items.empty());
661}
662
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000663TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
664 auto Results = completions(R"cpp(
665 namespace clang { }
666 void f() {
667 clan^
668 }
669 )cpp");
670
671 EXPECT_THAT(Results.items, Contains(Labeled("clang")));
672 EXPECT_THAT(Results.items, Not(Contains(Labeled("clang::"))));
673}
674
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000675TEST(CompletionTest, BacktrackCrashes) {
676 // Sema calls code completion callbacks twice in these cases.
677 auto Results = completions(R"cpp(
678 namespace ns {
679 struct FooBarBaz {};
680 } // namespace ns
681
682 int foo(ns::FooBar^
683 )cpp");
684
685 EXPECT_THAT(Results.items, ElementsAre(Labeled("FooBarBaz")));
686
687 // Check we don't crash in that case too.
688 completions(R"cpp(
689 struct FooBarBaz {};
690 void test() {
691 if (FooBarBaz * x^) {}
692 }
693)cpp");
694}
695
Eric Liu42abe412018-05-24 11:20:19 +0000696TEST(CompletionTest, CompleteInMacroWithStringification) {
697 auto Results = completions(R"cpp(
698void f(const char *, int x);
699#define F(x) f(#x, x)
700
701namespace ns {
702int X;
703int Y;
704} // namespace ns
705
706int f(int input_num) {
707 F(ns::^)
708}
709)cpp");
710
711 EXPECT_THAT(Results.items,
712 UnorderedElementsAre(Named("X"), Named("Y")));
713}
714
715TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
716 auto Results = completions(R"cpp(
717void f(const char *, int x);
718#define F(x) f(#x, x)
719
720namespace ns {
721int X;
722
723int f(int input_num) {
724 F(^)
725}
726} // namespace ns
727)cpp");
728
729 EXPECT_THAT(Results.items, Contains(Named("X")));
730}
731
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000732TEST(CompletionTest, CompleteInExcludedPPBranch) {
733 auto Results = completions(R"cpp(
734 int bar(int param_in_bar) {
735 }
736
737 int foo(int param_in_foo) {
738#if 0
739 par^
740#endif
741 }
742)cpp");
743
744 EXPECT_THAT(Results.items, Contains(Labeled("param_in_foo")));
745 EXPECT_THAT(Results.items, Not(Contains(Labeled("param_in_bar"))));
746}
747
Sam McCall800d4372017-12-19 10:29:27 +0000748SignatureHelp signatures(StringRef Text) {
749 MockFSProvider FS;
750 MockCompilationDatabase CDB;
751 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000752 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Sam McCallc1568062018-02-16 09:41:43 +0000753 auto File = testPath("foo.cpp");
Sam McCall328cbdb2017-12-20 16:06:05 +0000754 Annotations Test(Text);
Sam McCall7363a2f2018-03-05 17:28:54 +0000755 runAddDocument(Server, File, Test.code());
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000756 return cantFail(runSignatureHelp(Server, File, Test.point()));
Sam McCall800d4372017-12-19 10:29:27 +0000757}
758
759MATCHER_P(ParamsAre, P, "") {
760 if (P.size() != arg.parameters.size())
761 return false;
762 for (unsigned I = 0; I < P.size(); ++I)
763 if (P[I] != arg.parameters[I].label)
764 return false;
765 return true;
766}
767
768Matcher<SignatureInformation> Sig(std::string Label,
769 std::vector<std::string> Params) {
770 return AllOf(Labeled(Label), ParamsAre(Params));
771}
772
773TEST(SignatureHelpTest, Overloads) {
774 auto Results = signatures(R"cpp(
775 void foo(int x, int y);
776 void foo(int x, float y);
777 void foo(float x, int y);
778 void foo(float x, float y);
779 void bar(int x, int y = 0);
780 int main() { foo(^); }
781 )cpp");
782 EXPECT_THAT(Results.signatures,
783 UnorderedElementsAre(
784 Sig("foo(float x, float y) -> void", {"float x", "float y"}),
785 Sig("foo(float x, int y) -> void", {"float x", "int y"}),
786 Sig("foo(int x, float y) -> void", {"int x", "float y"}),
787 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
788 // We always prefer the first signature.
789 EXPECT_EQ(0, Results.activeSignature);
790 EXPECT_EQ(0, Results.activeParameter);
791}
792
793TEST(SignatureHelpTest, DefaultArgs) {
794 auto Results = signatures(R"cpp(
795 void bar(int x, int y = 0);
796 void bar(float x = 0, int y = 42);
797 int main() { bar(^
798 )cpp");
799 EXPECT_THAT(Results.signatures,
800 UnorderedElementsAre(
801 Sig("bar(int x, int y = 0) -> void", {"int x", "int y = 0"}),
802 Sig("bar(float x = 0, int y = 42) -> void",
803 {"float x = 0", "int y = 42"})));
804 EXPECT_EQ(0, Results.activeSignature);
805 EXPECT_EQ(0, Results.activeParameter);
806}
807
808TEST(SignatureHelpTest, ActiveArg) {
809 auto Results = signatures(R"cpp(
810 int baz(int a, int b, int c);
811 int main() { baz(baz(1,2,3), ^); }
812 )cpp");
813 EXPECT_THAT(Results.signatures,
814 ElementsAre(Sig("baz(int a, int b, int c) -> int",
815 {"int a", "int b", "int c"})));
816 EXPECT_EQ(0, Results.activeSignature);
817 EXPECT_EQ(1, Results.activeParameter);
818}
819
Haojian Wu061c73e2018-01-23 11:37:26 +0000820class IndexRequestCollector : public SymbolIndex {
821public:
822 bool
Sam McCalld1a7a372018-01-31 13:40:48 +0000823 fuzzyFind(const FuzzyFindRequest &Req,
Haojian Wu061c73e2018-01-23 11:37:26 +0000824 llvm::function_ref<void(const Symbol &)> Callback) const override {
825 Requests.push_back(Req);
Sam McCallab8e3932018-02-19 13:04:41 +0000826 return true;
Haojian Wu061c73e2018-01-23 11:37:26 +0000827 }
828
Eric Liu9ec459f2018-03-14 09:48:05 +0000829 void lookup(const LookupRequest &,
830 llvm::function_ref<void(const Symbol &)>) const override {}
831
Haojian Wu061c73e2018-01-23 11:37:26 +0000832 const std::vector<FuzzyFindRequest> allRequests() const { return Requests; }
833
834private:
835 mutable std::vector<FuzzyFindRequest> Requests;
836};
837
838std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code) {
839 clangd::CodeCompleteOptions Opts;
840 IndexRequestCollector Requests;
841 Opts.Index = &Requests;
842 completions(Code, {}, Opts);
843 return Requests.allRequests();
844}
845
846TEST(CompletionTest, UnqualifiedIdQuery) {
847 auto Requests = captureIndexRequests(R"cpp(
848 namespace std {}
849 using namespace std;
850 namespace ns {
851 void f() {
852 vec^
853 }
854 }
855 )cpp");
856
857 EXPECT_THAT(Requests,
858 ElementsAre(Field(&FuzzyFindRequest::Scopes,
859 UnorderedElementsAre("", "ns::", "std::"))));
860}
861
862TEST(CompletionTest, ResolvedQualifiedIdQuery) {
863 auto Requests = captureIndexRequests(R"cpp(
864 namespace ns1 {}
865 namespace ns2 {} // ignore
866 namespace ns3 { namespace nns3 {} }
867 namespace foo {
868 using namespace ns1;
869 using namespace ns3::nns3;
870 }
871 namespace ns {
872 void f() {
873 foo::^
874 }
875 }
876 )cpp");
877
878 EXPECT_THAT(Requests,
879 ElementsAre(Field(
880 &FuzzyFindRequest::Scopes,
881 UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::"))));
882}
883
884TEST(CompletionTest, UnresolvedQualifierIdQuery) {
885 auto Requests = captureIndexRequests(R"cpp(
886 namespace a {}
887 using namespace a;
888 namespace ns {
889 void f() {
890 bar::^
891 }
892 } // namespace ns
893 )cpp");
894
895 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
896 UnorderedElementsAre("bar::"))));
897}
898
899TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
900 auto Requests = captureIndexRequests(R"cpp(
901 namespace a {}
902 using namespace a;
903 namespace ns {
904 void f() {
905 ::a::bar::^
906 }
907 } // namespace ns
908 )cpp");
909
910 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
911 UnorderedElementsAre("a::bar::"))));
912}
913
914TEST(CompletionTest, EmptyQualifiedQuery) {
915 auto Requests = captureIndexRequests(R"cpp(
916 namespace ns {
917 void f() {
918 ^
919 }
920 } // namespace ns
921 )cpp");
922
923 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
924 UnorderedElementsAre("", "ns::"))));
925}
926
927TEST(CompletionTest, GlobalQualifiedQuery) {
928 auto Requests = captureIndexRequests(R"cpp(
929 namespace ns {
930 void f() {
931 ::^
932 }
933 } // namespace ns
934 )cpp");
935
936 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
937 UnorderedElementsAre(""))));
938}
939
Ilya Biryukova907ba42018-05-14 10:50:04 +0000940TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
941 auto Completions = completions(
942 R"cpp(
943 struct Foo {
944 int SomeNameOfField;
945 typedef int SomeNameOfTypedefField;
946 };
947
948 Foo::^)cpp",
949 {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")});
950
951 EXPECT_THAT(Completions.items,
952 AllOf(Contains(Labeled("SomeNameOfField")),
953 Contains(Labeled("SomeNameOfTypedefField")),
954 Not(Contains(Labeled("SomeNameInTheIndex")))));
955}
956
957TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
958 {
959 auto Completions = completions(
960 R"cpp(
961 template <class T>
962 void foo() {
963 T::^
964 }
965 )cpp",
966 {func("::SomeNameInTheIndex")});
967
968 EXPECT_THAT(Completions.items,
969 Not(Contains(Labeled("SomeNameInTheIndex"))));
970 }
971
972 {
973 auto Completions = completions(
974 R"cpp(
975 template <class T>
976 void foo() {
977 T::template Y<int>::^
978 }
979 )cpp",
980 {func("::SomeNameInTheIndex")});
981
982 EXPECT_THAT(Completions.items,
983 Not(Contains(Labeled("SomeNameInTheIndex"))));
984 }
985
986 {
987 auto Completions = completions(
988 R"cpp(
989 template <class T>
990 void foo() {
991 T::foo::^
992 }
993 )cpp",
994 {func("::SomeNameInTheIndex")});
995
996 EXPECT_THAT(Completions.items,
997 Not(Contains(Labeled("SomeNameInTheIndex"))));
998 }
999}
1000
Sam McCall9aad25f2017-12-05 07:20:26 +00001001} // namespace
1002} // namespace clangd
1003} // namespace clang