blob: 145eb8018212eff3765ab60320f697c32547dc84 [file] [log] [blame]
Sam McCall9aad25f2017-12-05 07:20:26 +00001//===-- CodeCompleteTests.cpp -----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Eric Liu6f648df2017-12-19 16:50:37 +00009
Sam McCall328cbdb2017-12-20 16:06:05 +000010#include "Annotations.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000011#include "ClangdServer.h"
Sam McCall328cbdb2017-12-20 16:06:05 +000012#include "CodeComplete.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000013#include "Compiler.h"
Ilya Biryukov5a85b8e2017-12-13 12:53:16 +000014#include "Matchers.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000015#include "Protocol.h"
Sam McCalle746a2b2018-07-02 11:13:16 +000016#include "Quality.h"
Sam McCallb536a2a2017-12-19 12:23:48 +000017#include "SourceCode.h"
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000018#include "SyncAPI.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000019#include "TestFS.h"
Eric Liu6f648df2017-12-19 16:50:37 +000020#include "index/MemIndex.h"
Eric Liu5d2a8072018-07-23 10:56:37 +000021#include "clang/Sema/CodeCompleteConsumer.h"
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +000022#include "llvm/Support/Error.h"
Ilya Biryukov981a35d2018-05-28 12:11:37 +000023#include "llvm/Testing/Support/Error.h"
Sam McCallf6ae3232017-12-05 20:11:29 +000024#include "gmock/gmock.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000025#include "gtest/gtest.h"
26
27namespace clang {
28namespace clangd {
Sam McCallf6ae3232017-12-05 20:11:29 +000029
Sam McCall9aad25f2017-12-05 07:20:26 +000030namespace {
31using namespace llvm;
Sam McCallf6ae3232017-12-05 20:11:29 +000032using ::testing::AllOf;
33using ::testing::Contains;
Ilya Biryukov5a5e1ca2017-12-29 14:59:22 +000034using ::testing::Each;
Sam McCallf6ae3232017-12-05 20:11:29 +000035using ::testing::ElementsAre;
Ilya Biryukov71028b82018-03-12 15:28:22 +000036using ::testing::Field;
Sam McCallc18c2802018-06-15 11:06:29 +000037using ::testing::HasSubstr;
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +000038using ::testing::IsEmpty;
Sam McCallf6ae3232017-12-05 20:11:29 +000039using ::testing::Not;
Sam McCall3d139c52018-01-12 18:30:08 +000040using ::testing::UnorderedElementsAre;
Sam McCall9aad25f2017-12-05 07:20:26 +000041
42class IgnoreDiagnostics : public DiagnosticsConsumer {
Ilya Biryukov71028b82018-03-12 15:28:22 +000043 void onDiagnosticsReady(PathRef File,
Sam McCalla7bb0cc2018-03-12 23:22:35 +000044 std::vector<Diag> Diagnostics) override {}
Sam McCall9aad25f2017-12-05 07:20:26 +000045};
46
Sam McCallf6ae3232017-12-05 20:11:29 +000047// GMock helpers for matching completion items.
Sam McCalle746a2b2018-07-02 11:13:16 +000048MATCHER_P(Named, Name, "") { return arg.Name == Name; }
49MATCHER_P(Scope, S, "") { return arg.Scope == S; }
50MATCHER_P(Qualifier, Q, "") { return arg.RequiredQualifier == Q; }
Eric Liu8f3678d2018-06-15 13:34:18 +000051MATCHER_P(Labeled, Label, "") {
Sam McCalle746a2b2018-07-02 11:13:16 +000052 return arg.RequiredQualifier + arg.Name + arg.Signature == Label;
Eric Liu8f3678d2018-06-15 13:34:18 +000053}
54MATCHER_P(SigHelpLabeled, Label, "") { return arg.label == Label; }
Sam McCalle746a2b2018-07-02 11:13:16 +000055MATCHER_P(Kind, K, "") { return arg.Kind == K; }
56MATCHER_P(Doc, D, "") { return arg.Documentation == D; }
57MATCHER_P(ReturnType, D, "") { return arg.ReturnType == D; }
Eric Liu63f419a2018-05-15 15:29:32 +000058MATCHER_P(InsertInclude, IncludeHeader, "") {
Sam McCalle746a2b2018-07-02 11:13:16 +000059 return arg.Header == IncludeHeader && bool(arg.HeaderInsertion);
Eric Liu63f419a2018-05-15 15:29:32 +000060}
Sam McCalle746a2b2018-07-02 11:13:16 +000061MATCHER(InsertInclude, "") { return bool(arg.HeaderInsertion); }
62MATCHER_P(SnippetSuffix, Text, "") { return arg.SnippetSuffix == Text; }
Sam McCall2161ec72018-07-05 06:20:41 +000063MATCHER_P(Origin, OriginSet, "") { return arg.Origin == OriginSet; }
Eric Liu63f419a2018-05-15 15:29:32 +000064
Sam McCallf6ae3232017-12-05 20:11:29 +000065// Shorthand for Contains(Named(Name)).
Sam McCalle746a2b2018-07-02 11:13:16 +000066Matcher<const std::vector<CodeCompletion> &> Has(std::string Name) {
Sam McCallf6ae3232017-12-05 20:11:29 +000067 return Contains(Named(std::move(Name)));
68}
Sam McCalle746a2b2018-07-02 11:13:16 +000069Matcher<const std::vector<CodeCompletion> &> Has(std::string Name,
Sam McCall44fdcec22017-12-08 15:00:59 +000070 CompletionItemKind K) {
71 return Contains(AllOf(Named(std::move(Name)), Kind(K)));
Sam McCallf6ae3232017-12-05 20:11:29 +000072}
Sam McCalle746a2b2018-07-02 11:13:16 +000073MATCHER(IsDocumented, "") { return !arg.Documentation.empty(); }
Sam McCall9aad25f2017-12-05 07:20:26 +000074
Sam McCalla15c2d62018-01-18 09:27:56 +000075std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol> Symbols) {
76 SymbolSlab::Builder Slab;
77 for (const auto &Sym : Symbols)
78 Slab.insert(Sym);
79 return MemIndex::build(std::move(Slab).build());
80}
81
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +000082CodeCompleteResult completions(ClangdServer &Server, StringRef TestCode,
83 Position point,
84 std::vector<Symbol> IndexSymbols = {},
85 clangd::CodeCompleteOptions Opts = {}) {
86 std::unique_ptr<SymbolIndex> OverrideIndex;
87 if (!IndexSymbols.empty()) {
88 assert(!Opts.Index && "both Index and IndexSymbols given!");
89 OverrideIndex = memIndex(std::move(IndexSymbols));
90 Opts.Index = OverrideIndex.get();
91 }
92
93 auto File = testPath("foo.cpp");
94 runAddDocument(Server, File, TestCode);
95 auto CompletionList = cantFail(runCodeComplete(Server, File, point, Opts));
96 return CompletionList;
97}
98
Sam McCalle746a2b2018-07-02 11:13:16 +000099CodeCompleteResult completions(ClangdServer &Server, StringRef Text,
100 std::vector<Symbol> IndexSymbols = {},
101 clangd::CodeCompleteOptions Opts = {}) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000102 std::unique_ptr<SymbolIndex> OverrideIndex;
103 if (!IndexSymbols.empty()) {
104 assert(!Opts.Index && "both Index and IndexSymbols given!");
105 OverrideIndex = memIndex(std::move(IndexSymbols));
106 Opts.Index = OverrideIndex.get();
107 }
108
Sam McCallc1568062018-02-16 09:41:43 +0000109 auto File = testPath("foo.cpp");
Sam McCall328cbdb2017-12-20 16:06:05 +0000110 Annotations Test(Text);
Sam McCall7363a2f2018-03-05 17:28:54 +0000111 runAddDocument(Server, File, Test.code());
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000112 auto CompletionList =
113 cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Ilya Biryukov5a5e1ca2017-12-29 14:59:22 +0000114 return CompletionList;
Sam McCall9aad25f2017-12-05 07:20:26 +0000115}
116
Eric Liu63f419a2018-05-15 15:29:32 +0000117// Builds a server and runs code completion.
118// If IndexSymbols is non-empty, an index will be built and passed to opts.
Sam McCalle746a2b2018-07-02 11:13:16 +0000119CodeCompleteResult completions(StringRef Text,
120 std::vector<Symbol> IndexSymbols = {},
121 clangd::CodeCompleteOptions Opts = {}) {
Eric Liu63f419a2018-05-15 15:29:32 +0000122 MockFSProvider FS;
123 MockCompilationDatabase CDB;
124 IgnoreDiagnostics DiagConsumer;
125 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
126 return completions(Server, Text, std::move(IndexSymbols), std::move(Opts));
127}
128
Sam McCall545a20d2018-01-19 14:34:02 +0000129std::string replace(StringRef Haystack, StringRef Needle, StringRef Repl) {
130 std::string Result;
131 raw_string_ostream OS(Result);
132 std::pair<StringRef, StringRef> Split;
133 for (Split = Haystack.split(Needle); !Split.second.empty();
134 Split = Split.first.split(Needle))
135 OS << Split.first << Repl;
136 Result += Split.first;
137 OS.flush();
138 return Result;
139}
140
Sam McCalla15c2d62018-01-18 09:27:56 +0000141// Helpers to produce fake index symbols for memIndex() or completions().
Sam McCall545a20d2018-01-19 14:34:02 +0000142// USRFormat is a regex replacement string for the unqualified part of the USR.
143Symbol sym(StringRef QName, index::SymbolKind Kind, StringRef USRFormat) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000144 Symbol Sym;
Sam McCall545a20d2018-01-19 14:34:02 +0000145 std::string USR = "c:"; // We synthesize a few simple cases of USRs by hand!
Sam McCalla15c2d62018-01-18 09:27:56 +0000146 size_t Pos = QName.rfind("::");
147 if (Pos == llvm::StringRef::npos) {
148 Sym.Name = QName;
149 Sym.Scope = "";
150 } else {
151 Sym.Name = QName.substr(Pos + 2);
Sam McCall8b2faee2018-01-19 22:18:21 +0000152 Sym.Scope = QName.substr(0, Pos + 2);
153 USR += "@N@" + replace(QName.substr(0, Pos), "::", "@N@"); // ns:: -> @N@ns
Sam McCalla15c2d62018-01-18 09:27:56 +0000154 }
Sam McCall545a20d2018-01-19 14:34:02 +0000155 USR += Regex("^.*$").sub(USRFormat, Sym.Name); // e.g. func -> @F@func#
156 Sym.ID = SymbolID(USR);
Sam McCalla15c2d62018-01-18 09:27:56 +0000157 Sym.SymInfo.Kind = Kind;
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000158 Sym.IsIndexedForCodeCompletion = true;
Sam McCall2161ec72018-07-05 06:20:41 +0000159 Sym.Origin = SymbolOrigin::Static;
Sam McCalla15c2d62018-01-18 09:27:56 +0000160 return Sym;
161}
Sam McCall545a20d2018-01-19 14:34:02 +0000162Symbol func(StringRef Name) { // Assumes the function has no args.
163 return sym(Name, index::SymbolKind::Function, "@F@\\0#"); // no args
164}
165Symbol cls(StringRef Name) {
Eric Liu9b3cba72018-05-30 09:03:39 +0000166 return sym(Name, index::SymbolKind::Class, "@S@\\0");
Sam McCall545a20d2018-01-19 14:34:02 +0000167}
168Symbol var(StringRef Name) {
169 return sym(Name, index::SymbolKind::Variable, "@\\0");
170}
Sam McCalldc8abc42018-05-03 14:53:02 +0000171Symbol ns(StringRef Name) {
172 return sym(Name, index::SymbolKind::Namespace, "@N@\\0");
173}
174Symbol withReferences(int N, Symbol S) {
175 S.References = N;
176 return S;
177}
Sam McCalla15c2d62018-01-18 09:27:56 +0000178
Sam McCallf6ae3232017-12-05 20:11:29 +0000179TEST(CompletionTest, Limit) {
180 clangd::CodeCompleteOptions Opts;
181 Opts.Limit = 2;
182 auto Results = completions(R"cpp(
Sam McCall9aad25f2017-12-05 07:20:26 +0000183struct ClassWithMembers {
184 int AAA();
185 int BBB();
186 int CCC();
187}
Sam McCallf6ae3232017-12-05 20:11:29 +0000188int main() { ClassWithMembers().^ }
Sam McCall9aad25f2017-12-05 07:20:26 +0000189 )cpp",
Sam McCalla15c2d62018-01-18 09:27:56 +0000190 /*IndexSymbols=*/{}, Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000191
Sam McCalle746a2b2018-07-02 11:13:16 +0000192 EXPECT_TRUE(Results.HasMore);
193 EXPECT_THAT(Results.Completions, ElementsAre(Named("AAA"), Named("BBB")));
Sam McCall9aad25f2017-12-05 07:20:26 +0000194}
195
Sam McCallf6ae3232017-12-05 20:11:29 +0000196TEST(CompletionTest, Filter) {
197 std::string Body = R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000198 #define MotorCar
199 int Car;
Sam McCall9aad25f2017-12-05 07:20:26 +0000200 struct S {
201 int FooBar;
202 int FooBaz;
203 int Qux;
204 };
205 )cpp";
Sam McCall8b2dcc12018-06-14 13:50:30 +0000206
207 // Only items matching the fuzzy query are returned.
Sam McCalle746a2b2018-07-02 11:13:16 +0000208 EXPECT_THAT(completions(Body + "int main() { S().Foba^ }").Completions,
Sam McCall8b2dcc12018-06-14 13:50:30 +0000209 AllOf(Has("FooBar"), Has("FooBaz"), Not(Has("Qux"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000210
Sam McCall8b2dcc12018-06-14 13:50:30 +0000211 // Macros require prefix match.
Sam McCalle746a2b2018-07-02 11:13:16 +0000212 EXPECT_THAT(completions(Body + "int main() { C^ }").Completions,
Sam McCall8b2dcc12018-06-14 13:50:30 +0000213 AllOf(Has("Car"), Not(Has("MotorCar"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000214}
215
Sam McCallf6ae3232017-12-05 20:11:29 +0000216void TestAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000217 auto Results = completions(
218 R"cpp(
219 #define MACRO X
Sam McCall9aad25f2017-12-05 07:20:26 +0000220
Sam McCall44fdcec22017-12-08 15:00:59 +0000221 int global_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000222
Sam McCall44fdcec22017-12-08 15:00:59 +0000223 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000224
Sam McCall44fdcec22017-12-08 15:00:59 +0000225 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000226
Sam McCall44fdcec22017-12-08 15:00:59 +0000227 struct ClassWithMembers {
228 /// Doc for method.
229 int method();
Sam McCall9aad25f2017-12-05 07:20:26 +0000230
Sam McCall44fdcec22017-12-08 15:00:59 +0000231 int field;
232 private:
233 int private_field;
234 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000235
Sam McCall44fdcec22017-12-08 15:00:59 +0000236 int test() {
237 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000238
Sam McCall44fdcec22017-12-08 15:00:59 +0000239 /// Doc for local_var.
240 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000241
Sam McCall44fdcec22017-12-08 15:00:59 +0000242 ClassWithMembers().^
243 }
244 )cpp",
Sam McCall545a20d2018-01-19 14:34:02 +0000245 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000246
Sam McCallf6ae3232017-12-05 20:11:29 +0000247 // Class members. The only items that must be present in after-dot
248 // completion.
Sam McCalle746a2b2018-07-02 11:13:16 +0000249 EXPECT_THAT(Results.Completions,
250 AllOf(Has("method"), Has("field"), Not(Has("ClassWithMembers")),
Sam McCall4caa8512018-06-07 12:49:17 +0000251 Not(Has("operator=")), Not(Has("~ClassWithMembers"))));
Sam McCalle746a2b2018-07-02 11:13:16 +0000252 EXPECT_IFF(Opts.IncludeIneligibleResults, Results.Completions,
Sam McCall44fdcec22017-12-08 15:00:59 +0000253 Has("private_field"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000254 // Global items.
Sam McCall545a20d2018-01-19 14:34:02 +0000255 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +0000256 Results.Completions,
Sam McCall545a20d2018-01-19 14:34:02 +0000257 Not(AnyOf(Has("global_var"), Has("index_var"), Has("global_func"),
258 Has("global_func()"), Has("index_func"), Has("GlobalClass"),
259 Has("IndexClass"), Has("MACRO"), Has("LocalClass"))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000260 // There should be no code patterns (aka snippets) in after-dot
261 // completion. At least there aren't any we're aware of.
Sam McCalle746a2b2018-07-02 11:13:16 +0000262 EXPECT_THAT(Results.Completions,
263 Not(Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000264 // Check documentation.
Sam McCalle746a2b2018-07-02 11:13:16 +0000265 EXPECT_IFF(Opts.IncludeComments, Results.Completions,
266 Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000267}
Sam McCall9aad25f2017-12-05 07:20:26 +0000268
Sam McCallf6ae3232017-12-05 20:11:29 +0000269void TestGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000270 auto Results = completions(
271 R"cpp(
272 #define MACRO X
Sam McCall9aad25f2017-12-05 07:20:26 +0000273
Sam McCall44fdcec22017-12-08 15:00:59 +0000274 int global_var;
275 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000276
Sam McCall44fdcec22017-12-08 15:00:59 +0000277 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000278
Sam McCall44fdcec22017-12-08 15:00:59 +0000279 struct ClassWithMembers {
280 /// Doc for method.
281 int method();
282 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000283
Sam McCall44fdcec22017-12-08 15:00:59 +0000284 int test() {
285 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000286
Sam McCall44fdcec22017-12-08 15:00:59 +0000287 /// Doc for local_var.
288 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000289
Sam McCall44fdcec22017-12-08 15:00:59 +0000290 ^
291 }
292 )cpp",
Sam McCall545a20d2018-01-19 14:34:02 +0000293 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
Sam McCallf6ae3232017-12-05 20:11:29 +0000294
295 // Class members. Should never be present in global completions.
Sam McCalle746a2b2018-07-02 11:13:16 +0000296 EXPECT_THAT(Results.Completions,
Sam McCallf6ae3232017-12-05 20:11:29 +0000297 Not(AnyOf(Has("method"), Has("method()"), Has("field"))));
298 // Global items.
Sam McCalle746a2b2018-07-02 11:13:16 +0000299 EXPECT_THAT(Results.Completions,
300 AllOf(Has("global_var"), Has("index_var"), Has("global_func"),
Sam McCall545a20d2018-01-19 14:34:02 +0000301 Has("index_func" /* our fake symbol doesn't include () */),
302 Has("GlobalClass"), Has("IndexClass")));
Sam McCallf6ae3232017-12-05 20:11:29 +0000303 // A macro.
Sam McCalle746a2b2018-07-02 11:13:16 +0000304 EXPECT_IFF(Opts.IncludeMacros, Results.Completions, Has("MACRO"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000305 // Local items. Must be present always.
Sam McCalle746a2b2018-07-02 11:13:16 +0000306 EXPECT_THAT(Results.Completions,
Ilya Biryukov9b5ffc22017-12-12 12:56:46 +0000307 AllOf(Has("local_var"), Has("LocalClass"),
308 Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000309 // Check documentation.
Sam McCalle746a2b2018-07-02 11:13:16 +0000310 EXPECT_IFF(Opts.IncludeComments, Results.Completions,
311 Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000312}
313
314TEST(CompletionTest, CompletionOptions) {
Sam McCall2c3849a2018-01-16 12:21:24 +0000315 auto Test = [&](const clangd::CodeCompleteOptions &Opts) {
316 TestAfterDotCompletion(Opts);
317 TestGlobalScopeCompletion(Opts);
318 };
319 // We used to test every combination of options, but that got too slow (2^N).
320 auto Flags = {
Ilya Biryukov71028b82018-03-12 15:28:22 +0000321 &clangd::CodeCompleteOptions::IncludeMacros,
Ilya Biryukov43714502018-05-16 12:32:44 +0000322 &clangd::CodeCompleteOptions::IncludeComments,
Ilya Biryukov71028b82018-03-12 15:28:22 +0000323 &clangd::CodeCompleteOptions::IncludeCodePatterns,
324 &clangd::CodeCompleteOptions::IncludeIneligibleResults,
Sam McCall2c3849a2018-01-16 12:21:24 +0000325 };
326 // Test default options.
327 Test({});
328 // Test with one flag flipped.
329 for (auto &F : Flags) {
330 clangd::CodeCompleteOptions O;
331 O.*F ^= true;
332 Test(O);
Sam McCall9aad25f2017-12-05 07:20:26 +0000333 }
334}
335
Sam McCall44fdcec22017-12-08 15:00:59 +0000336TEST(CompletionTest, Priorities) {
337 auto Internal = completions(R"cpp(
338 class Foo {
339 public: void pub();
340 protected: void prot();
341 private: void priv();
342 };
343 void Foo::pub() { this->^ }
344 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000345 EXPECT_THAT(Internal.Completions,
Sam McCall44fdcec22017-12-08 15:00:59 +0000346 HasSubsequence(Named("priv"), Named("prot"), Named("pub")));
347
348 auto External = completions(R"cpp(
349 class Foo {
350 public: void pub();
351 protected: void prot();
352 private: void priv();
353 };
354 void test() {
355 Foo F;
356 F.^
357 }
358 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000359 EXPECT_THAT(External.Completions,
Sam McCall44fdcec22017-12-08 15:00:59 +0000360 AllOf(Has("pub"), Not(Has("prot")), Not(Has("priv"))));
361}
362
363TEST(CompletionTest, Qualifiers) {
364 auto Results = completions(R"cpp(
365 class Foo {
366 public: int foo() const;
367 int bar() const;
368 };
369 class Bar : public Foo {
370 int foo() const;
371 };
372 void test() { Bar().^ }
373 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000374 EXPECT_THAT(Results.Completions,
375 HasSubsequence(AllOf(Qualifier(""), Named("bar")),
376 AllOf(Qualifier("Foo::"), Named("foo"))));
377 EXPECT_THAT(Results.Completions,
378 Not(Contains(AllOf(Qualifier(""), Named("foo"))))); // private
Sam McCall44fdcec22017-12-08 15:00:59 +0000379}
380
Sam McCall4caa8512018-06-07 12:49:17 +0000381TEST(CompletionTest, InjectedTypename) {
382 // These are suppressed when accessed as a member...
Sam McCalle746a2b2018-07-02 11:13:16 +0000383 EXPECT_THAT(completions("struct X{}; void foo(){ X().^ }").Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000384 Not(Has("X")));
Sam McCalle746a2b2018-07-02 11:13:16 +0000385 EXPECT_THAT(completions("struct X{ void foo(){ this->^ } };").Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000386 Not(Has("X")));
387 // ...but accessible in other, more useful cases.
Sam McCalle746a2b2018-07-02 11:13:16 +0000388 EXPECT_THAT(completions("struct X{ void foo(){ ^ } };").Completions,
389 Has("X"));
390 EXPECT_THAT(
391 completions("struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions,
392 Has("Y"));
Sam McCall4caa8512018-06-07 12:49:17 +0000393 EXPECT_THAT(
394 completions(
395 "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };")
Sam McCalle746a2b2018-07-02 11:13:16 +0000396 .Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000397 Has("Y"));
398 // This case is marginal (`using X::X` is useful), we allow it for now.
Sam McCalle746a2b2018-07-02 11:13:16 +0000399 EXPECT_THAT(completions("struct X{}; void foo(){ X::^ }").Completions,
400 Has("X"));
Sam McCall4caa8512018-06-07 12:49:17 +0000401}
402
Sam McCall44fdcec22017-12-08 15:00:59 +0000403TEST(CompletionTest, Snippets) {
404 clangd::CodeCompleteOptions Opts;
Sam McCall44fdcec22017-12-08 15:00:59 +0000405 auto Results = completions(
406 R"cpp(
407 struct fake {
408 int a;
409 int f(int i, const float f) const;
410 };
411 int main() {
412 fake f;
413 f.^
414 }
415 )cpp",
Sam McCalla15c2d62018-01-18 09:27:56 +0000416 /*IndexSymbols=*/{}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000417 EXPECT_THAT(
418 Results.Completions,
419 HasSubsequence(Named("a"),
420 SnippetSuffix("(${1:int i}, ${2:const float f})")));
Sam McCall44fdcec22017-12-08 15:00:59 +0000421}
422
423TEST(CompletionTest, Kinds) {
Sam McCall545a20d2018-01-19 14:34:02 +0000424 auto Results = completions(
425 R"cpp(
426 #define MACRO X
427 int variable;
428 struct Struct {};
429 int function();
430 int X = ^
431 )cpp",
432 {func("indexFunction"), var("indexVariable"), cls("indexClass")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000433 EXPECT_THAT(Results.Completions,
Sam McCall545a20d2018-01-19 14:34:02 +0000434 AllOf(Has("function", CompletionItemKind::Function),
435 Has("variable", CompletionItemKind::Variable),
436 Has("int", CompletionItemKind::Keyword),
437 Has("Struct", CompletionItemKind::Class),
438 Has("MACRO", CompletionItemKind::Text),
439 Has("indexFunction", CompletionItemKind::Function),
440 Has("indexVariable", CompletionItemKind::Variable),
441 Has("indexClass", CompletionItemKind::Class)));
Sam McCall44fdcec22017-12-08 15:00:59 +0000442
Sam McCall44fdcec22017-12-08 15:00:59 +0000443 Results = completions("nam^");
Sam McCalle746a2b2018-07-02 11:13:16 +0000444 EXPECT_THAT(Results.Completions,
445 Has("namespace", CompletionItemKind::Snippet));
Sam McCall44fdcec22017-12-08 15:00:59 +0000446}
447
Sam McCall84652cc2018-01-12 16:16:09 +0000448TEST(CompletionTest, NoDuplicates) {
Sam McCall545a20d2018-01-19 14:34:02 +0000449 auto Results = completions(
450 R"cpp(
451 class Adapter {
Sam McCall545a20d2018-01-19 14:34:02 +0000452 };
Sam McCall84652cc2018-01-12 16:16:09 +0000453
Eric Liu9b3cba72018-05-30 09:03:39 +0000454 void f() {
Sam McCall545a20d2018-01-19 14:34:02 +0000455 Adapter^
456 }
457 )cpp",
458 {cls("Adapter")});
Sam McCall84652cc2018-01-12 16:16:09 +0000459
460 // Make sure there are no duplicate entries of 'Adapter'.
Sam McCalle746a2b2018-07-02 11:13:16 +0000461 EXPECT_THAT(Results.Completions, ElementsAre(Named("Adapter")));
Sam McCall84652cc2018-01-12 16:16:09 +0000462}
463
Sam McCall545a20d2018-01-19 14:34:02 +0000464TEST(CompletionTest, ScopedNoIndex) {
465 auto Results = completions(
466 R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000467 namespace fake { int BigBang, Babble, Box; };
468 int main() { fake::ba^ }
Sam McCall545a20d2018-01-19 14:34:02 +0000469 ")cpp");
Sam McCall8b2dcc12018-06-14 13:50:30 +0000470 // Babble is a better match than BigBang. Box doesn't match at all.
Sam McCalle746a2b2018-07-02 11:13:16 +0000471 EXPECT_THAT(Results.Completions,
472 ElementsAre(Named("Babble"), Named("BigBang")));
Sam McCall84652cc2018-01-12 16:16:09 +0000473}
474
Sam McCall545a20d2018-01-19 14:34:02 +0000475TEST(CompletionTest, Scoped) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000476 auto Results = completions(
477 R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000478 namespace fake { int Babble, Box; };
479 int main() { fake::ba^ }
Sam McCall545a20d2018-01-19 14:34:02 +0000480 ")cpp",
481 {var("fake::BigBang")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000482 EXPECT_THAT(Results.Completions,
483 ElementsAre(Named("Babble"), Named("BigBang")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000484}
485
Sam McCall545a20d2018-01-19 14:34:02 +0000486TEST(CompletionTest, ScopedWithFilter) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000487 auto Results = completions(
488 R"cpp(
489 void f() { ns::x^ }
490 )cpp",
491 {cls("ns::XYZ"), func("ns::foo")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000492 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("XYZ")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000493}
494
Sam McCalldc8abc42018-05-03 14:53:02 +0000495TEST(CompletionTest, ReferencesAffectRanking) {
Eric Liu84bd5db2018-07-25 11:26:35 +0000496 auto Results = completions("int main() { abs^ }", {ns("absl"), func("absb")});
497 EXPECT_THAT(Results.Completions, HasSubsequence(Named("absb"), Named("absl")));
Sam McCalldc8abc42018-05-03 14:53:02 +0000498 Results = completions("int main() { abs^ }",
Eric Liu84bd5db2018-07-25 11:26:35 +0000499 {withReferences(10000, ns("absl")), func("absb")});
500 EXPECT_THAT(Results.Completions,
501 HasSubsequence(Named("absl"), Named("absb")));
Sam McCalldc8abc42018-05-03 14:53:02 +0000502}
503
Sam McCall545a20d2018-01-19 14:34:02 +0000504TEST(CompletionTest, GlobalQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000505 auto Results = completions(
506 R"cpp(
507 void f() { ::^ }
508 )cpp",
509 {cls("XYZ")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000510 EXPECT_THAT(Results.Completions,
511 AllOf(Has("XYZ", CompletionItemKind::Class),
512 Has("f", CompletionItemKind::Function)));
Sam McCalla15c2d62018-01-18 09:27:56 +0000513}
514
Sam McCall545a20d2018-01-19 14:34:02 +0000515TEST(CompletionTest, FullyQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000516 auto Results = completions(
517 R"cpp(
Sam McCall545a20d2018-01-19 14:34:02 +0000518 namespace ns { void bar(); }
Sam McCalla15c2d62018-01-18 09:27:56 +0000519 void f() { ::ns::^ }
520 )cpp",
521 {cls("ns::XYZ")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000522 EXPECT_THAT(Results.Completions,
523 AllOf(Has("XYZ", CompletionItemKind::Class),
524 Has("bar", CompletionItemKind::Function)));
Sam McCall545a20d2018-01-19 14:34:02 +0000525}
526
527TEST(CompletionTest, SemaIndexMerge) {
528 auto Results = completions(
529 R"cpp(
530 namespace ns { int local; void both(); }
531 void f() { ::ns::^ }
532 )cpp",
533 {func("ns::both"), cls("ns::Index")});
534 // We get results from both index and sema, with no duplicates.
Sam McCall2161ec72018-07-05 06:20:41 +0000535 EXPECT_THAT(Results.Completions,
536 UnorderedElementsAre(
537 AllOf(Named("local"), Origin(SymbolOrigin::AST)),
538 AllOf(Named("Index"), Origin(SymbolOrigin::Static)),
539 AllOf(Named("both"),
540 Origin(SymbolOrigin::AST | SymbolOrigin::Static))));
Sam McCalla15c2d62018-01-18 09:27:56 +0000541}
542
Haojian Wu48b48652018-01-25 09:20:09 +0000543TEST(CompletionTest, SemaIndexMergeWithLimit) {
544 clangd::CodeCompleteOptions Opts;
545 Opts.Limit = 1;
546 auto Results = completions(
547 R"cpp(
548 namespace ns { int local; void both(); }
549 void f() { ::ns::^ }
550 )cpp",
551 {func("ns::both"), cls("ns::Index")}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000552 EXPECT_EQ(Results.Completions.size(), Opts.Limit);
553 EXPECT_TRUE(Results.HasMore);
Haojian Wu48b48652018-01-25 09:20:09 +0000554}
555
Eric Liu63f419a2018-05-15 15:29:32 +0000556TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
557 MockFSProvider FS;
558 MockCompilationDatabase CDB;
559 std::string Subdir = testPath("sub");
560 std::string SearchDirArg = (llvm::Twine("-I") + Subdir).str();
561 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
562 std::string BarHeader = testPath("sub/bar.h");
563 FS.Files[BarHeader] = "";
564
565 IgnoreDiagnostics DiagConsumer;
566 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Eric Liu63f419a2018-05-15 15:29:32 +0000567 auto BarURI = URI::createFile(BarHeader).toString();
568 Symbol Sym = cls("ns::X");
569 Sym.CanonicalDeclaration.FileURI = BarURI;
Sam McCall2e5700f2018-08-31 13:55:01 +0000570 Sym.IncludeHeader = BarURI;
Eric Liu63f419a2018-05-15 15:29:32 +0000571 // Shoten include path based on search dirctory and insert.
572 auto Results = completions(Server,
573 R"cpp(
574 int main() { ns::^ }
575 )cpp",
576 {Sym});
Sam McCalle746a2b2018-07-02 11:13:16 +0000577 EXPECT_THAT(Results.Completions,
578 ElementsAre(AllOf(Named("X"), InsertInclude("\"bar.h\""))));
Eric Liu63f419a2018-05-15 15:29:32 +0000579 // Duplicate based on inclusions in preamble.
580 Results = completions(Server,
581 R"cpp(
582 #include "sub/bar.h" // not shortest, so should only match resolved.
583 int main() { ns::^ }
584 )cpp",
585 {Sym});
Sam McCalle746a2b2018-07-02 11:13:16 +0000586 EXPECT_THAT(Results.Completions, ElementsAre(AllOf(Named("X"), Labeled("X"),
587 Not(InsertInclude()))));
Eric Liu63f419a2018-05-15 15:29:32 +0000588}
589
Eric Liu9b3cba72018-05-30 09:03:39 +0000590TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {
591 MockFSProvider FS;
592 MockCompilationDatabase CDB;
593
594 IgnoreDiagnostics DiagConsumer;
595 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Eric Liu9b3cba72018-05-30 09:03:39 +0000596 Symbol SymX = cls("ns::X");
597 Symbol SymY = cls("ns::Y");
598 std::string BarHeader = testPath("bar.h");
599 auto BarURI = URI::createFile(BarHeader).toString();
600 SymX.CanonicalDeclaration.FileURI = BarURI;
601 SymY.CanonicalDeclaration.FileURI = BarURI;
Sam McCall2e5700f2018-08-31 13:55:01 +0000602 SymX.IncludeHeader = "<bar>";
603 SymY.IncludeHeader = "<bar>";
Eric Liu9b3cba72018-05-30 09:03:39 +0000604 // Shoten include path based on search dirctory and insert.
605 auto Results = completions(Server,
606 R"cpp(
607 namespace ns {
608 class X;
609 class Y {}
610 }
611 int main() { ns::^ }
612 )cpp",
613 {SymX, SymY});
Sam McCalle746a2b2018-07-02 11:13:16 +0000614 EXPECT_THAT(Results.Completions,
615 ElementsAre(AllOf(Named("X"), Not(InsertInclude())),
616 AllOf(Named("Y"), Not(InsertInclude()))));
Eric Liu9b3cba72018-05-30 09:03:39 +0000617}
618
Sam McCalla15c2d62018-01-18 09:27:56 +0000619TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
620 MockFSProvider FS;
621 MockCompilationDatabase CDB;
622 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000623 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Sam McCalla15c2d62018-01-18 09:27:56 +0000624
Sam McCallc1568062018-02-16 09:41:43 +0000625 FS.Files[testPath("bar.h")] =
Sam McCalld5ea3e32018-01-24 17:53:32 +0000626 R"cpp(namespace ns { struct preamble { int member; }; })cpp";
Sam McCallc1568062018-02-16 09:41:43 +0000627 auto File = testPath("foo.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000628 Annotations Test(R"cpp(
629 #include "bar.h"
630 namespace ns { int local; }
Sam McCalld5ea3e32018-01-24 17:53:32 +0000631 void f() { ns::^; }
632 void f() { ns::preamble().$2^; }
Sam McCalla15c2d62018-01-18 09:27:56 +0000633 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000634 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000635 clangd::CodeCompleteOptions Opts = {};
636
Sam McCalla15c2d62018-01-18 09:27:56 +0000637 auto I = memIndex({var("ns::index")});
638 Opts.Index = I.get();
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000639 auto WithIndex = cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000640 EXPECT_THAT(WithIndex.Completions,
Sam McCalla15c2d62018-01-18 09:27:56 +0000641 UnorderedElementsAre(Named("local"), Named("index")));
Sam McCalld5ea3e32018-01-24 17:53:32 +0000642 auto ClassFromPreamble =
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000643 cantFail(runCodeComplete(Server, File, Test.point("2"), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000644 EXPECT_THAT(ClassFromPreamble.Completions, Contains(Named("member")));
Sam McCall0bb24cd2018-02-13 08:59:23 +0000645
646 Opts.Index = nullptr;
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000647 auto WithoutIndex =
648 cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000649 EXPECT_THAT(WithoutIndex.Completions,
Sam McCall0bb24cd2018-02-13 08:59:23 +0000650 UnorderedElementsAre(Named("local"), Named("preamble")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000651}
652
653TEST(CompletionTest, DynamicIndexMultiFile) {
654 MockFSProvider FS;
655 MockCompilationDatabase CDB;
656 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000657 auto Opts = ClangdServer::optsForTest();
658 Opts.BuildDynamicSymbolIndex = true;
659 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
Sam McCalla15c2d62018-01-18 09:27:56 +0000660
Eric Liu709bde82018-02-19 18:48:44 +0000661 FS.Files[testPath("foo.h")] = R"cpp(
Sam McCalla15c2d62018-01-18 09:27:56 +0000662 namespace ns { class XYZ {}; void foo(int x) {} }
Eric Liu709bde82018-02-19 18:48:44 +0000663 )cpp";
Sam McCall7363a2f2018-03-05 17:28:54 +0000664 runAddDocument(Server, testPath("foo.cpp"), R"cpp(
Eric Liu709bde82018-02-19 18:48:44 +0000665 #include "foo.h"
Sam McCall0bb24cd2018-02-13 08:59:23 +0000666 )cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000667
Sam McCallc1568062018-02-16 09:41:43 +0000668 auto File = testPath("bar.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000669 Annotations Test(R"cpp(
670 namespace ns {
671 class XXX {};
672 /// Doooc
673 void fooooo() {}
674 }
675 void f() { ns::^ }
676 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000677 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000678
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000679 auto Results = cantFail(runCodeComplete(Server, File, Test.point(), {}));
Sam McCalla15c2d62018-01-18 09:27:56 +0000680 // "XYZ" and "foo" are not included in the file being completed but are still
681 // visible through the index.
Sam McCalle746a2b2018-07-02 11:13:16 +0000682 EXPECT_THAT(Results.Completions, Has("XYZ", CompletionItemKind::Class));
683 EXPECT_THAT(Results.Completions, Has("foo", CompletionItemKind::Function));
684 EXPECT_THAT(Results.Completions, Has("XXX", CompletionItemKind::Class));
685 EXPECT_THAT(Results.Completions,
686 Contains((Named("fooooo"), Kind(CompletionItemKind::Function),
687 Doc("Doooc"), ReturnType("void"))));
Sam McCalla15c2d62018-01-18 09:27:56 +0000688}
689
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000690TEST(CompletionTest, Documentation) {
691 auto Results = completions(
692 R"cpp(
693 // Non-doxygen comment.
694 int foo();
695 /// Doxygen comment.
696 /// \param int a
697 int bar(int a);
698 /* Multi-line
699 block comment
700 */
701 int baz();
702
703 int x = ^
704 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000705 EXPECT_THAT(Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000706 Contains(AllOf(Named("foo"), Doc("Non-doxygen comment."))));
707 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +0000708 Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000709 Contains(AllOf(Named("bar"), Doc("Doxygen comment.\n\\param int a"))));
Sam McCalle746a2b2018-07-02 11:13:16 +0000710 EXPECT_THAT(Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000711 Contains(AllOf(Named("baz"), Doc("Multi-line\nblock comment"))));
712}
713
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000714TEST(CompletionTest, GlobalCompletionFiltering) {
715
716 Symbol Class = cls("XYZ");
717 Class.IsIndexedForCodeCompletion = false;
718 Symbol Func = func("XYZ::foooo");
719 Func.IsIndexedForCodeCompletion = false;
720
721 auto Results = completions(R"(// void f() {
722 XYZ::foooo^
723 })",
724 {Class, Func});
Sam McCalle746a2b2018-07-02 11:13:16 +0000725 EXPECT_THAT(Results.Completions, IsEmpty());
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000726}
727
Haojian Wu58d208d2018-01-25 09:44:06 +0000728TEST(CodeCompleteTest, DisableTypoCorrection) {
729 auto Results = completions(R"cpp(
730 namespace clang { int v; }
731 void f() { clangd::^
732 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000733 EXPECT_TRUE(Results.Completions.empty());
Haojian Wu58d208d2018-01-25 09:44:06 +0000734}
735
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000736TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
737 auto Results = completions(R"cpp(
738 namespace clang { }
739 void f() {
740 clan^
741 }
742 )cpp");
743
Sam McCalle746a2b2018-07-02 11:13:16 +0000744 EXPECT_THAT(Results.Completions, Contains(Labeled("clang")));
745 EXPECT_THAT(Results.Completions, Not(Contains(Labeled("clang::"))));
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000746}
747
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000748TEST(CompletionTest, BacktrackCrashes) {
749 // Sema calls code completion callbacks twice in these cases.
750 auto Results = completions(R"cpp(
751 namespace ns {
752 struct FooBarBaz {};
753 } // namespace ns
754
755 int foo(ns::FooBar^
756 )cpp");
757
Sam McCalle746a2b2018-07-02 11:13:16 +0000758 EXPECT_THAT(Results.Completions, ElementsAre(Labeled("FooBarBaz")));
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000759
760 // Check we don't crash in that case too.
761 completions(R"cpp(
762 struct FooBarBaz {};
763 void test() {
764 if (FooBarBaz * x^) {}
765 }
766)cpp");
767}
768
Eric Liu42abe412018-05-24 11:20:19 +0000769TEST(CompletionTest, CompleteInMacroWithStringification) {
770 auto Results = completions(R"cpp(
771void f(const char *, int x);
772#define F(x) f(#x, x)
773
774namespace ns {
775int X;
776int Y;
777} // namespace ns
778
779int f(int input_num) {
780 F(ns::^)
781}
782)cpp");
783
Sam McCalle746a2b2018-07-02 11:13:16 +0000784 EXPECT_THAT(Results.Completions,
Eric Liu42abe412018-05-24 11:20:19 +0000785 UnorderedElementsAre(Named("X"), Named("Y")));
786}
787
788TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
789 auto Results = completions(R"cpp(
790void f(const char *, int x);
791#define F(x) f(#x, x)
792
793namespace ns {
794int X;
795
796int f(int input_num) {
797 F(^)
798}
799} // namespace ns
800)cpp");
801
Sam McCalle746a2b2018-07-02 11:13:16 +0000802 EXPECT_THAT(Results.Completions, Contains(Named("X")));
Eric Liu42abe412018-05-24 11:20:19 +0000803}
804
Eric Liu485074f2018-07-11 13:15:31 +0000805TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000806 auto Results = completions(R"cpp(
807 int bar(int param_in_bar) {
808 }
809
810 int foo(int param_in_foo) {
811#if 0
Eric Liu485074f2018-07-11 13:15:31 +0000812 // In recorvery mode, "param_in_foo" will also be suggested among many other
813 // unrelated symbols; however, this is really a special case where this works.
814 // If the #if block is outside of the function, "param_in_foo" is still
815 // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't
816 // really provide useful results in excluded branches.
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000817 par^
818#endif
819 }
820)cpp");
821
Eric Liu485074f2018-07-11 13:15:31 +0000822 EXPECT_TRUE(Results.Completions.empty());
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000823}
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000824SignatureHelp signatures(StringRef Text, Position Point,
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +0000825 std::vector<Symbol> IndexSymbols = {}) {
826 std::unique_ptr<SymbolIndex> Index;
827 if (!IndexSymbols.empty())
828 Index = memIndex(IndexSymbols);
829
Sam McCall800d4372017-12-19 10:29:27 +0000830 MockFSProvider FS;
831 MockCompilationDatabase CDB;
832 IgnoreDiagnostics DiagConsumer;
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +0000833 ClangdServer::Options Opts = ClangdServer::optsForTest();
834 Opts.StaticIndex = Index.get();
835
836 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
Sam McCallc1568062018-02-16 09:41:43 +0000837 auto File = testPath("foo.cpp");
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000838 runAddDocument(Server, File, Text);
839 return cantFail(runSignatureHelp(Server, File, Point));
840}
841
842SignatureHelp signatures(StringRef Text,
843 std::vector<Symbol> IndexSymbols = {}) {
Sam McCall328cbdb2017-12-20 16:06:05 +0000844 Annotations Test(Text);
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000845 return signatures(Test.code(), Test.point(), std::move(IndexSymbols));
Sam McCall800d4372017-12-19 10:29:27 +0000846}
847
848MATCHER_P(ParamsAre, P, "") {
849 if (P.size() != arg.parameters.size())
850 return false;
851 for (unsigned I = 0; I < P.size(); ++I)
852 if (P[I] != arg.parameters[I].label)
853 return false;
854 return true;
855}
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +0000856MATCHER_P(SigDoc, Doc, "") { return arg.documentation == Doc; }
Sam McCall800d4372017-12-19 10:29:27 +0000857
858Matcher<SignatureInformation> Sig(std::string Label,
859 std::vector<std::string> Params) {
Eric Liu8f3678d2018-06-15 13:34:18 +0000860 return AllOf(SigHelpLabeled(Label), ParamsAre(Params));
Sam McCall800d4372017-12-19 10:29:27 +0000861}
862
863TEST(SignatureHelpTest, Overloads) {
864 auto Results = signatures(R"cpp(
865 void foo(int x, int y);
866 void foo(int x, float y);
867 void foo(float x, int y);
868 void foo(float x, float y);
869 void bar(int x, int y = 0);
870 int main() { foo(^); }
871 )cpp");
872 EXPECT_THAT(Results.signatures,
873 UnorderedElementsAre(
874 Sig("foo(float x, float y) -> void", {"float x", "float y"}),
875 Sig("foo(float x, int y) -> void", {"float x", "int y"}),
876 Sig("foo(int x, float y) -> void", {"int x", "float y"}),
877 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
878 // We always prefer the first signature.
879 EXPECT_EQ(0, Results.activeSignature);
880 EXPECT_EQ(0, Results.activeParameter);
881}
882
883TEST(SignatureHelpTest, DefaultArgs) {
884 auto Results = signatures(R"cpp(
885 void bar(int x, int y = 0);
886 void bar(float x = 0, int y = 42);
887 int main() { bar(^
888 )cpp");
889 EXPECT_THAT(Results.signatures,
890 UnorderedElementsAre(
891 Sig("bar(int x, int y = 0) -> void", {"int x", "int y = 0"}),
892 Sig("bar(float x = 0, int y = 42) -> void",
893 {"float x = 0", "int y = 42"})));
894 EXPECT_EQ(0, Results.activeSignature);
895 EXPECT_EQ(0, Results.activeParameter);
896}
897
898TEST(SignatureHelpTest, ActiveArg) {
899 auto Results = signatures(R"cpp(
900 int baz(int a, int b, int c);
901 int main() { baz(baz(1,2,3), ^); }
902 )cpp");
903 EXPECT_THAT(Results.signatures,
904 ElementsAre(Sig("baz(int a, int b, int c) -> int",
905 {"int a", "int b", "int c"})));
906 EXPECT_EQ(0, Results.activeSignature);
907 EXPECT_EQ(1, Results.activeParameter);
908}
909
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000910TEST(SignatureHelpTest, OpeningParen) {
911 llvm::StringLiteral Tests[] = {// Recursive function call.
912 R"cpp(
913 int foo(int a, int b, int c);
914 int main() {
915 foo(foo $p^( foo(10, 10, 10), ^ )));
916 })cpp",
917 // Functional type cast.
918 R"cpp(
919 struct Foo {
920 Foo(int a, int b, int c);
921 };
922 int main() {
923 Foo $p^( 10, ^ );
924 })cpp",
925 // New expression.
926 R"cpp(
927 struct Foo {
928 Foo(int a, int b, int c);
929 };
930 int main() {
931 new Foo $p^( 10, ^ );
932 })cpp",
933 // Macro expansion.
934 R"cpp(
935 int foo(int a, int b, int c);
936 #define FOO foo(
937
938 int main() {
939 // Macro expansions.
940 $p^FOO 10, ^ );
941 })cpp",
942 // Macro arguments.
943 R"cpp(
944 int foo(int a, int b, int c);
945 int main() {
946 #define ID(X) X
947 ID(foo $p^( foo(10), ^ ))
948 })cpp"};
949
950 for (auto Test : Tests) {
951 Annotations Code(Test);
952 EXPECT_EQ(signatures(Code.code(), Code.point()).argListStart,
953 Code.point("p"))
954 << "Test source:" << Test;
955 }
956}
957
Haojian Wu061c73e2018-01-23 11:37:26 +0000958class IndexRequestCollector : public SymbolIndex {
959public:
960 bool
Sam McCalld1a7a372018-01-31 13:40:48 +0000961 fuzzyFind(const FuzzyFindRequest &Req,
Haojian Wu061c73e2018-01-23 11:37:26 +0000962 llvm::function_ref<void(const Symbol &)> Callback) const override {
963 Requests.push_back(Req);
Sam McCallab8e3932018-02-19 13:04:41 +0000964 return true;
Haojian Wu061c73e2018-01-23 11:37:26 +0000965 }
966
Eric Liu9ec459f2018-03-14 09:48:05 +0000967 void lookup(const LookupRequest &,
968 llvm::function_ref<void(const Symbol &)>) const override {}
969
Haojian Wu65ac3212018-08-06 13:14:32 +0000970 void findOccurrences(const OccurrencesRequest &Req,
971 llvm::function_ref<void(const SymbolOccurrence &)>
972 Callback) const override {}
973
Kirill Bobyrevfc890012018-08-24 09:12:54 +0000974 // This is incorrect, but IndexRequestCollector is not an actual index and it
975 // isn't used in production code.
976 size_t estimateMemoryUsage() const override { return 0; }
977
Eric Liu25d74e92018-08-24 11:23:56 +0000978 const std::vector<FuzzyFindRequest> consumeRequests() const {
979 auto Reqs = std::move(Requests);
980 Requests = {};
981 return Reqs;
982 }
Haojian Wu061c73e2018-01-23 11:37:26 +0000983
984private:
985 mutable std::vector<FuzzyFindRequest> Requests;
986};
987
988std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code) {
989 clangd::CodeCompleteOptions Opts;
990 IndexRequestCollector Requests;
991 Opts.Index = &Requests;
992 completions(Code, {}, Opts);
Eric Liu25d74e92018-08-24 11:23:56 +0000993 return Requests.consumeRequests();
Haojian Wu061c73e2018-01-23 11:37:26 +0000994}
995
996TEST(CompletionTest, UnqualifiedIdQuery) {
997 auto Requests = captureIndexRequests(R"cpp(
998 namespace std {}
999 using namespace std;
1000 namespace ns {
1001 void f() {
1002 vec^
1003 }
1004 }
1005 )cpp");
1006
1007 EXPECT_THAT(Requests,
1008 ElementsAre(Field(&FuzzyFindRequest::Scopes,
1009 UnorderedElementsAre("", "ns::", "std::"))));
1010}
1011
1012TEST(CompletionTest, ResolvedQualifiedIdQuery) {
1013 auto Requests = captureIndexRequests(R"cpp(
1014 namespace ns1 {}
1015 namespace ns2 {} // ignore
1016 namespace ns3 { namespace nns3 {} }
1017 namespace foo {
1018 using namespace ns1;
1019 using namespace ns3::nns3;
1020 }
1021 namespace ns {
1022 void f() {
1023 foo::^
1024 }
1025 }
1026 )cpp");
1027
1028 EXPECT_THAT(Requests,
1029 ElementsAre(Field(
1030 &FuzzyFindRequest::Scopes,
1031 UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::"))));
1032}
1033
1034TEST(CompletionTest, UnresolvedQualifierIdQuery) {
1035 auto Requests = captureIndexRequests(R"cpp(
1036 namespace a {}
1037 using namespace a;
1038 namespace ns {
1039 void f() {
1040 bar::^
1041 }
1042 } // namespace ns
1043 )cpp");
1044
1045 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1046 UnorderedElementsAre("bar::"))));
1047}
1048
1049TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
1050 auto Requests = captureIndexRequests(R"cpp(
1051 namespace a {}
1052 using namespace a;
1053 namespace ns {
1054 void f() {
1055 ::a::bar::^
1056 }
1057 } // namespace ns
1058 )cpp");
1059
1060 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1061 UnorderedElementsAre("a::bar::"))));
1062}
1063
1064TEST(CompletionTest, EmptyQualifiedQuery) {
1065 auto Requests = captureIndexRequests(R"cpp(
1066 namespace ns {
1067 void f() {
1068 ^
1069 }
1070 } // namespace ns
1071 )cpp");
1072
1073 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1074 UnorderedElementsAre("", "ns::"))));
1075}
1076
1077TEST(CompletionTest, GlobalQualifiedQuery) {
1078 auto Requests = captureIndexRequests(R"cpp(
1079 namespace ns {
1080 void f() {
1081 ::^
1082 }
1083 } // namespace ns
1084 )cpp");
1085
1086 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1087 UnorderedElementsAre(""))));
1088}
1089
Ilya Biryukova907ba42018-05-14 10:50:04 +00001090TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
1091 auto Completions = completions(
1092 R"cpp(
1093 struct Foo {
1094 int SomeNameOfField;
1095 typedef int SomeNameOfTypedefField;
1096 };
1097
1098 Foo::^)cpp",
1099 {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")});
1100
Sam McCalle746a2b2018-07-02 11:13:16 +00001101 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001102 AllOf(Contains(Labeled("SomeNameOfField")),
1103 Contains(Labeled("SomeNameOfTypedefField")),
1104 Not(Contains(Labeled("SomeNameInTheIndex")))));
1105}
1106
1107TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
1108 {
1109 auto Completions = completions(
1110 R"cpp(
1111 template <class T>
1112 void foo() {
1113 T::^
1114 }
1115 )cpp",
1116 {func("::SomeNameInTheIndex")});
1117
Sam McCalle746a2b2018-07-02 11:13:16 +00001118 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001119 Not(Contains(Labeled("SomeNameInTheIndex"))));
1120 }
1121
1122 {
1123 auto Completions = completions(
1124 R"cpp(
1125 template <class T>
1126 void foo() {
1127 T::template Y<int>::^
1128 }
1129 )cpp",
1130 {func("::SomeNameInTheIndex")});
1131
Sam McCalle746a2b2018-07-02 11:13:16 +00001132 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001133 Not(Contains(Labeled("SomeNameInTheIndex"))));
1134 }
1135
1136 {
1137 auto Completions = completions(
1138 R"cpp(
1139 template <class T>
1140 void foo() {
1141 T::foo::^
1142 }
1143 )cpp",
1144 {func("::SomeNameInTheIndex")});
1145
Sam McCalle746a2b2018-07-02 11:13:16 +00001146 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001147 Not(Contains(Labeled("SomeNameInTheIndex"))));
1148 }
1149}
1150
Sam McCallc18c2802018-06-15 11:06:29 +00001151TEST(CompletionTest, OverloadBundling) {
1152 clangd::CodeCompleteOptions Opts;
1153 Opts.BundleOverloads = true;
1154
1155 std::string Context = R"cpp(
1156 struct X {
1157 // Overload with int
1158 int a(int);
1159 // Overload with bool
1160 int a(bool);
1161 int b(float);
1162 };
1163 int GFuncC(int);
1164 int GFuncD(int);
1165 )cpp";
1166
1167 // Member completions are bundled.
Sam McCalle746a2b2018-07-02 11:13:16 +00001168 EXPECT_THAT(completions(Context + "int y = X().^", {}, Opts).Completions,
Sam McCallc18c2802018-06-15 11:06:29 +00001169 UnorderedElementsAre(Labeled("a(…)"), Labeled("b(float)")));
1170
1171 // Non-member completions are bundled, including index+sema.
1172 Symbol NoArgsGFunc = func("GFuncC");
1173 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001174 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
Sam McCallc18c2802018-06-15 11:06:29 +00001175 UnorderedElementsAre(Labeled("GFuncC(…)"), Labeled("GFuncD(int)")));
1176
1177 // Differences in header-to-insert suppress bundling.
Sam McCallc18c2802018-06-15 11:06:29 +00001178 std::string DeclFile = URI::createFile(testPath("foo")).toString();
1179 NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile;
Sam McCall2e5700f2018-08-31 13:55:01 +00001180 NoArgsGFunc.IncludeHeader = "<foo>";
Sam McCallc18c2802018-06-15 11:06:29 +00001181 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001182 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1183 UnorderedElementsAre(AllOf(Named("GFuncC"), InsertInclude("<foo>")),
1184 Labeled("GFuncC(int)"), Labeled("GFuncD(int)")));
Sam McCallc18c2802018-06-15 11:06:29 +00001185
1186 // Examine a bundled completion in detail.
Sam McCalle746a2b2018-07-02 11:13:16 +00001187 auto A =
1188 completions(Context + "int y = X().a^", {}, Opts).Completions.front();
1189 EXPECT_EQ(A.Name, "a");
1190 EXPECT_EQ(A.Signature, "(…)");
1191 EXPECT_EQ(A.BundleSize, 2u);
1192 EXPECT_EQ(A.Kind, CompletionItemKind::Method);
1193 EXPECT_EQ(A.ReturnType, "int"); // All overloads return int.
Sam McCallc18c2802018-06-15 11:06:29 +00001194 // For now we just return one of the doc strings arbitrarily.
Sam McCalle746a2b2018-07-02 11:13:16 +00001195 EXPECT_THAT(A.Documentation, AnyOf(HasSubstr("Overload with int"),
Sam McCallc18c2802018-06-15 11:06:29 +00001196 HasSubstr("Overload with bool")));
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001197 EXPECT_EQ(A.SnippetSuffix, "($0)");
Sam McCallc18c2802018-06-15 11:06:29 +00001198}
1199
Ilya Biryukov30b04b12018-05-28 09:54:51 +00001200TEST(CompletionTest, DocumentationFromChangedFileCrash) {
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001201 MockFSProvider FS;
1202 auto FooH = testPath("foo.h");
1203 auto FooCpp = testPath("foo.cpp");
1204 FS.Files[FooH] = R"cpp(
1205 // this is my documentation comment.
1206 int func();
1207 )cpp";
1208 FS.Files[FooCpp] = "";
1209
1210 MockCompilationDatabase CDB;
1211 IgnoreDiagnostics DiagConsumer;
1212 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1213
1214 Annotations Source(R"cpp(
1215 #include "foo.h"
1216 int func() {
1217 // This makes sure we have func from header in the AST.
1218 }
1219 int a = fun^
1220 )cpp");
1221 Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
1222 // We need to wait for preamble to build.
1223 ASSERT_TRUE(Server.blockUntilIdleForTest());
1224
1225 // Change the header file. Completion will reuse the old preamble!
1226 FS.Files[FooH] = R"cpp(
1227 int func();
1228 )cpp";
1229
1230 clangd::CodeCompleteOptions Opts;
1231 Opts.IncludeComments = true;
Sam McCalle746a2b2018-07-02 11:13:16 +00001232 CodeCompleteResult Completions =
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001233 cantFail(runCodeComplete(Server, FooCpp, Source.point(), Opts));
1234 // We shouldn't crash. Unfortunately, current workaround is to not produce
1235 // comments for symbols from headers.
Sam McCalle746a2b2018-07-02 11:13:16 +00001236 EXPECT_THAT(Completions.Completions,
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001237 Contains(AllOf(Not(IsDocumented()), Named("func"))));
1238}
1239
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001240TEST(CompletionTest, NonDocComments) {
1241 MockFSProvider FS;
1242 auto FooCpp = testPath("foo.cpp");
1243 FS.Files[FooCpp] = "";
1244
1245 MockCompilationDatabase CDB;
1246 IgnoreDiagnostics DiagConsumer;
1247 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1248
1249 Annotations Source(R"cpp(
Ilya Biryukovda8dd8b2018-06-27 09:47:20 +00001250 // We ignore namespace comments, for rationale see CodeCompletionStrings.h.
1251 namespace comments_ns {
1252 }
1253
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001254 // ------------------
1255 int comments_foo();
1256
1257 // A comment and a decl are separated by newlines.
1258 // Therefore, the comment shouldn't show up as doc comment.
1259
1260 int comments_bar();
1261
1262 // this comment should be in the results.
1263 int comments_baz();
1264
1265
1266 template <class T>
1267 struct Struct {
1268 int comments_qux();
1269 int comments_quux();
1270 };
1271
1272
1273 // This comment should not be there.
1274
1275 template <class T>
1276 int Struct<T>::comments_qux() {
1277 }
1278
1279 // This comment **should** be in results.
1280 template <class T>
1281 int Struct<T>::comments_quux() {
1282 int a = comments^;
1283 }
1284 )cpp");
Reid Kleckner80274b12018-06-18 18:55:10 +00001285 // FIXME: Auto-completion in a template requires disabling delayed template
1286 // parsing.
1287 CDB.ExtraClangFlags.push_back("-fno-delayed-template-parsing");
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001288 Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
Sam McCalle746a2b2018-07-02 11:13:16 +00001289 CodeCompleteResult Completions = cantFail(runCodeComplete(
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001290 Server, FooCpp, Source.point(), clangd::CodeCompleteOptions()));
1291
1292 // We should not get any of those comments in completion.
1293 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001294 Completions.Completions,
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001295 UnorderedElementsAre(AllOf(Not(IsDocumented()), Named("comments_foo")),
1296 AllOf(IsDocumented(), Named("comments_baz")),
1297 AllOf(IsDocumented(), Named("comments_quux")),
Ilya Biryukovda8dd8b2018-06-27 09:47:20 +00001298 AllOf(Not(IsDocumented()), Named("comments_ns")),
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001299 // FIXME(ibiryukov): the following items should have
1300 // empty documentation, since they are separated from
1301 // a comment with an empty line. Unfortunately, I
1302 // couldn't make Sema tests pass if we ignore those.
1303 AllOf(IsDocumented(), Named("comments_bar")),
1304 AllOf(IsDocumented(), Named("comments_qux"))));
1305}
1306
Ilya Biryukov981a35d2018-05-28 12:11:37 +00001307TEST(CompletionTest, CompleteOnInvalidLine) {
1308 auto FooCpp = testPath("foo.cpp");
1309
1310 MockCompilationDatabase CDB;
1311 IgnoreDiagnostics DiagConsumer;
1312 MockFSProvider FS;
1313 FS.Files[FooCpp] = "// empty file";
1314
1315 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1316 // Run completion outside the file range.
1317 Position Pos;
1318 Pos.line = 100;
1319 Pos.character = 0;
1320 EXPECT_THAT_EXPECTED(
1321 runCodeComplete(Server, FooCpp, Pos, clangd::CodeCompleteOptions()),
1322 Failed());
1323}
1324
Eric Liu7ad16962018-06-22 10:46:59 +00001325TEST(CompletionTest, QualifiedNames) {
1326 auto Results = completions(
1327 R"cpp(
1328 namespace ns { int local; void both(); }
1329 void f() { ::ns::^ }
1330 )cpp",
1331 {func("ns::both"), cls("ns::Index")});
1332 // We get results from both index and sema, with no duplicates.
Sam McCalle746a2b2018-07-02 11:13:16 +00001333 EXPECT_THAT(
1334 Results.Completions,
1335 UnorderedElementsAre(Scope("ns::"), Scope("ns::"), Scope("ns::")));
1336}
1337
1338TEST(CompletionTest, Render) {
1339 CodeCompletion C;
1340 C.Name = "x";
1341 C.Signature = "(bool) const";
1342 C.SnippetSuffix = "(${0:bool})";
1343 C.ReturnType = "int";
1344 C.RequiredQualifier = "Foo::";
1345 C.Scope = "ns::Foo::";
1346 C.Documentation = "This is x().";
1347 C.Header = "\"foo.h\"";
1348 C.Kind = CompletionItemKind::Method;
1349 C.Score.Total = 1.0;
Sam McCall4e5742a2018-07-06 11:50:49 +00001350 C.Origin = SymbolOrigin::AST | SymbolOrigin::Static;
Sam McCalle746a2b2018-07-02 11:13:16 +00001351
1352 CodeCompleteOptions Opts;
1353 Opts.IncludeIndicator.Insert = "^";
1354 Opts.IncludeIndicator.NoInsert = "";
1355 Opts.EnableSnippets = false;
1356
1357 auto R = C.render(Opts);
1358 EXPECT_EQ(R.label, "Foo::x(bool) const");
1359 EXPECT_EQ(R.insertText, "Foo::x");
1360 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
1361 EXPECT_EQ(R.filterText, "x");
1362 EXPECT_EQ(R.detail, "int\n\"foo.h\"");
1363 EXPECT_EQ(R.documentation, "This is x().");
1364 EXPECT_THAT(R.additionalTextEdits, IsEmpty());
Sam McCalle746a2b2018-07-02 11:13:16 +00001365 EXPECT_EQ(R.sortText, sortText(1.0, "x"));
1366
1367 Opts.EnableSnippets = true;
1368 R = C.render(Opts);
1369 EXPECT_EQ(R.insertText, "Foo::x(${0:bool})");
1370 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
1371
1372 C.HeaderInsertion.emplace();
1373 R = C.render(Opts);
1374 EXPECT_EQ(R.label, "^Foo::x(bool) const");
1375 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
1376
Sam McCall2161ec72018-07-05 06:20:41 +00001377 Opts.ShowOrigins = true;
1378 R = C.render(Opts);
1379 EXPECT_EQ(R.label, "^[AS]Foo::x(bool) const");
1380
Sam McCalle746a2b2018-07-02 11:13:16 +00001381 C.BundleSize = 2;
1382 R = C.render(Opts);
1383 EXPECT_EQ(R.detail, "[2 overloads]\n\"foo.h\"");
Eric Liu7ad16962018-06-22 10:46:59 +00001384}
Ilya Biryukov981a35d2018-05-28 12:11:37 +00001385
Eric Liu485074f2018-07-11 13:15:31 +00001386TEST(CompletionTest, IgnoreRecoveryResults) {
1387 auto Results = completions(
1388 R"cpp(
1389 namespace ns { int NotRecovered() { return 0; } }
1390 void f() {
1391 // Sema enters recovery mode first and then normal mode.
1392 if (auto x = ns::NotRecover^)
1393 }
1394 )cpp");
1395 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("NotRecovered")));
1396}
1397
Eric Liuf433c2d2018-07-18 15:31:14 +00001398TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
1399 auto Results = completions(
1400 R"cpp(
1401 namespace ns {
1402 class X { public: X(); int x_; };
1403 X::X() : x_^(0) {}
1404 }
1405 )cpp");
1406 EXPECT_THAT(Results.Completions,
1407 UnorderedElementsAre(AllOf(Scope("ns::X::"), Named("x_"))));
1408}
1409
Eric Liu5d2a8072018-07-23 10:56:37 +00001410TEST(CompletionTest, CodeCompletionContext) {
1411 auto Results = completions(
1412 R"cpp(
1413 namespace ns {
1414 class X { public: X(); int x_; };
1415 void f() {
1416 X x;
1417 x.^;
1418 }
1419 }
1420 )cpp");
1421
1422 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
1423}
1424
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001425TEST(CompletionTest, FixItForArrowToDot) {
1426 MockFSProvider FS;
1427 MockCompilationDatabase CDB;
1428 IgnoreDiagnostics DiagConsumer;
1429 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1430
1431 CodeCompleteOptions Opts;
1432 Opts.IncludeFixIts = true;
1433 Annotations TestCode(
1434 R"cpp(
1435 class Auxilary {
1436 public:
1437 void AuxFunction();
1438 };
1439 class ClassWithPtr {
1440 public:
1441 void MemberFunction();
1442 Auxilary* operator->() const;
1443 Auxilary* Aux;
1444 };
1445 void f() {
1446 ClassWithPtr x;
1447 x[[->]]^;
1448 }
1449 )cpp");
1450 auto Results =
1451 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1452 EXPECT_EQ(Results.Completions.size(), 3u);
1453
1454 TextEdit ReplacementEdit;
1455 ReplacementEdit.range = TestCode.range();
1456 ReplacementEdit.newText = ".";
1457 for (const auto &C : Results.Completions) {
1458 EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction");
Haojian Wu1793bc92018-08-10 08:34:16 +00001459 if (!C.FixIts.empty()) {
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001460 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
Haojian Wu1793bc92018-08-10 08:34:16 +00001461 }
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001462 }
1463}
1464
1465TEST(CompletionTest, FixItForDotToArrow) {
1466 MockFSProvider FS;
1467 MockCompilationDatabase CDB;
1468 IgnoreDiagnostics DiagConsumer;
1469 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1470
1471 CodeCompleteOptions Opts;
1472 Opts.IncludeFixIts = true;
1473 Annotations TestCode(
1474 R"cpp(
1475 class Auxilary {
1476 public:
1477 void AuxFunction();
1478 };
1479 class ClassWithPtr {
1480 public:
1481 void MemberFunction();
1482 Auxilary* operator->() const;
1483 Auxilary* Aux;
1484 };
1485 void f() {
1486 ClassWithPtr x;
1487 x[[.]]^;
1488 }
1489 )cpp");
1490 auto Results =
1491 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1492 EXPECT_EQ(Results.Completions.size(), 3u);
1493
1494 TextEdit ReplacementEdit;
1495 ReplacementEdit.range = TestCode.range();
1496 ReplacementEdit.newText = "->";
1497 for (const auto &C : Results.Completions) {
1498 EXPECT_TRUE(C.FixIts.empty() || C.Name == "AuxFunction");
1499 if (!C.FixIts.empty()) {
1500 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
1501 }
1502 }
1503}
1504
Kadir Cetinkayaa9c9d002018-08-13 08:23:01 +00001505TEST(CompletionTest, RenderWithFixItMerged) {
1506 TextEdit FixIt;
1507 FixIt.range.end.character = 5;
1508 FixIt.newText = "->";
1509
1510 CodeCompletion C;
1511 C.Name = "x";
1512 C.RequiredQualifier = "Foo::";
1513 C.FixIts = {FixIt};
1514 C.CompletionTokenRange.start.character = 5;
1515
1516 CodeCompleteOptions Opts;
1517 Opts.IncludeFixIts = true;
1518
1519 auto R = C.render(Opts);
1520 EXPECT_TRUE(R.textEdit);
1521 EXPECT_EQ(R.textEdit->newText, "->Foo::x");
1522 EXPECT_TRUE(R.additionalTextEdits.empty());
1523}
1524
1525TEST(CompletionTest, RenderWithFixItNonMerged) {
1526 TextEdit FixIt;
1527 FixIt.range.end.character = 4;
1528 FixIt.newText = "->";
1529
1530 CodeCompletion C;
1531 C.Name = "x";
1532 C.RequiredQualifier = "Foo::";
1533 C.FixIts = {FixIt};
1534 C.CompletionTokenRange.start.character = 5;
1535
1536 CodeCompleteOptions Opts;
1537 Opts.IncludeFixIts = true;
1538
1539 auto R = C.render(Opts);
1540 EXPECT_TRUE(R.textEdit);
1541 EXPECT_EQ(R.textEdit->newText, "Foo::x");
1542 EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
1543}
1544
1545TEST(CompletionTest, CompletionTokenRange) {
1546 MockFSProvider FS;
1547 MockCompilationDatabase CDB;
1548 IgnoreDiagnostics DiagConsumer;
1549 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1550
1551 constexpr const char *TestCodes[] = {
1552 R"cpp(
1553 class Auxilary {
1554 public:
1555 void AuxFunction();
1556 };
1557 void f() {
1558 Auxilary x;
1559 x.[[Aux]]^;
1560 }
1561 )cpp",
1562 R"cpp(
1563 class Auxilary {
1564 public:
1565 void AuxFunction();
1566 };
1567 void f() {
1568 Auxilary x;
1569 x.[[]]^;
1570 }
1571 )cpp"};
1572 for (const auto &Text : TestCodes) {
1573 Annotations TestCode(Text);
1574 auto Results = completions(Server, TestCode.code(), TestCode.point());
1575
1576 EXPECT_EQ(Results.Completions.size(), 1u);
1577 EXPECT_THAT(Results.Completions.front().CompletionTokenRange, TestCode.range());
1578 }
1579}
1580
Kadir Cetinkayae486e372018-08-13 08:40:05 +00001581TEST(SignatureHelpTest, OverloadsOrdering) {
1582 const auto Results = signatures(R"cpp(
1583 void foo(int x);
1584 void foo(int x, float y);
1585 void foo(float x, int y);
1586 void foo(float x, float y);
1587 void foo(int x, int y = 0);
1588 int main() { foo(^); }
1589 )cpp");
1590 EXPECT_THAT(
1591 Results.signatures,
1592 ElementsAre(
1593 Sig("foo(int x) -> void", {"int x"}),
1594 Sig("foo(int x, int y = 0) -> void", {"int x", "int y = 0"}),
1595 Sig("foo(float x, int y) -> void", {"float x", "int y"}),
1596 Sig("foo(int x, float y) -> void", {"int x", "float y"}),
1597 Sig("foo(float x, float y) -> void", {"float x", "float y"})));
1598 // We always prefer the first signature.
1599 EXPECT_EQ(0, Results.activeSignature);
1600 EXPECT_EQ(0, Results.activeParameter);
1601}
1602
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001603TEST(SignatureHelpTest, InstantiatedSignatures) {
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001604 StringRef Sig0 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001605 template <class T>
1606 void foo(T, T, T);
1607
1608 int main() {
1609 foo<int>(^);
1610 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001611 )cpp";
1612
1613 EXPECT_THAT(signatures(Sig0).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001614 ElementsAre(Sig("foo(T, T, T) -> void", {"T", "T", "T"})));
1615
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001616 StringRef Sig1 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001617 template <class T>
1618 void foo(T, T, T);
1619
1620 int main() {
1621 foo(10, ^);
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001622 })cpp";
1623
1624 EXPECT_THAT(signatures(Sig1).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001625 ElementsAre(Sig("foo(T, T, T) -> void", {"T", "T", "T"})));
1626
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001627 StringRef Sig2 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001628 template <class ...T>
1629 void foo(T...);
1630
1631 int main() {
1632 foo<int>(^);
1633 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001634 )cpp";
1635
1636 EXPECT_THAT(signatures(Sig2).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001637 ElementsAre(Sig("foo(T...) -> void", {"T..."})));
1638
1639 // It is debatable whether we should substitute the outer template parameter
1640 // ('T') in that case. Currently we don't substitute it in signature help, but
1641 // do substitute in code complete.
1642 // FIXME: make code complete and signature help consistent, figure out which
1643 // way is better.
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001644 StringRef Sig3 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001645 template <class T>
1646 struct X {
1647 template <class U>
1648 void foo(T, U);
1649 };
1650
1651 int main() {
1652 X<int>().foo<double>(^)
1653 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001654 )cpp";
1655
1656 EXPECT_THAT(signatures(Sig3).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001657 ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
1658}
1659
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001660TEST(SignatureHelpTest, IndexDocumentation) {
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001661 Symbol Foo0 = sym("foo", index::SymbolKind::Function, "@F@\\0#");
Sam McCall2e5700f2018-08-31 13:55:01 +00001662 Foo0.Documentation = "Doc from the index";
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001663 Symbol Foo1 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#");
Sam McCall2e5700f2018-08-31 13:55:01 +00001664 Foo1.Documentation = "Doc from the index";
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001665 Symbol Foo2 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#I#");
1666
Simon Pilgrim24d34922018-08-17 10:40:05 +00001667 StringRef Sig0 = R"cpp(
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001668 int foo();
1669 int foo(double);
1670
1671 void test() {
1672 foo(^);
1673 }
Simon Pilgrim24d34922018-08-17 10:40:05 +00001674 )cpp";
1675
1676 EXPECT_THAT(
1677 signatures(Sig0, {Foo0}).signatures,
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001678 ElementsAre(AllOf(Sig("foo() -> int", {}), SigDoc("Doc from the index")),
1679 AllOf(Sig("foo(double) -> int", {"double"}), SigDoc(""))));
1680
Simon Pilgrim24d34922018-08-17 10:40:05 +00001681 StringRef Sig1 = R"cpp(
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001682 int foo();
1683 // Overriden doc from sema
1684 int foo(int);
1685 // Doc from sema
1686 int foo(int, int);
1687
1688 void test() {
1689 foo(^);
1690 }
Simon Pilgrim24d34922018-08-17 10:40:05 +00001691 )cpp";
1692
1693 EXPECT_THAT(
1694 signatures(Sig1, {Foo0, Foo1, Foo2}).signatures,
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001695 ElementsAre(AllOf(Sig("foo() -> int", {}), SigDoc("Doc from the index")),
1696 AllOf(Sig("foo(int) -> int", {"int"}),
1697 SigDoc("Overriden doc from sema")),
1698 AllOf(Sig("foo(int, int) -> int", {"int", "int"}),
1699 SigDoc("Doc from sema"))));
1700}
1701
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001702TEST(CompletionTest, CompletionFunctionArgsDisabled) {
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001703 CodeCompleteOptions Opts;
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001704 Opts.EnableSnippets = true;
1705 Opts.EnableFunctionArgSnippets = false;
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001706 const std::string Header =
1707 R"cpp(
1708 void xfoo();
1709 void xfoo(int x, int y);
1710 void xbar();
1711 void f() {
1712 )cpp";
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001713 {
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001714 auto Results = completions(Header + "\nxfo^", {}, Opts);
1715 EXPECT_THAT(
1716 Results.Completions,
1717 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("()")),
1718 AllOf(Named("xfoo"), SnippetSuffix("($0)"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001719 }
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001720 {
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001721 auto Results = completions(Header + "\nxba^", {}, Opts);
1722 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
1723 Named("xbar"), SnippetSuffix("()"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001724 }
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001725 {
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001726 Opts.BundleOverloads = true;
1727 auto Results = completions(Header + "\nxfo^", {}, Opts);
1728 EXPECT_THAT(
1729 Results.Completions,
1730 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("($0)"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001731 }
1732}
1733
Kadir Cetinkayaf8b85a32018-08-23 13:14:50 +00001734TEST(CompletionTest, SuggestOverrides) {
1735 constexpr const char *const Text(R"cpp(
1736 class A {
1737 public:
1738 virtual void vfunc(bool param);
1739 virtual void vfunc(bool param, int p);
1740 void func(bool param);
1741 };
1742 class B : public A {
1743 virtual void ttt(bool param) const;
1744 void vfunc(bool param, int p) override;
1745 };
1746 class C : public B {
1747 public:
1748 void vfunc(bool param) override;
1749 ^
1750 };
1751 )cpp");
1752 const auto Results = completions(Text);
1753 EXPECT_THAT(Results.Completions,
1754 AllOf(Contains(Labeled("void vfunc(bool param, int p) override")),
1755 Contains(Labeled("void ttt(bool param) const override")),
1756 Not(Contains(Labeled("void vfunc(bool param) override")))));
1757}
1758
Eric Liu25d74e92018-08-24 11:23:56 +00001759TEST(SpeculateCompletionFilter, Filters) {
1760 Annotations F(R"cpp($bof^
1761 $bol^
1762 ab$ab^
1763 x.ab$dot^
1764 x.$dotempty^
1765 x::ab$scoped^
1766 x::$scopedempty^
1767
1768 )cpp");
1769 auto speculate = [&](StringRef PointName) {
1770 auto Filter = speculateCompletionFilter(F.code(), F.point(PointName));
1771 assert(Filter);
1772 return *Filter;
1773 };
1774 EXPECT_EQ(speculate("bof"), "");
1775 EXPECT_EQ(speculate("bol"), "");
1776 EXPECT_EQ(speculate("ab"), "ab");
1777 EXPECT_EQ(speculate("dot"), "ab");
1778 EXPECT_EQ(speculate("dotempty"), "");
1779 EXPECT_EQ(speculate("scoped"), "ab");
1780 EXPECT_EQ(speculate("scopedempty"), "");
1781}
1782
1783TEST(CompletionTest, EnableSpeculativeIndexRequest) {
1784 MockFSProvider FS;
1785 MockCompilationDatabase CDB;
1786 IgnoreDiagnostics DiagConsumer;
1787 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1788
1789 auto File = testPath("foo.cpp");
1790 Annotations Test(R"cpp(
1791 namespace ns1 { int abc; }
1792 namespace ns2 { int abc; }
1793 void f() { ns1::ab$1^; ns1::ab$2^; }
1794 void f() { ns2::ab$3^; }
1795 )cpp");
1796 runAddDocument(Server, File, Test.code());
1797 clangd::CodeCompleteOptions Opts = {};
1798
1799 IndexRequestCollector Requests;
1800 Opts.Index = &Requests;
1801 Opts.SpeculativeIndexRequest = true;
1802
1803 auto CompleteAtPoint = [&](StringRef P) {
1804 cantFail(runCodeComplete(Server, File, Test.point(P), Opts));
1805 // Sleep for a while to make sure asynchronous call (if applicable) is also
1806 // triggered before callback is invoked.
1807 std::this_thread::sleep_for(std::chrono::milliseconds(100));
1808 };
1809
1810 CompleteAtPoint("1");
1811 auto Reqs1 = Requests.consumeRequests();
1812 ASSERT_EQ(Reqs1.size(), 1u);
1813 EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre("ns1::"));
1814
1815 CompleteAtPoint("2");
1816 auto Reqs2 = Requests.consumeRequests();
1817 // Speculation succeeded. Used speculative index result.
1818 ASSERT_EQ(Reqs2.size(), 1u);
1819 EXPECT_EQ(Reqs2[0], Reqs1[0]);
1820
1821 CompleteAtPoint("3");
1822 // Speculation failed. Sent speculative index request and the new index
1823 // request after sema.
1824 auto Reqs3 = Requests.consumeRequests();
1825 ASSERT_EQ(Reqs3.size(), 2u);
1826}
1827
Sam McCall9aad25f2017-12-05 07:20:26 +00001828} // namespace
1829} // namespace clangd
1830} // namespace clang