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