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