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