24 #include "clang/Sema/CodeCompleteConsumer.h" 25 #include "clang/Tooling/CompilationDatabase.h" 26 #include "llvm/Support/Error.h" 27 #include "llvm/Support/Path.h" 28 #include "llvm/Testing/Support/Error.h" 29 #include "gmock/gmock.h" 30 #include "gtest/gtest.h" 31 #include <condition_variable> 39 using ::testing::AllOf;
40 using ::testing::Contains;
41 using ::testing::ElementsAre;
42 using ::testing::Field;
43 using ::testing::HasSubstr;
44 using ::testing::IsEmpty;
46 using ::testing::UnorderedElementsAre;
48 class IgnoreDiagnostics :
public DiagnosticsConsumer {
50 std::vector<Diag> Diagnostics)
override {}
56 return llvm::StringRef(arg.Name).startswith(Prefix);
58 MATCHER_P(Scope, S,
"") {
return arg.Scope == S; }
59 MATCHER_P(Qualifier, Q,
"") {
return arg.RequiredQualifier == Q; }
61 return arg.RequiredQualifier + arg.Name + arg.Signature == Label;
63 MATCHER_P(SigHelpLabeled, Label,
"") {
return arg.label == Label; }
65 MATCHER_P(Doc, D,
"") {
return arg.Documentation == D; }
68 return !arg.Includes.empty() && arg.Includes[0].Header ==
IncludeHeader;
71 return !arg.Includes.empty() && arg.Includes[0].Header ==
IncludeHeader &&
72 bool(arg.Includes[0].Insertion);
75 return !arg.Includes.empty() && bool(arg.Includes[0].Insertion);
78 MATCHER_P(Origin, OriginSet,
"") {
return arg.Origin == OriginSet; }
82 Matcher<const std::vector<CodeCompletion> &> Has(std::string
Name) {
83 return Contains(Named(std::move(Name)));
85 Matcher<const std::vector<CodeCompletion> &> Has(std::string Name,
87 return Contains(AllOf(Named(std::move(Name)),
Kind(K)));
89 MATCHER(IsDocumented,
"") {
return !arg.Documentation.empty(); }
90 MATCHER(Deprecated,
"") {
return arg.Deprecated; }
92 std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol>
Symbols) {
94 for (
const auto &Sym : Symbols)
96 return MemIndex::build(std::move(Slab).build(), RefSlab(), RelationSlab());
99 CodeCompleteResult completions(ClangdServer &
Server, llvm::StringRef TestCode,
101 std::vector<Symbol> IndexSymbols = {},
102 clangd::CodeCompleteOptions Opts = {}) {
103 std::unique_ptr<SymbolIndex> OverrideIndex;
104 if (!IndexSymbols.empty()) {
105 assert(!Opts.Index &&
"both Index and IndexSymbols given!");
106 OverrideIndex = memIndex(std::move(IndexSymbols));
107 Opts.Index = OverrideIndex.get();
112 auto CompletionList =
114 return CompletionList;
117 CodeCompleteResult completions(ClangdServer &Server, llvm::StringRef
Text,
118 std::vector<Symbol> IndexSymbols = {},
119 clangd::CodeCompleteOptions Opts = {},
120 PathRef FilePath =
"foo.cpp") {
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 Annotations Test(Text);
131 auto CompletionList =
133 return CompletionList;
138 CodeCompleteResult completions(llvm::StringRef Text,
139 std::vector<Symbol> IndexSymbols = {},
140 clangd::CodeCompleteOptions Opts = {},
141 PathRef FilePath =
"foo.cpp") {
143 MockCompilationDatabase CDB;
145 CDB.ExtraClangFlags = {
"-fno-delayed-template-parsing"};
148 return completions(Server, Text, std::move(IndexSymbols), std::move(Opts),
154 CodeCompleteResult completionsNoCompile(llvm::StringRef Text,
155 std::vector<Symbol> IndexSymbols = {},
156 clangd::CodeCompleteOptions Opts = {},
157 PathRef FilePath =
"foo.cpp") {
158 std::unique_ptr<SymbolIndex> OverrideIndex;
159 if (!IndexSymbols.empty()) {
160 assert(!Opts.Index &&
"both Index and IndexSymbols given!");
161 OverrideIndex = memIndex(std::move(IndexSymbols));
162 Opts.Index = OverrideIndex.get();
166 Annotations Test(Text);
167 return codeComplete(FilePath, tooling::CompileCommand(),
nullptr,
168 Test.code(), Test.point(), FS.getFileSystem(), Opts);
171 Symbol withReferences(
int N, Symbol S) {
177 clangd::CodeCompleteOptions Opts;
179 auto Results = completions(R
"cpp( 180 struct ClassWithMembers { 186 int main() { ClassWithMembers().^ } 191 EXPECT_THAT(
Results.Completions, ElementsAre(Named(
"AAA"), Named(
"BBB")));
194 TEST(CompletionTest, Filter) {
195 std::string Body = R
"cpp( 206 EXPECT_THAT(completions(Body +
"int main() { S().Foba^ }").Completions,
207 AllOf(Has(
"FooBar"), Has(
"FooBaz"), Not(Has(
"Qux"))));
210 EXPECT_THAT(completions(Body +
"int main() { C^ }").Completions,
211 AllOf(Has(
"Car"), Not(Has(
"MotorCar"))));
214 void testAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
221 // Make sure this is not in preamble. 224 struct GlobalClass {}; 226 struct ClassWithMembers { 236 struct LocalClass {};
244 {
cls(
"IndexClass"),
var(
"index_var"),
func(
"index_func")}, Opts);
246 EXPECT_TRUE(
Results.RanParser);
249 EXPECT_THAT(
Results.Completions,
250 AllOf(Has(
"method"), Has(
"field"), Not(Has(
"ClassWithMembers")),
251 Not(Has(
"operator=")), Not(Has(
"~ClassWithMembers"))));
253 Has(
"private_field"));
257 Not(AnyOf(Has(
"global_var"), Has(
"index_var"), Has(
"global_func"),
258 Has(
"global_func()"), Has(
"index_func"), Has(
"GlobalClass"),
259 Has(
"IndexClass"), Has(
"MACRO"), Has(
"LocalClass"))));
262 EXPECT_THAT(
Results.Completions,
266 Contains(IsDocumented()));
269 void testGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
275 // Make sure this is not in preamble. 278 struct GlobalClass {}; 280 struct ClassWithMembers { 286 struct LocalClass {};
294 {
cls(
"IndexClass"),
var(
"index_var"),
func(
"index_func")}, Opts);
296 EXPECT_TRUE(
Results.RanParser);
298 EXPECT_THAT(
Results.Completions,
299 Not(AnyOf(Has(
"method"), Has(
"method()"), Has(
"field"))));
301 EXPECT_THAT(
Results.Completions,
302 AllOf(Has(
"global_var"), Has(
"index_var"), Has(
"global_func"),
304 Has(
"GlobalClass"), Has(
"IndexClass")));
308 EXPECT_THAT(
Results.Completions,
309 AllOf(Has(
"local_var"), Has(
"LocalClass"),
313 Contains(IsDocumented()));
316 TEST(CompletionTest, CompletionOptions) {
317 auto Test = [&](
const clangd::CodeCompleteOptions &Opts) {
318 testAfterDotCompletion(Opts);
319 testGlobalScopeCompletion(Opts);
331 for (
auto &F :
Flags) {
332 clangd::CodeCompleteOptions O;
338 TEST(CompletionTest, Accessible) {
339 auto Internal = completions(R
"cpp( 342 protected: void prot(); 343 private: void priv(); 345 void Foo::pub() { this->^ } 347 EXPECT_THAT(Internal.Completions, 348 AllOf(Has("priv"), Has(
"prot"), Has(
"pub")));
350 auto External = completions(R
"cpp( 353 protected: void prot(); 354 private: void priv(); 361 EXPECT_THAT(External.Completions, 362 AllOf(Has("pub"), Not(Has(
"prot")), Not(Has(
"priv"))));
365 TEST(CompletionTest, Qualifiers) {
366 auto Results = completions(R
"cpp( 368 public: int foo() const; 371 class Bar : public Foo { 374 void test() { Bar().^ } 376 EXPECT_THAT(Results.Completions, 377 Contains(AllOf(Qualifier(""), Named(
"bar"))));
379 EXPECT_THAT(
Results.Completions,
380 Not(Contains(AllOf(
Qualifier(
"Foo::"), Named(
"foo")))));
382 EXPECT_THAT(
Results.Completions,
383 Not(Contains(AllOf(
Qualifier(
""), Named(
"foo")))));
386 TEST(CompletionTest, InjectedTypename) {
388 EXPECT_THAT(completions(
"struct X{}; void foo(){ X().^ }").Completions,
390 EXPECT_THAT(completions(
"struct X{ void foo(){ this->^ } };").Completions,
393 EXPECT_THAT(completions(
"struct X{ void foo(){ ^ } };").Completions,
396 completions(
"struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions,
400 "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };")
404 EXPECT_THAT(completions(
"struct X{}; void foo(){ X::^ }").Completions,
408 TEST(CompletionTest, SkipInjectedWhenUnqualified) {
409 EXPECT_THAT(completions(
"struct X { void f() { X^ }};").Completions,
410 ElementsAre(Named(
"X"), Named(
"~X")));
413 TEST(CompletionTest, Snippets) {
414 clangd::CodeCompleteOptions Opts;
419 int f(int i, const float f) const; 433 TEST(CompletionTest, NoSnippetsInUsings) {
434 clangd::CodeCompleteOptions Opts;
435 Opts.EnableSnippets =
true;
439 int func(int a, int b); 445 EXPECT_THAT(
Results.Completions,
446 ElementsAre(AllOf(Named(
"func"), Labeled(
"func(int a, int b)"),
450 auto Func =
func(
"ns::func");
451 Func.CompletionSnippetSuffix =
"(${1:int a}, ${2: int b})";
452 Func.Signature =
"(int a, int b)";
453 Func.ReturnType =
"void";
460 EXPECT_THAT(
Results.Completions,
461 ElementsAre(AllOf(Named(
"func"), Labeled(
"func(int a, int b)"),
465 Opts.AllScopes =
true;
470 EXPECT_THAT(
Results.Completions,
471 Contains(AllOf(Named(
"func"), Labeled(
"ns::func(int a, int b)"),
475 TEST(CompletionTest, Kinds) {
481 // make sure MACRO is not included in preamble. 485 {func("indexFunction"),
var(
"indexVariable"),
cls(
"indexClass")});
486 EXPECT_THAT(
Results.Completions,
497 EXPECT_THAT(
Results.Completions,
517 template <class T> struct complete_class {}; 518 template <class T> void complete_function(); 519 template <class T> using complete_type_alias = int; 520 template <class T> int complete_variable = 10; 523 template <class T> static int complete_static_member = 10; 525 static auto x = complete_^ 530 UnorderedElementsAre( 533 AllOf(Named(
"complete_type_alias"),
536 AllOf(Named(
"complete_static_member"),
540 TEST(CompletionTest, NoDuplicates) {
553 EXPECT_THAT(
Results.Completions, ElementsAre(Named(
"Adapter")));
556 TEST(CompletionTest, ScopedNoIndex) {
559 namespace fake { int BigBang, Babble, Box; }; 560 int main() { fake::ba^ } 563 EXPECT_THAT(
Results.Completions,
564 ElementsAre(Named(
"Babble"), Named(
"BigBang")));
567 TEST(CompletionTest, Scoped) {
570 namespace fake { int Babble, Box; }; 571 int main() { fake::ba^ } 573 {var("fake::BigBang")});
574 EXPECT_THAT(
Results.Completions,
575 ElementsAre(Named(
"Babble"), Named(
"BigBang")));
578 TEST(CompletionTest, ScopedWithFilter) {
583 {cls("ns::XYZ"),
func(
"ns::foo")});
584 EXPECT_THAT(
Results.Completions, UnorderedElementsAre(Named(
"XYZ")));
587 TEST(CompletionTest, ReferencesAffectRanking) {
588 auto Results = completions(
"int main() { abs^ }", {
ns(
"absl"),
func(
"absb")});
589 EXPECT_THAT(
Results.Completions,
591 Results = completions(
"int main() { abs^ }",
592 {withReferences(10000,
ns(
"absl")),
func(
"absb")});
593 EXPECT_THAT(
Results.Completions,
597 TEST(CompletionTest, ContextWords) {
598 auto Results = completions(R
"cpp( 599 enum class Color { RED, YELLOW, BLUE }; 601 // (blank lines so the definition above isn't "context") 603 // "It was a yellow car," he said. "Big yellow car, new." 604 auto Finish = Color::^ 608 ASSERT_THAT(
Results.Completions,
612 TEST(CompletionTest, GlobalQualified) {
618 EXPECT_THAT(
Results.Completions,
623 TEST(CompletionTest, FullyQualified) {
626 namespace ns { void bar(); } 630 EXPECT_THAT(
Results.Completions,
635 TEST(CompletionTest, SemaIndexMerge) {
638 namespace ns { int local; void both(); } 641 {func("ns::both"),
cls(
"ns::Index")});
643 EXPECT_THAT(
Results.Completions,
644 UnorderedElementsAre(
651 TEST(CompletionTest, SemaIndexMergeWithLimit) {
652 clangd::CodeCompleteOptions Opts;
656 namespace ns { int local; void both(); } 659 {func("ns::both"),
cls(
"ns::Index")}, Opts);
660 EXPECT_EQ(
Results.Completions.size(), Opts.Limit);
664 TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
666 MockCompilationDatabase CDB;
669 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
670 std::string BarHeader =
testPath(
"sub/bar.h");
671 FS.Files[BarHeader] =
"";
676 Symbol Sym =
cls(
"ns::X");
677 Sym.CanonicalDeclaration.FileURI = BarURI.c_str();
678 Sym.IncludeHeaders.emplace_back(BarURI, 1);
680 auto Results = completions(Server,
685 EXPECT_THAT(Results.Completions, 686 ElementsAre(AllOf(Named("X"), InsertInclude(
"\"bar.h\""))));
688 CodeCompleteOptions NoInsertion;
695 EXPECT_THAT(Results.Completions, 696 ElementsAre(AllOf(Named("X"), Not(InsertInclude()))));
700 #include "sub/bar.h" // not shortest, so should only match resolved. 704 EXPECT_THAT(Results.Completions, ElementsAre(AllOf(Named("X"), Labeled(
"X"),
705 Not(InsertInclude()))));
708 TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {
710 MockCompilationDatabase CDB;
714 Symbol SymX =
cls(
"ns::X");
715 Symbol SymY =
cls(
"ns::Y");
716 std::string BarHeader =
testPath(
"bar.h");
718 SymX.CanonicalDeclaration.FileURI = BarURI.c_str();
719 SymY.CanonicalDeclaration.FileURI = BarURI.c_str();
720 SymX.IncludeHeaders.emplace_back(
"<bar>", 1);
721 SymY.IncludeHeaders.emplace_back(
"<bar>", 1);
723 auto Results = completions(Server,
732 EXPECT_THAT(Results.Completions, 733 ElementsAre(AllOf(Named("X"), Not(InsertInclude())),
734 AllOf(Named(
"Y"), Not(InsertInclude()))));
737 TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
739 MockCompilationDatabase CDB;
744 R
"cpp(namespace ns { struct preamble { int member; }; })cpp"; 746 Annotations Test(R
"cpp( 748 namespace ns { int local; } 750 void f2() { ns::preamble().$2^; } 753 clangd::CodeCompleteOptions Opts = {}; 755 auto I = memIndex({
var(
"ns::index")});
756 Opts.Index = I.get();
758 EXPECT_THAT(WithIndex.Completions,
759 UnorderedElementsAre(Named(
"local"), Named(
"index")));
760 auto ClassFromPreamble =
762 EXPECT_THAT(ClassFromPreamble.Completions, Contains(Named(
"member")));
764 Opts.Index =
nullptr;
767 EXPECT_THAT(WithoutIndex.Completions,
768 UnorderedElementsAre(Named(
"local"), Named(
"preamble")));
775 TEST(CompletionTest, CompletionInPreamble) {
776 auto Results = completions(R
"cpp( 784 EXPECT_THAT(Results, ElementsAre(Named("ifndef")));
787 TEST(CompletionTest, DynamicIndexIncludeInsertion) {
789 MockCompilationDatabase CDB;
792 Opts.BuildDynamicSymbolIndex =
true;
793 ClangdServer
Server(CDB, FS, DiagConsumer, Opts);
795 FS.Files[
testPath(
"foo_header.h")] = R
"cpp( 802 const std::string FileContent(R
"cpp( 803 #include "foo_header.h" 808 Server.addDocument(testPath("foo_impl.cpp"), FileContent);
810 ASSERT_TRUE(Server.blockUntilIdleForTest());
811 EXPECT_THAT(completions(Server,
"Foo^ foo;").Completions,
812 ElementsAre(AllOf(Named(
"Foo"), HasInclude(
"\"foo_header.h\""),
816 TEST(CompletionTest, DynamicIndexMultiFile) {
818 MockCompilationDatabase CDB;
821 Opts.BuildDynamicSymbolIndex =
true;
822 ClangdServer
Server(CDB, FS, DiagConsumer, Opts);
824 FS.Files[
testPath(
"foo.h")] = R
"cpp( 825 namespace ns { class XYZ {}; void foo(int x) {} } 832 Annotations Test(R
"cpp( 848 EXPECT_THAT(Results.Completions,
853 TEST(CompletionTest, Documentation) {
854 auto Results = completions(
856 // Non-doxygen comment. 868 EXPECT_THAT(Results.Completions,
869 Contains(AllOf(Named(
"foo"), Doc(
"Non-doxygen comment."))));
872 Contains(AllOf(Named(
"bar"), Doc(
"Doxygen comment.\n\\param int a"))));
873 EXPECT_THAT(Results.Completions,
874 Contains(AllOf(Named(
"baz"), Doc(
"Multi-line\nblock comment"))));
877 TEST(CompletionTest, CommentsFromSystemHeaders) {
879 MockCompilationDatabase CDB;
883 Opts.BuildDynamicSymbolIndex =
true;
885 ClangdServer
Server(CDB, FS, DiagConsumer, Opts);
887 FS.Files[
testPath(
"foo.h")] = R
"cpp( 888 #pragma GCC system_header 890 // This comment should be retained! 894 auto Results = completions(Server,
901 Contains(AllOf(Named("foo"), Doc(
"This comment should be retained!"))));
904 TEST(CompletionTest, GlobalCompletionFiltering) {
909 Symbol Func =
func(
"XYZ::foooo");
913 auto Results = completions(R
"(// void f() { 917 EXPECT_THAT(Results.Completions, IsEmpty()); 920 TEST(CodeCompleteTest, DisableTypoCorrection) { 921 auto Results = completions(R
"cpp( 922 namespace clang { int v; } 925 EXPECT_TRUE(Results.Completions.empty()); 928 TEST(CodeCompleteTest, NoColonColonAtTheEnd) { 929 auto Results = completions(R
"cpp( 936 EXPECT_THAT(Results.Completions, Contains(Labeled("clang")));
937 EXPECT_THAT(Results.Completions, Not(Contains(Labeled(
"clang::"))));
940 TEST(CompletionTest, BacktrackCrashes) {
942 auto Results = completions(R
"cpp( 950 EXPECT_THAT(Results.Completions, ElementsAre(Labeled("FooBarBaz")));
956 if (FooBarBaz * x^) {} 961 TEST(CompletionTest, CompleteInMacroWithStringification) { 962 auto Results = completions(R
"cpp( 963 void f(const char *, int x); 964 #define F(x) f(#x, x) 971 int f(int input_num) { 976 EXPECT_THAT(Results.Completions, 977 UnorderedElementsAre(Named("X"), Named(
"Y")));
980 TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
981 auto Results = completions(R
"cpp( 982 void f(const char *, int x); 983 #define F(x) f(#x, x) 988 int f(int input_num) { 994 EXPECT_THAT(Results.Completions, Contains(Named("X")));
997 TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
998 auto Results = completions(R
"cpp( 999 int bar(int param_in_bar) { 1002 int foo(int param_in_foo) { 1004 // In recorvery mode, "param_in_foo" will also be suggested among many other 1005 // unrelated symbols; however, this is really a special case where this works. 1006 // If the #if block is outside of the function, "param_in_foo" is still 1007 // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't 1008 // really provide useful results in excluded branches. 1014 EXPECT_TRUE(Results.Completions.empty()); 1017 TEST(CompletionTest, DefaultArgs) { 1018 clangd::CodeCompleteOptions Opts; 1019 std::string Context = R"cpp( 1021 int Y(int A, int B = 0); 1022 int Z(int A, int B = 0, int C = 0, int D = 0); 1024 EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions,
1025 UnorderedElementsAre(Labeled(
"X(int A = 0)")));
1026 EXPECT_THAT(completions(Context +
"int y = Y^", {}, Opts).Completions,
1027 UnorderedElementsAre(AllOf(Labeled(
"Y(int A, int B = 0)"),
1029 EXPECT_THAT(completions(Context +
"int y = Z^", {}, Opts).Completions,
1030 UnorderedElementsAre(
1031 AllOf(Labeled(
"Z(int A, int B = 0, int C = 0, int D = 0)"),
1035 TEST(CompletionTest, NoCrashWithTemplateParamsAndPreferredTypes) {
1036 auto Completions = completions(R
"cpp( 1037 template <template <class> class TT> int foo() { 1042 EXPECT_THAT(Completions, Contains(Named("TT")));
1045 SignatureHelp signatures(llvm::StringRef Text, Position Point,
1046 std::vector<Symbol> IndexSymbols = {}) {
1047 std::unique_ptr<SymbolIndex>
Index;
1048 if (!IndexSymbols.empty())
1049 Index = memIndex(IndexSymbols);
1052 MockCompilationDatabase CDB;
1055 Opts.StaticIndex = Index.get();
1057 ClangdServer
Server(CDB, FS, DiagConsumer, Opts);
1063 SignatureHelp signatures(llvm::StringRef Text,
1064 std::vector<Symbol> IndexSymbols = {}) {
1065 Annotations Test(Text);
1066 return signatures(Test.code(), Test.point(), std::move(IndexSymbols));
1069 struct ExpectedParameter {
1074 if (P.size() != arg.parameters.size())
1076 for (
unsigned I = 0; I < P.size(); ++I) {
1077 if (P[I].Text != arg.parameters[I].labelString ||
1078 P[I].Offsets != arg.parameters[I].labelOffsets)
1083 MATCHER_P(SigDoc, Doc,
"") {
return arg.documentation == Doc; }
1087 Matcher<SignatureInformation> Sig(llvm::StringRef AnnotatedLabel) {
1088 llvm::Annotations A(AnnotatedLabel);
1089 std::string Label = A.code();
1091 for (
auto Range : A.ranges()) {
1092 Parameters.emplace_back();
1094 ExpectedParameter &P = Parameters.back();
1096 P.Offsets.first =
lspLength(llvm::StringRef(Label).substr(0,
Range.Begin));
1097 P.Offsets.second =
lspLength(llvm::StringRef(Label).substr(1,
Range.End));
1099 return AllOf(SigHelpLabeled(Label), ParamsAre(Parameters));
1102 TEST(SignatureHelpTest, Overloads) {
1103 auto Results = signatures(R
"cpp( 1104 void foo(int x, int y); 1105 void foo(int x, float y); 1106 void foo(float x, int y); 1107 void foo(float x, float y); 1108 void bar(int x, int y = 0); 1109 int main() { foo(^); } 1111 EXPECT_THAT(Results.signatures, 1112 UnorderedElementsAre(Sig("foo([[float x]], [[float y]]) -> void"),
1113 Sig(
"foo([[float x]], [[int y]]) -> void"),
1114 Sig(
"foo([[int x]], [[float y]]) -> void"),
1115 Sig(
"foo([[int x]], [[int y]]) -> void")));
1117 EXPECT_EQ(0, Results.activeSignature);
1118 EXPECT_EQ(0, Results.activeParameter);
1121 TEST(SignatureHelpTest, DefaultArgs) {
1122 auto Results = signatures(R
"cpp( 1123 void bar(int x, int y = 0); 1124 void bar(float x = 0, int y = 42); 1127 EXPECT_THAT(Results.signatures, 1128 UnorderedElementsAre( 1129 Sig("bar([[int x]], [[int y = 0]]) -> void"),
1130 Sig(
"bar([[float x = 0]], [[int y = 42]]) -> void")));
1131 EXPECT_EQ(0, Results.activeSignature);
1132 EXPECT_EQ(0, Results.activeParameter);
1135 TEST(SignatureHelpTest, ActiveArg) {
1136 auto Results = signatures(R
"cpp( 1137 int baz(int a, int b, int c); 1138 int main() { baz(baz(1,2,3), ^); } 1140 EXPECT_THAT(Results.signatures, 1141 ElementsAre(Sig("baz([[int a]], [[int b]], [[int c]]) -> int")));
1142 EXPECT_EQ(0, Results.activeSignature);
1143 EXPECT_EQ(1, Results.activeParameter);
1146 TEST(SignatureHelpTest, OpeningParen) {
1147 llvm::StringLiteral Tests[] = {
1149 int foo(int a, int b, int c); 1151 foo(foo $p^( foo(10, 10, 10), ^ ))); 1156 Foo(int a, int b, int c); 1164 Foo(int a, int b, int c); 1167 new Foo $p^( 10, ^ ); 1171 int foo(int a, int b, int c); 1175 // Macro expansions. 1180 int foo(int a, int b, int c); 1183 ID(foo $p^( foo(10), ^ )) 1186 for (
auto Test : Tests) {
1187 Annotations
Code(Test);
1188 EXPECT_EQ(signatures(Code.code(), Code.point()).argListStart,
1190 <<
"Test source:" << Test;
1194 class IndexRequestCollector :
public SymbolIndex {
1197 fuzzyFind(
const FuzzyFindRequest &Req,
1198 llvm::function_ref<
void(
const Symbol &)>
Callback)
const override {
1199 std::unique_lock<std::mutex> Lock(Mut);
1200 Requests.push_back(Req);
1201 ReceivedRequestCV.notify_one();
1205 void lookup(
const LookupRequest &,
1206 llvm::function_ref<
void(
const Symbol &)>)
const override {}
1208 bool refs(
const RefsRequest &,
1209 llvm::function_ref<
void(
const Ref &)>)
const override {
1213 void relations(
const RelationsRequest &,
1214 llvm::function_ref<
void(
const SymbolID &,
const Symbol &)>)
1219 size_t estimateMemoryUsage()
const override {
return 0; }
1221 const std::vector<FuzzyFindRequest> consumeRequests(
size_t Num)
const {
1222 std::unique_lock<std::mutex> Lock(Mut);
1224 [
this, Num] {
return Requests.size() == Num; }));
1225 auto Reqs = std::move(Requests);
1232 mutable std::condition_variable ReceivedRequestCV;
1233 mutable std::mutex Mut;
1234 mutable std::vector<FuzzyFindRequest> Requests;
1238 std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef
Code,
1240 clangd::CodeCompleteOptions Opts;
1241 IndexRequestCollector Requests;
1242 Opts.Index = &Requests;
1243 completions(Code, {}, Opts);
1244 const auto Reqs = Requests.consumeRequests(Num);
1245 EXPECT_EQ(Reqs.size(), Num);
1249 TEST(CompletionTest, UnqualifiedIdQuery) {
1250 auto Requests = captureIndexRequests(R
"cpp( 1252 using namespace std; 1260 EXPECT_THAT(Requests, 1262 UnorderedElementsAre("",
"ns::",
"std::"))));
1265 TEST(CompletionTest, EnclosingScopeComesFirst) {
1266 auto Requests = captureIndexRequests(R
"cpp( 1268 using namespace std; 1280 EXPECT_THAT(Requests, 1283 UnorderedElementsAre("",
"std::",
"nx::ns::",
"nx::"))));
1284 EXPECT_EQ(Requests[0].Scopes[0],
"nx::ns::");
1287 TEST(CompletionTest, ResolvedQualifiedIdQuery) {
1288 auto Requests = captureIndexRequests(R
"cpp( 1290 namespace ns2 {} // ignore 1291 namespace ns3 { namespace nns3 {} } 1293 using namespace ns1; 1294 using namespace ns3::nns3; 1303 EXPECT_THAT(Requests, 1306 UnorderedElementsAre("foo::",
"ns1::",
"ns3::nns3::"))));
1309 TEST(CompletionTest, UnresolvedQualifierIdQuery) {
1310 auto Requests = captureIndexRequests(R
"cpp( 1320 EXPECT_THAT(Requests, 1323 UnorderedElementsAre("a::bar::",
"ns::bar::",
"bar::"))));
1326 TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
1327 auto Requests = captureIndexRequests(R
"cpp( 1338 UnorderedElementsAre("a::bar::"))));
1341 TEST(CompletionTest, EmptyQualifiedQuery) {
1342 auto Requests = captureIndexRequests(R
"cpp( 1351 UnorderedElementsAre("",
"ns::"))));
1354 TEST(CompletionTest, GlobalQualifiedQuery) {
1355 auto Requests = captureIndexRequests(R
"cpp( 1364 UnorderedElementsAre(""))));
1367 TEST(CompletionTest, NoDuplicatedQueryScopes) {
1368 auto Requests = captureIndexRequests(R
"cpp( 1379 EXPECT_THAT(Requests, 1381 UnorderedElementsAre("na::",
"na::nb::",
""))));
1384 TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
1385 auto Completions = completions(
1388 int SomeNameOfField; 1389 typedef int SomeNameOfTypedefField; 1393 {func("::SomeNameInTheIndex"),
func(
"::Foo::SomeNameInTheIndex")});
1395 EXPECT_THAT(Completions.Completions,
1396 AllOf(Contains(Labeled(
"SomeNameOfField")),
1397 Contains(Labeled(
"SomeNameOfTypedefField")),
1398 Not(Contains(Labeled(
"SomeNameInTheIndex")))));
1401 TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
1403 auto Completions = completions(
1410 {func("::SomeNameInTheIndex")});
1412 EXPECT_THAT(Completions.Completions,
1413 Not(Contains(Labeled(
"SomeNameInTheIndex"))));
1417 auto Completions = completions(
1421 T::template Y<int>::^ 1424 {func("::SomeNameInTheIndex")});
1426 EXPECT_THAT(Completions.Completions,
1427 Not(Contains(Labeled(
"SomeNameInTheIndex"))));
1431 auto Completions = completions(
1438 {func("::SomeNameInTheIndex")});
1440 EXPECT_THAT(Completions.Completions,
1441 Not(Contains(Labeled(
"SomeNameInTheIndex"))));
1445 TEST(CompletionTest, OverloadBundling) {
1446 clangd::CodeCompleteOptions Opts;
1447 Opts.BundleOverloads =
true;
1449 std::string Context = R
"cpp( 1451 // Overload with int 1453 // Overload with bool 1462 EXPECT_THAT(completions(Context +
"int y = X().^", {}, Opts).Completions,
1463 UnorderedElementsAre(Labeled(
"a(…)"), Labeled(
"b(float)")));
1466 Symbol NoArgsGFunc =
func(
"GFuncC");
1468 completions(Context +
"int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1469 UnorderedElementsAre(Labeled(
"GFuncC(…)"), Labeled(
"GFuncD(int)")));
1473 NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile.c_str();
1474 NoArgsGFunc.IncludeHeaders.emplace_back(
"<foo>", 1);
1476 completions(Context +
"int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1477 UnorderedElementsAre(AllOf(Named(
"GFuncC"), InsertInclude(
"<foo>")),
1478 Labeled(
"GFuncC(int)"), Labeled(
"GFuncD(int)")));
1482 completions(Context +
"int y = X().a^", {}, Opts).Completions.front();
1483 EXPECT_EQ(A.Name,
"a");
1484 EXPECT_EQ(A.Signature,
"(…)");
1485 EXPECT_EQ(A.BundleSize, 2u);
1487 EXPECT_EQ(A.ReturnType,
"int");
1489 EXPECT_THAT(A.Documentation, AnyOf(HasSubstr(
"Overload with int"),
1490 HasSubstr(
"Overload with bool")));
1491 EXPECT_EQ(A.SnippetSuffix,
"($0)");
1494 TEST(CompletionTest, DocumentationFromChangedFileCrash) {
1498 FS.Files[FooH] = R
"cpp( 1499 // this is my documentation comment. 1502 FS.Files[FooCpp] = "";
1504 MockCompilationDatabase CDB;
1508 Annotations Source(R
"cpp( 1511 // This makes sure we have func from header in the AST. 1517 ASSERT_TRUE(Server.blockUntilIdleForTest());
1520 FS.Files[FooH] = R
"cpp( 1524 clangd::CodeCompleteOptions Opts; 1525 Opts.IncludeComments = true;
1526 CodeCompleteResult Completions =
1530 EXPECT_THAT(Completions.Completions,
1531 Contains(AllOf(Not(IsDocumented()), Named(
"func"))));
1534 TEST(CompletionTest, NonDocComments) {
1537 FS.Files[FooCpp] =
"";
1539 MockCompilationDatabase CDB;
1543 Annotations Source(R
"cpp( 1544 // We ignore namespace comments, for rationale see CodeCompletionStrings.h. 1545 namespace comments_ns { 1548 // ------------------ 1551 // A comment and a decl are separated by newlines. 1552 // Therefore, the comment shouldn't show up as doc comment. 1556 // this comment should be in the results. 1563 int comments_quux(); 1567 // This comment should not be there. 1570 int Struct<T>::comments_qux() { 1573 // This comment **should** be in results. 1575 int Struct<T>::comments_quux() { 1581 CDB.ExtraClangFlags.push_back(
"-fno-delayed-template-parsing");
1584 Server, FooCpp, Source.point(), clangd::CodeCompleteOptions()));
1588 Completions.Completions,
1589 UnorderedElementsAre(AllOf(Not(IsDocumented()), Named(
"comments_foo")),
1590 AllOf(IsDocumented(), Named(
"comments_baz")),
1591 AllOf(IsDocumented(), Named(
"comments_quux")),
1592 AllOf(Not(IsDocumented()), Named(
"comments_ns")),
1597 AllOf(IsDocumented(), Named(
"comments_bar")),
1598 AllOf(IsDocumented(), Named(
"comments_qux"))));
1601 TEST(CompletionTest, CompleteOnInvalidLine) {
1604 MockCompilationDatabase CDB;
1607 FS.Files[FooCpp] =
"// empty file";
1614 EXPECT_THAT_EXPECTED(
1619 TEST(CompletionTest, QualifiedNames) {
1620 auto Results = completions(
1622 namespace ns { int local; void both(); } 1623 void f() { ::ns::^ } 1625 {func("ns::both"),
cls(
"ns::Index")});
1628 Results.Completions,
1629 UnorderedElementsAre(Scope(
"ns::"), Scope(
"ns::"), Scope(
"ns::")));
1632 TEST(CompletionTest, Render) {
1635 C.Signature =
"(bool) const";
1636 C.SnippetSuffix =
"(${0:bool})";
1637 C.ReturnType =
"int";
1638 C.RequiredQualifier =
"Foo::";
1639 C.Scope =
"ns::Foo::";
1640 C.Documentation =
"This is x().";
1641 C.Includes.emplace_back();
1642 auto &Include = C.Includes.back();
1643 Include.Header =
"\"foo.h\"";
1645 C.Score.Total = 1.0;
1648 CodeCompleteOptions Opts;
1649 Opts.IncludeIndicator.Insert =
"^";
1650 Opts.IncludeIndicator.NoInsert =
"";
1651 Opts.EnableSnippets =
false;
1653 auto R = C.render(Opts);
1654 EXPECT_EQ(R.label,
"Foo::x(bool) const");
1655 EXPECT_EQ(R.insertText,
"Foo::x");
1657 EXPECT_EQ(R.filterText,
"x");
1658 EXPECT_EQ(R.detail,
"int\n\"foo.h\"");
1659 EXPECT_EQ(R.documentation,
"This is x().");
1660 EXPECT_THAT(R.additionalTextEdits, IsEmpty());
1661 EXPECT_EQ(R.sortText,
sortText(1.0,
"x"));
1662 EXPECT_FALSE(R.deprecated);
1664 Opts.EnableSnippets =
true;
1666 EXPECT_EQ(R.insertText,
"Foo::x(${0:bool})");
1669 Include.Insertion.emplace();
1671 EXPECT_EQ(R.label,
"^Foo::x(bool) const");
1672 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
1674 Opts.ShowOrigins =
true;
1676 EXPECT_EQ(R.label,
"^[AS]Foo::x(bool) const");
1680 EXPECT_EQ(R.detail,
"[2 overloads]\n\"foo.h\"");
1682 C.Deprecated =
true;
1684 EXPECT_TRUE(R.deprecated);
1687 TEST(CompletionTest, IgnoreRecoveryResults) {
1688 auto Results = completions(
1690 namespace ns { int NotRecovered() { return 0; } } 1692 // Sema enters recovery mode first and then normal mode. 1693 if (auto x = ns::NotRecover^) 1696 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("NotRecovered")));
1699 TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
1700 auto Results = completions(
1703 class X { public: X(); int x_; }; 1707 EXPECT_THAT(Results.Completions, 1708 UnorderedElementsAre(AllOf(Scope("ns::X::"), Named(
"x_"))));
1711 TEST(CompletionTest, CodeCompletionContext) {
1712 auto Results = completions(
1715 class X { public: X(); int x_; }; 1723 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess); 1726 TEST(CompletionTest, FixItForArrowToDot) { 1728 MockCompilationDatabase CDB; 1732 CodeCompleteOptions Opts; 1733 Opts.IncludeFixIts = true;
1734 Annotations TestCode(
1740 class ClassWithPtr { 1742 void MemberFunction(); 1743 Auxilary* operator->() const; 1752 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1753 EXPECT_EQ(Results.Completions.size(), 3u);
1755 TextEdit ReplacementEdit;
1756 ReplacementEdit.range = TestCode.range();
1757 ReplacementEdit.newText =
".";
1758 for (
const auto &C : Results.Completions) {
1759 EXPECT_TRUE(C.FixIts.size() == 1u || C.Name ==
"AuxFunction");
1760 if (!C.FixIts.empty()) {
1761 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
1766 TEST(CompletionTest, FixItForDotToArrow) {
1768 MockCompilationDatabase CDB;
1772 CodeCompleteOptions Opts;
1773 Opts.IncludeFixIts =
true;
1774 Annotations TestCode(
1780 class ClassWithPtr { 1782 void MemberFunction(); 1783 Auxilary* operator->() const; 1792 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1793 EXPECT_EQ(Results.Completions.size(), 3u);
1795 TextEdit ReplacementEdit;
1796 ReplacementEdit.range = TestCode.range();
1797 ReplacementEdit.newText =
"->";
1798 for (
const auto &C : Results.Completions) {
1799 EXPECT_TRUE(C.FixIts.empty() || C.Name ==
"AuxFunction");
1800 if (!C.FixIts.empty()) {
1801 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
1806 TEST(CompletionTest, RenderWithFixItMerged) {
1808 FixIt.range.end.character = 5;
1809 FixIt.newText =
"->";
1813 C.RequiredQualifier =
"Foo::";
1815 C.CompletionTokenRange.start.character = 5;
1817 CodeCompleteOptions Opts;
1818 Opts.IncludeFixIts =
true;
1820 auto R = C.render(Opts);
1821 EXPECT_TRUE(R.textEdit);
1822 EXPECT_EQ(R.textEdit->newText,
"->Foo::x");
1823 EXPECT_TRUE(R.additionalTextEdits.empty());
1826 TEST(CompletionTest, RenderWithFixItNonMerged) {
1828 FixIt.range.end.character = 4;
1829 FixIt.newText =
"->";
1833 C.RequiredQualifier =
"Foo::";
1835 C.CompletionTokenRange.start.character = 5;
1837 CodeCompleteOptions Opts;
1838 Opts.IncludeFixIts =
true;
1840 auto R = C.render(Opts);
1841 EXPECT_TRUE(R.textEdit);
1842 EXPECT_EQ(R.textEdit->newText,
"Foo::x");
1843 EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
1846 TEST(CompletionTest, CompletionTokenRange) {
1848 MockCompilationDatabase CDB;
1852 constexpr
const char *TestCodes[] = {
1873 for (
const auto &Text : TestCodes) {
1874 Annotations TestCode(Text);
1875 auto Results = completions(Server, TestCode.code(), TestCode.point());
1877 if (Results.Completions.size() != 1) {
1878 ADD_FAILURE() <<
"Results.Completions.size() != 1";
1881 EXPECT_THAT(Results.Completions.front().CompletionTokenRange,
1886 TEST(SignatureHelpTest, OverloadsOrdering) {
1887 const auto Results = signatures(R
"cpp( 1889 void foo(int x, float y); 1890 void foo(float x, int y); 1891 void foo(float x, float y); 1892 void foo(int x, int y = 0); 1893 int main() { foo(^); } 1895 EXPECT_THAT(Results.signatures, 1896 ElementsAre(Sig("foo([[int x]]) -> void"),
1897 Sig(
"foo([[int x]], [[int y = 0]]) -> void"),
1898 Sig(
"foo([[float x]], [[int y]]) -> void"),
1899 Sig(
"foo([[int x]], [[float y]]) -> void"),
1900 Sig(
"foo([[float x]], [[float y]]) -> void")));
1902 EXPECT_EQ(0, Results.activeSignature);
1903 EXPECT_EQ(0, Results.activeParameter);
1906 TEST(SignatureHelpTest, InstantiatedSignatures) {
1907 StringRef Sig0 = R
"cpp( 1916 EXPECT_THAT(signatures(Sig0).signatures, 1917 ElementsAre(Sig("foo([[T]], [[T]], [[T]]) -> void")));
1919 StringRef Sig1 = R
"cpp( 1927 EXPECT_THAT(signatures(Sig1).signatures, 1928 ElementsAre(Sig("foo([[T]], [[T]], [[T]]) -> void")));
1930 StringRef Sig2 = R
"cpp( 1931 template <class ...T> 1939 EXPECT_THAT(signatures(Sig2).signatures, 1940 ElementsAre(Sig("foo([[T...]]) -> void")));
1947 StringRef Sig3 = R
"cpp( 1955 X<int>().foo<double>(^) 1959 EXPECT_THAT(signatures(Sig3).signatures, 1960 ElementsAre(Sig("foo([[T]], [[U]]) -> void")));
1963 TEST(SignatureHelpTest, IndexDocumentation) {
1964 Symbol Foo0 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#");
1965 Foo0.Documentation =
"Doc from the index";
1966 Symbol Foo1 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#I#");
1967 Foo1.Documentation =
"Doc from the index";
1968 Symbol Foo2 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#I#I#");
1970 StringRef Sig0 = R
"cpp( 1980 signatures(Sig0, {Foo0}).signatures, 1981 ElementsAre(AllOf(Sig("foo() -> int"), SigDoc(
"Doc from the index")),
1982 AllOf(Sig(
"foo([[double]]) -> int"), SigDoc(
""))));
1984 StringRef Sig1 = R
"cpp( 1986 // Overriden doc from sema 1997 signatures(Sig1, {Foo0, Foo1, Foo2}).signatures, 1999 AllOf(Sig("foo() -> int"), SigDoc(
"Doc from the index")),
2000 AllOf(Sig(
"foo([[int]]) -> int"), SigDoc(
"Overriden doc from sema")),
2001 AllOf(Sig(
"foo([[int]], [[int]]) -> int"), SigDoc(
"Doc from sema"))));
2004 TEST(SignatureHelpTest, DynamicIndexDocumentation) {
2006 MockCompilationDatabase CDB;
2009 Opts.BuildDynamicSymbolIndex =
true;
2010 ClangdServer
Server(CDB, FS, DiagConsumer, Opts);
2012 FS.Files[
testPath(
"foo.h")] = R
"cpp( 2018 Annotations FileContent(R"cpp( 2026 Server.addDocument(
File, FileContent.code());
2028 ASSERT_TRUE(Server.blockUntilIdleForTest());
2032 ElementsAre(AllOf(Sig(
"foo() -> int"), SigDoc(
"Member doc"))));
2035 TEST(CompletionTest, CompletionFunctionArgsDisabled) {
2036 CodeCompleteOptions Opts;
2037 Opts.EnableSnippets =
true;
2038 Opts.EnableFunctionArgSnippets =
false;
2041 auto Results = completions(
2044 void xfoo(int x, int y); 2045 void f() { xfo^ })cpp", 2048 Results.Completions, 2049 UnorderedElementsAre(AllOf(Named("xfoo"),
SnippetSuffix(
"()")),
2053 auto Results = completions(
2056 void f() { xba^ })cpp", 2058 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf( 2062 Opts.BundleOverloads =
true;
2063 auto Results = completions(
2066 void xfoo(int x, int y); 2067 void f() { xfo^ })cpp", 2070 Results.Completions, 2071 UnorderedElementsAre(AllOf(Named("xfoo"),
SnippetSuffix(
"($0)"))));
2074 auto Results = completions(
2076 template <class T, class U> 2077 void xfoo(int a, U b); 2078 void f() { xfo^ })cpp", 2081 Results.Completions, 2082 UnorderedElementsAre(AllOf(Named("xfoo"),
SnippetSuffix(
"<$1>($0)"))));
2085 auto Results = completions(
2090 using foo_alias = T**; 2091 void f() { foo_^ })cpp", 2094 Results.Completions, 2095 UnorderedElementsAre(AllOf(Named("foo_class"),
SnippetSuffix(
"<$0>")),
2100 TEST(CompletionTest, SuggestOverrides) {
2101 constexpr
const char *
const Text(R
"cpp( 2104 virtual void vfunc(bool param); 2105 virtual void vfunc(bool param, int p); 2106 void func(bool param); 2108 class B : public A { 2109 virtual void ttt(bool param) const; 2110 void vfunc(bool param, int p) override; 2112 class C : public B { 2114 void vfunc(bool param) override; 2118 const auto Results = completions(Text);
2120 Results.Completions,
2121 AllOf(Contains(AllOf(Labeled(
"void vfunc(bool param, int p) override"),
2122 NameStartsWith(
"vfunc"))),
2123 Contains(AllOf(Labeled(
"void ttt(bool param) const override"),
2124 NameStartsWith(
"ttt"))),
2125 Not(Contains(Labeled(
"void vfunc(bool param) override")))));
2128 TEST(CompletionTest, OverridesNonIdentName) {
2132 virtual ~Base() = 0; 2133 virtual operator int() = 0; 2134 virtual Base& operator+(Base&) = 0; 2137 struct Derived : Base { 2143 TEST(GuessCompletionPrefix, Filters) { 2144 for (llvm::StringRef Case : {
2145 "[[scope::]][[ident]]^",
2154 "some text [[scope::more::]][[identif]]^ier",
2155 "some text [[scope::]][[mor]]^e::identifier",
2156 "weird case foo::[[::bar::]][[baz]]^",
2158 Annotations F(Case);
2160 auto ToStringRef = [&](
Range R) {
2164 auto WantQualifier = ToStringRef(F.ranges()[0]),
2165 WantName = ToStringRef(F.ranges()[1]);
2169 EXPECT_EQ(WantQualifier, Prefix.Qualifier) << Case;
2170 EXPECT_EQ(WantQualifier.begin(), Prefix.Qualifier.begin()) << Case;
2171 EXPECT_EQ(WantName, Prefix.Name) << Case;
2172 EXPECT_EQ(WantName.begin(), Prefix.Name.begin()) << Case;
2176 TEST(CompletionTest, EnableSpeculativeIndexRequest) {
2178 MockCompilationDatabase CDB;
2183 Annotations Test(R
"cpp( 2184 namespace ns1 { int abc; } 2185 namespace ns2 { int abc; } 2186 void f() { ns1::ab$1^; ns1::ab$2^; } 2187 void f2() { ns2::ab$3^; } 2190 clangd::CodeCompleteOptions Opts = {}; 2192 IndexRequestCollector Requests; 2193 Opts.Index = &Requests; 2194 Opts.SpeculativeIndexRequest = true;
2196 auto CompleteAtPoint = [&](StringRef P) {
2200 CompleteAtPoint(
"1");
2201 auto Reqs1 = Requests.consumeRequests(1);
2202 ASSERT_EQ(Reqs1.size(), 1u);
2203 EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre(
"ns1::"));
2205 CompleteAtPoint(
"2");
2206 auto Reqs2 = Requests.consumeRequests(1);
2208 ASSERT_EQ(Reqs2.size(), 1u);
2209 EXPECT_EQ(Reqs2[0], Reqs1[0]);
2211 CompleteAtPoint(
"3");
2214 auto Reqs3 = Requests.consumeRequests(2);
2215 ASSERT_EQ(Reqs3.size(), 2u);
2218 TEST(CompletionTest, InsertTheMostPopularHeader) {
2220 Symbol Sym =
func(
"Func");
2221 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2222 Sym.IncludeHeaders.emplace_back(
"\"foo.h\"", 2);
2223 Sym.IncludeHeaders.emplace_back(
"\"bar.h\"", 1000);
2225 auto Results = completions(
"Fun^", {Sym}).Completions;
2226 assert(!Results.empty());
2227 EXPECT_THAT(Results[0], AllOf(Named(
"Func"), InsertInclude(
"\"bar.h\"")));
2228 EXPECT_EQ(Results[0].Includes.size(), 2u);
2231 TEST(CompletionTest, NoInsertIncludeIfOnePresent) {
2233 MockCompilationDatabase CDB;
2235 std::string FooHeader =
testPath(
"foo.h");
2236 FS.Files[FooHeader] =
"";
2242 Symbol Sym =
func(
"Func");
2243 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2244 Sym.IncludeHeaders.emplace_back(
"\"foo.h\"", 2);
2245 Sym.IncludeHeaders.emplace_back(
"\"bar.h\"", 1000);
2248 completions(Server,
"#include \"foo.h\"\nFun^", {Sym}).Completions,
2249 UnorderedElementsAre(
2250 AllOf(Named(
"Func"), HasInclude(
"\"foo.h\""), Not(InsertInclude()))));
2253 TEST(CompletionTest, MergeMacrosFromIndexAndSema) {
2255 Sym.Name =
"Clangd_Macro_Test";
2256 Sym.ID =
SymbolID(
"c:foo.cpp@8@macro@Clangd_Macro_Test");
2257 Sym.SymInfo.Kind = index::SymbolKind::Macro;
2259 EXPECT_THAT(completions(
"#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym})
2261 UnorderedElementsAre(Named(
"Clangd_Macro_Test")));
2264 TEST(CompletionTest, MacroFromPreamble) {
2266 MockCompilationDatabase CDB;
2267 std::string FooHeader =
testPath(
"foo.h");
2268 FS.Files[FooHeader] =
"#define CLANGD_PREAMBLE_HEADER x\n";
2271 auto Results = completions(
2272 R
"cpp(#include "foo.h" 2273 #define CLANGD_PREAMBLE_MAIN x 2276 #define CLANGD_MAIN x 2277 void f() { CLANGD_^ } 2279 {func("CLANGD_INDEX")});
2282 EXPECT_THAT(Results.Completions,
2283 UnorderedElementsAre(Named(
"CLANGD_PREAMBLE_MAIN"),
2284 Named(
"CLANGD_MAIN"),
2285 Named(
"CLANGD_INDEX")));
2288 TEST(CompletionTest, DeprecatedResults) {
2289 std::string Body = R
"cpp( 2291 void TestClangc() __attribute__((deprecated("", ""))); 2295 completions(Body + "int main() { TestClang^ }").Completions,
2296 UnorderedElementsAre(AllOf(Named(
"TestClangd"), Not(Deprecated())),
2297 AllOf(Named(
"TestClangc"), Deprecated())));
2300 TEST(SignatureHelpTest, InsideArgument) {
2302 const auto Results = signatures(R
"cpp( 2304 void foo(int x, int y); 2305 int main() { foo(1+^); } 2307 EXPECT_THAT(Results.signatures, 2308 ElementsAre(Sig("foo([[int x]]) -> void"),
2309 Sig(
"foo([[int x]], [[int y]]) -> void")));
2310 EXPECT_EQ(0, Results.activeParameter);
2313 const auto Results = signatures(R
"cpp( 2315 void foo(int x, int y); 2316 int main() { foo(1^); } 2318 EXPECT_THAT(Results.signatures, 2319 ElementsAre(Sig("foo([[int x]]) -> void"),
2320 Sig(
"foo([[int x]], [[int y]]) -> void")));
2321 EXPECT_EQ(0, Results.activeParameter);
2324 const auto Results = signatures(R
"cpp( 2326 void foo(int x, int y); 2327 int main() { foo(1^0); } 2329 EXPECT_THAT(Results.signatures, 2330 ElementsAre(Sig("foo([[int x]]) -> void"),
2331 Sig(
"foo([[int x]], [[int y]]) -> void")));
2332 EXPECT_EQ(0, Results.activeParameter);
2335 const auto Results = signatures(R
"cpp( 2337 void foo(int x, int y); 2338 int bar(int x, int y); 2339 int main() { bar(foo(2, 3^)); } 2341 EXPECT_THAT(Results.signatures, 2342 ElementsAre(Sig("foo([[int x]], [[int y]]) -> void")));
2343 EXPECT_EQ(1, Results.activeParameter);
2347 TEST(SignatureHelpTest, ConstructorInitializeFields) {
2349 const auto Results = signatures(R
"cpp( 2358 EXPECT_THAT(Results.signatures, 2359 UnorderedElementsAre(Sig("A([[int]])"), Sig(
"A([[A &&]])"),
2360 Sig(
"A([[const A &]])")));
2363 const auto Results = signatures(R
"cpp( 2372 B() : c_elem(A(1^)) {} 2376 EXPECT_THAT(Results.signatures, 2377 UnorderedElementsAre(Sig("A([[int]])"), Sig(
"A([[A &&]])"),
2378 Sig(
"A([[const A &]])")));
2382 TEST(CompletionTest, IncludedCompletionKinds) {
2384 MockCompilationDatabase CDB;
2385 std::string Subdir =
testPath(
"sub");
2386 std::string SearchDirArg = (Twine(
"-I") +
Subdir).str();
2387 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
2388 std::string BarHeader =
testPath(
"sub/bar.h");
2389 FS.Files[BarHeader] =
"";
2392 auto Results = completions(Server,
2396 EXPECT_THAT(Results.Completions, 2401 TEST(CompletionTest, NoCrashAtNonAlphaIncludeHeader) {
2402 auto Results = completions(
2406 EXPECT_TRUE(Results.Completions.empty()); 2409 TEST(CompletionTest, NoAllScopesCompletionWhenQualified) { 2410 clangd::CodeCompleteOptions Opts = {}; 2411 Opts.AllScopes = true;
2413 auto Results = completions(
2415 void f() { na::Clangd^ } 2417 {cls("na::ClangdA"),
cls(
"nx::ClangdX"),
cls(
"Clangd3")}, Opts);
2418 EXPECT_THAT(Results.Completions,
2419 UnorderedElementsAre(
2420 AllOf(Qualifier(
""), Scope(
"na::"), Named(
"ClangdA"))));
2423 TEST(CompletionTest, AllScopesCompletion) {
2424 clangd::CodeCompleteOptions Opts = {};
2425 Opts.AllScopes =
true;
2427 auto Results = completions(
2430 void f() { Clangd^ } 2433 {cls("nx::Clangd1"),
cls(
"ny::Clangd2"),
cls(
"Clangd3"),
2434 cls(
"na::nb::Clangd4")},
2437 Results.Completions,
2438 UnorderedElementsAre(AllOf(Qualifier(
"nx::"), Named(
"Clangd1")),
2439 AllOf(Qualifier(
"ny::"), Named(
"Clangd2")),
2440 AllOf(Qualifier(
""), Scope(
""), Named(
"Clangd3")),
2441 AllOf(Qualifier(
"nb::"), Named(
"Clangd4"))));
2444 TEST(CompletionTest, NoQualifierIfShadowed) {
2445 clangd::CodeCompleteOptions Opts = {};
2446 Opts.AllScopes =
true;
2448 auto Results = completions(R
"cpp( 2449 namespace nx { class Clangd1 {}; } 2451 void f() { Clangd^ } 2453 {cls("nx::Clangd1"),
cls(
"nx::Clangd2")}, Opts);
2456 EXPECT_THAT(Results.Completions,
2457 UnorderedElementsAre(AllOf(Qualifier(
""), Named(
"Clangd1")),
2458 AllOf(Qualifier(
"nx::"), Named(
"Clangd2"))));
2461 TEST(CompletionTest, NoCompletionsForNewNames) {
2462 clangd::CodeCompleteOptions Opts;
2463 Opts.AllScopes =
true;
2464 auto Results = completions(R
"cpp( 2467 {cls("naber"),
cls(
"nx::naber")}, Opts);
2468 EXPECT_THAT(Results.Completions, UnorderedElementsAre());
2471 TEST(CompletionTest, Lambda) {
2472 clangd::CodeCompleteOptions Opts = {};
2474 auto Results = completions(R
"cpp( 2476 auto Lambda = [](int a, const double &b) {return 1.f;}; 2482 ASSERT_EQ(Results.Completions.size(), 1u); 2483 const auto &A = Results.Completions.front();
2484 EXPECT_EQ(A.Name,
"Lambda");
2485 EXPECT_EQ(A.Signature,
"(int a, const double &b) const");
2487 EXPECT_EQ(A.ReturnType,
"float");
2488 EXPECT_EQ(A.SnippetSuffix,
"(${1:int a}, ${2:const double &b})");
2491 TEST(CompletionTest, ObjectiveCMethodNoArguments) {
2492 auto Results = completions(R
"objc( 2494 @property(nonatomic, setter=setXToIgnoreComplete:) int value; 2496 Foo *foo = [Foo new]; int y = [foo v^] 2501 auto C = Results.Completions;
2502 EXPECT_THAT(C, ElementsAre(Named(
"value")));
2504 EXPECT_THAT(C, ElementsAre(
ReturnType(
"int")));
2505 EXPECT_THAT(C, ElementsAre(
Signature(
"")));
2509 TEST(CompletionTest, ObjectiveCMethodOneArgument) {
2510 auto Results = completions(R
"objc( 2512 - (int)valueForCharacter:(char)c; 2514 Foo *foo = [Foo new]; int y = [foo v^] 2519 auto C = Results.Completions;
2520 EXPECT_THAT(C, ElementsAre(Named(
"valueForCharacter:")));
2522 EXPECT_THAT(C, ElementsAre(
ReturnType(
"int")));
2523 EXPECT_THAT(C, ElementsAre(
Signature(
"(char)")));
2527 TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromBeginning) {
2528 auto Results = completions(R
"objc( 2530 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey; 2537 auto C = Results.Completions;
2538 EXPECT_THAT(C, ElementsAre(Named(
"fooWithValue:")));
2540 EXPECT_THAT(C, ElementsAre(
ReturnType(
"id")));
2541 EXPECT_THAT(C, ElementsAre(
Signature(
"(int) fooey:(unsigned int)")));
2543 C, ElementsAre(
SnippetSuffix(
"${1:(int)} fooey:${2:(unsigned int)}")));
2546 TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
2547 auto Results = completions(R
"objc( 2549 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey; 2551 id val = [Foo fooWithValue:10 f^] 2556 auto C = Results.Completions;
2557 EXPECT_THAT(C, ElementsAre(Named(
"fooey:")));
2559 EXPECT_THAT(C, ElementsAre(
ReturnType(
"id")));
2560 EXPECT_THAT(C, ElementsAre(
Signature(
"(unsigned int)")));
2561 EXPECT_THAT(C, ElementsAre(
SnippetSuffix(
"${1:(unsigned int)}")));
2564 TEST(CompletionTest, CursorInSnippets) {
2565 clangd::CodeCompleteOptions Options;
2566 Options.EnableSnippets =
true;
2567 auto Results = completions(
2569 void while_foo(int a, int b); 2576 EXPECT_THAT(Results.Completions,
2579 SnippetSuffix(
" (${1:condition}) {\n${0:statements}\n}"))));
2581 EXPECT_THAT(Results.Completions,
2582 Contains(AllOf(Named(
"while_foo"),
2586 TEST(CompletionTest, WorksWithNullType) {
2587 auto R = completions(R
"cpp( 2589 for (auto [loopVar] : y ) { // y has to be unresolved. 2594 EXPECT_THAT(R.Completions, ElementsAre(Named("loopVar")));
2597 TEST(CompletionTest, UsingDecl) {
2598 const char *Header(R
"cpp( 2603 const char *Source(R
"cpp( 2608 clangd::CodeCompleteOptions Opts;
2609 Opts.Index = Index.get();
2610 Opts.AllScopes =
true;
2611 auto R = completions(Source, {}, Opts);
2612 EXPECT_THAT(R.Completions,
2613 ElementsAre(AllOf(Scope(
"std::"), Named(
"foo"),
2617 TEST(CompletionTest, ScopeIsUnresolved) {
2618 clangd::CodeCompleteOptions Opts = {};
2619 Opts.AllScopes =
true;
2621 auto Results = completions(R
"cpp( 2626 {cls("a::b::XYZ")}, Opts);
2627 EXPECT_THAT(Results.Completions,
2628 UnorderedElementsAre(AllOf(Qualifier(
""), Named(
"XYZ"))));
2631 TEST(CompletionTest, NestedScopeIsUnresolved) {
2632 clangd::CodeCompleteOptions Opts = {};
2633 Opts.AllScopes =
true;
2635 auto Results = completions(R
"cpp( 2638 void f() { b::c::X^ } 2641 {cls("a::b::c::XYZ")}, Opts);
2642 EXPECT_THAT(Results.Completions,
2643 UnorderedElementsAre(AllOf(Qualifier(
""), Named(
"XYZ"))));
2648 TEST(CompletionTest, NamespaceDoubleInsertion) {
2649 clangd::CodeCompleteOptions Opts = {};
2651 auto Results = completions(R
"cpp( 2658 {cls("foo::ns::ABCDE")}, Opts);
2659 EXPECT_THAT(Results.Completions,
2660 UnorderedElementsAre(AllOf(Qualifier(
""), Named(
"ABCDE"))));
2663 TEST(CompletionTest, DerivedMethodsAreAlwaysVisible) {
2666 auto Completions = completions(R
"cpp( 2669 double size() const; 2671 struct deque : deque_base { 2678 EXPECT_THAT(Completions, 2679 ElementsAre(AllOf(ReturnType("int"), Named(
"size"))));
2682 TEST(NoCompileCompletionTest, Basic) {
2683 auto Results = completionsNoCompile(R
"cpp( 2690 EXPECT_FALSE(Results.RanParser); 2691 EXPECT_THAT(Results.Completions, 2692 UnorderedElementsAre(Named("void"), Named(
"func"), Named(
"int"),
2693 Named(
"xyz"), Named(
"abc")));
2696 TEST(NoCompileCompletionTest, WithFilter) {
2697 auto Results = completionsNoCompile(R
"cpp( 2706 EXPECT_THAT(Results.Completions, 2707 UnorderedElementsAre(Named("sym1"), Named(
"sym2")));
2710 TEST(NoCompileCompletionTest, WithIndex) {
2711 std::vector<Symbol> Syms = {
func(
"xxx"),
func(
"a::xxx"),
func(
"ns::b::xxx"),
2712 func(
"c::xxx"),
func(
"ns::d::xxx")};
2713 auto Results = completionsNoCompile(
2715 // Current-scopes, unqualified completion. 2725 EXPECT_THAT(Results.Completions, 2726 UnorderedElementsAre(AllOf(Qualifier(""), Scope(
"")),
2727 AllOf(Qualifier(
""), Scope(
"a::")),
2728 AllOf(Qualifier(
""), Scope(
"ns::b::"))));
2729 CodeCompleteOptions Opts;
2730 Opts.AllScopes =
true;
2731 Results = completionsNoCompile(
2733 // All-scopes unqualified completion. 2743 EXPECT_THAT(Results.Completions, 2744 UnorderedElementsAre(AllOf(Qualifier(""), Scope(
"")),
2745 AllOf(Qualifier(
""), Scope(
"a::")),
2746 AllOf(Qualifier(
""), Scope(
"ns::b::")),
2747 AllOf(Qualifier(
"c::"), Scope(
"c::")),
2748 AllOf(Qualifier(
"d::"), Scope(
"ns::d::"))));
2749 Results = completionsNoCompile(
2751 // Qualified completion. 2761 EXPECT_THAT(Results.Completions, 2762 ElementsAre(AllOf(Qualifier(""), Scope(
"ns::b::"))));
2763 Results = completionsNoCompile(
2765 // Absolutely qualified completion. 2775 EXPECT_THAT(Results.Completions, 2776 ElementsAre(AllOf(Qualifier(""), Scope(
"a::"))));
llvm::Expected< CodeCompleteResult > runCodeComplete(ClangdServer &Server, PathRef File, Position Pos, clangd::CodeCompleteOptions Opts)
Symbol cls(llvm::StringRef Name)
The primary text to be inserted is treated as a snippet.
llvm::Expected< SignatureHelp > runSignatureHelp(ClangdServer &Server, PathRef File, Position Pos)
size_t lspLength(llvm::StringRef Code)
The primary text to be inserted is treated as a plain string.
PolySubsequenceMatcher< Args... > HasSubsequence(Args &&... M)
std::string sortText(float Score, llvm::StringRef Name)
Returns a string that sorts in the same order as (-Score, Tiebreak), for LSP.
Symbol ns(llvm::StringRef Name)
llvm::StringRef PathRef
A typedef to represent a ref to file path.
std::vector< CodeCompletionResult > Results
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
static Options optsForTest()
Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, llvm::StringRef USRFormat)
Symbol var(llvm::StringRef Name)
std::vector< std::string > Scopes
If this is non-empty, symbols must be in at least one of the scopes (e.g.
CompletionItemKind
The kind of a completion entry.
bool IncludeComments
Add comments to code completion results, if available.
bool IncludeCodePatterns
Add code patterns to completion results.
static std::unique_ptr< SymbolIndex > build(SymbolSlab Symbols, RefSlab Refs, RelationSlab Relations)
Builds an index from slabs. The index takes ownership of the data.
static TestTU withHeaderCode(llvm::StringRef HeaderCode)
Whether or not this symbol is meant to be used for the code completion.
std::vector< std::string > lookup(const SymbolIndex &I, llvm::ArrayRef< SymbolID > IDs)
TEST(BackgroundQueueTest, Priority)
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
std::string testPath(PathRef File)
virtual void onDiagnosticsReady(PathRef File, std::vector< Diag > Diagnostics)=0
Called by ClangdServer when Diagnostics for File are ready.
bool IncludeIneligibleResults
Include results that are not legal completions in the current context.
static constexpr llvm::StringLiteral Name
void wait(std::unique_lock< std::mutex > &Lock, std::condition_variable &CV, Deadline D)
Wait once on CV for the specified duration.
std::string SnippetSuffix
CodeCompleteResult codeComplete(PathRef FileName, const tooling::CompileCommand &Command, const PreambleData *Preamble, llvm::StringRef Contents, Position Pos, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, CodeCompleteOptions Opts, SpeculativeFuzzyFind *SpecFuzzyFind)
CodeCompletionBuilder Builder
static llvm::Expected< URI > create(llvm::StringRef AbsolutePath, llvm::StringRef Scheme)
Creates a URI for a file in the given scheme.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Deadline timeoutSeconds(llvm::Optional< double > Seconds)
Makes a deadline from a timeout in seconds. None means wait forever.
CharSourceRange Range
SourceRange for the file name.
std::string IncludeHeader
std::unique_ptr< SymbolIndex > index() const
bool IncludeMacros
Add macros to code completion results.
IgnoreDiagnostics DiagConsumer
llvm::Optional< FixItHint > FixIt
CompletionPrefix guessCompletionPrefix(llvm::StringRef Content, unsigned Offset)
std::pair< unsigned, unsigned > Offsets
std::array< uint8_t, 20 > SymbolID
#define EXPECT_IFF(condition, value, matcher)
void runAddDocument(ClangdServer &Server, PathRef File, llvm::StringRef Contents, WantDiagnostics WantDiags)
const SymbolIndex * Index
Symbol func(llvm::StringRef Name)