blob: ae2fe27a748613e469edaf7a2ac61cd2e9d3db85 [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//===----------------------------------------------------------------------===//
9#include "ClangdServer.h"
10#include "Compiler.h"
Ilya Biryukov940901e2017-12-13 12:51:22 +000011#include "Context.h"
Ilya Biryukov5a85b8e2017-12-13 12:53:16 +000012#include "Matchers.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000013#include "Protocol.h"
14#include "TestFS.h"
Sam McCallf6ae3232017-12-05 20:11:29 +000015#include "gmock/gmock.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000016#include "gtest/gtest.h"
17
18namespace clang {
19namespace clangd {
Sam McCall800d4372017-12-19 10:29:27 +000020// Let GMock print completion items and signature help.
Sam McCallf6ae3232017-12-05 20:11:29 +000021void PrintTo(const CompletionItem &I, std::ostream *O) {
22 llvm::raw_os_ostream OS(*O);
Sam McCall44fdcec22017-12-08 15:00:59 +000023 OS << I.label << " - " << toJSON(I);
24}
25void PrintTo(const std::vector<CompletionItem> &V, std::ostream *O) {
26 *O << "{\n";
27 for (const auto &I : V) {
28 *O << "\t";
29 PrintTo(I, O);
30 *O << "\n";
31 }
32 *O << "}";
Sam McCallf6ae3232017-12-05 20:11:29 +000033}
Sam McCall800d4372017-12-19 10:29:27 +000034void PrintTo(const SignatureInformation &I, std::ostream *O) {
35 llvm::raw_os_ostream OS(*O);
36 OS << I.label << " - " << toJSON(I);
37}
38void PrintTo(const std::vector<SignatureInformation> &V, std::ostream *O) {
39 *O << "{\n";
40 for (const auto &I : V) {
41 *O << "\t";
42 PrintTo(I, O);
43 *O << "\n";
44 }
45 *O << "}";
46}
Sam McCallf6ae3232017-12-05 20:11:29 +000047
Sam McCall9aad25f2017-12-05 07:20:26 +000048namespace {
49using namespace llvm;
Sam McCallf6ae3232017-12-05 20:11:29 +000050using ::testing::AllOf;
51using ::testing::Contains;
52using ::testing::ElementsAre;
Sam McCallf6ae3232017-12-05 20:11:29 +000053using ::testing::Not;
Sam McCall9aad25f2017-12-05 07:20:26 +000054
55class IgnoreDiagnostics : public DiagnosticsConsumer {
56 void onDiagnosticsReady(
57 PathRef File, Tagged<std::vector<DiagWithFixIts>> Diagnostics) override {}
58};
59
60struct StringWithPos {
61 std::string Text;
62 clangd::Position MarkerPos;
63};
64
Sam McCallf6ae3232017-12-05 20:11:29 +000065/// Accepts a source file with a cursor marker ^.
66/// Returns the source file with the marker removed, and the marker position.
67StringWithPos parseTextMarker(StringRef Text) {
68 std::size_t MarkerOffset = Text.find('^');
69 assert(MarkerOffset != StringRef::npos && "^ wasn't found in Text.");
Sam McCall9aad25f2017-12-05 07:20:26 +000070
71 std::string WithoutMarker;
72 WithoutMarker += Text.take_front(MarkerOffset);
Sam McCallf6ae3232017-12-05 20:11:29 +000073 WithoutMarker += Text.drop_front(MarkerOffset + 1);
74 assert(StringRef(WithoutMarker).find('^') == StringRef::npos &&
75 "There were multiple occurences of ^ inside Text");
Sam McCall9aad25f2017-12-05 07:20:26 +000076
Sam McCallf6ae3232017-12-05 20:11:29 +000077 auto MarkerPos = offsetToPosition(WithoutMarker, MarkerOffset);
Sam McCall9aad25f2017-12-05 07:20:26 +000078 return {std::move(WithoutMarker), MarkerPos};
79}
80
Sam McCallf6ae3232017-12-05 20:11:29 +000081// GMock helpers for matching completion items.
82MATCHER_P(Named, Name, "") { return arg.insertText == Name; }
Sam McCall44fdcec22017-12-08 15:00:59 +000083MATCHER_P(Labeled, Label, "") { return arg.label == Label; }
84MATCHER_P(Kind, K, "") { return arg.kind == K; }
85MATCHER_P(PlainText, Text, "") {
86 return arg.insertTextFormat == clangd::InsertTextFormat::PlainText &&
87 arg.insertText == Text;
88}
89MATCHER_P(Snippet, Text, "") {
90 return arg.insertTextFormat == clangd::InsertTextFormat::Snippet &&
91 arg.insertText == Text;
92}
Sam McCallf6ae3232017-12-05 20:11:29 +000093// Shorthand for Contains(Named(Name)).
94Matcher<const std::vector<CompletionItem> &> Has(std::string Name) {
95 return Contains(Named(std::move(Name)));
96}
Sam McCall44fdcec22017-12-08 15:00:59 +000097Matcher<const std::vector<CompletionItem> &> Has(std::string Name,
98 CompletionItemKind K) {
99 return Contains(AllOf(Named(std::move(Name)), Kind(K)));
Sam McCallf6ae3232017-12-05 20:11:29 +0000100}
Sam McCall44fdcec22017-12-08 15:00:59 +0000101MATCHER(IsDocumented, "") { return !arg.documentation.empty(); }
Sam McCall9aad25f2017-12-05 07:20:26 +0000102
Sam McCallf6ae3232017-12-05 20:11:29 +0000103CompletionList completions(StringRef Text,
104 clangd::CodeCompleteOptions Opts = {}) {
Sam McCall9aad25f2017-12-05 07:20:26 +0000105 MockFSProvider FS;
Sam McCall93cd9912017-12-05 07:34:35 +0000106 MockCompilationDatabase CDB;
Sam McCallf6ae3232017-12-05 20:11:29 +0000107 IgnoreDiagnostics DiagConsumer;
Sam McCall9aad25f2017-12-05 07:20:26 +0000108 ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
Ilya Biryukov940901e2017-12-13 12:51:22 +0000109 /*StorePreamblesInMemory=*/true);
Sam McCallf6ae3232017-12-05 20:11:29 +0000110 auto File = getVirtualTestFilePath("foo.cpp");
111 auto Test = parseTextMarker(Text);
Ilya Biryukov940901e2017-12-13 12:51:22 +0000112 Server.addDocument(Context::empty(), File, Test.Text);
113 return Server.codeComplete(Context::empty(), File, Test.MarkerPos, Opts)
114 .get()
115 .second.Value;
Sam McCall9aad25f2017-12-05 07:20:26 +0000116}
117
Sam McCallf6ae3232017-12-05 20:11:29 +0000118TEST(CompletionTest, Limit) {
119 clangd::CodeCompleteOptions Opts;
120 Opts.Limit = 2;
121 auto Results = completions(R"cpp(
Sam McCall9aad25f2017-12-05 07:20:26 +0000122struct ClassWithMembers {
123 int AAA();
124 int BBB();
125 int CCC();
126}
Sam McCallf6ae3232017-12-05 20:11:29 +0000127int main() { ClassWithMembers().^ }
Sam McCall9aad25f2017-12-05 07:20:26 +0000128 )cpp",
Sam McCallf6ae3232017-12-05 20:11:29 +0000129 Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000130
131 EXPECT_TRUE(Results.isIncomplete);
Sam McCallf6ae3232017-12-05 20:11:29 +0000132 EXPECT_THAT(Results.items, ElementsAre(Named("AAA"), Named("BBB")));
Sam McCall9aad25f2017-12-05 07:20:26 +0000133}
134
Sam McCallf6ae3232017-12-05 20:11:29 +0000135TEST(CompletionTest, Filter) {
136 std::string Body = R"cpp(
Sam McCall9aad25f2017-12-05 07:20:26 +0000137 int Abracadabra;
138 int Alakazam;
139 struct S {
140 int FooBar;
141 int FooBaz;
142 int Qux;
143 };
144 )cpp";
Sam McCallf6ae3232017-12-05 20:11:29 +0000145 EXPECT_THAT(completions(Body + "int main() { S().Foba^ }").items,
146 AllOf(Has("FooBar"), Has("FooBaz"), Not(Has("Qux"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000147
Sam McCallf6ae3232017-12-05 20:11:29 +0000148 EXPECT_THAT(completions(Body + "int main() { S().FR^ }").items,
149 AllOf(Has("FooBar"), Not(Has("FooBaz")), Not(Has("Qux"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000150
Sam McCallf6ae3232017-12-05 20:11:29 +0000151 EXPECT_THAT(completions(Body + "int main() { S().opr^ }").items,
152 Has("operator="));
Sam McCall9aad25f2017-12-05 07:20:26 +0000153
Sam McCallf6ae3232017-12-05 20:11:29 +0000154 EXPECT_THAT(completions(Body + "int main() { aaa^ }").items,
155 AllOf(Has("Abracadabra"), Has("Alakazam")));
Sam McCall9aad25f2017-12-05 07:20:26 +0000156
Sam McCallf6ae3232017-12-05 20:11:29 +0000157 EXPECT_THAT(completions(Body + "int main() { _a^ }").items,
158 AllOf(Has("static_cast"), Not(Has("Abracadabra"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000159}
160
Sam McCallf6ae3232017-12-05 20:11:29 +0000161void TestAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000162 auto Results = completions(
163 R"cpp(
164 #define MACRO X
Sam McCall9aad25f2017-12-05 07:20:26 +0000165
Sam McCall44fdcec22017-12-08 15:00:59 +0000166 int global_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000167
Sam McCall44fdcec22017-12-08 15:00:59 +0000168 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000169
Sam McCall44fdcec22017-12-08 15:00:59 +0000170 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000171
Sam McCall44fdcec22017-12-08 15:00:59 +0000172 struct ClassWithMembers {
173 /// Doc for method.
174 int method();
Sam McCall9aad25f2017-12-05 07:20:26 +0000175
Sam McCall44fdcec22017-12-08 15:00:59 +0000176 int field;
177 private:
178 int private_field;
179 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000180
Sam McCall44fdcec22017-12-08 15:00:59 +0000181 int test() {
182 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000183
Sam McCall44fdcec22017-12-08 15:00:59 +0000184 /// Doc for local_var.
185 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000186
Sam McCall44fdcec22017-12-08 15:00:59 +0000187 ClassWithMembers().^
188 }
189 )cpp",
190 Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000191
Sam McCallf6ae3232017-12-05 20:11:29 +0000192 // Class members. The only items that must be present in after-dot
193 // completion.
Sam McCall44fdcec22017-12-08 15:00:59 +0000194 EXPECT_THAT(
195 Results.items,
196 AllOf(Has(Opts.EnableSnippets ? "method()" : "method"), Has("field")));
197 EXPECT_IFF(Opts.IncludeIneligibleResults, Results.items,
198 Has("private_field"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000199 // Global items.
Sam McCall44fdcec22017-12-08 15:00:59 +0000200 EXPECT_THAT(Results.items, Not(AnyOf(Has("global_var"), Has("global_func"),
201 Has("global_func()"), Has("GlobalClass"),
202 Has("MACRO"), Has("LocalClass"))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000203 // There should be no code patterns (aka snippets) in after-dot
204 // completion. At least there aren't any we're aware of.
Sam McCall44fdcec22017-12-08 15:00:59 +0000205 EXPECT_THAT(Results.items, Not(Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000206 // Check documentation.
Sam McCall44fdcec22017-12-08 15:00:59 +0000207 EXPECT_IFF(Opts.IncludeBriefComments, Results.items,
208 Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000209}
Sam McCall9aad25f2017-12-05 07:20:26 +0000210
Sam McCallf6ae3232017-12-05 20:11:29 +0000211void TestGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000212 auto Results = completions(
213 R"cpp(
214 #define MACRO X
Sam McCall9aad25f2017-12-05 07:20:26 +0000215
Sam McCall44fdcec22017-12-08 15:00:59 +0000216 int global_var;
217 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000218
Sam McCall44fdcec22017-12-08 15:00:59 +0000219 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000220
Sam McCall44fdcec22017-12-08 15:00:59 +0000221 struct ClassWithMembers {
222 /// Doc for method.
223 int method();
224 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000225
Sam McCall44fdcec22017-12-08 15:00:59 +0000226 int test() {
227 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000228
Sam McCall44fdcec22017-12-08 15:00:59 +0000229 /// Doc for local_var.
230 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000231
Sam McCall44fdcec22017-12-08 15:00:59 +0000232 ^
233 }
234 )cpp",
235 Opts);
Sam McCallf6ae3232017-12-05 20:11:29 +0000236
237 // Class members. Should never be present in global completions.
Sam McCall44fdcec22017-12-08 15:00:59 +0000238 EXPECT_THAT(Results.items,
Sam McCallf6ae3232017-12-05 20:11:29 +0000239 Not(AnyOf(Has("method"), Has("method()"), Has("field"))));
240 // Global items.
Sam McCall44fdcec22017-12-08 15:00:59 +0000241 EXPECT_IFF(Opts.IncludeGlobals, Results.items,
Sam McCallf6ae3232017-12-05 20:11:29 +0000242 AllOf(Has("global_var"),
243 Has(Opts.EnableSnippets ? "global_func()" : "global_func"),
244 Has("GlobalClass")));
245 // A macro.
Sam McCall44fdcec22017-12-08 15:00:59 +0000246 EXPECT_IFF(Opts.IncludeMacros, Results.items, Has("MACRO"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000247 // Local items. Must be present always.
Ilya Biryukov9b5ffc22017-12-12 12:56:46 +0000248 EXPECT_THAT(Results.items,
249 AllOf(Has("local_var"), Has("LocalClass"),
250 Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000251 // Check documentation.
Sam McCall44fdcec22017-12-08 15:00:59 +0000252 EXPECT_IFF(Opts.IncludeBriefComments, Results.items,
253 Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000254}
255
256TEST(CompletionTest, CompletionOptions) {
257 clangd::CodeCompleteOptions Opts;
Sam McCall9aad25f2017-12-05 07:20:26 +0000258 for (bool IncludeMacros : {true, false}) {
Sam McCallf6ae3232017-12-05 20:11:29 +0000259 Opts.IncludeMacros = IncludeMacros;
Sam McCall9aad25f2017-12-05 07:20:26 +0000260 for (bool IncludeGlobals : {true, false}) {
Sam McCallf6ae3232017-12-05 20:11:29 +0000261 Opts.IncludeGlobals = IncludeGlobals;
Sam McCall9aad25f2017-12-05 07:20:26 +0000262 for (bool IncludeBriefComments : {true, false}) {
Sam McCallf6ae3232017-12-05 20:11:29 +0000263 Opts.IncludeBriefComments = IncludeBriefComments;
Sam McCall9aad25f2017-12-05 07:20:26 +0000264 for (bool EnableSnippets : {true, false}) {
Sam McCallf6ae3232017-12-05 20:11:29 +0000265 Opts.EnableSnippets = EnableSnippets;
Sam McCall9aad25f2017-12-05 07:20:26 +0000266 for (bool IncludeCodePatterns : {true, false}) {
Sam McCallf6ae3232017-12-05 20:11:29 +0000267 Opts.IncludeCodePatterns = IncludeCodePatterns;
Sam McCall9aad25f2017-12-05 07:20:26 +0000268 for (bool IncludeIneligibleResults : {true, false}) {
Sam McCallf6ae3232017-12-05 20:11:29 +0000269 Opts.IncludeIneligibleResults = IncludeIneligibleResults;
270 TestAfterDotCompletion(Opts);
271 TestGlobalScopeCompletion(Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000272 }
273 }
274 }
275 }
276 }
277 }
278}
279
Sam McCallf6ae3232017-12-05 20:11:29 +0000280// Check code completion works when the file contents are overridden.
281TEST(CompletionTest, CheckContentsOverride) {
282 MockFSProvider FS;
283 IgnoreDiagnostics DiagConsumer;
284 MockCompilationDatabase CDB;
285 ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
Ilya Biryukov940901e2017-12-13 12:51:22 +0000286 /*StorePreamblesInMemory=*/true);
Sam McCallf6ae3232017-12-05 20:11:29 +0000287 auto File = getVirtualTestFilePath("foo.cpp");
Ilya Biryukov940901e2017-12-13 12:51:22 +0000288 Server.addDocument(Context::empty(), File, "ignored text!");
Sam McCallf6ae3232017-12-05 20:11:29 +0000289
290 auto Example = parseTextMarker("int cbc; int b = ^;");
291 auto Results =
292 Server
Ilya Biryukov940901e2017-12-13 12:51:22 +0000293 .codeComplete(Context::empty(), File, Example.MarkerPos,
294 clangd::CodeCompleteOptions(), StringRef(Example.Text))
Sam McCallf6ae3232017-12-05 20:11:29 +0000295 .get()
Ilya Biryukov940901e2017-12-13 12:51:22 +0000296 .second.Value;
Sam McCallf6ae3232017-12-05 20:11:29 +0000297 EXPECT_THAT(Results.items, Contains(Named("cbc")));
298}
299
Sam McCall44fdcec22017-12-08 15:00:59 +0000300TEST(CompletionTest, Priorities) {
301 auto Internal = completions(R"cpp(
302 class Foo {
303 public: void pub();
304 protected: void prot();
305 private: void priv();
306 };
307 void Foo::pub() { this->^ }
308 )cpp");
309 EXPECT_THAT(Internal.items,
310 HasSubsequence(Named("priv"), Named("prot"), Named("pub")));
311
312 auto External = completions(R"cpp(
313 class Foo {
314 public: void pub();
315 protected: void prot();
316 private: void priv();
317 };
318 void test() {
319 Foo F;
320 F.^
321 }
322 )cpp");
323 EXPECT_THAT(External.items,
324 AllOf(Has("pub"), Not(Has("prot")), Not(Has("priv"))));
325}
326
327TEST(CompletionTest, Qualifiers) {
328 auto Results = completions(R"cpp(
329 class Foo {
330 public: int foo() const;
331 int bar() const;
332 };
333 class Bar : public Foo {
334 int foo() const;
335 };
336 void test() { Bar().^ }
337 )cpp");
338 EXPECT_THAT(Results.items, HasSubsequence(Labeled("bar() const"),
339 Labeled("Foo::foo() const")));
340 EXPECT_THAT(Results.items, Not(Contains(Labeled("foo() const")))); // private
341}
342
343TEST(CompletionTest, Snippets) {
344 clangd::CodeCompleteOptions Opts;
345 Opts.EnableSnippets = true;
346 auto Results = completions(
347 R"cpp(
348 struct fake {
349 int a;
350 int f(int i, const float f) const;
351 };
352 int main() {
353 fake f;
354 f.^
355 }
356 )cpp",
357 Opts);
358 EXPECT_THAT(Results.items,
359 HasSubsequence(PlainText("a"),
360 Snippet("f(${1:int i}, ${2:const float f})")));
361}
362
363TEST(CompletionTest, Kinds) {
364 auto Results = completions(R"cpp(
365 #define MACRO X
366 int variable;
367 struct Struct {};
368 int function();
369 int X = ^
370 )cpp");
371 EXPECT_THAT(Results.items, Has("function", CompletionItemKind::Function));
372 EXPECT_THAT(Results.items, Has("variable", CompletionItemKind::Variable));
373 EXPECT_THAT(Results.items, Has("int", CompletionItemKind::Keyword));
374 EXPECT_THAT(Results.items, Has("Struct", CompletionItemKind::Class));
375 EXPECT_THAT(Results.items, Has("MACRO", CompletionItemKind::Text));
376
377 clangd::CodeCompleteOptions Opts;
378 Opts.EnableSnippets = true; // Needed for code patterns.
379
380 Results = completions("nam^");
381 EXPECT_THAT(Results.items, Has("namespace", CompletionItemKind::Snippet));
382}
383
Sam McCall800d4372017-12-19 10:29:27 +0000384SignatureHelp signatures(StringRef Text) {
385 MockFSProvider FS;
386 MockCompilationDatabase CDB;
387 IgnoreDiagnostics DiagConsumer;
388 ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
389 /*StorePreamblesInMemory=*/true);
390 auto File = getVirtualTestFilePath("foo.cpp");
391 auto Test = parseTextMarker(Text);
392 Server.addDocument(Context::empty(), File, Test.Text);
393 auto R = Server.signatureHelp(Context::empty(), File, Test.MarkerPos);
394 assert(R);
395 return R.get().Value;
396}
397
398MATCHER_P(ParamsAre, P, "") {
399 if (P.size() != arg.parameters.size())
400 return false;
401 for (unsigned I = 0; I < P.size(); ++I)
402 if (P[I] != arg.parameters[I].label)
403 return false;
404 return true;
405}
406
407Matcher<SignatureInformation> Sig(std::string Label,
408 std::vector<std::string> Params) {
409 return AllOf(Labeled(Label), ParamsAre(Params));
410}
411
412TEST(SignatureHelpTest, Overloads) {
413 auto Results = signatures(R"cpp(
414 void foo(int x, int y);
415 void foo(int x, float y);
416 void foo(float x, int y);
417 void foo(float x, float y);
418 void bar(int x, int y = 0);
419 int main() { foo(^); }
420 )cpp");
421 EXPECT_THAT(Results.signatures,
422 UnorderedElementsAre(
423 Sig("foo(float x, float y) -> void", {"float x", "float y"}),
424 Sig("foo(float x, int y) -> void", {"float x", "int y"}),
425 Sig("foo(int x, float y) -> void", {"int x", "float y"}),
426 Sig("foo(int x, int y) -> void", {"int x", "int y"})));
427 // We always prefer the first signature.
428 EXPECT_EQ(0, Results.activeSignature);
429 EXPECT_EQ(0, Results.activeParameter);
430}
431
432TEST(SignatureHelpTest, DefaultArgs) {
433 auto Results = signatures(R"cpp(
434 void bar(int x, int y = 0);
435 void bar(float x = 0, int y = 42);
436 int main() { bar(^
437 )cpp");
438 EXPECT_THAT(Results.signatures,
439 UnorderedElementsAre(
440 Sig("bar(int x, int y = 0) -> void", {"int x", "int y = 0"}),
441 Sig("bar(float x = 0, int y = 42) -> void",
442 {"float x = 0", "int y = 42"})));
443 EXPECT_EQ(0, Results.activeSignature);
444 EXPECT_EQ(0, Results.activeParameter);
445}
446
447TEST(SignatureHelpTest, ActiveArg) {
448 auto Results = signatures(R"cpp(
449 int baz(int a, int b, int c);
450 int main() { baz(baz(1,2,3), ^); }
451 )cpp");
452 EXPECT_THAT(Results.signatures,
453 ElementsAre(Sig("baz(int a, int b, int c) -> int",
454 {"int a", "int b", "int c"})));
455 EXPECT_EQ(0, Results.activeSignature);
456 EXPECT_EQ(1, Results.activeParameter);
457}
458
Sam McCall9aad25f2017-12-05 07:20:26 +0000459} // namespace
460} // namespace clangd
461} // namespace clang