blob: e6720a31f7d54944715edf84853cef3f752cf1b6 [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 Liu83f63e42018-09-03 10:18:21 +000058MATCHER_P(HasInclude, IncludeHeader, "") {
59 return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader;
Eric Liu63f419a2018-05-15 15:29:32 +000060}
Eric Liu83f63e42018-09-03 10:18:21 +000061MATCHER_P(InsertInclude, IncludeHeader, "") {
62 return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader &&
63 bool(arg.Includes[0].Insertion);
64}
65MATCHER(InsertInclude, "") {
66 return !arg.Includes.empty() && bool(arg.Includes[0].Insertion);
67}
Sam McCalle746a2b2018-07-02 11:13:16 +000068MATCHER_P(SnippetSuffix, Text, "") { return arg.SnippetSuffix == Text; }
Sam McCall2161ec72018-07-05 06:20:41 +000069MATCHER_P(Origin, OriginSet, "") { return arg.Origin == OriginSet; }
Eric Liu63f419a2018-05-15 15:29:32 +000070
Sam McCallf6ae3232017-12-05 20:11:29 +000071// Shorthand for Contains(Named(Name)).
Sam McCalle746a2b2018-07-02 11:13:16 +000072Matcher<const std::vector<CodeCompletion> &> Has(std::string Name) {
Sam McCallf6ae3232017-12-05 20:11:29 +000073 return Contains(Named(std::move(Name)));
74}
Sam McCalle746a2b2018-07-02 11:13:16 +000075Matcher<const std::vector<CodeCompletion> &> Has(std::string Name,
Sam McCall44fdcec22017-12-08 15:00:59 +000076 CompletionItemKind K) {
77 return Contains(AllOf(Named(std::move(Name)), Kind(K)));
Sam McCallf6ae3232017-12-05 20:11:29 +000078}
Sam McCalle746a2b2018-07-02 11:13:16 +000079MATCHER(IsDocumented, "") { return !arg.Documentation.empty(); }
Eric Liu6df66002018-09-06 18:52:26 +000080MATCHER(Deprecated, "") { return arg.Deprecated; }
Sam McCall9aad25f2017-12-05 07:20:26 +000081
Sam McCalla15c2d62018-01-18 09:27:56 +000082std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol> Symbols) {
83 SymbolSlab::Builder Slab;
84 for (const auto &Sym : Symbols)
85 Slab.insert(Sym);
Sam McCallb0138312018-09-04 14:39:56 +000086 return MemIndex::build(std::move(Slab).build(), RefSlab());
Sam McCalla15c2d62018-01-18 09:27:56 +000087}
88
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +000089CodeCompleteResult completions(ClangdServer &Server, StringRef TestCode,
90 Position point,
91 std::vector<Symbol> IndexSymbols = {},
92 clangd::CodeCompleteOptions Opts = {}) {
93 std::unique_ptr<SymbolIndex> OverrideIndex;
94 if (!IndexSymbols.empty()) {
95 assert(!Opts.Index && "both Index and IndexSymbols given!");
96 OverrideIndex = memIndex(std::move(IndexSymbols));
97 Opts.Index = OverrideIndex.get();
98 }
99
100 auto File = testPath("foo.cpp");
101 runAddDocument(Server, File, TestCode);
102 auto CompletionList = cantFail(runCodeComplete(Server, File, point, Opts));
103 return CompletionList;
104}
105
Sam McCalle746a2b2018-07-02 11:13:16 +0000106CodeCompleteResult completions(ClangdServer &Server, StringRef Text,
107 std::vector<Symbol> IndexSymbols = {},
108 clangd::CodeCompleteOptions Opts = {}) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000109 std::unique_ptr<SymbolIndex> OverrideIndex;
110 if (!IndexSymbols.empty()) {
111 assert(!Opts.Index && "both Index and IndexSymbols given!");
112 OverrideIndex = memIndex(std::move(IndexSymbols));
113 Opts.Index = OverrideIndex.get();
114 }
115
Sam McCallc1568062018-02-16 09:41:43 +0000116 auto File = testPath("foo.cpp");
Sam McCall328cbdb2017-12-20 16:06:05 +0000117 Annotations Test(Text);
Sam McCall7363a2f2018-03-05 17:28:54 +0000118 runAddDocument(Server, File, Test.code());
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000119 auto CompletionList =
120 cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Ilya Biryukov5a5e1ca2017-12-29 14:59:22 +0000121 return CompletionList;
Sam McCall9aad25f2017-12-05 07:20:26 +0000122}
123
Eric Liu63f419a2018-05-15 15:29:32 +0000124// Builds a server and runs code completion.
125// If IndexSymbols is non-empty, an index will be built and passed to opts.
Sam McCalle746a2b2018-07-02 11:13:16 +0000126CodeCompleteResult completions(StringRef Text,
127 std::vector<Symbol> IndexSymbols = {},
128 clangd::CodeCompleteOptions Opts = {}) {
Eric Liu63f419a2018-05-15 15:29:32 +0000129 MockFSProvider FS;
130 MockCompilationDatabase CDB;
131 IgnoreDiagnostics DiagConsumer;
132 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
133 return completions(Server, Text, std::move(IndexSymbols), std::move(Opts));
134}
135
Sam McCall545a20d2018-01-19 14:34:02 +0000136std::string replace(StringRef Haystack, StringRef Needle, StringRef Repl) {
137 std::string Result;
138 raw_string_ostream OS(Result);
139 std::pair<StringRef, StringRef> Split;
140 for (Split = Haystack.split(Needle); !Split.second.empty();
141 Split = Split.first.split(Needle))
142 OS << Split.first << Repl;
143 Result += Split.first;
144 OS.flush();
145 return Result;
146}
147
Sam McCalla15c2d62018-01-18 09:27:56 +0000148// Helpers to produce fake index symbols for memIndex() or completions().
Sam McCall545a20d2018-01-19 14:34:02 +0000149// USRFormat is a regex replacement string for the unqualified part of the USR.
150Symbol sym(StringRef QName, index::SymbolKind Kind, StringRef USRFormat) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000151 Symbol Sym;
Sam McCall545a20d2018-01-19 14:34:02 +0000152 std::string USR = "c:"; // We synthesize a few simple cases of USRs by hand!
Sam McCalla15c2d62018-01-18 09:27:56 +0000153 size_t Pos = QName.rfind("::");
154 if (Pos == llvm::StringRef::npos) {
155 Sym.Name = QName;
156 Sym.Scope = "";
157 } else {
158 Sym.Name = QName.substr(Pos + 2);
Sam McCall8b2faee2018-01-19 22:18:21 +0000159 Sym.Scope = QName.substr(0, Pos + 2);
160 USR += "@N@" + replace(QName.substr(0, Pos), "::", "@N@"); // ns:: -> @N@ns
Sam McCalla15c2d62018-01-18 09:27:56 +0000161 }
Sam McCall545a20d2018-01-19 14:34:02 +0000162 USR += Regex("^.*$").sub(USRFormat, Sym.Name); // e.g. func -> @F@func#
163 Sym.ID = SymbolID(USR);
Sam McCalla15c2d62018-01-18 09:27:56 +0000164 Sym.SymInfo.Kind = Kind;
Eric Liu6df66002018-09-06 18:52:26 +0000165 Sym.Flags |= Symbol::IndexedForCodeCompletion;
Sam McCall2161ec72018-07-05 06:20:41 +0000166 Sym.Origin = SymbolOrigin::Static;
Sam McCalla15c2d62018-01-18 09:27:56 +0000167 return Sym;
168}
Sam McCall545a20d2018-01-19 14:34:02 +0000169Symbol func(StringRef Name) { // Assumes the function has no args.
170 return sym(Name, index::SymbolKind::Function, "@F@\\0#"); // no args
171}
172Symbol cls(StringRef Name) {
Eric Liu9b3cba72018-05-30 09:03:39 +0000173 return sym(Name, index::SymbolKind::Class, "@S@\\0");
Sam McCall545a20d2018-01-19 14:34:02 +0000174}
175Symbol var(StringRef Name) {
176 return sym(Name, index::SymbolKind::Variable, "@\\0");
177}
Sam McCalldc8abc42018-05-03 14:53:02 +0000178Symbol ns(StringRef Name) {
179 return sym(Name, index::SymbolKind::Namespace, "@N@\\0");
180}
181Symbol withReferences(int N, Symbol S) {
182 S.References = N;
183 return S;
184}
Sam McCalla15c2d62018-01-18 09:27:56 +0000185
Sam McCallf6ae3232017-12-05 20:11:29 +0000186TEST(CompletionTest, Limit) {
187 clangd::CodeCompleteOptions Opts;
188 Opts.Limit = 2;
189 auto Results = completions(R"cpp(
Sam McCall9aad25f2017-12-05 07:20:26 +0000190struct ClassWithMembers {
191 int AAA();
192 int BBB();
193 int CCC();
194}
Sam McCallf6ae3232017-12-05 20:11:29 +0000195int main() { ClassWithMembers().^ }
Sam McCall9aad25f2017-12-05 07:20:26 +0000196 )cpp",
Sam McCalla15c2d62018-01-18 09:27:56 +0000197 /*IndexSymbols=*/{}, Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000198
Sam McCalle746a2b2018-07-02 11:13:16 +0000199 EXPECT_TRUE(Results.HasMore);
200 EXPECT_THAT(Results.Completions, ElementsAre(Named("AAA"), Named("BBB")));
Sam McCall9aad25f2017-12-05 07:20:26 +0000201}
202
Sam McCallf6ae3232017-12-05 20:11:29 +0000203TEST(CompletionTest, Filter) {
204 std::string Body = R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000205 #define MotorCar
206 int Car;
Sam McCall9aad25f2017-12-05 07:20:26 +0000207 struct S {
208 int FooBar;
209 int FooBaz;
210 int Qux;
211 };
212 )cpp";
Sam McCall8b2dcc12018-06-14 13:50:30 +0000213
214 // Only items matching the fuzzy query are returned.
Sam McCalle746a2b2018-07-02 11:13:16 +0000215 EXPECT_THAT(completions(Body + "int main() { S().Foba^ }").Completions,
Sam McCall8b2dcc12018-06-14 13:50:30 +0000216 AllOf(Has("FooBar"), Has("FooBaz"), Not(Has("Qux"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000217
Sam McCall8b2dcc12018-06-14 13:50:30 +0000218 // Macros require prefix match.
Sam McCalle746a2b2018-07-02 11:13:16 +0000219 EXPECT_THAT(completions(Body + "int main() { C^ }").Completions,
Sam McCall8b2dcc12018-06-14 13:50:30 +0000220 AllOf(Has("Car"), Not(Has("MotorCar"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000221}
222
Sam McCallf6ae3232017-12-05 20:11:29 +0000223void TestAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000224 auto Results = completions(
225 R"cpp(
226 #define MACRO X
Sam McCall9aad25f2017-12-05 07:20:26 +0000227
Sam McCall44fdcec22017-12-08 15:00:59 +0000228 int global_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000229
Sam McCall44fdcec22017-12-08 15:00:59 +0000230 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000231
Sam McCall44fdcec22017-12-08 15:00:59 +0000232 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000233
Sam McCall44fdcec22017-12-08 15:00:59 +0000234 struct ClassWithMembers {
235 /// Doc for method.
236 int method();
Sam McCall9aad25f2017-12-05 07:20:26 +0000237
Sam McCall44fdcec22017-12-08 15:00:59 +0000238 int field;
239 private:
240 int private_field;
241 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000242
Sam McCall44fdcec22017-12-08 15:00:59 +0000243 int test() {
244 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000245
Sam McCall44fdcec22017-12-08 15:00:59 +0000246 /// Doc for local_var.
247 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000248
Sam McCall44fdcec22017-12-08 15:00:59 +0000249 ClassWithMembers().^
250 }
251 )cpp",
Sam McCall545a20d2018-01-19 14:34:02 +0000252 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000253
Sam McCallf6ae3232017-12-05 20:11:29 +0000254 // Class members. The only items that must be present in after-dot
255 // completion.
Sam McCalle746a2b2018-07-02 11:13:16 +0000256 EXPECT_THAT(Results.Completions,
257 AllOf(Has("method"), Has("field"), Not(Has("ClassWithMembers")),
Sam McCall4caa8512018-06-07 12:49:17 +0000258 Not(Has("operator=")), Not(Has("~ClassWithMembers"))));
Sam McCalle746a2b2018-07-02 11:13:16 +0000259 EXPECT_IFF(Opts.IncludeIneligibleResults, Results.Completions,
Sam McCall44fdcec22017-12-08 15:00:59 +0000260 Has("private_field"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000261 // Global items.
Sam McCall545a20d2018-01-19 14:34:02 +0000262 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +0000263 Results.Completions,
Sam McCall545a20d2018-01-19 14:34:02 +0000264 Not(AnyOf(Has("global_var"), Has("index_var"), Has("global_func"),
265 Has("global_func()"), Has("index_func"), Has("GlobalClass"),
266 Has("IndexClass"), Has("MACRO"), Has("LocalClass"))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000267 // There should be no code patterns (aka snippets) in after-dot
268 // completion. At least there aren't any we're aware of.
Sam McCalle746a2b2018-07-02 11:13:16 +0000269 EXPECT_THAT(Results.Completions,
270 Not(Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000271 // Check documentation.
Sam McCalle746a2b2018-07-02 11:13:16 +0000272 EXPECT_IFF(Opts.IncludeComments, Results.Completions,
273 Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000274}
Sam McCall9aad25f2017-12-05 07:20:26 +0000275
Sam McCallf6ae3232017-12-05 20:11:29 +0000276void TestGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000277 auto Results = completions(
278 R"cpp(
279 #define MACRO X
Sam McCall9aad25f2017-12-05 07:20:26 +0000280
Sam McCall44fdcec22017-12-08 15:00:59 +0000281 int global_var;
282 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000283
Sam McCall44fdcec22017-12-08 15:00:59 +0000284 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000285
Sam McCall44fdcec22017-12-08 15:00:59 +0000286 struct ClassWithMembers {
287 /// Doc for method.
288 int method();
289 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000290
Sam McCall44fdcec22017-12-08 15:00:59 +0000291 int test() {
292 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000293
Sam McCall44fdcec22017-12-08 15:00:59 +0000294 /// Doc for local_var.
295 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000296
Sam McCall44fdcec22017-12-08 15:00:59 +0000297 ^
298 }
299 )cpp",
Sam McCall545a20d2018-01-19 14:34:02 +0000300 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
Sam McCallf6ae3232017-12-05 20:11:29 +0000301
302 // Class members. Should never be present in global completions.
Sam McCalle746a2b2018-07-02 11:13:16 +0000303 EXPECT_THAT(Results.Completions,
Sam McCallf6ae3232017-12-05 20:11:29 +0000304 Not(AnyOf(Has("method"), Has("method()"), Has("field"))));
305 // Global items.
Sam McCalle746a2b2018-07-02 11:13:16 +0000306 EXPECT_THAT(Results.Completions,
307 AllOf(Has("global_var"), Has("index_var"), Has("global_func"),
Sam McCall545a20d2018-01-19 14:34:02 +0000308 Has("index_func" /* our fake symbol doesn't include () */),
309 Has("GlobalClass"), Has("IndexClass")));
Sam McCallf6ae3232017-12-05 20:11:29 +0000310 // A macro.
Sam McCalle746a2b2018-07-02 11:13:16 +0000311 EXPECT_IFF(Opts.IncludeMacros, Results.Completions, Has("MACRO"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000312 // Local items. Must be present always.
Sam McCalle746a2b2018-07-02 11:13:16 +0000313 EXPECT_THAT(Results.Completions,
Ilya Biryukov9b5ffc22017-12-12 12:56:46 +0000314 AllOf(Has("local_var"), Has("LocalClass"),
315 Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000316 // Check documentation.
Sam McCalle746a2b2018-07-02 11:13:16 +0000317 EXPECT_IFF(Opts.IncludeComments, Results.Completions,
318 Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000319}
320
321TEST(CompletionTest, CompletionOptions) {
Sam McCall2c3849a2018-01-16 12:21:24 +0000322 auto Test = [&](const clangd::CodeCompleteOptions &Opts) {
323 TestAfterDotCompletion(Opts);
324 TestGlobalScopeCompletion(Opts);
325 };
326 // We used to test every combination of options, but that got too slow (2^N).
327 auto Flags = {
Ilya Biryukov71028b82018-03-12 15:28:22 +0000328 &clangd::CodeCompleteOptions::IncludeMacros,
Ilya Biryukov43714502018-05-16 12:32:44 +0000329 &clangd::CodeCompleteOptions::IncludeComments,
Ilya Biryukov71028b82018-03-12 15:28:22 +0000330 &clangd::CodeCompleteOptions::IncludeCodePatterns,
331 &clangd::CodeCompleteOptions::IncludeIneligibleResults,
Sam McCall2c3849a2018-01-16 12:21:24 +0000332 };
333 // Test default options.
334 Test({});
335 // Test with one flag flipped.
336 for (auto &F : Flags) {
337 clangd::CodeCompleteOptions O;
338 O.*F ^= true;
339 Test(O);
Sam McCall9aad25f2017-12-05 07:20:26 +0000340 }
341}
342
Sam McCall44fdcec22017-12-08 15:00:59 +0000343TEST(CompletionTest, Priorities) {
344 auto Internal = completions(R"cpp(
345 class Foo {
346 public: void pub();
347 protected: void prot();
348 private: void priv();
349 };
350 void Foo::pub() { this->^ }
351 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000352 EXPECT_THAT(Internal.Completions,
Sam McCall44fdcec22017-12-08 15:00:59 +0000353 HasSubsequence(Named("priv"), Named("prot"), Named("pub")));
354
355 auto External = completions(R"cpp(
356 class Foo {
357 public: void pub();
358 protected: void prot();
359 private: void priv();
360 };
361 void test() {
362 Foo F;
363 F.^
364 }
365 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000366 EXPECT_THAT(External.Completions,
Sam McCall44fdcec22017-12-08 15:00:59 +0000367 AllOf(Has("pub"), Not(Has("prot")), Not(Has("priv"))));
368}
369
370TEST(CompletionTest, Qualifiers) {
371 auto Results = completions(R"cpp(
372 class Foo {
373 public: int foo() const;
374 int bar() const;
375 };
376 class Bar : public Foo {
377 int foo() const;
378 };
379 void test() { Bar().^ }
380 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000381 EXPECT_THAT(Results.Completions,
382 HasSubsequence(AllOf(Qualifier(""), Named("bar")),
383 AllOf(Qualifier("Foo::"), Named("foo"))));
384 EXPECT_THAT(Results.Completions,
385 Not(Contains(AllOf(Qualifier(""), Named("foo"))))); // private
Sam McCall44fdcec22017-12-08 15:00:59 +0000386}
387
Sam McCall4caa8512018-06-07 12:49:17 +0000388TEST(CompletionTest, InjectedTypename) {
389 // These are suppressed when accessed as a member...
Sam McCalle746a2b2018-07-02 11:13:16 +0000390 EXPECT_THAT(completions("struct X{}; void foo(){ X().^ }").Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000391 Not(Has("X")));
Sam McCalle746a2b2018-07-02 11:13:16 +0000392 EXPECT_THAT(completions("struct X{ void foo(){ this->^ } };").Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000393 Not(Has("X")));
394 // ...but accessible in other, more useful cases.
Sam McCalle746a2b2018-07-02 11:13:16 +0000395 EXPECT_THAT(completions("struct X{ void foo(){ ^ } };").Completions,
396 Has("X"));
397 EXPECT_THAT(
398 completions("struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions,
399 Has("Y"));
Sam McCall4caa8512018-06-07 12:49:17 +0000400 EXPECT_THAT(
401 completions(
402 "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };")
Sam McCalle746a2b2018-07-02 11:13:16 +0000403 .Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000404 Has("Y"));
405 // This case is marginal (`using X::X` is useful), we allow it for now.
Sam McCalle746a2b2018-07-02 11:13:16 +0000406 EXPECT_THAT(completions("struct X{}; void foo(){ X::^ }").Completions,
407 Has("X"));
Sam McCall4caa8512018-06-07 12:49:17 +0000408}
409
Sam McCall44fdcec22017-12-08 15:00:59 +0000410TEST(CompletionTest, Snippets) {
411 clangd::CodeCompleteOptions Opts;
Sam McCall44fdcec22017-12-08 15:00:59 +0000412 auto Results = completions(
413 R"cpp(
414 struct fake {
415 int a;
416 int f(int i, const float f) const;
417 };
418 int main() {
419 fake f;
420 f.^
421 }
422 )cpp",
Sam McCalla15c2d62018-01-18 09:27:56 +0000423 /*IndexSymbols=*/{}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000424 EXPECT_THAT(
425 Results.Completions,
426 HasSubsequence(Named("a"),
427 SnippetSuffix("(${1:int i}, ${2:const float f})")));
Sam McCall44fdcec22017-12-08 15:00:59 +0000428}
429
430TEST(CompletionTest, Kinds) {
Sam McCall545a20d2018-01-19 14:34:02 +0000431 auto Results = completions(
432 R"cpp(
433 #define MACRO X
434 int variable;
435 struct Struct {};
436 int function();
437 int X = ^
438 )cpp",
439 {func("indexFunction"), var("indexVariable"), cls("indexClass")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000440 EXPECT_THAT(Results.Completions,
Sam McCall545a20d2018-01-19 14:34:02 +0000441 AllOf(Has("function", CompletionItemKind::Function),
442 Has("variable", CompletionItemKind::Variable),
443 Has("int", CompletionItemKind::Keyword),
444 Has("Struct", CompletionItemKind::Class),
445 Has("MACRO", CompletionItemKind::Text),
446 Has("indexFunction", CompletionItemKind::Function),
447 Has("indexVariable", CompletionItemKind::Variable),
448 Has("indexClass", CompletionItemKind::Class)));
Sam McCall44fdcec22017-12-08 15:00:59 +0000449
Sam McCall44fdcec22017-12-08 15:00:59 +0000450 Results = completions("nam^");
Sam McCalle746a2b2018-07-02 11:13:16 +0000451 EXPECT_THAT(Results.Completions,
452 Has("namespace", CompletionItemKind::Snippet));
Sam McCall44fdcec22017-12-08 15:00:59 +0000453}
454
Sam McCall84652cc2018-01-12 16:16:09 +0000455TEST(CompletionTest, NoDuplicates) {
Sam McCall545a20d2018-01-19 14:34:02 +0000456 auto Results = completions(
457 R"cpp(
458 class Adapter {
Sam McCall545a20d2018-01-19 14:34:02 +0000459 };
Sam McCall84652cc2018-01-12 16:16:09 +0000460
Eric Liu9b3cba72018-05-30 09:03:39 +0000461 void f() {
Sam McCall545a20d2018-01-19 14:34:02 +0000462 Adapter^
463 }
464 )cpp",
465 {cls("Adapter")});
Sam McCall84652cc2018-01-12 16:16:09 +0000466
467 // Make sure there are no duplicate entries of 'Adapter'.
Sam McCalle746a2b2018-07-02 11:13:16 +0000468 EXPECT_THAT(Results.Completions, ElementsAre(Named("Adapter")));
Sam McCall84652cc2018-01-12 16:16:09 +0000469}
470
Sam McCall545a20d2018-01-19 14:34:02 +0000471TEST(CompletionTest, ScopedNoIndex) {
472 auto Results = completions(
473 R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000474 namespace fake { int BigBang, Babble, Box; };
475 int main() { fake::ba^ }
Sam McCall545a20d2018-01-19 14:34:02 +0000476 ")cpp");
Sam McCall8b2dcc12018-06-14 13:50:30 +0000477 // Babble is a better match than BigBang. Box doesn't match at all.
Sam McCalle746a2b2018-07-02 11:13:16 +0000478 EXPECT_THAT(Results.Completions,
479 ElementsAre(Named("Babble"), Named("BigBang")));
Sam McCall84652cc2018-01-12 16:16:09 +0000480}
481
Sam McCall545a20d2018-01-19 14:34:02 +0000482TEST(CompletionTest, Scoped) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000483 auto Results = completions(
484 R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000485 namespace fake { int Babble, Box; };
486 int main() { fake::ba^ }
Sam McCall545a20d2018-01-19 14:34:02 +0000487 ")cpp",
488 {var("fake::BigBang")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000489 EXPECT_THAT(Results.Completions,
490 ElementsAre(Named("Babble"), Named("BigBang")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000491}
492
Sam McCall545a20d2018-01-19 14:34:02 +0000493TEST(CompletionTest, ScopedWithFilter) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000494 auto Results = completions(
495 R"cpp(
496 void f() { ns::x^ }
497 )cpp",
498 {cls("ns::XYZ"), func("ns::foo")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000499 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("XYZ")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000500}
501
Sam McCalldc8abc42018-05-03 14:53:02 +0000502TEST(CompletionTest, ReferencesAffectRanking) {
Eric Liu84bd5db2018-07-25 11:26:35 +0000503 auto Results = completions("int main() { abs^ }", {ns("absl"), func("absb")});
504 EXPECT_THAT(Results.Completions, HasSubsequence(Named("absb"), Named("absl")));
Sam McCalldc8abc42018-05-03 14:53:02 +0000505 Results = completions("int main() { abs^ }",
Eric Liu84bd5db2018-07-25 11:26:35 +0000506 {withReferences(10000, ns("absl")), func("absb")});
507 EXPECT_THAT(Results.Completions,
508 HasSubsequence(Named("absl"), Named("absb")));
Sam McCalldc8abc42018-05-03 14:53:02 +0000509}
510
Sam McCall545a20d2018-01-19 14:34:02 +0000511TEST(CompletionTest, GlobalQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000512 auto Results = completions(
513 R"cpp(
514 void f() { ::^ }
515 )cpp",
516 {cls("XYZ")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000517 EXPECT_THAT(Results.Completions,
518 AllOf(Has("XYZ", CompletionItemKind::Class),
519 Has("f", CompletionItemKind::Function)));
Sam McCalla15c2d62018-01-18 09:27:56 +0000520}
521
Sam McCall545a20d2018-01-19 14:34:02 +0000522TEST(CompletionTest, FullyQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000523 auto Results = completions(
524 R"cpp(
Sam McCall545a20d2018-01-19 14:34:02 +0000525 namespace ns { void bar(); }
Sam McCalla15c2d62018-01-18 09:27:56 +0000526 void f() { ::ns::^ }
527 )cpp",
528 {cls("ns::XYZ")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000529 EXPECT_THAT(Results.Completions,
530 AllOf(Has("XYZ", CompletionItemKind::Class),
531 Has("bar", CompletionItemKind::Function)));
Sam McCall545a20d2018-01-19 14:34:02 +0000532}
533
534TEST(CompletionTest, SemaIndexMerge) {
535 auto Results = completions(
536 R"cpp(
537 namespace ns { int local; void both(); }
538 void f() { ::ns::^ }
539 )cpp",
540 {func("ns::both"), cls("ns::Index")});
541 // We get results from both index and sema, with no duplicates.
Sam McCall2161ec72018-07-05 06:20:41 +0000542 EXPECT_THAT(Results.Completions,
543 UnorderedElementsAre(
544 AllOf(Named("local"), Origin(SymbolOrigin::AST)),
545 AllOf(Named("Index"), Origin(SymbolOrigin::Static)),
546 AllOf(Named("both"),
547 Origin(SymbolOrigin::AST | SymbolOrigin::Static))));
Sam McCalla15c2d62018-01-18 09:27:56 +0000548}
549
Haojian Wu48b48652018-01-25 09:20:09 +0000550TEST(CompletionTest, SemaIndexMergeWithLimit) {
551 clangd::CodeCompleteOptions Opts;
552 Opts.Limit = 1;
553 auto Results = completions(
554 R"cpp(
555 namespace ns { int local; void both(); }
556 void f() { ::ns::^ }
557 )cpp",
558 {func("ns::both"), cls("ns::Index")}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000559 EXPECT_EQ(Results.Completions.size(), Opts.Limit);
560 EXPECT_TRUE(Results.HasMore);
Haojian Wu48b48652018-01-25 09:20:09 +0000561}
562
Eric Liu63f419a2018-05-15 15:29:32 +0000563TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
564 MockFSProvider FS;
565 MockCompilationDatabase CDB;
566 std::string Subdir = testPath("sub");
567 std::string SearchDirArg = (llvm::Twine("-I") + Subdir).str();
568 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
569 std::string BarHeader = testPath("sub/bar.h");
570 FS.Files[BarHeader] = "";
571
572 IgnoreDiagnostics DiagConsumer;
573 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Eric Liu63f419a2018-05-15 15:29:32 +0000574 auto BarURI = URI::createFile(BarHeader).toString();
575 Symbol Sym = cls("ns::X");
576 Sym.CanonicalDeclaration.FileURI = BarURI;
Eric Liu83f63e42018-09-03 10:18:21 +0000577 Sym.IncludeHeaders.emplace_back(BarURI, 1);
Eric Liu63f419a2018-05-15 15:29:32 +0000578 // Shoten include path based on search dirctory and insert.
579 auto Results = completions(Server,
580 R"cpp(
581 int main() { ns::^ }
582 )cpp",
583 {Sym});
Sam McCalle746a2b2018-07-02 11:13:16 +0000584 EXPECT_THAT(Results.Completions,
585 ElementsAre(AllOf(Named("X"), InsertInclude("\"bar.h\""))));
Eric Liu63f419a2018-05-15 15:29:32 +0000586 // Duplicate based on inclusions in preamble.
587 Results = completions(Server,
588 R"cpp(
589 #include "sub/bar.h" // not shortest, so should only match resolved.
590 int main() { ns::^ }
591 )cpp",
592 {Sym});
Sam McCalle746a2b2018-07-02 11:13:16 +0000593 EXPECT_THAT(Results.Completions, ElementsAre(AllOf(Named("X"), Labeled("X"),
594 Not(InsertInclude()))));
Eric Liu63f419a2018-05-15 15:29:32 +0000595}
596
Eric Liu9b3cba72018-05-30 09:03:39 +0000597TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {
598 MockFSProvider FS;
599 MockCompilationDatabase CDB;
600
601 IgnoreDiagnostics DiagConsumer;
602 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Eric Liu9b3cba72018-05-30 09:03:39 +0000603 Symbol SymX = cls("ns::X");
604 Symbol SymY = cls("ns::Y");
605 std::string BarHeader = testPath("bar.h");
606 auto BarURI = URI::createFile(BarHeader).toString();
607 SymX.CanonicalDeclaration.FileURI = BarURI;
608 SymY.CanonicalDeclaration.FileURI = BarURI;
Eric Liu83f63e42018-09-03 10:18:21 +0000609 SymX.IncludeHeaders.emplace_back("<bar>", 1);
610 SymY.IncludeHeaders.emplace_back("<bar>", 1);
Eric Liu9b3cba72018-05-30 09:03:39 +0000611 // Shoten include path based on search dirctory and insert.
612 auto Results = completions(Server,
613 R"cpp(
614 namespace ns {
615 class X;
616 class Y {}
617 }
618 int main() { ns::^ }
619 )cpp",
620 {SymX, SymY});
Sam McCalle746a2b2018-07-02 11:13:16 +0000621 EXPECT_THAT(Results.Completions,
622 ElementsAre(AllOf(Named("X"), Not(InsertInclude())),
623 AllOf(Named("Y"), Not(InsertInclude()))));
Eric Liu9b3cba72018-05-30 09:03:39 +0000624}
625
Sam McCalla15c2d62018-01-18 09:27:56 +0000626TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
627 MockFSProvider FS;
628 MockCompilationDatabase CDB;
629 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000630 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Sam McCalla15c2d62018-01-18 09:27:56 +0000631
Sam McCallc1568062018-02-16 09:41:43 +0000632 FS.Files[testPath("bar.h")] =
Sam McCalld5ea3e32018-01-24 17:53:32 +0000633 R"cpp(namespace ns { struct preamble { int member; }; })cpp";
Sam McCallc1568062018-02-16 09:41:43 +0000634 auto File = testPath("foo.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000635 Annotations Test(R"cpp(
636 #include "bar.h"
637 namespace ns { int local; }
Sam McCalld5ea3e32018-01-24 17:53:32 +0000638 void f() { ns::^; }
639 void f() { ns::preamble().$2^; }
Sam McCalla15c2d62018-01-18 09:27:56 +0000640 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000641 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000642 clangd::CodeCompleteOptions Opts = {};
643
Sam McCalla15c2d62018-01-18 09:27:56 +0000644 auto I = memIndex({var("ns::index")});
645 Opts.Index = I.get();
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000646 auto WithIndex = cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000647 EXPECT_THAT(WithIndex.Completions,
Sam McCalla15c2d62018-01-18 09:27:56 +0000648 UnorderedElementsAre(Named("local"), Named("index")));
Sam McCalld5ea3e32018-01-24 17:53:32 +0000649 auto ClassFromPreamble =
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000650 cantFail(runCodeComplete(Server, File, Test.point("2"), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000651 EXPECT_THAT(ClassFromPreamble.Completions, Contains(Named("member")));
Sam McCall0bb24cd2018-02-13 08:59:23 +0000652
653 Opts.Index = nullptr;
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000654 auto WithoutIndex =
655 cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000656 EXPECT_THAT(WithoutIndex.Completions,
Sam McCall0bb24cd2018-02-13 08:59:23 +0000657 UnorderedElementsAre(Named("local"), Named("preamble")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000658}
659
Sam McCallebef8122018-09-14 12:36:06 +0000660// This verifies that we get normal preprocessor completions in the preamble.
661// This is a regression test for an old bug: if we override the preamble and
662// try to complete inside it, clang kicks our completion point just outside the
663// preamble, resulting in always getting top-level completions.
664TEST(CompletionTest, CompletionInPreamble) {
Sam McCall0be9c4e2018-09-14 18:49:16 +0000665 auto Results = completions(R"cpp(
Sam McCallebef8122018-09-14 12:36:06 +0000666 #ifnd^ef FOO_H_
667 #define BAR_H_
668 #include <bar.h>
669 int foo() {}
670 #endif
671 )cpp")
Sam McCall0be9c4e2018-09-14 18:49:16 +0000672 .Completions;
673 EXPECT_THAT(Results, ElementsAre(Named("ifndef")));
Sam McCallebef8122018-09-14 12:36:06 +0000674};
675
Sam McCalla15c2d62018-01-18 09:27:56 +0000676TEST(CompletionTest, DynamicIndexMultiFile) {
677 MockFSProvider FS;
678 MockCompilationDatabase CDB;
679 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000680 auto Opts = ClangdServer::optsForTest();
681 Opts.BuildDynamicSymbolIndex = true;
682 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
Sam McCalla15c2d62018-01-18 09:27:56 +0000683
Eric Liu709bde82018-02-19 18:48:44 +0000684 FS.Files[testPath("foo.h")] = R"cpp(
Sam McCalla15c2d62018-01-18 09:27:56 +0000685 namespace ns { class XYZ {}; void foo(int x) {} }
Eric Liu709bde82018-02-19 18:48:44 +0000686 )cpp";
Sam McCall7363a2f2018-03-05 17:28:54 +0000687 runAddDocument(Server, testPath("foo.cpp"), R"cpp(
Eric Liu709bde82018-02-19 18:48:44 +0000688 #include "foo.h"
Sam McCall0bb24cd2018-02-13 08:59:23 +0000689 )cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000690
Sam McCallc1568062018-02-16 09:41:43 +0000691 auto File = testPath("bar.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000692 Annotations Test(R"cpp(
693 namespace ns {
694 class XXX {};
695 /// Doooc
696 void fooooo() {}
697 }
698 void f() { ns::^ }
699 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000700 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000701
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000702 auto Results = cantFail(runCodeComplete(Server, File, Test.point(), {}));
Sam McCalla15c2d62018-01-18 09:27:56 +0000703 // "XYZ" and "foo" are not included in the file being completed but are still
704 // visible through the index.
Sam McCalle746a2b2018-07-02 11:13:16 +0000705 EXPECT_THAT(Results.Completions, Has("XYZ", CompletionItemKind::Class));
706 EXPECT_THAT(Results.Completions, Has("foo", CompletionItemKind::Function));
707 EXPECT_THAT(Results.Completions, Has("XXX", CompletionItemKind::Class));
708 EXPECT_THAT(Results.Completions,
709 Contains((Named("fooooo"), Kind(CompletionItemKind::Function),
710 Doc("Doooc"), ReturnType("void"))));
Sam McCalla15c2d62018-01-18 09:27:56 +0000711}
712
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000713TEST(CompletionTest, Documentation) {
714 auto Results = completions(
715 R"cpp(
716 // Non-doxygen comment.
717 int foo();
718 /// Doxygen comment.
719 /// \param int a
720 int bar(int a);
721 /* Multi-line
722 block comment
723 */
724 int baz();
725
726 int x = ^
727 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000728 EXPECT_THAT(Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000729 Contains(AllOf(Named("foo"), Doc("Non-doxygen comment."))));
730 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +0000731 Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000732 Contains(AllOf(Named("bar"), Doc("Doxygen comment.\n\\param int a"))));
Sam McCalle746a2b2018-07-02 11:13:16 +0000733 EXPECT_THAT(Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000734 Contains(AllOf(Named("baz"), Doc("Multi-line\nblock comment"))));
735}
736
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000737TEST(CompletionTest, GlobalCompletionFiltering) {
738
739 Symbol Class = cls("XYZ");
Eric Liu6df66002018-09-06 18:52:26 +0000740 Class.Flags = static_cast<Symbol::SymbolFlag>(
741 Class.Flags & ~(Symbol::IndexedForCodeCompletion));
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000742 Symbol Func = func("XYZ::foooo");
Eric Liu6df66002018-09-06 18:52:26 +0000743 Func.Flags = static_cast<Symbol::SymbolFlag>(
744 Func.Flags & ~(Symbol::IndexedForCodeCompletion));
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000745
746 auto Results = completions(R"(// void f() {
747 XYZ::foooo^
748 })",
749 {Class, Func});
Sam McCalle746a2b2018-07-02 11:13:16 +0000750 EXPECT_THAT(Results.Completions, IsEmpty());
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000751}
752
Haojian Wu58d208d2018-01-25 09:44:06 +0000753TEST(CodeCompleteTest, DisableTypoCorrection) {
754 auto Results = completions(R"cpp(
755 namespace clang { int v; }
756 void f() { clangd::^
757 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000758 EXPECT_TRUE(Results.Completions.empty());
Haojian Wu58d208d2018-01-25 09:44:06 +0000759}
760
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000761TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
762 auto Results = completions(R"cpp(
763 namespace clang { }
764 void f() {
765 clan^
766 }
767 )cpp");
768
Sam McCalle746a2b2018-07-02 11:13:16 +0000769 EXPECT_THAT(Results.Completions, Contains(Labeled("clang")));
770 EXPECT_THAT(Results.Completions, Not(Contains(Labeled("clang::"))));
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000771}
772
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000773TEST(CompletionTest, BacktrackCrashes) {
774 // Sema calls code completion callbacks twice in these cases.
775 auto Results = completions(R"cpp(
776 namespace ns {
777 struct FooBarBaz {};
778 } // namespace ns
779
780 int foo(ns::FooBar^
781 )cpp");
782
Sam McCalle746a2b2018-07-02 11:13:16 +0000783 EXPECT_THAT(Results.Completions, ElementsAre(Labeled("FooBarBaz")));
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000784
785 // Check we don't crash in that case too.
786 completions(R"cpp(
787 struct FooBarBaz {};
788 void test() {
789 if (FooBarBaz * x^) {}
790 }
791)cpp");
792}
793
Eric Liu42abe412018-05-24 11:20:19 +0000794TEST(CompletionTest, CompleteInMacroWithStringification) {
795 auto Results = completions(R"cpp(
796void f(const char *, int x);
797#define F(x) f(#x, x)
798
799namespace ns {
800int X;
801int Y;
802} // namespace ns
803
804int f(int input_num) {
805 F(ns::^)
806}
807)cpp");
808
Sam McCalle746a2b2018-07-02 11:13:16 +0000809 EXPECT_THAT(Results.Completions,
Eric Liu42abe412018-05-24 11:20:19 +0000810 UnorderedElementsAre(Named("X"), Named("Y")));
811}
812
813TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
814 auto Results = completions(R"cpp(
815void f(const char *, int x);
816#define F(x) f(#x, x)
817
818namespace ns {
819int X;
820
821int f(int input_num) {
822 F(^)
823}
824} // namespace ns
825)cpp");
826
Sam McCalle746a2b2018-07-02 11:13:16 +0000827 EXPECT_THAT(Results.Completions, Contains(Named("X")));
Eric Liu42abe412018-05-24 11:20:19 +0000828}
829
Eric Liu485074f2018-07-11 13:15:31 +0000830TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000831 auto Results = completions(R"cpp(
832 int bar(int param_in_bar) {
833 }
834
835 int foo(int param_in_foo) {
836#if 0
Eric Liu485074f2018-07-11 13:15:31 +0000837 // In recorvery mode, "param_in_foo" will also be suggested among many other
838 // unrelated symbols; however, this is really a special case where this works.
839 // If the #if block is outside of the function, "param_in_foo" is still
840 // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't
841 // really provide useful results in excluded branches.
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000842 par^
843#endif
844 }
845)cpp");
846
Eric Liu485074f2018-07-11 13:15:31 +0000847 EXPECT_TRUE(Results.Completions.empty());
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000848}
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000849SignatureHelp signatures(StringRef Text, Position Point,
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +0000850 std::vector<Symbol> IndexSymbols = {}) {
851 std::unique_ptr<SymbolIndex> Index;
852 if (!IndexSymbols.empty())
853 Index = memIndex(IndexSymbols);
854
Sam McCall800d4372017-12-19 10:29:27 +0000855 MockFSProvider FS;
856 MockCompilationDatabase CDB;
857 IgnoreDiagnostics DiagConsumer;
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +0000858 ClangdServer::Options Opts = ClangdServer::optsForTest();
859 Opts.StaticIndex = Index.get();
860
861 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
Sam McCallc1568062018-02-16 09:41:43 +0000862 auto File = testPath("foo.cpp");
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000863 runAddDocument(Server, File, Text);
864 return cantFail(runSignatureHelp(Server, File, Point));
865}
866
867SignatureHelp signatures(StringRef Text,
868 std::vector<Symbol> IndexSymbols = {}) {
Sam McCall328cbdb2017-12-20 16:06:05 +0000869 Annotations Test(Text);
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000870 return signatures(Test.code(), Test.point(), std::move(IndexSymbols));
Sam McCall800d4372017-12-19 10:29:27 +0000871}
872
873MATCHER_P(ParamsAre, P, "") {
874 if (P.size() != arg.parameters.size())
875 return false;
876 for (unsigned I = 0; I < P.size(); ++I)
877 if (P[I] != arg.parameters[I].label)
878 return false;
879 return true;
880}
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +0000881MATCHER_P(SigDoc, Doc, "") { return arg.documentation == Doc; }
Sam McCall800d4372017-12-19 10:29:27 +0000882
883Matcher<SignatureInformation> Sig(std::string Label,
884 std::vector<std::string> Params) {
Eric Liu8f3678d2018-06-15 13:34:18 +0000885 return AllOf(SigHelpLabeled(Label), ParamsAre(Params));
Sam McCall800d4372017-12-19 10:29:27 +0000886}
887
888TEST(SignatureHelpTest, Overloads) {
889 auto Results = signatures(R"cpp(
890 void foo(int x, int y);
891 void foo(int x, float y);
892 void foo(float x, int y);
893 void foo(float x, float y);
894 void bar(int x, int y = 0);
895 int main() { foo(^); }
896 )cpp");
897 EXPECT_THAT(Results.signatures,
898 UnorderedElementsAre(
899 Sig("foo(float x, float y) -> void", {"float x", "float y"}),
900 Sig("foo(float x, int y) -> void", {"float x", "int y"}),
901 Sig("foo(int x, float y) -> void", {"int x", "float y"}),
902 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
903 // We always prefer the first signature.
904 EXPECT_EQ(0, Results.activeSignature);
905 EXPECT_EQ(0, Results.activeParameter);
906}
907
908TEST(SignatureHelpTest, DefaultArgs) {
909 auto Results = signatures(R"cpp(
910 void bar(int x, int y = 0);
911 void bar(float x = 0, int y = 42);
912 int main() { bar(^
913 )cpp");
914 EXPECT_THAT(Results.signatures,
915 UnorderedElementsAre(
916 Sig("bar(int x, int y = 0) -> void", {"int x", "int y = 0"}),
917 Sig("bar(float x = 0, int y = 42) -> void",
918 {"float x = 0", "int y = 42"})));
919 EXPECT_EQ(0, Results.activeSignature);
920 EXPECT_EQ(0, Results.activeParameter);
921}
922
923TEST(SignatureHelpTest, ActiveArg) {
924 auto Results = signatures(R"cpp(
925 int baz(int a, int b, int c);
926 int main() { baz(baz(1,2,3), ^); }
927 )cpp");
928 EXPECT_THAT(Results.signatures,
929 ElementsAre(Sig("baz(int a, int b, int c) -> int",
930 {"int a", "int b", "int c"})));
931 EXPECT_EQ(0, Results.activeSignature);
932 EXPECT_EQ(1, Results.activeParameter);
933}
934
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000935TEST(SignatureHelpTest, OpeningParen) {
936 llvm::StringLiteral Tests[] = {// Recursive function call.
937 R"cpp(
938 int foo(int a, int b, int c);
939 int main() {
940 foo(foo $p^( foo(10, 10, 10), ^ )));
941 })cpp",
942 // Functional type cast.
943 R"cpp(
944 struct Foo {
945 Foo(int a, int b, int c);
946 };
947 int main() {
948 Foo $p^( 10, ^ );
949 })cpp",
950 // New expression.
951 R"cpp(
952 struct Foo {
953 Foo(int a, int b, int c);
954 };
955 int main() {
956 new Foo $p^( 10, ^ );
957 })cpp",
958 // Macro expansion.
959 R"cpp(
960 int foo(int a, int b, int c);
961 #define FOO foo(
962
963 int main() {
964 // Macro expansions.
965 $p^FOO 10, ^ );
966 })cpp",
967 // Macro arguments.
968 R"cpp(
969 int foo(int a, int b, int c);
970 int main() {
971 #define ID(X) X
972 ID(foo $p^( foo(10), ^ ))
973 })cpp"};
974
975 for (auto Test : Tests) {
976 Annotations Code(Test);
977 EXPECT_EQ(signatures(Code.code(), Code.point()).argListStart,
978 Code.point("p"))
979 << "Test source:" << Test;
980 }
981}
982
Haojian Wu061c73e2018-01-23 11:37:26 +0000983class IndexRequestCollector : public SymbolIndex {
984public:
985 bool
Sam McCalld1a7a372018-01-31 13:40:48 +0000986 fuzzyFind(const FuzzyFindRequest &Req,
Haojian Wu061c73e2018-01-23 11:37:26 +0000987 llvm::function_ref<void(const Symbol &)> Callback) const override {
Ilya Biryukov5c4d6e62018-09-06 11:04:56 +0000988 std::lock_guard<std::mutex> Lock(Mut);
Haojian Wu061c73e2018-01-23 11:37:26 +0000989 Requests.push_back(Req);
Sam McCallab8e3932018-02-19 13:04:41 +0000990 return true;
Haojian Wu061c73e2018-01-23 11:37:26 +0000991 }
992
Eric Liu9ec459f2018-03-14 09:48:05 +0000993 void lookup(const LookupRequest &,
994 llvm::function_ref<void(const Symbol &)>) const override {}
995
Sam McCallb0138312018-09-04 14:39:56 +0000996 void refs(const RefsRequest &,
997 llvm::function_ref<void(const Ref &)>) const override {}
Haojian Wu65ac3212018-08-06 13:14:32 +0000998
Kirill Bobyrevfc890012018-08-24 09:12:54 +0000999 // This is incorrect, but IndexRequestCollector is not an actual index and it
1000 // isn't used in production code.
1001 size_t estimateMemoryUsage() const override { return 0; }
1002
Eric Liu25d74e92018-08-24 11:23:56 +00001003 const std::vector<FuzzyFindRequest> consumeRequests() const {
Ilya Biryukov5c4d6e62018-09-06 11:04:56 +00001004 std::lock_guard<std::mutex> Lock(Mut);
Eric Liu25d74e92018-08-24 11:23:56 +00001005 auto Reqs = std::move(Requests);
1006 Requests = {};
1007 return Reqs;
1008 }
Haojian Wu061c73e2018-01-23 11:37:26 +00001009
1010private:
Ilya Biryukov5c4d6e62018-09-06 11:04:56 +00001011 // We need a mutex to handle async fuzzy find requests.
1012 mutable std::mutex Mut;
Haojian Wu061c73e2018-01-23 11:37:26 +00001013 mutable std::vector<FuzzyFindRequest> Requests;
1014};
1015
1016std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code) {
1017 clangd::CodeCompleteOptions Opts;
1018 IndexRequestCollector Requests;
1019 Opts.Index = &Requests;
1020 completions(Code, {}, Opts);
Eric Liu25d74e92018-08-24 11:23:56 +00001021 return Requests.consumeRequests();
Haojian Wu061c73e2018-01-23 11:37:26 +00001022}
1023
1024TEST(CompletionTest, UnqualifiedIdQuery) {
1025 auto Requests = captureIndexRequests(R"cpp(
1026 namespace std {}
1027 using namespace std;
1028 namespace ns {
1029 void f() {
1030 vec^
1031 }
1032 }
1033 )cpp");
1034
1035 EXPECT_THAT(Requests,
1036 ElementsAre(Field(&FuzzyFindRequest::Scopes,
1037 UnorderedElementsAre("", "ns::", "std::"))));
1038}
1039
1040TEST(CompletionTest, ResolvedQualifiedIdQuery) {
1041 auto Requests = captureIndexRequests(R"cpp(
1042 namespace ns1 {}
1043 namespace ns2 {} // ignore
1044 namespace ns3 { namespace nns3 {} }
1045 namespace foo {
1046 using namespace ns1;
1047 using namespace ns3::nns3;
1048 }
1049 namespace ns {
1050 void f() {
1051 foo::^
1052 }
1053 }
1054 )cpp");
1055
1056 EXPECT_THAT(Requests,
1057 ElementsAre(Field(
1058 &FuzzyFindRequest::Scopes,
1059 UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::"))));
1060}
1061
1062TEST(CompletionTest, UnresolvedQualifierIdQuery) {
1063 auto Requests = captureIndexRequests(R"cpp(
1064 namespace a {}
1065 using namespace a;
1066 namespace ns {
1067 void f() {
1068 bar::^
1069 }
1070 } // namespace ns
1071 )cpp");
1072
1073 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1074 UnorderedElementsAre("bar::"))));
1075}
1076
1077TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
1078 auto Requests = captureIndexRequests(R"cpp(
1079 namespace a {}
1080 using namespace a;
1081 namespace ns {
1082 void f() {
1083 ::a::bar::^
1084 }
1085 } // namespace ns
1086 )cpp");
1087
1088 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1089 UnorderedElementsAre("a::bar::"))));
1090}
1091
1092TEST(CompletionTest, EmptyQualifiedQuery) {
1093 auto Requests = captureIndexRequests(R"cpp(
1094 namespace ns {
1095 void f() {
1096 ^
1097 }
1098 } // namespace ns
1099 )cpp");
1100
1101 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1102 UnorderedElementsAre("", "ns::"))));
1103}
1104
1105TEST(CompletionTest, GlobalQualifiedQuery) {
1106 auto Requests = captureIndexRequests(R"cpp(
1107 namespace ns {
1108 void f() {
1109 ::^
1110 }
1111 } // namespace ns
1112 )cpp");
1113
1114 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1115 UnorderedElementsAre(""))));
1116}
1117
Ilya Biryukova907ba42018-05-14 10:50:04 +00001118TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
1119 auto Completions = completions(
1120 R"cpp(
1121 struct Foo {
1122 int SomeNameOfField;
1123 typedef int SomeNameOfTypedefField;
1124 };
1125
1126 Foo::^)cpp",
1127 {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")});
1128
Sam McCalle746a2b2018-07-02 11:13:16 +00001129 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001130 AllOf(Contains(Labeled("SomeNameOfField")),
1131 Contains(Labeled("SomeNameOfTypedefField")),
1132 Not(Contains(Labeled("SomeNameInTheIndex")))));
1133}
1134
1135TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
1136 {
1137 auto Completions = completions(
1138 R"cpp(
1139 template <class T>
1140 void foo() {
1141 T::^
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 {
1151 auto Completions = completions(
1152 R"cpp(
1153 template <class T>
1154 void foo() {
1155 T::template Y<int>::^
1156 }
1157 )cpp",
1158 {func("::SomeNameInTheIndex")});
1159
Sam McCalle746a2b2018-07-02 11:13:16 +00001160 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001161 Not(Contains(Labeled("SomeNameInTheIndex"))));
1162 }
1163
1164 {
1165 auto Completions = completions(
1166 R"cpp(
1167 template <class T>
1168 void foo() {
1169 T::foo::^
1170 }
1171 )cpp",
1172 {func("::SomeNameInTheIndex")});
1173
Sam McCalle746a2b2018-07-02 11:13:16 +00001174 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001175 Not(Contains(Labeled("SomeNameInTheIndex"))));
1176 }
1177}
1178
Sam McCallc18c2802018-06-15 11:06:29 +00001179TEST(CompletionTest, OverloadBundling) {
1180 clangd::CodeCompleteOptions Opts;
1181 Opts.BundleOverloads = true;
1182
1183 std::string Context = R"cpp(
1184 struct X {
1185 // Overload with int
1186 int a(int);
1187 // Overload with bool
1188 int a(bool);
1189 int b(float);
1190 };
1191 int GFuncC(int);
1192 int GFuncD(int);
1193 )cpp";
1194
1195 // Member completions are bundled.
Sam McCalle746a2b2018-07-02 11:13:16 +00001196 EXPECT_THAT(completions(Context + "int y = X().^", {}, Opts).Completions,
Sam McCallc18c2802018-06-15 11:06:29 +00001197 UnorderedElementsAre(Labeled("a(…)"), Labeled("b(float)")));
1198
1199 // Non-member completions are bundled, including index+sema.
1200 Symbol NoArgsGFunc = func("GFuncC");
1201 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001202 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
Sam McCallc18c2802018-06-15 11:06:29 +00001203 UnorderedElementsAre(Labeled("GFuncC(…)"), Labeled("GFuncD(int)")));
1204
1205 // Differences in header-to-insert suppress bundling.
Sam McCallc18c2802018-06-15 11:06:29 +00001206 std::string DeclFile = URI::createFile(testPath("foo")).toString();
1207 NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile;
Eric Liu83f63e42018-09-03 10:18:21 +00001208 NoArgsGFunc.IncludeHeaders.emplace_back("<foo>", 1);
Sam McCallc18c2802018-06-15 11:06:29 +00001209 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001210 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1211 UnorderedElementsAre(AllOf(Named("GFuncC"), InsertInclude("<foo>")),
1212 Labeled("GFuncC(int)"), Labeled("GFuncD(int)")));
Sam McCallc18c2802018-06-15 11:06:29 +00001213
1214 // Examine a bundled completion in detail.
Sam McCalle746a2b2018-07-02 11:13:16 +00001215 auto A =
1216 completions(Context + "int y = X().a^", {}, Opts).Completions.front();
1217 EXPECT_EQ(A.Name, "a");
1218 EXPECT_EQ(A.Signature, "(…)");
1219 EXPECT_EQ(A.BundleSize, 2u);
1220 EXPECT_EQ(A.Kind, CompletionItemKind::Method);
1221 EXPECT_EQ(A.ReturnType, "int"); // All overloads return int.
Sam McCallc18c2802018-06-15 11:06:29 +00001222 // For now we just return one of the doc strings arbitrarily.
Sam McCalle746a2b2018-07-02 11:13:16 +00001223 EXPECT_THAT(A.Documentation, AnyOf(HasSubstr("Overload with int"),
Sam McCallc18c2802018-06-15 11:06:29 +00001224 HasSubstr("Overload with bool")));
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001225 EXPECT_EQ(A.SnippetSuffix, "($0)");
Sam McCallc18c2802018-06-15 11:06:29 +00001226}
1227
Ilya Biryukov30b04b12018-05-28 09:54:51 +00001228TEST(CompletionTest, DocumentationFromChangedFileCrash) {
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001229 MockFSProvider FS;
1230 auto FooH = testPath("foo.h");
1231 auto FooCpp = testPath("foo.cpp");
1232 FS.Files[FooH] = R"cpp(
1233 // this is my documentation comment.
1234 int func();
1235 )cpp";
1236 FS.Files[FooCpp] = "";
1237
1238 MockCompilationDatabase CDB;
1239 IgnoreDiagnostics DiagConsumer;
1240 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1241
1242 Annotations Source(R"cpp(
1243 #include "foo.h"
1244 int func() {
1245 // This makes sure we have func from header in the AST.
1246 }
1247 int a = fun^
1248 )cpp");
1249 Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
1250 // We need to wait for preamble to build.
1251 ASSERT_TRUE(Server.blockUntilIdleForTest());
1252
1253 // Change the header file. Completion will reuse the old preamble!
1254 FS.Files[FooH] = R"cpp(
1255 int func();
1256 )cpp";
1257
1258 clangd::CodeCompleteOptions Opts;
1259 Opts.IncludeComments = true;
Sam McCalle746a2b2018-07-02 11:13:16 +00001260 CodeCompleteResult Completions =
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001261 cantFail(runCodeComplete(Server, FooCpp, Source.point(), Opts));
1262 // We shouldn't crash. Unfortunately, current workaround is to not produce
1263 // comments for symbols from headers.
Sam McCalle746a2b2018-07-02 11:13:16 +00001264 EXPECT_THAT(Completions.Completions,
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001265 Contains(AllOf(Not(IsDocumented()), Named("func"))));
1266}
1267
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001268TEST(CompletionTest, NonDocComments) {
1269 MockFSProvider FS;
1270 auto FooCpp = testPath("foo.cpp");
1271 FS.Files[FooCpp] = "";
1272
1273 MockCompilationDatabase CDB;
1274 IgnoreDiagnostics DiagConsumer;
1275 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1276
1277 Annotations Source(R"cpp(
Ilya Biryukovda8dd8b2018-06-27 09:47:20 +00001278 // We ignore namespace comments, for rationale see CodeCompletionStrings.h.
1279 namespace comments_ns {
1280 }
1281
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001282 // ------------------
1283 int comments_foo();
1284
1285 // A comment and a decl are separated by newlines.
1286 // Therefore, the comment shouldn't show up as doc comment.
1287
1288 int comments_bar();
1289
1290 // this comment should be in the results.
1291 int comments_baz();
1292
1293
1294 template <class T>
1295 struct Struct {
1296 int comments_qux();
1297 int comments_quux();
1298 };
1299
1300
1301 // This comment should not be there.
1302
1303 template <class T>
1304 int Struct<T>::comments_qux() {
1305 }
1306
1307 // This comment **should** be in results.
1308 template <class T>
1309 int Struct<T>::comments_quux() {
1310 int a = comments^;
1311 }
1312 )cpp");
Reid Kleckner80274b12018-06-18 18:55:10 +00001313 // FIXME: Auto-completion in a template requires disabling delayed template
1314 // parsing.
1315 CDB.ExtraClangFlags.push_back("-fno-delayed-template-parsing");
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001316 Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
Sam McCalle746a2b2018-07-02 11:13:16 +00001317 CodeCompleteResult Completions = cantFail(runCodeComplete(
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001318 Server, FooCpp, Source.point(), clangd::CodeCompleteOptions()));
1319
1320 // We should not get any of those comments in completion.
1321 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001322 Completions.Completions,
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001323 UnorderedElementsAre(AllOf(Not(IsDocumented()), Named("comments_foo")),
1324 AllOf(IsDocumented(), Named("comments_baz")),
1325 AllOf(IsDocumented(), Named("comments_quux")),
Ilya Biryukovda8dd8b2018-06-27 09:47:20 +00001326 AllOf(Not(IsDocumented()), Named("comments_ns")),
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001327 // FIXME(ibiryukov): the following items should have
1328 // empty documentation, since they are separated from
1329 // a comment with an empty line. Unfortunately, I
1330 // couldn't make Sema tests pass if we ignore those.
1331 AllOf(IsDocumented(), Named("comments_bar")),
1332 AllOf(IsDocumented(), Named("comments_qux"))));
1333}
1334
Ilya Biryukov981a35d2018-05-28 12:11:37 +00001335TEST(CompletionTest, CompleteOnInvalidLine) {
1336 auto FooCpp = testPath("foo.cpp");
1337
1338 MockCompilationDatabase CDB;
1339 IgnoreDiagnostics DiagConsumer;
1340 MockFSProvider FS;
1341 FS.Files[FooCpp] = "// empty file";
1342
1343 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1344 // Run completion outside the file range.
1345 Position Pos;
1346 Pos.line = 100;
1347 Pos.character = 0;
1348 EXPECT_THAT_EXPECTED(
1349 runCodeComplete(Server, FooCpp, Pos, clangd::CodeCompleteOptions()),
1350 Failed());
1351}
1352
Eric Liu7ad16962018-06-22 10:46:59 +00001353TEST(CompletionTest, QualifiedNames) {
1354 auto Results = completions(
1355 R"cpp(
1356 namespace ns { int local; void both(); }
1357 void f() { ::ns::^ }
1358 )cpp",
1359 {func("ns::both"), cls("ns::Index")});
1360 // We get results from both index and sema, with no duplicates.
Sam McCalle746a2b2018-07-02 11:13:16 +00001361 EXPECT_THAT(
1362 Results.Completions,
1363 UnorderedElementsAre(Scope("ns::"), Scope("ns::"), Scope("ns::")));
1364}
1365
1366TEST(CompletionTest, Render) {
1367 CodeCompletion C;
1368 C.Name = "x";
1369 C.Signature = "(bool) const";
1370 C.SnippetSuffix = "(${0:bool})";
1371 C.ReturnType = "int";
1372 C.RequiredQualifier = "Foo::";
1373 C.Scope = "ns::Foo::";
1374 C.Documentation = "This is x().";
Eric Liu83f63e42018-09-03 10:18:21 +00001375 C.Includes.emplace_back();
1376 auto &Include = C.Includes.back();
1377 Include.Header = "\"foo.h\"";
Sam McCalle746a2b2018-07-02 11:13:16 +00001378 C.Kind = CompletionItemKind::Method;
1379 C.Score.Total = 1.0;
Sam McCall4e5742a2018-07-06 11:50:49 +00001380 C.Origin = SymbolOrigin::AST | SymbolOrigin::Static;
Sam McCalle746a2b2018-07-02 11:13:16 +00001381
1382 CodeCompleteOptions Opts;
1383 Opts.IncludeIndicator.Insert = "^";
1384 Opts.IncludeIndicator.NoInsert = "";
1385 Opts.EnableSnippets = false;
1386
1387 auto R = C.render(Opts);
1388 EXPECT_EQ(R.label, "Foo::x(bool) const");
1389 EXPECT_EQ(R.insertText, "Foo::x");
1390 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
1391 EXPECT_EQ(R.filterText, "x");
1392 EXPECT_EQ(R.detail, "int\n\"foo.h\"");
1393 EXPECT_EQ(R.documentation, "This is x().");
1394 EXPECT_THAT(R.additionalTextEdits, IsEmpty());
Sam McCalle746a2b2018-07-02 11:13:16 +00001395 EXPECT_EQ(R.sortText, sortText(1.0, "x"));
Eric Liu6df66002018-09-06 18:52:26 +00001396 EXPECT_FALSE(R.deprecated);
Sam McCalle746a2b2018-07-02 11:13:16 +00001397
1398 Opts.EnableSnippets = true;
1399 R = C.render(Opts);
1400 EXPECT_EQ(R.insertText, "Foo::x(${0:bool})");
1401 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
1402
Eric Liu83f63e42018-09-03 10:18:21 +00001403 Include.Insertion.emplace();
Sam McCalle746a2b2018-07-02 11:13:16 +00001404 R = C.render(Opts);
1405 EXPECT_EQ(R.label, "^Foo::x(bool) const");
1406 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
1407
Sam McCall2161ec72018-07-05 06:20:41 +00001408 Opts.ShowOrigins = true;
1409 R = C.render(Opts);
1410 EXPECT_EQ(R.label, "^[AS]Foo::x(bool) const");
1411
Sam McCalle746a2b2018-07-02 11:13:16 +00001412 C.BundleSize = 2;
1413 R = C.render(Opts);
1414 EXPECT_EQ(R.detail, "[2 overloads]\n\"foo.h\"");
Eric Liu6df66002018-09-06 18:52:26 +00001415
1416 C.Deprecated = true;
1417 R = C.render(Opts);
1418 EXPECT_TRUE(R.deprecated);
Eric Liu7ad16962018-06-22 10:46:59 +00001419}
Ilya Biryukov981a35d2018-05-28 12:11:37 +00001420
Eric Liu485074f2018-07-11 13:15:31 +00001421TEST(CompletionTest, IgnoreRecoveryResults) {
1422 auto Results = completions(
1423 R"cpp(
1424 namespace ns { int NotRecovered() { return 0; } }
1425 void f() {
1426 // Sema enters recovery mode first and then normal mode.
1427 if (auto x = ns::NotRecover^)
1428 }
1429 )cpp");
1430 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("NotRecovered")));
1431}
1432
Eric Liuf433c2d2018-07-18 15:31:14 +00001433TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
1434 auto Results = completions(
1435 R"cpp(
1436 namespace ns {
1437 class X { public: X(); int x_; };
1438 X::X() : x_^(0) {}
1439 }
1440 )cpp");
1441 EXPECT_THAT(Results.Completions,
1442 UnorderedElementsAre(AllOf(Scope("ns::X::"), Named("x_"))));
1443}
1444
Eric Liu5d2a8072018-07-23 10:56:37 +00001445TEST(CompletionTest, CodeCompletionContext) {
1446 auto Results = completions(
1447 R"cpp(
1448 namespace ns {
1449 class X { public: X(); int x_; };
1450 void f() {
1451 X x;
1452 x.^;
1453 }
1454 }
1455 )cpp");
1456
1457 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
1458}
1459
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001460TEST(CompletionTest, FixItForArrowToDot) {
1461 MockFSProvider FS;
1462 MockCompilationDatabase CDB;
1463 IgnoreDiagnostics DiagConsumer;
1464 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1465
1466 CodeCompleteOptions Opts;
1467 Opts.IncludeFixIts = true;
1468 Annotations TestCode(
1469 R"cpp(
1470 class Auxilary {
1471 public:
1472 void AuxFunction();
1473 };
1474 class ClassWithPtr {
1475 public:
1476 void MemberFunction();
1477 Auxilary* operator->() const;
1478 Auxilary* Aux;
1479 };
1480 void f() {
1481 ClassWithPtr x;
1482 x[[->]]^;
1483 }
1484 )cpp");
1485 auto Results =
1486 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1487 EXPECT_EQ(Results.Completions.size(), 3u);
1488
1489 TextEdit ReplacementEdit;
1490 ReplacementEdit.range = TestCode.range();
1491 ReplacementEdit.newText = ".";
1492 for (const auto &C : Results.Completions) {
1493 EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction");
Haojian Wu1793bc92018-08-10 08:34:16 +00001494 if (!C.FixIts.empty()) {
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001495 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
Haojian Wu1793bc92018-08-10 08:34:16 +00001496 }
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001497 }
1498}
1499
1500TEST(CompletionTest, FixItForDotToArrow) {
1501 MockFSProvider FS;
1502 MockCompilationDatabase CDB;
1503 IgnoreDiagnostics DiagConsumer;
1504 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1505
1506 CodeCompleteOptions Opts;
1507 Opts.IncludeFixIts = true;
1508 Annotations TestCode(
1509 R"cpp(
1510 class Auxilary {
1511 public:
1512 void AuxFunction();
1513 };
1514 class ClassWithPtr {
1515 public:
1516 void MemberFunction();
1517 Auxilary* operator->() const;
1518 Auxilary* Aux;
1519 };
1520 void f() {
1521 ClassWithPtr x;
1522 x[[.]]^;
1523 }
1524 )cpp");
1525 auto Results =
1526 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1527 EXPECT_EQ(Results.Completions.size(), 3u);
1528
1529 TextEdit ReplacementEdit;
1530 ReplacementEdit.range = TestCode.range();
1531 ReplacementEdit.newText = "->";
1532 for (const auto &C : Results.Completions) {
1533 EXPECT_TRUE(C.FixIts.empty() || C.Name == "AuxFunction");
1534 if (!C.FixIts.empty()) {
1535 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
1536 }
1537 }
1538}
1539
Kadir Cetinkayaa9c9d002018-08-13 08:23:01 +00001540TEST(CompletionTest, RenderWithFixItMerged) {
1541 TextEdit FixIt;
1542 FixIt.range.end.character = 5;
1543 FixIt.newText = "->";
1544
1545 CodeCompletion C;
1546 C.Name = "x";
1547 C.RequiredQualifier = "Foo::";
1548 C.FixIts = {FixIt};
1549 C.CompletionTokenRange.start.character = 5;
1550
1551 CodeCompleteOptions Opts;
1552 Opts.IncludeFixIts = true;
1553
1554 auto R = C.render(Opts);
1555 EXPECT_TRUE(R.textEdit);
1556 EXPECT_EQ(R.textEdit->newText, "->Foo::x");
1557 EXPECT_TRUE(R.additionalTextEdits.empty());
1558}
1559
1560TEST(CompletionTest, RenderWithFixItNonMerged) {
1561 TextEdit FixIt;
1562 FixIt.range.end.character = 4;
1563 FixIt.newText = "->";
1564
1565 CodeCompletion C;
1566 C.Name = "x";
1567 C.RequiredQualifier = "Foo::";
1568 C.FixIts = {FixIt};
1569 C.CompletionTokenRange.start.character = 5;
1570
1571 CodeCompleteOptions Opts;
1572 Opts.IncludeFixIts = true;
1573
1574 auto R = C.render(Opts);
1575 EXPECT_TRUE(R.textEdit);
1576 EXPECT_EQ(R.textEdit->newText, "Foo::x");
1577 EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
1578}
1579
1580TEST(CompletionTest, CompletionTokenRange) {
1581 MockFSProvider FS;
1582 MockCompilationDatabase CDB;
1583 IgnoreDiagnostics DiagConsumer;
1584 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1585
1586 constexpr const char *TestCodes[] = {
1587 R"cpp(
1588 class Auxilary {
1589 public:
1590 void AuxFunction();
1591 };
1592 void f() {
1593 Auxilary x;
1594 x.[[Aux]]^;
1595 }
1596 )cpp",
1597 R"cpp(
1598 class Auxilary {
1599 public:
1600 void AuxFunction();
1601 };
1602 void f() {
1603 Auxilary x;
1604 x.[[]]^;
1605 }
1606 )cpp"};
1607 for (const auto &Text : TestCodes) {
1608 Annotations TestCode(Text);
1609 auto Results = completions(Server, TestCode.code(), TestCode.point());
1610
1611 EXPECT_EQ(Results.Completions.size(), 1u);
1612 EXPECT_THAT(Results.Completions.front().CompletionTokenRange, TestCode.range());
1613 }
1614}
1615
Kadir Cetinkayae486e372018-08-13 08:40:05 +00001616TEST(SignatureHelpTest, OverloadsOrdering) {
1617 const auto Results = signatures(R"cpp(
1618 void foo(int x);
1619 void foo(int x, float y);
1620 void foo(float x, int y);
1621 void foo(float x, float y);
1622 void foo(int x, int y = 0);
1623 int main() { foo(^); }
1624 )cpp");
1625 EXPECT_THAT(
1626 Results.signatures,
1627 ElementsAre(
1628 Sig("foo(int x) -> void", {"int x"}),
1629 Sig("foo(int x, int y = 0) -> void", {"int x", "int y = 0"}),
1630 Sig("foo(float x, int y) -> void", {"float x", "int y"}),
1631 Sig("foo(int x, float y) -> void", {"int x", "float y"}),
1632 Sig("foo(float x, float y) -> void", {"float x", "float y"})));
1633 // We always prefer the first signature.
1634 EXPECT_EQ(0, Results.activeSignature);
1635 EXPECT_EQ(0, Results.activeParameter);
1636}
1637
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001638TEST(SignatureHelpTest, InstantiatedSignatures) {
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001639 StringRef Sig0 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001640 template <class T>
1641 void foo(T, T, T);
1642
1643 int main() {
1644 foo<int>(^);
1645 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001646 )cpp";
1647
1648 EXPECT_THAT(signatures(Sig0).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001649 ElementsAre(Sig("foo(T, T, T) -> void", {"T", "T", "T"})));
1650
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001651 StringRef Sig1 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001652 template <class T>
1653 void foo(T, T, T);
1654
1655 int main() {
1656 foo(10, ^);
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001657 })cpp";
1658
1659 EXPECT_THAT(signatures(Sig1).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001660 ElementsAre(Sig("foo(T, T, T) -> void", {"T", "T", "T"})));
1661
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001662 StringRef Sig2 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001663 template <class ...T>
1664 void foo(T...);
1665
1666 int main() {
1667 foo<int>(^);
1668 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001669 )cpp";
1670
1671 EXPECT_THAT(signatures(Sig2).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001672 ElementsAre(Sig("foo(T...) -> void", {"T..."})));
1673
1674 // It is debatable whether we should substitute the outer template parameter
1675 // ('T') in that case. Currently we don't substitute it in signature help, but
1676 // do substitute in code complete.
1677 // FIXME: make code complete and signature help consistent, figure out which
1678 // way is better.
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001679 StringRef Sig3 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001680 template <class T>
1681 struct X {
1682 template <class U>
1683 void foo(T, U);
1684 };
1685
1686 int main() {
1687 X<int>().foo<double>(^)
1688 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001689 )cpp";
1690
1691 EXPECT_THAT(signatures(Sig3).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001692 ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
1693}
1694
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001695TEST(SignatureHelpTest, IndexDocumentation) {
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001696 Symbol Foo0 = sym("foo", index::SymbolKind::Function, "@F@\\0#");
Sam McCall2e5700f2018-08-31 13:55:01 +00001697 Foo0.Documentation = "Doc from the index";
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001698 Symbol Foo1 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#");
Sam McCall2e5700f2018-08-31 13:55:01 +00001699 Foo1.Documentation = "Doc from the index";
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001700 Symbol Foo2 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#I#");
1701
Simon Pilgrim24d34922018-08-17 10:40:05 +00001702 StringRef Sig0 = R"cpp(
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001703 int foo();
1704 int foo(double);
1705
1706 void test() {
1707 foo(^);
1708 }
Simon Pilgrim24d34922018-08-17 10:40:05 +00001709 )cpp";
1710
1711 EXPECT_THAT(
1712 signatures(Sig0, {Foo0}).signatures,
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001713 ElementsAre(AllOf(Sig("foo() -> int", {}), SigDoc("Doc from the index")),
1714 AllOf(Sig("foo(double) -> int", {"double"}), SigDoc(""))));
1715
Simon Pilgrim24d34922018-08-17 10:40:05 +00001716 StringRef Sig1 = R"cpp(
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001717 int foo();
1718 // Overriden doc from sema
1719 int foo(int);
1720 // Doc from sema
1721 int foo(int, int);
1722
1723 void test() {
1724 foo(^);
1725 }
Simon Pilgrim24d34922018-08-17 10:40:05 +00001726 )cpp";
1727
1728 EXPECT_THAT(
1729 signatures(Sig1, {Foo0, Foo1, Foo2}).signatures,
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001730 ElementsAre(AllOf(Sig("foo() -> int", {}), SigDoc("Doc from the index")),
1731 AllOf(Sig("foo(int) -> int", {"int"}),
1732 SigDoc("Overriden doc from sema")),
1733 AllOf(Sig("foo(int, int) -> int", {"int", "int"}),
1734 SigDoc("Doc from sema"))));
1735}
1736
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001737TEST(CompletionTest, CompletionFunctionArgsDisabled) {
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001738 CodeCompleteOptions Opts;
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001739 Opts.EnableSnippets = true;
1740 Opts.EnableFunctionArgSnippets = false;
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001741 const std::string Header =
1742 R"cpp(
1743 void xfoo();
1744 void xfoo(int x, int y);
1745 void xbar();
1746 void f() {
1747 )cpp";
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001748 {
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001749 auto Results = completions(Header + "\nxfo^", {}, Opts);
1750 EXPECT_THAT(
1751 Results.Completions,
1752 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("()")),
1753 AllOf(Named("xfoo"), SnippetSuffix("($0)"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001754 }
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001755 {
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001756 auto Results = completions(Header + "\nxba^", {}, Opts);
1757 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
1758 Named("xbar"), SnippetSuffix("()"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001759 }
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001760 {
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001761 Opts.BundleOverloads = true;
1762 auto Results = completions(Header + "\nxfo^", {}, Opts);
1763 EXPECT_THAT(
1764 Results.Completions,
1765 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("($0)"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001766 }
1767}
1768
Kadir Cetinkayaf8b85a32018-08-23 13:14:50 +00001769TEST(CompletionTest, SuggestOverrides) {
1770 constexpr const char *const Text(R"cpp(
1771 class A {
1772 public:
1773 virtual void vfunc(bool param);
1774 virtual void vfunc(bool param, int p);
1775 void func(bool param);
1776 };
1777 class B : public A {
1778 virtual void ttt(bool param) const;
1779 void vfunc(bool param, int p) override;
1780 };
1781 class C : public B {
1782 public:
1783 void vfunc(bool param) override;
1784 ^
1785 };
1786 )cpp");
1787 const auto Results = completions(Text);
1788 EXPECT_THAT(Results.Completions,
1789 AllOf(Contains(Labeled("void vfunc(bool param, int p) override")),
1790 Contains(Labeled("void ttt(bool param) const override")),
1791 Not(Contains(Labeled("void vfunc(bool param) override")))));
1792}
1793
Ilya Biryukov5a79d1e2018-09-03 15:25:27 +00001794TEST(CompletionTest, OverridesNonIdentName) {
1795 // Check the completions call does not crash.
1796 completions(R"cpp(
1797 struct Base {
1798 virtual ~Base() = 0;
1799 virtual operator int() = 0;
1800 virtual Base& operator+(Base&) = 0;
1801 };
1802
1803 struct Derived : Base {
1804 ^
1805 };
1806 )cpp");
1807}
1808
Eric Liu25d74e92018-08-24 11:23:56 +00001809TEST(SpeculateCompletionFilter, Filters) {
1810 Annotations F(R"cpp($bof^
1811 $bol^
1812 ab$ab^
1813 x.ab$dot^
1814 x.$dotempty^
1815 x::ab$scoped^
1816 x::$scopedempty^
1817
1818 )cpp");
1819 auto speculate = [&](StringRef PointName) {
1820 auto Filter = speculateCompletionFilter(F.code(), F.point(PointName));
1821 assert(Filter);
1822 return *Filter;
1823 };
1824 EXPECT_EQ(speculate("bof"), "");
1825 EXPECT_EQ(speculate("bol"), "");
1826 EXPECT_EQ(speculate("ab"), "ab");
1827 EXPECT_EQ(speculate("dot"), "ab");
1828 EXPECT_EQ(speculate("dotempty"), "");
1829 EXPECT_EQ(speculate("scoped"), "ab");
1830 EXPECT_EQ(speculate("scopedempty"), "");
1831}
1832
1833TEST(CompletionTest, EnableSpeculativeIndexRequest) {
1834 MockFSProvider FS;
1835 MockCompilationDatabase CDB;
1836 IgnoreDiagnostics DiagConsumer;
1837 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1838
1839 auto File = testPath("foo.cpp");
1840 Annotations Test(R"cpp(
1841 namespace ns1 { int abc; }
1842 namespace ns2 { int abc; }
1843 void f() { ns1::ab$1^; ns1::ab$2^; }
1844 void f() { ns2::ab$3^; }
1845 )cpp");
1846 runAddDocument(Server, File, Test.code());
1847 clangd::CodeCompleteOptions Opts = {};
1848
1849 IndexRequestCollector Requests;
1850 Opts.Index = &Requests;
1851 Opts.SpeculativeIndexRequest = true;
1852
1853 auto CompleteAtPoint = [&](StringRef P) {
1854 cantFail(runCodeComplete(Server, File, Test.point(P), Opts));
1855 // Sleep for a while to make sure asynchronous call (if applicable) is also
1856 // triggered before callback is invoked.
1857 std::this_thread::sleep_for(std::chrono::milliseconds(100));
1858 };
1859
1860 CompleteAtPoint("1");
1861 auto Reqs1 = Requests.consumeRequests();
1862 ASSERT_EQ(Reqs1.size(), 1u);
1863 EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre("ns1::"));
1864
1865 CompleteAtPoint("2");
1866 auto Reqs2 = Requests.consumeRequests();
1867 // Speculation succeeded. Used speculative index result.
1868 ASSERT_EQ(Reqs2.size(), 1u);
1869 EXPECT_EQ(Reqs2[0], Reqs1[0]);
1870
1871 CompleteAtPoint("3");
1872 // Speculation failed. Sent speculative index request and the new index
1873 // request after sema.
1874 auto Reqs3 = Requests.consumeRequests();
1875 ASSERT_EQ(Reqs3.size(), 2u);
1876}
1877
Eric Liu83f63e42018-09-03 10:18:21 +00001878TEST(CompletionTest, InsertTheMostPopularHeader) {
1879 std::string DeclFile = URI::createFile(testPath("foo")).toString();
1880 Symbol sym = func("Func");
1881 sym.CanonicalDeclaration.FileURI = DeclFile;
1882 sym.IncludeHeaders.emplace_back("\"foo.h\"", 2);
1883 sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000);
1884
1885 auto Results = completions("Fun^", {sym}).Completions;
1886 assert(!Results.empty());
1887 EXPECT_THAT(Results[0], AllOf(Named("Func"), InsertInclude("\"bar.h\"")));
1888 EXPECT_EQ(Results[0].Includes.size(), 2u);
1889}
1890
1891TEST(CompletionTest, NoInsertIncludeIfOnePresent) {
1892 MockFSProvider FS;
1893 MockCompilationDatabase CDB;
1894
1895 std::string FooHeader = testPath("foo.h");
1896 FS.Files[FooHeader] = "";
1897
1898 IgnoreDiagnostics DiagConsumer;
1899 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1900
1901 std::string DeclFile = URI::createFile(testPath("foo")).toString();
1902 Symbol sym = func("Func");
1903 sym.CanonicalDeclaration.FileURI = DeclFile;
1904 sym.IncludeHeaders.emplace_back("\"foo.h\"", 2);
1905 sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000);
1906
1907 EXPECT_THAT(
1908 completions(Server, "#include \"foo.h\"\nFun^", {sym}).Completions,
1909 UnorderedElementsAre(
1910 AllOf(Named("Func"), HasInclude("\"foo.h\""), Not(InsertInclude()))));
1911}
1912
Eric Liud25f1212018-09-06 09:59:37 +00001913TEST(CompletionTest, MergeMacrosFromIndexAndSema) {
1914 Symbol Sym;
1915 Sym.Name = "Clangd_Macro_Test";
1916 Sym.ID = SymbolID("c:foo.cpp@8@macro@Clangd_Macro_Test");
1917 Sym.SymInfo.Kind = index::SymbolKind::Macro;
Eric Liu6df66002018-09-06 18:52:26 +00001918 Sym.Flags |= Symbol::IndexedForCodeCompletion;
Eric Liud25f1212018-09-06 09:59:37 +00001919 EXPECT_THAT(completions("#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym})
1920 .Completions,
1921 UnorderedElementsAre(Named("Clangd_Macro_Test")));
1922}
1923
Eric Liu6df66002018-09-06 18:52:26 +00001924TEST(CompletionTest, DeprecatedResults) {
1925 std::string Body = R"cpp(
1926 void TestClangd();
1927 void TestClangc() __attribute__((deprecated("", "")));
1928 )cpp";
1929
1930 EXPECT_THAT(
1931 completions(Body + "int main() { TestClang^ }").Completions,
1932 UnorderedElementsAre(AllOf(Named("TestClangd"), Not(Deprecated())),
1933 AllOf(Named("TestClangc"), Deprecated())));
1934}
1935
Kadir Cetinkaya0b77d032018-09-10 14:22:42 +00001936TEST(SignatureHelpTest, InsideArgument) {
1937 {
1938 const auto Results = signatures(R"cpp(
1939 void foo(int x);
1940 void foo(int x, int y);
1941 int main() { foo(1+^); }
1942 )cpp");
1943 EXPECT_THAT(
1944 Results.signatures,
1945 ElementsAre(Sig("foo(int x) -> void", {"int x"}),
1946 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
1947 EXPECT_EQ(0, Results.activeParameter);
1948 }
1949 {
1950 const auto Results = signatures(R"cpp(
1951 void foo(int x);
1952 void foo(int x, int y);
1953 int main() { foo(1^); }
1954 )cpp");
1955 EXPECT_THAT(
1956 Results.signatures,
1957 ElementsAre(Sig("foo(int x) -> void", {"int x"}),
1958 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
1959 EXPECT_EQ(0, Results.activeParameter);
1960 }
1961 {
1962 const auto Results = signatures(R"cpp(
1963 void foo(int x);
1964 void foo(int x, int y);
1965 int main() { foo(1^0); }
1966 )cpp");
1967 EXPECT_THAT(
1968 Results.signatures,
1969 ElementsAre(Sig("foo(int x) -> void", {"int x"}),
1970 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
1971 EXPECT_EQ(0, Results.activeParameter);
1972 }
1973 {
1974 const auto Results = signatures(R"cpp(
1975 void foo(int x);
1976 void foo(int x, int y);
1977 int bar(int x, int y);
1978 int main() { bar(foo(2, 3^)); }
1979 )cpp");
1980 EXPECT_THAT(Results.signatures, ElementsAre(Sig("foo(int x, int y) -> void",
1981 {"int x", "int y"})));
1982 EXPECT_EQ(1, Results.activeParameter);
1983 }
1984}
1985
Kadir Cetinkaya873cae52018-09-11 15:12:10 +00001986TEST(SignatureHelpTest, ConstructorInitializeFields) {
1987 {
1988 const auto Results = signatures(R"cpp(
1989 struct A {
1990 A(int);
1991 };
1992 struct B {
1993 B() : a_elem(^) {}
1994 A a_elem;
1995 };
1996 )cpp");
1997 EXPECT_THAT(Results.signatures, UnorderedElementsAre(
1998 Sig("A(int)", {"int"}),
1999 Sig("A(A &&)", {"A &&"}),
2000 Sig("A(const A &)", {"const A &"})
2001 ));
2002 }
2003 {
2004 const auto Results = signatures(R"cpp(
2005 struct A {
2006 A(int);
2007 };
2008 struct C {
2009 C(int);
2010 C(A);
2011 };
2012 struct B {
2013 B() : c_elem(A(1^)) {}
2014 C c_elem;
2015 };
2016 )cpp");
2017 EXPECT_THAT(Results.signatures, UnorderedElementsAre(
2018 Sig("A(int)", {"int"}),
2019 Sig("A(A &&)", {"A &&"}),
2020 Sig("A(const A &)", {"const A &"})
2021 ));
2022 }
2023}
2024
Sam McCall9aad25f2017-12-05 07:20:26 +00002025} // namespace
2026} // namespace clangd
2027} // namespace clang