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;
1646 C.Score.ExcludingName = .5;
1649 CodeCompleteOptions Opts;
1650 Opts.IncludeIndicator.Insert =
"^";
1651 Opts.IncludeIndicator.NoInsert =
"";
1652 Opts.EnableSnippets =
false;
1654 auto R = C.render(Opts);
1655 EXPECT_EQ(R.label,
"Foo::x(bool) const");
1656 EXPECT_EQ(R.insertText,
"Foo::x");
1658 EXPECT_EQ(R.filterText,
"x");
1659 EXPECT_EQ(R.detail,
"int\n\"foo.h\"");
1660 EXPECT_EQ(R.documentation,
"This is x().");
1661 EXPECT_THAT(R.additionalTextEdits, IsEmpty());
1662 EXPECT_EQ(R.sortText,
sortText(1.0,
"x"));
1663 EXPECT_FALSE(R.deprecated);
1664 EXPECT_EQ(R.score, .5f);
1666 Opts.EnableSnippets =
true;
1668 EXPECT_EQ(R.insertText,
"Foo::x(${0:bool})");
1671 Include.Insertion.emplace();
1673 EXPECT_EQ(R.label,
"^Foo::x(bool) const");
1674 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
1676 Opts.ShowOrigins =
true;
1678 EXPECT_EQ(R.label,
"^[AS]Foo::x(bool) const");
1682 EXPECT_EQ(R.detail,
"[2 overloads]\n\"foo.h\"");
1684 C.Deprecated =
true;
1686 EXPECT_TRUE(R.deprecated);
1689 TEST(CompletionTest, IgnoreRecoveryResults) {
1690 auto Results = completions(
1692 namespace ns { int NotRecovered() { return 0; } } 1694 // Sema enters recovery mode first and then normal mode. 1695 if (auto x = ns::NotRecover^) 1698 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("NotRecovered")));
1701 TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
1702 auto Results = completions(
1705 class X { public: X(); int x_; }; 1709 EXPECT_THAT(Results.Completions, 1710 UnorderedElementsAre(AllOf(Scope("ns::X::"), Named(
"x_"))));
1713 TEST(CompletionTest, CodeCompletionContext) {
1714 auto Results = completions(
1717 class X { public: X(); int x_; }; 1725 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess); 1728 TEST(CompletionTest, FixItForArrowToDot) { 1730 MockCompilationDatabase CDB; 1734 CodeCompleteOptions Opts; 1735 Opts.IncludeFixIts = true;
1736 Annotations TestCode(
1742 class ClassWithPtr { 1744 void MemberFunction(); 1745 Auxilary* operator->() const; 1754 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1755 EXPECT_EQ(Results.Completions.size(), 3u);
1757 TextEdit ReplacementEdit;
1758 ReplacementEdit.range = TestCode.range();
1759 ReplacementEdit.newText =
".";
1760 for (
const auto &C : Results.Completions) {
1761 EXPECT_TRUE(C.FixIts.size() == 1u || C.Name ==
"AuxFunction");
1762 if (!C.FixIts.empty()) {
1763 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
1768 TEST(CompletionTest, FixItForDotToArrow) {
1770 MockCompilationDatabase CDB;
1774 CodeCompleteOptions Opts;
1775 Opts.IncludeFixIts =
true;
1776 Annotations TestCode(
1782 class ClassWithPtr { 1784 void MemberFunction(); 1785 Auxilary* operator->() const; 1794 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1795 EXPECT_EQ(Results.Completions.size(), 3u);
1797 TextEdit ReplacementEdit;
1798 ReplacementEdit.range = TestCode.range();
1799 ReplacementEdit.newText =
"->";
1800 for (
const auto &C : Results.Completions) {
1801 EXPECT_TRUE(C.FixIts.empty() || C.Name ==
"AuxFunction");
1802 if (!C.FixIts.empty()) {
1803 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
1808 TEST(CompletionTest, RenderWithFixItMerged) {
1810 FixIt.range.end.character = 5;
1811 FixIt.newText =
"->";
1815 C.RequiredQualifier =
"Foo::";
1817 C.CompletionTokenRange.start.character = 5;
1819 CodeCompleteOptions Opts;
1820 Opts.IncludeFixIts =
true;
1822 auto R = C.render(Opts);
1823 EXPECT_TRUE(R.textEdit);
1824 EXPECT_EQ(R.textEdit->newText,
"->Foo::x");
1825 EXPECT_TRUE(R.additionalTextEdits.empty());
1828 TEST(CompletionTest, RenderWithFixItNonMerged) {
1830 FixIt.range.end.character = 4;
1831 FixIt.newText =
"->";
1835 C.RequiredQualifier =
"Foo::";
1837 C.CompletionTokenRange.start.character = 5;
1839 CodeCompleteOptions Opts;
1840 Opts.IncludeFixIts =
true;
1842 auto R = C.render(Opts);
1843 EXPECT_TRUE(R.textEdit);
1844 EXPECT_EQ(R.textEdit->newText,
"Foo::x");
1845 EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
1848 TEST(CompletionTest, CompletionTokenRange) {
1850 MockCompilationDatabase CDB;
1854 constexpr
const char *TestCodes[] = {
1875 for (
const auto &Text : TestCodes) {
1876 Annotations TestCode(Text);
1877 auto Results = completions(Server, TestCode.code(), TestCode.point());
1879 if (Results.Completions.size() != 1) {
1880 ADD_FAILURE() <<
"Results.Completions.size() != 1";
1883 EXPECT_THAT(Results.Completions.front().CompletionTokenRange,
1888 TEST(SignatureHelpTest, OverloadsOrdering) {
1889 const auto Results = signatures(R
"cpp( 1891 void foo(int x, float y); 1892 void foo(float x, int y); 1893 void foo(float x, float y); 1894 void foo(int x, int y = 0); 1895 int main() { foo(^); } 1897 EXPECT_THAT(Results.signatures, 1898 ElementsAre(Sig("foo([[int x]]) -> void"),
1899 Sig(
"foo([[int x]], [[int y = 0]]) -> void"),
1900 Sig(
"foo([[float x]], [[int y]]) -> void"),
1901 Sig(
"foo([[int x]], [[float y]]) -> void"),
1902 Sig(
"foo([[float x]], [[float y]]) -> void")));
1904 EXPECT_EQ(0, Results.activeSignature);
1905 EXPECT_EQ(0, Results.activeParameter);
1908 TEST(SignatureHelpTest, InstantiatedSignatures) {
1909 StringRef Sig0 = R
"cpp( 1918 EXPECT_THAT(signatures(Sig0).signatures, 1919 ElementsAre(Sig("foo([[T]], [[T]], [[T]]) -> void")));
1921 StringRef Sig1 = R
"cpp( 1929 EXPECT_THAT(signatures(Sig1).signatures, 1930 ElementsAre(Sig("foo([[T]], [[T]], [[T]]) -> void")));
1932 StringRef Sig2 = R
"cpp( 1933 template <class ...T> 1941 EXPECT_THAT(signatures(Sig2).signatures, 1942 ElementsAre(Sig("foo([[T...]]) -> void")));
1949 StringRef Sig3 = R
"cpp( 1957 X<int>().foo<double>(^) 1961 EXPECT_THAT(signatures(Sig3).signatures, 1962 ElementsAre(Sig("foo([[T]], [[U]]) -> void")));
1965 TEST(SignatureHelpTest, IndexDocumentation) {
1966 Symbol Foo0 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#");
1967 Foo0.Documentation =
"Doc from the index";
1968 Symbol Foo1 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#I#");
1969 Foo1.Documentation =
"Doc from the index";
1970 Symbol Foo2 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#I#I#");
1972 StringRef Sig0 = R
"cpp( 1982 signatures(Sig0, {Foo0}).signatures, 1983 ElementsAre(AllOf(Sig("foo() -> int"), SigDoc(
"Doc from the index")),
1984 AllOf(Sig(
"foo([[double]]) -> int"), SigDoc(
""))));
1986 StringRef Sig1 = R
"cpp( 1988 // Overriden doc from sema 1999 signatures(Sig1, {Foo0, Foo1, Foo2}).signatures, 2001 AllOf(Sig("foo() -> int"), SigDoc(
"Doc from the index")),
2002 AllOf(Sig(
"foo([[int]]) -> int"), SigDoc(
"Overriden doc from sema")),
2003 AllOf(Sig(
"foo([[int]], [[int]]) -> int"), SigDoc(
"Doc from sema"))));
2006 TEST(SignatureHelpTest, DynamicIndexDocumentation) {
2008 MockCompilationDatabase CDB;
2011 Opts.BuildDynamicSymbolIndex =
true;
2012 ClangdServer
Server(CDB, FS, DiagConsumer, Opts);
2014 FS.Files[
testPath(
"foo.h")] = R
"cpp( 2020 Annotations FileContent(R"cpp( 2028 Server.addDocument(
File, FileContent.code());
2030 ASSERT_TRUE(Server.blockUntilIdleForTest());
2034 ElementsAre(AllOf(Sig(
"foo() -> int"), SigDoc(
"Member doc"))));
2037 TEST(CompletionTest, CompletionFunctionArgsDisabled) {
2038 CodeCompleteOptions Opts;
2039 Opts.EnableSnippets =
true;
2040 Opts.EnableFunctionArgSnippets =
false;
2043 auto Results = completions(
2046 void xfoo(int x, int y); 2047 void f() { xfo^ })cpp", 2050 Results.Completions, 2051 UnorderedElementsAre(AllOf(Named("xfoo"),
SnippetSuffix(
"()")),
2055 auto Results = completions(
2058 void f() { xba^ })cpp", 2060 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf( 2064 Opts.BundleOverloads =
true;
2065 auto Results = completions(
2068 void xfoo(int x, int y); 2069 void f() { xfo^ })cpp", 2072 Results.Completions, 2073 UnorderedElementsAre(AllOf(Named("xfoo"),
SnippetSuffix(
"($0)"))));
2076 auto Results = completions(
2078 template <class T, class U> 2079 void xfoo(int a, U b); 2080 void f() { xfo^ })cpp", 2083 Results.Completions, 2084 UnorderedElementsAre(AllOf(Named("xfoo"),
SnippetSuffix(
"<$1>($0)"))));
2087 auto Results = completions(
2092 using foo_alias = T**; 2093 void f() { foo_^ })cpp", 2096 Results.Completions, 2097 UnorderedElementsAre(AllOf(Named("foo_class"),
SnippetSuffix(
"<$0>")),
2102 TEST(CompletionTest, SuggestOverrides) {
2103 constexpr
const char *
const Text(R
"cpp( 2106 virtual void vfunc(bool param); 2107 virtual void vfunc(bool param, int p); 2108 void func(bool param); 2110 class B : public A { 2111 virtual void ttt(bool param) const; 2112 void vfunc(bool param, int p) override; 2114 class C : public B { 2116 void vfunc(bool param) override; 2120 const auto Results = completions(Text);
2122 Results.Completions,
2123 AllOf(Contains(AllOf(Labeled(
"void vfunc(bool param, int p) override"),
2124 NameStartsWith(
"vfunc"))),
2125 Contains(AllOf(Labeled(
"void ttt(bool param) const override"),
2126 NameStartsWith(
"ttt"))),
2127 Not(Contains(Labeled(
"void vfunc(bool param) override")))));
2130 TEST(CompletionTest, OverridesNonIdentName) {
2134 virtual ~Base() = 0; 2135 virtual operator int() = 0; 2136 virtual Base& operator+(Base&) = 0; 2139 struct Derived : Base { 2145 TEST(GuessCompletionPrefix, Filters) { 2146 for (llvm::StringRef Case : {
2147 "[[scope::]][[ident]]^",
2156 "some text [[scope::more::]][[identif]]^ier",
2157 "some text [[scope::]][[mor]]^e::identifier",
2158 "weird case foo::[[::bar::]][[baz]]^",
2160 Annotations F(Case);
2162 auto ToStringRef = [&](
Range R) {
2166 auto WantQualifier = ToStringRef(F.ranges()[0]),
2167 WantName = ToStringRef(F.ranges()[1]);
2171 EXPECT_EQ(WantQualifier, Prefix.Qualifier) << Case;
2172 EXPECT_EQ(WantQualifier.begin(), Prefix.Qualifier.begin()) << Case;
2173 EXPECT_EQ(WantName, Prefix.Name) << Case;
2174 EXPECT_EQ(WantName.begin(), Prefix.Name.begin()) << Case;
2178 TEST(CompletionTest, EnableSpeculativeIndexRequest) {
2180 MockCompilationDatabase CDB;
2185 Annotations Test(R
"cpp( 2186 namespace ns1 { int abc; } 2187 namespace ns2 { int abc; } 2188 void f() { ns1::ab$1^; ns1::ab$2^; } 2189 void f2() { ns2::ab$3^; } 2192 clangd::CodeCompleteOptions Opts = {}; 2194 IndexRequestCollector Requests; 2195 Opts.Index = &Requests; 2196 Opts.SpeculativeIndexRequest = true;
2198 auto CompleteAtPoint = [&](StringRef P) {
2202 CompleteAtPoint(
"1");
2203 auto Reqs1 = Requests.consumeRequests(1);
2204 ASSERT_EQ(Reqs1.size(), 1u);
2205 EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre(
"ns1::"));
2207 CompleteAtPoint(
"2");
2208 auto Reqs2 = Requests.consumeRequests(1);
2210 ASSERT_EQ(Reqs2.size(), 1u);
2211 EXPECT_EQ(Reqs2[0], Reqs1[0]);
2213 CompleteAtPoint(
"3");
2216 auto Reqs3 = Requests.consumeRequests(2);
2217 ASSERT_EQ(Reqs3.size(), 2u);
2220 TEST(CompletionTest, InsertTheMostPopularHeader) {
2222 Symbol Sym =
func(
"Func");
2223 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2224 Sym.IncludeHeaders.emplace_back(
"\"foo.h\"", 2);
2225 Sym.IncludeHeaders.emplace_back(
"\"bar.h\"", 1000);
2227 auto Results = completions(
"Fun^", {Sym}).Completions;
2228 assert(!Results.empty());
2229 EXPECT_THAT(Results[0], AllOf(Named(
"Func"), InsertInclude(
"\"bar.h\"")));
2230 EXPECT_EQ(Results[0].Includes.size(), 2u);
2233 TEST(CompletionTest, NoInsertIncludeIfOnePresent) {
2235 MockCompilationDatabase CDB;
2237 std::string FooHeader =
testPath(
"foo.h");
2238 FS.Files[FooHeader] =
"";
2244 Symbol Sym =
func(
"Func");
2245 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2246 Sym.IncludeHeaders.emplace_back(
"\"foo.h\"", 2);
2247 Sym.IncludeHeaders.emplace_back(
"\"bar.h\"", 1000);
2250 completions(Server,
"#include \"foo.h\"\nFun^", {Sym}).Completions,
2251 UnorderedElementsAre(
2252 AllOf(Named(
"Func"), HasInclude(
"\"foo.h\""), Not(InsertInclude()))));
2255 TEST(CompletionTest, MergeMacrosFromIndexAndSema) {
2257 Sym.Name =
"Clangd_Macro_Test";
2258 Sym.ID =
SymbolID(
"c:foo.cpp@8@macro@Clangd_Macro_Test");
2259 Sym.SymInfo.Kind = index::SymbolKind::Macro;
2261 EXPECT_THAT(completions(
"#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym})
2263 UnorderedElementsAre(Named(
"Clangd_Macro_Test")));
2266 TEST(CompletionTest, MacroFromPreamble) {
2268 MockCompilationDatabase CDB;
2269 std::string FooHeader =
testPath(
"foo.h");
2270 FS.Files[FooHeader] =
"#define CLANGD_PREAMBLE_HEADER x\n";
2273 auto Results = completions(
2274 R
"cpp(#include "foo.h" 2275 #define CLANGD_PREAMBLE_MAIN x 2278 #define CLANGD_MAIN x 2279 void f() { CLANGD_^ } 2281 {func("CLANGD_INDEX")});
2284 EXPECT_THAT(Results.Completions,
2285 UnorderedElementsAre(Named(
"CLANGD_PREAMBLE_MAIN"),
2286 Named(
"CLANGD_MAIN"),
2287 Named(
"CLANGD_INDEX")));
2290 TEST(CompletionTest, DeprecatedResults) {
2291 std::string Body = R
"cpp( 2293 void TestClangc() __attribute__((deprecated("", ""))); 2297 completions(Body + "int main() { TestClang^ }").Completions,
2298 UnorderedElementsAre(AllOf(Named(
"TestClangd"), Not(Deprecated())),
2299 AllOf(Named(
"TestClangc"), Deprecated())));
2302 TEST(SignatureHelpTest, InsideArgument) {
2304 const auto Results = signatures(R
"cpp( 2306 void foo(int x, int y); 2307 int main() { foo(1+^); } 2309 EXPECT_THAT(Results.signatures, 2310 ElementsAre(Sig("foo([[int x]]) -> void"),
2311 Sig(
"foo([[int x]], [[int y]]) -> void")));
2312 EXPECT_EQ(0, Results.activeParameter);
2315 const auto Results = signatures(R
"cpp( 2317 void foo(int x, int y); 2318 int main() { foo(1^); } 2320 EXPECT_THAT(Results.signatures, 2321 ElementsAre(Sig("foo([[int x]]) -> void"),
2322 Sig(
"foo([[int x]], [[int y]]) -> void")));
2323 EXPECT_EQ(0, Results.activeParameter);
2326 const auto Results = signatures(R
"cpp( 2328 void foo(int x, int y); 2329 int main() { foo(1^0); } 2331 EXPECT_THAT(Results.signatures, 2332 ElementsAre(Sig("foo([[int x]]) -> void"),
2333 Sig(
"foo([[int x]], [[int y]]) -> void")));
2334 EXPECT_EQ(0, Results.activeParameter);
2337 const auto Results = signatures(R
"cpp( 2339 void foo(int x, int y); 2340 int bar(int x, int y); 2341 int main() { bar(foo(2, 3^)); } 2343 EXPECT_THAT(Results.signatures, 2344 ElementsAre(Sig("foo([[int x]], [[int y]]) -> void")));
2345 EXPECT_EQ(1, Results.activeParameter);
2349 TEST(SignatureHelpTest, ConstructorInitializeFields) {
2351 const auto Results = signatures(R
"cpp( 2360 EXPECT_THAT(Results.signatures, 2361 UnorderedElementsAre(Sig("A([[int]])"), Sig(
"A([[A &&]])"),
2362 Sig(
"A([[const A &]])")));
2365 const auto Results = signatures(R
"cpp( 2374 B() : c_elem(A(1^)) {} 2378 EXPECT_THAT(Results.signatures, 2379 UnorderedElementsAre(Sig("A([[int]])"), Sig(
"A([[A &&]])"),
2380 Sig(
"A([[const A &]])")));
2384 TEST(CompletionTest, IncludedCompletionKinds) {
2386 MockCompilationDatabase CDB;
2387 std::string Subdir =
testPath(
"sub");
2388 std::string SearchDirArg = (Twine(
"-I") +
Subdir).str();
2389 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
2390 std::string BarHeader =
testPath(
"sub/bar.h");
2391 FS.Files[BarHeader] =
"";
2394 auto Results = completions(Server,
2398 EXPECT_THAT(Results.Completions, 2403 TEST(CompletionTest, NoCrashAtNonAlphaIncludeHeader) {
2404 auto Results = completions(
2408 EXPECT_TRUE(Results.Completions.empty()); 2411 TEST(CompletionTest, NoAllScopesCompletionWhenQualified) { 2412 clangd::CodeCompleteOptions Opts = {}; 2413 Opts.AllScopes = true;
2415 auto Results = completions(
2417 void f() { na::Clangd^ } 2419 {cls("na::ClangdA"),
cls(
"nx::ClangdX"),
cls(
"Clangd3")}, Opts);
2420 EXPECT_THAT(Results.Completions,
2421 UnorderedElementsAre(
2422 AllOf(Qualifier(
""), Scope(
"na::"), Named(
"ClangdA"))));
2425 TEST(CompletionTest, AllScopesCompletion) {
2426 clangd::CodeCompleteOptions Opts = {};
2427 Opts.AllScopes =
true;
2429 auto Results = completions(
2432 void f() { Clangd^ } 2435 {cls("nx::Clangd1"),
cls(
"ny::Clangd2"),
cls(
"Clangd3"),
2436 cls(
"na::nb::Clangd4")},
2439 Results.Completions,
2440 UnorderedElementsAre(AllOf(Qualifier(
"nx::"), Named(
"Clangd1")),
2441 AllOf(Qualifier(
"ny::"), Named(
"Clangd2")),
2442 AllOf(Qualifier(
""), Scope(
""), Named(
"Clangd3")),
2443 AllOf(Qualifier(
"nb::"), Named(
"Clangd4"))));
2446 TEST(CompletionTest, NoQualifierIfShadowed) {
2447 clangd::CodeCompleteOptions Opts = {};
2448 Opts.AllScopes =
true;
2450 auto Results = completions(R
"cpp( 2451 namespace nx { class Clangd1 {}; } 2453 void f() { Clangd^ } 2455 {cls("nx::Clangd1"),
cls(
"nx::Clangd2")}, Opts);
2458 EXPECT_THAT(Results.Completions,
2459 UnorderedElementsAre(AllOf(Qualifier(
""), Named(
"Clangd1")),
2460 AllOf(Qualifier(
"nx::"), Named(
"Clangd2"))));
2463 TEST(CompletionTest, NoCompletionsForNewNames) {
2464 clangd::CodeCompleteOptions Opts;
2465 Opts.AllScopes =
true;
2466 auto Results = completions(R
"cpp( 2469 {cls("naber"),
cls(
"nx::naber")}, Opts);
2470 EXPECT_THAT(Results.Completions, UnorderedElementsAre());
2473 TEST(CompletionTest, Lambda) {
2474 clangd::CodeCompleteOptions Opts = {};
2476 auto Results = completions(R
"cpp( 2478 auto Lambda = [](int a, const double &b) {return 1.f;}; 2484 ASSERT_EQ(Results.Completions.size(), 1u); 2485 const auto &A = Results.Completions.front();
2486 EXPECT_EQ(A.Name,
"Lambda");
2487 EXPECT_EQ(A.Signature,
"(int a, const double &b) const");
2489 EXPECT_EQ(A.ReturnType,
"float");
2490 EXPECT_EQ(A.SnippetSuffix,
"(${1:int a}, ${2:const double &b})");
2493 TEST(CompletionTest, ObjectiveCMethodNoArguments) {
2494 auto Results = completions(R
"objc( 2496 @property(nonatomic, setter=setXToIgnoreComplete:) int value; 2498 Foo *foo = [Foo new]; int y = [foo v^] 2503 auto C = Results.Completions;
2504 EXPECT_THAT(C, ElementsAre(Named(
"value")));
2506 EXPECT_THAT(C, ElementsAre(
ReturnType(
"int")));
2507 EXPECT_THAT(C, ElementsAre(
Signature(
"")));
2511 TEST(CompletionTest, ObjectiveCMethodOneArgument) {
2512 auto Results = completions(R
"objc( 2514 - (int)valueForCharacter:(char)c; 2516 Foo *foo = [Foo new]; int y = [foo v^] 2521 auto C = Results.Completions;
2522 EXPECT_THAT(C, ElementsAre(Named(
"valueForCharacter:")));
2524 EXPECT_THAT(C, ElementsAre(
ReturnType(
"int")));
2525 EXPECT_THAT(C, ElementsAre(
Signature(
"(char)")));
2529 TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromBeginning) {
2530 auto Results = completions(R
"objc( 2532 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey; 2539 auto C = Results.Completions;
2540 EXPECT_THAT(C, ElementsAre(Named(
"fooWithValue:")));
2542 EXPECT_THAT(C, ElementsAre(
ReturnType(
"id")));
2543 EXPECT_THAT(C, ElementsAre(
Signature(
"(int) fooey:(unsigned int)")));
2545 C, ElementsAre(
SnippetSuffix(
"${1:(int)} fooey:${2:(unsigned int)}")));
2548 TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
2549 auto Results = completions(R
"objc( 2551 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey; 2553 id val = [Foo fooWithValue:10 f^] 2558 auto C = Results.Completions;
2559 EXPECT_THAT(C, ElementsAre(Named(
"fooey:")));
2561 EXPECT_THAT(C, ElementsAre(
ReturnType(
"id")));
2562 EXPECT_THAT(C, ElementsAre(
Signature(
"(unsigned int)")));
2563 EXPECT_THAT(C, ElementsAre(
SnippetSuffix(
"${1:(unsigned int)}")));
2566 TEST(CompletionTest, CursorInSnippets) {
2567 clangd::CodeCompleteOptions Options;
2568 Options.EnableSnippets =
true;
2569 auto Results = completions(
2571 void while_foo(int a, int b); 2578 EXPECT_THAT(Results.Completions,
2581 SnippetSuffix(
" (${1:condition}) {\n${0:statements}\n}"))));
2583 EXPECT_THAT(Results.Completions,
2584 Contains(AllOf(Named(
"while_foo"),
2588 TEST(CompletionTest, WorksWithNullType) {
2589 auto R = completions(R
"cpp( 2591 for (auto [loopVar] : y ) { // y has to be unresolved. 2596 EXPECT_THAT(R.Completions, ElementsAre(Named("loopVar")));
2599 TEST(CompletionTest, UsingDecl) {
2600 const char *Header(R
"cpp( 2605 const char *Source(R
"cpp( 2610 clangd::CodeCompleteOptions Opts;
2611 Opts.Index = Index.get();
2612 Opts.AllScopes =
true;
2613 auto R = completions(Source, {}, Opts);
2614 EXPECT_THAT(R.Completions,
2615 ElementsAre(AllOf(Scope(
"std::"), Named(
"foo"),
2619 TEST(CompletionTest, ScopeIsUnresolved) {
2620 clangd::CodeCompleteOptions Opts = {};
2621 Opts.AllScopes =
true;
2623 auto Results = completions(R
"cpp( 2628 {cls("a::b::XYZ")}, Opts);
2629 EXPECT_THAT(Results.Completions,
2630 UnorderedElementsAre(AllOf(Qualifier(
""), Named(
"XYZ"))));
2633 TEST(CompletionTest, NestedScopeIsUnresolved) {
2634 clangd::CodeCompleteOptions Opts = {};
2635 Opts.AllScopes =
true;
2637 auto Results = completions(R
"cpp( 2640 void f() { b::c::X^ } 2643 {cls("a::b::c::XYZ")}, Opts);
2644 EXPECT_THAT(Results.Completions,
2645 UnorderedElementsAre(AllOf(Qualifier(
""), Named(
"XYZ"))));
2650 TEST(CompletionTest, NamespaceDoubleInsertion) {
2651 clangd::CodeCompleteOptions Opts = {};
2653 auto Results = completions(R
"cpp( 2660 {cls("foo::ns::ABCDE")}, Opts);
2661 EXPECT_THAT(Results.Completions,
2662 UnorderedElementsAre(AllOf(Qualifier(
""), Named(
"ABCDE"))));
2665 TEST(CompletionTest, DerivedMethodsAreAlwaysVisible) {
2668 auto Completions = completions(R
"cpp( 2671 double size() const; 2673 struct deque : deque_base { 2680 EXPECT_THAT(Completions, 2681 ElementsAre(AllOf(ReturnType("int"), Named(
"size"))));
2684 TEST(NoCompileCompletionTest, Basic) {
2685 auto Results = completionsNoCompile(R
"cpp( 2692 EXPECT_FALSE(Results.RanParser); 2693 EXPECT_THAT(Results.Completions, 2694 UnorderedElementsAre(Named("void"), Named(
"func"), Named(
"int"),
2695 Named(
"xyz"), Named(
"abc")));
2698 TEST(NoCompileCompletionTest, WithFilter) {
2699 auto Results = completionsNoCompile(R
"cpp( 2708 EXPECT_THAT(Results.Completions, 2709 UnorderedElementsAre(Named("sym1"), Named(
"sym2")));
2712 TEST(NoCompileCompletionTest, WithIndex) {
2713 std::vector<Symbol> Syms = {
func(
"xxx"),
func(
"a::xxx"),
func(
"ns::b::xxx"),
2714 func(
"c::xxx"),
func(
"ns::d::xxx")};
2715 auto Results = completionsNoCompile(
2717 // Current-scopes, unqualified completion. 2727 EXPECT_THAT(Results.Completions, 2728 UnorderedElementsAre(AllOf(Qualifier(""), Scope(
"")),
2729 AllOf(Qualifier(
""), Scope(
"a::")),
2730 AllOf(Qualifier(
""), Scope(
"ns::b::"))));
2731 CodeCompleteOptions Opts;
2732 Opts.AllScopes =
true;
2733 Results = completionsNoCompile(
2735 // All-scopes unqualified completion. 2745 EXPECT_THAT(Results.Completions, 2746 UnorderedElementsAre(AllOf(Qualifier(""), Scope(
"")),
2747 AllOf(Qualifier(
""), Scope(
"a::")),
2748 AllOf(Qualifier(
""), Scope(
"ns::b::")),
2749 AllOf(Qualifier(
"c::"), Scope(
"c::")),
2750 AllOf(Qualifier(
"d::"), Scope(
"ns::d::"))));
2751 Results = completionsNoCompile(
2753 // Qualified completion. 2763 EXPECT_THAT(Results.Completions, 2764 ElementsAre(AllOf(Qualifier(""), Scope(
"ns::b::"))));
2765 Results = completionsNoCompile(
2767 // Absolutely qualified completion. 2777 EXPECT_THAT(Results.Completions, 2778 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)
std::vector< const char * > Flags
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)