blob: 2f04bef2e43490f038111ac4bb37e6a5238abff7 [file] [log] [blame]
Sam McCall9aad25f2017-12-05 07:20:26 +00001//===-- CodeCompleteTests.cpp -----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Eric Liu6f648df2017-12-19 16:50:37 +00009
Sam McCall328cbdb2017-12-20 16:06:05 +000010#include "Annotations.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000011#include "ClangdServer.h"
Sam McCall328cbdb2017-12-20 16:06:05 +000012#include "CodeComplete.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000013#include "Compiler.h"
Ilya Biryukov5a85b8e2017-12-13 12:53:16 +000014#include "Matchers.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000015#include "Protocol.h"
Sam McCalle746a2b2018-07-02 11:13:16 +000016#include "Quality.h"
Sam McCallb536a2a2017-12-19 12:23:48 +000017#include "SourceCode.h"
Ilya Biryukovcd5eb002018-02-12 11:37:28 +000018#include "SyncAPI.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000019#include "TestFS.h"
Eric Liu6f648df2017-12-19 16:50:37 +000020#include "index/MemIndex.h"
Eric Liu5d2a8072018-07-23 10:56:37 +000021#include "clang/Sema/CodeCompleteConsumer.h"
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +000022#include "llvm/Support/Error.h"
Ilya Biryukov981a35d2018-05-28 12:11:37 +000023#include "llvm/Testing/Support/Error.h"
Sam McCallf6ae3232017-12-05 20:11:29 +000024#include "gmock/gmock.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000025#include "gtest/gtest.h"
26
27namespace clang {
28namespace clangd {
Sam McCallf6ae3232017-12-05 20:11:29 +000029
Sam McCall9aad25f2017-12-05 07:20:26 +000030namespace {
31using namespace llvm;
Sam McCallf6ae3232017-12-05 20:11:29 +000032using ::testing::AllOf;
33using ::testing::Contains;
Ilya Biryukov5a5e1ca2017-12-29 14:59:22 +000034using ::testing::Each;
Sam McCallf6ae3232017-12-05 20:11:29 +000035using ::testing::ElementsAre;
Ilya Biryukov71028b82018-03-12 15:28:22 +000036using ::testing::Field;
Sam McCallc18c2802018-06-15 11:06:29 +000037using ::testing::HasSubstr;
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +000038using ::testing::IsEmpty;
Sam McCallf6ae3232017-12-05 20:11:29 +000039using ::testing::Not;
Sam McCall3d139c52018-01-12 18:30:08 +000040using ::testing::UnorderedElementsAre;
Sam McCall9aad25f2017-12-05 07:20:26 +000041
42class IgnoreDiagnostics : public DiagnosticsConsumer {
Ilya Biryukov71028b82018-03-12 15:28:22 +000043 void onDiagnosticsReady(PathRef File,
Sam McCalla7bb0cc2018-03-12 23:22:35 +000044 std::vector<Diag> Diagnostics) override {}
Sam McCall9aad25f2017-12-05 07:20:26 +000045};
46
Sam McCallf6ae3232017-12-05 20:11:29 +000047// GMock helpers for matching completion items.
Sam McCalle746a2b2018-07-02 11:13:16 +000048MATCHER_P(Named, Name, "") { return arg.Name == Name; }
49MATCHER_P(Scope, S, "") { return arg.Scope == S; }
50MATCHER_P(Qualifier, Q, "") { return arg.RequiredQualifier == Q; }
Eric Liu8f3678d2018-06-15 13:34:18 +000051MATCHER_P(Labeled, Label, "") {
Sam McCalle746a2b2018-07-02 11:13:16 +000052 return arg.RequiredQualifier + arg.Name + arg.Signature == Label;
Eric Liu8f3678d2018-06-15 13:34:18 +000053}
54MATCHER_P(SigHelpLabeled, Label, "") { return arg.label == Label; }
Sam McCalle746a2b2018-07-02 11:13:16 +000055MATCHER_P(Kind, K, "") { return arg.Kind == K; }
56MATCHER_P(Doc, D, "") { return arg.Documentation == D; }
57MATCHER_P(ReturnType, D, "") { return arg.ReturnType == D; }
Eric Liu63f419a2018-05-15 15:29:32 +000058MATCHER_P(InsertInclude, IncludeHeader, "") {
Sam McCalle746a2b2018-07-02 11:13:16 +000059 return arg.Header == IncludeHeader && bool(arg.HeaderInsertion);
Eric Liu63f419a2018-05-15 15:29:32 +000060}
Sam McCalle746a2b2018-07-02 11:13:16 +000061MATCHER(InsertInclude, "") { return bool(arg.HeaderInsertion); }
62MATCHER_P(SnippetSuffix, Text, "") { return arg.SnippetSuffix == Text; }
Sam McCall2161ec72018-07-05 06:20:41 +000063MATCHER_P(Origin, OriginSet, "") { return arg.Origin == OriginSet; }
Eric Liu63f419a2018-05-15 15:29:32 +000064
Sam McCallf6ae3232017-12-05 20:11:29 +000065// Shorthand for Contains(Named(Name)).
Sam McCalle746a2b2018-07-02 11:13:16 +000066Matcher<const std::vector<CodeCompletion> &> Has(std::string Name) {
Sam McCallf6ae3232017-12-05 20:11:29 +000067 return Contains(Named(std::move(Name)));
68}
Sam McCalle746a2b2018-07-02 11:13:16 +000069Matcher<const std::vector<CodeCompletion> &> Has(std::string Name,
Sam McCall44fdcec22017-12-08 15:00:59 +000070 CompletionItemKind K) {
71 return Contains(AllOf(Named(std::move(Name)), Kind(K)));
Sam McCallf6ae3232017-12-05 20:11:29 +000072}
Sam McCalle746a2b2018-07-02 11:13:16 +000073MATCHER(IsDocumented, "") { return !arg.Documentation.empty(); }
Sam McCall9aad25f2017-12-05 07:20:26 +000074
Sam McCalla15c2d62018-01-18 09:27:56 +000075std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol> Symbols) {
76 SymbolSlab::Builder Slab;
77 for (const auto &Sym : Symbols)
78 Slab.insert(Sym);
79 return MemIndex::build(std::move(Slab).build());
80}
81
Sam McCalle746a2b2018-07-02 11:13:16 +000082CodeCompleteResult completions(ClangdServer &Server, StringRef Text,
83 std::vector<Symbol> IndexSymbols = {},
84 clangd::CodeCompleteOptions Opts = {}) {
Sam McCalla15c2d62018-01-18 09:27:56 +000085 std::unique_ptr<SymbolIndex> OverrideIndex;
86 if (!IndexSymbols.empty()) {
87 assert(!Opts.Index && "both Index and IndexSymbols given!");
88 OverrideIndex = memIndex(std::move(IndexSymbols));
89 Opts.Index = OverrideIndex.get();
90 }
91
Sam McCallc1568062018-02-16 09:41:43 +000092 auto File = testPath("foo.cpp");
Sam McCall328cbdb2017-12-20 16:06:05 +000093 Annotations Test(Text);
Sam McCall7363a2f2018-03-05 17:28:54 +000094 runAddDocument(Server, File, Test.code());
Sam McCalla7bb0cc2018-03-12 23:22:35 +000095 auto CompletionList =
96 cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Ilya Biryukov5a5e1ca2017-12-29 14:59:22 +000097 return CompletionList;
Sam McCall9aad25f2017-12-05 07:20:26 +000098}
99
Eric Liu63f419a2018-05-15 15:29:32 +0000100// Builds a server and runs code completion.
101// If IndexSymbols is non-empty, an index will be built and passed to opts.
Sam McCalle746a2b2018-07-02 11:13:16 +0000102CodeCompleteResult completions(StringRef Text,
103 std::vector<Symbol> IndexSymbols = {},
104 clangd::CodeCompleteOptions Opts = {}) {
Eric Liu63f419a2018-05-15 15:29:32 +0000105 MockFSProvider FS;
106 MockCompilationDatabase CDB;
107 IgnoreDiagnostics DiagConsumer;
108 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
109 return completions(Server, Text, std::move(IndexSymbols), std::move(Opts));
110}
111
Sam McCall545a20d2018-01-19 14:34:02 +0000112std::string replace(StringRef Haystack, StringRef Needle, StringRef Repl) {
113 std::string Result;
114 raw_string_ostream OS(Result);
115 std::pair<StringRef, StringRef> Split;
116 for (Split = Haystack.split(Needle); !Split.second.empty();
117 Split = Split.first.split(Needle))
118 OS << Split.first << Repl;
119 Result += Split.first;
120 OS.flush();
121 return Result;
122}
123
Sam McCalla15c2d62018-01-18 09:27:56 +0000124// Helpers to produce fake index symbols for memIndex() or completions().
Sam McCall545a20d2018-01-19 14:34:02 +0000125// USRFormat is a regex replacement string for the unqualified part of the USR.
126Symbol sym(StringRef QName, index::SymbolKind Kind, StringRef USRFormat) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000127 Symbol Sym;
Sam McCall545a20d2018-01-19 14:34:02 +0000128 std::string USR = "c:"; // We synthesize a few simple cases of USRs by hand!
Sam McCalla15c2d62018-01-18 09:27:56 +0000129 size_t Pos = QName.rfind("::");
130 if (Pos == llvm::StringRef::npos) {
131 Sym.Name = QName;
132 Sym.Scope = "";
133 } else {
134 Sym.Name = QName.substr(Pos + 2);
Sam McCall8b2faee2018-01-19 22:18:21 +0000135 Sym.Scope = QName.substr(0, Pos + 2);
136 USR += "@N@" + replace(QName.substr(0, Pos), "::", "@N@"); // ns:: -> @N@ns
Sam McCalla15c2d62018-01-18 09:27:56 +0000137 }
Sam McCall545a20d2018-01-19 14:34:02 +0000138 USR += Regex("^.*$").sub(USRFormat, Sym.Name); // e.g. func -> @F@func#
139 Sym.ID = SymbolID(USR);
Sam McCalla15c2d62018-01-18 09:27:56 +0000140 Sym.SymInfo.Kind = Kind;
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000141 Sym.IsIndexedForCodeCompletion = true;
Sam McCall2161ec72018-07-05 06:20:41 +0000142 Sym.Origin = SymbolOrigin::Static;
Sam McCalla15c2d62018-01-18 09:27:56 +0000143 return Sym;
144}
Sam McCall545a20d2018-01-19 14:34:02 +0000145Symbol func(StringRef Name) { // Assumes the function has no args.
146 return sym(Name, index::SymbolKind::Function, "@F@\\0#"); // no args
147}
148Symbol cls(StringRef Name) {
Eric Liu9b3cba72018-05-30 09:03:39 +0000149 return sym(Name, index::SymbolKind::Class, "@S@\\0");
Sam McCall545a20d2018-01-19 14:34:02 +0000150}
151Symbol var(StringRef Name) {
152 return sym(Name, index::SymbolKind::Variable, "@\\0");
153}
Sam McCalldc8abc42018-05-03 14:53:02 +0000154Symbol ns(StringRef Name) {
155 return sym(Name, index::SymbolKind::Namespace, "@N@\\0");
156}
157Symbol withReferences(int N, Symbol S) {
158 S.References = N;
159 return S;
160}
Sam McCalla15c2d62018-01-18 09:27:56 +0000161
Sam McCallf6ae3232017-12-05 20:11:29 +0000162TEST(CompletionTest, Limit) {
163 clangd::CodeCompleteOptions Opts;
164 Opts.Limit = 2;
165 auto Results = completions(R"cpp(
Sam McCall9aad25f2017-12-05 07:20:26 +0000166struct ClassWithMembers {
167 int AAA();
168 int BBB();
169 int CCC();
170}
Sam McCallf6ae3232017-12-05 20:11:29 +0000171int main() { ClassWithMembers().^ }
Sam McCall9aad25f2017-12-05 07:20:26 +0000172 )cpp",
Sam McCalla15c2d62018-01-18 09:27:56 +0000173 /*IndexSymbols=*/{}, Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000174
Sam McCalle746a2b2018-07-02 11:13:16 +0000175 EXPECT_TRUE(Results.HasMore);
176 EXPECT_THAT(Results.Completions, ElementsAre(Named("AAA"), Named("BBB")));
Sam McCall9aad25f2017-12-05 07:20:26 +0000177}
178
Sam McCallf6ae3232017-12-05 20:11:29 +0000179TEST(CompletionTest, Filter) {
180 std::string Body = R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000181 #define MotorCar
182 int Car;
Sam McCall9aad25f2017-12-05 07:20:26 +0000183 struct S {
184 int FooBar;
185 int FooBaz;
186 int Qux;
187 };
188 )cpp";
Sam McCall8b2dcc12018-06-14 13:50:30 +0000189
190 // Only items matching the fuzzy query are returned.
Sam McCalle746a2b2018-07-02 11:13:16 +0000191 EXPECT_THAT(completions(Body + "int main() { S().Foba^ }").Completions,
Sam McCall8b2dcc12018-06-14 13:50:30 +0000192 AllOf(Has("FooBar"), Has("FooBaz"), Not(Has("Qux"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000193
Sam McCall8b2dcc12018-06-14 13:50:30 +0000194 // Macros require prefix match.
Sam McCalle746a2b2018-07-02 11:13:16 +0000195 EXPECT_THAT(completions(Body + "int main() { C^ }").Completions,
Sam McCall8b2dcc12018-06-14 13:50:30 +0000196 AllOf(Has("Car"), Not(Has("MotorCar"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000197}
198
Sam McCallf6ae3232017-12-05 20:11:29 +0000199void TestAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000200 auto Results = completions(
201 R"cpp(
202 #define MACRO X
Sam McCall9aad25f2017-12-05 07:20:26 +0000203
Sam McCall44fdcec22017-12-08 15:00:59 +0000204 int global_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000205
Sam McCall44fdcec22017-12-08 15:00:59 +0000206 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000207
Sam McCall44fdcec22017-12-08 15:00:59 +0000208 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000209
Sam McCall44fdcec22017-12-08 15:00:59 +0000210 struct ClassWithMembers {
211 /// Doc for method.
212 int method();
Sam McCall9aad25f2017-12-05 07:20:26 +0000213
Sam McCall44fdcec22017-12-08 15:00:59 +0000214 int field;
215 private:
216 int private_field;
217 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000218
Sam McCall44fdcec22017-12-08 15:00:59 +0000219 int test() {
220 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000221
Sam McCall44fdcec22017-12-08 15:00:59 +0000222 /// Doc for local_var.
223 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000224
Sam McCall44fdcec22017-12-08 15:00:59 +0000225 ClassWithMembers().^
226 }
227 )cpp",
Sam McCall545a20d2018-01-19 14:34:02 +0000228 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000229
Sam McCallf6ae3232017-12-05 20:11:29 +0000230 // Class members. The only items that must be present in after-dot
231 // completion.
Sam McCalle746a2b2018-07-02 11:13:16 +0000232 EXPECT_THAT(Results.Completions,
233 AllOf(Has("method"), Has("field"), Not(Has("ClassWithMembers")),
Sam McCall4caa8512018-06-07 12:49:17 +0000234 Not(Has("operator=")), Not(Has("~ClassWithMembers"))));
Sam McCalle746a2b2018-07-02 11:13:16 +0000235 EXPECT_IFF(Opts.IncludeIneligibleResults, Results.Completions,
Sam McCall44fdcec22017-12-08 15:00:59 +0000236 Has("private_field"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000237 // Global items.
Sam McCall545a20d2018-01-19 14:34:02 +0000238 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +0000239 Results.Completions,
Sam McCall545a20d2018-01-19 14:34:02 +0000240 Not(AnyOf(Has("global_var"), Has("index_var"), Has("global_func"),
241 Has("global_func()"), Has("index_func"), Has("GlobalClass"),
242 Has("IndexClass"), Has("MACRO"), Has("LocalClass"))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000243 // There should be no code patterns (aka snippets) in after-dot
244 // completion. At least there aren't any we're aware of.
Sam McCalle746a2b2018-07-02 11:13:16 +0000245 EXPECT_THAT(Results.Completions,
246 Not(Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000247 // Check documentation.
Sam McCalle746a2b2018-07-02 11:13:16 +0000248 EXPECT_IFF(Opts.IncludeComments, Results.Completions,
249 Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000250}
Sam McCall9aad25f2017-12-05 07:20:26 +0000251
Sam McCallf6ae3232017-12-05 20:11:29 +0000252void TestGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000253 auto Results = completions(
254 R"cpp(
255 #define MACRO X
Sam McCall9aad25f2017-12-05 07:20:26 +0000256
Sam McCall44fdcec22017-12-08 15:00:59 +0000257 int global_var;
258 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000259
Sam McCall44fdcec22017-12-08 15:00:59 +0000260 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000261
Sam McCall44fdcec22017-12-08 15:00:59 +0000262 struct ClassWithMembers {
263 /// Doc for method.
264 int method();
265 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000266
Sam McCall44fdcec22017-12-08 15:00:59 +0000267 int test() {
268 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000269
Sam McCall44fdcec22017-12-08 15:00:59 +0000270 /// Doc for local_var.
271 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000272
Sam McCall44fdcec22017-12-08 15:00:59 +0000273 ^
274 }
275 )cpp",
Sam McCall545a20d2018-01-19 14:34:02 +0000276 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
Sam McCallf6ae3232017-12-05 20:11:29 +0000277
278 // Class members. Should never be present in global completions.
Sam McCalle746a2b2018-07-02 11:13:16 +0000279 EXPECT_THAT(Results.Completions,
Sam McCallf6ae3232017-12-05 20:11:29 +0000280 Not(AnyOf(Has("method"), Has("method()"), Has("field"))));
281 // Global items.
Sam McCalle746a2b2018-07-02 11:13:16 +0000282 EXPECT_THAT(Results.Completions,
283 AllOf(Has("global_var"), Has("index_var"), Has("global_func"),
Sam McCall545a20d2018-01-19 14:34:02 +0000284 Has("index_func" /* our fake symbol doesn't include () */),
285 Has("GlobalClass"), Has("IndexClass")));
Sam McCallf6ae3232017-12-05 20:11:29 +0000286 // A macro.
Sam McCalle746a2b2018-07-02 11:13:16 +0000287 EXPECT_IFF(Opts.IncludeMacros, Results.Completions, Has("MACRO"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000288 // Local items. Must be present always.
Sam McCalle746a2b2018-07-02 11:13:16 +0000289 EXPECT_THAT(Results.Completions,
Ilya Biryukov9b5ffc22017-12-12 12:56:46 +0000290 AllOf(Has("local_var"), Has("LocalClass"),
291 Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000292 // Check documentation.
Sam McCalle746a2b2018-07-02 11:13:16 +0000293 EXPECT_IFF(Opts.IncludeComments, Results.Completions,
294 Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000295}
296
297TEST(CompletionTest, CompletionOptions) {
Sam McCall2c3849a2018-01-16 12:21:24 +0000298 auto Test = [&](const clangd::CodeCompleteOptions &Opts) {
299 TestAfterDotCompletion(Opts);
300 TestGlobalScopeCompletion(Opts);
301 };
302 // We used to test every combination of options, but that got too slow (2^N).
303 auto Flags = {
Ilya Biryukov71028b82018-03-12 15:28:22 +0000304 &clangd::CodeCompleteOptions::IncludeMacros,
Ilya Biryukov43714502018-05-16 12:32:44 +0000305 &clangd::CodeCompleteOptions::IncludeComments,
Ilya Biryukov71028b82018-03-12 15:28:22 +0000306 &clangd::CodeCompleteOptions::IncludeCodePatterns,
307 &clangd::CodeCompleteOptions::IncludeIneligibleResults,
Sam McCall2c3849a2018-01-16 12:21:24 +0000308 };
309 // Test default options.
310 Test({});
311 // Test with one flag flipped.
312 for (auto &F : Flags) {
313 clangd::CodeCompleteOptions O;
314 O.*F ^= true;
315 Test(O);
Sam McCall9aad25f2017-12-05 07:20:26 +0000316 }
317}
318
Sam McCall44fdcec22017-12-08 15:00:59 +0000319TEST(CompletionTest, Priorities) {
320 auto Internal = completions(R"cpp(
321 class Foo {
322 public: void pub();
323 protected: void prot();
324 private: void priv();
325 };
326 void Foo::pub() { this->^ }
327 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000328 EXPECT_THAT(Internal.Completions,
Sam McCall44fdcec22017-12-08 15:00:59 +0000329 HasSubsequence(Named("priv"), Named("prot"), Named("pub")));
330
331 auto External = completions(R"cpp(
332 class Foo {
333 public: void pub();
334 protected: void prot();
335 private: void priv();
336 };
337 void test() {
338 Foo F;
339 F.^
340 }
341 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000342 EXPECT_THAT(External.Completions,
Sam McCall44fdcec22017-12-08 15:00:59 +0000343 AllOf(Has("pub"), Not(Has("prot")), Not(Has("priv"))));
344}
345
346TEST(CompletionTest, Qualifiers) {
347 auto Results = completions(R"cpp(
348 class Foo {
349 public: int foo() const;
350 int bar() const;
351 };
352 class Bar : public Foo {
353 int foo() const;
354 };
355 void test() { Bar().^ }
356 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000357 EXPECT_THAT(Results.Completions,
358 HasSubsequence(AllOf(Qualifier(""), Named("bar")),
359 AllOf(Qualifier("Foo::"), Named("foo"))));
360 EXPECT_THAT(Results.Completions,
361 Not(Contains(AllOf(Qualifier(""), Named("foo"))))); // private
Sam McCall44fdcec22017-12-08 15:00:59 +0000362}
363
Sam McCall4caa8512018-06-07 12:49:17 +0000364TEST(CompletionTest, InjectedTypename) {
365 // These are suppressed when accessed as a member...
Sam McCalle746a2b2018-07-02 11:13:16 +0000366 EXPECT_THAT(completions("struct X{}; void foo(){ X().^ }").Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000367 Not(Has("X")));
Sam McCalle746a2b2018-07-02 11:13:16 +0000368 EXPECT_THAT(completions("struct X{ void foo(){ this->^ } };").Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000369 Not(Has("X")));
370 // ...but accessible in other, more useful cases.
Sam McCalle746a2b2018-07-02 11:13:16 +0000371 EXPECT_THAT(completions("struct X{ void foo(){ ^ } };").Completions,
372 Has("X"));
373 EXPECT_THAT(
374 completions("struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions,
375 Has("Y"));
Sam McCall4caa8512018-06-07 12:49:17 +0000376 EXPECT_THAT(
377 completions(
378 "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };")
Sam McCalle746a2b2018-07-02 11:13:16 +0000379 .Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000380 Has("Y"));
381 // This case is marginal (`using X::X` is useful), we allow it for now.
Sam McCalle746a2b2018-07-02 11:13:16 +0000382 EXPECT_THAT(completions("struct X{}; void foo(){ X::^ }").Completions,
383 Has("X"));
Sam McCall4caa8512018-06-07 12:49:17 +0000384}
385
Sam McCall44fdcec22017-12-08 15:00:59 +0000386TEST(CompletionTest, Snippets) {
387 clangd::CodeCompleteOptions Opts;
Sam McCall44fdcec22017-12-08 15:00:59 +0000388 auto Results = completions(
389 R"cpp(
390 struct fake {
391 int a;
392 int f(int i, const float f) const;
393 };
394 int main() {
395 fake f;
396 f.^
397 }
398 )cpp",
Sam McCalla15c2d62018-01-18 09:27:56 +0000399 /*IndexSymbols=*/{}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000400 EXPECT_THAT(
401 Results.Completions,
402 HasSubsequence(Named("a"),
403 SnippetSuffix("(${1:int i}, ${2:const float f})")));
Sam McCall44fdcec22017-12-08 15:00:59 +0000404}
405
406TEST(CompletionTest, Kinds) {
Sam McCall545a20d2018-01-19 14:34:02 +0000407 auto Results = completions(
408 R"cpp(
409 #define MACRO X
410 int variable;
411 struct Struct {};
412 int function();
413 int X = ^
414 )cpp",
415 {func("indexFunction"), var("indexVariable"), cls("indexClass")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000416 EXPECT_THAT(Results.Completions,
Sam McCall545a20d2018-01-19 14:34:02 +0000417 AllOf(Has("function", CompletionItemKind::Function),
418 Has("variable", CompletionItemKind::Variable),
419 Has("int", CompletionItemKind::Keyword),
420 Has("Struct", CompletionItemKind::Class),
421 Has("MACRO", CompletionItemKind::Text),
422 Has("indexFunction", CompletionItemKind::Function),
423 Has("indexVariable", CompletionItemKind::Variable),
424 Has("indexClass", CompletionItemKind::Class)));
Sam McCall44fdcec22017-12-08 15:00:59 +0000425
Sam McCall44fdcec22017-12-08 15:00:59 +0000426 Results = completions("nam^");
Sam McCalle746a2b2018-07-02 11:13:16 +0000427 EXPECT_THAT(Results.Completions,
428 Has("namespace", CompletionItemKind::Snippet));
Sam McCall44fdcec22017-12-08 15:00:59 +0000429}
430
Sam McCall84652cc2018-01-12 16:16:09 +0000431TEST(CompletionTest, NoDuplicates) {
Sam McCall545a20d2018-01-19 14:34:02 +0000432 auto Results = completions(
433 R"cpp(
434 class Adapter {
Sam McCall545a20d2018-01-19 14:34:02 +0000435 };
Sam McCall84652cc2018-01-12 16:16:09 +0000436
Eric Liu9b3cba72018-05-30 09:03:39 +0000437 void f() {
Sam McCall545a20d2018-01-19 14:34:02 +0000438 Adapter^
439 }
440 )cpp",
441 {cls("Adapter")});
Sam McCall84652cc2018-01-12 16:16:09 +0000442
443 // Make sure there are no duplicate entries of 'Adapter'.
Sam McCalle746a2b2018-07-02 11:13:16 +0000444 EXPECT_THAT(Results.Completions, ElementsAre(Named("Adapter")));
Sam McCall84652cc2018-01-12 16:16:09 +0000445}
446
Sam McCall545a20d2018-01-19 14:34:02 +0000447TEST(CompletionTest, ScopedNoIndex) {
448 auto Results = completions(
449 R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000450 namespace fake { int BigBang, Babble, Box; };
451 int main() { fake::ba^ }
Sam McCall545a20d2018-01-19 14:34:02 +0000452 ")cpp");
Sam McCall8b2dcc12018-06-14 13:50:30 +0000453 // Babble is a better match than BigBang. Box doesn't match at all.
Sam McCalle746a2b2018-07-02 11:13:16 +0000454 EXPECT_THAT(Results.Completions,
455 ElementsAre(Named("Babble"), Named("BigBang")));
Sam McCall84652cc2018-01-12 16:16:09 +0000456}
457
Sam McCall545a20d2018-01-19 14:34:02 +0000458TEST(CompletionTest, Scoped) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000459 auto Results = completions(
460 R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000461 namespace fake { int Babble, Box; };
462 int main() { fake::ba^ }
Sam McCall545a20d2018-01-19 14:34:02 +0000463 ")cpp",
464 {var("fake::BigBang")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000465 EXPECT_THAT(Results.Completions,
466 ElementsAre(Named("Babble"), Named("BigBang")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000467}
468
Sam McCall545a20d2018-01-19 14:34:02 +0000469TEST(CompletionTest, ScopedWithFilter) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000470 auto Results = completions(
471 R"cpp(
472 void f() { ns::x^ }
473 )cpp",
474 {cls("ns::XYZ"), func("ns::foo")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000475 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("XYZ")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000476}
477
Sam McCalldc8abc42018-05-03 14:53:02 +0000478TEST(CompletionTest, ReferencesAffectRanking) {
Eric Liu84bd5db2018-07-25 11:26:35 +0000479 auto Results = completions("int main() { abs^ }", {ns("absl"), func("absb")});
480 EXPECT_THAT(Results.Completions, HasSubsequence(Named("absb"), Named("absl")));
Sam McCalldc8abc42018-05-03 14:53:02 +0000481 Results = completions("int main() { abs^ }",
Eric Liu84bd5db2018-07-25 11:26:35 +0000482 {withReferences(10000, ns("absl")), func("absb")});
483 EXPECT_THAT(Results.Completions,
484 HasSubsequence(Named("absl"), Named("absb")));
Sam McCalldc8abc42018-05-03 14:53:02 +0000485}
486
Sam McCall545a20d2018-01-19 14:34:02 +0000487TEST(CompletionTest, GlobalQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000488 auto Results = completions(
489 R"cpp(
490 void f() { ::^ }
491 )cpp",
492 {cls("XYZ")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000493 EXPECT_THAT(Results.Completions,
494 AllOf(Has("XYZ", CompletionItemKind::Class),
495 Has("f", CompletionItemKind::Function)));
Sam McCalla15c2d62018-01-18 09:27:56 +0000496}
497
Sam McCall545a20d2018-01-19 14:34:02 +0000498TEST(CompletionTest, FullyQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000499 auto Results = completions(
500 R"cpp(
Sam McCall545a20d2018-01-19 14:34:02 +0000501 namespace ns { void bar(); }
Sam McCalla15c2d62018-01-18 09:27:56 +0000502 void f() { ::ns::^ }
503 )cpp",
504 {cls("ns::XYZ")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000505 EXPECT_THAT(Results.Completions,
506 AllOf(Has("XYZ", CompletionItemKind::Class),
507 Has("bar", CompletionItemKind::Function)));
Sam McCall545a20d2018-01-19 14:34:02 +0000508}
509
510TEST(CompletionTest, SemaIndexMerge) {
511 auto Results = completions(
512 R"cpp(
513 namespace ns { int local; void both(); }
514 void f() { ::ns::^ }
515 )cpp",
516 {func("ns::both"), cls("ns::Index")});
517 // We get results from both index and sema, with no duplicates.
Sam McCall2161ec72018-07-05 06:20:41 +0000518 EXPECT_THAT(Results.Completions,
519 UnorderedElementsAre(
520 AllOf(Named("local"), Origin(SymbolOrigin::AST)),
521 AllOf(Named("Index"), Origin(SymbolOrigin::Static)),
522 AllOf(Named("both"),
523 Origin(SymbolOrigin::AST | SymbolOrigin::Static))));
Sam McCalla15c2d62018-01-18 09:27:56 +0000524}
525
Haojian Wu48b48652018-01-25 09:20:09 +0000526TEST(CompletionTest, SemaIndexMergeWithLimit) {
527 clangd::CodeCompleteOptions Opts;
528 Opts.Limit = 1;
529 auto Results = completions(
530 R"cpp(
531 namespace ns { int local; void both(); }
532 void f() { ::ns::^ }
533 )cpp",
534 {func("ns::both"), cls("ns::Index")}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000535 EXPECT_EQ(Results.Completions.size(), Opts.Limit);
536 EXPECT_TRUE(Results.HasMore);
Haojian Wu48b48652018-01-25 09:20:09 +0000537}
538
Eric Liu63f419a2018-05-15 15:29:32 +0000539TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
540 MockFSProvider FS;
541 MockCompilationDatabase CDB;
542 std::string Subdir = testPath("sub");
543 std::string SearchDirArg = (llvm::Twine("-I") + Subdir).str();
544 CDB.ExtraClangFlags = {SearchDirArg.c_str()};
545 std::string BarHeader = testPath("sub/bar.h");
546 FS.Files[BarHeader] = "";
547
548 IgnoreDiagnostics DiagConsumer;
549 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
550 Symbol::Details Scratch;
551 auto BarURI = URI::createFile(BarHeader).toString();
552 Symbol Sym = cls("ns::X");
553 Sym.CanonicalDeclaration.FileURI = BarURI;
554 Scratch.IncludeHeader = BarURI;
555 Sym.Detail = &Scratch;
556 // Shoten include path based on search dirctory and insert.
557 auto Results = completions(Server,
558 R"cpp(
559 int main() { ns::^ }
560 )cpp",
561 {Sym});
Sam McCalle746a2b2018-07-02 11:13:16 +0000562 EXPECT_THAT(Results.Completions,
563 ElementsAre(AllOf(Named("X"), InsertInclude("\"bar.h\""))));
Eric Liu63f419a2018-05-15 15:29:32 +0000564 // Duplicate based on inclusions in preamble.
565 Results = completions(Server,
566 R"cpp(
567 #include "sub/bar.h" // not shortest, so should only match resolved.
568 int main() { ns::^ }
569 )cpp",
570 {Sym});
Sam McCalle746a2b2018-07-02 11:13:16 +0000571 EXPECT_THAT(Results.Completions, ElementsAre(AllOf(Named("X"), Labeled("X"),
572 Not(InsertInclude()))));
Eric Liu63f419a2018-05-15 15:29:32 +0000573}
574
Eric Liu9b3cba72018-05-30 09:03:39 +0000575TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {
576 MockFSProvider FS;
577 MockCompilationDatabase CDB;
578
579 IgnoreDiagnostics DiagConsumer;
580 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
581 Symbol::Details Scratch;
582 Symbol SymX = cls("ns::X");
583 Symbol SymY = cls("ns::Y");
584 std::string BarHeader = testPath("bar.h");
585 auto BarURI = URI::createFile(BarHeader).toString();
586 SymX.CanonicalDeclaration.FileURI = BarURI;
587 SymY.CanonicalDeclaration.FileURI = BarURI;
588 Scratch.IncludeHeader = "<bar>";
589 SymX.Detail = &Scratch;
590 SymY.Detail = &Scratch;
591 // Shoten include path based on search dirctory and insert.
592 auto Results = completions(Server,
593 R"cpp(
594 namespace ns {
595 class X;
596 class Y {}
597 }
598 int main() { ns::^ }
599 )cpp",
600 {SymX, SymY});
Sam McCalle746a2b2018-07-02 11:13:16 +0000601 EXPECT_THAT(Results.Completions,
602 ElementsAre(AllOf(Named("X"), Not(InsertInclude())),
603 AllOf(Named("Y"), Not(InsertInclude()))));
Eric Liu9b3cba72018-05-30 09:03:39 +0000604}
605
Sam McCalla15c2d62018-01-18 09:27:56 +0000606TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
607 MockFSProvider FS;
608 MockCompilationDatabase CDB;
609 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000610 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Sam McCalla15c2d62018-01-18 09:27:56 +0000611
Sam McCallc1568062018-02-16 09:41:43 +0000612 FS.Files[testPath("bar.h")] =
Sam McCalld5ea3e32018-01-24 17:53:32 +0000613 R"cpp(namespace ns { struct preamble { int member; }; })cpp";
Sam McCallc1568062018-02-16 09:41:43 +0000614 auto File = testPath("foo.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000615 Annotations Test(R"cpp(
616 #include "bar.h"
617 namespace ns { int local; }
Sam McCalld5ea3e32018-01-24 17:53:32 +0000618 void f() { ns::^; }
619 void f() { ns::preamble().$2^; }
Sam McCalla15c2d62018-01-18 09:27:56 +0000620 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000621 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000622 clangd::CodeCompleteOptions Opts = {};
623
Sam McCalla15c2d62018-01-18 09:27:56 +0000624 auto I = memIndex({var("ns::index")});
625 Opts.Index = I.get();
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000626 auto WithIndex = cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000627 EXPECT_THAT(WithIndex.Completions,
Sam McCalla15c2d62018-01-18 09:27:56 +0000628 UnorderedElementsAre(Named("local"), Named("index")));
Sam McCalld5ea3e32018-01-24 17:53:32 +0000629 auto ClassFromPreamble =
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000630 cantFail(runCodeComplete(Server, File, Test.point("2"), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000631 EXPECT_THAT(ClassFromPreamble.Completions, Contains(Named("member")));
Sam McCall0bb24cd2018-02-13 08:59:23 +0000632
633 Opts.Index = nullptr;
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000634 auto WithoutIndex =
635 cantFail(runCodeComplete(Server, File, Test.point(), Opts));
Sam McCalle746a2b2018-07-02 11:13:16 +0000636 EXPECT_THAT(WithoutIndex.Completions,
Sam McCall0bb24cd2018-02-13 08:59:23 +0000637 UnorderedElementsAre(Named("local"), Named("preamble")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000638}
639
640TEST(CompletionTest, DynamicIndexMultiFile) {
641 MockFSProvider FS;
642 MockCompilationDatabase CDB;
643 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000644 auto Opts = ClangdServer::optsForTest();
645 Opts.BuildDynamicSymbolIndex = true;
646 ClangdServer Server(CDB, FS, DiagConsumer, Opts);
Sam McCalla15c2d62018-01-18 09:27:56 +0000647
Eric Liu709bde82018-02-19 18:48:44 +0000648 FS.Files[testPath("foo.h")] = R"cpp(
Sam McCalla15c2d62018-01-18 09:27:56 +0000649 namespace ns { class XYZ {}; void foo(int x) {} }
Eric Liu709bde82018-02-19 18:48:44 +0000650 )cpp";
Sam McCall7363a2f2018-03-05 17:28:54 +0000651 runAddDocument(Server, testPath("foo.cpp"), R"cpp(
Eric Liu709bde82018-02-19 18:48:44 +0000652 #include "foo.h"
Sam McCall0bb24cd2018-02-13 08:59:23 +0000653 )cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000654
Sam McCallc1568062018-02-16 09:41:43 +0000655 auto File = testPath("bar.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000656 Annotations Test(R"cpp(
657 namespace ns {
658 class XXX {};
659 /// Doooc
660 void fooooo() {}
661 }
662 void f() { ns::^ }
663 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000664 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000665
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000666 auto Results = cantFail(runCodeComplete(Server, File, Test.point(), {}));
Sam McCalla15c2d62018-01-18 09:27:56 +0000667 // "XYZ" and "foo" are not included in the file being completed but are still
668 // visible through the index.
Sam McCalle746a2b2018-07-02 11:13:16 +0000669 EXPECT_THAT(Results.Completions, Has("XYZ", CompletionItemKind::Class));
670 EXPECT_THAT(Results.Completions, Has("foo", CompletionItemKind::Function));
671 EXPECT_THAT(Results.Completions, Has("XXX", CompletionItemKind::Class));
672 EXPECT_THAT(Results.Completions,
673 Contains((Named("fooooo"), Kind(CompletionItemKind::Function),
674 Doc("Doooc"), ReturnType("void"))));
Sam McCalla15c2d62018-01-18 09:27:56 +0000675}
676
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000677TEST(CompletionTest, Documentation) {
678 auto Results = completions(
679 R"cpp(
680 // Non-doxygen comment.
681 int foo();
682 /// Doxygen comment.
683 /// \param int a
684 int bar(int a);
685 /* Multi-line
686 block comment
687 */
688 int baz();
689
690 int x = ^
691 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000692 EXPECT_THAT(Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000693 Contains(AllOf(Named("foo"), Doc("Non-doxygen comment."))));
694 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +0000695 Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000696 Contains(AllOf(Named("bar"), Doc("Doxygen comment.\n\\param int a"))));
Sam McCalle746a2b2018-07-02 11:13:16 +0000697 EXPECT_THAT(Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000698 Contains(AllOf(Named("baz"), Doc("Multi-line\nblock comment"))));
699}
700
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000701TEST(CompletionTest, GlobalCompletionFiltering) {
702
703 Symbol Class = cls("XYZ");
704 Class.IsIndexedForCodeCompletion = false;
705 Symbol Func = func("XYZ::foooo");
706 Func.IsIndexedForCodeCompletion = false;
707
708 auto Results = completions(R"(// void f() {
709 XYZ::foooo^
710 })",
711 {Class, Func});
Sam McCalle746a2b2018-07-02 11:13:16 +0000712 EXPECT_THAT(Results.Completions, IsEmpty());
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000713}
714
Haojian Wu58d208d2018-01-25 09:44:06 +0000715TEST(CodeCompleteTest, DisableTypoCorrection) {
716 auto Results = completions(R"cpp(
717 namespace clang { int v; }
718 void f() { clangd::^
719 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000720 EXPECT_TRUE(Results.Completions.empty());
Haojian Wu58d208d2018-01-25 09:44:06 +0000721}
722
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000723TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
724 auto Results = completions(R"cpp(
725 namespace clang { }
726 void f() {
727 clan^
728 }
729 )cpp");
730
Sam McCalle746a2b2018-07-02 11:13:16 +0000731 EXPECT_THAT(Results.Completions, Contains(Labeled("clang")));
732 EXPECT_THAT(Results.Completions, Not(Contains(Labeled("clang::"))));
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000733}
734
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000735TEST(CompletionTest, BacktrackCrashes) {
736 // Sema calls code completion callbacks twice in these cases.
737 auto Results = completions(R"cpp(
738 namespace ns {
739 struct FooBarBaz {};
740 } // namespace ns
741
742 int foo(ns::FooBar^
743 )cpp");
744
Sam McCalle746a2b2018-07-02 11:13:16 +0000745 EXPECT_THAT(Results.Completions, ElementsAre(Labeled("FooBarBaz")));
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000746
747 // Check we don't crash in that case too.
748 completions(R"cpp(
749 struct FooBarBaz {};
750 void test() {
751 if (FooBarBaz * x^) {}
752 }
753)cpp");
754}
755
Eric Liu42abe412018-05-24 11:20:19 +0000756TEST(CompletionTest, CompleteInMacroWithStringification) {
757 auto Results = completions(R"cpp(
758void f(const char *, int x);
759#define F(x) f(#x, x)
760
761namespace ns {
762int X;
763int Y;
764} // namespace ns
765
766int f(int input_num) {
767 F(ns::^)
768}
769)cpp");
770
Sam McCalle746a2b2018-07-02 11:13:16 +0000771 EXPECT_THAT(Results.Completions,
Eric Liu42abe412018-05-24 11:20:19 +0000772 UnorderedElementsAre(Named("X"), Named("Y")));
773}
774
775TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
776 auto Results = completions(R"cpp(
777void f(const char *, int x);
778#define F(x) f(#x, x)
779
780namespace ns {
781int X;
782
783int f(int input_num) {
784 F(^)
785}
786} // namespace ns
787)cpp");
788
Sam McCalle746a2b2018-07-02 11:13:16 +0000789 EXPECT_THAT(Results.Completions, Contains(Named("X")));
Eric Liu42abe412018-05-24 11:20:19 +0000790}
791
Eric Liu485074f2018-07-11 13:15:31 +0000792TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000793 auto Results = completions(R"cpp(
794 int bar(int param_in_bar) {
795 }
796
797 int foo(int param_in_foo) {
798#if 0
Eric Liu485074f2018-07-11 13:15:31 +0000799 // In recorvery mode, "param_in_foo" will also be suggested among many other
800 // unrelated symbols; however, this is really a special case where this works.
801 // If the #if block is outside of the function, "param_in_foo" is still
802 // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't
803 // really provide useful results in excluded branches.
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000804 par^
805#endif
806 }
807)cpp");
808
Eric Liu485074f2018-07-11 13:15:31 +0000809 EXPECT_TRUE(Results.Completions.empty());
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000810}
811
Sam McCall800d4372017-12-19 10:29:27 +0000812SignatureHelp signatures(StringRef Text) {
813 MockFSProvider FS;
814 MockCompilationDatabase CDB;
815 IgnoreDiagnostics DiagConsumer;
Sam McCall7363a2f2018-03-05 17:28:54 +0000816 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
Sam McCallc1568062018-02-16 09:41:43 +0000817 auto File = testPath("foo.cpp");
Sam McCall328cbdb2017-12-20 16:06:05 +0000818 Annotations Test(Text);
Sam McCall7363a2f2018-03-05 17:28:54 +0000819 runAddDocument(Server, File, Test.code());
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000820 return cantFail(runSignatureHelp(Server, File, Test.point()));
Sam McCall800d4372017-12-19 10:29:27 +0000821}
822
823MATCHER_P(ParamsAre, P, "") {
824 if (P.size() != arg.parameters.size())
825 return false;
826 for (unsigned I = 0; I < P.size(); ++I)
827 if (P[I] != arg.parameters[I].label)
828 return false;
829 return true;
830}
831
832Matcher<SignatureInformation> Sig(std::string Label,
833 std::vector<std::string> Params) {
Eric Liu8f3678d2018-06-15 13:34:18 +0000834 return AllOf(SigHelpLabeled(Label), ParamsAre(Params));
Sam McCall800d4372017-12-19 10:29:27 +0000835}
836
837TEST(SignatureHelpTest, Overloads) {
838 auto Results = signatures(R"cpp(
839 void foo(int x, int y);
840 void foo(int x, float y);
841 void foo(float x, int y);
842 void foo(float x, float y);
843 void bar(int x, int y = 0);
844 int main() { foo(^); }
845 )cpp");
846 EXPECT_THAT(Results.signatures,
847 UnorderedElementsAre(
848 Sig("foo(float x, float y) -> void", {"float x", "float y"}),
849 Sig("foo(float x, int y) -> void", {"float x", "int y"}),
850 Sig("foo(int x, float y) -> void", {"int x", "float y"}),
851 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
852 // We always prefer the first signature.
853 EXPECT_EQ(0, Results.activeSignature);
854 EXPECT_EQ(0, Results.activeParameter);
855}
856
857TEST(SignatureHelpTest, DefaultArgs) {
858 auto Results = signatures(R"cpp(
859 void bar(int x, int y = 0);
860 void bar(float x = 0, int y = 42);
861 int main() { bar(^
862 )cpp");
863 EXPECT_THAT(Results.signatures,
864 UnorderedElementsAre(
865 Sig("bar(int x, int y = 0) -> void", {"int x", "int y = 0"}),
866 Sig("bar(float x = 0, int y = 42) -> void",
867 {"float x = 0", "int y = 42"})));
868 EXPECT_EQ(0, Results.activeSignature);
869 EXPECT_EQ(0, Results.activeParameter);
870}
871
872TEST(SignatureHelpTest, ActiveArg) {
873 auto Results = signatures(R"cpp(
874 int baz(int a, int b, int c);
875 int main() { baz(baz(1,2,3), ^); }
876 )cpp");
877 EXPECT_THAT(Results.signatures,
878 ElementsAre(Sig("baz(int a, int b, int c) -> int",
879 {"int a", "int b", "int c"})));
880 EXPECT_EQ(0, Results.activeSignature);
881 EXPECT_EQ(1, Results.activeParameter);
882}
883
Haojian Wu061c73e2018-01-23 11:37:26 +0000884class IndexRequestCollector : public SymbolIndex {
885public:
886 bool
Sam McCalld1a7a372018-01-31 13:40:48 +0000887 fuzzyFind(const FuzzyFindRequest &Req,
Haojian Wu061c73e2018-01-23 11:37:26 +0000888 llvm::function_ref<void(const Symbol &)> Callback) const override {
889 Requests.push_back(Req);
Sam McCallab8e3932018-02-19 13:04:41 +0000890 return true;
Haojian Wu061c73e2018-01-23 11:37:26 +0000891 }
892
Eric Liu9ec459f2018-03-14 09:48:05 +0000893 void lookup(const LookupRequest &,
894 llvm::function_ref<void(const Symbol &)>) const override {}
895
Haojian Wu061c73e2018-01-23 11:37:26 +0000896 const std::vector<FuzzyFindRequest> allRequests() const { return Requests; }
897
898private:
899 mutable std::vector<FuzzyFindRequest> Requests;
900};
901
902std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code) {
903 clangd::CodeCompleteOptions Opts;
904 IndexRequestCollector Requests;
905 Opts.Index = &Requests;
906 completions(Code, {}, Opts);
907 return Requests.allRequests();
908}
909
910TEST(CompletionTest, UnqualifiedIdQuery) {
911 auto Requests = captureIndexRequests(R"cpp(
912 namespace std {}
913 using namespace std;
914 namespace ns {
915 void f() {
916 vec^
917 }
918 }
919 )cpp");
920
921 EXPECT_THAT(Requests,
922 ElementsAre(Field(&FuzzyFindRequest::Scopes,
923 UnorderedElementsAre("", "ns::", "std::"))));
924}
925
926TEST(CompletionTest, ResolvedQualifiedIdQuery) {
927 auto Requests = captureIndexRequests(R"cpp(
928 namespace ns1 {}
929 namespace ns2 {} // ignore
930 namespace ns3 { namespace nns3 {} }
931 namespace foo {
932 using namespace ns1;
933 using namespace ns3::nns3;
934 }
935 namespace ns {
936 void f() {
937 foo::^
938 }
939 }
940 )cpp");
941
942 EXPECT_THAT(Requests,
943 ElementsAre(Field(
944 &FuzzyFindRequest::Scopes,
945 UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::"))));
946}
947
948TEST(CompletionTest, UnresolvedQualifierIdQuery) {
949 auto Requests = captureIndexRequests(R"cpp(
950 namespace a {}
951 using namespace a;
952 namespace ns {
953 void f() {
954 bar::^
955 }
956 } // namespace ns
957 )cpp");
958
959 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
960 UnorderedElementsAre("bar::"))));
961}
962
963TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
964 auto Requests = captureIndexRequests(R"cpp(
965 namespace a {}
966 using namespace a;
967 namespace ns {
968 void f() {
969 ::a::bar::^
970 }
971 } // namespace ns
972 )cpp");
973
974 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
975 UnorderedElementsAre("a::bar::"))));
976}
977
978TEST(CompletionTest, EmptyQualifiedQuery) {
979 auto Requests = captureIndexRequests(R"cpp(
980 namespace ns {
981 void f() {
982 ^
983 }
984 } // namespace ns
985 )cpp");
986
987 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
988 UnorderedElementsAre("", "ns::"))));
989}
990
991TEST(CompletionTest, GlobalQualifiedQuery) {
992 auto Requests = captureIndexRequests(R"cpp(
993 namespace ns {
994 void f() {
995 ::^
996 }
997 } // namespace ns
998 )cpp");
999
1000 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1001 UnorderedElementsAre(""))));
1002}
1003
Ilya Biryukova907ba42018-05-14 10:50:04 +00001004TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
1005 auto Completions = completions(
1006 R"cpp(
1007 struct Foo {
1008 int SomeNameOfField;
1009 typedef int SomeNameOfTypedefField;
1010 };
1011
1012 Foo::^)cpp",
1013 {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")});
1014
Sam McCalle746a2b2018-07-02 11:13:16 +00001015 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001016 AllOf(Contains(Labeled("SomeNameOfField")),
1017 Contains(Labeled("SomeNameOfTypedefField")),
1018 Not(Contains(Labeled("SomeNameInTheIndex")))));
1019}
1020
1021TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
1022 {
1023 auto Completions = completions(
1024 R"cpp(
1025 template <class T>
1026 void foo() {
1027 T::^
1028 }
1029 )cpp",
1030 {func("::SomeNameInTheIndex")});
1031
Sam McCalle746a2b2018-07-02 11:13:16 +00001032 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001033 Not(Contains(Labeled("SomeNameInTheIndex"))));
1034 }
1035
1036 {
1037 auto Completions = completions(
1038 R"cpp(
1039 template <class T>
1040 void foo() {
1041 T::template Y<int>::^
1042 }
1043 )cpp",
1044 {func("::SomeNameInTheIndex")});
1045
Sam McCalle746a2b2018-07-02 11:13:16 +00001046 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001047 Not(Contains(Labeled("SomeNameInTheIndex"))));
1048 }
1049
1050 {
1051 auto Completions = completions(
1052 R"cpp(
1053 template <class T>
1054 void foo() {
1055 T::foo::^
1056 }
1057 )cpp",
1058 {func("::SomeNameInTheIndex")});
1059
Sam McCalle746a2b2018-07-02 11:13:16 +00001060 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001061 Not(Contains(Labeled("SomeNameInTheIndex"))));
1062 }
1063}
1064
Sam McCallc18c2802018-06-15 11:06:29 +00001065TEST(CompletionTest, OverloadBundling) {
1066 clangd::CodeCompleteOptions Opts;
1067 Opts.BundleOverloads = true;
1068
1069 std::string Context = R"cpp(
1070 struct X {
1071 // Overload with int
1072 int a(int);
1073 // Overload with bool
1074 int a(bool);
1075 int b(float);
1076 };
1077 int GFuncC(int);
1078 int GFuncD(int);
1079 )cpp";
1080
1081 // Member completions are bundled.
Sam McCalle746a2b2018-07-02 11:13:16 +00001082 EXPECT_THAT(completions(Context + "int y = X().^", {}, Opts).Completions,
Sam McCallc18c2802018-06-15 11:06:29 +00001083 UnorderedElementsAre(Labeled("a(…)"), Labeled("b(float)")));
1084
1085 // Non-member completions are bundled, including index+sema.
1086 Symbol NoArgsGFunc = func("GFuncC");
1087 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001088 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
Sam McCallc18c2802018-06-15 11:06:29 +00001089 UnorderedElementsAre(Labeled("GFuncC(…)"), Labeled("GFuncD(int)")));
1090
1091 // Differences in header-to-insert suppress bundling.
1092 Symbol::Details Detail;
1093 std::string DeclFile = URI::createFile(testPath("foo")).toString();
1094 NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile;
1095 Detail.IncludeHeader = "<foo>";
1096 NoArgsGFunc.Detail = &Detail;
1097 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001098 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1099 UnorderedElementsAre(AllOf(Named("GFuncC"), InsertInclude("<foo>")),
1100 Labeled("GFuncC(int)"), Labeled("GFuncD(int)")));
Sam McCallc18c2802018-06-15 11:06:29 +00001101
1102 // Examine a bundled completion in detail.
Sam McCalle746a2b2018-07-02 11:13:16 +00001103 auto A =
1104 completions(Context + "int y = X().a^", {}, Opts).Completions.front();
1105 EXPECT_EQ(A.Name, "a");
1106 EXPECT_EQ(A.Signature, "(…)");
1107 EXPECT_EQ(A.BundleSize, 2u);
1108 EXPECT_EQ(A.Kind, CompletionItemKind::Method);
1109 EXPECT_EQ(A.ReturnType, "int"); // All overloads return int.
Sam McCallc18c2802018-06-15 11:06:29 +00001110 // For now we just return one of the doc strings arbitrarily.
Sam McCalle746a2b2018-07-02 11:13:16 +00001111 EXPECT_THAT(A.Documentation, AnyOf(HasSubstr("Overload with int"),
Sam McCallc18c2802018-06-15 11:06:29 +00001112 HasSubstr("Overload with bool")));
Sam McCalle746a2b2018-07-02 11:13:16 +00001113 EXPECT_EQ(A.SnippetSuffix, "(${0})");
Sam McCallc18c2802018-06-15 11:06:29 +00001114}
1115
Ilya Biryukov30b04b12018-05-28 09:54:51 +00001116TEST(CompletionTest, DocumentationFromChangedFileCrash) {
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001117 MockFSProvider FS;
1118 auto FooH = testPath("foo.h");
1119 auto FooCpp = testPath("foo.cpp");
1120 FS.Files[FooH] = R"cpp(
1121 // this is my documentation comment.
1122 int func();
1123 )cpp";
1124 FS.Files[FooCpp] = "";
1125
1126 MockCompilationDatabase CDB;
1127 IgnoreDiagnostics DiagConsumer;
1128 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1129
1130 Annotations Source(R"cpp(
1131 #include "foo.h"
1132 int func() {
1133 // This makes sure we have func from header in the AST.
1134 }
1135 int a = fun^
1136 )cpp");
1137 Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
1138 // We need to wait for preamble to build.
1139 ASSERT_TRUE(Server.blockUntilIdleForTest());
1140
1141 // Change the header file. Completion will reuse the old preamble!
1142 FS.Files[FooH] = R"cpp(
1143 int func();
1144 )cpp";
1145
1146 clangd::CodeCompleteOptions Opts;
1147 Opts.IncludeComments = true;
Sam McCalle746a2b2018-07-02 11:13:16 +00001148 CodeCompleteResult Completions =
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001149 cantFail(runCodeComplete(Server, FooCpp, Source.point(), Opts));
1150 // We shouldn't crash. Unfortunately, current workaround is to not produce
1151 // comments for symbols from headers.
Sam McCalle746a2b2018-07-02 11:13:16 +00001152 EXPECT_THAT(Completions.Completions,
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001153 Contains(AllOf(Not(IsDocumented()), Named("func"))));
1154}
1155
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001156TEST(CompletionTest, NonDocComments) {
1157 MockFSProvider FS;
1158 auto FooCpp = testPath("foo.cpp");
1159 FS.Files[FooCpp] = "";
1160
1161 MockCompilationDatabase CDB;
1162 IgnoreDiagnostics DiagConsumer;
1163 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1164
1165 Annotations Source(R"cpp(
Ilya Biryukovda8dd8b2018-06-27 09:47:20 +00001166 // We ignore namespace comments, for rationale see CodeCompletionStrings.h.
1167 namespace comments_ns {
1168 }
1169
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001170 // ------------------
1171 int comments_foo();
1172
1173 // A comment and a decl are separated by newlines.
1174 // Therefore, the comment shouldn't show up as doc comment.
1175
1176 int comments_bar();
1177
1178 // this comment should be in the results.
1179 int comments_baz();
1180
1181
1182 template <class T>
1183 struct Struct {
1184 int comments_qux();
1185 int comments_quux();
1186 };
1187
1188
1189 // This comment should not be there.
1190
1191 template <class T>
1192 int Struct<T>::comments_qux() {
1193 }
1194
1195 // This comment **should** be in results.
1196 template <class T>
1197 int Struct<T>::comments_quux() {
1198 int a = comments^;
1199 }
1200 )cpp");
Reid Kleckner80274b12018-06-18 18:55:10 +00001201 // FIXME: Auto-completion in a template requires disabling delayed template
1202 // parsing.
1203 CDB.ExtraClangFlags.push_back("-fno-delayed-template-parsing");
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001204 Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes);
Sam McCalle746a2b2018-07-02 11:13:16 +00001205 CodeCompleteResult Completions = cantFail(runCodeComplete(
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001206 Server, FooCpp, Source.point(), clangd::CodeCompleteOptions()));
1207
1208 // We should not get any of those comments in completion.
1209 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001210 Completions.Completions,
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001211 UnorderedElementsAre(AllOf(Not(IsDocumented()), Named("comments_foo")),
1212 AllOf(IsDocumented(), Named("comments_baz")),
1213 AllOf(IsDocumented(), Named("comments_quux")),
Ilya Biryukovda8dd8b2018-06-27 09:47:20 +00001214 AllOf(Not(IsDocumented()), Named("comments_ns")),
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001215 // FIXME(ibiryukov): the following items should have
1216 // empty documentation, since they are separated from
1217 // a comment with an empty line. Unfortunately, I
1218 // couldn't make Sema tests pass if we ignore those.
1219 AllOf(IsDocumented(), Named("comments_bar")),
1220 AllOf(IsDocumented(), Named("comments_qux"))));
1221}
1222
Ilya Biryukov981a35d2018-05-28 12:11:37 +00001223TEST(CompletionTest, CompleteOnInvalidLine) {
1224 auto FooCpp = testPath("foo.cpp");
1225
1226 MockCompilationDatabase CDB;
1227 IgnoreDiagnostics DiagConsumer;
1228 MockFSProvider FS;
1229 FS.Files[FooCpp] = "// empty file";
1230
1231 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
1232 // Run completion outside the file range.
1233 Position Pos;
1234 Pos.line = 100;
1235 Pos.character = 0;
1236 EXPECT_THAT_EXPECTED(
1237 runCodeComplete(Server, FooCpp, Pos, clangd::CodeCompleteOptions()),
1238 Failed());
1239}
1240
Eric Liu7ad16962018-06-22 10:46:59 +00001241TEST(CompletionTest, QualifiedNames) {
1242 auto Results = completions(
1243 R"cpp(
1244 namespace ns { int local; void both(); }
1245 void f() { ::ns::^ }
1246 )cpp",
1247 {func("ns::both"), cls("ns::Index")});
1248 // We get results from both index and sema, with no duplicates.
Sam McCalle746a2b2018-07-02 11:13:16 +00001249 EXPECT_THAT(
1250 Results.Completions,
1251 UnorderedElementsAre(Scope("ns::"), Scope("ns::"), Scope("ns::")));
1252}
1253
1254TEST(CompletionTest, Render) {
1255 CodeCompletion C;
1256 C.Name = "x";
1257 C.Signature = "(bool) const";
1258 C.SnippetSuffix = "(${0:bool})";
1259 C.ReturnType = "int";
1260 C.RequiredQualifier = "Foo::";
1261 C.Scope = "ns::Foo::";
1262 C.Documentation = "This is x().";
1263 C.Header = "\"foo.h\"";
1264 C.Kind = CompletionItemKind::Method;
1265 C.Score.Total = 1.0;
Sam McCall4e5742a2018-07-06 11:50:49 +00001266 C.Origin = SymbolOrigin::AST | SymbolOrigin::Static;
Sam McCalle746a2b2018-07-02 11:13:16 +00001267
1268 CodeCompleteOptions Opts;
1269 Opts.IncludeIndicator.Insert = "^";
1270 Opts.IncludeIndicator.NoInsert = "";
1271 Opts.EnableSnippets = false;
1272
1273 auto R = C.render(Opts);
1274 EXPECT_EQ(R.label, "Foo::x(bool) const");
1275 EXPECT_EQ(R.insertText, "Foo::x");
1276 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
1277 EXPECT_EQ(R.filterText, "x");
1278 EXPECT_EQ(R.detail, "int\n\"foo.h\"");
1279 EXPECT_EQ(R.documentation, "This is x().");
1280 EXPECT_THAT(R.additionalTextEdits, IsEmpty());
Sam McCalle746a2b2018-07-02 11:13:16 +00001281 EXPECT_EQ(R.sortText, sortText(1.0, "x"));
1282
1283 Opts.EnableSnippets = true;
1284 R = C.render(Opts);
1285 EXPECT_EQ(R.insertText, "Foo::x(${0:bool})");
1286 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
1287
1288 C.HeaderInsertion.emplace();
1289 R = C.render(Opts);
1290 EXPECT_EQ(R.label, "^Foo::x(bool) const");
1291 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
1292
Sam McCall2161ec72018-07-05 06:20:41 +00001293 Opts.ShowOrigins = true;
1294 R = C.render(Opts);
1295 EXPECT_EQ(R.label, "^[AS]Foo::x(bool) const");
1296
Sam McCalle746a2b2018-07-02 11:13:16 +00001297 C.BundleSize = 2;
1298 R = C.render(Opts);
1299 EXPECT_EQ(R.detail, "[2 overloads]\n\"foo.h\"");
Eric Liu7ad16962018-06-22 10:46:59 +00001300}
Ilya Biryukov981a35d2018-05-28 12:11:37 +00001301
Eric Liu485074f2018-07-11 13:15:31 +00001302TEST(CompletionTest, IgnoreRecoveryResults) {
1303 auto Results = completions(
1304 R"cpp(
1305 namespace ns { int NotRecovered() { return 0; } }
1306 void f() {
1307 // Sema enters recovery mode first and then normal mode.
1308 if (auto x = ns::NotRecover^)
1309 }
1310 )cpp");
1311 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("NotRecovered")));
1312}
1313
Eric Liuf433c2d2018-07-18 15:31:14 +00001314TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
1315 auto Results = completions(
1316 R"cpp(
1317 namespace ns {
1318 class X { public: X(); int x_; };
1319 X::X() : x_^(0) {}
1320 }
1321 )cpp");
1322 EXPECT_THAT(Results.Completions,
1323 UnorderedElementsAre(AllOf(Scope("ns::X::"), Named("x_"))));
1324}
1325
Eric Liu5d2a8072018-07-23 10:56:37 +00001326TEST(CompletionTest, CodeCompletionContext) {
1327 auto Results = completions(
1328 R"cpp(
1329 namespace ns {
1330 class X { public: X(); int x_; };
1331 void f() {
1332 X x;
1333 x.^;
1334 }
1335 }
1336 )cpp");
1337
1338 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
1339}
1340
Sam McCall9aad25f2017-12-05 07:20:26 +00001341} // namespace
1342} // namespace clangd
1343} // namespace clang