blob: 3e60b6273a457af14cec71af77f3d93c72b989ad [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
Sam McCallc008af62018-10-20 15:30:37 +000027using namespace llvm;
Sam McCall9aad25f2017-12-05 07:20:26 +000028namespace clang {
29namespace clangd {
Sam McCallf6ae3232017-12-05 20:11:29 +000030
Sam McCall9aad25f2017-12-05 07:20:26 +000031namespace {
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("::");
Sam McCallc008af62018-10-20 15:30:37 +0000154 if (Pos == StringRef::npos) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000155 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(
Sam McCall44fdcec22017-12-08 15:00:59 +0000226 int global_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000227
Sam McCall44fdcec22017-12-08 15:00:59 +0000228 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000229
Eric Liu467c5f92018-09-19 09:35:04 +0000230 // Make sure this is not in preamble.
231 #define MACRO X
232
Sam McCall44fdcec22017-12-08 15:00:59 +0000233 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000234
Sam McCall44fdcec22017-12-08 15:00:59 +0000235 struct ClassWithMembers {
236 /// Doc for method.
237 int method();
Sam McCall9aad25f2017-12-05 07:20:26 +0000238
Sam McCall44fdcec22017-12-08 15:00:59 +0000239 int field;
240 private:
241 int private_field;
242 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000243
Sam McCall44fdcec22017-12-08 15:00:59 +0000244 int test() {
245 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000246
Sam McCall44fdcec22017-12-08 15:00:59 +0000247 /// Doc for local_var.
248 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000249
Sam McCall44fdcec22017-12-08 15:00:59 +0000250 ClassWithMembers().^
251 }
252 )cpp",
Sam McCall545a20d2018-01-19 14:34:02 +0000253 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000254
Sam McCallf6ae3232017-12-05 20:11:29 +0000255 // Class members. The only items that must be present in after-dot
256 // completion.
Sam McCalle746a2b2018-07-02 11:13:16 +0000257 EXPECT_THAT(Results.Completions,
258 AllOf(Has("method"), Has("field"), Not(Has("ClassWithMembers")),
Sam McCall4caa8512018-06-07 12:49:17 +0000259 Not(Has("operator=")), Not(Has("~ClassWithMembers"))));
Sam McCalle746a2b2018-07-02 11:13:16 +0000260 EXPECT_IFF(Opts.IncludeIneligibleResults, Results.Completions,
Sam McCall44fdcec22017-12-08 15:00:59 +0000261 Has("private_field"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000262 // Global items.
Sam McCall545a20d2018-01-19 14:34:02 +0000263 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +0000264 Results.Completions,
Sam McCall545a20d2018-01-19 14:34:02 +0000265 Not(AnyOf(Has("global_var"), Has("index_var"), Has("global_func"),
266 Has("global_func()"), Has("index_func"), Has("GlobalClass"),
267 Has("IndexClass"), Has("MACRO"), Has("LocalClass"))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000268 // There should be no code patterns (aka snippets) in after-dot
269 // completion. At least there aren't any we're aware of.
Sam McCalle746a2b2018-07-02 11:13:16 +0000270 EXPECT_THAT(Results.Completions,
271 Not(Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000272 // Check documentation.
Sam McCalle746a2b2018-07-02 11:13:16 +0000273 EXPECT_IFF(Opts.IncludeComments, Results.Completions,
274 Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000275}
Sam McCall9aad25f2017-12-05 07:20:26 +0000276
Sam McCallf6ae3232017-12-05 20:11:29 +0000277void TestGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000278 auto Results = completions(
279 R"cpp(
Sam McCall44fdcec22017-12-08 15:00:59 +0000280 int global_var;
281 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000282
Eric Liu467c5f92018-09-19 09:35:04 +0000283 // Make sure this is not in preamble.
284 #define MACRO X
285
Sam McCall44fdcec22017-12-08 15:00:59 +0000286 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000287
Sam McCall44fdcec22017-12-08 15:00:59 +0000288 struct ClassWithMembers {
289 /// Doc for method.
290 int method();
291 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000292
Sam McCall44fdcec22017-12-08 15:00:59 +0000293 int test() {
294 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000295
Sam McCall44fdcec22017-12-08 15:00:59 +0000296 /// Doc for local_var.
297 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000298
Sam McCall44fdcec22017-12-08 15:00:59 +0000299 ^
300 }
301 )cpp",
Sam McCall545a20d2018-01-19 14:34:02 +0000302 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
Sam McCallf6ae3232017-12-05 20:11:29 +0000303
304 // Class members. Should never be present in global completions.
Sam McCalle746a2b2018-07-02 11:13:16 +0000305 EXPECT_THAT(Results.Completions,
Sam McCallf6ae3232017-12-05 20:11:29 +0000306 Not(AnyOf(Has("method"), Has("method()"), Has("field"))));
307 // Global items.
Sam McCalle746a2b2018-07-02 11:13:16 +0000308 EXPECT_THAT(Results.Completions,
309 AllOf(Has("global_var"), Has("index_var"), Has("global_func"),
Sam McCall545a20d2018-01-19 14:34:02 +0000310 Has("index_func" /* our fake symbol doesn't include () */),
311 Has("GlobalClass"), Has("IndexClass")));
Sam McCallf6ae3232017-12-05 20:11:29 +0000312 // A macro.
Sam McCalle746a2b2018-07-02 11:13:16 +0000313 EXPECT_IFF(Opts.IncludeMacros, Results.Completions, Has("MACRO"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000314 // Local items. Must be present always.
Sam McCalle746a2b2018-07-02 11:13:16 +0000315 EXPECT_THAT(Results.Completions,
Ilya Biryukov9b5ffc22017-12-12 12:56:46 +0000316 AllOf(Has("local_var"), Has("LocalClass"),
317 Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000318 // Check documentation.
Sam McCalle746a2b2018-07-02 11:13:16 +0000319 EXPECT_IFF(Opts.IncludeComments, Results.Completions,
320 Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000321}
322
323TEST(CompletionTest, CompletionOptions) {
Sam McCall2c3849a2018-01-16 12:21:24 +0000324 auto Test = [&](const clangd::CodeCompleteOptions &Opts) {
325 TestAfterDotCompletion(Opts);
326 TestGlobalScopeCompletion(Opts);
327 };
328 // We used to test every combination of options, but that got too slow (2^N).
329 auto Flags = {
Ilya Biryukov71028b82018-03-12 15:28:22 +0000330 &clangd::CodeCompleteOptions::IncludeMacros,
Ilya Biryukov43714502018-05-16 12:32:44 +0000331 &clangd::CodeCompleteOptions::IncludeComments,
Ilya Biryukov71028b82018-03-12 15:28:22 +0000332 &clangd::CodeCompleteOptions::IncludeCodePatterns,
333 &clangd::CodeCompleteOptions::IncludeIneligibleResults,
Sam McCall2c3849a2018-01-16 12:21:24 +0000334 };
335 // Test default options.
336 Test({});
337 // Test with one flag flipped.
338 for (auto &F : Flags) {
339 clangd::CodeCompleteOptions O;
340 O.*F ^= true;
341 Test(O);
Sam McCall9aad25f2017-12-05 07:20:26 +0000342 }
343}
344
Sam McCall44fdcec22017-12-08 15:00:59 +0000345TEST(CompletionTest, Priorities) {
346 auto Internal = completions(R"cpp(
347 class Foo {
348 public: void pub();
349 protected: void prot();
350 private: void priv();
351 };
352 void Foo::pub() { this->^ }
353 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000354 EXPECT_THAT(Internal.Completions,
Sam McCall44fdcec22017-12-08 15:00:59 +0000355 HasSubsequence(Named("priv"), Named("prot"), Named("pub")));
356
357 auto External = completions(R"cpp(
358 class Foo {
359 public: void pub();
360 protected: void prot();
361 private: void priv();
362 };
363 void test() {
364 Foo F;
365 F.^
366 }
367 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000368 EXPECT_THAT(External.Completions,
Sam McCall44fdcec22017-12-08 15:00:59 +0000369 AllOf(Has("pub"), Not(Has("prot")), Not(Has("priv"))));
370}
371
372TEST(CompletionTest, Qualifiers) {
373 auto Results = completions(R"cpp(
374 class Foo {
375 public: int foo() const;
376 int bar() const;
377 };
378 class Bar : public Foo {
379 int foo() const;
380 };
381 void test() { Bar().^ }
382 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000383 EXPECT_THAT(Results.Completions,
Sam McCalle8437cb2018-10-24 13:51:44 +0000384 Contains(AllOf(Qualifier(""), Named("bar"))));
385 // Hidden members are not shown.
Sam McCalle746a2b2018-07-02 11:13:16 +0000386 EXPECT_THAT(Results.Completions,
Sam McCalle8437cb2018-10-24 13:51:44 +0000387 Not(Contains(AllOf(Qualifier("Foo::"), Named("foo")))));
388 // Private members are not shown.
389 EXPECT_THAT(Results.Completions,
390 Not(Contains(AllOf(Qualifier(""), Named("foo")))));
Sam McCall44fdcec22017-12-08 15:00:59 +0000391}
392
Sam McCall4caa8512018-06-07 12:49:17 +0000393TEST(CompletionTest, InjectedTypename) {
394 // These are suppressed when accessed as a member...
Sam McCalle746a2b2018-07-02 11:13:16 +0000395 EXPECT_THAT(completions("struct X{}; void foo(){ X().^ }").Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000396 Not(Has("X")));
Sam McCalle746a2b2018-07-02 11:13:16 +0000397 EXPECT_THAT(completions("struct X{ void foo(){ this->^ } };").Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000398 Not(Has("X")));
399 // ...but accessible in other, more useful cases.
Sam McCalle746a2b2018-07-02 11:13:16 +0000400 EXPECT_THAT(completions("struct X{ void foo(){ ^ } };").Completions,
401 Has("X"));
402 EXPECT_THAT(
403 completions("struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions,
404 Has("Y"));
Sam McCall4caa8512018-06-07 12:49:17 +0000405 EXPECT_THAT(
406 completions(
407 "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };")
Sam McCalle746a2b2018-07-02 11:13:16 +0000408 .Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000409 Has("Y"));
410 // This case is marginal (`using X::X` is useful), we allow it for now.
Sam McCalle746a2b2018-07-02 11:13:16 +0000411 EXPECT_THAT(completions("struct X{}; void foo(){ X::^ }").Completions,
412 Has("X"));
Sam McCall4caa8512018-06-07 12:49:17 +0000413}
414
Sam McCall44fdcec22017-12-08 15:00:59 +0000415TEST(CompletionTest, Snippets) {
416 clangd::CodeCompleteOptions Opts;
Sam McCall44fdcec22017-12-08 15:00:59 +0000417 auto Results = completions(
418 R"cpp(
419 struct fake {
420 int a;
421 int f(int i, const float f) const;
422 };
423 int main() {
424 fake f;
425 f.^
426 }
427 )cpp",
Sam McCalla15c2d62018-01-18 09:27:56 +0000428 /*IndexSymbols=*/{}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000429 EXPECT_THAT(
430 Results.Completions,
431 HasSubsequence(Named("a"),
432 SnippetSuffix("(${1:int i}, ${2:const float f})")));
Sam McCall44fdcec22017-12-08 15:00:59 +0000433}
434
435TEST(CompletionTest, Kinds) {
Sam McCall545a20d2018-01-19 14:34:02 +0000436 auto Results = completions(
437 R"cpp(
Sam McCall545a20d2018-01-19 14:34:02 +0000438 int variable;
439 struct Struct {};
440 int function();
Eric Liu467c5f92018-09-19 09:35:04 +0000441 // make sure MACRO is not included in preamble.
442 #define MACRO 10
Sam McCall545a20d2018-01-19 14:34:02 +0000443 int X = ^
444 )cpp",
445 {func("indexFunction"), var("indexVariable"), cls("indexClass")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000446 EXPECT_THAT(Results.Completions,
Sam McCall545a20d2018-01-19 14:34:02 +0000447 AllOf(Has("function", CompletionItemKind::Function),
448 Has("variable", CompletionItemKind::Variable),
449 Has("int", CompletionItemKind::Keyword),
450 Has("Struct", CompletionItemKind::Class),
451 Has("MACRO", CompletionItemKind::Text),
452 Has("indexFunction", CompletionItemKind::Function),
453 Has("indexVariable", CompletionItemKind::Variable),
454 Has("indexClass", CompletionItemKind::Class)));
Sam McCall44fdcec22017-12-08 15:00:59 +0000455
Sam McCall44fdcec22017-12-08 15:00:59 +0000456 Results = completions("nam^");
Sam McCalle746a2b2018-07-02 11:13:16 +0000457 EXPECT_THAT(Results.Completions,
458 Has("namespace", CompletionItemKind::Snippet));
Sam McCall44fdcec22017-12-08 15:00:59 +0000459}
460
Sam McCall84652cc2018-01-12 16:16:09 +0000461TEST(CompletionTest, NoDuplicates) {
Sam McCall545a20d2018-01-19 14:34:02 +0000462 auto Results = completions(
463 R"cpp(
464 class Adapter {
Sam McCall545a20d2018-01-19 14:34:02 +0000465 };
Sam McCall84652cc2018-01-12 16:16:09 +0000466
Eric Liu9b3cba72018-05-30 09:03:39 +0000467 void f() {
Sam McCall545a20d2018-01-19 14:34:02 +0000468 Adapter^
469 }
470 )cpp",
471 {cls("Adapter")});
Sam McCall84652cc2018-01-12 16:16:09 +0000472
473 // Make sure there are no duplicate entries of 'Adapter'.
Sam McCalle746a2b2018-07-02 11:13:16 +0000474 EXPECT_THAT(Results.Completions, ElementsAre(Named("Adapter")));
Sam McCall84652cc2018-01-12 16:16:09 +0000475}
476
Sam McCall545a20d2018-01-19 14:34:02 +0000477TEST(CompletionTest, ScopedNoIndex) {
478 auto Results = completions(
479 R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000480 namespace fake { int BigBang, Babble, Box; };
481 int main() { fake::ba^ }
Sam McCall545a20d2018-01-19 14:34:02 +0000482 ")cpp");
Sam McCall8b2dcc12018-06-14 13:50:30 +0000483 // Babble is a better match than BigBang. Box doesn't match at all.
Sam McCalle746a2b2018-07-02 11:13:16 +0000484 EXPECT_THAT(Results.Completions,
485 ElementsAre(Named("Babble"), Named("BigBang")));
Sam McCall84652cc2018-01-12 16:16:09 +0000486}
487
Sam McCall545a20d2018-01-19 14:34:02 +0000488TEST(CompletionTest, Scoped) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000489 auto Results = completions(
490 R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000491 namespace fake { int Babble, Box; };
492 int main() { fake::ba^ }
Sam McCall545a20d2018-01-19 14:34:02 +0000493 ")cpp",
494 {var("fake::BigBang")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000495 EXPECT_THAT(Results.Completions,
496 ElementsAre(Named("Babble"), Named("BigBang")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000497}
498
Sam McCall545a20d2018-01-19 14:34:02 +0000499TEST(CompletionTest, ScopedWithFilter) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000500 auto Results = completions(
501 R"cpp(
502 void f() { ns::x^ }
503 )cpp",
504 {cls("ns::XYZ"), func("ns::foo")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000505 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("XYZ")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000506}
507
Sam McCalldc8abc42018-05-03 14:53:02 +0000508TEST(CompletionTest, ReferencesAffectRanking) {
Eric Liu84bd5db2018-07-25 11:26:35 +0000509 auto Results = completions("int main() { abs^ }", {ns("absl"), func("absb")});
510 EXPECT_THAT(Results.Completions, HasSubsequence(Named("absb"), Named("absl")));
Sam McCalldc8abc42018-05-03 14:53:02 +0000511 Results = completions("int main() { abs^ }",
Eric Liu84bd5db2018-07-25 11:26:35 +0000512 {withReferences(10000, ns("absl")), func("absb")});
513 EXPECT_THAT(Results.Completions,
514 HasSubsequence(Named("absl"), Named("absb")));
Sam McCalldc8abc42018-05-03 14:53:02 +0000515}
516
Sam McCall545a20d2018-01-19 14:34:02 +0000517TEST(CompletionTest, GlobalQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000518 auto Results = completions(
519 R"cpp(
520 void f() { ::^ }
521 )cpp",
522 {cls("XYZ")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000523 EXPECT_THAT(Results.Completions,
524 AllOf(Has("XYZ", CompletionItemKind::Class),
525 Has("f", CompletionItemKind::Function)));
Sam McCalla15c2d62018-01-18 09:27:56 +0000526}
527
Sam McCall545a20d2018-01-19 14:34:02 +0000528TEST(CompletionTest, FullyQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000529 auto Results = completions(
530 R"cpp(
Sam McCall545a20d2018-01-19 14:34:02 +0000531 namespace ns { void bar(); }
Sam McCalla15c2d62018-01-18 09:27:56 +0000532 void f() { ::ns::^ }
533 )cpp",
534 {cls("ns::XYZ")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000535 EXPECT_THAT(Results.Completions,
536 AllOf(Has("XYZ", CompletionItemKind::Class),
537 Has("bar", CompletionItemKind::Function)));
Sam McCall545a20d2018-01-19 14:34:02 +0000538}
539
540TEST(CompletionTest, SemaIndexMerge) {
541 auto Results = completions(
542 R"cpp(
543 namespace ns { int local; void both(); }
544 void f() { ::ns::^ }
545 )cpp",
546 {func("ns::both"), cls("ns::Index")});
547 // We get results from both index and sema, with no duplicates.
Sam McCall2161ec72018-07-05 06:20:41 +0000548 EXPECT_THAT(Results.Completions,
549 UnorderedElementsAre(
550 AllOf(Named("local"), Origin(SymbolOrigin::AST)),
551 AllOf(Named("Index"), Origin(SymbolOrigin::Static)),
552 AllOf(Named("both"),
553 Origin(SymbolOrigin::AST | SymbolOrigin::Static))));
Sam McCalla15c2d62018-01-18 09:27:56 +0000554}
555
Haojian Wu48b48652018-01-25 09:20:09 +0000556TEST(CompletionTest, SemaIndexMergeWithLimit) {
557 clangd::CodeCompleteOptions Opts;
558 Opts.Limit = 1;
559 auto Results = completions(
560 R"cpp(
561 namespace ns { int local; void both(); }
562 void f() { ::ns::^ }
563 )cpp",
564 {func("ns::both"), cls("ns::Index")}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000565 EXPECT_EQ(Results.Completions.size(), Opts.Limit);
566 EXPECT_TRUE(Results.HasMore);
Haojian Wu48b48652018-01-25 09:20:09 +0000567}
568
Eric Liu63f419a2018-05-15 15:29:32 +0000569TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
570 MockFSProvider FS;
571 MockCompilationDatabase CDB;
572 std::string Subdir = testPath("sub");
Sam McCallc008af62018-10-20 15:30:37 +0000573 std::string SearchDirArg = (Twine("-I") + Subdir).str();
Eric Liu63f419a2018-05-15 15:29:32 +0000574 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
575 std::string BarHeader = testPath("sub/bar.h");
576 FS.Files[BarHeader] = "";
577
578 IgnoreDiagnostics DiagConsumer;
579 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Eric Liu63f419a2018-05-15 15:29:32 +0000580 auto BarURI = URI::createFile(BarHeader).toString();
581 Symbol Sym = cls("ns::X");
582 Sym.CanonicalDeclaration.FileURI = BarURI;
Eric Liu83f63e42018-09-03 10:18:21 +0000583 Sym.IncludeHeaders.emplace_back(BarURI, 1);
Eric Liu63f419a2018-05-15 15:29:32 +0000584 // Shoten include path based on search dirctory and insert.
585 auto Results = completions(Server,
586 R"cpp(
587 int main() { ns::^ }
588 )cpp",
589 {Sym});
Sam McCalle746a2b2018-07-02 11:13:16 +0000590 EXPECT_THAT(Results.Completions,
591 ElementsAre(AllOf(Named("X"), InsertInclude("\"bar.h\""))));
Eric Liu63f419a2018-05-15 15:29:32 +0000592 // Duplicate based on inclusions in preamble.
593 Results = completions(Server,
594 R"cpp(
595 #include "sub/bar.h" // not shortest, so should only match resolved.
596 int main() { ns::^ }
597 )cpp",
598 {Sym});
Sam McCalle746a2b2018-07-02 11:13:16 +0000599 EXPECT_THAT(Results.Completions, ElementsAre(AllOf(Named("X"), Labeled("X"),
600 Not(InsertInclude()))));
Eric Liu63f419a2018-05-15 15:29:32 +0000601}
602
Eric Liu9b3cba72018-05-30 09:03:39 +0000603TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {
604 MockFSProvider FS;
605 MockCompilationDatabase CDB;
606
607 IgnoreDiagnostics DiagConsumer;
608 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Eric Liu9b3cba72018-05-30 09:03:39 +0000609 Symbol SymX = cls("ns::X");
610 Symbol SymY = cls("ns::Y");
611 std::string BarHeader = testPath("bar.h");
612 auto BarURI = URI::createFile(BarHeader).toString();
613 SymX.CanonicalDeclaration.FileURI = BarURI;
614 SymY.CanonicalDeclaration.FileURI = BarURI;
Eric Liu83f63e42018-09-03 10:18:21 +0000615 SymX.IncludeHeaders.emplace_back("<bar>", 1);
616 SymY.IncludeHeaders.emplace_back("<bar>", 1);
Eric Liu9b3cba72018-05-30 09:03:39 +0000617 // Shoten include path based on search dirctory and insert.
618 auto Results = completions(Server,
619 R"cpp(
620 namespace ns {
621 class X;
622 class Y {}
623 }
624 int main() { ns::^ }
625 )cpp",
626 {SymX, SymY});
Sam McCalle746a2b2018-07-02 11:13:16 +0000627 EXPECT_THAT(Results.Completions,
628 ElementsAre(AllOf(Named("X"), Not(InsertInclude())),
629 AllOf(Named("Y"), Not(InsertInclude()))));
Eric Liu9b3cba72018-05-30 09:03:39 +0000630}
631
Sam McCalla15c2d62018-01-18 09:27:56 +0000632TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
633 MockFSProvider FS;
634 MockCompilationDatabase CDB;
635 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000636 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Sam McCalla15c2d62018-01-18 09:27:56 +0000637
Sam McCallc1568062018-02-16 09:41:43 +0000638 FS.Files[testPath("bar.h")] =
Sam McCalld5ea3e32018-01-24 17:53:32 +0000639 R"cpp(namespace ns { struct preamble { int member; }; })cpp";
Sam McCallc1568062018-02-16 09:41:43 +0000640 auto File = testPath("foo.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000641 Annotations Test(R"cpp(
642 #include "bar.h"
643 namespace ns { int local; }
Sam McCalld5ea3e32018-01-24 17:53:32 +0000644 void f() { ns::^; }
645 void f() { ns::preamble().$2^; }
Sam McCalla15c2d62018-01-18 09:27:56 +0000646 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000647 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000648 clangd::CodeCompleteOptions Opts = {};
649
Sam McCalla15c2d62018-01-18 09:27:56 +0000650 auto I = memIndex({var("ns::index")});
651 Opts.Index = I.get();
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000652 auto WithIndex = cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000653 EXPECT_THAT(WithIndex.Completions,
Sam McCalla15c2d62018-01-18 09:27:56 +0000654 UnorderedElementsAre(Named("local"), Named("index")));
Sam McCalld5ea3e32018-01-24 17:53:32 +0000655 auto ClassFromPreamble =
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000656 cantFail(runCodeComplete(Server, File, Test.point("2"), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000657 EXPECT_THAT(ClassFromPreamble.Completions, Contains(Named("member")));
Sam McCall0bb24cd2018-02-13 08:59:23 +0000658
659 Opts.Index = nullptr;
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000660 auto WithoutIndex =
661 cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000662 EXPECT_THAT(WithoutIndex.Completions,
Sam McCall0bb24cd2018-02-13 08:59:23 +0000663 UnorderedElementsAre(Named("local"), Named("preamble")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000664}
665
Sam McCallebef8122018-09-14 12:36:06 +0000666// This verifies that we get normal preprocessor completions in the preamble.
667// This is a regression test for an old bug: if we override the preamble and
668// try to complete inside it, clang kicks our completion point just outside the
669// preamble, resulting in always getting top-level completions.
670TEST(CompletionTest, CompletionInPreamble) {
Sam McCall0be9c4e2018-09-14 18:49:16 +0000671 auto Results = completions(R"cpp(
Sam McCallebef8122018-09-14 12:36:06 +0000672 #ifnd^ef FOO_H_
673 #define BAR_H_
674 #include <bar.h>
675 int foo() {}
676 #endif
677 )cpp")
Sam McCall0be9c4e2018-09-14 18:49:16 +0000678 .Completions;
679 EXPECT_THAT(Results, ElementsAre(Named("ifndef")));
Jonas Tothad515192018-09-14 19:42:37 +0000680}
Sam McCallebef8122018-09-14 12:36:06 +0000681
Sam McCalla15c2d62018-01-18 09:27:56 +0000682TEST(CompletionTest, DynamicIndexMultiFile) {
683 MockFSProvider FS;
684 MockCompilationDatabase CDB;
685 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000686 auto Opts = ClangdServer::optsForTest();
687 Opts.BuildDynamicSymbolIndex = true;
688 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
Sam McCalla15c2d62018-01-18 09:27:56 +0000689
Eric Liu709bde82018-02-19 18:48:44 +0000690 FS.Files[testPath("foo.h")] = R"cpp(
Sam McCalla15c2d62018-01-18 09:27:56 +0000691 namespace ns { class XYZ {}; void foo(int x) {} }
Eric Liu709bde82018-02-19 18:48:44 +0000692 )cpp";
Sam McCall7363a2f2018-03-05 17:28:54 +0000693 runAddDocument(Server, testPath("foo.cpp"), R"cpp(
Eric Liu709bde82018-02-19 18:48:44 +0000694 #include "foo.h"
Sam McCall0bb24cd2018-02-13 08:59:23 +0000695 )cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000696
Sam McCallc1568062018-02-16 09:41:43 +0000697 auto File = testPath("bar.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000698 Annotations Test(R"cpp(
699 namespace ns {
700 class XXX {};
701 /// Doooc
702 void fooooo() {}
703 }
704 void f() { ns::^ }
705 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000706 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000707
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000708 auto Results = cantFail(runCodeComplete(Server, File, Test.point(), {}));
Sam McCalla15c2d62018-01-18 09:27:56 +0000709 // "XYZ" and "foo" are not included in the file being completed but are still
710 // visible through the index.
Sam McCalle746a2b2018-07-02 11:13:16 +0000711 EXPECT_THAT(Results.Completions, Has("XYZ", CompletionItemKind::Class));
712 EXPECT_THAT(Results.Completions, Has("foo", CompletionItemKind::Function));
713 EXPECT_THAT(Results.Completions, Has("XXX", CompletionItemKind::Class));
714 EXPECT_THAT(Results.Completions,
715 Contains((Named("fooooo"), Kind(CompletionItemKind::Function),
716 Doc("Doooc"), ReturnType("void"))));
Sam McCalla15c2d62018-01-18 09:27:56 +0000717}
718
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000719TEST(CompletionTest, Documentation) {
720 auto Results = completions(
721 R"cpp(
722 // Non-doxygen comment.
723 int foo();
724 /// Doxygen comment.
725 /// \param int a
726 int bar(int a);
727 /* Multi-line
728 block comment
729 */
730 int baz();
731
732 int x = ^
733 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000734 EXPECT_THAT(Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000735 Contains(AllOf(Named("foo"), Doc("Non-doxygen comment."))));
736 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +0000737 Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000738 Contains(AllOf(Named("bar"), Doc("Doxygen comment.\n\\param int a"))));
Sam McCalle746a2b2018-07-02 11:13:16 +0000739 EXPECT_THAT(Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000740 Contains(AllOf(Named("baz"), Doc("Multi-line\nblock comment"))));
741}
742
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000743TEST(CompletionTest, GlobalCompletionFiltering) {
744
745 Symbol Class = cls("XYZ");
Eric Liu6df66002018-09-06 18:52:26 +0000746 Class.Flags = static_cast<Symbol::SymbolFlag>(
747 Class.Flags & ~(Symbol::IndexedForCodeCompletion));
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000748 Symbol Func = func("XYZ::foooo");
Eric Liu6df66002018-09-06 18:52:26 +0000749 Func.Flags = static_cast<Symbol::SymbolFlag>(
750 Func.Flags & ~(Symbol::IndexedForCodeCompletion));
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000751
752 auto Results = completions(R"(// void f() {
753 XYZ::foooo^
754 })",
755 {Class, Func});
Sam McCalle746a2b2018-07-02 11:13:16 +0000756 EXPECT_THAT(Results.Completions, IsEmpty());
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000757}
758
Haojian Wu58d208d2018-01-25 09:44:06 +0000759TEST(CodeCompleteTest, DisableTypoCorrection) {
760 auto Results = completions(R"cpp(
761 namespace clang { int v; }
762 void f() { clangd::^
763 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000764 EXPECT_TRUE(Results.Completions.empty());
Haojian Wu58d208d2018-01-25 09:44:06 +0000765}
766
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000767TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
768 auto Results = completions(R"cpp(
769 namespace clang { }
770 void f() {
771 clan^
772 }
773 )cpp");
774
Sam McCalle746a2b2018-07-02 11:13:16 +0000775 EXPECT_THAT(Results.Completions, Contains(Labeled("clang")));
776 EXPECT_THAT(Results.Completions, Not(Contains(Labeled("clang::"))));
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000777}
778
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000779TEST(CompletionTest, BacktrackCrashes) {
780 // Sema calls code completion callbacks twice in these cases.
781 auto Results = completions(R"cpp(
782 namespace ns {
783 struct FooBarBaz {};
784 } // namespace ns
785
786 int foo(ns::FooBar^
787 )cpp");
788
Sam McCalle746a2b2018-07-02 11:13:16 +0000789 EXPECT_THAT(Results.Completions, ElementsAre(Labeled("FooBarBaz")));
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000790
791 // Check we don't crash in that case too.
792 completions(R"cpp(
793 struct FooBarBaz {};
794 void test() {
795 if (FooBarBaz * x^) {}
796 }
797)cpp");
798}
799
Eric Liu42abe412018-05-24 11:20:19 +0000800TEST(CompletionTest, CompleteInMacroWithStringification) {
801 auto Results = completions(R"cpp(
802void f(const char *, int x);
803#define F(x) f(#x, x)
804
805namespace ns {
806int X;
807int Y;
808} // namespace ns
809
810int f(int input_num) {
811 F(ns::^)
812}
813)cpp");
814
Sam McCalle746a2b2018-07-02 11:13:16 +0000815 EXPECT_THAT(Results.Completions,
Eric Liu42abe412018-05-24 11:20:19 +0000816 UnorderedElementsAre(Named("X"), Named("Y")));
817}
818
819TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
820 auto Results = completions(R"cpp(
821void f(const char *, int x);
822#define F(x) f(#x, x)
823
824namespace ns {
825int X;
826
827int f(int input_num) {
828 F(^)
829}
830} // namespace ns
831)cpp");
832
Sam McCalle746a2b2018-07-02 11:13:16 +0000833 EXPECT_THAT(Results.Completions, Contains(Named("X")));
Eric Liu42abe412018-05-24 11:20:19 +0000834}
835
Eric Liu485074f2018-07-11 13:15:31 +0000836TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000837 auto Results = completions(R"cpp(
838 int bar(int param_in_bar) {
839 }
840
841 int foo(int param_in_foo) {
842#if 0
Eric Liu485074f2018-07-11 13:15:31 +0000843 // In recorvery mode, "param_in_foo" will also be suggested among many other
844 // unrelated symbols; however, this is really a special case where this works.
845 // If the #if block is outside of the function, "param_in_foo" is still
846 // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't
847 // really provide useful results in excluded branches.
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000848 par^
849#endif
850 }
851)cpp");
852
Eric Liu485074f2018-07-11 13:15:31 +0000853 EXPECT_TRUE(Results.Completions.empty());
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000854}
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000855SignatureHelp signatures(StringRef Text, Position Point,
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +0000856 std::vector<Symbol> IndexSymbols = {}) {
857 std::unique_ptr<SymbolIndex> Index;
858 if (!IndexSymbols.empty())
859 Index = memIndex(IndexSymbols);
860
Sam McCall800d4372017-12-19 10:29:27 +0000861 MockFSProvider FS;
862 MockCompilationDatabase CDB;
863 IgnoreDiagnostics DiagConsumer;
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +0000864 ClangdServer::Options Opts = ClangdServer::optsForTest();
865 Opts.StaticIndex = Index.get();
866
867 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
Sam McCallc1568062018-02-16 09:41:43 +0000868 auto File = testPath("foo.cpp");
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000869 runAddDocument(Server, File, Text);
870 return cantFail(runSignatureHelp(Server, File, Point));
871}
872
873SignatureHelp signatures(StringRef Text,
874 std::vector<Symbol> IndexSymbols = {}) {
Sam McCall328cbdb2017-12-20 16:06:05 +0000875 Annotations Test(Text);
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000876 return signatures(Test.code(), Test.point(), std::move(IndexSymbols));
Sam McCall800d4372017-12-19 10:29:27 +0000877}
878
879MATCHER_P(ParamsAre, P, "") {
880 if (P.size() != arg.parameters.size())
881 return false;
882 for (unsigned I = 0; I < P.size(); ++I)
883 if (P[I] != arg.parameters[I].label)
884 return false;
885 return true;
886}
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +0000887MATCHER_P(SigDoc, Doc, "") { return arg.documentation == Doc; }
Sam McCall800d4372017-12-19 10:29:27 +0000888
889Matcher<SignatureInformation> Sig(std::string Label,
890 std::vector<std::string> Params) {
Eric Liu8f3678d2018-06-15 13:34:18 +0000891 return AllOf(SigHelpLabeled(Label), ParamsAre(Params));
Sam McCall800d4372017-12-19 10:29:27 +0000892}
893
894TEST(SignatureHelpTest, Overloads) {
895 auto Results = signatures(R"cpp(
896 void foo(int x, int y);
897 void foo(int x, float y);
898 void foo(float x, int y);
899 void foo(float x, float y);
900 void bar(int x, int y = 0);
901 int main() { foo(^); }
902 )cpp");
903 EXPECT_THAT(Results.signatures,
904 UnorderedElementsAre(
905 Sig("foo(float x, float y) -> void", {"float x", "float y"}),
906 Sig("foo(float x, int y) -> void", {"float x", "int y"}),
907 Sig("foo(int x, float y) -> void", {"int x", "float y"}),
908 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
909 // We always prefer the first signature.
910 EXPECT_EQ(0, Results.activeSignature);
911 EXPECT_EQ(0, Results.activeParameter);
912}
913
914TEST(SignatureHelpTest, DefaultArgs) {
915 auto Results = signatures(R"cpp(
916 void bar(int x, int y = 0);
917 void bar(float x = 0, int y = 42);
918 int main() { bar(^
919 )cpp");
920 EXPECT_THAT(Results.signatures,
921 UnorderedElementsAre(
922 Sig("bar(int x, int y = 0) -> void", {"int x", "int y = 0"}),
923 Sig("bar(float x = 0, int y = 42) -> void",
924 {"float x = 0", "int y = 42"})));
925 EXPECT_EQ(0, Results.activeSignature);
926 EXPECT_EQ(0, Results.activeParameter);
927}
928
929TEST(SignatureHelpTest, ActiveArg) {
930 auto Results = signatures(R"cpp(
931 int baz(int a, int b, int c);
932 int main() { baz(baz(1,2,3), ^); }
933 )cpp");
934 EXPECT_THAT(Results.signatures,
935 ElementsAre(Sig("baz(int a, int b, int c) -> int",
936 {"int a", "int b", "int c"})));
937 EXPECT_EQ(0, Results.activeSignature);
938 EXPECT_EQ(1, Results.activeParameter);
939}
940
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000941TEST(SignatureHelpTest, OpeningParen) {
942 llvm::StringLiteral Tests[] = {// Recursive function call.
943 R"cpp(
944 int foo(int a, int b, int c);
945 int main() {
946 foo(foo $p^( foo(10, 10, 10), ^ )));
947 })cpp",
948 // Functional type cast.
949 R"cpp(
950 struct Foo {
951 Foo(int a, int b, int c);
952 };
953 int main() {
954 Foo $p^( 10, ^ );
955 })cpp",
956 // New expression.
957 R"cpp(
958 struct Foo {
959 Foo(int a, int b, int c);
960 };
961 int main() {
962 new Foo $p^( 10, ^ );
963 })cpp",
964 // Macro expansion.
965 R"cpp(
966 int foo(int a, int b, int c);
967 #define FOO foo(
968
969 int main() {
970 // Macro expansions.
971 $p^FOO 10, ^ );
972 })cpp",
973 // Macro arguments.
974 R"cpp(
975 int foo(int a, int b, int c);
976 int main() {
977 #define ID(X) X
978 ID(foo $p^( foo(10), ^ ))
979 })cpp"};
980
981 for (auto Test : Tests) {
982 Annotations Code(Test);
983 EXPECT_EQ(signatures(Code.code(), Code.point()).argListStart,
984 Code.point("p"))
985 << "Test source:" << Test;
986 }
987}
988
Haojian Wu061c73e2018-01-23 11:37:26 +0000989class IndexRequestCollector : public SymbolIndex {
990public:
Sam McCallc008af62018-10-20 15:30:37 +0000991 bool fuzzyFind(const FuzzyFindRequest &Req,
992 function_ref<void(const Symbol &)> Callback) const override {
Ilya Biryukov5c4d6e62018-09-06 11:04:56 +0000993 std::lock_guard<std::mutex> Lock(Mut);
Haojian Wu061c73e2018-01-23 11:37:26 +0000994 Requests.push_back(Req);
Sam McCallab8e3932018-02-19 13:04:41 +0000995 return true;
Haojian Wu061c73e2018-01-23 11:37:26 +0000996 }
997
Eric Liu9ec459f2018-03-14 09:48:05 +0000998 void lookup(const LookupRequest &,
Sam McCallc008af62018-10-20 15:30:37 +0000999 function_ref<void(const Symbol &)>) const override {}
Eric Liu9ec459f2018-03-14 09:48:05 +00001000
Sam McCallb0138312018-09-04 14:39:56 +00001001 void refs(const RefsRequest &,
Sam McCallc008af62018-10-20 15:30:37 +00001002 function_ref<void(const Ref &)>) const override {}
Haojian Wu65ac3212018-08-06 13:14:32 +00001003
Kirill Bobyrevfc890012018-08-24 09:12:54 +00001004 // This is incorrect, but IndexRequestCollector is not an actual index and it
1005 // isn't used in production code.
1006 size_t estimateMemoryUsage() const override { return 0; }
1007
Eric Liu25d74e92018-08-24 11:23:56 +00001008 const std::vector<FuzzyFindRequest> consumeRequests() const {
Ilya Biryukov5c4d6e62018-09-06 11:04:56 +00001009 std::lock_guard<std::mutex> Lock(Mut);
Eric Liu25d74e92018-08-24 11:23:56 +00001010 auto Reqs = std::move(Requests);
1011 Requests = {};
1012 return Reqs;
1013 }
Haojian Wu061c73e2018-01-23 11:37:26 +00001014
1015private:
Ilya Biryukov5c4d6e62018-09-06 11:04:56 +00001016 // We need a mutex to handle async fuzzy find requests.
1017 mutable std::mutex Mut;
Haojian Wu061c73e2018-01-23 11:37:26 +00001018 mutable std::vector<FuzzyFindRequest> Requests;
1019};
1020
Sam McCallc008af62018-10-20 15:30:37 +00001021std::vector<FuzzyFindRequest> captureIndexRequests(StringRef Code) {
Haojian Wu061c73e2018-01-23 11:37:26 +00001022 clangd::CodeCompleteOptions Opts;
1023 IndexRequestCollector Requests;
1024 Opts.Index = &Requests;
1025 completions(Code, {}, Opts);
Eric Liu25d74e92018-08-24 11:23:56 +00001026 return Requests.consumeRequests();
Haojian Wu061c73e2018-01-23 11:37:26 +00001027}
1028
1029TEST(CompletionTest, UnqualifiedIdQuery) {
1030 auto Requests = captureIndexRequests(R"cpp(
1031 namespace std {}
1032 using namespace std;
1033 namespace ns {
1034 void f() {
1035 vec^
1036 }
1037 }
1038 )cpp");
1039
1040 EXPECT_THAT(Requests,
1041 ElementsAre(Field(&FuzzyFindRequest::Scopes,
1042 UnorderedElementsAre("", "ns::", "std::"))));
1043}
1044
Eric Liu3fac4ef2018-10-17 11:19:02 +00001045TEST(CompletionTest, EnclosingScopeComesFirst) {
1046 auto Requests = captureIndexRequests(R"cpp(
1047 namespace std {}
1048 using namespace std;
1049 namespace nx {
1050 namespace ns {
1051 namespace {
1052 void f() {
1053 vec^
1054 }
1055 }
1056 }
1057 }
1058 )cpp");
1059
1060 EXPECT_THAT(Requests,
1061 ElementsAre(Field(
1062 &FuzzyFindRequest::Scopes,
1063 UnorderedElementsAre("", "std::", "nx::ns::", "nx::"))));
1064 EXPECT_EQ(Requests[0].Scopes[0], "nx::ns::");
1065}
1066
Haojian Wu061c73e2018-01-23 11:37:26 +00001067TEST(CompletionTest, ResolvedQualifiedIdQuery) {
1068 auto Requests = captureIndexRequests(R"cpp(
1069 namespace ns1 {}
1070 namespace ns2 {} // ignore
1071 namespace ns3 { namespace nns3 {} }
1072 namespace foo {
1073 using namespace ns1;
1074 using namespace ns3::nns3;
1075 }
1076 namespace ns {
1077 void f() {
1078 foo::^
1079 }
1080 }
1081 )cpp");
1082
1083 EXPECT_THAT(Requests,
1084 ElementsAre(Field(
1085 &FuzzyFindRequest::Scopes,
1086 UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::"))));
1087}
1088
1089TEST(CompletionTest, UnresolvedQualifierIdQuery) {
1090 auto Requests = captureIndexRequests(R"cpp(
1091 namespace a {}
1092 using namespace a;
1093 namespace ns {
1094 void f() {
1095 bar::^
1096 }
1097 } // namespace ns
1098 )cpp");
1099
1100 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1101 UnorderedElementsAre("bar::"))));
1102}
1103
1104TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
1105 auto Requests = captureIndexRequests(R"cpp(
1106 namespace a {}
1107 using namespace a;
1108 namespace ns {
1109 void f() {
1110 ::a::bar::^
1111 }
1112 } // namespace ns
1113 )cpp");
1114
1115 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1116 UnorderedElementsAre("a::bar::"))));
1117}
1118
1119TEST(CompletionTest, EmptyQualifiedQuery) {
1120 auto Requests = captureIndexRequests(R"cpp(
1121 namespace ns {
1122 void f() {
1123 ^
1124 }
1125 } // namespace ns
1126 )cpp");
1127
1128 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1129 UnorderedElementsAre("", "ns::"))));
1130}
1131
1132TEST(CompletionTest, GlobalQualifiedQuery) {
1133 auto Requests = captureIndexRequests(R"cpp(
1134 namespace ns {
1135 void f() {
1136 ::^
1137 }
1138 } // namespace ns
1139 )cpp");
1140
1141 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1142 UnorderedElementsAre(""))));
1143}
1144
Ilya Biryukova907ba42018-05-14 10:50:04 +00001145TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
1146 auto Completions = completions(
1147 R"cpp(
1148 struct Foo {
1149 int SomeNameOfField;
1150 typedef int SomeNameOfTypedefField;
1151 };
1152
1153 Foo::^)cpp",
1154 {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")});
1155
Sam McCalle746a2b2018-07-02 11:13:16 +00001156 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001157 AllOf(Contains(Labeled("SomeNameOfField")),
1158 Contains(Labeled("SomeNameOfTypedefField")),
1159 Not(Contains(Labeled("SomeNameInTheIndex")))));
1160}
1161
1162TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
1163 {
1164 auto Completions = completions(
1165 R"cpp(
1166 template <class T>
1167 void foo() {
1168 T::^
1169 }
1170 )cpp",
1171 {func("::SomeNameInTheIndex")});
1172
Sam McCalle746a2b2018-07-02 11:13:16 +00001173 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001174 Not(Contains(Labeled("SomeNameInTheIndex"))));
1175 }
1176
1177 {
1178 auto Completions = completions(
1179 R"cpp(
1180 template <class T>
1181 void foo() {
1182 T::template Y<int>::^
1183 }
1184 )cpp",
1185 {func("::SomeNameInTheIndex")});
1186
Sam McCalle746a2b2018-07-02 11:13:16 +00001187 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001188 Not(Contains(Labeled("SomeNameInTheIndex"))));
1189 }
1190
1191 {
1192 auto Completions = completions(
1193 R"cpp(
1194 template <class T>
1195 void foo() {
1196 T::foo::^
1197 }
1198 )cpp",
1199 {func("::SomeNameInTheIndex")});
1200
Sam McCalle746a2b2018-07-02 11:13:16 +00001201 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001202 Not(Contains(Labeled("SomeNameInTheIndex"))));
1203 }
1204}
1205
Sam McCallc18c2802018-06-15 11:06:29 +00001206TEST(CompletionTest, OverloadBundling) {
1207 clangd::CodeCompleteOptions Opts;
1208 Opts.BundleOverloads = true;
1209
1210 std::string Context = R"cpp(
1211 struct X {
1212 // Overload with int
1213 int a(int);
1214 // Overload with bool
1215 int a(bool);
1216 int b(float);
1217 };
1218 int GFuncC(int);
1219 int GFuncD(int);
1220 )cpp";
1221
1222 // Member completions are bundled.
Sam McCalle746a2b2018-07-02 11:13:16 +00001223 EXPECT_THAT(completions(Context + "int y = X().^", {}, Opts).Completions,
Sam McCallc18c2802018-06-15 11:06:29 +00001224 UnorderedElementsAre(Labeled("a(…)"), Labeled("b(float)")));
1225
1226 // Non-member completions are bundled, including index+sema.
1227 Symbol NoArgsGFunc = func("GFuncC");
1228 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001229 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
Sam McCallc18c2802018-06-15 11:06:29 +00001230 UnorderedElementsAre(Labeled("GFuncC(…)"), Labeled("GFuncD(int)")));
1231
1232 // Differences in header-to-insert suppress bundling.
Sam McCallc18c2802018-06-15 11:06:29 +00001233 std::string DeclFile = URI::createFile(testPath("foo")).toString();
1234 NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile;
Eric Liu83f63e42018-09-03 10:18:21 +00001235 NoArgsGFunc.IncludeHeaders.emplace_back("<foo>", 1);
Sam McCallc18c2802018-06-15 11:06:29 +00001236 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001237 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1238 UnorderedElementsAre(AllOf(Named("GFuncC"), InsertInclude("<foo>")),
1239 Labeled("GFuncC(int)"), Labeled("GFuncD(int)")));
Sam McCallc18c2802018-06-15 11:06:29 +00001240
1241 // Examine a bundled completion in detail.
Sam McCalle746a2b2018-07-02 11:13:16 +00001242 auto A =
1243 completions(Context + "int y = X().a^", {}, Opts).Completions.front();
1244 EXPECT_EQ(A.Name, "a");
1245 EXPECT_EQ(A.Signature, "(…)");
1246 EXPECT_EQ(A.BundleSize, 2u);
1247 EXPECT_EQ(A.Kind, CompletionItemKind::Method);
1248 EXPECT_EQ(A.ReturnType, "int"); // All overloads return int.
Sam McCallc18c2802018-06-15 11:06:29 +00001249 // For now we just return one of the doc strings arbitrarily.
Sam McCalle746a2b2018-07-02 11:13:16 +00001250 EXPECT_THAT(A.Documentation, AnyOf(HasSubstr("Overload with int"),
Sam McCallc18c2802018-06-15 11:06:29 +00001251 HasSubstr("Overload with bool")));
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001252 EXPECT_EQ(A.SnippetSuffix, "($0)");
Sam McCallc18c2802018-06-15 11:06:29 +00001253}
1254
Ilya Biryukov30b04b12018-05-28 09:54:51 +00001255TEST(CompletionTest, DocumentationFromChangedFileCrash) {
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001256 MockFSProvider FS;
1257 auto FooH = testPath("foo.h");
1258 auto FooCpp = testPath("foo.cpp");
1259 FS.Files[FooH] = R"cpp(
1260 // this is my documentation comment.
1261 int func();
1262 )cpp";
1263 FS.Files[FooCpp] = "";
1264
1265 MockCompilationDatabase CDB;
1266 IgnoreDiagnostics DiagConsumer;
1267 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1268
1269 Annotations Source(R"cpp(
1270 #include "foo.h"
1271 int func() {
1272 // This makes sure we have func from header in the AST.
1273 }
1274 int a = fun^
1275 )cpp");
1276 Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
1277 // We need to wait for preamble to build.
1278 ASSERT_TRUE(Server.blockUntilIdleForTest());
1279
1280 // Change the header file. Completion will reuse the old preamble!
1281 FS.Files[FooH] = R"cpp(
1282 int func();
1283 )cpp";
1284
1285 clangd::CodeCompleteOptions Opts;
1286 Opts.IncludeComments = true;
Sam McCalle746a2b2018-07-02 11:13:16 +00001287 CodeCompleteResult Completions =
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001288 cantFail(runCodeComplete(Server, FooCpp, Source.point(), Opts));
1289 // We shouldn't crash. Unfortunately, current workaround is to not produce
1290 // comments for symbols from headers.
Sam McCalle746a2b2018-07-02 11:13:16 +00001291 EXPECT_THAT(Completions.Completions,
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001292 Contains(AllOf(Not(IsDocumented()), Named("func"))));
1293}
1294
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001295TEST(CompletionTest, NonDocComments) {
1296 MockFSProvider FS;
1297 auto FooCpp = testPath("foo.cpp");
1298 FS.Files[FooCpp] = "";
1299
1300 MockCompilationDatabase CDB;
1301 IgnoreDiagnostics DiagConsumer;
1302 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1303
1304 Annotations Source(R"cpp(
Ilya Biryukovda8dd8b2018-06-27 09:47:20 +00001305 // We ignore namespace comments, for rationale see CodeCompletionStrings.h.
1306 namespace comments_ns {
1307 }
1308
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001309 // ------------------
1310 int comments_foo();
1311
1312 // A comment and a decl are separated by newlines.
1313 // Therefore, the comment shouldn't show up as doc comment.
1314
1315 int comments_bar();
1316
1317 // this comment should be in the results.
1318 int comments_baz();
1319
1320
1321 template <class T>
1322 struct Struct {
1323 int comments_qux();
1324 int comments_quux();
1325 };
1326
1327
1328 // This comment should not be there.
1329
1330 template <class T>
1331 int Struct<T>::comments_qux() {
1332 }
1333
1334 // This comment **should** be in results.
1335 template <class T>
1336 int Struct<T>::comments_quux() {
1337 int a = comments^;
1338 }
1339 )cpp");
Reid Kleckner80274b12018-06-18 18:55:10 +00001340 // FIXME: Auto-completion in a template requires disabling delayed template
1341 // parsing.
1342 CDB.ExtraClangFlags.push_back("-fno-delayed-template-parsing");
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001343 Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
Sam McCalle746a2b2018-07-02 11:13:16 +00001344 CodeCompleteResult Completions = cantFail(runCodeComplete(
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001345 Server, FooCpp, Source.point(), clangd::CodeCompleteOptions()));
1346
1347 // We should not get any of those comments in completion.
1348 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001349 Completions.Completions,
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001350 UnorderedElementsAre(AllOf(Not(IsDocumented()), Named("comments_foo")),
1351 AllOf(IsDocumented(), Named("comments_baz")),
1352 AllOf(IsDocumented(), Named("comments_quux")),
Ilya Biryukovda8dd8b2018-06-27 09:47:20 +00001353 AllOf(Not(IsDocumented()), Named("comments_ns")),
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001354 // FIXME(ibiryukov): the following items should have
1355 // empty documentation, since they are separated from
1356 // a comment with an empty line. Unfortunately, I
1357 // couldn't make Sema tests pass if we ignore those.
1358 AllOf(IsDocumented(), Named("comments_bar")),
1359 AllOf(IsDocumented(), Named("comments_qux"))));
1360}
1361
Ilya Biryukov981a35d2018-05-28 12:11:37 +00001362TEST(CompletionTest, CompleteOnInvalidLine) {
1363 auto FooCpp = testPath("foo.cpp");
1364
1365 MockCompilationDatabase CDB;
1366 IgnoreDiagnostics DiagConsumer;
1367 MockFSProvider FS;
1368 FS.Files[FooCpp] = "// empty file";
1369
1370 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1371 // Run completion outside the file range.
1372 Position Pos;
1373 Pos.line = 100;
1374 Pos.character = 0;
1375 EXPECT_THAT_EXPECTED(
1376 runCodeComplete(Server, FooCpp, Pos, clangd::CodeCompleteOptions()),
1377 Failed());
1378}
1379
Eric Liu7ad16962018-06-22 10:46:59 +00001380TEST(CompletionTest, QualifiedNames) {
1381 auto Results = completions(
1382 R"cpp(
1383 namespace ns { int local; void both(); }
1384 void f() { ::ns::^ }
1385 )cpp",
1386 {func("ns::both"), cls("ns::Index")});
1387 // We get results from both index and sema, with no duplicates.
Sam McCalle746a2b2018-07-02 11:13:16 +00001388 EXPECT_THAT(
1389 Results.Completions,
1390 UnorderedElementsAre(Scope("ns::"), Scope("ns::"), Scope("ns::")));
1391}
1392
1393TEST(CompletionTest, Render) {
1394 CodeCompletion C;
1395 C.Name = "x";
1396 C.Signature = "(bool) const";
1397 C.SnippetSuffix = "(${0:bool})";
1398 C.ReturnType = "int";
1399 C.RequiredQualifier = "Foo::";
1400 C.Scope = "ns::Foo::";
1401 C.Documentation = "This is x().";
Eric Liu83f63e42018-09-03 10:18:21 +00001402 C.Includes.emplace_back();
1403 auto &Include = C.Includes.back();
1404 Include.Header = "\"foo.h\"";
Sam McCalle746a2b2018-07-02 11:13:16 +00001405 C.Kind = CompletionItemKind::Method;
1406 C.Score.Total = 1.0;
Sam McCall4e5742a2018-07-06 11:50:49 +00001407 C.Origin = SymbolOrigin::AST | SymbolOrigin::Static;
Sam McCalle746a2b2018-07-02 11:13:16 +00001408
1409 CodeCompleteOptions Opts;
1410 Opts.IncludeIndicator.Insert = "^";
1411 Opts.IncludeIndicator.NoInsert = "";
1412 Opts.EnableSnippets = false;
1413
1414 auto R = C.render(Opts);
1415 EXPECT_EQ(R.label, "Foo::x(bool) const");
1416 EXPECT_EQ(R.insertText, "Foo::x");
1417 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
1418 EXPECT_EQ(R.filterText, "x");
1419 EXPECT_EQ(R.detail, "int\n\"foo.h\"");
1420 EXPECT_EQ(R.documentation, "This is x().");
1421 EXPECT_THAT(R.additionalTextEdits, IsEmpty());
Sam McCalle746a2b2018-07-02 11:13:16 +00001422 EXPECT_EQ(R.sortText, sortText(1.0, "x"));
Eric Liu6df66002018-09-06 18:52:26 +00001423 EXPECT_FALSE(R.deprecated);
Sam McCalle746a2b2018-07-02 11:13:16 +00001424
1425 Opts.EnableSnippets = true;
1426 R = C.render(Opts);
1427 EXPECT_EQ(R.insertText, "Foo::x(${0:bool})");
1428 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
1429
Eric Liu83f63e42018-09-03 10:18:21 +00001430 Include.Insertion.emplace();
Sam McCalle746a2b2018-07-02 11:13:16 +00001431 R = C.render(Opts);
1432 EXPECT_EQ(R.label, "^Foo::x(bool) const");
1433 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
1434
Sam McCall2161ec72018-07-05 06:20:41 +00001435 Opts.ShowOrigins = true;
1436 R = C.render(Opts);
1437 EXPECT_EQ(R.label, "^[AS]Foo::x(bool) const");
1438
Sam McCalle746a2b2018-07-02 11:13:16 +00001439 C.BundleSize = 2;
1440 R = C.render(Opts);
1441 EXPECT_EQ(R.detail, "[2 overloads]\n\"foo.h\"");
Eric Liu6df66002018-09-06 18:52:26 +00001442
1443 C.Deprecated = true;
1444 R = C.render(Opts);
1445 EXPECT_TRUE(R.deprecated);
Eric Liu7ad16962018-06-22 10:46:59 +00001446}
Ilya Biryukov981a35d2018-05-28 12:11:37 +00001447
Eric Liu485074f2018-07-11 13:15:31 +00001448TEST(CompletionTest, IgnoreRecoveryResults) {
1449 auto Results = completions(
1450 R"cpp(
1451 namespace ns { int NotRecovered() { return 0; } }
1452 void f() {
1453 // Sema enters recovery mode first and then normal mode.
1454 if (auto x = ns::NotRecover^)
1455 }
1456 )cpp");
1457 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("NotRecovered")));
1458}
1459
Eric Liuf433c2d2018-07-18 15:31:14 +00001460TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
1461 auto Results = completions(
1462 R"cpp(
1463 namespace ns {
1464 class X { public: X(); int x_; };
1465 X::X() : x_^(0) {}
1466 }
1467 )cpp");
1468 EXPECT_THAT(Results.Completions,
1469 UnorderedElementsAre(AllOf(Scope("ns::X::"), Named("x_"))));
1470}
1471
Eric Liu5d2a8072018-07-23 10:56:37 +00001472TEST(CompletionTest, CodeCompletionContext) {
1473 auto Results = completions(
1474 R"cpp(
1475 namespace ns {
1476 class X { public: X(); int x_; };
1477 void f() {
1478 X x;
1479 x.^;
1480 }
1481 }
1482 )cpp");
1483
1484 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
1485}
1486
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001487TEST(CompletionTest, FixItForArrowToDot) {
1488 MockFSProvider FS;
1489 MockCompilationDatabase CDB;
1490 IgnoreDiagnostics DiagConsumer;
1491 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1492
1493 CodeCompleteOptions Opts;
1494 Opts.IncludeFixIts = true;
1495 Annotations TestCode(
1496 R"cpp(
1497 class Auxilary {
1498 public:
1499 void AuxFunction();
1500 };
1501 class ClassWithPtr {
1502 public:
1503 void MemberFunction();
1504 Auxilary* operator->() const;
1505 Auxilary* Aux;
1506 };
1507 void f() {
1508 ClassWithPtr x;
1509 x[[->]]^;
1510 }
1511 )cpp");
1512 auto Results =
1513 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1514 EXPECT_EQ(Results.Completions.size(), 3u);
1515
1516 TextEdit ReplacementEdit;
1517 ReplacementEdit.range = TestCode.range();
1518 ReplacementEdit.newText = ".";
1519 for (const auto &C : Results.Completions) {
1520 EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction");
Haojian Wu1793bc92018-08-10 08:34:16 +00001521 if (!C.FixIts.empty()) {
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001522 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
Haojian Wu1793bc92018-08-10 08:34:16 +00001523 }
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001524 }
1525}
1526
1527TEST(CompletionTest, FixItForDotToArrow) {
1528 MockFSProvider FS;
1529 MockCompilationDatabase CDB;
1530 IgnoreDiagnostics DiagConsumer;
1531 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1532
1533 CodeCompleteOptions Opts;
1534 Opts.IncludeFixIts = true;
1535 Annotations TestCode(
1536 R"cpp(
1537 class Auxilary {
1538 public:
1539 void AuxFunction();
1540 };
1541 class ClassWithPtr {
1542 public:
1543 void MemberFunction();
1544 Auxilary* operator->() const;
1545 Auxilary* Aux;
1546 };
1547 void f() {
1548 ClassWithPtr x;
1549 x[[.]]^;
1550 }
1551 )cpp");
1552 auto Results =
1553 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1554 EXPECT_EQ(Results.Completions.size(), 3u);
1555
1556 TextEdit ReplacementEdit;
1557 ReplacementEdit.range = TestCode.range();
1558 ReplacementEdit.newText = "->";
1559 for (const auto &C : Results.Completions) {
1560 EXPECT_TRUE(C.FixIts.empty() || C.Name == "AuxFunction");
1561 if (!C.FixIts.empty()) {
1562 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
1563 }
1564 }
1565}
1566
Kadir Cetinkayaa9c9d002018-08-13 08:23:01 +00001567TEST(CompletionTest, RenderWithFixItMerged) {
1568 TextEdit FixIt;
1569 FixIt.range.end.character = 5;
1570 FixIt.newText = "->";
1571
1572 CodeCompletion C;
1573 C.Name = "x";
1574 C.RequiredQualifier = "Foo::";
1575 C.FixIts = {FixIt};
1576 C.CompletionTokenRange.start.character = 5;
1577
1578 CodeCompleteOptions Opts;
1579 Opts.IncludeFixIts = true;
1580
1581 auto R = C.render(Opts);
1582 EXPECT_TRUE(R.textEdit);
1583 EXPECT_EQ(R.textEdit->newText, "->Foo::x");
1584 EXPECT_TRUE(R.additionalTextEdits.empty());
1585}
1586
1587TEST(CompletionTest, RenderWithFixItNonMerged) {
1588 TextEdit FixIt;
1589 FixIt.range.end.character = 4;
1590 FixIt.newText = "->";
1591
1592 CodeCompletion C;
1593 C.Name = "x";
1594 C.RequiredQualifier = "Foo::";
1595 C.FixIts = {FixIt};
1596 C.CompletionTokenRange.start.character = 5;
1597
1598 CodeCompleteOptions Opts;
1599 Opts.IncludeFixIts = true;
1600
1601 auto R = C.render(Opts);
1602 EXPECT_TRUE(R.textEdit);
1603 EXPECT_EQ(R.textEdit->newText, "Foo::x");
1604 EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
1605}
1606
1607TEST(CompletionTest, CompletionTokenRange) {
1608 MockFSProvider FS;
1609 MockCompilationDatabase CDB;
1610 IgnoreDiagnostics DiagConsumer;
1611 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1612
1613 constexpr const char *TestCodes[] = {
1614 R"cpp(
1615 class Auxilary {
1616 public:
1617 void AuxFunction();
1618 };
1619 void f() {
1620 Auxilary x;
1621 x.[[Aux]]^;
1622 }
1623 )cpp",
1624 R"cpp(
1625 class Auxilary {
1626 public:
1627 void AuxFunction();
1628 };
1629 void f() {
1630 Auxilary x;
1631 x.[[]]^;
1632 }
1633 )cpp"};
1634 for (const auto &Text : TestCodes) {
1635 Annotations TestCode(Text);
1636 auto Results = completions(Server, TestCode.code(), TestCode.point());
1637
1638 EXPECT_EQ(Results.Completions.size(), 1u);
1639 EXPECT_THAT(Results.Completions.front().CompletionTokenRange, TestCode.range());
1640 }
1641}
1642
Kadir Cetinkayae486e372018-08-13 08:40:05 +00001643TEST(SignatureHelpTest, OverloadsOrdering) {
1644 const auto Results = signatures(R"cpp(
1645 void foo(int x);
1646 void foo(int x, float y);
1647 void foo(float x, int y);
1648 void foo(float x, float y);
1649 void foo(int x, int y = 0);
1650 int main() { foo(^); }
1651 )cpp");
1652 EXPECT_THAT(
1653 Results.signatures,
1654 ElementsAre(
1655 Sig("foo(int x) -> void", {"int x"}),
1656 Sig("foo(int x, int y = 0) -> void", {"int x", "int y = 0"}),
1657 Sig("foo(float x, int y) -> void", {"float x", "int y"}),
1658 Sig("foo(int x, float y) -> void", {"int x", "float y"}),
1659 Sig("foo(float x, float y) -> void", {"float x", "float y"})));
1660 // We always prefer the first signature.
1661 EXPECT_EQ(0, Results.activeSignature);
1662 EXPECT_EQ(0, Results.activeParameter);
1663}
1664
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001665TEST(SignatureHelpTest, InstantiatedSignatures) {
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001666 StringRef Sig0 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001667 template <class T>
1668 void foo(T, T, T);
1669
1670 int main() {
1671 foo<int>(^);
1672 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001673 )cpp";
1674
1675 EXPECT_THAT(signatures(Sig0).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001676 ElementsAre(Sig("foo(T, T, T) -> void", {"T", "T", "T"})));
1677
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001678 StringRef Sig1 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001679 template <class T>
1680 void foo(T, T, T);
1681
1682 int main() {
1683 foo(10, ^);
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001684 })cpp";
1685
1686 EXPECT_THAT(signatures(Sig1).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001687 ElementsAre(Sig("foo(T, T, T) -> void", {"T", "T", "T"})));
1688
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001689 StringRef Sig2 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001690 template <class ...T>
1691 void foo(T...);
1692
1693 int main() {
1694 foo<int>(^);
1695 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001696 )cpp";
1697
1698 EXPECT_THAT(signatures(Sig2).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001699 ElementsAre(Sig("foo(T...) -> void", {"T..."})));
1700
1701 // It is debatable whether we should substitute the outer template parameter
1702 // ('T') in that case. Currently we don't substitute it in signature help, but
1703 // do substitute in code complete.
1704 // FIXME: make code complete and signature help consistent, figure out which
1705 // way is better.
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001706 StringRef Sig3 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001707 template <class T>
1708 struct X {
1709 template <class U>
1710 void foo(T, U);
1711 };
1712
1713 int main() {
1714 X<int>().foo<double>(^)
1715 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001716 )cpp";
1717
1718 EXPECT_THAT(signatures(Sig3).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001719 ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
1720}
1721
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001722TEST(SignatureHelpTest, IndexDocumentation) {
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001723 Symbol Foo0 = sym("foo", index::SymbolKind::Function, "@F@\\0#");
Sam McCall2e5700f2018-08-31 13:55:01 +00001724 Foo0.Documentation = "Doc from the index";
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001725 Symbol Foo1 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#");
Sam McCall2e5700f2018-08-31 13:55:01 +00001726 Foo1.Documentation = "Doc from the index";
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001727 Symbol Foo2 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#I#");
1728
Simon Pilgrim24d34922018-08-17 10:40:05 +00001729 StringRef Sig0 = R"cpp(
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001730 int foo();
1731 int foo(double);
1732
1733 void test() {
1734 foo(^);
1735 }
Simon Pilgrim24d34922018-08-17 10:40:05 +00001736 )cpp";
1737
1738 EXPECT_THAT(
1739 signatures(Sig0, {Foo0}).signatures,
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001740 ElementsAre(AllOf(Sig("foo() -> int", {}), SigDoc("Doc from the index")),
1741 AllOf(Sig("foo(double) -> int", {"double"}), SigDoc(""))));
1742
Simon Pilgrim24d34922018-08-17 10:40:05 +00001743 StringRef Sig1 = R"cpp(
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001744 int foo();
1745 // Overriden doc from sema
1746 int foo(int);
1747 // Doc from sema
1748 int foo(int, int);
1749
1750 void test() {
1751 foo(^);
1752 }
Simon Pilgrim24d34922018-08-17 10:40:05 +00001753 )cpp";
1754
1755 EXPECT_THAT(
1756 signatures(Sig1, {Foo0, Foo1, Foo2}).signatures,
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001757 ElementsAre(AllOf(Sig("foo() -> int", {}), SigDoc("Doc from the index")),
1758 AllOf(Sig("foo(int) -> int", {"int"}),
1759 SigDoc("Overriden doc from sema")),
1760 AllOf(Sig("foo(int, int) -> int", {"int", "int"}),
1761 SigDoc("Doc from sema"))));
1762}
1763
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001764TEST(CompletionTest, CompletionFunctionArgsDisabled) {
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001765 CodeCompleteOptions Opts;
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001766 Opts.EnableSnippets = true;
1767 Opts.EnableFunctionArgSnippets = false;
Ilya Biryukov4f984702018-09-26 05:45:31 +00001768
1769 {
1770 auto Results = completions(
1771 R"cpp(
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001772 void xfoo();
1773 void xfoo(int x, int y);
Ilya Biryukov4f984702018-09-26 05:45:31 +00001774 void f() { xfo^ })cpp",
1775 {}, Opts);
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001776 EXPECT_THAT(
1777 Results.Completions,
1778 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("()")),
1779 AllOf(Named("xfoo"), SnippetSuffix("($0)"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001780 }
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001781 {
Ilya Biryukov4f984702018-09-26 05:45:31 +00001782 auto Results = completions(
1783 R"cpp(
1784 void xbar();
1785 void f() { xba^ })cpp",
1786 {}, Opts);
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001787 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
1788 Named("xbar"), SnippetSuffix("()"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001789 }
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001790 {
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001791 Opts.BundleOverloads = true;
Ilya Biryukov4f984702018-09-26 05:45:31 +00001792 auto Results = completions(
1793 R"cpp(
1794 void xfoo();
1795 void xfoo(int x, int y);
1796 void f() { xfo^ })cpp",
1797 {}, Opts);
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001798 EXPECT_THAT(
1799 Results.Completions,
1800 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("($0)"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001801 }
Ilya Biryukov4f984702018-09-26 05:45:31 +00001802 {
1803 auto Results = completions(
1804 R"cpp(
1805 template <class T, class U>
1806 void xfoo(int a, U b);
1807 void f() { xfo^ })cpp",
1808 {}, Opts);
1809 EXPECT_THAT(
1810 Results.Completions,
1811 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("<$1>($0)"))));
1812 }
1813 {
1814 auto Results = completions(
1815 R"cpp(
1816 template <class T>
1817 class foo_class{};
1818 template <class T>
1819 using foo_alias = T**;
1820 void f() { foo_^ })cpp",
1821 {}, Opts);
1822 EXPECT_THAT(
1823 Results.Completions,
1824 UnorderedElementsAre(AllOf(Named("foo_class"), SnippetSuffix("<$0>")),
1825 AllOf(Named("foo_alias"), SnippetSuffix("<$0>"))));
1826 }
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001827}
1828
Kadir Cetinkayaf8b85a32018-08-23 13:14:50 +00001829TEST(CompletionTest, SuggestOverrides) {
1830 constexpr const char *const Text(R"cpp(
1831 class A {
1832 public:
1833 virtual void vfunc(bool param);
1834 virtual void vfunc(bool param, int p);
1835 void func(bool param);
1836 };
1837 class B : public A {
1838 virtual void ttt(bool param) const;
1839 void vfunc(bool param, int p) override;
1840 };
1841 class C : public B {
1842 public:
1843 void vfunc(bool param) override;
1844 ^
1845 };
1846 )cpp");
1847 const auto Results = completions(Text);
1848 EXPECT_THAT(Results.Completions,
1849 AllOf(Contains(Labeled("void vfunc(bool param, int p) override")),
1850 Contains(Labeled("void ttt(bool param) const override")),
1851 Not(Contains(Labeled("void vfunc(bool param) override")))));
1852}
1853
Ilya Biryukov5a79d1e2018-09-03 15:25:27 +00001854TEST(CompletionTest, OverridesNonIdentName) {
1855 // Check the completions call does not crash.
1856 completions(R"cpp(
1857 struct Base {
1858 virtual ~Base() = 0;
1859 virtual operator int() = 0;
1860 virtual Base& operator+(Base&) = 0;
1861 };
1862
1863 struct Derived : Base {
1864 ^
1865 };
1866 )cpp");
1867}
1868
Eric Liu25d74e92018-08-24 11:23:56 +00001869TEST(SpeculateCompletionFilter, Filters) {
1870 Annotations F(R"cpp($bof^
1871 $bol^
1872 ab$ab^
1873 x.ab$dot^
1874 x.$dotempty^
1875 x::ab$scoped^
1876 x::$scopedempty^
1877
1878 )cpp");
1879 auto speculate = [&](StringRef PointName) {
1880 auto Filter = speculateCompletionFilter(F.code(), F.point(PointName));
1881 assert(Filter);
1882 return *Filter;
1883 };
1884 EXPECT_EQ(speculate("bof"), "");
1885 EXPECT_EQ(speculate("bol"), "");
1886 EXPECT_EQ(speculate("ab"), "ab");
1887 EXPECT_EQ(speculate("dot"), "ab");
1888 EXPECT_EQ(speculate("dotempty"), "");
1889 EXPECT_EQ(speculate("scoped"), "ab");
1890 EXPECT_EQ(speculate("scopedempty"), "");
1891}
1892
1893TEST(CompletionTest, EnableSpeculativeIndexRequest) {
1894 MockFSProvider FS;
1895 MockCompilationDatabase CDB;
1896 IgnoreDiagnostics DiagConsumer;
1897 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1898
1899 auto File = testPath("foo.cpp");
1900 Annotations Test(R"cpp(
1901 namespace ns1 { int abc; }
1902 namespace ns2 { int abc; }
1903 void f() { ns1::ab$1^; ns1::ab$2^; }
1904 void f() { ns2::ab$3^; }
1905 )cpp");
1906 runAddDocument(Server, File, Test.code());
1907 clangd::CodeCompleteOptions Opts = {};
1908
1909 IndexRequestCollector Requests;
1910 Opts.Index = &Requests;
1911 Opts.SpeculativeIndexRequest = true;
1912
1913 auto CompleteAtPoint = [&](StringRef P) {
1914 cantFail(runCodeComplete(Server, File, Test.point(P), Opts));
1915 // Sleep for a while to make sure asynchronous call (if applicable) is also
1916 // triggered before callback is invoked.
1917 std::this_thread::sleep_for(std::chrono::milliseconds(100));
1918 };
1919
1920 CompleteAtPoint("1");
1921 auto Reqs1 = Requests.consumeRequests();
1922 ASSERT_EQ(Reqs1.size(), 1u);
1923 EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre("ns1::"));
1924
1925 CompleteAtPoint("2");
1926 auto Reqs2 = Requests.consumeRequests();
1927 // Speculation succeeded. Used speculative index result.
1928 ASSERT_EQ(Reqs2.size(), 1u);
1929 EXPECT_EQ(Reqs2[0], Reqs1[0]);
1930
1931 CompleteAtPoint("3");
1932 // Speculation failed. Sent speculative index request and the new index
1933 // request after sema.
1934 auto Reqs3 = Requests.consumeRequests();
1935 ASSERT_EQ(Reqs3.size(), 2u);
1936}
1937
Eric Liu83f63e42018-09-03 10:18:21 +00001938TEST(CompletionTest, InsertTheMostPopularHeader) {
1939 std::string DeclFile = URI::createFile(testPath("foo")).toString();
1940 Symbol sym = func("Func");
1941 sym.CanonicalDeclaration.FileURI = DeclFile;
1942 sym.IncludeHeaders.emplace_back("\"foo.h\"", 2);
1943 sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000);
1944
1945 auto Results = completions("Fun^", {sym}).Completions;
1946 assert(!Results.empty());
1947 EXPECT_THAT(Results[0], AllOf(Named("Func"), InsertInclude("\"bar.h\"")));
1948 EXPECT_EQ(Results[0].Includes.size(), 2u);
1949}
1950
1951TEST(CompletionTest, NoInsertIncludeIfOnePresent) {
1952 MockFSProvider FS;
1953 MockCompilationDatabase CDB;
1954
1955 std::string FooHeader = testPath("foo.h");
1956 FS.Files[FooHeader] = "";
1957
1958 IgnoreDiagnostics DiagConsumer;
1959 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1960
1961 std::string DeclFile = URI::createFile(testPath("foo")).toString();
1962 Symbol sym = func("Func");
1963 sym.CanonicalDeclaration.FileURI = DeclFile;
1964 sym.IncludeHeaders.emplace_back("\"foo.h\"", 2);
1965 sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000);
1966
1967 EXPECT_THAT(
1968 completions(Server, "#include \"foo.h\"\nFun^", {sym}).Completions,
1969 UnorderedElementsAre(
1970 AllOf(Named("Func"), HasInclude("\"foo.h\""), Not(InsertInclude()))));
1971}
1972
Eric Liud25f1212018-09-06 09:59:37 +00001973TEST(CompletionTest, MergeMacrosFromIndexAndSema) {
1974 Symbol Sym;
1975 Sym.Name = "Clangd_Macro_Test";
1976 Sym.ID = SymbolID("c:foo.cpp@8@macro@Clangd_Macro_Test");
1977 Sym.SymInfo.Kind = index::SymbolKind::Macro;
Eric Liu6df66002018-09-06 18:52:26 +00001978 Sym.Flags |= Symbol::IndexedForCodeCompletion;
Eric Liud25f1212018-09-06 09:59:37 +00001979 EXPECT_THAT(completions("#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym})
1980 .Completions,
1981 UnorderedElementsAre(Named("Clangd_Macro_Test")));
1982}
1983
Eric Liu467c5f92018-09-19 09:35:04 +00001984TEST(CompletionTest, NoMacroFromPreambleIfIndexIsSet) {
1985 auto Results = completions(
1986 R"cpp(#define CLANGD_PREAMBLE x
1987
1988 int x = 0;
1989 #define CLANGD_MAIN x
1990 void f() { CLANGD_^ }
1991 )cpp",
1992 {func("CLANGD_INDEX")});
1993 // Index is overriden in code completion options, so the preamble symbol is
1994 // not seen.
1995 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("CLANGD_MAIN"),
1996 Named("CLANGD_INDEX")));
1997}
1998
Eric Liu6df66002018-09-06 18:52:26 +00001999TEST(CompletionTest, DeprecatedResults) {
2000 std::string Body = R"cpp(
2001 void TestClangd();
2002 void TestClangc() __attribute__((deprecated("", "")));
2003 )cpp";
2004
2005 EXPECT_THAT(
2006 completions(Body + "int main() { TestClang^ }").Completions,
2007 UnorderedElementsAre(AllOf(Named("TestClangd"), Not(Deprecated())),
2008 AllOf(Named("TestClangc"), Deprecated())));
2009}
2010
Kadir Cetinkaya0b77d032018-09-10 14:22:42 +00002011TEST(SignatureHelpTest, InsideArgument) {
2012 {
2013 const auto Results = signatures(R"cpp(
2014 void foo(int x);
2015 void foo(int x, int y);
2016 int main() { foo(1+^); }
2017 )cpp");
2018 EXPECT_THAT(
2019 Results.signatures,
2020 ElementsAre(Sig("foo(int x) -> void", {"int x"}),
2021 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
2022 EXPECT_EQ(0, Results.activeParameter);
2023 }
2024 {
2025 const auto Results = signatures(R"cpp(
2026 void foo(int x);
2027 void foo(int x, int y);
2028 int main() { foo(1^); }
2029 )cpp");
2030 EXPECT_THAT(
2031 Results.signatures,
2032 ElementsAre(Sig("foo(int x) -> void", {"int x"}),
2033 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
2034 EXPECT_EQ(0, Results.activeParameter);
2035 }
2036 {
2037 const auto Results = signatures(R"cpp(
2038 void foo(int x);
2039 void foo(int x, int y);
2040 int main() { foo(1^0); }
2041 )cpp");
2042 EXPECT_THAT(
2043 Results.signatures,
2044 ElementsAre(Sig("foo(int x) -> void", {"int x"}),
2045 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
2046 EXPECT_EQ(0, Results.activeParameter);
2047 }
2048 {
2049 const auto Results = signatures(R"cpp(
2050 void foo(int x);
2051 void foo(int x, int y);
2052 int bar(int x, int y);
2053 int main() { bar(foo(2, 3^)); }
2054 )cpp");
2055 EXPECT_THAT(Results.signatures, ElementsAre(Sig("foo(int x, int y) -> void",
2056 {"int x", "int y"})));
2057 EXPECT_EQ(1, Results.activeParameter);
2058 }
2059}
2060
Kadir Cetinkaya873cae52018-09-11 15:12:10 +00002061TEST(SignatureHelpTest, ConstructorInitializeFields) {
2062 {
2063 const auto Results = signatures(R"cpp(
2064 struct A {
2065 A(int);
2066 };
2067 struct B {
2068 B() : a_elem(^) {}
2069 A a_elem;
2070 };
2071 )cpp");
2072 EXPECT_THAT(Results.signatures, UnorderedElementsAre(
2073 Sig("A(int)", {"int"}),
2074 Sig("A(A &&)", {"A &&"}),
2075 Sig("A(const A &)", {"const A &"})
2076 ));
2077 }
2078 {
2079 const auto Results = signatures(R"cpp(
2080 struct A {
2081 A(int);
2082 };
2083 struct C {
2084 C(int);
2085 C(A);
2086 };
2087 struct B {
2088 B() : c_elem(A(1^)) {}
2089 C c_elem;
2090 };
2091 )cpp");
2092 EXPECT_THAT(Results.signatures, UnorderedElementsAre(
2093 Sig("A(int)", {"int"}),
2094 Sig("A(A &&)", {"A &&"}),
2095 Sig("A(const A &)", {"const A &"})
2096 ));
2097 }
2098}
2099
Kadir Cetinkaya0ed5d292018-09-27 14:21:07 +00002100TEST(CompletionTest, IncludedCompletionKinds) {
2101 MockFSProvider FS;
2102 MockCompilationDatabase CDB;
2103 std::string Subdir = testPath("sub");
Sam McCallc008af62018-10-20 15:30:37 +00002104 std::string SearchDirArg = (Twine("-I") + Subdir).str();
Kadir Cetinkaya0ed5d292018-09-27 14:21:07 +00002105 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
2106 std::string BarHeader = testPath("sub/bar.h");
2107 FS.Files[BarHeader] = "";
2108 IgnoreDiagnostics DiagConsumer;
2109 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
2110 auto Results = completions(Server,
2111 R"cpp(
2112 #include "^"
2113 )cpp"
2114 );
2115 EXPECT_THAT(Results.Completions,
2116 AllOf(Has("sub/", CompletionItemKind::Folder),
2117 Has("bar.h\"", CompletionItemKind::File)));
2118}
2119
Haojian Wu1c6b6de2018-10-02 14:46:08 +00002120TEST(CompletionTest, NoCrashAtNonAlphaIncludeHeader) {
2121 auto Results = completions(
2122 R"cpp(
2123 #include "./^"
2124 )cpp"
2125 );
2126 EXPECT_TRUE(Results.Completions.empty());
2127}
2128
Eric Liu670c1472018-09-27 18:46:00 +00002129TEST(CompletionTest, NoAllScopesCompletionWhenQualified) {
2130 clangd::CodeCompleteOptions Opts = {};
2131 Opts.AllScopes = true;
2132
2133 auto Results = completions(
2134 R"cpp(
2135 void f() { na::Clangd^ }
2136 )cpp",
2137 {cls("na::ClangdA"), cls("nx::ClangdX"), cls("Clangd3")}, Opts);
2138 EXPECT_THAT(Results.Completions,
2139 UnorderedElementsAre(
2140 AllOf(Qualifier(""), Scope("na::"), Named("ClangdA"))));
2141}
2142
2143TEST(CompletionTest, AllScopesCompletion) {
2144 clangd::CodeCompleteOptions Opts = {};
2145 Opts.AllScopes = true;
2146
2147 auto Results = completions(
2148 R"cpp(
2149 namespace na {
2150 void f() { Clangd^ }
2151 }
2152 )cpp",
2153 {cls("nx::Clangd1"), cls("ny::Clangd2"), cls("Clangd3"),
2154 cls("na::nb::Clangd4")},
2155 Opts);
2156 EXPECT_THAT(
2157 Results.Completions,
2158 UnorderedElementsAre(AllOf(Qualifier("nx::"), Named("Clangd1")),
2159 AllOf(Qualifier("ny::"), Named("Clangd2")),
2160 AllOf(Qualifier(""), Scope(""), Named("Clangd3")),
2161 AllOf(Qualifier("nb::"), Named("Clangd4"))));
2162}
2163
2164TEST(CompletionTest, NoQualifierIfShadowed) {
2165 clangd::CodeCompleteOptions Opts = {};
2166 Opts.AllScopes = true;
2167
2168 auto Results = completions(R"cpp(
2169 namespace nx { class Clangd1 {}; }
2170 using nx::Clangd1;
2171 void f() { Clangd^ }
2172 )cpp",
2173 {cls("nx::Clangd1"), cls("nx::Clangd2")}, Opts);
2174 // Although Clangd1 is from another namespace, Sema tells us it's in-scope and
2175 // needs no qualifier.
2176 EXPECT_THAT(Results.Completions,
2177 UnorderedElementsAre(AllOf(Qualifier(""), Named("Clangd1")),
2178 AllOf(Qualifier("nx::"), Named("Clangd2"))));
2179}
Kadir Cetinkaya0ed5d292018-09-27 14:21:07 +00002180
Kadir Cetinkayab9157902018-10-24 15:24:29 +00002181TEST(CompletionTest, NoCompletionsForNewNames) {
2182 clangd::CodeCompleteOptions Opts;
2183 Opts.AllScopes = true;
2184 auto Results = completions(R"cpp(
2185 void f() { int n^ }
2186 )cpp",
2187 {cls("naber"), cls("nx::naber")}, Opts);
2188 EXPECT_THAT(Results.Completions, UnorderedElementsAre());
2189}
Sam McCall9aad25f2017-12-05 07:20:26 +00002190} // namespace
2191} // namespace clangd
2192} // namespace clang