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