blob: 68b13da17e17f31f87adec557e58e6479e26e358 [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(
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,
384 HasSubsequence(AllOf(Qualifier(""), Named("bar")),
385 AllOf(Qualifier("Foo::"), Named("foo"))));
386 EXPECT_THAT(Results.Completions,
387 Not(Contains(AllOf(Qualifier(""), Named("foo"))))); // private
Sam McCall44fdcec22017-12-08 15:00:59 +0000388}
389
Sam McCall4caa8512018-06-07 12:49:17 +0000390TEST(CompletionTest, InjectedTypename) {
391 // These are suppressed when accessed as a member...
Sam McCalle746a2b2018-07-02 11:13:16 +0000392 EXPECT_THAT(completions("struct X{}; void foo(){ X().^ }").Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000393 Not(Has("X")));
Sam McCalle746a2b2018-07-02 11:13:16 +0000394 EXPECT_THAT(completions("struct X{ void foo(){ this->^ } };").Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000395 Not(Has("X")));
396 // ...but accessible in other, more useful cases.
Sam McCalle746a2b2018-07-02 11:13:16 +0000397 EXPECT_THAT(completions("struct X{ void foo(){ ^ } };").Completions,
398 Has("X"));
399 EXPECT_THAT(
400 completions("struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions,
401 Has("Y"));
Sam McCall4caa8512018-06-07 12:49:17 +0000402 EXPECT_THAT(
403 completions(
404 "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };")
Sam McCalle746a2b2018-07-02 11:13:16 +0000405 .Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000406 Has("Y"));
407 // This case is marginal (`using X::X` is useful), we allow it for now.
Sam McCalle746a2b2018-07-02 11:13:16 +0000408 EXPECT_THAT(completions("struct X{}; void foo(){ X::^ }").Completions,
409 Has("X"));
Sam McCall4caa8512018-06-07 12:49:17 +0000410}
411
Sam McCall44fdcec22017-12-08 15:00:59 +0000412TEST(CompletionTest, Snippets) {
413 clangd::CodeCompleteOptions Opts;
Sam McCall44fdcec22017-12-08 15:00:59 +0000414 auto Results = completions(
415 R"cpp(
416 struct fake {
417 int a;
418 int f(int i, const float f) const;
419 };
420 int main() {
421 fake f;
422 f.^
423 }
424 )cpp",
Sam McCalla15c2d62018-01-18 09:27:56 +0000425 /*IndexSymbols=*/{}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000426 EXPECT_THAT(
427 Results.Completions,
428 HasSubsequence(Named("a"),
429 SnippetSuffix("(${1:int i}, ${2:const float f})")));
Sam McCall44fdcec22017-12-08 15:00:59 +0000430}
431
432TEST(CompletionTest, Kinds) {
Sam McCall545a20d2018-01-19 14:34:02 +0000433 auto Results = completions(
434 R"cpp(
Sam McCall545a20d2018-01-19 14:34:02 +0000435 int variable;
436 struct Struct {};
437 int function();
Eric Liu467c5f92018-09-19 09:35:04 +0000438 // make sure MACRO is not included in preamble.
439 #define MACRO 10
Sam McCall545a20d2018-01-19 14:34:02 +0000440 int X = ^
441 )cpp",
442 {func("indexFunction"), var("indexVariable"), cls("indexClass")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000443 EXPECT_THAT(Results.Completions,
Sam McCall545a20d2018-01-19 14:34:02 +0000444 AllOf(Has("function", CompletionItemKind::Function),
445 Has("variable", CompletionItemKind::Variable),
446 Has("int", CompletionItemKind::Keyword),
447 Has("Struct", CompletionItemKind::Class),
448 Has("MACRO", CompletionItemKind::Text),
449 Has("indexFunction", CompletionItemKind::Function),
450 Has("indexVariable", CompletionItemKind::Variable),
451 Has("indexClass", CompletionItemKind::Class)));
Sam McCall44fdcec22017-12-08 15:00:59 +0000452
Sam McCall44fdcec22017-12-08 15:00:59 +0000453 Results = completions("nam^");
Sam McCalle746a2b2018-07-02 11:13:16 +0000454 EXPECT_THAT(Results.Completions,
455 Has("namespace", CompletionItemKind::Snippet));
Sam McCall44fdcec22017-12-08 15:00:59 +0000456}
457
Sam McCall84652cc2018-01-12 16:16:09 +0000458TEST(CompletionTest, NoDuplicates) {
Sam McCall545a20d2018-01-19 14:34:02 +0000459 auto Results = completions(
460 R"cpp(
461 class Adapter {
Sam McCall545a20d2018-01-19 14:34:02 +0000462 };
Sam McCall84652cc2018-01-12 16:16:09 +0000463
Eric Liu9b3cba72018-05-30 09:03:39 +0000464 void f() {
Sam McCall545a20d2018-01-19 14:34:02 +0000465 Adapter^
466 }
467 )cpp",
468 {cls("Adapter")});
Sam McCall84652cc2018-01-12 16:16:09 +0000469
470 // Make sure there are no duplicate entries of 'Adapter'.
Sam McCalle746a2b2018-07-02 11:13:16 +0000471 EXPECT_THAT(Results.Completions, ElementsAre(Named("Adapter")));
Sam McCall84652cc2018-01-12 16:16:09 +0000472}
473
Sam McCall545a20d2018-01-19 14:34:02 +0000474TEST(CompletionTest, ScopedNoIndex) {
475 auto Results = completions(
476 R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000477 namespace fake { int BigBang, Babble, Box; };
478 int main() { fake::ba^ }
Sam McCall545a20d2018-01-19 14:34:02 +0000479 ")cpp");
Sam McCall8b2dcc12018-06-14 13:50:30 +0000480 // Babble is a better match than BigBang. Box doesn't match at all.
Sam McCalle746a2b2018-07-02 11:13:16 +0000481 EXPECT_THAT(Results.Completions,
482 ElementsAre(Named("Babble"), Named("BigBang")));
Sam McCall84652cc2018-01-12 16:16:09 +0000483}
484
Sam McCall545a20d2018-01-19 14:34:02 +0000485TEST(CompletionTest, Scoped) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000486 auto Results = completions(
487 R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000488 namespace fake { int Babble, Box; };
489 int main() { fake::ba^ }
Sam McCall545a20d2018-01-19 14:34:02 +0000490 ")cpp",
491 {var("fake::BigBang")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000492 EXPECT_THAT(Results.Completions,
493 ElementsAre(Named("Babble"), Named("BigBang")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000494}
495
Sam McCall545a20d2018-01-19 14:34:02 +0000496TEST(CompletionTest, ScopedWithFilter) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000497 auto Results = completions(
498 R"cpp(
499 void f() { ns::x^ }
500 )cpp",
501 {cls("ns::XYZ"), func("ns::foo")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000502 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("XYZ")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000503}
504
Sam McCalldc8abc42018-05-03 14:53:02 +0000505TEST(CompletionTest, ReferencesAffectRanking) {
Eric Liu84bd5db2018-07-25 11:26:35 +0000506 auto Results = completions("int main() { abs^ }", {ns("absl"), func("absb")});
507 EXPECT_THAT(Results.Completions, HasSubsequence(Named("absb"), Named("absl")));
Sam McCalldc8abc42018-05-03 14:53:02 +0000508 Results = completions("int main() { abs^ }",
Eric Liu84bd5db2018-07-25 11:26:35 +0000509 {withReferences(10000, ns("absl")), func("absb")});
510 EXPECT_THAT(Results.Completions,
511 HasSubsequence(Named("absl"), Named("absb")));
Sam McCalldc8abc42018-05-03 14:53:02 +0000512}
513
Sam McCall545a20d2018-01-19 14:34:02 +0000514TEST(CompletionTest, GlobalQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000515 auto Results = completions(
516 R"cpp(
517 void f() { ::^ }
518 )cpp",
519 {cls("XYZ")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000520 EXPECT_THAT(Results.Completions,
521 AllOf(Has("XYZ", CompletionItemKind::Class),
522 Has("f", CompletionItemKind::Function)));
Sam McCalla15c2d62018-01-18 09:27:56 +0000523}
524
Sam McCall545a20d2018-01-19 14:34:02 +0000525TEST(CompletionTest, FullyQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000526 auto Results = completions(
527 R"cpp(
Sam McCall545a20d2018-01-19 14:34:02 +0000528 namespace ns { void bar(); }
Sam McCalla15c2d62018-01-18 09:27:56 +0000529 void f() { ::ns::^ }
530 )cpp",
531 {cls("ns::XYZ")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000532 EXPECT_THAT(Results.Completions,
533 AllOf(Has("XYZ", CompletionItemKind::Class),
534 Has("bar", CompletionItemKind::Function)));
Sam McCall545a20d2018-01-19 14:34:02 +0000535}
536
537TEST(CompletionTest, SemaIndexMerge) {
538 auto Results = completions(
539 R"cpp(
540 namespace ns { int local; void both(); }
541 void f() { ::ns::^ }
542 )cpp",
543 {func("ns::both"), cls("ns::Index")});
544 // We get results from both index and sema, with no duplicates.
Sam McCall2161ec72018-07-05 06:20:41 +0000545 EXPECT_THAT(Results.Completions,
546 UnorderedElementsAre(
547 AllOf(Named("local"), Origin(SymbolOrigin::AST)),
548 AllOf(Named("Index"), Origin(SymbolOrigin::Static)),
549 AllOf(Named("both"),
550 Origin(SymbolOrigin::AST | SymbolOrigin::Static))));
Sam McCalla15c2d62018-01-18 09:27:56 +0000551}
552
Haojian Wu48b48652018-01-25 09:20:09 +0000553TEST(CompletionTest, SemaIndexMergeWithLimit) {
554 clangd::CodeCompleteOptions Opts;
555 Opts.Limit = 1;
556 auto Results = completions(
557 R"cpp(
558 namespace ns { int local; void both(); }
559 void f() { ::ns::^ }
560 )cpp",
561 {func("ns::both"), cls("ns::Index")}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000562 EXPECT_EQ(Results.Completions.size(), Opts.Limit);
563 EXPECT_TRUE(Results.HasMore);
Haojian Wu48b48652018-01-25 09:20:09 +0000564}
565
Eric Liu63f419a2018-05-15 15:29:32 +0000566TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
567 MockFSProvider FS;
568 MockCompilationDatabase CDB;
569 std::string Subdir = testPath("sub");
570 std::string SearchDirArg = (llvm::Twine("-I") + Subdir).str();
571 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
572 std::string BarHeader = testPath("sub/bar.h");
573 FS.Files[BarHeader] = "";
574
575 IgnoreDiagnostics DiagConsumer;
576 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Eric Liu63f419a2018-05-15 15:29:32 +0000577 auto BarURI = URI::createFile(BarHeader).toString();
578 Symbol Sym = cls("ns::X");
579 Sym.CanonicalDeclaration.FileURI = BarURI;
Eric Liu83f63e42018-09-03 10:18:21 +0000580 Sym.IncludeHeaders.emplace_back(BarURI, 1);
Eric Liu63f419a2018-05-15 15:29:32 +0000581 // Shoten include path based on search dirctory and insert.
582 auto Results = completions(Server,
583 R"cpp(
584 int main() { ns::^ }
585 )cpp",
586 {Sym});
Sam McCalle746a2b2018-07-02 11:13:16 +0000587 EXPECT_THAT(Results.Completions,
588 ElementsAre(AllOf(Named("X"), InsertInclude("\"bar.h\""))));
Eric Liu63f419a2018-05-15 15:29:32 +0000589 // Duplicate based on inclusions in preamble.
590 Results = completions(Server,
591 R"cpp(
592 #include "sub/bar.h" // not shortest, so should only match resolved.
593 int main() { ns::^ }
594 )cpp",
595 {Sym});
Sam McCalle746a2b2018-07-02 11:13:16 +0000596 EXPECT_THAT(Results.Completions, ElementsAre(AllOf(Named("X"), Labeled("X"),
597 Not(InsertInclude()))));
Eric Liu63f419a2018-05-15 15:29:32 +0000598}
599
Eric Liu9b3cba72018-05-30 09:03:39 +0000600TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {
601 MockFSProvider FS;
602 MockCompilationDatabase CDB;
603
604 IgnoreDiagnostics DiagConsumer;
605 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Eric Liu9b3cba72018-05-30 09:03:39 +0000606 Symbol SymX = cls("ns::X");
607 Symbol SymY = cls("ns::Y");
608 std::string BarHeader = testPath("bar.h");
609 auto BarURI = URI::createFile(BarHeader).toString();
610 SymX.CanonicalDeclaration.FileURI = BarURI;
611 SymY.CanonicalDeclaration.FileURI = BarURI;
Eric Liu83f63e42018-09-03 10:18:21 +0000612 SymX.IncludeHeaders.emplace_back("<bar>", 1);
613 SymY.IncludeHeaders.emplace_back("<bar>", 1);
Eric Liu9b3cba72018-05-30 09:03:39 +0000614 // Shoten include path based on search dirctory and insert.
615 auto Results = completions(Server,
616 R"cpp(
617 namespace ns {
618 class X;
619 class Y {}
620 }
621 int main() { ns::^ }
622 )cpp",
623 {SymX, SymY});
Sam McCalle746a2b2018-07-02 11:13:16 +0000624 EXPECT_THAT(Results.Completions,
625 ElementsAre(AllOf(Named("X"), Not(InsertInclude())),
626 AllOf(Named("Y"), Not(InsertInclude()))));
Eric Liu9b3cba72018-05-30 09:03:39 +0000627}
628
Sam McCalla15c2d62018-01-18 09:27:56 +0000629TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
630 MockFSProvider FS;
631 MockCompilationDatabase CDB;
632 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000633 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Sam McCalla15c2d62018-01-18 09:27:56 +0000634
Sam McCallc1568062018-02-16 09:41:43 +0000635 FS.Files[testPath("bar.h")] =
Sam McCalld5ea3e32018-01-24 17:53:32 +0000636 R"cpp(namespace ns { struct preamble { int member; }; })cpp";
Sam McCallc1568062018-02-16 09:41:43 +0000637 auto File = testPath("foo.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000638 Annotations Test(R"cpp(
639 #include "bar.h"
640 namespace ns { int local; }
Sam McCalld5ea3e32018-01-24 17:53:32 +0000641 void f() { ns::^; }
642 void f() { ns::preamble().$2^; }
Sam McCalla15c2d62018-01-18 09:27:56 +0000643 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000644 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000645 clangd::CodeCompleteOptions Opts = {};
646
Sam McCalla15c2d62018-01-18 09:27:56 +0000647 auto I = memIndex({var("ns::index")});
648 Opts.Index = I.get();
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000649 auto WithIndex = cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000650 EXPECT_THAT(WithIndex.Completions,
Sam McCalla15c2d62018-01-18 09:27:56 +0000651 UnorderedElementsAre(Named("local"), Named("index")));
Sam McCalld5ea3e32018-01-24 17:53:32 +0000652 auto ClassFromPreamble =
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000653 cantFail(runCodeComplete(Server, File, Test.point("2"), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000654 EXPECT_THAT(ClassFromPreamble.Completions, Contains(Named("member")));
Sam McCall0bb24cd2018-02-13 08:59:23 +0000655
656 Opts.Index = nullptr;
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000657 auto WithoutIndex =
658 cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000659 EXPECT_THAT(WithoutIndex.Completions,
Sam McCall0bb24cd2018-02-13 08:59:23 +0000660 UnorderedElementsAre(Named("local"), Named("preamble")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000661}
662
Sam McCallebef8122018-09-14 12:36:06 +0000663// This verifies that we get normal preprocessor completions in the preamble.
664// This is a regression test for an old bug: if we override the preamble and
665// try to complete inside it, clang kicks our completion point just outside the
666// preamble, resulting in always getting top-level completions.
667TEST(CompletionTest, CompletionInPreamble) {
Sam McCall0be9c4e2018-09-14 18:49:16 +0000668 auto Results = completions(R"cpp(
Sam McCallebef8122018-09-14 12:36:06 +0000669 #ifnd^ef FOO_H_
670 #define BAR_H_
671 #include <bar.h>
672 int foo() {}
673 #endif
674 )cpp")
Sam McCall0be9c4e2018-09-14 18:49:16 +0000675 .Completions;
676 EXPECT_THAT(Results, ElementsAre(Named("ifndef")));
Jonas Tothad515192018-09-14 19:42:37 +0000677}
Sam McCallebef8122018-09-14 12:36:06 +0000678
Sam McCalla15c2d62018-01-18 09:27:56 +0000679TEST(CompletionTest, DynamicIndexMultiFile) {
680 MockFSProvider FS;
681 MockCompilationDatabase CDB;
682 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000683 auto Opts = ClangdServer::optsForTest();
684 Opts.BuildDynamicSymbolIndex = true;
685 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
Sam McCalla15c2d62018-01-18 09:27:56 +0000686
Eric Liu709bde82018-02-19 18:48:44 +0000687 FS.Files[testPath("foo.h")] = R"cpp(
Sam McCalla15c2d62018-01-18 09:27:56 +0000688 namespace ns { class XYZ {}; void foo(int x) {} }
Eric Liu709bde82018-02-19 18:48:44 +0000689 )cpp";
Sam McCall7363a2f2018-03-05 17:28:54 +0000690 runAddDocument(Server, testPath("foo.cpp"), R"cpp(
Eric Liu709bde82018-02-19 18:48:44 +0000691 #include "foo.h"
Sam McCall0bb24cd2018-02-13 08:59:23 +0000692 )cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000693
Sam McCallc1568062018-02-16 09:41:43 +0000694 auto File = testPath("bar.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000695 Annotations Test(R"cpp(
696 namespace ns {
697 class XXX {};
698 /// Doooc
699 void fooooo() {}
700 }
701 void f() { ns::^ }
702 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000703 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000704
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000705 auto Results = cantFail(runCodeComplete(Server, File, Test.point(), {}));
Sam McCalla15c2d62018-01-18 09:27:56 +0000706 // "XYZ" and "foo" are not included in the file being completed but are still
707 // visible through the index.
Sam McCalle746a2b2018-07-02 11:13:16 +0000708 EXPECT_THAT(Results.Completions, Has("XYZ", CompletionItemKind::Class));
709 EXPECT_THAT(Results.Completions, Has("foo", CompletionItemKind::Function));
710 EXPECT_THAT(Results.Completions, Has("XXX", CompletionItemKind::Class));
711 EXPECT_THAT(Results.Completions,
712 Contains((Named("fooooo"), Kind(CompletionItemKind::Function),
713 Doc("Doooc"), ReturnType("void"))));
Sam McCalla15c2d62018-01-18 09:27:56 +0000714}
715
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000716TEST(CompletionTest, Documentation) {
717 auto Results = completions(
718 R"cpp(
719 // Non-doxygen comment.
720 int foo();
721 /// Doxygen comment.
722 /// \param int a
723 int bar(int a);
724 /* Multi-line
725 block comment
726 */
727 int baz();
728
729 int x = ^
730 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000731 EXPECT_THAT(Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000732 Contains(AllOf(Named("foo"), Doc("Non-doxygen comment."))));
733 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +0000734 Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000735 Contains(AllOf(Named("bar"), Doc("Doxygen comment.\n\\param int a"))));
Sam McCalle746a2b2018-07-02 11:13:16 +0000736 EXPECT_THAT(Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000737 Contains(AllOf(Named("baz"), Doc("Multi-line\nblock comment"))));
738}
739
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000740TEST(CompletionTest, GlobalCompletionFiltering) {
741
742 Symbol Class = cls("XYZ");
Eric Liu6df66002018-09-06 18:52:26 +0000743 Class.Flags = static_cast<Symbol::SymbolFlag>(
744 Class.Flags & ~(Symbol::IndexedForCodeCompletion));
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000745 Symbol Func = func("XYZ::foooo");
Eric Liu6df66002018-09-06 18:52:26 +0000746 Func.Flags = static_cast<Symbol::SymbolFlag>(
747 Func.Flags & ~(Symbol::IndexedForCodeCompletion));
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000748
749 auto Results = completions(R"(// void f() {
750 XYZ::foooo^
751 })",
752 {Class, Func});
Sam McCalle746a2b2018-07-02 11:13:16 +0000753 EXPECT_THAT(Results.Completions, IsEmpty());
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000754}
755
Haojian Wu58d208d2018-01-25 09:44:06 +0000756TEST(CodeCompleteTest, DisableTypoCorrection) {
757 auto Results = completions(R"cpp(
758 namespace clang { int v; }
759 void f() { clangd::^
760 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000761 EXPECT_TRUE(Results.Completions.empty());
Haojian Wu58d208d2018-01-25 09:44:06 +0000762}
763
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000764TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
765 auto Results = completions(R"cpp(
766 namespace clang { }
767 void f() {
768 clan^
769 }
770 )cpp");
771
Sam McCalle746a2b2018-07-02 11:13:16 +0000772 EXPECT_THAT(Results.Completions, Contains(Labeled("clang")));
773 EXPECT_THAT(Results.Completions, Not(Contains(Labeled("clang::"))));
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000774}
775
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000776TEST(CompletionTest, BacktrackCrashes) {
777 // Sema calls code completion callbacks twice in these cases.
778 auto Results = completions(R"cpp(
779 namespace ns {
780 struct FooBarBaz {};
781 } // namespace ns
782
783 int foo(ns::FooBar^
784 )cpp");
785
Sam McCalle746a2b2018-07-02 11:13:16 +0000786 EXPECT_THAT(Results.Completions, ElementsAre(Labeled("FooBarBaz")));
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000787
788 // Check we don't crash in that case too.
789 completions(R"cpp(
790 struct FooBarBaz {};
791 void test() {
792 if (FooBarBaz * x^) {}
793 }
794)cpp");
795}
796
Eric Liu42abe412018-05-24 11:20:19 +0000797TEST(CompletionTest, CompleteInMacroWithStringification) {
798 auto Results = completions(R"cpp(
799void f(const char *, int x);
800#define F(x) f(#x, x)
801
802namespace ns {
803int X;
804int Y;
805} // namespace ns
806
807int f(int input_num) {
808 F(ns::^)
809}
810)cpp");
811
Sam McCalle746a2b2018-07-02 11:13:16 +0000812 EXPECT_THAT(Results.Completions,
Eric Liu42abe412018-05-24 11:20:19 +0000813 UnorderedElementsAre(Named("X"), Named("Y")));
814}
815
816TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
817 auto Results = completions(R"cpp(
818void f(const char *, int x);
819#define F(x) f(#x, x)
820
821namespace ns {
822int X;
823
824int f(int input_num) {
825 F(^)
826}
827} // namespace ns
828)cpp");
829
Sam McCalle746a2b2018-07-02 11:13:16 +0000830 EXPECT_THAT(Results.Completions, Contains(Named("X")));
Eric Liu42abe412018-05-24 11:20:19 +0000831}
832
Eric Liu485074f2018-07-11 13:15:31 +0000833TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000834 auto Results = completions(R"cpp(
835 int bar(int param_in_bar) {
836 }
837
838 int foo(int param_in_foo) {
839#if 0
Eric Liu485074f2018-07-11 13:15:31 +0000840 // In recorvery mode, "param_in_foo" will also be suggested among many other
841 // unrelated symbols; however, this is really a special case where this works.
842 // If the #if block is outside of the function, "param_in_foo" is still
843 // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't
844 // really provide useful results in excluded branches.
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000845 par^
846#endif
847 }
848)cpp");
849
Eric Liu485074f2018-07-11 13:15:31 +0000850 EXPECT_TRUE(Results.Completions.empty());
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000851}
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000852SignatureHelp signatures(StringRef Text, Position Point,
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +0000853 std::vector<Symbol> IndexSymbols = {}) {
854 std::unique_ptr<SymbolIndex> Index;
855 if (!IndexSymbols.empty())
856 Index = memIndex(IndexSymbols);
857
Sam McCall800d4372017-12-19 10:29:27 +0000858 MockFSProvider FS;
859 MockCompilationDatabase CDB;
860 IgnoreDiagnostics DiagConsumer;
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +0000861 ClangdServer::Options Opts = ClangdServer::optsForTest();
862 Opts.StaticIndex = Index.get();
863
864 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
Sam McCallc1568062018-02-16 09:41:43 +0000865 auto File = testPath("foo.cpp");
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000866 runAddDocument(Server, File, Text);
867 return cantFail(runSignatureHelp(Server, File, Point));
868}
869
870SignatureHelp signatures(StringRef Text,
871 std::vector<Symbol> IndexSymbols = {}) {
Sam McCall328cbdb2017-12-20 16:06:05 +0000872 Annotations Test(Text);
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000873 return signatures(Test.code(), Test.point(), std::move(IndexSymbols));
Sam McCall800d4372017-12-19 10:29:27 +0000874}
875
876MATCHER_P(ParamsAre, P, "") {
877 if (P.size() != arg.parameters.size())
878 return false;
879 for (unsigned I = 0; I < P.size(); ++I)
880 if (P[I] != arg.parameters[I].label)
881 return false;
882 return true;
883}
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +0000884MATCHER_P(SigDoc, Doc, "") { return arg.documentation == Doc; }
Sam McCall800d4372017-12-19 10:29:27 +0000885
886Matcher<SignatureInformation> Sig(std::string Label,
887 std::vector<std::string> Params) {
Eric Liu8f3678d2018-06-15 13:34:18 +0000888 return AllOf(SigHelpLabeled(Label), ParamsAre(Params));
Sam McCall800d4372017-12-19 10:29:27 +0000889}
890
891TEST(SignatureHelpTest, Overloads) {
892 auto Results = signatures(R"cpp(
893 void foo(int x, int y);
894 void foo(int x, float y);
895 void foo(float x, int y);
896 void foo(float x, float y);
897 void bar(int x, int y = 0);
898 int main() { foo(^); }
899 )cpp");
900 EXPECT_THAT(Results.signatures,
901 UnorderedElementsAre(
902 Sig("foo(float x, float y) -> void", {"float x", "float y"}),
903 Sig("foo(float x, int y) -> void", {"float x", "int y"}),
904 Sig("foo(int x, float y) -> void", {"int x", "float y"}),
905 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
906 // We always prefer the first signature.
907 EXPECT_EQ(0, Results.activeSignature);
908 EXPECT_EQ(0, Results.activeParameter);
909}
910
911TEST(SignatureHelpTest, DefaultArgs) {
912 auto Results = signatures(R"cpp(
913 void bar(int x, int y = 0);
914 void bar(float x = 0, int y = 42);
915 int main() { bar(^
916 )cpp");
917 EXPECT_THAT(Results.signatures,
918 UnorderedElementsAre(
919 Sig("bar(int x, int y = 0) -> void", {"int x", "int y = 0"}),
920 Sig("bar(float x = 0, int y = 42) -> void",
921 {"float x = 0", "int y = 42"})));
922 EXPECT_EQ(0, Results.activeSignature);
923 EXPECT_EQ(0, Results.activeParameter);
924}
925
926TEST(SignatureHelpTest, ActiveArg) {
927 auto Results = signatures(R"cpp(
928 int baz(int a, int b, int c);
929 int main() { baz(baz(1,2,3), ^); }
930 )cpp");
931 EXPECT_THAT(Results.signatures,
932 ElementsAre(Sig("baz(int a, int b, int c) -> int",
933 {"int a", "int b", "int c"})));
934 EXPECT_EQ(0, Results.activeSignature);
935 EXPECT_EQ(1, Results.activeParameter);
936}
937
Ilya Biryukov43c292c2018-08-30 13:14:31 +0000938TEST(SignatureHelpTest, OpeningParen) {
939 llvm::StringLiteral Tests[] = {// Recursive function call.
940 R"cpp(
941 int foo(int a, int b, int c);
942 int main() {
943 foo(foo $p^( foo(10, 10, 10), ^ )));
944 })cpp",
945 // Functional type cast.
946 R"cpp(
947 struct Foo {
948 Foo(int a, int b, int c);
949 };
950 int main() {
951 Foo $p^( 10, ^ );
952 })cpp",
953 // New expression.
954 R"cpp(
955 struct Foo {
956 Foo(int a, int b, int c);
957 };
958 int main() {
959 new Foo $p^( 10, ^ );
960 })cpp",
961 // Macro expansion.
962 R"cpp(
963 int foo(int a, int b, int c);
964 #define FOO foo(
965
966 int main() {
967 // Macro expansions.
968 $p^FOO 10, ^ );
969 })cpp",
970 // Macro arguments.
971 R"cpp(
972 int foo(int a, int b, int c);
973 int main() {
974 #define ID(X) X
975 ID(foo $p^( foo(10), ^ ))
976 })cpp"};
977
978 for (auto Test : Tests) {
979 Annotations Code(Test);
980 EXPECT_EQ(signatures(Code.code(), Code.point()).argListStart,
981 Code.point("p"))
982 << "Test source:" << Test;
983 }
984}
985
Haojian Wu061c73e2018-01-23 11:37:26 +0000986class IndexRequestCollector : public SymbolIndex {
987public:
988 bool
Sam McCalld1a7a372018-01-31 13:40:48 +0000989 fuzzyFind(const FuzzyFindRequest &Req,
Haojian Wu061c73e2018-01-23 11:37:26 +0000990 llvm::function_ref<void(const Symbol &)> Callback) const override {
Ilya Biryukov5c4d6e62018-09-06 11:04:56 +0000991 std::lock_guard<std::mutex> Lock(Mut);
Haojian Wu061c73e2018-01-23 11:37:26 +0000992 Requests.push_back(Req);
Sam McCallab8e3932018-02-19 13:04:41 +0000993 return true;
Haojian Wu061c73e2018-01-23 11:37:26 +0000994 }
995
Eric Liu9ec459f2018-03-14 09:48:05 +0000996 void lookup(const LookupRequest &,
997 llvm::function_ref<void(const Symbol &)>) const override {}
998
Sam McCallb0138312018-09-04 14:39:56 +0000999 void refs(const RefsRequest &,
1000 llvm::function_ref<void(const Ref &)>) const override {}
Haojian Wu65ac3212018-08-06 13:14:32 +00001001
Kirill Bobyrevfc890012018-08-24 09:12:54 +00001002 // This is incorrect, but IndexRequestCollector is not an actual index and it
1003 // isn't used in production code.
1004 size_t estimateMemoryUsage() const override { return 0; }
1005
Eric Liu25d74e92018-08-24 11:23:56 +00001006 const std::vector<FuzzyFindRequest> consumeRequests() const {
Ilya Biryukov5c4d6e62018-09-06 11:04:56 +00001007 std::lock_guard<std::mutex> Lock(Mut);
Eric Liu25d74e92018-08-24 11:23:56 +00001008 auto Reqs = std::move(Requests);
1009 Requests = {};
1010 return Reqs;
1011 }
Haojian Wu061c73e2018-01-23 11:37:26 +00001012
1013private:
Ilya Biryukov5c4d6e62018-09-06 11:04:56 +00001014 // We need a mutex to handle async fuzzy find requests.
1015 mutable std::mutex Mut;
Haojian Wu061c73e2018-01-23 11:37:26 +00001016 mutable std::vector<FuzzyFindRequest> Requests;
1017};
1018
1019std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code) {
1020 clangd::CodeCompleteOptions Opts;
1021 IndexRequestCollector Requests;
1022 Opts.Index = &Requests;
1023 completions(Code, {}, Opts);
Eric Liu25d74e92018-08-24 11:23:56 +00001024 return Requests.consumeRequests();
Haojian Wu061c73e2018-01-23 11:37:26 +00001025}
1026
1027TEST(CompletionTest, UnqualifiedIdQuery) {
1028 auto Requests = captureIndexRequests(R"cpp(
1029 namespace std {}
1030 using namespace std;
1031 namespace ns {
1032 void f() {
1033 vec^
1034 }
1035 }
1036 )cpp");
1037
1038 EXPECT_THAT(Requests,
1039 ElementsAre(Field(&FuzzyFindRequest::Scopes,
1040 UnorderedElementsAre("", "ns::", "std::"))));
1041}
1042
1043TEST(CompletionTest, ResolvedQualifiedIdQuery) {
1044 auto Requests = captureIndexRequests(R"cpp(
1045 namespace ns1 {}
1046 namespace ns2 {} // ignore
1047 namespace ns3 { namespace nns3 {} }
1048 namespace foo {
1049 using namespace ns1;
1050 using namespace ns3::nns3;
1051 }
1052 namespace ns {
1053 void f() {
1054 foo::^
1055 }
1056 }
1057 )cpp");
1058
1059 EXPECT_THAT(Requests,
1060 ElementsAre(Field(
1061 &FuzzyFindRequest::Scopes,
1062 UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::"))));
1063}
1064
1065TEST(CompletionTest, UnresolvedQualifierIdQuery) {
1066 auto Requests = captureIndexRequests(R"cpp(
1067 namespace a {}
1068 using namespace a;
1069 namespace ns {
1070 void f() {
1071 bar::^
1072 }
1073 } // namespace ns
1074 )cpp");
1075
1076 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1077 UnorderedElementsAre("bar::"))));
1078}
1079
1080TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
1081 auto Requests = captureIndexRequests(R"cpp(
1082 namespace a {}
1083 using namespace a;
1084 namespace ns {
1085 void f() {
1086 ::a::bar::^
1087 }
1088 } // namespace ns
1089 )cpp");
1090
1091 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1092 UnorderedElementsAre("a::bar::"))));
1093}
1094
1095TEST(CompletionTest, EmptyQualifiedQuery) {
1096 auto Requests = captureIndexRequests(R"cpp(
1097 namespace ns {
1098 void f() {
1099 ^
1100 }
1101 } // namespace ns
1102 )cpp");
1103
1104 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1105 UnorderedElementsAre("", "ns::"))));
1106}
1107
1108TEST(CompletionTest, GlobalQualifiedQuery) {
1109 auto Requests = captureIndexRequests(R"cpp(
1110 namespace ns {
1111 void f() {
1112 ::^
1113 }
1114 } // namespace ns
1115 )cpp");
1116
1117 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1118 UnorderedElementsAre(""))));
1119}
1120
Ilya Biryukova907ba42018-05-14 10:50:04 +00001121TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
1122 auto Completions = completions(
1123 R"cpp(
1124 struct Foo {
1125 int SomeNameOfField;
1126 typedef int SomeNameOfTypedefField;
1127 };
1128
1129 Foo::^)cpp",
1130 {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")});
1131
Sam McCalle746a2b2018-07-02 11:13:16 +00001132 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001133 AllOf(Contains(Labeled("SomeNameOfField")),
1134 Contains(Labeled("SomeNameOfTypedefField")),
1135 Not(Contains(Labeled("SomeNameInTheIndex")))));
1136}
1137
1138TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
1139 {
1140 auto Completions = completions(
1141 R"cpp(
1142 template <class T>
1143 void foo() {
1144 T::^
1145 }
1146 )cpp",
1147 {func("::SomeNameInTheIndex")});
1148
Sam McCalle746a2b2018-07-02 11:13:16 +00001149 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001150 Not(Contains(Labeled("SomeNameInTheIndex"))));
1151 }
1152
1153 {
1154 auto Completions = completions(
1155 R"cpp(
1156 template <class T>
1157 void foo() {
1158 T::template Y<int>::^
1159 }
1160 )cpp",
1161 {func("::SomeNameInTheIndex")});
1162
Sam McCalle746a2b2018-07-02 11:13:16 +00001163 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001164 Not(Contains(Labeled("SomeNameInTheIndex"))));
1165 }
1166
1167 {
1168 auto Completions = completions(
1169 R"cpp(
1170 template <class T>
1171 void foo() {
1172 T::foo::^
1173 }
1174 )cpp",
1175 {func("::SomeNameInTheIndex")});
1176
Sam McCalle746a2b2018-07-02 11:13:16 +00001177 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001178 Not(Contains(Labeled("SomeNameInTheIndex"))));
1179 }
1180}
1181
Sam McCallc18c2802018-06-15 11:06:29 +00001182TEST(CompletionTest, OverloadBundling) {
1183 clangd::CodeCompleteOptions Opts;
1184 Opts.BundleOverloads = true;
1185
1186 std::string Context = R"cpp(
1187 struct X {
1188 // Overload with int
1189 int a(int);
1190 // Overload with bool
1191 int a(bool);
1192 int b(float);
1193 };
1194 int GFuncC(int);
1195 int GFuncD(int);
1196 )cpp";
1197
1198 // Member completions are bundled.
Sam McCalle746a2b2018-07-02 11:13:16 +00001199 EXPECT_THAT(completions(Context + "int y = X().^", {}, Opts).Completions,
Sam McCallc18c2802018-06-15 11:06:29 +00001200 UnorderedElementsAre(Labeled("a(…)"), Labeled("b(float)")));
1201
1202 // Non-member completions are bundled, including index+sema.
1203 Symbol NoArgsGFunc = func("GFuncC");
1204 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001205 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
Sam McCallc18c2802018-06-15 11:06:29 +00001206 UnorderedElementsAre(Labeled("GFuncC(…)"), Labeled("GFuncD(int)")));
1207
1208 // Differences in header-to-insert suppress bundling.
Sam McCallc18c2802018-06-15 11:06:29 +00001209 std::string DeclFile = URI::createFile(testPath("foo")).toString();
1210 NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile;
Eric Liu83f63e42018-09-03 10:18:21 +00001211 NoArgsGFunc.IncludeHeaders.emplace_back("<foo>", 1);
Sam McCallc18c2802018-06-15 11:06:29 +00001212 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001213 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1214 UnorderedElementsAre(AllOf(Named("GFuncC"), InsertInclude("<foo>")),
1215 Labeled("GFuncC(int)"), Labeled("GFuncD(int)")));
Sam McCallc18c2802018-06-15 11:06:29 +00001216
1217 // Examine a bundled completion in detail.
Sam McCalle746a2b2018-07-02 11:13:16 +00001218 auto A =
1219 completions(Context + "int y = X().a^", {}, Opts).Completions.front();
1220 EXPECT_EQ(A.Name, "a");
1221 EXPECT_EQ(A.Signature, "(…)");
1222 EXPECT_EQ(A.BundleSize, 2u);
1223 EXPECT_EQ(A.Kind, CompletionItemKind::Method);
1224 EXPECT_EQ(A.ReturnType, "int"); // All overloads return int.
Sam McCallc18c2802018-06-15 11:06:29 +00001225 // For now we just return one of the doc strings arbitrarily.
Sam McCalle746a2b2018-07-02 11:13:16 +00001226 EXPECT_THAT(A.Documentation, AnyOf(HasSubstr("Overload with int"),
Sam McCallc18c2802018-06-15 11:06:29 +00001227 HasSubstr("Overload with bool")));
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001228 EXPECT_EQ(A.SnippetSuffix, "($0)");
Sam McCallc18c2802018-06-15 11:06:29 +00001229}
1230
Ilya Biryukov30b04b12018-05-28 09:54:51 +00001231TEST(CompletionTest, DocumentationFromChangedFileCrash) {
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001232 MockFSProvider FS;
1233 auto FooH = testPath("foo.h");
1234 auto FooCpp = testPath("foo.cpp");
1235 FS.Files[FooH] = R"cpp(
1236 // this is my documentation comment.
1237 int func();
1238 )cpp";
1239 FS.Files[FooCpp] = "";
1240
1241 MockCompilationDatabase CDB;
1242 IgnoreDiagnostics DiagConsumer;
1243 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1244
1245 Annotations Source(R"cpp(
1246 #include "foo.h"
1247 int func() {
1248 // This makes sure we have func from header in the AST.
1249 }
1250 int a = fun^
1251 )cpp");
1252 Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
1253 // We need to wait for preamble to build.
1254 ASSERT_TRUE(Server.blockUntilIdleForTest());
1255
1256 // Change the header file. Completion will reuse the old preamble!
1257 FS.Files[FooH] = R"cpp(
1258 int func();
1259 )cpp";
1260
1261 clangd::CodeCompleteOptions Opts;
1262 Opts.IncludeComments = true;
Sam McCalle746a2b2018-07-02 11:13:16 +00001263 CodeCompleteResult Completions =
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001264 cantFail(runCodeComplete(Server, FooCpp, Source.point(), Opts));
1265 // We shouldn't crash. Unfortunately, current workaround is to not produce
1266 // comments for symbols from headers.
Sam McCalle746a2b2018-07-02 11:13:16 +00001267 EXPECT_THAT(Completions.Completions,
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001268 Contains(AllOf(Not(IsDocumented()), Named("func"))));
1269}
1270
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001271TEST(CompletionTest, NonDocComments) {
1272 MockFSProvider FS;
1273 auto FooCpp = testPath("foo.cpp");
1274 FS.Files[FooCpp] = "";
1275
1276 MockCompilationDatabase CDB;
1277 IgnoreDiagnostics DiagConsumer;
1278 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1279
1280 Annotations Source(R"cpp(
Ilya Biryukovda8dd8b2018-06-27 09:47:20 +00001281 // We ignore namespace comments, for rationale see CodeCompletionStrings.h.
1282 namespace comments_ns {
1283 }
1284
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001285 // ------------------
1286 int comments_foo();
1287
1288 // A comment and a decl are separated by newlines.
1289 // Therefore, the comment shouldn't show up as doc comment.
1290
1291 int comments_bar();
1292
1293 // this comment should be in the results.
1294 int comments_baz();
1295
1296
1297 template <class T>
1298 struct Struct {
1299 int comments_qux();
1300 int comments_quux();
1301 };
1302
1303
1304 // This comment should not be there.
1305
1306 template <class T>
1307 int Struct<T>::comments_qux() {
1308 }
1309
1310 // This comment **should** be in results.
1311 template <class T>
1312 int Struct<T>::comments_quux() {
1313 int a = comments^;
1314 }
1315 )cpp");
Reid Kleckner80274b12018-06-18 18:55:10 +00001316 // FIXME: Auto-completion in a template requires disabling delayed template
1317 // parsing.
1318 CDB.ExtraClangFlags.push_back("-fno-delayed-template-parsing");
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001319 Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
Sam McCalle746a2b2018-07-02 11:13:16 +00001320 CodeCompleteResult Completions = cantFail(runCodeComplete(
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001321 Server, FooCpp, Source.point(), clangd::CodeCompleteOptions()));
1322
1323 // We should not get any of those comments in completion.
1324 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001325 Completions.Completions,
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001326 UnorderedElementsAre(AllOf(Not(IsDocumented()), Named("comments_foo")),
1327 AllOf(IsDocumented(), Named("comments_baz")),
1328 AllOf(IsDocumented(), Named("comments_quux")),
Ilya Biryukovda8dd8b2018-06-27 09:47:20 +00001329 AllOf(Not(IsDocumented()), Named("comments_ns")),
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001330 // FIXME(ibiryukov): the following items should have
1331 // empty documentation, since they are separated from
1332 // a comment with an empty line. Unfortunately, I
1333 // couldn't make Sema tests pass if we ignore those.
1334 AllOf(IsDocumented(), Named("comments_bar")),
1335 AllOf(IsDocumented(), Named("comments_qux"))));
1336}
1337
Ilya Biryukov981a35d2018-05-28 12:11:37 +00001338TEST(CompletionTest, CompleteOnInvalidLine) {
1339 auto FooCpp = testPath("foo.cpp");
1340
1341 MockCompilationDatabase CDB;
1342 IgnoreDiagnostics DiagConsumer;
1343 MockFSProvider FS;
1344 FS.Files[FooCpp] = "// empty file";
1345
1346 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1347 // Run completion outside the file range.
1348 Position Pos;
1349 Pos.line = 100;
1350 Pos.character = 0;
1351 EXPECT_THAT_EXPECTED(
1352 runCodeComplete(Server, FooCpp, Pos, clangd::CodeCompleteOptions()),
1353 Failed());
1354}
1355
Eric Liu7ad16962018-06-22 10:46:59 +00001356TEST(CompletionTest, QualifiedNames) {
1357 auto Results = completions(
1358 R"cpp(
1359 namespace ns { int local; void both(); }
1360 void f() { ::ns::^ }
1361 )cpp",
1362 {func("ns::both"), cls("ns::Index")});
1363 // We get results from both index and sema, with no duplicates.
Sam McCalle746a2b2018-07-02 11:13:16 +00001364 EXPECT_THAT(
1365 Results.Completions,
1366 UnorderedElementsAre(Scope("ns::"), Scope("ns::"), Scope("ns::")));
1367}
1368
1369TEST(CompletionTest, Render) {
1370 CodeCompletion C;
1371 C.Name = "x";
1372 C.Signature = "(bool) const";
1373 C.SnippetSuffix = "(${0:bool})";
1374 C.ReturnType = "int";
1375 C.RequiredQualifier = "Foo::";
1376 C.Scope = "ns::Foo::";
1377 C.Documentation = "This is x().";
Eric Liu83f63e42018-09-03 10:18:21 +00001378 C.Includes.emplace_back();
1379 auto &Include = C.Includes.back();
1380 Include.Header = "\"foo.h\"";
Sam McCalle746a2b2018-07-02 11:13:16 +00001381 C.Kind = CompletionItemKind::Method;
1382 C.Score.Total = 1.0;
Sam McCall4e5742a2018-07-06 11:50:49 +00001383 C.Origin = SymbolOrigin::AST | SymbolOrigin::Static;
Sam McCalle746a2b2018-07-02 11:13:16 +00001384
1385 CodeCompleteOptions Opts;
1386 Opts.IncludeIndicator.Insert = "^";
1387 Opts.IncludeIndicator.NoInsert = "";
1388 Opts.EnableSnippets = false;
1389
1390 auto R = C.render(Opts);
1391 EXPECT_EQ(R.label, "Foo::x(bool) const");
1392 EXPECT_EQ(R.insertText, "Foo::x");
1393 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
1394 EXPECT_EQ(R.filterText, "x");
1395 EXPECT_EQ(R.detail, "int\n\"foo.h\"");
1396 EXPECT_EQ(R.documentation, "This is x().");
1397 EXPECT_THAT(R.additionalTextEdits, IsEmpty());
Sam McCalle746a2b2018-07-02 11:13:16 +00001398 EXPECT_EQ(R.sortText, sortText(1.0, "x"));
Eric Liu6df66002018-09-06 18:52:26 +00001399 EXPECT_FALSE(R.deprecated);
Sam McCalle746a2b2018-07-02 11:13:16 +00001400
1401 Opts.EnableSnippets = true;
1402 R = C.render(Opts);
1403 EXPECT_EQ(R.insertText, "Foo::x(${0:bool})");
1404 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
1405
Eric Liu83f63e42018-09-03 10:18:21 +00001406 Include.Insertion.emplace();
Sam McCalle746a2b2018-07-02 11:13:16 +00001407 R = C.render(Opts);
1408 EXPECT_EQ(R.label, "^Foo::x(bool) const");
1409 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
1410
Sam McCall2161ec72018-07-05 06:20:41 +00001411 Opts.ShowOrigins = true;
1412 R = C.render(Opts);
1413 EXPECT_EQ(R.label, "^[AS]Foo::x(bool) const");
1414
Sam McCalle746a2b2018-07-02 11:13:16 +00001415 C.BundleSize = 2;
1416 R = C.render(Opts);
1417 EXPECT_EQ(R.detail, "[2 overloads]\n\"foo.h\"");
Eric Liu6df66002018-09-06 18:52:26 +00001418
1419 C.Deprecated = true;
1420 R = C.render(Opts);
1421 EXPECT_TRUE(R.deprecated);
Eric Liu7ad16962018-06-22 10:46:59 +00001422}
Ilya Biryukov981a35d2018-05-28 12:11:37 +00001423
Eric Liu485074f2018-07-11 13:15:31 +00001424TEST(CompletionTest, IgnoreRecoveryResults) {
1425 auto Results = completions(
1426 R"cpp(
1427 namespace ns { int NotRecovered() { return 0; } }
1428 void f() {
1429 // Sema enters recovery mode first and then normal mode.
1430 if (auto x = ns::NotRecover^)
1431 }
1432 )cpp");
1433 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("NotRecovered")));
1434}
1435
Eric Liuf433c2d2018-07-18 15:31:14 +00001436TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
1437 auto Results = completions(
1438 R"cpp(
1439 namespace ns {
1440 class X { public: X(); int x_; };
1441 X::X() : x_^(0) {}
1442 }
1443 )cpp");
1444 EXPECT_THAT(Results.Completions,
1445 UnorderedElementsAre(AllOf(Scope("ns::X::"), Named("x_"))));
1446}
1447
Eric Liu5d2a8072018-07-23 10:56:37 +00001448TEST(CompletionTest, CodeCompletionContext) {
1449 auto Results = completions(
1450 R"cpp(
1451 namespace ns {
1452 class X { public: X(); int x_; };
1453 void f() {
1454 X x;
1455 x.^;
1456 }
1457 }
1458 )cpp");
1459
1460 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
1461}
1462
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001463TEST(CompletionTest, FixItForArrowToDot) {
1464 MockFSProvider FS;
1465 MockCompilationDatabase CDB;
1466 IgnoreDiagnostics DiagConsumer;
1467 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1468
1469 CodeCompleteOptions Opts;
1470 Opts.IncludeFixIts = true;
1471 Annotations TestCode(
1472 R"cpp(
1473 class Auxilary {
1474 public:
1475 void AuxFunction();
1476 };
1477 class ClassWithPtr {
1478 public:
1479 void MemberFunction();
1480 Auxilary* operator->() const;
1481 Auxilary* Aux;
1482 };
1483 void f() {
1484 ClassWithPtr x;
1485 x[[->]]^;
1486 }
1487 )cpp");
1488 auto Results =
1489 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1490 EXPECT_EQ(Results.Completions.size(), 3u);
1491
1492 TextEdit ReplacementEdit;
1493 ReplacementEdit.range = TestCode.range();
1494 ReplacementEdit.newText = ".";
1495 for (const auto &C : Results.Completions) {
1496 EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction");
Haojian Wu1793bc92018-08-10 08:34:16 +00001497 if (!C.FixIts.empty()) {
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001498 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
Haojian Wu1793bc92018-08-10 08:34:16 +00001499 }
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001500 }
1501}
1502
1503TEST(CompletionTest, FixItForDotToArrow) {
1504 MockFSProvider FS;
1505 MockCompilationDatabase CDB;
1506 IgnoreDiagnostics DiagConsumer;
1507 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1508
1509 CodeCompleteOptions Opts;
1510 Opts.IncludeFixIts = true;
1511 Annotations TestCode(
1512 R"cpp(
1513 class Auxilary {
1514 public:
1515 void AuxFunction();
1516 };
1517 class ClassWithPtr {
1518 public:
1519 void MemberFunction();
1520 Auxilary* operator->() const;
1521 Auxilary* Aux;
1522 };
1523 void f() {
1524 ClassWithPtr x;
1525 x[[.]]^;
1526 }
1527 )cpp");
1528 auto Results =
1529 completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
1530 EXPECT_EQ(Results.Completions.size(), 3u);
1531
1532 TextEdit ReplacementEdit;
1533 ReplacementEdit.range = TestCode.range();
1534 ReplacementEdit.newText = "->";
1535 for (const auto &C : Results.Completions) {
1536 EXPECT_TRUE(C.FixIts.empty() || C.Name == "AuxFunction");
1537 if (!C.FixIts.empty()) {
1538 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
1539 }
1540 }
1541}
1542
Kadir Cetinkayaa9c9d002018-08-13 08:23:01 +00001543TEST(CompletionTest, RenderWithFixItMerged) {
1544 TextEdit FixIt;
1545 FixIt.range.end.character = 5;
1546 FixIt.newText = "->";
1547
1548 CodeCompletion C;
1549 C.Name = "x";
1550 C.RequiredQualifier = "Foo::";
1551 C.FixIts = {FixIt};
1552 C.CompletionTokenRange.start.character = 5;
1553
1554 CodeCompleteOptions Opts;
1555 Opts.IncludeFixIts = true;
1556
1557 auto R = C.render(Opts);
1558 EXPECT_TRUE(R.textEdit);
1559 EXPECT_EQ(R.textEdit->newText, "->Foo::x");
1560 EXPECT_TRUE(R.additionalTextEdits.empty());
1561}
1562
1563TEST(CompletionTest, RenderWithFixItNonMerged) {
1564 TextEdit FixIt;
1565 FixIt.range.end.character = 4;
1566 FixIt.newText = "->";
1567
1568 CodeCompletion C;
1569 C.Name = "x";
1570 C.RequiredQualifier = "Foo::";
1571 C.FixIts = {FixIt};
1572 C.CompletionTokenRange.start.character = 5;
1573
1574 CodeCompleteOptions Opts;
1575 Opts.IncludeFixIts = true;
1576
1577 auto R = C.render(Opts);
1578 EXPECT_TRUE(R.textEdit);
1579 EXPECT_EQ(R.textEdit->newText, "Foo::x");
1580 EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
1581}
1582
1583TEST(CompletionTest, CompletionTokenRange) {
1584 MockFSProvider FS;
1585 MockCompilationDatabase CDB;
1586 IgnoreDiagnostics DiagConsumer;
1587 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1588
1589 constexpr const char *TestCodes[] = {
1590 R"cpp(
1591 class Auxilary {
1592 public:
1593 void AuxFunction();
1594 };
1595 void f() {
1596 Auxilary x;
1597 x.[[Aux]]^;
1598 }
1599 )cpp",
1600 R"cpp(
1601 class Auxilary {
1602 public:
1603 void AuxFunction();
1604 };
1605 void f() {
1606 Auxilary x;
1607 x.[[]]^;
1608 }
1609 )cpp"};
1610 for (const auto &Text : TestCodes) {
1611 Annotations TestCode(Text);
1612 auto Results = completions(Server, TestCode.code(), TestCode.point());
1613
1614 EXPECT_EQ(Results.Completions.size(), 1u);
1615 EXPECT_THAT(Results.Completions.front().CompletionTokenRange, TestCode.range());
1616 }
1617}
1618
Kadir Cetinkayae486e372018-08-13 08:40:05 +00001619TEST(SignatureHelpTest, OverloadsOrdering) {
1620 const auto Results = signatures(R"cpp(
1621 void foo(int x);
1622 void foo(int x, float y);
1623 void foo(float x, int y);
1624 void foo(float x, float y);
1625 void foo(int x, int y = 0);
1626 int main() { foo(^); }
1627 )cpp");
1628 EXPECT_THAT(
1629 Results.signatures,
1630 ElementsAre(
1631 Sig("foo(int x) -> void", {"int x"}),
1632 Sig("foo(int x, int y = 0) -> void", {"int x", "int y = 0"}),
1633 Sig("foo(float x, int y) -> void", {"float x", "int y"}),
1634 Sig("foo(int x, float y) -> void", {"int x", "float y"}),
1635 Sig("foo(float x, float y) -> void", {"float x", "float y"})));
1636 // We always prefer the first signature.
1637 EXPECT_EQ(0, Results.activeSignature);
1638 EXPECT_EQ(0, Results.activeParameter);
1639}
1640
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001641TEST(SignatureHelpTest, InstantiatedSignatures) {
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001642 StringRef Sig0 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001643 template <class T>
1644 void foo(T, T, T);
1645
1646 int main() {
1647 foo<int>(^);
1648 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001649 )cpp";
1650
1651 EXPECT_THAT(signatures(Sig0).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001652 ElementsAre(Sig("foo(T, T, T) -> void", {"T", "T", "T"})));
1653
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001654 StringRef Sig1 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001655 template <class T>
1656 void foo(T, T, T);
1657
1658 int main() {
1659 foo(10, ^);
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001660 })cpp";
1661
1662 EXPECT_THAT(signatures(Sig1).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001663 ElementsAre(Sig("foo(T, T, T) -> void", {"T", "T", "T"})));
1664
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001665 StringRef Sig2 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001666 template <class ...T>
1667 void foo(T...);
1668
1669 int main() {
1670 foo<int>(^);
1671 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001672 )cpp";
1673
1674 EXPECT_THAT(signatures(Sig2).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001675 ElementsAre(Sig("foo(T...) -> void", {"T..."})));
1676
1677 // It is debatable whether we should substitute the outer template parameter
1678 // ('T') in that case. Currently we don't substitute it in signature help, but
1679 // do substitute in code complete.
1680 // FIXME: make code complete and signature help consistent, figure out which
1681 // way is better.
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001682 StringRef Sig3 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001683 template <class T>
1684 struct X {
1685 template <class U>
1686 void foo(T, U);
1687 };
1688
1689 int main() {
1690 X<int>().foo<double>(^)
1691 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001692 )cpp";
1693
1694 EXPECT_THAT(signatures(Sig3).signatures,
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001695 ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
1696}
1697
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001698TEST(SignatureHelpTest, IndexDocumentation) {
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001699 Symbol Foo0 = sym("foo", index::SymbolKind::Function, "@F@\\0#");
Sam McCall2e5700f2018-08-31 13:55:01 +00001700 Foo0.Documentation = "Doc from the index";
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001701 Symbol Foo1 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#");
Sam McCall2e5700f2018-08-31 13:55:01 +00001702 Foo1.Documentation = "Doc from the index";
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001703 Symbol Foo2 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#I#");
1704
Simon Pilgrim24d34922018-08-17 10:40:05 +00001705 StringRef Sig0 = R"cpp(
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001706 int foo();
1707 int foo(double);
1708
1709 void test() {
1710 foo(^);
1711 }
Simon Pilgrim24d34922018-08-17 10:40:05 +00001712 )cpp";
1713
1714 EXPECT_THAT(
1715 signatures(Sig0, {Foo0}).signatures,
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001716 ElementsAre(AllOf(Sig("foo() -> int", {}), SigDoc("Doc from the index")),
1717 AllOf(Sig("foo(double) -> int", {"double"}), SigDoc(""))));
1718
Simon Pilgrim24d34922018-08-17 10:40:05 +00001719 StringRef Sig1 = R"cpp(
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001720 int foo();
1721 // Overriden doc from sema
1722 int foo(int);
1723 // Doc from sema
1724 int foo(int, int);
1725
1726 void test() {
1727 foo(^);
1728 }
Simon Pilgrim24d34922018-08-17 10:40:05 +00001729 )cpp";
1730
1731 EXPECT_THAT(
1732 signatures(Sig1, {Foo0, Foo1, Foo2}).signatures,
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001733 ElementsAre(AllOf(Sig("foo() -> int", {}), SigDoc("Doc from the index")),
1734 AllOf(Sig("foo(int) -> int", {"int"}),
1735 SigDoc("Overriden doc from sema")),
1736 AllOf(Sig("foo(int, int) -> int", {"int", "int"}),
1737 SigDoc("Doc from sema"))));
1738}
1739
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001740TEST(CompletionTest, CompletionFunctionArgsDisabled) {
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001741 CodeCompleteOptions Opts;
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001742 Opts.EnableSnippets = true;
1743 Opts.EnableFunctionArgSnippets = false;
Ilya Biryukov4f984702018-09-26 05:45:31 +00001744
1745 {
1746 auto Results = completions(
1747 R"cpp(
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001748 void xfoo();
1749 void xfoo(int x, int y);
Ilya Biryukov4f984702018-09-26 05:45:31 +00001750 void f() { xfo^ })cpp",
1751 {}, Opts);
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001752 EXPECT_THAT(
1753 Results.Completions,
1754 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("()")),
1755 AllOf(Named("xfoo"), SnippetSuffix("($0)"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001756 }
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001757 {
Ilya Biryukov4f984702018-09-26 05:45:31 +00001758 auto Results = completions(
1759 R"cpp(
1760 void xbar();
1761 void f() { xba^ })cpp",
1762 {}, Opts);
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001763 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
1764 Named("xbar"), SnippetSuffix("()"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001765 }
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001766 {
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001767 Opts.BundleOverloads = true;
Ilya Biryukov4f984702018-09-26 05:45:31 +00001768 auto Results = completions(
1769 R"cpp(
1770 void xfoo();
1771 void xfoo(int x, int y);
1772 void f() { xfo^ })cpp",
1773 {}, Opts);
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001774 EXPECT_THAT(
1775 Results.Completions,
1776 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("($0)"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001777 }
Ilya Biryukov4f984702018-09-26 05:45:31 +00001778 {
1779 auto Results = completions(
1780 R"cpp(
1781 template <class T, class U>
1782 void xfoo(int a, U b);
1783 void f() { xfo^ })cpp",
1784 {}, Opts);
1785 EXPECT_THAT(
1786 Results.Completions,
1787 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("<$1>($0)"))));
1788 }
1789 {
1790 auto Results = completions(
1791 R"cpp(
1792 template <class T>
1793 class foo_class{};
1794 template <class T>
1795 using foo_alias = T**;
1796 void f() { foo_^ })cpp",
1797 {}, Opts);
1798 EXPECT_THAT(
1799 Results.Completions,
1800 UnorderedElementsAre(AllOf(Named("foo_class"), SnippetSuffix("<$0>")),
1801 AllOf(Named("foo_alias"), SnippetSuffix("<$0>"))));
1802 }
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00001803}
1804
Kadir Cetinkayaf8b85a32018-08-23 13:14:50 +00001805TEST(CompletionTest, SuggestOverrides) {
1806 constexpr const char *const Text(R"cpp(
1807 class A {
1808 public:
1809 virtual void vfunc(bool param);
1810 virtual void vfunc(bool param, int p);
1811 void func(bool param);
1812 };
1813 class B : public A {
1814 virtual void ttt(bool param) const;
1815 void vfunc(bool param, int p) override;
1816 };
1817 class C : public B {
1818 public:
1819 void vfunc(bool param) override;
1820 ^
1821 };
1822 )cpp");
1823 const auto Results = completions(Text);
1824 EXPECT_THAT(Results.Completions,
1825 AllOf(Contains(Labeled("void vfunc(bool param, int p) override")),
1826 Contains(Labeled("void ttt(bool param) const override")),
1827 Not(Contains(Labeled("void vfunc(bool param) override")))));
1828}
1829
Ilya Biryukov5a79d1e2018-09-03 15:25:27 +00001830TEST(CompletionTest, OverridesNonIdentName) {
1831 // Check the completions call does not crash.
1832 completions(R"cpp(
1833 struct Base {
1834 virtual ~Base() = 0;
1835 virtual operator int() = 0;
1836 virtual Base& operator+(Base&) = 0;
1837 };
1838
1839 struct Derived : Base {
1840 ^
1841 };
1842 )cpp");
1843}
1844
Eric Liu25d74e92018-08-24 11:23:56 +00001845TEST(SpeculateCompletionFilter, Filters) {
1846 Annotations F(R"cpp($bof^
1847 $bol^
1848 ab$ab^
1849 x.ab$dot^
1850 x.$dotempty^
1851 x::ab$scoped^
1852 x::$scopedempty^
1853
1854 )cpp");
1855 auto speculate = [&](StringRef PointName) {
1856 auto Filter = speculateCompletionFilter(F.code(), F.point(PointName));
1857 assert(Filter);
1858 return *Filter;
1859 };
1860 EXPECT_EQ(speculate("bof"), "");
1861 EXPECT_EQ(speculate("bol"), "");
1862 EXPECT_EQ(speculate("ab"), "ab");
1863 EXPECT_EQ(speculate("dot"), "ab");
1864 EXPECT_EQ(speculate("dotempty"), "");
1865 EXPECT_EQ(speculate("scoped"), "ab");
1866 EXPECT_EQ(speculate("scopedempty"), "");
1867}
1868
1869TEST(CompletionTest, EnableSpeculativeIndexRequest) {
1870 MockFSProvider FS;
1871 MockCompilationDatabase CDB;
1872 IgnoreDiagnostics DiagConsumer;
1873 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1874
1875 auto File = testPath("foo.cpp");
1876 Annotations Test(R"cpp(
1877 namespace ns1 { int abc; }
1878 namespace ns2 { int abc; }
1879 void f() { ns1::ab$1^; ns1::ab$2^; }
1880 void f() { ns2::ab$3^; }
1881 )cpp");
1882 runAddDocument(Server, File, Test.code());
1883 clangd::CodeCompleteOptions Opts = {};
1884
1885 IndexRequestCollector Requests;
1886 Opts.Index = &Requests;
1887 Opts.SpeculativeIndexRequest = true;
1888
1889 auto CompleteAtPoint = [&](StringRef P) {
1890 cantFail(runCodeComplete(Server, File, Test.point(P), Opts));
1891 // Sleep for a while to make sure asynchronous call (if applicable) is also
1892 // triggered before callback is invoked.
1893 std::this_thread::sleep_for(std::chrono::milliseconds(100));
1894 };
1895
1896 CompleteAtPoint("1");
1897 auto Reqs1 = Requests.consumeRequests();
1898 ASSERT_EQ(Reqs1.size(), 1u);
1899 EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre("ns1::"));
1900
1901 CompleteAtPoint("2");
1902 auto Reqs2 = Requests.consumeRequests();
1903 // Speculation succeeded. Used speculative index result.
1904 ASSERT_EQ(Reqs2.size(), 1u);
1905 EXPECT_EQ(Reqs2[0], Reqs1[0]);
1906
1907 CompleteAtPoint("3");
1908 // Speculation failed. Sent speculative index request and the new index
1909 // request after sema.
1910 auto Reqs3 = Requests.consumeRequests();
1911 ASSERT_EQ(Reqs3.size(), 2u);
1912}
1913
Eric Liu83f63e42018-09-03 10:18:21 +00001914TEST(CompletionTest, InsertTheMostPopularHeader) {
1915 std::string DeclFile = URI::createFile(testPath("foo")).toString();
1916 Symbol sym = func("Func");
1917 sym.CanonicalDeclaration.FileURI = DeclFile;
1918 sym.IncludeHeaders.emplace_back("\"foo.h\"", 2);
1919 sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000);
1920
1921 auto Results = completions("Fun^", {sym}).Completions;
1922 assert(!Results.empty());
1923 EXPECT_THAT(Results[0], AllOf(Named("Func"), InsertInclude("\"bar.h\"")));
1924 EXPECT_EQ(Results[0].Includes.size(), 2u);
1925}
1926
1927TEST(CompletionTest, NoInsertIncludeIfOnePresent) {
1928 MockFSProvider FS;
1929 MockCompilationDatabase CDB;
1930
1931 std::string FooHeader = testPath("foo.h");
1932 FS.Files[FooHeader] = "";
1933
1934 IgnoreDiagnostics DiagConsumer;
1935 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1936
1937 std::string DeclFile = URI::createFile(testPath("foo")).toString();
1938 Symbol sym = func("Func");
1939 sym.CanonicalDeclaration.FileURI = DeclFile;
1940 sym.IncludeHeaders.emplace_back("\"foo.h\"", 2);
1941 sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000);
1942
1943 EXPECT_THAT(
1944 completions(Server, "#include \"foo.h\"\nFun^", {sym}).Completions,
1945 UnorderedElementsAre(
1946 AllOf(Named("Func"), HasInclude("\"foo.h\""), Not(InsertInclude()))));
1947}
1948
Eric Liud25f1212018-09-06 09:59:37 +00001949TEST(CompletionTest, MergeMacrosFromIndexAndSema) {
1950 Symbol Sym;
1951 Sym.Name = "Clangd_Macro_Test";
1952 Sym.ID = SymbolID("c:foo.cpp@8@macro@Clangd_Macro_Test");
1953 Sym.SymInfo.Kind = index::SymbolKind::Macro;
Eric Liu6df66002018-09-06 18:52:26 +00001954 Sym.Flags |= Symbol::IndexedForCodeCompletion;
Eric Liud25f1212018-09-06 09:59:37 +00001955 EXPECT_THAT(completions("#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym})
1956 .Completions,
1957 UnorderedElementsAre(Named("Clangd_Macro_Test")));
1958}
1959
Eric Liu467c5f92018-09-19 09:35:04 +00001960TEST(CompletionTest, NoMacroFromPreambleIfIndexIsSet) {
1961 auto Results = completions(
1962 R"cpp(#define CLANGD_PREAMBLE x
1963
1964 int x = 0;
1965 #define CLANGD_MAIN x
1966 void f() { CLANGD_^ }
1967 )cpp",
1968 {func("CLANGD_INDEX")});
1969 // Index is overriden in code completion options, so the preamble symbol is
1970 // not seen.
1971 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("CLANGD_MAIN"),
1972 Named("CLANGD_INDEX")));
1973}
1974
Eric Liu6df66002018-09-06 18:52:26 +00001975TEST(CompletionTest, DeprecatedResults) {
1976 std::string Body = R"cpp(
1977 void TestClangd();
1978 void TestClangc() __attribute__((deprecated("", "")));
1979 )cpp";
1980
1981 EXPECT_THAT(
1982 completions(Body + "int main() { TestClang^ }").Completions,
1983 UnorderedElementsAre(AllOf(Named("TestClangd"), Not(Deprecated())),
1984 AllOf(Named("TestClangc"), Deprecated())));
1985}
1986
Kadir Cetinkaya0b77d032018-09-10 14:22:42 +00001987TEST(SignatureHelpTest, InsideArgument) {
1988 {
1989 const auto Results = signatures(R"cpp(
1990 void foo(int x);
1991 void foo(int x, int y);
1992 int main() { foo(1+^); }
1993 )cpp");
1994 EXPECT_THAT(
1995 Results.signatures,
1996 ElementsAre(Sig("foo(int x) -> void", {"int x"}),
1997 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
1998 EXPECT_EQ(0, Results.activeParameter);
1999 }
2000 {
2001 const auto Results = signatures(R"cpp(
2002 void foo(int x);
2003 void foo(int x, int y);
2004 int main() { foo(1^); }
2005 )cpp");
2006 EXPECT_THAT(
2007 Results.signatures,
2008 ElementsAre(Sig("foo(int x) -> void", {"int x"}),
2009 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
2010 EXPECT_EQ(0, Results.activeParameter);
2011 }
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^0); }
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 bar(int x, int y);
2029 int main() { bar(foo(2, 3^)); }
2030 )cpp");
2031 EXPECT_THAT(Results.signatures, ElementsAre(Sig("foo(int x, int y) -> void",
2032 {"int x", "int y"})));
2033 EXPECT_EQ(1, Results.activeParameter);
2034 }
2035}
2036
Kadir Cetinkaya873cae52018-09-11 15:12:10 +00002037TEST(SignatureHelpTest, ConstructorInitializeFields) {
2038 {
2039 const auto Results = signatures(R"cpp(
2040 struct A {
2041 A(int);
2042 };
2043 struct B {
2044 B() : a_elem(^) {}
2045 A a_elem;
2046 };
2047 )cpp");
2048 EXPECT_THAT(Results.signatures, UnorderedElementsAre(
2049 Sig("A(int)", {"int"}),
2050 Sig("A(A &&)", {"A &&"}),
2051 Sig("A(const A &)", {"const A &"})
2052 ));
2053 }
2054 {
2055 const auto Results = signatures(R"cpp(
2056 struct A {
2057 A(int);
2058 };
2059 struct C {
2060 C(int);
2061 C(A);
2062 };
2063 struct B {
2064 B() : c_elem(A(1^)) {}
2065 C c_elem;
2066 };
2067 )cpp");
2068 EXPECT_THAT(Results.signatures, UnorderedElementsAre(
2069 Sig("A(int)", {"int"}),
2070 Sig("A(A &&)", {"A &&"}),
2071 Sig("A(const A &)", {"const A &"})
2072 ));
2073 }
2074}
2075
Kadir Cetinkaya0ed5d292018-09-27 14:21:07 +00002076TEST(CompletionTest, IncludedCompletionKinds) {
2077 MockFSProvider FS;
2078 MockCompilationDatabase CDB;
2079 std::string Subdir = testPath("sub");
2080 std::string SearchDirArg = (llvm::Twine("-I") + Subdir).str();
2081 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
2082 std::string BarHeader = testPath("sub/bar.h");
2083 FS.Files[BarHeader] = "";
2084 IgnoreDiagnostics DiagConsumer;
2085 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
2086 auto Results = completions(Server,
2087 R"cpp(
2088 #include "^"
2089 )cpp"
2090 );
2091 EXPECT_THAT(Results.Completions,
2092 AllOf(Has("sub/", CompletionItemKind::Folder),
2093 Has("bar.h\"", CompletionItemKind::File)));
2094}
2095
Eric Liu670c1472018-09-27 18:46:00 +00002096TEST(CompletionTest, NoAllScopesCompletionWhenQualified) {
2097 clangd::CodeCompleteOptions Opts = {};
2098 Opts.AllScopes = true;
2099
2100 auto Results = completions(
2101 R"cpp(
2102 void f() { na::Clangd^ }
2103 )cpp",
2104 {cls("na::ClangdA"), cls("nx::ClangdX"), cls("Clangd3")}, Opts);
2105 EXPECT_THAT(Results.Completions,
2106 UnorderedElementsAre(
2107 AllOf(Qualifier(""), Scope("na::"), Named("ClangdA"))));
2108}
2109
2110TEST(CompletionTest, AllScopesCompletion) {
2111 clangd::CodeCompleteOptions Opts = {};
2112 Opts.AllScopes = true;
2113
2114 auto Results = completions(
2115 R"cpp(
2116 namespace na {
2117 void f() { Clangd^ }
2118 }
2119 )cpp",
2120 {cls("nx::Clangd1"), cls("ny::Clangd2"), cls("Clangd3"),
2121 cls("na::nb::Clangd4")},
2122 Opts);
2123 EXPECT_THAT(
2124 Results.Completions,
2125 UnorderedElementsAre(AllOf(Qualifier("nx::"), Named("Clangd1")),
2126 AllOf(Qualifier("ny::"), Named("Clangd2")),
2127 AllOf(Qualifier(""), Scope(""), Named("Clangd3")),
2128 AllOf(Qualifier("nb::"), Named("Clangd4"))));
2129}
2130
2131TEST(CompletionTest, NoQualifierIfShadowed) {
2132 clangd::CodeCompleteOptions Opts = {};
2133 Opts.AllScopes = true;
2134
2135 auto Results = completions(R"cpp(
2136 namespace nx { class Clangd1 {}; }
2137 using nx::Clangd1;
2138 void f() { Clangd^ }
2139 )cpp",
2140 {cls("nx::Clangd1"), cls("nx::Clangd2")}, Opts);
2141 // Although Clangd1 is from another namespace, Sema tells us it's in-scope and
2142 // needs no qualifier.
2143 EXPECT_THAT(Results.Completions,
2144 UnorderedElementsAre(AllOf(Qualifier(""), Named("Clangd1")),
2145 AllOf(Qualifier("nx::"), Named("Clangd2"))));
2146}
Kadir Cetinkaya0ed5d292018-09-27 14:21:07 +00002147
Sam McCall9aad25f2017-12-05 07:20:26 +00002148} // namespace
2149} // namespace clangd
2150} // namespace clang