clang-tools 23.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) {
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;
182 Opts.RankingModel = CodeCompleteOptions::DecisionForest;
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;
198 Opts.RankingModel = CodeCompleteOptions::DecisionForest;
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;
218 Opts.RankingModel = CodeCompleteOptions::DecisionForest;
219 Opts.DecisionForestScorer = [&](const SymbolQualitySignals &,
220 const SymbolRelevanceSignals &, float Base) {
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.
234 Opts.RankingModel = CodeCompleteOptions::Heuristics;
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"))));
323 EXPECT_IFF(Opts.IncludeIneligibleResults, Results.Completions,
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 = {
392 &clangd::CodeCompleteOptions::IncludeIneligibleResults,
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 = Config::HeaderInsertionPolicy::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, IncludeInsertionRespectsQuotedAngledConfig) {
924 TestTU TU;
925 TU.ExtraArgs.push_back("-I" + testPath("sub"));
926 TU.AdditionalFiles["sub/bar.h"] = "";
927 auto BarURI = URI::create(testPath("sub/bar.h")).toString();
928
929 Symbol Sym = cls("ns::X");
930 Sym.CanonicalDeclaration.FileURI = BarURI.c_str();
931 Sym.IncludeHeaders.emplace_back(BarURI, 1, Symbol::Include);
932 Annotations Test("int main() { ns::^ }");
933 TU.Code = Test.code().str();
934 auto Results = completions(TU, Test.point(), {Sym});
935 // Default for a local path is quoted include
936 EXPECT_THAT(Results.Completions,
937 ElementsAre(AllOf(named("X"), insertInclude("\"bar.h\""))));
938 {
939 Config C;
940 C.Style.AngledHeaders.push_back(
941 [](auto header) { return header.contains("bar.h"); });
942 WithContextValue WithCfg(Config::Key, std::move(C));
943 Results = completions(TU, Test.point(), {Sym});
944 EXPECT_THAT(Results.Completions,
945 ElementsAre(AllOf(named("X"), insertInclude("<bar.h>"))));
946 }
947 {
948 Config C;
949 C.Style.QuotedHeaders.push_back(
950 [](auto header) { return header.contains("bar.h"); });
951 WithContextValue WithCfg(Config::Key, std::move(C));
952 Results = completions(TU, Test.point(), {Sym});
953 EXPECT_THAT(Results.Completions,
954 ElementsAre(AllOf(named("X"), insertInclude("\"bar.h\""))));
955 }
956}
957
958TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
959 Annotations Test(R"cpp(
960 #include "bar.h"
961 namespace ns { int local; }
962 void f() { ns::^; }
963 void f2() { ns::preamble().$2^; }
964 )cpp");
965 auto TU = TestTU::withCode(Test.code());
966 TU.AdditionalFiles["bar.h"] =
967 R"cpp(namespace ns { struct preamble { int member; }; })cpp";
968
969 clangd::CodeCompleteOptions Opts = {};
970 auto I = memIndex({var("ns::index")});
971 Opts.Index = I.get();
972 auto WithIndex = completions(TU, Test.point(), {}, Opts);
973 EXPECT_THAT(WithIndex.Completions,
974 UnorderedElementsAre(named("local"), named("index")));
975 auto ClassFromPreamble = completions(TU, Test.point("2"), {}, Opts);
976 EXPECT_THAT(ClassFromPreamble.Completions, Contains(named("member")));
977
978 Opts.Index = nullptr;
979 auto WithoutIndex = completions(TU, Test.point(), {}, Opts);
980 EXPECT_THAT(WithoutIndex.Completions,
981 UnorderedElementsAre(named("local"), named("preamble")));
982}
983
984// This verifies that we get normal preprocessor completions in the preamble.
985// This is a regression test for an old bug: if we override the preamble and
986// try to complete inside it, clang kicks our completion point just outside the
987// preamble, resulting in always getting top-level completions.
988TEST(CompletionTest, CompletionInPreamble) {
989 auto Results = completions(R"cpp(
990 #ifnd^ef FOO_H_
991 #define BAR_H_
992 #include <bar.h>
993 int foo() {}
994 #endif
995 )cpp")
996 .Completions;
997 EXPECT_THAT(Results, ElementsAre(named("ifndef")));
998}
999
1000TEST(CompletionTest, CompletionRecoveryASTType) {
1001 auto Results = completions(R"cpp(
1002 struct S { int member; };
1003 S overloaded(int);
1004 void foo() {
1005 // No overload matches, but we have recovery-expr with the correct type.
1006 overloaded().^
1007 })cpp")
1008 .Completions;
1009 EXPECT_THAT(Results, ElementsAre(named("member")));
1010}
1011
1012TEST(CompletionTest, DynamicIndexIncludeInsertion) {
1013 MockFS FS;
1016 Opts.BuildDynamicSymbolIndex = true;
1017 ClangdServer Server(CDB, FS, Opts);
1018
1019 FS.Files[testPath("foo_header.h")] = R"cpp(
1020 #pragma once
1021 struct Foo {
1022 // Member doc
1023 int foo();
1024 };
1025 )cpp";
1026 const std::string FileContent(R"cpp(
1027 #include "foo_header.h"
1028 int Foo::foo() {
1029 return 42;
1030 }
1031 )cpp");
1032 Server.addDocument(testPath("foo_impl.cpp"), FileContent);
1033 // Wait for the dynamic index being built.
1034 ASSERT_TRUE(Server.blockUntilIdleForTest());
1035
1036 auto File = testPath("foo.cpp");
1037 Annotations Test("Foo^ foo;");
1038 runAddDocument(Server, File, Test.code());
1039 auto CompletionList =
1040 llvm::cantFail(runCodeComplete(Server, File, Test.point(), {}));
1041
1042 EXPECT_THAT(CompletionList.Completions,
1043 ElementsAre(AllOf(named("Foo"), hasInclude("\"foo_header.h\""),
1044 insertInclude())));
1045}
1046
1047TEST(CompletionTest, DynamicIndexMultiFile) {
1048 MockFS FS;
1050 auto Opts = ClangdServer::optsForTest();
1051 Opts.BuildDynamicSymbolIndex = true;
1052 ClangdServer Server(CDB, FS, Opts);
1053
1054 FS.Files[testPath("foo.h")] = R"cpp(
1055 namespace ns { class XYZ {}; void foo(int x) {} }
1056 )cpp";
1057 runAddDocument(Server, testPath("foo.cpp"), R"cpp(
1058 #include "foo.h"
1059 )cpp");
1060
1061 auto File = testPath("bar.cpp");
1062 Annotations Test(R"cpp(
1063 namespace ns {
1064 class XXX {};
1065 /// Doooc
1066 void fooooo() {}
1067 }
1068 void f() { ns::^ }
1069 )cpp");
1070 runAddDocument(Server, File, Test.code());
1071
1072 auto Results = cantFail(runCodeComplete(Server, File, Test.point(), {}));
1073 // "XYZ" and "foo" are not included in the file being completed but are still
1074 // visible through the index.
1075 EXPECT_THAT(Results.Completions, has("XYZ", CompletionItemKind::Class));
1076 EXPECT_THAT(Results.Completions, has("foo", CompletionItemKind::Function));
1077 EXPECT_THAT(Results.Completions, has("XXX", CompletionItemKind::Class));
1078 EXPECT_THAT(Results.Completions,
1079 Contains((named("fooooo"), kind(CompletionItemKind::Function),
1080 doc("Doooc"), returnType("void"))));
1081}
1082
1083TEST(CompletionTest, Documentation) {
1084 auto Results = completions(
1085 R"cpp(
1086 // Non-doxygen comment.
1087 __attribute__((annotate("custom_annotation"))) int foo();
1088 /// Doxygen comment.
1089 /// \param int a
1090 int bar(int a);
1091 /* Multi-line
1092 block comment
1093 */
1094 int baz();
1095
1096 int x = ^
1097 )cpp");
1098 EXPECT_THAT(
1099 Results.Completions,
1100 Contains(
1101 AllOf(named("foo"),
1102 doc("Annotation: custom_annotation\n\nNon-doxygen comment."))));
1103 EXPECT_THAT(
1104 Results.Completions,
1105 Contains(AllOf(named("bar"), doc("Doxygen comment.\n\\param int a"))));
1106 EXPECT_THAT(Results.Completions,
1107 Contains(AllOf(named("baz"), doc("Multi-line block comment"))));
1108}
1109
1110TEST(CompletionTest, CommentsFromSystemHeaders) {
1111 MockFS FS;
1113
1114 auto Opts = ClangdServer::optsForTest();
1115 Opts.BuildDynamicSymbolIndex = true;
1116
1117 ClangdServer Server(CDB, FS, Opts);
1118
1119 FS.Files[testPath("foo.h")] = R"cpp(
1120 #pragma GCC system_header
1121
1122 // This comment should be retained!
1123 int foo();
1124 )cpp";
1125
1126 auto File = testPath("foo.cpp");
1127 Annotations Test(R"cpp(
1128#include "foo.h"
1129int x = foo^
1130 )cpp");
1131 runAddDocument(Server, File, Test.code());
1132 auto CompletionList =
1133 llvm::cantFail(runCodeComplete(Server, File, Test.point(), {}));
1134
1135 EXPECT_THAT(
1136 CompletionList.Completions,
1137 Contains(AllOf(named("foo"), doc("This comment should be retained!"))));
1138}
1139
1140TEST(CompletionTest, CommentsOnMembersFromHeader) {
1141 MockFS FS;
1143
1144 auto Opts = ClangdServer::optsForTest();
1145 Opts.BuildDynamicSymbolIndex = true;
1146
1147 ClangdServer Server(CDB, FS, Opts);
1148
1149 FS.Files[testPath("foo.h")] = R"cpp(
1150 struct alpha {
1151 /// This is a member field.
1152 int gamma;
1153
1154 /// This is a member function.
1155 int delta();
1156 };
1157
1158 template <typename T>
1159 struct beta {
1160 /// This is a member field inside a template.
1161 int omega;
1162
1163 /// This is a member function inside a template.
1164 int epsilon();
1165 };
1166 )cpp";
1167
1168 auto File = testPath("foo.cpp");
1169 Annotations Test(R"cpp(
1170#include "foo.h"
1171alpha a;
1172beta<int> b;
1173int x = a.$p1^;
1174int y = b.$p2^;
1175 )cpp");
1176 runAddDocument(Server, File, Test.code());
1177 auto CompletionList =
1178 llvm::cantFail(runCodeComplete(Server, File, Test.point("p1"), {}));
1179
1180 EXPECT_THAT(CompletionList.Completions,
1181 Contains(AllOf(named("gamma"), doc("This is a member field."))));
1182 EXPECT_THAT(
1183 CompletionList.Completions,
1184 Contains(AllOf(named("delta"), doc("This is a member function."))));
1185
1187 llvm::cantFail(runCodeComplete(Server, File, Test.point("p2"), {}));
1188
1189 EXPECT_THAT(CompletionList.Completions,
1190 Contains(AllOf(named("omega")
1191 /* FIXME: Doc retrieval does not work yet*/)));
1192 EXPECT_THAT(
1193 CompletionList.Completions,
1194 Contains(AllOf(named("epsilon"),
1195 doc("This is a member function inside a template."))));
1196}
1197
1198TEST(CompletionTest, CommentsOnMembersFromHeaderOverloadBundling) {
1199 using testing::AnyOf;
1200 MockFS FS;
1202
1203 auto Opts = ClangdServer::optsForTest();
1204 Opts.BuildDynamicSymbolIndex = true;
1205
1206 ClangdServer Server(CDB, FS, Opts);
1207
1208 FS.Files[testPath("foo.h")] = R"cpp(
1209 struct alpha {
1210 /// bool overload.
1211 int delta(bool b);
1212
1213 /// int overload.
1214 int delta(int i);
1215
1216 void epsilon(long l);
1217
1218 /// This one has a comment.
1219 void epsilon(int i);
1220 };
1221 )cpp";
1222
1223 auto File = testPath("foo.cpp");
1224 Annotations Test(R"cpp(
1225#include "foo.h"
1226alpha a;
1227int x = a.^
1228 )cpp");
1229 runAddDocument(Server, File, Test.code());
1230 clangd::CodeCompleteOptions CCOpts;
1231 CCOpts.BundleOverloads = true;
1232 auto CompletionList =
1233 llvm::cantFail(runCodeComplete(Server, File, Test.point(), CCOpts));
1234
1235 EXPECT_THAT(
1236 CompletionList.Completions,
1237 Contains(AllOf(named("epsilon"), doc("This one has a comment."))));
1238 EXPECT_THAT(CompletionList.Completions,
1239 Contains(AllOf(named("delta"), AnyOf(doc("bool overload."),
1240 doc("int overload.")))));
1241}
1242
1243TEST(CompletionTest, GlobalCompletionFiltering) {
1244
1245 Symbol Class = cls("XYZ");
1246 Class.Flags = static_cast<Symbol::SymbolFlag>(
1248 Symbol Func = func("XYZ::foooo");
1249 Func.Flags = static_cast<Symbol::SymbolFlag>(
1250 Func.Flags & ~(Symbol::IndexedForCodeCompletion));
1251
1252 auto Results = completions(R"(// void f() {
1253 XYZ::foooo^
1254 })",
1255 {Class, Func});
1256 EXPECT_THAT(Results.Completions, IsEmpty());
1257}
1258
1259TEST(CodeCompleteTest, DisableTypoCorrection) {
1260 auto Results = completions(R"cpp(
1261 namespace clang { int v; }
1262 void f() { clangd::^
1263 )cpp");
1264 EXPECT_TRUE(Results.Completions.empty());
1265}
1266
1267TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
1268 auto Results = completions(R"cpp(
1269 namespace clang { }
1270 void f() {
1271 clan^
1272 }
1273 )cpp");
1274
1275 EXPECT_THAT(Results.Completions, Contains(labeled("clang")));
1276 EXPECT_THAT(Results.Completions, Not(Contains(labeled("clang::"))));
1277}
1278
1279TEST(CompletionTests, EmptySnippetDoesNotCrash) {
1280 // See https://github.com/clangd/clangd/issues/1216
1281 auto Results = completions(R"cpp(
1282 int main() {
1283 auto w = [&](auto &&f) { return f(f); };
1284 auto f = w([&](auto &&f) {
1285 return [&](auto &&n) {
1286 if (n == 0) {
1287 return 1;
1288 }
1289 return n * ^(f)(n - 1);
1290 };
1291 })(10);
1292 }
1293 )cpp");
1294}
1295
1296TEST(CompletionTest, Issue1427Crash) {
1297 // Need to provide main file signals to ensure that the branch in
1298 // SymbolRelevanceSignals::computeASTSignals() that tries to
1299 // compute a symbol ID is taken.
1300 ASTSignals MainFileSignals;
1302 Opts.MainFileSignals = &MainFileSignals;
1303 completions(R"cpp(
1304 auto f = []() {
1305 1.0_^
1306 };
1307 )cpp",
1308 {}, Opts);
1309}
1310
1311TEST(CompletionTest, BacktrackCrashes) {
1312 // Sema calls code completion callbacks twice in these cases.
1313 auto Results = completions(R"cpp(
1314 namespace ns {
1315 struct FooBarBaz {};
1316 } // namespace ns
1317
1318 int foo(ns::FooBar^
1319 )cpp");
1320
1321 EXPECT_THAT(Results.Completions, ElementsAre(labeled("FooBarBaz")));
1322
1323 // Check we don't crash in that case too.
1324 completions(R"cpp(
1325 struct FooBarBaz {};
1326 void test() {
1327 if (FooBarBaz * x^) {}
1328 }
1329)cpp");
1330}
1331
1332TEST(CompletionTest, CompleteInMacroWithStringification) {
1333 auto Results = completions(R"cpp(
1334void f(const char *, int x);
1335#define F(x) f(#x, x)
1336
1337namespace ns {
1338int X;
1339int Y;
1340} // namespace ns
1341
1342int f(int input_num) {
1343 F(ns::^)
1344}
1345)cpp");
1346
1347 EXPECT_THAT(Results.Completions,
1348 UnorderedElementsAre(named("X"), named("Y")));
1349}
1350
1351TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
1352 auto Results = completions(R"cpp(
1353void f(const char *, int x);
1354#define F(x) f(#x, x)
1355
1356namespace ns {
1357int X;
1358
1359int f(int input_num) {
1360 F(^)
1361}
1362} // namespace ns
1363)cpp");
1364
1365 EXPECT_THAT(Results.Completions, Contains(named("X")));
1366}
1367
1368TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
1369 auto Results = completions(R"cpp(
1370 int bar(int param_in_bar) {
1371 }
1372
1373 int foo(int param_in_foo) {
1374#if 0
1375 // In recovery mode, "param_in_foo" will also be suggested among many other
1376 // unrelated symbols; however, this is really a special case where this works.
1377 // If the #if block is outside of the function, "param_in_foo" is still
1378 // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't
1379 // really provide useful results in excluded branches.
1380 par^
1381#endif
1382 }
1383)cpp");
1384
1385 EXPECT_TRUE(Results.Completions.empty());
1386}
1387
1388TEST(CompletionTest, DefaultArgs) {
1389 clangd::CodeCompleteOptions Opts;
1390 std::string Context = R"cpp(
1391 int X(int A = 0);
1392 int Y(int A, int B = 0);
1393 int Z(int A, int B = 0, int C = 0, int D = 0);
1394 )cpp";
1395 EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions,
1396 UnorderedElementsAre(labeled("X(int A = 0)")));
1397 EXPECT_THAT(completions(Context + "int y = Y^", {}, Opts).Completions,
1398 UnorderedElementsAre(AllOf(labeled("Y(int A, int B = 0)"),
1399 snippetSuffix("(${1:int A})"))));
1400 EXPECT_THAT(completions(Context + "int y = Z^", {}, Opts).Completions,
1401 UnorderedElementsAre(
1402 AllOf(labeled("Z(int A, int B = 0, int C = 0, int D = 0)"),
1403 snippetSuffix("(${1:int A})"))));
1404}
1405
1406TEST(CompletionTest, NoCrashWithTemplateParamsAndPreferredTypes) {
1407 auto Completions = completions(R"cpp(
1408template <template <class> class TT> int foo() {
1409 int a = ^
1410}
1411)cpp")
1412 .Completions;
1413 EXPECT_THAT(Completions, Contains(named("TT")));
1414}
1415
1416TEST(CompletionTest, NestedTemplateHeuristics) {
1417 auto Completions = completions(R"cpp(
1418struct Plain { int xxx; };
1419template <typename T> class Templ { Plain ppp; };
1420template <typename T> void foo(Templ<T> &t) {
1421 // Formally ppp has DependentTy, because Templ may be specialized.
1422 // However we sholud be able to see into it using the primary template.
1423 t.ppp.^
1424}
1425)cpp")
1426 .Completions;
1427 EXPECT_THAT(Completions, Contains(named("xxx")));
1428}
1429
1430TEST(CompletionTest, RecordCCResultCallback) {
1431 std::vector<CodeCompletion> RecordedCompletions;
1433 Opts.RecordCCResult = [&RecordedCompletions](const CodeCompletion &CC,
1434 const SymbolQualitySignals &,
1435 const SymbolRelevanceSignals &,
1436 float Score) {
1437 RecordedCompletions.push_back(CC);
1438 };
1439
1440 completions("int xy1, xy2; int a = xy^", /*IndexSymbols=*/{}, Opts);
1441 EXPECT_THAT(RecordedCompletions,
1442 UnorderedElementsAre(named("xy1"), named("xy2")));
1443}
1444
1445TEST(CompletionTest, ASTSignals) {
1446 struct Completion {
1447 std::string Name;
1448 unsigned MainFileRefs;
1449 unsigned ScopeRefsInFile;
1450 };
1452 std::vector<Completion> RecordedCompletions;
1453 Opts.RecordCCResult = [&RecordedCompletions](const CodeCompletion &CC,
1454 const SymbolQualitySignals &,
1455 const SymbolRelevanceSignals &R,
1456 float Score) {
1457 RecordedCompletions.push_back({CC.Name, R.MainFileRefs, R.ScopeRefsInFile});
1458 };
1459 ASTSignals MainFileSignals;
1460 MainFileSignals.ReferencedSymbols[var("xy1").ID] = 3;
1461 MainFileSignals.ReferencedSymbols[var("xy2").ID] = 1;
1462 MainFileSignals.ReferencedSymbols[var("xyindex").ID] = 10;
1463 MainFileSignals.RelatedNamespaces["tar::"] = 5;
1464 MainFileSignals.RelatedNamespaces["bar::"] = 3;
1465 Opts.MainFileSignals = &MainFileSignals;
1466 Opts.AllScopes = true;
1467 completions(
1468 R"cpp(
1469 int xy1;
1470 int xy2;
1471 namespace bar {
1472 int xybar = 1;
1473 int a = xy^
1474 }
1475 )cpp",
1476 /*IndexSymbols=*/{var("xyindex"), var("tar::xytar"), var("bar::xybar")},
1477 Opts);
1478 EXPECT_THAT(RecordedCompletions,
1479 UnorderedElementsAre(
1480 AllOf(named("xy1"), mainFileRefs(3u), scopeRefs(0u)),
1481 AllOf(named("xy2"), mainFileRefs(1u), scopeRefs(0u)),
1482 AllOf(named("xyindex"), mainFileRefs(10u), scopeRefs(0u)),
1483 AllOf(named("xytar"), mainFileRefs(0u), scopeRefs(5u)),
1484 AllOf(/*both from sema and index*/ named("xybar"),
1485 mainFileRefs(0u), scopeRefs(3u))));
1486}
1487
1489signatures(llvm::StringRef Text, Position Point,
1490 std::vector<Symbol> IndexSymbols = {},
1491 MarkupKind DocumentationFormat = MarkupKind::PlainText) {
1492 std::unique_ptr<SymbolIndex> Index;
1493 if (!IndexSymbols.empty())
1494 Index = memIndex(IndexSymbols);
1495
1496 auto TU = TestTU::withCode(Text);
1497 MockFS FS;
1498 auto Inputs = TU.inputs(FS);
1499 Inputs.Index = Index.get();
1500 IgnoreDiagnostics Diags;
1501 auto CI = buildCompilerInvocation(Inputs, Diags);
1502 if (!CI) {
1503 ADD_FAILURE() << "Couldn't build CompilerInvocation";
1504 return {};
1505 }
1506 auto Preamble = buildPreamble(testPath(TU.Filename), *CI, Inputs,
1507 /*InMemory=*/true, /*Callback=*/nullptr);
1508 if (!Preamble) {
1509 ADD_FAILURE() << "Couldn't build Preamble";
1510 return {};
1511 }
1512 return signatureHelp(testPath(TU.Filename), Point, *Preamble, Inputs,
1513 DocumentationFormat);
1514}
1515
1517signatures(llvm::StringRef Text, std::vector<Symbol> IndexSymbols = {},
1518 MarkupKind DocumentationFormat = MarkupKind::PlainText) {
1519 Annotations Test(Text);
1520 return signatures(Test.code(), Test.point(), std::move(IndexSymbols),
1521 DocumentationFormat);
1522}
1523
1524struct ExpectedParameter {
1525 std::string Text;
1526 std::pair<unsigned, unsigned> Offsets;
1527};
1528llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
1529 const ExpectedParameter &P) {
1530 return OS << P.Text;
1531}
1532MATCHER_P(paramsAre, P, "") {
1533 if (P.size() != arg.parameters.size())
1534 return false;
1535 for (unsigned I = 0; I < P.size(); ++I) {
1536 if (P[I].Text != arg.parameters[I].labelString ||
1537 P[I].Offsets != arg.parameters[I].labelOffsets)
1538 return false;
1539 }
1540 return true;
1541}
1542MATCHER_P(sigDoc, doc, "") { return arg.documentation.value == doc; }
1543
1544/// \p AnnotatedLabel is a signature label with ranges marking parameters, e.g.
1545/// foo([[int p1]], [[double p2]]) -> void
1546Matcher<SignatureInformation> sig(llvm::StringRef AnnotatedLabel) {
1547 llvm::Annotations A(AnnotatedLabel);
1548 std::string Label = std::string(A.code());
1549 std::vector<ExpectedParameter> Parameters;
1550 for (auto Range : A.ranges()) {
1551 Parameters.emplace_back();
1552
1553 ExpectedParameter &P = Parameters.back();
1554 P.Text = Label.substr(Range.Begin, Range.End - Range.Begin);
1555 P.Offsets.first = lspLength(llvm::StringRef(Label).substr(0, Range.Begin));
1556 P.Offsets.second = lspLength(llvm::StringRef(Label).substr(1, Range.End));
1557 }
1558 return AllOf(sigHelpLabeled(Label), paramsAre(Parameters));
1559}
1560
1561TEST(SignatureHelpTest, Overloads) {
1562 auto Results = signatures(R"cpp(
1563 void foo(int x, int y);
1564 void foo(int x, float y);
1565 void foo(float x, int y);
1566 void foo(float x, float y);
1567 void bar(int x, int y = 0);
1568 int main() { foo(^); }
1569 )cpp");
1570 EXPECT_THAT(Results.signatures,
1571 UnorderedElementsAre(sig("foo([[float x]], [[float y]]) -> void"),
1572 sig("foo([[float x]], [[int y]]) -> void"),
1573 sig("foo([[int x]], [[float y]]) -> void"),
1574 sig("foo([[int x]], [[int y]]) -> void")));
1575 // We always prefer the first signature.
1576 EXPECT_EQ(0, Results.activeSignature);
1577 EXPECT_EQ(0, Results.activeParameter);
1578}
1579
1580TEST(SignatureHelpTest, FunctionPointers) {
1581 llvm::StringLiteral Tests[] = {
1582 // Variable of function pointer type
1583 R"cpp(
1584 void (*foo)(int x, int y);
1585 int main() { foo(^); }
1586 )cpp",
1587 // Wrapped in an AttributedType
1588 R"cpp(
1589 void (__stdcall *foo)(int x, int y);
1590 int main() { foo(^); }
1591 )cpp",
1592 // Another syntax for an AttributedType
1593 R"cpp(
1594 void (__attribute__(stdcall) *foo)(int x, int y);
1595 int main() { foo(^); },
1596 )cpp",
1597 // Wrapped in a typedef
1598 R"cpp(
1599 typedef void (*fn)(int x, int y);
1600 fn foo;
1601 int main() { foo(^); }
1602 )cpp",
1603 // Wrapped in both a typedef and an AttributedTyped
1604 R"cpp(
1605 typedef void (__stdcall *fn)(int x, int y);
1606 fn foo;
1607 int main() { foo(^); }
1608 )cpp",
1609 // Field of function pointer type
1610 R"cpp(
1611 struct S {
1612 void (*foo)(int x, int y);
1613 };
1614 S s;
1615 int main() { s.foo(^); }
1616 )cpp",
1617 // Field of function pointer typedef type
1618 R"cpp(
1619 typedef void (*fn)(int x, int y);
1620 struct S {
1621 fn foo;
1622 };
1623 S s;
1624 int main() { s.foo(^); }
1625 )cpp"};
1626 for (auto Test : Tests)
1627 EXPECT_THAT(signatures(Test).signatures,
1628 UnorderedElementsAre(sig("([[int x]], [[int y]]) -> void")));
1629}
1630
1631TEST(SignatureHelpTest, Constructors) {
1632 std::string Top = R"cpp(
1633 struct S {
1634 S(int);
1635 S(const S &) = delete;
1636 };
1637 )cpp";
1638
1639 auto CheckParenInit = [&](std::string Init) {
1640 EXPECT_THAT(signatures(Top + Init).signatures,
1641 UnorderedElementsAre(sig("S([[int]])")))
1642 << Init;
1643 };
1644 CheckParenInit("S s(^);");
1645 CheckParenInit("auto s = S(^);");
1646 CheckParenInit("auto s = new S(^);");
1647
1648 auto CheckBracedInit = [&](std::string Init) {
1649 EXPECT_THAT(signatures(Top + Init).signatures,
1650 UnorderedElementsAre(sig("S{[[int]]}")))
1651 << Init;
1652 };
1653 CheckBracedInit("S s{^};");
1654 CheckBracedInit("S s = {^};");
1655 CheckBracedInit("auto s = S{^};");
1656 // FIXME: doesn't work: no ExpectedType set in ParseCXXNewExpression.
1657 // CheckBracedInit("auto s = new S{^};");
1658 CheckBracedInit("int x(S); int i = x({^});");
1659}
1660
1661TEST(SignatureHelpTest, Aggregates) {
1662 std::string Top = R"cpp(
1663 struct S {
1664 int a, b, c, d;
1665 };
1666 )cpp";
1667 auto AggregateSig = sig("S{[[int a]], [[int b]], [[int c]], [[int d]]}");
1668 EXPECT_THAT(signatures(Top + "S s{^}").signatures,
1669 UnorderedElementsAre(AggregateSig, sig("S{}"),
1670 sig("S{[[const S &]]}"),
1671 sig("S{[[S &&]]}")));
1672 EXPECT_THAT(signatures(Top + "S s{1,^}").signatures,
1673 ElementsAre(AggregateSig));
1674 EXPECT_EQ(signatures(Top + "S s{1,^}").activeParameter, 1);
1675 EXPECT_THAT(signatures(Top + "S s{.c=3,^}").signatures,
1676 ElementsAre(AggregateSig));
1677 EXPECT_EQ(signatures(Top + "S s{.c=3,^}").activeParameter, 3);
1678}
1679
1680TEST(SignatureHelpTest, OverloadInitListRegression) {
1681 auto Results = signatures(R"cpp(
1682 struct A {int x;};
1683 struct B {B(A);};
1684 void f();
1685 int main() {
1686 B b({1});
1687 f(^);
1688 }
1689 )cpp");
1690 EXPECT_THAT(Results.signatures, UnorderedElementsAre(sig("f() -> void")));
1691}
1692
1693TEST(SignatureHelpTest, DefaultArgs) {
1694 auto Results = signatures(R"cpp(
1695 void bar(int x, int y = 0);
1696 void bar(float x = 0, int y = 42);
1697 int main() { bar(^
1698 )cpp");
1699 EXPECT_THAT(Results.signatures,
1700 UnorderedElementsAre(
1701 sig("bar([[int x]], [[int y = 0]]) -> void"),
1702 sig("bar([[float x = 0]], [[int y = 42]]) -> void")));
1703 EXPECT_EQ(0, Results.activeSignature);
1704 EXPECT_EQ(0, Results.activeParameter);
1705}
1706
1707TEST(SignatureHelpTest, ActiveArg) {
1708 auto Results = signatures(R"cpp(
1709 int baz(int a, int b, int c);
1710 int main() { baz(baz(1,2,3), ^); }
1711 )cpp");
1712 EXPECT_THAT(Results.signatures,
1713 ElementsAre(sig("baz([[int a]], [[int b]], [[int c]]) -> int")));
1714 EXPECT_EQ(0, Results.activeSignature);
1715 EXPECT_EQ(1, Results.activeParameter);
1716}
1717
1718TEST(SignatureHelpTest, OpeningParen) {
1719 llvm::StringLiteral Tests[] = {
1720 // Recursive function call.
1721 R"cpp(
1722 int foo(int a, int b, int c);
1723 int main() {
1724 foo(foo $p^( foo(10, 10, 10), ^ )));
1725 })cpp",
1726 // Functional type cast.
1727 R"cpp(
1728 struct Foo {
1729 Foo(int a, int b, int c);
1730 };
1731 int main() {
1732 Foo $p^( 10, ^ );
1733 })cpp",
1734 // New expression.
1735 R"cpp(
1736 struct Foo {
1737 Foo(int a, int b, int c);
1738 };
1739 int main() {
1740 new Foo $p^( 10, ^ );
1741 })cpp",
1742 // Macro expansion.
1743 R"cpp(
1744 int foo(int a, int b, int c);
1745 #define FOO foo(
1746
1747 int main() {
1748 // Macro expansions.
1749 $p^FOO 10, ^ );
1750 })cpp",
1751 // Macro arguments.
1752 R"cpp(
1753 int foo(int a, int b, int c);
1754 int main() {
1755 #define ID(X) X
1756 // FIXME: figure out why ID(foo (foo(10), )) doesn't work when preserving
1757 // the recovery expression.
1758 ID(foo $p^( 10, ^ ))
1759 })cpp",
1760 // Dependent args.
1761 R"cpp(
1762 int foo(int a, int b);
1763 template <typename T> void bar(T t) {
1764 foo$p^(t, ^t);
1765 })cpp",
1766 // Dependent args on templated func.
1767 R"cpp(
1768 template <typename T>
1769 int foo(T, T);
1770 template <typename T> void bar(T t) {
1771 foo$p^(t, ^t);
1772 })cpp",
1773 // Dependent args on member.
1774 R"cpp(
1775 struct Foo { int foo(int, int); };
1776 template <typename T> void bar(T t) {
1777 Foo f;
1778 f.foo$p^(t, ^t);
1779 })cpp",
1780 // Dependent args on templated member.
1781 R"cpp(
1782 struct Foo { template <typename T> int foo(T, T); };
1783 template <typename T> void bar(T t) {
1784 Foo f;
1785 f.foo$p^(t, ^t);
1786 })cpp",
1787 };
1788
1789 for (auto Test : Tests) {
1790 Annotations Code(Test);
1791 EXPECT_EQ(signatures(Code.code(), Code.point()).argListStart,
1792 Code.point("p"))
1793 << "Test source:" << Test;
1794 }
1795}
1796
1797TEST(SignatureHelpTest, StalePreamble) {
1798 TestTU TU;
1799 TU.Code = "";
1800 IgnoreDiagnostics Diags;
1801 MockFS FS;
1802 auto Inputs = TU.inputs(FS);
1803 auto CI = buildCompilerInvocation(Inputs, Diags);
1804 ASSERT_TRUE(CI);
1805 auto EmptyPreamble = buildPreamble(testPath(TU.Filename), *CI, Inputs,
1806 /*InMemory=*/true, /*Callback=*/nullptr);
1807 ASSERT_TRUE(EmptyPreamble);
1808
1809 TU.AdditionalFiles["a.h"] = "int foo(int x);";
1810 const Annotations Test(R"cpp(
1811 #include "a.h"
1812 void bar() { foo(^2); })cpp");
1813 TU.Code = Test.code().str();
1814 auto Results =
1815 signatureHelp(testPath(TU.Filename), Test.point(), *EmptyPreamble,
1816 TU.inputs(FS), MarkupKind::PlainText);
1817 EXPECT_THAT(Results.signatures, ElementsAre(sig("foo([[int x]]) -> int")));
1818 EXPECT_EQ(0, Results.activeSignature);
1819 EXPECT_EQ(0, Results.activeParameter);
1820}
1821
1822class IndexRequestCollector : public SymbolIndex {
1823public:
1824 IndexRequestCollector(std::vector<Symbol> Syms = {}) : Symbols(Syms) {}
1825
1826 bool
1827 fuzzyFind(const FuzzyFindRequest &Req,
1828 llvm::function_ref<void(const Symbol &)> Callback) const override {
1829 std::unique_lock<std::mutex> Lock(Mut);
1830 Requests.push_back(Req);
1831 ReceivedRequestCV.notify_one();
1832 for (const auto &Sym : Symbols)
1833 Callback(Sym);
1834 return true;
1835 }
1836
1837 void lookup(const LookupRequest &,
1838 llvm::function_ref<void(const Symbol &)>) const override {}
1839
1840 bool refs(const RefsRequest &,
1841 llvm::function_ref<void(const Ref &)>) const override {
1842 return false;
1843 }
1844
1845 bool containedRefs(
1846 const ContainedRefsRequest &,
1847 llvm::function_ref<void(const ContainedRefsResult &)>) const override {
1848 return false;
1849 }
1850
1851 void relations(const RelationsRequest &,
1852 llvm::function_ref<void(const SymbolID &, const Symbol &)>)
1853 const override {}
1854
1855 void
1856 reverseRelations(const RelationsRequest &,
1857 llvm::function_ref<void(const SymbolID &, const Symbol &)>)
1858 const override {}
1859
1860 llvm::unique_function<IndexContents(llvm::StringRef) const>
1861 indexedFiles() const override {
1862 return [](llvm::StringRef) { return IndexContents::None; };
1863 }
1864
1865 // This is incorrect, but IndexRequestCollector is not an actual index and it
1866 // isn't used in production code.
1867 size_t estimateMemoryUsage() const override { return 0; }
1868
1869 const std::vector<FuzzyFindRequest> consumeRequests(size_t Num) const {
1870 std::unique_lock<std::mutex> Lock(Mut);
1871 EXPECT_TRUE(wait(Lock, ReceivedRequestCV, timeoutSeconds(30),
1872 [this, Num] { return Requests.size() == Num; }));
1873 auto Reqs = std::move(Requests);
1874 Requests = {};
1875 return Reqs;
1876 }
1877
1878private:
1879 std::vector<Symbol> Symbols;
1880 // We need a mutex to handle async fuzzy find requests.
1881 mutable std::condition_variable ReceivedRequestCV;
1882 mutable std::mutex Mut;
1883 mutable std::vector<FuzzyFindRequest> Requests;
1884};
1885
1886// Clients have to consume exactly Num requests.
1887std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code,
1888 size_t Num = 1) {
1889 clangd::CodeCompleteOptions Opts;
1890 IndexRequestCollector Requests;
1891 Opts.Index = &Requests;
1892 completions(Code, {}, Opts);
1893 const auto Reqs = Requests.consumeRequests(Num);
1894 EXPECT_EQ(Reqs.size(), Num);
1895 return Reqs;
1896}
1897
1898TEST(CompletionTest, UnqualifiedIdQuery) {
1899 auto Requests = captureIndexRequests(R"cpp(
1900 namespace std {}
1901 using namespace std;
1902 namespace ns {
1903 void f() {
1904 vec^
1905 }
1906 }
1907 )cpp");
1908
1909 EXPECT_THAT(Requests,
1910 ElementsAre(Field(&FuzzyFindRequest::Scopes,
1911 UnorderedElementsAre("", "ns::", "std::"))));
1912}
1913
1914TEST(CompletionTest, EnclosingScopeComesFirst) {
1915 auto Requests = captureIndexRequests(R"cpp(
1916 namespace std {}
1917 using namespace std;
1918 namespace nx {
1919 namespace ns {
1920 namespace {
1921 void f() {
1922 vec^
1923 }
1924 }
1925 }
1926 }
1927 )cpp");
1928
1929 EXPECT_THAT(Requests,
1930 ElementsAre(Field(
1932 UnorderedElementsAre("", "std::", "nx::ns::", "nx::"))));
1933 EXPECT_EQ(Requests[0].Scopes[0], "nx::ns::");
1934}
1935
1936TEST(CompletionTest, ResolvedQualifiedIdQuery) {
1937 auto Requests = captureIndexRequests(R"cpp(
1938 namespace ns1 {}
1939 namespace ns2 {} // ignore
1940 namespace ns3 { namespace nns3 {} }
1941 namespace foo {
1942 using namespace ns1;
1943 using namespace ns3::nns3;
1944 }
1945 namespace ns {
1946 void f() {
1947 foo::^
1948 }
1949 }
1950 )cpp");
1951
1952 EXPECT_THAT(Requests,
1953 ElementsAre(Field(
1955 UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::"))));
1956}
1957
1958TEST(CompletionTest, UnresolvedQualifierIdQuery) {
1959 auto Requests = captureIndexRequests(R"cpp(
1960 namespace a {}
1961 using namespace a;
1962 namespace ns {
1963 void f() {
1964 bar::^
1965 }
1966 } // namespace ns
1967 )cpp");
1968
1969 EXPECT_THAT(Requests,
1970 ElementsAre(Field(
1972 UnorderedElementsAre("a::bar::", "ns::bar::", "bar::"))));
1973}
1974
1975TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
1976 auto Requests = captureIndexRequests(R"cpp(
1977 namespace a {}
1978 using namespace a;
1979 namespace ns {
1980 void f() {
1981 ::a::bar::^
1982 }
1983 } // namespace ns
1984 )cpp");
1985
1986 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1987 UnorderedElementsAre("a::bar::"))));
1988}
1989
1990TEST(CompletionTest, EmptyQualifiedQuery) {
1991 auto Requests = captureIndexRequests(R"cpp(
1992 namespace ns {
1993 void f() {
1994 ^
1995 }
1996 } // namespace ns
1997 )cpp");
1998
1999 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
2000 UnorderedElementsAre("", "ns::"))));
2001}
2002
2003TEST(CompletionTest, GlobalQualifiedQuery) {
2004 auto Requests = captureIndexRequests(R"cpp(
2005 namespace ns {
2006 void f() {
2007 ::^
2008 }
2009 } // namespace ns
2010 )cpp");
2011
2012 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
2013 UnorderedElementsAre(""))));
2014}
2015
2016TEST(CompletionTest, NoDuplicatedQueryScopes) {
2017 auto Requests = captureIndexRequests(R"cpp(
2018 namespace {}
2019
2020 namespace na {
2021 namespace {}
2022 namespace nb {
2023 ^
2024 } // namespace nb
2025 } // namespace na
2026 )cpp");
2027
2028 EXPECT_THAT(Requests,
2029 ElementsAre(Field(&FuzzyFindRequest::Scopes,
2030 UnorderedElementsAre("na::", "na::nb::", ""))));
2031}
2032
2033TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
2034 auto Completions = completions(
2035 R"cpp(
2036 struct Foo {
2037 int SomeNameOfField;
2038 typedef int SomeNameOfTypedefField;
2039 };
2040
2041 Foo::^)cpp",
2042 {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")});
2043
2044 EXPECT_THAT(Completions.Completions,
2045 AllOf(Contains(labeled("SomeNameOfField")),
2046 Contains(labeled("SomeNameOfTypedefField")),
2047 Not(Contains(labeled("SomeNameInTheIndex")))));
2048}
2049
2050TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
2051 {
2052 auto Completions = completions(
2053 R"cpp(
2054 template <class T>
2055 void foo() {
2056 T::^
2057 }
2058 )cpp",
2059 {func("::SomeNameInTheIndex")});
2060
2061 EXPECT_THAT(Completions.Completions,
2062 Not(Contains(labeled("SomeNameInTheIndex"))));
2063 }
2064
2065 {
2066 auto Completions = completions(
2067 R"cpp(
2068 template <class T>
2069 void foo() {
2070 T::template Y<int>::^
2071 }
2072 )cpp",
2073 {func("::SomeNameInTheIndex")});
2074
2075 EXPECT_THAT(Completions.Completions,
2076 Not(Contains(labeled("SomeNameInTheIndex"))));
2077 }
2078
2079 {
2080 auto Completions = completions(
2081 R"cpp(
2082 template <class T>
2083 void foo() {
2084 T::foo::^
2085 }
2086 )cpp",
2087 {func("::SomeNameInTheIndex")});
2088
2089 EXPECT_THAT(Completions.Completions,
2090 Not(Contains(labeled("SomeNameInTheIndex"))));
2091 }
2092}
2093
2094TEST(CompletionTest, OverloadBundling) {
2095 clangd::CodeCompleteOptions Opts;
2096 Opts.BundleOverloads = true;
2097
2098 std::string Context = R"cpp(
2099 struct X {
2100 // Overload with int
2101 int a(int) __attribute__((deprecated("", "")));
2102 // Overload with bool
2103 int a(bool);
2104 int b(float);
2105
2106 X(int);
2107 X(float);
2108 };
2109 int GFuncC(int);
2110 int GFuncD(int);
2111 )cpp";
2112
2113 // Member completions are bundled.
2114 EXPECT_THAT(completions(Context + "int y = X().^", {}, Opts).Completions,
2115 UnorderedElementsAre(labeled("a(…)"), labeled("b(float)")));
2116
2117 // Constructor completions are bundled.
2118 EXPECT_THAT(completions(Context + "X z = X^", {}, Opts).Completions,
2119 UnorderedElementsAre(labeled("X"), labeled("X(…)")));
2120
2121 // Non-member completions are bundled, including index+sema.
2122 Symbol NoArgsGFunc = func("GFuncC");
2123 EXPECT_THAT(
2124 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
2125 UnorderedElementsAre(labeled("GFuncC(…)"), labeled("GFuncD(int)")));
2126
2127 // Differences in header-to-insert suppress bundling.
2128 std::string DeclFile = URI::create(testPath("foo")).toString();
2129 NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile.c_str();
2130 NoArgsGFunc.IncludeHeaders.emplace_back("<foo>", 1, Symbol::Include);
2131 EXPECT_THAT(
2132 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
2133 UnorderedElementsAre(AllOf(named("GFuncC"), insertInclude("<foo>")),
2134 labeled("GFuncC(int)"), labeled("GFuncD(int)")));
2135
2136 // Examine a bundled completion in detail.
2137 auto A =
2138 completions(Context + "int y = X().a^", {}, Opts).Completions.front();
2139 EXPECT_EQ(A.Name, "a");
2140 EXPECT_EQ(A.Signature, "(…)");
2141 EXPECT_EQ(A.BundleSize, 2u);
2142 EXPECT_EQ(A.Kind, CompletionItemKind::Method);
2143 EXPECT_EQ(A.ReturnType, "int"); // All overloads return int.
2144 // For now we just return one of the doc strings arbitrarily.
2145 ASSERT_TRUE(A.Documentation);
2146 ASSERT_FALSE(A.Deprecated); // Not all overloads deprecated.
2147 EXPECT_THAT(
2148 A.Documentation->asPlainText(),
2149 AnyOf(HasSubstr("Overload with int"), HasSubstr("Overload with bool")));
2150 EXPECT_EQ(A.SnippetSuffix, "($0)");
2151}
2152
2153TEST(CompletionTest, OverloadBundlingSameFileDifferentURI) {
2154 clangd::CodeCompleteOptions Opts;
2155 Opts.BundleOverloads = true;
2156
2157 Symbol SymX = sym("ns::X", index::SymbolKind::Function, "@F@\\0#");
2158 Symbol SymY = sym("ns::X", index::SymbolKind::Function, "@F@\\0#I#");
2159 std::string BarHeader = testPath("bar.h");
2160 auto BarURI = URI::create(BarHeader).toString();
2161 SymX.CanonicalDeclaration.FileURI = BarURI.c_str();
2162 SymY.CanonicalDeclaration.FileURI = BarURI.c_str();
2163 // The include header is different, but really it's the same file.
2164 SymX.IncludeHeaders.emplace_back("\"bar.h\"", 1, Symbol::Include);
2165 SymY.IncludeHeaders.emplace_back(BarURI.c_str(), 1, Symbol::Include);
2166
2167 auto Results = completions("void f() { ::ns::^ }", {SymX, SymY}, Opts);
2168 // Expect both results are bundled, despite the different-but-same
2169 // IncludeHeader.
2170 ASSERT_EQ(1u, Results.Completions.size());
2171 const auto &R = Results.Completions.front();
2172 EXPECT_EQ("X", R.Name);
2173 EXPECT_EQ(2u, R.BundleSize);
2174}
2175
2176TEST(CompletionTest, DocumentationFromChangedFileCrash) {
2177 MockFS FS;
2178 auto FooH = testPath("foo.h");
2179 auto FooCpp = testPath("foo.cpp");
2180 FS.Files[FooH] = R"cpp(
2181 // this is my documentation comment.
2182 int func();
2183 )cpp";
2184 FS.Files[FooCpp] = "";
2185
2187 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
2188
2189 Annotations Source(R"cpp(
2190 #include "foo.h"
2191 int func() {
2192 // This makes sure we have func from header in the AST.
2193 }
2194 int a = fun^
2195 )cpp");
2196 Server.addDocument(FooCpp, Source.code(), "null", WantDiagnostics::Yes);
2197 // We need to wait for preamble to build.
2198 ASSERT_TRUE(Server.blockUntilIdleForTest());
2199
2200 // Change the header file. Completion will reuse the old preamble!
2201 FS.Files[FooH] = R"cpp(
2202 int func();
2203 )cpp";
2204
2205 clangd::CodeCompleteOptions Opts;
2206 CodeCompleteResult Completions =
2207 cantFail(runCodeComplete(Server, FooCpp, Source.point(), Opts));
2208 // We shouldn't crash. Unfortunately, current workaround is to not produce
2209 // comments for symbols from headers.
2210 EXPECT_THAT(Completions.Completions,
2211 Contains(AllOf(Not(isDocumented()), named("func"))));
2212}
2213
2214TEST(CompletionTest, NonDocComments) {
2215 const char *Text = R"cpp(
2216 // We ignore namespace comments, for rationale see CodeCompletionStrings.h.
2217 namespace comments_ns {
2218 }
2219
2220 // ------------------
2221 int comments_foo();
2222
2223 // A comment and a decl are separated by newlines.
2224 // Therefore, the comment shouldn't show up as doc comment.
2225
2226 int comments_bar();
2227
2228 // this comment should be in the results.
2229 int comments_baz();
2230
2231
2232 template <class T>
2233 struct Struct {
2234 int comments_qux();
2235 int comments_quux();
2236 };
2237
2238
2239 // This comment should not be there.
2240
2241 template <class T>
2242 int Struct<T>::comments_qux() {
2243 }
2244
2245 // This comment **should** be in results.
2246 template <class T>
2247 int Struct<T>::comments_quux() {
2248 int a = comments^;
2249 }
2250 )cpp";
2251
2252 // We should not get any of those comments in completion.
2253 EXPECT_THAT(
2254 completions(Text).Completions,
2255 UnorderedElementsAre(AllOf(Not(isDocumented()), named("comments_foo")),
2256 AllOf(isDocumented(), named("comments_baz")),
2257 AllOf(isDocumented(), named("comments_quux")),
2258 AllOf(Not(isDocumented()), named("comments_ns")),
2259 // FIXME(ibiryukov): the following items should have
2260 // empty documentation, since they are separated from
2261 // a comment with an empty line. Unfortunately, I
2262 // couldn't make Sema tests pass if we ignore those.
2263 AllOf(isDocumented(), named("comments_bar")),
2264 AllOf(isDocumented(), named("comments_qux"))));
2265}
2266
2267TEST(CompletionTest, CompleteOnInvalidLine) {
2268 auto FooCpp = testPath("foo.cpp");
2269
2271 MockFS FS;
2272 FS.Files[FooCpp] = "// empty file";
2273
2274 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
2275 // Run completion outside the file range.
2276 Position Pos;
2277 Pos.line = 100;
2278 Pos.character = 0;
2279 EXPECT_THAT_EXPECTED(
2280 runCodeComplete(Server, FooCpp, Pos, clangd::CodeCompleteOptions()),
2281 Failed());
2282}
2283
2284TEST(CompletionTest, QualifiedNames) {
2285 auto Results = completions(
2286 R"cpp(
2287 namespace ns { int local; void both(); }
2288 void f() { ::ns::^ }
2289 )cpp",
2290 {func("ns::both"), cls("ns::Index")});
2291 // We get results from both index and sema, with no duplicates.
2292 EXPECT_THAT(
2293 Results.Completions,
2294 UnorderedElementsAre(scope("ns::"), scope("ns::"), scope("ns::")));
2295}
2296
2297TEST(CompletionTest, Render) {
2298 CodeCompletion C;
2299 C.Name = "x";
2300 C.FilterText = "x";
2301 C.Signature = "(bool) const";
2302 C.SnippetSuffix = "(${0:bool})";
2303 C.ReturnType = "int";
2304 C.RequiredQualifier = "Foo::";
2305 C.Scope = "ns::Foo::";
2306 C.Documentation.emplace();
2307 C.Documentation->addParagraph().appendText("This is ").appendCode("x()");
2308 C.Includes.emplace_back();
2309 auto &Include = C.Includes.back();
2310 Include.Header = "\"foo.h\"";
2312 C.Score.Total = 1.0;
2313 C.Score.ExcludingName = .5;
2315
2317 Opts.IncludeIndicator.Insert = "^";
2318 Opts.IncludeIndicator.NoInsert = "";
2319 Opts.EnableSnippets = false;
2320
2321 auto R = C.render(Opts);
2322 EXPECT_EQ(R.label, "Foo::x");
2323 EXPECT_EQ(R.labelDetails->detail, "(bool) const");
2324 EXPECT_EQ(R.insertText, "Foo::x");
2325 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
2326 EXPECT_EQ(R.filterText, "x");
2327 EXPECT_EQ(R.detail, "int");
2328 EXPECT_EQ(R.documentation->value, "From \"foo.h\"\n\nThis is x()");
2329 EXPECT_THAT(R.additionalTextEdits, IsEmpty());
2330 EXPECT_EQ(R.sortText, sortText(1.0, "x"));
2331 EXPECT_FALSE(R.deprecated);
2332 EXPECT_EQ(R.score, .5f);
2333
2334 C.FilterText = "xtra";
2335 R = C.render(Opts);
2336 EXPECT_EQ(R.filterText, "xtra");
2337 EXPECT_EQ(R.sortText, sortText(1.0, "xtra"));
2338
2339 Opts.EnableSnippets = true;
2340 R = C.render(Opts);
2341 EXPECT_EQ(R.insertText, "Foo::x(${0:bool})");
2342 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
2343
2344 C.SnippetSuffix = "";
2345 R = C.render(Opts);
2346 EXPECT_EQ(R.insertText, "Foo::x");
2347 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
2348
2349 Include.Insertion.emplace();
2350 R = C.render(Opts);
2351 EXPECT_EQ(R.label, "^Foo::x");
2352 EXPECT_EQ(R.labelDetails->detail, "(bool) const");
2353 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
2354
2355 Opts.ShowOrigins = true;
2356 R = C.render(Opts);
2357 EXPECT_EQ(R.label, "^[AS]Foo::x");
2358 EXPECT_EQ(R.labelDetails->detail, "(bool) const");
2359
2360 C.BundleSize = 2;
2361 R = C.render(Opts);
2362 EXPECT_EQ(R.detail, "[2 overloads]");
2363 EXPECT_EQ(R.documentation->value, "From \"foo.h\"\n\nThis is x()");
2364
2365 C.Deprecated = true;
2366 R = C.render(Opts);
2367 EXPECT_TRUE(R.deprecated);
2368
2369 Opts.DocumentationFormat = MarkupKind::Markdown;
2370 R = C.render(Opts);
2371 EXPECT_EQ(R.documentation->value, "From `\"foo.h\"`\n\nThis is `x()`");
2372}
2373
2374TEST(CompletionTest, IgnoreRecoveryResults) {
2375 auto Results = completions(
2376 R"cpp(
2377 namespace ns { int NotRecovered() { return 0; } }
2378 void f() {
2379 // Sema enters recovery mode first and then normal mode.
2380 if (auto x = ns::NotRecover^)
2381 }
2382 )cpp");
2383 EXPECT_THAT(Results.Completions, UnorderedElementsAre(named("NotRecovered")));
2384}
2385
2386TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
2387 auto Results = completions(
2388 R"cpp(
2389 namespace ns {
2390 class X { public: X(); int x_; };
2391 X::X() : x_^(0) {}
2392 }
2393 )cpp");
2394 EXPECT_THAT(Results.Completions,
2395 UnorderedElementsAre(AllOf(scope("ns::X::"), named("x_"))));
2396}
2397
2398// Like other class members, constructor init lists have to parse what's below,
2399// after the completion point.
2400// But recovering from an incomplete constructor init list is particularly
2401// tricky because the bulk of the list is not surrounded by brackets.
2402TEST(CompletionTest, ConstructorInitListIncomplete) {
2403 auto Results = completions(
2404 R"cpp(
2405 namespace ns {
2406 struct X {
2407 X() : x^
2408 int xyz_;
2409 };
2410 }
2411 )cpp");
2412 EXPECT_THAT(Results.Completions, ElementsAre(named("xyz_")));
2413
2414 Results = completions(
2415 R"cpp(
2416 int foo();
2417
2418 namespace ns {
2419 struct X {
2420 X() : xyz_(fo^
2421 int xyz_;
2422 };
2423 }
2424 )cpp");
2425 EXPECT_THAT(Results.Completions, ElementsAre(named("foo")));
2426}
2427
2428TEST(CompletionTest, CodeCompletionContext) {
2429 auto Results = completions(
2430 R"cpp(
2431 namespace ns {
2432 class X { public: X(); int x_; };
2433 void f() {
2434 X x;
2435 x.^;
2436 }
2437 }
2438 )cpp");
2439
2440 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
2441}
2442
2443TEST(CompletionTest, FixItForArrowToDot) {
2444 MockFS FS;
2446
2448 Opts.IncludeFixIts = true;
2449 const char *Code =
2450 R"cpp(
2451 class Auxilary {
2452 public:
2453 void AuxFunction();
2454 };
2455 class ClassWithPtr {
2456 public:
2457 void MemberFunction();
2458 Auxilary* operator->() const;
2459 Auxilary* Aux;
2460 };
2461 void f() {
2462 ClassWithPtr x;
2463 x[[->]]^;
2464 }
2465 )cpp";
2466 auto Results = completions(Code, {}, Opts);
2467 EXPECT_EQ(Results.Completions.size(), 3u);
2468
2469 TextEdit ReplacementEdit;
2470 ReplacementEdit.range = Annotations(Code).range();
2471 ReplacementEdit.newText = ".";
2472 for (const auto &C : Results.Completions) {
2473 EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction");
2474 if (!C.FixIts.empty()) {
2475 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
2476 }
2477 }
2478}
2479
2480TEST(CompletionTest, FixItForDotToArrow) {
2482 Opts.IncludeFixIts = true;
2483 const char *Code =
2484 R"cpp(
2485 class Auxilary {
2486 public:
2487 void AuxFunction();
2488 };
2489 class ClassWithPtr {
2490 public:
2491 void MemberFunction();
2492 Auxilary* operator->() const;
2493 Auxilary* Aux;
2494 };
2495 void f() {
2496 ClassWithPtr x;
2497 x[[.]]^;
2498 }
2499 )cpp";
2500 auto Results = completions(Code, {}, Opts);
2501 EXPECT_EQ(Results.Completions.size(), 3u);
2502
2503 TextEdit ReplacementEdit;
2504 ReplacementEdit.range = Annotations(Code).range();
2505 ReplacementEdit.newText = "->";
2506 for (const auto &C : Results.Completions) {
2507 EXPECT_TRUE(C.FixIts.empty() || C.Name == "AuxFunction");
2508 if (!C.FixIts.empty()) {
2509 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
2510 }
2511 }
2512}
2513
2514TEST(CompletionTest, RenderWithFixItMerged) {
2515 TextEdit FixIt;
2516 FixIt.range.end.character = 5;
2517 FixIt.newText = "->";
2518
2519 CodeCompletion C;
2520 C.Name = "x";
2521 C.RequiredQualifier = "Foo::";
2522 C.FixIts = {FixIt};
2523 C.CompletionTokenRange.start.character = 5;
2524
2526 Opts.IncludeFixIts = true;
2527
2528 auto R = C.render(Opts);
2529 EXPECT_TRUE(R.textEdit);
2530 EXPECT_EQ(R.textEdit->newText, "->Foo::x");
2531 EXPECT_TRUE(R.additionalTextEdits.empty());
2532}
2533
2534TEST(CompletionTest, RenderWithFixItNonMerged) {
2535 TextEdit FixIt;
2536 FixIt.range.end.character = 4;
2537 FixIt.newText = "->";
2538
2539 CodeCompletion C;
2540 C.Name = "x";
2541 C.RequiredQualifier = "Foo::";
2542 C.FixIts = {FixIt};
2543 C.CompletionTokenRange.start.character = 5;
2544
2546 Opts.IncludeFixIts = true;
2547
2548 auto R = C.render(Opts);
2549 EXPECT_TRUE(R.textEdit);
2550 EXPECT_EQ(R.textEdit->newText, "Foo::x");
2551 EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
2552}
2553
2554TEST(CompletionTest, CompletionTokenRange) {
2555 MockFS FS;
2557 TestTU TU;
2558 TU.AdditionalFiles["foo/abc/foo.h"] = "";
2559
2560 constexpr const char *TestCodes[] = {
2561 R"cpp(
2562 class Auxilary {
2563 public:
2564 void AuxFunction();
2565 };
2566 void f() {
2567 Auxilary x;
2568 x.[[Aux]]^;
2569 }
2570 )cpp",
2571 R"cpp(
2572 class Auxilary {
2573 public:
2574 void AuxFunction();
2575 };
2576 void f() {
2577 Auxilary x;
2578 x.[[]]^;
2579 }
2580 )cpp",
2581 R"cpp(
2582 #include "foo/[[a^/]]foo.h"
2583 )cpp",
2584 R"cpp(
2585 #include "foo/abc/[[fo^o.h"]]
2586 )cpp",
2587 };
2588 for (const auto &Text : TestCodes) {
2589 Annotations TestCode(Text);
2590 TU.Code = TestCode.code().str();
2591 auto Results = completions(TU, TestCode.point());
2592 if (Results.Completions.size() != 1) {
2593 ADD_FAILURE() << "Results.Completions.size() != 1" << Text;
2594 continue;
2595 }
2596 EXPECT_THAT(Results.Completions.front().CompletionTokenRange,
2597 TestCode.range());
2598 }
2599}
2600
2601TEST(SignatureHelpTest, OverloadsOrdering) {
2602 const auto Results = signatures(R"cpp(
2603 void foo(int x);
2604 void foo(int x, float y);
2605 void foo(float x, int y);
2606 void foo(float x, float y);
2607 void foo(int x, int y = 0);
2608 int main() { foo(^); }
2609 )cpp");
2610 EXPECT_THAT(Results.signatures,
2611 ElementsAre(sig("foo([[int x]]) -> void"),
2612 sig("foo([[int x]], [[int y = 0]]) -> void"),
2613 sig("foo([[float x]], [[int y]]) -> void"),
2614 sig("foo([[int x]], [[float y]]) -> void"),
2615 sig("foo([[float x]], [[float y]]) -> void")));
2616 // We always prefer the first signature.
2617 EXPECT_EQ(0, Results.activeSignature);
2618 EXPECT_EQ(0, Results.activeParameter);
2619}
2620
2621TEST(SignatureHelpTest, InstantiatedSignatures) {
2622 StringRef Sig0 = R"cpp(
2623 template <class T>
2624 void foo(T, T, T);
2625
2626 int main() {
2627 foo<int>(^);
2628 }
2629 )cpp";
2630
2631 EXPECT_THAT(signatures(Sig0).signatures,
2632 ElementsAre(sig("foo([[T]], [[T]], [[T]]) -> void")));
2633
2634 StringRef Sig1 = R"cpp(
2635 template <class T>
2636 void foo(T, T, T);
2637
2638 int main() {
2639 foo(10, ^);
2640 })cpp";
2641
2642 EXPECT_THAT(signatures(Sig1).signatures,
2643 ElementsAre(sig("foo([[T]], [[T]], [[T]]) -> void")));
2644
2645 StringRef Sig2 = R"cpp(
2646 template <class ...T>
2647 void foo(T...);
2648
2649 int main() {
2650 foo<int>(^);
2651 }
2652 )cpp";
2653
2654 EXPECT_THAT(signatures(Sig2).signatures,
2655 ElementsAre(sig("foo([[T...]]) -> void")));
2656
2657 // It is debatable whether we should substitute the outer template parameter
2658 // ('T') in that case. Currently we don't substitute it in signature help, but
2659 // do substitute in code complete.
2660 // FIXME: make code complete and signature help consistent, figure out which
2661 // way is better.
2662 StringRef Sig3 = R"cpp(
2663 template <class T>
2664 struct X {
2665 template <class U>
2666 void foo(T, U);
2667 };
2668
2669 int main() {
2670 X<int>().foo<double>(^)
2671 }
2672 )cpp";
2673
2674 EXPECT_THAT(signatures(Sig3).signatures,
2675 ElementsAre(sig("foo([[T]], [[U]]) -> void")));
2676}
2677
2678TEST(SignatureHelpTest, IndexDocumentation) {
2679 Symbol Foo0 = sym("foo", index::SymbolKind::Function, "@F@\\0#");
2680 Foo0.Documentation = "doc from the index";
2681 Symbol Foo1 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#");
2682 Foo1.Documentation = "doc from the index";
2683 Symbol Foo2 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#I#");
2684
2685 StringRef Sig0 = R"cpp(
2686 int foo();
2687 int foo(double);
2688
2689 void test() {
2690 foo(^);
2691 }
2692 )cpp";
2693
2694 EXPECT_THAT(
2695 signatures(Sig0, {Foo0}).signatures,
2696 ElementsAre(AllOf(sig("foo() -> int"), sigDoc("doc from the index")),
2697 AllOf(sig("foo([[double]]) -> int"), sigDoc(""))));
2698
2699 StringRef Sig1 = R"cpp(
2700 int foo();
2701 // Overriden doc from sema
2702 int foo(int);
2703 // doc from sema
2704 int foo(int, int);
2705
2706 void test() {
2707 foo(^);
2708 }
2709 )cpp";
2710
2711 EXPECT_THAT(
2712 signatures(Sig1, {Foo0, Foo1, Foo2}).signatures,
2713 ElementsAre(
2714 AllOf(sig("foo() -> int"), sigDoc("doc from the index")),
2715 AllOf(sig("foo([[int]]) -> int"), sigDoc("Overriden doc from sema")),
2716 AllOf(sig("foo([[int]], [[int]]) -> int"), sigDoc("doc from sema"))));
2717}
2718
2719TEST(SignatureHelpTest, DynamicIndexDocumentation) {
2720 MockFS FS;
2723 Opts.BuildDynamicSymbolIndex = true;
2724 ClangdServer Server(CDB, FS, Opts);
2725
2726 FS.Files[testPath("foo.h")] = R"cpp(
2727 struct Foo {
2728 // Member doc
2729 int foo();
2730 };
2731 )cpp";
2732 Annotations FileContent(R"cpp(
2733 #include "foo.h"
2734 void test() {
2735 Foo f;
2736 f.foo(^);
2737 }
2738 )cpp");
2739 auto File = testPath("test.cpp");
2740 Server.addDocument(File, FileContent.code());
2741 // Wait for the dynamic index being built.
2742 ASSERT_TRUE(Server.blockUntilIdleForTest());
2743 EXPECT_THAT(llvm::cantFail(runSignatureHelp(Server, File, FileContent.point(),
2745 .signatures,
2746 ElementsAre(AllOf(sig("foo() -> int"), sigDoc("Member doc"))));
2747}
2748
2749TEST(CompletionTest, ArgumentListsPolicy) {
2751 Opts.EnableSnippets = true;
2752 Opts.ArgumentLists = Config::ArgumentListsPolicy::Delimiters;
2753
2754 {
2755 auto Results = completions(
2756 R"cpp(
2757 void xfoo();
2758 void xfoo(int x, int y);
2759 void f() { xfo^ })cpp",
2760 {}, Opts);
2761 EXPECT_THAT(
2762 Results.Completions,
2763 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix("()")),
2764 AllOf(named("xfoo"), snippetSuffix("($0)"))));
2765 }
2766 {
2767 auto Results = completions(
2768 R"cpp(
2769 void xbar();
2770 void f() { xba^ })cpp",
2771 {}, Opts);
2772 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
2773 named("xbar"), snippetSuffix("()"))));
2774 }
2775 {
2776 Opts.BundleOverloads = true;
2777 auto Results = completions(
2778 R"cpp(
2779 void xfoo();
2780 void xfoo(int x, int y);
2781 void f() { xfo^ })cpp",
2782 {}, Opts);
2783 EXPECT_THAT(
2784 Results.Completions,
2785 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix("($0)"))));
2786 }
2787 {
2788 auto Results = completions(
2789 R"cpp(
2790 template <class T, class U>
2791 void xfoo(int a, U b);
2792 void f() { xfo^ })cpp",
2793 {}, Opts);
2794 EXPECT_THAT(
2795 Results.Completions,
2796 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix("<$1>($0)"))));
2797 }
2798 {
2799 auto Results = completions(
2800 R"cpp(
2801 template <class T>
2802 class foo_class{};
2803 template <class T>
2804 using foo_alias = T**;
2805 template <class T>
2806 T foo_var = T{};
2807 void f() { foo_^ })cpp",
2808 {}, Opts);
2809 EXPECT_THAT(
2810 Results.Completions,
2811 UnorderedElementsAre(AllOf(named("foo_class"), snippetSuffix("<$0>")),
2812 AllOf(named("foo_alias"), snippetSuffix("<$0>")),
2813 AllOf(named("foo_var"), snippetSuffix("<$0>"))));
2814 }
2815 {
2816 auto Results = completions(
2817 R"cpp(
2818 #define FOO(x, y) x##f
2819 FO^ )cpp",
2820 {}, Opts);
2821 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
2822 named("FOO"), snippetSuffix("($0)"))));
2823 }
2824 {
2825 auto Results = completions(
2826 R"cpp(
2827 void function() {
2828 auto Lambda = [](int a, const double &b) {return 1.f;};
2829 Lam^
2830 })cpp",
2831 {}, Opts);
2832 EXPECT_THAT(
2833 Results.Completions,
2834 UnorderedElementsAre(AllOf(named("Lambda"), snippetSuffix("($0)"))));
2835 }
2836 {
2837 Opts.ArgumentLists = Config::ArgumentListsPolicy::None;
2838 auto Results = completions(
2839 R"cpp(
2840 void xfoo(int x, int y);
2841 void f() { xfo^ })cpp",
2842 {}, Opts);
2843 EXPECT_THAT(Results.Completions,
2844 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix(""))));
2845 }
2846 {
2847 Opts.ArgumentLists = Config::ArgumentListsPolicy::OpenDelimiter;
2848 auto Results = completions(
2849 R"cpp(
2850 void xfoo(int x, int y);
2851 void f() { xfo^ })cpp",
2852 {}, Opts);
2853 EXPECT_THAT(Results.Completions,
2854 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix("("))));
2855 }
2856}
2857
2858TEST(CompletionTest, SuggestOverrides) {
2859 constexpr const char *const Text(R"cpp(
2860 class A {
2861 public:
2862 virtual void vfunc(bool param);
2863 virtual void vfunc(bool param, int p);
2864 void func(bool param);
2865 };
2866 class B : public A {
2867 virtual void ttt(bool param) const;
2868 void vfunc(bool param, int p) override;
2869 };
2870 class C : public B {
2871 public:
2872 void vfunc(bool param) override;
2873 ^
2874 };
2875 )cpp");
2876 const auto Results = completions(Text);
2877 EXPECT_THAT(
2878 Results.Completions,
2879 AllOf(Contains(AllOf(labeled("void vfunc(bool param, int p) override"),
2880 nameStartsWith("vfunc"))),
2881 Contains(AllOf(labeled("void ttt(bool param) const override"),
2882 nameStartsWith("ttt"))),
2883 Not(Contains(labeled("void vfunc(bool param) override")))));
2884}
2885
2886TEST(CompletionTest, OverridesNonIdentName) {
2887 // Check the completions call does not crash.
2888 completions(R"cpp(
2889 struct Base {
2890 virtual ~Base() = 0;
2891 virtual operator int() = 0;
2892 virtual Base& operator+(Base&) = 0;
2893 };
2894
2895 struct Derived : Base {
2896 ^
2897 };
2898 )cpp");
2899}
2900
2901TEST(CompletionTest, NoCrashOnMissingNewLineAtEOF) {
2902 auto FooCpp = testPath("foo.cpp");
2903
2905 MockFS FS;
2906 Annotations F("#pragma ^ // no new line");
2907 FS.Files[FooCpp] = F.code().str();
2908 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
2909 runAddDocument(Server, FooCpp, F.code());
2910 // Run completion outside the file range.
2911 EXPECT_THAT(cantFail(runCodeComplete(Server, FooCpp, F.point(),
2912 clangd::CodeCompleteOptions()))
2913 .Completions,
2914 IsEmpty());
2915 EXPECT_THAT(cantFail(runSignatureHelp(Server, FooCpp, F.point(),
2917 .signatures,
2918 IsEmpty());
2919}
2920
2921TEST(GuessCompletionPrefix, Filters) {
2922 for (llvm::StringRef Case : {
2923 "[[scope::]][[ident]]^",
2924 "[[]][[]]^",
2925 "\n[[]][[]]^",
2926 "[[]][[ab]]^",
2927 "x.[[]][[ab]]^",
2928 "x.[[]][[]]^",
2929 "[[x::]][[ab]]^",
2930 "[[x::]][[]]^",
2931 "[[::x::]][[ab]]^",
2932 "some text [[scope::more::]][[identif]]^ier",
2933 "some text [[scope::]][[mor]]^e::identifier",
2934 "weird case foo::[[::bar::]][[baz]]^",
2935 "/* [[]][[]]^ */",
2936 }) {
2937 Annotations F(Case);
2938 auto Offset = cantFail(positionToOffset(F.code(), F.point()));
2939 auto ToStringRef = [&](Range R) {
2940 return F.code().slice(cantFail(positionToOffset(F.code(), R.start)),
2941 cantFail(positionToOffset(F.code(), R.end)));
2942 };
2943 auto WantQualifier = ToStringRef(F.ranges()[0]),
2944 WantName = ToStringRef(F.ranges()[1]);
2945
2946 auto Prefix = guessCompletionPrefix(F.code(), Offset);
2947 // Even when components are empty, check their offsets are correct.
2948 EXPECT_EQ(WantQualifier, Prefix.Qualifier) << Case;
2949 EXPECT_EQ(WantQualifier.begin(), Prefix.Qualifier.begin()) << Case;
2950 EXPECT_EQ(WantName, Prefix.Name) << Case;
2951 EXPECT_EQ(WantName.begin(), Prefix.Name.begin()) << Case;
2952 }
2953}
2954
2955TEST(CompletionTest, EnableSpeculativeIndexRequest) {
2956 MockFS FS;
2958 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
2959
2960 auto File = testPath("foo.cpp");
2961 Annotations Test(R"cpp(
2962 namespace ns1 { int abc; }
2963 namespace ns2 { int abc; }
2964 void f() { ns1::ab$1^; ns1::ab$2^; }
2965 void f2() { ns2::ab$3^; }
2966 )cpp");
2967 runAddDocument(Server, File, Test.code());
2968 clangd::CodeCompleteOptions Opts = {};
2969
2970 IndexRequestCollector Requests;
2971 Opts.Index = &Requests;
2972
2973 auto CompleteAtPoint = [&](StringRef P) {
2974 auto CCR = cantFail(runCodeComplete(Server, File, Test.point(P), Opts));
2975 EXPECT_TRUE(CCR.HasMore);
2976 };
2977
2978 CompleteAtPoint("1");
2979 auto Reqs1 = Requests.consumeRequests(1);
2980 ASSERT_EQ(Reqs1.size(), 1u);
2981 EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre("ns1::"));
2982
2983 CompleteAtPoint("2");
2984 auto Reqs2 = Requests.consumeRequests(1);
2985 // Speculation succeeded. Used speculative index result.
2986 ASSERT_EQ(Reqs2.size(), 1u);
2987 EXPECT_EQ(Reqs2[0], Reqs1[0]);
2988
2989 CompleteAtPoint("3");
2990 // Speculation failed. Sent speculative index request and the new index
2991 // request after sema.
2992 auto Reqs3 = Requests.consumeRequests(2);
2993 ASSERT_EQ(Reqs3.size(), 2u);
2994}
2995
2996TEST(CompletionTest, InsertTheMostPopularHeader) {
2997 std::string DeclFile = URI::create(testPath("foo")).toString();
2998 Symbol Sym = func("Func");
2999 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
3000 Sym.IncludeHeaders.emplace_back("\"foo.h\"", 2, Symbol::Include);
3001 Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000, Symbol::Include);
3002
3003 auto Results = completions("Fun^", {Sym}).Completions;
3004 assert(!Results.empty());
3005 EXPECT_THAT(Results[0], AllOf(named("Func"), insertInclude("\"bar.h\"")));
3006 EXPECT_EQ(Results[0].Includes.size(), 2u);
3007}
3008
3009TEST(CompletionTest, InsertIncludeOrImport) {
3010 std::string DeclFile = URI::create(testPath("foo")).toString();
3011 Symbol Sym = func("Func");
3012 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
3013 Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000,
3016 // Should only take effect in import contexts.
3017 Opts.ImportInsertions = true;
3018 auto Results = completions("Fun^", {Sym}, Opts).Completions;
3019 assert(!Results.empty());
3020 EXPECT_THAT(Results[0],
3021 AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
3022
3023 ASTSignals Signals;
3025 Opts.MainFileSignals = &Signals;
3026 Results = completions("Fun^", {Sym}, Opts, "Foo.m").Completions;
3027 assert(!Results.empty());
3028 EXPECT_THAT(Results[0],
3029 AllOf(named("Func"), insertIncludeText("#import \"bar.h\"\n")));
3030
3031 Sym.IncludeHeaders[0].SupportedDirectives = Symbol::Import;
3032 Results = completions("Fun^", {Sym}).Completions;
3033 assert(!Results.empty());
3034 EXPECT_THAT(Results[0], AllOf(named("Func"), Not(insertInclude())));
3035}
3036
3037TEST(CompletionTest, NoInsertIncludeIfOnePresent) {
3038 Annotations Test(R"cpp(
3039 #include "foo.h"
3040 Fun^
3041 )cpp");
3042 auto TU = TestTU::withCode(Test.code());
3043 TU.AdditionalFiles["foo.h"] = "";
3044
3045 std::string DeclFile = URI::create(testPath("foo")).toString();
3046 Symbol Sym = func("Func");
3047 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
3048 Sym.IncludeHeaders.emplace_back("\"foo.h\"", 2, Symbol::Include);
3049 Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000, Symbol::Include);
3050
3051 EXPECT_THAT(completions(TU, Test.point(), {Sym}).Completions,
3052 UnorderedElementsAre(AllOf(named("Func"), hasInclude("\"foo.h\""),
3053 Not(insertInclude()))));
3054}
3055
3056TEST(CompletionTest, MergeMacrosFromIndexAndSema) {
3057 Symbol Sym;
3058 Sym.Name = "Clangd_Macro_Test";
3059 Sym.ID = SymbolID("c:foo.cpp@8@macro@Clangd_Macro_Test");
3060 Sym.SymInfo.Kind = index::SymbolKind::Macro;
3062 EXPECT_THAT(completions("#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym})
3063 .Completions,
3064 UnorderedElementsAre(named("Clangd_Macro_Test")));
3065}
3066
3067TEST(CompletionTest, MacroFromPreamble) {
3068 Annotations Test(R"cpp(#define CLANGD_PREAMBLE_MAIN x
3069
3070 int x = 0;
3071 #define CLANGD_MAIN x
3072 void f() { CLANGD_^ }
3073 )cpp");
3074 auto TU = TestTU::withCode(Test.code());
3075 TU.HeaderCode = "#define CLANGD_PREAMBLE_HEADER x";
3076 auto Results = completions(TU, Test.point(), {func("CLANGD_INDEX")});
3077 // We should get results from the main file, including the preamble section.
3078 // However no results from included files (the index should cover them).
3079 EXPECT_THAT(Results.Completions,
3080 UnorderedElementsAre(named("CLANGD_PREAMBLE_MAIN"),
3081 named("CLANGD_MAIN"),
3082 named("CLANGD_INDEX")));
3083}
3084
3085TEST(CompletionTest, DeprecatedResults) {
3086 std::string Body = R"cpp(
3087 void TestClangd();
3088 void TestClangc() __attribute__((deprecated("", "")));
3089 )cpp";
3090
3091 EXPECT_THAT(
3092 completions(Body + "int main() { TestClang^ }").Completions,
3093 UnorderedElementsAre(AllOf(named("TestClangd"), Not(deprecated())),
3094 AllOf(named("TestClangc"), deprecated())));
3095}
3096
3097TEST(SignatureHelpTest, PartialSpec) {
3098 const auto Results = signatures(R"cpp(
3099 template <typename T> struct Foo {};
3100 template <typename T> struct Foo<T*> { Foo(T); };
3101 Foo<int*> F(^);)cpp");
3102 EXPECT_THAT(Results.signatures, Contains(sig("Foo([[T]])")));
3103 EXPECT_EQ(0, Results.activeParameter);
3104}
3105
3106TEST(SignatureHelpTest, InsideArgument) {
3107 {
3108 const auto Results = signatures(R"cpp(
3109 void foo(int x);
3110 void foo(int x, int y);
3111 int main() { foo(1+^); }
3112 )cpp");
3113 EXPECT_THAT(Results.signatures,
3114 ElementsAre(sig("foo([[int x]]) -> void"),
3115 sig("foo([[int x]], [[int y]]) -> void")));
3116 EXPECT_EQ(0, Results.activeParameter);
3117 }
3118 {
3119 const auto Results = signatures(R"cpp(
3120 void foo(int x);
3121 void foo(int x, int y);
3122 int main() { foo(1^); }
3123 )cpp");
3124 EXPECT_THAT(Results.signatures,
3125 ElementsAre(sig("foo([[int x]]) -> void"),
3126 sig("foo([[int x]], [[int y]]) -> void")));
3127 EXPECT_EQ(0, Results.activeParameter);
3128 }
3129 {
3130 const auto Results = signatures(R"cpp(
3131 void foo(int x);
3132 void foo(int x, int y);
3133 int main() { foo(1^0); }
3134 )cpp");
3135 EXPECT_THAT(Results.signatures,
3136 ElementsAre(sig("foo([[int x]]) -> void"),
3137 sig("foo([[int x]], [[int y]]) -> void")));
3138 EXPECT_EQ(0, Results.activeParameter);
3139 }
3140 {
3141 const auto Results = signatures(R"cpp(
3142 void foo(int x);
3143 void foo(int x, int y);
3144 int bar(int x, int y);
3145 int main() { bar(foo(2, 3^)); }
3146 )cpp");
3147 EXPECT_THAT(Results.signatures,
3148 ElementsAre(sig("foo([[int x]], [[int y]]) -> void")));
3149 EXPECT_EQ(1, Results.activeParameter);
3150 }
3151}
3152
3153TEST(SignatureHelpTest, ConstructorInitializeFields) {
3154 {
3155 const auto Results = signatures(R"cpp(
3156 struct A { A(int); };
3157 struct B {
3158 B() : a_elem(^) {}
3159 A a_elem;
3160 };
3161 )cpp");
3162 EXPECT_THAT(Results.signatures,
3163 UnorderedElementsAre(sig("A([[int]])"), sig("A([[A &&]])"),
3164 sig("A([[const A &]])")));
3165 }
3166 {
3167 const auto Results = signatures(R"cpp(
3168 struct A { A(int); };
3169 struct B {
3170 B() : a_elem(^
3171 A a_elem;
3172 };
3173 )cpp");
3174 // FIXME: currently the parser skips over the decl of a_elem as part of the
3175 // (broken) init list, so we don't get signatures for the first member.
3176 EXPECT_THAT(Results.signatures, IsEmpty());
3177 }
3178 {
3179 const auto Results = signatures(R"cpp(
3180 struct A { A(int); };
3181 struct B {
3182 B() : a_elem(^
3183 int dummy_elem;
3184 A a_elem;
3185 };
3186 )cpp");
3187 EXPECT_THAT(Results.signatures,
3188 UnorderedElementsAre(sig("A([[int]])"), sig("A([[A &&]])"),
3189 sig("A([[const A &]])")));
3190 }
3191 {
3192 const auto Results = signatures(R"cpp(
3193 struct A {
3194 A(int);
3195 };
3196 struct C {
3197 C(int);
3198 C(A);
3199 };
3200 struct B {
3201 B() : c_elem(A(1^)) {}
3202 C c_elem;
3203 };
3204 )cpp");
3205 EXPECT_THAT(Results.signatures,
3206 UnorderedElementsAre(sig("A([[int]])"), sig("A([[A &&]])"),
3207 sig("A([[const A &]])")));
3208 }
3209}
3210
3211TEST(SignatureHelpTest, Variadic) {
3212 const std::string Header = R"cpp(
3213 void fun(int x, ...) {}
3214 void test() {)cpp";
3215 const std::string ExpectedSig = "fun([[int x]], [[...]]) -> void";
3216
3217 {
3218 const auto Result = signatures(Header + "fun(^);}");
3219 EXPECT_EQ(0, Result.activeParameter);
3220 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3221 }
3222 {
3223 const auto Result = signatures(Header + "fun(1, ^);}");
3224 EXPECT_EQ(1, Result.activeParameter);
3225 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3226 }
3227 {
3228 const auto Result = signatures(Header + "fun(1, 2, ^);}");
3229 EXPECT_EQ(1, Result.activeParameter);
3230 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3231 }
3232}
3233
3234TEST(SignatureHelpTest, VariadicTemplate) {
3235 const std::string Header = R"cpp(
3236 template<typename T, typename ...Args>
3237 void fun(T t, Args ...args) {}
3238 void test() {)cpp";
3239 const std::string ExpectedSig = "fun([[T t]], [[Args args...]]) -> void";
3240
3241 {
3242 const auto Result = signatures(Header + "fun(^);}");
3243 EXPECT_EQ(0, Result.activeParameter);
3244 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3245 }
3246 {
3247 const auto Result = signatures(Header + "fun(1, ^);}");
3248 EXPECT_EQ(1, Result.activeParameter);
3249 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3250 }
3251 {
3252 const auto Result = signatures(Header + "fun(1, 2, ^);}");
3253 EXPECT_EQ(1, Result.activeParameter);
3254 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3255 }
3256}
3257
3258TEST(SignatureHelpTest, VariadicMethod) {
3259 const std::string Header = R"cpp(
3260 class C {
3261 template<typename T, typename ...Args>
3262 void fun(T t, Args ...args) {}
3263 };
3264 void test() {C c; )cpp";
3265 const std::string ExpectedSig = "fun([[T t]], [[Args args...]]) -> void";
3266
3267 {
3268 const auto Result = signatures(Header + "c.fun(^);}");
3269 EXPECT_EQ(0, Result.activeParameter);
3270 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3271 }
3272 {
3273 const auto Result = signatures(Header + "c.fun(1, ^);}");
3274 EXPECT_EQ(1, Result.activeParameter);
3275 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3276 }
3277 {
3278 const auto Result = signatures(Header + "c.fun(1, 2, ^);}");
3279 EXPECT_EQ(1, Result.activeParameter);
3280 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3281 }
3282}
3283
3284TEST(SignatureHelpTest, VariadicType) {
3285 const std::string Header = R"cpp(
3286 void fun(int x, ...) {}
3287 auto get_fun() { return fun; }
3288 void test() {
3289 )cpp";
3290 const std::string ExpectedSig = "([[int]], [[...]]) -> void";
3291
3292 {
3293 const auto Result = signatures(Header + "get_fun()(^);}");
3294 EXPECT_EQ(0, Result.activeParameter);
3295 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3296 }
3297 {
3298 const auto Result = signatures(Header + "get_fun()(1, ^);}");
3299 EXPECT_EQ(1, Result.activeParameter);
3300 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3301 }
3302 {
3303 const auto Result = signatures(Header + "get_fun()(1, 2, ^);}");
3304 EXPECT_EQ(1, Result.activeParameter);
3305 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3306 }
3307}
3308
3309TEST(SignatureHelpTest, SkipExplicitObjectParameter) {
3310 Annotations Code(R"cpp(
3311 struct A {
3312 void foo(this auto&& self, int arg);
3313 void bar(this A self, int arg);
3314 };
3315 int main() {
3316 A a {};
3317 a.foo($c1^);
3318 (&A::bar)($c2^);
3319 (&A::foo)($c3^);
3320 }
3321 )cpp");
3322
3323 auto TU = TestTU::withCode(Code.code());
3324 TU.ExtraArgs = {"-std=c++23"};
3325
3326 MockFS FS;
3327 auto Inputs = TU.inputs(FS);
3328
3329 auto Preamble = TU.preamble();
3330 ASSERT_TRUE(Preamble);
3331
3332 {
3333 const auto Result = signatureHelp(testPath(TU.Filename), Code.point("c1"),
3335
3336 EXPECT_EQ(1U, Result.signatures.size());
3337
3338 EXPECT_THAT(Result.signatures[0], AllOf(sig("foo([[int arg]]) -> void")));
3339 }
3340 {
3341 const auto Result = signatureHelp(testPath(TU.Filename), Code.point("c2"),
3343
3344 EXPECT_EQ(1U, Result.signatures.size());
3345
3346 EXPECT_THAT(Result.signatures[0], AllOf(sig("([[A]], [[int]]) -> void")));
3347 }
3348 {
3349 // TODO: llvm/llvm-project/146649
3350 const auto Result = signatureHelp(testPath(TU.Filename), Code.point("c3"),
3352 // TODO: We expect 1 signature here, with this signature
3353 EXPECT_EQ(0U, Result.signatures.size());
3354 // EXPECT_THAT(Result.signatures[0], AllOf(sig("([[auto&&]], [[int]]) ->
3355 // void")));
3356 }
3357}
3358
3359TEST(CompletionTest, IncludedCompletionKinds) {
3360 Annotations Test(R"cpp(#include "^)cpp");
3361 auto TU = TestTU::withCode(Test.code());
3362 TU.AdditionalFiles["sub/bar.h"] = "";
3363 TU.ExtraArgs.push_back("-I" + testPath("sub"));
3364
3365 auto Results = completions(TU, Test.point());
3366 EXPECT_THAT(Results.Completions,
3367 AllOf(has("sub/", CompletionItemKind::Folder),
3368 has("bar.h\"", CompletionItemKind::File)));
3369}
3370
3371TEST(CompletionTest, NoCrashAtNonAlphaIncludeHeader) {
3372 completions(
3373 R"cpp(
3374 #include "./^"
3375 )cpp");
3376}
3377
3378TEST(CompletionTest, NoAllScopesCompletionWhenQualified) {
3379 clangd::CodeCompleteOptions Opts = {};
3380 Opts.AllScopes = true;
3381
3382 auto Results = completions(
3383 R"cpp(
3384 void f() { na::Clangd^ }
3385 )cpp",
3386 {cls("na::ClangdA"), cls("nx::ClangdX"), cls("Clangd3")}, Opts);
3387 EXPECT_THAT(Results.Completions,
3388 UnorderedElementsAre(
3389 AllOf(qualifier(""), scope("na::"), named("ClangdA"))));
3390}
3391
3392TEST(CompletionTest, AllScopesCompletion) {
3393 clangd::CodeCompleteOptions Opts = {};
3394 Opts.AllScopes = true;
3395
3396 auto Results = completions(
3397 R"cpp(
3398 namespace na {
3399 void f() { Clangd^ }
3400 }
3401 )cpp",
3402 {cls("nx::Clangd1"), cls("ny::Clangd2"), cls("Clangd3"),
3403 cls("na::nb::Clangd4"), enmConstant("na::C::Clangd5")},
3404 Opts);
3405 EXPECT_THAT(
3406 Results.Completions,
3407 UnorderedElementsAre(AllOf(qualifier("nx::"), named("Clangd1"),
3409 AllOf(qualifier("ny::"), named("Clangd2"),
3411 AllOf(qualifier(""), scope(""), named("Clangd3"),
3413 AllOf(qualifier("nb::"), named("Clangd4"),
3415 AllOf(qualifier("C::"), named("Clangd5"),
3417}
3418
3419TEST(CompletionTest, NoCodePatternsIfDisabled) {
3420 clangd::CodeCompleteOptions Opts = {};
3421 Opts.EnableSnippets = true;
3422 Opts.CodePatterns = Config::CodePatternsPolicy::None;
3423
3424 auto Results = completions(R"cpp(
3425 void function() {
3426 /// Trying to trigger "for (init-statement; condition; inc-expression)
3427 /// {statements}~" code pattern
3428 for^
3429 }
3430 )cpp",
3431 {}, Opts);
3432
3433 EXPECT_THAT(Results.Completions,
3434 Not(Contains(kind(CompletionItemKind::Snippet))));
3435}
3436
3437TEST(CompletionTest, CompleteIncludeIfCodePatternsNone) {
3438 clangd::CodeCompleteOptions Opts = {};
3439 Opts.EnableSnippets = true;
3440 Opts.CodePatterns = Config::CodePatternsPolicy::None;
3441
3442 Annotations Test(R"cpp(#include "^)cpp");
3443 auto TU = TestTU::withCode(Test.code());
3444 TU.AdditionalFiles["foo/bar.h"] = "";
3445 TU.ExtraArgs.push_back("-I" + testPath("foo"));
3446
3447 auto Results = completions(TU, Test.point(), {}, Opts);
3448 EXPECT_THAT(Results.Completions,
3449 AllOf(has("foo/", CompletionItemKind::Folder),
3450 has("bar.h\"", CompletionItemKind::File)));
3451}
3452
3453TEST(CompletionTest, NoQualifierIfShadowed) {
3454 clangd::CodeCompleteOptions Opts = {};
3455 Opts.AllScopes = true;
3456
3457 auto Results = completions(R"cpp(
3458 namespace nx { class Clangd1 {}; }
3459 using nx::Clangd1;
3460 void f() { Clangd^ }
3461 )cpp",
3462 {cls("nx::Clangd1"), cls("nx::Clangd2")}, Opts);
3463 // Although Clangd1 is from another namespace, Sema tells us it's in-scope and
3464 // needs no qualifier.
3465 EXPECT_THAT(Results.Completions,
3466 UnorderedElementsAre(AllOf(qualifier(""), named("Clangd1")),
3467 AllOf(qualifier("nx::"), named("Clangd2"))));
3468}
3469
3470TEST(CompletionTest, NoCompletionsForNewNames) {
3471 clangd::CodeCompleteOptions Opts;
3472 Opts.AllScopes = true;
3473 auto Results = completions(R"cpp(
3474 void f() { int n^ }
3475 )cpp",
3476 {cls("naber"), cls("nx::naber")}, Opts);
3477 EXPECT_THAT(Results.Completions, UnorderedElementsAre());
3478}
3479
3480TEST(CompletionTest, Lambda) {
3481 clangd::CodeCompleteOptions Opts = {};
3482
3483 auto Results = completions(R"cpp(
3484 void function() {
3485 auto Lambda = [](int a, const double &b) {return 1.f;};
3486 Lam^
3487 }
3488 )cpp",
3489 {}, Opts);
3490
3491 ASSERT_EQ(Results.Completions.size(), 1u);
3492 const auto &A = Results.Completions.front();
3493 EXPECT_EQ(A.Name, "Lambda");
3494 EXPECT_EQ(A.Signature, "(int a, const double &b) const");
3495 EXPECT_EQ(A.Kind, CompletionItemKind::Variable);
3496 EXPECT_EQ(A.ReturnType, "float");
3497 EXPECT_EQ(A.SnippetSuffix, "(${1:int a}, ${2:const double &b})");
3498}
3499
3500TEST(CompletionTest, StructuredBinding) {
3501 clangd::CodeCompleteOptions Opts = {};
3502
3503 auto Results = completions(R"cpp(
3504 struct S {
3505 using Float = float;
3506 int x;
3507 Float y;
3508 };
3509 void function() {
3510 const auto &[xxx, yyy] = S{};
3511 yyy^
3512 }
3513 )cpp",
3514 {}, Opts);
3515
3516 ASSERT_EQ(Results.Completions.size(), 1u);
3517 const auto &A = Results.Completions.front();
3518 EXPECT_EQ(A.Name, "yyy");
3519 EXPECT_EQ(A.Kind, CompletionItemKind::Variable);
3520 EXPECT_EQ(A.ReturnType, "const Float");
3521}
3522
3523TEST(CompletionTest, ObjectiveCMethodNoArguments) {
3524 auto Results = completions(R"objc(
3525 @interface Foo
3526 @property(nonatomic, setter=setXToIgnoreComplete:) int value;
3527 @end
3528 Foo *foo = [Foo new]; int y = [foo v^]
3529 )objc",
3530 /*IndexSymbols=*/{},
3531 /*Opts=*/{}, "Foo.m");
3532
3533 auto C = Results.Completions;
3534 EXPECT_THAT(C, ElementsAre(named("value")));
3535 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3536 EXPECT_THAT(C, ElementsAre(returnType("int")));
3537 EXPECT_THAT(C, ElementsAre(signature("")));
3538 EXPECT_THAT(C, ElementsAre(snippetSuffix("")));
3539}
3540
3541TEST(CompletionTest, ObjectiveCMethodOneArgument) {
3542 auto Results = completions(R"objc(
3543 @interface Foo
3544 - (int)valueForCharacter:(char)c;
3545 @end
3546 Foo *foo = [Foo new]; int y = [foo v^]
3547 )objc",
3548 /*IndexSymbols=*/{},
3549 /*Opts=*/{}, "Foo.m");
3550
3551 auto C = Results.Completions;
3552 EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));
3553 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3554 EXPECT_THAT(C, ElementsAre(returnType("int")));
3555 EXPECT_THAT(C, ElementsAre(signature("(char)")));
3556 EXPECT_THAT(C, ElementsAre(snippetSuffix("${1:(char)}")));
3557}
3558
3559TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromBeginning) {
3560 auto Results = completions(R"objc(
3561 @interface Foo
3562 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;
3563 @end
3564 id val = [Foo foo^]
3565 )objc",
3566 /*IndexSymbols=*/{},
3567 /*Opts=*/{}, "Foo.m");
3568
3569 auto C = Results.Completions;
3570 EXPECT_THAT(C, ElementsAre(named("fooWithValue:")));
3571 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3572 EXPECT_THAT(C, ElementsAre(returnType("id")));
3573 EXPECT_THAT(C, ElementsAre(signature("(int) fooey:(unsigned int)")));
3574 EXPECT_THAT(
3575 C, ElementsAre(snippetSuffix("${1:(int)} fooey:${2:(unsigned int)}")));
3576}
3577
3578TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
3579 auto Results = completions(R"objc(
3580 @interface Foo
3581 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;
3582 @end
3583 id val = [Foo fooWithValue:10 f^]
3584 )objc",
3585 /*IndexSymbols=*/{},
3586 /*Opts=*/{}, "Foo.m");
3587
3588 auto C = Results.Completions;
3589 EXPECT_THAT(C, ElementsAre(named("fooey:")));
3590 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3591 EXPECT_THAT(C, ElementsAre(returnType("id")));
3592 EXPECT_THAT(C, ElementsAre(signature("(unsigned int)")));
3593 EXPECT_THAT(C, ElementsAre(snippetSuffix("${1:(unsigned int)}")));
3594}
3595
3596TEST(CompletionTest, ObjectiveCMethodFilterOnEntireSelector) {
3597 auto Results = completions(R"objc(
3598 @interface Foo
3599 + (id)player:(id)player willRun:(id)run;
3600 @end
3601 id val = [Foo wi^]
3602 )objc",
3603 /*IndexSymbols=*/{},
3604 /*Opts=*/{}, "Foo.m");
3605
3606 auto C = Results.Completions;
3607 EXPECT_THAT(C, ElementsAre(named("player:")));
3608 EXPECT_THAT(C, ElementsAre(filterText("player:willRun:")));
3609 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3610 EXPECT_THAT(C, ElementsAre(returnType("id")));
3611 EXPECT_THAT(C, ElementsAre(signature("(id) willRun:(id)")));
3612 EXPECT_THAT(C, ElementsAre(snippetSuffix("${1:(id)} willRun:${2:(id)}")));
3613}
3614
3615TEST(CompletionTest, ObjectiveCSimpleMethodDeclaration) {
3616 auto Results = completions(R"objc(
3617 @interface Foo
3618 - (void)foo;
3619 @end
3620 @implementation Foo
3621 fo^
3622 @end
3623 )objc",
3624 /*IndexSymbols=*/{},
3625 /*Opts=*/{}, "Foo.m");
3626
3627 auto C = Results.Completions;
3628 EXPECT_THAT(C, ElementsAre(named("foo")));
3629 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3630 EXPECT_THAT(C, ElementsAre(qualifier("- (void)")));
3631}
3632
3633TEST(CompletionTest, ObjectiveCMethodDeclaration) {
3634 auto Results = completions(R"objc(
3635 @interface Foo
3636 - (int)valueForCharacter:(char)c secondArgument:(id)object;
3637 @end
3638 @implementation Foo
3639 valueFor^
3640 @end
3641 )objc",
3642 /*IndexSymbols=*/{},
3643 /*Opts=*/{}, "Foo.m");
3644
3645 auto C = Results.Completions;
3646 EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));
3647 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3648 EXPECT_THAT(C, ElementsAre(qualifier("- (int)")));
3649 EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
3650}
3651
3652TEST(CompletionTest, ObjectiveCMethodDeclarationFilterOnEntireSelector) {
3653 auto Results = completions(R"objc(
3654 @interface Foo
3655 - (int)valueForCharacter:(char)c secondArgument:(id)object;
3656 @end
3657 @implementation Foo
3658 secondArg^
3659 @end
3660 )objc",
3661 /*IndexSymbols=*/{},
3662 /*Opts=*/{}, "Foo.m");
3663
3664 auto C = Results.Completions;
3665 EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));
3666 EXPECT_THAT(C, ElementsAre(filterText("valueForCharacter:secondArgument:")));
3667 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3668 EXPECT_THAT(C, ElementsAre(qualifier("- (int)")));
3669 EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
3670}
3671
3672TEST(CompletionTest, ObjectiveCMethodDeclarationPrefixTyped) {
3673 auto Results = completions(R"objc(
3674 @interface Foo
3675 - (int)valueForCharacter:(char)c;
3676 @end
3677 @implementation Foo
3678 - (int)valueFor^
3679 @end
3680 )objc",
3681 /*IndexSymbols=*/{},
3682 /*Opts=*/{}, "Foo.m");
3683
3684 auto C = Results.Completions;
3685 EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));
3686 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3687 EXPECT_THAT(C, ElementsAre(signature("(char)c")));
3688}
3689
3690TEST(CompletionTest, ObjectiveCMethodDeclarationFromMiddle) {
3691 auto Results = completions(R"objc(
3692 @interface Foo
3693 - (int)valueForCharacter:(char)c secondArgument:(id)object;
3694 @end
3695 @implementation Foo
3696 - (int)valueForCharacter:(char)c second^
3697 @end
3698 )objc",
3699 /*IndexSymbols=*/{},
3700 /*Opts=*/{}, "Foo.m");
3701
3702 auto C = Results.Completions;
3703 EXPECT_THAT(C, ElementsAre(named("secondArgument:")));
3704 EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
3705 EXPECT_THAT(C, ElementsAre(signature("(id)object")));
3706}
3707
3708TEST(CompletionTest, ObjectiveCProtocolFromIndex) {
3709 Symbol FoodClass = objcClass("FoodClass");
3710 Symbol SymFood = objcProtocol("Food");
3711 Symbol SymFooey = objcProtocol("Fooey");
3712 auto Results = completions("id<Foo^>", {SymFood, FoodClass, SymFooey},
3713 /*Opts=*/{}, "Foo.m");
3714
3715 // Should only give protocols for ObjC protocol completions.
3716 EXPECT_THAT(Results.Completions,
3717 UnorderedElementsAre(
3718 AllOf(named("Food"), kind(CompletionItemKind::Interface)),
3719 AllOf(named("Fooey"), kind(CompletionItemKind::Interface))));
3720
3721 Results = completions("Fo^", {SymFood, FoodClass, SymFooey},
3722 /*Opts=*/{}, "Foo.m");
3723 // Shouldn't give protocols for non protocol completions.
3724 EXPECT_THAT(
3725 Results.Completions,
3726 ElementsAre(AllOf(named("FoodClass"), kind(CompletionItemKind::Class))));
3727}
3728
3729TEST(CompletionTest, ObjectiveCProtocolFromIndexSpeculation) {
3730 MockFS FS;
3732 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
3733
3734 auto File = testPath("Foo.m");
3735 Annotations Test(R"cpp(
3736 @protocol Food
3737 @end
3738 id<Foo$1^> foo;
3739 Foo$2^ bar;
3740 )cpp");
3741 runAddDocument(Server, File, Test.code());
3742 clangd::CodeCompleteOptions Opts = {};
3743
3744 Symbol FoodClass = objcClass("FoodClass");
3745 IndexRequestCollector Requests({FoodClass});
3746 Opts.Index = &Requests;
3747
3748 auto CompleteAtPoint = [&](StringRef P) {
3749 return cantFail(runCodeComplete(Server, File, Test.point(P), Opts))
3750 .Completions;
3751 };
3752
3753 auto C = CompleteAtPoint("1");
3754 auto Reqs1 = Requests.consumeRequests(1);
3755 ASSERT_EQ(Reqs1.size(), 1u);
3756 EXPECT_THAT(C, ElementsAre(AllOf(named("Food"),
3758
3759 C = CompleteAtPoint("2");
3760 auto Reqs2 = Requests.consumeRequests(1);
3761 // Speculation succeeded. Used speculative index result, but filtering now to
3762 // now include FoodClass.
3763 ASSERT_EQ(Reqs2.size(), 1u);
3764 EXPECT_EQ(Reqs2[0], Reqs1[0]);
3765 EXPECT_THAT(C, ElementsAre(AllOf(named("FoodClass"),
3767}
3768
3769TEST(CompletionTest, ObjectiveCCategoryFromIndexIgnored) {
3770 Symbol FoodCategory = objcCategory("FoodClass", "Extension");
3771 auto Results = completions(R"objc(
3772 @interface Foo
3773 @end
3774 @interface Foo (^)
3775 @end
3776 )objc",
3777 {FoodCategory},
3778 /*Opts=*/{}, "Foo.m");
3779 EXPECT_THAT(Results.Completions, IsEmpty());
3780}
3781
3782TEST(CompletionTest, ObjectiveCForwardDeclFromIndex) {
3783 Symbol FoodClass = objcClass("FoodClass");
3784 FoodClass.IncludeHeaders.emplace_back("\"Foo.h\"", 2, Symbol::Import);
3785 Symbol SymFood = objcProtocol("Food");
3786 auto Results = completions("@class Foo^", {SymFood, FoodClass},
3787 /*Opts=*/{}, "Foo.m");
3788
3789 // Should only give class names without any include insertion.
3790 EXPECT_THAT(Results.Completions,
3791 UnorderedElementsAre(AllOf(named("FoodClass"),
3793 Not(insertInclude()))));
3794}
3795
3796TEST(CompletionTest, CursorInSnippets) {
3797 clangd::CodeCompleteOptions Options;
3798 Options.EnableSnippets = true;
3799 auto Results = completions(
3800 R"cpp(
3801 void while_foo(int a, int b);
3802 void test() {
3803 whil^
3804 })cpp",
3805 /*IndexSymbols=*/{}, Options);
3806
3807 // Last placeholder in code patterns should be $0 to put the cursor there.
3808 EXPECT_THAT(Results.Completions,
3809 Contains(AllOf(named("while"),
3810 snippetSuffix(" (${1:condition}) {\n$0\n}"))));
3811 // However, snippets for functions must *not* end with $0.
3812 EXPECT_THAT(Results.Completions,
3813 Contains(AllOf(named("while_foo"),
3814 snippetSuffix("(${1:int a}, ${2:int b})"))));
3815
3816 Results = completions(R"cpp(
3817 struct Base {
3818 Base(int a, int b) {}
3819 };
3820
3821 struct Derived : Base {
3822 Derived() : Base^
3823 };
3824 )cpp",
3825 /*IndexSymbols=*/{}, Options);
3826 // Constructors from base classes are a kind of pattern that shouldn't end
3827 // with $0.
3828 EXPECT_THAT(Results.Completions,
3829 Contains(AllOf(named("Base"),
3830 snippetSuffix("(${1:int a}, ${2:int b})"))));
3831}
3832
3833TEST(CompletionTest, WorksWithNullType) {
3834 auto R = completions(R"cpp(
3835 int main() {
3836 for (auto [loopVar] : y ) { // y has to be unresolved.
3837 int z = loopV^;
3838 }
3839 }
3840 )cpp");
3841 EXPECT_THAT(R.Completions, ElementsAre(named("loopVar")));
3842}
3843
3844TEST(CompletionTest, UsingDecl) {
3845 const char *Header(R"cpp(
3846 void foo(int);
3847 namespace std {
3848 using ::foo;
3849 })cpp");
3850 const char *Source(R"cpp(
3851 void bar() {
3852 std::^;
3853 })cpp");
3854 auto Index = TestTU::withHeaderCode(Header).index();
3855 clangd::CodeCompleteOptions Opts;
3856 Opts.Index = Index.get();
3857 Opts.AllScopes = true;
3858 auto R = completions(Source, {}, Opts);
3859 EXPECT_THAT(R.Completions,
3860 ElementsAre(AllOf(scope("std::"), named("foo"),
3862}
3863
3864TEST(CompletionTest, Enums) {
3865 const char *Header(R"cpp(
3866 namespace ns {
3867 enum Unscoped { Clangd1 };
3868 class C {
3869 enum Unscoped { Clangd2 };
3870 };
3871 enum class Scoped { Clangd3 };
3872 })cpp");
3873 const char *Source(R"cpp(
3874 void bar() {
3875 Clangd^
3876 })cpp");
3877 auto Index = TestTU::withHeaderCode(Header).index();
3878 clangd::CodeCompleteOptions Opts;
3879 Opts.Index = Index.get();
3880 Opts.AllScopes = true;
3881 auto R = completions(Source, {}, Opts);
3882 EXPECT_THAT(R.Completions, UnorderedElementsAre(
3883 AllOf(scope("ns::"), named("Clangd1"),
3885 AllOf(scope("ns::C::"), named("Clangd2"),
3887 AllOf(scope("ns::Scoped::"), named("Clangd3"),
3889}
3890
3891TEST(CompletionTest, ScopeIsUnresolved) {
3892 clangd::CodeCompleteOptions Opts = {};
3893 Opts.AllScopes = true;
3894
3895 auto Results = completions(R"cpp(
3896 namespace a {
3897 void f() { b::X^ }
3898 }
3899 )cpp",
3900 {cls("a::b::XYZ")}, Opts);
3901 EXPECT_THAT(Results.Completions,
3902 UnorderedElementsAre(AllOf(qualifier(""), named("XYZ"))));
3903}
3904
3905TEST(CompletionTest, NestedScopeIsUnresolved) {
3906 clangd::CodeCompleteOptions Opts = {};
3907 Opts.AllScopes = true;
3908
3909 auto Results = completions(R"cpp(
3910 namespace a {
3911 namespace b {}
3912 void f() { b::c::X^ }
3913 }
3914 )cpp",
3915 {cls("a::b::c::XYZ")}, Opts);
3916 EXPECT_THAT(Results.Completions,
3917 UnorderedElementsAre(AllOf(qualifier(""), named("XYZ"))));
3918}
3919
3920// Clang parser gets confused here and doesn't report the ns:: prefix.
3921// Naive behavior is to insert it again. We examine the source and recover.
3922TEST(CompletionTest, NamespaceDoubleInsertion) {
3923 clangd::CodeCompleteOptions Opts = {};
3924
3925 auto Results = completions(R"cpp(
3926 namespace foo {
3927 namespace ns {}
3928 #define M(X) < X
3929 M(ns::ABC^
3930 }
3931 )cpp",
3932 {cls("foo::ns::ABCDE")}, Opts);
3933 EXPECT_THAT(Results.Completions,
3934 UnorderedElementsAre(AllOf(qualifier(""), named("ABCDE"))));
3935}
3936
3937TEST(CompletionTest, DerivedMethodsAreAlwaysVisible) {
3938 // Despite the fact that base method matches the ref-qualifier better,
3939 // completion results should only include the derived method.
3940 auto Completions = completions(R"cpp(
3941 struct deque_base {
3942 float size();
3943 double size() const;
3944 };
3945 struct deque : deque_base {
3946 int size() const;
3947 };
3948
3949 auto x = deque().^
3950 )cpp")
3951 .Completions;
3952 EXPECT_THAT(Completions,
3953 ElementsAre(AllOf(returnType("int"), named("size"))));
3954}
3955
3956TEST(CompletionTest, NoCrashWithIncompleteLambda) {
3957 auto Completions = completions("auto&& x = []{^").Completions;
3958 // The completion of x itself can cause a problem: in the code completion
3959 // callback, its type is not known, which affects the linkage calculation.
3960 // A bad linkage value gets cached, and subsequently updated.
3961 EXPECT_THAT(Completions, Contains(named("x")));
3962
3963 auto Signatures = signatures("auto x() { x(^").signatures;
3964 EXPECT_THAT(Signatures, Contains(sig("x() -> auto")));
3965}
3966
3967TEST(CompletionTest, DelayedTemplateParsing) {
3968 Annotations Test(R"cpp(
3969 int xxx;
3970 template <typename T> int foo() { return xx^; }
3971 )cpp");
3972 auto TU = TestTU::withCode(Test.code());
3973 // Even though delayed-template-parsing is on, we will disable it to provide
3974 // completion in templates.
3975 TU.ExtraArgs.push_back("-fdelayed-template-parsing");
3976
3977 EXPECT_THAT(completions(TU, Test.point()).Completions,
3978 Contains(named("xxx")));
3979}
3980
3981TEST(CompletionTest, CompletionRange) {
3982 const char *WithRange = "auto x = [[abc]]^";
3983 auto Completions = completions(WithRange);
3984 EXPECT_EQ(Completions.CompletionRange, Annotations(WithRange).range());
3985 Completions = completionsNoCompile(WithRange);
3986 EXPECT_EQ(Completions.CompletionRange, Annotations(WithRange).range());
3987
3988 const char *EmptyRange = "auto x = [[]]^";
3989 Completions = completions(EmptyRange);
3990 EXPECT_EQ(Completions.CompletionRange, Annotations(EmptyRange).range());
3991 Completions = completionsNoCompile(EmptyRange);
3992 EXPECT_EQ(Completions.CompletionRange, Annotations(EmptyRange).range());
3993
3994 // Sema doesn't trigger at all here, while the no-sema completion runs
3995 // heuristics as normal and reports a range. It'd be nice to be consistent.
3996 const char *NoCompletion = "/* foo [[]]^ */";
3997 Completions = completions(NoCompletion);
3998 EXPECT_EQ(Completions.CompletionRange, std::nullopt);
3999 Completions = completionsNoCompile(NoCompletion);
4000 EXPECT_EQ(Completions.CompletionRange, Annotations(NoCompletion).range());
4001}
4002
4003TEST(NoCompileCompletionTest, Basic) {
4004 auto Results = completionsNoCompile(R"cpp(
4005 void func() {
4006 int xyz;
4007 int abc;
4008 ^
4009 }
4010 )cpp");
4011 EXPECT_FALSE(Results.RanParser);
4012 EXPECT_THAT(Results.Completions,
4013 UnorderedElementsAre(named("void"), named("func"), named("int"),
4014 named("xyz"), named("abc")));
4015}
4016
4017TEST(NoCompileCompletionTest, WithFilter) {
4018 auto Results = completionsNoCompile(R"cpp(
4019 void func() {
4020 int sym1;
4021 int sym2;
4022 int xyz1;
4023 int xyz2;
4024 sy^
4025 }
4026 )cpp");
4027 EXPECT_THAT(Results.Completions,
4028 UnorderedElementsAre(named("sym1"), named("sym2")));
4029}
4030
4031TEST(NoCompileCompletionTest, WithIndex) {
4032 std::vector<Symbol> Syms = {func("xxx"), func("a::xxx"), func("ns::b::xxx"),
4033 func("c::xxx"), func("ns::d::xxx")};
4034 auto Results = completionsNoCompile(
4035 R"cpp(
4036 // Current-scopes, unqualified completion.
4037 using namespace a;
4038 namespace ns {
4039 using namespace b;
4040 void foo() {
4041 xx^
4042 }
4043 }
4044 )cpp",
4045 Syms);
4046 EXPECT_THAT(Results.Completions,
4047 UnorderedElementsAre(AllOf(qualifier(""), scope("")),
4048 AllOf(qualifier(""), scope("a::")),
4049 AllOf(qualifier(""), scope("ns::b::"))));
4051 Opts.AllScopes = true;
4052 Results = completionsNoCompile(
4053 R"cpp(
4054 // All-scopes unqualified completion.
4055 using namespace a;
4056 namespace ns {
4057 using namespace b;
4058 void foo() {
4059 xx^
4060 }
4061 }
4062 )cpp",
4063 Syms, Opts);
4064 EXPECT_THAT(Results.Completions,
4065 UnorderedElementsAre(AllOf(qualifier(""), scope("")),
4066 AllOf(qualifier(""), scope("a::")),
4067 AllOf(qualifier(""), scope("ns::b::")),
4068 AllOf(qualifier("c::"), scope("c::")),
4069 AllOf(qualifier("d::"), scope("ns::d::"))));
4070 Results = completionsNoCompile(
4071 R"cpp(
4072 // Qualified completion.
4073 using namespace a;
4074 namespace ns {
4075 using namespace b;
4076 void foo() {
4077 b::xx^
4078 }
4079 }
4080 )cpp",
4081 Syms, Opts);
4082 EXPECT_THAT(Results.Completions,
4083 ElementsAre(AllOf(qualifier(""), scope("ns::b::"))));
4084 Results = completionsNoCompile(
4085 R"cpp(
4086 // Absolutely qualified completion.
4087 using namespace a;
4088 namespace ns {
4089 using namespace b;
4090 void foo() {
4091 ::a::xx^
4092 }
4093 }
4094 )cpp",
4095 Syms, Opts);
4096 EXPECT_THAT(Results.Completions,
4097 ElementsAre(AllOf(qualifier(""), scope("a::"))));
4098}
4099
4100TEST(AllowImplicitCompletion, All) {
4101 const char *Yes[] = {
4102 "foo.^bar",
4103 "foo->^bar",
4104 "foo::^bar",
4105 " # include <^foo.h>",
4106 "#import <foo/^bar.h>",
4107 "#include_next \"^",
4108 };
4109 const char *No[] = {
4110 "foo>^bar",
4111 "foo:^bar",
4112 "foo\n^bar",
4113 "#include <foo.h> //^",
4114 "#include \"foo.h\"^",
4115 "#error <^",
4116 "#<^",
4117 };
4118 for (const char *Test : Yes) {
4119 llvm::Annotations A(Test);
4120 EXPECT_TRUE(allowImplicitCompletion(A.code(), A.point())) << Test;
4121 }
4122 for (const char *Test : No) {
4123 llvm::Annotations A(Test);
4124 EXPECT_FALSE(allowImplicitCompletion(A.code(), A.point())) << Test;
4125 }
4126}
4127
4128TEST(CompletionTest, FunctionArgsExist) {
4129 clangd::CodeCompleteOptions Opts;
4130 Opts.EnableSnippets = true;
4131 std::string Context = R"cpp(
4132 #define MACRO(x)
4133 int foo(int A);
4134 int bar();
4135 struct Object {
4136 Object(int B) {}
4137 };
4138 template <typename T>
4139 struct Container {
4140 Container(int Size) {}
4141 };
4142 )cpp";
4143 EXPECT_THAT(completions(Context + "int y = fo^", {}, Opts).Completions,
4144 UnorderedElementsAre(
4145 AllOf(labeled("foo(int A)"), snippetSuffix("(${1:int A})"))));
4146 EXPECT_THAT(
4147 completions(Context + "int y = fo^(42)", {}, Opts).Completions,
4148 UnorderedElementsAre(AllOf(labeled("foo(int A)"), snippetSuffix(""))));
4149 // FIXME(kirillbobyrev): No snippet should be produced here.
4150 EXPECT_THAT(completions(Context + "int y = fo^o(42)", {}, Opts).Completions,
4151 UnorderedElementsAre(
4152 AllOf(labeled("foo(int A)"), snippetSuffix("(${1:int A})"))));
4153 EXPECT_THAT(
4154 completions(Context + "int y = ba^", {}, Opts).Completions,
4155 UnorderedElementsAre(AllOf(labeled("bar()"), snippetSuffix("()"))));
4156 EXPECT_THAT(completions(Context + "int y = ba^()", {}, Opts).Completions,
4157 UnorderedElementsAre(AllOf(labeled("bar()"), snippetSuffix(""))));
4158 EXPECT_THAT(
4159 completions(Context + "Object o = Obj^", {}, Opts).Completions,
4160 Contains(AllOf(labeled("Object(int B)"), snippetSuffix("(${1:int B})"),
4162 EXPECT_THAT(completions(Context + "Object o = Obj^()", {}, Opts).Completions,
4163 Contains(AllOf(labeled("Object(int B)"), snippetSuffix(""),
4165 EXPECT_THAT(
4166 completions(Context + "Container c = Cont^", {}, Opts).Completions,
4167 Contains(AllOf(labeled("Container<typename T>(int Size)"),
4168 snippetSuffix("<${1:typename T}>(${2:int Size})"),
4170 EXPECT_THAT(
4171 completions(Context + "Container c = Cont^()", {}, Opts).Completions,
4172 Contains(AllOf(labeled("Container<typename T>(int Size)"),
4173 snippetSuffix("<${1:typename T}>"),
4175 EXPECT_THAT(
4176 completions(Context + "Container c = Cont^<int>()", {}, Opts).Completions,
4177 Contains(AllOf(labeled("Container<typename T>(int Size)"),
4178 snippetSuffix(""),
4180 EXPECT_THAT(completions(Context + "MAC^(2)", {}, Opts).Completions,
4181 Contains(AllOf(labeled("MACRO(x)"), snippetSuffix(""),
4183}
4184
4185TEST(CompletionTest, FunctionArgsExist_Issue1785) {
4186 // This is a scenario where the implementation of our check for
4187 // "is there a function argument list right after the cursor"
4188 // gave a bogus result.
4189 clangd::CodeCompleteOptions Opts;
4190 Opts.EnableSnippets = true;
4191 // The whitespace in this testcase is important!
4192 std::string Code = R"cpp(
4193void waldo(int);
4194
4195int main()
4196{
4197 wal^
4198
4199
4200 // ( )
4201}
4202 )cpp";
4203 EXPECT_THAT(
4204 completions(Code, {}, Opts).Completions,
4205 Contains(AllOf(labeled("waldo(int)"), snippetSuffix("(${1:int})"))));
4206}
4207
4208TEST(CompletionTest, NoCrashDueToMacroOrdering) {
4209 EXPECT_THAT(completions(R"cpp(
4210 #define ECHO(X) X
4211 #define ECHO2(X) ECHO(X)
4212 int finish_preamble = EC^HO(2);)cpp")
4213 .Completions,
4214 UnorderedElementsAre(labeled("ECHO(X)"), labeled("ECHO2(X)")));
4215}
4216
4217TEST(CompletionTest, ObjCCategoryDecls) {
4218 TestTU TU;
4219 TU.ExtraArgs.push_back("-xobjective-c");
4220 TU.HeaderCode = R"objc(
4221 @interface Foo
4222 @end
4223
4224 @interface Foo (FooExt1)
4225 @end
4226
4227 @interface Foo (FooExt2)
4228 @end
4229
4230 @interface Bar
4231 @end
4232
4233 @interface Bar (BarExt)
4234 @end)objc";
4235
4236 {
4237 Annotations Test(R"objc(
4238 @implementation Foo (^)
4239 @end
4240 )objc");
4241 TU.Code = Test.code().str();
4242 auto Results = completions(TU, Test.point());
4243 EXPECT_THAT(Results.Completions,
4244 UnorderedElementsAre(labeled("FooExt1"), labeled("FooExt2")));
4245 }
4246 {
4247 Annotations Test(R"objc(
4248 @interface Foo (^)
4249 @end
4250 )objc");
4251 TU.Code = Test.code().str();
4252 auto Results = completions(TU, Test.point());
4253 EXPECT_THAT(Results.Completions, UnorderedElementsAre(labeled("BarExt")));
4254 }
4255}
4256
4257TEST(CompletionTest, PreambleCodeComplete) {
4258 llvm::StringLiteral Baseline = "\n#define MACRO 12\nint num = MACRO;";
4259 llvm::StringLiteral ModifiedCC =
4260 "#include \"header.h\"\n#define MACRO 12\nint num = MACRO; int num2 = M^";
4261
4262 Annotations Test(ModifiedCC);
4263 auto BaselineTU = TestTU::withCode(Baseline);
4264 auto ModifiedTU = TestTU::withCode(Test.code());
4265
4266 MockFS FS;
4267 auto Inputs = ModifiedTU.inputs(FS);
4268 auto Result = codeComplete(testPath(ModifiedTU.Filename), Test.point(),
4269 BaselineTU.preamble().get(), Inputs, {});
4270 EXPECT_THAT(Result.Completions, Not(testing::IsEmpty()));
4271}
4272
4273TEST(CompletionTest, CommentParamName) {
4274 const std::string Code = R"cpp(
4275 void fun(int foo, int bar);
4276 void overloaded(int param_int);
4277 void overloaded(int param_int, int param_other);
4278 void overloaded(char param_char);
4279 int main() {
4280 )cpp";
4281
4282 EXPECT_THAT(completions(Code + "fun(/*^").Completions,
4283 UnorderedElementsAre(labeled("foo=*/")));
4284 EXPECT_THAT(completions(Code + "fun(1, /*^").Completions,
4285 UnorderedElementsAre(labeled("bar=*/")));
4286 EXPECT_THAT(completions(Code + "/*^").Completions, IsEmpty());
4287 // Test de-duplication.
4288 EXPECT_THAT(
4289 completions(Code + "overloaded(/*^").Completions,
4290 UnorderedElementsAre(labeled("param_int=*/"), labeled("param_char=*/")));
4291 // Comment already has some text in it.
4292 EXPECT_THAT(completions(Code + "fun(/* ^").Completions,
4293 UnorderedElementsAre(labeled("foo=*/")));
4294 EXPECT_THAT(completions(Code + "fun(/* f^").Completions,
4295 UnorderedElementsAre(labeled("foo=*/")));
4296 EXPECT_THAT(completions(Code + "fun(/* x^").Completions, IsEmpty());
4297 EXPECT_THAT(completions(Code + "fun(/* f ^").Completions, IsEmpty());
4298
4299 // Test ranges
4300 {
4301 std::string CompletionRangeTest(Code + "fun(/*[[^]]");
4302 auto Results = completions(CompletionRangeTest);
4303 EXPECT_THAT(Results.CompletionRange,
4304 llvm::ValueIs(Annotations(CompletionRangeTest).range()));
4305 EXPECT_THAT(
4306 Results.Completions,
4307 testing::Each(
4308 AllOf(replacesRange(Annotations(CompletionRangeTest).range()),
4310 }
4311 {
4312 std::string CompletionRangeTest(Code + "fun(/*[[fo^]]");
4313 auto Results = completions(CompletionRangeTest);
4314 EXPECT_THAT(Results.CompletionRange,
4315 llvm::ValueIs(Annotations(CompletionRangeTest).range()));
4316 EXPECT_THAT(
4317 Results.Completions,
4318 testing::Each(
4319 AllOf(replacesRange(Annotations(CompletionRangeTest).range()),
4321 }
4322}
4323
4324TEST(CompletionTest, Concepts) {
4325 Annotations Code(R"cpp(
4326 template<class T>
4327 concept A = sizeof(T) <= 8;
4328
4329 template<$tparam^A U>
4330 int foo();
4331
4332 template<typename T>
4333 int bar(T t) requires $expr^A<int>;
4334
4335 template<class T>
4336 concept b = $expr^A && $expr^sizeof(T) % 2 == 0 || $expr^A && sizeof(T) == 1;
4337
4338 $toplevel^A auto i = 19;
4339
4340 template<$toplevel^A auto i> void constrainedNTTP();
4341
4342 // FIXME: The first parameter should be dropped in this case.
4343 void abbreviated($expr^A auto x) {}
4344 )cpp");
4345 TestTU TU;
4346 TU.Code = Code.code().str();
4347 TU.ExtraArgs = {"-std=c++20"};
4348
4349 auto Sym = conceptSym("same_as");
4350 Sym.Signature = "<typename Tp, typename Up>";
4351 Sym.CompletionSnippetSuffix = "<${1:typename Tp}, ${2:typename Up}>";
4352 std::vector<Symbol> Syms = {Sym};
4353 for (auto P : Code.points("tparam")) {
4354 ASSERT_THAT(
4355 completions(TU, P, Syms).Completions,
4356 AllOf(Contains(AllOf(named("A"), signature(""), snippetSuffix(""))),
4357 Contains(AllOf(named("same_as"), signature("<typename Up>"),
4358 snippetSuffix("<${2:typename Up}>"))),
4359 Contains(named("class")), Contains(named("typename"))))
4360 << "Completing template parameter at position " << P;
4361 }
4362
4363 for (auto P : Code.points("toplevel")) {
4364 EXPECT_THAT(
4365 completions(TU, P, Syms).Completions,
4366 AllOf(Contains(AllOf(named("A"), signature(""), snippetSuffix(""))),
4367 Contains(AllOf(named("same_as"), signature("<typename Up>"),
4368 snippetSuffix("<${2:typename Up}>")))))
4369 << "Completing 'requires' expression at position " << P;
4370 }
4371
4372 for (auto P : Code.points("expr")) {
4373 EXPECT_THAT(
4374 completions(TU, P, Syms).Completions,
4375 AllOf(Contains(AllOf(named("A"), signature("<class T>"),
4376 snippetSuffix("<${1:class T}>"))),
4377 Contains(AllOf(
4378 named("same_as"), signature("<typename Tp, typename Up>"),
4379 snippetSuffix("<${1:typename Tp}, ${2:typename Up}>")))))
4380 << "Completing 'requires' expression at position " << P;
4381 }
4382}
4383
4384TEST(SignatureHelp, DocFormat) {
4385 Annotations Code(R"cpp(
4386 // Comment `with` markup.
4387 void foo(int);
4388 void bar() { foo(^); }
4389 )cpp");
4390 for (auto DocumentationFormat :
4392 auto Sigs = signatures(Code.code(), Code.point(), /*IndexSymbols=*/{},
4393 DocumentationFormat);
4394 ASSERT_EQ(Sigs.signatures.size(), 1U);
4395 EXPECT_EQ(Sigs.signatures[0].documentation.kind, DocumentationFormat);
4396 }
4397}
4398
4399TEST(SignatureHelp, TemplateArguments) {
4400 std::string Top = R"cpp(
4401 template <typename T, int> bool foo(char);
4402 template <int I, int> bool foo(float);
4403 )cpp";
4404
4405 auto First = signatures(Top + "bool x = foo<^");
4406 EXPECT_THAT(
4407 First.signatures,
4408 UnorderedElementsAre(sig("foo<[[typename T]], [[int]]>() -> bool"),
4409 sig("foo<[[int I]], [[int]]>() -> bool")));
4410 EXPECT_EQ(First.activeParameter, 0);
4411
4412 auto Second = signatures(Top + "bool x = foo<1, ^");
4413 EXPECT_THAT(Second.signatures,
4414 ElementsAre(sig("foo<[[int I]], [[int]]>() -> bool")));
4415 EXPECT_EQ(Second.activeParameter, 1);
4416}
4417
4418TEST(CompletionTest, DoNotCrash) {
4419 llvm::StringLiteral Cases[] = {
4420 R"cpp(
4421 template <typename = int> struct Foo {};
4422 auto a = [x(3)](Foo<^>){};
4423 )cpp",
4424 };
4425 for (auto Case : Cases) {
4426 SCOPED_TRACE(Case);
4427 auto Completions = completions(Case);
4428 }
4429}
4430TEST(CompletionTest, PreambleFromDifferentTarget) {
4431 constexpr std::string_view PreambleTarget = "x86_64";
4432 constexpr std::string_view Contents =
4433 "int foo(int); int num; int num2 = foo(n^";
4434
4435 Annotations Test(Contents);
4436 auto TU = TestTU::withCode(Test.code());
4437 TU.ExtraArgs.emplace_back("-target");
4438 TU.ExtraArgs.emplace_back(PreambleTarget);
4439 auto Preamble = TU.preamble();
4440 ASSERT_TRUE(Preamble);
4441 // Switch target to wasm.
4442 TU.ExtraArgs.pop_back();
4443 TU.ExtraArgs.emplace_back("wasm32");
4444
4445 MockFS FS;
4446 auto Inputs = TU.inputs(FS);
4447 auto Result = codeComplete(testPath(TU.Filename), Test.point(),
4448 Preamble.get(), Inputs, {});
4449 auto Signatures =
4450 signatureHelp(testPath(TU.Filename), Test.point(), *Preamble, Inputs, {});
4451
4452 // Make sure we don't crash.
4453 EXPECT_THAT(Result.Completions, Not(testing::IsEmpty()));
4454 EXPECT_THAT(Signatures.signatures, Not(testing::IsEmpty()));
4455}
4456
4457TEST(CompletionTest, SkipExplicitObjectParameter) {
4458 Annotations Code(R"cpp(
4459 struct A {
4460 void foo(this auto&& self, int arg);
4461 void bar(this A self, int arg);
4462 };
4463
4464 int main() {
4465 A a {};
4466 a.$c1^;
4467 (&A::fo$c2^;
4468 (&A::ba$c3^;
4469 }
4470 )cpp");
4471
4472 // TODO: llvm/llvm-project/146649
4473 // This is incorrect behavior. Correct Result should be a variant of,
4474 // c2: signature = (auto&& self, int arg)
4475 // snippet = (${1: auto&& self}, ${2: int arg})
4476 // c3: signature = (A self, int arg)
4477 // snippet = (${1: A self}, ${2: int arg})
4478
4479 auto TU = TestTU::withCode(Code.code());
4480 TU.ExtraArgs = {"-std=c++23"};
4481
4482 auto Preamble = TU.preamble();
4483 ASSERT_TRUE(Preamble);
4484
4485 CodeCompleteOptions Opts{};
4486
4487 MockFS FS;
4488 auto Inputs = TU.inputs(FS);
4489 {
4490 auto Result = codeComplete(testPath(TU.Filename), Code.point("c1"),
4491 Preamble.get(), Inputs, Opts);
4492
4493 EXPECT_THAT(Result.Completions,
4494 UnorderedElementsAre(AllOf(named("foo"), signature("(int arg)"),
4495 snippetSuffix("(${1:int arg})")),
4496 AllOf(named("bar"), signature("(int arg)"),
4497 snippetSuffix("(${1:int arg})"))));
4498 }
4499 {
4500 auto Result = codeComplete(testPath(TU.Filename), Code.point("c2"),
4501 Preamble.get(), Inputs, Opts);
4502 EXPECT_THAT(
4503 Result.Completions,
4504 ElementsAre(AllOf(named("foo"), signature("<class self:auto>(int arg)"),
4505 snippetSuffix("<${1:class self:auto}>"))));
4506 }
4507 {
4508 auto Result = codeComplete(testPath(TU.Filename), Code.point("c3"),
4509 Preamble.get(), Inputs, Opts);
4510 EXPECT_THAT(Result.Completions,
4511 ElementsAre(AllOf(named("bar"), signature("(int arg)"),
4512 snippetSuffix(""))));
4513 }
4514}
4515
4516TEST(CompletionTest, MemberAccessInExplicitObjMemfn) {
4517 Annotations Code(R"cpp(
4518 struct A {
4519 int member {};
4520 int memberFnA(int a);
4521 int memberFnA(this A&, float a);
4522
4523 void foo(this A& self) {
4524 // Should not offer any members here, since
4525 // it needs to be referenced through `self`.
4526 mem$c1^;
4527 // should offer all results
4528 self.mem$c2^;
4529
4530 [&]() {
4531 // should not offer any results
4532 mem$c3^;
4533 }();
4534 }
4535 };
4536 )cpp");
4537
4538 auto TU = TestTU::withCode(Code.code());
4539 TU.ExtraArgs = {"-std=c++23"};
4540
4541 auto Preamble = TU.preamble();
4542 ASSERT_TRUE(Preamble);
4543
4544 CodeCompleteOptions Opts{};
4545
4546 MockFS FS;
4547 auto Inputs = TU.inputs(FS);
4548
4549 {
4550 auto Result = codeComplete(testPath(TU.Filename), Code.point("c1"),
4551 Preamble.get(), Inputs, Opts);
4552
4553 EXPECT_THAT(Result.Completions, ElementsAre());
4554 }
4555 {
4556 auto Result = codeComplete(testPath(TU.Filename), Code.point("c2"),
4557 Preamble.get(), Inputs, Opts);
4558
4559 EXPECT_THAT(
4560 Result.Completions,
4561 UnorderedElementsAre(named("member"),
4562 AllOf(named("memberFnA"), signature("(int a)"),
4563 snippetSuffix("(${1:int a})")),
4564 AllOf(named("memberFnA"), signature("(float a)"),
4565 snippetSuffix("(${1:float a})"))));
4566 }
4567 {
4568 auto Result = codeComplete(testPath(TU.Filename), Code.point("c3"),
4569 Preamble.get(), Inputs, Opts);
4570
4571 EXPECT_THAT(Result.Completions, ElementsAre());
4572 }
4573}
4574
4575TEST(CompletionTest, ListExplicitObjectOverloads) {
4576 Annotations Code(R"cpp(
4577 struct S {
4578 void foo1(int a);
4579 void foo2(int a) const;
4580 void foo2(this const S& self, float a);
4581 void foo3(this const S& self, int a);
4582 void foo4(this S& self, int a);
4583 };
4584
4585 void S::foo1(int a) {
4586 this->$c1^;
4587 }
4588
4589 void S::foo2(int a) const {
4590 this->$c2^;
4591 }
4592
4593 void S::foo3(this const S& self, int a) {
4594 self.$c3^;
4595 }
4596
4597 void S::foo4(this S& self, int a) {
4598 self.$c4^;
4599 }
4600
4601 void test1(S s) {
4602 s.$c5^;
4603 }
4604
4605 void test2(const S s) {
4606 s.$c6^;
4607 }
4608 )cpp");
4609
4610 auto TU = TestTU::withCode(Code.code());
4611 TU.ExtraArgs = {"-std=c++23"};
4612
4613 auto Preamble = TU.preamble();
4614 ASSERT_TRUE(Preamble);
4615
4616 CodeCompleteOptions Opts{};
4617
4618 MockFS FS;
4619 auto Inputs = TU.inputs(FS);
4620
4621 {
4622 auto Result = codeComplete(testPath(TU.Filename), Code.point("c1"),
4623 Preamble.get(), Inputs, Opts);
4624 EXPECT_THAT(
4625 Result.Completions,
4626 UnorderedElementsAre(AllOf(named("foo1"), signature("(int a)"),
4627 snippetSuffix("(${1:int a})")),
4628 AllOf(named("foo2"), signature("(int a) const"),
4629 snippetSuffix("(${1:int a})")),
4630 AllOf(named("foo2"), signature("(float a) const"),
4631 snippetSuffix("(${1:float a})")),
4632 AllOf(named("foo3"), signature("(int a) const"),
4633 snippetSuffix("(${1:int a})")),
4634 AllOf(named("foo4"), signature("(int a)"),
4635 snippetSuffix("(${1:int a})"))));
4636 }
4637 {
4638 auto Result = codeComplete(testPath(TU.Filename), Code.point("c2"),
4639 Preamble.get(), Inputs, Opts);
4640 EXPECT_THAT(
4641 Result.Completions,
4642 UnorderedElementsAre(AllOf(named("foo2"), signature("(int a) const"),
4643 snippetSuffix("(${1:int a})")),
4644 AllOf(named("foo2"), signature("(float a) const"),
4645 snippetSuffix("(${1:float a})")),
4646 AllOf(named("foo3"), signature("(int a) const"),
4647 snippetSuffix("(${1:int a})"))));
4648 }
4649 {
4650 auto Result = codeComplete(testPath(TU.Filename), Code.point("c3"),
4651 Preamble.get(), Inputs, Opts);
4652 EXPECT_THAT(
4653 Result.Completions,
4654 UnorderedElementsAre(AllOf(named("foo2"), signature("(int a) const"),
4655 snippetSuffix("(${1:int a})")),
4656 AllOf(named("foo2"), signature("(float a) const"),
4657 snippetSuffix("(${1:float a})")),
4658 AllOf(named("foo3"), signature("(int a) const"),
4659 snippetSuffix("(${1:int a})"))));
4660 }
4661 {
4662 auto Result = codeComplete(testPath(TU.Filename), Code.point("c4"),
4663 Preamble.get(), Inputs, Opts);
4664 EXPECT_THAT(
4665 Result.Completions,
4666 UnorderedElementsAre(AllOf(named("foo1"), signature("(int a)"),
4667 snippetSuffix("(${1:int a})")),
4668 AllOf(named("foo2"), signature("(int a) const"),
4669 snippetSuffix("(${1:int a})")),
4670 AllOf(named("foo2"), signature("(float a) const"),
4671 snippetSuffix("(${1:float a})")),
4672 AllOf(named("foo3"), signature("(int a) const"),
4673 snippetSuffix("(${1:int a})")),
4674 AllOf(named("foo4"), signature("(int a)"),
4675 snippetSuffix("(${1:int a})"))));
4676 }
4677 {
4678 auto Result = codeComplete(testPath(TU.Filename), Code.point("c5"),
4679 Preamble.get(), Inputs, Opts);
4680 EXPECT_THAT(
4681 Result.Completions,
4682 UnorderedElementsAre(AllOf(named("foo1"), signature("(int a)"),
4683 snippetSuffix("(${1:int a})")),
4684 AllOf(named("foo2"), signature("(int a) const"),
4685 snippetSuffix("(${1:int a})")),
4686 AllOf(named("foo2"), signature("(float a) const"),
4687 snippetSuffix("(${1:float a})")),
4688 AllOf(named("foo3"), signature("(int a) const"),
4689 snippetSuffix("(${1:int a})")),
4690 AllOf(named("foo4"), signature("(int a)"),
4691 snippetSuffix("(${1:int a})"))));
4692 }
4693 {
4694 auto Result = codeComplete(testPath(TU.Filename), Code.point("c6"),
4695 Preamble.get(), Inputs, Opts);
4696 EXPECT_THAT(
4697 Result.Completions,
4698 UnorderedElementsAre(AllOf(named("foo2"), signature("(int a) const"),
4699 snippetSuffix("(${1:int a})")),
4700 AllOf(named("foo2"), signature("(float a) const"),
4701 snippetSuffix("(${1:float a})")),
4702 AllOf(named("foo3"), signature("(int a) const"),
4703 snippetSuffix("(${1:int a})"))));
4704 }
4705}
4706
4707TEST(CompletionTest, FuzzyMatchMacro) {
4708 Annotations Code(R"cpp(
4709 #define gl_foo() 42
4710 #define _gl_foo() 42
4711 #define glfbar() 42
4712
4713 int gl_frob();
4714 int _gl_frob();
4715
4716 int main() {
4717 int y = glf$c1^;
4718 int y = _gl$c2^;
4719 }
4720 )cpp");
4721
4722 auto TU = TestTU::withCode(Code.code());
4723
4724 // Exact prefix should match macro or symbol
4725 {
4726 CodeCompleteOptions Opts{};
4727 EXPECT_EQ(Opts.MacroFilter, Config::MacroFilterPolicy::ExactPrefix);
4728
4729 {
4730 auto Results = completions(TU, Code.point("c1"), {}, Opts);
4731 EXPECT_THAT(
4732 Results.Completions,
4733 ElementsAre(named("gl_frob"), named("_gl_frob"), named("glfbar")));
4734 }
4735
4736 {
4737 auto Results = completions(TU, Code.point("c2"), {}, Opts);
4738 EXPECT_THAT(Results.Completions,
4739 ElementsAre(named("_gl_frob"), named("_gl_foo")));
4740 }
4741 }
4742
4743 // but with fuzzy match
4744 {
4745 CodeCompleteOptions Opts{};
4746 Opts.MacroFilter = Config::MacroFilterPolicy::FuzzyMatch;
4747
4748 // don't suggest underscore macros in general,
4749 {
4750 auto Results = completions(TU, Code.point("c1"), {}, Opts);
4751 EXPECT_THAT(Results.Completions,
4752 ElementsAre(named("gl_frob"), named("_gl_frob"),
4753 named("glfbar"), named("gl_foo")));
4754 }
4755
4756 // but do suggest when macro contains exact prefix
4757 {
4758 auto Results = completions(TU, Code.point("c2"), {}, Opts);
4759 EXPECT_THAT(Results.Completions,
4760 ElementsAre(named("_gl_frob"), named("_gl_foo")));
4761 }
4762 }
4763}
4764
4765} // namespace
4766} // namespace clangd
4767} // namespace clang
#define EXPECT_IFF(condition, value, matcher)
Same as llvm::Annotations, but adjusts functions to LSP-specific types for positions and ranges.
Definition Annotations.h:23
clangd::Range range(llvm::StringRef Name="") const
Manages a collection of source files and derived data (ASTs, indexes), and provides language-aware fe...
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition Context.h:69
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
llvm::StringMap< std::string > Files
Definition TestFS.h:45
An efficient structure of storing large set of symbol references in memory.
Definition Ref.h:111
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
Definition Index.h:134
SymbolSlab::Builder is a mutable container that can 'freeze' to SymbolSlab.
Definition Symbol.h:224
void insert(const Symbol &S)
Adds a symbol, overwriting any existing one with the same ID.
Definition Symbol.cpp:52
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
WithContextValue extends Context::current() with a single value.
Definition Context.h:200
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
Definition AST.cpp:44
Symbol objcProtocol(llvm::StringRef Name)
Symbol objcClass(llvm::StringRef Name)
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)
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:552
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)
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:96
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::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition Function.h:28
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
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:571
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.
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
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
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition Path.h:29
@ No
Diagnostics must be generated for this snapshot.
Definition TUScheduler.h:55
std::vector< std::string > lookup(const SymbolIndex &I, llvm::ArrayRef< SymbolID > IDs)
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.
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.
Definition Protocol.h:1310
@ Snippet
The primary text to be inserted is treated as a snippet.
Definition Protocol.h:1320
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
cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccessCheck P
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Signals derived from a valid AST of a file.
Definition ASTSignals.h:27
llvm::DenseMap< SymbolID, unsigned > ReferencedSymbols
Number of occurrences of each symbol present in the file.
Definition ASTSignals.h:29
Symbol::IncludeDirective InsertionDirective
Preferred preprocessor directive to use for inclusions by the file.
Definition ASTSignals.h:34
Represents a collection of completion items to be presented in the editor.
Definition Protocol.h:1412
Settings that express user/project preferences and control clangd behavior.
Definition Config.h:44
static clangd::Key< Config > Key
Context key which can be used to set the current Config.
Definition Config.h:48
@ None
nothing, no argument list and also NO Delimiters "()" or "<>".
Definition Config.h:141
@ Delimiters
empty pair of delimiters "()" or "<>".
Definition Config.h:145
@ OpenDelimiter
open, only opening delimiter "(" or "<".
Definition Config.h:143
Same semantics as CodeComplete::Score.
Definition Quality.h:179
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
Information required to run clang, e.g. to parse AST or do code completion.
Definition Compiler.h:49
int line
Line position in a document (zero-based).
Definition Protocol.h:158
int character
Character offset on a line in a document (zero-based).
Definition Protocol.h:163
Position end
The range's end position.
Definition Protocol.h:190
Represents the signature of a callable.
Definition Protocol.h:1456
Attributes of a symbol that affect how much we like it.
Definition Quality.h:56
Attributes of a symbol-query pair that affect how much we like it.
Definition Quality.h:86
The class presents a C++ symbol, e.g.
Definition Symbol.h:39
@ 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
std::vector< std::string > ExtraArgs
Definition TestTU.h:60
std::string Code
Definition TestTU.h:49
static TestTU withHeaderCode(llvm::StringRef HeaderCode)
Definition TestTU.h:42
static TestTU withCode(llvm::StringRef Code)
Definition TestTU.h:36
llvm::StringMap< std::string > AdditionalFiles
Definition TestTU.h:57
std::unique_ptr< SymbolIndex > index() const
Definition TestTU.cpp:176
Range range
The range of the text document to be manipulated.
Definition Protocol.h:246