clang-tools 20.0.0git
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 "ASTSignals.h"
10#include "Annotations.h"
11#include "ClangdServer.h"
12#include "CodeComplete.h"
13#include "Compiler.h"
14#include "Config.h"
15#include "Feature.h"
16#include "Matchers.h"
17#include "Protocol.h"
18#include "Quality.h"
19#include "SourceCode.h"
20#include "SyncAPI.h"
21#include "TestFS.h"
22#include "TestIndex.h"
23#include "TestTU.h"
24#include "index/Index.h"
25#include "index/MemIndex.h"
26#include "index/SymbolOrigin.h"
27#include "support/Threading.h"
28#include "clang/Sema/CodeCompleteConsumer.h"
29#include "clang/Tooling/CompilationDatabase.h"
30#include "llvm/ADT/StringRef.h"
31#include "llvm/Support/Error.h"
32#include "llvm/Support/Path.h"
33#include "llvm/Testing/Annotations/Annotations.h"
34#include "llvm/Testing/Support/Error.h"
35#include "llvm/Testing/Support/SupportHelpers.h"
36#include "gmock/gmock.h"
37#include "gtest/gtest.h"
38#include <condition_variable>
39#include <functional>
40#include <mutex>
41#include <vector>
42
43namespace clang {
44namespace clangd {
45
46namespace {
47using ::llvm::Failed;
48using ::testing::AllOf;
49using ::testing::Contains;
50using ::testing::ElementsAre;
51using ::testing::Field;
52using ::testing::HasSubstr;
53using ::testing::IsEmpty;
54using ::testing::Not;
55using ::testing::UnorderedElementsAre;
56using ContextKind = CodeCompletionContext::Kind;
57
58// GMock helpers for matching completion items.
59MATCHER_P(named, Name, "") { return arg.Name == Name; }
60MATCHER_P(mainFileRefs, Refs, "") { return arg.MainFileRefs == Refs; }
61MATCHER_P(scopeRefs, Refs, "") { return arg.ScopeRefsInFile == Refs; }
62MATCHER_P(nameStartsWith, Prefix, "") {
63 return llvm::StringRef(arg.Name).starts_with(Prefix);
64}
65MATCHER_P(filterText, F, "") { return arg.FilterText == F; }
66MATCHER_P(scope, S, "") { return arg.Scope == S; }
67MATCHER_P(qualifier, Q, "") { return arg.RequiredQualifier == Q; }
68MATCHER_P(labeled, Label, "") {
69 return arg.RequiredQualifier + arg.Name + arg.Signature == Label;
70}
71MATCHER_P(sigHelpLabeled, Label, "") { return arg.label == Label; }
72MATCHER_P(kind, K, "") { return arg.Kind == K; }
73MATCHER_P(doc, D, "") {
74 return arg.Documentation && arg.Documentation->asPlainText() == D;
75}
76MATCHER_P(returnType, D, "") { return arg.ReturnType == D; }
77MATCHER_P(hasInclude, IncludeHeader, "") {
78 return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader;
79}
80MATCHER_P(insertInclude, IncludeHeader, "") {
81 return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader &&
82 bool(arg.Includes[0].Insertion);
83}
84MATCHER_P(insertIncludeText, InsertedText, "") {
85 return !arg.Includes.empty() && arg.Includes[0].Insertion &&
86 arg.Includes[0].Insertion->newText == InsertedText;
87}
88MATCHER(insertInclude, "") {
89 return !arg.Includes.empty() && bool(arg.Includes[0].Insertion);
90}
91MATCHER_P(snippetSuffix, Text, "") { return arg.SnippetSuffix == Text; }
92MATCHER_P(origin, OriginSet, "") { return arg.Origin == OriginSet; }
93MATCHER_P(signature, S, "") { return arg.Signature == S; }
94MATCHER_P(replacesRange, Range, "") {
95 return arg.CompletionTokenRange == Range;
96}
97
98// Shorthand for Contains(named(Name)).
99Matcher<const std::vector<CodeCompletion> &> has(std::string Name) {
100 return Contains(named(std::move(Name)));
101}
102Matcher<const std::vector<CodeCompletion> &> has(std::string Name,
104 return Contains(AllOf(named(std::move(Name)), kind(K)));
105}
106MATCHER(isDocumented, "") { return arg.Documentation.has_value(); }
107MATCHER(deprecated, "") { return arg.Deprecated; }
108
109std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol> Symbols) {
110 SymbolSlab::Builder Slab;
111 for (const auto &Sym : Symbols)
112 Slab.insert(Sym);
113 return MemIndex::build(std::move(Slab).build(), RefSlab(), RelationSlab());
114}
115
116// Runs code completion.
117// If IndexSymbols is non-empty, an index will be built and passed to opts.
118CodeCompleteResult completions(const TestTU &TU, Position Point,
119 std::vector<Symbol> IndexSymbols = {},
120 clangd::CodeCompleteOptions Opts = {}) {
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 MockFS FS;
129 auto Inputs = TU.inputs(FS);
130 IgnoreDiagnostics Diags;
131 auto CI = buildCompilerInvocation(Inputs, Diags);
132 if (!CI) {
133 ADD_FAILURE() << "Couldn't build CompilerInvocation";
134 return {};
135 }
136 auto Preamble = buildPreamble(testPath(TU.Filename), *CI, Inputs,
137 /*InMemory=*/true, /*Callback=*/nullptr);
138 return codeComplete(testPath(TU.Filename), Point, Preamble.get(), Inputs,
139 Opts);
140}
141
142// Runs code completion.
143CodeCompleteResult completions(llvm::StringRef Text,
144 std::vector<Symbol> IndexSymbols = {},
145 clangd::CodeCompleteOptions Opts = {},
146 PathRef FilePath = "foo.cpp") {
147 Annotations Test(Text);
148 auto TU = TestTU::withCode(Test.code());
149 // To make sure our tests for completiopns inside templates work on Windows.
150 TU.Filename = FilePath.str();
151 return completions(TU, Test.point(), std::move(IndexSymbols),
152 std::move(Opts));
153}
154
155// Runs code completion without the clang parser.
156CodeCompleteResult completionsNoCompile(llvm::StringRef Text,
157 std::vector<Symbol> IndexSymbols = {},
158 clangd::CodeCompleteOptions Opts = {},
159 PathRef FilePath = "foo.cpp") {
160 std::unique_ptr<SymbolIndex> OverrideIndex;
161 if (!IndexSymbols.empty()) {
162 assert(!Opts.Index && "both Index and IndexSymbols given!");
163 OverrideIndex = memIndex(std::move(IndexSymbols));
164 Opts.Index = OverrideIndex.get();
165 }
166
167 MockFS FS;
168 Annotations Test(Text);
169 ParseInputs ParseInput{tooling::CompileCommand(), &FS, Test.code().str()};
170 return codeComplete(FilePath, Test.point(), /*Preamble=*/nullptr, ParseInput,
171 Opts);
172}
173
174Symbol withReferences(int N, Symbol S) {
175 S.References = N;
176 return S;
177}
178
179#if CLANGD_DECISION_FOREST
180TEST(DecisionForestRankingModel, NameMatchSanityTest) {
181 clangd::CodeCompleteOptions Opts;
183 auto Results = completions(
184 R"cpp(
185struct MemberAccess {
186 int ABG();
187 int AlphaBetaGamma();
188};
189int func() { MemberAccess().ABG^ }
190)cpp",
191 /*IndexSymbols=*/{}, Opts);
192 EXPECT_THAT(Results.Completions,
193 ElementsAre(named("ABG"), named("AlphaBetaGamma")));
194}
195
196TEST(DecisionForestRankingModel, ReferencesAffectRanking) {
197 clangd::CodeCompleteOptions Opts;
199 constexpr int NumReferences = 100000;
200 EXPECT_THAT(
201 completions("int main() { clang^ }",
202 {ns("clangA"), withReferences(NumReferences, func("clangD"))},
203 Opts)
204 .Completions,
205 ElementsAre(named("clangD"), named("clangA")));
206 EXPECT_THAT(
207 completions("int main() { clang^ }",
208 {withReferences(NumReferences, ns("clangA")), func("clangD")},
209 Opts)
210 .Completions,
211 ElementsAre(named("clangA"), named("clangD")));
212}
213#endif // CLANGD_DECISION_FOREST
214
215TEST(DecisionForestRankingModel, DecisionForestScorerCallbackTest) {
216 clangd::CodeCompleteOptions Opts;
217 constexpr float MagicNumber = 1234.5678f;
219 Opts.DecisionForestScorer = [&](const SymbolQualitySignals &,
220 const SymbolRelevanceSignals &, float Base) {
221 DecisionForestScores Scores;
222 Scores.Total = MagicNumber;
223 Scores.ExcludingName = MagicNumber;
224 return Scores;
225 };
226 llvm::StringRef Code = "int func() { int xyz; xy^ }";
227 auto Results = completions(Code,
228 /*IndexSymbols=*/{}, Opts);
229 ASSERT_EQ(Results.Completions.size(), 1u);
230 EXPECT_EQ(Results.Completions[0].Score.Total, MagicNumber);
231 EXPECT_EQ(Results.Completions[0].Score.ExcludingName, MagicNumber);
232
233 // Do not use DecisionForestScorer for heuristics model.
235 Results = completions(Code,
236 /*IndexSymbols=*/{}, Opts);
237 ASSERT_EQ(Results.Completions.size(), 1u);
238 EXPECT_NE(Results.Completions[0].Score.Total, MagicNumber);
239 EXPECT_NE(Results.Completions[0].Score.ExcludingName, MagicNumber);
240}
241
242TEST(CompletionTest, Limit) {
243 clangd::CodeCompleteOptions Opts;
244 Opts.Limit = 2;
245 auto Results = completions(R"cpp(
246struct ClassWithMembers {
247 int AAA();
248 int BBB();
249 int CCC();
250};
251
252int main() { ClassWithMembers().^ }
253 )cpp",
254 /*IndexSymbols=*/{}, Opts);
255
256 EXPECT_TRUE(Results.HasMore);
257 EXPECT_THAT(Results.Completions, ElementsAre(named("AAA"), named("BBB")));
258}
259
260TEST(CompletionTest, Filter) {
261 std::string Body = R"cpp(
262 #define MotorCar
263 int Car;
264 struct S {
265 int FooBar;
266 int FooBaz;
267 int Qux;
268 };
269 )cpp";
270
271 // Only items matching the fuzzy query are returned.
272 EXPECT_THAT(completions(Body + "int main() { S().Foba^ }").Completions,
273 AllOf(has("FooBar"), has("FooBaz"), Not(has("Qux"))));
274
275 // Macros require prefix match, either from index or AST.
276 Symbol Sym = var("MotorCarIndex");
277 Sym.SymInfo.Kind = index::SymbolKind::Macro;
278 EXPECT_THAT(
279 completions(Body + "int main() { C^ }", {Sym}).Completions,
280 AllOf(has("Car"), Not(has("MotorCar")), Not(has("MotorCarIndex"))));
281 EXPECT_THAT(completions(Body + "int main() { M^ }", {Sym}).Completions,
282 AllOf(has("MotorCar"), has("MotorCarIndex")));
283}
284
285void testAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
286 auto Results = completions(
287 R"cpp(
288 int global_var;
289
290 int global_func();
291
292 // Make sure this is not in preamble.
293 #define MACRO X
294
295 struct GlobalClass {};
296
297 struct ClassWithMembers {
298 /// doc for method.
299 int method();
300
301 int field;
302 private:
303 int private_field;
304 };
305
306 int test() {
307 struct LocalClass {};
308
309 /// doc for local_var.
310 int local_var;
311
312 ClassWithMembers().^
313 }
314 )cpp",
315 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
316
317 EXPECT_TRUE(Results.RanParser);
318 // Class members. The only items that must be present in after-dot
319 // completion.
320 EXPECT_THAT(Results.Completions,
321 AllOf(has("method"), has("field"), Not(has("ClassWithMembers")),
322 Not(has("operator=")), Not(has("~ClassWithMembers"))));
324 has("private_field"));
325 // Global items.
326 EXPECT_THAT(
327 Results.Completions,
328 Not(AnyOf(has("global_var"), has("index_var"), has("global_func"),
329 has("global_func()"), has("index_func"), has("GlobalClass"),
330 has("IndexClass"), has("MACRO"), has("LocalClass"))));
331 // There should be no code patterns (aka snippets) in after-dot
332 // completion. At least there aren't any we're aware of.
333 EXPECT_THAT(Results.Completions,
334 Not(Contains(kind(CompletionItemKind::Snippet))));
335 // Check documentation.
336 EXPECT_THAT(Results.Completions, Contains(isDocumented()));
337}
338
339void testGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
340 auto Results = completions(
341 R"cpp(
342 int global_var;
343 int global_func();
344
345 // Make sure this is not in preamble.
346 #define MACRO X
347
348 struct GlobalClass {};
349
350 struct ClassWithMembers {
351 /// doc for method.
352 int method();
353 };
354
355 int test() {
356 struct LocalClass {};
357
358 /// doc for local_var.
359 int local_var;
360
361 ^
362 }
363 )cpp",
364 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
365
366 EXPECT_TRUE(Results.RanParser);
367 // Class members. Should never be present in global completions.
368 EXPECT_THAT(Results.Completions,
369 Not(AnyOf(has("method"), has("method()"), has("field"))));
370 // Global items.
371 EXPECT_THAT(Results.Completions,
372 AllOf(has("global_var"), has("index_var"), has("global_func"),
373 has("index_func" /* our fake symbol doesn't include () */),
374 has("GlobalClass"), has("IndexClass")));
375 // A macro.
376 EXPECT_THAT(Results.Completions, has("MACRO"));
377 // Local items. Must be present always.
378 EXPECT_THAT(Results.Completions,
379 AllOf(has("local_var"), has("LocalClass"),
380 Contains(kind(CompletionItemKind::Snippet))));
381 // Check documentation.
382 EXPECT_THAT(Results.Completions, Contains(isDocumented()));
383}
384
385TEST(CompletionTest, CompletionOptions) {
386 auto Test = [&](const clangd::CodeCompleteOptions &Opts) {
387 testAfterDotCompletion(Opts);
388 testGlobalScopeCompletion(Opts);
389 };
390 // We used to test every combination of options, but that got too slow (2^N).
391 auto Flags = {
393 };
394 // Test default options.
395 Test({});
396 // Test with one flag flipped.
397 for (auto &F : Flags) {
398 clangd::CodeCompleteOptions O;
399 O.*F ^= true;
400 Test(O);
401 }
402}
403
404TEST(CompletionTest, Accessible) {
405 auto Internal = completions(R"cpp(
406 class Foo {
407 public: void pub();
408 protected: void prot();
409 private: void priv();
410 };
411 void Foo::pub() { this->^ }
412 )cpp");
413 EXPECT_THAT(Internal.Completions,
414 AllOf(has("priv"), has("prot"), has("pub")));
415
416 auto External = completions(R"cpp(
417 class Foo {
418 public: void pub();
419 protected: void prot();
420 private: void priv();
421 };
422 void test() {
423 Foo F;
424 F.^
425 }
426 )cpp");
427 EXPECT_THAT(External.Completions,
428 AllOf(has("pub"), Not(has("prot")), Not(has("priv"))));
429
430 auto Results = completions(R"cpp(
431 struct Foo {
432 public: void pub();
433 protected: void prot();
434 private: void priv();
435 };
436 struct Bar : public Foo {
437 private: using Foo::pub;
438 };
439 void test() {
440 Bar B;
441 B.^
442 }
443 )cpp");
444 EXPECT_THAT(Results.Completions,
445 AllOf(Not(has("priv")), Not(has("prot")), Not(has("pub"))));
446}
447
448TEST(CompletionTest, Qualifiers) {
449 auto Results = completions(R"cpp(
450 class Foo {
451 public: int foo() const;
452 int bar() const;
453 };
454 class Bar : public Foo {
455 int foo() const;
456 };
457 void test() { Bar().^ }
458 )cpp");
459 EXPECT_THAT(Results.Completions,
460 Contains(AllOf(qualifier(""), named("bar"))));
461 // Hidden members are not shown.
462 EXPECT_THAT(Results.Completions,
463 Not(Contains(AllOf(qualifier("Foo::"), named("foo")))));
464 // Private members are not shown.
465 EXPECT_THAT(Results.Completions,
466 Not(Contains(AllOf(qualifier(""), named("foo")))));
467}
468
469// https://github.com/clangd/clangd/issues/1451
470TEST(CompletionTest, QualificationWithInlineNamespace) {
471 auto Results = completions(R"cpp(
472 namespace a { inline namespace b {} }
473 using namespace a::b;
474 void f() { Foo^ }
475 )cpp",
476 {cls("a::Foo")});
477 EXPECT_THAT(Results.Completions,
478 UnorderedElementsAre(AllOf(qualifier("a::"), named("Foo"))));
479}
480
481TEST(CompletionTest, InjectedTypename) {
482 // These are suppressed when accessed as a member...
483 EXPECT_THAT(completions("struct X{}; void foo(){ X().^ }").Completions,
484 Not(has("X")));
485 EXPECT_THAT(completions("struct X{ void foo(){ this->^ } };").Completions,
486 Not(has("X")));
487 // ...but accessible in other, more useful cases.
488 EXPECT_THAT(completions("struct X{ void foo(){ ^ } };").Completions,
489 has("X"));
490 EXPECT_THAT(
491 completions("struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions,
492 has("Y"));
493 EXPECT_THAT(
494 completions(
495 "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };")
496 .Completions,
497 has("Y"));
498 // This case is marginal (`using X::X` is useful), we allow it for now.
499 EXPECT_THAT(completions("struct X{}; void foo(){ X::^ }").Completions,
500 has("X"));
501}
502
503TEST(CompletionTest, SkipInjectedWhenUnqualified) {
504 EXPECT_THAT(completions("struct X { void f() { X^ }};").Completions,
505 ElementsAre(named("X"), named("~X")));
506}
507
508TEST(CompletionTest, Snippets) {
509 clangd::CodeCompleteOptions Opts;
510 auto Results = completions(
511 R"cpp(
512 struct fake {
513 int a;
514 int f(int i, const float f) const;
515 };
516 int main() {
517 fake f;
518 f.^
519 }
520 )cpp",
521 /*IndexSymbols=*/{}, Opts);
522 EXPECT_THAT(
523 Results.Completions,
524 HasSubsequence(named("a"),
525 snippetSuffix("(${1:int i}, ${2:const float f})")));
526}
527
528TEST(CompletionTest, HeuristicsForMemberFunctionCompletion) {
529 clangd::CodeCompleteOptions Opts;
530 Opts.EnableSnippets = true;
531
532 Annotations Code(R"cpp(
533 struct Foo {
534 static int staticMethod(int);
535 int method(int) const;
536 template <typename T, typename U, typename V = int>
537 T generic(U, V);
538 template <typename T, int U>
539 static T staticGeneric();
540 Foo() {
541 this->$canBeCall^
542 $canBeCall^
543 Foo::$canBeCall^
544 }
545 };
546
547 struct Derived : Foo {
548 using Foo::method;
549 using Foo::generic;
550 Derived() {
551 Foo::$canBeCall^
552 }
553 };
554
555 struct OtherClass {
556 OtherClass() {
557 Foo f;
558 Derived d;
559 f.$canBeCall^
560 ; // Prevent parsing as 'f.f'
561 f.Foo::$canBeCall^
562 &Foo::$canNotBeCall^
563 ;
564 d.Foo::$canBeCall^
565 ;
566 d.Derived::$canBeCall^
567 }
568 };
569
570 int main() {
571 Foo f;
572 Derived d;
573 f.$canBeCall^
574 ; // Prevent parsing as 'f.f'
575 f.Foo::$canBeCall^
576 &Foo::$canNotBeCall^
577 ;
578 d.Foo::$canBeCall^
579 ;
580 d.Derived::$canBeCall^
581 }
582 )cpp");
583 auto TU = TestTU::withCode(Code.code());
584
585 for (const auto &P : Code.points("canNotBeCall")) {
586 auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
587 EXPECT_THAT(Results.Completions,
588 Contains(AllOf(named("method"), signature("(int) const"),
589 snippetSuffix(""))));
590 // We don't have any arguments to deduce against if this isn't a call.
591 // Thus, we should emit these deducible template arguments explicitly.
592 EXPECT_THAT(
593 Results.Completions,
594 Contains(AllOf(named("generic"),
595 signature("<typename T, typename U>(U, V)"),
596 snippetSuffix("<${1:typename T}, ${2:typename U}>"))));
597 }
598
599 for (const auto &P : Code.points("canBeCall")) {
600 auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
601 EXPECT_THAT(Results.Completions,
602 Contains(AllOf(named("method"), signature("(int) const"),
603 snippetSuffix("(${1:int})"))));
604 EXPECT_THAT(
605 Results.Completions,
606 Contains(AllOf(named("generic"), signature("<typename T>(U, V)"),
607 snippetSuffix("<${1:typename T}>(${2:U}, ${3:V})"))));
608 }
609
610 // static method will always keep the snippet
611 for (const auto &P : Code.points()) {
612 auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
613 EXPECT_THAT(Results.Completions,
614 Contains(AllOf(named("staticMethod"), signature("(int)"),
615 snippetSuffix("(${1:int})"))));
616 EXPECT_THAT(Results.Completions,
617 Contains(AllOf(
618 named("staticGeneric"), signature("<typename T, int U>()"),
619 snippetSuffix("<${1:typename T}, ${2:int U}>()"))));
620 }
621}
622
623TEST(CompletionTest, NoSnippetsInUsings) {
624 clangd::CodeCompleteOptions Opts;
625 Opts.EnableSnippets = true;
626 auto Results = completions(
627 R"cpp(
628 namespace ns {
629 int func(int a, int b);
630 }
631
632 using ns::^;
633 )cpp",
634 /*IndexSymbols=*/{}, Opts);
635 EXPECT_THAT(Results.Completions,
636 ElementsAre(AllOf(named("func"), labeled("func(int a, int b)"),
637 snippetSuffix(""))));
638
639 // Check index completions too.
640 auto Func = func("ns::func");
641 Func.CompletionSnippetSuffix = "(${1:int a}, ${2: int b})";
642 Func.Signature = "(int a, int b)";
643 Func.ReturnType = "void";
644
645 Results = completions(R"cpp(
646 namespace ns {}
647 using ns::^;
648 )cpp",
649 /*IndexSymbols=*/{Func}, Opts);
650 EXPECT_THAT(Results.Completions,
651 ElementsAre(AllOf(named("func"), labeled("func(int a, int b)"),
652 snippetSuffix(""))));
653
654 // Check all-scopes completions too.
655 Opts.AllScopes = true;
656 Results = completions(R"cpp(
657 using ^;
658 )cpp",
659 /*IndexSymbols=*/{Func}, Opts);
660 EXPECT_THAT(Results.Completions,
661 Contains(AllOf(named("func"), labeled("ns::func(int a, int b)"),
662 snippetSuffix(""))));
663}
664
665TEST(CompletionTest, Kinds) {
666 auto Results = completions(
667 R"cpp(
668 int variable;
669 struct Struct {};
670 int function();
671 // make sure MACRO is not included in preamble.
672 #define MACRO 10
673 int X = ^
674 )cpp",
675 {func("indexFunction"), var("indexVariable"), cls("indexClass"),
676 macro("indexObjMacro"), macro("indexFuncMacro", "(x, y)")});
677 EXPECT_THAT(Results.Completions,
678 AllOf(has("function", CompletionItemKind::Function),
679 has("variable", CompletionItemKind::Variable),
680 has("int", CompletionItemKind::Keyword),
681 has("Struct", CompletionItemKind::Struct),
682 has("MACRO", CompletionItemKind::Constant),
683 has("indexFunction", CompletionItemKind::Function),
684 has("indexVariable", CompletionItemKind::Variable),
685 has("indexClass", CompletionItemKind::Class),
686 has("indexObjMacro", CompletionItemKind::Constant),
687 has("indexFuncMacro", CompletionItemKind::Function)));
688
689 Results = completions("nam^");
690 EXPECT_THAT(Results.Completions,
691 has("namespace", CompletionItemKind::Snippet));
692
693 // Members of anonymous unions are of kind 'field'.
694 Results = completions(
695 R"cpp(
696 struct X{
697 union {
698 void *a;
699 };
700 };
701 auto u = X().^
702 )cpp");
703 EXPECT_THAT(
704 Results.Completions,
705 UnorderedElementsAre(AllOf(named("a"), kind(CompletionItemKind::Field))));
706
707 // Completion kinds for templates should not be unknown.
708 Results = completions(
709 R"cpp(
710 template <class T> struct complete_class {};
711 template <class T> void complete_function();
712 template <class T> using complete_type_alias = int;
713 template <class T> int complete_variable = 10;
714
715 struct X {
716 template <class T> static int complete_static_member = 10;
717
718 static auto x = complete_^
719 }
720 )cpp");
721 EXPECT_THAT(
722 Results.Completions,
723 UnorderedElementsAre(
724 AllOf(named("complete_class"), kind(CompletionItemKind::Class)),
725 AllOf(named("complete_function"), kind(CompletionItemKind::Function)),
726 AllOf(named("complete_type_alias"),
728 AllOf(named("complete_variable"), kind(CompletionItemKind::Variable)),
729 AllOf(named("complete_static_member"),
731
732 Results = completions(
733 R"cpp(
734 enum Color {
735 Red
736 };
737 Color u = ^
738 )cpp");
739 EXPECT_THAT(
740 Results.Completions,
741 Contains(AllOf(named("Red"), kind(CompletionItemKind::EnumMember))));
742}
743
744TEST(CompletionTest, NoDuplicates) {
745 auto Results = completions(
746 R"cpp(
747 class Adapter {
748 };
749
750 void f() {
751 Adapter^
752 }
753 )cpp",
754 {cls("Adapter")});
755
756 // Make sure there are no duplicate entries of 'Adapter'.
757 EXPECT_THAT(Results.Completions, ElementsAre(named("Adapter")));
758}
759
760TEST(CompletionTest, ScopedNoIndex) {
761 auto Results = completions(
762 R"cpp(
763 namespace fake { int BigBang, Babble, Box; };
764 int main() { fake::ba^ }
765 ")cpp");
766 // Babble is a better match than BigBang. Box doesn't match at all.
767 EXPECT_THAT(Results.Completions,
768 ElementsAre(named("Babble"), named("BigBang")));
769}
770
771TEST(CompletionTest, Scoped) {
772 auto Results = completions(
773 R"cpp(
774 namespace fake { int Babble, Box; };
775 int main() { fake::ba^ }
776 ")cpp",
777 {var("fake::BigBang")});
778 EXPECT_THAT(Results.Completions,
779 ElementsAre(named("Babble"), named("BigBang")));
780}
781
782TEST(CompletionTest, ScopedWithFilter) {
783 auto Results = completions(
784 R"cpp(
785 void f() { ns::x^ }
786 )cpp",
787 {cls("ns::XYZ"), func("ns::foo")});
788 EXPECT_THAT(Results.Completions, UnorderedElementsAre(named("XYZ")));
789}
790
791TEST(CompletionTest, ReferencesAffectRanking) {
792 EXPECT_THAT(completions("int main() { abs^ }", {func("absA"), func("absB")})
793 .Completions,
794 HasSubsequence(named("absA"), named("absB")));
795 EXPECT_THAT(completions("int main() { abs^ }",
796 {func("absA"), withReferences(1000, func("absB"))})
797 .Completions,
798 HasSubsequence(named("absB"), named("absA")));
799}
800
801TEST(CompletionTest, ContextWords) {
802 auto Results = completions(R"cpp(
803 enum class Color { RED, YELLOW, BLUE };
804
805 // (blank lines so the definition above isn't "context")
806
807 // "It was a yellow car," he said. "Big yellow car, new."
808 auto Finish = Color::^
809 )cpp");
810 // Yellow would normally sort last (alphabetic).
811 // But the recent mention should bump it up.
812 ASSERT_THAT(Results.Completions,
813 HasSubsequence(named("YELLOW"), named("BLUE")));
814}
815
816TEST(CompletionTest, GlobalQualified) {
817 auto Results = completions(
818 R"cpp(
819 void f() { ::^ }
820 )cpp",
821 {cls("XYZ")});
822 EXPECT_THAT(Results.Completions,
823 AllOf(has("XYZ", CompletionItemKind::Class),
825}
826
827TEST(CompletionTest, FullyQualified) {
828 auto Results = completions(
829 R"cpp(
830 namespace ns { void bar(); }
831 void f() { ::ns::^ }
832 )cpp",
833 {cls("ns::XYZ")});
834 EXPECT_THAT(Results.Completions,
835 AllOf(has("XYZ", CompletionItemKind::Class),
836 has("bar", CompletionItemKind::Function)));
837}
838
839TEST(CompletionTest, SemaIndexMerge) {
840 auto Results = completions(
841 R"cpp(
842 namespace ns { int local; void both(); }
843 void f() { ::ns::^ }
844 )cpp",
845 {func("ns::both"), cls("ns::Index")});
846 // We get results from both index and sema, with no duplicates.
847 EXPECT_THAT(Results.Completions,
848 UnorderedElementsAre(
849 AllOf(named("local"), origin(SymbolOrigin::AST)),
850 AllOf(named("Index"), origin(SymbolOrigin::Static)),
851 AllOf(named("both"),
853}
854
855TEST(CompletionTest, SemaIndexMergeWithLimit) {
856 clangd::CodeCompleteOptions Opts;
857 Opts.Limit = 1;
858 auto Results = completions(
859 R"cpp(
860 namespace ns { int local; void both(); }
861 void f() { ::ns::^ }
862 )cpp",
863 {func("ns::both"), cls("ns::Index")}, Opts);
864 EXPECT_EQ(Results.Completions.size(), Opts.Limit);
865 EXPECT_TRUE(Results.HasMore);
866}
867
868TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
869 TestTU TU;
870 TU.ExtraArgs.push_back("-I" + testPath("sub"));
871 TU.AdditionalFiles["sub/bar.h"] = "";
872 auto BarURI = URI::create(testPath("sub/bar.h")).toString();
873
874 Symbol Sym = cls("ns::X");
875 Sym.CanonicalDeclaration.FileURI = BarURI.c_str();
876 Sym.IncludeHeaders.emplace_back(BarURI, 1, Symbol::Include);
877 // Shorten include path based on search directory and insert.
878 Annotations Test("int main() { ns::^ }");
879 TU.Code = Test.code().str();
880 auto Results = completions(TU, Test.point(), {Sym});
881 EXPECT_THAT(Results.Completions,
882 ElementsAre(AllOf(named("X"), insertInclude("\"bar.h\""))));
883 // Can be disabled via option.
884 CodeCompleteOptions NoInsertion;
885 NoInsertion.InsertIncludes = CodeCompleteOptions::NeverInsert;
886 Results = completions(TU, Test.point(), {Sym}, NoInsertion);
887 EXPECT_THAT(Results.Completions,
888 ElementsAre(AllOf(named("X"), Not(insertInclude()))));
889 // Duplicate based on inclusions in preamble.
890 Test = Annotations(R"cpp(
891 #include "sub/bar.h" // not shortest, so should only match resolved.
892 int main() { ns::^ }
893 )cpp");
894 TU.Code = Test.code().str();
895 Results = completions(TU, Test.point(), {Sym});
896 EXPECT_THAT(Results.Completions, ElementsAre(AllOf(named("X"), labeled("X"),
897 Not(insertInclude()))));
898}
899
900TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {
901 Symbol SymX = cls("ns::X");
902 Symbol SymY = cls("ns::Y");
903 std::string BarHeader = testPath("bar.h");
904 auto BarURI = URI::create(BarHeader).toString();
905 SymX.CanonicalDeclaration.FileURI = BarURI.c_str();
906 SymY.CanonicalDeclaration.FileURI = BarURI.c_str();
907 SymX.IncludeHeaders.emplace_back("<bar>", 1, Symbol::Include);
908 SymY.IncludeHeaders.emplace_back("<bar>", 1, Symbol::Include);
909 // Shorten include path based on search directory and insert.
910 auto Results = completions(R"cpp(
911 namespace ns {
912 class X;
913 class Y {};
914 }
915 int main() { ns::^ }
916 )cpp",
917 {SymX, SymY});
918 EXPECT_THAT(Results.Completions,
919 ElementsAre(AllOf(named("X"), Not(insertInclude())),
920 AllOf(named("Y"), Not(insertInclude()))));
921}
922
923TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
924 Annotations Test(R"cpp(
925 #include "bar.h"
926 namespace ns { int local; }
927 void f() { ns::^; }
928 void f2() { ns::preamble().$2^; }
929 )cpp");
930 auto TU = TestTU::withCode(Test.code());
931 TU.AdditionalFiles["bar.h"] =
932 R"cpp(namespace ns { struct preamble { int member; }; })cpp";
933
934 clangd::CodeCompleteOptions Opts = {};
935 auto I = memIndex({var("ns::index")});
936 Opts.Index = I.get();
937 auto WithIndex = completions(TU, Test.point(), {}, Opts);
938 EXPECT_THAT(WithIndex.Completions,
939 UnorderedElementsAre(named("local"), named("index")));
940 auto ClassFromPreamble = completions(TU, Test.point("2"), {}, Opts);
941 EXPECT_THAT(ClassFromPreamble.Completions, Contains(named("member")));
942
943 Opts.Index = nullptr;
944 auto WithoutIndex = completions(TU, Test.point(), {}, Opts);
945 EXPECT_THAT(WithoutIndex.Completions,
946 UnorderedElementsAre(named("local"), named("preamble")));
947}
948
949// This verifies that we get normal preprocessor completions in the preamble.
950// This is a regression test for an old bug: if we override the preamble and
951// try to complete inside it, clang kicks our completion point just outside the
952// preamble, resulting in always getting top-level completions.
953TEST(CompletionTest, CompletionInPreamble) {
954 auto Results = completions(R"cpp(
955 #ifnd^ef FOO_H_
956 #define BAR_H_
957 #include <bar.h>
958 int foo() {}
959 #endif
960 )cpp")
961 .Completions;
962 EXPECT_THAT(Results, ElementsAre(named("ifndef")));
963}
964
965TEST(CompletionTest, CompletionRecoveryASTType) {
966 auto Results = completions(R"cpp(
967 struct S { int member; };
968 S overloaded(int);
969 void foo() {
970 // No overload matches, but we have recovery-expr with the correct type.
971 overloaded().^
972 })cpp")
973 .Completions;
974 EXPECT_THAT(Results, ElementsAre(named("member")));
975}
976
977TEST(CompletionTest, DynamicIndexIncludeInsertion) {
978 MockFS FS;
979 MockCompilationDatabase CDB;
980 ClangdServer::Options Opts = ClangdServer::optsForTest();
981 Opts.BuildDynamicSymbolIndex = true;
982 ClangdServer Server(CDB, FS, Opts);
983
984 FS.Files[testPath("foo_header.h")] = R"cpp(
985 #pragma once
986 struct Foo {
987 // Member doc
988 int foo();
989 };
990 )cpp";
991 const std::string FileContent(R"cpp(
992 #include "foo_header.h"
993 int Foo::foo() {
994 return 42;
995 }
996 )cpp");
997 Server.addDocument(testPath("foo_impl.cpp"), FileContent);
998 // Wait for the dynamic index being built.
999 ASSERT_TRUE(Server.blockUntilIdleForTest());
1000
1001 auto File = testPath("foo.cpp");
1002 Annotations Test("Foo^ foo;");
1003 runAddDocument(Server, File, Test.code());
1004 auto CompletionList =
1005 llvm::cantFail(runCodeComplete(Server, File, Test.point(), {}));
1006
1007 EXPECT_THAT(CompletionList.Completions,
1008 ElementsAre(AllOf(named("Foo"), hasInclude("\"foo_header.h\""),
1009 insertInclude())));
1010}
1011
1012TEST(CompletionTest, DynamicIndexMultiFile) {
1013 MockFS FS;
1014 MockCompilationDatabase CDB;
1015 auto Opts = ClangdServer::optsForTest();
1016 Opts.BuildDynamicSymbolIndex = true;
1017 ClangdServer Server(CDB, FS, Opts);
1018
1019 FS.Files[testPath("foo.h")] = R"cpp(
1020 namespace ns { class XYZ {}; void foo(int x) {} }
1021 )cpp";
1022 runAddDocument(Server, testPath("foo.cpp"), R"cpp(
1023 #include "foo.h"
1024 )cpp");
1025
1026 auto File = testPath("bar.cpp");
1027 Annotations Test(R"cpp(
1028 namespace ns {
1029 class XXX {};
1030 /// Doooc
1031 void fooooo() {}
1032 }
1033 void f() { ns::^ }
1034 )cpp");
1035 runAddDocument(Server, File, Test.code());
1036
1037 auto Results = cantFail(runCodeComplete(Server, File, Test.point(), {}));
1038 // "XYZ" and "foo" are not included in the file being completed but are still
1039 // visible through the index.
1040 EXPECT_THAT(Results.Completions, has("XYZ", CompletionItemKind::Class));
1041 EXPECT_THAT(Results.Completions, has("foo", CompletionItemKind::Function));
1042 EXPECT_THAT(Results.Completions, has("XXX", CompletionItemKind::Class));
1043 EXPECT_THAT(Results.Completions,
1044 Contains((named("fooooo"), kind(CompletionItemKind::Function),
1045 doc("Doooc"), returnType("void"))));
1046}
1047
1048TEST(CompletionTest, Documentation) {
1049 auto Results = completions(
1050 R"cpp(
1051 // Non-doxygen comment.
1052 __attribute__((annotate("custom_annotation"))) int foo();
1053 /// Doxygen comment.
1054 /// \param int a
1055 int bar(int a);
1056 /* Multi-line
1057 block comment
1058 */
1059 int baz();
1060
1061 int x = ^
1062 )cpp");
1063 EXPECT_THAT(Results.Completions,
1064 Contains(AllOf(
1065 named("foo"),
1066 doc("Annotation: custom_annotation\nNon-doxygen comment."))));
1067 EXPECT_THAT(
1068 Results.Completions,
1069 Contains(AllOf(named("bar"), doc("Doxygen comment.\n\\param int a"))));
1070 EXPECT_THAT(Results.Completions,
1071 Contains(AllOf(named("baz"), doc("Multi-line block comment"))));
1072}
1073
1074TEST(CompletionTest, CommentsFromSystemHeaders) {
1075 MockFS FS;
1076 MockCompilationDatabase CDB;
1077
1078 auto Opts = ClangdServer::optsForTest();
1079 Opts.BuildDynamicSymbolIndex = true;
1080
1081 ClangdServer Server(CDB, FS, Opts);
1082
1083 FS.Files[testPath("foo.h")] = R"cpp(
1084 #pragma GCC system_header
1085
1086 // This comment should be retained!
1087 int foo();
1088 )cpp";
1089
1090 auto File = testPath("foo.cpp");
1091 Annotations Test(R"cpp(
1092#include "foo.h"
1093int x = foo^
1094 )cpp");
1095 runAddDocument(Server, File, Test.code());
1096 auto CompletionList =
1097 llvm::cantFail(runCodeComplete(Server, File, Test.point(), {}));
1098
1099 EXPECT_THAT(
1100 CompletionList.Completions,
1101 Contains(AllOf(named("foo"), doc("This comment should be retained!"))));
1102}
1103
1104TEST(CompletionTest, GlobalCompletionFiltering) {
1105
1106 Symbol Class = cls("XYZ");
1107 Class.Flags = static_cast<Symbol::SymbolFlag>(
1109 Symbol Func = func("XYZ::foooo");
1110 Func.Flags = static_cast<Symbol::SymbolFlag>(
1111 Func.Flags & ~(Symbol::IndexedForCodeCompletion));
1112
1113 auto Results = completions(R"(// void f() {
1114 XYZ::foooo^
1115 })",
1116 {Class, Func});
1117 EXPECT_THAT(Results.Completions, IsEmpty());
1118}
1119
1120TEST(CodeCompleteTest, DisableTypoCorrection) {
1121 auto Results = completions(R"cpp(
1122 namespace clang { int v; }
1123 void f() { clangd::^
1124 )cpp");
1125 EXPECT_TRUE(Results.Completions.empty());
1126}
1127
1128TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
1129 auto Results = completions(R"cpp(
1130 namespace clang { }
1131 void f() {
1132 clan^
1133 }
1134 )cpp");
1135
1136 EXPECT_THAT(Results.Completions, Contains(labeled("clang")));
1137 EXPECT_THAT(Results.Completions, Not(Contains(labeled("clang::"))));
1138}
1139
1140TEST(CompletionTests, EmptySnippetDoesNotCrash) {
1141 // See https://github.com/clangd/clangd/issues/1216
1142 auto Results = completions(R"cpp(
1143 int main() {
1144 auto w = [&](auto &&f) { return f(f); };
1145 auto f = w([&](auto &&f) {
1146 return [&](auto &&n) {
1147 if (n == 0) {
1148 return 1;
1149 }
1150 return n * ^(f)(n - 1);
1151 };
1152 })(10);
1153 }
1154 )cpp");
1155}
1156
1157TEST(CompletionTest, Issue1427Crash) {
1158 // Need to provide main file signals to ensure that the branch in
1159 // SymbolRelevanceSignals::computeASTSignals() that tries to
1160 // compute a symbol ID is taken.
1161 ASTSignals MainFileSignals;
1162 CodeCompleteOptions Opts;
1163 Opts.MainFileSignals = &MainFileSignals;
1164 completions(R"cpp(
1165 auto f = []() {
1166 1.0_^
1167 };
1168 )cpp",
1169 {}, Opts);
1170}
1171
1172TEST(CompletionTest, BacktrackCrashes) {
1173 // Sema calls code completion callbacks twice in these cases.
1174 auto Results = completions(R"cpp(
1175 namespace ns {
1176 struct FooBarBaz {};
1177 } // namespace ns
1178
1179 int foo(ns::FooBar^
1180 )cpp");
1181
1182 EXPECT_THAT(Results.Completions, ElementsAre(labeled("FooBarBaz")));
1183
1184 // Check we don't crash in that case too.
1185 completions(R"cpp(
1186 struct FooBarBaz {};
1187 void test() {
1188 if (FooBarBaz * x^) {}
1189 }
1190)cpp");
1191}
1192
1193TEST(CompletionTest, CompleteInMacroWithStringification) {
1194 auto Results = completions(R"cpp(
1195void f(const char *, int x);
1196#define F(x) f(#x, x)
1197
1198namespace ns {
1199int X;
1200int Y;
1201} // namespace ns
1202
1203int f(int input_num) {
1204 F(ns::^)
1205}
1206)cpp");
1207
1208 EXPECT_THAT(Results.Completions,
1209 UnorderedElementsAre(named("X"), named("Y")));
1210}
1211
1212TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
1213 auto Results = completions(R"cpp(
1214void f(const char *, int x);
1215#define F(x) f(#x, x)
1216
1217namespace ns {
1218int X;
1219
1220int f(int input_num) {
1221 F(^)
1222}
1223} // namespace ns
1224)cpp");
1225
1226 EXPECT_THAT(Results.Completions, Contains(named("X")));
1227}
1228
1229TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
1230 auto Results = completions(R"cpp(
1231 int bar(int param_in_bar) {
1232 }
1233
1234 int foo(int param_in_foo) {
1235#if 0
1236 // In recovery mode, "param_in_foo" will also be suggested among many other
1237 // unrelated symbols; however, this is really a special case where this works.
1238 // If the #if block is outside of the function, "param_in_foo" is still
1239 // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't
1240 // really provide useful results in excluded branches.
1241 par^
1242#endif
1243 }
1244)cpp");
1245
1246 EXPECT_TRUE(Results.Completions.empty());
1247}
1248
1249TEST(CompletionTest, DefaultArgs) {
1250 clangd::CodeCompleteOptions Opts;
1251 std::string Context = R"cpp(
1252 int X(int A = 0);
1253 int Y(int A, int B = 0);
1254 int Z(int A, int B = 0, int C = 0, int D = 0);
1255 )cpp";
1256 EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions,
1257 UnorderedElementsAre(labeled("X(int A = 0)")));
1258 EXPECT_THAT(completions(Context + "int y = Y^", {}, Opts).Completions,
1259 UnorderedElementsAre(AllOf(labeled("Y(int A, int B = 0)"),
1260 snippetSuffix("(${1:int A})"))));
1261 EXPECT_THAT(completions(Context + "int y = Z^", {}, Opts).Completions,
1262 UnorderedElementsAre(
1263 AllOf(labeled("Z(int A, int B = 0, int C = 0, int D = 0)"),
1264 snippetSuffix("(${1:int A})"))));
1265}
1266
1267TEST(CompletionTest, NoCrashWithTemplateParamsAndPreferredTypes) {
1268 auto Completions = completions(R"cpp(
1269template <template <class> class TT> int foo() {
1270 int a = ^
1271}
1272)cpp")
1273 .Completions;
1274 EXPECT_THAT(Completions, Contains(named("TT")));
1275}
1276
1277TEST(CompletionTest, NestedTemplateHeuristics) {
1278 auto Completions = completions(R"cpp(
1279struct Plain { int xxx; };
1280template <typename T> class Templ { Plain ppp; };
1281template <typename T> void foo(Templ<T> &t) {
1282 // Formally ppp has DependentTy, because Templ may be specialized.
1283 // However we sholud be able to see into it using the primary template.
1284 t.ppp.^
1285}
1286)cpp")
1287 .Completions;
1288 EXPECT_THAT(Completions, Contains(named("xxx")));
1289}
1290
1291TEST(CompletionTest, RecordCCResultCallback) {
1292 std::vector<CodeCompletion> RecordedCompletions;
1293 CodeCompleteOptions Opts;
1294 Opts.RecordCCResult = [&RecordedCompletions](const CodeCompletion &CC,
1295 const SymbolQualitySignals &,
1296 const SymbolRelevanceSignals &,
1297 float Score) {
1298 RecordedCompletions.push_back(CC);
1299 };
1300
1301 completions("int xy1, xy2; int a = xy^", /*IndexSymbols=*/{}, Opts);
1302 EXPECT_THAT(RecordedCompletions,
1303 UnorderedElementsAre(named("xy1"), named("xy2")));
1304}
1305
1306TEST(CompletionTest, ASTSignals) {
1307 struct Completion {
1308 std::string Name;
1309 unsigned MainFileRefs;
1310 unsigned ScopeRefsInFile;
1311 };
1312 CodeCompleteOptions Opts;
1313 std::vector<Completion> RecordedCompletions;
1314 Opts.RecordCCResult = [&RecordedCompletions](const CodeCompletion &CC,
1315 const SymbolQualitySignals &,
1316 const SymbolRelevanceSignals &R,
1317 float Score) {
1318 RecordedCompletions.push_back({CC.Name, R.MainFileRefs, R.ScopeRefsInFile});
1319 };
1320 ASTSignals MainFileSignals;
1321 MainFileSignals.ReferencedSymbols[var("xy1").ID] = 3;
1322 MainFileSignals.ReferencedSymbols[var("xy2").ID] = 1;
1323 MainFileSignals.ReferencedSymbols[var("xyindex").ID] = 10;
1324 MainFileSignals.RelatedNamespaces["tar::"] = 5;
1325 MainFileSignals.RelatedNamespaces["bar::"] = 3;
1326 Opts.MainFileSignals = &MainFileSignals;
1327 Opts.AllScopes = true;
1328 completions(
1329 R"cpp(
1330 int xy1;
1331 int xy2;
1332 namespace bar {
1333 int xybar = 1;
1334 int a = xy^
1335 }
1336 )cpp",
1337 /*IndexSymbols=*/{var("xyindex"), var("tar::xytar"), var("bar::xybar")},
1338 Opts);
1339 EXPECT_THAT(RecordedCompletions,
1340 UnorderedElementsAre(
1341 AllOf(named("xy1"), mainFileRefs(3u), scopeRefs(0u)),
1342 AllOf(named("xy2"), mainFileRefs(1u), scopeRefs(0u)),
1343 AllOf(named("xyindex"), mainFileRefs(10u), scopeRefs(0u)),
1344 AllOf(named("xytar"), mainFileRefs(0u), scopeRefs(5u)),
1345 AllOf(/*both from sema and index*/ named("xybar"),
1346 mainFileRefs(0u), scopeRefs(3u))));
1347}
1348
1349SignatureHelp
1350signatures(llvm::StringRef Text, Position Point,
1351 std::vector<Symbol> IndexSymbols = {},
1352 MarkupKind DocumentationFormat = MarkupKind::PlainText) {
1353 std::unique_ptr<SymbolIndex> Index;
1354 if (!IndexSymbols.empty())
1355 Index = memIndex(IndexSymbols);
1356
1357 auto TU = TestTU::withCode(Text);
1358 MockFS FS;
1359 auto Inputs = TU.inputs(FS);
1360 Inputs.Index = Index.get();
1361 IgnoreDiagnostics Diags;
1362 auto CI = buildCompilerInvocation(Inputs, Diags);
1363 if (!CI) {
1364 ADD_FAILURE() << "Couldn't build CompilerInvocation";
1365 return {};
1366 }
1367 auto Preamble = buildPreamble(testPath(TU.Filename), *CI, Inputs,
1368 /*InMemory=*/true, /*Callback=*/nullptr);
1369 if (!Preamble) {
1370 ADD_FAILURE() << "Couldn't build Preamble";
1371 return {};
1372 }
1373 return signatureHelp(testPath(TU.Filename), Point, *Preamble, Inputs,
1374 DocumentationFormat);
1375}
1376
1377SignatureHelp
1378signatures(llvm::StringRef Text, std::vector<Symbol> IndexSymbols = {},
1379 MarkupKind DocumentationFormat = MarkupKind::PlainText) {
1380 Annotations Test(Text);
1381 return signatures(Test.code(), Test.point(), std::move(IndexSymbols),
1382 DocumentationFormat);
1383}
1384
1385struct ExpectedParameter {
1386 std::string Text;
1387 std::pair<unsigned, unsigned> Offsets;
1388};
1389llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
1390 const ExpectedParameter &P) {
1391 return OS << P.Text;
1392}
1393MATCHER_P(paramsAre, P, "") {
1394 if (P.size() != arg.parameters.size())
1395 return false;
1396 for (unsigned I = 0; I < P.size(); ++I) {
1397 if (P[I].Text != arg.parameters[I].labelString ||
1398 P[I].Offsets != arg.parameters[I].labelOffsets)
1399 return false;
1400 }
1401 return true;
1402}
1403MATCHER_P(sigDoc, doc, "") { return arg.documentation.value == doc; }
1404
1405/// \p AnnotatedLabel is a signature label with ranges marking parameters, e.g.
1406/// foo([[int p1]], [[double p2]]) -> void
1407Matcher<SignatureInformation> sig(llvm::StringRef AnnotatedLabel) {
1408 llvm::Annotations A(AnnotatedLabel);
1409 std::string Label = std::string(A.code());
1410 std::vector<ExpectedParameter> Parameters;
1411 for (auto Range : A.ranges()) {
1412 Parameters.emplace_back();
1413
1414 ExpectedParameter &P = Parameters.back();
1415 P.Text = Label.substr(Range.Begin, Range.End - Range.Begin);
1416 P.Offsets.first = lspLength(llvm::StringRef(Label).substr(0, Range.Begin));
1417 P.Offsets.second = lspLength(llvm::StringRef(Label).substr(1, Range.End));
1418 }
1419 return AllOf(sigHelpLabeled(Label), paramsAre(Parameters));
1420}
1421
1422TEST(SignatureHelpTest, Overloads) {
1423 auto Results = signatures(R"cpp(
1424 void foo(int x, int y);
1425 void foo(int x, float y);
1426 void foo(float x, int y);
1427 void foo(float x, float y);
1428 void bar(int x, int y = 0);
1429 int main() { foo(^); }
1430 )cpp");
1431 EXPECT_THAT(Results.signatures,
1432 UnorderedElementsAre(sig("foo([[float x]], [[float y]]) -> void"),
1433 sig("foo([[float x]], [[int y]]) -> void"),
1434 sig("foo([[int x]], [[float y]]) -> void"),
1435 sig("foo([[int x]], [[int y]]) -> void")));
1436 // We always prefer the first signature.
1437 EXPECT_EQ(0, Results.activeSignature);
1438 EXPECT_EQ(0, Results.activeParameter);
1439}
1440
1441TEST(SignatureHelpTest, FunctionPointers) {
1442 llvm::StringLiteral Tests[] = {
1443 // Variable of function pointer type
1444 R"cpp(
1445 void (*foo)(int x, int y);
1446 int main() { foo(^); }
1447 )cpp",
1448 // Wrapped in an AttributedType
1449 R"cpp(
1450 void (__stdcall *foo)(int x, int y);
1451 int main() { foo(^); }
1452 )cpp",
1453 // Another syntax for an AttributedType
1454 R"cpp(
1455 void (__attribute__(stdcall) *foo)(int x, int y);
1456 int main() { foo(^); },
1457 )cpp",
1458 // Wrapped in a typedef
1459 R"cpp(
1460 typedef void (*fn)(int x, int y);
1461 fn foo;
1462 int main() { foo(^); }
1463 )cpp",
1464 // Wrapped in both a typedef and an AttributedTyped
1465 R"cpp(
1466 typedef void (__stdcall *fn)(int x, int y);
1467 fn foo;
1468 int main() { foo(^); }
1469 )cpp",
1470 // Field of function pointer type
1471 R"cpp(
1472 struct S {
1473 void (*foo)(int x, int y);
1474 };
1475 S s;
1476 int main() { s.foo(^); }
1477 )cpp",
1478 // Field of function pointer typedef type
1479 R"cpp(
1480 typedef void (*fn)(int x, int y);
1481 struct S {
1482 fn foo;
1483 };
1484 S s;
1485 int main() { s.foo(^); }
1486 )cpp"};
1487 for (auto Test : Tests)
1488 EXPECT_THAT(signatures(Test).signatures,
1489 UnorderedElementsAre(sig("([[int x]], [[int y]]) -> void")));
1490}
1491
1492TEST(SignatureHelpTest, Constructors) {
1493 std::string Top = R"cpp(
1494 struct S {
1495 S(int);
1496 S(const S &) = delete;
1497 };
1498 )cpp";
1499
1500 auto CheckParenInit = [&](std::string Init) {
1501 EXPECT_THAT(signatures(Top + Init).signatures,
1502 UnorderedElementsAre(sig("S([[int]])")))
1503 << Init;
1504 };
1505 CheckParenInit("S s(^);");
1506 CheckParenInit("auto s = S(^);");
1507 CheckParenInit("auto s = new S(^);");
1508
1509 auto CheckBracedInit = [&](std::string Init) {
1510 EXPECT_THAT(signatures(Top + Init).signatures,
1511 UnorderedElementsAre(sig("S{[[int]]}")))
1512 << Init;
1513 };
1514 CheckBracedInit("S s{^};");
1515 CheckBracedInit("S s = {^};");
1516 CheckBracedInit("auto s = S{^};");
1517 // FIXME: doesn't work: no ExpectedType set in ParseCXXNewExpression.
1518 // CheckBracedInit("auto s = new S{^};");
1519 CheckBracedInit("int x(S); int i = x({^});");
1520}
1521
1522TEST(SignatureHelpTest, Aggregates) {
1523 std::string Top = R"cpp(
1524 struct S {
1525 int a, b, c, d;
1526 };
1527 )cpp";
1528 auto AggregateSig = sig("S{[[int a]], [[int b]], [[int c]], [[int d]]}");
1529 EXPECT_THAT(signatures(Top + "S s{^}").signatures,
1530 UnorderedElementsAre(AggregateSig, sig("S{}"),
1531 sig("S{[[const S &]]}"),
1532 sig("S{[[S &&]]}")));
1533 EXPECT_THAT(signatures(Top + "S s{1,^}").signatures,
1534 ElementsAre(AggregateSig));
1535 EXPECT_EQ(signatures(Top + "S s{1,^}").activeParameter, 1);
1536 EXPECT_THAT(signatures(Top + "S s{.c=3,^}").signatures,
1537 ElementsAre(AggregateSig));
1538 EXPECT_EQ(signatures(Top + "S s{.c=3,^}").activeParameter, 3);
1539}
1540
1541TEST(SignatureHelpTest, OverloadInitListRegression) {
1542 auto Results = signatures(R"cpp(
1543 struct A {int x;};
1544 struct B {B(A);};
1545 void f();
1546 int main() {
1547 B b({1});
1548 f(^);
1549 }
1550 )cpp");
1551 EXPECT_THAT(Results.signatures, UnorderedElementsAre(sig("f() -> void")));
1552}
1553
1554TEST(SignatureHelpTest, DefaultArgs) {
1555 auto Results = signatures(R"cpp(
1556 void bar(int x, int y = 0);
1557 void bar(float x = 0, int y = 42);
1558 int main() { bar(^
1559 )cpp");
1560 EXPECT_THAT(Results.signatures,
1561 UnorderedElementsAre(
1562 sig("bar([[int x]], [[int y = 0]]) -> void"),
1563 sig("bar([[float x = 0]], [[int y = 42]]) -> void")));
1564 EXPECT_EQ(0, Results.activeSignature);
1565 EXPECT_EQ(0, Results.activeParameter);
1566}
1567
1568TEST(SignatureHelpTest, ActiveArg) {
1569 auto Results = signatures(R"cpp(
1570 int baz(int a, int b, int c);
1571 int main() { baz(baz(1,2,3), ^); }
1572 )cpp");
1573 EXPECT_THAT(Results.signatures,
1574 ElementsAre(sig("baz([[int a]], [[int b]], [[int c]]) -> int")));
1575 EXPECT_EQ(0, Results.activeSignature);
1576 EXPECT_EQ(1, Results.activeParameter);
1577}
1578
1579TEST(SignatureHelpTest, OpeningParen) {
1580 llvm::StringLiteral Tests[] = {
1581 // Recursive function call.
1582 R"cpp(
1583 int foo(int a, int b, int c);
1584 int main() {
1585 foo(foo $p^( foo(10, 10, 10), ^ )));
1586 })cpp",
1587 // Functional type cast.
1588 R"cpp(
1589 struct Foo {
1590 Foo(int a, int b, int c);
1591 };
1592 int main() {
1593 Foo $p^( 10, ^ );
1594 })cpp",
1595 // New expression.
1596 R"cpp(
1597 struct Foo {
1598 Foo(int a, int b, int c);
1599 };
1600 int main() {
1601 new Foo $p^( 10, ^ );
1602 })cpp",
1603 // Macro expansion.
1604 R"cpp(
1605 int foo(int a, int b, int c);
1606 #define FOO foo(
1607
1608 int main() {
1609 // Macro expansions.
1610 $p^FOO 10, ^ );
1611 })cpp",
1612 // Macro arguments.
1613 R"cpp(
1614 int foo(int a, int b, int c);
1615 int main() {
1616 #define ID(X) X
1617 // FIXME: figure out why ID(foo (foo(10), )) doesn't work when preserving
1618 // the recovery expression.
1619 ID(foo $p^( 10, ^ ))
1620 })cpp",
1621 // Dependent args.
1622 R"cpp(
1623 int foo(int a, int b);
1624 template <typename T> void bar(T t) {
1625 foo$p^(t, ^t);
1626 })cpp",
1627 // Dependent args on templated func.
1628 R"cpp(
1629 template <typename T>
1630 int foo(T, T);
1631 template <typename T> void bar(T t) {
1632 foo$p^(t, ^t);
1633 })cpp",
1634 // Dependent args on member.
1635 R"cpp(
1636 struct Foo { int foo(int, int); };
1637 template <typename T> void bar(T t) {
1638 Foo f;
1639 f.foo$p^(t, ^t);
1640 })cpp",
1641 // Dependent args on templated member.
1642 R"cpp(
1643 struct Foo { template <typename T> int foo(T, T); };
1644 template <typename T> void bar(T t) {
1645 Foo f;
1646 f.foo$p^(t, ^t);
1647 })cpp",
1648 };
1649
1650 for (auto Test : Tests) {
1651 Annotations Code(Test);
1652 EXPECT_EQ(signatures(Code.code(), Code.point()).argListStart,
1653 Code.point("p"))
1654 << "Test source:" << Test;
1655 }
1656}
1657
1658TEST(SignatureHelpTest, StalePreamble) {
1659 TestTU TU;
1660 TU.Code = "";
1661 IgnoreDiagnostics Diags;
1662 MockFS FS;
1663 auto Inputs = TU.inputs(FS);
1664 auto CI = buildCompilerInvocation(Inputs, Diags);
1665 ASSERT_TRUE(CI);
1666 auto EmptyPreamble = buildPreamble(testPath(TU.Filename), *CI, Inputs,
1667 /*InMemory=*/true, /*Callback=*/nullptr);
1668 ASSERT_TRUE(EmptyPreamble);
1669
1670 TU.AdditionalFiles["a.h"] = "int foo(int x);";
1671 const Annotations Test(R"cpp(
1672 #include "a.h"
1673 void bar() { foo(^2); })cpp");
1674 TU.Code = Test.code().str();
1675 auto Results =
1676 signatureHelp(testPath(TU.Filename), Test.point(), *EmptyPreamble,
1677 TU.inputs(FS), MarkupKind::PlainText);
1678 EXPECT_THAT(Results.signatures, ElementsAre(sig("foo([[int x]]) -> int")));
1679 EXPECT_EQ(0, Results.activeSignature);
1680 EXPECT_EQ(0, Results.activeParameter);
1681}
1682
1683class IndexRequestCollector : public SymbolIndex {
1684public:
1685 IndexRequestCollector(std::vector<Symbol> Syms = {}) : Symbols(Syms) {}
1686
1687 bool
1688 fuzzyFind(const FuzzyFindRequest &Req,
1689 llvm::function_ref<void(const Symbol &)> Callback) const override {
1690 std::unique_lock<std::mutex> Lock(Mut);
1691 Requests.push_back(Req);
1692 ReceivedRequestCV.notify_one();
1693 for (const auto &Sym : Symbols)
1694 Callback(Sym);
1695 return true;
1696 }
1697
1698 void lookup(const LookupRequest &,
1699 llvm::function_ref<void(const Symbol &)>) const override {}
1700
1701 bool refs(const RefsRequest &,
1702 llvm::function_ref<void(const Ref &)>) const override {
1703 return false;
1704 }
1705
1706 bool containedRefs(
1707 const ContainedRefsRequest &,
1708 llvm::function_ref<void(const ContainedRefsResult &)>) const override {
1709 return false;
1710 }
1711
1712 void relations(const RelationsRequest &,
1713 llvm::function_ref<void(const SymbolID &, const Symbol &)>)
1714 const override {}
1715
1716 llvm::unique_function<IndexContents(llvm::StringRef) const>
1717 indexedFiles() const override {
1718 return [](llvm::StringRef) { return IndexContents::None; };
1719 }
1720
1721 // This is incorrect, but IndexRequestCollector is not an actual index and it
1722 // isn't used in production code.
1723 size_t estimateMemoryUsage() const override { return 0; }
1724
1725 const std::vector<FuzzyFindRequest> consumeRequests(size_t Num) const {
1726 std::unique_lock<std::mutex> Lock(Mut);
1727 EXPECT_TRUE(wait(Lock, ReceivedRequestCV, timeoutSeconds(30),
1728 [this, Num] { return Requests.size() == Num; }));
1729 auto Reqs = std::move(Requests);
1730 Requests = {};
1731 return Reqs;
1732 }
1733
1734private:
1735 std::vector<Symbol> Symbols;
1736 // We need a mutex to handle async fuzzy find requests.
1737 mutable std::condition_variable ReceivedRequestCV;
1738 mutable std::mutex Mut;
1739 mutable std::vector<FuzzyFindRequest> Requests;
1740};
1741
1742// Clients have to consume exactly Num requests.
1743std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code,
1744 size_t Num = 1) {
1745 clangd::CodeCompleteOptions Opts;
1746 IndexRequestCollector Requests;
1747 Opts.Index = &Requests;
1748 completions(Code, {}, Opts);
1749 const auto Reqs = Requests.consumeRequests(Num);
1750 EXPECT_EQ(Reqs.size(), Num);
1751 return Reqs;
1752}
1753
1754TEST(CompletionTest, UnqualifiedIdQuery) {
1755 auto Requests = captureIndexRequests(R"cpp(
1756 namespace std {}
1757 using namespace std;
1758 namespace ns {
1759 void f() {
1760 vec^
1761 }
1762 }
1763 )cpp");
1764
1765 EXPECT_THAT(Requests,
1766 ElementsAre(Field(&FuzzyFindRequest::Scopes,
1767 UnorderedElementsAre("", "ns::", "std::"))));
1768}
1769
1770TEST(CompletionTest, EnclosingScopeComesFirst) {
1771 auto Requests = captureIndexRequests(R"cpp(
1772 namespace std {}
1773 using namespace std;
1774 namespace nx {
1775 namespace ns {
1776 namespace {
1777 void f() {
1778 vec^
1779 }
1780 }
1781 }
1782 }
1783 )cpp");
1784
1785 EXPECT_THAT(Requests,
1786 ElementsAre(Field(
1788 UnorderedElementsAre("", "std::", "nx::ns::", "nx::"))));
1789 EXPECT_EQ(Requests[0].Scopes[0], "nx::ns::");
1790}
1791
1792TEST(CompletionTest, ResolvedQualifiedIdQuery) {
1793 auto Requests = captureIndexRequests(R"cpp(
1794 namespace ns1 {}
1795 namespace ns2 {} // ignore
1796 namespace ns3 { namespace nns3 {} }
1797 namespace foo {
1798 using namespace ns1;
1799 using namespace ns3::nns3;
1800 }
1801 namespace ns {
1802 void f() {
1803 foo::^
1804 }
1805 }
1806 )cpp");
1807
1808 EXPECT_THAT(Requests,
1809 ElementsAre(Field(
1811 UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::"))));
1812}
1813
1814TEST(CompletionTest, UnresolvedQualifierIdQuery) {
1815 auto Requests = captureIndexRequests(R"cpp(
1816 namespace a {}
1817 using namespace a;
1818 namespace ns {
1819 void f() {
1820 bar::^
1821 }
1822 } // namespace ns
1823 )cpp");
1824
1825 EXPECT_THAT(Requests,
1826 ElementsAre(Field(
1828 UnorderedElementsAre("a::bar::", "ns::bar::", "bar::"))));
1829}
1830
1831TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
1832 auto Requests = captureIndexRequests(R"cpp(
1833 namespace a {}
1834 using namespace a;
1835 namespace ns {
1836 void f() {
1837 ::a::bar::^
1838 }
1839 } // namespace ns
1840 )cpp");
1841
1842 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1843 UnorderedElementsAre("a::bar::"))));
1844}
1845
1846TEST(CompletionTest, EmptyQualifiedQuery) {
1847 auto Requests = captureIndexRequests(R"cpp(
1848 namespace ns {
1849 void f() {
1850 ^
1851 }
1852 } // namespace ns
1853 )cpp");
1854
1855 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1856 UnorderedElementsAre("", "ns::"))));
1857}
1858
1859TEST(CompletionTest, GlobalQualifiedQuery) {
1860 auto Requests = captureIndexRequests(R"cpp(
1861 namespace ns {
1862 void f() {
1863 ::^
1864 }
1865 } // namespace ns
1866 )cpp");
1867
1868 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1869 UnorderedElementsAre(""))));
1870}
1871
1872TEST(CompletionTest, NoDuplicatedQueryScopes) {
1873 auto Requests = captureIndexRequests(R"cpp(
1874 namespace {}
1875
1876 namespace na {
1877 namespace {}
1878 namespace nb {
1879 ^
1880 } // namespace nb
1881 } // namespace na
1882 )cpp");
1883
1884 EXPECT_THAT(Requests,
1885 ElementsAre(Field(&FuzzyFindRequest::Scopes,
1886 UnorderedElementsAre("na::", "na::nb::", ""))));
1887}
1888
1889TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
1890 auto Completions = completions(
1891 R"cpp(
1892 struct Foo {
1893 int SomeNameOfField;
1894 typedef int SomeNameOfTypedefField;
1895 };
1896
1897 Foo::^)cpp",
1898 {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")});
1899
1900 EXPECT_THAT(Completions.Completions,
1901 AllOf(Contains(labeled("SomeNameOfField")),
1902 Contains(labeled("SomeNameOfTypedefField")),
1903 Not(Contains(labeled("SomeNameInTheIndex")))));
1904}
1905
1906TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
1907 {
1908 auto Completions = completions(
1909 R"cpp(
1910 template <class T>
1911 void foo() {
1912 T::^
1913 }
1914 )cpp",
1915 {func("::SomeNameInTheIndex")});
1916
1917 EXPECT_THAT(Completions.Completions,
1918 Not(Contains(labeled("SomeNameInTheIndex"))));
1919 }
1920
1921 {
1922 auto Completions = completions(
1923 R"cpp(
1924 template <class T>
1925 void foo() {
1926 T::template Y<int>::^
1927 }
1928 )cpp",
1929 {func("::SomeNameInTheIndex")});
1930
1931 EXPECT_THAT(Completions.Completions,
1932 Not(Contains(labeled("SomeNameInTheIndex"))));
1933 }
1934
1935 {
1936 auto Completions = completions(
1937 R"cpp(
1938 template <class T>
1939 void foo() {
1940 T::foo::^
1941 }
1942 )cpp",
1943 {func("::SomeNameInTheIndex")});
1944
1945 EXPECT_THAT(Completions.Completions,
1946 Not(Contains(labeled("SomeNameInTheIndex"))));
1947 }
1948}
1949
1950TEST(CompletionTest, OverloadBundling) {
1951 clangd::CodeCompleteOptions Opts;
1952 Opts.BundleOverloads = true;
1953
1954 std::string Context = R"cpp(
1955 struct X {
1956 // Overload with int
1957 int a(int) __attribute__((deprecated("", "")));
1958 // Overload with bool
1959 int a(bool);
1960 int b(float);
1961
1962 X(int);
1963 X(float);
1964 };
1965 int GFuncC(int);
1966 int GFuncD(int);
1967 )cpp";
1968
1969 // Member completions are bundled.
1970 EXPECT_THAT(completions(Context + "int y = X().^", {}, Opts).Completions,
1971 UnorderedElementsAre(labeled("a(…)"), labeled("b(float)")));
1972
1973 // Constructor completions are bundled.
1974 EXPECT_THAT(completions(Context + "X z = X^", {}, Opts).Completions,
1975 UnorderedElementsAre(labeled("X"), labeled("X(…)")));
1976
1977 // Non-member completions are bundled, including index+sema.
1978 Symbol NoArgsGFunc = func("GFuncC");
1979 EXPECT_THAT(
1980 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1981 UnorderedElementsAre(labeled("GFuncC(…)"), labeled("GFuncD(int)")));
1982
1983 // Differences in header-to-insert suppress bundling.
1984 std::string DeclFile = URI::create(testPath("foo")).toString();
1985 NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile.c_str();
1986 NoArgsGFunc.IncludeHeaders.emplace_back("<foo>", 1, Symbol::Include);
1987 EXPECT_THAT(
1988 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1989 UnorderedElementsAre(AllOf(named("GFuncC"), insertInclude("<foo>")),
1990 labeled("GFuncC(int)"), labeled("GFuncD(int)")));
1991
1992 // Examine a bundled completion in detail.
1993 auto A =
1994 completions(Context + "int y = X().a^", {}, Opts).Completions.front();
1995 EXPECT_EQ(A.Name, "a");
1996 EXPECT_EQ(A.Signature, "(…)");
1997 EXPECT_EQ(A.BundleSize, 2u);
1998 EXPECT_EQ(A.Kind, CompletionItemKind::Method);
1999 EXPECT_EQ(A.ReturnType, "int"); // All overloads return int.
2000 // For now we just return one of the doc strings arbitrarily.
2001 ASSERT_TRUE(A.Documentation);
2002 ASSERT_FALSE(A.Deprecated); // Not all overloads deprecated.
2003 EXPECT_THAT(
2004 A.Documentation->asPlainText(),
2005 AnyOf(HasSubstr("Overload with int"), HasSubstr("Overload with bool")));
2006 EXPECT_EQ(A.SnippetSuffix, "($0)");
2007}
2008
2009TEST(CompletionTest, OverloadBundlingSameFileDifferentURI) {
2010 clangd::CodeCompleteOptions Opts;
2011 Opts.BundleOverloads = true;
2012
2013 Symbol SymX = sym("ns::X", index::SymbolKind::Function, "@F@\\0#");
2014 Symbol SymY = sym("ns::X", index::SymbolKind::Function, "@F@\\0#I#");
2015 std::string BarHeader = testPath("bar.h");
2016 auto BarURI = URI::create(BarHeader).toString();
2017 SymX.CanonicalDeclaration.FileURI = BarURI.c_str();
2018 SymY.CanonicalDeclaration.FileURI = BarURI.c_str();
2019 // The include header is different, but really it's the same file.
2020 SymX.IncludeHeaders.emplace_back("\"bar.h\"", 1, Symbol::Include);
2021 SymY.IncludeHeaders.emplace_back(BarURI.c_str(), 1, Symbol::Include);
2022
2023 auto Results = completions("void f() { ::ns::^ }", {SymX, SymY}, Opts);
2024 // Expect both results are bundled, despite the different-but-same
2025 // IncludeHeader.
2026 ASSERT_EQ(1u, Results.Completions.size());
2027 const auto &R = Results.Completions.front();
2028 EXPECT_EQ("X", R.Name);
2029 EXPECT_EQ(2u, R.BundleSize);
2030}
2031
2032TEST(CompletionTest, DocumentationFromChangedFileCrash) {
2033 MockFS FS;
2034 auto FooH = testPath("foo.h");
2035 auto FooCpp = testPath("foo.cpp");
2036 FS.Files[FooH] = R"cpp(
2037 // this is my documentation comment.
2038 int func();
2039 )cpp";
2040 FS.Files[FooCpp] = "";
2041
2042 MockCompilationDatabase CDB;
2043 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
2044
2045 Annotations Source(R"cpp(
2046 #include "foo.h"
2047 int func() {
2048 // This makes sure we have func from header in the AST.
2049 }
2050 int a = fun^
2051 )cpp");
2052 Server.addDocument(FooCpp, Source.code(), "null", WantDiagnostics::Yes);
2053 // We need to wait for preamble to build.
2054 ASSERT_TRUE(Server.blockUntilIdleForTest());
2055
2056 // Change the header file. Completion will reuse the old preamble!
2057 FS.Files[FooH] = R"cpp(
2058 int func();
2059 )cpp";
2060
2061 clangd::CodeCompleteOptions Opts;
2062 CodeCompleteResult Completions =
2063 cantFail(runCodeComplete(Server, FooCpp, Source.point(), Opts));
2064 // We shouldn't crash. Unfortunately, current workaround is to not produce
2065 // comments for symbols from headers.
2066 EXPECT_THAT(Completions.Completions,
2067 Contains(AllOf(Not(isDocumented()), named("func"))));
2068}
2069
2070TEST(CompletionTest, NonDocComments) {
2071 const char *Text = R"cpp(
2072 // We ignore namespace comments, for rationale see CodeCompletionStrings.h.
2073 namespace comments_ns {
2074 }
2075
2076 // ------------------
2077 int comments_foo();
2078
2079 // A comment and a decl are separated by newlines.
2080 // Therefore, the comment shouldn't show up as doc comment.
2081
2082 int comments_bar();
2083
2084 // this comment should be in the results.
2085 int comments_baz();
2086
2087
2088 template <class T>
2089 struct Struct {
2090 int comments_qux();
2091 int comments_quux();
2092 };
2093
2094
2095 // This comment should not be there.
2096
2097 template <class T>
2098 int Struct<T>::comments_qux() {
2099 }
2100
2101 // This comment **should** be in results.
2102 template <class T>
2103 int Struct<T>::comments_quux() {
2104 int a = comments^;
2105 }
2106 )cpp";
2107
2108 // We should not get any of those comments in completion.
2109 EXPECT_THAT(
2110 completions(Text).Completions,
2111 UnorderedElementsAre(AllOf(Not(isDocumented()), named("comments_foo")),
2112 AllOf(isDocumented(), named("comments_baz")),
2113 AllOf(isDocumented(), named("comments_quux")),
2114 AllOf(Not(isDocumented()), named("comments_ns")),
2115 // FIXME(ibiryukov): the following items should have
2116 // empty documentation, since they are separated from
2117 // a comment with an empty line. Unfortunately, I
2118 // couldn't make Sema tests pass if we ignore those.
2119 AllOf(isDocumented(), named("comments_bar")),
2120 AllOf(isDocumented(), named("comments_qux"))));
2121}
2122
2123TEST(CompletionTest, CompleteOnInvalidLine) {
2124 auto FooCpp = testPath("foo.cpp");
2125
2126 MockCompilationDatabase CDB;
2127 MockFS FS;
2128 FS.Files[FooCpp] = "// empty file";
2129
2130 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
2131 // Run completion outside the file range.
2132 Position Pos;
2133 Pos.line = 100;
2134 Pos.character = 0;
2135 EXPECT_THAT_EXPECTED(
2136 runCodeComplete(Server, FooCpp, Pos, clangd::CodeCompleteOptions()),
2137 Failed());
2138}
2139
2140TEST(CompletionTest, QualifiedNames) {
2141 auto Results = completions(
2142 R"cpp(
2143 namespace ns { int local; void both(); }
2144 void f() { ::ns::^ }
2145 )cpp",
2146 {func("ns::both"), cls("ns::Index")});
2147 // We get results from both index and sema, with no duplicates.
2148 EXPECT_THAT(
2149 Results.Completions,
2150 UnorderedElementsAre(scope("ns::"), scope("ns::"), scope("ns::")));
2151}
2152
2153TEST(CompletionTest, Render) {
2154 CodeCompletion C;
2155 C.Name = "x";
2156 C.FilterText = "x";
2157 C.Signature = "(bool) const";
2158 C.SnippetSuffix = "(${0:bool})";
2159 C.ReturnType = "int";
2160 C.RequiredQualifier = "Foo::";
2161 C.Scope = "ns::Foo::";
2162 C.Documentation.emplace();
2163 C.Documentation->addParagraph().appendText("This is ").appendCode("x()");
2164 C.Includes.emplace_back();
2165 auto &Include = C.Includes.back();
2166 Include.Header = "\"foo.h\"";
2168 C.Score.Total = 1.0;
2169 C.Score.ExcludingName = .5;
2171
2172 CodeCompleteOptions Opts;
2173 Opts.IncludeIndicator.Insert = "^";
2174 Opts.IncludeIndicator.NoInsert = "";
2175 Opts.EnableSnippets = false;
2176
2177 auto R = C.render(Opts);
2178 EXPECT_EQ(R.label, "Foo::x");
2179 EXPECT_EQ(R.labelDetails->detail, "(bool) const");
2180 EXPECT_EQ(R.insertText, "Foo::x");
2181 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
2182 EXPECT_EQ(R.filterText, "x");
2183 EXPECT_EQ(R.detail, "int");
2184 EXPECT_EQ(R.documentation->value, "From \"foo.h\"\nThis is x()");
2185 EXPECT_THAT(R.additionalTextEdits, IsEmpty());
2186 EXPECT_EQ(R.sortText, sortText(1.0, "x"));
2187 EXPECT_FALSE(R.deprecated);
2188 EXPECT_EQ(R.score, .5f);
2189
2190 C.FilterText = "xtra";
2191 R = C.render(Opts);
2192 EXPECT_EQ(R.filterText, "xtra");
2193 EXPECT_EQ(R.sortText, sortText(1.0, "xtra"));
2194
2195 Opts.EnableSnippets = true;
2196 R = C.render(Opts);
2197 EXPECT_EQ(R.insertText, "Foo::x(${0:bool})");
2198 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
2199
2200 C.SnippetSuffix = "";
2201 R = C.render(Opts);
2202 EXPECT_EQ(R.insertText, "Foo::x");
2203 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
2204
2205 Include.Insertion.emplace();
2206 R = C.render(Opts);
2207 EXPECT_EQ(R.label, "^Foo::x");
2208 EXPECT_EQ(R.labelDetails->detail, "(bool) const");
2209 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
2210
2211 Opts.ShowOrigins = true;
2212 R = C.render(Opts);
2213 EXPECT_EQ(R.label, "^[AS]Foo::x");
2214 EXPECT_EQ(R.labelDetails->detail, "(bool) const");
2215
2216 C.BundleSize = 2;
2217 R = C.render(Opts);
2218 EXPECT_EQ(R.detail, "[2 overloads]");
2219 EXPECT_EQ(R.documentation->value, "From \"foo.h\"\nThis is x()");
2220
2221 C.Deprecated = true;
2222 R = C.render(Opts);
2223 EXPECT_TRUE(R.deprecated);
2224
2226 R = C.render(Opts);
2227 EXPECT_EQ(R.documentation->value, "From `\"foo.h\"` \nThis is `x()`");
2228}
2229
2230TEST(CompletionTest, IgnoreRecoveryResults) {
2231 auto Results = completions(
2232 R"cpp(
2233 namespace ns { int NotRecovered() { return 0; } }
2234 void f() {
2235 // Sema enters recovery mode first and then normal mode.
2236 if (auto x = ns::NotRecover^)
2237 }
2238 )cpp");
2239 EXPECT_THAT(Results.Completions, UnorderedElementsAre(named("NotRecovered")));
2240}
2241
2242TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
2243 auto Results = completions(
2244 R"cpp(
2245 namespace ns {
2246 class X { public: X(); int x_; };
2247 X::X() : x_^(0) {}
2248 }
2249 )cpp");
2250 EXPECT_THAT(Results.Completions,
2251 UnorderedElementsAre(AllOf(scope("ns::X::"), named("x_"))));
2252}
2253
2254// Like other class members, constructor init lists have to parse what's below,
2255// after the completion point.
2256// But recovering from an incomplete constructor init list is particularly
2257// tricky because the bulk of the list is not surrounded by brackets.
2258TEST(CompletionTest, ConstructorInitListIncomplete) {
2259 auto Results = completions(
2260 R"cpp(
2261 namespace ns {
2262 struct X {
2263 X() : x^
2264 int xyz_;
2265 };
2266 }
2267 )cpp");
2268 EXPECT_THAT(Results.Completions, ElementsAre(named("xyz_")));
2269
2270 Results = completions(
2271 R"cpp(
2272 int foo();
2273
2274 namespace ns {
2275 struct X {
2276 X() : xyz_(fo^
2277 int xyz_;
2278 };
2279 }
2280 )cpp");
2281 EXPECT_THAT(Results.Completions, ElementsAre(named("foo")));
2282}
2283
2284TEST(CompletionTest, CodeCompletionContext) {
2285 auto Results = completions(
2286 R"cpp(
2287 namespace ns {
2288 class X { public: X(); int x_; };
2289 void f() {
2290 X x;
2291 x.^;
2292 }
2293 }
2294 )cpp");
2295
2296 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
2297}
2298
2299TEST(CompletionTest, FixItForArrowToDot) {
2300 MockFS FS;
2301 MockCompilationDatabase CDB;
2302
2303 CodeCompleteOptions Opts;
2304 Opts.IncludeFixIts = true;
2305 const char *Code =
2306 R"cpp(
2307 class Auxilary {
2308 public:
2309 void AuxFunction();
2310 };
2311 class ClassWithPtr {
2312 public:
2313 void MemberFunction();
2314 Auxilary* operator->() const;
2315 Auxilary* Aux;
2316 };
2317 void f() {
2318 ClassWithPtr x;
2319 x[[->]]^;
2320 }
2321 )cpp";
2322 auto Results = completions(Code, {}, Opts);
2323 EXPECT_EQ(Results.Completions.size(), 3u);
2324
2325 TextEdit ReplacementEdit;
2326 ReplacementEdit.range = Annotations(Code).range();
2327 ReplacementEdit.newText = ".";
2328 for (const auto &C : Results.Completions) {
2329 EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction");
2330 if (!C.FixIts.empty()) {
2331 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
2332 }
2333 }
2334}
2335
2336TEST(CompletionTest, FixItForDotToArrow) {
2337 CodeCompleteOptions Opts;
2338 Opts.IncludeFixIts = true;
2339 const char *Code =
2340 R"cpp(
2341 class Auxilary {
2342 public:
2343 void AuxFunction();
2344 };
2345 class ClassWithPtr {
2346 public:
2347 void MemberFunction();
2348 Auxilary* operator->() const;
2349 Auxilary* Aux;
2350 };
2351 void f() {
2352 ClassWithPtr x;
2353 x[[.]]^;
2354 }
2355 )cpp";
2356 auto Results = completions(Code, {}, Opts);
2357 EXPECT_EQ(Results.Completions.size(), 3u);
2358
2359 TextEdit ReplacementEdit;
2360 ReplacementEdit.range = Annotations(Code).range();
2361 ReplacementEdit.newText = "->";
2362 for (const auto &C : Results.Completions) {
2363 EXPECT_TRUE(C.FixIts.empty() || C.Name == "AuxFunction");
2364 if (!C.FixIts.empty()) {
2365 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
2366 }
2367 }
2368}
2369
2370TEST(CompletionTest, RenderWithFixItMerged) {
2371 TextEdit FixIt;
2372 FixIt.range.end.character = 5;
2373 FixIt.newText = "->";
2374
2375 CodeCompletion C;
2376 C.Name = "x";
2377 C.RequiredQualifier = "Foo::";
2378 C.FixIts = {FixIt};
2379 C.CompletionTokenRange.start.character = 5;
2380
2381 CodeCompleteOptions Opts;
2382 Opts.IncludeFixIts = true;
2383
2384 auto R = C.render(Opts);
2385 EXPECT_TRUE(R.textEdit);
2386 EXPECT_EQ(R.textEdit->newText, "->Foo::x");
2387 EXPECT_TRUE(R.additionalTextEdits.empty());
2388}
2389
2390TEST(CompletionTest, RenderWithFixItNonMerged) {
2391 TextEdit FixIt;
2392 FixIt.range.end.character = 4;
2393 FixIt.newText = "->";
2394
2395 CodeCompletion C;
2396 C.Name = "x";
2397 C.RequiredQualifier = "Foo::";
2398 C.FixIts = {FixIt};
2399 C.CompletionTokenRange.start.character = 5;
2400
2401 CodeCompleteOptions Opts;
2402 Opts.IncludeFixIts = true;
2403
2404 auto R = C.render(Opts);
2405 EXPECT_TRUE(R.textEdit);
2406 EXPECT_EQ(R.textEdit->newText, "Foo::x");
2407 EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
2408}
2409
2410TEST(CompletionTest, CompletionTokenRange) {
2411 MockFS FS;
2412 MockCompilationDatabase CDB;
2413 TestTU TU;
2414 TU.AdditionalFiles["foo/abc/foo.h"] = "";
2415
2416 constexpr const char *TestCodes[] = {
2417 R"cpp(
2418 class Auxilary {
2419 public:
2420 void AuxFunction();
2421 };
2422 void f() {
2423 Auxilary x;
2424 x.[[Aux]]^;
2425 }
2426 )cpp",
2427 R"cpp(
2428 class Auxilary {
2429 public:
2430 void AuxFunction();
2431 };
2432 void f() {
2433 Auxilary x;
2434 x.[[]]^;
2435 }
2436 )cpp",
2437 R"cpp(
2438 #include "foo/[[a^/]]foo.h"
2439 )cpp",
2440 R"cpp(
2441 #include "foo/abc/[[fo^o.h"]]
2442 )cpp",
2443 };
2444 for (const auto &Text : TestCodes) {
2445 Annotations TestCode(Text);
2446 TU.Code = TestCode.code().str();
2447 auto Results = completions(TU, TestCode.point());
2448 if (Results.Completions.size() != 1) {
2449 ADD_FAILURE() << "Results.Completions.size() != 1" << Text;
2450 continue;
2451 }
2452 EXPECT_THAT(Results.Completions.front().CompletionTokenRange,
2453 TestCode.range());
2454 }
2455}
2456
2457TEST(SignatureHelpTest, OverloadsOrdering) {
2458 const auto Results = signatures(R"cpp(
2459 void foo(int x);
2460 void foo(int x, float y);
2461 void foo(float x, int y);
2462 void foo(float x, float y);
2463 void foo(int x, int y = 0);
2464 int main() { foo(^); }
2465 )cpp");
2466 EXPECT_THAT(Results.signatures,
2467 ElementsAre(sig("foo([[int x]]) -> void"),
2468 sig("foo([[int x]], [[int y = 0]]) -> void"),
2469 sig("foo([[float x]], [[int y]]) -> void"),
2470 sig("foo([[int x]], [[float y]]) -> void"),
2471 sig("foo([[float x]], [[float y]]) -> void")));
2472 // We always prefer the first signature.
2473 EXPECT_EQ(0, Results.activeSignature);
2474 EXPECT_EQ(0, Results.activeParameter);
2475}
2476
2477TEST(SignatureHelpTest, InstantiatedSignatures) {
2478 StringRef Sig0 = R"cpp(
2479 template <class T>
2480 void foo(T, T, T);
2481
2482 int main() {
2483 foo<int>(^);
2484 }
2485 )cpp";
2486
2487 EXPECT_THAT(signatures(Sig0).signatures,
2488 ElementsAre(sig("foo([[T]], [[T]], [[T]]) -> void")));
2489
2490 StringRef Sig1 = R"cpp(
2491 template <class T>
2492 void foo(T, T, T);
2493
2494 int main() {
2495 foo(10, ^);
2496 })cpp";
2497
2498 EXPECT_THAT(signatures(Sig1).signatures,
2499 ElementsAre(sig("foo([[T]], [[T]], [[T]]) -> void")));
2500
2501 StringRef Sig2 = R"cpp(
2502 template <class ...T>
2503 void foo(T...);
2504
2505 int main() {
2506 foo<int>(^);
2507 }
2508 )cpp";
2509
2510 EXPECT_THAT(signatures(Sig2).signatures,
2511 ElementsAre(sig("foo([[T...]]) -> void")));
2512
2513 // It is debatable whether we should substitute the outer template parameter
2514 // ('T') in that case. Currently we don't substitute it in signature help, but
2515 // do substitute in code complete.
2516 // FIXME: make code complete and signature help consistent, figure out which
2517 // way is better.
2518 StringRef Sig3 = R"cpp(
2519 template <class T>
2520 struct X {
2521 template <class U>
2522 void foo(T, U);
2523 };
2524
2525 int main() {
2526 X<int>().foo<double>(^)
2527 }
2528 )cpp";
2529
2530 EXPECT_THAT(signatures(Sig3).signatures,
2531 ElementsAre(sig("foo([[T]], [[U]]) -> void")));
2532}
2533
2534TEST(SignatureHelpTest, IndexDocumentation) {
2535 Symbol Foo0 = sym("foo", index::SymbolKind::Function, "@F@\\0#");
2536 Foo0.Documentation = "doc from the index";
2537 Symbol Foo1 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#");
2538 Foo1.Documentation = "doc from the index";
2539 Symbol Foo2 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#I#");
2540
2541 StringRef Sig0 = R"cpp(
2542 int foo();
2543 int foo(double);
2544
2545 void test() {
2546 foo(^);
2547 }
2548 )cpp";
2549
2550 EXPECT_THAT(
2551 signatures(Sig0, {Foo0}).signatures,
2552 ElementsAre(AllOf(sig("foo() -> int"), sigDoc("doc from the index")),
2553 AllOf(sig("foo([[double]]) -> int"), sigDoc(""))));
2554
2555 StringRef Sig1 = R"cpp(
2556 int foo();
2557 // Overriden doc from sema
2558 int foo(int);
2559 // doc from sema
2560 int foo(int, int);
2561
2562 void test() {
2563 foo(^);
2564 }
2565 )cpp";
2566
2567 EXPECT_THAT(
2568 signatures(Sig1, {Foo0, Foo1, Foo2}).signatures,
2569 ElementsAre(
2570 AllOf(sig("foo() -> int"), sigDoc("doc from the index")),
2571 AllOf(sig("foo([[int]]) -> int"), sigDoc("Overriden doc from sema")),
2572 AllOf(sig("foo([[int]], [[int]]) -> int"), sigDoc("doc from sema"))));
2573}
2574
2575TEST(SignatureHelpTest, DynamicIndexDocumentation) {
2576 MockFS FS;
2577 MockCompilationDatabase CDB;
2578 ClangdServer::Options Opts = ClangdServer::optsForTest();
2579 Opts.BuildDynamicSymbolIndex = true;
2580 ClangdServer Server(CDB, FS, Opts);
2581
2582 FS.Files[testPath("foo.h")] = R"cpp(
2583 struct Foo {
2584 // Member doc
2585 int foo();
2586 };
2587 )cpp";
2588 Annotations FileContent(R"cpp(
2589 #include "foo.h"
2590 void test() {
2591 Foo f;
2592 f.foo(^);
2593 }
2594 )cpp");
2595 auto File = testPath("test.cpp");
2596 Server.addDocument(File, FileContent.code());
2597 // Wait for the dynamic index being built.
2598 ASSERT_TRUE(Server.blockUntilIdleForTest());
2599 EXPECT_THAT(llvm::cantFail(runSignatureHelp(Server, File, FileContent.point(),
2601 .signatures,
2602 ElementsAre(AllOf(sig("foo() -> int"), sigDoc("Member doc"))));
2603}
2604
2605TEST(CompletionTest, ArgumentListsPolicy) {
2606 CodeCompleteOptions Opts;
2607 Opts.EnableSnippets = true;
2609
2610 {
2611 auto Results = completions(
2612 R"cpp(
2613 void xfoo();
2614 void xfoo(int x, int y);
2615 void f() { xfo^ })cpp",
2616 {}, Opts);
2617 EXPECT_THAT(
2618 Results.Completions,
2619 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix("()")),
2620 AllOf(named("xfoo"), snippetSuffix("($0)"))));
2621 }
2622 {
2623 auto Results = completions(
2624 R"cpp(
2625 void xbar();
2626 void f() { xba^ })cpp",
2627 {}, Opts);
2628 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
2629 named("xbar"), snippetSuffix("()"))));
2630 }
2631 {
2632 Opts.BundleOverloads = true;
2633 auto Results = completions(
2634 R"cpp(
2635 void xfoo();
2636 void xfoo(int x, int y);
2637 void f() { xfo^ })cpp",
2638 {}, Opts);
2639 EXPECT_THAT(
2640 Results.Completions,
2641 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix("($0)"))));
2642 }
2643 {
2644 auto Results = completions(
2645 R"cpp(
2646 template <class T, class U>
2647 void xfoo(int a, U b);
2648 void f() { xfo^ })cpp",
2649 {}, Opts);
2650 EXPECT_THAT(
2651 Results.Completions,
2652 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix("<$1>($0)"))));
2653 }
2654 {
2655 auto Results = completions(
2656 R"cpp(
2657 template <class T>
2658 class foo_class{};
2659 template <class T>
2660 using foo_alias = T**;
2661 template <class T>
2662 T foo_var = T{};
2663 void f() { foo_^ })cpp",
2664 {}, Opts);
2665 EXPECT_THAT(
2666 Results.Completions,
2667 UnorderedElementsAre(AllOf(named("foo_class"), snippetSuffix("<$0>")),
2668 AllOf(named("foo_alias"), snippetSuffix("<$0>")),
2669 AllOf(named("foo_var"), snippetSuffix("<$0>"))));
2670 }
2671 {
2672 auto Results = completions(
2673 R"cpp(
2674 #define FOO(x, y) x##f
2675 FO^ )cpp",
2676 {}, Opts);
2677 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
2678 named("FOO"), snippetSuffix("($0)"))));
2679 }
2680 {
2682 auto Results = completions(
2683 R"cpp(
2684 void xfoo(int x, int y);
2685 void f() { xfo^ })cpp",
2686 {}, Opts);
2687 EXPECT_THAT(Results.Completions,
2688 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix(""))));
2689 }
2690 {
2692 auto Results = completions(
2693 R"cpp(
2694 void xfoo(int x, int y);
2695 void f() { xfo^ })cpp",
2696 {}, Opts);
2697 EXPECT_THAT(Results.Completions,
2698 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix("("))));
2699 }
2700}
2701
2702TEST(CompletionTest, SuggestOverrides) {
2703 constexpr const char *const Text(R"cpp(
2704 class A {
2705 public:
2706 virtual void vfunc(bool param);
2707 virtual void vfunc(bool param, int p);
2708 void func(bool param);
2709 };
2710 class B : public A {
2711 virtual void ttt(bool param) const;
2712 void vfunc(bool param, int p) override;
2713 };
2714 class C : public B {
2715 public:
2716 void vfunc(bool param) override;
2717 ^
2718 };
2719 )cpp");
2720 const auto Results = completions(Text);
2721 EXPECT_THAT(
2722 Results.Completions,
2723 AllOf(Contains(AllOf(labeled("void vfunc(bool param, int p) override"),
2724 nameStartsWith("vfunc"))),
2725 Contains(AllOf(labeled("void ttt(bool param) const override"),
2726 nameStartsWith("ttt"))),
2727 Not(Contains(labeled("void vfunc(bool param) override")))));
2728}
2729
2730TEST(CompletionTest, OverridesNonIdentName) {
2731 // Check the completions call does not crash.
2732 completions(R"cpp(
2733 struct Base {
2734 virtual ~Base() = 0;
2735 virtual operator int() = 0;
2736 virtual Base& operator+(Base&) = 0;
2737 };
2738
2739 struct Derived : Base {
2740 ^
2741 };
2742 )cpp");
2743}
2744
2745TEST(CompletionTest, NoCrashOnMissingNewLineAtEOF) {
2746 auto FooCpp = testPath("foo.cpp");
2747
2748 MockCompilationDatabase CDB;
2749 MockFS FS;
2750 Annotations F("#pragma ^ // no new line");
2751 FS.Files[FooCpp] = F.code().str();
2752 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
2753 runAddDocument(Server, FooCpp, F.code());
2754 // Run completion outside the file range.
2755 EXPECT_THAT(cantFail(runCodeComplete(Server, FooCpp, F.point(),
2756 clangd::CodeCompleteOptions()))
2757 .Completions,
2758 IsEmpty());
2759 EXPECT_THAT(cantFail(runSignatureHelp(Server, FooCpp, F.point(),
2761 .signatures,
2762 IsEmpty());
2763}
2764
2765TEST(GuessCompletionPrefix, Filters) {
2766 for (llvm::StringRef Case : {
2767 "[[scope::]][[ident]]^",
2768 "[[]][[]]^",
2769 "\n[[]][[]]^",
2770 "[[]][[ab]]^",
2771 "x.[[]][[ab]]^",
2772 "x.[[]][[]]^",
2773 "[[x::]][[ab]]^",
2774 "[[x::]][[]]^",
2775 "[[::x::]][[ab]]^",
2776 "some text [[scope::more::]][[identif]]^ier",
2777 "some text [[scope::]][[mor]]^e::identifier",
2778 "weird case foo::[[::bar::]][[baz]]^",
2779 "/* [[]][[]]^ */",
2780 }) {
2781 Annotations F(Case);
2782 auto Offset = cantFail(positionToOffset(F.code(), F.point()));
2783 auto ToStringRef = [&](Range R) {
2784 return F.code().slice(cantFail(positionToOffset(F.code(), R.start)),
2785 cantFail(positionToOffset(F.code(), R.end)));
2786 };
2787 auto WantQualifier = ToStringRef(F.ranges()[0]),
2788 WantName = ToStringRef(F.ranges()[1]);
2789
2790 auto Prefix = guessCompletionPrefix(F.code(), Offset);
2791 // Even when components are empty, check their offsets are correct.
2792 EXPECT_EQ(WantQualifier, Prefix.Qualifier) << Case;
2793 EXPECT_EQ(WantQualifier.begin(), Prefix.Qualifier.begin()) << Case;
2794 EXPECT_EQ(WantName, Prefix.Name) << Case;
2795 EXPECT_EQ(WantName.begin(), Prefix.Name.begin()) << Case;
2796 }
2797}
2798
2799TEST(CompletionTest, EnableSpeculativeIndexRequest) {
2800 MockFS FS;
2801 MockCompilationDatabase CDB;
2802 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
2803
2804 auto File = testPath("foo.cpp");
2805 Annotations Test(R"cpp(
2806 namespace ns1 { int abc; }
2807 namespace ns2 { int abc; }
2808 void f() { ns1::ab$1^; ns1::ab$2^; }
2809 void f2() { ns2::ab$3^; }
2810 )cpp");
2811 runAddDocument(Server, File, Test.code());
2812 clangd::CodeCompleteOptions Opts = {};
2813
2814 IndexRequestCollector Requests;
2815 Opts.Index = &Requests;
2816
2817 auto CompleteAtPoint = [&](StringRef P) {
2818 auto CCR = cantFail(runCodeComplete(Server, File, Test.point(P), Opts));
2819 EXPECT_TRUE(CCR.HasMore);
2820 };
2821
2822 CompleteAtPoint("1");
2823 auto Reqs1 = Requests.consumeRequests(1);
2824 ASSERT_EQ(Reqs1.size(), 1u);
2825 EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre("ns1::"));
2826
2827 CompleteAtPoint("2");
2828 auto Reqs2 = Requests.consumeRequests(1);
2829 // Speculation succeeded. Used speculative index result.
2830 ASSERT_EQ(Reqs2.size(), 1u);
2831 EXPECT_EQ(Reqs2[0], Reqs1[0]);
2832
2833 CompleteAtPoint("3");
2834 // Speculation failed. Sent speculative index request and the new index
2835 // request after sema.
2836 auto Reqs3 = Requests.consumeRequests(2);
2837 ASSERT_EQ(Reqs3.size(), 2u);
2838}
2839
2840TEST(CompletionTest, InsertTheMostPopularHeader) {
2841 std::string DeclFile = URI::create(testPath("foo")).toString();
2842 Symbol Sym = func("Func");
2843 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2844 Sym.IncludeHeaders.emplace_back("\"foo.h\"", 2, Symbol::Include);
2845 Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000, Symbol::Include);
2846
2847 auto Results = completions("Fun^", {Sym}).Completions;
2848 assert(!Results.empty());
2849 EXPECT_THAT(Results[0], AllOf(named("Func"), insertInclude("\"bar.h\"")));
2850 EXPECT_EQ(Results[0].Includes.size(), 2u);
2851}
2852
2853TEST(CompletionTest, InsertIncludeOrImport) {
2854 std::string DeclFile = URI::create(testPath("foo")).toString();
2855 Symbol Sym = func("Func");
2856 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2857 Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000,
2859 CodeCompleteOptions Opts;
2860 // Should only take effect in import contexts.
2861 Opts.ImportInsertions = true;
2862 auto Results = completions("Fun^", {Sym}, Opts).Completions;
2863 assert(!Results.empty());
2864 EXPECT_THAT(Results[0],
2865 AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
2866
2867 ASTSignals Signals;
2868 Signals.InsertionDirective = Symbol::IncludeDirective::Import;
2869 Opts.MainFileSignals = &Signals;
2870 Results = completions("Fun^", {Sym}, Opts, "Foo.m").Completions;
2871 assert(!Results.empty());
2872 EXPECT_THAT(Results[0],
2873 AllOf(named("Func"), insertIncludeText("#import \"bar.h\"\n")));
2874
2875 Sym.IncludeHeaders[0].SupportedDirectives = Symbol::Import;
2876 Results = completions("Fun^", {Sym}).Completions;
2877 assert(!Results.empty());
2878 EXPECT_THAT(Results[0], AllOf(named("Func"), Not(insertInclude())));
2879}
2880
2881TEST(CompletionTest, NoInsertIncludeIfOnePresent) {
2882 Annotations Test(R"cpp(
2883 #include "foo.h"
2884 Fun^
2885 )cpp");
2886 auto TU = TestTU::withCode(Test.code());
2887 TU.AdditionalFiles["foo.h"] = "";
2888
2889 std::string DeclFile = URI::create(testPath("foo")).toString();
2890 Symbol Sym = func("Func");
2891 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2892 Sym.IncludeHeaders.emplace_back("\"foo.h\"", 2, Symbol::Include);
2893 Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000, Symbol::Include);
2894
2895 EXPECT_THAT(completions(TU, Test.point(), {Sym}).Completions,
2896 UnorderedElementsAre(AllOf(named("Func"), hasInclude("\"foo.h\""),
2897 Not(insertInclude()))));
2898}
2899
2900TEST(CompletionTest, MergeMacrosFromIndexAndSema) {
2901 Symbol Sym;
2902 Sym.Name = "Clangd_Macro_Test";
2903 Sym.ID = SymbolID("c:foo.cpp@8@macro@Clangd_Macro_Test");
2904 Sym.SymInfo.Kind = index::SymbolKind::Macro;
2906 EXPECT_THAT(completions("#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym})
2907 .Completions,
2908 UnorderedElementsAre(named("Clangd_Macro_Test")));
2909}
2910
2911TEST(CompletionTest, MacroFromPreamble) {
2912 Annotations Test(R"cpp(#define CLANGD_PREAMBLE_MAIN x
2913
2914 int x = 0;
2915 #define CLANGD_MAIN x
2916 void f() { CLANGD_^ }
2917 )cpp");
2918 auto TU = TestTU::withCode(Test.code());
2919 TU.HeaderCode = "#define CLANGD_PREAMBLE_HEADER x";
2920 auto Results = completions(TU, Test.point(), {func("CLANGD_INDEX")});
2921 // We should get results from the main file, including the preamble section.
2922 // However no results from included files (the index should cover them).
2923 EXPECT_THAT(Results.Completions,
2924 UnorderedElementsAre(named("CLANGD_PREAMBLE_MAIN"),
2925 named("CLANGD_MAIN"),
2926 named("CLANGD_INDEX")));
2927}
2928
2929TEST(CompletionTest, DeprecatedResults) {
2930 std::string Body = R"cpp(
2931 void TestClangd();
2932 void TestClangc() __attribute__((deprecated("", "")));
2933 )cpp";
2934
2935 EXPECT_THAT(
2936 completions(Body + "int main() { TestClang^ }").Completions,
2937 UnorderedElementsAre(AllOf(named("TestClangd"), Not(deprecated())),
2938 AllOf(named("TestClangc"), deprecated())));
2939}
2940
2941TEST(SignatureHelpTest, PartialSpec) {
2942 const auto Results = signatures(R"cpp(
2943 template <typename T> struct Foo {};
2944 template <typename T> struct Foo<T*> { Foo(T); };
2945 Foo<int*> F(^);)cpp");
2946 EXPECT_THAT(Results.signatures, Contains(sig("Foo([[T]])")));
2947 EXPECT_EQ(0, Results.activeParameter);
2948}
2949
2950TEST(SignatureHelpTest, InsideArgument) {
2951 {
2952 const auto Results = signatures(R"cpp(
2953 void foo(int x);
2954 void foo(int x, int y);
2955 int main() { foo(1+^); }
2956 )cpp");
2957 EXPECT_THAT(Results.signatures,
2958 ElementsAre(sig("foo([[int x]]) -> void"),
2959 sig("foo([[int x]], [[int y]]) -> void")));
2960 EXPECT_EQ(0, Results.activeParameter);
2961 }
2962 {
2963 const auto Results = signatures(R"cpp(
2964 void foo(int x);
2965 void foo(int x, int y);
2966 int main() { foo(1^); }
2967 )cpp");
2968 EXPECT_THAT(Results.signatures,
2969 ElementsAre(sig("foo([[int x]]) -> void"),
2970 sig("foo([[int x]], [[int y]]) -> void")));
2971 EXPECT_EQ(0, Results.activeParameter);
2972 }
2973 {
2974 const auto Results = signatures(R"cpp(
2975 void foo(int x);
2976 void foo(int x, int y);
2977 int main() { foo(1^0); }
2978 )cpp");
2979 EXPECT_THAT(Results.signatures,
2980 ElementsAre(sig("foo([[int x]]) -> void"),
2981 sig("foo([[int x]], [[int y]]) -> void")));
2982 EXPECT_EQ(0, Results.activeParameter);
2983 }
2984 {
2985 const auto Results = signatures(R"cpp(
2986 void foo(int x);
2987 void foo(int x, int y);
2988 int bar(int x, int y);
2989 int main() { bar(foo(2, 3^)); }
2990 )cpp");
2991 EXPECT_THAT(Results.signatures,
2992 ElementsAre(sig("foo([[int x]], [[int y]]) -> void")));
2993 EXPECT_EQ(1, Results.activeParameter);
2994 }
2995}
2996
2997TEST(SignatureHelpTest, ConstructorInitializeFields) {
2998 {
2999 const auto Results = signatures(R"cpp(
3000 struct A { A(int); };
3001 struct B {
3002 B() : a_elem(^) {}
3003 A a_elem;
3004 };
3005 )cpp");
3006 EXPECT_THAT(Results.signatures,
3007 UnorderedElementsAre(sig("A([[int]])"), sig("A([[A &&]])"),
3008 sig("A([[const A &]])")));
3009 }
3010 {
3011 const auto Results = signatures(R"cpp(
3012 struct A { A(int); };
3013 struct B {
3014 B() : a_elem(^
3015 A a_elem;
3016 };
3017 )cpp");
3018 // FIXME: currently the parser skips over the decl of a_elem as part of the
3019 // (broken) init list, so we don't get signatures for the first member.
3020 EXPECT_THAT(Results.signatures, IsEmpty());
3021 }
3022 {
3023 const auto Results = signatures(R"cpp(
3024 struct A { A(int); };
3025 struct B {
3026 B() : a_elem(^
3027 int dummy_elem;
3028 A a_elem;
3029 };
3030 )cpp");
3031 EXPECT_THAT(Results.signatures,
3032 UnorderedElementsAre(sig("A([[int]])"), sig("A([[A &&]])"),
3033 sig("A([[const A &]])")));
3034 }
3035 {
3036 const auto Results = signatures(R"cpp(
3037 struct A {
3038 A(int);
3039 };
3040 struct C {
3041 C(int);
3042 C(A);
3043 };
3044 struct B {
3045 B() : c_elem(A(1^)) {}
3046 C c_elem;
3047 };
3048 )cpp");
3049 EXPECT_THAT(Results.signatures,
3050 UnorderedElementsAre(sig("A([[int]])"), sig("A([[A &&]])"),
3051 sig("A([[const A &]])")));
3052 }
3053}
3054
3055TEST(SignatureHelpTest, Variadic) {
3056 const std::string Header = R"cpp(
3057 void fun(int x, ...) {}
3058 void test() {)cpp";
3059 const std::string ExpectedSig = "fun([[int x]], [[...]]) -> void";
3060
3061 {
3062 const auto Result = signatures(Header + "fun(^);}");
3063 EXPECT_EQ(0, Result.activeParameter);
3064 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3065 }
3066 {
3067 const auto Result = signatures(Header + "fun(1, ^);}");
3068 EXPECT_EQ(1, Result.activeParameter);
3069 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3070 }
3071 {
3072 const auto Result = signatures(Header + "fun(1, 2, ^);}");
3073 EXPECT_EQ(1, Result.activeParameter);
3074 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3075 }
3076}
3077
3078TEST(SignatureHelpTest, VariadicTemplate) {
3079 const std::string Header = R"cpp(
3080 template<typename T, typename ...Args>
3081 void fun(T t, Args ...args) {}
3082 void test() {)cpp";
3083 const std::string ExpectedSig = "fun([[T t]], [[Args args...]]) -> void";
3084
3085 {
3086 const auto Result = signatures(Header + "fun(^);}");
3087 EXPECT_EQ(0, Result.activeParameter);
3088 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3089 }
3090 {
3091 const auto Result = signatures(Header + "fun(1, ^);}");
3092 EXPECT_EQ(1, Result.activeParameter);
3093 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3094 }
3095 {
3096 const auto Result = signatures(Header + "fun(1, 2, ^);}");
3097 EXPECT_EQ(1, Result.activeParameter);
3098 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3099 }
3100}
3101
3102TEST(SignatureHelpTest, VariadicMethod) {
3103 const std::string Header = R"cpp(
3104 class C {
3105 template<typename T, typename ...Args>
3106 void fun(T t, Args ...args) {}
3107 };
3108 void test() {C c; )cpp";
3109 const std::string ExpectedSig = "fun([[T t]], [[Args args...]]) -> void";
3110
3111 {
3112 const auto Result = signatures(Header + "c.fun(^);}");
3113 EXPECT_EQ(0, Result.activeParameter);
3114 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3115 }
3116 {
3117 const auto Result = signatures(Header + "c.fun(1, ^);}");
3118 EXPECT_EQ(1, Result.activeParameter);
3119 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3120 }
3121 {
3122 const auto Result = signatures(Header + "c.fun(1, 2, ^);}");
3123 EXPECT_EQ(1, Result.activeParameter);
3124 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3125 }
3126}
3127
3128TEST(SignatureHelpTest, VariadicType) {
3129 const std::string Header = R"cpp(
3130 void fun(int x, ...) {}
3131 auto get_fun() { return fun; }
3132 void test() {
3133 )cpp";
3134 const std::string ExpectedSig = "([[int]], [[...]]) -> void";
3135
3136 {
3137 const auto Result = signatures(Header + "get_fun()(^);}");
3138 EXPECT_EQ(0, Result.activeParameter);
3139 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3140 }
3141 {
3142 const auto Result = signatures(Header + "get_fun()(1, ^);}");
3143 EXPECT_EQ(1, Result.activeParameter);
3144 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3145 }
3146 {
3147 const auto Result = signatures(Header + "get_fun()(1, 2, ^);}");
3148 EXPECT_EQ(1, Result.activeParameter);
3149 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3150 }
3151}
3152
3153TEST(CompletionTest, IncludedCompletionKinds) {
3154 Annotations Test(R"cpp(#include "^)cpp");
3155 auto TU = TestTU::withCode(Test.code());
3156 TU.AdditionalFiles["sub/bar.h"] = "";
3157 TU.ExtraArgs.push_back("-I" + testPath("sub"));
3158
3159 auto Results = completions(TU, Test.point());
3160 EXPECT_THAT(Results.Completions,
3161 AllOf(has("sub/", CompletionItemKind::Folder),
3162 has("bar.h\"", CompletionItemKind::File)));
3163}
3164
3165TEST(CompletionTest, NoCrashAtNonAlphaIncludeHeader) {
3166 completions(
3167 R"cpp(
3168 #include "./^"
3169 )cpp");
3170}
3171
3172TEST(CompletionTest, NoAllScopesCompletionWhenQualified) {
3173 clangd::CodeCompleteOptions Opts = {};
3174 Opts.AllScopes = true;
3175
3176 auto Results = completions(
3177 R"cpp(
3178 void f() { na::Clangd^ }
3179 )cpp",
3180 {cls("na::ClangdA"), cls("nx::ClangdX"), cls("Clangd3")}, Opts);
3181 EXPECT_THAT(Results.Completions,
3182 UnorderedElementsAre(
3183 AllOf(qualifier(""), scope("na::"), named("ClangdA"))));
3184}
3185
3186TEST(CompletionTest, AllScopesCompletion) {
3187 clangd::CodeCompleteOptions Opts = {};
3188 Opts.AllScopes = true;
3189
3190 auto Results = completions(
3191 R"cpp(
3192 namespace na {
3193 void f() { Clangd^ }
3194 }
3195 )cpp",
3196 {cls("nx::Clangd1"), cls("ny::Clangd2"), cls("Clangd3"),
3197 cls("na::nb::Clangd4"), enmConstant("na::C::Clangd5")},
3198 Opts);
3199 EXPECT_THAT(
3200 Results.Completions,
3201 UnorderedElementsAre(AllOf(qualifier("nx::"), named("Clangd1"),
3203 AllOf(qualifier("ny::"), named("Clangd2"),
3205 AllOf(qualifier(""), scope(""), named("Clangd3"),
3207 AllOf(qualifier("nb::"), named("Clangd4"),
3209 AllOf(qualifier("C::"), named("Clangd5"),
3211}
3212
3213TEST(CompletionTest, NoQualifierIfShadowed) {
3214 clangd::CodeCompleteOptions Opts = {};
3215 Opts.AllScopes = true;
3216
3217 auto Results = completions(R"cpp(
3218 namespace nx { class Clangd1 {}; }
3219 using nx::Clangd1;
3220 void f() { Clangd^ }
3221 )cpp",
3222 {cls("nx::Clangd1"), cls("nx::Clangd2")}, Opts);
3223 // Although Clangd1 is from another namespace, Sema tells us it's in-scope and
3224 // needs no qualifier.
3225 EXPECT_THAT(Results.Completions,
3226 UnorderedElementsAre(AllOf(qualifier(""), named("Clangd1")),
3227 AllOf(qualifier("nx::"), named("Clangd2"))));
3228}
3229
3230TEST(CompletionTest, NoCompletionsForNewNames) {
3231 clangd::CodeCompleteOptions Opts;
3232 Opts.AllScopes = true;
3233 auto Results = completions(R"cpp(
3234 void f() { int n^ }
3235 )cpp",
3236 {cls("naber"), cls("nx::naber")}, Opts);
3237 EXPECT_THAT(Results.Completions, UnorderedElementsAre());
3238}
3239
3240TEST(CompletionTest, Lambda) {
3241 clangd::CodeCompleteOptions Opts = {};
3242
3243 auto Results = completions(R"cpp(
3244 void function() {
3245 auto Lambda = [](int a, const double &b) {return 1.f;};
3246 Lam^
3247 }
3248 )cpp",
3249 {}, Opts);
3250
3251 ASSERT_EQ(Results.Completions.size(), 1u);
3252 const auto &A = Results.Completions.front();
3253 EXPECT_EQ(A.Name, "Lambda");
3254 EXPECT_EQ(A.Signature, "(int a, const double &b) const");
3255 EXPECT_EQ(A.Kind, CompletionItemKind::Variable);
3256 EXPECT_EQ(A.ReturnType, "float");
3257 EXPECT_EQ(A.SnippetSuffix, "(${1:int a}, ${2:const double &b})");
3258}
3259
3260TEST(CompletionTest, StructuredBinding) {
3261 clangd::CodeCompleteOptions Opts = {};
3262
3263 auto Results = completions(R"cpp(
3264 struct S {
3265 using Float = float;
3266 int x;
3267 Float y;
3268 };
3269 void function() {
3270 const auto &[xxx, yyy] = S{};
3271 yyy^
3272 }
3273 )cpp",
3274 {}, Opts);
3275
3276 ASSERT_EQ(Results.Completions.size(), 1u);
3277 const auto &A = Results.Completions.front();
3278 EXPECT_EQ(A.Name, "yyy");
3279 EXPECT_EQ(A.Kind, CompletionItemKind::Variable);
3280 EXPECT_EQ(A.ReturnType, "const Float");
3281}
3282
3283TEST(CompletionTest, ObjectiveCMethodNoArguments) {
3284 auto Results = completions(R"objc(
3285 @interface Foo
3286 @property(nonatomic, setter=setXToIgnoreComplete:) int value;
3287 @end
3288 Foo *foo = [Foo new]; int y = [foo v^]
3289 )objc",
3290 /*IndexSymbols=*/{},
3291 /*Opts=*/{}, "Foo.m");
3292
3293 auto C = Results.Completions;
3294 EXPECT_THAT(C, ElementsAre(named("value")));
3295 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3296 EXPECT_THAT(C, ElementsAre(returnType("int")));
3297 EXPECT_THAT(C, ElementsAre(signature("")));
3298 EXPECT_THAT(C, ElementsAre(snippetSuffix("")));
3299}
3300
3301TEST(CompletionTest, ObjectiveCMethodOneArgument) {
3302 auto Results = completions(R"objc(
3303 @interface Foo
3304 - (int)valueForCharacter:(char)c;
3305 @end
3306 Foo *foo = [Foo new]; int y = [foo v^]
3307 )objc",
3308 /*IndexSymbols=*/{},
3309 /*Opts=*/{}, "Foo.m");
3310
3311 auto C = Results.Completions;
3312 EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));
3313 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3314 EXPECT_THAT(C, ElementsAre(returnType("int")));
3315 EXPECT_THAT(C, ElementsAre(signature("(char)")));
3316 EXPECT_THAT(C, ElementsAre(snippetSuffix("${1:(char)}")));
3317}
3318
3319TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromBeginning) {
3320 auto Results = completions(R"objc(
3321 @interface Foo
3322 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;
3323 @end
3324 id val = [Foo foo^]
3325 )objc",
3326 /*IndexSymbols=*/{},
3327 /*Opts=*/{}, "Foo.m");
3328
3329 auto C = Results.Completions;
3330 EXPECT_THAT(C, ElementsAre(named("fooWithValue:")));
3331 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3332 EXPECT_THAT(C, ElementsAre(returnType("id")));
3333 EXPECT_THAT(C, ElementsAre(signature("(int) fooey:(unsigned int)")));
3334 EXPECT_THAT(
3335 C, ElementsAre(snippetSuffix("${1:(int)} fooey:${2:(unsigned int)}")));
3336}
3337
3338TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
3339 auto Results = completions(R"objc(
3340 @interface Foo
3341 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;
3342 @end
3343 id val = [Foo fooWithValue:10 f^]
3344 )objc",
3345 /*IndexSymbols=*/{},
3346 /*Opts=*/{}, "Foo.m");
3347
3348 auto C = Results.Completions;
3349 EXPECT_THAT(C, ElementsAre(named("fooey:")));
3350 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3351 EXPECT_THAT(C, ElementsAre(returnType("id")));
3352 EXPECT_THAT(C, ElementsAre(signature("(unsigned int)")));
3353 EXPECT_THAT(C, ElementsAre(snippetSuffix("${1:(unsigned int)}")));
3354}
3355
3356TEST(CompletionTest, ObjectiveCMethodFilterOnEntireSelector) {
3357 auto Results = completions(R"objc(
3358 @interface Foo
3359 + (id)player:(id)player willRun:(id)run;
3360 @end
3361 id val = [Foo wi^]
3362 )objc",
3363 /*IndexSymbols=*/{},
3364 /*Opts=*/{}, "Foo.m");
3365
3366 auto C = Results.Completions;
3367 EXPECT_THAT(C, ElementsAre(named("player:")));
3368 EXPECT_THAT(C, ElementsAre(filterText("player:willRun:")));
3369 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3370 EXPECT_THAT(C, ElementsAre(returnType("id")));
3371 EXPECT_THAT(C, ElementsAre(signature("(id) willRun:(id)")));
3372 EXPECT_THAT(C, ElementsAre(snippetSuffix("${1:(id)} willRun:${2:(id)}")));
3373}
3374
3375TEST(CompletionTest, ObjectiveCSimpleMethodDeclaration) {
3376 auto Results = completions(R"objc(
3377 @interface Foo
3378 - (void)foo;
3379 @end
3380 @implementation Foo
3381 fo^
3382 @end
3383 )objc",
3384 /*IndexSymbols=*/{},
3385 /*Opts=*/{}, "Foo.m");
3386
3387 auto C = Results.Completions;
3388 EXPECT_THAT(C, ElementsAre(named("foo")));
3389 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3390 EXPECT_THAT(C, ElementsAre(qualifier("- (void)")));
3391}
3392
3393TEST(CompletionTest, ObjectiveCMethodDeclaration) {
3394 auto Results = completions(R"objc(
3395 @interface Foo
3396 - (int)valueForCharacter:(char)c secondArgument:(id)object;
3397 @end
3398 @implementation Foo
3399 valueFor^
3400 @end
3401 )objc",
3402 /*IndexSymbols=*/{},
3403 /*Opts=*/{}, "Foo.m");
3404
3405 auto C = Results.Completions;
3406 EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));
3407 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3408 EXPECT_THAT(C, ElementsAre(qualifier("- (int)")));
3409 EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
3410}
3411
3412TEST(CompletionTest, ObjectiveCMethodDeclarationFilterOnEntireSelector) {
3413 auto Results = completions(R"objc(
3414 @interface Foo
3415 - (int)valueForCharacter:(char)c secondArgument:(id)object;
3416 @end
3417 @implementation Foo
3418 secondArg^
3419 @end
3420 )objc",
3421 /*IndexSymbols=*/{},
3422 /*Opts=*/{}, "Foo.m");
3423
3424 auto C = Results.Completions;
3425 EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));
3426 EXPECT_THAT(C, ElementsAre(filterText("valueForCharacter:secondArgument:")));
3427 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3428 EXPECT_THAT(C, ElementsAre(qualifier("- (int)")));
3429 EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
3430}
3431
3432TEST(CompletionTest, ObjectiveCMethodDeclarationPrefixTyped) {
3433 auto Results = completions(R"objc(
3434 @interface Foo
3435 - (int)valueForCharacter:(char)c;
3436 @end
3437 @implementation Foo
3438 - (int)valueFor^
3439 @end
3440 )objc",
3441 /*IndexSymbols=*/{},
3442 /*Opts=*/{}, "Foo.m");
3443
3444 auto C = Results.Completions;
3445 EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));
3446 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3447 EXPECT_THAT(C, ElementsAre(signature("(char)c")));
3448}
3449
3450TEST(CompletionTest, ObjectiveCMethodDeclarationFromMiddle) {
3451 auto Results = completions(R"objc(
3452 @interface Foo
3453 - (int)valueForCharacter:(char)c secondArgument:(id)object;
3454 @end
3455 @implementation Foo
3456 - (int)valueForCharacter:(char)c second^
3457 @end
3458 )objc",
3459 /*IndexSymbols=*/{},
3460 /*Opts=*/{}, "Foo.m");
3461
3462 auto C = Results.Completions;
3463 EXPECT_THAT(C, ElementsAre(named("secondArgument:")));
3464 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3465 EXPECT_THAT(C, ElementsAre(signature("(id)object")));
3466}
3467
3468TEST(CompletionTest, ObjectiveCProtocolFromIndex) {
3469 Symbol FoodClass = objcClass("FoodClass");
3470 Symbol SymFood = objcProtocol("Food");
3471 Symbol SymFooey = objcProtocol("Fooey");
3472 auto Results = completions("id<Foo^>", {SymFood, FoodClass, SymFooey},
3473 /*Opts=*/{}, "Foo.m");
3474
3475 // Should only give protocols for ObjC protocol completions.
3476 EXPECT_THAT(Results.Completions,
3477 UnorderedElementsAre(
3478 AllOf(named("Food"), kind(CompletionItemKind::Interface)),
3479 AllOf(named("Fooey"), kind(CompletionItemKind::Interface))));
3480
3481 Results = completions("Fo^", {SymFood, FoodClass, SymFooey},
3482 /*Opts=*/{}, "Foo.m");
3483 // Shouldn't give protocols for non protocol completions.
3484 EXPECT_THAT(
3485 Results.Completions,
3486 ElementsAre(AllOf(named("FoodClass"), kind(CompletionItemKind::Class))));
3487}
3488
3489TEST(CompletionTest, ObjectiveCProtocolFromIndexSpeculation) {
3490 MockFS FS;
3491 MockCompilationDatabase CDB;
3492 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
3493
3494 auto File = testPath("Foo.m");
3495 Annotations Test(R"cpp(
3496 @protocol Food
3497 @end
3498 id<Foo$1^> foo;
3499 Foo$2^ bar;
3500 )cpp");
3501 runAddDocument(Server, File, Test.code());
3502 clangd::CodeCompleteOptions Opts = {};
3503
3504 Symbol FoodClass = objcClass("FoodClass");
3505 IndexRequestCollector Requests({FoodClass});
3506 Opts.Index = &Requests;
3507
3508 auto CompleteAtPoint = [&](StringRef P) {
3509 return cantFail(runCodeComplete(Server, File, Test.point(P), Opts))
3510 .Completions;
3511 };
3512
3513 auto C = CompleteAtPoint("1");
3514 auto Reqs1 = Requests.consumeRequests(1);
3515 ASSERT_EQ(Reqs1.size(), 1u);
3516 EXPECT_THAT(C, ElementsAre(AllOf(named("Food"),
3518
3519 C = CompleteAtPoint("2");
3520 auto Reqs2 = Requests.consumeRequests(1);
3521 // Speculation succeeded. Used speculative index result, but filtering now to
3522 // now include FoodClass.
3523 ASSERT_EQ(Reqs2.size(), 1u);
3524 EXPECT_EQ(Reqs2[0], Reqs1[0]);
3525 EXPECT_THAT(C, ElementsAre(AllOf(named("FoodClass"),
3527}
3528
3529TEST(CompletionTest, ObjectiveCCategoryFromIndexIgnored) {
3530 Symbol FoodCategory = objcCategory("FoodClass", "Extension");
3531 auto Results = completions(R"objc(
3532 @interface Foo
3533 @end
3534 @interface Foo (^)
3535 @end
3536 )objc",
3537 {FoodCategory},
3538 /*Opts=*/{}, "Foo.m");
3539 EXPECT_THAT(Results.Completions, IsEmpty());
3540}
3541
3542TEST(CompletionTest, ObjectiveCForwardDeclFromIndex) {
3543 Symbol FoodClass = objcClass("FoodClass");
3544 FoodClass.IncludeHeaders.emplace_back("\"Foo.h\"", 2, Symbol::Import);
3545 Symbol SymFood = objcProtocol("Food");
3546 auto Results = completions("@class Foo^", {SymFood, FoodClass},
3547 /*Opts=*/{}, "Foo.m");
3548
3549 // Should only give class names without any include insertion.
3550 EXPECT_THAT(Results.Completions,
3551 UnorderedElementsAre(AllOf(named("FoodClass"),
3553 Not(insertInclude()))));
3554}
3555
3556TEST(CompletionTest, CursorInSnippets) {
3557 clangd::CodeCompleteOptions Options;
3558 Options.EnableSnippets = true;
3559 auto Results = completions(
3560 R"cpp(
3561 void while_foo(int a, int b);
3562 void test() {
3563 whil^
3564 })cpp",
3565 /*IndexSymbols=*/{}, Options);
3566
3567 // Last placeholder in code patterns should be $0 to put the cursor there.
3568 EXPECT_THAT(Results.Completions,
3569 Contains(AllOf(named("while"),
3570 snippetSuffix(" (${1:condition}) {\n$0\n}"))));
3571 // However, snippets for functions must *not* end with $0.
3572 EXPECT_THAT(Results.Completions,
3573 Contains(AllOf(named("while_foo"),
3574 snippetSuffix("(${1:int a}, ${2:int b})"))));
3575
3576 Results = completions(R"cpp(
3577 struct Base {
3578 Base(int a, int b) {}
3579 };
3580
3581 struct Derived : Base {
3582 Derived() : Base^
3583 };
3584 )cpp",
3585 /*IndexSymbols=*/{}, Options);
3586 // Constructors from base classes are a kind of pattern that shouldn't end
3587 // with $0.
3588 EXPECT_THAT(Results.Completions,
3589 Contains(AllOf(named("Base"),
3590 snippetSuffix("(${1:int a}, ${2:int b})"))));
3591}
3592
3593TEST(CompletionTest, WorksWithNullType) {
3594 auto R = completions(R"cpp(
3595 int main() {
3596 for (auto [loopVar] : y ) { // y has to be unresolved.
3597 int z = loopV^;
3598 }
3599 }
3600 )cpp");
3601 EXPECT_THAT(R.Completions, ElementsAre(named("loopVar")));
3602}
3603
3604TEST(CompletionTest, UsingDecl) {
3605 const char *Header(R"cpp(
3606 void foo(int);
3607 namespace std {
3608 using ::foo;
3609 })cpp");
3610 const char *Source(R"cpp(
3611 void bar() {
3612 std::^;
3613 })cpp");
3614 auto Index = TestTU::withHeaderCode(Header).index();
3615 clangd::CodeCompleteOptions Opts;
3616 Opts.Index = Index.get();
3617 Opts.AllScopes = true;
3618 auto R = completions(Source, {}, Opts);
3619 EXPECT_THAT(R.Completions,
3620 ElementsAre(AllOf(scope("std::"), named("foo"),
3622}
3623
3624TEST(CompletionTest, Enums) {
3625 const char *Header(R"cpp(
3626 namespace ns {
3627 enum Unscoped { Clangd1 };
3628 class C {
3629 enum Unscoped { Clangd2 };
3630 };
3631 enum class Scoped { Clangd3 };
3632 })cpp");
3633 const char *Source(R"cpp(
3634 void bar() {
3635 Clangd^
3636 })cpp");
3637 auto Index = TestTU::withHeaderCode(Header).index();
3638 clangd::CodeCompleteOptions Opts;
3639 Opts.Index = Index.get();
3640 Opts.AllScopes = true;
3641 auto R = completions(Source, {}, Opts);
3642 EXPECT_THAT(R.Completions, UnorderedElementsAre(
3643 AllOf(scope("ns::"), named("Clangd1"),
3645 AllOf(scope("ns::C::"), named("Clangd2"),
3647 AllOf(scope("ns::Scoped::"), named("Clangd3"),
3649}
3650
3651TEST(CompletionTest, ScopeIsUnresolved) {
3652 clangd::CodeCompleteOptions Opts = {};
3653 Opts.AllScopes = true;
3654
3655 auto Results = completions(R"cpp(
3656 namespace a {
3657 void f() { b::X^ }
3658 }
3659 )cpp",
3660 {cls("a::b::XYZ")}, Opts);
3661 EXPECT_THAT(Results.Completions,
3662 UnorderedElementsAre(AllOf(qualifier(""), named("XYZ"))));
3663}
3664
3665TEST(CompletionTest, NestedScopeIsUnresolved) {
3666 clangd::CodeCompleteOptions Opts = {};
3667 Opts.AllScopes = true;
3668
3669 auto Results = completions(R"cpp(
3670 namespace a {
3671 namespace b {}
3672 void f() { b::c::X^ }
3673 }
3674 )cpp",
3675 {cls("a::b::c::XYZ")}, Opts);
3676 EXPECT_THAT(Results.Completions,
3677 UnorderedElementsAre(AllOf(qualifier(""), named("XYZ"))));
3678}
3679
3680// Clang parser gets confused here and doesn't report the ns:: prefix.
3681// Naive behavior is to insert it again. We examine the source and recover.
3682TEST(CompletionTest, NamespaceDoubleInsertion) {
3683 clangd::CodeCompleteOptions Opts = {};
3684
3685 auto Results = completions(R"cpp(
3686 namespace foo {
3687 namespace ns {}
3688 #define M(X) < X
3689 M(ns::ABC^
3690 }
3691 )cpp",
3692 {cls("foo::ns::ABCDE")}, Opts);
3693 EXPECT_THAT(Results.Completions,
3694 UnorderedElementsAre(AllOf(qualifier(""), named("ABCDE"))));
3695}
3696
3697TEST(CompletionTest, DerivedMethodsAreAlwaysVisible) {
3698 // Despite the fact that base method matches the ref-qualifier better,
3699 // completion results should only include the derived method.
3700 auto Completions = completions(R"cpp(
3701 struct deque_base {
3702 float size();
3703 double size() const;
3704 };
3705 struct deque : deque_base {
3706 int size() const;
3707 };
3708
3709 auto x = deque().^
3710 )cpp")
3711 .Completions;
3712 EXPECT_THAT(Completions,
3713 ElementsAre(AllOf(returnType("int"), named("size"))));
3714}
3715
3716TEST(CompletionTest, NoCrashWithIncompleteLambda) {
3717 auto Completions = completions("auto&& x = []{^").Completions;
3718 // The completion of x itself can cause a problem: in the code completion
3719 // callback, its type is not known, which affects the linkage calculation.
3720 // A bad linkage value gets cached, and subsequently updated.
3721 EXPECT_THAT(Completions, Contains(named("x")));
3722
3723 auto Signatures = signatures("auto x() { x(^").signatures;
3724 EXPECT_THAT(Signatures, Contains(sig("x() -> auto")));
3725}
3726
3727TEST(CompletionTest, DelayedTemplateParsing) {
3728 Annotations Test(R"cpp(
3729 int xxx;
3730 template <typename T> int foo() { return xx^; }
3731 )cpp");
3732 auto TU = TestTU::withCode(Test.code());
3733 // Even though delayed-template-parsing is on, we will disable it to provide
3734 // completion in templates.
3735 TU.ExtraArgs.push_back("-fdelayed-template-parsing");
3736
3737 EXPECT_THAT(completions(TU, Test.point()).Completions,
3738 Contains(named("xxx")));
3739}
3740
3741TEST(CompletionTest, CompletionRange) {
3742 const char *WithRange = "auto x = [[abc]]^";
3743 auto Completions = completions(WithRange);
3744 EXPECT_EQ(Completions.CompletionRange, Annotations(WithRange).range());
3745 Completions = completionsNoCompile(WithRange);
3746 EXPECT_EQ(Completions.CompletionRange, Annotations(WithRange).range());
3747
3748 const char *EmptyRange = "auto x = [[]]^";
3749 Completions = completions(EmptyRange);
3750 EXPECT_EQ(Completions.CompletionRange, Annotations(EmptyRange).range());
3751 Completions = completionsNoCompile(EmptyRange);
3752 EXPECT_EQ(Completions.CompletionRange, Annotations(EmptyRange).range());
3753
3754 // Sema doesn't trigger at all here, while the no-sema completion runs
3755 // heuristics as normal and reports a range. It'd be nice to be consistent.
3756 const char *NoCompletion = "/* foo [[]]^ */";
3757 Completions = completions(NoCompletion);
3758 EXPECT_EQ(Completions.CompletionRange, std::nullopt);
3759 Completions = completionsNoCompile(NoCompletion);
3760 EXPECT_EQ(Completions.CompletionRange, Annotations(NoCompletion).range());
3761}
3762
3763TEST(NoCompileCompletionTest, Basic) {
3764 auto Results = completionsNoCompile(R"cpp(
3765 void func() {
3766 int xyz;
3767 int abc;
3768 ^
3769 }
3770 )cpp");
3771 EXPECT_FALSE(Results.RanParser);
3772 EXPECT_THAT(Results.Completions,
3773 UnorderedElementsAre(named("void"), named("func"), named("int"),
3774 named("xyz"), named("abc")));
3775}
3776
3777TEST(NoCompileCompletionTest, WithFilter) {
3778 auto Results = completionsNoCompile(R"cpp(
3779 void func() {
3780 int sym1;
3781 int sym2;
3782 int xyz1;
3783 int xyz2;
3784 sy^
3785 }
3786 )cpp");
3787 EXPECT_THAT(Results.Completions,
3788 UnorderedElementsAre(named("sym1"), named("sym2")));
3789}
3790
3791TEST(NoCompileCompletionTest, WithIndex) {
3792 std::vector<Symbol> Syms = {func("xxx"), func("a::xxx"), func("ns::b::xxx"),
3793 func("c::xxx"), func("ns::d::xxx")};
3794 auto Results = completionsNoCompile(
3795 R"cpp(
3796 // Current-scopes, unqualified completion.
3797 using namespace a;
3798 namespace ns {
3799 using namespace b;
3800 void foo() {
3801 xx^
3802 }
3803 }
3804 )cpp",
3805 Syms);
3806 EXPECT_THAT(Results.Completions,
3807 UnorderedElementsAre(AllOf(qualifier(""), scope("")),
3808 AllOf(qualifier(""), scope("a::")),
3809 AllOf(qualifier(""), scope("ns::b::"))));
3810 CodeCompleteOptions Opts;
3811 Opts.AllScopes = true;
3812 Results = completionsNoCompile(
3813 R"cpp(
3814 // All-scopes unqualified completion.
3815 using namespace a;
3816 namespace ns {
3817 using namespace b;
3818 void foo() {
3819 xx^
3820 }
3821 }
3822 )cpp",
3823 Syms, Opts);
3824 EXPECT_THAT(Results.Completions,
3825 UnorderedElementsAre(AllOf(qualifier(""), scope("")),
3826 AllOf(qualifier(""), scope("a::")),
3827 AllOf(qualifier(""), scope("ns::b::")),
3828 AllOf(qualifier("c::"), scope("c::")),
3829 AllOf(qualifier("d::"), scope("ns::d::"))));
3830 Results = completionsNoCompile(
3831 R"cpp(
3832 // Qualified completion.
3833 using namespace a;
3834 namespace ns {
3835 using namespace b;
3836 void foo() {
3837 b::xx^
3838 }
3839 }
3840 )cpp",
3841 Syms, Opts);
3842 EXPECT_THAT(Results.Completions,
3843 ElementsAre(AllOf(qualifier(""), scope("ns::b::"))));
3844 Results = completionsNoCompile(
3845 R"cpp(
3846 // Absolutely qualified completion.
3847 using namespace a;
3848 namespace ns {
3849 using namespace b;
3850 void foo() {
3851 ::a::xx^
3852 }
3853 }
3854 )cpp",
3855 Syms, Opts);
3856 EXPECT_THAT(Results.Completions,
3857 ElementsAre(AllOf(qualifier(""), scope("a::"))));
3858}
3859
3860TEST(AllowImplicitCompletion, All) {
3861 const char *Yes[] = {
3862 "foo.^bar",
3863 "foo->^bar",
3864 "foo::^bar",
3865 " # include <^foo.h>",
3866 "#import <foo/^bar.h>",
3867 "#include_next \"^",
3868 };
3869 const char *No[] = {
3870 "foo>^bar",
3871 "foo:^bar",
3872 "foo\n^bar",
3873 "#include <foo.h> //^",
3874 "#include \"foo.h\"^",
3875 "#error <^",
3876 "#<^",
3877 };
3878 for (const char *Test : Yes) {
3879 llvm::Annotations A(Test);
3880 EXPECT_TRUE(allowImplicitCompletion(A.code(), A.point())) << Test;
3881 }
3882 for (const char *Test : No) {
3883 llvm::Annotations A(Test);
3884 EXPECT_FALSE(allowImplicitCompletion(A.code(), A.point())) << Test;
3885 }
3886}
3887
3888TEST(CompletionTest, FunctionArgsExist) {
3889 clangd::CodeCompleteOptions Opts;
3890 Opts.EnableSnippets = true;
3891 std::string Context = R"cpp(
3892 #define MACRO(x)
3893 int foo(int A);
3894 int bar();
3895 struct Object {
3896 Object(int B) {}
3897 };
3898 template <typename T>
3899 struct Container {
3900 Container(int Size) {}
3901 };
3902 )cpp";
3903 EXPECT_THAT(completions(Context + "int y = fo^", {}, Opts).Completions,
3904 UnorderedElementsAre(
3905 AllOf(labeled("foo(int A)"), snippetSuffix("(${1:int A})"))));
3906 EXPECT_THAT(
3907 completions(Context + "int y = fo^(42)", {}, Opts).Completions,
3908 UnorderedElementsAre(AllOf(labeled("foo(int A)"), snippetSuffix(""))));
3909 // FIXME(kirillbobyrev): No snippet should be produced here.
3910 EXPECT_THAT(completions(Context + "int y = fo^o(42)", {}, Opts).Completions,
3911 UnorderedElementsAre(
3912 AllOf(labeled("foo(int A)"), snippetSuffix("(${1:int A})"))));
3913 EXPECT_THAT(
3914 completions(Context + "int y = ba^", {}, Opts).Completions,
3915 UnorderedElementsAre(AllOf(labeled("bar()"), snippetSuffix("()"))));
3916 EXPECT_THAT(completions(Context + "int y = ba^()", {}, Opts).Completions,
3917 UnorderedElementsAre(AllOf(labeled("bar()"), snippetSuffix(""))));
3918 EXPECT_THAT(
3919 completions(Context + "Object o = Obj^", {}, Opts).Completions,
3920 Contains(AllOf(labeled("Object(int B)"), snippetSuffix("(${1:int B})"),
3922 EXPECT_THAT(completions(Context + "Object o = Obj^()", {}, Opts).Completions,
3923 Contains(AllOf(labeled("Object(int B)"), snippetSuffix(""),
3925 EXPECT_THAT(
3926 completions(Context + "Container c = Cont^", {}, Opts).Completions,
3927 Contains(AllOf(labeled("Container<typename T>(int Size)"),
3928 snippetSuffix("<${1:typename T}>(${2:int Size})"),
3930 EXPECT_THAT(
3931 completions(Context + "Container c = Cont^()", {}, Opts).Completions,
3932 Contains(AllOf(labeled("Container<typename T>(int Size)"),
3933 snippetSuffix("<${1:typename T}>"),
3935 EXPECT_THAT(
3936 completions(Context + "Container c = Cont^<int>()", {}, Opts).Completions,
3937 Contains(AllOf(labeled("Container<typename T>(int Size)"),
3938 snippetSuffix(""),
3940 EXPECT_THAT(completions(Context + "MAC^(2)", {}, Opts).Completions,
3941 Contains(AllOf(labeled("MACRO(x)"), snippetSuffix(""),
3943}
3944
3945TEST(CompletionTest, FunctionArgsExist_Issue1785) {
3946 // This is a scenario where the implementation of our check for
3947 // "is there a function argument list right after the cursor"
3948 // gave a bogus result.
3949 clangd::CodeCompleteOptions Opts;
3950 Opts.EnableSnippets = true;
3951 // The whitespace in this testcase is important!
3952 std::string Code = R"cpp(
3953void waldo(int);
3954
3955int main()
3956{
3957 wal^
3958
3959
3960 // ( )
3961}
3962 )cpp";
3963 EXPECT_THAT(
3964 completions(Code, {}, Opts).Completions,
3965 Contains(AllOf(labeled("waldo(int)"), snippetSuffix("(${1:int})"))));
3966}
3967
3968TEST(CompletionTest, NoCrashDueToMacroOrdering) {
3969 EXPECT_THAT(completions(R"cpp(
3970 #define ECHO(X) X
3971 #define ECHO2(X) ECHO(X)
3972 int finish_preamble = EC^HO(2);)cpp")
3973 .Completions,
3974 UnorderedElementsAre(labeled("ECHO(X)"), labeled("ECHO2(X)")));
3975}
3976
3977TEST(CompletionTest, ObjCCategoryDecls) {
3978 TestTU TU;
3979 TU.ExtraArgs.push_back("-xobjective-c");
3980 TU.HeaderCode = R"objc(
3981 @interface Foo
3982 @end
3983
3984 @interface Foo (FooExt1)
3985 @end
3986
3987 @interface Foo (FooExt2)
3988 @end
3989
3990 @interface Bar
3991 @end
3992
3993 @interface Bar (BarExt)
3994 @end)objc";
3995
3996 {
3997 Annotations Test(R"objc(
3998 @implementation Foo (^)
3999 @end
4000 )objc");
4001 TU.Code = Test.code().str();
4002 auto Results = completions(TU, Test.point());
4003 EXPECT_THAT(Results.Completions,
4004 UnorderedElementsAre(labeled("FooExt1"), labeled("FooExt2")));
4005 }
4006 {
4007 Annotations Test(R"objc(
4008 @interface Foo (^)
4009 @end
4010 )objc");
4011 TU.Code = Test.code().str();
4012 auto Results = completions(TU, Test.point());
4013 EXPECT_THAT(Results.Completions, UnorderedElementsAre(labeled("BarExt")));
4014 }
4015}
4016
4017TEST(CompletionTest, PreambleCodeComplete) {
4018 llvm::StringLiteral Baseline = "\n#define MACRO 12\nint num = MACRO;";
4019 llvm::StringLiteral ModifiedCC =
4020 "#include \"header.h\"\n#define MACRO 12\nint num = MACRO; int num2 = M^";
4021
4022 Annotations Test(ModifiedCC);
4023 auto BaselineTU = TestTU::withCode(Baseline);
4024 auto ModifiedTU = TestTU::withCode(Test.code());
4025
4026 MockFS FS;
4027 auto Inputs = ModifiedTU.inputs(FS);
4028 auto Result = codeComplete(testPath(ModifiedTU.Filename), Test.point(),
4029 BaselineTU.preamble().get(), Inputs, {});
4030 EXPECT_THAT(Result.Completions, Not(testing::IsEmpty()));
4031}
4032
4033TEST(CompletionTest, CommentParamName) {
4034 const std::string Code = R"cpp(
4035 void fun(int foo, int bar);
4036 void overloaded(int param_int);
4037 void overloaded(int param_int, int param_other);
4038 void overloaded(char param_char);
4039 int main() {
4040 )cpp";
4041
4042 EXPECT_THAT(completions(Code + "fun(/*^").Completions,
4043 UnorderedElementsAre(labeled("foo=*/")));
4044 EXPECT_THAT(completions(Code + "fun(1, /*^").Completions,
4045 UnorderedElementsAre(labeled("bar=*/")));
4046 EXPECT_THAT(completions(Code + "/*^").Completions, IsEmpty());
4047 // Test de-duplication.
4048 EXPECT_THAT(
4049 completions(Code + "overloaded(/*^").Completions,
4050 UnorderedElementsAre(labeled("param_int=*/"), labeled("param_char=*/")));
4051 // Comment already has some text in it.
4052 EXPECT_THAT(completions(Code + "fun(/* ^").Completions,
4053 UnorderedElementsAre(labeled("foo=*/")));
4054 EXPECT_THAT(completions(Code + "fun(/* f^").Completions,
4055 UnorderedElementsAre(labeled("foo=*/")));
4056 EXPECT_THAT(completions(Code + "fun(/* x^").Completions, IsEmpty());
4057 EXPECT_THAT(completions(Code + "fun(/* f ^").Completions, IsEmpty());
4058
4059 // Test ranges
4060 {
4061 std::string CompletionRangeTest(Code + "fun(/*[[^]]");
4062 auto Results = completions(CompletionRangeTest);
4063 EXPECT_THAT(Results.CompletionRange,
4064 llvm::ValueIs(Annotations(CompletionRangeTest).range()));
4065 EXPECT_THAT(
4066 Results.Completions,
4067 testing::Each(
4068 AllOf(replacesRange(Annotations(CompletionRangeTest).range()),
4070 }
4071 {
4072 std::string CompletionRangeTest(Code + "fun(/*[[fo^]]");
4073 auto Results = completions(CompletionRangeTest);
4074 EXPECT_THAT(Results.CompletionRange,
4075 llvm::ValueIs(Annotations(CompletionRangeTest).range()));
4076 EXPECT_THAT(
4077 Results.Completions,
4078 testing::Each(
4079 AllOf(replacesRange(Annotations(CompletionRangeTest).range()),
4081 }
4082}
4083
4084TEST(CompletionTest, Concepts) {
4085 Annotations Code(R"cpp(
4086 template<class T>
4087 concept A = sizeof(T) <= 8;
4088
4089 template<$tparam^A U>
4090 int foo();
4091
4092 template<typename T>
4093 int bar(T t) requires $expr^A<int>;
4094
4095 template<class T>
4096 concept b = $expr^A && $expr^sizeof(T) % 2 == 0 || $expr^A && sizeof(T) == 1;
4097
4098 $toplevel^A auto i = 19;
4099
4100 template<$toplevel^A auto i> void constrainedNTTP();
4101
4102 // FIXME: The first parameter should be dropped in this case.
4103 void abbreviated($expr^A auto x) {}
4104 )cpp");
4105 TestTU TU;
4106 TU.Code = Code.code().str();
4107 TU.ExtraArgs = {"-std=c++20"};
4108
4109 auto Sym = conceptSym("same_as");
4110 Sym.Signature = "<typename Tp, typename Up>";
4111 Sym.CompletionSnippetSuffix = "<${1:typename Tp}, ${2:typename Up}>";
4112 std::vector<Symbol> Syms = {Sym};
4113 for (auto P : Code.points("tparam")) {
4114 ASSERT_THAT(
4115 completions(TU, P, Syms).Completions,
4116 AllOf(Contains(AllOf(named("A"), signature(""), snippetSuffix(""))),
4117 Contains(AllOf(named("same_as"), signature("<typename Up>"),
4118 snippetSuffix("<${2:typename Up}>"))),
4119 Contains(named("class")), Contains(named("typename"))))
4120 << "Completing template parameter at position " << P;
4121 }
4122
4123 for (auto P : Code.points("toplevel")) {
4124 EXPECT_THAT(
4125 completions(TU, P, Syms).Completions,
4126 AllOf(Contains(AllOf(named("A"), signature(""), snippetSuffix(""))),
4127 Contains(AllOf(named("same_as"), signature("<typename Up>"),
4128 snippetSuffix("<${2:typename Up}>")))))
4129 << "Completing 'requires' expression at position " << P;
4130 }
4131
4132 for (auto P : Code.points("expr")) {
4133 EXPECT_THAT(
4134 completions(TU, P, Syms).Completions,
4135 AllOf(Contains(AllOf(named("A"), signature("<class T>"),
4136 snippetSuffix("<${1:class T}>"))),
4137 Contains(AllOf(
4138 named("same_as"), signature("<typename Tp, typename Up>"),
4139 snippetSuffix("<${1:typename Tp}, ${2:typename Up}>")))))
4140 << "Completing 'requires' expression at position " << P;
4141 }
4142}
4143
4144TEST(SignatureHelp, DocFormat) {
4145 Annotations Code(R"cpp(
4146 // Comment `with` markup.
4147 void foo(int);
4148 void bar() { foo(^); }
4149 )cpp");
4150 for (auto DocumentationFormat :
4152 auto Sigs = signatures(Code.code(), Code.point(), /*IndexSymbols=*/{},
4153 DocumentationFormat);
4154 ASSERT_EQ(Sigs.signatures.size(), 1U);
4155 EXPECT_EQ(Sigs.signatures[0].documentation.kind, DocumentationFormat);
4156 }
4157}
4158
4159TEST(SignatureHelp, TemplateArguments) {
4160 std::string Top = R"cpp(
4161 template <typename T, int> bool foo(char);
4162 template <int I, int> bool foo(float);
4163 )cpp";
4164
4165 auto First = signatures(Top + "bool x = foo<^");
4166 EXPECT_THAT(
4167 First.signatures,
4168 UnorderedElementsAre(sig("foo<[[typename T]], [[int]]>() -> bool"),
4169 sig("foo<[[int I]], [[int]]>() -> bool")));
4170 EXPECT_EQ(First.activeParameter, 0);
4171
4172 auto Second = signatures(Top + "bool x = foo<1, ^");
4173 EXPECT_THAT(Second.signatures,
4174 ElementsAre(sig("foo<[[int I]], [[int]]>() -> bool")));
4175 EXPECT_EQ(Second.activeParameter, 1);
4176}
4177
4178TEST(CompletionTest, DoNotCrash) {
4179 llvm::StringLiteral Cases[] = {
4180 R"cpp(
4181 template <typename = int> struct Foo {};
4182 auto a = [x(3)](Foo<^>){};
4183 )cpp",
4184 };
4185 for (auto Case : Cases) {
4186 SCOPED_TRACE(Case);
4187 auto Completions = completions(Case);
4188 }
4189}
4190TEST(CompletionTest, PreambleFromDifferentTarget) {
4191 constexpr std::string_view PreambleTarget = "x86_64";
4192 constexpr std::string_view Contents =
4193 "int foo(int); int num; int num2 = foo(n^";
4194
4195 Annotations Test(Contents);
4196 auto TU = TestTU::withCode(Test.code());
4197 TU.ExtraArgs.emplace_back("-target");
4198 TU.ExtraArgs.emplace_back(PreambleTarget);
4199 auto Preamble = TU.preamble();
4200 ASSERT_TRUE(Preamble);
4201 // Switch target to wasm.
4202 TU.ExtraArgs.pop_back();
4203 TU.ExtraArgs.emplace_back("wasm32");
4204
4205 MockFS FS;
4206 auto Inputs = TU.inputs(FS);
4207 auto Result = codeComplete(testPath(TU.Filename), Test.point(),
4208 Preamble.get(), Inputs, {});
4209 auto Signatures =
4210 signatureHelp(testPath(TU.Filename), Test.point(), *Preamble, Inputs, {});
4211
4212 // Make sure we don't crash.
4213 EXPECT_THAT(Result.Completions, Not(testing::IsEmpty()));
4214 EXPECT_THAT(Signatures.signatures, Not(testing::IsEmpty()));
4215}
4216} // namespace
4217} // namespace clangd
4218} // namespace clang
ArrayRef< const ParmVarDecl * > Parameters
Definition: AST.cpp:801
llvm::SmallString< 256U > Name
const ParseInputs & ParseInput
size_t Offset
std::vector< CodeCompletionResult > Results
llvm::raw_ostream & OS
const Criteria C
CognitiveComplexity CC
std::optional< float > Score
std::string Text
CharSourceRange Range
SourceRange for the file name.
size_t Pos
Kind K
Definition: Rename.cpp:474
std::unique_ptr< CompilerInvocation > CI
std::optional< FixItHint > FixIt
#define EXPECT_IFF(condition, value, matcher)
static Options optsForTest()
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:18
static llvm::Expected< URI > create(llvm::StringRef AbsolutePath, llvm::StringRef Scheme)
Creates a URI for a file in the given scheme.
Definition: URI.cpp:208
Symbol objcProtocol(llvm::StringRef Name)
Definition: TestIndex.cpp:117
Symbol objcClass(llvm::StringRef Name)
Definition: TestIndex.cpp:108
Symbol func(llvm::StringRef Name)
Definition: TestIndex.cpp:62
Symbol cls(llvm::StringRef Name)
Definition: TestIndex.cpp:66
Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName)
Definition: TestIndex.cpp:112
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:549
Symbol conceptSym(llvm::StringRef Name)
Definition: TestIndex.cpp:86
IndexContents
Describes what data is covered by an index.
Definition: Index.h:114
size_t lspLength(llvm::StringRef Code)
Definition: SourceCode.cpp:149
CompletionPrefix guessCompletionPrefix(llvm::StringRef Content, unsigned Offset)
std::unique_ptr< CompilerInvocation > buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D, std::vector< std::string > *CC1Args)
Builds compiler invocation that could be used to build AST or preamble.
Definition: Compiler.cpp:95
Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, llvm::StringRef USRFormat, llvm::StringRef Signature)
Definition: TestIndex.cpp:40
CompletionItemKind
The kind of a completion entry.
Definition: Protocol.h:338
Symbol ns(llvm::StringRef Name)
Definition: TestIndex.cpp:82
bool allowImplicitCompletion(llvm::StringRef Content, unsigned Offset)
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
llvm::Expected< CodeCompleteResult > runCodeComplete(ClangdServer &Server, PathRef File, Position Pos, clangd::CodeCompleteOptions Opts)
Definition: SyncAPI.cpp:72
MATCHER_P(named, N, "")
llvm::Expected< SignatureHelp > runSignatureHelp(ClangdServer &Server, PathRef File, Position Pos, MarkupKind DocumentationFormat)
Definition: SyncAPI.cpp:79
std::string testPath(PathRef File, llvm::sys::path::Style Style)
Definition: TestFS.cpp:93
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition: Function.h:28
std::shared_ptr< const PreambleData > buildPreamble(PathRef FileName, CompilerInvocation CI, const ParseInputs &Inputs, bool StoreInMemory, PreambleParsedCallback PreambleCallback, PreambleBuildStats *Stats)
Build a preamble for the new inputs unless an old one can be reused.
Definition: Preamble.cpp:591
TEST(BackgroundQueueTest, Priority)
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:121
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:173
void runAddDocument(ClangdServer &Server, PathRef File, llvm::StringRef Contents, llvm::StringRef Version, WantDiagnostics WantDiags, bool ForceRebuild)
Definition: SyncAPI.cpp:17
Symbol macro(llvm::StringRef Name, llvm::StringRef ArgList)
Definition: TestIndex.cpp:90
@ No
Diagnostics must be generated for this snapshot.
std::vector< std::string > lookup(const SymbolIndex &I, llvm::ArrayRef< SymbolID > IDs)
Definition: TestIndex.cpp:151
Symbol enmConstant(llvm::StringRef Name)
Definition: TestIndex.cpp:74
Deadline timeoutSeconds(std::optional< double > Seconds)
Makes a deadline from a timeout in seconds. std::nullopt means wait forever.
Definition: Threading.cpp:113
MATCHER(declared, "")
CodeCompleteResult codeComplete(PathRef FileName, Position Pos, const PreambleData *Preamble, const ParseInputs &ParseInput, CodeCompleteOptions Opts, SpeculativeFuzzyFind *SpecFuzzyFind)
Gets code completions at a specified Pos in FileName.
@ PlainText
The primary text to be inserted is treated as a plain string.
@ Snippet
The primary text to be inserted is treated as a snippet.
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:29
SignatureHelp signatureHelp(PathRef FileName, Position Pos, const PreambleData &Preamble, const ParseInputs &ParseInput, MarkupKind DocumentationFormat)
Get signature help at a specified Pos in FileName.
PolySubsequenceMatcher< Args... > HasSubsequence(Args &&... M)
Symbol var(llvm::StringRef Name)
Definition: TestIndex.cpp:78
std::array< uint8_t, 20 > SymbolID
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::function< void(const CodeCompletion &, const SymbolQualitySignals &, const SymbolRelevanceSignals &, float Score)> RecordCCResult
Callback invoked on all CompletionCandidate after they are scored and before they are ranked (by -Sco...
Definition: CodeComplete.h:137
MarkupKind DocumentationFormat
Whether to present doc comments as plain-text or markdown.
Definition: CodeComplete.h:72
bool IncludeIneligibleResults
Include results that are not legal completions in the current context.
Definition: CodeComplete.h:54
Config::ArgumentListsPolicy ArgumentLists
The way argument list on calls '()' and generics '<>' are handled.
Definition: CodeComplete.h:113
const SymbolIndex * Index
If Index is set, it is used to augment the code completion results.
Definition: CodeComplete.h:98
const ASTSignals * MainFileSignals
Definition: CodeComplete.h:100
std::function< DecisionForestScores(const SymbolQualitySignals &, const SymbolRelevanceSignals &, float Base)> DecisionForestScorer
Callback used to score a CompletionCandidate if DecisionForest ranking model is enabled.
Definition: CodeComplete.h:153
CodeCompletionRankingModel RankingModel
Definition: CodeComplete.h:145
bool ImportInsertions
Whether include insertions for Objective-C code should use #import instead of #include.
Definition: CodeComplete.h:81
bool AllScopes
Whether to include index symbols that are not defined in the scopes visible from the code completion ...
Definition: CodeComplete.h:110
size_t Limit
Limit the number of results returned (0 means no limit).
Definition: CodeComplete.h:69
std::optional< bool > BundleOverloads
Combine overloads into a single completion item where possible.
Definition: CodeComplete.h:65
bool IncludeFixIts
Include completions that require small corrections, e.g.
Definition: CodeComplete.h:103
struct clang::clangd::CodeCompleteOptions::IncludeInsertionIndicator IncludeIndicator
bool EnableSnippets
When true, completion items will contain expandable code snippets in completion (e....
Definition: CodeComplete.h:50
bool ShowOrigins
Expose origins of completion items in the label (for debugging).
Definition: CodeComplete.h:91
@ None
nothing, no argument list and also NO Delimiters "()" or "<>".
@ Delimiters
empty pair of delimiters "()" or "<>".
@ OpenDelimiter
open, only opening delimiter "(" or "<".
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
const SymbolIndex * Index
Definition: Compiler.h:59
@ IndexedForCodeCompletion
Whether or not this symbol is meant to be used for the code completion.
Definition: Symbol.h:141
@ Include
#include "header.h"
Definition: Symbol.h:93
@ Import
#import "header.h"
Definition: Symbol.h:95
SymbolID ID
The ID of the symbol.
Definition: Symbol.h:41
static TestTU withHeaderCode(llvm::StringRef HeaderCode)
Definition: TestTU.h:42
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:36
std::unique_ptr< SymbolIndex > index() const
Definition: TestTU.cpp:175