27#include "clang/Sema/CodeCompleteConsumer.h"
28#include "clang/Tooling/CompilationDatabase.h"
29#include "llvm/ADT/StringRef.h"
30#include "llvm/Support/Error.h"
31#include "llvm/Support/Path.h"
32#include "llvm/Testing/Annotations/Annotations.h"
33#include "llvm/Testing/Support/Error.h"
34#include "llvm/Testing/Support/SupportHelpers.h"
35#include "gmock/gmock.h"
36#include "gtest/gtest.h"
37#include <condition_variable>
47using ::testing::AllOf;
48using ::testing::Contains;
49using ::testing::ElementsAre;
50using ::testing::Field;
51using ::testing::HasSubstr;
52using ::testing::IsEmpty;
54using ::testing::UnorderedElementsAre;
55using ContextKind = CodeCompletionContext::Kind;
59MATCHER_P(mainFileRefs, Refs,
"") {
return arg.MainFileRefs == Refs; }
60MATCHER_P(scopeRefs, Refs,
"") {
return arg.ScopeRefsInFile == Refs; }
62 return llvm::StringRef(arg.Name).starts_with(Prefix);
64MATCHER_P(filterText, F,
"") {
return arg.FilterText == F; }
65MATCHER_P(scope, S,
"") {
return arg.Scope == S; }
66MATCHER_P(qualifier, Q,
"") {
return arg.RequiredQualifier == Q; }
68 return arg.RequiredQualifier + arg.Name + arg.Signature ==
Label;
73 return arg.Documentation && arg.Documentation->asPlainText() == D;
75MATCHER_P(returnType, D,
"") {
return arg.ReturnType == D; }
77 return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader;
79MATCHER_P(insertInclude, IncludeHeader,
"") {
80 return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader &&
81 bool(arg.Includes[0].Insertion);
83MATCHER_P(insertIncludeText, InsertedText,
"") {
84 return !arg.Includes.empty() && arg.Includes[0].Insertion &&
85 arg.Includes[0].Insertion->newText == InsertedText;
88 return !arg.Includes.empty() && bool(arg.Includes[0].Insertion);
91MATCHER_P(origin, OriginSet,
"") {
return arg.Origin == OriginSet; }
92MATCHER_P(signature, S,
"") {
return arg.Signature == S; }
94 return arg.CompletionTokenRange ==
Range;
98Matcher<const std::vector<CodeCompletion> &> has(std::string
Name) {
99 return Contains(named(std::move(
Name)));
101Matcher<const std::vector<CodeCompletion> &> has(std::string
Name,
103 return Contains(AllOf(named(std::move(
Name)), kind(
K)));
105MATCHER(isDocumented,
"") {
return arg.Documentation.has_value(); }
106MATCHER(deprecated,
"") {
return arg.Deprecated; }
108std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol>
Symbols) {
109 SymbolSlab::Builder Slab;
110 for (
const auto &Sym :
Symbols)
112 return MemIndex::build(std::move(Slab).build(), RefSlab(), RelationSlab());
117CodeCompleteResult completions(
const TestTU &TU, Position Point,
118 std::vector<Symbol> IndexSymbols = {},
119 clangd::CodeCompleteOptions Opts = {}) {
120 std::unique_ptr<SymbolIndex> OverrideIndex;
121 if (!IndexSymbols.empty()) {
122 assert(!Opts.
Index &&
"both Index and IndexSymbols given!");
123 OverrideIndex = memIndex(std::move(IndexSymbols));
124 Opts.
Index = OverrideIndex.get();
128 auto Inputs = TU.inputs(FS);
129 IgnoreDiagnostics Diags;
132 ADD_FAILURE() <<
"Couldn't build CompilerInvocation";
142CodeCompleteResult completions(llvm::StringRef
Text,
143 std::vector<Symbol> IndexSymbols = {},
144 clangd::CodeCompleteOptions Opts = {},
145 PathRef FilePath =
"foo.cpp") {
146 Annotations Test(
Text);
149 TU.Filename = FilePath.str();
150 return completions(TU, Test.point(), std::move(IndexSymbols),
155CodeCompleteResult completionsNoCompile(llvm::StringRef
Text,
156 std::vector<Symbol> IndexSymbols = {},
157 clangd::CodeCompleteOptions Opts = {},
158 PathRef FilePath =
"foo.cpp") {
159 std::unique_ptr<SymbolIndex> OverrideIndex;
160 if (!IndexSymbols.empty()) {
161 assert(!Opts.
Index &&
"both Index and IndexSymbols given!");
162 OverrideIndex = memIndex(std::move(IndexSymbols));
163 Opts.
Index = OverrideIndex.get();
167 Annotations Test(
Text);
168 ParseInputs
ParseInput{tooling::CompileCommand(), &FS, Test.code().str()};
173Symbol withReferences(
int N, Symbol S) {
178#if CLANGD_DECISION_FOREST
179TEST(DecisionForestRankingModel, NameMatchSanityTest) {
180 clangd::CodeCompleteOptions Opts;
186 int AlphaBetaGamma();
188int func() { MemberAccess().ABG^ }
191 EXPECT_THAT(
Results.Completions,
192 ElementsAre(named(
"ABG"), named(
"AlphaBetaGamma")));
195TEST(DecisionForestRankingModel, ReferencesAffectRanking) {
196 clangd::CodeCompleteOptions Opts;
198 constexpr int NumReferences = 100000;
200 completions(
"int main() { clang^ }",
201 {
ns(
"clangA"), withReferences(NumReferences,
func(
"clangD"))},
204 ElementsAre(named(
"clangD"), named(
"clangA")));
206 completions(
"int main() { clang^ }",
207 {withReferences(NumReferences,
ns(
"clangA")),
func(
"clangD")},
210 ElementsAre(named(
"clangA"), named(
"clangD")));
214TEST(DecisionForestRankingModel, DecisionForestScorerCallbackTest) {
215 clangd::CodeCompleteOptions Opts;
216 constexpr float MagicNumber = 1234.5678f;
219 const SymbolRelevanceSignals &,
float Base) {
220 DecisionForestScores Scores;
221 Scores.Total = MagicNumber;
222 Scores.ExcludingName = MagicNumber;
225 llvm::StringRef
Code =
"int func() { int xyz; xy^ }";
228 ASSERT_EQ(
Results.Completions.size(), 1u);
229 EXPECT_EQ(
Results.Completions[0].Score.Total, MagicNumber);
230 EXPECT_EQ(
Results.Completions[0].Score.ExcludingName, MagicNumber);
236 ASSERT_EQ(
Results.Completions.size(), 1u);
237 EXPECT_NE(
Results.Completions[0].Score.Total, MagicNumber);
238 EXPECT_NE(
Results.Completions[0].Score.ExcludingName, MagicNumber);
241TEST(CompletionTest, Limit) {
242 clangd::CodeCompleteOptions Opts;
244 auto Results = completions(R
"cpp(
245struct ClassWithMembers {
251int main() { ClassWithMembers().^ }
256 EXPECT_THAT(
Results.Completions, ElementsAre(named(
"AAA"), named(
"BBB")));
259TEST(CompletionTest, Filter) {
260 std::string Body = R
"cpp(
271 EXPECT_THAT(completions(Body +
"int main() { S().Foba^ }").Completions,
272 AllOf(has(
"FooBar"), has(
"FooBaz"), Not(has(
"Qux"))));
275 Symbol Sym =
var(
"MotorCarIndex");
276 Sym.SymInfo.Kind = index::SymbolKind::Macro;
278 completions(Body +
"int main() { C^ }", {Sym}).Completions,
279 AllOf(has(
"Car"), Not(has(
"MotorCar")), Not(has(
"MotorCarIndex"))));
280 EXPECT_THAT(completions(Body +
"int main() { M^ }", {Sym}).Completions,
281 AllOf(has(
"MotorCar"), has(
"MotorCarIndex")));
284void testAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
291 // Make sure this is not in preamble.
294 struct GlobalClass {};
296 struct ClassWithMembers {
306 struct LocalClass {};
314 {
cls(
"IndexClass"),
var(
"index_var"),
func(
"index_func")}, Opts);
316 EXPECT_TRUE(
Results.RanParser);
319 EXPECT_THAT(
Results.Completions,
320 AllOf(has(
"method"), has(
"field"), Not(has(
"ClassWithMembers")),
321 Not(has(
"operator=")), Not(has(
"~ClassWithMembers"))));
323 has(
"private_field"));
327 Not(AnyOf(has(
"global_var"), has(
"index_var"), has(
"global_func"),
328 has(
"global_func()"), has(
"index_func"), has(
"GlobalClass"),
329 has(
"IndexClass"), has(
"MACRO"), has(
"LocalClass"))));
332 EXPECT_THAT(
Results.Completions,
335 EXPECT_THAT(
Results.Completions, Contains(isDocumented()));
338void testGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
344 // Make sure this is not in preamble.
347 struct GlobalClass {};
349 struct ClassWithMembers {
355 struct LocalClass {};
363 {
cls(
"IndexClass"),
var(
"index_var"),
func(
"index_func")}, Opts);
365 EXPECT_TRUE(
Results.RanParser);
367 EXPECT_THAT(
Results.Completions,
368 Not(AnyOf(has(
"method"), has(
"method()"), has(
"field"))));
370 EXPECT_THAT(
Results.Completions,
371 AllOf(has(
"global_var"), has(
"index_var"), has(
"global_func"),
373 has(
"GlobalClass"), has(
"IndexClass")));
375 EXPECT_THAT(
Results.Completions, has(
"MACRO"));
377 EXPECT_THAT(
Results.Completions,
378 AllOf(has(
"local_var"), has(
"LocalClass"),
381 EXPECT_THAT(
Results.Completions, Contains(isDocumented()));
384TEST(CompletionTest, CompletionOptions) {
385 auto Test = [&](
const clangd::CodeCompleteOptions &Opts) {
386 testAfterDotCompletion(Opts);
387 testGlobalScopeCompletion(Opts);
396 for (
auto &F :
Flags) {
397 clangd::CodeCompleteOptions O;
403TEST(CompletionTest, Accessible) {
404 auto Internal = completions(R
"cpp(
407 protected: void prot();
408 private: void priv();
410 void Foo::pub() { this->^ }
412 EXPECT_THAT(Internal.Completions,
413 AllOf(has("priv"), has(
"prot"), has(
"pub")));
415 auto External = completions(R
"cpp(
418 protected: void prot();
419 private: void priv();
426 EXPECT_THAT(External.Completions,
427 AllOf(has("pub"), Not(has(
"prot")), Not(has(
"priv"))));
429 auto Results = completions(R
"cpp(
432 protected: void prot();
433 private: void priv();
435 struct Bar : public Foo {
436 private: using Foo::pub;
443 EXPECT_THAT(Results.Completions,
444 AllOf(Not(has("priv")), Not(has(
"prot")), Not(has(
"pub"))));
447TEST(CompletionTest, Qualifiers) {
448 auto Results = completions(R
"cpp(
450 public: int foo() const;
453 class Bar : public Foo {
456 void test() { Bar().^ }
458 EXPECT_THAT(Results.Completions,
459 Contains(AllOf(qualifier(""), named(
"bar"))));
461 EXPECT_THAT(
Results.Completions,
462 Not(Contains(AllOf(qualifier(
"Foo::"), named(
"foo")))));
464 EXPECT_THAT(
Results.Completions,
465 Not(Contains(AllOf(qualifier(
""), named(
"foo")))));
469TEST(CompletionTest, QualificationWithInlineNamespace) {
470 auto Results = completions(R
"cpp(
471 namespace a { inline namespace b {} }
472 using namespace a::b;
476 EXPECT_THAT(
Results.Completions,
477 UnorderedElementsAre(AllOf(qualifier(
"a::"), named(
"Foo"))));
480TEST(CompletionTest, InjectedTypename) {
482 EXPECT_THAT(completions(
"struct X{}; void foo(){ X().^ }").Completions,
484 EXPECT_THAT(completions(
"struct X{ void foo(){ this->^ } };").Completions,
487 EXPECT_THAT(completions(
"struct X{ void foo(){ ^ } };").Completions,
490 completions(
"struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions,
494 "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };")
498 EXPECT_THAT(completions(
"struct X{}; void foo(){ X::^ }").Completions,
502TEST(CompletionTest, SkipInjectedWhenUnqualified) {
503 EXPECT_THAT(completions(
"struct X { void f() { X^ }};").Completions,
504 ElementsAre(named(
"X"), named(
"~X")));
507TEST(CompletionTest, Snippets) {
508 clangd::CodeCompleteOptions Opts;
513 int f(int i, const float f) const;
524 snippetSuffix(
"(${1:int i}, ${2:const float f})")));
527TEST(CompletionTest, HeuristicsForMemberFunctionCompletion) {
528 clangd::CodeCompleteOptions Opts;
531 Annotations
Code(R
"cpp(
533 static int staticMethod(int);
534 int method(int) const;
535 template <typename T, typename U, typename V = int>
537 template <typename T, int U>
538 static T staticGeneric();
546 struct Derived : Foo {
559 ; // Prevent parsing as 'f.f'
565 d.Derived::$canBeCall^
573 ; // Prevent parsing as 'f.f'
579 d.Derived::$canBeCall^
584 for (
const auto &P :
Code.points(
"canNotBeCall")) {
585 auto Results = completions(TU, P, {}, Opts);
586 EXPECT_THAT(
Results.Completions,
587 Contains(AllOf(named(
"method"), signature(
"(int) const"),
588 snippetSuffix(
""))));
593 Contains(AllOf(named(
"generic"),
594 signature(
"<typename T, typename U>(U, V)"),
595 snippetSuffix(
"<${1:typename T}, ${2:typename U}>"))));
598 for (
const auto &P :
Code.points(
"canBeCall")) {
599 auto Results = completions(TU, P, {}, Opts);
600 EXPECT_THAT(
Results.Completions,
601 Contains(AllOf(named(
"method"), signature(
"(int) const"),
602 snippetSuffix(
"(${1:int})"))));
605 Contains(AllOf(named(
"generic"), signature(
"<typename T>(U, V)"),
606 snippetSuffix(
"<${1:typename T}>(${2:U}, ${3:V})"))));
610 for (
const auto &P :
Code.points()) {
611 auto Results = completions(TU, P, {}, Opts);
612 EXPECT_THAT(
Results.Completions,
613 Contains(AllOf(named(
"staticMethod"), signature(
"(int)"),
614 snippetSuffix(
"(${1:int})"))));
615 EXPECT_THAT(
Results.Completions,
617 named(
"staticGeneric"), signature(
"<typename T, int U>()"),
618 snippetSuffix(
"<${1:typename T}, ${2:int U}>()"))));
622TEST(CompletionTest, NoSnippetsInUsings) {
623 clangd::CodeCompleteOptions Opts;
628 int func(int a, int b);
634 EXPECT_THAT(
Results.Completions,
635 ElementsAre(AllOf(named(
"func"), labeled(
"func(int a, int b)"),
636 snippetSuffix(
""))));
639 auto Func =
func(
"ns::func");
640 Func.CompletionSnippetSuffix =
"(${1:int a}, ${2: int b})";
641 Func.Signature =
"(int a, int b)";
642 Func.ReturnType =
"void";
649 EXPECT_THAT(
Results.Completions,
650 ElementsAre(AllOf(named(
"func"), labeled(
"func(int a, int b)"),
651 snippetSuffix(
""))));
659 EXPECT_THAT(
Results.Completions,
660 Contains(AllOf(named(
"func"), labeled(
"ns::func(int a, int b)"),
661 snippetSuffix(
""))));
664TEST(CompletionTest, Kinds) {
670 // make sure MACRO is not included in preamble.
674 {func("indexFunction"),
var(
"indexVariable"),
cls(
"indexClass"),
675 macro(
"indexObjMacro"),
macro(
"indexFuncMacro",
"(x, y)")});
676 EXPECT_THAT(
Results.Completions,
689 EXPECT_THAT(
Results.Completions,
709 template <class T> struct complete_class {};
710 template <class T> void complete_function();
711 template <class T> using complete_type_alias = int;
712 template <class T> int complete_variable = 10;
715 template <class T> static int complete_static_member = 10;
717 static auto x = complete_^
722 UnorderedElementsAre(
725 AllOf(named(
"complete_type_alias"),
728 AllOf(named(
"complete_static_member"),
743TEST(CompletionTest, NoDuplicates) {
756 EXPECT_THAT(
Results.Completions, ElementsAre(named(
"Adapter")));
759TEST(CompletionTest, ScopedNoIndex) {
762 namespace fake { int BigBang, Babble, Box; };
763 int main() { fake::ba^ }
766 EXPECT_THAT(
Results.Completions,
767 ElementsAre(named(
"Babble"), named(
"BigBang")));
770TEST(CompletionTest, Scoped) {
773 namespace fake { int Babble, Box; };
774 int main() { fake::ba^ }
776 {var("fake::BigBang")});
777 EXPECT_THAT(
Results.Completions,
778 ElementsAre(named(
"Babble"), named(
"BigBang")));
781TEST(CompletionTest, ScopedWithFilter) {
786 {cls("ns::XYZ"),
func(
"ns::foo")});
787 EXPECT_THAT(
Results.Completions, UnorderedElementsAre(named(
"XYZ")));
790TEST(CompletionTest, ReferencesAffectRanking) {
791 EXPECT_THAT(completions(
"int main() { abs^ }", {
func(
"absA"),
func(
"absB")})
794 EXPECT_THAT(completions(
"int main() { abs^ }",
795 {
func(
"absA"), withReferences(1000,
func(
"absB"))})
800TEST(CompletionTest, ContextWords) {
801 auto Results = completions(R
"cpp(
802 enum class Color { RED, YELLOW, BLUE };
804 // (blank lines so the definition above isn't "context")
806 // "It was a yellow car," he said. "Big yellow car, new."
807 auto Finish = Color::^
811 ASSERT_THAT(
Results.Completions,
815TEST(CompletionTest, GlobalQualified) {
821 EXPECT_THAT(
Results.Completions,
826TEST(CompletionTest, FullyQualified) {
829 namespace ns { void bar(); }
833 EXPECT_THAT(
Results.Completions,
838TEST(CompletionTest, SemaIndexMerge) {
841 namespace ns { int local; void both(); }
844 {func("ns::both"),
cls(
"ns::Index")});
846 EXPECT_THAT(
Results.Completions,
847 UnorderedElementsAre(
854TEST(CompletionTest, SemaIndexMergeWithLimit) {
855 clangd::CodeCompleteOptions Opts;
859 namespace ns { int local; void both(); }
862 {func("ns::both"),
cls(
"ns::Index")}, Opts);
867TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
869 TU.ExtraArgs.push_back(
"-I" +
testPath(
"sub"));
870 TU.AdditionalFiles[
"sub/bar.h"] =
"";
873 Symbol Sym =
cls(
"ns::X");
874 Sym.CanonicalDeclaration.FileURI = BarURI.c_str();
877 Annotations Test(
"int main() { ns::^ }");
878 TU.Code = Test.code().str();
879 auto Results = completions(TU, Test.point(), {Sym});
880 EXPECT_THAT(
Results.Completions,
881 ElementsAre(AllOf(named(
"X"), insertInclude(
"\"bar.h\""))));
883 CodeCompleteOptions NoInsertion;
885 Results = completions(TU, Test.point(), {Sym}, NoInsertion);
886 EXPECT_THAT(
Results.Completions,
887 ElementsAre(AllOf(named(
"X"), Not(insertInclude()))));
889 Test = Annotations(R
"cpp(
890 #include "sub/bar.h" // not shortest, so should only match resolved.
893 TU.Code = Test.code().str();
894 Results = completions(TU, Test.point(), {Sym});
895 EXPECT_THAT(Results.Completions, ElementsAre(AllOf(named("X"), labeled(
"X"),
896 Not(insertInclude()))));
899TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {
900 Symbol SymX =
cls(
"ns::X");
901 Symbol SymY =
cls(
"ns::Y");
902 std::string BarHeader =
testPath(
"bar.h");
904 SymX.CanonicalDeclaration.FileURI = BarURI.c_str();
905 SymY.CanonicalDeclaration.FileURI = BarURI.c_str();
909 auto Results = completions(R
"cpp(
917 EXPECT_THAT(Results.Completions,
918 ElementsAre(AllOf(named("X"), Not(insertInclude())),
919 AllOf(named(
"Y"), Not(insertInclude()))));
922TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
923 Annotations Test(R
"cpp(
925 namespace ns { int local; }
927 void f2() { ns::preamble().$2^; }
930 TU.AdditionalFiles[
"bar.h"] =
931 R
"cpp(namespace ns { struct preamble { int member; }; })cpp";
933 clangd::CodeCompleteOptions Opts = {};
934 auto I = memIndex({
var(
"ns::index")});
935 Opts.
Index = I.get();
936 auto WithIndex = completions(TU, Test.point(), {}, Opts);
937 EXPECT_THAT(WithIndex.Completions,
938 UnorderedElementsAre(named(
"local"), named(
"index")));
939 auto ClassFromPreamble = completions(TU, Test.point(
"2"), {}, Opts);
940 EXPECT_THAT(ClassFromPreamble.Completions, Contains(named(
"member")));
942 Opts.
Index =
nullptr;
943 auto WithoutIndex = completions(TU, Test.point(), {}, Opts);
944 EXPECT_THAT(WithoutIndex.Completions,
945 UnorderedElementsAre(named(
"local"), named(
"preamble")));
952TEST(CompletionTest, CompletionInPreamble) {
953 auto Results = completions(R
"cpp(
961 EXPECT_THAT(Results, ElementsAre(named("ifndef")));
964TEST(CompletionTest, CompletionRecoveryASTType) {
965 auto Results = completions(R
"cpp(
966 struct S { int member; };
969 // No overload matches, but we have recovery-expr with the correct type.
973 EXPECT_THAT(Results, ElementsAre(named("member")));
976TEST(CompletionTest, DynamicIndexIncludeInsertion) {
978 MockCompilationDatabase CDB;
980 Opts.BuildDynamicSymbolIndex =
true;
981 ClangdServer Server(CDB, FS, Opts);
983 FS.Files[
testPath(
"foo_header.h")] = R
"cpp(
990 const std::string FileContent(R
"cpp(
991 #include "foo_header.h"
996 Server.addDocument(testPath("foo_impl.cpp"), FileContent);
998 ASSERT_TRUE(Server.blockUntilIdleForTest());
1001 Annotations Test(
"Foo^ foo;");
1003 auto CompletionList =
1006 EXPECT_THAT(CompletionList.Completions,
1007 ElementsAre(AllOf(named(
"Foo"), hasInclude(
"\"foo_header.h\""),
1011TEST(CompletionTest, DynamicIndexMultiFile) {
1013 MockCompilationDatabase CDB;
1015 Opts.BuildDynamicSymbolIndex =
true;
1016 ClangdServer Server(CDB, FS, Opts);
1018 FS.Files[
testPath(
"foo.h")] = R
"cpp(
1019 namespace ns { class XYZ {}; void foo(int x) {} }
1026 Annotations Test(R
"cpp(
1042 EXPECT_THAT(
Results.Completions,
1044 doc(
"Doooc"), returnType(
"void"))));
1047TEST(CompletionTest, Documentation) {
1050 // Non-doxygen comment.
1051 __attribute__((annotate("custom_annotation"))) int foo();
1062 EXPECT_THAT(
Results.Completions,
1065 doc(
"Annotation: custom_annotation\nNon-doxygen comment."))));
1068 Contains(AllOf(named(
"bar"), doc(
"Doxygen comment.\n\\param int a"))));
1069 EXPECT_THAT(
Results.Completions,
1070 Contains(AllOf(named(
"baz"), doc(
"Multi-line block comment"))));
1073TEST(CompletionTest, CommentsFromSystemHeaders) {
1075 MockCompilationDatabase CDB;
1078 Opts.BuildDynamicSymbolIndex =
true;
1080 ClangdServer Server(CDB, FS, Opts);
1082 FS.Files[
testPath(
"foo.h")] = R
"cpp(
1083 #pragma GCC system_header
1085 // This comment should be retained!
1090 Annotations Test(R
"cpp(
1095 auto CompletionList =
1099 CompletionList.Completions,
1100 Contains(AllOf(named(
"foo"), doc(
"This comment should be retained!"))));
1103TEST(CompletionTest, GlobalCompletionFiltering) {
1108 Symbol Func =
func(
"XYZ::foooo");
1112 auto Results = completions(R
"(// void f() {
1116 EXPECT_THAT(Results.Completions, IsEmpty());
1119TEST(CodeCompleteTest, DisableTypoCorrection) {
1120 auto Results = completions(R
"cpp(
1121 namespace clang { int v; }
1122 void f() { clangd::^
1124 EXPECT_TRUE(Results.Completions.empty());
1127TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
1128 auto Results = completions(R
"cpp(
1135 EXPECT_THAT(Results.Completions, Contains(labeled("clang")));
1136 EXPECT_THAT(
Results.Completions, Not(Contains(labeled(
"clang::"))));
1139TEST(CompletionTests, EmptySnippetDoesNotCrash) {
1141 auto Results = completions(R
"cpp(
1143 auto w = [&](auto &&f) { return f(f); };
1144 auto f = w([&](auto &&f) {
1145 return [&](auto &&n) {
1149 return n * ^(f)(n - 1);
1156TEST(CompletionTest, Issue1427Crash) {
1160 ASTSignals MainFileSignals;
1161 CodeCompleteOptions Opts;
1171TEST(CompletionTest, BacktrackCrashes) {
1173 auto Results = completions(R
"cpp(
1175 struct FooBarBaz {};
1181 EXPECT_THAT(Results.Completions, ElementsAre(labeled("FooBarBaz")));
1185 struct FooBarBaz {};
1187 if (FooBarBaz * x^) {}
1192TEST(CompletionTest, CompleteInMacroWithStringification) {
1193 auto Results = completions(R
"cpp(
1194void f(const char *, int x);
1195#define F(x) f(#x, x)
1202int f(int input_num) {
1207 EXPECT_THAT(Results.Completions,
1208 UnorderedElementsAre(named("X"), named(
"Y")));
1211TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
1212 auto Results = completions(R
"cpp(
1213void f(const char *, int x);
1214#define F(x) f(#x, x)
1219int f(int input_num) {
1225 EXPECT_THAT(Results.Completions, Contains(named("X")));
1228TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
1229 auto Results = completions(R
"cpp(
1230 int bar(int param_in_bar) {
1233 int foo(int param_in_foo) {
1235 // In recovery mode, "param_in_foo" will also be suggested among many other
1236 // unrelated symbols; however, this is really a special case where this works.
1237 // If the #if block is outside of the function, "param_in_foo" is still
1238 // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't
1239 // really provide useful results in excluded branches.
1245 EXPECT_TRUE(Results.Completions.empty());
1248TEST(CompletionTest, DefaultArgs) {
1249 clangd::CodeCompleteOptions Opts;
1250 std::string Context = R"cpp(
1252 int Y(int A, int B = 0);
1253 int Z(int A, int B = 0, int C = 0, int D = 0);
1255 EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions,
1256 UnorderedElementsAre(labeled(
"X(int A = 0)")));
1257 EXPECT_THAT(completions(Context +
"int y = Y^", {}, Opts).Completions,
1258 UnorderedElementsAre(AllOf(labeled(
"Y(int A, int B = 0)"),
1259 snippetSuffix(
"(${1:int A})"))));
1260 EXPECT_THAT(completions(Context +
"int y = Z^", {}, Opts).Completions,
1261 UnorderedElementsAre(
1262 AllOf(labeled(
"Z(int A, int B = 0, int C = 0, int D = 0)"),
1263 snippetSuffix(
"(${1:int A})"))));
1266TEST(CompletionTest, NoCrashWithTemplateParamsAndPreferredTypes) {
1267 auto Completions = completions(R
"cpp(
1268template <template <class> class TT> int foo() {
1273 EXPECT_THAT(Completions, Contains(named("TT")));
1276TEST(CompletionTest, NestedTemplateHeuristics) {
1277 auto Completions = completions(R
"cpp(
1278struct Plain { int xxx; };
1279template <typename T> class Templ { Plain ppp; };
1280template <typename T> void foo(Templ<T> &t) {
1281 // Formally ppp has DependentTy, because Templ may be specialized.
1282 // However we sholud be able to see into it using the primary template.
1287 EXPECT_THAT(Completions, Contains(named("xxx")));
1290TEST(CompletionTest, RecordCCResultCallback) {
1291 std::vector<CodeCompletion> RecordedCompletions;
1292 CodeCompleteOptions Opts;
1294 const SymbolQualitySignals &,
1295 const SymbolRelevanceSignals &,
1297 RecordedCompletions.push_back(
CC);
1300 completions(
"int xy1, xy2; int a = xy^", {}, Opts);
1301 EXPECT_THAT(RecordedCompletions,
1302 UnorderedElementsAre(named(
"xy1"), named(
"xy2")));
1305TEST(CompletionTest, ASTSignals) {
1308 unsigned MainFileRefs;
1309 unsigned ScopeRefsInFile;
1311 CodeCompleteOptions Opts;
1312 std::vector<Completion> RecordedCompletions;
1314 const SymbolQualitySignals &,
1315 const SymbolRelevanceSignals &R,
1317 RecordedCompletions.push_back({
CC.Name, R.MainFileRefs, R.ScopeRefsInFile});
1319 ASTSignals MainFileSignals;
1320 MainFileSignals.ReferencedSymbols[
var(
"xy1").
ID] = 3;
1321 MainFileSignals.ReferencedSymbols[
var(
"xy2").
ID] = 1;
1322 MainFileSignals.ReferencedSymbols[
var(
"xyindex").
ID] = 10;
1323 MainFileSignals.RelatedNamespaces[
"tar::"] = 5;
1324 MainFileSignals.RelatedNamespaces[
"bar::"] = 3;
1336 {
var(
"xyindex"),
var(
"tar::xytar"),
var(
"bar::xybar")},
1338 EXPECT_THAT(RecordedCompletions,
1339 UnorderedElementsAre(
1340 AllOf(named(
"xy1"), mainFileRefs(3u), scopeRefs(0u)),
1341 AllOf(named(
"xy2"), mainFileRefs(1u), scopeRefs(0u)),
1342 AllOf(named(
"xyindex"), mainFileRefs(10u), scopeRefs(0u)),
1343 AllOf(named(
"xytar"), mainFileRefs(0u), scopeRefs(5u)),
1344 AllOf( named(
"xybar"),
1345 mainFileRefs(0u), scopeRefs(3u))));
1349signatures(llvm::StringRef
Text, Position Point,
1350 std::vector<Symbol> IndexSymbols = {},
1352 std::unique_ptr<SymbolIndex> Index;
1353 if (!IndexSymbols.empty())
1354 Index = memIndex(IndexSymbols);
1358 auto Inputs = TU.inputs(FS);
1359 Inputs.
Index = Index.get();
1360 IgnoreDiagnostics Diags;
1363 ADD_FAILURE() <<
"Couldn't build CompilerInvocation";
1369 ADD_FAILURE() <<
"Couldn't build Preamble";
1373 DocumentationFormat);
1377signatures(llvm::StringRef
Text, std::vector<Symbol> IndexSymbols = {},
1379 Annotations Test(
Text);
1380 return signatures(Test.code(), Test.point(), std::move(IndexSymbols),
1381 DocumentationFormat);
1384struct ExpectedParameter {
1386 std::pair<unsigned, unsigned> Offsets;
1389 const ExpectedParameter &P) {
1390 return OS << P.Text;
1393 if (P.size() != arg.parameters.size())
1395 for (
unsigned I = 0; I < P.size(); ++I) {
1396 if (P[I].
Text != arg.parameters[I].labelString ||
1397 P[I].Offsets != arg.parameters[I].labelOffsets)
1402MATCHER_P(sigDoc, doc,
"") {
return arg.documentation.value == doc; }
1406Matcher<SignatureInformation> sig(llvm::StringRef AnnotatedLabel) {
1407 llvm::Annotations
A(AnnotatedLabel);
1408 std::string
Label = std::string(
A.code());
1410 for (
auto Range :
A.ranges()) {
1421TEST(SignatureHelpTest, Overloads) {
1422 auto Results = signatures(R
"cpp(
1423 void foo(int x, int y);
1424 void foo(int x, float y);
1425 void foo(float x, int y);
1426 void foo(float x, float y);
1427 void bar(int x, int y = 0);
1428 int main() { foo(^); }
1430 EXPECT_THAT(Results.signatures,
1431 UnorderedElementsAre(sig("foo([[float x]], [[float y]]) -> void"),
1432 sig(
"foo([[float x]], [[int y]]) -> void"),
1433 sig(
"foo([[int x]], [[float y]]) -> void"),
1434 sig(
"foo([[int x]], [[int y]]) -> void")));
1436 EXPECT_EQ(0,
Results.activeSignature);
1437 EXPECT_EQ(0,
Results.activeParameter);
1440TEST(SignatureHelpTest, FunctionPointers) {
1441 llvm::StringLiteral Tests[] = {
1444 void (*foo)(int x, int y);
1445 int main() { foo(^); }
1449 void (__stdcall *foo)(int x, int y);
1450 int main() { foo(^); }
1454 void (__attribute__(stdcall) *foo)(int x, int y);
1455 int main() { foo(^); },
1459 typedef void (*fn)(int x, int y);
1461 int main() { foo(^); }
1465 typedef void (__stdcall *fn)(int x, int y);
1467 int main() { foo(^); }
1472 void (*foo)(int x, int y);
1475 int main() { s.foo(^); }
1479 typedef void (*fn)(int x, int y);
1484 int main() { s.foo(^); }
1486 for (
auto Test : Tests)
1487 EXPECT_THAT(signatures(Test).signatures,
1488 UnorderedElementsAre(sig(
"([[int x]], [[int y]]) -> void")));
1491TEST(SignatureHelpTest, Constructors) {
1492 std::string Top = R
"cpp(
1495 S(const S &) = delete;
1499 auto CheckParenInit = [&](std::string Init) {
1500 EXPECT_THAT(signatures(Top + Init).signatures,
1501 UnorderedElementsAre(sig(
"S([[int]])")))
1504 CheckParenInit(
"S s(^);");
1505 CheckParenInit(
"auto s = S(^);");
1506 CheckParenInit(
"auto s = new S(^);");
1508 auto CheckBracedInit = [&](std::string Init) {
1509 EXPECT_THAT(signatures(Top + Init).signatures,
1510 UnorderedElementsAre(sig(
"S{[[int]]}")))
1513 CheckBracedInit(
"S s{^};");
1514 CheckBracedInit(
"S s = {^};");
1515 CheckBracedInit(
"auto s = S{^};");
1518 CheckBracedInit(
"int x(S); int i = x({^});");
1521TEST(SignatureHelpTest, Aggregates) {
1522 std::string Top = R
"cpp(
1527 auto AggregateSig = sig(
"S{[[int a]], [[int b]], [[int c]], [[int d]]}");
1528 EXPECT_THAT(signatures(Top +
"S s{^}").signatures,
1529 UnorderedElementsAre(AggregateSig, sig(
"S{}"),
1530 sig(
"S{[[const S &]]}"),
1531 sig(
"S{[[S &&]]}")));
1532 EXPECT_THAT(signatures(Top +
"S s{1,^}").signatures,
1533 ElementsAre(AggregateSig));
1534 EXPECT_EQ(signatures(Top +
"S s{1,^}").activeParameter, 1);
1535 EXPECT_THAT(signatures(Top +
"S s{.c=3,^}").signatures,
1536 ElementsAre(AggregateSig));
1537 EXPECT_EQ(signatures(Top +
"S s{.c=3,^}").activeParameter, 3);
1540TEST(SignatureHelpTest, OverloadInitListRegression) {
1541 auto Results = signatures(R
"cpp(
1550 EXPECT_THAT(Results.signatures, UnorderedElementsAre(sig("f() -> void")));
1553TEST(SignatureHelpTest, DefaultArgs) {
1554 auto Results = signatures(R
"cpp(
1555 void bar(int x, int y = 0);
1556 void bar(float x = 0, int y = 42);
1559 EXPECT_THAT(Results.signatures,
1560 UnorderedElementsAre(
1561 sig("bar([[int x]], [[int y = 0]]) -> void"),
1562 sig(
"bar([[float x = 0]], [[int y = 42]]) -> void")));
1563 EXPECT_EQ(0,
Results.activeSignature);
1564 EXPECT_EQ(0,
Results.activeParameter);
1567TEST(SignatureHelpTest, ActiveArg) {
1568 auto Results = signatures(R
"cpp(
1569 int baz(int a, int b, int c);
1570 int main() { baz(baz(1,2,3), ^); }
1572 EXPECT_THAT(Results.signatures,
1573 ElementsAre(sig("baz([[int a]], [[int b]], [[int c]]) -> int")));
1574 EXPECT_EQ(0,
Results.activeSignature);
1575 EXPECT_EQ(1,
Results.activeParameter);
1578TEST(SignatureHelpTest, OpeningParen) {
1579 llvm::StringLiteral Tests[] = {
1582 int foo(int a, int b, int c);
1584 foo(foo $p^( foo(10, 10, 10), ^ )));
1589 Foo(int a, int b, int c);
1597 Foo(int a, int b, int c);
1600 new Foo $p^( 10, ^ );
1604 int foo(int a, int b, int c);
1608 // Macro expansions.
1613 int foo(int a, int b, int c);
1616 // FIXME: figure out why ID(foo (foo(10), )) doesn't work when preserving
1617 // the recovery expression.
1618 ID(foo $p^( 10, ^ ))
1622 int foo(int a, int b);
1623 template <typename T> void bar(T t) {
1628 template <typename T>
1630 template <typename T> void bar(T t) {
1635 struct Foo { int foo(int, int); };
1636 template <typename T> void bar(T t) {
1642 struct Foo { template <typename T> int foo(T, T); };
1643 template <typename T> void bar(T t) {
1649 for (
auto Test : Tests) {
1650 Annotations
Code(Test);
1651 EXPECT_EQ(signatures(
Code.code(),
Code.point()).argListStart,
1653 <<
"Test source:" << Test;
1657TEST(SignatureHelpTest, StalePreamble) {
1660 IgnoreDiagnostics Diags;
1662 auto Inputs = TU.inputs(FS);
1667 ASSERT_TRUE(EmptyPreamble);
1669 TU.AdditionalFiles[
"a.h"] =
"int foo(int x);";
1670 const Annotations Test(R
"cpp(
1672 void bar() { foo(^2); })cpp");
1673 TU.Code = Test.code().str();
1677 EXPECT_THAT(
Results.signatures, ElementsAre(sig(
"foo([[int x]]) -> int")));
1678 EXPECT_EQ(0,
Results.activeSignature);
1679 EXPECT_EQ(0,
Results.activeParameter);
1682class IndexRequestCollector :
public SymbolIndex {
1684 IndexRequestCollector(std::vector<Symbol> Syms = {}) : Symbols(Syms) {}
1687 fuzzyFind(
const FuzzyFindRequest &Req,
1688 llvm::function_ref<
void(
const Symbol &)> Callback)
const override {
1689 std::unique_lock<std::mutex> Lock(Mut);
1690 Requests.push_back(Req);
1691 ReceivedRequestCV.notify_one();
1692 for (
const auto &Sym : Symbols)
1697 void lookup(
const LookupRequest &,
1698 llvm::function_ref<
void(
const Symbol &)>)
const override {}
1700 bool refs(
const RefsRequest &,
1701 llvm::function_ref<
void(
const Ref &)>)
const override {
1705 void relations(
const RelationsRequest &,
1706 llvm::function_ref<
void(
const SymbolID &,
const Symbol &)>)
1710 indexedFiles()
const override {
1711 return [](llvm::StringRef) {
return IndexContents::None; };
1716 size_t estimateMemoryUsage()
const override {
return 0; }
1718 const std::vector<FuzzyFindRequest> consumeRequests(
size_t Num)
const {
1719 std::unique_lock<std::mutex> Lock(Mut);
1721 [
this, Num] {
return Requests.size() == Num; }));
1722 auto Reqs = std::move(Requests);
1728 std::vector<Symbol> Symbols;
1730 mutable std::condition_variable ReceivedRequestCV;
1731 mutable std::mutex Mut;
1732 mutable std::vector<FuzzyFindRequest> Requests;
1736std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef
Code,
1738 clangd::CodeCompleteOptions Opts;
1739 IndexRequestCollector Requests;
1740 Opts.
Index = &Requests;
1741 completions(
Code, {}, Opts);
1742 const auto Reqs = Requests.consumeRequests(Num);
1743 EXPECT_EQ(Reqs.size(), Num);
1747TEST(CompletionTest, UnqualifiedIdQuery) {
1748 auto Requests = captureIndexRequests(R
"cpp(
1750 using namespace std;
1758 EXPECT_THAT(Requests,
1760 UnorderedElementsAre("",
"ns::",
"std::"))));
1763TEST(CompletionTest, EnclosingScopeComesFirst) {
1764 auto Requests = captureIndexRequests(R
"cpp(
1766 using namespace std;
1778 EXPECT_THAT(Requests,
1781 UnorderedElementsAre("",
"std::",
"nx::ns::",
"nx::"))));
1782 EXPECT_EQ(Requests[0].Scopes[0],
"nx::ns::");
1785TEST(CompletionTest, ResolvedQualifiedIdQuery) {
1786 auto Requests = captureIndexRequests(R
"cpp(
1788 namespace ns2 {} // ignore
1789 namespace ns3 { namespace nns3 {} }
1791 using namespace ns1;
1792 using namespace ns3::nns3;
1801 EXPECT_THAT(Requests,
1804 UnorderedElementsAre("foo::",
"ns1::",
"ns3::nns3::"))));
1807TEST(CompletionTest, UnresolvedQualifierIdQuery) {
1808 auto Requests = captureIndexRequests(R
"cpp(
1818 EXPECT_THAT(Requests,
1821 UnorderedElementsAre("a::bar::",
"ns::bar::",
"bar::"))));
1824TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
1825 auto Requests = captureIndexRequests(R
"cpp(
1836 UnorderedElementsAre("a::bar::"))));
1839TEST(CompletionTest, EmptyQualifiedQuery) {
1840 auto Requests = captureIndexRequests(R
"cpp(
1849 UnorderedElementsAre("",
"ns::"))));
1852TEST(CompletionTest, GlobalQualifiedQuery) {
1853 auto Requests = captureIndexRequests(R
"cpp(
1862 UnorderedElementsAre(""))));
1865TEST(CompletionTest, NoDuplicatedQueryScopes) {
1866 auto Requests = captureIndexRequests(R
"cpp(
1877 EXPECT_THAT(Requests,
1879 UnorderedElementsAre("na::",
"na::nb::",
""))));
1882TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
1883 auto Completions = completions(
1886 int SomeNameOfField;
1887 typedef int SomeNameOfTypedefField;
1891 {func("::SomeNameInTheIndex"),
func(
"::Foo::SomeNameInTheIndex")});
1893 EXPECT_THAT(Completions.Completions,
1894 AllOf(Contains(labeled(
"SomeNameOfField")),
1895 Contains(labeled(
"SomeNameOfTypedefField")),
1896 Not(Contains(labeled(
"SomeNameInTheIndex")))));
1899TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
1901 auto Completions = completions(
1908 {func("::SomeNameInTheIndex")});
1910 EXPECT_THAT(Completions.Completions,
1911 Not(Contains(labeled(
"SomeNameInTheIndex"))));
1915 auto Completions = completions(
1919 T::template Y<int>::^
1922 {func("::SomeNameInTheIndex")});
1924 EXPECT_THAT(Completions.Completions,
1925 Not(Contains(labeled(
"SomeNameInTheIndex"))));
1929 auto Completions = completions(
1936 {func("::SomeNameInTheIndex")});
1938 EXPECT_THAT(Completions.Completions,
1939 Not(Contains(labeled(
"SomeNameInTheIndex"))));
1943TEST(CompletionTest, OverloadBundling) {
1944 clangd::CodeCompleteOptions Opts;
1947 std::string Context = R
"cpp(
1949 // Overload with int
1950 int a(int) __attribute__((deprecated("", "")));
1951 // Overload with bool
1963 EXPECT_THAT(completions(Context +
"int y = X().^", {}, Opts).Completions,
1964 UnorderedElementsAre(labeled(
"a(…)"), labeled(
"b(float)")));
1967 EXPECT_THAT(completions(Context +
"X z = X^", {}, Opts).Completions,
1968 UnorderedElementsAre(labeled(
"X"), labeled(
"X(…)")));
1971 Symbol NoArgsGFunc =
func(
"GFuncC");
1973 completions(Context +
"int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1974 UnorderedElementsAre(labeled(
"GFuncC(…)"), labeled(
"GFuncD(int)")));
1978 NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile.c_str();
1981 completions(Context +
"int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1982 UnorderedElementsAre(AllOf(named(
"GFuncC"), insertInclude(
"<foo>")),
1983 labeled(
"GFuncC(int)"), labeled(
"GFuncD(int)")));
1987 completions(Context +
"int y = X().a^", {}, Opts).Completions.front();
1988 EXPECT_EQ(
A.Name,
"a");
1989 EXPECT_EQ(
A.Signature,
"(…)");
1990 EXPECT_EQ(
A.BundleSize, 2u);
1992 EXPECT_EQ(
A.ReturnType,
"int");
1994 ASSERT_TRUE(
A.Documentation);
1995 ASSERT_FALSE(
A.Deprecated);
1997 A.Documentation->asPlainText(),
1998 AnyOf(HasSubstr(
"Overload with int"), HasSubstr(
"Overload with bool")));
1999 EXPECT_EQ(
A.SnippetSuffix,
"($0)");
2002TEST(CompletionTest, OverloadBundlingSameFileDifferentURI) {
2003 clangd::CodeCompleteOptions Opts;
2006 Symbol SymX =
sym(
"ns::X", index::SymbolKind::Function,
"@F@\\0#");
2007 Symbol SymY =
sym(
"ns::X", index::SymbolKind::Function,
"@F@\\0#I#");
2008 std::string BarHeader =
testPath(
"bar.h");
2010 SymX.CanonicalDeclaration.FileURI = BarURI.c_str();
2011 SymY.CanonicalDeclaration.FileURI = BarURI.c_str();
2016 auto Results = completions(
"void f() { ::ns::^ }", {SymX, SymY}, Opts);
2019 ASSERT_EQ(1u,
Results.Completions.size());
2020 const auto &R =
Results.Completions.front();
2021 EXPECT_EQ(
"X", R.Name);
2022 EXPECT_EQ(2u, R.BundleSize);
2025TEST(CompletionTest, DocumentationFromChangedFileCrash) {
2029 FS.Files[FooH] = R
"cpp(
2030 // this is my documentation comment.
2033 FS.Files[FooCpp] = "";
2035 MockCompilationDatabase CDB;
2038 Annotations Source(R
"cpp(
2041 // This makes sure we have func from header in the AST.
2047 ASSERT_TRUE(Server.blockUntilIdleForTest());
2050 FS.Files[FooH] = R
"cpp(
2054 clangd::CodeCompleteOptions Opts;
2055 CodeCompleteResult Completions =
2059 EXPECT_THAT(Completions.Completions,
2060 Contains(AllOf(Not(isDocumented()), named(
"func"))));
2063TEST(CompletionTest, NonDocComments) {
2064 const char *
Text = R
"cpp(
2065 // We ignore namespace comments, for rationale see CodeCompletionStrings.h.
2066 namespace comments_ns {
2069 // ------------------
2072 // A comment and a decl are separated by newlines.
2073 // Therefore, the comment shouldn't show up as doc comment.
2077 // this comment should be in the results.
2084 int comments_quux();
2088 // This comment should not be there.
2091 int Struct<T>::comments_qux() {
2094 // This comment **should** be in results.
2096 int Struct<T>::comments_quux() {
2103 completions(
Text).Completions,
2104 UnorderedElementsAre(AllOf(Not(isDocumented()), named(
"comments_foo")),
2105 AllOf(isDocumented(), named(
"comments_baz")),
2106 AllOf(isDocumented(), named(
"comments_quux")),
2107 AllOf(Not(isDocumented()), named(
"comments_ns")),
2112 AllOf(isDocumented(), named(
"comments_bar")),
2113 AllOf(isDocumented(), named(
"comments_qux"))));
2116TEST(CompletionTest, CompleteOnInvalidLine) {
2119 MockCompilationDatabase CDB;
2121 FS.Files[FooCpp] =
"// empty file";
2128 EXPECT_THAT_EXPECTED(
2133TEST(CompletionTest, QualifiedNames) {
2136 namespace ns { int local; void both(); }
2137 void f() { ::ns::^ }
2139 {func("ns::both"),
cls(
"ns::Index")});
2143 UnorderedElementsAre(scope(
"ns::"), scope(
"ns::"), scope(
"ns::")));
2146TEST(CompletionTest, Render) {
2150 C.Signature =
"(bool) const";
2151 C.SnippetSuffix =
"(${0:bool})";
2152 C.ReturnType =
"int";
2153 C.RequiredQualifier =
"Foo::";
2154 C.Scope =
"ns::Foo::";
2155 C.Documentation.emplace();
2156 C.Documentation->addParagraph().appendText(
"This is ").appendCode(
"x()");
2157 C.Includes.emplace_back();
2158 auto &Include =
C.Includes.back();
2159 Include.Header =
"\"foo.h\"";
2161 C.Score.Total = 1.0;
2162 C.Score.ExcludingName = .5;
2165 CodeCompleteOptions Opts;
2170 auto R =
C.render(Opts);
2171 EXPECT_EQ(R.label,
"Foo::x");
2172 EXPECT_EQ(R.labelDetails->detail,
"(bool) const");
2173 EXPECT_EQ(R.insertText,
"Foo::x");
2175 EXPECT_EQ(R.filterText,
"x");
2176 EXPECT_EQ(R.detail,
"int");
2177 EXPECT_EQ(R.documentation->value,
"From \"foo.h\"\nThis is x()");
2178 EXPECT_THAT(R.additionalTextEdits, IsEmpty());
2179 EXPECT_EQ(R.sortText,
sortText(1.0,
"x"));
2180 EXPECT_FALSE(R.deprecated);
2181 EXPECT_EQ(R.score, .5f);
2183 C.FilterText =
"xtra";
2185 EXPECT_EQ(R.filterText,
"xtra");
2186 EXPECT_EQ(R.sortText,
sortText(1.0,
"xtra"));
2190 EXPECT_EQ(R.insertText,
"Foo::x(${0:bool})");
2193 C.SnippetSuffix =
"";
2195 EXPECT_EQ(R.insertText,
"Foo::x");
2198 Include.Insertion.emplace();
2200 EXPECT_EQ(R.label,
"^Foo::x");
2201 EXPECT_EQ(R.labelDetails->detail,
"(bool) const");
2202 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
2206 EXPECT_EQ(R.label,
"^[AS]Foo::x");
2207 EXPECT_EQ(R.labelDetails->detail,
"(bool) const");
2211 EXPECT_EQ(R.detail,
"[2 overloads]");
2212 EXPECT_EQ(R.documentation->value,
"From \"foo.h\"\nThis is x()");
2214 C.Deprecated =
true;
2216 EXPECT_TRUE(R.deprecated);
2220 EXPECT_EQ(R.documentation->value,
"From `\"foo.h\"` \nThis is `x()`");
2223TEST(CompletionTest, IgnoreRecoveryResults) {
2226 namespace ns { int NotRecovered() { return 0; } }
2228 // Sema enters recovery mode first and then normal mode.
2229 if (auto x = ns::NotRecover^)
2232 EXPECT_THAT(Results.Completions, UnorderedElementsAre(named("NotRecovered")));
2235TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
2239 class X { public: X(); int x_; };
2243 EXPECT_THAT(Results.Completions,
2244 UnorderedElementsAre(AllOf(scope("ns::X::"), named(
"x_"))));
2251TEST(CompletionTest, ConstructorInitListIncomplete) {
2261 EXPECT_THAT(Results.Completions, ElementsAre(named("xyz_")));
2274 EXPECT_THAT(Results.Completions, ElementsAre(named("foo")));
2277TEST(CompletionTest, CodeCompletionContext) {
2281 class X { public: X(); int x_; };
2289 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
2292TEST(CompletionTest, FixItForArrowToDot) {
2294 MockCompilationDatabase CDB;
2296 CodeCompleteOptions Opts;
2304 class ClassWithPtr {
2306 void MemberFunction();
2307 Auxilary* operator->() const;
2316 EXPECT_EQ(
Results.Completions.size(), 3u);
2318 TextEdit ReplacementEdit;
2319 ReplacementEdit.range = Annotations(
Code).range();
2320 ReplacementEdit.newText =
".";
2321 for (
const auto &
C :
Results.Completions) {
2322 EXPECT_TRUE(
C.FixIts.size() == 1u ||
C.Name ==
"AuxFunction");
2323 if (!
C.FixIts.empty()) {
2324 EXPECT_THAT(
C.FixIts, ElementsAre(ReplacementEdit));
2329TEST(CompletionTest, FixItForDotToArrow) {
2330 CodeCompleteOptions Opts;
2338 class ClassWithPtr {
2340 void MemberFunction();
2341 Auxilary* operator->() const;
2350 EXPECT_EQ(
Results.Completions.size(), 3u);
2352 TextEdit ReplacementEdit;
2353 ReplacementEdit.range = Annotations(
Code).range();
2354 ReplacementEdit.newText =
"->";
2355 for (
const auto &
C :
Results.Completions) {
2356 EXPECT_TRUE(
C.FixIts.empty() ||
C.Name ==
"AuxFunction");
2357 if (!
C.FixIts.empty()) {
2358 EXPECT_THAT(
C.FixIts, ElementsAre(ReplacementEdit));
2363TEST(CompletionTest, RenderWithFixItMerged) {
2365 FixIt.range.end.character = 5;
2366 FixIt.newText =
"->";
2370 C.RequiredQualifier =
"Foo::";
2372 C.CompletionTokenRange.start.character = 5;
2374 CodeCompleteOptions Opts;
2377 auto R =
C.render(Opts);
2378 EXPECT_TRUE(R.textEdit);
2379 EXPECT_EQ(R.textEdit->newText,
"->Foo::x");
2380 EXPECT_TRUE(R.additionalTextEdits.empty());
2383TEST(CompletionTest, RenderWithFixItNonMerged) {
2385 FixIt.range.end.character = 4;
2386 FixIt.newText =
"->";
2390 C.RequiredQualifier =
"Foo::";
2392 C.CompletionTokenRange.start.character = 5;
2394 CodeCompleteOptions Opts;
2397 auto R =
C.render(Opts);
2398 EXPECT_TRUE(R.textEdit);
2399 EXPECT_EQ(R.textEdit->newText,
"Foo::x");
2400 EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(
FixIt));
2403TEST(CompletionTest, CompletionTokenRange) {
2405 MockCompilationDatabase CDB;
2407 TU.AdditionalFiles[
"foo/abc/foo.h"] =
"";
2409 constexpr const char *TestCodes[] = {
2431 #include "foo/[[a^/]]foo.h"
2434 #include "foo/abc/[[fo^o.h"]]
2437 for (
const auto &
Text : TestCodes) {
2438 Annotations TestCode(
Text);
2439 TU.Code = TestCode.code().str();
2440 auto Results = completions(TU, TestCode.point());
2441 if (
Results.Completions.size() != 1) {
2442 ADD_FAILURE() <<
"Results.Completions.size() != 1" <<
Text;
2445 EXPECT_THAT(
Results.Completions.front().CompletionTokenRange,
2450TEST(SignatureHelpTest, OverloadsOrdering) {
2451 const auto Results = signatures(R
"cpp(
2453 void foo(int x, float y);
2454 void foo(float x, int y);
2455 void foo(float x, float y);
2456 void foo(int x, int y = 0);
2457 int main() { foo(^); }
2459 EXPECT_THAT(Results.signatures,
2460 ElementsAre(sig("foo([[int x]]) -> void"),
2461 sig(
"foo([[int x]], [[int y = 0]]) -> void"),
2462 sig(
"foo([[float x]], [[int y]]) -> void"),
2463 sig(
"foo([[int x]], [[float y]]) -> void"),
2464 sig(
"foo([[float x]], [[float y]]) -> void")));
2466 EXPECT_EQ(0,
Results.activeSignature);
2467 EXPECT_EQ(0,
Results.activeParameter);
2470TEST(SignatureHelpTest, InstantiatedSignatures) {
2471 StringRef Sig0 = R
"cpp(
2480 EXPECT_THAT(signatures(Sig0).signatures,
2481 ElementsAre(sig("foo([[T]], [[T]], [[T]]) -> void")));
2483 StringRef Sig1 = R
"cpp(
2491 EXPECT_THAT(signatures(Sig1).signatures,
2492 ElementsAre(sig("foo([[T]], [[T]], [[T]]) -> void")));
2494 StringRef Sig2 = R
"cpp(
2495 template <class ...T>
2503 EXPECT_THAT(signatures(Sig2).signatures,
2504 ElementsAre(sig("foo([[T...]]) -> void")));
2511 StringRef Sig3 = R
"cpp(
2519 X<int>().foo<double>(^)
2523 EXPECT_THAT(signatures(Sig3).signatures,
2524 ElementsAre(sig("foo([[T]], [[U]]) -> void")));
2527TEST(SignatureHelpTest, IndexDocumentation) {
2528 Symbol Foo0 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#");
2529 Foo0.Documentation =
"doc from the index";
2530 Symbol Foo1 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#I#");
2531 Foo1.Documentation =
"doc from the index";
2532 Symbol Foo2 =
sym(
"foo", index::SymbolKind::Function,
"@F@\\0#I#I#");
2534 StringRef Sig0 = R
"cpp(
2544 signatures(Sig0, {Foo0}).signatures,
2545 ElementsAre(AllOf(sig("foo() -> int"), sigDoc(
"doc from the index")),
2546 AllOf(sig(
"foo([[double]]) -> int"), sigDoc(
""))));
2548 StringRef Sig1 = R
"cpp(
2550 // Overriden doc from sema
2561 signatures(Sig1, {Foo0, Foo1, Foo2}).signatures,
2563 AllOf(sig("foo() -> int"), sigDoc(
"doc from the index")),
2564 AllOf(sig(
"foo([[int]]) -> int"), sigDoc(
"Overriden doc from sema")),
2565 AllOf(sig(
"foo([[int]], [[int]]) -> int"), sigDoc(
"doc from sema"))));
2568TEST(SignatureHelpTest, DynamicIndexDocumentation) {
2570 MockCompilationDatabase CDB;
2572 Opts.BuildDynamicSymbolIndex =
true;
2573 ClangdServer Server(CDB, FS, Opts);
2575 FS.Files[
testPath(
"foo.h")] = R
"cpp(
2581 Annotations FileContent(R"cpp(
2589 Server.addDocument(
File, FileContent.code());
2591 ASSERT_TRUE(Server.blockUntilIdleForTest());
2595 ElementsAre(AllOf(sig(
"foo() -> int"), sigDoc(
"Member doc"))));
2598TEST(CompletionTest, CompletionFunctionArgsDisabled) {
2599 CodeCompleteOptions Opts;
2607 void xfoo(int x, int y);
2608 void f() { xfo^ })cpp",
2612 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix(
"()")),
2613 AllOf(named(
"xfoo"), snippetSuffix(
"($0)"))));
2619 void f() { xba^ })cpp",
2621 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
2622 named("xbar"), snippetSuffix(
"()"))));
2629 void xfoo(int x, int y);
2630 void f() { xfo^ })cpp",
2634 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix(
"($0)"))));
2639 template <class T, class U>
2640 void xfoo(int a, U b);
2641 void f() { xfo^ })cpp",
2645 UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix(
"<$1>($0)"))));
2653 using foo_alias = T**;
2656 void f() { foo_^ })cpp",
2660 UnorderedElementsAre(AllOf(named("foo_class"), snippetSuffix(
"<$0>")),
2661 AllOf(named(
"foo_alias"), snippetSuffix(
"<$0>")),
2662 AllOf(named(
"foo_var"), snippetSuffix(
"<$0>"))));
2667 #define FOO(x, y) x##f
2670 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
2671 named("FOO"), snippetSuffix(
"($0)"))));
2675TEST(CompletionTest, SuggestOverrides) {
2676 constexpr const char *
const Text(R
"cpp(
2679 virtual void vfunc(bool param);
2680 virtual void vfunc(bool param, int p);
2681 void func(bool param);
2683 class B : public A {
2684 virtual void ttt(bool param) const;
2685 void vfunc(bool param, int p) override;
2687 class C : public B {
2689 void vfunc(bool param) override;
2696 AllOf(Contains(AllOf(labeled(
"void vfunc(bool param, int p) override"),
2697 nameStartsWith(
"vfunc"))),
2698 Contains(AllOf(labeled(
"void ttt(bool param) const override"),
2699 nameStartsWith(
"ttt"))),
2700 Not(Contains(labeled(
"void vfunc(bool param) override")))));
2703TEST(CompletionTest, OverridesNonIdentName) {
2707 virtual ~Base() = 0;
2708 virtual operator int() = 0;
2709 virtual Base& operator+(Base&) = 0;
2712 struct Derived : Base {
2718TEST(CompletionTest, NoCrashOnMissingNewLineAtEOF) {
2721 MockCompilationDatabase CDB;
2723 Annotations F(
"#pragma ^ // no new line");
2724 FS.Files[FooCpp] = F.code().str();
2729 clangd::CodeCompleteOptions()))
2738TEST(GuessCompletionPrefix, Filters) {
2739 for (llvm::StringRef Case : {
2740 "[[scope::]][[ident]]^",
2749 "some text [[scope::more::]][[identif]]^ier",
2750 "some text [[scope::]][[mor]]^e::identifier",
2751 "weird case foo::[[::bar::]][[baz]]^",
2754 Annotations F(Case);
2756 auto ToStringRef = [&](
Range R) {
2760 auto WantQualifier = ToStringRef(F.ranges()[0]),
2761 WantName = ToStringRef(F.ranges()[1]);
2765 EXPECT_EQ(WantQualifier, Prefix.Qualifier) << Case;
2766 EXPECT_EQ(WantQualifier.begin(), Prefix.Qualifier.begin()) << Case;
2767 EXPECT_EQ(WantName, Prefix.Name) << Case;
2768 EXPECT_EQ(WantName.begin(), Prefix.Name.begin()) << Case;
2772TEST(CompletionTest, EnableSpeculativeIndexRequest) {
2774 MockCompilationDatabase CDB;
2778 Annotations Test(R
"cpp(
2779 namespace ns1 { int abc; }
2780 namespace ns2 { int abc; }
2781 void f() { ns1::ab$1^; ns1::ab$2^; }
2782 void f2() { ns2::ab$3^; }
2785 clangd::CodeCompleteOptions Opts = {};
2787 IndexRequestCollector Requests;
2788 Opts.Index = &Requests;
2790 auto CompleteAtPoint = [&](StringRef P) {
2792 EXPECT_TRUE(CCR.HasMore);
2795 CompleteAtPoint(
"1");
2796 auto Reqs1 = Requests.consumeRequests(1);
2797 ASSERT_EQ(Reqs1.size(), 1u);
2798 EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre(
"ns1::"));
2800 CompleteAtPoint(
"2");
2801 auto Reqs2 = Requests.consumeRequests(1);
2803 ASSERT_EQ(Reqs2.size(), 1u);
2804 EXPECT_EQ(Reqs2[0], Reqs1[0]);
2806 CompleteAtPoint(
"3");
2809 auto Reqs3 = Requests.consumeRequests(2);
2810 ASSERT_EQ(Reqs3.size(), 2u);
2813TEST(CompletionTest, InsertTheMostPopularHeader) {
2815 Symbol Sym =
func(
"Func");
2816 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2820 auto Results = completions(
"Fun^", {Sym}).Completions;
2822 EXPECT_THAT(
Results[0], AllOf(named(
"Func"), insertInclude(
"\"bar.h\"")));
2823 EXPECT_EQ(
Results[0].Includes.size(), 2u);
2826TEST(CompletionTest, InsertIncludeOrImport) {
2828 Symbol Sym =
func(
"Func");
2829 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2830 Sym.IncludeHeaders.emplace_back(
"\"bar.h\"", 1000,
2832 CodeCompleteOptions Opts;
2835 auto Results = completions(
"Fun^", {Sym}, Opts).Completions;
2838 AllOf(named(
"Func"), insertIncludeText(
"#include \"bar.h\"\n")));
2843 Results = completions(
"Fun^", {Sym}, Opts,
"Foo.m").Completions;
2846 AllOf(named(
"Func"), insertIncludeText(
"#import \"bar.h\"\n")));
2849 Results = completions(
"Fun^", {Sym}).Completions;
2851 EXPECT_THAT(
Results[0], AllOf(named(
"Func"), Not(insertInclude())));
2854TEST(CompletionTest, NoInsertIncludeIfOnePresent) {
2855 Annotations Test(R
"cpp(
2860 TU.AdditionalFiles[
"foo.h"] =
"";
2863 Symbol Sym =
func(
"Func");
2864 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2868 EXPECT_THAT(completions(TU, Test.point(), {Sym}).Completions,
2869 UnorderedElementsAre(AllOf(named(
"Func"), hasInclude(
"\"foo.h\""),
2870 Not(insertInclude()))));
2873TEST(CompletionTest, MergeMacrosFromIndexAndSema) {
2875 Sym.Name =
"Clangd_Macro_Test";
2876 Sym.ID =
SymbolID(
"c:foo.cpp@8@macro@Clangd_Macro_Test");
2877 Sym.SymInfo.Kind = index::SymbolKind::Macro;
2879 EXPECT_THAT(completions(
"#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym})
2881 UnorderedElementsAre(named(
"Clangd_Macro_Test")));
2884TEST(CompletionTest, MacroFromPreamble) {
2885 Annotations Test(R
"cpp(#define CLANGD_PREAMBLE_MAIN x
2888 #define CLANGD_MAIN x
2889 void f() { CLANGD_^ }
2892 TU.HeaderCode =
"#define CLANGD_PREAMBLE_HEADER x";
2893 auto Results = completions(TU, Test.point(), {func(
"CLANGD_INDEX")});
2896 EXPECT_THAT(
Results.Completions,
2897 UnorderedElementsAre(named(
"CLANGD_PREAMBLE_MAIN"),
2898 named(
"CLANGD_MAIN"),
2899 named(
"CLANGD_INDEX")));
2902TEST(CompletionTest, DeprecatedResults) {
2903 std::string Body = R
"cpp(
2905 void TestClangc() __attribute__((deprecated("", "")));
2909 completions(Body + "int main() { TestClang^ }").Completions,
2910 UnorderedElementsAre(AllOf(named(
"TestClangd"), Not(deprecated())),
2911 AllOf(named(
"TestClangc"), deprecated())));
2914TEST(SignatureHelpTest, PartialSpec) {
2915 const auto Results = signatures(R
"cpp(
2916 template <typename T> struct Foo {};
2917 template <typename T> struct Foo<T*> { Foo(T); };
2918 Foo<int*> F(^);)cpp");
2919 EXPECT_THAT(Results.signatures, Contains(sig("Foo([[T]])")));
2920 EXPECT_EQ(0,
Results.activeParameter);
2923TEST(SignatureHelpTest, InsideArgument) {
2925 const auto Results = signatures(R
"cpp(
2927 void foo(int x, int y);
2928 int main() { foo(1+^); }
2930 EXPECT_THAT(Results.signatures,
2931 ElementsAre(sig("foo([[int x]]) -> void"),
2932 sig(
"foo([[int x]], [[int y]]) -> void")));
2933 EXPECT_EQ(0,
Results.activeParameter);
2936 const auto Results = signatures(R
"cpp(
2938 void foo(int x, int y);
2939 int main() { foo(1^); }
2941 EXPECT_THAT(Results.signatures,
2942 ElementsAre(sig("foo([[int x]]) -> void"),
2943 sig(
"foo([[int x]], [[int y]]) -> void")));
2944 EXPECT_EQ(0,
Results.activeParameter);
2947 const auto Results = signatures(R
"cpp(
2949 void foo(int x, int y);
2950 int main() { foo(1^0); }
2952 EXPECT_THAT(Results.signatures,
2953 ElementsAre(sig("foo([[int x]]) -> void"),
2954 sig(
"foo([[int x]], [[int y]]) -> void")));
2955 EXPECT_EQ(0,
Results.activeParameter);
2958 const auto Results = signatures(R
"cpp(
2960 void foo(int x, int y);
2961 int bar(int x, int y);
2962 int main() { bar(foo(2, 3^)); }
2964 EXPECT_THAT(Results.signatures,
2965 ElementsAre(sig("foo([[int x]], [[int y]]) -> void")));
2966 EXPECT_EQ(1,
Results.activeParameter);
2970TEST(SignatureHelpTest, ConstructorInitializeFields) {
2972 const auto Results = signatures(R
"cpp(
2973 struct A { A(int); };
2979 EXPECT_THAT(Results.signatures,
2980 UnorderedElementsAre(sig("A([[int]])"), sig(
"A([[A &&]])"),
2981 sig(
"A([[const A &]])")));
2984 const auto Results = signatures(R
"cpp(
2985 struct A { A(int); };
2993 EXPECT_THAT(
Results.signatures, IsEmpty());
2996 const auto Results = signatures(R
"cpp(
2997 struct A { A(int); };
3004 EXPECT_THAT(Results.signatures,
3005 UnorderedElementsAre(sig("A([[int]])"), sig(
"A([[A &&]])"),
3006 sig(
"A([[const A &]])")));
3009 const auto Results = signatures(R
"cpp(
3018 B() : c_elem(A(1^)) {}
3022 EXPECT_THAT(Results.signatures,
3023 UnorderedElementsAre(sig("A([[int]])"), sig(
"A([[A &&]])"),
3024 sig(
"A([[const A &]])")));
3028TEST(SignatureHelpTest, Variadic) {
3029 const std::string Header = R
"cpp(
3030 void fun(int x, ...) {}
3032 const std::string ExpectedSig =
"fun([[int x]], [[...]]) -> void";
3035 const auto Result = signatures(Header +
"fun(^);}");
3036 EXPECT_EQ(0, Result.activeParameter);
3037 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3040 const auto Result = signatures(Header +
"fun(1, ^);}");
3041 EXPECT_EQ(1, Result.activeParameter);
3042 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3045 const auto Result = signatures(Header +
"fun(1, 2, ^);}");
3046 EXPECT_EQ(1, Result.activeParameter);
3047 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3051TEST(SignatureHelpTest, VariadicTemplate) {
3052 const std::string Header = R
"cpp(
3053 template<typename T, typename ...Args>
3054 void fun(T t, Args ...args) {}
3056 const std::string ExpectedSig =
"fun([[T t]], [[Args args...]]) -> void";
3059 const auto Result = signatures(Header +
"fun(^);}");
3060 EXPECT_EQ(0, Result.activeParameter);
3061 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3064 const auto Result = signatures(Header +
"fun(1, ^);}");
3065 EXPECT_EQ(1, Result.activeParameter);
3066 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3069 const auto Result = signatures(Header +
"fun(1, 2, ^);}");
3070 EXPECT_EQ(1, Result.activeParameter);
3071 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3075TEST(SignatureHelpTest, VariadicMethod) {
3076 const std::string Header = R
"cpp(
3078 template<typename T, typename ...Args>
3079 void fun(T t, Args ...args) {}
3081 void test() {C c; )cpp";
3082 const std::string ExpectedSig =
"fun([[T t]], [[Args args...]]) -> void";
3085 const auto Result = signatures(Header +
"c.fun(^);}");
3086 EXPECT_EQ(0, Result.activeParameter);
3087 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3090 const auto Result = signatures(Header +
"c.fun(1, ^);}");
3091 EXPECT_EQ(1, Result.activeParameter);
3092 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3095 const auto Result = signatures(Header +
"c.fun(1, 2, ^);}");
3096 EXPECT_EQ(1, Result.activeParameter);
3097 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3101TEST(SignatureHelpTest, VariadicType) {
3102 const std::string Header = R
"cpp(
3103 void fun(int x, ...) {}
3104 auto get_fun() { return fun; }
3107 const std::string ExpectedSig =
"([[int]], [[...]]) -> void";
3110 const auto Result = signatures(Header +
"get_fun()(^);}");
3111 EXPECT_EQ(0, Result.activeParameter);
3112 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3115 const auto Result = signatures(Header +
"get_fun()(1, ^);}");
3116 EXPECT_EQ(1, Result.activeParameter);
3117 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3120 const auto Result = signatures(Header +
"get_fun()(1, 2, ^);}");
3121 EXPECT_EQ(1, Result.activeParameter);
3122 EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));
3126TEST(CompletionTest, IncludedCompletionKinds) {
3127 Annotations Test(R
"cpp(#include "^)cpp");
3129 TU.AdditionalFiles[
"sub/bar.h"] =
"";
3130 TU.ExtraArgs.push_back(
"-I" +
testPath(
"sub"));
3132 auto Results = completions(TU, Test.point());
3133 EXPECT_THAT(
Results.Completions,
3138TEST(CompletionTest, NoCrashAtNonAlphaIncludeHeader) {
3145TEST(CompletionTest, NoAllScopesCompletionWhenQualified) {
3146 clangd::CodeCompleteOptions Opts = {};
3151 void f() { na::Clangd^ }
3153 {cls("na::ClangdA"),
cls(
"nx::ClangdX"),
cls(
"Clangd3")}, Opts);
3154 EXPECT_THAT(
Results.Completions,
3155 UnorderedElementsAre(
3156 AllOf(qualifier(
""), scope(
"na::"), named(
"ClangdA"))));
3159TEST(CompletionTest, AllScopesCompletion) {
3160 clangd::CodeCompleteOptions Opts = {};
3166 void f() { Clangd^ }
3169 {cls("nx::Clangd1"),
cls(
"ny::Clangd2"),
cls(
"Clangd3"),
3174 UnorderedElementsAre(AllOf(qualifier(
"nx::"), named(
"Clangd1"),
3176 AllOf(qualifier(
"ny::"), named(
"Clangd2"),
3178 AllOf(qualifier(
""), scope(
""), named(
"Clangd3"),
3180 AllOf(qualifier(
"nb::"), named(
"Clangd4"),
3182 AllOf(qualifier(
"C::"), named(
"Clangd5"),
3186TEST(CompletionTest, NoQualifierIfShadowed) {
3187 clangd::CodeCompleteOptions Opts = {};
3190 auto Results = completions(R
"cpp(
3191 namespace nx { class Clangd1 {}; }
3193 void f() { Clangd^ }
3195 {cls("nx::Clangd1"),
cls(
"nx::Clangd2")}, Opts);
3198 EXPECT_THAT(
Results.Completions,
3199 UnorderedElementsAre(AllOf(qualifier(
""), named(
"Clangd1")),
3200 AllOf(qualifier(
"nx::"), named(
"Clangd2"))));
3203TEST(CompletionTest, NoCompletionsForNewNames) {
3204 clangd::CodeCompleteOptions Opts;
3206 auto Results = completions(R
"cpp(
3209 {cls("naber"),
cls(
"nx::naber")}, Opts);
3210 EXPECT_THAT(
Results.Completions, UnorderedElementsAre());
3213TEST(CompletionTest, Lambda) {
3214 clangd::CodeCompleteOptions Opts = {};
3216 auto Results = completions(R
"cpp(
3218 auto Lambda = [](int a, const double &b) {return 1.f;};
3224 ASSERT_EQ(Results.Completions.size(), 1u);
3225 const auto &
A =
Results.Completions.front();
3226 EXPECT_EQ(
A.Name,
"Lambda");
3227 EXPECT_EQ(
A.Signature,
"(int a, const double &b) const");
3229 EXPECT_EQ(
A.ReturnType,
"float");
3230 EXPECT_EQ(
A.SnippetSuffix,
"(${1:int a}, ${2:const double &b})");
3233TEST(CompletionTest, StructuredBinding) {
3234 clangd::CodeCompleteOptions Opts = {};
3236 auto Results = completions(R
"cpp(
3238 using Float = float;
3243 const auto &[xxx, yyy] = S{};
3249 ASSERT_EQ(Results.Completions.size(), 1u);
3250 const auto &
A =
Results.Completions.front();
3251 EXPECT_EQ(
A.Name,
"yyy");
3253 EXPECT_EQ(
A.ReturnType,
"const Float");
3256TEST(CompletionTest, ObjectiveCMethodNoArguments) {
3257 auto Results = completions(R
"objc(
3259 @property(nonatomic, setter=setXToIgnoreComplete:) int value;
3261 Foo *foo = [Foo new]; int y = [foo v^]
3267 EXPECT_THAT(
C, ElementsAre(named(
"value")));
3269 EXPECT_THAT(
C, ElementsAre(returnType(
"int")));
3270 EXPECT_THAT(
C, ElementsAre(signature(
"")));
3271 EXPECT_THAT(
C, ElementsAre(snippetSuffix(
"")));
3274TEST(CompletionTest, ObjectiveCMethodOneArgument) {
3275 auto Results = completions(R
"objc(
3277 - (int)valueForCharacter:(char)c;
3279 Foo *foo = [Foo new]; int y = [foo v^]
3285 EXPECT_THAT(
C, ElementsAre(named(
"valueForCharacter:")));
3287 EXPECT_THAT(
C, ElementsAre(returnType(
"int")));
3288 EXPECT_THAT(
C, ElementsAre(signature(
"(char)")));
3289 EXPECT_THAT(
C, ElementsAre(snippetSuffix(
"${1:(char)}")));
3292TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromBeginning) {
3293 auto Results = completions(R
"objc(
3295 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;
3303 EXPECT_THAT(
C, ElementsAre(named(
"fooWithValue:")));
3305 EXPECT_THAT(
C, ElementsAre(returnType(
"id")));
3306 EXPECT_THAT(
C, ElementsAre(signature(
"(int) fooey:(unsigned int)")));
3308 C, ElementsAre(snippetSuffix(
"${1:(int)} fooey:${2:(unsigned int)}")));
3311TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
3312 auto Results = completions(R
"objc(
3314 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;
3316 id val = [Foo fooWithValue:10 f^]
3322 EXPECT_THAT(
C, ElementsAre(named(
"fooey:")));
3324 EXPECT_THAT(
C, ElementsAre(returnType(
"id")));
3325 EXPECT_THAT(
C, ElementsAre(signature(
"(unsigned int)")));
3326 EXPECT_THAT(
C, ElementsAre(snippetSuffix(
"${1:(unsigned int)}")));
3329TEST(CompletionTest, ObjectiveCMethodFilterOnEntireSelector) {
3330 auto Results = completions(R
"objc(
3332 + (id)player:(id)player willRun:(id)run;
3340 EXPECT_THAT(
C, ElementsAre(named(
"player:")));
3341 EXPECT_THAT(
C, ElementsAre(filterText(
"player:willRun:")));
3343 EXPECT_THAT(
C, ElementsAre(returnType(
"id")));
3344 EXPECT_THAT(
C, ElementsAre(signature(
"(id) willRun:(id)")));
3345 EXPECT_THAT(
C, ElementsAre(snippetSuffix(
"${1:(id)} willRun:${2:(id)}")));
3348TEST(CompletionTest, ObjectiveCSimpleMethodDeclaration) {
3349 auto Results = completions(R
"objc(
3361 EXPECT_THAT(
C, ElementsAre(named(
"foo")));
3363 EXPECT_THAT(
C, ElementsAre(qualifier(
"- (void)")));
3366TEST(CompletionTest, ObjectiveCMethodDeclaration) {
3367 auto Results = completions(R
"objc(
3369 - (int)valueForCharacter:(char)c secondArgument:(id)object;
3379 EXPECT_THAT(
C, ElementsAre(named(
"valueForCharacter:")));
3381 EXPECT_THAT(
C, ElementsAre(qualifier(
"- (int)")));
3382 EXPECT_THAT(
C, ElementsAre(signature(
"(char)c secondArgument:(id)object")));
3385TEST(CompletionTest, ObjectiveCMethodDeclarationFilterOnEntireSelector) {
3386 auto Results = completions(R
"objc(
3388 - (int)valueForCharacter:(char)c secondArgument:(id)object;
3398 EXPECT_THAT(
C, ElementsAre(named(
"valueForCharacter:")));
3399 EXPECT_THAT(
C, ElementsAre(filterText(
"valueForCharacter:secondArgument:")));
3401 EXPECT_THAT(
C, ElementsAre(qualifier(
"- (int)")));
3402 EXPECT_THAT(
C, ElementsAre(signature(
"(char)c secondArgument:(id)object")));
3405TEST(CompletionTest, ObjectiveCMethodDeclarationPrefixTyped) {
3406 auto Results = completions(R
"objc(
3408 - (int)valueForCharacter:(char)c;
3418 EXPECT_THAT(
C, ElementsAre(named(
"valueForCharacter:")));
3420 EXPECT_THAT(
C, ElementsAre(signature(
"(char)c")));
3423TEST(CompletionTest, ObjectiveCMethodDeclarationFromMiddle) {
3424 auto Results = completions(R
"objc(
3426 - (int)valueForCharacter:(char)c secondArgument:(id)object;
3429 - (int)valueForCharacter:(char)c second^
3436 EXPECT_THAT(
C, ElementsAre(named(
"secondArgument:")));
3438 EXPECT_THAT(
C, ElementsAre(signature(
"(id)object")));
3441TEST(CompletionTest, ObjectiveCProtocolFromIndex) {
3442 Symbol FoodClass =
objcClass(
"FoodClass");
3445 auto Results = completions(
"id<Foo^>", {SymFood, FoodClass, SymFooey},
3449 EXPECT_THAT(
Results.Completions,
3450 UnorderedElementsAre(
3454 Results = completions(
"Fo^", {SymFood, FoodClass, SymFooey},
3462TEST(CompletionTest, ObjectiveCProtocolFromIndexSpeculation) {
3464 MockCompilationDatabase CDB;
3468 Annotations Test(R
"cpp(
3475 clangd::CodeCompleteOptions Opts = {};
3477 Symbol FoodClass = objcClass("FoodClass");
3478 IndexRequestCollector Requests({FoodClass});
3479 Opts.
Index = &Requests;
3481 auto CompleteAtPoint = [&](StringRef P) {
3486 auto C = CompleteAtPoint(
"1");
3487 auto Reqs1 = Requests.consumeRequests(1);
3488 ASSERT_EQ(Reqs1.size(), 1u);
3489 EXPECT_THAT(
C, ElementsAre(AllOf(named(
"Food"),
3492 C = CompleteAtPoint(
"2");
3493 auto Reqs2 = Requests.consumeRequests(1);
3496 ASSERT_EQ(Reqs2.size(), 1u);
3497 EXPECT_EQ(Reqs2[0], Reqs1[0]);
3498 EXPECT_THAT(
C, ElementsAre(AllOf(named(
"FoodClass"),
3502TEST(CompletionTest, ObjectiveCCategoryFromIndexIgnored) {
3503 Symbol FoodCategory =
objcCategory(
"FoodClass",
"Extension");
3504 auto Results = completions(R
"objc(
3512 EXPECT_THAT(
Results.Completions, IsEmpty());
3515TEST(CompletionTest, ObjectiveCForwardDeclFromIndex) {
3516 Symbol FoodClass =
objcClass(
"FoodClass");
3517 FoodClass.IncludeHeaders.emplace_back(
"\"Foo.h\"", 2,
Symbol::Import);
3519 auto Results = completions(
"@class Foo^", {SymFood, FoodClass},
3523 EXPECT_THAT(
Results.Completions,
3524 UnorderedElementsAre(AllOf(named(
"FoodClass"),
3526 Not(insertInclude()))));
3529TEST(CompletionTest, CursorInSnippets) {
3530 clangd::CodeCompleteOptions Options;
3531 Options.EnableSnippets =
true;
3534 void while_foo(int a, int b);
3541 EXPECT_THAT(
Results.Completions,
3542 Contains(AllOf(named(
"while"),
3543 snippetSuffix(
" (${1:condition}) {\n$0\n}"))));
3545 EXPECT_THAT(
Results.Completions,
3546 Contains(AllOf(named(
"while_foo"),
3547 snippetSuffix(
"(${1:int a}, ${2:int b})"))));
3551 Base(int a, int b) {}
3554 struct Derived : Base {
3561 EXPECT_THAT(
Results.Completions,
3562 Contains(AllOf(named(
"Base"),
3563 snippetSuffix(
"(${1:int a}, ${2:int b})"))));
3566TEST(CompletionTest, WorksWithNullType) {
3567 auto R = completions(R
"cpp(
3569 for (auto [loopVar] : y ) { // y has to be unresolved.
3574 EXPECT_THAT(R.Completions, ElementsAre(named("loopVar")));
3577TEST(CompletionTest, UsingDecl) {
3578 const char *Header(R
"cpp(
3583 const char *Source(R
"cpp(
3588 clangd::CodeCompleteOptions Opts;
3589 Opts.
Index = Index.get();
3591 auto R = completions(Source, {}, Opts);
3592 EXPECT_THAT(R.Completions,
3593 ElementsAre(AllOf(scope(
"std::"), named(
"foo"),
3597TEST(CompletionTest, Enums) {
3598 const char *Header(R
"cpp(
3600 enum Unscoped { Clangd1 };
3602 enum Unscoped { Clangd2 };
3604 enum class Scoped { Clangd3 };
3606 const char *Source(R
"cpp(
3611 clangd::CodeCompleteOptions Opts;
3612 Opts.
Index = Index.get();
3614 auto R = completions(Source, {}, Opts);
3615 EXPECT_THAT(R.Completions, UnorderedElementsAre(
3616 AllOf(scope(
"ns::"), named(
"Clangd1"),
3618 AllOf(scope(
"ns::C::"), named(
"Clangd2"),
3620 AllOf(scope(
"ns::Scoped::"), named(
"Clangd3"),
3624TEST(CompletionTest, ScopeIsUnresolved) {
3625 clangd::CodeCompleteOptions Opts = {};
3628 auto Results = completions(R
"cpp(
3633 {cls("a::b::XYZ")}, Opts);
3634 EXPECT_THAT(
Results.Completions,
3635 UnorderedElementsAre(AllOf(qualifier(
""), named(
"XYZ"))));
3638TEST(CompletionTest, NestedScopeIsUnresolved) {
3639 clangd::CodeCompleteOptions Opts = {};
3642 auto Results = completions(R
"cpp(
3645 void f() { b::c::X^ }
3648 {cls("a::b::c::XYZ")}, Opts);
3649 EXPECT_THAT(
Results.Completions,
3650 UnorderedElementsAre(AllOf(qualifier(
""), named(
"XYZ"))));
3655TEST(CompletionTest, NamespaceDoubleInsertion) {
3656 clangd::CodeCompleteOptions Opts = {};
3658 auto Results = completions(R
"cpp(
3665 {cls("foo::ns::ABCDE")}, Opts);
3666 EXPECT_THAT(
Results.Completions,
3667 UnorderedElementsAre(AllOf(qualifier(
""), named(
"ABCDE"))));
3670TEST(CompletionTest, DerivedMethodsAreAlwaysVisible) {
3673 auto Completions = completions(R
"cpp(
3676 double size() const;
3678 struct deque : deque_base {
3685 EXPECT_THAT(Completions,
3686 ElementsAre(AllOf(returnType("int"), named(
"size"))));
3689TEST(CompletionTest, NoCrashWithIncompleteLambda) {
3690 auto Completions = completions(
"auto&& x = []{^").Completions;
3694 EXPECT_THAT(Completions, Contains(named(
"x")));
3696 auto Signatures = signatures(
"auto x() { x(^").signatures;
3697 EXPECT_THAT(Signatures, Contains(sig(
"x() -> auto")));
3700TEST(CompletionTest, DelayedTemplateParsing) {
3701 Annotations Test(R
"cpp(
3703 template <typename T> int foo() { return xx^; }
3708 TU.ExtraArgs.push_back(
"-fdelayed-template-parsing");
3710 EXPECT_THAT(completions(TU, Test.point()).Completions,
3711 Contains(named(
"xxx")));
3714TEST(CompletionTest, CompletionRange) {
3715 const char *WithRange =
"auto x = [[abc]]^";
3716 auto Completions = completions(WithRange);
3717 EXPECT_EQ(Completions.CompletionRange, Annotations(WithRange).range());
3718 Completions = completionsNoCompile(WithRange);
3719 EXPECT_EQ(Completions.CompletionRange, Annotations(WithRange).range());
3721 const char *EmptyRange =
"auto x = [[]]^";
3722 Completions = completions(EmptyRange);
3723 EXPECT_EQ(Completions.CompletionRange, Annotations(EmptyRange).range());
3724 Completions = completionsNoCompile(EmptyRange);
3725 EXPECT_EQ(Completions.CompletionRange, Annotations(EmptyRange).range());
3729 const char *NoCompletion =
"/* foo [[]]^ */";
3730 Completions = completions(NoCompletion);
3731 EXPECT_EQ(Completions.CompletionRange, std::nullopt);
3732 Completions = completionsNoCompile(NoCompletion);
3733 EXPECT_EQ(Completions.CompletionRange, Annotations(NoCompletion).range());
3736TEST(NoCompileCompletionTest, Basic) {
3737 auto Results = completionsNoCompile(R
"cpp(
3744 EXPECT_FALSE(Results.RanParser);
3745 EXPECT_THAT(Results.Completions,
3746 UnorderedElementsAre(named("void"), named(
"func"), named(
"int"),
3747 named(
"xyz"), named(
"abc")));
3750TEST(NoCompileCompletionTest, WithFilter) {
3751 auto Results = completionsNoCompile(R
"cpp(
3760 EXPECT_THAT(Results.Completions,
3761 UnorderedElementsAre(named("sym1"), named(
"sym2")));
3764TEST(NoCompileCompletionTest, WithIndex) {
3765 std::vector<Symbol> Syms = {
func(
"xxx"),
func(
"a::xxx"),
func(
"ns::b::xxx"),
3766 func(
"c::xxx"),
func(
"ns::d::xxx")};
3767 auto Results = completionsNoCompile(
3769 // Current-scopes, unqualified completion.
3779 EXPECT_THAT(Results.Completions,
3780 UnorderedElementsAre(AllOf(qualifier(""), scope(
"")),
3781 AllOf(qualifier(
""), scope(
"a::")),
3782 AllOf(qualifier(
""), scope(
"ns::b::"))));
3783 CodeCompleteOptions Opts;
3785 Results = completionsNoCompile(
3787 // All-scopes unqualified completion.
3797 EXPECT_THAT(Results.Completions,
3798 UnorderedElementsAre(AllOf(qualifier(""), scope(
"")),
3799 AllOf(qualifier(
""), scope(
"a::")),
3800 AllOf(qualifier(
""), scope(
"ns::b::")),
3801 AllOf(qualifier(
"c::"), scope(
"c::")),
3802 AllOf(qualifier(
"d::"), scope(
"ns::d::"))));
3803 Results = completionsNoCompile(
3805 // Qualified completion.
3815 EXPECT_THAT(Results.Completions,
3816 ElementsAre(AllOf(qualifier(""), scope(
"ns::b::"))));
3817 Results = completionsNoCompile(
3819 // Absolutely qualified completion.
3829 EXPECT_THAT(Results.Completions,
3830 ElementsAre(AllOf(qualifier(""), scope(
"a::"))));
3833TEST(AllowImplicitCompletion,
All) {
3834 const char *
Yes[] = {
3838 " # include <^foo.h>",
3839 "#import <foo/^bar.h>",
3840 "#include_next \"^",
3842 const char *
No[] = {
3846 "#include <foo.h> //^",
3847 "#include \"foo.h\"^",
3851 for (
const char *Test :
Yes) {
3852 llvm::Annotations
A(Test);
3855 for (
const char *Test :
No) {
3856 llvm::Annotations
A(Test);
3861TEST(CompletionTest, FunctionArgsExist) {
3862 clangd::CodeCompleteOptions Opts;
3864 std::string Context = R
"cpp(
3871 template <typename T>
3873 Container(int Size) {}
3876 EXPECT_THAT(completions(Context + "int y = fo^", {}, Opts).Completions,
3877 UnorderedElementsAre(
3878 AllOf(labeled(
"foo(int A)"), snippetSuffix(
"(${1:int A})"))));
3880 completions(Context +
"int y = fo^(42)", {}, Opts).Completions,
3881 UnorderedElementsAre(AllOf(labeled(
"foo(int A)"), snippetSuffix(
""))));
3883 EXPECT_THAT(completions(Context +
"int y = fo^o(42)", {}, Opts).Completions,
3884 UnorderedElementsAre(
3885 AllOf(labeled(
"foo(int A)"), snippetSuffix(
"(${1:int A})"))));
3887 completions(Context +
"int y = ba^", {}, Opts).Completions,
3888 UnorderedElementsAre(AllOf(labeled(
"bar()"), snippetSuffix(
"()"))));
3889 EXPECT_THAT(completions(Context +
"int y = ba^()", {}, Opts).Completions,
3890 UnorderedElementsAre(AllOf(labeled(
"bar()"), snippetSuffix(
""))));
3892 completions(Context +
"Object o = Obj^", {}, Opts).Completions,
3893 Contains(AllOf(labeled(
"Object(int B)"), snippetSuffix(
"(${1:int B})"),
3895 EXPECT_THAT(completions(Context +
"Object o = Obj^()", {}, Opts).Completions,
3896 Contains(AllOf(labeled(
"Object(int B)"), snippetSuffix(
""),
3899 completions(Context +
"Container c = Cont^", {}, Opts).Completions,
3900 Contains(AllOf(labeled(
"Container<typename T>(int Size)"),
3901 snippetSuffix(
"<${1:typename T}>(${2:int Size})"),
3904 completions(Context +
"Container c = Cont^()", {}, Opts).Completions,
3905 Contains(AllOf(labeled(
"Container<typename T>(int Size)"),
3906 snippetSuffix(
"<${1:typename T}>"),
3909 completions(Context +
"Container c = Cont^<int>()", {}, Opts).Completions,
3910 Contains(AllOf(labeled(
"Container<typename T>(int Size)"),
3913 EXPECT_THAT(completions(Context +
"MAC^(2)", {}, Opts).Completions,
3914 Contains(AllOf(labeled(
"MACRO(x)"), snippetSuffix(
""),
3918TEST(CompletionTest, FunctionArgsExist_Issue1785) {
3922 clangd::CodeCompleteOptions Opts;
3925 std::string
Code = R
"cpp(
3937 completions(Code, {}, Opts).Completions,
3938 Contains(AllOf(labeled("waldo(int)"), snippetSuffix(
"(${1:int})"))));
3941TEST(CompletionTest, NoCrashDueToMacroOrdering) {
3942 EXPECT_THAT(completions(R
"cpp(
3944 #define ECHO2(X) ECHO(X)
3945 int finish_preamble = EC^HO(2);)cpp")
3947 UnorderedElementsAre(labeled("ECHO(X)"), labeled(
"ECHO2(X)")));
3950TEST(CompletionTest, ObjCCategoryDecls) {
3952 TU.ExtraArgs.push_back(
"-xobjective-c");
3953 TU.HeaderCode = R
"objc(
3957 @interface Foo (FooExt1)
3960 @interface Foo (FooExt2)
3966 @interface Bar (BarExt)
3970 Annotations Test(R"objc(
3971 @implementation Foo (^)
3974 TU.Code = Test.code().str();
3975 auto Results = completions(TU, Test.point());
3976 EXPECT_THAT(
Results.Completions,
3977 UnorderedElementsAre(labeled(
"FooExt1"), labeled(
"FooExt2")));
3980 Annotations Test(R
"objc(
3984 TU.Code = Test.code().str();
3985 auto Results = completions(TU, Test.point());
3986 EXPECT_THAT(
Results.Completions, UnorderedElementsAre(labeled(
"BarExt")));
3990TEST(CompletionTest, PreambleCodeComplete) {
3991 llvm::StringLiteral Baseline =
"\n#define MACRO 12\nint num = MACRO;";
3992 llvm::StringLiteral ModifiedCC =
3993 "#include \"header.h\"\n#define MACRO 12\nint num = MACRO; int num2 = M^";
3995 Annotations Test(ModifiedCC);
4000 auto Inputs = ModifiedTU.inputs(FS);
4002 BaselineTU.preamble().get(), Inputs, {});
4003 EXPECT_THAT(Result.Completions, Not(testing::IsEmpty()));
4006TEST(CompletionTest, CommentParamName) {
4007 const std::string
Code = R
"cpp(
4008 void fun(int foo, int bar);
4009 void overloaded(int param_int);
4010 void overloaded(int param_int, int param_other);
4011 void overloaded(char param_char);
4015 EXPECT_THAT(completions(Code + "fun(/*^").Completions,
4016 UnorderedElementsAre(labeled(
"foo=*/")));
4017 EXPECT_THAT(completions(
Code +
"fun(1, /*^").Completions,
4018 UnorderedElementsAre(labeled(
"bar=*/")));
4019 EXPECT_THAT(completions(
Code +
"/*^").Completions, IsEmpty());
4022 completions(
Code +
"overloaded(/*^").Completions,
4023 UnorderedElementsAre(labeled(
"param_int=*/"), labeled(
"param_char=*/")));
4025 EXPECT_THAT(completions(
Code +
"fun(/* ^").Completions,
4026 UnorderedElementsAre(labeled(
"foo=*/")));
4027 EXPECT_THAT(completions(
Code +
"fun(/* f^").Completions,
4028 UnorderedElementsAre(labeled(
"foo=*/")));
4029 EXPECT_THAT(completions(
Code +
"fun(/* x^").Completions, IsEmpty());
4030 EXPECT_THAT(completions(
Code +
"fun(/* f ^").Completions, IsEmpty());
4034 std::string CompletionRangeTest(
Code +
"fun(/*[[^]]");
4035 auto Results = completions(CompletionRangeTest);
4036 EXPECT_THAT(
Results.CompletionRange,
4037 llvm::ValueIs(Annotations(CompletionRangeTest).range()));
4041 AllOf(replacesRange(Annotations(CompletionRangeTest).range()),
4045 std::string CompletionRangeTest(
Code +
"fun(/*[[fo^]]");
4046 auto Results = completions(CompletionRangeTest);
4047 EXPECT_THAT(
Results.CompletionRange,
4048 llvm::ValueIs(Annotations(CompletionRangeTest).range()));
4052 AllOf(replacesRange(Annotations(CompletionRangeTest).range()),
4057TEST(CompletionTest, Concepts) {
4058 Annotations
Code(R
"cpp(
4060 concept A = sizeof(T) <= 8;
4062 template<$tparam^A U>
4065 template<typename T>
4066 int bar(T t) requires $expr^A<int>;
4069 concept b = $expr^A && $expr^sizeof(T) % 2 == 0 || $expr^A && sizeof(T) == 1;
4071 $toplevel^A auto i = 19;
4073 template<$toplevel^A auto i> void constrainedNTTP();
4075 // FIXME: The first parameter should be dropped in this case.
4076 void abbreviated($expr^A auto x) {}
4079 TU.Code = Code.code().str();
4080 TU.ExtraArgs = {"-std=c++20"};
4083 Sym.Signature =
"<typename Tp, typename Up>";
4084 Sym.CompletionSnippetSuffix =
"<${1:typename Tp}, ${2:typename Up}>";
4085 std::vector<Symbol> Syms = {Sym};
4086 for (
auto P :
Code.points(
"tparam")) {
4088 completions(TU, P, Syms).Completions,
4089 AllOf(Contains(AllOf(named(
"A"), signature(
""), snippetSuffix(
""))),
4090 Contains(AllOf(named(
"same_as"), signature(
"<typename Up>"),
4091 snippetSuffix(
"<${2:typename Up}>"))),
4092 Contains(named(
"class")), Contains(named(
"typename"))))
4093 <<
"Completing template parameter at position " << P;
4096 for (
auto P :
Code.points(
"toplevel")) {
4098 completions(TU, P, Syms).Completions,
4099 AllOf(Contains(AllOf(named(
"A"), signature(
""), snippetSuffix(
""))),
4100 Contains(AllOf(named(
"same_as"), signature(
"<typename Up>"),
4101 snippetSuffix(
"<${2:typename Up}>")))))
4102 <<
"Completing 'requires' expression at position " << P;
4105 for (
auto P :
Code.points(
"expr")) {
4107 completions(TU, P, Syms).Completions,
4108 AllOf(Contains(AllOf(named(
"A"), signature(
"<class T>"),
4109 snippetSuffix(
"<${1:class T}>"))),
4111 named(
"same_as"), signature(
"<typename Tp, typename Up>"),
4112 snippetSuffix(
"<${1:typename Tp}, ${2:typename Up}>")))))
4113 <<
"Completing 'requires' expression at position " << P;
4117TEST(SignatureHelp, DocFormat) {
4118 Annotations
Code(R
"cpp(
4119 // Comment `with` markup.
4121 void bar() { foo(^); }
4123 for (
auto DocumentationFormat :
4125 auto Sigs = signatures(
Code.code(),
Code.point(), {},
4126 DocumentationFormat);
4127 ASSERT_EQ(Sigs.signatures.size(), 1U);
4128 EXPECT_EQ(Sigs.signatures[0].documentation.kind, DocumentationFormat);
4132TEST(SignatureHelp, TemplateArguments) {
4133 std::string Top = R
"cpp(
4134 template <typename T, int> bool foo(char);
4135 template <int I, int> bool foo(float);
4138 auto First = signatures(Top +
"bool x = foo<^");
4141 UnorderedElementsAre(sig(
"foo<[[typename T]], [[int]]>() -> bool"),
4142 sig(
"foo<[[int I]], [[int]]>() -> bool")));
4143 EXPECT_EQ(First.activeParameter, 0);
4145 auto Second = signatures(Top +
"bool x = foo<1, ^");
4146 EXPECT_THAT(Second.signatures,
4147 ElementsAre(sig(
"foo<[[int I]], [[int]]>() -> bool")));
4148 EXPECT_EQ(Second.activeParameter, 1);
4151TEST(CompletionTest, DoNotCrash) {
4152 llvm::StringLiteral Cases[] = {
4154 template <typename = int> struct Foo {};
4155 auto a = [x(3)](Foo<^>){};
4158 for (
auto Case : Cases) {
4160 auto Completions = completions(Case);
4163TEST(CompletionTest, PreambleFromDifferentTarget) {
4164 constexpr std::string_view PreambleTarget =
"x86_64";
4165 constexpr std::string_view Contents =
4166 "int foo(int); int num; int num2 = foo(n^";
4168 Annotations Test(Contents);
4170 TU.ExtraArgs.emplace_back(
"-target");
4171 TU.ExtraArgs.emplace_back(PreambleTarget);
4175 TU.ExtraArgs.pop_back();
4176 TU.ExtraArgs.emplace_back(
"wasm32");
4179 auto Inputs = TU.inputs(FS);
4186 EXPECT_THAT(Result.Completions, Not(testing::IsEmpty()));
4187 EXPECT_THAT(Signatures.signatures, Not(testing::IsEmpty()));
ArrayRef< const ParmVarDecl * > Parameters
llvm::SmallString< 256U > Name
const ParseInputs & ParseInput
std::vector< CodeCompletionResult > Results
std::optional< float > Score
CharSourceRange Range
SourceRange for the file name.
std::unique_ptr< CompilerInvocation > CI
llvm::raw_string_ostream OS
std::optional< FixItHint > FixIt
#define EXPECT_IFF(condition, value, matcher)
static Options optsForTest()
static std::unique_ptr< SymbolIndex > build(SymbolSlab Symbols, RefSlab Refs, RelationSlab Relations)
Builds an index from slabs. The index takes ownership of the data.
static llvm::Expected< URI > create(llvm::StringRef AbsolutePath, llvm::StringRef Scheme)
Creates a URI for a file in the given scheme.
Symbol objcProtocol(llvm::StringRef Name)
Symbol objcClass(llvm::StringRef Name)
Symbol func(llvm::StringRef Name)
Symbol cls(llvm::StringRef Name)
Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName)
std::string sortText(float Score, llvm::StringRef Name)
Returns a string that sorts in the same order as (-Score, Tiebreak), for LSP.
Symbol conceptSym(llvm::StringRef Name)
IndexContents
Describes what data is covered by an index.
size_t lspLength(llvm::StringRef Code)
CompletionPrefix guessCompletionPrefix(llvm::StringRef Content, unsigned Offset)
std::unique_ptr< CompilerInvocation > buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D, std::vector< std::string > *CC1Args)
Builds compiler invocation that could be used to build AST or preamble.
Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, llvm::StringRef USRFormat, llvm::StringRef Signature)
CompletionItemKind
The kind of a completion entry.
Symbol ns(llvm::StringRef Name)
bool allowImplicitCompletion(llvm::StringRef Content, unsigned Offset)
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
llvm::Expected< CodeCompleteResult > runCodeComplete(ClangdServer &Server, PathRef File, Position Pos, clangd::CodeCompleteOptions Opts)
llvm::Expected< SignatureHelp > runSignatureHelp(ClangdServer &Server, PathRef File, Position Pos, MarkupKind DocumentationFormat)
std::string testPath(PathRef File, llvm::sys::path::Style Style)
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
std::shared_ptr< const PreambleData > buildPreamble(PathRef FileName, CompilerInvocation CI, const ParseInputs &Inputs, bool StoreInMemory, PreambleParsedCallback PreambleCallback, PreambleBuildStats *Stats)
Build a preamble for the new inputs unless an old one can be reused.
TEST(BackgroundQueueTest, Priority)
void wait(std::unique_lock< std::mutex > &Lock, std::condition_variable &CV, Deadline D)
Wait once on CV for the specified duration.
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
void runAddDocument(ClangdServer &Server, PathRef File, llvm::StringRef Contents, llvm::StringRef Version, WantDiagnostics WantDiags, bool ForceRebuild)
Symbol macro(llvm::StringRef Name, llvm::StringRef ArgList)
@ No
Diagnostics must be generated for this snapshot.
std::vector< std::string > lookup(const SymbolIndex &I, llvm::ArrayRef< SymbolID > IDs)
Symbol enmConstant(llvm::StringRef Name)
Deadline timeoutSeconds(std::optional< double > Seconds)
Makes a deadline from a timeout in seconds. std::nullopt means wait forever.
CodeCompleteResult codeComplete(PathRef FileName, Position Pos, const PreambleData *Preamble, const ParseInputs &ParseInput, CodeCompleteOptions Opts, SpeculativeFuzzyFind *SpecFuzzyFind)
Gets code completions at a specified Pos in FileName.
@ PlainText
The primary text to be inserted is treated as a plain string.
@ Snippet
The primary text to be inserted is treated as a snippet.
llvm::StringRef PathRef
A typedef to represent a ref to file path.
SignatureHelp signatureHelp(PathRef FileName, Position Pos, const PreambleData &Preamble, const ParseInputs &ParseInput, MarkupKind DocumentationFormat)
Get signature help at a specified Pos in FileName.
PolySubsequenceMatcher< Args... > HasSubsequence(Args &&... M)
Symbol var(llvm::StringRef Name)
std::array< uint8_t, 20 > SymbolID
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::function< void(const CodeCompletion &, const SymbolQualitySignals &, const SymbolRelevanceSignals &, float Score)> RecordCCResult
Callback invoked on all CompletionCandidate after they are scored and before they are ranked (by -Sco...
MarkupKind DocumentationFormat
Whether to present doc comments as plain-text or markdown.
bool IncludeIneligibleResults
Include results that are not legal completions in the current context.
const SymbolIndex * Index
If Index is set, it is used to augment the code completion results.
const ASTSignals * MainFileSignals
std::function< DecisionForestScores(const SymbolQualitySignals &, const SymbolRelevanceSignals &, float Base)> DecisionForestScorer
Callback used to score a CompletionCandidate if DecisionForest ranking model is enabled.
CodeCompletionRankingModel RankingModel
bool ImportInsertions
Whether include insertions for Objective-C code should use #import instead of #include.
bool AllScopes
Whether to include index symbols that are not defined in the scopes visible from the code completion ...
bool EnableFunctionArgSnippets
Whether to generate snippets for function arguments on code-completion.
size_t Limit
Limit the number of results returned (0 means no limit).
std::optional< bool > BundleOverloads
Combine overloads into a single completion item where possible.
bool IncludeFixIts
Include completions that require small corrections, e.g.
struct clang::clangd::CodeCompleteOptions::IncludeInsertionIndicator IncludeIndicator
bool EnableSnippets
When true, completion items will contain expandable code snippets in completion (e....
bool ShowOrigins
Expose origins of completion items in the label (for debugging).
std::vector< std::string > Scopes
If this is non-empty, symbols must be in at least one of the scopes (e.g.
@ IndexedForCodeCompletion
Whether or not this symbol is meant to be used for the code completion.
@ Include
#include "header.h"
@ Import
#import "header.h"
SymbolID ID
The ID of the symbol.
static TestTU withHeaderCode(llvm::StringRef HeaderCode)
static TestTU withCode(llvm::StringRef Code)
std::unique_ptr< SymbolIndex > index() const