clang-tools 10.0.0

CodeCompleteTests.cpp
Go to the documentation of this file.
1 //===-- CodeCompleteTests.cpp -----------------------------------*- C++ -*-===//
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 "Annotations.h"
10 #include "ClangdServer.h"
11 #include "CodeComplete.h"
12 #include "Compiler.h"
13 #include "Matchers.h"
14 #include "Protocol.h"
15 #include "Quality.h"
16 #include "SourceCode.h"
17 #include "SyncAPI.h"
18 #include "TestFS.h"
19 #include "TestIndex.h"
20 #include "TestTU.h"
21 #include "Threading.h"
22 #include "index/Index.h"
23 #include "index/MemIndex.h"
24 #include "clang/Sema/CodeCompleteConsumer.h"
25 #include "clang/Tooling/CompilationDatabase.h"
26 #include "llvm/Support/Error.h"
27 #include "llvm/Support/Path.h"
28 #include "llvm/Testing/Support/Error.h"
29 #include "gmock/gmock.h"
30 #include "gtest/gtest.h"
31 #include <condition_variable>
32 #include <mutex>
33
34 namespace clang {
35 namespace clangd {
36
37 namespace {
38 using ::llvm::Failed;
39 using ::testing::AllOf;
40 using ::testing::Contains;
41 using ::testing::ElementsAre;
42 using ::testing::Field;
43 using ::testing::HasSubstr;
44 using ::testing::IsEmpty;
45 using ::testing::Not;
46 using ::testing::UnorderedElementsAre;
47
48 class IgnoreDiagnostics : public DiagnosticsConsumer {
49 void onDiagnosticsReady(PathRef File,
50 std::vector<Diag> Diagnostics) override {}
51 };
52
53 // GMock helpers for matching completion items.
54 MATCHER_P(Named, Name, "") { return arg.Name == Name; }
55 MATCHER_P(NameStartsWith, Prefix, "") {
56 return llvm::StringRef(arg.Name).startswith(Prefix);
57 }
58 MATCHER_P(Scope, S, "") { return arg.Scope == S; }
59 MATCHER_P(Qualifier, Q, "") { return arg.RequiredQualifier == Q; }
60 MATCHER_P(Labeled, Label, "") {
61 return arg.RequiredQualifier + arg.Name + arg.Signature == Label;
62 }
63 MATCHER_P(SigHelpLabeled, Label, "") { return arg.label == Label; }
64 MATCHER_P(Kind, K, "") { return arg.Kind == K; }
65 MATCHER_P(Doc, D, "") { return arg.Documentation == D; }
66 MATCHER_P(ReturnType, D, "") { return arg.ReturnType == D; }
67 MATCHER_P(HasInclude, IncludeHeader, "") {
68 return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader;
69 }
70 MATCHER_P(InsertInclude, IncludeHeader, "") {
71 return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader &&
72 bool(arg.Includes[0].Insertion);
73 }
74 MATCHER(InsertInclude, "") {
75 return !arg.Includes.empty() && bool(arg.Includes[0].Insertion);
76 }
77 MATCHER_P(SnippetSuffix, Text, "") { return arg.SnippetSuffix == Text; }
78 MATCHER_P(Origin, OriginSet, "") { return arg.Origin == OriginSet; }
79 MATCHER_P(Signature, S, "") { return arg.Signature == S; }
80
81 // Shorthand for Contains(Named(Name)).
82 Matcher<const std::vector<CodeCompletion> &> Has(std::string Name) {
83 return Contains(Named(std::move(Name)));
84 }
85 Matcher<const std::vector<CodeCompletion> &> Has(std::string Name,
86 CompletionItemKind K) {
87 return Contains(AllOf(Named(std::move(Name)), Kind(K)));
88 }
89 MATCHER(IsDocumented, "") { return !arg.Documentation.empty(); }
90 MATCHER(Deprecated, "") { return arg.Deprecated; }
91
92 std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol> Symbols) {
93 SymbolSlab::Builder Slab;
94 for (const auto &Sym : Symbols)
95 Slab.insert(Sym);
96 return MemIndex::build(std::move(Slab).build(), RefSlab(), RelationSlab());
97 }
98
99 CodeCompleteResult completions(ClangdServer &Server, llvm::StringRef TestCode,
100 Position Point,
101 std::vector<Symbol> IndexSymbols = {},
102 clangd::CodeCompleteOptions Opts = {}) {
103 std::unique_ptr<SymbolIndex> OverrideIndex;
104 if (!IndexSymbols.empty()) {
105 assert(!Opts.Index && "both Index and IndexSymbols given!");
106 OverrideIndex = memIndex(std::move(IndexSymbols));
107 Opts.Index = OverrideIndex.get();
108 }
109
110 auto File = testPath("foo.cpp");
111 runAddDocument(Server, File, TestCode);
112 auto CompletionList =
113 llvm::cantFail(runCodeComplete(Server, File, Point, Opts));
114 return CompletionList;
115 }
116
117 CodeCompleteResult completions(ClangdServer &Server, llvm::StringRef Text,
118 std::vector<Symbol> IndexSymbols = {},
119 clangd::CodeCompleteOptions Opts = {},
120 PathRef FilePath = "foo.cpp") {
121 std::unique_ptr<SymbolIndex> OverrideIndex;
122 if (!IndexSymbols.empty()) {
123 assert(!Opts.Index && "both Index and IndexSymbols given!");
124 OverrideIndex = memIndex(std::move(IndexSymbols));
125 Opts.Index = OverrideIndex.get();
126 }
127
128 auto File = testPath(FilePath);
129 Annotations Test(Text);
130 runAddDocument(Server, File, Test.code());
131 auto CompletionList =
132 llvm::cantFail(runCodeComplete(Server, File, Test.point(), Opts));
133 return CompletionList;
134 }
135
136 // Builds a server and runs code completion.
137 // If IndexSymbols is non-empty, an index will be built and passed to opts.
138 CodeCompleteResult completions(llvm::StringRef Text,
139 std::vector<Symbol> IndexSymbols = {},
140 clangd::CodeCompleteOptions Opts = {},
141 PathRef FilePath = "foo.cpp") {
142 MockFSProvider FS;
143 MockCompilationDatabase CDB;
144 // To make sure our tests for completiopns inside templates work on Windows.
145 CDB.ExtraClangFlags = {"-fno-delayed-template-parsing"};
146 IgnoreDiagnostics DiagConsumer;
147 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
148 return completions(Server, Text, std::move(IndexSymbols), std::move(Opts),
149 FilePath);
150 }
151
152 // Builds a server and runs code completion.
153 // If IndexSymbols is non-empty, an index will be built and passed to opts.
154 CodeCompleteResult completionsNoCompile(llvm::StringRef Text,
155 std::vector<Symbol> IndexSymbols = {},
156 clangd::CodeCompleteOptions Opts = {},
157 PathRef FilePath = "foo.cpp") {
158 std::unique_ptr<SymbolIndex> OverrideIndex;
159 if (!IndexSymbols.empty()) {
160 assert(!Opts.Index && "both Index and IndexSymbols given!");
161 OverrideIndex = memIndex(std::move(IndexSymbols));
162 Opts.Index = OverrideIndex.get();
163 }
164
165 MockFSProvider FS;
166 Annotations Test(Text);
167 return codeComplete(FilePath, tooling::CompileCommand(), /*Preamble=*/nullptr,
168 Test.code(), Test.point(), FS.getFileSystem(), Opts);
169 }
170
171 Symbol withReferences(int N, Symbol S) {
172 S.References = N;
173 return S;
174 }
175
176 TEST(CompletionTest, Limit) {
177 clangd::CodeCompleteOptions Opts;
178 Opts.Limit = 2;
179 auto Results = completions(R"cpp(
180 struct ClassWithMembers {
181 int AAA();
182 int BBB();
183 int CCC();
184 };
185
186 int main() { ClassWithMembers().^ }
187 )cpp",
188 /*IndexSymbols=*/{}, Opts);
189
190 EXPECT_TRUE(Results.HasMore);
191 EXPECT_THAT(Results.Completions, ElementsAre(Named("AAA"), Named("BBB")));
192 }
193
194 TEST(CompletionTest, Filter) {
195 std::string Body = R"cpp(
196 #define MotorCar
197 int Car;
198 struct S {
199 int FooBar;
200 int FooBaz;
201 int Qux;
202 };
203 )cpp";
204
205 // Only items matching the fuzzy query are returned.
206 EXPECT_THAT(completions(Body + "int main() { S().Foba^ }").Completions,
207 AllOf(Has("FooBar"), Has("FooBaz"), Not(Has("Qux"))));
208
209 // Macros require prefix match.
210 EXPECT_THAT(completions(Body + "int main() { C^ }").Completions,
211 AllOf(Has("Car"), Not(Has("MotorCar"))));
212 }
213
214 void testAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
215 auto Results = completions(
216 R"cpp(
217 int global_var;
218
219 int global_func();
220
221 // Make sure this is not in preamble.
222 #define MACRO X
223
224 struct GlobalClass {};
225
226 struct ClassWithMembers {
227 /// Doc for method.
228 int method();
229
230 int field;
231 private:
232 int private_field;
233 };
234
235 int test() {
236 struct LocalClass {};
237
238 /// Doc for local_var.
239 int local_var;
240
241 ClassWithMembers().^
242 }
243 )cpp",
244 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
245
246 EXPECT_TRUE(Results.RanParser);
247 // Class members. The only items that must be present in after-dot
248 // completion.
249 EXPECT_THAT(Results.Completions,
250 AllOf(Has("method"), Has("field"), Not(Has("ClassWithMembers")),
251 Not(Has("operator=")), Not(Has("~ClassWithMembers"))));
252 EXPECT_IFF(Opts.IncludeIneligibleResults, Results.Completions,
253 Has("private_field"));
254 // Global items.
255 EXPECT_THAT(
256 Results.Completions,
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"))));
260 // There should be no code patterns (aka snippets) in after-dot
261 // completion. At least there aren't any we're aware of.
262 EXPECT_THAT(Results.Completions,
263 Not(Contains(Kind(CompletionItemKind::Snippet))));
264 // Check documentation.
265 EXPECT_IFF(Opts.IncludeComments, Results.Completions,
266 Contains(IsDocumented()));
267 }
268
269 void testGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
270 auto Results = completions(
271 R"cpp(
272 int global_var;
273 int global_func();
274
275 // Make sure this is not in preamble.
276 #define MACRO X
277
278 struct GlobalClass {};
279
280 struct ClassWithMembers {
281 /// Doc for method.
282 int method();
283 };
284
285 int test() {
286 struct LocalClass {};
287
288 /// Doc for local_var.
289 int local_var;
290
291 ^
292 }
293 )cpp",
294 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
295
296 EXPECT_TRUE(Results.RanParser);
297 // Class members. Should never be present in global completions.
298 EXPECT_THAT(Results.Completions,
299 Not(AnyOf(Has("method"), Has("method()"), Has("field"))));
300 // Global items.
301 EXPECT_THAT(Results.Completions,
302 AllOf(Has("global_var"), Has("index_var"), Has("global_func"),
303 Has("index_func" /* our fake symbol doesn't include () */),
304 Has("GlobalClass"), Has("IndexClass")));
305 // A macro.
306 EXPECT_IFF(Opts.IncludeMacros, Results.Completions, Has("MACRO"));
307 // Local items. Must be present always.
308 EXPECT_THAT(Results.Completions,
309 AllOf(Has("local_var"), Has("LocalClass"),
310 Contains(Kind(CompletionItemKind::Snippet))));
311 // Check documentation.
312 EXPECT_IFF(Opts.IncludeComments, Results.Completions,
313 Contains(IsDocumented()));
314 }
315
316 TEST(CompletionTest, CompletionOptions) {
317 auto Test = [&](const clangd::CodeCompleteOptions &Opts) {
318 testAfterDotCompletion(Opts);
319 testGlobalScopeCompletion(Opts);
320 };
321 // We used to test every combination of options, but that got too slow (2^N).
322 auto Flags = {
323 &clangd::CodeCompleteOptions::IncludeMacros,
324 &clangd::CodeCompleteOptions::IncludeComments,
325 &clangd::CodeCompleteOptions::IncludeCodePatterns,
326 &clangd::CodeCompleteOptions::IncludeIneligibleResults,
327 };
328 // Test default options.
329 Test({});
330 // Test with one flag flipped.
331 for (auto &F : Flags) {
332 clangd::CodeCompleteOptions O;
333 O.*F ^= true;
334 Test(O);
335 }
336 }
337
338 TEST(CompletionTest, Accessible) {
339 auto Internal = completions(R"cpp(
340 class Foo {
341 public: void pub();
342 protected: void prot();
343 private: void priv();
344 };
345 void Foo::pub() { this->^ }
346 )cpp");
347 EXPECT_THAT(Internal.Completions,
348 AllOf(Has("priv"), Has("prot"), Has("pub")));
349
350 auto External = completions(R"cpp(
351 class Foo {
352 public: void pub();
353 protected: void prot();
354 private: void priv();
355 };
356 void test() {
357 Foo F;
358 F.^
359 }
360 )cpp");
361 EXPECT_THAT(External.Completions,
362 AllOf(Has("pub"), Not(Has("prot")), Not(Has("priv"))));
363 }
364
365 TEST(CompletionTest, Qualifiers) {
366 auto Results = completions(R"cpp(
367 class Foo {
368 public: int foo() const;
369 int bar() const;
370 };
371 class Bar : public Foo {
372 int foo() const;
373 };
374 void test() { Bar().^ }
375 )cpp");
376 EXPECT_THAT(Results.Completions,
377 Contains(AllOf(Qualifier(""), Named("bar"))));
378 // Hidden members are not shown.
379 EXPECT_THAT(Results.Completions,
380 Not(Contains(AllOf(Qualifier("Foo::"), Named("foo")))));
381 // Private members are not shown.
382 EXPECT_THAT(Results.Completions,
383 Not(Contains(AllOf(Qualifier(""), Named("foo")))));
384 }
385
386 TEST(CompletionTest, InjectedTypename) {
387 // These are suppressed when accessed as a member...
388 EXPECT_THAT(completions("struct X{}; void foo(){ X().^ }").Completions,
389 Not(Has("X")));
390 EXPECT_THAT(completions("struct X{ void foo(){ this->^ } };").Completions,
391 Not(Has("X")));
392 // ...but accessible in other, more useful cases.
393 EXPECT_THAT(completions("struct X{ void foo(){ ^ } };").Completions,
394 Has("X"));
395 EXPECT_THAT(
396 completions("struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions,
397 Has("Y"));
398 EXPECT_THAT(
399 completions(
400 "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };")
401 .Completions,
402 Has("Y"));
403 // This case is marginal (`using X::X` is useful), we allow it for now.
404 EXPECT_THAT(completions("struct X{}; void foo(){ X::^ }").Completions,
405 Has("X"));
406 }
407
408 TEST(CompletionTest, SkipInjectedWhenUnqualified) {
409 EXPECT_THAT(completions("struct X { void f() { X^ }};").Completions,
410 ElementsAre(Named("X"), Named("~X")));
411 }
412
413 TEST(CompletionTest, Snippets) {
414 clangd::CodeCompleteOptions Opts;
415 auto Results = completions(
416 R"cpp(
417 struct fake {
418 int a;
419 int f(int i, const float f) const;
420 };
421 int main() {
422 fake f;
423 f.^
424 }
425 )cpp",
426 /*IndexSymbols=*/{}, Opts);
427 EXPECT_THAT(
428 Results.Completions,
429 HasSubsequence(Named("a"),
430 SnippetSuffix("(${1:int i}, ${2:const float f})")));
431 }
432
433 TEST(CompletionTest, NoSnippetsInUsings) {
434 clangd::CodeCompleteOptions Opts;
435 Opts.EnableSnippets = true;
436 auto Results = completions(
437 R"cpp(
438 namespace ns {
439 int func(int a, int b);
440 }
441
442 using ns::^;
443 )cpp",
444 /*IndexSymbols=*/{}, Opts);
445 EXPECT_THAT(Results.Completions,
446 ElementsAre(AllOf(Named("func"), Labeled("func(int a, int b)"),
447 SnippetSuffix(""))));
448
449 // Check index completions too.
450 auto Func = func("ns::func");
451 Func.CompletionSnippetSuffix = "(${1:int a}, ${2: int b})";
452 Func.Signature = "(int a, int b)";
453 Func.ReturnType = "void";
454
455 Results = completions(R"cpp(
456 namespace ns {}
457 using ns::^;
458 )cpp",
459 /*IndexSymbols=*/{Func}, Opts);
460 EXPECT_THAT(Results.Completions,
461 ElementsAre(AllOf(Named("func"), Labeled("func(int a, int b)"),
462 SnippetSuffix(""))));
463
464 // Check all-scopes completions too.
465 Opts.AllScopes = true;
466 Results = completions(R"cpp(
467 using ^;
468 )cpp",
469 /*IndexSymbols=*/{Func}, Opts);
470 EXPECT_THAT(Results.Completions,
471 Contains(AllOf(Named("func"), Labeled("ns::func(int a, int b)"),
472 SnippetSuffix(""))));
473 }
474
475 TEST(CompletionTest, Kinds) {
476 auto Results = completions(
477 R"cpp(
478 int variable;
479 struct Struct {};
480 int function();
481 // make sure MACRO is not included in preamble.
482 #define MACRO 10
483 int X = ^
484 )cpp",
485 {func("indexFunction"), var("indexVariable"), cls("indexClass")});
486 EXPECT_THAT(Results.Completions,
487 AllOf(Has("function", CompletionItemKind::Function),
488 Has("variable", CompletionItemKind::Variable),
489 Has("int", CompletionItemKind::Keyword),
490 Has("Struct", CompletionItemKind::Class),
491 Has("MACRO", CompletionItemKind::Text),
492 Has("indexFunction", CompletionItemKind::Function),
493 Has("indexVariable", CompletionItemKind::Variable),
494 Has("indexClass", CompletionItemKind::Class)));
495
496 Results = completions("nam^");
497 EXPECT_THAT(Results.Completions,
498 Has("namespace", CompletionItemKind::Snippet));
499
500 // Members of anonymous unions are of kind 'field'.
501 Results = completions(
502 R"cpp(
503 struct X{
504 union {
505 void *a;
506 };
507 };
508 auto u = X().^
509 )cpp");
510 EXPECT_THAT(
511 Results.Completions,
512 UnorderedElementsAre(AllOf(Named("a"), Kind(CompletionItemKind::Field))));
513
514 // Completion kinds for templates should not be unknown.
515 Results = completions(
516 R"cpp(
517 template <class T> struct complete_class {};
518 template <class T> void complete_function();
519 template <class T> using complete_type_alias = int;
520 template <class T> int complete_variable = 10;
521
522 struct X {
523 template <class T> static int complete_static_member = 10;
524
525 static auto x = complete_^
526 }
527 )cpp");
528 EXPECT_THAT(
529 Results.Completions,
530 UnorderedElementsAre(
531 AllOf(Named("complete_class"), Kind(CompletionItemKind::Class)),
532 AllOf(Named("complete_function"), Kind(CompletionItemKind::Function)),
533 AllOf(Named("complete_type_alias"),
534 Kind(CompletionItemKind::Interface)),
535 AllOf(Named("complete_variable"), Kind(CompletionItemKind::Variable)),
536 AllOf(Named("complete_static_member"),
537 Kind(CompletionItemKind::Property))));
538 }
539
540 TEST(CompletionTest, NoDuplicates) {
541 auto Results = completions(
542 R"cpp(
543 class Adapter {
544 };
545
546 void f() {
547 Adapter^
548 }
549 )cpp",
550 {cls("Adapter")});
551
552 // Make sure there are no duplicate entries of 'Adapter'.
553 EXPECT_THAT(Results.Completions, ElementsAre(Named("Adapter")));
554 }
555
556 TEST(CompletionTest, ScopedNoIndex) {
557 auto Results = completions(
558 R"cpp(
559 namespace fake { int BigBang, Babble, Box; };
560 int main() { fake::ba^ }
561 ")cpp");
562 // Babble is a better match than BigBang. Box doesn't match at all.
563 EXPECT_THAT(Results.Completions,
564 ElementsAre(Named("Babble"), Named("BigBang")));
565 }
566
567 TEST(CompletionTest, Scoped) {
568 auto Results = completions(
569 R"cpp(
570 namespace fake { int Babble, Box; };
571 int main() { fake::ba^ }
572 ")cpp",
573 {var("fake::BigBang")});
574 EXPECT_THAT(Results.Completions,
575 ElementsAre(Named("Babble"), Named("BigBang")));
576 }
577
578 TEST(CompletionTest, ScopedWithFilter) {
579 auto Results = completions(
580 R"cpp(
581 void f() { ns::x^ }
582 )cpp",
583 {cls("ns::XYZ"), func("ns::foo")});
584 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("XYZ")));
585 }
586
587 TEST(CompletionTest, ReferencesAffectRanking) {
588 auto Results = completions("int main() { abs^ }", {ns("absl"), func("absb")});
589 EXPECT_THAT(Results.Completions,
590 HasSubsequence(Named("absb"), Named("absl")));
591 Results = completions("int main() { abs^ }",
592 {withReferences(10000, ns("absl")), func("absb")});
593 EXPECT_THAT(Results.Completions,
594 HasSubsequence(Named("absl"), Named("absb")));
595 }
596
597 TEST(CompletionTest, ContextWords) {
598 auto Results = completions(R"cpp(
599 enum class Color { RED, YELLOW, BLUE };
600
601 // (blank lines so the definition above isn't "context")
602
603 // "It was a yellow car," he said. "Big yellow car, new."
604 auto Finish = Color::^
605 )cpp");
606 // Yellow would normally sort last (alphabetic).
607 // But the recent mention shuold bump it up.
608 ASSERT_THAT(Results.Completions,
609 HasSubsequence(Named("YELLOW"), Named("BLUE")));
610 }
611
612 TEST(CompletionTest, GlobalQualified) {
613 auto Results = completions(
614 R"cpp(
615 void f() { ::^ }
616 )cpp",
617 {cls("XYZ")});
618 EXPECT_THAT(Results.Completions,
619 AllOf(Has("XYZ", CompletionItemKind::Class),
620 Has("f", CompletionItemKind::Function)));
621 }
622
623 TEST(CompletionTest, FullyQualified) {
624 auto Results = completions(
625 R"cpp(
626 namespace ns { void bar(); }
627 void f() { ::ns::^ }
628 )cpp",
629 {cls("ns::XYZ")});
630 EXPECT_THAT(Results.Completions,
631 AllOf(Has("XYZ", CompletionItemKind::Class),
632 Has("bar", CompletionItemKind::Function)));
633 }
634
635 TEST(CompletionTest, SemaIndexMerge) {
636 auto Results = completions(
637 R"cpp(
638 namespace ns { int local; void both(); }
639 void f() { ::ns::^ }
640 )cpp",
641 {func("ns::both"), cls("ns::Index")});
642 // We get results from both index and sema, with no duplicates.
643 EXPECT_THAT(Results.Completions,
644 UnorderedElementsAre(
645 AllOf(Named("local"), Origin(SymbolOrigin::AST)),
646 AllOf(Named("Index"), Origin(SymbolOrigin::Static)),
647 AllOf(Named("both"),
648 Origin(SymbolOrigin::AST | SymbolOrigin::Static))));
649 }
650
651 TEST(CompletionTest, SemaIndexMergeWithLimit) {
652 clangd::CodeCompleteOptions Opts;
653 Opts.Limit = 1;
654 auto Results = completions(
655 R"cpp(
656 namespace ns { int local; void both(); }
657 void f() { ::ns::^ }
658 )cpp",
659 {func("ns::both"), cls("ns::Index")}, Opts);
660 EXPECT_EQ(Results.Completions.size(), Opts.Limit);
661 EXPECT_TRUE(Results.HasMore);
662 }
663
664 TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
665 MockFSProvider FS;
666 MockCompilationDatabase CDB;
667 std::string Subdir = testPath("sub");
668 std::string SearchDirArg = (Twine("-I") + Subdir).str();
669 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
670 std::string BarHeader = testPath("sub/bar.h");
671 FS.Files[BarHeader] = "";
672
673 IgnoreDiagnostics DiagConsumer;
674 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
675 auto BarURI = URI::create(BarHeader).toString();
676 Symbol Sym = cls("ns::X");
677 Sym.CanonicalDeclaration.FileURI = BarURI.c_str();
678 Sym.IncludeHeaders.emplace_back(BarURI, 1);
679 // Shoten include path based on search directory and insert.
680 auto Results = completions(Server,
681 R"cpp(
682 int main() { ns::^ }
683 )cpp",
684 {Sym});
685 EXPECT_THAT(Results.Completions,
686 ElementsAre(AllOf(Named("X"), InsertInclude("\"bar.h\""))));
687 // Can be disabled via option.
688 CodeCompleteOptions NoInsertion;
689 NoInsertion.InsertIncludes = CodeCompleteOptions::NeverInsert;
690 Results = completions(Server,
691 R"cpp(
692 int main() { ns::^ }
693 )cpp",
694 {Sym}, NoInsertion);
695 EXPECT_THAT(Results.Completions,
696 ElementsAre(AllOf(Named("X"), Not(InsertInclude()))));
697 // Duplicate based on inclusions in preamble.
698 Results = completions(Server,
699 R"cpp(
700 #include "sub/bar.h" // not shortest, so should only match resolved.
701 int main() { ns::^ }
702 )cpp",
703 {Sym});
704 EXPECT_THAT(Results.Completions, ElementsAre(AllOf(Named("X"), Labeled("X"),
705 Not(InsertInclude()))));
706 }
707
708 TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {
709 MockFSProvider FS;
710 MockCompilationDatabase CDB;
711
712 IgnoreDiagnostics DiagConsumer;
713 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
714 Symbol SymX = cls("ns::X");
715 Symbol SymY = cls("ns::Y");
716 std::string BarHeader = testPath("bar.h");
717 auto BarURI = URI::create(BarHeader).toString();
718 SymX.CanonicalDeclaration.FileURI = BarURI.c_str();
719 SymY.CanonicalDeclaration.FileURI = BarURI.c_str();
720 SymX.IncludeHeaders.emplace_back("<bar>", 1);
721 SymY.IncludeHeaders.emplace_back("<bar>", 1);
722 // Shoten include path based on search directory and insert.
723 auto Results = completions(Server,
724 R"cpp(
725 namespace ns {
726 class X;
727 class Y {};
728 }
729 int main() { ns::^ }
730 )cpp",
731 {SymX, SymY});
732 EXPECT_THAT(Results.Completions,
733 ElementsAre(AllOf(Named("X"), Not(InsertInclude())),
734 AllOf(Named("Y"), Not(InsertInclude()))));
735 }
736
737 TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
738 MockFSProvider FS;
739 MockCompilationDatabase CDB;
740 IgnoreDiagnostics DiagConsumer;
741 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
742
743 FS.Files[testPath("bar.h")] =
744 R"cpp(namespace ns { struct preamble { int member; }; })cpp";
745 auto File = testPath("foo.cpp");
746 Annotations Test(R"cpp(
747 #include "bar.h"
748 namespace ns { int local; }
749 void f() { ns::^; }
750 void f2() { ns::preamble().$2^; }
751 )cpp");
752 runAddDocument(Server, File, Test.code());
753 clangd::CodeCompleteOptions Opts = {};
754
755 auto I = memIndex({var("ns::index")});
756 Opts.Index = I.get();
757 auto WithIndex = cantFail(runCodeComplete(Server, File, Test.point(), Opts));
758 EXPECT_THAT(WithIndex.Completions,
759 UnorderedElementsAre(Named("local"), Named("index")));
760 auto ClassFromPreamble =
761 cantFail(runCodeComplete(Server, File, Test.point("2"), Opts));
762 EXPECT_THAT(ClassFromPreamble.Completions, Contains(Named("member")));
763
764 Opts.Index = nullptr;
765 auto WithoutIndex =
766 cantFail(runCodeComplete(Server, File, Test.point(), Opts));
767 EXPECT_THAT(WithoutIndex.Completions,
768 UnorderedElementsAre(Named("local"), Named("preamble")));
769 }
770
771 // This verifies that we get normal preprocessor completions in the preamble.
772 // This is a regression test for an old bug: if we override the preamble and
773 // try to complete inside it, clang kicks our completion point just outside the
774 // preamble, resulting in always getting top-level completions.
775 TEST(CompletionTest, CompletionInPreamble) {
776 auto Results = completions(R"cpp(
777 #ifnd^ef FOO_H_
778 #define BAR_H_
779 #include <bar.h>
780 int foo() {}
781 #endif
782 )cpp")
783 .Completions;
784 EXPECT_THAT(Results, ElementsAre(Named("ifndef")));
785 }
786
787 TEST(CompletionTest, DynamicIndexIncludeInsertion) {
788 MockFSProvider FS;
789 MockCompilationDatabase CDB;
790 IgnoreDiagnostics DiagConsumer;
791 ClangdServer::Options Opts = ClangdServer::optsForTest();
792 Opts.BuildDynamicSymbolIndex = true;
793 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
794
795 FS.Files[testPath("foo_header.h")] = R"cpp(
796 #pragma once
797 struct Foo {
798 // Member doc
799 int foo();
800 };
801 )cpp";
802 const std::string FileContent(R"cpp(
803 #include "foo_header.h"
804 int Foo::foo() {
805 return 42;
806 }
807 )cpp");
808 Server.addDocument(testPath("foo_impl.cpp"), FileContent);
809 // Wait for the dynamic index being built.
810 ASSERT_TRUE(Server.blockUntilIdleForTest());
811 EXPECT_THAT(completions(Server, "Foo^ foo;").Completions,
812 ElementsAre(AllOf(Named("Foo"), HasInclude("\"foo_header.h\""),
813 InsertInclude())));
814 }
815
816 TEST(CompletionTest, DynamicIndexMultiFile) {
817 MockFSProvider FS;
818 MockCompilationDatabase CDB;
819 IgnoreDiagnostics DiagConsumer;
820 auto Opts = ClangdServer::optsForTest();
821 Opts.BuildDynamicSymbolIndex = true;
822 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
823
824 FS.Files[testPath("foo.h")] = R"cpp(
825 namespace ns { class XYZ {}; void foo(int x) {} }
826 )cpp";
827 runAddDocument(Server, testPath("foo.cpp"), R"cpp(
828 #include "foo.h"
829 )cpp");
830
831 auto File = testPath("bar.cpp");
832 Annotations Test(R"cpp(
833 namespace ns {
834 class XXX {};
835 /// Doooc
836 void fooooo() {}
837 }
838 void f() { ns::^ }
839 )cpp");
840 runAddDocument(Server, File, Test.code());
841
842 auto Results = cantFail(runCodeComplete(Server, File, Test.point(), {}));
843 // "XYZ" and "foo" are not included in the file being completed but are still
844 // visible through the index.
845 EXPECT_THAT(Results.Completions, Has("XYZ", CompletionItemKind::Class));
846 EXPECT_THAT(Results.Completions, Has("foo", CompletionItemKind::Function));
847 EXPECT_THAT(Results.Completions, Has("XXX", CompletionItemKind::Class));
848 EXPECT_THAT(Results.Completions,
849 Contains((Named("fooooo"), Kind(CompletionItemKind::Function),
850 Doc("Doooc"), ReturnType("void"))));
851 }
852
853 TEST(CompletionTest, Documentation) {
854 auto Results = completions(
855 R"cpp(
856 // Non-doxygen comment.
857 int foo();
858 /// Doxygen comment.
859 /// \param int a
860 int bar(int a);
861 /* Multi-line
862 block comment
863 */
864 int baz();
865
866 int x = ^
867 )cpp");
868 EXPECT_THAT(Results.Completions,
869 Contains(AllOf(Named("foo"), Doc("Non-doxygen comment."))));
870 EXPECT_THAT(
871 Results.Completions,
872 Contains(AllOf(Named("bar"), Doc("Doxygen comment.\n\\param int a"))));
873 EXPECT_THAT(Results.Completions,
874 Contains(AllOf(Named("baz"), Doc("Multi-line\nblock comment"))));
875 }
876
877 TEST(CompletionTest, CommentsFromSystemHeaders) {
878 MockFSProvider FS;
879 MockCompilationDatabase CDB;
880 IgnoreDiagnostics DiagConsumer;
881
882 auto Opts = ClangdServer::optsForTest();
883 Opts.BuildDynamicSymbolIndex = true;
884
885 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
886
887 FS.Files[testPath("foo.h")] = R"cpp(
888 #pragma GCC system_header
889
890 // This comment should be retained!
891 int foo();
892 )cpp";
893
894 auto Results = completions(Server,
895 R"cpp(
896 #include "foo.h"
897 int x = foo^
898 )cpp");
899 EXPECT_THAT(
900 Results.Completions,
901 Contains(AllOf(Named("foo"), Doc("This comment should be retained!"))));
902 }
903
904 TEST(CompletionTest, GlobalCompletionFiltering) {
905
906 Symbol Class = cls("XYZ");
907 Class.Flags = static_cast<Symbol::SymbolFlag>(
908 Class.Flags & ~(Symbol::IndexedForCodeCompletion));
909 Symbol Func = func("XYZ::foooo");
910 Func.Flags = static_cast<Symbol::SymbolFlag>(
911 Func.Flags & ~(Symbol::IndexedForCodeCompletion));
912
913 auto Results = completions(R"(// void f() {
914 XYZ::foooo^
915 })",
916 {Class, Func});
917 EXPECT_THAT(Results.Completions, IsEmpty());
918 }
919
920 TEST(CodeCompleteTest, DisableTypoCorrection) {
921 auto Results = completions(R"cpp(
922 namespace clang { int v; }
923 void f() { clangd::^
924 )cpp");
925 EXPECT_TRUE(Results.Completions.empty());
926 }
927
928 TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
929 auto Results = completions(R"cpp(
930 namespace clang { }
931 void f() {
932 clan^
933 }
934 )cpp");
935
936 EXPECT_THAT(Results.Completions, Contains(Labeled("clang")));
937 EXPECT_THAT(Results.Completions, Not(Contains(Labeled("clang::"))));
938 }
939
940 TEST(CompletionTest, BacktrackCrashes) {
941 // Sema calls code completion callbacks twice in these cases.
942 auto Results = completions(R"cpp(
943 namespace ns {
944 struct FooBarBaz {};
945 } // namespace ns
946
947 int foo(ns::FooBar^
948 )cpp");
949
950 EXPECT_THAT(Results.Completions, ElementsAre(Labeled("FooBarBaz")));
951
952 // Check we don't crash in that case too.
953 completions(R"cpp(
954 struct FooBarBaz {};
955 void test() {
956 if (FooBarBaz * x^) {}
957 }
958 )cpp");
959 }
960
961 TEST(CompletionTest, CompleteInMacroWithStringification) {
962 auto Results = completions(R"cpp(
963 void f(const char *, int x);
964 #define F(x) f(#x, x)
965
966 namespace ns {
967 int X;
968 int Y;
969 } // namespace ns
970
971 int f(int input_num) {
972 F(ns::^)
973 }
974 )cpp");
975
976 EXPECT_THAT(Results.Completions,
977 UnorderedElementsAre(Named("X"), Named("Y")));
978 }
979
980 TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
981 auto Results = completions(R"cpp(
982 void f(const char *, int x);
983 #define F(x) f(#x, x)
984
985 namespace ns {
986 int X;
987
988 int f(int input_num) {
989 F(^)
990 }
991 } // namespace ns
992 )cpp");
993
994 EXPECT_THAT(Results.Completions, Contains(Named("X")));
995 }
996
997 TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
998 auto Results = completions(R"cpp(
999 int bar(int param_in_bar) {
1000 }
1001
1002 int foo(int param_in_foo) {
1003 #if 0
1004 // In recorvery mode, "param_in_foo" will also be suggested among many other
1005 // unrelated symbols; however, this is really a special case where this works.
1006 // If the #if block is outside of the function, "param_in_foo" is still
1007 // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't
1008 // really provide useful results in excluded branches.
1009 par^
1010 #endif
1011 }
1012 )cpp");
1013
1014 EXPECT_TRUE(Results.Completions.empty());
1015 }
1016
1017 TEST(CompletionTest, DefaultArgs) {
1018 clangd::CodeCompleteOptions Opts;
1019 std::string Context = R"cpp(
1020 int X(int A = 0);
1021 int Y(int A, int B = 0);
1022 int Z(int A, int B = 0, int C = 0, int D = 0);
1023 )cpp";
1024 EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions,
1025 UnorderedElementsAre(Labeled("X(int A = 0)")));
1026 EXPECT_THAT(completions(Context + "int y = Y^", {}, Opts).Completions,
1027 UnorderedElementsAre(AllOf(Labeled("Y(int A, int B = 0)"),
1028 SnippetSuffix("(${1:int A})"))));
1029 EXPECT_THAT(completions(Context + "int y = Z^", {}, Opts).Completions,
1030 UnorderedElementsAre(
1031 AllOf(Labeled("Z(int A, int B = 0, int C = 0, int D = 0)"),
1032 SnippetSuffix("(${1:int A})"))));
1033 }
1034
1035 TEST(CompletionTest, NoCrashWithTemplateParamsAndPreferredTypes) {
1036 auto Completions = completions(R"cpp(
1037 template <template <class> class TT> int foo() {
1038 int a = ^
1039 }
1040 )cpp")
1041 .Completions;
1042 EXPECT_THAT(Completions, Contains(Named("TT")));
1043 }
1044
1045 SignatureHelp signatures(llvm::StringRef Text, Position Point,
1046 std::vector<Symbol> IndexSymbols = {}) {
1047 std::unique_ptr<SymbolIndex> Index;
1048 if (!IndexSymbols.empty())
1049 Index = memIndex(IndexSymbols);
1050
1051 MockFSProvider FS;
1052 MockCompilationDatabase CDB;
1053 IgnoreDiagnostics DiagConsumer;
1054 ClangdServer::Options Opts = ClangdServer::optsForTest();
1055 Opts.StaticIndex = Index.get();
1056
1057 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
1058 auto File = testPath("foo.cpp");
1059 runAddDocument(Server, File, Text);
1060 return llvm::cantFail(runSignatureHelp(Server, File, Point));
1061 }
1062
1063 SignatureHelp signatures(llvm::StringRef Text,
1064 std::vector<Symbol> IndexSymbols = {}) {
1065 Annotations Test(Text);
1066 return signatures(Test.code(), Test.point(), std::move(IndexSymbols));
1067 }
1068
1069 struct ExpectedParameter {
1070 std::string Text;
1071 std::pair<unsigned, unsigned> Offsets;
1072 };
1073 MATCHER_P(ParamsAre, P, "") {
1074 if (P.size() != arg.parameters.size())
1075 return false;
1076 for (unsigned I = 0; I < P.size(); ++I) {
1077 if (P[I].Text != arg.parameters[I].labelString ||
1078 P[I].Offsets != arg.parameters[I].labelOffsets)
1079 return false;
1080 }
1081 return true;
1082 }
1083 MATCHER_P(SigDoc, Doc, "") { return arg.documentation == Doc; }
1084
1085 /// \p AnnotatedLabel is a signature label with ranges marking parameters, e.g.
1086 /// foo([[int p1]], [[double p2]]) -> void
1087 Matcher<SignatureInformation> Sig(llvm::StringRef AnnotatedLabel) {
1088 llvm::Annotations A(AnnotatedLabel);
1089 std::string Label = A.code();
1090 std::vector<ExpectedParameter> Parameters;
1091 for (auto Range : A.ranges()) {
1092 Parameters.emplace_back();
1093
1094 ExpectedParameter &P = Parameters.back();
1095 P.Text = Label.substr(Range.Begin, Range.End - Range.Begin);
1096 P.Offsets.first = lspLength(llvm::StringRef(Label).substr(0, Range.Begin));
1097 P.Offsets.second = lspLength(llvm::StringRef(Label).substr(1, Range.End));
1098 }
1099 return AllOf(SigHelpLabeled(Label), ParamsAre(Parameters));
1100 }
1101
1102 TEST(SignatureHelpTest, Overloads) {
1103 auto Results = signatures(R"cpp(
1104 void foo(int x, int y);
1105 void foo(int x, float y);
1106 void foo(float x, int y);
1107 void foo(float x, float y);
1108 void bar(int x, int y = 0);
1109 int main() { foo(^); }
1110 )cpp");
1111 EXPECT_THAT(Results.signatures,
1112 UnorderedElementsAre(Sig("foo([[float x]], [[float y]]) -> void"),
1113 Sig("foo([[float x]], [[int y]]) -> void"),
1114 Sig("foo([[int x]], [[float y]]) -> void"),
1115 Sig("foo([[int x]], [[int y]]) -> void")));
1116 // We always prefer the first signature.
1117 EXPECT_EQ(0, Results.activeSignature);
1118 EXPECT_EQ(0, Results.activeParameter);
1119 }
1120
1121 TEST(SignatureHelpTest, DefaultArgs) {
1122 auto Results = signatures(R"cpp(
1123 void bar(int x, int y = 0);
1124 void bar(float x = 0, int y = 42);
1125 int main() { bar(^
1126 )cpp");
1127 EXPECT_THAT(Results.signatures,
1128 UnorderedElementsAre(
1129 Sig("bar([[int x]], [[int y = 0]]) -> void"),
1130 Sig("bar([[float x = 0]], [[int y = 42]]) -> void")));
1131 EXPECT_EQ(0, Results.activeSignature);
1132 EXPECT_EQ(0, Results.activeParameter);
1133 }
1134
1135 TEST(SignatureHelpTest, ActiveArg) {
1136 auto Results = signatures(R"cpp(
1137 int baz(int a, int b, int c);
1138 int main() { baz(baz(1,2,3), ^); }
1139 )cpp");
1140 EXPECT_THAT(Results.signatures,
1141 ElementsAre(Sig("baz([[int a]], [[int b]], [[int c]]) -> int")));
1142 EXPECT_EQ(0, Results.activeSignature);
1143 EXPECT_EQ(1, Results.activeParameter);
1144 }
1145
1146 TEST(SignatureHelpTest, OpeningParen) {
1147 llvm::StringLiteral Tests[] = {// Recursive function call.
1148 R"cpp(
1149 int foo(int a, int b, int c);
1150 int main() {
1151 foo(foo $p^( foo(10, 10, 10), ^ )));
1152 })cpp",
1153 // Functional type cast.
1154 R"cpp(
1155 struct Foo {
1156 Foo(int a, int b, int c);
1157 };
1158 int main() {
1159 Foo $p^( 10, ^ );
1160 })cpp",
1161 // New expression.
1162 R"cpp(
1163 struct Foo {
1164 Foo(int a, int b, int c);
1165 };
1166 int main() {
1167 new Foo $p^( 10, ^ );
1168 })cpp",
1169 // Macro expansion.
1170 R"cpp(
1171 int foo(int a, int b, int c);
1172 #define FOO foo(
1173
1174 int main() {
1175 // Macro expansions.
1176 $p^FOO 10, ^ );
1177 })cpp",
1178 // Macro arguments.
1179 R"cpp(
1180 int foo(int a, int b, int c);
1181 int main() {
1182 #define ID(X) X
1183 ID(foo $p^( foo(10), ^ ))
1184 })cpp"};
1185
1186 for (auto Test : Tests) {
1187 Annotations Code(Test);
1188 EXPECT_EQ(signatures(Code.code(), Code.point()).argListStart,
1189 Code.point("p"))
1190 << "Test source:" << Test;
1191 }
1192 }
1193
1194 class IndexRequestCollector : public SymbolIndex {
1195 public:
1196 bool
1197 fuzzyFind(const FuzzyFindRequest &Req,
1198 llvm::function_ref<void(const Symbol &)> Callback) const override {
1199 std::unique_lock<std::mutex> Lock(Mut);
1200 Requests.push_back(Req);
1201 ReceivedRequestCV.notify_one();
1202 return true;
1203 }
1204
1205 void lookup(const LookupRequest &,
1206 llvm::function_ref<void(const Symbol &)>) const override {}
1207
1208 bool refs(const RefsRequest &,
1209 llvm::function_ref<void(const Ref &)>) const override {
1210 return false;
1211 }
1212
1213 void relations(const RelationsRequest &,
1214 llvm::function_ref<void(const SymbolID &, const Symbol &)>)
1215 const override {}
1216
1217 // This is incorrect, but IndexRequestCollector is not an actual index and it
1218 // isn't used in production code.
1219 size_t estimateMemoryUsage() const override { return 0; }
1220
1221 const std::vector<FuzzyFindRequest> consumeRequests(size_t Num) const {
1222 std::unique_lock<std::mutex> Lock(Mut);
1223 EXPECT_TRUE(wait(Lock, ReceivedRequestCV, timeoutSeconds(30),
1224 [this, Num] { return Requests.size() == Num; }));
1225 auto Reqs = std::move(Requests);
1226 Requests = {};
1227 return Reqs;
1228 }
1229
1230 private:
1231 // We need a mutex to handle async fuzzy find requests.
1232 mutable std::condition_variable ReceivedRequestCV;
1233 mutable std::mutex Mut;
1234 mutable std::vector<FuzzyFindRequest> Requests;
1235 };
1236
1237 // Clients have to consume exactly Num requests.
1238 std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code,
1239 size_t Num = 1) {
1240 clangd::CodeCompleteOptions Opts;
1241 IndexRequestCollector Requests;
1242 Opts.Index = &Requests;
1243 completions(Code, {}, Opts);
1244 const auto Reqs = Requests.consumeRequests(Num);
1245 EXPECT_EQ(Reqs.size(), Num);
1246 return Reqs;
1247 }
1248
1249 TEST(CompletionTest, UnqualifiedIdQuery) {
1250 auto Requests = captureIndexRequests(R"cpp(
1251 namespace std {}
1252 using namespace std;
1253 namespace ns {
1254 void f() {
1255 vec^
1256 }
1257 }
1258 )cpp");
1259
1260 EXPECT_THAT(Requests,
1261 ElementsAre(Field(&FuzzyFindRequest::Scopes,
1262 UnorderedElementsAre("", "ns::", "std::"))));
1263 }
1264
1265 TEST(CompletionTest, EnclosingScopeComesFirst) {
1266 auto Requests = captureIndexRequests(R"cpp(
1267 namespace std {}
1268 using namespace std;
1269 namespace nx {
1270 namespace ns {
1271 namespace {
1272 void f() {
1273 vec^
1274 }
1275 }
1276 }
1277 }
1278 )cpp");
1279
1280 EXPECT_THAT(Requests,
1281 ElementsAre(Field(
1282 &FuzzyFindRequest::Scopes,
1283 UnorderedElementsAre("", "std::", "nx::ns::", "nx::"))));
1284 EXPECT_EQ(Requests[0].Scopes[0], "nx::ns::");
1285 }
1286
1287 TEST(CompletionTest, ResolvedQualifiedIdQuery) {
1288 auto Requests = captureIndexRequests(R"cpp(
1289 namespace ns1 {}
1290 namespace ns2 {} // ignore
1291 namespace ns3 { namespace nns3 {} }
1292 namespace foo {
1293 using namespace ns1;
1294 using namespace ns3::nns3;
1295 }
1296 namespace ns {
1297 void f() {
1298 foo::^
1299 }
1300 }
1301 )cpp");
1302
1303 EXPECT_THAT(Requests,
1304 ElementsAre(Field(
1305 &FuzzyFindRequest::Scopes,
1306 UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::"))));
1307 }
1308
1309 TEST(CompletionTest, UnresolvedQualifierIdQuery) {
1310 auto Requests = captureIndexRequests(R"cpp(
1311 namespace a {}
1312 using namespace a;
1313 namespace ns {
1314 void f() {
1315 bar::^
1316 }
1317 } // namespace ns
1318 )cpp");
1319
1320 EXPECT_THAT(Requests,
1321 ElementsAre(Field(
1322 &FuzzyFindRequest::Scopes,
1323 UnorderedElementsAre("a::bar::", "ns::bar::", "bar::"))));
1324 }
1325
1326 TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
1327 auto Requests = captureIndexRequests(R"cpp(
1328 namespace a {}
1329 using namespace a;
1330 namespace ns {
1331 void f() {
1332 ::a::bar::^
1333 }
1334 } // namespace ns
1335 )cpp");
1336
1337 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1338 UnorderedElementsAre("a::bar::"))));
1339 }
1340
1341 TEST(CompletionTest, EmptyQualifiedQuery) {
1342 auto Requests = captureIndexRequests(R"cpp(
1343 namespace ns {
1344 void f() {
1345 ^
1346 }
1347 } // namespace ns
1348 )cpp");
1349
1350 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1351 UnorderedElementsAre("", "ns::"))));
1352 }
1353
1354 TEST(CompletionTest, GlobalQualifiedQuery) {
1355 auto Requests = captureIndexRequests(R"cpp(
1356 namespace ns {
1357 void f() {
1358 ::^
1359 }
1360 } // namespace ns
1361 )cpp");
1362
1363 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1364 UnorderedElementsAre(""))));
1365 }
1366
1367 TEST(CompletionTest, NoDuplicatedQueryScopes) {
1368 auto Requests = captureIndexRequests(R"cpp(
1369 namespace {}
1370
1371 namespace na {
1372 namespace {}
1373 namespace nb {
1374 ^
1375 } // namespace nb
1376 } // namespace na
1377 )cpp");
1378
1379 EXPECT_THAT(Requests,
1380 ElementsAre(Field(&FuzzyFindRequest::Scopes,
1381 UnorderedElementsAre("na::", "na::nb::", ""))));
1382 }
1383
1384 TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
1385 auto Completions = completions(
1386 R"cpp(
1387 struct Foo {
1388 int SomeNameOfField;
1389 typedef int SomeNameOfTypedefField;
1390 };
1391
1392 Foo::^)cpp",
1393 {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")});
1394
1395 EXPECT_THAT(Completions.Completions,
1396 AllOf(Contains(Labeled("SomeNameOfField")),
1397 Contains(Labeled("SomeNameOfTypedefField")),
1398 Not(Contains(Labeled("SomeNameInTheIndex")))));
1399 }
1400
1401 TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
1402 {
1403 auto Completions = completions(
1404 R"cpp(
1405 template <class T>
1406 void foo() {
1407 T::^
1408 }
1409 )cpp",
1410 {func("::SomeNameInTheIndex")});
1411
1412 EXPECT_THAT(Completions.Completions,
1413 Not(Contains(Labeled("SomeNameInTheIndex"))));
1414 }
1415
1416 {
1417 auto Completions = completions(
1418 R"cpp(
1419 template <class T>
1420 void foo() {
1421 T::template Y<int>::^
1422 }
1423 )cpp",
1424 {func("::SomeNameInTheIndex")});
1425
1426 EXPECT_THAT(Completions.Completions,
1427 Not(Contains(Labeled("SomeNameInTheIndex"))));
1428 }
1429
1430 {
1431 auto Completions = completions(
1432 R"cpp(
1433 template <class T>
1434 void foo() {
1435 T::foo::^
1436 }
1437 )cpp",
1438 {func("::SomeNameInTheIndex")});
1439
1440 EXPECT_THAT(Completions.Completions,
1441 Not(Contains(Labeled("SomeNameInTheIndex"))));
1442 }
1443 }
1444
1445 TEST(CompletionTest, OverloadBundling) {
1446 clangd::CodeCompleteOptions Opts;
1447 Opts.BundleOverloads = true;
1448
1449 std::string Context = R"cpp(
1450 struct X {
1451 // Overload with int
1452 int a(int);
1453 // Overload with bool
1454 int a(bool);
1455 int b(float);
1456 };
1457 int GFuncC(int);
1458 int GFuncD(int);
1459 )cpp";
1460
1461 // Member completions are bundled.
1462 EXPECT_THAT(completions(Context + "int y = X().^", {}, Opts).Completions,
1463 UnorderedElementsAre(Labeled("a(…)"), Labeled("b(float)")));
1464
1465 // Non-member completions are bundled, including index+sema.
1466 Symbol NoArgsGFunc = func("GFuncC");
1467 EXPECT_THAT(
1468 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1469 UnorderedElementsAre(Labeled("GFuncC(…)"), Labeled("GFuncD(int)")));
1470
1471 // Differences in header-to-insert suppress bundling.
1472 std::string DeclFile = URI::create(testPath("foo")).toString();
1473 NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile.c_str();
1474 NoArgsGFunc.IncludeHeaders.emplace_back("<foo>", 1);
1475 EXPECT_THAT(
1476 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1477 UnorderedElementsAre(AllOf(Named("GFuncC"), InsertInclude("<foo>")),
1478 Labeled("GFuncC(int)"), Labeled("GFuncD(int)")));
1479
1480 // Examine a bundled completion in detail.
1481 auto A =
1482 completions(Context + "int y = X().a^", {}, Opts).Completions.front();
1483 EXPECT_EQ(A.Name, "a");
1484 EXPECT_EQ(A.Signature, "(…)");
1485 EXPECT_EQ(A.BundleSize, 2u);
1486 EXPECT_EQ(A.Kind, CompletionItemKind::Method);
1487 EXPECT_EQ(A.ReturnType, "int"); // All overloads return int.
1488 // For now we just return one of the doc strings arbitrarily.
1489 EXPECT_THAT(A.Documentation, AnyOf(HasSubstr("Overload with int"),
1490 HasSubstr("Overload with bool")));
1491 EXPECT_EQ(A.SnippetSuffix, "($0)");
1492 }
1493
1494 TEST(CompletionTest, DocumentationFromChangedFileCrash) {
1495 MockFSProvider FS;
1496 auto FooH = testPath("foo.h");
1497 auto FooCpp = testPath("foo.cpp");
1498 FS.Files[FooH] = R"cpp(
1499 // this is my documentation comment.
1500 int func();
1501 )cpp";
1502 FS.Files[FooCpp] = "";
1503
1504 MockCompilationDatabase CDB;
1505 IgnoreDiagnostics DiagConsumer;
1506 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1507
1508 Annotations Source(R"cpp(
1509 #include "foo.h"
1510 int func() {
1511 // This makes sure we have func from header in the AST.
1512 }
1513 int a = fun^
1514 )cpp");
1515 Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
1516 // We need to wait for preamble to build.
1517 ASSERT_TRUE(Server.blockUntilIdleForTest());
1518
1519 // Change the header file. Completion will reuse the old preamble!
1520 FS.Files[FooH] = R"cpp(
1521 int func();
1522 )cpp";
1523
1524 clangd::CodeCompleteOptions Opts;
1525 Opts.IncludeComments = true;
1526 CodeCompleteResult Completions =
1527 cantFail(runCodeComplete(Server, FooCpp, Source.point(), Opts));
1528 // We shouldn't crash. Unfortunately, current workaround is to not produce
1529 // comments for symbols from headers.
1530 EXPECT_THAT(Completions.Completions,
1531 Contains(AllOf(Not(IsDocumented()), Named("func"))));
1532 }
1533
1534 TEST(CompletionTest, NonDocComments) {
1535 MockFSProvider FS;
1536 auto FooCpp = testPath("foo.cpp");
1537 FS.Files[FooCpp] = "";
1538
1539 MockCompilationDatabase CDB;
1540 IgnoreDiagnostics DiagConsumer;
1541 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1542
1543 Annotations Source(R"cpp(
1544 // We ignore namespace comments, for rationale see CodeCompletionStrings.h.
1545 namespace comments_ns {
1546 }
1547
1548 // ------------------
1549 int comments_foo();
1550
1551 // A comment and a decl are separated by newlines.
1552 // Therefore, the comment shouldn't show up as doc comment.
1553
1554 int comments_bar();
1555
1556 // this comment should be in the results.
1557 int comments_baz();
1558
1559
1560 template <class T>
1561 struct Struct {
1562 int comments_qux();
1563 int comments_quux();
1564 };
1565
1566
1567 // This comment should not be there.
1568
1569 template <class T>
1570 int Struct<T>::comments_qux() {
1571 }
1572
1573 // This comment **should** be in results.
1574 template <class T>
1575 int Struct<T>::comments_quux() {
1576 int a = comments^;
1577 }
1578 )cpp");
1579 // FIXME: Auto-completion in a template requires disabling delayed template
1580 // parsing.
1581 CDB.ExtraClangFlags.push_back("-fno-delayed-template-parsing");
1582 runAddDocument(Server, FooCpp, Source.code(), WantDiagnostics::Yes);
1583 CodeCompleteResult Completions = cantFail(runCodeComplete(
1584 Server, FooCpp, Source.point(), clangd::CodeCompleteOptions()));
1585
1586 // We should not get any of those comments in completion.
1587 EXPECT_THAT(
1588 Completions.Completions,
1589 UnorderedElementsAre(AllOf(Not(IsDocumented()), Named("comments_foo")),
1590 AllOf(IsDocumented(), Named("comments_baz")),
1591 AllOf(IsDocumented(), Named("comments_quux")),
1592 AllOf(Not(IsDocumented()), Named("comments_ns")),
1593 // FIXME(ibiryukov): the following items should have
1594 // empty documentation, since they are separated from
1595 // a comment with an empty line. Unfortunately, I
1596 // couldn't make Sema tests pass if we ignore those.
1597 AllOf(IsDocumented(), Named("comments_bar")),
1598 AllOf(IsDocumented(), Named("comments_qux"))));
1599 }
1600
1601 TEST(CompletionTest, CompleteOnInvalidLine) {
1602 auto FooCpp = testPath("foo.cpp");
1603
1604 MockCompilationDatabase CDB;
1605 IgnoreDiagnostics DiagConsumer;
1606 MockFSProvider FS;
1607 FS.Files[FooCpp] = "// empty file";
1608
1609 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1610 // Run completion outside the file range.
1611 Position Pos;
1612 Pos.line = 100;
1613 Pos.character = 0;
1614 EXPECT_THAT_EXPECTED(
1615 runCodeComplete(Server, FooCpp, Pos, clangd::CodeCompleteOptions()),
1616 Failed());
1617 }
1618
1619 TEST(CompletionTest, QualifiedNames) {
1620 auto Results = completions(
1621 R"cpp(
1622 namespace ns { int local; void both(); }
1623 void f() { ::ns::^ }
1624 )cpp",
1625 {func("ns::both"), cls("ns::Index")});
1626 // We get results from both index and sema, with no duplicates.
1627 EXPECT_THAT(
1628 Results.Completions,
1629 UnorderedElementsAre(Scope("ns::"), Scope("ns::"), Scope("ns::")));
1630 }
1631
1632 TEST(CompletionTest, Render) {
1633 CodeCompletion C;
1634 C.Name = "x";
1635 C.Signature = "(bool) const";
1636 C.SnippetSuffix = "(${0:bool})";
1637 C.ReturnType = "int";
1638 C.RequiredQualifier = "Foo::";
1639 C.Scope = "ns::Foo::";
1640 C.Documentation = "This is x().";
1641 C.Includes.emplace_back();
1642 auto &Include = C.Includes.back();
1643 Include.Header = "\"foo.h\"";
1644 C.Kind = CompletionItemKind::Method;
1645 C.Score.Total = 1.0;
1646 C.Score.ExcludingName = .5;
1647 C.Origin = SymbolOrigin::AST | SymbolOrigin::Static;
1648
1649 CodeCompleteOptions Opts;
1650 Opts.IncludeIndicator.Insert = "^";
1651 Opts.IncludeIndicator.NoInsert = "";
1652 Opts.EnableSnippets = false;
1653
1654 auto R = C.render(Opts);
1655 EXPECT_EQ(R.label, "Foo::x(bool) const");
1656 EXPECT_EQ(R.insertText, "Foo::x");
1657 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
1658 EXPECT_EQ(R.filterText, "x");
1659 EXPECT_EQ(R.detail, "int\n\"foo.h\"");
1660 EXPECT_EQ(R.documentation, "This is x().");
1661 EXPECT_THAT(R.additionalTextEdits, IsEmpty());
1662 EXPECT_EQ(R.sortText, sortText(1.0, "x"));
1663 EXPECT_FALSE(R.deprecated);
1664 EXPECT_EQ(R.score, .5f);
1665
1666 Opts.EnableSnippets = true;
1667 R = C.render(Opts);
1668 EXPECT_EQ(R.insertText, "Foo::x(${0:bool})");
1669 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
1670
1671 Include.Insertion.emplace();
1672 R = C.render(Opts);
1673 EXPECT_EQ(R.label, "^Foo::x(bool) const");
1674 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
1675
1676 Opts.ShowOrigins = true;
1677 R = C.render(Opts);
1678 EXPECT_EQ(R.label, "^[AS]Foo::x(bool) const");
1679
1680 C.BundleSize = 2;
1681 R = C.render(Opts);
1682 EXPECT_EQ(R.detail, "[2 overloads]\n\"foo.h\"");
1683
1684 C.Deprecated = true;
1685 R = C.render(Opts);
1686 EXPECT_TRUE(R.deprecated);
1687 }
1688
1689 TEST(CompletionTest, IgnoreRecoveryResults) {
1690 auto Results = completions(
1691 R"cpp(
1692 namespace ns { int NotRecovered() { return 0; } }
1693 void f() {
1694 // Sema enters recovery mode first and then normal mode.
1695 if (auto x = ns::NotRecover^)
1696 }
1697 )cpp");
1698 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("NotRecovered")));
1699 }
1700
1701 TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
1702 auto Results = completions(
1703 R"cpp(
1704 namespace ns {
1705 class X { public: X(); int x_; };
1706 X::X() : x_^(0) {}
1707 }
1708 )cpp");
1709 EXPECT_THAT(Results.Completions,
1710 UnorderedElementsAre(AllOf(Scope("ns::X::"), Named("x_"))));
1711 }
1712
1713 TEST(CompletionTest, CodeCompletionContext) {
1714 auto Results = completions(
1715 R"cpp(
1716 namespace ns {
1717 class X { public: X(); int x_; };
1718 void f() {
1719 X x;
1720 x.^;
1721 }
1722 }
1723 )cpp");
1724
1725 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
1726 }
1727
1728 TEST(CompletionTest, FixItForArrowToDot) {
1729 MockFSProvider FS;
1730 MockCompilationDatabase CDB;
1731 IgnoreDiagnostics DiagConsumer;
1732 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1733
1734 CodeCompleteOptions Opts;
1735 Opts.IncludeFixIts = true;
1736 Annotations TestCode(
1737 R"cpp(
1738 class Auxilary {
1739 public:
1740 void AuxFunction();
1741 };
1742 class ClassWithPtr {
1743 public:
1744 void MemberFunction();
1745 Auxilary* operator->() const;
1746 Auxilary* Aux;
1747 };
1748 void f() {
1749 ClassWithPtr x;
1750 x[[->]]^;
1751 }
1752 )cpp");
1753 auto Results =
1754 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1755 EXPECT_EQ(Results.Completions.size(), 3u);
1756
1757 TextEdit ReplacementEdit;
1758 ReplacementEdit.range = TestCode.range();
1759 ReplacementEdit.newText = ".";
1760 for (const auto &C : Results.Completions) {
1761 EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction");
1762 if (!C.FixIts.empty()) {
1763 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
1764 }
1765 }
1766 }
1767
1768 TEST(CompletionTest, FixItForDotToArrow) {
1769 MockFSProvider FS;
1770 MockCompilationDatabase CDB;
1771 IgnoreDiagnostics DiagConsumer;
1772 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1773
1774 CodeCompleteOptions Opts;
1775 Opts.IncludeFixIts = true;
1776 Annotations TestCode(
1777 R"cpp(
1778 class Auxilary {
1779 public:
1780 void AuxFunction();
1781 };
1782 class ClassWithPtr {
1783 public:
1784 void MemberFunction();
1785 Auxilary* operator->() const;
1786 Auxilary* Aux;
1787 };
1788 void f() {
1789 ClassWithPtr x;
1790 x[[.]]^;
1791 }
1792 )cpp");
1793 auto Results =
1794 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1795 EXPECT_EQ(Results.Completions.size(), 3u);
1796
1797 TextEdit ReplacementEdit;
1798 ReplacementEdit.range = TestCode.range();
1799 ReplacementEdit.newText = "->";
1800 for (const auto &C : Results.Completions) {
1801 EXPECT_TRUE(C.FixIts.empty() || C.Name == "AuxFunction");
1802 if (!C.FixIts.empty()) {
1803 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
1804 }
1805 }
1806 }
1807
1808 TEST(CompletionTest, RenderWithFixItMerged) {
1809 TextEdit FixIt;
1810 FixIt.range.end.character = 5;
1811 FixIt.newText = "->";
1812
1813 CodeCompletion C;
1814 C.Name = "x";
1815 C.RequiredQualifier = "Foo::";
1816 C.FixIts = {FixIt};
1817 C.CompletionTokenRange.start.character = 5;
1818
1819 CodeCompleteOptions Opts;
1820 Opts.IncludeFixIts = true;
1821
1822 auto R = C.render(Opts);
1823 EXPECT_TRUE(R.textEdit);
1824 EXPECT_EQ(R.textEdit->newText, "->Foo::x");
1825 EXPECT_TRUE(R.additionalTextEdits.empty());
1826 }
1827
1828 TEST(CompletionTest, RenderWithFixItNonMerged) {
1829 TextEdit FixIt;
1830 FixIt.range.end.character = 4;
1831 FixIt.newText = "->";
1832
1833 CodeCompletion C;
1834 C.Name = "x";
1835 C.RequiredQualifier = "Foo::";
1836 C.FixIts = {FixIt};
1837 C.CompletionTokenRange.start.character = 5;
1838
1839 CodeCompleteOptions Opts;
1840 Opts.IncludeFixIts = true;
1841
1842 auto R = C.render(Opts);
1843 EXPECT_TRUE(R.textEdit);
1844 EXPECT_EQ(R.textEdit->newText, "Foo::x");
1845 EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
1846 }
1847
1848 TEST(CompletionTest, CompletionTokenRange) {
1849 MockFSProvider FS;
1850 MockCompilationDatabase CDB;
1851 IgnoreDiagnostics DiagConsumer;
1852 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1853
1854 constexpr const char *TestCodes[] = {
1855 R"cpp(
1856 class Auxilary {
1857 public:
1858 void AuxFunction();
1859 };
1860 void f() {
1861 Auxilary x;
1862 x.[[Aux]]^;
1863 }
1864 )cpp",
1865 R"cpp(
1866 class Auxilary {
1867 public:
1868 void AuxFunction();
1869 };
1870 void f() {
1871 Auxilary x;
1872 x.[[]]^;
1873 }
1874 )cpp"};
1875 for (const auto &Text : TestCodes) {
1876 Annotations TestCode(Text);
1877 auto Results = completions(Server, TestCode.code(), TestCode.point());
1878
1879 if (Results.Completions.size() != 1) {
1880 ADD_FAILURE() << "Results.Completions.size() != 1";
1881 continue;
1882 }
1883 EXPECT_THAT(Results.Completions.front().CompletionTokenRange,
1884 TestCode.range());
1885 }
1886 }
1887
1888 TEST(SignatureHelpTest, OverloadsOrdering) {
1889 const auto Results = signatures(R"cpp(
1890 void foo(int x);
1891 void foo(int x, float y);
1892 void foo(float x, int y);
1893 void foo(float x, float y);
1894 void foo(int x, int y = 0);
1895 int main() { foo(^); }
1896 )cpp");
1897 EXPECT_THAT(Results.signatures,
1898 ElementsAre(Sig("foo([[int x]]) -> void"),
1899 Sig("foo([[int x]], [[int y = 0]]) -> void"),
1900 Sig("foo([[float x]], [[int y]]) -> void"),
1901 Sig("foo([[int x]], [[float y]]) -> void"),
1902 Sig("foo([[float x]], [[float y]]) -> void")));
1903 // We always prefer the first signature.
1904 EXPECT_EQ(0, Results.activeSignature);
1905 EXPECT_EQ(0, Results.activeParameter);
1906 }
1907
1908 TEST(SignatureHelpTest, InstantiatedSignatures) {
1909 StringRef Sig0 = R"cpp(
1910 template <class T>
1911 void foo(T, T, T);
1912
1913 int main() {
1914 foo<int>(^);
1915 }
1916 )cpp";
1917
1918 EXPECT_THAT(signatures(Sig0).signatures,
1919 ElementsAre(Sig("foo([[T]], [[T]], [[T]]) -> void")));
1920
1921 StringRef Sig1 = R"cpp(
1922 template <class T>
1923 void foo(T, T, T);
1924
1925 int main() {
1926 foo(10, ^);
1927 })cpp";
1928
1929 EXPECT_THAT(signatures(Sig1).signatures,
1930 ElementsAre(Sig("foo([[T]], [[T]], [[T]]) -> void")));
1931
1932 StringRef Sig2 = R"cpp(
1933 template <class ...T>
1934 void foo(T...);
1935
1936 int main() {
1937 foo<int>(^);
1938 }
1939 )cpp";
1940
1941 EXPECT_THAT(signatures(Sig2).signatures,
1942 ElementsAre(Sig("foo([[T...]]) -> void")));
1943
1944 // It is debatable whether we should substitute the outer template parameter
1945 // ('T') in that case. Currently we don't substitute it in signature help, but
1946 // do substitute in code complete.
1947 // FIXME: make code complete and signature help consistent, figure out which
1948 // way is better.
1949 StringRef Sig3 = R"cpp(
1950 template <class T>
1951 struct X {
1952 template <class U>
1953 void foo(T, U);
1954 };
1955
1956 int main() {
1957 X<int>().foo<double>(^)
1958 }
1959 )cpp";
1960
1961 EXPECT_THAT(signatures(Sig3).signatures,
1962 ElementsAre(Sig("foo([[T]], [[U]]) -> void")));
1963 }
1964
1965 TEST(SignatureHelpTest, IndexDocumentation) {
1966 Symbol Foo0 = sym("foo", index::SymbolKind::Function, "@F@\\0#");
1967 Foo0.Documentation = "Doc from the index";
1968 Symbol Foo1 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#");
1969 Foo1.Documentation = "Doc from the index";
1970 Symbol Foo2 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#I#");
1971
1972 StringRef Sig0 = R"cpp(
1973 int foo();
1974 int foo(double);
1975
1976 void test() {
1977 foo(^);
1978 }
1979 )cpp";
1980
1981 EXPECT_THAT(
1982 signatures(Sig0, {Foo0}).signatures,
1983 ElementsAre(AllOf(Sig("foo() -> int"), SigDoc("Doc from the index")),
1984 AllOf(Sig("foo([[double]]) -> int"), SigDoc(""))));
1985
1986 StringRef Sig1 = R"cpp(
1987 int foo();
1988 // Overriden doc from sema
1989 int foo(int);
1990 // Doc from sema
1991 int foo(int, int);
1992
1993 void test() {
1994 foo(^);
1995 }
1996 )cpp";
1997
1998 EXPECT_THAT(
1999 signatures(Sig1, {Foo0, Foo1, Foo2}).signatures,
2000 ElementsAre(
2001 AllOf(Sig("foo() -> int"), SigDoc("Doc from the index")),
2002 AllOf(Sig("foo([[int]]) -> int"), SigDoc("Overriden doc from sema")),
2003 AllOf(Sig("foo([[int]], [[int]]) -> int"), SigDoc("Doc from sema"))));
2004 }
2005
2006 TEST(SignatureHelpTest, DynamicIndexDocumentation) {
2007 MockFSProvider FS;
2008 MockCompilationDatabase CDB;
2009 IgnoreDiagnostics DiagConsumer;
2010 ClangdServer::Options Opts = ClangdServer::optsForTest();
2011 Opts.BuildDynamicSymbolIndex = true;
2012 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
2013
2014 FS.Files[testPath("foo.h")] = R"cpp(
2015 struct Foo {
2016 // Member doc
2017 int foo();
2018 };
2019 )cpp";
2020 Annotations FileContent(R"cpp(
2021 #include "foo.h"
2022 void test() {
2023 Foo f;
2024 f.foo(^);
2025 }
2026 )cpp");
2027 auto File = testPath("test.cpp");
2028 Server.addDocument(File, FileContent.code());
2029 // Wait for the dynamic index being built.
2030 ASSERT_TRUE(Server.blockUntilIdleForTest());
2031 EXPECT_THAT(
2032 llvm::cantFail(runSignatureHelp(Server, File, FileContent.point()))
2033 .signatures,
2034 ElementsAre(AllOf(Sig("foo() -> int"), SigDoc("Member doc"))));
2035 }
2036
2037 TEST(CompletionTest, CompletionFunctionArgsDisabled) {
2038 CodeCompleteOptions Opts;
2039 Opts.EnableSnippets = true;
2040 Opts.EnableFunctionArgSnippets = false;
2041
2042 {
2043 auto Results = completions(
2044 R"cpp(
2045 void xfoo();
2046 void xfoo(int x, int y);
2047 void f() { xfo^ })cpp",
2048 {}, Opts);
2049 EXPECT_THAT(
2050 Results.Completions,
2051 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("()")),
2052 AllOf(Named("xfoo"), SnippetSuffix("($0)"))));
2053 }
2054 {
2055 auto Results = completions(
2056 R"cpp(
2057 void xbar();
2058 void f() { xba^ })cpp",
2059 {}, Opts);
2060 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
2061 Named("xbar"), SnippetSuffix("()"))));
2062 }
2063 {
2064 Opts.BundleOverloads = true;
2065 auto Results = completions(
2066 R"cpp(
2067 void xfoo();
2068 void xfoo(int x, int y);
2069 void f() { xfo^ })cpp",
2070 {}, Opts);
2071 EXPECT_THAT(
2072 Results.Completions,
2073 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("($0)"))));
2074 }
2075 {
2076 auto Results = completions(
2077 R"cpp(
2078 template <class T, class U>
2079 void xfoo(int a, U b);
2080 void f() { xfo^ })cpp",
2081 {}, Opts);
2082 EXPECT_THAT(
2083 Results.Completions,
2084 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("<$1>($0)"))));
2085 }
2086 {
2087 auto Results = completions(
2088 R"cpp(
2089 template <class T>
2090 class foo_class{};
2091 template <class T>
2092 using foo_alias = T**;
2093 void f() { foo_^ })cpp",
2094 {}, Opts);
2095 EXPECT_THAT(
2096 Results.Completions,
2097 UnorderedElementsAre(AllOf(Named("foo_class"), SnippetSuffix("<$0>")),
2098 AllOf(Named("foo_alias"), SnippetSuffix("<$0>"))));
2099 }
2100 }
2101
2102 TEST(CompletionTest, SuggestOverrides) {
2103 constexpr const char *const Text(R"cpp(
2104 class A {
2105 public:
2106 virtual void vfunc(bool param);
2107 virtual void vfunc(bool param, int p);
2108 void func(bool param);
2109 };
2110 class B : public A {
2111 virtual void ttt(bool param) const;
2112 void vfunc(bool param, int p) override;
2113 };
2114 class C : public B {
2115 public:
2116 void vfunc(bool param) override;
2117 ^
2118 };
2119 )cpp");
2120 const auto Results = completions(Text);
2121 EXPECT_THAT(
2122 Results.Completions,
2123 AllOf(Contains(AllOf(Labeled("void vfunc(bool param, int p) override"),
2124 NameStartsWith("vfunc"))),
2125 Contains(AllOf(Labeled("void ttt(bool param) const override"),
2126 NameStartsWith("ttt"))),
2127 Not(Contains(Labeled("void vfunc(bool param) override")))));
2128 }
2129
2130 TEST(CompletionTest, OverridesNonIdentName) {
2131 // Check the completions call does not crash.
2132 completions(R"cpp(
2133 struct Base {
2134 virtual ~Base() = 0;
2135 virtual operator int() = 0;
2136 virtual Base& operator+(Base&) = 0;
2137 };
2138
2139 struct Derived : Base {
2140 ^
2141 };
2142 )cpp");
2143 }
2144
2145 TEST(GuessCompletionPrefix, Filters) {
2146 for (llvm::StringRef Case : {
2147 "[[scope::]][[ident]]^",
2148 "[[]][[]]^",
2149 "\n[[]][[]]^",
2150 "[[]][[ab]]^",
2151 "x.[[]][[ab]]^",
2152 "x.[[]][[]]^",
2153 "[[x::]][[ab]]^",
2154 "[[x::]][[]]^",
2155 "[[::x::]][[ab]]^",
2156 "some text [[scope::more::]][[identif]]^ier",
2157 "some text [[scope::]][[mor]]^e::identifier",
2158 "weird case foo::[[::bar::]][[baz]]^",
2159 }) {
2160 Annotations F(Case);
2161 auto Offset = cantFail(positionToOffset(F.code(), F.point()));
2162 auto ToStringRef = [&](Range R) {
2163 return F.code().slice(cantFail(positionToOffset(F.code(), R.start)),
2164 cantFail(positionToOffset(F.code(), R.end)));
2165 };
2166 auto WantQualifier = ToStringRef(F.ranges()[0]),
2167 WantName = ToStringRef(F.ranges()[1]);
2168
2169 auto Prefix = guessCompletionPrefix(F.code(), Offset);
2170 // Even when components are empty, check their offsets are correct.
2171 EXPECT_EQ(WantQualifier, Prefix.Qualifier) << Case;
2172 EXPECT_EQ(WantQualifier.begin(), Prefix.Qualifier.begin()) << Case;
2173 EXPECT_EQ(WantName, Prefix.Name) << Case;
2174 EXPECT_EQ(WantName.begin(), Prefix.Name.begin()) << Case;
2175 }
2176 }
2177
2178 TEST(CompletionTest, EnableSpeculativeIndexRequest) {
2179 MockFSProvider FS;
2180 MockCompilationDatabase CDB;
2181 IgnoreDiagnostics DiagConsumer;
2182 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
2183
2184 auto File = testPath("foo.cpp");
2185 Annotations Test(R"cpp(
2186 namespace ns1 { int abc; }
2187 namespace ns2 { int abc; }
2188 void f() { ns1::ab$1^; ns1::ab$2^; }
2189 void f2() { ns2::ab$3^; }
2190 )cpp");
2191 runAddDocument(Server, File, Test.code());
2192 clangd::CodeCompleteOptions Opts = {};
2193
2194 IndexRequestCollector Requests;
2195 Opts.Index = &Requests;
2196 Opts.SpeculativeIndexRequest = true;
2197
2198 auto CompleteAtPoint = [&](StringRef P) {
2199 cantFail(runCodeComplete(Server, File, Test.point(P), Opts));
2200 };
2201
2202 CompleteAtPoint("1");
2203 auto Reqs1 = Requests.consumeRequests(1);
2204 ASSERT_EQ(Reqs1.size(), 1u);
2205 EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre("ns1::"));
2206
2207 CompleteAtPoint("2");
2208 auto Reqs2 = Requests.consumeRequests(1);
2209 // Speculation succeeded. Used speculative index result.
2210 ASSERT_EQ(Reqs2.size(), 1u);
2211 EXPECT_EQ(Reqs2[0], Reqs1[0]);
2212
2213 CompleteAtPoint("3");
2214 // Speculation failed. Sent speculative index request and the new index
2215 // request after sema.
2216 auto Reqs3 = Requests.consumeRequests(2);
2217 ASSERT_EQ(Reqs3.size(), 2u);
2218 }
2219
2220 TEST(CompletionTest, InsertTheMostPopularHeader) {
2221 std::string DeclFile = URI::create(testPath("foo")).toString();
2222 Symbol Sym = func("Func");
2223 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2224 Sym.IncludeHeaders.emplace_back("\"foo.h\"", 2);
2225 Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000);
2226
2227 auto Results = completions("Fun^", {Sym}).Completions;
2228 assert(!Results.empty());
2229 EXPECT_THAT(Results[0], AllOf(Named("Func"), InsertInclude("\"bar.h\"")));
2230 EXPECT_EQ(Results[0].Includes.size(), 2u);
2231 }
2232
2233 TEST(CompletionTest, NoInsertIncludeIfOnePresent) {
2234 MockFSProvider FS;
2235 MockCompilationDatabase CDB;
2236
2237 std::string FooHeader = testPath("foo.h");
2238 FS.Files[FooHeader] = "";
2239
2240 IgnoreDiagnostics DiagConsumer;
2241 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
2242
2243 std::string DeclFile = URI::create(testPath("foo")).toString();
2244 Symbol Sym = func("Func");
2245 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2246 Sym.IncludeHeaders.emplace_back("\"foo.h\"", 2);
2247 Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000);
2248
2249 EXPECT_THAT(
2250 completions(Server, "#include \"foo.h\"\nFun^", {Sym}).Completions,
2251 UnorderedElementsAre(
2252 AllOf(Named("Func"), HasInclude("\"foo.h\""), Not(InsertInclude()))));
2253 }
2254
2255 TEST(CompletionTest, MergeMacrosFromIndexAndSema) {
2256 Symbol Sym;
2257 Sym.Name = "Clangd_Macro_Test";
2258 Sym.ID = SymbolID("c:foo.cpp@8@macro@Clangd_Macro_Test");
2259 Sym.SymInfo.Kind = index::SymbolKind::Macro;
2260 Sym.Flags |= Symbol::IndexedForCodeCompletion;
2261 EXPECT_THAT(completions("#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym})
2262 .Completions,
2263 UnorderedElementsAre(Named("Clangd_Macro_Test")));
2264 }
2265
2266 TEST(CompletionTest, MacroFromPreamble) {
2267 MockFSProvider FS;
2268 MockCompilationDatabase CDB;
2269 std::string FooHeader = testPath("foo.h");
2270 FS.Files[FooHeader] = "#define CLANGD_PREAMBLE_HEADER x\n";
2271 IgnoreDiagnostics DiagConsumer;
2272 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
2273 auto Results = completions(
2274 R"cpp(#include "foo.h"
2275 #define CLANGD_PREAMBLE_MAIN x
2276
2277 int x = 0;
2278 #define CLANGD_MAIN x
2279 void f() { CLANGD_^ }
2280 )cpp",
2281 {func("CLANGD_INDEX")});
2282 // We should get results from the main file, including the preamble section.
2283 // However no results from included files (the index should cover them).
2284 EXPECT_THAT(Results.Completions,
2285 UnorderedElementsAre(Named("CLANGD_PREAMBLE_MAIN"),
2286 Named("CLANGD_MAIN"),
2287 Named("CLANGD_INDEX")));
2288 }
2289
2290 TEST(CompletionTest, DeprecatedResults) {
2291 std::string Body = R"cpp(
2292 void TestClangd();
2293 void TestClangc() __attribute__((deprecated("", "")));
2294 )cpp";
2295
2296 EXPECT_THAT(
2297 completions(Body + "int main() { TestClang^ }").Completions,
2298 UnorderedElementsAre(AllOf(Named("TestClangd"), Not(Deprecated())),
2299 AllOf(Named("TestClangc"), Deprecated())));
2300 }
2301
2302 TEST(SignatureHelpTest, InsideArgument) {
2303 {
2304 const auto Results = signatures(R"cpp(
2305 void foo(int x);
2306 void foo(int x, int y);
2307 int main() { foo(1+^); }
2308 )cpp");
2309 EXPECT_THAT(Results.signatures,
2310 ElementsAre(Sig("foo([[int x]]) -> void"),
2311 Sig("foo([[int x]], [[int y]]) -> void")));
2312 EXPECT_EQ(0, Results.activeParameter);
2313 }
2314 {
2315 const auto Results = signatures(R"cpp(
2316 void foo(int x);
2317 void foo(int x, int y);
2318 int main() { foo(1^); }
2319 )cpp");
2320 EXPECT_THAT(Results.signatures,
2321 ElementsAre(Sig("foo([[int x]]) -> void"),
2322 Sig("foo([[int x]], [[int y]]) -> void")));
2323 EXPECT_EQ(0, Results.activeParameter);
2324 }
2325 {
2326 const auto Results = signatures(R"cpp(
2327 void foo(int x);
2328 void foo(int x, int y);
2329 int main() { foo(1^0); }
2330 )cpp");
2331 EXPECT_THAT(Results.signatures,
2332 ElementsAre(Sig("foo([[int x]]) -> void"),
2333 Sig("foo([[int x]], [[int y]]) -> void")));
2334 EXPECT_EQ(0, Results.activeParameter);
2335 }
2336 {
2337 const auto Results = signatures(R"cpp(
2338 void foo(int x);
2339 void foo(int x, int y);
2340 int bar(int x, int y);
2341 int main() { bar(foo(2, 3^)); }
2342 )cpp");
2343 EXPECT_THAT(Results.signatures,
2344 ElementsAre(Sig("foo([[int x]], [[int y]]) -> void")));
2345 EXPECT_EQ(1, Results.activeParameter);
2346 }
2347 }
2348
2349 TEST(SignatureHelpTest, ConstructorInitializeFields) {
2350 {
2351 const auto Results = signatures(R"cpp(
2352 struct A {
2353 A(int);
2354 };
2355 struct B {
2356 B() : a_elem(^) {}
2357 A a_elem;
2358 };
2359 )cpp");
2360 EXPECT_THAT(Results.signatures,
2361 UnorderedElementsAre(Sig("A([[int]])"), Sig("A([[A &&]])"),
2362 Sig("A([[const A &]])")));
2363 }
2364 {
2365 const auto Results = signatures(R"cpp(
2366 struct A {
2367 A(int);
2368 };
2369 struct C {
2370 C(int);
2371 C(A);
2372 };
2373 struct B {
2374 B() : c_elem(A(1^)) {}
2375 C c_elem;
2376 };
2377 )cpp");
2378 EXPECT_THAT(Results.signatures,
2379 UnorderedElementsAre(Sig("A([[int]])"), Sig("A([[A &&]])"),
2380 Sig("A([[const A &]])")));
2381 }
2382 }
2383
2384 TEST(CompletionTest, IncludedCompletionKinds) {
2385 MockFSProvider FS;
2386 MockCompilationDatabase CDB;
2387 std::string Subdir = testPath("sub");
2388 std::string SearchDirArg = (Twine("-I") + Subdir).str();
2389 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
2390 std::string BarHeader = testPath("sub/bar.h");
2391 FS.Files[BarHeader] = "";
2392 IgnoreDiagnostics DiagConsumer;
2393 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
2394 auto Results = completions(Server,
2395 R"cpp(
2396 #include "^"
2397 )cpp");
2398 EXPECT_THAT(Results.Completions,
2399 AllOf(Has("sub/", CompletionItemKind::Folder),
2400 Has("bar.h\"", CompletionItemKind::File)));
2401 }
2402
2403 TEST(CompletionTest, NoCrashAtNonAlphaIncludeHeader) {
2404 auto Results = completions(
2405 R"cpp(
2406 #include "./^"
2407 )cpp");
2408 EXPECT_TRUE(Results.Completions.empty());
2409 }
2410
2411 TEST(CompletionTest, NoAllScopesCompletionWhenQualified) {
2412 clangd::CodeCompleteOptions Opts = {};
2413 Opts.AllScopes = true;
2414
2415 auto Results = completions(
2416 R"cpp(
2417 void f() { na::Clangd^ }
2418 )cpp",
2419 {cls("na::ClangdA"), cls("nx::ClangdX"), cls("Clangd3")}, Opts);
2420 EXPECT_THAT(Results.Completions,
2421 UnorderedElementsAre(
2422 AllOf(Qualifier(""), Scope("na::"), Named("ClangdA"))));
2423 }
2424
2425 TEST(CompletionTest, AllScopesCompletion) {
2426 clangd::CodeCompleteOptions Opts = {};
2427 Opts.AllScopes = true;
2428
2429 auto Results = completions(
2430 R"cpp(
2431 namespace na {
2432 void f() { Clangd^ }
2433 }
2434 )cpp",
2435 {cls("nx::Clangd1"), cls("ny::Clangd2"), cls("Clangd3"),
2436 cls("na::nb::Clangd4")},
2437 Opts);
2438 EXPECT_THAT(
2439 Results.Completions,
2440 UnorderedElementsAre(AllOf(Qualifier("nx::"), Named("Clangd1")),
2441 AllOf(Qualifier("ny::"), Named("Clangd2")),
2442 AllOf(Qualifier(""), Scope(""), Named("Clangd3")),
2443 AllOf(Qualifier("nb::"), Named("Clangd4"))));
2444 }
2445
2446 TEST(CompletionTest, NoQualifierIfShadowed) {
2447 clangd::CodeCompleteOptions Opts = {};
2448 Opts.AllScopes = true;
2449
2450 auto Results = completions(R"cpp(
2451 namespace nx { class Clangd1 {}; }
2452 using nx::Clangd1;
2453 void f() { Clangd^ }
2454 )cpp",
2455 {cls("nx::Clangd1"), cls("nx::Clangd2")}, Opts);
2456 // Although Clangd1 is from another namespace, Sema tells us it's in-scope and
2457 // needs no qualifier.
2458 EXPECT_THAT(Results.Completions,
2459 UnorderedElementsAre(AllOf(Qualifier(""), Named("Clangd1")),
2460 AllOf(Qualifier("nx::"), Named("Clangd2"))));
2461 }
2462
2463 TEST(CompletionTest, NoCompletionsForNewNames) {
2464 clangd::CodeCompleteOptions Opts;
2465 Opts.AllScopes = true;
2466 auto Results = completions(R"cpp(
2467 void f() { int n^ }
2468 )cpp",
2469 {cls("naber"), cls("nx::naber")}, Opts);
2470 EXPECT_THAT(Results.Completions, UnorderedElementsAre());
2471 }
2472
2473 TEST(CompletionTest, Lambda) {
2474 clangd::CodeCompleteOptions Opts = {};
2475
2476 auto Results = completions(R"cpp(
2477 void function() {
2478 auto Lambda = [](int a, const double &b) {return 1.f;};
2479 Lam^
2480 }
2481 )cpp",
2482 {}, Opts);
2483
2484 ASSERT_EQ(Results.Completions.size(), 1u);
2485 const auto &A = Results.Completions.front();
2486 EXPECT_EQ(A.Name, "Lambda");
2487 EXPECT_EQ(A.Signature, "(int a, const double &b) const");
2488 EXPECT_EQ(A.Kind, CompletionItemKind::Variable);
2489 EXPECT_EQ(A.ReturnType, "float");
2490 EXPECT_EQ(A.SnippetSuffix, "(${1:int a}, ${2:const double &b})");
2491 }
2492
2493 TEST(CompletionTest, ObjectiveCMethodNoArguments) {
2494 auto Results = completions(R"objc(
2495 @interface Foo
2496 @property(nonatomic, setter=setXToIgnoreComplete:) int value;
2497 @end
2498 Foo *foo = [Foo new]; int y = [foo v^]
2499 )objc",
2500 /*IndexSymbols=*/{},
2501 /*Opts=*/{}, "Foo.m");
2502
2503 auto C = Results.Completions;
2504 EXPECT_THAT(C, ElementsAre(Named("value")));
2505 EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method)));
2506 EXPECT_THAT(C, ElementsAre(ReturnType("int")));
2507 EXPECT_THAT(C, ElementsAre(Signature("")));
2508 EXPECT_THAT(C, ElementsAre(SnippetSuffix("")));
2509 }
2510
2511 TEST(CompletionTest, ObjectiveCMethodOneArgument) {
2512 auto Results = completions(R"objc(
2513 @interface Foo
2514 - (int)valueForCharacter:(char)c;
2515 @end
2516 Foo *foo = [Foo new]; int y = [foo v^]
2517 )objc",
2518 /*IndexSymbols=*/{},
2519 /*Opts=*/{}, "Foo.m");
2520
2521 auto C = Results.Completions;
2522 EXPECT_THAT(C, ElementsAre(Named("valueForCharacter:")));
2523 EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method)));
2524 EXPECT_THAT(C, ElementsAre(ReturnType("int")));
2525 EXPECT_THAT(C, ElementsAre(Signature("(char)")));
2526 EXPECT_THAT(C, ElementsAre(SnippetSuffix("${1:(char)}")));
2527 }
2528
2529 TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromBeginning) {
2530 auto Results = completions(R"objc(
2531 @interface Foo
2532 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;
2533 @end
2534 id val = [Foo foo^]
2535 )objc",
2536 /*IndexSymbols=*/{},
2537 /*Opts=*/{}, "Foo.m");
2538
2539 auto C = Results.Completions;
2540 EXPECT_THAT(C, ElementsAre(Named("fooWithValue:")));
2541 EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method)));
2542 EXPECT_THAT(C, ElementsAre(ReturnType("id")));
2543 EXPECT_THAT(C, ElementsAre(Signature("(int) fooey:(unsigned int)")));
2544 EXPECT_THAT(
2545 C, ElementsAre(SnippetSuffix("${1:(int)} fooey:${2:(unsigned int)}")));
2546 }
2547
2548 TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
2549 auto Results = completions(R"objc(
2550 @interface Foo
2551 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;
2552 @end
2553 id val = [Foo fooWithValue:10 f^]
2554 )objc",
2555 /*IndexSymbols=*/{},
2556 /*Opts=*/{}, "Foo.m");
2557
2558 auto C = Results.Completions;
2559 EXPECT_THAT(C, ElementsAre(Named("fooey:")));
2560 EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method)));
2561 EXPECT_THAT(C, ElementsAre(ReturnType("id")));
2562 EXPECT_THAT(C, ElementsAre(Signature("(unsigned int)")));
2563 EXPECT_THAT(C, ElementsAre(SnippetSuffix("${1:(unsigned int)}")));
2564 }
2565
2566 TEST(CompletionTest, CursorInSnippets) {
2567 clangd::CodeCompleteOptions Options;
2568 Options.EnableSnippets = true;
2569 auto Results = completions(
2570 R"cpp(
2571 void while_foo(int a, int b);
2572 void test() {
2573 whil^
2574 })cpp",
2575 /*IndexSymbols=*/{}, Options);
2576
2577 // Last placeholder in code patterns should be $0 to put the cursor there.
2578 EXPECT_THAT(Results.Completions,
2579 Contains(AllOf(
2580 Named("while"),
2581 SnippetSuffix(" (${1:condition}) {\n${0:statements}\n}"))));
2582 // However, snippets for functions must *not* end with $0.
2583 EXPECT_THAT(Results.Completions,
2584 Contains(AllOf(Named("while_foo"),
2585 SnippetSuffix("(${1:int a}, ${2:int b})"))));
2586 }
2587
2588 TEST(CompletionTest, WorksWithNullType) {
2589 auto R = completions(R"cpp(
2590 int main() {
2591 for (auto [loopVar] : y ) { // y has to be unresolved.
2592 int z = loopV^;
2593 }
2594 }
2595 )cpp");
2596 EXPECT_THAT(R.Completions, ElementsAre(Named("loopVar")));
2597 }
2598
2599 TEST(CompletionTest, UsingDecl) {
2600 const char *Header(R"cpp(
2601 void foo(int);
2602 namespace std {
2603 using ::foo;
2604 })cpp");
2605 const char *Source(R"cpp(
2606 void bar() {
2607 std::^;
2608 })cpp");
2609 auto Index = TestTU::withHeaderCode(Header).index();
2610 clangd::CodeCompleteOptions Opts;
2611 Opts.Index = Index.get();
2612 Opts.AllScopes = true;
2613 auto R = completions(Source, {}, Opts);
2614 EXPECT_THAT(R.Completions,
2615 ElementsAre(AllOf(Scope("std::"), Named("foo"),
2616 Kind(CompletionItemKind::Reference))));
2617 }
2618
2619 TEST(CompletionTest, ScopeIsUnresolved) {
2620 clangd::CodeCompleteOptions Opts = {};
2621 Opts.AllScopes = true;
2622
2623 auto Results = completions(R"cpp(
2624 namespace a {
2625 void f() { b::X^ }
2626 }
2627 )cpp",
2628 {cls("a::b::XYZ")}, Opts);
2629 EXPECT_THAT(Results.Completions,
2630 UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ"))));
2631 }
2632
2633 TEST(CompletionTest, NestedScopeIsUnresolved) {
2634 clangd::CodeCompleteOptions Opts = {};
2635 Opts.AllScopes = true;
2636
2637 auto Results = completions(R"cpp(
2638 namespace a {
2639 namespace b {}
2640 void f() { b::c::X^ }
2641 }
2642 )cpp",
2643 {cls("a::b::c::XYZ")}, Opts);
2644 EXPECT_THAT(Results.Completions,
2645 UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ"))));
2646 }
2647
2648 // Clang parser gets confused here and doesn't report the ns:: prefix.
2649 // Naive behavior is to insert it again. We examine the source and recover.
2650 TEST(CompletionTest, NamespaceDoubleInsertion) {
2651 clangd::CodeCompleteOptions Opts = {};
2652
2653 auto Results = completions(R"cpp(
2654 namespace foo {
2655 namespace ns {}
2656 #define M(X) < X
2657 M(ns::ABC^
2658 }
2659 )cpp",
2660 {cls("foo::ns::ABCDE")}, Opts);
2661 EXPECT_THAT(Results.Completions,
2662 UnorderedElementsAre(AllOf(Qualifier(""), Named("ABCDE"))));
2663 }
2664
2665 TEST(CompletionTest, DerivedMethodsAreAlwaysVisible) {
2666 // Despite the fact that base method matches the ref-qualifier better,
2667 // completion results should only include the derived method.
2668 auto Completions = completions(R"cpp(
2669 struct deque_base {
2670 float size();
2671 double size() const;
2672 };
2673 struct deque : deque_base {
2674 int size() const;
2675 };
2676
2677 auto x = deque().^
2678 )cpp")
2679 .Completions;
2680 EXPECT_THAT(Completions,
2681 ElementsAre(AllOf(ReturnType("int"), Named("size"))));
2682 }
2683
2684 TEST(NoCompileCompletionTest, Basic) {
2685 auto Results = completionsNoCompile(R"cpp(
2686 void func() {
2687 int xyz;
2688 int abc;
2689 ^
2690 }
2691 )cpp");
2692 EXPECT_FALSE(Results.RanParser);
2693 EXPECT_THAT(Results.Completions,
2694 UnorderedElementsAre(Named("void"), Named("func"), Named("int"),
2695 Named("xyz"), Named("abc")));
2696 }
2697
2698 TEST(NoCompileCompletionTest, WithFilter) {
2699 auto Results = completionsNoCompile(R"cpp(
2700 void func() {
2701 int sym1;
2702 int sym2;
2703 int xyz1;
2704 int xyz2;
2705 sy^
2706 }
2707 )cpp");
2708 EXPECT_THAT(Results.Completions,
2709 UnorderedElementsAre(Named("sym1"), Named("sym2")));
2710 }
2711
2712 TEST(NoCompileCompletionTest, WithIndex) {
2713 std::vector<Symbol> Syms = {func("xxx"), func("a::xxx"), func("ns::b::xxx"),
2714 func("c::xxx"), func("ns::d::xxx")};
2715 auto Results = completionsNoCompile(
2716 R"cpp(
2717 // Current-scopes, unqualified completion.
2718 using namespace a;
2719 namespace ns {
2720 using namespace b;
2721 void foo() {
2722 xx^
2723 }
2724 }
2725 )cpp",
2726 Syms);
2727 EXPECT_THAT(Results.Completions,
2728 UnorderedElementsAre(AllOf(Qualifier(""), Scope("")),
2729 AllOf(Qualifier(""), Scope("a::")),
2730 AllOf(Qualifier(""), Scope("ns::b::"))));
2731 CodeCompleteOptions Opts;
2732 Opts.AllScopes = true;
2733 Results = completionsNoCompile(
2734 R"cpp(
2735 // All-scopes unqualified completion.
2736 using namespace a;
2737 namespace ns {
2738 using namespace b;
2739 void foo() {
2740 xx^
2741 }
2742 }
2743 )cpp",
2744 Syms, Opts);
2745 EXPECT_THAT(Results.Completions,
2746 UnorderedElementsAre(AllOf(Qualifier(""), Scope("")),
2747 AllOf(Qualifier(""), Scope("a::")),
2748 AllOf(Qualifier(""), Scope("ns::b::")),
2749 AllOf(Qualifier("c::"), Scope("c::")),
2750 AllOf(Qualifier("d::"), Scope("ns::d::"))));
2751 Results = completionsNoCompile(
2752 R"cpp(
2753 // Qualified completion.
2754 using namespace a;
2755 namespace ns {
2756 using namespace b;
2757 void foo() {
2758 b::xx^
2759 }
2760 }
2761 )cpp",
2762 Syms, Opts);
2763 EXPECT_THAT(Results.Completions,
2764 ElementsAre(AllOf(Qualifier(""), Scope("ns::b::"))));
2765 Results = completionsNoCompile(
2766 R"cpp(
2767 // Absolutely qualified completion.
2768 using namespace a;
2769 namespace ns {
2770 using namespace b;
2771 void foo() {
2772 ::a::xx^
2773 }
2774 }
2775 )cpp",
2776 Syms, Opts);
2777 EXPECT_THAT(Results.Completions,
2778 ElementsAre(AllOf(Qualifier(""), Scope("a::"))));
2779 }
2780
2781 } // namespace
2782 } // namespace clangd
2783 } // namespace clang
Limit
int Limit
Definition: FindSymbolsTests.cpp:71
Code
std::string Code
Definition: FindTargetTests.cpp:67
clang::clangd::MATCHER_P
MATCHER_P(Named, N, "")
Definition: BackgroundIndexTests.cpp:26
clang::clangd::runCodeComplete
llvm::Expected< CodeCompleteResult > runCodeComplete(ClangdServer &Server, PathRef File, Position Pos, clangd::CodeCompleteOptions Opts)
Definition: SyncAPI.cpp:71
clang::clangd::CompletionItemKind::Property
clang::clangd::cls
Symbol cls(llvm::StringRef Name)
Definition: TestIndex.cpp:64
Index.h
ClangdServer.h
clang::clangd::InsertTextFormat::Snippet
The primary text to be inserted is treated as a snippet.
clang::clangd::CompletionItemKind::Class
clang::clangd::runSignatureHelp
llvm::Expected< SignatureHelp > runSignatureHelp(ClangdServer &Server, PathRef File, Position Pos)
Definition: SyncAPI.cpp:78
clang::clangd::lspLength
size_t lspLength(llvm::StringRef Code)
Definition: SourceCode.cpp:131
clang::clangd::InsertTextFormat::PlainText
The primary text to be inserted is treated as a plain string.
Subdir
std::string Subdir
Definition: HeadersTests.cpp:122
SourceCode.h
clang::clangd::HasSubsequence
PolySubsequenceMatcher< Args... > HasSubsequence(Args &&... M)
Definition: clangd/unittests/Matchers.h:106
Matchers.h
clang::clangd::sortText
std::string sortText(float Score, llvm::StringRef Name)
Returns a string that sorts in the same order as (-Score, Tiebreak), for LSP.
Definition: Quality.cpp:481
clang::clangd::ns
Symbol ns(llvm::StringRef Name)
Definition: TestIndex.cpp:72
Protocol.h
Flags
std::vector< const char * > Flags
Definition: FindTargetTests.cpp:68
MemIndex.h
clang::clangd::PathRef
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:23
clang::clangd::CompletionItemKind::Folder
Results
std::vector< CodeCompletionResult > Results
Definition: CodeComplete.cpp:689
clang::clangd::Callback
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition: Function.h:28
FS
MockFSProvider FS
Definition: HeadersTests.cpp:119
clang::clangd::Symbol::SymbolFlag
SymbolFlag
Definition: Symbol.h:113
clang::clangd::ClangdServer::optsForTest
static Options optsForTest()
Definition: ClangdServer.cpp:103
TestFS.h
clang::clangd::sym
Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, llvm::StringRef USRFormat)
Definition: TestIndex.cpp:39
TestTU.h
clang::clangd::var
Symbol var(llvm::StringRef Name)
Definition: TestIndex.cpp:68
clang::clangd::FuzzyFindRequest::Scopes
std::vector< std::string > Scopes
If this is non-empty, symbols must be in at least one of the scopes (e.g.
Definition: Index.h:36
clang::clangd::CompletionItemKind
CompletionItemKind
The kind of a completion entry.
Definition: Protocol.h:260
Kind
BindArgumentKind Kind
Definition: AvoidBindCheck.cpp:57
clang::clangd::WantDiagnostics::Yes
clang::clangd::CompletionItemKind::Text
clang::clangd::CodeCompleteOptions::IncludeComments
bool IncludeComments
Add comments to code completion results, if available.
Definition: CodeComplete.h:57
clang::clangd::CodeCompleteOptions::IncludeCodePatterns
bool IncludeCodePatterns
Add code patterns to completion results.
Definition: CodeComplete.h:51
clang::clangd::MemIndex::build
static std::unique_ptr< SymbolIndex > build(SymbolSlab Symbols, RefSlab Refs, RelationSlab Relations)
Builds an index from slabs. The index takes ownership of the data.
Definition: MemIndex.cpp:19
clang::clangd::SymbolOrigin::AST
clang::clangd::TestTU::withHeaderCode
static TestTU withHeaderCode(llvm::StringRef HeaderCode)
Definition: TestTU.h:39
Annotations.h
CodeComplete.h
clang::clangd::Symbol::IndexedForCodeCompletion
Whether or not this symbol is meant to be used for the code completion.
Definition: Symbol.h:119
clang::clangd::lookup
std::vector< std::string > lookup(const SymbolIndex &I, llvm::ArrayRef< SymbolID > IDs)
Definition: TestIndex.cpp:106
clang::clangd::TEST
TEST(BackgroundQueueTest, Priority)
Definition: BackgroundIndexTests.cpp:647
clang::clangd::positionToOffset
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
Definition: SourceCode.cpp:155
clang::clangd::testPath
std::string testPath(PathRef File)
Definition: TestFS.cpp:82
Compiler.h
SearchDirArg
std::string SearchDirArg
Definition: HeadersTests.cpp:123
clang::clangd::CompletionItemKind::Field
Signature
std::string Signature
Definition: CodeComplete.cpp:394
clang::clangd::DiagnosticsConsumer::onDiagnosticsReady
virtual void onDiagnosticsReady(PathRef File, std::vector< Diag > Diagnostics)=0
Called by ClangdServer when Diagnostics for File are ready.
clang::clangd::SymbolOrigin::Static
clang::clangd::MATCHER
MATCHER(Declared, "")
Definition: BackgroundIndexTests.cpp:27
clang::clangd::CodeCompleteOptions::IncludeIneligibleResults
bool IncludeIneligibleResults
Include results that are not legal completions in the current context.
Definition: CodeComplete.h:61
Name
static constexpr llvm::StringLiteral Name
Definition: UppercaseLiteralSuffixCheck.cpp:27
clang::clangd::CompletionItemKind::Snippet
Quality.h
clang::clangd::CompletionItemKind::Interface
clang::clangd::wait
void wait(std::unique_lock< std::mutex > &Lock, std::condition_variable &CV, Deadline D)
Wait once on CV for the specified duration.
Definition: Threading.cpp:107
Symbols
SymbolSlab Symbols
Definition: SymbolCollectorTests.cpp:295
clang::clangd::CodeCompleteOptions::NeverInsert
Definition: CodeComplete.h:75
clang::clangd::CompletionItemKind::Method
ReturnType
std::string ReturnType
Definition: CodeComplete.cpp:395
Pos
Position Pos
Definition: SourceCode.cpp:772
SnippetSuffix
std::string SnippetSuffix
Definition: CodeComplete.cpp:393
clang::clangd::codeComplete
CodeCompleteResult codeComplete(PathRef FileName, const tooling::CompileCommand &Command, const PreambleData *Preamble, llvm::StringRef Contents, Position Pos, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, CodeCompleteOptions Opts, SpeculativeFuzzyFind *SpecFuzzyFind)
Definition: CodeComplete.cpp:1731
Builder
CodeCompletionBuilder Builder
Definition: CodeCompletionStringsTests.cpp:35
Offset
size_t Offset
Definition: CodeComplete.cpp:1022
clang::clangd::CompletionItemKind::Function
clang::clangd::URI::create
static llvm::Expected< URI > create(llvm::StringRef AbsolutePath, llvm::StringRef Scheme)
Creates a URI for a file in the given scheme.
Definition: URI.cpp:197
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::timeoutSeconds
Deadline timeoutSeconds(llvm::Optional< double > Seconds)
Makes a deadline from a timeout in seconds. None means wait forever.
Definition: Threading.cpp:99
Server
ClangdServer Server
Definition: FindSymbolsTests.cpp:70
Range
CharSourceRange Range
SourceRange for the file name.
Definition: IncludeOrderCheck.cpp:38
IncludeHeader
std::string IncludeHeader
Definition: DiagnosticsTests.cpp:525
clang::clangd::TestTU::index
std::unique_ptr< SymbolIndex > index() const
Definition: TestTU.cpp:88
clang::clangd::CodeCompleteOptions::IncludeMacros
bool IncludeMacros
Add macros to code completion results.
Definition: CodeComplete.h:54
SyncAPI.h
clang::clangd::CompletionItemKind::Variable
DiagConsumer
IgnoreDiagnostics DiagConsumer
Definition: FindSymbolsTests.cpp:69
Parameters
std::vector< Parameter > Parameters
Definition: ExtractFunction.cpp:303
TestIndex.h
FixIt
llvm::Optional< FixItHint > FixIt
Definition: UppercaseLiteralSuffixCheck.cpp:62
clang::clangd::guessCompletionPrefix
CompletionPrefix guessCompletionPrefix(llvm::StringRef Content, unsigned Offset)
Definition: CodeComplete.cpp:1708
Offsets
std::pair< unsigned, unsigned > Offsets
Definition: CodeCompleteTests.cpp:1071
clang::clangd::CompletionItemKind::File
clang::doc::SymbolID
std::array< uint8_t, 20 > SymbolID
Definition: Representation.h:30
EXPECT_IFF
#define EXPECT_IFF(condition, value, matcher)
Definition: clangd/unittests/Matchers.h:24
clang::clangd::CompletionItemKind::Keyword
clang::tidy::readability::@556::Qualifier
Qualifier
Definition: QualifiedAutoCheck.cpp:29
clang::clangd::CompletionItemKind::Reference
clang::clangd::runAddDocument
void runAddDocument(ClangdServer &Server, PathRef File, llvm::StringRef Contents, WantDiagnostics WantDiags)
Definition: SyncAPI.cpp:15
Index
const SymbolIndex * Index
Definition: Dexp.cpp:84
Threading.h
clang::clangd::func
Symbol func(llvm::StringRef Name)
Definition: TestIndex.cpp:60