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>
48using ::testing::AllOf;
49using ::testing::Contains;
50using ::testing::ElementsAre;
51using ::testing::Field;
52using ::testing::HasSubstr;
53using ::testing::IsEmpty;
55using ::testing::UnorderedElementsAre;
56using ContextKind = CodeCompletionContext::Kind;
59MATCHER_P(named, Name,
"") {
return arg.Name == Name; }
60MATCHER_P(mainFileRefs, Refs,
"") {
return arg.MainFileRefs == Refs; }
61MATCHER_P(scopeRefs, Refs,
"") {
return arg.ScopeRefsInFile == Refs; }
63 return llvm::StringRef(arg.Name).starts_with(Prefix);
65MATCHER_P(filterText, F,
"") {
return arg.FilterText == F; }
66MATCHER_P(scope, S,
"") {
return arg.Scope == S; }
67MATCHER_P(qualifier, Q,
"") {
return arg.RequiredQualifier == Q; }
69 return arg.RequiredQualifier + arg.Name + arg.Signature ==
Label;
72MATCHER_P(kind, K,
"") {
return arg.Kind == K; }
74 return arg.Documentation && arg.Documentation->asPlainText() ==
D;
76MATCHER_P(returnType, D,
"") {
return arg.ReturnType ==
D; }
78 return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader;
80MATCHER_P(insertInclude, IncludeHeader,
"") {
81 return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader &&
82 bool(arg.Includes[0].Insertion);
84MATCHER_P(insertIncludeText, InsertedText,
"") {
85 return !arg.Includes.empty() && arg.Includes[0].Insertion &&
86 arg.Includes[0].Insertion->newText == InsertedText;
89 return !arg.Includes.empty() && bool(arg.Includes[0].Insertion);
92MATCHER_P(origin, OriginSet,
"") {
return arg.Origin == OriginSet; }
93MATCHER_P(signature, S,
"") {
return arg.Signature == S; }
95 return arg.CompletionTokenRange ==
Range;
99Matcher<const std::vector<CodeCompletion> &> has(std::string Name) {
100 return Contains(named(std::move(Name)));
102Matcher<const std::vector<CodeCompletion> &> has(std::string Name,
104 return Contains(AllOf(named(std::move(Name)), kind(K)));
106MATCHER(isDocumented,
"") {
return arg.Documentation.has_value(); }
107MATCHER(deprecated,
"") {
return arg.Deprecated; }
109std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol>
Symbols) {
111 for (
const auto &Sym :
Symbols)
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();
129 auto Inputs = TU.inputs(FS);
133 ADD_FAILURE() <<
"Couldn't build CompilerInvocation";
143CodeCompleteResult completions(llvm::StringRef
Text,
144 std::vector<Symbol> IndexSymbols = {},
145 clangd::CodeCompleteOptions Opts = {},
146 PathRef FilePath =
"foo.cpp") {
150 TU.Filename = FilePath.str();
151 return completions(TU, Test.point(), std::move(IndexSymbols),
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();
169 ParseInputs ParseInput{tooling::CompileCommand(), &FS, Test.code().str()};
170 return codeComplete(FilePath, Test.point(),
nullptr, ParseInput,
179#if CLANGD_DECISION_FOREST
180TEST(DecisionForestRankingModel, NameMatchSanityTest) {
181 clangd::CodeCompleteOptions Opts;
182 Opts.RankingModel = CodeCompleteOptions::DecisionForest;
183 auto Results = completions(
187 int AlphaBetaGamma();
189int func() { MemberAccess().ABG^ }
192 EXPECT_THAT(Results.Completions,
193 ElementsAre(named(
"ABG"), named(
"AlphaBetaGamma")));
196TEST(DecisionForestRankingModel, ReferencesAffectRanking) {
197 clangd::CodeCompleteOptions Opts;
198 Opts.RankingModel = CodeCompleteOptions::DecisionForest;
199 constexpr int NumReferences = 100000;
201 completions(
"int main() { clang^ }",
202 {
ns(
"clangA"), withReferences(NumReferences,
func(
"clangD"))},
205 ElementsAre(named(
"clangD"), named(
"clangA")));
207 completions(
"int main() { clang^ }",
208 {withReferences(NumReferences,
ns(
"clangA")),
func(
"clangD")},
211 ElementsAre(named(
"clangA"), named(
"clangD")));
215TEST(DecisionForestRankingModel, DecisionForestScorerCallbackTest) {
216 clangd::CodeCompleteOptions Opts;
217 constexpr float MagicNumber = 1234.5678f;
218 Opts.RankingModel = CodeCompleteOptions::DecisionForest;
222 Scores.
Total = MagicNumber;
223 Scores.ExcludingName = MagicNumber;
226 llvm::StringRef Code =
"int func() { int xyz; xy^ }";
227 auto Results = completions(Code,
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);
234 Opts.RankingModel = CodeCompleteOptions::Heuristics;
235 Results = completions(Code,
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);
242TEST(CompletionTest, Limit) {
243 clangd::CodeCompleteOptions Opts;
245 auto Results = completions(R
"cpp(
246struct ClassWithMembers {
252int main() { ClassWithMembers().^ }
256 EXPECT_TRUE(Results.HasMore);
257 EXPECT_THAT(Results.Completions, ElementsAre(named(
"AAA"), named(
"BBB")));
260TEST(CompletionTest, Filter) {
261 std::string Body = R
"cpp(
272 EXPECT_THAT(completions(Body +
"int main() { S().Foba^ }").Completions,
273 AllOf(has(
"FooBar"), has(
"FooBaz"), Not(has(
"Qux"))));
277 Sym.SymInfo.Kind = index::SymbolKind::Macro;
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")));
285void testAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
286 auto Results = completions(
292 // Make sure this is not in preamble.
295 struct GlobalClass {};
297 struct ClassWithMembers {
307 struct LocalClass {};
315 {
cls(
"IndexClass"),
var(
"index_var"),
func(
"index_func")}, Opts);
317 EXPECT_TRUE(Results.RanParser);
320 EXPECT_THAT(Results.Completions,
321 AllOf(has(
"method"), has(
"field"), Not(has(
"ClassWithMembers")),
322 Not(has(
"operator=")), Not(has(
"~ClassWithMembers"))));
323 EXPECT_IFF(Opts.IncludeIneligibleResults, Results.Completions,
324 has(
"private_field"));
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"))));
333 EXPECT_THAT(Results.Completions,
336 EXPECT_THAT(Results.Completions, Contains(isDocumented()));
339void testGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
340 auto Results = completions(
345 // Make sure this is not in preamble.
348 struct GlobalClass {};
350 struct ClassWithMembers {
356 struct LocalClass {};
364 {
cls(
"IndexClass"),
var(
"index_var"),
func(
"index_func")}, Opts);
366 EXPECT_TRUE(Results.RanParser);
368 EXPECT_THAT(Results.Completions,
369 Not(AnyOf(has(
"method"), has(
"method()"), has(
"field"))));
371 EXPECT_THAT(Results.Completions,
372 AllOf(has(
"global_var"), has(
"index_var"), has(
"global_func"),
374 has(
"GlobalClass"), has(
"IndexClass")));
376 EXPECT_THAT(Results.Completions, has(
"MACRO"));
378 EXPECT_THAT(Results.Completions,
379 AllOf(has(
"local_var"), has(
"LocalClass"),
382 EXPECT_THAT(Results.Completions, Contains(isDocumented()));
385TEST(CompletionTest, CompletionOptions) {
386 auto Test = [&](
const clangd::CodeCompleteOptions &Opts) {
387 testAfterDotCompletion(Opts);
388 testGlobalScopeCompletion(Opts);
392 &clangd::CodeCompleteOptions::IncludeIneligibleResults,
397 for (
auto &F : Flags) {
398 clangd::CodeCompleteOptions O;
404TEST(CompletionTest, Accessible) {
405 auto Internal = completions(R
"cpp(
408 protected: void prot();
409 private: void priv();
411 void Foo::pub() { this->^ }
413 EXPECT_THAT(Internal.Completions,
414 AllOf(has("priv"), has(
"prot"), has(
"pub")));
416 auto External = completions(R
"cpp(
419 protected: void prot();
420 private: void priv();
427 EXPECT_THAT(External.Completions,
428 AllOf(has("pub"), Not(has(
"prot")), Not(has(
"priv"))));
430 auto Results = completions(R
"cpp(
433 protected: void prot();
434 private: void priv();
436 struct Bar : public Foo {
437 private: using Foo::pub;
444 EXPECT_THAT(Results.Completions,
445 AllOf(Not(has("priv")), Not(has(
"prot")), Not(has(
"pub"))));
448TEST(CompletionTest, Qualifiers) {
449 auto Results = completions(R
"cpp(
451 public: int foo() const;
454 class Bar : public Foo {
457 void test() { Bar().^ }
459 EXPECT_THAT(Results.Completions,
460 Contains(AllOf(qualifier(""), named(
"bar"))));
462 EXPECT_THAT(Results.Completions,
463 Not(Contains(AllOf(qualifier(
"Foo::"), named(
"foo")))));
465 EXPECT_THAT(Results.Completions,
466 Not(Contains(AllOf(qualifier(
""), named(
"foo")))));
470TEST(CompletionTest, QualificationWithInlineNamespace) {
471 auto Results = completions(R
"cpp(
472 namespace a { inline namespace b {} }
473 using namespace a::b;
477 EXPECT_THAT(Results.Completions,
478 UnorderedElementsAre(AllOf(qualifier(
"a::"), named(
"Foo"))));
481TEST(CompletionTest, InjectedTypename) {
483 EXPECT_THAT(completions(
"struct X{}; void foo(){ X().^ }").Completions,
485 EXPECT_THAT(completions(
"struct X{ void foo(){ this->^ } };").Completions,
488 EXPECT_THAT(completions(
"struct X{ void foo(){ ^ } };").Completions,
491 completions(
"struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions,
495 "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };")
499 EXPECT_THAT(completions(
"struct X{}; void foo(){ X::^ }").Completions,
503TEST(CompletionTest, SkipInjectedWhenUnqualified) {
504 EXPECT_THAT(completions(
"struct X { void f() { X^ }};").Completions,
505 ElementsAre(named(
"X"), named(
"~X")));
508TEST(CompletionTest, Snippets) {
509 clangd::CodeCompleteOptions Opts;
510 auto Results = completions(
514 int f(int i, const float f) const;
525 snippetSuffix(
"(${1:int i}, ${2:const float f})")));
528TEST(CompletionTest, HeuristicsForMemberFunctionCompletion) {
529 clangd::CodeCompleteOptions Opts;
530 Opts.EnableSnippets =
true;
534 static int staticMethod(int);
535 int method(int) const;
536 template <typename T, typename U, typename V = int>
538 template <typename T, int U>
539 static T staticGeneric();
547 struct Derived : Foo {
560 ; // Prevent parsing as 'f.f'
566 d.Derived::$canBeCall^
574 ; // Prevent parsing as 'f.f'
580 d.Derived::$canBeCall^
585 for (
const auto &P : Code.points(
"canNotBeCall")) {
586 auto Results = completions(TU, P, {}, Opts);
587 EXPECT_THAT(Results.Completions,
588 Contains(AllOf(named(
"method"), signature(
"(int) const"),
589 snippetSuffix(
""))));
594 Contains(AllOf(named(
"generic"),
595 signature(
"<typename T, typename U>(U, V)"),
596 snippetSuffix(
"<${1:typename T}, ${2:typename U}>"))));
599 for (
const auto &P : Code.points(
"canBeCall")) {
600 auto Results = completions(TU, P, {}, Opts);
601 EXPECT_THAT(Results.Completions,
602 Contains(AllOf(named(
"method"), signature(
"(int) const"),
603 snippetSuffix(
"(${1:int})"))));
606 Contains(AllOf(named(
"generic"), signature(
"<typename T>(U, V)"),
607 snippetSuffix(
"<${1:typename T}>(${2:U}, ${3:V})"))));
611 for (
const auto &P : Code.points()) {
612 auto Results = completions(TU, P, {}, Opts);
613 EXPECT_THAT(Results.Completions,
614 Contains(AllOf(named(
"staticMethod"), signature(
"(int)"),
615 snippetSuffix(
"(${1:int})"))));
616 EXPECT_THAT(Results.Completions,
618 named(
"staticGeneric"), signature(
"<typename T, int U>()"),
619 snippetSuffix(
"<${1:typename T}, ${2:int U}>()"))));
623TEST(CompletionTest, NoSnippetsInUsings) {
624 clangd::CodeCompleteOptions Opts;
625 Opts.EnableSnippets =
true;
626 auto Results = completions(
629 int func(int a, int b);
635 EXPECT_THAT(Results.Completions,
636 ElementsAre(AllOf(named(
"func"), labeled(
"func(int a, int b)"),
637 snippetSuffix(
""))));
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";
645 Results = completions(R
"cpp(
650 EXPECT_THAT(Results.Completions,
651 ElementsAre(AllOf(named(
"func"), labeled(
"func(int a, int b)"),
652 snippetSuffix(
""))));
655 Opts.AllScopes =
true;
656 Results = completions(R
"cpp(
660 EXPECT_THAT(Results.Completions,
661 Contains(AllOf(named(
"func"), labeled(
"ns::func(int a, int b)"),
662 snippetSuffix(
""))));
665TEST(CompletionTest, Kinds) {
666 auto Results = completions(
671 // make sure MACRO is not included in preamble.
675 {func("indexFunction"),
var(
"indexVariable"),
cls(
"indexClass"),
676 macro(
"indexObjMacro"),
macro(
"indexFuncMacro",
"(x, y)")});
677 EXPECT_THAT(Results.Completions,
689 Results = completions(
"nam^");
690 EXPECT_THAT(Results.Completions,
694 Results = completions(
708 Results = completions(
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;
716 template <class T> static int complete_static_member = 10;
718 static auto x = complete_^
723 UnorderedElementsAre(
726 AllOf(named(
"complete_type_alias"),
729 AllOf(named(
"complete_static_member"),
732 Results = completions(
744TEST(CompletionTest, NoDuplicates) {
745 auto Results = completions(
757 EXPECT_THAT(Results.Completions, ElementsAre(named(
"Adapter")));
760TEST(CompletionTest, ScopedNoIndex) {
761 auto Results = completions(
763 namespace fake { int BigBang, Babble, Box; };
764 int main() { fake::ba^ }
767 EXPECT_THAT(Results.Completions,
768 ElementsAre(named(
"Babble"), named(
"BigBang")));
771TEST(CompletionTest, Scoped) {
772 auto Results = completions(
774 namespace fake { int Babble, Box; };
775 int main() { fake::ba^ }
777 {var("fake::BigBang")});
778 EXPECT_THAT(Results.Completions,
779 ElementsAre(named(
"Babble"), named(
"BigBang")));
782TEST(CompletionTest, ScopedWithFilter) {
783 auto Results = completions(
787 {cls("ns::XYZ"),
func(
"ns::foo")});
788 EXPECT_THAT(Results.Completions, UnorderedElementsAre(named(
"XYZ")));
791TEST(CompletionTest, ReferencesAffectRanking) {
792 EXPECT_THAT(completions(
"int main() { abs^ }", {
func(
"absA"),
func(
"absB")})
795 EXPECT_THAT(completions(
"int main() { abs^ }",
796 {
func(
"absA"), withReferences(1000,
func(
"absB"))})
801TEST(CompletionTest, ContextWords) {
802 auto Results = completions(R
"cpp(
803 enum class Color { RED, YELLOW, BLUE };
805 // (blank lines so the definition above isn't "context")
807 // "It was a yellow car," he said. "Big yellow car, new."
808 auto Finish = Color::^
812 ASSERT_THAT(Results.Completions,
816TEST(CompletionTest, GlobalQualified) {
817 auto Results = completions(
822 EXPECT_THAT(Results.Completions,
827TEST(CompletionTest, FullyQualified) {
828 auto Results = completions(
830 namespace ns { void bar(); }
834 EXPECT_THAT(Results.Completions,
839TEST(CompletionTest, SemaIndexMerge) {
840 auto Results = completions(
842 namespace ns { int local; void both(); }
845 {func("ns::both"),
cls(
"ns::Index")});
847 EXPECT_THAT(Results.Completions,
848 UnorderedElementsAre(
855TEST(CompletionTest, SemaIndexMergeWithLimit) {
856 clangd::CodeCompleteOptions Opts;
858 auto Results = completions(
860 namespace ns { int local; void both(); }
863 {func("ns::both"),
cls(
"ns::Index")}, Opts);
864 EXPECT_EQ(Results.Completions.size(), Opts.Limit);
865 EXPECT_TRUE(Results.HasMore);
868TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
871 TU.AdditionalFiles[
"sub/bar.h"] =
"";
875 Sym.CanonicalDeclaration.FileURI = BarURI.c_str();
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\""))));
886 Results = completions(TU, Test.point(), {Sym}, NoInsertion);
887 EXPECT_THAT(Results.Completions,
888 ElementsAre(AllOf(named(
"X"), Not(insertInclude()))));
891 #include "sub/bar.h" // not shortest, so should only match resolved.
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()))));
900TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {
903 std::string BarHeader =
testPath(
"bar.h");
905 SymX.CanonicalDeclaration.FileURI = BarURI.c_str();
906 SymY.CanonicalDeclaration.FileURI = BarURI.c_str();
910 auto Results = completions(R
"cpp(
918 EXPECT_THAT(Results.Completions,
919 ElementsAre(AllOf(named("X"), Not(insertInclude())),
920 AllOf(named(
"Y"), Not(insertInclude()))));
923TEST(CompletionTest, IncludeInsertionRespectsQuotedAngledConfig) {
926 TU.AdditionalFiles[
"sub/bar.h"] =
"";
930 Sym.CanonicalDeclaration.FileURI = BarURI.c_str();
933 TU.Code = Test.code().str();
934 auto Results = completions(TU, Test.point(), {Sym});
936 EXPECT_THAT(Results.Completions,
937 ElementsAre(AllOf(named(
"X"), insertInclude(
"\"bar.h\""))));
940 C.Style.AngledHeaders.push_back(
941 [](
auto header) {
return header.contains(
"bar.h"); });
943 Results = completions(TU, Test.point(), {Sym});
944 EXPECT_THAT(Results.Completions,
945 ElementsAre(AllOf(named(
"X"), insertInclude(
"<bar.h>"))));
949 C.Style.QuotedHeaders.push_back(
950 [](
auto header) {
return header.contains(
"bar.h"); });
952 Results = completions(TU, Test.point(), {Sym});
953 EXPECT_THAT(Results.Completions,
954 ElementsAre(AllOf(named(
"X"), insertInclude(
"\"bar.h\""))));
958TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
961 namespace ns { int local; }
963 void f2() { ns::preamble().$2^; }
966 TU.AdditionalFiles[
"bar.h"] =
967 R
"cpp(namespace ns { struct preamble { int member; }; })cpp";
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")));
978 Opts.Index =
nullptr;
979 auto WithoutIndex = completions(TU, Test.point(), {}, Opts);
980 EXPECT_THAT(WithoutIndex.Completions,
981 UnorderedElementsAre(named(
"local"), named(
"preamble")));
988TEST(CompletionTest, CompletionInPreamble) {
989 auto Results = completions(R
"cpp(
997 EXPECT_THAT(Results, ElementsAre(named("ifndef")));
1000TEST(CompletionTest, CompletionRecoveryASTType) {
1001 auto Results = completions(R
"cpp(
1002 struct S { int member; };
1005 // No overload matches, but we have recovery-expr with the correct type.
1009 EXPECT_THAT(Results, ElementsAre(named("member")));
1012TEST(CompletionTest, DynamicIndexIncludeInsertion) {
1016 Opts.BuildDynamicSymbolIndex =
true;
1019 FS.Files[
testPath(
"foo_header.h")] = R
"cpp(
1026 const std::string FileContent(R
"cpp(
1027 #include "foo_header.h"
1032 Server.addDocument(testPath("foo_impl.cpp"), FileContent);
1034 ASSERT_TRUE(Server.blockUntilIdleForTest());
1043 ElementsAre(AllOf(named(
"Foo"), hasInclude(
"\"foo_header.h\""),
1047TEST(CompletionTest, DynamicIndexMultiFile) {
1051 Opts.BuildDynamicSymbolIndex =
true;
1054 FS.Files[
testPath(
"foo.h")] = R
"cpp(
1055 namespace ns { class XYZ {}; void foo(int x) {} }
1078 EXPECT_THAT(Results.Completions,
1080 doc(
"Doooc"), returnType(
"void"))));
1083TEST(CompletionTest, Documentation) {
1084 auto Results = completions(
1086 // Non-doxygen comment.
1087 __attribute__((annotate("custom_annotation"))) int foo();
1099 Results.Completions,
1102 doc(
"Annotation: custom_annotation\n\nNon-doxygen comment."))));
1104 Results.Completions,
1105 Contains(AllOf(named(
"bar"), doc(
"Doxygen comment.\n\\param int a"))));
1106 EXPECT_THAT(Results.Completions,
1107 Contains(AllOf(named(
"baz"), doc(
"Multi-line block comment"))));
1110TEST(CompletionTest, CommentsFromSystemHeaders) {
1115 Opts.BuildDynamicSymbolIndex =
true;
1119 FS.Files[
testPath(
"foo.h")] = R
"cpp(
1120 #pragma GCC system_header
1122 // This comment should be retained!
1137 Contains(AllOf(named(
"foo"), doc(
"This comment should be retained!"))));
1140TEST(CompletionTest, CommentsOnMembersFromHeader) {
1145 Opts.BuildDynamicSymbolIndex =
true;
1149 FS.Files[
testPath(
"foo.h")] = R
"cpp(
1158 template <typename T>
1181 Contains(AllOf(named(
"gamma"), doc(
"This is a member field."))));
1184 Contains(AllOf(named(
"delta"), doc(
"This is a member function."))));
1190 Contains(AllOf(named(
"omega")
1194 Contains(AllOf(named(
"epsilon"),
1195 doc(
"This is a member function inside a template."))));
1198TEST(CompletionTest, CommentsOnMembersFromHeaderOverloadBundling) {
1199 using testing::AnyOf;
1204 Opts.BuildDynamicSymbolIndex =
true;
1208 FS.Files[
testPath(
"foo.h")] = R
"cpp(
1216 void epsilon(long l);
1219 void epsilon(int i);
1230 clangd::CodeCompleteOptions CCOpts;
1231 CCOpts.BundleOverloads = true;
1237 Contains(AllOf(named(
"epsilon"), doc(
"This one has a comment."))));
1239 Contains(AllOf(named(
"delta"), AnyOf(doc(
"bool overload."),
1240 doc(
"int overload.")))));
1243TEST(CompletionTest, GlobalCompletionFiltering) {
1252 auto Results = completions(R
"(// void f() {
1256 EXPECT_THAT(Results.Completions, IsEmpty());
1259TEST(CodeCompleteTest, DisableTypoCorrection) {
1260 auto Results = completions(R
"cpp(
1261 namespace clang { int v; }
1262 void f() { clangd::^
1264 EXPECT_TRUE(Results.Completions.empty());
1267TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
1268 auto Results = completions(R
"cpp(
1275 EXPECT_THAT(Results.Completions, Contains(labeled("clang")));
1276 EXPECT_THAT(Results.Completions, Not(Contains(labeled(
"clang::"))));
1279TEST(CompletionTests, EmptySnippetDoesNotCrash) {
1281 auto Results = completions(R
"cpp(
1283 auto w = [&](auto &&f) { return f(f); };
1284 auto f = w([&](auto &&f) {
1285 return [&](auto &&n) {
1289 return n * ^(f)(n - 1);
1296TEST(CompletionTest, Issue1427Crash) {
1302 Opts.MainFileSignals = &MainFileSignals;
1311TEST(CompletionTest, BacktrackCrashes) {
1313 auto Results = completions(R
"cpp(
1315 struct FooBarBaz {};
1321 EXPECT_THAT(Results.Completions, ElementsAre(labeled("FooBarBaz")));
1325 struct FooBarBaz {};
1327 if (FooBarBaz * x^) {}
1332TEST(CompletionTest, CompleteInMacroWithStringification) {
1333 auto Results = completions(R
"cpp(
1334void f(const char *, int x);
1335#define F(x) f(#x, x)
1342int f(int input_num) {
1347 EXPECT_THAT(Results.Completions,
1348 UnorderedElementsAre(named("X"), named(
"Y")));
1351TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
1352 auto Results = completions(R
"cpp(
1353void f(const char *, int x);
1354#define F(x) f(#x, x)
1359int f(int input_num) {
1365 EXPECT_THAT(Results.Completions, Contains(named("X")));
1368TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
1369 auto Results = completions(R
"cpp(
1370 int bar(int param_in_bar) {
1373 int foo(int param_in_foo) {
1375 // In recovery mode, "param_in_foo" will also be suggested among many other
1376 // unrelated symbols; however, this is really a special case where this works.
1377 // If the #if block is outside of the function, "param_in_foo" is still
1378 // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't
1379 // really provide useful results in excluded branches.
1385 EXPECT_TRUE(Results.Completions.empty());
1388TEST(CompletionTest, DefaultArgs) {
1389 clangd::CodeCompleteOptions Opts;
1392 int Y(int A, int B = 0);
1393 int Z(int A, int B = 0, int C = 0, int D = 0);
1395 EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions,
1396 UnorderedElementsAre(labeled(
"X(int A = 0)")));
1397 EXPECT_THAT(completions(
Context +
"int y = Y^", {}, Opts).Completions,
1398 UnorderedElementsAre(AllOf(labeled(
"Y(int A, int B = 0)"),
1399 snippetSuffix(
"(${1:int A})"))));
1400 EXPECT_THAT(completions(
Context +
"int y = Z^", {}, Opts).Completions,
1401 UnorderedElementsAre(
1402 AllOf(labeled(
"Z(int A, int B = 0, int C = 0, int D = 0)"),
1403 snippetSuffix(
"(${1:int A})"))));
1406TEST(CompletionTest, NoCrashWithTemplateParamsAndPreferredTypes) {
1407 auto Completions = completions(R
"cpp(
1408template <template <class> class TT> int foo() {
1413 EXPECT_THAT(Completions, Contains(named("TT")));
1416TEST(CompletionTest, NestedTemplateHeuristics) {
1417 auto Completions = completions(R
"cpp(
1418struct Plain { int xxx; };
1419template <typename T> class Templ { Plain ppp; };
1420template <typename T> void foo(Templ<T> &t) {
1421 // Formally ppp has DependentTy, because Templ may be specialized.
1422 // However we sholud be able to see into it using the primary template.
1427 EXPECT_THAT(Completions, Contains(named("xxx")));
1430TEST(CompletionTest, RecordCCResultCallback) {
1431 std::vector<CodeCompletion> RecordedCompletions;
1433 Opts.RecordCCResult = [&RecordedCompletions](
const CodeCompletion &CC,
1437 RecordedCompletions.push_back(CC);
1440 completions(
"int xy1, xy2; int a = xy^", {}, Opts);
1441 EXPECT_THAT(RecordedCompletions,
1442 UnorderedElementsAre(named(
"xy1"), named(
"xy2")));
1448 unsigned MainFileRefs;
1449 unsigned ScopeRefsInFile;
1452 std::vector<Completion> RecordedCompletions;
1453 Opts.RecordCCResult = [&RecordedCompletions](
const CodeCompletion &CC,
1457 RecordedCompletions.push_back({CC.Name, R.MainFileRefs, R.ScopeRefsInFile});
1461 MainFileSignals.ReferencedSymbols[
var(
"xy2").
ID] = 1;
1462 MainFileSignals.ReferencedSymbols[
var(
"xyindex").
ID] = 10;
1463 MainFileSignals.RelatedNamespaces[
"tar::"] = 5;
1464 MainFileSignals.RelatedNamespaces[
"bar::"] = 3;
1465 Opts.MainFileSignals = &MainFileSignals;
1466 Opts.AllScopes =
true;
1476 {
var(
"xyindex"),
var(
"tar::xytar"),
var(
"bar::xybar")},
1478 EXPECT_THAT(RecordedCompletions,
1479 UnorderedElementsAre(
1480 AllOf(named(
"xy1"), mainFileRefs(3u), scopeRefs(0u)),
1481 AllOf(named(
"xy2"), mainFileRefs(1u), scopeRefs(0u)),
1482 AllOf(named(
"xyindex"), mainFileRefs(10u), scopeRefs(0u)),
1483 AllOf(named(
"xytar"), mainFileRefs(0u), scopeRefs(5u)),
1484 AllOf( named(
"xybar"),
1485 mainFileRefs(0u), scopeRefs(3u))));
1490 std::vector<Symbol> IndexSymbols = {},
1492 std::unique_ptr<SymbolIndex> Index;
1493 if (!IndexSymbols.empty())
1494 Index = memIndex(IndexSymbols);
1498 auto Inputs = TU.inputs(FS);
1499 Inputs.Index = Index.get();
1503 ADD_FAILURE() <<
"Couldn't build CompilerInvocation";
1509 ADD_FAILURE() <<
"Couldn't build Preamble";
1513 DocumentationFormat);
1517signatures(llvm::StringRef
Text, std::vector<Symbol> IndexSymbols = {},
1520 return signatures(Test.code(), Test.point(), std::move(IndexSymbols),
1521 DocumentationFormat);
1524struct ExpectedParameter {
1526 std::pair<unsigned, unsigned> Offsets;
1528llvm::raw_ostream &
operator<<(llvm::raw_ostream &OS,
1529 const ExpectedParameter &P) {
1530 return OS <<
P.Text;
1533 if (
P.size() != arg.parameters.size())
1535 for (
unsigned I = 0; I <
P.size(); ++I) {
1536 if (P[I].
Text != arg.parameters[I].labelString ||
1537 P[I].Offsets != arg.parameters[I].labelOffsets)
1542MATCHER_P(sigDoc, doc,
"") {
return arg.documentation.value == doc; }
1546Matcher<SignatureInformation> sig(llvm::StringRef AnnotatedLabel) {
1547 llvm::Annotations
A(AnnotatedLabel);
1548 std::string
Label = std::string(
A.code());
1549 std::vector<ExpectedParameter> Parameters;
1550 for (
auto Range :
A.ranges()) {
1551 Parameters.emplace_back();
1553 ExpectedParameter &
P = Parameters.back();
1558 return AllOf(sigHelpLabeled(
Label), paramsAre(Parameters));
1561TEST(SignatureHelpTest, Overloads) {
1562 auto Results = signatures(R
"cpp(
1563 void foo(int x, int y);
1564 void foo(int x, float y);
1565 void foo(float x, int y);
1566 void foo(float x, float y);
1567 void bar(int x, int y = 0);
1568 int main() { foo(^); }
1570 EXPECT_THAT(Results.signatures,
1571 UnorderedElementsAre(sig("foo([[float x]], [[float y]]) -> void"),
1572 sig(
"foo([[float x]], [[int y]]) -> void"),
1573 sig(
"foo([[int x]], [[float y]]) -> void"),
1574 sig(
"foo([[int x]], [[int y]]) -> void")));
1576 EXPECT_EQ(0, Results.activeSignature);
1577 EXPECT_EQ(0, Results.activeParameter);
1580TEST(SignatureHelpTest, FunctionPointers) {
1581 llvm::StringLiteral Tests[] = {
1584 void (*foo)(int x, int y);
1585 int main() { foo(^); }
1589 void (__stdcall *foo)(int x, int y);
1590 int main() { foo(^); }
1594 void (__attribute__(stdcall) *foo)(int x, int y);
1595 int main() { foo(^); },
1599 typedef void (*fn)(int x, int y);
1601 int main() { foo(^); }
1605 typedef void (__stdcall *fn)(int x, int y);
1607 int main() { foo(^); }
1612 void (*foo)(int x, int y);
1615 int main() { s.foo(^); }
1619 typedef void (*fn)(int x, int y);
1624 int main() { s.foo(^); }
1626 for (
auto Test : Tests)
1627 EXPECT_THAT(signatures(Test).signatures,
1628 UnorderedElementsAre(sig(
"([[int x]], [[int y]]) -> void")));
1631TEST(SignatureHelpTest, Constructors) {
1632 std::string Top = R
"cpp(
1635 S(const S &) = delete;
1639 auto CheckParenInit = [&](std::string Init) {
1640 EXPECT_THAT(signatures(Top + Init).signatures,
1641 UnorderedElementsAre(sig(
"S([[int]])")))
1644 CheckParenInit(
"S s(^);");
1645 CheckParenInit(
"auto s = S(^);");
1646 CheckParenInit(
"auto s = new S(^);");
1648 auto CheckBracedInit = [&](std::string Init) {
1649 EXPECT_THAT(signatures(Top + Init).signatures,
1650 UnorderedElementsAre(sig(
"S{[[int]]}")))
1653 CheckBracedInit(
"S s{^};");
1654 CheckBracedInit(
"S s = {^};");
1655 CheckBracedInit(
"auto s = S{^};");
1658 CheckBracedInit(
"int x(S); int i = x({^});");
1661TEST(SignatureHelpTest, Aggregates) {
1662 std::string Top = R
"cpp(
1667 auto AggregateSig = sig(
"S{[[int a]], [[int b]], [[int c]], [[int d]]}");
1668 EXPECT_THAT(signatures(Top +
"S s{^}").signatures,
1669 UnorderedElementsAre(AggregateSig, sig(
"S{}"),
1670 sig(
"S{[[const S &]]}"),
1671 sig(
"S{[[S &&]]}")));
1672 EXPECT_THAT(signatures(Top +
"S s{1,^}").signatures,
1673 ElementsAre(AggregateSig));
1674 EXPECT_EQ(signatures(Top +
"S s{1,^}").activeParameter, 1);
1675 EXPECT_THAT(signatures(Top +
"S s{.c=3,^}").signatures,
1676 ElementsAre(AggregateSig));
1677 EXPECT_EQ(signatures(Top +
"S s{.c=3,^}").activeParameter, 3);
1680TEST(SignatureHelpTest, OverloadInitListRegression) {
1681 auto Results = signatures(R
"cpp(
1690 EXPECT_THAT(Results.signatures, UnorderedElementsAre(sig("f() -> void")));
1693TEST(SignatureHelpTest, DefaultArgs) {
1694 auto Results = signatures(R
"cpp(
1695 void bar(int x, int y = 0);
1696 void bar(float x = 0, int y = 42);
1699 EXPECT_THAT(Results.signatures,
1700 UnorderedElementsAre(
1701 sig("bar([[int x]], [[int y = 0]]) -> void"),
1702 sig(
"bar([[float x = 0]], [[int y = 42]]) -> void")));
1703 EXPECT_EQ(0, Results.activeSignature);
1704 EXPECT_EQ(0, Results.activeParameter);
1707TEST(SignatureHelpTest, ActiveArg) {
1708 auto Results = signatures(R
"cpp(
1709 int baz(int a, int b, int c);
1710 int main() { baz(baz(1,2,3), ^); }
1712 EXPECT_THAT(Results.signatures,
1713 ElementsAre(sig("baz([[int a]], [[int b]], [[int c]]) -> int")));
1714 EXPECT_EQ(0, Results.activeSignature);
1715 EXPECT_EQ(1, Results.activeParameter);
1718TEST(SignatureHelpTest, OpeningParen) {
1719 llvm::StringLiteral Tests[] = {
1722 int foo(int a, int b, int c);
1724 foo(foo $p^( foo(10, 10, 10), ^ )));
1729 Foo(int a, int b, int c);
1737 Foo(int a, int b, int c);
1740 new Foo $p^( 10, ^ );
1744 int foo(int a, int b, int c);
1748 // Macro expansions.
1753 int foo(int a, int b, int c);
1756 // FIXME: figure out why ID(foo (foo(10), )) doesn't work when preserving
1757 // the recovery expression.
1758 ID(foo $p^( 10, ^ ))
1762 int foo(int a, int b);
1763 template <typename T> void bar(T t) {
1768 template <typename T>
1770 template <typename T> void bar(T t) {
1775 struct Foo { int foo(int, int); };
1776 template <typename T> void bar(T t) {
1782 struct Foo { template <typename T> int foo(T, T); };
1783 template <typename T> void bar(T t) {
1789 for (
auto Test : Tests) {
1791 EXPECT_EQ(signatures(Code.code(), Code.point()).argListStart,
1793 <<
"Test source:" << Test;
1797TEST(SignatureHelpTest, StalePreamble) {
1802 auto Inputs = TU.inputs(FS);
1807 ASSERT_TRUE(EmptyPreamble);
1809 TU.AdditionalFiles[
"a.h"] =
"int foo(int x);";
1812 void bar() { foo(^2); })cpp");
1813 TU.Code = Test.code().str();
1817 EXPECT_THAT(Results.signatures, ElementsAre(sig(
"foo([[int x]]) -> int")));
1818 EXPECT_EQ(0, Results.activeSignature);
1819 EXPECT_EQ(0, Results.activeParameter);
1824 IndexRequestCollector(std::vector<Symbol> Syms = {}) : Symbols(Syms) {}
1827 fuzzyFind(
const FuzzyFindRequest &Req,
1828 llvm::function_ref<
void(
const Symbol &)>
Callback)
const override {
1829 std::unique_lock<std::mutex> Lock(Mut);
1830 Requests.push_back(Req);
1831 ReceivedRequestCV.notify_one();
1832 for (
const auto &Sym : Symbols)
1837 void lookup(
const LookupRequest &,
1838 llvm::function_ref<
void(
const Symbol &)>)
const override {}
1840 bool refs(
const RefsRequest &,
1841 llvm::function_ref<
void(
const Ref &)>)
const override {
1846 const ContainedRefsRequest &,
1847 llvm::function_ref<
void(
const ContainedRefsResult &)>)
const override {
1851 void relations(
const RelationsRequest &,
1852 llvm::function_ref<
void(
const SymbolID &,
const Symbol &)>)
1856 reverseRelations(
const RelationsRequest &,
1857 llvm::function_ref<
void(
const SymbolID &,
const Symbol &)>)
1861 indexedFiles()
const override {
1867 size_t estimateMemoryUsage()
const override {
return 0; }
1869 const std::vector<FuzzyFindRequest> consumeRequests(
size_t Num)
const {
1870 std::unique_lock<std::mutex> Lock(Mut);
1872 [
this, Num] {
return Requests.size() == Num; }));
1873 auto Reqs = std::move(Requests);
1879 std::vector<Symbol> Symbols;
1881 mutable std::condition_variable ReceivedRequestCV;
1882 mutable std::mutex Mut;
1883 mutable std::vector<FuzzyFindRequest> Requests;
1887std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code,
1889 clangd::CodeCompleteOptions Opts;
1890 IndexRequestCollector Requests;
1891 Opts.Index = &Requests;
1892 completions(Code, {}, Opts);
1893 const auto Reqs = Requests.consumeRequests(Num);
1894 EXPECT_EQ(Reqs.size(), Num);
1898TEST(CompletionTest, UnqualifiedIdQuery) {
1899 auto Requests = captureIndexRequests(R
"cpp(
1901 using namespace std;
1909 EXPECT_THAT(Requests,
1911 UnorderedElementsAre("",
"ns::",
"std::"))));
1914TEST(CompletionTest, EnclosingScopeComesFirst) {
1915 auto Requests = captureIndexRequests(R
"cpp(
1917 using namespace std;
1929 EXPECT_THAT(Requests,
1932 UnorderedElementsAre("",
"std::",
"nx::ns::",
"nx::"))));
1933 EXPECT_EQ(Requests[0].Scopes[0],
"nx::ns::");
1936TEST(CompletionTest, ResolvedQualifiedIdQuery) {
1937 auto Requests = captureIndexRequests(R
"cpp(
1939 namespace ns2 {} // ignore
1940 namespace ns3 { namespace nns3 {} }
1942 using namespace ns1;
1943 using namespace ns3::nns3;
1952 EXPECT_THAT(Requests,
1955 UnorderedElementsAre("foo::",
"ns1::",
"ns3::nns3::"))));
1958TEST(CompletionTest, UnresolvedQualifierIdQuery) {
1959 auto Requests = captureIndexRequests(R
"cpp(
1969 EXPECT_THAT(Requests,
1972 UnorderedElementsAre("a::bar::",
"ns::bar::",
"bar::"))));
1975TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
1976 auto Requests = captureIndexRequests(R
"cpp(
1987 UnorderedElementsAre("a::bar::"))));
1990TEST(CompletionTest, EmptyQualifiedQuery) {
1991 auto Requests = captureIndexRequests(R
"cpp(
2000 UnorderedElementsAre("",
"ns::"))));
2003TEST(CompletionTest, GlobalQualifiedQuery) {
2004 auto Requests = captureIndexRequests(R
"cpp(
2013 UnorderedElementsAre(""))));
2016TEST(CompletionTest, NoDuplicatedQueryScopes) {
2017 auto Requests = captureIndexRequests(R
"cpp(
2028 EXPECT_THAT(Requests,
2030 UnorderedElementsAre("na::",
"na::nb::",
""))));
2033TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
2034 auto Completions = completions(
2037 int SomeNameOfField;
2038 typedef int SomeNameOfTypedefField;
2042 {func("::SomeNameInTheIndex"),
func(
"::Foo::SomeNameInTheIndex")});
2044 EXPECT_THAT(Completions.Completions,
2045 AllOf(Contains(labeled(
"SomeNameOfField")),
2046 Contains(labeled(
"SomeNameOfTypedefField")),
2047 Not(Contains(labeled(
"SomeNameInTheIndex")))));
2050TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
2052 auto Completions = completions(
2059 {func("::SomeNameInTheIndex")});
2061 EXPECT_THAT(Completions.Completions,
2062 Not(Contains(labeled(
"SomeNameInTheIndex"))));
2066 auto Completions = completions(
2070 T::template Y<int>::^
2073 {func("::SomeNameInTheIndex")});
2075 EXPECT_THAT(Completions.Completions,
2076 Not(Contains(labeled(
"SomeNameInTheIndex"))));
2080 auto Completions = completions(
2087 {func("::SomeNameInTheIndex")});
2089 EXPECT_THAT(Completions.Completions,
2090 Not(Contains(labeled(
"SomeNameInTheIndex"))));
2094TEST(CompletionTest, OverloadBundling) {
2095 clangd::CodeCompleteOptions Opts;
2096 Opts.BundleOverloads =
true;
2100 // Overload with int
2101 int a(int) __attribute__((deprecated("", "")));
2102 // Overload with bool
2114 EXPECT_THAT(completions(
Context +
"int y = X().^", {}, Opts).Completions,
2115 UnorderedElementsAre(labeled(
"a(…)"), labeled(
"b(float)")));
2118 EXPECT_THAT(completions(
Context +
"X z = X^", {}, Opts).Completions,
2119 UnorderedElementsAre(labeled(
"X"), labeled(
"X(…)")));
2124 completions(
Context +
"int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
2125 UnorderedElementsAre(labeled(
"GFuncC(…)"), labeled(
"GFuncD(int)")));
2129 NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile.c_str();
2132 completions(
Context +
"int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
2133 UnorderedElementsAre(AllOf(named(
"GFuncC"), insertInclude(
"<foo>")),
2134 labeled(
"GFuncC(int)"), labeled(
"GFuncD(int)")));
2138 completions(
Context +
"int y = X().a^", {}, Opts).Completions.front();
2139 EXPECT_EQ(
A.Name,
"a");
2140 EXPECT_EQ(
A.Signature,
"(…)");
2141 EXPECT_EQ(
A.BundleSize, 2u);
2143 EXPECT_EQ(
A.ReturnType,
"int");
2145 ASSERT_TRUE(
A.Documentation);
2146 ASSERT_FALSE(
A.Deprecated);
2148 A.Documentation->asPlainText(),
2149 AnyOf(HasSubstr(
"Overload with int"), HasSubstr(
"Overload with bool")));
2150 EXPECT_EQ(
A.SnippetSuffix,
"($0)");
2153TEST(CompletionTest, OverloadBundlingSameFileDifferentURI) {
2154 clangd::CodeCompleteOptions Opts;
2155 Opts.BundleOverloads =
true;
2157 Symbol SymX =
sym(
"ns::X", index::SymbolKind::Function,
"@F@\\0#");
2158 Symbol SymY =
sym(
"ns::X", index::SymbolKind::Function,
"@F@\\0#I#");
2159 std::string BarHeader =
testPath(
"bar.h");
2161 SymX.CanonicalDeclaration.FileURI = BarURI.c_str();
2162 SymY.CanonicalDeclaration.FileURI = BarURI.c_str();
2167 auto Results = completions(
"void f() { ::ns::^ }", {SymX, SymY}, Opts);
2170 ASSERT_EQ(1u, Results.Completions.size());
2171 const auto &R = Results.Completions.front();
2172 EXPECT_EQ(
"X", R.Name);
2173 EXPECT_EQ(2u, R.BundleSize);
2176TEST(CompletionTest, DocumentationFromChangedFileCrash) {
2180 FS.Files[FooH] = R
"cpp(
2181 // this is my documentation comment.
2184 FS.Files[FooCpp] = "";
2192 // This makes sure we have func from header in the AST.
2198 ASSERT_TRUE(Server.blockUntilIdleForTest());
2201 FS.Files[FooH] = R
"cpp(
2205 clangd::CodeCompleteOptions Opts;
2206 CodeCompleteResult Completions =
2210 EXPECT_THAT(Completions.Completions,
2211 Contains(AllOf(Not(isDocumented()), named(
"func"))));
2214TEST(CompletionTest, NonDocComments) {
2215 const char *
Text = R
"cpp(
2216 // We ignore namespace comments, for rationale see CodeCompletionStrings.h.
2217 namespace comments_ns {
2220 // ------------------
2223 // A comment and a decl are separated by newlines.
2224 // Therefore, the comment shouldn't show up as doc comment.
2228 // this comment should be in the results.
2235 int comments_quux();
2239 // This comment should not be there.
2242 int Struct<T>::comments_qux() {
2245 // This comment **should** be in results.
2247 int Struct<T>::comments_quux() {
2254 completions(
Text).Completions,
2255 UnorderedElementsAre(AllOf(Not(isDocumented()), named(
"comments_foo")),
2256 AllOf(isDocumented(), named(
"comments_baz")),
2257 AllOf(isDocumented(), named(
"comments_quux")),
2258 AllOf(Not(isDocumented()), named(
"comments_ns")),
2263 AllOf(isDocumented(), named(
"comments_bar")),
2264 AllOf(isDocumented(), named(
"comments_qux"))));
2267TEST(CompletionTest, CompleteOnInvalidLine) {
2272 FS.
Files[FooCpp] =
"// empty file";
2279 EXPECT_THAT_EXPECTED(
2284TEST(CompletionTest, QualifiedNames) {
2285 auto Results = completions(
2287 namespace ns { int local; void both(); }
2288 void f() { ::ns::^ }
2290 {func("ns::both"),
cls(
"ns::Index")});
2293 Results.Completions,
2294 UnorderedElementsAre(scope(
"ns::"), scope(
"ns::"), scope(
"ns::")));
2297TEST(CompletionTest, Render) {
2301 C.Signature =
"(bool) const";
2302 C.SnippetSuffix =
"(${0:bool})";
2303 C.ReturnType =
"int";
2304 C.RequiredQualifier =
"Foo::";
2305 C.Scope =
"ns::Foo::";
2306 C.Documentation.emplace();
2307 C.Documentation->addParagraph().appendText(
"This is ").appendCode(
"x()");
2308 C.Includes.emplace_back();
2309 auto &Include =
C.Includes.back();
2310 Include.Header =
"\"foo.h\"";
2312 C.Score.Total = 1.0;
2313 C.Score.ExcludingName = .5;
2317 Opts.IncludeIndicator.Insert =
"^";
2318 Opts.IncludeIndicator.NoInsert =
"";
2319 Opts.EnableSnippets =
false;
2321 auto R =
C.render(Opts);
2322 EXPECT_EQ(R.label,
"Foo::x");
2323 EXPECT_EQ(R.labelDetails->detail,
"(bool) const");
2324 EXPECT_EQ(R.insertText,
"Foo::x");
2326 EXPECT_EQ(R.filterText,
"x");
2327 EXPECT_EQ(R.detail,
"int");
2328 EXPECT_EQ(R.documentation->value,
"From \"foo.h\"\n\nThis is x()");
2329 EXPECT_THAT(R.additionalTextEdits, IsEmpty());
2330 EXPECT_EQ(R.sortText,
sortText(1.0,
"x"));
2331 EXPECT_FALSE(R.deprecated);
2332 EXPECT_EQ(R.score, .5f);
2334 C.FilterText =
"xtra";
2336 EXPECT_EQ(R.filterText,
"xtra");
2337 EXPECT_EQ(R.sortText,
sortText(1.0,
"xtra"));
2339 Opts.EnableSnippets =
true;
2341 EXPECT_EQ(R.insertText,
"Foo::x(${0:bool})");
2344 C.SnippetSuffix =
"";
2346 EXPECT_EQ(R.insertText,
"Foo::x");
2349 Include.Insertion.emplace();
2351 EXPECT_EQ(R.label,
"^Foo::x");
2352 EXPECT_EQ(R.labelDetails->detail,
"(bool) const");
2353 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
2355 Opts.ShowOrigins =
true;
2357 EXPECT_EQ(R.label,
"^[AS]Foo::x");
2358 EXPECT_EQ(R.labelDetails->detail,
"(bool) const");
2362 EXPECT_EQ(R.detail,
"[2 overloads]");
2363 EXPECT_EQ(R.documentation->value,
"From \"foo.h\"\n\nThis is x()");
2365 C.Deprecated =
true;
2367 EXPECT_TRUE(R.deprecated);
2371 EXPECT_EQ(R.documentation->value,
"From `\"foo.h\"`\n\nThis is `x()`");
2374TEST(CompletionTest, IgnoreRecoveryResults) {
2375 auto Results = completions(
2377 namespace ns { int NotRecovered() { return 0; } }
2379 // Sema enters recovery mode first and then normal mode.
2380 if (auto x = ns::NotRecover^)
2383 EXPECT_THAT(Results.Completions, UnorderedElementsAre(named("NotRecovered")));
2386TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
2387 auto Results = completions(
2390 class X { public: X(); int x_; };
2394 EXPECT_THAT(Results.Completions,
2395 UnorderedElementsAre(AllOf(scope("ns::X::"), named(
"x_"))));
2402TEST(CompletionTest, ConstructorInitListIncomplete) {
2403 auto Results = completions(
2412 EXPECT_THAT(Results.Completions, ElementsAre(named("xyz_")));
2414 Results = completions(
2425 EXPECT_THAT(Results.Completions, ElementsAre(named("foo")));
2428TEST(CompletionTest, CodeCompletionContext) {
2429 auto Results = completions(
2432 class X { public: X(); int x_; };
2440 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
2443TEST(CompletionTest, FixItForArrowToDot) {
2448 Opts.IncludeFixIts = true;
2455 class ClassWithPtr {
2457 void MemberFunction();
2458 Auxilary* operator->() const;
2466 auto Results = completions(Code, {}, Opts);
2467 EXPECT_EQ(Results.Completions.size(), 3u);
2471 ReplacementEdit.newText =
".";
2472 for (
const auto &C : Results.Completions) {
2473 EXPECT_TRUE(
C.FixIts.size() == 1u ||
C.Name ==
"AuxFunction");
2474 if (!
C.FixIts.empty()) {
2475 EXPECT_THAT(
C.FixIts, ElementsAre(ReplacementEdit));
2480TEST(CompletionTest, FixItForDotToArrow) {
2482 Opts.IncludeFixIts =
true;
2489 class ClassWithPtr {
2491 void MemberFunction();
2492 Auxilary* operator->() const;
2500 auto Results = completions(Code, {}, Opts);
2501 EXPECT_EQ(Results.Completions.size(), 3u);
2505 ReplacementEdit.newText =
"->";
2506 for (
const auto &C : Results.Completions) {
2507 EXPECT_TRUE(
C.FixIts.empty() ||
C.Name ==
"AuxFunction");
2508 if (!
C.FixIts.empty()) {
2509 EXPECT_THAT(
C.FixIts, ElementsAre(ReplacementEdit));
2514TEST(CompletionTest, RenderWithFixItMerged) {
2517 FixIt.newText =
"->";
2521 C.RequiredQualifier =
"Foo::";
2523 C.CompletionTokenRange.start.character = 5;
2526 Opts.IncludeFixIts =
true;
2528 auto R =
C.render(Opts);
2529 EXPECT_TRUE(R.textEdit);
2530 EXPECT_EQ(R.textEdit->newText,
"->Foo::x");
2531 EXPECT_TRUE(R.additionalTextEdits.empty());
2534TEST(CompletionTest, RenderWithFixItNonMerged) {
2537 FixIt.newText =
"->";
2541 C.RequiredQualifier =
"Foo::";
2543 C.CompletionTokenRange.start.character = 5;
2546 Opts.IncludeFixIts =
true;
2548 auto R =
C.render(Opts);
2549 EXPECT_TRUE(R.textEdit);
2550 EXPECT_EQ(R.textEdit->newText,
"Foo::x");
2551 EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
2554TEST(CompletionTest, CompletionTokenRange) {
2560 constexpr const char *TestCodes[] = {
2582 #include "foo/[[a^/]]foo.h"
2585 #include "foo/abc/[[fo^o.h"]]
2588 for (
const auto &
Text : TestCodes) {
2590 TU.Code = TestCode.code().str();
2591 auto Results = completions(TU, TestCode.point());
2592 if (Results.Completions.size() != 1) {
2593 ADD_FAILURE() <<
"Results.Completions.size() != 1" <<
Text;
2596 EXPECT_THAT(Results.Completions.front().CompletionTokenRange,
2601TEST(SignatureHelpTest, OverloadsOrdering) {
2602 const auto Results = signatures(R
"cpp(
2604 void foo(int x, float y);
2605 void foo(float x, int y);
2606 void foo(float x, float y);
2607 void foo(int x, int y = 0);
2608 int main() { foo(^); }
2610 EXPECT_THAT(Results.signatures,
2611 ElementsAre(sig("foo([[int x]]) -> void"),
2612 sig(
"foo([[int x]], [[int y = 0]]) -> void"),
2613 sig(
"foo([[float x]], [[int y]]) -> void"),
2614 sig(
"foo([[int x]], [[float y]]) -> void"),
2615 sig(
"foo([[float x]], [[float y]]) -> void")));
2617 EXPECT_EQ(0, Results.activeSignature);
2618 EXPECT_EQ(0, Results.activeParameter);
2621TEST(SignatureHelpTest, InstantiatedSignatures) {
2622 StringRef Sig0 = R
"cpp(
2631 EXPECT_THAT(signatures(Sig0).signatures,
2632 ElementsAre(sig("foo([[T]], [[T]], [[T]]) -> void")));
2634 StringRef Sig1 = R
"cpp(
2642 EXPECT_THAT(signatures(Sig1).signatures,
2643 ElementsAre(sig("foo([[T]], [[T]], [[T]]) -> void")));
2645 StringRef Sig2 = R
"cpp(
2646 template <class ...T>
2654 EXPECT_THAT(signatures(Sig2).signatures,
2655 ElementsAre(sig("foo([[T...]]) -> void")));
2662 StringRef Sig3 = R
"cpp(
2670 X<int>().foo<double>(^)
2674 EXPECT_THAT(signatures(Sig3).signatures,
2675 ElementsAre(sig("foo([[T]], [[U]]) -> void")));
2678TEST(SignatureHelpTest, IndexDocumentation) {
2679 Symbol Foo0 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#");
2680 Foo0.Documentation =
"doc from the index";
2681 Symbol Foo1 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#I#");
2682 Foo1.Documentation =
"doc from the index";
2683 Symbol Foo2 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#I#I#");
2685 StringRef Sig0 = R
"cpp(
2695 signatures(Sig0, {Foo0}).signatures,
2696 ElementsAre(AllOf(sig("foo() -> int"), sigDoc(
"doc from the index")),
2697 AllOf(sig(
"foo([[double]]) -> int"), sigDoc(
""))));
2699 StringRef Sig1 = R
"cpp(
2701 // Overriden doc from sema
2712 signatures(Sig1, {Foo0, Foo1, Foo2}).signatures,
2714 AllOf(sig("foo() -> int"), sigDoc(
"doc from the index")),
2715 AllOf(sig(
"foo([[int]]) -> int"), sigDoc(
"Overriden doc from sema")),
2716 AllOf(sig(
"foo([[int]], [[int]]) -> int"), sigDoc(
"doc from sema"))));
2719TEST(SignatureHelpTest, DynamicIndexDocumentation) {
2723 Opts.BuildDynamicSymbolIndex =
true;
2726 FS.Files[
testPath(
"foo.h")] = R
"cpp(
2740 Server.addDocument(
File, FileContent.code());
2742 ASSERT_TRUE(Server.blockUntilIdleForTest());
2746 ElementsAre(AllOf(sig(
"foo() -> int"), sigDoc(
"Member doc"))));
2749TEST(CompletionTest, ArgumentListsPolicy) {
2751 Opts.EnableSnippets =
true;
2755 auto Results = completions(
2758 void xfoo(int x, int y);
2759 void f() { xfo^ })cpp",
2762 Results.Completions,
2763 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix(
"()")),
2764 AllOf(named(
"xfoo"), snippetSuffix(
"($0)"))));
2767 auto Results = completions(
2770 void f() { xba^ })cpp",
2772 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
2773 named("xbar"), snippetSuffix(
"()"))));
2776 Opts.BundleOverloads =
true;
2777 auto Results = completions(
2780 void xfoo(int x, int y);
2781 void f() { xfo^ })cpp",
2784 Results.Completions,
2785 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix(
"($0)"))));
2788 auto Results = completions(
2790 template <class T, class U>
2791 void xfoo(int a, U b);
2792 void f() { xfo^ })cpp",
2795 Results.Completions,
2796 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix(
"<$1>($0)"))));
2799 auto Results = completions(
2804 using foo_alias = T**;
2807 void f() { foo_^ })cpp",
2810 Results.Completions,
2811 UnorderedElementsAre(AllOf(named("foo_class"), snippetSuffix(
"<$0>")),
2812 AllOf(named(
"foo_alias"), snippetSuffix(
"<$0>")),
2813 AllOf(named(
"foo_var"), snippetSuffix(
"<$0>"))));
2816 auto Results = completions(
2818 #define FOO(x, y) x##f
2821 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
2822 named("FOO"), snippetSuffix(
"($0)"))));
2826 auto Results = completions(
2828 void xfoo(int x, int y);
2829 void f() { xfo^ })cpp",
2831 EXPECT_THAT(Results.Completions,
2832 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix(
""))));
2836 auto Results = completions(
2838 void xfoo(int x, int y);
2839 void f() { xfo^ })cpp",
2841 EXPECT_THAT(Results.Completions,
2842 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix(
"("))));
2846TEST(CompletionTest, SuggestOverrides) {
2847 constexpr const char *
const Text(R
"cpp(
2850 virtual void vfunc(bool param);
2851 virtual void vfunc(bool param, int p);
2852 void func(bool param);
2854 class B : public A {
2855 virtual void ttt(bool param) const;
2856 void vfunc(bool param, int p) override;
2858 class C : public B {
2860 void vfunc(bool param) override;
2864 const auto Results = completions(
Text);
2866 Results.Completions,
2867 AllOf(Contains(AllOf(labeled(
"void vfunc(bool param, int p) override"),
2868 nameStartsWith(
"vfunc"))),
2869 Contains(AllOf(labeled(
"void ttt(bool param) const override"),
2870 nameStartsWith(
"ttt"))),
2871 Not(Contains(labeled(
"void vfunc(bool param) override")))));
2874TEST(CompletionTest, OverridesNonIdentName) {
2878 virtual ~Base() = 0;
2879 virtual operator int() = 0;
2880 virtual Base& operator+(Base&) = 0;
2883 struct Derived : Base {
2889TEST(CompletionTest, NoCrashOnMissingNewLineAtEOF) {
2895 FS.Files[FooCpp] = F.code().str();
2900 clangd::CodeCompleteOptions()))
2909TEST(GuessCompletionPrefix, Filters) {
2910 for (llvm::StringRef Case : {
2911 "[[scope::]][[ident]]^",
2920 "some text [[scope::more::]][[identif]]^ier",
2921 "some text [[scope::]][[mor]]^e::identifier",
2922 "weird case foo::[[::bar::]][[baz]]^",
2927 auto ToStringRef = [&](
Range R) {
2931 auto WantQualifier = ToStringRef(F.ranges()[0]),
2932 WantName = ToStringRef(F.ranges()[1]);
2936 EXPECT_EQ(WantQualifier, Prefix.Qualifier) << Case;
2937 EXPECT_EQ(WantQualifier.begin(), Prefix.Qualifier.begin()) << Case;
2938 EXPECT_EQ(WantName, Prefix.Name) << Case;
2939 EXPECT_EQ(WantName.begin(), Prefix.Name.begin()) << Case;
2943TEST(CompletionTest, EnableSpeculativeIndexRequest) {
2950 namespace ns1 { int abc; }
2951 namespace ns2 { int abc; }
2952 void f() { ns1::ab$1^; ns1::ab$2^; }
2953 void f2() { ns2::ab$3^; }
2956 clangd::CodeCompleteOptions Opts = {};
2958 IndexRequestCollector Requests;
2959 Opts.Index = &Requests;
2961 auto CompleteAtPoint = [&](StringRef
P) {
2963 EXPECT_TRUE(CCR.HasMore);
2966 CompleteAtPoint(
"1");
2967 auto Reqs1 = Requests.consumeRequests(1);
2968 ASSERT_EQ(Reqs1.size(), 1u);
2969 EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre(
"ns1::"));
2971 CompleteAtPoint(
"2");
2972 auto Reqs2 = Requests.consumeRequests(1);
2974 ASSERT_EQ(Reqs2.size(), 1u);
2975 EXPECT_EQ(Reqs2[0], Reqs1[0]);
2977 CompleteAtPoint(
"3");
2980 auto Reqs3 = Requests.consumeRequests(2);
2981 ASSERT_EQ(Reqs3.size(), 2u);
2984TEST(CompletionTest, InsertTheMostPopularHeader) {
2987 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2991 auto Results = completions(
"Fun^", {Sym}).Completions;
2992 assert(!Results.empty());
2993 EXPECT_THAT(Results[0], AllOf(named(
"Func"), insertInclude(
"\"bar.h\"")));
2994 EXPECT_EQ(Results[0].Includes.size(), 2u);
2997TEST(CompletionTest, InsertIncludeOrImport) {
3000 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
3001 Sym.IncludeHeaders.emplace_back(
"\"bar.h\"", 1000,
3005 Opts.ImportInsertions =
true;
3006 auto Results = completions(
"Fun^", {Sym}, Opts).Completions;
3007 assert(!Results.empty());
3008 EXPECT_THAT(Results[0],
3009 AllOf(named(
"Func"), insertIncludeText(
"#include \"bar.h\"\n")));
3013 Opts.MainFileSignals = &Signals;
3014 Results = completions(
"Fun^", {Sym}, Opts,
"Foo.m").Completions;
3015 assert(!Results.empty());
3016 EXPECT_THAT(Results[0],
3017 AllOf(named(
"Func"), insertIncludeText(
"#import \"bar.h\"\n")));
3020 Results = completions(
"Fun^", {Sym}).Completions;
3021 assert(!Results.empty());
3022 EXPECT_THAT(Results[0], AllOf(named(
"Func"), Not(insertInclude())));
3025TEST(CompletionTest, NoInsertIncludeIfOnePresent) {
3031 TU.AdditionalFiles[
"foo.h"] =
"";
3035 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
3039 EXPECT_THAT(completions(TU, Test.point(), {Sym}).Completions,
3040 UnorderedElementsAre(AllOf(named(
"Func"), hasInclude(
"\"foo.h\""),
3041 Not(insertInclude()))));
3044TEST(CompletionTest, MergeMacrosFromIndexAndSema) {
3046 Sym.Name =
"Clangd_Macro_Test";
3047 Sym.ID =
SymbolID(
"c:foo.cpp@8@macro@Clangd_Macro_Test");
3048 Sym.SymInfo.Kind = index::SymbolKind::Macro;
3050 EXPECT_THAT(completions(
"#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym})
3052 UnorderedElementsAre(named(
"Clangd_Macro_Test")));
3055TEST(CompletionTest, MacroFromPreamble) {
3056 Annotations Test(R
"cpp(#define CLANGD_PREAMBLE_MAIN x
3059 #define CLANGD_MAIN x
3060 void f() { CLANGD_^ }
3063 TU.HeaderCode =
"#define CLANGD_PREAMBLE_HEADER x";
3064 auto Results = completions(TU, Test.point(), {func(
"CLANGD_INDEX")});
3067 EXPECT_THAT(Results.Completions,
3068 UnorderedElementsAre(named(
"CLANGD_PREAMBLE_MAIN"),
3069 named(
"CLANGD_MAIN"),
3070 named(
"CLANGD_INDEX")));
3073TEST(CompletionTest, DeprecatedResults) {
3074 std::string Body = R
"cpp(
3076 void TestClangc() __attribute__((deprecated("", "")));
3080 completions(Body + "int main() { TestClang^ }").Completions,
3081 UnorderedElementsAre(AllOf(named(
"TestClangd"), Not(deprecated())),
3082 AllOf(named(
"TestClangc"), deprecated())));
3085TEST(SignatureHelpTest, PartialSpec) {
3086 const auto Results = signatures(R
"cpp(
3087 template <typename T> struct Foo {};
3088 template <typename T> struct Foo<T*> { Foo(T); };
3089 Foo<int*> F(^);)cpp");
3090 EXPECT_THAT(Results.signatures, Contains(sig("Foo([[T]])")));
3091 EXPECT_EQ(0, Results.activeParameter);
3094TEST(SignatureHelpTest, InsideArgument) {
3096 const auto Results = signatures(R
"cpp(
3098 void foo(int x, int y);
3099 int main() { foo(1+^); }
3101 EXPECT_THAT(Results.signatures,
3102 ElementsAre(sig("foo([[int x]]) -> void"),
3103 sig(
"foo([[int x]], [[int y]]) -> void")));
3104 EXPECT_EQ(0, Results.activeParameter);
3107 const auto Results = signatures(R
"cpp(
3109 void foo(int x, int y);
3110 int main() { foo(1^); }
3112 EXPECT_THAT(Results.signatures,
3113 ElementsAre(sig("foo([[int x]]) -> void"),
3114 sig(
"foo([[int x]], [[int y]]) -> void")));
3115 EXPECT_EQ(0, Results.activeParameter);
3118 const auto Results = signatures(R
"cpp(
3120 void foo(int x, int y);
3121 int main() { foo(1^0); }
3123 EXPECT_THAT(Results.signatures,
3124 ElementsAre(sig("foo([[int x]]) -> void"),
3125 sig(
"foo([[int x]], [[int y]]) -> void")));
3126 EXPECT_EQ(0, Results.activeParameter);
3129 const auto Results = signatures(R
"cpp(
3131 void foo(int x, int y);
3132 int bar(int x, int y);
3133 int main() { bar(foo(2, 3^)); }
3135 EXPECT_THAT(Results.signatures,
3136 ElementsAre(sig("foo([[int x]], [[int y]]) -> void")));
3137 EXPECT_EQ(1, Results.activeParameter);
3141TEST(SignatureHelpTest, ConstructorInitializeFields) {
3143 const auto Results = signatures(R
"cpp(
3144 struct A { A(int); };
3150 EXPECT_THAT(Results.signatures,
3151 UnorderedElementsAre(sig("A([[int]])"), sig(
"A([[A &&]])"),
3152 sig(
"A([[const A &]])")));
3155 const auto Results = signatures(R
"cpp(
3156 struct A { A(int); };
3164 EXPECT_THAT(Results.signatures, IsEmpty());
3167 const auto Results = signatures(R
"cpp(
3168 struct A { A(int); };
3175 EXPECT_THAT(Results.signatures,
3176 UnorderedElementsAre(sig("A([[int]])"), sig(
"A([[A &&]])"),
3177 sig(
"A([[const A &]])")));
3180 const auto Results = signatures(R
"cpp(
3189 B() : c_elem(A(1^)) {}
3193 EXPECT_THAT(Results.signatures,
3194 UnorderedElementsAre(sig("A([[int]])"), sig(
"A([[A &&]])"),
3195 sig(
"A([[const A &]])")));
3199TEST(SignatureHelpTest, Variadic) {
3200 const std::string Header = R
"cpp(
3201 void fun(int x, ...) {}
3203 const std::string ExpectedSig =
"fun([[int x]], [[...]]) -> void";
3206 const auto Result = signatures(Header +
"fun(^);}");
3207 EXPECT_EQ(0, Result.activeParameter);
3208 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3211 const auto Result = signatures(Header +
"fun(1, ^);}");
3212 EXPECT_EQ(1, Result.activeParameter);
3213 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3216 const auto Result = signatures(Header +
"fun(1, 2, ^);}");
3217 EXPECT_EQ(1, Result.activeParameter);
3218 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3222TEST(SignatureHelpTest, VariadicTemplate) {
3223 const std::string Header = R
"cpp(
3224 template<typename T, typename ...Args>
3225 void fun(T t, Args ...args) {}
3227 const std::string ExpectedSig =
"fun([[T t]], [[Args args...]]) -> void";
3230 const auto Result = signatures(Header +
"fun(^);}");
3231 EXPECT_EQ(0, Result.activeParameter);
3232 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3235 const auto Result = signatures(Header +
"fun(1, ^);}");
3236 EXPECT_EQ(1, Result.activeParameter);
3237 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3240 const auto Result = signatures(Header +
"fun(1, 2, ^);}");
3241 EXPECT_EQ(1, Result.activeParameter);
3242 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3246TEST(SignatureHelpTest, VariadicMethod) {
3247 const std::string Header = R
"cpp(
3249 template<typename T, typename ...Args>
3250 void fun(T t, Args ...args) {}
3252 void test() {C c; )cpp";
3253 const std::string ExpectedSig =
"fun([[T t]], [[Args args...]]) -> void";
3256 const auto Result = signatures(Header +
"c.fun(^);}");
3257 EXPECT_EQ(0, Result.activeParameter);
3258 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3261 const auto Result = signatures(Header +
"c.fun(1, ^);}");
3262 EXPECT_EQ(1, Result.activeParameter);
3263 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3266 const auto Result = signatures(Header +
"c.fun(1, 2, ^);}");
3267 EXPECT_EQ(1, Result.activeParameter);
3268 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3272TEST(SignatureHelpTest, VariadicType) {
3273 const std::string Header = R
"cpp(
3274 void fun(int x, ...) {}
3275 auto get_fun() { return fun; }
3278 const std::string ExpectedSig =
"([[int]], [[...]]) -> void";
3281 const auto Result = signatures(Header +
"get_fun()(^);}");
3282 EXPECT_EQ(0, Result.activeParameter);
3283 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3286 const auto Result = signatures(Header +
"get_fun()(1, ^);}");
3287 EXPECT_EQ(1, Result.activeParameter);
3288 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3291 const auto Result = signatures(Header +
"get_fun()(1, 2, ^);}");
3292 EXPECT_EQ(1, Result.activeParameter);
3293 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3297TEST(SignatureHelpTest, SkipExplicitObjectParameter) {
3300 void foo(this auto&& self, int arg);
3301 void bar(this A self, int arg);
3312 TU.ExtraArgs = {
"-std=c++23"};
3315 auto Inputs = TU.inputs(FS);
3324 EXPECT_EQ(1U, Result.signatures.size());
3326 EXPECT_THAT(Result.signatures[0], AllOf(sig(
"foo([[int arg]]) -> void")));
3332 EXPECT_EQ(1U, Result.signatures.size());
3334 EXPECT_THAT(Result.signatures[0], AllOf(sig(
"([[A]], [[int]]) -> void")));
3341 EXPECT_EQ(0U, Result.signatures.size());
3347TEST(CompletionTest, IncludedCompletionKinds) {
3350 TU.AdditionalFiles[
"sub/bar.h"] =
"";
3351 TU.ExtraArgs.push_back(
"-I" +
testPath(
"sub"));
3353 auto Results = completions(TU, Test.point());
3354 EXPECT_THAT(Results.Completions,
3359TEST(CompletionTest, NoCrashAtNonAlphaIncludeHeader) {
3366TEST(CompletionTest, NoAllScopesCompletionWhenQualified) {
3367 clangd::CodeCompleteOptions Opts = {};
3368 Opts.AllScopes = true;
3370 auto Results = completions(
3372 void f() { na::Clangd^ }
3374 {cls("na::ClangdA"),
cls(
"nx::ClangdX"),
cls(
"Clangd3")}, Opts);
3375 EXPECT_THAT(Results.Completions,
3376 UnorderedElementsAre(
3377 AllOf(qualifier(
""), scope(
"na::"), named(
"ClangdA"))));
3380TEST(CompletionTest, AllScopesCompletion) {
3381 clangd::CodeCompleteOptions Opts = {};
3382 Opts.AllScopes =
true;
3384 auto Results = completions(
3387 void f() { Clangd^ }
3390 {cls("nx::Clangd1"),
cls(
"ny::Clangd2"),
cls(
"Clangd3"),
3394 Results.Completions,
3395 UnorderedElementsAre(AllOf(qualifier(
"nx::"), named(
"Clangd1"),
3397 AllOf(qualifier(
"ny::"), named(
"Clangd2"),
3399 AllOf(qualifier(
""), scope(
""), named(
"Clangd3"),
3401 AllOf(qualifier(
"nb::"), named(
"Clangd4"),
3403 AllOf(qualifier(
"C::"), named(
"Clangd5"),
3407TEST(CompletionTest, NoCodePatternsIfDisabled) {
3408 clangd::CodeCompleteOptions Opts = {};
3409 Opts.EnableSnippets =
true;
3412 auto Results = completions(R
"cpp(
3421 EXPECT_THAT(Results.Completions,
3425TEST(CompletionTest, CompleteIncludeIfCodePatternsNone) {
3426 clangd::CodeCompleteOptions Opts = {};
3427 Opts.EnableSnippets =
true;
3432 TU.AdditionalFiles[
"foo/bar.h"] =
"";
3433 TU.ExtraArgs.push_back(
"-I" +
testPath(
"foo"));
3435 auto Results = completions(TU, Test.point(), {}, Opts);
3436 EXPECT_THAT(Results.Completions,
3441TEST(CompletionTest, NoQualifierIfShadowed) {
3442 clangd::CodeCompleteOptions Opts = {};
3443 Opts.AllScopes =
true;
3445 auto Results = completions(R
"cpp(
3446 namespace nx { class Clangd1 {}; }
3448 void f() { Clangd^ }
3450 {cls("nx::Clangd1"),
cls(
"nx::Clangd2")}, Opts);
3453 EXPECT_THAT(Results.Completions,
3454 UnorderedElementsAre(AllOf(qualifier(
""), named(
"Clangd1")),
3455 AllOf(qualifier(
"nx::"), named(
"Clangd2"))));
3458TEST(CompletionTest, NoCompletionsForNewNames) {
3459 clangd::CodeCompleteOptions Opts;
3460 Opts.AllScopes =
true;
3461 auto Results = completions(R
"cpp(
3464 {cls("naber"),
cls(
"nx::naber")}, Opts);
3465 EXPECT_THAT(Results.Completions, UnorderedElementsAre());
3468TEST(CompletionTest, Lambda) {
3469 clangd::CodeCompleteOptions Opts = {};
3471 auto Results = completions(R
"cpp(
3473 auto Lambda = [](int a, const double &b) {return 1.f;};
3479 ASSERT_EQ(Results.Completions.size(), 1u);
3480 const auto &
A = Results.Completions.front();
3481 EXPECT_EQ(
A.Name,
"Lambda");
3482 EXPECT_EQ(
A.Signature,
"(int a, const double &b) const");
3484 EXPECT_EQ(
A.ReturnType,
"float");
3485 EXPECT_EQ(
A.SnippetSuffix,
"(${1:int a}, ${2:const double &b})");
3488TEST(CompletionTest, StructuredBinding) {
3489 clangd::CodeCompleteOptions Opts = {};
3491 auto Results = completions(R
"cpp(
3493 using Float = float;
3498 const auto &[xxx, yyy] = S{};
3504 ASSERT_EQ(Results.Completions.size(), 1u);
3505 const auto &
A = Results.Completions.front();
3506 EXPECT_EQ(
A.Name,
"yyy");
3508 EXPECT_EQ(
A.ReturnType,
"const Float");
3511TEST(CompletionTest, ObjectiveCMethodNoArguments) {
3512 auto Results = completions(R
"objc(
3514 @property(nonatomic, setter=setXToIgnoreComplete:) int value;
3516 Foo *foo = [Foo new]; int y = [foo v^]
3521 auto C = Results.Completions;
3522 EXPECT_THAT(C, ElementsAre(named(
"value")));
3524 EXPECT_THAT(C, ElementsAre(returnType(
"int")));
3525 EXPECT_THAT(C, ElementsAre(signature(
"")));
3526 EXPECT_THAT(C, ElementsAre(snippetSuffix(
"")));
3529TEST(CompletionTest, ObjectiveCMethodOneArgument) {
3530 auto Results = completions(R
"objc(
3532 - (int)valueForCharacter:(char)c;
3534 Foo *foo = [Foo new]; int y = [foo v^]
3539 auto C = Results.Completions;
3540 EXPECT_THAT(C, ElementsAre(named(
"valueForCharacter:")));
3542 EXPECT_THAT(C, ElementsAre(returnType(
"int")));
3543 EXPECT_THAT(C, ElementsAre(signature(
"(char)")));
3544 EXPECT_THAT(C, ElementsAre(snippetSuffix(
"${1:(char)}")));
3547TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromBeginning) {
3548 auto Results = completions(R
"objc(
3550 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;
3557 auto C = Results.Completions;
3558 EXPECT_THAT(C, ElementsAre(named(
"fooWithValue:")));
3560 EXPECT_THAT(C, ElementsAre(returnType(
"id")));
3561 EXPECT_THAT(C, ElementsAre(signature(
"(int) fooey:(unsigned int)")));
3563 C, ElementsAre(snippetSuffix(
"${1:(int)} fooey:${2:(unsigned int)}")));
3566TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
3567 auto Results = completions(R
"objc(
3569 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;
3571 id val = [Foo fooWithValue:10 f^]
3576 auto C = Results.Completions;
3577 EXPECT_THAT(C, ElementsAre(named(
"fooey:")));
3579 EXPECT_THAT(C, ElementsAre(returnType(
"id")));
3580 EXPECT_THAT(C, ElementsAre(signature(
"(unsigned int)")));
3581 EXPECT_THAT(C, ElementsAre(snippetSuffix(
"${1:(unsigned int)}")));
3584TEST(CompletionTest, ObjectiveCMethodFilterOnEntireSelector) {
3585 auto Results = completions(R
"objc(
3587 + (id)player:(id)player willRun:(id)run;
3594 auto C = Results.Completions;
3595 EXPECT_THAT(C, ElementsAre(named(
"player:")));
3596 EXPECT_THAT(C, ElementsAre(filterText(
"player:willRun:")));
3598 EXPECT_THAT(C, ElementsAre(returnType(
"id")));
3599 EXPECT_THAT(C, ElementsAre(signature(
"(id) willRun:(id)")));
3600 EXPECT_THAT(C, ElementsAre(snippetSuffix(
"${1:(id)} willRun:${2:(id)}")));
3603TEST(CompletionTest, ObjectiveCSimpleMethodDeclaration) {
3604 auto Results = completions(R
"objc(
3615 auto C = Results.Completions;
3616 EXPECT_THAT(C, ElementsAre(named(
"foo")));
3618 EXPECT_THAT(C, ElementsAre(qualifier(
"- (void)")));
3621TEST(CompletionTest, ObjectiveCMethodDeclaration) {
3622 auto Results = completions(R
"objc(
3624 - (int)valueForCharacter:(char)c secondArgument:(id)object;
3633 auto C = Results.Completions;
3634 EXPECT_THAT(C, ElementsAre(named(
"valueForCharacter:")));
3636 EXPECT_THAT(C, ElementsAre(qualifier(
"- (int)")));
3637 EXPECT_THAT(C, ElementsAre(signature(
"(char)c secondArgument:(id)object")));
3640TEST(CompletionTest, ObjectiveCMethodDeclarationFilterOnEntireSelector) {
3641 auto Results = completions(R
"objc(
3643 - (int)valueForCharacter:(char)c secondArgument:(id)object;
3652 auto C = Results.Completions;
3653 EXPECT_THAT(C, ElementsAre(named(
"valueForCharacter:")));
3654 EXPECT_THAT(C, ElementsAre(filterText(
"valueForCharacter:secondArgument:")));
3656 EXPECT_THAT(C, ElementsAre(qualifier(
"- (int)")));
3657 EXPECT_THAT(C, ElementsAre(signature(
"(char)c secondArgument:(id)object")));
3660TEST(CompletionTest, ObjectiveCMethodDeclarationPrefixTyped) {
3661 auto Results = completions(R
"objc(
3663 - (int)valueForCharacter:(char)c;
3672 auto C = Results.Completions;
3673 EXPECT_THAT(C, ElementsAre(named(
"valueForCharacter:")));
3675 EXPECT_THAT(C, ElementsAre(signature(
"(char)c")));
3678TEST(CompletionTest, ObjectiveCMethodDeclarationFromMiddle) {
3679 auto Results = completions(R
"objc(
3681 - (int)valueForCharacter:(char)c secondArgument:(id)object;
3684 - (int)valueForCharacter:(char)c second^
3690 auto C = Results.Completions;
3691 EXPECT_THAT(C, ElementsAre(named(
"secondArgument:")));
3693 EXPECT_THAT(C, ElementsAre(signature(
"(id)object")));
3696TEST(CompletionTest, ObjectiveCProtocolFromIndex) {
3700 auto Results = completions(
"id<Foo^>", {SymFood, FoodClass, SymFooey},
3704 EXPECT_THAT(Results.Completions,
3705 UnorderedElementsAre(
3709 Results = completions(
"Fo^", {SymFood, FoodClass, SymFooey},
3713 Results.Completions,
3717TEST(CompletionTest, ObjectiveCProtocolFromIndexSpeculation) {
3730 clangd::CodeCompleteOptions Opts = {};
3733 IndexRequestCollector Requests({FoodClass});
3734 Opts.Index = &Requests;
3736 auto CompleteAtPoint = [&](StringRef
P) {
3741 auto C = CompleteAtPoint(
"1");
3742 auto Reqs1 = Requests.consumeRequests(1);
3743 ASSERT_EQ(Reqs1.size(), 1u);
3744 EXPECT_THAT(C, ElementsAre(AllOf(named(
"Food"),
3747 C = CompleteAtPoint(
"2");
3748 auto Reqs2 = Requests.consumeRequests(1);
3751 ASSERT_EQ(Reqs2.size(), 1u);
3752 EXPECT_EQ(Reqs2[0], Reqs1[0]);
3753 EXPECT_THAT(C, ElementsAre(AllOf(named(
"FoodClass"),
3757TEST(CompletionTest, ObjectiveCCategoryFromIndexIgnored) {
3759 auto Results = completions(R
"objc(
3767 EXPECT_THAT(Results.Completions, IsEmpty());
3770TEST(CompletionTest, ObjectiveCForwardDeclFromIndex) {
3772 FoodClass.IncludeHeaders.emplace_back(
"\"Foo.h\"", 2,
Symbol::Import);
3774 auto Results = completions(
"@class Foo^", {SymFood, FoodClass},
3778 EXPECT_THAT(Results.Completions,
3779 UnorderedElementsAre(AllOf(named(
"FoodClass"),
3781 Not(insertInclude()))));
3784TEST(CompletionTest, CursorInSnippets) {
3785 clangd::CodeCompleteOptions Options;
3786 Options.EnableSnippets =
true;
3787 auto Results = completions(
3789 void while_foo(int a, int b);
3796 EXPECT_THAT(Results.Completions,
3797 Contains(AllOf(named(
"while"),
3798 snippetSuffix(
" (${1:condition}) {\n$0\n}"))));
3800 EXPECT_THAT(Results.Completions,
3801 Contains(AllOf(named(
"while_foo"),
3802 snippetSuffix(
"(${1:int a}, ${2:int b})"))));
3804 Results = completions(R
"cpp(
3806 Base(int a, int b) {}
3809 struct Derived : Base {
3816 EXPECT_THAT(Results.Completions,
3817 Contains(AllOf(named(
"Base"),
3818 snippetSuffix(
"(${1:int a}, ${2:int b})"))));
3821TEST(CompletionTest, WorksWithNullType) {
3822 auto R = completions(R
"cpp(
3824 for (auto [loopVar] : y ) { // y has to be unresolved.
3829 EXPECT_THAT(R.Completions, ElementsAre(named("loopVar")));
3832TEST(CompletionTest, UsingDecl) {
3833 const char *Header(R
"cpp(
3838 const char *Source(R
"cpp(
3843 clangd::CodeCompleteOptions Opts;
3844 Opts.Index = Index.get();
3845 Opts.AllScopes =
true;
3846 auto R = completions(Source, {}, Opts);
3847 EXPECT_THAT(R.Completions,
3848 ElementsAre(AllOf(scope(
"std::"), named(
"foo"),
3852TEST(CompletionTest, Enums) {
3853 const char *Header(R
"cpp(
3855 enum Unscoped { Clangd1 };
3857 enum Unscoped { Clangd2 };
3859 enum class Scoped { Clangd3 };
3861 const char *Source(R
"cpp(
3866 clangd::CodeCompleteOptions Opts;
3867 Opts.Index = Index.get();
3868 Opts.AllScopes =
true;
3869 auto R = completions(Source, {}, Opts);
3870 EXPECT_THAT(R.Completions, UnorderedElementsAre(
3871 AllOf(scope(
"ns::"), named(
"Clangd1"),
3873 AllOf(scope(
"ns::C::"), named(
"Clangd2"),
3875 AllOf(scope(
"ns::Scoped::"), named(
"Clangd3"),
3879TEST(CompletionTest, ScopeIsUnresolved) {
3880 clangd::CodeCompleteOptions Opts = {};
3881 Opts.AllScopes =
true;
3883 auto Results = completions(R
"cpp(
3888 {cls("a::b::XYZ")}, Opts);
3889 EXPECT_THAT(Results.Completions,
3890 UnorderedElementsAre(AllOf(qualifier(
""), named(
"XYZ"))));
3893TEST(CompletionTest, NestedScopeIsUnresolved) {
3894 clangd::CodeCompleteOptions Opts = {};
3895 Opts.AllScopes =
true;
3897 auto Results = completions(R
"cpp(
3900 void f() { b::c::X^ }
3903 {cls("a::b::c::XYZ")}, Opts);
3904 EXPECT_THAT(Results.Completions,
3905 UnorderedElementsAre(AllOf(qualifier(
""), named(
"XYZ"))));
3910TEST(CompletionTest, NamespaceDoubleInsertion) {
3911 clangd::CodeCompleteOptions Opts = {};
3913 auto Results = completions(R
"cpp(
3920 {cls("foo::ns::ABCDE")}, Opts);
3921 EXPECT_THAT(Results.Completions,
3922 UnorderedElementsAre(AllOf(qualifier(
""), named(
"ABCDE"))));
3925TEST(CompletionTest, DerivedMethodsAreAlwaysVisible) {
3928 auto Completions = completions(R
"cpp(
3931 double size() const;
3933 struct deque : deque_base {
3940 EXPECT_THAT(Completions,
3941 ElementsAre(AllOf(returnType("int"), named(
"size"))));
3944TEST(CompletionTest, NoCrashWithIncompleteLambda) {
3945 auto Completions = completions(
"auto&& x = []{^").Completions;
3949 EXPECT_THAT(Completions, Contains(named(
"x")));
3951 auto Signatures = signatures(
"auto x() { x(^").signatures;
3952 EXPECT_THAT(Signatures, Contains(sig(
"x() -> auto")));
3955TEST(CompletionTest, DelayedTemplateParsing) {
3958 template <typename T> int foo() { return xx^; }
3963 TU.ExtraArgs.push_back(
"-fdelayed-template-parsing");
3965 EXPECT_THAT(completions(TU, Test.point()).Completions,
3966 Contains(named(
"xxx")));
3969TEST(CompletionTest, CompletionRange) {
3970 const char *WithRange =
"auto x = [[abc]]^";
3971 auto Completions = completions(WithRange);
3972 EXPECT_EQ(Completions.CompletionRange,
Annotations(WithRange).range());
3973 Completions = completionsNoCompile(WithRange);
3974 EXPECT_EQ(Completions.CompletionRange,
Annotations(WithRange).range());
3976 const char *EmptyRange =
"auto x = [[]]^";
3977 Completions = completions(EmptyRange);
3978 EXPECT_EQ(Completions.CompletionRange,
Annotations(EmptyRange).range());
3979 Completions = completionsNoCompile(EmptyRange);
3980 EXPECT_EQ(Completions.CompletionRange,
Annotations(EmptyRange).range());
3984 const char *NoCompletion =
"/* foo [[]]^ */";
3985 Completions = completions(NoCompletion);
3986 EXPECT_EQ(Completions.CompletionRange, std::nullopt);
3987 Completions = completionsNoCompile(NoCompletion);
3988 EXPECT_EQ(Completions.CompletionRange,
Annotations(NoCompletion).range());
3991TEST(NoCompileCompletionTest, Basic) {
3992 auto Results = completionsNoCompile(R
"cpp(
3999 EXPECT_FALSE(Results.RanParser);
4000 EXPECT_THAT(Results.Completions,
4001 UnorderedElementsAre(named("void"), named(
"func"), named(
"int"),
4002 named(
"xyz"), named(
"abc")));
4005TEST(NoCompileCompletionTest, WithFilter) {
4006 auto Results = completionsNoCompile(R
"cpp(
4015 EXPECT_THAT(Results.Completions,
4016 UnorderedElementsAre(named("sym1"), named(
"sym2")));
4019TEST(NoCompileCompletionTest, WithIndex) {
4020 std::vector<Symbol> Syms = {
func(
"xxx"),
func(
"a::xxx"),
func(
"ns::b::xxx"),
4021 func(
"c::xxx"),
func(
"ns::d::xxx")};
4022 auto Results = completionsNoCompile(
4024 // Current-scopes, unqualified completion.
4034 EXPECT_THAT(Results.Completions,
4035 UnorderedElementsAre(AllOf(qualifier(""), scope(
"")),
4036 AllOf(qualifier(
""), scope(
"a::")),
4037 AllOf(qualifier(
""), scope(
"ns::b::"))));
4039 Opts.AllScopes =
true;
4040 Results = completionsNoCompile(
4042 // All-scopes unqualified completion.
4052 EXPECT_THAT(Results.Completions,
4053 UnorderedElementsAre(AllOf(qualifier(""), scope(
"")),
4054 AllOf(qualifier(
""), scope(
"a::")),
4055 AllOf(qualifier(
""), scope(
"ns::b::")),
4056 AllOf(qualifier(
"c::"), scope(
"c::")),
4057 AllOf(qualifier(
"d::"), scope(
"ns::d::"))));
4058 Results = completionsNoCompile(
4060 // Qualified completion.
4070 EXPECT_THAT(Results.Completions,
4071 ElementsAre(AllOf(qualifier(""), scope(
"ns::b::"))));
4072 Results = completionsNoCompile(
4074 // Absolutely qualified completion.
4084 EXPECT_THAT(Results.Completions,
4085 ElementsAre(AllOf(qualifier(""), scope(
"a::"))));
4088TEST(AllowImplicitCompletion,
All) {
4089 const char *
Yes[] = {
4093 " # include <^foo.h>",
4094 "#import <foo/^bar.h>",
4095 "#include_next \"^",
4097 const char *
No[] = {
4101 "#include <foo.h> //^",
4102 "#include \"foo.h\"^",
4106 for (
const char *Test :
Yes) {
4107 llvm::Annotations
A(Test);
4110 for (
const char *Test :
No) {
4111 llvm::Annotations
A(Test);
4116TEST(CompletionTest, FunctionArgsExist) {
4117 clangd::CodeCompleteOptions Opts;
4118 Opts.EnableSnippets =
true;
4126 template <typename T>
4128 Container(int Size) {}
4131 EXPECT_THAT(completions(Context + "int y = fo^", {}, Opts).Completions,
4132 UnorderedElementsAre(
4133 AllOf(labeled(
"foo(int A)"), snippetSuffix(
"(${1:int A})"))));
4135 completions(
Context +
"int y = fo^(42)", {}, Opts).Completions,
4136 UnorderedElementsAre(AllOf(labeled(
"foo(int A)"), snippetSuffix(
""))));
4138 EXPECT_THAT(completions(
Context +
"int y = fo^o(42)", {}, Opts).Completions,
4139 UnorderedElementsAre(
4140 AllOf(labeled(
"foo(int A)"), snippetSuffix(
"(${1:int A})"))));
4142 completions(
Context +
"int y = ba^", {}, Opts).Completions,
4143 UnorderedElementsAre(AllOf(labeled(
"bar()"), snippetSuffix(
"()"))));
4144 EXPECT_THAT(completions(
Context +
"int y = ba^()", {}, Opts).Completions,
4145 UnorderedElementsAre(AllOf(labeled(
"bar()"), snippetSuffix(
""))));
4147 completions(
Context +
"Object o = Obj^", {}, Opts).Completions,
4148 Contains(AllOf(labeled(
"Object(int B)"), snippetSuffix(
"(${1:int B})"),
4150 EXPECT_THAT(completions(
Context +
"Object o = Obj^()", {}, Opts).Completions,
4151 Contains(AllOf(labeled(
"Object(int B)"), snippetSuffix(
""),
4154 completions(
Context +
"Container c = Cont^", {}, Opts).Completions,
4155 Contains(AllOf(labeled(
"Container<typename T>(int Size)"),
4156 snippetSuffix(
"<${1:typename T}>(${2:int Size})"),
4159 completions(
Context +
"Container c = Cont^()", {}, Opts).Completions,
4160 Contains(AllOf(labeled(
"Container<typename T>(int Size)"),
4161 snippetSuffix(
"<${1:typename T}>"),
4164 completions(
Context +
"Container c = Cont^<int>()", {}, Opts).Completions,
4165 Contains(AllOf(labeled(
"Container<typename T>(int Size)"),
4168 EXPECT_THAT(completions(
Context +
"MAC^(2)", {}, Opts).Completions,
4169 Contains(AllOf(labeled(
"MACRO(x)"), snippetSuffix(
""),
4173TEST(CompletionTest, FunctionArgsExist_Issue1785) {
4177 clangd::CodeCompleteOptions Opts;
4178 Opts.EnableSnippets =
true;
4180 std::string Code = R
"cpp(
4192 completions(Code, {}, Opts).Completions,
4193 Contains(AllOf(labeled("waldo(int)"), snippetSuffix(
"(${1:int})"))));
4196TEST(CompletionTest, NoCrashDueToMacroOrdering) {
4197 EXPECT_THAT(completions(R
"cpp(
4199 #define ECHO2(X) ECHO(X)
4200 int finish_preamble = EC^HO(2);)cpp")
4202 UnorderedElementsAre(labeled("ECHO(X)"), labeled(
"ECHO2(X)")));
4205TEST(CompletionTest, ObjCCategoryDecls) {
4207 TU.
ExtraArgs.push_back(
"-xobjective-c");
4208 TU.HeaderCode = R
"objc(
4212 @interface Foo (FooExt1)
4215 @interface Foo (FooExt2)
4221 @interface Bar (BarExt)
4226 @implementation Foo (^)
4229 TU.Code = Test.code().str();
4230 auto Results = completions(TU, Test.point());
4231 EXPECT_THAT(Results.Completions,
4232 UnorderedElementsAre(labeled(
"FooExt1"), labeled(
"FooExt2")));
4239 TU.Code = Test.code().str();
4240 auto Results = completions(TU, Test.point());
4241 EXPECT_THAT(Results.Completions, UnorderedElementsAre(labeled(
"BarExt")));
4245TEST(CompletionTest, PreambleCodeComplete) {
4246 llvm::StringLiteral Baseline =
"\n#define MACRO 12\nint num = MACRO;";
4247 llvm::StringLiteral ModifiedCC =
4248 "#include \"header.h\"\n#define MACRO 12\nint num = MACRO; int num2 = M^";
4255 auto Inputs = ModifiedTU.inputs(FS);
4257 BaselineTU.preamble().get(), Inputs, {});
4258 EXPECT_THAT(Result.Completions, Not(testing::IsEmpty()));
4261TEST(CompletionTest, CommentParamName) {
4262 const std::string Code = R
"cpp(
4263 void fun(int foo, int bar);
4264 void overloaded(int param_int);
4265 void overloaded(int param_int, int param_other);
4266 void overloaded(char param_char);
4270 EXPECT_THAT(completions(Code + "fun(/*^").Completions,
4271 UnorderedElementsAre(labeled(
"foo=*/")));
4272 EXPECT_THAT(completions(Code +
"fun(1, /*^").Completions,
4273 UnorderedElementsAre(labeled(
"bar=*/")));
4274 EXPECT_THAT(completions(Code +
"/*^").Completions, IsEmpty());
4277 completions(Code +
"overloaded(/*^").Completions,
4278 UnorderedElementsAre(labeled(
"param_int=*/"), labeled(
"param_char=*/")));
4280 EXPECT_THAT(completions(Code +
"fun(/* ^").Completions,
4281 UnorderedElementsAre(labeled(
"foo=*/")));
4282 EXPECT_THAT(completions(Code +
"fun(/* f^").Completions,
4283 UnorderedElementsAre(labeled(
"foo=*/")));
4284 EXPECT_THAT(completions(Code +
"fun(/* x^").Completions, IsEmpty());
4285 EXPECT_THAT(completions(Code +
"fun(/* f ^").Completions, IsEmpty());
4289 std::string CompletionRangeTest(Code +
"fun(/*[[^]]");
4290 auto Results = completions(CompletionRangeTest);
4291 EXPECT_THAT(Results.CompletionRange,
4292 llvm::ValueIs(
Annotations(CompletionRangeTest).range()));
4294 Results.Completions,
4296 AllOf(replacesRange(
Annotations(CompletionRangeTest).range()),
4300 std::string CompletionRangeTest(Code +
"fun(/*[[fo^]]");
4301 auto Results = completions(CompletionRangeTest);
4302 EXPECT_THAT(Results.CompletionRange,
4303 llvm::ValueIs(
Annotations(CompletionRangeTest).range()));
4305 Results.Completions,
4307 AllOf(replacesRange(
Annotations(CompletionRangeTest).range()),
4312TEST(CompletionTest, Concepts) {
4315 concept A = sizeof(T) <= 8;
4317 template<$tparam^A U>
4320 template<typename T>
4321 int bar(T t) requires $expr^A<int>;
4324 concept b = $expr^A && $expr^sizeof(T) % 2 == 0 || $expr^A && sizeof(T) == 1;
4326 $toplevel^A auto i = 19;
4328 template<$toplevel^A auto i> void constrainedNTTP();
4330 // FIXME: The first parameter should be dropped in this case.
4331 void abbreviated($expr^A auto x) {}
4334 TU.Code = Code.code().str();
4335 TU.ExtraArgs = {"-std=c++20"};
4338 Sym.Signature =
"<typename Tp, typename Up>";
4339 Sym.CompletionSnippetSuffix =
"<${1:typename Tp}, ${2:typename Up}>";
4340 std::vector<Symbol> Syms = {Sym};
4341 for (
auto P : Code.points(
"tparam")) {
4343 completions(TU, P, Syms).Completions,
4344 AllOf(Contains(AllOf(named(
"A"), signature(
""), snippetSuffix(
""))),
4345 Contains(AllOf(named(
"same_as"), signature(
"<typename Up>"),
4346 snippetSuffix(
"<${2:typename Up}>"))),
4347 Contains(named(
"class")), Contains(named(
"typename"))))
4348 <<
"Completing template parameter at position " <<
P;
4351 for (
auto P : Code.points(
"toplevel")) {
4353 completions(TU, P, Syms).Completions,
4354 AllOf(Contains(AllOf(named(
"A"), signature(
""), snippetSuffix(
""))),
4355 Contains(AllOf(named(
"same_as"), signature(
"<typename Up>"),
4356 snippetSuffix(
"<${2:typename Up}>")))))
4357 <<
"Completing 'requires' expression at position " <<
P;
4360 for (
auto P : Code.points(
"expr")) {
4362 completions(TU, P, Syms).Completions,
4363 AllOf(Contains(AllOf(named(
"A"), signature(
"<class T>"),
4364 snippetSuffix(
"<${1:class T}>"))),
4366 named(
"same_as"), signature(
"<typename Tp, typename Up>"),
4367 snippetSuffix(
"<${1:typename Tp}, ${2:typename Up}>")))))
4368 <<
"Completing 'requires' expression at position " <<
P;
4374 // Comment `with` markup.
4376 void bar() { foo(^); }
4378 for (
auto DocumentationFormat :
4380 auto Sigs = signatures(Code.code(), Code.point(), {},
4381 DocumentationFormat);
4382 ASSERT_EQ(Sigs.signatures.size(), 1U);
4383 EXPECT_EQ(Sigs.signatures[0].documentation.kind, DocumentationFormat);
4388 std::string Top = R
"cpp(
4389 template <typename T, int> bool foo(char);
4390 template <int I, int> bool foo(float);
4393 auto First = signatures(Top +
"bool x = foo<^");
4396 UnorderedElementsAre(sig(
"foo<[[typename T]], [[int]]>() -> bool"),
4397 sig(
"foo<[[int I]], [[int]]>() -> bool")));
4398 EXPECT_EQ(First.activeParameter, 0);
4400 auto Second = signatures(Top +
"bool x = foo<1, ^");
4401 EXPECT_THAT(Second.signatures,
4402 ElementsAre(sig(
"foo<[[int I]], [[int]]>() -> bool")));
4403 EXPECT_EQ(Second.activeParameter, 1);
4406TEST(CompletionTest, DoNotCrash) {
4407 llvm::StringLiteral Cases[] = {
4409 template <typename = int> struct Foo {};
4410 auto a = [x(3)](Foo<^>){};
4413 for (
auto Case : Cases) {
4415 auto Completions = completions(Case);
4418TEST(CompletionTest, PreambleFromDifferentTarget) {
4419 constexpr std::string_view PreambleTarget =
"x86_64";
4420 constexpr std::string_view Contents =
4421 "int foo(int); int num; int num2 = foo(n^";
4425 TU.ExtraArgs.emplace_back(
"-target");
4426 TU.ExtraArgs.emplace_back(PreambleTarget);
4430 TU.ExtraArgs.pop_back();
4431 TU.ExtraArgs.emplace_back(
"wasm32");
4434 auto Inputs = TU.inputs(FS);
4441 EXPECT_THAT(Result.Completions, Not(testing::IsEmpty()));
4442 EXPECT_THAT(Signatures.signatures, Not(testing::IsEmpty()));
4445TEST(CompletionTest, SkipExplicitObjectParameter) {
4448 void foo(this auto&& self, int arg);
4449 void bar(this A self, int arg);
4468 TU.ExtraArgs = {
"-std=c++23"};
4476 auto Inputs = TU.inputs(FS);
4481 EXPECT_THAT(Result.Completions,
4482 UnorderedElementsAre(AllOf(named(
"foo"), signature(
"(int arg)"),
4483 snippetSuffix(
"(${1:int arg})")),
4484 AllOf(named(
"bar"), signature(
"(int arg)"),
4485 snippetSuffix(
"(${1:int arg})"))));
4492 ElementsAre(AllOf(named(
"foo"), signature(
"<class self:auto>(int arg)"),
4493 snippetSuffix(
"<${1:class self:auto}>"))));
4498 EXPECT_THAT(Result.Completions,
4499 ElementsAre(AllOf(named(
"bar"), signature(
"(int arg)"),
4500 snippetSuffix(
""))));
4504TEST(CompletionTest, MemberAccessInExplicitObjMemfn) {
4508 int memberFnA(int a);
4509 int memberFnA(this A&, float a);
4511 void foo(this A& self) {
4512 // Should not offer any members here, since
4513 // it needs to be referenced through `self`.
4515 // should offer all results
4519 // should not offer any results
4527 TU.ExtraArgs = {
"-std=c++23"};
4535 auto Inputs = TU.inputs(FS);
4541 EXPECT_THAT(Result.Completions, ElementsAre());
4549 UnorderedElementsAre(named(
"member"),
4550 AllOf(named(
"memberFnA"), signature(
"(int a)"),
4551 snippetSuffix(
"(${1:int a})")),
4552 AllOf(named(
"memberFnA"), signature(
"(float a)"),
4553 snippetSuffix(
"(${1:float a})"))));
4559 EXPECT_THAT(Result.Completions, ElementsAre());
4563TEST(CompletionTest, ListExplicitObjectOverloads) {
4567 void foo2(int a) const;
4568 void foo2(this const S& self, float a);
4569 void foo3(this const S& self, int a);
4570 void foo4(this S& self, int a);
4573 void S::foo1(int a) {
4577 void S::foo2(int a) const {
4581 void S::foo3(this const S& self, int a) {
4585 void S::foo4(this S& self, int a) {
4593 void test2(const S s) {
4599 TU.ExtraArgs = {
"-std=c++23"};
4607 auto Inputs = TU.inputs(FS);
4614 UnorderedElementsAre(AllOf(named(
"foo1"), signature(
"(int a)"),
4615 snippetSuffix(
"(${1:int a})")),
4616 AllOf(named(
"foo2"), signature(
"(int a) const"),
4617 snippetSuffix(
"(${1:int a})")),
4618 AllOf(named(
"foo2"), signature(
"(float a) const"),
4619 snippetSuffix(
"(${1:float a})")),
4620 AllOf(named(
"foo3"), signature(
"(int a) const"),
4621 snippetSuffix(
"(${1:int a})")),
4622 AllOf(named(
"foo4"), signature(
"(int a)"),
4623 snippetSuffix(
"(${1:int a})"))));
4630 UnorderedElementsAre(AllOf(named(
"foo2"), signature(
"(int a) const"),
4631 snippetSuffix(
"(${1:int a})")),
4632 AllOf(named(
"foo2"), signature(
"(float a) const"),
4633 snippetSuffix(
"(${1:float a})")),
4634 AllOf(named(
"foo3"), signature(
"(int a) const"),
4635 snippetSuffix(
"(${1:int a})"))));
4642 UnorderedElementsAre(AllOf(named(
"foo2"), signature(
"(int a) const"),
4643 snippetSuffix(
"(${1:int a})")),
4644 AllOf(named(
"foo2"), signature(
"(float a) const"),
4645 snippetSuffix(
"(${1:float a})")),
4646 AllOf(named(
"foo3"), signature(
"(int a) const"),
4647 snippetSuffix(
"(${1:int a})"))));
4654 UnorderedElementsAre(AllOf(named(
"foo1"), signature(
"(int a)"),
4655 snippetSuffix(
"(${1:int a})")),
4656 AllOf(named(
"foo2"), signature(
"(int a) const"),
4657 snippetSuffix(
"(${1:int a})")),
4658 AllOf(named(
"foo2"), signature(
"(float a) const"),
4659 snippetSuffix(
"(${1:float a})")),
4660 AllOf(named(
"foo3"), signature(
"(int a) const"),
4661 snippetSuffix(
"(${1:int a})")),
4662 AllOf(named(
"foo4"), signature(
"(int a)"),
4663 snippetSuffix(
"(${1:int a})"))));
4670 UnorderedElementsAre(AllOf(named(
"foo1"), signature(
"(int a)"),
4671 snippetSuffix(
"(${1:int a})")),
4672 AllOf(named(
"foo2"), signature(
"(int a) const"),
4673 snippetSuffix(
"(${1:int a})")),
4674 AllOf(named(
"foo2"), signature(
"(float a) const"),
4675 snippetSuffix(
"(${1:float a})")),
4676 AllOf(named(
"foo3"), signature(
"(int a) const"),
4677 snippetSuffix(
"(${1:int a})")),
4678 AllOf(named(
"foo4"), signature(
"(int a)"),
4679 snippetSuffix(
"(${1:int a})"))));
4686 UnorderedElementsAre(AllOf(named(
"foo2"), signature(
"(int a) const"),
4687 snippetSuffix(
"(${1:int a})")),
4688 AllOf(named(
"foo2"), signature(
"(float a) const"),
4689 snippetSuffix(
"(${1:float a})")),
4690 AllOf(named(
"foo3"), signature(
"(int a) const"),
4691 snippetSuffix(
"(${1:int a})"))));
#define EXPECT_IFF(condition, value, matcher)
Same as llvm::Annotations, but adjusts functions to LSP-specific types for positions and ranges.
clangd::Range range(llvm::StringRef Name="") const
Manages a collection of source files and derived data (ASTs, indexes), and provides language-aware fe...
static Options optsForTest()
A context is an immutable container for per-request data that must be propagated through layers that ...
static std::unique_ptr< SymbolIndex > build(SymbolSlab Symbols, RefSlab Refs, RelationSlab Relations)
Builds an index from slabs. The index takes ownership of the data.
llvm::StringMap< std::string > Files
An efficient structure of storing large set of symbol references in memory.
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
SymbolSlab::Builder is a mutable container that can 'freeze' to SymbolSlab.
void insert(const Symbol &S)
Adds a symbol, overwriting any existing one with the same ID.
static llvm::Expected< URI > create(llvm::StringRef AbsolutePath, llvm::StringRef Scheme)
Creates a URI for a file in the given scheme.
WithContextValue extends Context::current() with a single value.
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
Symbol objcProtocol(llvm::StringRef Name)
Symbol objcClass(llvm::StringRef Name)
Symbol func(llvm::StringRef Name)
Symbol cls(llvm::StringRef Name)
Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName)
std::string sortText(float Score, llvm::StringRef Name)
Returns a string that sorts in the same order as (-Score, Tiebreak), for LSP.
Symbol conceptSym(llvm::StringRef Name)
IndexContents
Describes what data is covered by an index.
size_t lspLength(llvm::StringRef Code)
CompletionPrefix guessCompletionPrefix(llvm::StringRef Content, unsigned Offset)
std::unique_ptr< CompilerInvocation > buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D, std::vector< std::string > *CC1Args)
Builds compiler invocation that could be used to build AST or preamble.
Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, llvm::StringRef USRFormat, llvm::StringRef Signature)
CompletionItemKind
The kind of a completion entry.
Symbol ns(llvm::StringRef Name)
bool allowImplicitCompletion(llvm::StringRef Content, unsigned Offset)
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
llvm::Expected< CodeCompleteResult > runCodeComplete(ClangdServer &Server, PathRef File, Position Pos, clangd::CodeCompleteOptions Opts)
llvm::Expected< SignatureHelp > runSignatureHelp(ClangdServer &Server, PathRef File, Position Pos, MarkupKind DocumentationFormat)
std::string testPath(PathRef File, llvm::sys::path::Style Style)
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.
TEST(BackgroundQueueTest, Priority)
void wait(std::unique_lock< std::mutex > &Lock, std::condition_variable &CV, Deadline D)
Wait once on CV for the specified duration.
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
void runAddDocument(ClangdServer &Server, PathRef File, llvm::StringRef Contents, llvm::StringRef Version, WantDiagnostics WantDiags, bool ForceRebuild)
Symbol macro(llvm::StringRef Name, llvm::StringRef ArgList)
llvm::StringRef PathRef
A typedef to represent a ref to file path.
@ No
Diagnostics must be generated for this snapshot.
std::vector< std::string > lookup(const SymbolIndex &I, llvm::ArrayRef< SymbolID > IDs)
Symbol enmConstant(llvm::StringRef Name)
Deadline timeoutSeconds(std::optional< double > Seconds)
Makes a deadline from a timeout in seconds. std::nullopt means wait forever.
CodeCompleteResult codeComplete(PathRef FileName, Position Pos, const PreambleData *Preamble, const ParseInputs &ParseInput, CodeCompleteOptions Opts, SpeculativeFuzzyFind *SpecFuzzyFind)
Gets code completions at a specified Pos in FileName.
@ PlainText
The primary text to be inserted is treated as a plain string.
@ Snippet
The primary text to be inserted is treated as a snippet.
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)
cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccess P
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Signals derived from a valid AST of a file.
llvm::DenseMap< SymbolID, unsigned > ReferencedSymbols
Number of occurrences of each symbol present in the file.
Symbol::IncludeDirective InsertionDirective
Preferred preprocessor directive to use for inclusions by the file.
Represents a collection of completion items to be presented in the editor.
Settings that express user/project preferences and control clangd behavior.
static clangd::Key< Config > Key
Context key which can be used to set the current Config.
@ None
nothing, no argument list and also NO Delimiters "()" or "<>".
@ Delimiters
empty pair of delimiters "()" or "<>".
@ OpenDelimiter
open, only opening delimiter "(" or "<".
Same semantics as CodeComplete::Score.
std::vector< std::string > Scopes
If this is non-empty, symbols must be in at least one of the scopes (e.g.
int line
Line position in a document (zero-based).
int character
Character offset on a line in a document (zero-based).
Position end
The range's end position.
Represents the signature of a callable.
Attributes of a symbol that affect how much we like it.
Attributes of a symbol-query pair that affect how much we like it.
The class presents a C++ symbol, e.g.
@ IndexedForCodeCompletion
Whether or not this symbol is meant to be used for the code completion.
@ Include
#include "header.h"
@ Import
#import "header.h"
SymbolID ID
The ID of the symbol.
std::vector< std::string > ExtraArgs
static TestTU withHeaderCode(llvm::StringRef HeaderCode)
static TestTU withCode(llvm::StringRef Code)
llvm::StringMap< std::string > AdditionalFiles
std::unique_ptr< SymbolIndex > index() const
Range range
The range of the text document to be manipulated.