blob: c11bbf3c88c8a52b0345f71d7ed86370d358cd3e [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
Haojian Wu58d208d2018-01-25 09:44:06 +0000631TEST(CodeCompleteTest, DisableTypoCorrection) {
632 auto Results = completions(R"cpp(
633 namespace clang { int v; }
634 void f() { clangd::^
635 )cpp");
636 EXPECT_TRUE(Results.items.empty());
637}
638
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000639TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
640 auto Results = completions(R"cpp(
641 namespace clang { }
642 void f() {
643 clan^
644 }
645 )cpp");
646
647 EXPECT_THAT(Results.items, Contains(Labeled("clang")));
648 EXPECT_THAT(Results.items, Not(Contains(Labeled("clang::"))));
649}
650
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000651TEST(CompletionTest, BacktrackCrashes) {
652 // Sema calls code completion callbacks twice in these cases.
653 auto Results = completions(R"cpp(
654 namespace ns {
655 struct FooBarBaz {};
656 } // namespace ns
657
658 int foo(ns::FooBar^
659 )cpp");
660
661 EXPECT_THAT(Results.items, ElementsAre(Labeled("FooBarBaz")));
662
663 // Check we don't crash in that case too.
664 completions(R"cpp(
665 struct FooBarBaz {};
666 void test() {
667 if (FooBarBaz * x^) {}
668 }
669)cpp");
670}
671
672TEST(CompletionTest, CompleteInExcludedPPBranch) {
673 auto Results = completions(R"cpp(
674 int bar(int param_in_bar) {
675 }
676
677 int foo(int param_in_foo) {
678#if 0
679 par^
680#endif
681 }
682)cpp");
683
684 EXPECT_THAT(Results.items, Contains(Labeled("param_in_foo")));
685 EXPECT_THAT(Results.items, Not(Contains(Labeled("param_in_bar"))));
686}
687
Sam McCall800d4372017-12-19 10:29:27 +0000688SignatureHelp signatures(StringRef Text) {
689 MockFSProvider FS;
690 MockCompilationDatabase CDB;
691 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000692 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Sam McCallc1568062018-02-16 09:41:43 +0000693 auto File = testPath("foo.cpp");
Sam McCall328cbdb2017-12-20 16:06:05 +0000694 Annotations Test(Text);
Sam McCall7363a2f2018-03-05 17:28:54 +0000695 runAddDocument(Server, File, Test.code());
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000696 return cantFail(runSignatureHelp(Server, File, Test.point()));
Sam McCall800d4372017-12-19 10:29:27 +0000697}
698
699MATCHER_P(ParamsAre, P, "") {
700 if (P.size() != arg.parameters.size())
701 return false;
702 for (unsigned I = 0; I < P.size(); ++I)
703 if (P[I] != arg.parameters[I].label)
704 return false;
705 return true;
706}
707
708Matcher<SignatureInformation> Sig(std::string Label,
709 std::vector<std::string> Params) {
710 return AllOf(Labeled(Label), ParamsAre(Params));
711}
712
713TEST(SignatureHelpTest, Overloads) {
714 auto Results = signatures(R"cpp(
715 void foo(int x, int y);
716 void foo(int x, float y);
717 void foo(float x, int y);
718 void foo(float x, float y);
719 void bar(int x, int y = 0);
720 int main() { foo(^); }
721 )cpp");
722 EXPECT_THAT(Results.signatures,
723 UnorderedElementsAre(
724 Sig("foo(float x, float y) -> void", {"float x", "float y"}),
725 Sig("foo(float x, int y) -> void", {"float x", "int y"}),
726 Sig("foo(int x, float y) -> void", {"int x", "float y"}),
727 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
728 // We always prefer the first signature.
729 EXPECT_EQ(0, Results.activeSignature);
730 EXPECT_EQ(0, Results.activeParameter);
731}
732
733TEST(SignatureHelpTest, DefaultArgs) {
734 auto Results = signatures(R"cpp(
735 void bar(int x, int y = 0);
736 void bar(float x = 0, int y = 42);
737 int main() { bar(^
738 )cpp");
739 EXPECT_THAT(Results.signatures,
740 UnorderedElementsAre(
741 Sig("bar(int x, int y = 0) -> void", {"int x", "int y = 0"}),
742 Sig("bar(float x = 0, int y = 42) -> void",
743 {"float x = 0", "int y = 42"})));
744 EXPECT_EQ(0, Results.activeSignature);
745 EXPECT_EQ(0, Results.activeParameter);
746}
747
748TEST(SignatureHelpTest, ActiveArg) {
749 auto Results = signatures(R"cpp(
750 int baz(int a, int b, int c);
751 int main() { baz(baz(1,2,3), ^); }
752 )cpp");
753 EXPECT_THAT(Results.signatures,
754 ElementsAre(Sig("baz(int a, int b, int c) -> int",
755 {"int a", "int b", "int c"})));
756 EXPECT_EQ(0, Results.activeSignature);
757 EXPECT_EQ(1, Results.activeParameter);
758}
759
Haojian Wu061c73e2018-01-23 11:37:26 +0000760class IndexRequestCollector : public SymbolIndex {
761public:
762 bool
Sam McCalld1a7a372018-01-31 13:40:48 +0000763 fuzzyFind(const FuzzyFindRequest &Req,
Haojian Wu061c73e2018-01-23 11:37:26 +0000764 llvm::function_ref<void(const Symbol &)> Callback) const override {
765 Requests.push_back(Req);
Sam McCallab8e3932018-02-19 13:04:41 +0000766 return true;
Haojian Wu061c73e2018-01-23 11:37:26 +0000767 }
768
Eric Liu9ec459f2018-03-14 09:48:05 +0000769 void lookup(const LookupRequest &,
770 llvm::function_ref<void(const Symbol &)>) const override {}
771
Haojian Wu061c73e2018-01-23 11:37:26 +0000772 const std::vector<FuzzyFindRequest> allRequests() const { return Requests; }
773
774private:
775 mutable std::vector<FuzzyFindRequest> Requests;
776};
777
778std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code) {
779 clangd::CodeCompleteOptions Opts;
780 IndexRequestCollector Requests;
781 Opts.Index = &Requests;
782 completions(Code, {}, Opts);
783 return Requests.allRequests();
784}
785
786TEST(CompletionTest, UnqualifiedIdQuery) {
787 auto Requests = captureIndexRequests(R"cpp(
788 namespace std {}
789 using namespace std;
790 namespace ns {
791 void f() {
792 vec^
793 }
794 }
795 )cpp");
796
797 EXPECT_THAT(Requests,
798 ElementsAre(Field(&FuzzyFindRequest::Scopes,
799 UnorderedElementsAre("", "ns::", "std::"))));
800}
801
802TEST(CompletionTest, ResolvedQualifiedIdQuery) {
803 auto Requests = captureIndexRequests(R"cpp(
804 namespace ns1 {}
805 namespace ns2 {} // ignore
806 namespace ns3 { namespace nns3 {} }
807 namespace foo {
808 using namespace ns1;
809 using namespace ns3::nns3;
810 }
811 namespace ns {
812 void f() {
813 foo::^
814 }
815 }
816 )cpp");
817
818 EXPECT_THAT(Requests,
819 ElementsAre(Field(
820 &FuzzyFindRequest::Scopes,
821 UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::"))));
822}
823
824TEST(CompletionTest, UnresolvedQualifierIdQuery) {
825 auto Requests = captureIndexRequests(R"cpp(
826 namespace a {}
827 using namespace a;
828 namespace ns {
829 void f() {
830 bar::^
831 }
832 } // namespace ns
833 )cpp");
834
835 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
836 UnorderedElementsAre("bar::"))));
837}
838
839TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
840 auto Requests = captureIndexRequests(R"cpp(
841 namespace a {}
842 using namespace a;
843 namespace ns {
844 void f() {
845 ::a::bar::^
846 }
847 } // namespace ns
848 )cpp");
849
850 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
851 UnorderedElementsAre("a::bar::"))));
852}
853
854TEST(CompletionTest, EmptyQualifiedQuery) {
855 auto Requests = captureIndexRequests(R"cpp(
856 namespace ns {
857 void f() {
858 ^
859 }
860 } // namespace ns
861 )cpp");
862
863 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
864 UnorderedElementsAre("", "ns::"))));
865}
866
867TEST(CompletionTest, GlobalQualifiedQuery) {
868 auto Requests = captureIndexRequests(R"cpp(
869 namespace ns {
870 void f() {
871 ::^
872 }
873 } // namespace ns
874 )cpp");
875
876 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
877 UnorderedElementsAre(""))));
878}
879
Ilya Biryukova907ba42018-05-14 10:50:04 +0000880TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
881 auto Completions = completions(
882 R"cpp(
883 struct Foo {
884 int SomeNameOfField;
885 typedef int SomeNameOfTypedefField;
886 };
887
888 Foo::^)cpp",
889 {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")});
890
891 EXPECT_THAT(Completions.items,
892 AllOf(Contains(Labeled("SomeNameOfField")),
893 Contains(Labeled("SomeNameOfTypedefField")),
894 Not(Contains(Labeled("SomeNameInTheIndex")))));
895}
896
897TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
898 {
899 auto Completions = completions(
900 R"cpp(
901 template <class T>
902 void foo() {
903 T::^
904 }
905 )cpp",
906 {func("::SomeNameInTheIndex")});
907
908 EXPECT_THAT(Completions.items,
909 Not(Contains(Labeled("SomeNameInTheIndex"))));
910 }
911
912 {
913 auto Completions = completions(
914 R"cpp(
915 template <class T>
916 void foo() {
917 T::template Y<int>::^
918 }
919 )cpp",
920 {func("::SomeNameInTheIndex")});
921
922 EXPECT_THAT(Completions.items,
923 Not(Contains(Labeled("SomeNameInTheIndex"))));
924 }
925
926 {
927 auto Completions = completions(
928 R"cpp(
929 template <class T>
930 void foo() {
931 T::foo::^
932 }
933 )cpp",
934 {func("::SomeNameInTheIndex")});
935
936 EXPECT_THAT(Completions.items,
937 Not(Contains(Labeled("SomeNameInTheIndex"))));
938 }
939}
940
Sam McCall9aad25f2017-12-05 07:20:26 +0000941} // namespace
942} // namespace clangd
943} // namespace clang