23 #include "clang/Sema/CodeCompleteConsumer.h" 24 #include "clang/Tooling/CompilationDatabase.h" 25 #include "llvm/Support/Error.h" 26 #include "llvm/Support/Path.h" 27 #include "llvm/Testing/Support/Error.h" 28 #include "gmock/gmock.h" 29 #include "gtest/gtest.h" 36 using ::testing::AllOf;
37 using ::testing::Contains;
38 using ::testing::ElementsAre;
39 using ::testing::Field;
40 using ::testing::HasSubstr;
41 using ::testing::IsEmpty;
43 using ::testing::UnorderedElementsAre;
45 class IgnoreDiagnostics :
public DiagnosticsConsumer {
47 std::vector<Diag> Diagnostics)
override {}
53 return llvm::StringRef(arg.Name).startswith(Prefix);
55 MATCHER_P(Scope, S,
"") {
return arg.Scope == S; }
56 MATCHER_P(Qualifier, Q,
"") {
return arg.RequiredQualifier == Q; }
58 return arg.RequiredQualifier + arg.Name + arg.Signature == Label;
60 MATCHER_P(SigHelpLabeled, Label,
"") {
return arg.label == Label; }
62 MATCHER_P(Doc,
D,
"") {
return arg.Documentation ==
D; }
65 return !arg.Includes.empty() && arg.Includes[0].Header ==
IncludeHeader;
68 return !arg.Includes.empty() && arg.Includes[0].Header ==
IncludeHeader &&
69 bool(arg.Includes[0].Insertion);
72 return !arg.Includes.empty() && bool(arg.Includes[0].Insertion);
75 MATCHER_P(Origin, OriginSet,
"") {
return arg.Origin == OriginSet; }
79 Matcher<const std::vector<CodeCompletion> &> Has(std::string
Name) {
80 return Contains(Named(std::move(Name)));
82 Matcher<const std::vector<CodeCompletion> &> Has(std::string Name,
84 return Contains(AllOf(Named(std::move(Name)),
Kind(K)));
86 MATCHER(IsDocumented,
"") {
return !arg.Documentation.empty(); }
87 MATCHER(Deprecated,
"") {
return arg.Deprecated; }
89 std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol>
Symbols) {
91 for (
const auto &Sym : Symbols)
93 return MemIndex::build(std::move(Slab).build(), RefSlab(), RelationSlab());
96 CodeCompleteResult completions(ClangdServer &
Server, llvm::StringRef TestCode,
98 std::vector<Symbol> IndexSymbols = {},
99 clangd::CodeCompleteOptions Opts = {}) {
100 std::unique_ptr<SymbolIndex> OverrideIndex;
101 if (!IndexSymbols.empty()) {
102 assert(!Opts.Index &&
"both Index and IndexSymbols given!");
103 OverrideIndex = memIndex(std::move(IndexSymbols));
104 Opts.Index = OverrideIndex.get();
109 auto CompletionList =
111 return CompletionList;
114 CodeCompleteResult completions(ClangdServer &Server, llvm::StringRef
Text,
115 std::vector<Symbol> IndexSymbols = {},
116 clangd::CodeCompleteOptions Opts = {},
117 PathRef FilePath =
"foo.cpp") {
118 std::unique_ptr<SymbolIndex> OverrideIndex;
119 if (!IndexSymbols.empty()) {
120 assert(!Opts.Index &&
"both Index and IndexSymbols given!");
121 OverrideIndex = memIndex(std::move(IndexSymbols));
122 Opts.Index = OverrideIndex.get();
126 Annotations Test(Text);
128 auto CompletionList =
130 return CompletionList;
135 CodeCompleteResult completions(llvm::StringRef Text,
136 std::vector<Symbol> IndexSymbols = {},
137 clangd::CodeCompleteOptions Opts = {},
138 PathRef FilePath =
"foo.cpp") {
140 MockCompilationDatabase CDB;
143 return completions(Server, Text, std::move(IndexSymbols), std::move(Opts),
149 CodeCompleteResult completionsNoCompile(llvm::StringRef Text,
150 std::vector<Symbol> IndexSymbols = {},
151 clangd::CodeCompleteOptions Opts = {},
152 PathRef FilePath =
"foo.cpp") {
153 std::unique_ptr<SymbolIndex> OverrideIndex;
154 if (!IndexSymbols.empty()) {
155 assert(!Opts.Index &&
"both Index and IndexSymbols given!");
156 OverrideIndex = memIndex(std::move(IndexSymbols));
157 Opts.Index = OverrideIndex.get();
161 Annotations Test(Text);
162 return codeComplete(FilePath, tooling::CompileCommand(),
nullptr,
163 Test.code(), Test.point(), FS.getFileSystem(), Opts);
166 Symbol withReferences(
int N, Symbol S) {
172 clangd::CodeCompleteOptions Opts;
174 auto Results = completions(R
"cpp( 175 struct ClassWithMembers { 181 int main() { ClassWithMembers().^ } 186 EXPECT_THAT(
Results.Completions, ElementsAre(Named(
"AAA"), Named(
"BBB")));
189 TEST(CompletionTest, Filter) {
190 std::string Body = R
"cpp( 201 EXPECT_THAT(completions(Body +
"int main() { S().Foba^ }").Completions,
202 AllOf(Has(
"FooBar"), Has(
"FooBaz"), Not(Has(
"Qux"))));
205 EXPECT_THAT(completions(Body +
"int main() { C^ }").Completions,
206 AllOf(Has(
"Car"), Not(Has(
"MotorCar"))));
209 void TestAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
216 // Make sure this is not in preamble. 219 struct GlobalClass {}; 221 struct ClassWithMembers { 231 struct LocalClass {};
239 {
cls(
"IndexClass"),
var(
"index_var"),
func(
"index_func")}, Opts);
241 EXPECT_TRUE(
Results.RanParser);
244 EXPECT_THAT(
Results.Completions,
245 AllOf(Has(
"method"), Has(
"field"), Not(Has(
"ClassWithMembers")),
246 Not(Has(
"operator=")), Not(Has(
"~ClassWithMembers"))));
248 Has(
"private_field"));
252 Not(AnyOf(Has(
"global_var"), Has(
"index_var"), Has(
"global_func"),
253 Has(
"global_func()"), Has(
"index_func"), Has(
"GlobalClass"),
254 Has(
"IndexClass"), Has(
"MACRO"), Has(
"LocalClass"))));
257 EXPECT_THAT(
Results.Completions,
261 Contains(IsDocumented()));
264 void TestGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
270 // Make sure this is not in preamble. 273 struct GlobalClass {}; 275 struct ClassWithMembers { 281 struct LocalClass {};
289 {
cls(
"IndexClass"),
var(
"index_var"),
func(
"index_func")}, Opts);
291 EXPECT_TRUE(
Results.RanParser);
293 EXPECT_THAT(
Results.Completions,
294 Not(AnyOf(Has(
"method"), Has(
"method()"), Has(
"field"))));
296 EXPECT_THAT(
Results.Completions,
297 AllOf(Has(
"global_var"), Has(
"index_var"), Has(
"global_func"),
299 Has(
"GlobalClass"), Has(
"IndexClass")));
303 EXPECT_THAT(
Results.Completions,
304 AllOf(Has(
"local_var"), Has(
"LocalClass"),
308 Contains(IsDocumented()));
311 TEST(CompletionTest, CompletionOptions) {
312 auto Test = [&](
const clangd::CodeCompleteOptions &Opts) {
313 TestAfterDotCompletion(Opts);
314 TestGlobalScopeCompletion(Opts);
326 for (
auto &F : Flags) {
327 clangd::CodeCompleteOptions O;
333 TEST(CompletionTest, Accessible) {
334 auto Internal = completions(R
"cpp( 337 protected: void prot(); 338 private: void priv(); 340 void Foo::pub() { this->^ } 342 EXPECT_THAT(Internal.Completions, 343 AllOf(Has("priv"), Has(
"prot"), Has(
"pub")));
345 auto External = completions(R
"cpp( 348 protected: void prot(); 349 private: void priv(); 356 EXPECT_THAT(External.Completions, 357 AllOf(Has("pub"), Not(Has(
"prot")), Not(Has(
"priv"))));
360 TEST(CompletionTest, Qualifiers) {
361 auto Results = completions(R
"cpp( 363 public: int foo() const; 366 class Bar : public Foo { 369 void test() { Bar().^ } 371 EXPECT_THAT(Results.Completions, 372 Contains(AllOf(Qualifier(""), Named(
"bar"))));
374 EXPECT_THAT(
Results.Completions,
375 Not(Contains(AllOf(Qualifier(
"Foo::"), Named(
"foo")))));
377 EXPECT_THAT(
Results.Completions,
378 Not(Contains(AllOf(Qualifier(
""), Named(
"foo")))));
381 TEST(CompletionTest, InjectedTypename) {
383 EXPECT_THAT(completions(
"struct X{}; void foo(){ X().^ }").Completions,
385 EXPECT_THAT(completions(
"struct X{ void foo(){ this->^ } };").Completions,
388 EXPECT_THAT(completions(
"struct X{ void foo(){ ^ } };").Completions,
391 completions(
"struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions,
395 "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };")
399 EXPECT_THAT(completions(
"struct X{}; void foo(){ X::^ }").Completions,
403 TEST(CompletionTest, SkipInjectedWhenUnqualified) {
404 EXPECT_THAT(completions(
"struct X { void f() { X^ }};").Completions,
405 ElementsAre(Named(
"X"), Named(
"~X")));
408 TEST(CompletionTest, Snippets) {
409 clangd::CodeCompleteOptions Opts;
414 int f(int i, const float f) const; 428 TEST(CompletionTest, Kinds) {
434 // make sure MACRO is not included in preamble. 438 {func("indexFunction"),
var(
"indexVariable"),
cls(
"indexClass")});
439 EXPECT_THAT(
Results.Completions,
450 EXPECT_THAT(
Results.Completions,
470 template <class T> struct complete_class {}; 471 template <class T> void complete_function(); 472 template <class T> using complete_type_alias = int; 473 template <class T> int complete_variable = 10; 476 template <class T> static int complete_static_member = 10; 478 static auto x = complete_^ 483 UnorderedElementsAre( 486 AllOf(Named(
"complete_type_alias"),
489 AllOf(Named(
"complete_static_member"),
493 TEST(CompletionTest, NoDuplicates) {
506 EXPECT_THAT(
Results.Completions, ElementsAre(Named(
"Adapter")));
509 TEST(CompletionTest, ScopedNoIndex) {
512 namespace fake { int BigBang, Babble, Box; }; 513 int main() { fake::ba^ } 516 EXPECT_THAT(
Results.Completions,
517 ElementsAre(Named(
"Babble"), Named(
"BigBang")));
520 TEST(CompletionTest, Scoped) {
523 namespace fake { int Babble, Box; }; 524 int main() { fake::ba^ } 526 {var("fake::BigBang")});
527 EXPECT_THAT(
Results.Completions,
528 ElementsAre(Named(
"Babble"), Named(
"BigBang")));
531 TEST(CompletionTest, ScopedWithFilter) {
536 {cls("ns::XYZ"),
func(
"ns::foo")});
537 EXPECT_THAT(
Results.Completions, UnorderedElementsAre(Named(
"XYZ")));
540 TEST(CompletionTest, ReferencesAffectRanking) {
541 auto Results = completions(
"int main() { abs^ }", {
ns(
"absl"),
func(
"absb")});
542 EXPECT_THAT(
Results.Completions,
544 Results = completions(
"int main() { abs^ }",
545 {withReferences(10000,
ns(
"absl")),
func(
"absb")});
546 EXPECT_THAT(
Results.Completions,
550 TEST(CompletionTest, ContextWords) {
551 auto Results = completions(R
"cpp( 552 enum class Color { RED, YELLOW, BLUE }; 554 // (blank lines so the definition above isn't "context") 556 // "It was a yellow car," he said. "Big yellow car, new." 557 auto Finish = Color::^ 561 ASSERT_THAT(
Results.Completions,
565 TEST(CompletionTest, GlobalQualified) {
571 EXPECT_THAT(
Results.Completions,
576 TEST(CompletionTest, FullyQualified) {
579 namespace ns { void bar(); } 583 EXPECT_THAT(
Results.Completions,
588 TEST(CompletionTest, SemaIndexMerge) {
591 namespace ns { int local; void both(); } 594 {func("ns::both"),
cls(
"ns::Index")});
596 EXPECT_THAT(
Results.Completions,
597 UnorderedElementsAre(
604 TEST(CompletionTest, SemaIndexMergeWithLimit) {
605 clangd::CodeCompleteOptions Opts;
609 namespace ns { int local; void both(); } 612 {func("ns::both"),
cls(
"ns::Index")}, Opts);
613 EXPECT_EQ(
Results.Completions.size(), Opts.Limit);
617 TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
619 MockCompilationDatabase CDB;
622 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
623 std::string BarHeader =
testPath(
"sub/bar.h");
624 FS.Files[BarHeader] =
"";
629 Symbol Sym =
cls(
"ns::X");
630 Sym.CanonicalDeclaration.FileURI = BarURI.c_str();
631 Sym.IncludeHeaders.emplace_back(BarURI, 1);
633 auto Results = completions(Server,
638 EXPECT_THAT(Results.Completions, 639 ElementsAre(AllOf(Named("X"), InsertInclude(
"\"bar.h\""))));
641 CodeCompleteOptions NoInsertion;
648 EXPECT_THAT(Results.Completions, 649 ElementsAre(AllOf(Named("X"), Not(InsertInclude()))));
653 #include "sub/bar.h" // not shortest, so should only match resolved. 657 EXPECT_THAT(Results.Completions, ElementsAre(AllOf(Named("X"), Labeled(
"X"),
658 Not(InsertInclude()))));
661 TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {
663 MockCompilationDatabase CDB;
667 Symbol SymX =
cls(
"ns::X");
668 Symbol SymY =
cls(
"ns::Y");
669 std::string BarHeader =
testPath(
"bar.h");
671 SymX.CanonicalDeclaration.FileURI = BarURI.c_str();
672 SymY.CanonicalDeclaration.FileURI = BarURI.c_str();
673 SymX.IncludeHeaders.emplace_back(
"<bar>", 1);
674 SymY.IncludeHeaders.emplace_back(
"<bar>", 1);
676 auto Results = completions(Server,
685 EXPECT_THAT(Results.Completions, 686 ElementsAre(AllOf(Named("X"), Not(InsertInclude())),
687 AllOf(Named(
"Y"), Not(InsertInclude()))));
690 TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
692 MockCompilationDatabase CDB;
697 R
"cpp(namespace ns { struct preamble { int member; }; })cpp"; 699 Annotations Test(R
"cpp( 701 namespace ns { int local; } 703 void f2() { ns::preamble().$2^; } 706 clangd::CodeCompleteOptions Opts = {}; 708 auto I = memIndex({
var(
"ns::index")});
709 Opts.Index = I.get();
711 EXPECT_THAT(WithIndex.Completions,
712 UnorderedElementsAre(Named(
"local"), Named(
"index")));
713 auto ClassFromPreamble =
715 EXPECT_THAT(ClassFromPreamble.Completions, Contains(Named(
"member")));
717 Opts.Index =
nullptr;
720 EXPECT_THAT(WithoutIndex.Completions,
721 UnorderedElementsAre(Named(
"local"), Named(
"preamble")));
728 TEST(CompletionTest, CompletionInPreamble) {
729 auto Results = completions(R
"cpp( 737 EXPECT_THAT(Results, ElementsAre(Named("ifndef")));
740 TEST(CompletionTest, DynamicIndexIncludeInsertion) {
742 MockCompilationDatabase CDB;
745 Opts.BuildDynamicSymbolIndex =
true;
746 ClangdServer
Server(CDB, FS, DiagConsumer, Opts);
748 FS.Files[
testPath(
"foo_header.h")] = R
"cpp( 755 const std::string FileContent(R
"cpp( 756 #include "foo_header.h" 761 Server.addDocument(testPath("foo_impl.cpp"), FileContent);
763 ASSERT_TRUE(Server.blockUntilIdleForTest());
764 EXPECT_THAT(completions(Server,
"Foo^ foo;").Completions,
765 ElementsAre(AllOf(Named(
"Foo"), HasInclude(
"\"foo_header.h\""),
769 TEST(CompletionTest, DynamicIndexMultiFile) {
771 MockCompilationDatabase CDB;
774 Opts.BuildDynamicSymbolIndex =
true;
775 ClangdServer
Server(CDB, FS, DiagConsumer, Opts);
777 FS.Files[
testPath(
"foo.h")] = R
"cpp( 778 namespace ns { class XYZ {}; void foo(int x) {} } 785 Annotations Test(R
"cpp( 801 EXPECT_THAT(Results.Completions,
806 TEST(CompletionTest, Documentation) {
807 auto Results = completions(
809 // Non-doxygen comment. 821 EXPECT_THAT(Results.Completions,
822 Contains(AllOf(Named(
"foo"), Doc(
"Non-doxygen comment."))));
825 Contains(AllOf(Named(
"bar"), Doc(
"Doxygen comment.\n\\param int a"))));
826 EXPECT_THAT(Results.Completions,
827 Contains(AllOf(Named(
"baz"), Doc(
"Multi-line\nblock comment"))));
830 TEST(CompletionTest, GlobalCompletionFiltering) {
835 Symbol Func =
func(
"XYZ::foooo");
839 auto Results = completions(R
"(// void f() { 843 EXPECT_THAT(Results.Completions, IsEmpty()); 846 TEST(CodeCompleteTest, DisableTypoCorrection) { 847 auto Results = completions(R
"cpp( 848 namespace clang { int v; } 851 EXPECT_TRUE(Results.Completions.empty()); 854 TEST(CodeCompleteTest, NoColonColonAtTheEnd) { 855 auto Results = completions(R
"cpp( 862 EXPECT_THAT(Results.Completions, Contains(Labeled("clang")));
863 EXPECT_THAT(Results.Completions, Not(Contains(Labeled(
"clang::"))));
866 TEST(CompletionTest, BacktrackCrashes) {
868 auto Results = completions(R
"cpp( 876 EXPECT_THAT(Results.Completions, ElementsAre(Labeled("FooBarBaz")));
882 if (FooBarBaz * x^) {} 887 TEST(CompletionTest, CompleteInMacroWithStringification) { 888 auto Results = completions(R
"cpp( 889 void f(const char *, int x); 890 #define F(x) f(#x, x) 897 int f(int input_num) { 902 EXPECT_THAT(Results.Completions, 903 UnorderedElementsAre(Named("X"), Named(
"Y")));
906 TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
907 auto Results = completions(R
"cpp( 908 void f(const char *, int x); 909 #define F(x) f(#x, x) 914 int f(int input_num) { 920 EXPECT_THAT(Results.Completions, Contains(Named("X")));
923 TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
924 auto Results = completions(R
"cpp( 925 int bar(int param_in_bar) { 928 int foo(int param_in_foo) { 930 // In recorvery mode, "param_in_foo" will also be suggested among many other 931 // unrelated symbols; however, this is really a special case where this works. 932 // If the #if block is outside of the function, "param_in_foo" is still 933 // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't 934 // really provide useful results in excluded branches. 940 EXPECT_TRUE(Results.Completions.empty()); 942 SignatureHelp signatures(llvm::StringRef Text, Position Point, 943 std::vector<Symbol> IndexSymbols = {}) { 944 std::unique_ptr<SymbolIndex> Index; 945 if (!IndexSymbols.empty())
946 Index = memIndex(IndexSymbols);
949 MockCompilationDatabase CDB;
952 Opts.StaticIndex = Index.get();
954 ClangdServer
Server(CDB, FS, DiagConsumer, Opts);
960 SignatureHelp signatures(llvm::StringRef Text,
961 std::vector<Symbol> IndexSymbols = {}) {
962 Annotations Test(Text);
963 return signatures(Test.code(), Test.point(), std::move(IndexSymbols));
966 struct ExpectedParameter {
971 if (P.size() != arg.parameters.size())
973 for (
unsigned I = 0; I < P.size(); ++I) {
974 if (P[I].Text != arg.parameters[I].labelString ||
975 P[I].Offsets != arg.parameters[I].labelOffsets)
980 MATCHER_P(SigDoc, Doc,
"") {
return arg.documentation == Doc; }
984 Matcher<SignatureInformation> Sig(llvm::StringRef AnnotatedLabel) {
985 llvm::Annotations A(AnnotatedLabel);
986 std::string Label = A.code();
987 std::vector<ExpectedParameter> Parameters;
988 for (
auto Range : A.ranges()) {
989 Parameters.emplace_back();
991 ExpectedParameter &P = Parameters.back();
993 P.Offsets.first =
lspLength(llvm::StringRef(Label).substr(0,
Range.Begin));
994 P.Offsets.second =
lspLength(llvm::StringRef(Label).substr(1,
Range.End));
996 return AllOf(SigHelpLabeled(Label), ParamsAre(Parameters));
999 TEST(SignatureHelpTest, Overloads) {
1000 auto Results = signatures(R
"cpp( 1001 void foo(int x, int y); 1002 void foo(int x, float y); 1003 void foo(float x, int y); 1004 void foo(float x, float y); 1005 void bar(int x, int y = 0); 1006 int main() { foo(^); } 1008 EXPECT_THAT(Results.signatures, 1009 UnorderedElementsAre(Sig("foo([[float x]], [[float y]]) -> void"),
1010 Sig(
"foo([[float x]], [[int y]]) -> void"),
1011 Sig(
"foo([[int x]], [[float y]]) -> void"),
1012 Sig(
"foo([[int x]], [[int y]]) -> void")));
1014 EXPECT_EQ(0, Results.activeSignature);
1015 EXPECT_EQ(0, Results.activeParameter);
1018 TEST(SignatureHelpTest, DefaultArgs) {
1019 auto Results = signatures(R
"cpp( 1020 void bar(int x, int y = 0); 1021 void bar(float x = 0, int y = 42); 1024 EXPECT_THAT(Results.signatures, 1025 UnorderedElementsAre( 1026 Sig("bar([[int x]], [[int y = 0]]) -> void"),
1027 Sig(
"bar([[float x = 0]], [[int y = 42]]) -> void")));
1028 EXPECT_EQ(0, Results.activeSignature);
1029 EXPECT_EQ(0, Results.activeParameter);
1032 TEST(SignatureHelpTest, ActiveArg) {
1033 auto Results = signatures(R
"cpp( 1034 int baz(int a, int b, int c); 1035 int main() { baz(baz(1,2,3), ^); } 1037 EXPECT_THAT(Results.signatures, 1038 ElementsAre(Sig("baz([[int a]], [[int b]], [[int c]]) -> int")));
1039 EXPECT_EQ(0, Results.activeSignature);
1040 EXPECT_EQ(1, Results.activeParameter);
1043 TEST(SignatureHelpTest, OpeningParen) {
1044 llvm::StringLiteral Tests[] = {
1046 int foo(int a, int b, int c); 1048 foo(foo $p^( foo(10, 10, 10), ^ ))); 1053 Foo(int a, int b, int c); 1061 Foo(int a, int b, int c); 1064 new Foo $p^( 10, ^ ); 1068 int foo(int a, int b, int c); 1072 // Macro expansions. 1077 int foo(int a, int b, int c); 1080 ID(foo $p^( foo(10), ^ )) 1083 for (
auto Test : Tests) {
1084 Annotations Code(Test);
1085 EXPECT_EQ(signatures(Code.code(), Code.point()).argListStart,
1087 <<
"Test source:" << Test;
1091 class IndexRequestCollector :
public SymbolIndex {
1094 fuzzyFind(
const FuzzyFindRequest &Req,
1095 llvm::function_ref<
void(
const Symbol &)>
Callback)
const override {
1096 std::lock_guard<std::mutex> Lock(Mut);
1097 Requests.push_back(Req);
1101 void lookup(
const LookupRequest &,
1102 llvm::function_ref<
void(
const Symbol &)>)
const override {}
1104 void refs(
const RefsRequest &,
1105 llvm::function_ref<
void(
const Ref &)>)
const override {}
1107 void relations(
const RelationsRequest &,
1108 llvm::function_ref<
void(
const SymbolID &,
const Symbol &)>)
1113 size_t estimateMemoryUsage()
const override {
return 0; }
1115 const std::vector<FuzzyFindRequest> consumeRequests()
const {
1116 std::lock_guard<std::mutex> Lock(Mut);
1117 auto Reqs = std::move(Requests);
1124 mutable std::mutex Mut;
1125 mutable std::vector<FuzzyFindRequest> Requests;
1128 std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code) {
1129 clangd::CodeCompleteOptions Opts;
1130 IndexRequestCollector Requests;
1131 Opts.Index = &Requests;
1132 completions(Code, {}, Opts);
1133 return Requests.consumeRequests();
1136 TEST(CompletionTest, UnqualifiedIdQuery) {
1137 auto Requests = captureIndexRequests(R
"cpp( 1139 using namespace std; 1147 EXPECT_THAT(Requests, 1149 UnorderedElementsAre("",
"ns::",
"std::"))));
1152 TEST(CompletionTest, EnclosingScopeComesFirst) {
1153 auto Requests = captureIndexRequests(R
"cpp( 1155 using namespace std; 1167 EXPECT_THAT(Requests, 1170 UnorderedElementsAre("",
"std::",
"nx::ns::",
"nx::"))));
1171 EXPECT_EQ(Requests[0].Scopes[0],
"nx::ns::");
1174 TEST(CompletionTest, ResolvedQualifiedIdQuery) {
1175 auto Requests = captureIndexRequests(R
"cpp( 1177 namespace ns2 {} // ignore 1178 namespace ns3 { namespace nns3 {} } 1180 using namespace ns1; 1181 using namespace ns3::nns3; 1190 EXPECT_THAT(Requests, 1193 UnorderedElementsAre("foo::",
"ns1::",
"ns3::nns3::"))));
1196 TEST(CompletionTest, UnresolvedQualifierIdQuery) {
1197 auto Requests = captureIndexRequests(R
"cpp( 1207 EXPECT_THAT(Requests, 1210 UnorderedElementsAre("a::bar::",
"ns::bar::",
"bar::"))));
1213 TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
1214 auto Requests = captureIndexRequests(R
"cpp( 1225 UnorderedElementsAre("a::bar::"))));
1228 TEST(CompletionTest, EmptyQualifiedQuery) {
1229 auto Requests = captureIndexRequests(R
"cpp( 1238 UnorderedElementsAre("",
"ns::"))));
1241 TEST(CompletionTest, GlobalQualifiedQuery) {
1242 auto Requests = captureIndexRequests(R
"cpp( 1251 UnorderedElementsAre(""))));
1254 TEST(CompletionTest, NoDuplicatedQueryScopes) {
1255 auto Requests = captureIndexRequests(R
"cpp( 1266 EXPECT_THAT(Requests, 1268 UnorderedElementsAre("na::",
"na::nb::",
""))));
1271 TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
1272 auto Completions = completions(
1275 int SomeNameOfField; 1276 typedef int SomeNameOfTypedefField; 1280 {func("::SomeNameInTheIndex"),
func(
"::Foo::SomeNameInTheIndex")});
1282 EXPECT_THAT(Completions.Completions,
1283 AllOf(Contains(Labeled(
"SomeNameOfField")),
1284 Contains(Labeled(
"SomeNameOfTypedefField")),
1285 Not(Contains(Labeled(
"SomeNameInTheIndex")))));
1288 TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
1290 auto Completions = completions(
1297 {func("::SomeNameInTheIndex")});
1299 EXPECT_THAT(Completions.Completions,
1300 Not(Contains(Labeled(
"SomeNameInTheIndex"))));
1304 auto Completions = completions(
1308 T::template Y<int>::^ 1311 {func("::SomeNameInTheIndex")});
1313 EXPECT_THAT(Completions.Completions,
1314 Not(Contains(Labeled(
"SomeNameInTheIndex"))));
1318 auto Completions = completions(
1325 {func("::SomeNameInTheIndex")});
1327 EXPECT_THAT(Completions.Completions,
1328 Not(Contains(Labeled(
"SomeNameInTheIndex"))));
1332 TEST(CompletionTest, OverloadBundling) {
1333 clangd::CodeCompleteOptions Opts;
1334 Opts.BundleOverloads =
true;
1336 std::string Context = R
"cpp( 1338 // Overload with int 1340 // Overload with bool 1349 EXPECT_THAT(completions(Context +
"int y = X().^", {}, Opts).Completions,
1350 UnorderedElementsAre(Labeled(
"a(…)"), Labeled(
"b(float)")));
1353 Symbol NoArgsGFunc =
func(
"GFuncC");
1355 completions(Context +
"int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1356 UnorderedElementsAre(Labeled(
"GFuncC(…)"), Labeled(
"GFuncD(int)")));
1360 NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile.c_str();
1361 NoArgsGFunc.IncludeHeaders.emplace_back(
"<foo>", 1);
1363 completions(Context +
"int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1364 UnorderedElementsAre(AllOf(Named(
"GFuncC"), InsertInclude(
"<foo>")),
1365 Labeled(
"GFuncC(int)"), Labeled(
"GFuncD(int)")));
1369 completions(Context +
"int y = X().a^", {}, Opts).Completions.front();
1370 EXPECT_EQ(A.Name,
"a");
1371 EXPECT_EQ(A.Signature,
"(…)");
1372 EXPECT_EQ(A.BundleSize, 2u);
1374 EXPECT_EQ(A.ReturnType,
"int");
1376 EXPECT_THAT(A.Documentation, AnyOf(HasSubstr(
"Overload with int"),
1377 HasSubstr(
"Overload with bool")));
1378 EXPECT_EQ(A.SnippetSuffix,
"($0)");
1381 TEST(CompletionTest, DocumentationFromChangedFileCrash) {
1385 FS.Files[FooH] = R
"cpp( 1386 // this is my documentation comment. 1389 FS.Files[FooCpp] = "";
1391 MockCompilationDatabase CDB;
1395 Annotations Source(R
"cpp( 1398 // This makes sure we have func from header in the AST. 1404 ASSERT_TRUE(Server.blockUntilIdleForTest());
1407 FS.Files[FooH] = R
"cpp( 1411 clangd::CodeCompleteOptions Opts; 1412 Opts.IncludeComments = true;
1413 CodeCompleteResult Completions =
1417 EXPECT_THAT(Completions.Completions,
1418 Contains(AllOf(Not(IsDocumented()), Named(
"func"))));
1421 TEST(CompletionTest, NonDocComments) {
1424 FS.Files[FooCpp] =
"";
1426 MockCompilationDatabase CDB;
1430 Annotations Source(R
"cpp( 1431 // We ignore namespace comments, for rationale see CodeCompletionStrings.h. 1432 namespace comments_ns { 1435 // ------------------ 1438 // A comment and a decl are separated by newlines. 1439 // Therefore, the comment shouldn't show up as doc comment. 1443 // this comment should be in the results. 1450 int comments_quux(); 1454 // This comment should not be there. 1457 int Struct<T>::comments_qux() { 1460 // This comment **should** be in results. 1462 int Struct<T>::comments_quux() { 1468 CDB.ExtraClangFlags.push_back(
"-fno-delayed-template-parsing");
1471 Server, FooCpp, Source.point(), clangd::CodeCompleteOptions()));
1475 Completions.Completions,
1476 UnorderedElementsAre(AllOf(Not(IsDocumented()), Named(
"comments_foo")),
1477 AllOf(IsDocumented(), Named(
"comments_baz")),
1478 AllOf(IsDocumented(), Named(
"comments_quux")),
1479 AllOf(Not(IsDocumented()), Named(
"comments_ns")),
1484 AllOf(IsDocumented(), Named(
"comments_bar")),
1485 AllOf(IsDocumented(), Named(
"comments_qux"))));
1488 TEST(CompletionTest, CompleteOnInvalidLine) {
1491 MockCompilationDatabase CDB;
1494 FS.Files[FooCpp] =
"// empty file";
1501 EXPECT_THAT_EXPECTED(
1506 TEST(CompletionTest, QualifiedNames) {
1507 auto Results = completions(
1509 namespace ns { int local; void both(); } 1510 void f() { ::ns::^ } 1512 {func("ns::both"),
cls(
"ns::Index")});
1515 Results.Completions,
1516 UnorderedElementsAre(Scope(
"ns::"), Scope(
"ns::"), Scope(
"ns::")));
1519 TEST(CompletionTest, Render) {
1522 C.Signature =
"(bool) const";
1523 C.SnippetSuffix =
"(${0:bool})";
1524 C.ReturnType =
"int";
1525 C.RequiredQualifier =
"Foo::";
1526 C.Scope =
"ns::Foo::";
1527 C.Documentation =
"This is x().";
1528 C.Includes.emplace_back();
1529 auto &Include = C.Includes.back();
1530 Include.Header =
"\"foo.h\"";
1532 C.Score.Total = 1.0;
1535 CodeCompleteOptions Opts;
1536 Opts.IncludeIndicator.Insert =
"^";
1537 Opts.IncludeIndicator.NoInsert =
"";
1538 Opts.EnableSnippets =
false;
1540 auto R = C.render(Opts);
1541 EXPECT_EQ(R.label,
"Foo::x(bool) const");
1542 EXPECT_EQ(R.insertText,
"Foo::x");
1544 EXPECT_EQ(R.filterText,
"x");
1545 EXPECT_EQ(R.detail,
"int\n\"foo.h\"");
1546 EXPECT_EQ(R.documentation,
"This is x().");
1547 EXPECT_THAT(R.additionalTextEdits, IsEmpty());
1548 EXPECT_EQ(R.sortText,
sortText(1.0,
"x"));
1549 EXPECT_FALSE(R.deprecated);
1551 Opts.EnableSnippets =
true;
1553 EXPECT_EQ(R.insertText,
"Foo::x(${0:bool})");
1556 Include.Insertion.emplace();
1558 EXPECT_EQ(R.label,
"^Foo::x(bool) const");
1559 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
1561 Opts.ShowOrigins =
true;
1563 EXPECT_EQ(R.label,
"^[AS]Foo::x(bool) const");
1567 EXPECT_EQ(R.detail,
"[2 overloads]\n\"foo.h\"");
1569 C.Deprecated =
true;
1571 EXPECT_TRUE(R.deprecated);
1574 TEST(CompletionTest, IgnoreRecoveryResults) {
1575 auto Results = completions(
1577 namespace ns { int NotRecovered() { return 0; } } 1579 // Sema enters recovery mode first and then normal mode. 1580 if (auto x = ns::NotRecover^) 1583 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("NotRecovered")));
1586 TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
1587 auto Results = completions(
1590 class X { public: X(); int x_; }; 1594 EXPECT_THAT(Results.Completions, 1595 UnorderedElementsAre(AllOf(Scope("ns::X::"), Named(
"x_"))));
1598 TEST(CompletionTest, CodeCompletionContext) {
1599 auto Results = completions(
1602 class X { public: X(); int x_; }; 1610 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess); 1613 TEST(CompletionTest, FixItForArrowToDot) { 1615 MockCompilationDatabase CDB; 1619 CodeCompleteOptions Opts; 1620 Opts.IncludeFixIts = true;
1621 Annotations TestCode(
1627 class ClassWithPtr { 1629 void MemberFunction(); 1630 Auxilary* operator->() const; 1639 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1640 EXPECT_EQ(Results.Completions.size(), 3u);
1642 TextEdit ReplacementEdit;
1643 ReplacementEdit.range = TestCode.range();
1644 ReplacementEdit.newText =
".";
1645 for (
const auto &C : Results.Completions) {
1646 EXPECT_TRUE(C.FixIts.size() == 1u || C.Name ==
"AuxFunction");
1647 if (!C.FixIts.empty()) {
1648 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
1653 TEST(CompletionTest, FixItForDotToArrow) {
1655 MockCompilationDatabase CDB;
1659 CodeCompleteOptions Opts;
1660 Opts.IncludeFixIts =
true;
1661 Annotations TestCode(
1667 class ClassWithPtr { 1669 void MemberFunction(); 1670 Auxilary* operator->() const; 1679 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1680 EXPECT_EQ(Results.Completions.size(), 3u);
1682 TextEdit ReplacementEdit;
1683 ReplacementEdit.range = TestCode.range();
1684 ReplacementEdit.newText =
"->";
1685 for (
const auto &C : Results.Completions) {
1686 EXPECT_TRUE(C.FixIts.empty() || C.Name ==
"AuxFunction");
1687 if (!C.FixIts.empty()) {
1688 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
1693 TEST(CompletionTest, RenderWithFixItMerged) {
1695 FixIt.range.end.character = 5;
1696 FixIt.newText =
"->";
1700 C.RequiredQualifier =
"Foo::";
1702 C.CompletionTokenRange.start.character = 5;
1704 CodeCompleteOptions Opts;
1705 Opts.IncludeFixIts =
true;
1707 auto R = C.render(Opts);
1708 EXPECT_TRUE(R.textEdit);
1709 EXPECT_EQ(R.textEdit->newText,
"->Foo::x");
1710 EXPECT_TRUE(R.additionalTextEdits.empty());
1713 TEST(CompletionTest, RenderWithFixItNonMerged) {
1715 FixIt.range.end.character = 4;
1716 FixIt.newText =
"->";
1720 C.RequiredQualifier =
"Foo::";
1722 C.CompletionTokenRange.start.character = 5;
1724 CodeCompleteOptions Opts;
1725 Opts.IncludeFixIts =
true;
1727 auto R = C.render(Opts);
1728 EXPECT_TRUE(R.textEdit);
1729 EXPECT_EQ(R.textEdit->newText,
"Foo::x");
1730 EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
1733 TEST(CompletionTest, CompletionTokenRange) {
1735 MockCompilationDatabase CDB;
1739 constexpr
const char *TestCodes[] = {
1760 for (
const auto &Text : TestCodes) {
1761 Annotations TestCode(Text);
1762 auto Results = completions(Server, TestCode.code(), TestCode.point());
1764 EXPECT_EQ(Results.Completions.size(), 1u);
1765 EXPECT_THAT(Results.Completions.front().CompletionTokenRange,
1770 TEST(SignatureHelpTest, OverloadsOrdering) {
1771 const auto Results = signatures(R
"cpp( 1773 void foo(int x, float y); 1774 void foo(float x, int y); 1775 void foo(float x, float y); 1776 void foo(int x, int y = 0); 1777 int main() { foo(^); } 1779 EXPECT_THAT(Results.signatures, 1780 ElementsAre(Sig("foo([[int x]]) -> void"),
1781 Sig(
"foo([[int x]], [[int y = 0]]) -> void"),
1782 Sig(
"foo([[float x]], [[int y]]) -> void"),
1783 Sig(
"foo([[int x]], [[float y]]) -> void"),
1784 Sig(
"foo([[float x]], [[float y]]) -> void")));
1786 EXPECT_EQ(0, Results.activeSignature);
1787 EXPECT_EQ(0, Results.activeParameter);
1790 TEST(SignatureHelpTest, InstantiatedSignatures) {
1791 StringRef Sig0 = R
"cpp( 1800 EXPECT_THAT(signatures(Sig0).signatures, 1801 ElementsAre(Sig("foo([[T]], [[T]], [[T]]) -> void")));
1803 StringRef Sig1 = R
"cpp( 1811 EXPECT_THAT(signatures(Sig1).signatures, 1812 ElementsAre(Sig("foo([[T]], [[T]], [[T]]) -> void")));
1814 StringRef Sig2 = R
"cpp( 1815 template <class ...T> 1823 EXPECT_THAT(signatures(Sig2).signatures, 1824 ElementsAre(Sig("foo([[T...]]) -> void")));
1831 StringRef Sig3 = R
"cpp( 1839 X<int>().foo<double>(^) 1843 EXPECT_THAT(signatures(Sig3).signatures, 1844 ElementsAre(Sig("foo([[T]], [[U]]) -> void")));
1847 TEST(SignatureHelpTest, IndexDocumentation) {
1848 Symbol Foo0 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#");
1849 Foo0.Documentation =
"Doc from the index";
1850 Symbol Foo1 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#I#");
1851 Foo1.Documentation =
"Doc from the index";
1852 Symbol Foo2 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#I#I#");
1854 StringRef Sig0 = R
"cpp( 1864 signatures(Sig0, {Foo0}).signatures, 1865 ElementsAre(AllOf(Sig("foo() -> int"), SigDoc(
"Doc from the index")),
1866 AllOf(Sig(
"foo([[double]]) -> int"), SigDoc(
""))));
1868 StringRef Sig1 = R
"cpp( 1870 // Overriden doc from sema 1881 signatures(Sig1, {Foo0, Foo1, Foo2}).signatures, 1883 AllOf(Sig("foo() -> int"), SigDoc(
"Doc from the index")),
1884 AllOf(Sig(
"foo([[int]]) -> int"), SigDoc(
"Overriden doc from sema")),
1885 AllOf(Sig(
"foo([[int]], [[int]]) -> int"), SigDoc(
"Doc from sema"))));
1888 TEST(SignatureHelpTest, DynamicIndexDocumentation) {
1890 MockCompilationDatabase CDB;
1893 Opts.BuildDynamicSymbolIndex =
true;
1894 ClangdServer
Server(CDB, FS, DiagConsumer, Opts);
1896 FS.Files[
testPath(
"foo.h")] = R
"cpp( 1902 Annotations FileContent(R"cpp( 1910 Server.addDocument(
File, FileContent.code());
1912 ASSERT_TRUE(Server.blockUntilIdleForTest());
1916 ElementsAre(AllOf(Sig(
"foo() -> int"), SigDoc(
"Member doc"))));
1919 TEST(CompletionTest, CompletionFunctionArgsDisabled) {
1920 CodeCompleteOptions Opts;
1921 Opts.EnableSnippets =
true;
1922 Opts.EnableFunctionArgSnippets =
false;
1925 auto Results = completions(
1928 void xfoo(int x, int y); 1929 void f() { xfo^ })cpp", 1932 Results.Completions, 1933 UnorderedElementsAre(AllOf(Named("xfoo"),
SnippetSuffix(
"()")),
1937 auto Results = completions(
1940 void f() { xba^ })cpp", 1942 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf( 1946 Opts.BundleOverloads =
true;
1947 auto Results = completions(
1950 void xfoo(int x, int y); 1951 void f() { xfo^ })cpp", 1954 Results.Completions, 1955 UnorderedElementsAre(AllOf(Named("xfoo"),
SnippetSuffix(
"($0)"))));
1958 auto Results = completions(
1960 template <class T, class U> 1961 void xfoo(int a, U b); 1962 void f() { xfo^ })cpp", 1965 Results.Completions, 1966 UnorderedElementsAre(AllOf(Named("xfoo"),
SnippetSuffix(
"<$1>($0)"))));
1969 auto Results = completions(
1974 using foo_alias = T**; 1975 void f() { foo_^ })cpp", 1978 Results.Completions, 1979 UnorderedElementsAre(AllOf(Named("foo_class"),
SnippetSuffix(
"<$0>")),
1984 TEST(CompletionTest, SuggestOverrides) {
1985 constexpr
const char *
const Text(R
"cpp( 1988 virtual void vfunc(bool param); 1989 virtual void vfunc(bool param, int p); 1990 void func(bool param); 1992 class B : public A { 1993 virtual void ttt(bool param) const; 1994 void vfunc(bool param, int p) override; 1996 class C : public B { 1998 void vfunc(bool param) override; 2002 const auto Results = completions(Text);
2004 Results.Completions,
2005 AllOf(Contains(AllOf(Labeled(
"void vfunc(bool param, int p) override"),
2006 NameStartsWith(
"vfunc"))),
2007 Contains(AllOf(Labeled(
"void ttt(bool param) const override"),
2008 NameStartsWith(
"ttt"))),
2009 Not(Contains(Labeled(
"void vfunc(bool param) override")))));
2012 TEST(CompletionTest, OverridesNonIdentName) {
2016 virtual ~Base() = 0; 2017 virtual operator int() = 0; 2018 virtual Base& operator+(Base&) = 0; 2021 struct Derived : Base { 2027 TEST(GuessCompletionPrefix, Filters) { 2028 for (llvm::StringRef Case : {
2029 "[[scope::]][[ident]]^",
2038 "some text [[scope::more::]][[identif]]^ier",
2039 "some text [[scope::]][[mor]]^e::identifier",
2040 "weird case foo::[[::bar::]][[baz]]^",
2042 Annotations F(Case);
2044 auto ToStringRef = [&](
Range R) {
2048 auto WantQualifier = ToStringRef(F.ranges()[0]),
2049 WantName = ToStringRef(F.ranges()[1]);
2053 EXPECT_EQ(WantQualifier, Prefix.Qualifier) << Case;
2054 EXPECT_EQ(WantQualifier.begin(), Prefix.Qualifier.begin()) << Case;
2055 EXPECT_EQ(WantName, Prefix.Name) << Case;
2056 EXPECT_EQ(WantName.begin(), Prefix.Name.begin()) << Case;
2060 TEST(CompletionTest, EnableSpeculativeIndexRequest) {
2062 MockCompilationDatabase CDB;
2067 Annotations Test(R
"cpp( 2068 namespace ns1 { int abc; } 2069 namespace ns2 { int abc; } 2070 void f() { ns1::ab$1^; ns1::ab$2^; } 2071 void f2() { ns2::ab$3^; } 2074 clangd::CodeCompleteOptions Opts = {}; 2076 IndexRequestCollector Requests; 2077 Opts.Index = &Requests; 2078 Opts.SpeculativeIndexRequest = true;
2080 auto CompleteAtPoint = [&](StringRef P) {
2084 std::this_thread::sleep_for(std::chrono::milliseconds(100));
2087 CompleteAtPoint(
"1");
2088 auto Reqs1 = Requests.consumeRequests();
2089 ASSERT_EQ(Reqs1.size(), 1u);
2090 EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre(
"ns1::"));
2092 CompleteAtPoint(
"2");
2093 auto Reqs2 = Requests.consumeRequests();
2095 ASSERT_EQ(Reqs2.size(), 1u);
2096 EXPECT_EQ(Reqs2[0], Reqs1[0]);
2098 CompleteAtPoint(
"3");
2101 auto Reqs3 = Requests.consumeRequests();
2102 ASSERT_EQ(Reqs3.size(), 2u);
2105 TEST(CompletionTest, InsertTheMostPopularHeader) {
2108 sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2109 sym.IncludeHeaders.emplace_back(
"\"foo.h\"", 2);
2110 sym.IncludeHeaders.emplace_back(
"\"bar.h\"", 1000);
2112 auto Results = completions(
"Fun^", {sym}).Completions;
2113 assert(!Results.empty());
2114 EXPECT_THAT(Results[0], AllOf(Named(
"Func"), InsertInclude(
"\"bar.h\"")));
2115 EXPECT_EQ(Results[0].Includes.size(), 2u);
2118 TEST(CompletionTest, NoInsertIncludeIfOnePresent) {
2120 MockCompilationDatabase CDB;
2122 std::string FooHeader =
testPath(
"foo.h");
2123 FS.Files[FooHeader] =
"";
2130 sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2131 sym.IncludeHeaders.emplace_back(
"\"foo.h\"", 2);
2132 sym.IncludeHeaders.emplace_back(
"\"bar.h\"", 1000);
2135 completions(Server,
"#include \"foo.h\"\nFun^", {sym}).Completions,
2136 UnorderedElementsAre(
2137 AllOf(Named(
"Func"), HasInclude(
"\"foo.h\""), Not(InsertInclude()))));
2140 TEST(CompletionTest, MergeMacrosFromIndexAndSema) {
2142 Sym.Name =
"Clangd_Macro_Test";
2143 Sym.ID =
SymbolID(
"c:foo.cpp@8@macro@Clangd_Macro_Test");
2144 Sym.SymInfo.Kind = index::SymbolKind::Macro;
2146 EXPECT_THAT(completions(
"#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym})
2148 UnorderedElementsAre(Named(
"Clangd_Macro_Test")));
2151 TEST(CompletionTest, MacroFromPreamble) {
2153 MockCompilationDatabase CDB;
2154 std::string FooHeader =
testPath(
"foo.h");
2155 FS.Files[FooHeader] =
"#define CLANGD_PREAMBLE_HEADER x\n";
2158 auto Results = completions(
2159 R
"cpp(#include "foo.h" 2160 #define CLANGD_PREAMBLE_MAIN x 2163 #define CLANGD_MAIN x 2164 void f() { CLANGD_^ } 2166 {func("CLANGD_INDEX")});
2169 EXPECT_THAT(Results.Completions,
2170 UnorderedElementsAre(Named(
"CLANGD_PREAMBLE_MAIN"),
2171 Named(
"CLANGD_MAIN"),
2172 Named(
"CLANGD_INDEX")));
2175 TEST(CompletionTest, DeprecatedResults) {
2176 std::string Body = R
"cpp( 2178 void TestClangc() __attribute__((deprecated("", ""))); 2182 completions(Body + "int main() { TestClang^ }").Completions,
2183 UnorderedElementsAre(AllOf(Named(
"TestClangd"), Not(Deprecated())),
2184 AllOf(Named(
"TestClangc"), Deprecated())));
2187 TEST(SignatureHelpTest, InsideArgument) {
2189 const auto Results = signatures(R
"cpp( 2191 void foo(int x, int y); 2192 int main() { foo(1+^); } 2194 EXPECT_THAT(Results.signatures, 2195 ElementsAre(Sig("foo([[int x]]) -> void"),
2196 Sig(
"foo([[int x]], [[int y]]) -> void")));
2197 EXPECT_EQ(0, Results.activeParameter);
2200 const auto Results = signatures(R
"cpp( 2202 void foo(int x, int y); 2203 int main() { foo(1^); } 2205 EXPECT_THAT(Results.signatures, 2206 ElementsAre(Sig("foo([[int x]]) -> void"),
2207 Sig(
"foo([[int x]], [[int y]]) -> void")));
2208 EXPECT_EQ(0, Results.activeParameter);
2211 const auto Results = signatures(R
"cpp( 2213 void foo(int x, int y); 2214 int main() { foo(1^0); } 2216 EXPECT_THAT(Results.signatures, 2217 ElementsAre(Sig("foo([[int x]]) -> void"),
2218 Sig(
"foo([[int x]], [[int y]]) -> void")));
2219 EXPECT_EQ(0, Results.activeParameter);
2222 const auto Results = signatures(R
"cpp( 2224 void foo(int x, int y); 2225 int bar(int x, int y); 2226 int main() { bar(foo(2, 3^)); } 2228 EXPECT_THAT(Results.signatures, 2229 ElementsAre(Sig("foo([[int x]], [[int y]]) -> void")));
2230 EXPECT_EQ(1, Results.activeParameter);
2234 TEST(SignatureHelpTest, ConstructorInitializeFields) {
2236 const auto Results = signatures(R
"cpp( 2245 EXPECT_THAT(Results.signatures, 2246 UnorderedElementsAre(Sig("A([[int]])"), Sig(
"A([[A &&]])"),
2247 Sig(
"A([[const A &]])")));
2250 const auto Results = signatures(R
"cpp( 2259 B() : c_elem(A(1^)) {} 2263 EXPECT_THAT(Results.signatures, 2264 UnorderedElementsAre(Sig("A([[int]])"), Sig(
"A([[A &&]])"),
2265 Sig(
"A([[const A &]])")));
2269 TEST(CompletionTest, IncludedCompletionKinds) {
2271 MockCompilationDatabase CDB;
2272 std::string Subdir =
testPath(
"sub");
2273 std::string SearchDirArg = (Twine(
"-I") +
Subdir).str();
2274 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
2275 std::string BarHeader =
testPath(
"sub/bar.h");
2276 FS.Files[BarHeader] =
"";
2279 auto Results = completions(Server,
2283 EXPECT_THAT(Results.Completions, 2288 TEST(CompletionTest, NoCrashAtNonAlphaIncludeHeader) {
2289 auto Results = completions(
2293 EXPECT_TRUE(Results.Completions.empty()); 2296 TEST(CompletionTest, NoAllScopesCompletionWhenQualified) { 2297 clangd::CodeCompleteOptions Opts = {}; 2298 Opts.AllScopes = true;
2300 auto Results = completions(
2302 void f() { na::Clangd^ } 2304 {cls("na::ClangdA"),
cls(
"nx::ClangdX"),
cls(
"Clangd3")}, Opts);
2305 EXPECT_THAT(Results.Completions,
2306 UnorderedElementsAre(
2307 AllOf(Qualifier(
""), Scope(
"na::"), Named(
"ClangdA"))));
2310 TEST(CompletionTest, AllScopesCompletion) {
2311 clangd::CodeCompleteOptions Opts = {};
2312 Opts.AllScopes =
true;
2314 auto Results = completions(
2317 void f() { Clangd^ } 2320 {cls("nx::Clangd1"),
cls(
"ny::Clangd2"),
cls(
"Clangd3"),
2321 cls(
"na::nb::Clangd4")},
2324 Results.Completions,
2325 UnorderedElementsAre(AllOf(Qualifier(
"nx::"), Named(
"Clangd1")),
2326 AllOf(Qualifier(
"ny::"), Named(
"Clangd2")),
2327 AllOf(Qualifier(
""), Scope(
""), Named(
"Clangd3")),
2328 AllOf(Qualifier(
"nb::"), Named(
"Clangd4"))));
2331 TEST(CompletionTest, NoQualifierIfShadowed) {
2332 clangd::CodeCompleteOptions Opts = {};
2333 Opts.AllScopes =
true;
2335 auto Results = completions(R
"cpp( 2336 namespace nx { class Clangd1 {}; } 2338 void f() { Clangd^ } 2340 {cls("nx::Clangd1"),
cls(
"nx::Clangd2")}, Opts);
2343 EXPECT_THAT(Results.Completions,
2344 UnorderedElementsAre(AllOf(Qualifier(
""), Named(
"Clangd1")),
2345 AllOf(Qualifier(
"nx::"), Named(
"Clangd2"))));
2348 TEST(CompletionTest, NoCompletionsForNewNames) {
2349 clangd::CodeCompleteOptions Opts;
2350 Opts.AllScopes =
true;
2351 auto Results = completions(R
"cpp( 2354 {cls("naber"),
cls(
"nx::naber")}, Opts);
2355 EXPECT_THAT(Results.Completions, UnorderedElementsAre());
2358 TEST(CompletionTest, ObjectiveCMethodNoArguments) {
2359 auto Results = completions(R
"objc( 2361 @property(nonatomic, setter=setXToIgnoreComplete:) int value; 2363 Foo *foo = [Foo new]; int y = [foo v^] 2368 auto C = Results.Completions;
2369 EXPECT_THAT(C, ElementsAre(Named(
"value")));
2371 EXPECT_THAT(C, ElementsAre(
ReturnType(
"int")));
2372 EXPECT_THAT(C, ElementsAre(
Signature(
"")));
2376 TEST(CompletionTest, ObjectiveCMethodOneArgument) {
2377 auto Results = completions(R
"objc( 2379 - (int)valueForCharacter:(char)c; 2381 Foo *foo = [Foo new]; int y = [foo v^] 2386 auto C = Results.Completions;
2387 EXPECT_THAT(C, ElementsAre(Named(
"valueForCharacter:")));
2389 EXPECT_THAT(C, ElementsAre(
ReturnType(
"int")));
2390 EXPECT_THAT(C, ElementsAre(
Signature(
"(char)")));
2394 TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromBeginning) {
2395 auto Results = completions(R
"objc( 2397 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey; 2404 auto C = Results.Completions;
2405 EXPECT_THAT(C, ElementsAre(Named(
"fooWithValue:")));
2407 EXPECT_THAT(C, ElementsAre(
ReturnType(
"id")));
2408 EXPECT_THAT(C, ElementsAre(
Signature(
"(int) fooey:(unsigned int)")));
2410 C, ElementsAre(
SnippetSuffix(
"${1:(int)} fooey:${2:(unsigned int)}")));
2413 TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
2414 auto Results = completions(R
"objc( 2416 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey; 2418 id val = [Foo fooWithValue:10 f^] 2423 auto C = Results.Completions;
2424 EXPECT_THAT(C, ElementsAre(Named(
"fooey:")));
2426 EXPECT_THAT(C, ElementsAre(
ReturnType(
"id")));
2427 EXPECT_THAT(C, ElementsAre(
Signature(
"(unsigned int)")));
2428 EXPECT_THAT(C, ElementsAre(
SnippetSuffix(
"${1:(unsigned int)}")));
2431 TEST(CompletionTest, CursorInSnippets) {
2432 clangd::CodeCompleteOptions Options;
2433 Options.EnableSnippets =
true;
2434 auto Results = completions(
2436 void while_foo(int a, int b); 2443 EXPECT_THAT(Results.Completions,
2446 SnippetSuffix(
" (${1:condition}) {\n${0:statements}\n}"))));
2448 EXPECT_THAT(Results.Completions,
2449 Contains(AllOf(Named(
"while_foo"),
2453 TEST(CompletionTest, WorksWithNullType) {
2454 auto R = completions(R
"cpp( 2456 for (auto [loopVar] : y ) { // y has to be unresolved. 2461 EXPECT_THAT(R.Completions, ElementsAre(Named("loopVar")));
2464 TEST(CompletionTest, UsingDecl) {
2465 const char *Header(R
"cpp( 2470 const char *Source(R
"cpp( 2475 clangd::CodeCompleteOptions Opts;
2476 Opts.Index = Index.get();
2477 Opts.AllScopes =
true;
2478 auto R = completions(Source, {}, Opts);
2479 EXPECT_THAT(R.Completions,
2480 ElementsAre(AllOf(Scope(
"std::"), Named(
"foo"),
2484 TEST(CompletionTest, ScopeIsUnresolved) {
2485 clangd::CodeCompleteOptions Opts = {};
2486 Opts.AllScopes =
true;
2488 auto Results = completions(R
"cpp( 2493 {cls("a::b::XYZ")}, Opts);
2494 EXPECT_THAT(Results.Completions,
2495 UnorderedElementsAre(AllOf(Qualifier(
""), Named(
"XYZ"))));
2498 TEST(CompletionTest, NestedScopeIsUnresolved) {
2499 clangd::CodeCompleteOptions Opts = {};
2500 Opts.AllScopes =
true;
2502 auto Results = completions(R
"cpp( 2505 void f() { b::c::X^ } 2508 {cls("a::b::c::XYZ")}, Opts);
2509 EXPECT_THAT(Results.Completions,
2510 UnorderedElementsAre(AllOf(Qualifier(
""), Named(
"XYZ"))));
2515 TEST(CompletionTest, NamespaceDoubleInsertion) {
2516 clangd::CodeCompleteOptions Opts = {};
2518 auto Results = completions(R
"cpp( 2525 {cls("foo::ns::ABCDE")}, Opts);
2526 EXPECT_THAT(Results.Completions,
2527 UnorderedElementsAre(AllOf(Qualifier(
""), Named(
"ABCDE"))));
2530 TEST(NoCompileCompletionTest, Basic) {
2531 auto Results = completionsNoCompile(R
"cpp( 2538 EXPECT_FALSE(Results.RanParser); 2539 EXPECT_THAT(Results.Completions, 2540 UnorderedElementsAre(Named("void"), Named(
"func"), Named(
"int"),
2541 Named(
"xyz"), Named(
"abc")));
2544 TEST(NoCompileCompletionTest, WithFilter) {
2545 auto Results = completionsNoCompile(R
"cpp( 2554 EXPECT_THAT(Results.Completions, 2555 UnorderedElementsAre(Named("sym1"), Named(
"sym2")));
2558 TEST(NoCompileCompletionTest, WithIndex) {
2559 std::vector<Symbol> Syms = {
func(
"xxx"),
func(
"a::xxx"),
func(
"ns::b::xxx"),
2560 func(
"c::xxx"),
func(
"ns::d::xxx")};
2561 auto Results = completionsNoCompile(
2563 // Current-scopes, unqualified completion. 2572 EXPECT_THAT(Results.Completions, 2573 UnorderedElementsAre(AllOf(Qualifier(""), Scope(
"")),
2574 AllOf(Qualifier(
""), Scope(
"a::")),
2575 AllOf(Qualifier(
""), Scope(
"ns::b::"))));
2576 CodeCompleteOptions Opts;
2577 Opts.AllScopes =
true;
2578 Results = completionsNoCompile(
2580 // All-scopes unqualified completion. 2589 EXPECT_THAT(Results.Completions, 2590 UnorderedElementsAre(AllOf(Qualifier(""), Scope(
"")),
2591 AllOf(Qualifier(
""), Scope(
"a::")),
2592 AllOf(Qualifier(
""), Scope(
"ns::b::")),
2593 AllOf(Qualifier(
"c::"), Scope(
"c::")),
2594 AllOf(Qualifier(
"d::"), Scope(
"ns::d::"))));
2595 Results = completionsNoCompile(
2597 // Qualified completion. 2606 EXPECT_THAT(Results.Completions, 2607 ElementsAre(AllOf(Qualifier(""), Scope(
"ns::b::"))));
2608 Results = completionsNoCompile(
2610 // Absolutely qualified completion. 2619 EXPECT_THAT(Results.Completions, 2620 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
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++ -*-===//
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)