blob: afa6f1b8d91b469a12204240312e4cf76e98dc76 [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 McCallb536a2a2017-12-19 12:23:48 +000016#include "SourceCode.h"
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000017#include "SyncAPI.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000018#include "TestFS.h"
Eric Liu6f648df2017-12-19 16:50:37 +000019#include "index/MemIndex.h"
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +000020#include "llvm/Support/Error.h"
Sam McCallf6ae3232017-12-05 20:11:29 +000021#include "gmock/gmock.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000022#include "gtest/gtest.h"
23
24namespace clang {
25namespace clangd {
Sam McCallf6ae3232017-12-05 20:11:29 +000026
Sam McCall9aad25f2017-12-05 07:20:26 +000027namespace {
28using namespace llvm;
Sam McCallf6ae3232017-12-05 20:11:29 +000029using ::testing::AllOf;
30using ::testing::Contains;
Ilya Biryukov5a5e1ca2017-12-29 14:59:22 +000031using ::testing::Each;
Sam McCallf6ae3232017-12-05 20:11:29 +000032using ::testing::ElementsAre;
Ilya Biryukov71028b82018-03-12 15:28:22 +000033using ::testing::Field;
Sam McCallf6ae3232017-12-05 20:11:29 +000034using ::testing::Not;
Sam McCall3d139c52018-01-12 18:30:08 +000035using ::testing::UnorderedElementsAre;
Sam McCall9aad25f2017-12-05 07:20:26 +000036
37class IgnoreDiagnostics : public DiagnosticsConsumer {
Ilya Biryukov71028b82018-03-12 15:28:22 +000038 void onDiagnosticsReady(PathRef File,
Sam McCalla7bb0cc2018-03-12 23:22:35 +000039 std::vector<Diag> Diagnostics) override {}
Sam McCall9aad25f2017-12-05 07:20:26 +000040};
41
Sam McCallf6ae3232017-12-05 20:11:29 +000042// GMock helpers for matching completion items.
43MATCHER_P(Named, Name, "") { return arg.insertText == Name; }
Sam McCall44fdcec22017-12-08 15:00:59 +000044MATCHER_P(Labeled, Label, "") { return arg.label == Label; }
45MATCHER_P(Kind, K, "") { return arg.kind == K; }
Eric Liu6f648df2017-12-19 16:50:37 +000046MATCHER_P(Filter, F, "") { return arg.filterText == F; }
Eric Liu76f6b442018-01-09 17:32:00 +000047MATCHER_P(Doc, D, "") { return arg.documentation == D; }
48MATCHER_P(Detail, D, "") { return arg.detail == D; }
Eric Liu63f419a2018-05-15 15:29:32 +000049MATCHER_P(InsertInclude, IncludeHeader, "") {
50 if (arg.additionalTextEdits.size() != 1)
51 return false;
52 const auto &Edit = arg.additionalTextEdits[0];
53 if (Edit.range.start != Edit.range.end)
54 return false;
55 SmallVector<StringRef, 2> Matches;
56 llvm::Regex RE(R"(#include[ ]*(["<][^">]*[">]))");
57 return RE.match(Edit.newText, &Matches) && Matches[1] == IncludeHeader;
58}
Sam McCall44fdcec22017-12-08 15:00:59 +000059MATCHER_P(PlainText, Text, "") {
60 return arg.insertTextFormat == clangd::InsertTextFormat::PlainText &&
61 arg.insertText == Text;
62}
63MATCHER_P(Snippet, Text, "") {
64 return arg.insertTextFormat == clangd::InsertTextFormat::Snippet &&
65 arg.insertText == Text;
66}
Sam McCall545a20d2018-01-19 14:34:02 +000067MATCHER(NameContainsFilter, "") {
Ilya Biryukov5a5e1ca2017-12-29 14:59:22 +000068 if (arg.filterText.empty())
69 return true;
70 return llvm::StringRef(arg.insertText).contains(arg.filterText);
71}
Eric Liu63f419a2018-05-15 15:29:32 +000072MATCHER(HasAdditionalEdits, "") { return !arg.additionalTextEdits.empty(); }
73
Sam McCallf6ae3232017-12-05 20:11:29 +000074// Shorthand for Contains(Named(Name)).
75Matcher<const std::vector<CompletionItem> &> Has(std::string Name) {
76 return Contains(Named(std::move(Name)));
77}
Sam McCall44fdcec22017-12-08 15:00:59 +000078Matcher<const std::vector<CompletionItem> &> Has(std::string Name,
79 CompletionItemKind K) {
80 return Contains(AllOf(Named(std::move(Name)), Kind(K)));
Sam McCallf6ae3232017-12-05 20:11:29 +000081}
Sam McCall44fdcec22017-12-08 15:00:59 +000082MATCHER(IsDocumented, "") { return !arg.documentation.empty(); }
Sam McCall9aad25f2017-12-05 07:20:26 +000083
Sam McCalla15c2d62018-01-18 09:27:56 +000084std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol> Symbols) {
85 SymbolSlab::Builder Slab;
86 for (const auto &Sym : Symbols)
87 Slab.insert(Sym);
88 return MemIndex::build(std::move(Slab).build());
89}
90
Eric Liu63f419a2018-05-15 15:29:32 +000091CompletionList completions(ClangdServer &Server, StringRef Text,
Sam McCalla15c2d62018-01-18 09:27:56 +000092 std::vector<Symbol> IndexSymbols = {},
Sam McCallf6ae3232017-12-05 20:11:29 +000093 clangd::CodeCompleteOptions Opts = {}) {
Sam McCalla15c2d62018-01-18 09:27:56 +000094 std::unique_ptr<SymbolIndex> OverrideIndex;
95 if (!IndexSymbols.empty()) {
96 assert(!Opts.Index && "both Index and IndexSymbols given!");
97 OverrideIndex = memIndex(std::move(IndexSymbols));
98 Opts.Index = OverrideIndex.get();
99 }
100
Sam McCallc1568062018-02-16 09:41:43 +0000101 auto File = testPath("foo.cpp");
Sam McCall328cbdb2017-12-20 16:06:05 +0000102 Annotations Test(Text);
Sam McCall7363a2f2018-03-05 17:28:54 +0000103 runAddDocument(Server, File, Test.code());
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000104 auto CompletionList =
105 cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Ilya Biryukov5a5e1ca2017-12-29 14:59:22 +0000106 // Sanity-check that filterText is valid.
Sam McCall545a20d2018-01-19 14:34:02 +0000107 EXPECT_THAT(CompletionList.items, Each(NameContainsFilter()));
Ilya Biryukov5a5e1ca2017-12-29 14:59:22 +0000108 return CompletionList;
Sam McCall9aad25f2017-12-05 07:20:26 +0000109}
110
Eric Liu63f419a2018-05-15 15:29:32 +0000111// Builds a server and runs code completion.
112// If IndexSymbols is non-empty, an index will be built and passed to opts.
113CompletionList completions(StringRef Text,
114 std::vector<Symbol> IndexSymbols = {},
115 clangd::CodeCompleteOptions Opts = {}) {
116 MockFSProvider FS;
117 MockCompilationDatabase CDB;
118 IgnoreDiagnostics DiagConsumer;
119 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
120 return completions(Server, Text, std::move(IndexSymbols), std::move(Opts));
121}
122
Sam McCall545a20d2018-01-19 14:34:02 +0000123std::string replace(StringRef Haystack, StringRef Needle, StringRef Repl) {
124 std::string Result;
125 raw_string_ostream OS(Result);
126 std::pair<StringRef, StringRef> Split;
127 for (Split = Haystack.split(Needle); !Split.second.empty();
128 Split = Split.first.split(Needle))
129 OS << Split.first << Repl;
130 Result += Split.first;
131 OS.flush();
132 return Result;
133}
134
Sam McCalla15c2d62018-01-18 09:27:56 +0000135// Helpers to produce fake index symbols for memIndex() or completions().
Sam McCall545a20d2018-01-19 14:34:02 +0000136// USRFormat is a regex replacement string for the unqualified part of the USR.
137Symbol sym(StringRef QName, index::SymbolKind Kind, StringRef USRFormat) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000138 Symbol Sym;
Sam McCall545a20d2018-01-19 14:34:02 +0000139 std::string USR = "c:"; // We synthesize a few simple cases of USRs by hand!
Sam McCalla15c2d62018-01-18 09:27:56 +0000140 size_t Pos = QName.rfind("::");
141 if (Pos == llvm::StringRef::npos) {
142 Sym.Name = QName;
143 Sym.Scope = "";
144 } else {
145 Sym.Name = QName.substr(Pos + 2);
Sam McCall8b2faee2018-01-19 22:18:21 +0000146 Sym.Scope = QName.substr(0, Pos + 2);
147 USR += "@N@" + replace(QName.substr(0, Pos), "::", "@N@"); // ns:: -> @N@ns
Sam McCalla15c2d62018-01-18 09:27:56 +0000148 }
Sam McCall545a20d2018-01-19 14:34:02 +0000149 USR += Regex("^.*$").sub(USRFormat, Sym.Name); // e.g. func -> @F@func#
150 Sym.ID = SymbolID(USR);
Sam McCalla15c2d62018-01-18 09:27:56 +0000151 Sym.CompletionPlainInsertText = Sym.Name;
Sam McCall545a20d2018-01-19 14:34:02 +0000152 Sym.CompletionSnippetInsertText = Sym.Name;
Sam McCalla15c2d62018-01-18 09:27:56 +0000153 Sym.CompletionLabel = Sym.Name;
154 Sym.SymInfo.Kind = Kind;
155 return Sym;
156}
Sam McCall545a20d2018-01-19 14:34:02 +0000157Symbol func(StringRef Name) { // Assumes the function has no args.
158 return sym(Name, index::SymbolKind::Function, "@F@\\0#"); // no args
159}
160Symbol cls(StringRef Name) {
161 return sym(Name, index::SymbolKind::Class, "@S@\\0@S@\\0");
162}
163Symbol var(StringRef Name) {
164 return sym(Name, index::SymbolKind::Variable, "@\\0");
165}
Sam McCalldc8abc42018-05-03 14:53:02 +0000166Symbol ns(StringRef Name) {
167 return sym(Name, index::SymbolKind::Namespace, "@N@\\0");
168}
169Symbol withReferences(int N, Symbol S) {
170 S.References = N;
171 return S;
172}
Sam McCalla15c2d62018-01-18 09:27:56 +0000173
Sam McCallf6ae3232017-12-05 20:11:29 +0000174TEST(CompletionTest, Limit) {
175 clangd::CodeCompleteOptions Opts;
176 Opts.Limit = 2;
177 auto Results = completions(R"cpp(
Sam McCall9aad25f2017-12-05 07:20:26 +0000178struct ClassWithMembers {
179 int AAA();
180 int BBB();
181 int CCC();
182}
Sam McCallf6ae3232017-12-05 20:11:29 +0000183int main() { ClassWithMembers().^ }
Sam McCall9aad25f2017-12-05 07:20:26 +0000184 )cpp",
Sam McCalla15c2d62018-01-18 09:27:56 +0000185 /*IndexSymbols=*/{}, Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000186
187 EXPECT_TRUE(Results.isIncomplete);
Sam McCallf6ae3232017-12-05 20:11:29 +0000188 EXPECT_THAT(Results.items, ElementsAre(Named("AAA"), Named("BBB")));
Sam McCall9aad25f2017-12-05 07:20:26 +0000189}
190
Sam McCallf6ae3232017-12-05 20:11:29 +0000191TEST(CompletionTest, Filter) {
192 std::string Body = R"cpp(
Sam McCall9aad25f2017-12-05 07:20:26 +0000193 int Abracadabra;
194 int Alakazam;
195 struct S {
196 int FooBar;
197 int FooBaz;
198 int Qux;
199 };
200 )cpp";
Sam McCallf6ae3232017-12-05 20:11:29 +0000201 EXPECT_THAT(completions(Body + "int main() { S().Foba^ }").items,
202 AllOf(Has("FooBar"), Has("FooBaz"), Not(Has("Qux"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000203
Sam McCallf6ae3232017-12-05 20:11:29 +0000204 EXPECT_THAT(completions(Body + "int main() { S().FR^ }").items,
205 AllOf(Has("FooBar"), Not(Has("FooBaz")), Not(Has("Qux"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000206
Sam McCallf6ae3232017-12-05 20:11:29 +0000207 EXPECT_THAT(completions(Body + "int main() { S().opr^ }").items,
208 Has("operator="));
Sam McCall9aad25f2017-12-05 07:20:26 +0000209
Sam McCallf6ae3232017-12-05 20:11:29 +0000210 EXPECT_THAT(completions(Body + "int main() { aaa^ }").items,
211 AllOf(Has("Abracadabra"), Has("Alakazam")));
Sam McCall9aad25f2017-12-05 07:20:26 +0000212
Sam McCallf6ae3232017-12-05 20:11:29 +0000213 EXPECT_THAT(completions(Body + "int main() { _a^ }").items,
214 AllOf(Has("static_cast"), Not(Has("Abracadabra"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000215}
216
Sam McCallf6ae3232017-12-05 20:11:29 +0000217void TestAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000218 auto Results = completions(
219 R"cpp(
220 #define MACRO X
Sam McCall9aad25f2017-12-05 07:20:26 +0000221
Sam McCall44fdcec22017-12-08 15:00:59 +0000222 int global_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000223
Sam McCall44fdcec22017-12-08 15:00:59 +0000224 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000225
Sam McCall44fdcec22017-12-08 15:00:59 +0000226 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000227
Sam McCall44fdcec22017-12-08 15:00:59 +0000228 struct ClassWithMembers {
229 /// Doc for method.
230 int method();
Sam McCall9aad25f2017-12-05 07:20:26 +0000231
Sam McCall44fdcec22017-12-08 15:00:59 +0000232 int field;
233 private:
234 int private_field;
235 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000236
Sam McCall44fdcec22017-12-08 15:00:59 +0000237 int test() {
238 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000239
Sam McCall44fdcec22017-12-08 15:00:59 +0000240 /// Doc for local_var.
241 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000242
Sam McCall44fdcec22017-12-08 15:00:59 +0000243 ClassWithMembers().^
244 }
245 )cpp",
Sam McCall545a20d2018-01-19 14:34:02 +0000246 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000247
Sam McCallf6ae3232017-12-05 20:11:29 +0000248 // Class members. The only items that must be present in after-dot
249 // completion.
Sam McCall44fdcec22017-12-08 15:00:59 +0000250 EXPECT_THAT(
251 Results.items,
252 AllOf(Has(Opts.EnableSnippets ? "method()" : "method"), Has("field")));
253 EXPECT_IFF(Opts.IncludeIneligibleResults, Results.items,
254 Has("private_field"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000255 // Global items.
Sam McCall545a20d2018-01-19 14:34:02 +0000256 EXPECT_THAT(
257 Results.items,
258 Not(AnyOf(Has("global_var"), Has("index_var"), Has("global_func"),
259 Has("global_func()"), Has("index_func"), Has("GlobalClass"),
260 Has("IndexClass"), Has("MACRO"), Has("LocalClass"))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000261 // There should be no code patterns (aka snippets) in after-dot
262 // completion. At least there aren't any we're aware of.
Sam McCall44fdcec22017-12-08 15:00:59 +0000263 EXPECT_THAT(Results.items, Not(Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000264 // Check documentation.
Ilya Biryukov43714502018-05-16 12:32:44 +0000265 EXPECT_IFF(Opts.IncludeComments, Results.items, Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000266}
Sam McCall9aad25f2017-12-05 07:20:26 +0000267
Sam McCallf6ae3232017-12-05 20:11:29 +0000268void TestGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000269 auto Results = completions(
270 R"cpp(
271 #define MACRO X
Sam McCall9aad25f2017-12-05 07:20:26 +0000272
Sam McCall44fdcec22017-12-08 15:00:59 +0000273 int global_var;
274 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000275
Sam McCall44fdcec22017-12-08 15:00:59 +0000276 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000277
Sam McCall44fdcec22017-12-08 15:00:59 +0000278 struct ClassWithMembers {
279 /// Doc for method.
280 int method();
281 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000282
Sam McCall44fdcec22017-12-08 15:00:59 +0000283 int test() {
284 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000285
Sam McCall44fdcec22017-12-08 15:00:59 +0000286 /// Doc for local_var.
287 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000288
Sam McCall44fdcec22017-12-08 15:00:59 +0000289 ^
290 }
291 )cpp",
Sam McCall545a20d2018-01-19 14:34:02 +0000292 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
Sam McCallf6ae3232017-12-05 20:11:29 +0000293
294 // Class members. Should never be present in global completions.
Sam McCall44fdcec22017-12-08 15:00:59 +0000295 EXPECT_THAT(Results.items,
Sam McCallf6ae3232017-12-05 20:11:29 +0000296 Not(AnyOf(Has("method"), Has("method()"), Has("field"))));
297 // Global items.
Sam McCalld8169a82018-01-18 15:31:30 +0000298 EXPECT_THAT(Results.items,
Sam McCall545a20d2018-01-19 14:34:02 +0000299 AllOf(Has("global_var"), Has("index_var"),
Sam McCalld8169a82018-01-18 15:31:30 +0000300 Has(Opts.EnableSnippets ? "global_func()" : "global_func"),
Sam McCall545a20d2018-01-19 14:34:02 +0000301 Has("index_func" /* our fake symbol doesn't include () */),
302 Has("GlobalClass"), Has("IndexClass")));
Sam McCallf6ae3232017-12-05 20:11:29 +0000303 // A macro.
Sam McCall44fdcec22017-12-08 15:00:59 +0000304 EXPECT_IFF(Opts.IncludeMacros, Results.items, Has("MACRO"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000305 // Local items. Must be present always.
Ilya Biryukov9b5ffc22017-12-12 12:56:46 +0000306 EXPECT_THAT(Results.items,
307 AllOf(Has("local_var"), Has("LocalClass"),
308 Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000309 // Check documentation.
Ilya Biryukov43714502018-05-16 12:32:44 +0000310 EXPECT_IFF(Opts.IncludeComments, Results.items, Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000311}
312
313TEST(CompletionTest, CompletionOptions) {
Sam McCall2c3849a2018-01-16 12:21:24 +0000314 auto Test = [&](const clangd::CodeCompleteOptions &Opts) {
315 TestAfterDotCompletion(Opts);
316 TestGlobalScopeCompletion(Opts);
317 };
318 // We used to test every combination of options, but that got too slow (2^N).
319 auto Flags = {
Ilya Biryukov71028b82018-03-12 15:28:22 +0000320 &clangd::CodeCompleteOptions::IncludeMacros,
Ilya Biryukov43714502018-05-16 12:32:44 +0000321 &clangd::CodeCompleteOptions::IncludeComments,
Ilya Biryukov71028b82018-03-12 15:28:22 +0000322 &clangd::CodeCompleteOptions::EnableSnippets,
323 &clangd::CodeCompleteOptions::IncludeCodePatterns,
324 &clangd::CodeCompleteOptions::IncludeIneligibleResults,
Sam McCall2c3849a2018-01-16 12:21:24 +0000325 };
326 // Test default options.
327 Test({});
328 // Test with one flag flipped.
329 for (auto &F : Flags) {
330 clangd::CodeCompleteOptions O;
331 O.*F ^= true;
332 Test(O);
Sam McCall9aad25f2017-12-05 07:20:26 +0000333 }
334}
335
Sam McCall44fdcec22017-12-08 15:00:59 +0000336TEST(CompletionTest, Priorities) {
337 auto Internal = completions(R"cpp(
338 class Foo {
339 public: void pub();
340 protected: void prot();
341 private: void priv();
342 };
343 void Foo::pub() { this->^ }
344 )cpp");
345 EXPECT_THAT(Internal.items,
346 HasSubsequence(Named("priv"), Named("prot"), Named("pub")));
347
348 auto External = completions(R"cpp(
349 class Foo {
350 public: void pub();
351 protected: void prot();
352 private: void priv();
353 };
354 void test() {
355 Foo F;
356 F.^
357 }
358 )cpp");
359 EXPECT_THAT(External.items,
360 AllOf(Has("pub"), Not(Has("prot")), Not(Has("priv"))));
361}
362
363TEST(CompletionTest, Qualifiers) {
364 auto Results = completions(R"cpp(
365 class Foo {
366 public: int foo() const;
367 int bar() const;
368 };
369 class Bar : public Foo {
370 int foo() const;
371 };
372 void test() { Bar().^ }
373 )cpp");
374 EXPECT_THAT(Results.items, HasSubsequence(Labeled("bar() const"),
375 Labeled("Foo::foo() const")));
376 EXPECT_THAT(Results.items, Not(Contains(Labeled("foo() const")))); // private
377}
378
379TEST(CompletionTest, Snippets) {
380 clangd::CodeCompleteOptions Opts;
381 Opts.EnableSnippets = true;
382 auto Results = completions(
383 R"cpp(
384 struct fake {
385 int a;
386 int f(int i, const float f) const;
387 };
388 int main() {
389 fake f;
390 f.^
391 }
392 )cpp",
Sam McCalla15c2d62018-01-18 09:27:56 +0000393 /*IndexSymbols=*/{}, Opts);
Sam McCall44fdcec22017-12-08 15:00:59 +0000394 EXPECT_THAT(Results.items,
Eric Liu63696e12017-12-20 17:24:31 +0000395 HasSubsequence(Snippet("a"),
Sam McCall44fdcec22017-12-08 15:00:59 +0000396 Snippet("f(${1:int i}, ${2:const float f})")));
397}
398
399TEST(CompletionTest, Kinds) {
Sam McCall545a20d2018-01-19 14:34:02 +0000400 auto Results = completions(
401 R"cpp(
402 #define MACRO X
403 int variable;
404 struct Struct {};
405 int function();
406 int X = ^
407 )cpp",
408 {func("indexFunction"), var("indexVariable"), cls("indexClass")});
409 EXPECT_THAT(Results.items,
410 AllOf(Has("function", CompletionItemKind::Function),
411 Has("variable", CompletionItemKind::Variable),
412 Has("int", CompletionItemKind::Keyword),
413 Has("Struct", CompletionItemKind::Class),
414 Has("MACRO", CompletionItemKind::Text),
415 Has("indexFunction", CompletionItemKind::Function),
416 Has("indexVariable", CompletionItemKind::Variable),
417 Has("indexClass", CompletionItemKind::Class)));
Sam McCall44fdcec22017-12-08 15:00:59 +0000418
Sam McCall44fdcec22017-12-08 15:00:59 +0000419 Results = completions("nam^");
420 EXPECT_THAT(Results.items, Has("namespace", CompletionItemKind::Snippet));
421}
422
Sam McCall84652cc2018-01-12 16:16:09 +0000423TEST(CompletionTest, NoDuplicates) {
Sam McCall545a20d2018-01-19 14:34:02 +0000424 auto Results = completions(
425 R"cpp(
426 class Adapter {
427 void method();
428 };
Sam McCall84652cc2018-01-12 16:16:09 +0000429
Sam McCall545a20d2018-01-19 14:34:02 +0000430 void Adapter::method() {
431 Adapter^
432 }
433 )cpp",
434 {cls("Adapter")});
Sam McCall84652cc2018-01-12 16:16:09 +0000435
436 // Make sure there are no duplicate entries of 'Adapter'.
Sam McCalld2a95922018-01-22 21:05:00 +0000437 EXPECT_THAT(Results.items, ElementsAre(Named("Adapter")));
Sam McCall84652cc2018-01-12 16:16:09 +0000438}
439
Sam McCall545a20d2018-01-19 14:34:02 +0000440TEST(CompletionTest, ScopedNoIndex) {
441 auto Results = completions(
442 R"cpp(
443 namespace fake { int BigBang, Babble, Ball; };
444 int main() { fake::bb^ }
445 ")cpp");
Sam McCall84652cc2018-01-12 16:16:09 +0000446 // BigBang is a better match than Babble. Ball doesn't match at all.
Sam McCall545a20d2018-01-19 14:34:02 +0000447 EXPECT_THAT(Results.items, ElementsAre(Named("BigBang"), Named("Babble")));
Sam McCall84652cc2018-01-12 16:16:09 +0000448}
449
Sam McCall545a20d2018-01-19 14:34:02 +0000450TEST(CompletionTest, Scoped) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000451 auto Results = completions(
452 R"cpp(
Sam McCall545a20d2018-01-19 14:34:02 +0000453 namespace fake { int Babble, Ball; };
454 int main() { fake::bb^ }
455 ")cpp",
456 {var("fake::BigBang")});
457 EXPECT_THAT(Results.items, ElementsAre(Named("BigBang"), Named("Babble")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000458}
459
Sam McCall545a20d2018-01-19 14:34:02 +0000460TEST(CompletionTest, ScopedWithFilter) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000461 auto Results = completions(
462 R"cpp(
463 void f() { ns::x^ }
464 )cpp",
465 {cls("ns::XYZ"), func("ns::foo")});
466 EXPECT_THAT(Results.items,
467 UnorderedElementsAre(AllOf(Named("XYZ"), Filter("XYZ"))));
468}
469
Sam McCalldc8abc42018-05-03 14:53:02 +0000470TEST(CompletionTest, ReferencesAffectRanking) {
471 auto Results = completions("int main() { abs^ }", {ns("absl"), func("abs")});
472 EXPECT_THAT(Results.items, HasSubsequence(Named("abs"), Named("absl")));
473 Results = completions("int main() { abs^ }",
474 {withReferences(10000, ns("absl")), func("abs")});
475 EXPECT_THAT(Results.items, HasSubsequence(Named("absl"), Named("abs")));
476}
477
Sam McCall545a20d2018-01-19 14:34:02 +0000478TEST(CompletionTest, GlobalQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000479 auto Results = completions(
480 R"cpp(
481 void f() { ::^ }
482 )cpp",
483 {cls("XYZ")});
484 EXPECT_THAT(Results.items, AllOf(Has("XYZ", CompletionItemKind::Class),
485 Has("f", CompletionItemKind::Function)));
486}
487
Sam McCall545a20d2018-01-19 14:34:02 +0000488TEST(CompletionTest, FullyQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000489 auto Results = completions(
490 R"cpp(
Sam McCall545a20d2018-01-19 14:34:02 +0000491 namespace ns { void bar(); }
Sam McCalla15c2d62018-01-18 09:27:56 +0000492 void f() { ::ns::^ }
493 )cpp",
494 {cls("ns::XYZ")});
Sam McCall545a20d2018-01-19 14:34:02 +0000495 EXPECT_THAT(Results.items, AllOf(Has("XYZ", CompletionItemKind::Class),
496 Has("bar", CompletionItemKind::Function)));
497}
498
499TEST(CompletionTest, SemaIndexMerge) {
500 auto Results = completions(
501 R"cpp(
502 namespace ns { int local; void both(); }
503 void f() { ::ns::^ }
504 )cpp",
505 {func("ns::both"), cls("ns::Index")});
506 // We get results from both index and sema, with no duplicates.
507 EXPECT_THAT(
508 Results.items,
509 UnorderedElementsAre(Named("local"), Named("Index"), Named("both")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000510}
511
Haojian Wu48b48652018-01-25 09:20:09 +0000512TEST(CompletionTest, SemaIndexMergeWithLimit) {
513 clangd::CodeCompleteOptions Opts;
514 Opts.Limit = 1;
515 auto Results = completions(
516 R"cpp(
517 namespace ns { int local; void both(); }
518 void f() { ::ns::^ }
519 )cpp",
520 {func("ns::both"), cls("ns::Index")}, Opts);
521 EXPECT_EQ(Results.items.size(), Opts.Limit);
522 EXPECT_TRUE(Results.isIncomplete);
523}
524
Eric Liu63f419a2018-05-15 15:29:32 +0000525TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
526 MockFSProvider FS;
527 MockCompilationDatabase CDB;
528 std::string Subdir = testPath("sub");
529 std::string SearchDirArg = (llvm::Twine("-I") + Subdir).str();
530 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
531 std::string BarHeader = testPath("sub/bar.h");
532 FS.Files[BarHeader] = "";
533
534 IgnoreDiagnostics DiagConsumer;
535 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
536 Symbol::Details Scratch;
537 auto BarURI = URI::createFile(BarHeader).toString();
538 Symbol Sym = cls("ns::X");
539 Sym.CanonicalDeclaration.FileURI = BarURI;
540 Scratch.IncludeHeader = BarURI;
541 Sym.Detail = &Scratch;
542 // Shoten include path based on search dirctory and insert.
543 auto Results = completions(Server,
544 R"cpp(
545 int main() { ns::^ }
546 )cpp",
547 {Sym});
548 EXPECT_THAT(Results.items,
549 ElementsAre(AllOf(Named("X"), InsertInclude("\"bar.h\""))));
550 // Duplicate based on inclusions in preamble.
551 Results = completions(Server,
552 R"cpp(
553 #include "sub/bar.h" // not shortest, so should only match resolved.
554 int main() { ns::^ }
555 )cpp",
556 {Sym});
557 EXPECT_THAT(Results.items,
558 ElementsAre(AllOf(Named("X"), Not(HasAdditionalEdits()))));
559}
560
Sam McCalla15c2d62018-01-18 09:27:56 +0000561TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
562 MockFSProvider FS;
563 MockCompilationDatabase CDB;
564 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000565 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Sam McCalla15c2d62018-01-18 09:27:56 +0000566
Sam McCallc1568062018-02-16 09:41:43 +0000567 FS.Files[testPath("bar.h")] =
Sam McCalld5ea3e32018-01-24 17:53:32 +0000568 R"cpp(namespace ns { struct preamble { int member; }; })cpp";
Sam McCallc1568062018-02-16 09:41:43 +0000569 auto File = testPath("foo.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000570 Annotations Test(R"cpp(
571 #include "bar.h"
572 namespace ns { int local; }
Sam McCalld5ea3e32018-01-24 17:53:32 +0000573 void f() { ns::^; }
574 void f() { ns::preamble().$2^; }
Sam McCalla15c2d62018-01-18 09:27:56 +0000575 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000576 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000577 clangd::CodeCompleteOptions Opts = {};
578
Sam McCalla15c2d62018-01-18 09:27:56 +0000579 auto I = memIndex({var("ns::index")});
580 Opts.Index = I.get();
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000581 auto WithIndex = cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Sam McCalla15c2d62018-01-18 09:27:56 +0000582 EXPECT_THAT(WithIndex.items,
583 UnorderedElementsAre(Named("local"), Named("index")));
Sam McCalld5ea3e32018-01-24 17:53:32 +0000584 auto ClassFromPreamble =
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000585 cantFail(runCodeComplete(Server, File, Test.point("2"), Opts));
Sam McCalld5ea3e32018-01-24 17:53:32 +0000586 EXPECT_THAT(ClassFromPreamble.items, Contains(Named("member")));
Sam McCall0bb24cd2018-02-13 08:59:23 +0000587
588 Opts.Index = nullptr;
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000589 auto WithoutIndex =
590 cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Sam McCall0bb24cd2018-02-13 08:59:23 +0000591 EXPECT_THAT(WithoutIndex.items,
592 UnorderedElementsAre(Named("local"), Named("preamble")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000593}
594
595TEST(CompletionTest, DynamicIndexMultiFile) {
596 MockFSProvider FS;
597 MockCompilationDatabase CDB;
598 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000599 auto Opts = ClangdServer::optsForTest();
600 Opts.BuildDynamicSymbolIndex = true;
601 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
Sam McCalla15c2d62018-01-18 09:27:56 +0000602
Eric Liu709bde82018-02-19 18:48:44 +0000603 FS.Files[testPath("foo.h")] = R"cpp(
Sam McCalla15c2d62018-01-18 09:27:56 +0000604 namespace ns { class XYZ {}; void foo(int x) {} }
Eric Liu709bde82018-02-19 18:48:44 +0000605 )cpp";
Sam McCall7363a2f2018-03-05 17:28:54 +0000606 runAddDocument(Server, testPath("foo.cpp"), R"cpp(
Eric Liu709bde82018-02-19 18:48:44 +0000607 #include "foo.h"
Sam McCall0bb24cd2018-02-13 08:59:23 +0000608 )cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000609
Sam McCallc1568062018-02-16 09:41:43 +0000610 auto File = testPath("bar.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000611 Annotations Test(R"cpp(
612 namespace ns {
613 class XXX {};
614 /// Doooc
615 void fooooo() {}
616 }
617 void f() { ns::^ }
618 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000619 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000620
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000621 auto Results = cantFail(runCodeComplete(Server, File, Test.point(), {}));
Sam McCalla15c2d62018-01-18 09:27:56 +0000622 // "XYZ" and "foo" are not included in the file being completed but are still
623 // visible through the index.
624 EXPECT_THAT(Results.items, Has("XYZ", CompletionItemKind::Class));
625 EXPECT_THAT(Results.items, Has("foo", CompletionItemKind::Function));
626 EXPECT_THAT(Results.items, Has("XXX", CompletionItemKind::Class));
627 EXPECT_THAT(Results.items, Contains(AllOf(Named("fooooo"), Filter("fooooo"),
628 Kind(CompletionItemKind::Function),
629 Doc("Doooc"), Detail("void"))));
630}
631
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000632TEST(CompletionTest, Documentation) {
633 auto Results = completions(
634 R"cpp(
635 // Non-doxygen comment.
636 int foo();
637 /// Doxygen comment.
638 /// \param int a
639 int bar(int a);
640 /* Multi-line
641 block comment
642 */
643 int baz();
644
645 int x = ^
646 )cpp");
647 EXPECT_THAT(Results.items,
648 Contains(AllOf(Named("foo"), Doc("Non-doxygen comment."))));
649 EXPECT_THAT(
650 Results.items,
651 Contains(AllOf(Named("bar"), Doc("Doxygen comment.\n\\param int a"))));
652 EXPECT_THAT(Results.items,
653 Contains(AllOf(Named("baz"), Doc("Multi-line\nblock comment"))));
654}
655
Haojian Wu58d208d2018-01-25 09:44:06 +0000656TEST(CodeCompleteTest, DisableTypoCorrection) {
657 auto Results = completions(R"cpp(
658 namespace clang { int v; }
659 void f() { clangd::^
660 )cpp");
661 EXPECT_TRUE(Results.items.empty());
662}
663
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000664TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
665 auto Results = completions(R"cpp(
666 namespace clang { }
667 void f() {
668 clan^
669 }
670 )cpp");
671
672 EXPECT_THAT(Results.items, Contains(Labeled("clang")));
673 EXPECT_THAT(Results.items, Not(Contains(Labeled("clang::"))));
674}
675
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000676TEST(CompletionTest, BacktrackCrashes) {
677 // Sema calls code completion callbacks twice in these cases.
678 auto Results = completions(R"cpp(
679 namespace ns {
680 struct FooBarBaz {};
681 } // namespace ns
682
683 int foo(ns::FooBar^
684 )cpp");
685
686 EXPECT_THAT(Results.items, ElementsAre(Labeled("FooBarBaz")));
687
688 // Check we don't crash in that case too.
689 completions(R"cpp(
690 struct FooBarBaz {};
691 void test() {
692 if (FooBarBaz * x^) {}
693 }
694)cpp");
695}
696
Eric Liu42abe412018-05-24 11:20:19 +0000697TEST(CompletionTest, CompleteInMacroWithStringification) {
698 auto Results = completions(R"cpp(
699void f(const char *, int x);
700#define F(x) f(#x, x)
701
702namespace ns {
703int X;
704int Y;
705} // namespace ns
706
707int f(int input_num) {
708 F(ns::^)
709}
710)cpp");
711
712 EXPECT_THAT(Results.items,
713 UnorderedElementsAre(Named("X"), Named("Y")));
714}
715
716TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
717 auto Results = completions(R"cpp(
718void f(const char *, int x);
719#define F(x) f(#x, x)
720
721namespace ns {
722int X;
723
724int f(int input_num) {
725 F(^)
726}
727} // namespace ns
728)cpp");
729
730 EXPECT_THAT(Results.items, Contains(Named("X")));
731}
732
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000733TEST(CompletionTest, CompleteInExcludedPPBranch) {
734 auto Results = completions(R"cpp(
735 int bar(int param_in_bar) {
736 }
737
738 int foo(int param_in_foo) {
739#if 0
740 par^
741#endif
742 }
743)cpp");
744
745 EXPECT_THAT(Results.items, Contains(Labeled("param_in_foo")));
746 EXPECT_THAT(Results.items, Not(Contains(Labeled("param_in_bar"))));
747}
748
Sam McCall800d4372017-12-19 10:29:27 +0000749SignatureHelp signatures(StringRef Text) {
750 MockFSProvider FS;
751 MockCompilationDatabase CDB;
752 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000753 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Sam McCallc1568062018-02-16 09:41:43 +0000754 auto File = testPath("foo.cpp");
Sam McCall328cbdb2017-12-20 16:06:05 +0000755 Annotations Test(Text);
Sam McCall7363a2f2018-03-05 17:28:54 +0000756 runAddDocument(Server, File, Test.code());
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000757 return cantFail(runSignatureHelp(Server, File, Test.point()));
Sam McCall800d4372017-12-19 10:29:27 +0000758}
759
760MATCHER_P(ParamsAre, P, "") {
761 if (P.size() != arg.parameters.size())
762 return false;
763 for (unsigned I = 0; I < P.size(); ++I)
764 if (P[I] != arg.parameters[I].label)
765 return false;
766 return true;
767}
768
769Matcher<SignatureInformation> Sig(std::string Label,
770 std::vector<std::string> Params) {
771 return AllOf(Labeled(Label), ParamsAre(Params));
772}
773
774TEST(SignatureHelpTest, Overloads) {
775 auto Results = signatures(R"cpp(
776 void foo(int x, int y);
777 void foo(int x, float y);
778 void foo(float x, int y);
779 void foo(float x, float y);
780 void bar(int x, int y = 0);
781 int main() { foo(^); }
782 )cpp");
783 EXPECT_THAT(Results.signatures,
784 UnorderedElementsAre(
785 Sig("foo(float x, float y) -> void", {"float x", "float y"}),
786 Sig("foo(float x, int y) -> void", {"float x", "int y"}),
787 Sig("foo(int x, float y) -> void", {"int x", "float y"}),
788 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
789 // We always prefer the first signature.
790 EXPECT_EQ(0, Results.activeSignature);
791 EXPECT_EQ(0, Results.activeParameter);
792}
793
794TEST(SignatureHelpTest, DefaultArgs) {
795 auto Results = signatures(R"cpp(
796 void bar(int x, int y = 0);
797 void bar(float x = 0, int y = 42);
798 int main() { bar(^
799 )cpp");
800 EXPECT_THAT(Results.signatures,
801 UnorderedElementsAre(
802 Sig("bar(int x, int y = 0) -> void", {"int x", "int y = 0"}),
803 Sig("bar(float x = 0, int y = 42) -> void",
804 {"float x = 0", "int y = 42"})));
805 EXPECT_EQ(0, Results.activeSignature);
806 EXPECT_EQ(0, Results.activeParameter);
807}
808
809TEST(SignatureHelpTest, ActiveArg) {
810 auto Results = signatures(R"cpp(
811 int baz(int a, int b, int c);
812 int main() { baz(baz(1,2,3), ^); }
813 )cpp");
814 EXPECT_THAT(Results.signatures,
815 ElementsAre(Sig("baz(int a, int b, int c) -> int",
816 {"int a", "int b", "int c"})));
817 EXPECT_EQ(0, Results.activeSignature);
818 EXPECT_EQ(1, Results.activeParameter);
819}
820
Haojian Wu061c73e2018-01-23 11:37:26 +0000821class IndexRequestCollector : public SymbolIndex {
822public:
823 bool
Sam McCalld1a7a372018-01-31 13:40:48 +0000824 fuzzyFind(const FuzzyFindRequest &Req,
Haojian Wu061c73e2018-01-23 11:37:26 +0000825 llvm::function_ref<void(const Symbol &)> Callback) const override {
826 Requests.push_back(Req);
Sam McCallab8e3932018-02-19 13:04:41 +0000827 return true;
Haojian Wu061c73e2018-01-23 11:37:26 +0000828 }
829
Eric Liu9ec459f2018-03-14 09:48:05 +0000830 void lookup(const LookupRequest &,
831 llvm::function_ref<void(const Symbol &)>) const override {}
832
Haojian Wu061c73e2018-01-23 11:37:26 +0000833 const std::vector<FuzzyFindRequest> allRequests() const { return Requests; }
834
835private:
836 mutable std::vector<FuzzyFindRequest> Requests;
837};
838
839std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code) {
840 clangd::CodeCompleteOptions Opts;
841 IndexRequestCollector Requests;
842 Opts.Index = &Requests;
843 completions(Code, {}, Opts);
844 return Requests.allRequests();
845}
846
847TEST(CompletionTest, UnqualifiedIdQuery) {
848 auto Requests = captureIndexRequests(R"cpp(
849 namespace std {}
850 using namespace std;
851 namespace ns {
852 void f() {
853 vec^
854 }
855 }
856 )cpp");
857
858 EXPECT_THAT(Requests,
859 ElementsAre(Field(&FuzzyFindRequest::Scopes,
860 UnorderedElementsAre("", "ns::", "std::"))));
861}
862
863TEST(CompletionTest, ResolvedQualifiedIdQuery) {
864 auto Requests = captureIndexRequests(R"cpp(
865 namespace ns1 {}
866 namespace ns2 {} // ignore
867 namespace ns3 { namespace nns3 {} }
868 namespace foo {
869 using namespace ns1;
870 using namespace ns3::nns3;
871 }
872 namespace ns {
873 void f() {
874 foo::^
875 }
876 }
877 )cpp");
878
879 EXPECT_THAT(Requests,
880 ElementsAre(Field(
881 &FuzzyFindRequest::Scopes,
882 UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::"))));
883}
884
885TEST(CompletionTest, UnresolvedQualifierIdQuery) {
886 auto Requests = captureIndexRequests(R"cpp(
887 namespace a {}
888 using namespace a;
889 namespace ns {
890 void f() {
891 bar::^
892 }
893 } // namespace ns
894 )cpp");
895
896 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
897 UnorderedElementsAre("bar::"))));
898}
899
900TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
901 auto Requests = captureIndexRequests(R"cpp(
902 namespace a {}
903 using namespace a;
904 namespace ns {
905 void f() {
906 ::a::bar::^
907 }
908 } // namespace ns
909 )cpp");
910
911 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
912 UnorderedElementsAre("a::bar::"))));
913}
914
915TEST(CompletionTest, EmptyQualifiedQuery) {
916 auto Requests = captureIndexRequests(R"cpp(
917 namespace ns {
918 void f() {
919 ^
920 }
921 } // namespace ns
922 )cpp");
923
924 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
925 UnorderedElementsAre("", "ns::"))));
926}
927
928TEST(CompletionTest, GlobalQualifiedQuery) {
929 auto Requests = captureIndexRequests(R"cpp(
930 namespace ns {
931 void f() {
932 ::^
933 }
934 } // namespace ns
935 )cpp");
936
937 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
938 UnorderedElementsAre(""))));
939}
940
Ilya Biryukova907ba42018-05-14 10:50:04 +0000941TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
942 auto Completions = completions(
943 R"cpp(
944 struct Foo {
945 int SomeNameOfField;
946 typedef int SomeNameOfTypedefField;
947 };
948
949 Foo::^)cpp",
950 {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")});
951
952 EXPECT_THAT(Completions.items,
953 AllOf(Contains(Labeled("SomeNameOfField")),
954 Contains(Labeled("SomeNameOfTypedefField")),
955 Not(Contains(Labeled("SomeNameInTheIndex")))));
956}
957
958TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
959 {
960 auto Completions = completions(
961 R"cpp(
962 template <class T>
963 void foo() {
964 T::^
965 }
966 )cpp",
967 {func("::SomeNameInTheIndex")});
968
969 EXPECT_THAT(Completions.items,
970 Not(Contains(Labeled("SomeNameInTheIndex"))));
971 }
972
973 {
974 auto Completions = completions(
975 R"cpp(
976 template <class T>
977 void foo() {
978 T::template Y<int>::^
979 }
980 )cpp",
981 {func("::SomeNameInTheIndex")});
982
983 EXPECT_THAT(Completions.items,
984 Not(Contains(Labeled("SomeNameInTheIndex"))));
985 }
986
987 {
988 auto Completions = completions(
989 R"cpp(
990 template <class T>
991 void foo() {
992 T::foo::^
993 }
994 )cpp",
995 {func("::SomeNameInTheIndex")});
996
997 EXPECT_THAT(Completions.items,
998 Not(Contains(Labeled("SomeNameInTheIndex"))));
999 }
1000}
1001
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001002TEST(CompletionTest, DocumentationFromChangedFileCrash) {
1003 MockFSProvider FS;
1004 auto FooH = testPath("foo.h");
1005 auto FooCpp = testPath("foo.cpp");
1006 FS.Files[FooH] = R"cpp(
1007 // this is my documentation comment.
1008 int func();
1009 )cpp";
1010 FS.Files[FooCpp] = "";
1011
1012 MockCompilationDatabase CDB;
1013 IgnoreDiagnostics DiagConsumer;
1014 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1015
1016 Annotations Source(R"cpp(
1017 #include "foo.h"
1018 int func() {
1019 // This makes sure we have func from header in the AST.
1020 }
1021 int a = fun^
1022 )cpp");
1023 Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
1024 // We need to wait for preamble to build.
1025 ASSERT_TRUE(Server.blockUntilIdleForTest());
1026
1027 // Change the header file. Completion will reuse the old preamble!
1028 FS.Files[FooH] = R"cpp(
1029 int func();
1030 )cpp";
1031
1032 clangd::CodeCompleteOptions Opts;
1033 Opts.IncludeComments = true;
1034 CompletionList Completions =
1035 cantFail(runCodeComplete(Server, FooCpp, Source.point(), Opts));
1036 // We shouldn't crash. Unfortunately, current workaround is to not produce
1037 // comments for symbols from headers.
1038 EXPECT_THAT(Completions.items,
1039 Contains(AllOf(Not(IsDocumented()), Named("func"))));
1040}
1041
Sam McCall9aad25f2017-12-05 07:20:26 +00001042} // namespace
1043} // namespace clangd
1044} // namespace clang