blob: 1084b155057992ea3c8f63c67301cba2a11e40f5 [file] [log] [blame]
Sam McCall9aad25f2017-12-05 07:20:26 +00001//===-- CodeCompleteTests.cpp -----------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Sam McCall9aad25f2017-12-05 07:20:26 +00006//
7//===----------------------------------------------------------------------===//
Eric Liu6f648df2017-12-19 16:50:37 +00008
Sam McCall328cbdb2017-12-20 16:06:05 +00009#include "Annotations.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000010#include "ClangdServer.h"
Sam McCall328cbdb2017-12-20 16:06:05 +000011#include "CodeComplete.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000012#include "Compiler.h"
Ilya Biryukov5a85b8e2017-12-13 12:53:16 +000013#include "Matchers.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000014#include "Protocol.h"
Sam McCalle746a2b2018-07-02 11:13:16 +000015#include "Quality.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 Liudd662772019-01-28 14:01:55 +000019#include "TestIndex.h"
Kadir Cetinkaya60ec08f2019-02-26 14:23:47 +000020#include "TestTU.h"
Kadir Cetinkayade859972019-10-07 17:12:18 +000021#include "Threading.h"
Sam McCallc316b222019-04-26 07:45:49 +000022#include "index/Index.h"
Eric Liu6f648df2017-12-19 16:50:37 +000023#include "index/MemIndex.h"
Eric Liu5d2a8072018-07-23 10:56:37 +000024#include "clang/Sema/CodeCompleteConsumer.h"
Eric Liu00d99bd2019-04-11 09:36:36 +000025#include "clang/Tooling/CompilationDatabase.h"
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +000026#include "llvm/Support/Error.h"
Kadir Cetinkaya3ba9a432019-04-24 09:42:53 +000027#include "llvm/Support/Path.h"
Ilya Biryukov981a35d2018-05-28 12:11:37 +000028#include "llvm/Testing/Support/Error.h"
Sam McCallf6ae3232017-12-05 20:11:29 +000029#include "gmock/gmock.h"
Sam McCall9aad25f2017-12-05 07:20:26 +000030#include "gtest/gtest.h"
Kadir Cetinkayade859972019-10-07 17:12:18 +000031#include <condition_variable>
Utkarsh Saxenae397a0a2020-03-04 13:25:02 +010032#include <functional>
Kadir Cetinkayade859972019-10-07 17:12:18 +000033#include <mutex>
Utkarsh Saxenae397a0a2020-03-04 13:25:02 +010034#include <vector>
Sam McCall9aad25f2017-12-05 07:20:26 +000035
36namespace clang {
37namespace clangd {
Sam McCallf6ae3232017-12-05 20:11:29 +000038
Sam McCall9aad25f2017-12-05 07:20:26 +000039namespace {
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000040using ::llvm::Failed;
Sam McCallf6ae3232017-12-05 20:11:29 +000041using ::testing::AllOf;
42using ::testing::Contains;
43using ::testing::ElementsAre;
Ilya Biryukov71028b82018-03-12 15:28:22 +000044using ::testing::Field;
Sam McCallc18c2802018-06-15 11:06:29 +000045using ::testing::HasSubstr;
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +000046using ::testing::IsEmpty;
Sam McCallf6ae3232017-12-05 20:11:29 +000047using ::testing::Not;
Sam McCall3d139c52018-01-12 18:30:08 +000048using ::testing::UnorderedElementsAre;
Sam McCall9aad25f2017-12-05 07:20:26 +000049
Sam McCallf6ae3232017-12-05 20:11:29 +000050// GMock helpers for matching completion items.
Sam McCalle746a2b2018-07-02 11:13:16 +000051MATCHER_P(Named, Name, "") { return arg.Name == Name; }
Ilya Biryukovcabab292019-05-24 10:18:39 +000052MATCHER_P(NameStartsWith, Prefix, "") {
53 return llvm::StringRef(arg.Name).startswith(Prefix);
54}
Sam McCalle746a2b2018-07-02 11:13:16 +000055MATCHER_P(Scope, S, "") { return arg.Scope == S; }
56MATCHER_P(Qualifier, Q, "") { return arg.RequiredQualifier == Q; }
Eric Liu8f3678d2018-06-15 13:34:18 +000057MATCHER_P(Labeled, Label, "") {
Sam McCalle746a2b2018-07-02 11:13:16 +000058 return arg.RequiredQualifier + arg.Name + arg.Signature == Label;
Eric Liu8f3678d2018-06-15 13:34:18 +000059}
60MATCHER_P(SigHelpLabeled, Label, "") { return arg.label == Label; }
Sam McCalle746a2b2018-07-02 11:13:16 +000061MATCHER_P(Kind, K, "") { return arg.Kind == K; }
62MATCHER_P(Doc, D, "") { return arg.Documentation == D; }
63MATCHER_P(ReturnType, D, "") { return arg.ReturnType == D; }
Eric Liu83f63e42018-09-03 10:18:21 +000064MATCHER_P(HasInclude, IncludeHeader, "") {
65 return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader;
Eric Liu63f419a2018-05-15 15:29:32 +000066}
Eric Liu83f63e42018-09-03 10:18:21 +000067MATCHER_P(InsertInclude, IncludeHeader, "") {
68 return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader &&
69 bool(arg.Includes[0].Insertion);
70}
71MATCHER(InsertInclude, "") {
72 return !arg.Includes.empty() && bool(arg.Includes[0].Insertion);
73}
Sam McCalle746a2b2018-07-02 11:13:16 +000074MATCHER_P(SnippetSuffix, Text, "") { return arg.SnippetSuffix == Text; }
Sam McCall2161ec72018-07-05 06:20:41 +000075MATCHER_P(Origin, OriginSet, "") { return arg.Origin == OriginSet; }
Sam McCall39e86fa2018-11-14 09:05:19 +000076MATCHER_P(Signature, S, "") { return arg.Signature == S; }
Eric Liu63f419a2018-05-15 15:29:32 +000077
Sam McCallf6ae3232017-12-05 20:11:29 +000078// Shorthand for Contains(Named(Name)).
Sam McCalle746a2b2018-07-02 11:13:16 +000079Matcher<const std::vector<CodeCompletion> &> Has(std::string Name) {
Sam McCallf6ae3232017-12-05 20:11:29 +000080 return Contains(Named(std::move(Name)));
81}
Sam McCalle746a2b2018-07-02 11:13:16 +000082Matcher<const std::vector<CodeCompletion> &> Has(std::string Name,
Sam McCall44fdcec22017-12-08 15:00:59 +000083 CompletionItemKind K) {
84 return Contains(AllOf(Named(std::move(Name)), Kind(K)));
Sam McCallf6ae3232017-12-05 20:11:29 +000085}
Sam McCalle746a2b2018-07-02 11:13:16 +000086MATCHER(IsDocumented, "") { return !arg.Documentation.empty(); }
Eric Liu6df66002018-09-06 18:52:26 +000087MATCHER(Deprecated, "") { return arg.Deprecated; }
Sam McCall9aad25f2017-12-05 07:20:26 +000088
Sam McCalla15c2d62018-01-18 09:27:56 +000089std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol> Symbols) {
90 SymbolSlab::Builder Slab;
91 for (const auto &Sym : Symbols)
92 Slab.insert(Sym);
Nathan Ridgef1e6f572019-06-15 02:26:47 +000093 return MemIndex::build(std::move(Slab).build(), RefSlab(), RelationSlab());
Sam McCalla15c2d62018-01-18 09:27:56 +000094}
95
Sam McCall2dee4d42020-03-31 23:09:28 +020096// Runs code completion.
97// If IndexSymbols is non-empty, an index will be built and passed to opts.
98CodeCompleteResult completions(const TestTU &TU, Position Point,
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +000099 std::vector<Symbol> IndexSymbols = {},
100 clangd::CodeCompleteOptions Opts = {}) {
101 std::unique_ptr<SymbolIndex> OverrideIndex;
102 if (!IndexSymbols.empty()) {
103 assert(!Opts.Index && "both Index and IndexSymbols given!");
104 OverrideIndex = memIndex(std::move(IndexSymbols));
105 Opts.Index = OverrideIndex.get();
106 }
107
Sam McCall2dee4d42020-03-31 23:09:28 +0200108 auto Inputs = TU.inputs();
109 IgnoreDiagnostics Diags;
110 auto CI = buildCompilerInvocation(Inputs, Diags);
111 if (!CI) {
112 ADD_FAILURE() << "Couldn't build CompilerInvocation";
113 return {};
Sam McCalla15c2d62018-01-18 09:27:56 +0000114 }
Sam McCall2dee4d42020-03-31 23:09:28 +0200115 auto Preamble =
116 buildPreamble(testPath(TU.Filename), *CI, /*OldPreamble=*/nullptr, Inputs,
117 /*InMemory=*/true, /*Callback=*/nullptr);
118 return codeComplete(testPath(TU.Filename), Inputs.CompileCommand,
119 Preamble.get(), TU.Code, Point, Inputs.FS, Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000120}
121
Sam McCall2dee4d42020-03-31 23:09:28 +0200122// Runs code completion.
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000123CodeCompleteResult completions(llvm::StringRef Text,
Sam McCalle746a2b2018-07-02 11:13:16 +0000124 std::vector<Symbol> IndexSymbols = {},
Sam McCall39e86fa2018-11-14 09:05:19 +0000125 clangd::CodeCompleteOptions Opts = {},
126 PathRef FilePath = "foo.cpp") {
Sam McCall2dee4d42020-03-31 23:09:28 +0200127 Annotations Test(Text);
128 auto TU = TestTU::withCode(Test.code());
Ilya Biryukov339502c2019-11-20 15:51:18 +0100129 // To make sure our tests for completiopns inside templates work on Windows.
Sam McCall2dee4d42020-03-31 23:09:28 +0200130 TU.Filename = FilePath.str();
131 return completions(TU, Test.point(), std::move(IndexSymbols),
132 std::move(Opts));
Eric Liu63f419a2018-05-15 15:29:32 +0000133}
134
Sam McCall2dee4d42020-03-31 23:09:28 +0200135// Runs code completion without the clang parser.
Eric Liu00d99bd2019-04-11 09:36:36 +0000136CodeCompleteResult completionsNoCompile(llvm::StringRef Text,
137 std::vector<Symbol> IndexSymbols = {},
138 clangd::CodeCompleteOptions Opts = {},
139 PathRef FilePath = "foo.cpp") {
140 std::unique_ptr<SymbolIndex> OverrideIndex;
141 if (!IndexSymbols.empty()) {
142 assert(!Opts.Index && "both Index and IndexSymbols given!");
143 OverrideIndex = memIndex(std::move(IndexSymbols));
144 Opts.Index = OverrideIndex.get();
145 }
146
147 MockFSProvider FS;
148 Annotations Test(Text);
149 return codeComplete(FilePath, tooling::CompileCommand(), /*Preamble=*/nullptr,
150 Test.code(), Test.point(), FS.getFileSystem(), Opts);
151}
152
Sam McCalldc8abc42018-05-03 14:53:02 +0000153Symbol withReferences(int N, Symbol S) {
154 S.References = N;
155 return S;
156}
Sam McCalla15c2d62018-01-18 09:27:56 +0000157
Sam McCallf6ae3232017-12-05 20:11:29 +0000158TEST(CompletionTest, Limit) {
159 clangd::CodeCompleteOptions Opts;
160 Opts.Limit = 2;
161 auto Results = completions(R"cpp(
Sam McCall9aad25f2017-12-05 07:20:26 +0000162struct ClassWithMembers {
163 int AAA();
164 int BBB();
165 int CCC();
Haojian Wu744eb3c2018-12-21 09:32:49 +0000166};
Sam McCall9fb22b22019-05-06 10:25:10 +0000167
Sam McCallf6ae3232017-12-05 20:11:29 +0000168int main() { ClassWithMembers().^ }
Sam McCall9aad25f2017-12-05 07:20:26 +0000169 )cpp",
Sam McCalla15c2d62018-01-18 09:27:56 +0000170 /*IndexSymbols=*/{}, Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000171
Sam McCalle746a2b2018-07-02 11:13:16 +0000172 EXPECT_TRUE(Results.HasMore);
173 EXPECT_THAT(Results.Completions, ElementsAre(Named("AAA"), Named("BBB")));
Sam McCall9aad25f2017-12-05 07:20:26 +0000174}
175
Sam McCallf6ae3232017-12-05 20:11:29 +0000176TEST(CompletionTest, Filter) {
177 std::string Body = R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000178 #define MotorCar
179 int Car;
Sam McCall9aad25f2017-12-05 07:20:26 +0000180 struct S {
181 int FooBar;
182 int FooBaz;
183 int Qux;
184 };
185 )cpp";
Sam McCall8b2dcc12018-06-14 13:50:30 +0000186
187 // Only items matching the fuzzy query are returned.
Sam McCalle746a2b2018-07-02 11:13:16 +0000188 EXPECT_THAT(completions(Body + "int main() { S().Foba^ }").Completions,
Sam McCall8b2dcc12018-06-14 13:50:30 +0000189 AllOf(Has("FooBar"), Has("FooBaz"), Not(Has("Qux"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000190
Sam McCall8b2dcc12018-06-14 13:50:30 +0000191 // Macros require prefix match.
Sam McCalle746a2b2018-07-02 11:13:16 +0000192 EXPECT_THAT(completions(Body + "int main() { C^ }").Completions,
Sam McCall8b2dcc12018-06-14 13:50:30 +0000193 AllOf(Has("Car"), Not(Has("MotorCar"))));
Sam McCall9aad25f2017-12-05 07:20:26 +0000194}
195
Ilya Biryukoved913a22019-10-24 15:40:23 +0200196void testAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000197 auto Results = completions(
198 R"cpp(
Sam McCall44fdcec22017-12-08 15:00:59 +0000199 int global_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000200
Sam McCall44fdcec22017-12-08 15:00:59 +0000201 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000202
Eric Liu467c5f92018-09-19 09:35:04 +0000203 // Make sure this is not in preamble.
204 #define MACRO X
205
Sam McCall44fdcec22017-12-08 15:00:59 +0000206 struct GlobalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000207
Sam McCall44fdcec22017-12-08 15:00:59 +0000208 struct ClassWithMembers {
209 /// Doc for method.
210 int method();
Sam McCall9aad25f2017-12-05 07:20:26 +0000211
Sam McCall44fdcec22017-12-08 15:00:59 +0000212 int field;
213 private:
214 int private_field;
215 };
Sam McCall9aad25f2017-12-05 07:20:26 +0000216
Sam McCall44fdcec22017-12-08 15:00:59 +0000217 int test() {
218 struct LocalClass {};
Sam McCall9aad25f2017-12-05 07:20:26 +0000219
Sam McCall44fdcec22017-12-08 15:00:59 +0000220 /// Doc for local_var.
221 int local_var;
Sam McCall9aad25f2017-12-05 07:20:26 +0000222
Sam McCall44fdcec22017-12-08 15:00:59 +0000223 ClassWithMembers().^
224 }
225 )cpp",
Sam McCall545a20d2018-01-19 14:34:02 +0000226 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);
Sam McCall9aad25f2017-12-05 07:20:26 +0000227
Sam McCall8940f462019-05-06 12:03:26 +0000228 EXPECT_TRUE(Results.RanParser);
Sam McCallf6ae3232017-12-05 20:11:29 +0000229 // Class members. The only items that must be present in after-dot
230 // completion.
Sam McCalle746a2b2018-07-02 11:13:16 +0000231 EXPECT_THAT(Results.Completions,
232 AllOf(Has("method"), Has("field"), Not(Has("ClassWithMembers")),
Sam McCall4caa8512018-06-07 12:49:17 +0000233 Not(Has("operator=")), Not(Has("~ClassWithMembers"))));
Sam McCalle746a2b2018-07-02 11:13:16 +0000234 EXPECT_IFF(Opts.IncludeIneligibleResults, Results.Completions,
Sam McCall44fdcec22017-12-08 15:00:59 +0000235 Has("private_field"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000236 // Global items.
Sam McCall545a20d2018-01-19 14:34:02 +0000237 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +0000238 Results.Completions,
Sam McCall545a20d2018-01-19 14:34:02 +0000239 Not(AnyOf(Has("global_var"), Has("index_var"), Has("global_func"),
240 Has("global_func()"), Has("index_func"), Has("GlobalClass"),
241 Has("IndexClass"), Has("MACRO"), Has("LocalClass"))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000242 // There should be no code patterns (aka snippets) in after-dot
243 // completion. At least there aren't any we're aware of.
Sam McCalle746a2b2018-07-02 11:13:16 +0000244 EXPECT_THAT(Results.Completions,
245 Not(Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000246 // Check documentation.
Sam McCalle746a2b2018-07-02 11:13:16 +0000247 EXPECT_IFF(Opts.IncludeComments, Results.Completions,
248 Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000249}
Sam McCall9aad25f2017-12-05 07:20:26 +0000250
Ilya Biryukoved913a22019-10-24 15:40:23 +0200251void testGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000252 auto Results = completions(
253 R"cpp(
Sam McCall44fdcec22017-12-08 15:00:59 +0000254 int global_var;
255 int global_func();
Sam McCall9aad25f2017-12-05 07:20:26 +0000256
Eric Liu467c5f92018-09-19 09:35:04 +0000257 // Make sure this is not in preamble.
258 #define MACRO X
259
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
Sam McCall8940f462019-05-06 12:03:26 +0000278 EXPECT_TRUE(Results.RanParser);
Sam McCallf6ae3232017-12-05 20:11:29 +0000279 // Class members. Should never be present in global completions.
Sam McCalle746a2b2018-07-02 11:13:16 +0000280 EXPECT_THAT(Results.Completions,
Sam McCallf6ae3232017-12-05 20:11:29 +0000281 Not(AnyOf(Has("method"), Has("method()"), Has("field"))));
282 // Global items.
Sam McCalle746a2b2018-07-02 11:13:16 +0000283 EXPECT_THAT(Results.Completions,
284 AllOf(Has("global_var"), Has("index_var"), Has("global_func"),
Sam McCall545a20d2018-01-19 14:34:02 +0000285 Has("index_func" /* our fake symbol doesn't include () */),
286 Has("GlobalClass"), Has("IndexClass")));
Sam McCallf6ae3232017-12-05 20:11:29 +0000287 // A macro.
Sam McCalle746a2b2018-07-02 11:13:16 +0000288 EXPECT_IFF(Opts.IncludeMacros, Results.Completions, Has("MACRO"));
Sam McCallf6ae3232017-12-05 20:11:29 +0000289 // Local items. Must be present always.
Sam McCalle746a2b2018-07-02 11:13:16 +0000290 EXPECT_THAT(Results.Completions,
Ilya Biryukov9b5ffc22017-12-12 12:56:46 +0000291 AllOf(Has("local_var"), Has("LocalClass"),
292 Contains(Kind(CompletionItemKind::Snippet))));
Sam McCallf6ae3232017-12-05 20:11:29 +0000293 // Check documentation.
Sam McCalle746a2b2018-07-02 11:13:16 +0000294 EXPECT_IFF(Opts.IncludeComments, Results.Completions,
295 Contains(IsDocumented()));
Sam McCallf6ae3232017-12-05 20:11:29 +0000296}
297
298TEST(CompletionTest, CompletionOptions) {
Sam McCall2c3849a2018-01-16 12:21:24 +0000299 auto Test = [&](const clangd::CodeCompleteOptions &Opts) {
Ilya Biryukoved913a22019-10-24 15:40:23 +0200300 testAfterDotCompletion(Opts);
301 testGlobalScopeCompletion(Opts);
Sam McCall2c3849a2018-01-16 12:21:24 +0000302 };
303 // We used to test every combination of options, but that got too slow (2^N).
304 auto Flags = {
Ilya Biryukov71028b82018-03-12 15:28:22 +0000305 &clangd::CodeCompleteOptions::IncludeMacros,
Ilya Biryukov43714502018-05-16 12:32:44 +0000306 &clangd::CodeCompleteOptions::IncludeComments,
Ilya Biryukov71028b82018-03-12 15:28:22 +0000307 &clangd::CodeCompleteOptions::IncludeCodePatterns,
308 &clangd::CodeCompleteOptions::IncludeIneligibleResults,
Sam McCall2c3849a2018-01-16 12:21:24 +0000309 };
310 // Test default options.
311 Test({});
312 // Test with one flag flipped.
313 for (auto &F : Flags) {
314 clangd::CodeCompleteOptions O;
315 O.*F ^= true;
316 Test(O);
Sam McCall9aad25f2017-12-05 07:20:26 +0000317 }
318}
319
Sam McCall9fb22b22019-05-06 10:25:10 +0000320TEST(CompletionTest, Accessible) {
Sam McCall44fdcec22017-12-08 15:00:59 +0000321 auto Internal = completions(R"cpp(
322 class Foo {
323 public: void pub();
324 protected: void prot();
325 private: void priv();
326 };
327 void Foo::pub() { this->^ }
328 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000329 EXPECT_THAT(Internal.Completions,
Sam McCall9fb22b22019-05-06 10:25:10 +0000330 AllOf(Has("priv"), Has("prot"), Has("pub")));
Sam McCall44fdcec22017-12-08 15:00:59 +0000331
332 auto External = completions(R"cpp(
333 class Foo {
334 public: void pub();
335 protected: void prot();
336 private: void priv();
337 };
338 void test() {
339 Foo F;
340 F.^
341 }
342 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000343 EXPECT_THAT(External.Completions,
Sam McCall44fdcec22017-12-08 15:00:59 +0000344 AllOf(Has("pub"), Not(Has("prot")), Not(Has("priv"))));
345}
346
347TEST(CompletionTest, Qualifiers) {
348 auto Results = completions(R"cpp(
349 class Foo {
350 public: int foo() const;
351 int bar() const;
352 };
353 class Bar : public Foo {
354 int foo() const;
355 };
356 void test() { Bar().^ }
357 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000358 EXPECT_THAT(Results.Completions,
Sam McCalle8437cb2018-10-24 13:51:44 +0000359 Contains(AllOf(Qualifier(""), Named("bar"))));
360 // Hidden members are not shown.
Sam McCalle746a2b2018-07-02 11:13:16 +0000361 EXPECT_THAT(Results.Completions,
Sam McCalle8437cb2018-10-24 13:51:44 +0000362 Not(Contains(AllOf(Qualifier("Foo::"), Named("foo")))));
363 // Private members are not shown.
364 EXPECT_THAT(Results.Completions,
365 Not(Contains(AllOf(Qualifier(""), Named("foo")))));
Sam McCall44fdcec22017-12-08 15:00:59 +0000366}
367
Sam McCall4caa8512018-06-07 12:49:17 +0000368TEST(CompletionTest, InjectedTypename) {
369 // These are suppressed when accessed as a member...
Sam McCalle746a2b2018-07-02 11:13:16 +0000370 EXPECT_THAT(completions("struct X{}; void foo(){ X().^ }").Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000371 Not(Has("X")));
Sam McCalle746a2b2018-07-02 11:13:16 +0000372 EXPECT_THAT(completions("struct X{ void foo(){ this->^ } };").Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000373 Not(Has("X")));
374 // ...but accessible in other, more useful cases.
Sam McCalle746a2b2018-07-02 11:13:16 +0000375 EXPECT_THAT(completions("struct X{ void foo(){ ^ } };").Completions,
376 Has("X"));
377 EXPECT_THAT(
378 completions("struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions,
379 Has("Y"));
Sam McCall4caa8512018-06-07 12:49:17 +0000380 EXPECT_THAT(
381 completions(
382 "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };")
Sam McCalle746a2b2018-07-02 11:13:16 +0000383 .Completions,
Sam McCall4caa8512018-06-07 12:49:17 +0000384 Has("Y"));
385 // This case is marginal (`using X::X` is useful), we allow it for now.
Sam McCalle746a2b2018-07-02 11:13:16 +0000386 EXPECT_THAT(completions("struct X{}; void foo(){ X::^ }").Completions,
387 Has("X"));
Sam McCall4caa8512018-06-07 12:49:17 +0000388}
389
Eric Liub1317fa2018-11-30 11:12:40 +0000390TEST(CompletionTest, SkipInjectedWhenUnqualified) {
391 EXPECT_THAT(completions("struct X { void f() { X^ }};").Completions,
392 ElementsAre(Named("X"), Named("~X")));
393}
394
Sam McCall44fdcec22017-12-08 15:00:59 +0000395TEST(CompletionTest, Snippets) {
396 clangd::CodeCompleteOptions Opts;
Sam McCall44fdcec22017-12-08 15:00:59 +0000397 auto Results = completions(
398 R"cpp(
399 struct fake {
400 int a;
401 int f(int i, const float f) const;
402 };
403 int main() {
404 fake f;
405 f.^
406 }
407 )cpp",
Sam McCalla15c2d62018-01-18 09:27:56 +0000408 /*IndexSymbols=*/{}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000409 EXPECT_THAT(
410 Results.Completions,
411 HasSubsequence(Named("a"),
412 SnippetSuffix("(${1:int i}, ${2:const float f})")));
Sam McCall44fdcec22017-12-08 15:00:59 +0000413}
414
Ilya Biryukovd9971d02019-10-28 09:34:21 +0100415TEST(CompletionTest, NoSnippetsInUsings) {
416 clangd::CodeCompleteOptions Opts;
417 Opts.EnableSnippets = true;
418 auto Results = completions(
419 R"cpp(
420 namespace ns {
421 int func(int a, int b);
422 }
423
424 using ns::^;
425 )cpp",
426 /*IndexSymbols=*/{}, Opts);
427 EXPECT_THAT(Results.Completions,
428 ElementsAre(AllOf(Named("func"), Labeled("func(int a, int b)"),
429 SnippetSuffix(""))));
430
431 // Check index completions too.
432 auto Func = func("ns::func");
433 Func.CompletionSnippetSuffix = "(${1:int a}, ${2: int b})";
434 Func.Signature = "(int a, int b)";
435 Func.ReturnType = "void";
436
437 Results = completions(R"cpp(
438 namespace ns {}
439 using ns::^;
440 )cpp",
441 /*IndexSymbols=*/{Func}, Opts);
442 EXPECT_THAT(Results.Completions,
443 ElementsAre(AllOf(Named("func"), Labeled("func(int a, int b)"),
444 SnippetSuffix(""))));
445
446 // Check all-scopes completions too.
447 Opts.AllScopes = true;
448 Results = completions(R"cpp(
449 using ^;
450 )cpp",
451 /*IndexSymbols=*/{Func}, Opts);
452 EXPECT_THAT(Results.Completions,
453 Contains(AllOf(Named("func"), Labeled("ns::func(int a, int b)"),
454 SnippetSuffix(""))));
455}
456
Sam McCall44fdcec22017-12-08 15:00:59 +0000457TEST(CompletionTest, Kinds) {
Sam McCall545a20d2018-01-19 14:34:02 +0000458 auto Results = completions(
459 R"cpp(
Sam McCall545a20d2018-01-19 14:34:02 +0000460 int variable;
461 struct Struct {};
462 int function();
Eric Liu467c5f92018-09-19 09:35:04 +0000463 // make sure MACRO is not included in preamble.
464 #define MACRO 10
Sam McCall545a20d2018-01-19 14:34:02 +0000465 int X = ^
466 )cpp",
467 {func("indexFunction"), var("indexVariable"), cls("indexClass")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000468 EXPECT_THAT(Results.Completions,
Sam McCall545a20d2018-01-19 14:34:02 +0000469 AllOf(Has("function", CompletionItemKind::Function),
470 Has("variable", CompletionItemKind::Variable),
471 Has("int", CompletionItemKind::Keyword),
Haojian Wu5dc23142020-02-14 14:55:51 +0100472 Has("Struct", CompletionItemKind::Struct),
Sam McCall545a20d2018-01-19 14:34:02 +0000473 Has("MACRO", CompletionItemKind::Text),
474 Has("indexFunction", CompletionItemKind::Function),
475 Has("indexVariable", CompletionItemKind::Variable),
476 Has("indexClass", CompletionItemKind::Class)));
Sam McCall44fdcec22017-12-08 15:00:59 +0000477
Sam McCall44fdcec22017-12-08 15:00:59 +0000478 Results = completions("nam^");
Sam McCalle746a2b2018-07-02 11:13:16 +0000479 EXPECT_THAT(Results.Completions,
480 Has("namespace", CompletionItemKind::Snippet));
Ilya Biryukovbf559a72019-05-29 10:11:14 +0000481
482 // Members of anonymous unions are of kind 'field'.
483 Results = completions(
484 R"cpp(
485 struct X{
486 union {
487 void *a;
488 };
489 };
490 auto u = X().^
491 )cpp");
492 EXPECT_THAT(
493 Results.Completions,
494 UnorderedElementsAre(AllOf(Named("a"), Kind(CompletionItemKind::Field))));
Ilya Biryukovf6faa382019-05-29 17:49:30 +0000495
496 // Completion kinds for templates should not be unknown.
497 Results = completions(
498 R"cpp(
499 template <class T> struct complete_class {};
500 template <class T> void complete_function();
501 template <class T> using complete_type_alias = int;
502 template <class T> int complete_variable = 10;
503
504 struct X {
505 template <class T> static int complete_static_member = 10;
506
507 static auto x = complete_^
508 }
509 )cpp");
510 EXPECT_THAT(
511 Results.Completions,
512 UnorderedElementsAre(
513 AllOf(Named("complete_class"), Kind(CompletionItemKind::Class)),
514 AllOf(Named("complete_function"), Kind(CompletionItemKind::Function)),
515 AllOf(Named("complete_type_alias"),
516 Kind(CompletionItemKind::Interface)),
517 AllOf(Named("complete_variable"), Kind(CompletionItemKind::Variable)),
518 AllOf(Named("complete_static_member"),
519 Kind(CompletionItemKind::Property))));
Haojian Wu5dc23142020-02-14 14:55:51 +0100520
521 Results = completions(
522 R"cpp(
523 enum Color {
524 Red
525 };
526 Color u = ^
527 )cpp");
528 EXPECT_THAT(Results.Completions,
529 Contains(
530 AllOf(Named("Red"), Kind(CompletionItemKind::EnumMember))));
Sam McCall44fdcec22017-12-08 15:00:59 +0000531}
532
Sam McCall84652cc2018-01-12 16:16:09 +0000533TEST(CompletionTest, NoDuplicates) {
Sam McCall545a20d2018-01-19 14:34:02 +0000534 auto Results = completions(
535 R"cpp(
536 class Adapter {
Sam McCall545a20d2018-01-19 14:34:02 +0000537 };
Sam McCall84652cc2018-01-12 16:16:09 +0000538
Eric Liu9b3cba72018-05-30 09:03:39 +0000539 void f() {
Sam McCall545a20d2018-01-19 14:34:02 +0000540 Adapter^
541 }
542 )cpp",
543 {cls("Adapter")});
Sam McCall84652cc2018-01-12 16:16:09 +0000544
545 // Make sure there are no duplicate entries of 'Adapter'.
Sam McCalle746a2b2018-07-02 11:13:16 +0000546 EXPECT_THAT(Results.Completions, ElementsAre(Named("Adapter")));
Sam McCall84652cc2018-01-12 16:16:09 +0000547}
548
Sam McCall545a20d2018-01-19 14:34:02 +0000549TEST(CompletionTest, ScopedNoIndex) {
550 auto Results = completions(
551 R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000552 namespace fake { int BigBang, Babble, Box; };
553 int main() { fake::ba^ }
Sam McCall545a20d2018-01-19 14:34:02 +0000554 ")cpp");
Sam McCall8b2dcc12018-06-14 13:50:30 +0000555 // Babble is a better match than BigBang. Box doesn't match at all.
Sam McCalle746a2b2018-07-02 11:13:16 +0000556 EXPECT_THAT(Results.Completions,
557 ElementsAre(Named("Babble"), Named("BigBang")));
Sam McCall84652cc2018-01-12 16:16:09 +0000558}
559
Sam McCall545a20d2018-01-19 14:34:02 +0000560TEST(CompletionTest, Scoped) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000561 auto Results = completions(
562 R"cpp(
Sam McCall8b2dcc12018-06-14 13:50:30 +0000563 namespace fake { int Babble, Box; };
564 int main() { fake::ba^ }
Sam McCall545a20d2018-01-19 14:34:02 +0000565 ")cpp",
566 {var("fake::BigBang")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000567 EXPECT_THAT(Results.Completions,
568 ElementsAre(Named("Babble"), Named("BigBang")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000569}
570
Sam McCall545a20d2018-01-19 14:34:02 +0000571TEST(CompletionTest, ScopedWithFilter) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000572 auto Results = completions(
573 R"cpp(
574 void f() { ns::x^ }
575 )cpp",
576 {cls("ns::XYZ"), func("ns::foo")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000577 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("XYZ")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000578}
579
Sam McCalldc8abc42018-05-03 14:53:02 +0000580TEST(CompletionTest, ReferencesAffectRanking) {
Eric Liu84bd5db2018-07-25 11:26:35 +0000581 auto Results = completions("int main() { abs^ }", {ns("absl"), func("absb")});
Ilya Biryukov22fa4652019-01-03 13:28:05 +0000582 EXPECT_THAT(Results.Completions,
583 HasSubsequence(Named("absb"), Named("absl")));
Sam McCalldc8abc42018-05-03 14:53:02 +0000584 Results = completions("int main() { abs^ }",
Eric Liu84bd5db2018-07-25 11:26:35 +0000585 {withReferences(10000, ns("absl")), func("absb")});
586 EXPECT_THAT(Results.Completions,
587 HasSubsequence(Named("absl"), Named("absb")));
Sam McCalldc8abc42018-05-03 14:53:02 +0000588}
589
Sam McCall9fb22b22019-05-06 10:25:10 +0000590TEST(CompletionTest, ContextWords) {
591 auto Results = completions(R"cpp(
592 enum class Color { RED, YELLOW, BLUE };
593
594 // (blank lines so the definition above isn't "context")
595
596 // "It was a yellow car," he said. "Big yellow car, new."
597 auto Finish = Color::^
598 )cpp");
599 // Yellow would normally sort last (alphabetic).
600 // But the recent mention shuold bump it up.
601 ASSERT_THAT(Results.Completions,
602 HasSubsequence(Named("YELLOW"), Named("BLUE")));
603}
604
Sam McCall545a20d2018-01-19 14:34:02 +0000605TEST(CompletionTest, GlobalQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000606 auto Results = completions(
607 R"cpp(
608 void f() { ::^ }
609 )cpp",
610 {cls("XYZ")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000611 EXPECT_THAT(Results.Completions,
612 AllOf(Has("XYZ", CompletionItemKind::Class),
613 Has("f", CompletionItemKind::Function)));
Sam McCalla15c2d62018-01-18 09:27:56 +0000614}
615
Sam McCall545a20d2018-01-19 14:34:02 +0000616TEST(CompletionTest, FullyQualified) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000617 auto Results = completions(
618 R"cpp(
Sam McCall545a20d2018-01-19 14:34:02 +0000619 namespace ns { void bar(); }
Sam McCalla15c2d62018-01-18 09:27:56 +0000620 void f() { ::ns::^ }
621 )cpp",
622 {cls("ns::XYZ")});
Sam McCalle746a2b2018-07-02 11:13:16 +0000623 EXPECT_THAT(Results.Completions,
624 AllOf(Has("XYZ", CompletionItemKind::Class),
625 Has("bar", CompletionItemKind::Function)));
Sam McCall545a20d2018-01-19 14:34:02 +0000626}
627
628TEST(CompletionTest, SemaIndexMerge) {
629 auto Results = completions(
630 R"cpp(
631 namespace ns { int local; void both(); }
632 void f() { ::ns::^ }
633 )cpp",
634 {func("ns::both"), cls("ns::Index")});
635 // We get results from both index and sema, with no duplicates.
Sam McCall2161ec72018-07-05 06:20:41 +0000636 EXPECT_THAT(Results.Completions,
637 UnorderedElementsAre(
638 AllOf(Named("local"), Origin(SymbolOrigin::AST)),
639 AllOf(Named("Index"), Origin(SymbolOrigin::Static)),
640 AllOf(Named("both"),
641 Origin(SymbolOrigin::AST | SymbolOrigin::Static))));
Sam McCalla15c2d62018-01-18 09:27:56 +0000642}
643
Haojian Wu48b48652018-01-25 09:20:09 +0000644TEST(CompletionTest, SemaIndexMergeWithLimit) {
645 clangd::CodeCompleteOptions Opts;
646 Opts.Limit = 1;
647 auto Results = completions(
648 R"cpp(
649 namespace ns { int local; void both(); }
650 void f() { ::ns::^ }
651 )cpp",
652 {func("ns::both"), cls("ns::Index")}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000653 EXPECT_EQ(Results.Completions.size(), Opts.Limit);
654 EXPECT_TRUE(Results.HasMore);
Haojian Wu48b48652018-01-25 09:20:09 +0000655}
656
Eric Liu63f419a2018-05-15 15:29:32 +0000657TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {
Sam McCall2dee4d42020-03-31 23:09:28 +0200658 TestTU TU;
659 TU.ExtraArgs.push_back("-I" + testPath("sub"));
660 TU.AdditionalFiles["sub/bar.h"] = "";
661 auto BarURI = URI::create(testPath("sub/bar.h")).toString();
Eric Liu63f419a2018-05-15 15:29:32 +0000662
Eric Liu63f419a2018-05-15 15:29:32 +0000663 Symbol Sym = cls("ns::X");
Haojian Wuee54a2b2018-11-14 11:55:45 +0000664 Sym.CanonicalDeclaration.FileURI = BarURI.c_str();
Eric Liu83f63e42018-09-03 10:18:21 +0000665 Sym.IncludeHeaders.emplace_back(BarURI, 1);
Kazuaki Ishizakib7ecf1c2020-01-04 10:28:41 -0500666 // Shoten include path based on search directory and insert.
Sam McCall2dee4d42020-03-31 23:09:28 +0200667 Annotations Test("int main() { ns::^ }");
668 TU.Code = Test.code().str();
669 auto Results = completions(TU, Test.point(), {Sym});
Sam McCalle746a2b2018-07-02 11:13:16 +0000670 EXPECT_THAT(Results.Completions,
671 ElementsAre(AllOf(Named("X"), InsertInclude("\"bar.h\""))));
Sam McCall9b765de2019-04-10 12:15:35 +0000672 // Can be disabled via option.
673 CodeCompleteOptions NoInsertion;
674 NoInsertion.InsertIncludes = CodeCompleteOptions::NeverInsert;
Sam McCall2dee4d42020-03-31 23:09:28 +0200675 Results = completions(TU, Test.point(), {Sym}, NoInsertion);
Sam McCall9b765de2019-04-10 12:15:35 +0000676 EXPECT_THAT(Results.Completions,
677 ElementsAre(AllOf(Named("X"), Not(InsertInclude()))));
Eric Liu63f419a2018-05-15 15:29:32 +0000678 // Duplicate based on inclusions in preamble.
Sam McCall2dee4d42020-03-31 23:09:28 +0200679 Test = Annotations(R"cpp(
Eric Liu63f419a2018-05-15 15:29:32 +0000680 #include "sub/bar.h" // not shortest, so should only match resolved.
681 int main() { ns::^ }
Sam McCall2dee4d42020-03-31 23:09:28 +0200682 )cpp");
683 TU.Code = Test.code().str();
684 Results = completions(TU, Test.point(), {Sym});
Sam McCalle746a2b2018-07-02 11:13:16 +0000685 EXPECT_THAT(Results.Completions, ElementsAre(AllOf(Named("X"), Labeled("X"),
686 Not(InsertInclude()))));
Eric Liu63f419a2018-05-15 15:29:32 +0000687}
688
Eric Liu9b3cba72018-05-30 09:03:39 +0000689TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {
Eric Liu9b3cba72018-05-30 09:03:39 +0000690 Symbol SymX = cls("ns::X");
691 Symbol SymY = cls("ns::Y");
692 std::string BarHeader = testPath("bar.h");
Eric Liuc0ac4bb2018-11-22 15:02:05 +0000693 auto BarURI = URI::create(BarHeader).toString();
Haojian Wuee54a2b2018-11-14 11:55:45 +0000694 SymX.CanonicalDeclaration.FileURI = BarURI.c_str();
695 SymY.CanonicalDeclaration.FileURI = BarURI.c_str();
Eric Liu83f63e42018-09-03 10:18:21 +0000696 SymX.IncludeHeaders.emplace_back("<bar>", 1);
697 SymY.IncludeHeaders.emplace_back("<bar>", 1);
Kazuaki Ishizakib7ecf1c2020-01-04 10:28:41 -0500698 // Shoten include path based on search directory and insert.
Sam McCall2dee4d42020-03-31 23:09:28 +0200699 auto Results = completions(R"cpp(
Eric Liu9b3cba72018-05-30 09:03:39 +0000700 namespace ns {
701 class X;
Haojian Wu744eb3c2018-12-21 09:32:49 +0000702 class Y {};
Eric Liu9b3cba72018-05-30 09:03:39 +0000703 }
704 int main() { ns::^ }
705 )cpp",
706 {SymX, SymY});
Sam McCalle746a2b2018-07-02 11:13:16 +0000707 EXPECT_THAT(Results.Completions,
708 ElementsAre(AllOf(Named("X"), Not(InsertInclude())),
709 AllOf(Named("Y"), Not(InsertInclude()))));
Eric Liu9b3cba72018-05-30 09:03:39 +0000710}
711
Sam McCalla15c2d62018-01-18 09:27:56 +0000712TEST(CompletionTest, IndexSuppressesPreambleCompletions) {
Sam McCalla15c2d62018-01-18 09:27:56 +0000713 Annotations Test(R"cpp(
714 #include "bar.h"
715 namespace ns { int local; }
Sam McCalld5ea3e32018-01-24 17:53:32 +0000716 void f() { ns::^; }
Haojian Wu744eb3c2018-12-21 09:32:49 +0000717 void f2() { ns::preamble().$2^; }
Sam McCalla15c2d62018-01-18 09:27:56 +0000718 )cpp");
Sam McCall2dee4d42020-03-31 23:09:28 +0200719 auto TU = TestTU::withCode(Test.code());
720 TU.AdditionalFiles["bar.h"] =
721 R"cpp(namespace ns { struct preamble { int member; }; })cpp";
Sam McCalla15c2d62018-01-18 09:27:56 +0000722
Sam McCall2dee4d42020-03-31 23:09:28 +0200723 clangd::CodeCompleteOptions Opts = {};
Sam McCalla15c2d62018-01-18 09:27:56 +0000724 auto I = memIndex({var("ns::index")});
725 Opts.Index = I.get();
Sam McCall2dee4d42020-03-31 23:09:28 +0200726 auto WithIndex = completions(TU, Test.point(), {}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000727 EXPECT_THAT(WithIndex.Completions,
Sam McCalla15c2d62018-01-18 09:27:56 +0000728 UnorderedElementsAre(Named("local"), Named("index")));
Sam McCall2dee4d42020-03-31 23:09:28 +0200729 auto ClassFromPreamble = completions(TU, Test.point("2"), {}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000730 EXPECT_THAT(ClassFromPreamble.Completions, Contains(Named("member")));
Sam McCall0bb24cd2018-02-13 08:59:23 +0000731
732 Opts.Index = nullptr;
Sam McCall2dee4d42020-03-31 23:09:28 +0200733 auto WithoutIndex = completions(TU, Test.point(), {}, Opts);
Sam McCalle746a2b2018-07-02 11:13:16 +0000734 EXPECT_THAT(WithoutIndex.Completions,
Sam McCall0bb24cd2018-02-13 08:59:23 +0000735 UnorderedElementsAre(Named("local"), Named("preamble")));
Sam McCalla15c2d62018-01-18 09:27:56 +0000736}
737
Sam McCallebef8122018-09-14 12:36:06 +0000738// This verifies that we get normal preprocessor completions in the preamble.
739// This is a regression test for an old bug: if we override the preamble and
740// try to complete inside it, clang kicks our completion point just outside the
741// preamble, resulting in always getting top-level completions.
742TEST(CompletionTest, CompletionInPreamble) {
Sam McCall0be9c4e2018-09-14 18:49:16 +0000743 auto Results = completions(R"cpp(
Sam McCallebef8122018-09-14 12:36:06 +0000744 #ifnd^ef FOO_H_
745 #define BAR_H_
746 #include <bar.h>
747 int foo() {}
748 #endif
749 )cpp")
Sam McCall0be9c4e2018-09-14 18:49:16 +0000750 .Completions;
751 EXPECT_THAT(Results, ElementsAre(Named("ifndef")));
Jonas Tothad515192018-09-14 19:42:37 +0000752}
Sam McCallebef8122018-09-14 12:36:06 +0000753
Kadir Cetinkayac3dcd262019-02-04 16:19:57 +0000754TEST(CompletionTest, DynamicIndexIncludeInsertion) {
755 MockFSProvider FS;
756 MockCompilationDatabase CDB;
Kadir Cetinkayac3dcd262019-02-04 16:19:57 +0000757 ClangdServer::Options Opts = ClangdServer::optsForTest();
758 Opts.BuildDynamicSymbolIndex = true;
Sam McCall6ef1cce2020-01-24 14:08:56 +0100759 ClangdServer Server(CDB, FS, Opts);
Kadir Cetinkayac3dcd262019-02-04 16:19:57 +0000760
761 FS.Files[testPath("foo_header.h")] = R"cpp(
Sam McCall62e24722019-04-17 10:36:02 +0000762 #pragma once
Kadir Cetinkayac3dcd262019-02-04 16:19:57 +0000763 struct Foo {
764 // Member doc
765 int foo();
766 };
767 )cpp";
768 const std::string FileContent(R"cpp(
769 #include "foo_header.h"
770 int Foo::foo() {
771 return 42;
772 }
773 )cpp");
774 Server.addDocument(testPath("foo_impl.cpp"), FileContent);
775 // Wait for the dynamic index being built.
776 ASSERT_TRUE(Server.blockUntilIdleForTest());
Sam McCall2dee4d42020-03-31 23:09:28 +0200777
778 auto File = testPath("foo.cpp");
779 Annotations Test("Foo^ foo;");
780 runAddDocument(Server, File, Test.code());
781 auto CompletionList =
782 llvm::cantFail(runCodeComplete(Server, File, Test.point(), {}));
783
784 EXPECT_THAT(CompletionList.Completions,
Kadir Cetinkaya1f6d9842019-07-03 07:47:19 +0000785 ElementsAre(AllOf(Named("Foo"), HasInclude("\"foo_header.h\""),
Kadir Cetinkaya3ba9a432019-04-24 09:42:53 +0000786 InsertInclude())));
Kadir Cetinkayac3dcd262019-02-04 16:19:57 +0000787}
788
Sam McCalla15c2d62018-01-18 09:27:56 +0000789TEST(CompletionTest, DynamicIndexMultiFile) {
790 MockFSProvider FS;
791 MockCompilationDatabase CDB;
Sam McCall7363a2f2018-03-05 17:28:54 +0000792 auto Opts = ClangdServer::optsForTest();
793 Opts.BuildDynamicSymbolIndex = true;
Sam McCall6ef1cce2020-01-24 14:08:56 +0100794 ClangdServer Server(CDB, FS, Opts);
Sam McCalla15c2d62018-01-18 09:27:56 +0000795
Eric Liu709bde82018-02-19 18:48:44 +0000796 FS.Files[testPath("foo.h")] = R"cpp(
Sam McCalla15c2d62018-01-18 09:27:56 +0000797 namespace ns { class XYZ {}; void foo(int x) {} }
Eric Liu709bde82018-02-19 18:48:44 +0000798 )cpp";
Sam McCall7363a2f2018-03-05 17:28:54 +0000799 runAddDocument(Server, testPath("foo.cpp"), R"cpp(
Eric Liu709bde82018-02-19 18:48:44 +0000800 #include "foo.h"
Sam McCall0bb24cd2018-02-13 08:59:23 +0000801 )cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000802
Sam McCallc1568062018-02-16 09:41:43 +0000803 auto File = testPath("bar.cpp");
Sam McCalla15c2d62018-01-18 09:27:56 +0000804 Annotations Test(R"cpp(
805 namespace ns {
806 class XXX {};
807 /// Doooc
808 void fooooo() {}
809 }
810 void f() { ns::^ }
811 )cpp");
Sam McCall7363a2f2018-03-05 17:28:54 +0000812 runAddDocument(Server, File, Test.code());
Sam McCalla15c2d62018-01-18 09:27:56 +0000813
Sam McCalla7bb0cc2018-03-12 23:22:35 +0000814 auto Results = cantFail(runCodeComplete(Server, File, Test.point(), {}));
Sam McCalla15c2d62018-01-18 09:27:56 +0000815 // "XYZ" and "foo" are not included in the file being completed but are still
816 // visible through the index.
Sam McCalle746a2b2018-07-02 11:13:16 +0000817 EXPECT_THAT(Results.Completions, Has("XYZ", CompletionItemKind::Class));
818 EXPECT_THAT(Results.Completions, Has("foo", CompletionItemKind::Function));
819 EXPECT_THAT(Results.Completions, Has("XXX", CompletionItemKind::Class));
820 EXPECT_THAT(Results.Completions,
821 Contains((Named("fooooo"), Kind(CompletionItemKind::Function),
822 Doc("Doooc"), ReturnType("void"))));
Sam McCalla15c2d62018-01-18 09:27:56 +0000823}
824
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000825TEST(CompletionTest, Documentation) {
826 auto Results = completions(
827 R"cpp(
828 // Non-doxygen comment.
829 int foo();
830 /// Doxygen comment.
831 /// \param int a
832 int bar(int a);
833 /* Multi-line
834 block comment
835 */
836 int baz();
837
838 int x = ^
839 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000840 EXPECT_THAT(Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000841 Contains(AllOf(Named("foo"), Doc("Non-doxygen comment."))));
842 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +0000843 Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000844 Contains(AllOf(Named("bar"), Doc("Doxygen comment.\n\\param int a"))));
Sam McCalle746a2b2018-07-02 11:13:16 +0000845 EXPECT_THAT(Results.Completions,
Ilya Biryukovc22d3442018-05-16 12:32:49 +0000846 Contains(AllOf(Named("baz"), Doc("Multi-line\nblock comment"))));
847}
848
Ilya Biryukovdec8d8d2019-11-07 09:59:36 +0100849TEST(CompletionTest, CommentsFromSystemHeaders) {
850 MockFSProvider FS;
851 MockCompilationDatabase CDB;
Ilya Biryukovdec8d8d2019-11-07 09:59:36 +0100852
853 auto Opts = ClangdServer::optsForTest();
854 Opts.BuildDynamicSymbolIndex = true;
855
Sam McCall6ef1cce2020-01-24 14:08:56 +0100856 ClangdServer Server(CDB, FS, Opts);
Ilya Biryukovdec8d8d2019-11-07 09:59:36 +0100857
858 FS.Files[testPath("foo.h")] = R"cpp(
859 #pragma GCC system_header
860
861 // This comment should be retained!
862 int foo();
863 )cpp";
864
Sam McCall2dee4d42020-03-31 23:09:28 +0200865 auto File = testPath("foo.cpp");
866 Annotations Test(R"cpp(
Ilya Biryukovdec8d8d2019-11-07 09:59:36 +0100867#include "foo.h"
868int x = foo^
869 )cpp");
Sam McCall2dee4d42020-03-31 23:09:28 +0200870 runAddDocument(Server, File, Test.code());
871 auto CompletionList =
872 llvm::cantFail(runCodeComplete(Server, File, Test.point(), {}));
873
Ilya Biryukovdec8d8d2019-11-07 09:59:36 +0100874 EXPECT_THAT(
Sam McCall2dee4d42020-03-31 23:09:28 +0200875 CompletionList.Completions,
Ilya Biryukovdec8d8d2019-11-07 09:59:36 +0100876 Contains(AllOf(Named("foo"), Doc("This comment should be retained!"))));
877}
878
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000879TEST(CompletionTest, GlobalCompletionFiltering) {
880
881 Symbol Class = cls("XYZ");
Eric Liu6df66002018-09-06 18:52:26 +0000882 Class.Flags = static_cast<Symbol::SymbolFlag>(
883 Class.Flags & ~(Symbol::IndexedForCodeCompletion));
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000884 Symbol Func = func("XYZ::foooo");
Eric Liu6df66002018-09-06 18:52:26 +0000885 Func.Flags = static_cast<Symbol::SymbolFlag>(
886 Func.Flags & ~(Symbol::IndexedForCodeCompletion));
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000887
888 auto Results = completions(R"(// void f() {
889 XYZ::foooo^
890 })",
891 {Class, Func});
Sam McCalle746a2b2018-07-02 11:13:16 +0000892 EXPECT_THAT(Results.Completions, IsEmpty());
Marc-Andre Laperle945b5a32018-06-05 14:01:40 +0000893}
894
Haojian Wu58d208d2018-01-25 09:44:06 +0000895TEST(CodeCompleteTest, DisableTypoCorrection) {
896 auto Results = completions(R"cpp(
897 namespace clang { int v; }
898 void f() { clangd::^
899 )cpp");
Sam McCalle746a2b2018-07-02 11:13:16 +0000900 EXPECT_TRUE(Results.Completions.empty());
Haojian Wu58d208d2018-01-25 09:44:06 +0000901}
902
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000903TEST(CodeCompleteTest, NoColonColonAtTheEnd) {
904 auto Results = completions(R"cpp(
905 namespace clang { }
906 void f() {
907 clan^
908 }
909 )cpp");
910
Sam McCalle746a2b2018-07-02 11:13:16 +0000911 EXPECT_THAT(Results.Completions, Contains(Labeled("clang")));
912 EXPECT_THAT(Results.Completions, Not(Contains(Labeled("clang::"))));
Ilya Biryukov53d6d932018-03-06 16:45:21 +0000913}
914
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000915TEST(CompletionTest, BacktrackCrashes) {
916 // Sema calls code completion callbacks twice in these cases.
917 auto Results = completions(R"cpp(
918 namespace ns {
919 struct FooBarBaz {};
920 } // namespace ns
921
922 int foo(ns::FooBar^
923 )cpp");
924
Sam McCalle746a2b2018-07-02 11:13:16 +0000925 EXPECT_THAT(Results.Completions, ElementsAre(Labeled("FooBarBaz")));
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000926
927 // Check we don't crash in that case too.
928 completions(R"cpp(
929 struct FooBarBaz {};
930 void test() {
931 if (FooBarBaz * x^) {}
932 }
933)cpp");
934}
935
Eric Liu42abe412018-05-24 11:20:19 +0000936TEST(CompletionTest, CompleteInMacroWithStringification) {
937 auto Results = completions(R"cpp(
938void f(const char *, int x);
939#define F(x) f(#x, x)
940
941namespace ns {
942int X;
943int Y;
944} // namespace ns
945
946int f(int input_num) {
947 F(ns::^)
948}
949)cpp");
950
Sam McCalle746a2b2018-07-02 11:13:16 +0000951 EXPECT_THAT(Results.Completions,
Eric Liu42abe412018-05-24 11:20:19 +0000952 UnorderedElementsAre(Named("X"), Named("Y")));
953}
954
955TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {
956 auto Results = completions(R"cpp(
957void f(const char *, int x);
958#define F(x) f(#x, x)
959
960namespace ns {
961int X;
962
963int f(int input_num) {
964 F(^)
965}
966} // namespace ns
967)cpp");
968
Sam McCalle746a2b2018-07-02 11:13:16 +0000969 EXPECT_THAT(Results.Completions, Contains(Named("X")));
Eric Liu42abe412018-05-24 11:20:19 +0000970}
971
Eric Liu485074f2018-07-11 13:15:31 +0000972TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000973 auto Results = completions(R"cpp(
974 int bar(int param_in_bar) {
975 }
976
977 int foo(int param_in_foo) {
978#if 0
Eric Liu485074f2018-07-11 13:15:31 +0000979 // In recorvery mode, "param_in_foo" will also be suggested among many other
980 // unrelated symbols; however, this is really a special case where this works.
981 // If the #if block is outside of the function, "param_in_foo" is still
982 // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't
983 // really provide useful results in excluded branches.
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000984 par^
985#endif
986 }
987)cpp");
988
Eric Liu485074f2018-07-11 13:15:31 +0000989 EXPECT_TRUE(Results.Completions.empty());
Ilya Biryukov94da7bd2018-03-16 15:23:44 +0000990}
Sam McCall0e8dd4a2019-08-07 16:52:21 +0000991
992TEST(CompletionTest, DefaultArgs) {
993 clangd::CodeCompleteOptions Opts;
994 std::string Context = R"cpp(
995 int X(int A = 0);
996 int Y(int A, int B = 0);
997 int Z(int A, int B = 0, int C = 0, int D = 0);
998 )cpp";
999 EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions,
1000 UnorderedElementsAre(Labeled("X(int A = 0)")));
1001 EXPECT_THAT(completions(Context + "int y = Y^", {}, Opts).Completions,
1002 UnorderedElementsAre(AllOf(Labeled("Y(int A, int B = 0)"),
1003 SnippetSuffix("(${1:int A})"))));
1004 EXPECT_THAT(completions(Context + "int y = Z^", {}, Opts).Completions,
1005 UnorderedElementsAre(
1006 AllOf(Labeled("Z(int A, int B = 0, int C = 0, int D = 0)"),
1007 SnippetSuffix("(${1:int A})"))));
1008}
1009
Ilya Biryukov339502c2019-11-20 15:51:18 +01001010TEST(CompletionTest, NoCrashWithTemplateParamsAndPreferredTypes) {
1011 auto Completions = completions(R"cpp(
1012template <template <class> class TT> int foo() {
1013 int a = ^
1014}
1015)cpp")
1016 .Completions;
1017 EXPECT_THAT(Completions, Contains(Named("TT")));
1018}
1019
Utkarsh Saxenae397a0a2020-03-04 13:25:02 +01001020TEST(CompletionTest, RecordCCResultCallback) {
1021 std::vector<CodeCompletion> RecordedCompletions;
1022 CodeCompleteOptions Opts;
1023 Opts.RecordCCResult = [&RecordedCompletions](const CodeCompletion &CC,
1024 const SymbolQualitySignals &,
1025 const SymbolRelevanceSignals &,
1026 float Score) {
1027 RecordedCompletions.push_back(CC);
1028 };
1029
1030 completions("int xy1, xy2; int a = xy^", /*IndexSymbols=*/{}, Opts);
1031 EXPECT_THAT(RecordedCompletions,
1032 UnorderedElementsAre(Named("xy1"), Named("xy2")));
1033}
1034
Ilya Biryukovf2001aa2019-01-07 15:45:19 +00001035SignatureHelp signatures(llvm::StringRef Text, Position Point,
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001036 std::vector<Symbol> IndexSymbols = {}) {
1037 std::unique_ptr<SymbolIndex> Index;
1038 if (!IndexSymbols.empty())
1039 Index = memIndex(IndexSymbols);
1040
Sam McCall2dee4d42020-03-31 23:09:28 +02001041 auto TU = TestTU::withCode(Text);
1042 auto Inputs = TU.inputs();
1043 IgnoreDiagnostics Diags;
1044 auto CI = buildCompilerInvocation(Inputs, Diags);
1045 if (!CI) {
1046 ADD_FAILURE() << "Couldn't build CompilerInvocation";
1047 return {};
1048 }
1049 auto Preamble =
1050 buildPreamble(testPath(TU.Filename), *CI, /*OldPreamble=*/nullptr, Inputs,
1051 /*InMemory=*/true, /*Callback=*/nullptr);
Kadir Cetinkaya43aa04e2020-04-01 11:31:53 +02001052 if (!Preamble) {
1053 ADD_FAILURE() << "Couldn't build Preamble";
1054 return {};
1055 }
1056 return signatureHelp(testPath(TU.Filename), Inputs.CompileCommand, *Preamble,
1057 Text, Point, Inputs.FS, Index.get());
Ilya Biryukov43c292c2018-08-30 13:14:31 +00001058}
1059
Ilya Biryukovf2001aa2019-01-07 15:45:19 +00001060SignatureHelp signatures(llvm::StringRef Text,
Ilya Biryukov43c292c2018-08-30 13:14:31 +00001061 std::vector<Symbol> IndexSymbols = {}) {
Sam McCall328cbdb2017-12-20 16:06:05 +00001062 Annotations Test(Text);
Ilya Biryukov43c292c2018-08-30 13:14:31 +00001063 return signatures(Test.code(), Test.point(), std::move(IndexSymbols));
Sam McCall800d4372017-12-19 10:29:27 +00001064}
1065
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001066struct ExpectedParameter {
1067 std::string Text;
1068 std::pair<unsigned, unsigned> Offsets;
1069};
Sam McCall800d4372017-12-19 10:29:27 +00001070MATCHER_P(ParamsAre, P, "") {
1071 if (P.size() != arg.parameters.size())
1072 return false;
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001073 for (unsigned I = 0; I < P.size(); ++I) {
1074 if (P[I].Text != arg.parameters[I].labelString ||
1075 P[I].Offsets != arg.parameters[I].labelOffsets)
Sam McCall800d4372017-12-19 10:29:27 +00001076 return false;
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001077 }
Sam McCall800d4372017-12-19 10:29:27 +00001078 return true;
1079}
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001080MATCHER_P(SigDoc, Doc, "") { return arg.documentation == Doc; }
Sam McCall800d4372017-12-19 10:29:27 +00001081
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001082/// \p AnnotatedLabel is a signature label with ranges marking parameters, e.g.
1083/// foo([[int p1]], [[double p2]]) -> void
1084Matcher<SignatureInformation> Sig(llvm::StringRef AnnotatedLabel) {
1085 llvm::Annotations A(AnnotatedLabel);
Benjamin Krameradcd0262020-01-28 20:23:46 +01001086 std::string Label = std::string(A.code());
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001087 std::vector<ExpectedParameter> Parameters;
1088 for (auto Range : A.ranges()) {
1089 Parameters.emplace_back();
1090
1091 ExpectedParameter &P = Parameters.back();
1092 P.Text = Label.substr(Range.Begin, Range.End - Range.Begin);
1093 P.Offsets.first = lspLength(llvm::StringRef(Label).substr(0, Range.Begin));
1094 P.Offsets.second = lspLength(llvm::StringRef(Label).substr(1, Range.End));
1095 }
1096 return AllOf(SigHelpLabeled(Label), ParamsAre(Parameters));
Sam McCall800d4372017-12-19 10:29:27 +00001097}
1098
1099TEST(SignatureHelpTest, Overloads) {
1100 auto Results = signatures(R"cpp(
1101 void foo(int x, int y);
1102 void foo(int x, float y);
1103 void foo(float x, int y);
1104 void foo(float x, float y);
1105 void bar(int x, int y = 0);
1106 int main() { foo(^); }
1107 )cpp");
1108 EXPECT_THAT(Results.signatures,
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001109 UnorderedElementsAre(Sig("foo([[float x]], [[float y]]) -> void"),
1110 Sig("foo([[float x]], [[int y]]) -> void"),
1111 Sig("foo([[int x]], [[float y]]) -> void"),
1112 Sig("foo([[int x]], [[int y]]) -> void")));
Sam McCall800d4372017-12-19 10:29:27 +00001113 // We always prefer the first signature.
1114 EXPECT_EQ(0, Results.activeSignature);
1115 EXPECT_EQ(0, Results.activeParameter);
1116}
1117
1118TEST(SignatureHelpTest, DefaultArgs) {
1119 auto Results = signatures(R"cpp(
1120 void bar(int x, int y = 0);
1121 void bar(float x = 0, int y = 42);
1122 int main() { bar(^
1123 )cpp");
1124 EXPECT_THAT(Results.signatures,
1125 UnorderedElementsAre(
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001126 Sig("bar([[int x]], [[int y = 0]]) -> void"),
1127 Sig("bar([[float x = 0]], [[int y = 42]]) -> void")));
Sam McCall800d4372017-12-19 10:29:27 +00001128 EXPECT_EQ(0, Results.activeSignature);
1129 EXPECT_EQ(0, Results.activeParameter);
1130}
1131
1132TEST(SignatureHelpTest, ActiveArg) {
1133 auto Results = signatures(R"cpp(
1134 int baz(int a, int b, int c);
1135 int main() { baz(baz(1,2,3), ^); }
1136 )cpp");
1137 EXPECT_THAT(Results.signatures,
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001138 ElementsAre(Sig("baz([[int a]], [[int b]], [[int c]]) -> int")));
Sam McCall800d4372017-12-19 10:29:27 +00001139 EXPECT_EQ(0, Results.activeSignature);
1140 EXPECT_EQ(1, Results.activeParameter);
1141}
1142
Ilya Biryukov43c292c2018-08-30 13:14:31 +00001143TEST(SignatureHelpTest, OpeningParen) {
1144 llvm::StringLiteral Tests[] = {// Recursive function call.
1145 R"cpp(
1146 int foo(int a, int b, int c);
1147 int main() {
1148 foo(foo $p^( foo(10, 10, 10), ^ )));
1149 })cpp",
1150 // Functional type cast.
1151 R"cpp(
1152 struct Foo {
1153 Foo(int a, int b, int c);
1154 };
1155 int main() {
1156 Foo $p^( 10, ^ );
1157 })cpp",
1158 // New expression.
1159 R"cpp(
1160 struct Foo {
1161 Foo(int a, int b, int c);
1162 };
1163 int main() {
1164 new Foo $p^( 10, ^ );
1165 })cpp",
1166 // Macro expansion.
1167 R"cpp(
1168 int foo(int a, int b, int c);
1169 #define FOO foo(
1170
1171 int main() {
1172 // Macro expansions.
1173 $p^FOO 10, ^ );
1174 })cpp",
1175 // Macro arguments.
1176 R"cpp(
1177 int foo(int a, int b, int c);
1178 int main() {
1179 #define ID(X) X
Haojian Wu62dea6e2020-03-26 16:07:50 +01001180 ID(foo $p^( foo(10), ^ ))
Ilya Biryukov43c292c2018-08-30 13:14:31 +00001181 })cpp"};
1182
1183 for (auto Test : Tests) {
1184 Annotations Code(Test);
1185 EXPECT_EQ(signatures(Code.code(), Code.point()).argListStart,
1186 Code.point("p"))
1187 << "Test source:" << Test;
1188 }
1189}
1190
Haojian Wu061c73e2018-01-23 11:37:26 +00001191class IndexRequestCollector : public SymbolIndex {
1192public:
Ilya Biryukovf2001aa2019-01-07 15:45:19 +00001193 bool
1194 fuzzyFind(const FuzzyFindRequest &Req,
1195 llvm::function_ref<void(const Symbol &)> Callback) const override {
Kadir Cetinkayade859972019-10-07 17:12:18 +00001196 std::unique_lock<std::mutex> Lock(Mut);
Haojian Wu061c73e2018-01-23 11:37:26 +00001197 Requests.push_back(Req);
Kadir Cetinkayade859972019-10-07 17:12:18 +00001198 ReceivedRequestCV.notify_one();
Sam McCallab8e3932018-02-19 13:04:41 +00001199 return true;
Haojian Wu061c73e2018-01-23 11:37:26 +00001200 }
1201
Eric Liu9ec459f2018-03-14 09:48:05 +00001202 void lookup(const LookupRequest &,
Ilya Biryukovf2001aa2019-01-07 15:45:19 +00001203 llvm::function_ref<void(const Symbol &)>) const override {}
Eric Liu9ec459f2018-03-14 09:48:05 +00001204
Haojian Wu33e882d2019-11-13 14:42:26 +01001205 bool refs(const RefsRequest &,
1206 llvm::function_ref<void(const Ref &)>) const override {
1207 return false;
1208 }
Haojian Wu65ac3212018-08-06 13:14:32 +00001209
Nathan Ridgef1e6f572019-06-15 02:26:47 +00001210 void relations(const RelationsRequest &,
1211 llvm::function_ref<void(const SymbolID &, const Symbol &)>)
1212 const override {}
1213
Kirill Bobyrevfc890012018-08-24 09:12:54 +00001214 // This is incorrect, but IndexRequestCollector is not an actual index and it
1215 // isn't used in production code.
1216 size_t estimateMemoryUsage() const override { return 0; }
1217
Kadir Cetinkayade859972019-10-07 17:12:18 +00001218 const std::vector<FuzzyFindRequest> consumeRequests(size_t Num) const {
1219 std::unique_lock<std::mutex> Lock(Mut);
Kadir Cetinkaya3c464612019-10-08 13:54:03 +00001220 EXPECT_TRUE(wait(Lock, ReceivedRequestCV, timeoutSeconds(30),
Kadir Cetinkayade859972019-10-07 17:12:18 +00001221 [this, Num] { return Requests.size() == Num; }));
Eric Liu25d74e92018-08-24 11:23:56 +00001222 auto Reqs = std::move(Requests);
1223 Requests = {};
1224 return Reqs;
1225 }
Haojian Wu061c73e2018-01-23 11:37:26 +00001226
1227private:
Ilya Biryukov5c4d6e62018-09-06 11:04:56 +00001228 // We need a mutex to handle async fuzzy find requests.
Kadir Cetinkayade859972019-10-07 17:12:18 +00001229 mutable std::condition_variable ReceivedRequestCV;
Ilya Biryukov5c4d6e62018-09-06 11:04:56 +00001230 mutable std::mutex Mut;
Haojian Wu061c73e2018-01-23 11:37:26 +00001231 mutable std::vector<FuzzyFindRequest> Requests;
1232};
1233
Kadir Cetinkayade859972019-10-07 17:12:18 +00001234// Clients have to consume exactly Num requests.
1235std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code,
1236 size_t Num = 1) {
Haojian Wu061c73e2018-01-23 11:37:26 +00001237 clangd::CodeCompleteOptions Opts;
1238 IndexRequestCollector Requests;
1239 Opts.Index = &Requests;
1240 completions(Code, {}, Opts);
Kadir Cetinkayade859972019-10-07 17:12:18 +00001241 const auto Reqs = Requests.consumeRequests(Num);
1242 EXPECT_EQ(Reqs.size(), Num);
1243 return Reqs;
Haojian Wu061c73e2018-01-23 11:37:26 +00001244}
1245
1246TEST(CompletionTest, UnqualifiedIdQuery) {
1247 auto Requests = captureIndexRequests(R"cpp(
1248 namespace std {}
1249 using namespace std;
1250 namespace ns {
1251 void f() {
1252 vec^
1253 }
1254 }
1255 )cpp");
1256
1257 EXPECT_THAT(Requests,
1258 ElementsAre(Field(&FuzzyFindRequest::Scopes,
1259 UnorderedElementsAre("", "ns::", "std::"))));
1260}
1261
Eric Liu3fac4ef2018-10-17 11:19:02 +00001262TEST(CompletionTest, EnclosingScopeComesFirst) {
1263 auto Requests = captureIndexRequests(R"cpp(
1264 namespace std {}
1265 using namespace std;
1266 namespace nx {
1267 namespace ns {
1268 namespace {
1269 void f() {
1270 vec^
1271 }
1272 }
1273 }
1274 }
1275 )cpp");
1276
1277 EXPECT_THAT(Requests,
1278 ElementsAre(Field(
1279 &FuzzyFindRequest::Scopes,
1280 UnorderedElementsAre("", "std::", "nx::ns::", "nx::"))));
1281 EXPECT_EQ(Requests[0].Scopes[0], "nx::ns::");
1282}
1283
Haojian Wu061c73e2018-01-23 11:37:26 +00001284TEST(CompletionTest, ResolvedQualifiedIdQuery) {
1285 auto Requests = captureIndexRequests(R"cpp(
1286 namespace ns1 {}
1287 namespace ns2 {} // ignore
1288 namespace ns3 { namespace nns3 {} }
1289 namespace foo {
1290 using namespace ns1;
1291 using namespace ns3::nns3;
1292 }
1293 namespace ns {
1294 void f() {
1295 foo::^
1296 }
1297 }
1298 )cpp");
1299
1300 EXPECT_THAT(Requests,
1301 ElementsAre(Field(
1302 &FuzzyFindRequest::Scopes,
1303 UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::"))));
1304}
1305
1306TEST(CompletionTest, UnresolvedQualifierIdQuery) {
1307 auto Requests = captureIndexRequests(R"cpp(
1308 namespace a {}
1309 using namespace a;
1310 namespace ns {
1311 void f() {
1312 bar::^
1313 }
1314 } // namespace ns
1315 )cpp");
1316
Eric Liue98b86c2019-02-27 11:42:37 +00001317 EXPECT_THAT(Requests,
1318 ElementsAre(Field(
1319 &FuzzyFindRequest::Scopes,
1320 UnorderedElementsAre("a::bar::", "ns::bar::", "bar::"))));
Haojian Wu061c73e2018-01-23 11:37:26 +00001321}
1322
1323TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
1324 auto Requests = captureIndexRequests(R"cpp(
1325 namespace a {}
1326 using namespace a;
1327 namespace ns {
1328 void f() {
1329 ::a::bar::^
1330 }
1331 } // namespace ns
1332 )cpp");
1333
1334 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1335 UnorderedElementsAre("a::bar::"))));
1336}
1337
1338TEST(CompletionTest, EmptyQualifiedQuery) {
1339 auto Requests = captureIndexRequests(R"cpp(
1340 namespace ns {
1341 void f() {
1342 ^
1343 }
1344 } // namespace ns
1345 )cpp");
1346
1347 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1348 UnorderedElementsAre("", "ns::"))));
1349}
1350
1351TEST(CompletionTest, GlobalQualifiedQuery) {
1352 auto Requests = captureIndexRequests(R"cpp(
1353 namespace ns {
1354 void f() {
1355 ::^
1356 }
1357 } // namespace ns
1358 )cpp");
1359
1360 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
1361 UnorderedElementsAre(""))));
1362}
1363
Eric Liuabbd7132018-11-06 11:17:40 +00001364TEST(CompletionTest, NoDuplicatedQueryScopes) {
1365 auto Requests = captureIndexRequests(R"cpp(
1366 namespace {}
1367
1368 namespace na {
1369 namespace {}
1370 namespace nb {
1371 ^
1372 } // namespace nb
1373 } // namespace na
1374 )cpp");
1375
1376 EXPECT_THAT(Requests,
1377 ElementsAre(Field(&FuzzyFindRequest::Scopes,
1378 UnorderedElementsAre("na::", "na::nb::", ""))));
1379}
1380
Ilya Biryukova907ba42018-05-14 10:50:04 +00001381TEST(CompletionTest, NoIndexCompletionsInsideClasses) {
1382 auto Completions = completions(
1383 R"cpp(
1384 struct Foo {
1385 int SomeNameOfField;
1386 typedef int SomeNameOfTypedefField;
1387 };
1388
1389 Foo::^)cpp",
1390 {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")});
1391
Sam McCalle746a2b2018-07-02 11:13:16 +00001392 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001393 AllOf(Contains(Labeled("SomeNameOfField")),
1394 Contains(Labeled("SomeNameOfTypedefField")),
1395 Not(Contains(Labeled("SomeNameInTheIndex")))));
1396}
1397
1398TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {
1399 {
1400 auto Completions = completions(
1401 R"cpp(
1402 template <class T>
1403 void foo() {
1404 T::^
1405 }
1406 )cpp",
1407 {func("::SomeNameInTheIndex")});
1408
Sam McCalle746a2b2018-07-02 11:13:16 +00001409 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001410 Not(Contains(Labeled("SomeNameInTheIndex"))));
1411 }
1412
1413 {
1414 auto Completions = completions(
1415 R"cpp(
1416 template <class T>
1417 void foo() {
1418 T::template Y<int>::^
1419 }
1420 )cpp",
1421 {func("::SomeNameInTheIndex")});
1422
Sam McCalle746a2b2018-07-02 11:13:16 +00001423 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001424 Not(Contains(Labeled("SomeNameInTheIndex"))));
1425 }
1426
1427 {
1428 auto Completions = completions(
1429 R"cpp(
1430 template <class T>
1431 void foo() {
1432 T::foo::^
1433 }
1434 )cpp",
1435 {func("::SomeNameInTheIndex")});
1436
Sam McCalle746a2b2018-07-02 11:13:16 +00001437 EXPECT_THAT(Completions.Completions,
Ilya Biryukova907ba42018-05-14 10:50:04 +00001438 Not(Contains(Labeled("SomeNameInTheIndex"))));
1439 }
1440}
1441
Sam McCallc18c2802018-06-15 11:06:29 +00001442TEST(CompletionTest, OverloadBundling) {
1443 clangd::CodeCompleteOptions Opts;
1444 Opts.BundleOverloads = true;
1445
1446 std::string Context = R"cpp(
1447 struct X {
1448 // Overload with int
1449 int a(int);
1450 // Overload with bool
1451 int a(bool);
1452 int b(float);
1453 };
1454 int GFuncC(int);
1455 int GFuncD(int);
1456 )cpp";
1457
1458 // Member completions are bundled.
Sam McCalle746a2b2018-07-02 11:13:16 +00001459 EXPECT_THAT(completions(Context + "int y = X().^", {}, Opts).Completions,
Sam McCallc18c2802018-06-15 11:06:29 +00001460 UnorderedElementsAre(Labeled("a(…)"), Labeled("b(float)")));
1461
1462 // Non-member completions are bundled, including index+sema.
1463 Symbol NoArgsGFunc = func("GFuncC");
1464 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001465 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
Sam McCallc18c2802018-06-15 11:06:29 +00001466 UnorderedElementsAre(Labeled("GFuncC(…)"), Labeled("GFuncD(int)")));
1467
1468 // Differences in header-to-insert suppress bundling.
Eric Liuc0ac4bb2018-11-22 15:02:05 +00001469 std::string DeclFile = URI::create(testPath("foo")).toString();
Haojian Wuee54a2b2018-11-14 11:55:45 +00001470 NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile.c_str();
Eric Liu83f63e42018-09-03 10:18:21 +00001471 NoArgsGFunc.IncludeHeaders.emplace_back("<foo>", 1);
Sam McCallc18c2802018-06-15 11:06:29 +00001472 EXPECT_THAT(
Sam McCalle746a2b2018-07-02 11:13:16 +00001473 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,
1474 UnorderedElementsAre(AllOf(Named("GFuncC"), InsertInclude("<foo>")),
1475 Labeled("GFuncC(int)"), Labeled("GFuncD(int)")));
Sam McCallc18c2802018-06-15 11:06:29 +00001476
1477 // Examine a bundled completion in detail.
Sam McCalle746a2b2018-07-02 11:13:16 +00001478 auto A =
1479 completions(Context + "int y = X().a^", {}, Opts).Completions.front();
1480 EXPECT_EQ(A.Name, "a");
1481 EXPECT_EQ(A.Signature, "(…)");
1482 EXPECT_EQ(A.BundleSize, 2u);
1483 EXPECT_EQ(A.Kind, CompletionItemKind::Method);
1484 EXPECT_EQ(A.ReturnType, "int"); // All overloads return int.
Sam McCallc18c2802018-06-15 11:06:29 +00001485 // For now we just return one of the doc strings arbitrarily.
Sam McCalle746a2b2018-07-02 11:13:16 +00001486 EXPECT_THAT(A.Documentation, AnyOf(HasSubstr("Overload with int"),
Sam McCallc18c2802018-06-15 11:06:29 +00001487 HasSubstr("Overload with bool")));
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00001488 EXPECT_EQ(A.SnippetSuffix, "($0)");
Sam McCallc18c2802018-06-15 11:06:29 +00001489}
1490
Ilya Biryukov30b04b12018-05-28 09:54:51 +00001491TEST(CompletionTest, DocumentationFromChangedFileCrash) {
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001492 MockFSProvider FS;
1493 auto FooH = testPath("foo.h");
1494 auto FooCpp = testPath("foo.cpp");
1495 FS.Files[FooH] = R"cpp(
1496 // this is my documentation comment.
1497 int func();
1498 )cpp";
1499 FS.Files[FooCpp] = "";
1500
1501 MockCompilationDatabase CDB;
Sam McCall6ef1cce2020-01-24 14:08:56 +01001502 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001503
1504 Annotations Source(R"cpp(
1505 #include "foo.h"
1506 int func() {
1507 // This makes sure we have func from header in the AST.
1508 }
1509 int a = fun^
1510 )cpp");
Sam McCall2cd33e62020-03-04 00:33:29 +01001511 Server.addDocument(FooCpp, Source.code(), "null", WantDiagnostics::Yes);
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001512 // We need to wait for preamble to build.
1513 ASSERT_TRUE(Server.blockUntilIdleForTest());
1514
1515 // Change the header file. Completion will reuse the old preamble!
1516 FS.Files[FooH] = R"cpp(
1517 int func();
1518 )cpp";
1519
1520 clangd::CodeCompleteOptions Opts;
1521 Opts.IncludeComments = true;
Sam McCalle746a2b2018-07-02 11:13:16 +00001522 CodeCompleteResult Completions =
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001523 cantFail(runCodeComplete(Server, FooCpp, Source.point(), Opts));
1524 // We shouldn't crash. Unfortunately, current workaround is to not produce
1525 // comments for symbols from headers.
Sam McCalle746a2b2018-07-02 11:13:16 +00001526 EXPECT_THAT(Completions.Completions,
Ilya Biryukovbe0eb8f2018-05-24 14:49:23 +00001527 Contains(AllOf(Not(IsDocumented()), Named("func"))));
1528}
1529
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001530TEST(CompletionTest, NonDocComments) {
Sam McCall2dee4d42020-03-31 23:09:28 +02001531 const char *Text = R"cpp(
Ilya Biryukovda8dd8b2018-06-27 09:47:20 +00001532 // We ignore namespace comments, for rationale see CodeCompletionStrings.h.
1533 namespace comments_ns {
1534 }
1535
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001536 // ------------------
1537 int comments_foo();
1538
1539 // A comment and a decl are separated by newlines.
1540 // Therefore, the comment shouldn't show up as doc comment.
1541
1542 int comments_bar();
1543
1544 // this comment should be in the results.
1545 int comments_baz();
1546
1547
1548 template <class T>
1549 struct Struct {
1550 int comments_qux();
1551 int comments_quux();
1552 };
1553
1554
1555 // This comment should not be there.
1556
1557 template <class T>
1558 int Struct<T>::comments_qux() {
1559 }
1560
1561 // This comment **should** be in results.
1562 template <class T>
1563 int Struct<T>::comments_quux() {
1564 int a = comments^;
1565 }
Sam McCall2dee4d42020-03-31 23:09:28 +02001566 )cpp";
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001567
1568 // We should not get any of those comments in completion.
1569 EXPECT_THAT(
Sam McCall2dee4d42020-03-31 23:09:28 +02001570 completions(Text).Completions,
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001571 UnorderedElementsAre(AllOf(Not(IsDocumented()), Named("comments_foo")),
1572 AllOf(IsDocumented(), Named("comments_baz")),
1573 AllOf(IsDocumented(), Named("comments_quux")),
Ilya Biryukovda8dd8b2018-06-27 09:47:20 +00001574 AllOf(Not(IsDocumented()), Named("comments_ns")),
Ilya Biryukov89fcf6b2018-06-15 08:31:17 +00001575 // FIXME(ibiryukov): the following items should have
1576 // empty documentation, since they are separated from
1577 // a comment with an empty line. Unfortunately, I
1578 // couldn't make Sema tests pass if we ignore those.
1579 AllOf(IsDocumented(), Named("comments_bar")),
1580 AllOf(IsDocumented(), Named("comments_qux"))));
1581}
1582
Ilya Biryukov981a35d2018-05-28 12:11:37 +00001583TEST(CompletionTest, CompleteOnInvalidLine) {
1584 auto FooCpp = testPath("foo.cpp");
1585
1586 MockCompilationDatabase CDB;
Ilya Biryukov981a35d2018-05-28 12:11:37 +00001587 MockFSProvider FS;
1588 FS.Files[FooCpp] = "// empty file";
1589
Sam McCall6ef1cce2020-01-24 14:08:56 +01001590 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
Ilya Biryukov981a35d2018-05-28 12:11:37 +00001591 // Run completion outside the file range.
1592 Position Pos;
1593 Pos.line = 100;
1594 Pos.character = 0;
1595 EXPECT_THAT_EXPECTED(
1596 runCodeComplete(Server, FooCpp, Pos, clangd::CodeCompleteOptions()),
1597 Failed());
1598}
1599
Eric Liu7ad16962018-06-22 10:46:59 +00001600TEST(CompletionTest, QualifiedNames) {
1601 auto Results = completions(
1602 R"cpp(
1603 namespace ns { int local; void both(); }
1604 void f() { ::ns::^ }
1605 )cpp",
1606 {func("ns::both"), cls("ns::Index")});
1607 // We get results from both index and sema, with no duplicates.
Sam McCalle746a2b2018-07-02 11:13:16 +00001608 EXPECT_THAT(
1609 Results.Completions,
1610 UnorderedElementsAre(Scope("ns::"), Scope("ns::"), Scope("ns::")));
1611}
1612
1613TEST(CompletionTest, Render) {
1614 CodeCompletion C;
1615 C.Name = "x";
1616 C.Signature = "(bool) const";
1617 C.SnippetSuffix = "(${0:bool})";
1618 C.ReturnType = "int";
1619 C.RequiredQualifier = "Foo::";
1620 C.Scope = "ns::Foo::";
1621 C.Documentation = "This is x().";
Eric Liu83f63e42018-09-03 10:18:21 +00001622 C.Includes.emplace_back();
1623 auto &Include = C.Includes.back();
1624 Include.Header = "\"foo.h\"";
Sam McCalle746a2b2018-07-02 11:13:16 +00001625 C.Kind = CompletionItemKind::Method;
1626 C.Score.Total = 1.0;
Kirill Bobyrevff7b5ba2020-02-13 14:17:30 +01001627 C.Score.ExcludingName = .5;
Sam McCall4e5742a2018-07-06 11:50:49 +00001628 C.Origin = SymbolOrigin::AST | SymbolOrigin::Static;
Sam McCalle746a2b2018-07-02 11:13:16 +00001629
1630 CodeCompleteOptions Opts;
1631 Opts.IncludeIndicator.Insert = "^";
1632 Opts.IncludeIndicator.NoInsert = "";
1633 Opts.EnableSnippets = false;
1634
1635 auto R = C.render(Opts);
1636 EXPECT_EQ(R.label, "Foo::x(bool) const");
1637 EXPECT_EQ(R.insertText, "Foo::x");
1638 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
1639 EXPECT_EQ(R.filterText, "x");
1640 EXPECT_EQ(R.detail, "int\n\"foo.h\"");
1641 EXPECT_EQ(R.documentation, "This is x().");
1642 EXPECT_THAT(R.additionalTextEdits, IsEmpty());
Sam McCalle746a2b2018-07-02 11:13:16 +00001643 EXPECT_EQ(R.sortText, sortText(1.0, "x"));
Eric Liu6df66002018-09-06 18:52:26 +00001644 EXPECT_FALSE(R.deprecated);
Kirill Bobyrevff7b5ba2020-02-13 14:17:30 +01001645 EXPECT_EQ(R.score, .5f);
Sam McCalle746a2b2018-07-02 11:13:16 +00001646
1647 Opts.EnableSnippets = true;
1648 R = C.render(Opts);
1649 EXPECT_EQ(R.insertText, "Foo::x(${0:bool})");
1650 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
1651
Eric Liu83f63e42018-09-03 10:18:21 +00001652 Include.Insertion.emplace();
Sam McCalle746a2b2018-07-02 11:13:16 +00001653 R = C.render(Opts);
1654 EXPECT_EQ(R.label, "^Foo::x(bool) const");
1655 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
1656
Sam McCall2161ec72018-07-05 06:20:41 +00001657 Opts.ShowOrigins = true;
1658 R = C.render(Opts);
1659 EXPECT_EQ(R.label, "^[AS]Foo::x(bool) const");
1660
Sam McCalle746a2b2018-07-02 11:13:16 +00001661 C.BundleSize = 2;
1662 R = C.render(Opts);
1663 EXPECT_EQ(R.detail, "[2 overloads]\n\"foo.h\"");
Eric Liu6df66002018-09-06 18:52:26 +00001664
1665 C.Deprecated = true;
1666 R = C.render(Opts);
1667 EXPECT_TRUE(R.deprecated);
Eric Liu7ad16962018-06-22 10:46:59 +00001668}
Ilya Biryukov981a35d2018-05-28 12:11:37 +00001669
Eric Liu485074f2018-07-11 13:15:31 +00001670TEST(CompletionTest, IgnoreRecoveryResults) {
1671 auto Results = completions(
1672 R"cpp(
1673 namespace ns { int NotRecovered() { return 0; } }
1674 void f() {
1675 // Sema enters recovery mode first and then normal mode.
1676 if (auto x = ns::NotRecover^)
1677 }
1678 )cpp");
1679 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("NotRecovered")));
1680}
1681
Eric Liuf433c2d2018-07-18 15:31:14 +00001682TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {
1683 auto Results = completions(
1684 R"cpp(
1685 namespace ns {
1686 class X { public: X(); int x_; };
1687 X::X() : x_^(0) {}
1688 }
1689 )cpp");
1690 EXPECT_THAT(Results.Completions,
1691 UnorderedElementsAre(AllOf(Scope("ns::X::"), Named("x_"))));
1692}
1693
Eric Liu5d2a8072018-07-23 10:56:37 +00001694TEST(CompletionTest, CodeCompletionContext) {
1695 auto Results = completions(
1696 R"cpp(
1697 namespace ns {
1698 class X { public: X(); int x_; };
1699 void f() {
1700 X x;
1701 x.^;
1702 }
1703 }
1704 )cpp");
1705
1706 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
1707}
1708
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001709TEST(CompletionTest, FixItForArrowToDot) {
1710 MockFSProvider FS;
1711 MockCompilationDatabase CDB;
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001712
1713 CodeCompleteOptions Opts;
1714 Opts.IncludeFixIts = true;
Sam McCall2dee4d42020-03-31 23:09:28 +02001715 const char* Code =
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001716 R"cpp(
1717 class Auxilary {
1718 public:
1719 void AuxFunction();
1720 };
1721 class ClassWithPtr {
1722 public:
1723 void MemberFunction();
1724 Auxilary* operator->() const;
1725 Auxilary* Aux;
1726 };
1727 void f() {
1728 ClassWithPtr x;
1729 x[[->]]^;
1730 }
Sam McCall2dee4d42020-03-31 23:09:28 +02001731 )cpp";
1732 auto Results = completions(Code, {}, Opts);
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001733 EXPECT_EQ(Results.Completions.size(), 3u);
1734
1735 TextEdit ReplacementEdit;
Sam McCall2dee4d42020-03-31 23:09:28 +02001736 ReplacementEdit.range = Annotations(Code).range();
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001737 ReplacementEdit.newText = ".";
1738 for (const auto &C : Results.Completions) {
1739 EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction");
Haojian Wu1793bc92018-08-10 08:34:16 +00001740 if (!C.FixIts.empty()) {
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001741 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
Haojian Wu1793bc92018-08-10 08:34:16 +00001742 }
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001743 }
1744}
1745
1746TEST(CompletionTest, FixItForDotToArrow) {
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001747 CodeCompleteOptions Opts;
1748 Opts.IncludeFixIts = true;
Sam McCall2dee4d42020-03-31 23:09:28 +02001749 const char* Code =
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001750 R"cpp(
1751 class Auxilary {
1752 public:
1753 void AuxFunction();
1754 };
1755 class ClassWithPtr {
1756 public:
1757 void MemberFunction();
1758 Auxilary* operator->() const;
1759 Auxilary* Aux;
1760 };
1761 void f() {
1762 ClassWithPtr x;
1763 x[[.]]^;
1764 }
Sam McCall2dee4d42020-03-31 23:09:28 +02001765 )cpp";
1766 auto Results = completions(Code, {}, Opts);
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001767 EXPECT_EQ(Results.Completions.size(), 3u);
1768
1769 TextEdit ReplacementEdit;
Sam McCall2dee4d42020-03-31 23:09:28 +02001770 ReplacementEdit.range = Annotations(Code).range();
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +00001771 ReplacementEdit.newText = "->";
1772 for (const auto &C : Results.Completions) {
1773 EXPECT_TRUE(C.FixIts.empty() || C.Name == "AuxFunction");
1774 if (!C.FixIts.empty()) {
1775 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
1776 }
1777 }
1778}
1779
Kadir Cetinkayaa9c9d002018-08-13 08:23:01 +00001780TEST(CompletionTest, RenderWithFixItMerged) {
1781 TextEdit FixIt;
1782 FixIt.range.end.character = 5;
1783 FixIt.newText = "->";
1784
1785 CodeCompletion C;
1786 C.Name = "x";
1787 C.RequiredQualifier = "Foo::";
1788 C.FixIts = {FixIt};
1789 C.CompletionTokenRange.start.character = 5;
1790
1791 CodeCompleteOptions Opts;
1792 Opts.IncludeFixIts = true;
1793
1794 auto R = C.render(Opts);
1795 EXPECT_TRUE(R.textEdit);
1796 EXPECT_EQ(R.textEdit->newText, "->Foo::x");
1797 EXPECT_TRUE(R.additionalTextEdits.empty());
1798}
1799
1800TEST(CompletionTest, RenderWithFixItNonMerged) {
1801 TextEdit FixIt;
1802 FixIt.range.end.character = 4;
1803 FixIt.newText = "->";
1804
1805 CodeCompletion C;
1806 C.Name = "x";
1807 C.RequiredQualifier = "Foo::";
1808 C.FixIts = {FixIt};
1809 C.CompletionTokenRange.start.character = 5;
1810
1811 CodeCompleteOptions Opts;
1812 Opts.IncludeFixIts = true;
1813
1814 auto R = C.render(Opts);
1815 EXPECT_TRUE(R.textEdit);
1816 EXPECT_EQ(R.textEdit->newText, "Foo::x");
1817 EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
1818}
1819
1820TEST(CompletionTest, CompletionTokenRange) {
1821 MockFSProvider FS;
1822 MockCompilationDatabase CDB;
Sam McCall2dee4d42020-03-31 23:09:28 +02001823 TestTU TU;
1824 TU.AdditionalFiles["foo/abc/foo.h"] = "";
Kadir Cetinkayaa9c9d002018-08-13 08:23:01 +00001825
1826 constexpr const char *TestCodes[] = {
1827 R"cpp(
1828 class Auxilary {
1829 public:
1830 void AuxFunction();
1831 };
1832 void f() {
1833 Auxilary x;
1834 x.[[Aux]]^;
1835 }
1836 )cpp",
1837 R"cpp(
1838 class Auxilary {
1839 public:
1840 void AuxFunction();
1841 };
1842 void f() {
1843 Auxilary x;
1844 x.[[]]^;
1845 }
Haojian Wu297a9da2020-03-25 14:17:23 +01001846 )cpp",
1847 R"cpp(
1848 #include "foo/[[a^/]]foo.h"
1849 )cpp",
1850 R"cpp(
1851 #include "foo/abc/[[fo^o.h"]]
1852 )cpp",
1853 };
Kadir Cetinkayaa9c9d002018-08-13 08:23:01 +00001854 for (const auto &Text : TestCodes) {
1855 Annotations TestCode(Text);
Sam McCall2dee4d42020-03-31 23:09:28 +02001856 TU.Code = TestCode.code().str();
1857 auto Results = completions(TU, TestCode.point());
Kirill Bobyrevc547c222019-11-26 13:45:04 +01001858 if (Results.Completions.size() != 1) {
Sam McCall2dee4d42020-03-31 23:09:28 +02001859 ADD_FAILURE() << "Results.Completions.size() != 1" << Text;
Kirill Bobyrevc547c222019-11-26 13:45:04 +01001860 continue;
1861 }
Ilya Biryukov22fa4652019-01-03 13:28:05 +00001862 EXPECT_THAT(Results.Completions.front().CompletionTokenRange,
1863 TestCode.range());
Kadir Cetinkayaa9c9d002018-08-13 08:23:01 +00001864 }
1865}
1866
Kadir Cetinkayae486e372018-08-13 08:40:05 +00001867TEST(SignatureHelpTest, OverloadsOrdering) {
1868 const auto Results = signatures(R"cpp(
1869 void foo(int x);
1870 void foo(int x, float y);
1871 void foo(float x, int y);
1872 void foo(float x, float y);
1873 void foo(int x, int y = 0);
1874 int main() { foo(^); }
1875 )cpp");
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001876 EXPECT_THAT(Results.signatures,
1877 ElementsAre(Sig("foo([[int x]]) -> void"),
1878 Sig("foo([[int x]], [[int y = 0]]) -> void"),
1879 Sig("foo([[float x]], [[int y]]) -> void"),
1880 Sig("foo([[int x]], [[float y]]) -> void"),
1881 Sig("foo([[float x]], [[float y]]) -> void")));
Kadir Cetinkayae486e372018-08-13 08:40:05 +00001882 // We always prefer the first signature.
1883 EXPECT_EQ(0, Results.activeSignature);
1884 EXPECT_EQ(0, Results.activeParameter);
1885}
1886
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001887TEST(SignatureHelpTest, InstantiatedSignatures) {
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001888 StringRef Sig0 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001889 template <class T>
1890 void foo(T, T, T);
1891
1892 int main() {
1893 foo<int>(^);
1894 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001895 )cpp";
1896
1897 EXPECT_THAT(signatures(Sig0).signatures,
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001898 ElementsAre(Sig("foo([[T]], [[T]], [[T]]) -> void")));
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001899
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001900 StringRef Sig1 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001901 template <class T>
1902 void foo(T, T, T);
1903
1904 int main() {
1905 foo(10, ^);
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001906 })cpp";
1907
1908 EXPECT_THAT(signatures(Sig1).signatures,
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001909 ElementsAre(Sig("foo([[T]], [[T]], [[T]]) -> void")));
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001910
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001911 StringRef Sig2 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001912 template <class ...T>
1913 void foo(T...);
1914
1915 int main() {
1916 foo<int>(^);
1917 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001918 )cpp";
1919
1920 EXPECT_THAT(signatures(Sig2).signatures,
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001921 ElementsAre(Sig("foo([[T...]]) -> void")));
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001922
1923 // It is debatable whether we should substitute the outer template parameter
1924 // ('T') in that case. Currently we don't substitute it in signature help, but
1925 // do substitute in code complete.
1926 // FIXME: make code complete and signature help consistent, figure out which
1927 // way is better.
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001928 StringRef Sig3 = R"cpp(
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001929 template <class T>
1930 struct X {
1931 template <class U>
1932 void foo(T, U);
1933 };
1934
1935 int main() {
1936 X<int>().foo<double>(^)
1937 }
Simon Pilgrim83552ee2018-08-16 11:41:19 +00001938 )cpp";
1939
1940 EXPECT_THAT(signatures(Sig3).signatures,
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001941 ElementsAre(Sig("foo([[T]], [[U]]) -> void")));
Ilya Biryukov8fd44bb2018-08-14 09:36:32 +00001942}
1943
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001944TEST(SignatureHelpTest, IndexDocumentation) {
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001945 Symbol Foo0 = sym("foo", index::SymbolKind::Function, "@F@\\0#");
Sam McCall2e5700f2018-08-31 13:55:01 +00001946 Foo0.Documentation = "Doc from the index";
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001947 Symbol Foo1 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#");
Sam McCall2e5700f2018-08-31 13:55:01 +00001948 Foo1.Documentation = "Doc from the index";
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001949 Symbol Foo2 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#I#");
1950
Simon Pilgrim24d34922018-08-17 10:40:05 +00001951 StringRef Sig0 = R"cpp(
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001952 int foo();
1953 int foo(double);
1954
1955 void test() {
1956 foo(^);
1957 }
Simon Pilgrim24d34922018-08-17 10:40:05 +00001958 )cpp";
1959
1960 EXPECT_THAT(
1961 signatures(Sig0, {Foo0}).signatures,
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001962 ElementsAre(AllOf(Sig("foo() -> int"), SigDoc("Doc from the index")),
1963 AllOf(Sig("foo([[double]]) -> int"), SigDoc(""))));
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001964
Simon Pilgrim24d34922018-08-17 10:40:05 +00001965 StringRef Sig1 = R"cpp(
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001966 int foo();
1967 // Overriden doc from sema
1968 int foo(int);
1969 // Doc from sema
1970 int foo(int, int);
1971
1972 void test() {
1973 foo(^);
1974 }
Simon Pilgrim24d34922018-08-17 10:40:05 +00001975 )cpp";
1976
1977 EXPECT_THAT(
1978 signatures(Sig1, {Foo0, Foo1, Foo2}).signatures,
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00001979 ElementsAre(
1980 AllOf(Sig("foo() -> int"), SigDoc("Doc from the index")),
1981 AllOf(Sig("foo([[int]]) -> int"), SigDoc("Overriden doc from sema")),
1982 AllOf(Sig("foo([[int]], [[int]]) -> int"), SigDoc("Doc from sema"))));
Ilya Biryukov8a0f76b2018-08-17 09:32:30 +00001983}
1984
Haojian Wu0b097b12019-01-09 13:42:03 +00001985TEST(SignatureHelpTest, DynamicIndexDocumentation) {
1986 MockFSProvider FS;
1987 MockCompilationDatabase CDB;
Haojian Wu0b097b12019-01-09 13:42:03 +00001988 ClangdServer::Options Opts = ClangdServer::optsForTest();
1989 Opts.BuildDynamicSymbolIndex = true;
Sam McCall6ef1cce2020-01-24 14:08:56 +01001990 ClangdServer Server(CDB, FS, Opts);
Haojian Wu0b097b12019-01-09 13:42:03 +00001991
1992 FS.Files[testPath("foo.h")] = R"cpp(
1993 struct Foo {
1994 // Member doc
1995 int foo();
1996 };
1997 )cpp";
1998 Annotations FileContent(R"cpp(
1999 #include "foo.h"
2000 void test() {
2001 Foo f;
2002 f.foo(^);
2003 }
2004 )cpp");
2005 auto File = testPath("test.cpp");
2006 Server.addDocument(File, FileContent.code());
2007 // Wait for the dynamic index being built.
2008 ASSERT_TRUE(Server.blockUntilIdleForTest());
2009 EXPECT_THAT(
2010 llvm::cantFail(runSignatureHelp(Server, File, FileContent.point()))
2011 .signatures,
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00002012 ElementsAre(AllOf(Sig("foo() -> int"), SigDoc("Member doc"))));
Haojian Wu0b097b12019-01-09 13:42:03 +00002013}
2014
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00002015TEST(CompletionTest, CompletionFunctionArgsDisabled) {
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00002016 CodeCompleteOptions Opts;
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00002017 Opts.EnableSnippets = true;
2018 Opts.EnableFunctionArgSnippets = false;
Ilya Biryukov4f984702018-09-26 05:45:31 +00002019
2020 {
2021 auto Results = completions(
2022 R"cpp(
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00002023 void xfoo();
2024 void xfoo(int x, int y);
Ilya Biryukov4f984702018-09-26 05:45:31 +00002025 void f() { xfo^ })cpp",
2026 {}, Opts);
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00002027 EXPECT_THAT(
2028 Results.Completions,
2029 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("()")),
2030 AllOf(Named("xfoo"), SnippetSuffix("($0)"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00002031 }
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00002032 {
Ilya Biryukov4f984702018-09-26 05:45:31 +00002033 auto Results = completions(
2034 R"cpp(
2035 void xbar();
2036 void f() { xba^ })cpp",
2037 {}, Opts);
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00002038 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
2039 Named("xbar"), SnippetSuffix("()"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00002040 }
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00002041 {
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00002042 Opts.BundleOverloads = true;
Ilya Biryukov4f984702018-09-26 05:45:31 +00002043 auto Results = completions(
2044 R"cpp(
2045 void xfoo();
2046 void xfoo(int x, int y);
2047 void f() { xfo^ })cpp",
2048 {}, Opts);
Kadir Cetinkaya516fcda2018-08-23 12:19:39 +00002049 EXPECT_THAT(
2050 Results.Completions,
2051 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("($0)"))));
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00002052 }
Ilya Biryukov4f984702018-09-26 05:45:31 +00002053 {
2054 auto Results = completions(
2055 R"cpp(
2056 template <class T, class U>
2057 void xfoo(int a, U b);
2058 void f() { xfo^ })cpp",
2059 {}, Opts);
2060 EXPECT_THAT(
2061 Results.Completions,
2062 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("<$1>($0)"))));
2063 }
2064 {
2065 auto Results = completions(
2066 R"cpp(
2067 template <class T>
2068 class foo_class{};
2069 template <class T>
2070 using foo_alias = T**;
2071 void f() { foo_^ })cpp",
2072 {}, Opts);
2073 EXPECT_THAT(
2074 Results.Completions,
2075 UnorderedElementsAre(AllOf(Named("foo_class"), SnippetSuffix("<$0>")),
2076 AllOf(Named("foo_alias"), SnippetSuffix("<$0>"))));
2077 }
Kadir Cetinkaya6c9f15c2018-08-17 15:42:54 +00002078}
2079
Kadir Cetinkayaf8b85a32018-08-23 13:14:50 +00002080TEST(CompletionTest, SuggestOverrides) {
2081 constexpr const char *const Text(R"cpp(
2082 class A {
2083 public:
2084 virtual void vfunc(bool param);
2085 virtual void vfunc(bool param, int p);
2086 void func(bool param);
2087 };
2088 class B : public A {
2089 virtual void ttt(bool param) const;
2090 void vfunc(bool param, int p) override;
2091 };
2092 class C : public B {
2093 public:
2094 void vfunc(bool param) override;
2095 ^
2096 };
2097 )cpp");
2098 const auto Results = completions(Text);
Ilya Biryukovcabab292019-05-24 10:18:39 +00002099 EXPECT_THAT(
2100 Results.Completions,
2101 AllOf(Contains(AllOf(Labeled("void vfunc(bool param, int p) override"),
2102 NameStartsWith("vfunc"))),
2103 Contains(AllOf(Labeled("void ttt(bool param) const override"),
2104 NameStartsWith("ttt"))),
2105 Not(Contains(Labeled("void vfunc(bool param) override")))));
Kadir Cetinkayaf8b85a32018-08-23 13:14:50 +00002106}
2107
Ilya Biryukov5a79d1e2018-09-03 15:25:27 +00002108TEST(CompletionTest, OverridesNonIdentName) {
2109 // Check the completions call does not crash.
2110 completions(R"cpp(
2111 struct Base {
2112 virtual ~Base() = 0;
2113 virtual operator int() = 0;
2114 virtual Base& operator+(Base&) = 0;
2115 };
2116
2117 struct Derived : Base {
2118 ^
2119 };
2120 )cpp");
2121}
2122
Sam McCall6f997832019-04-10 11:50:40 +00002123TEST(GuessCompletionPrefix, Filters) {
2124 for (llvm::StringRef Case : {
Nathan Ridgef1e6f572019-06-15 02:26:47 +00002125 "[[scope::]][[ident]]^",
2126 "[[]][[]]^",
2127 "\n[[]][[]]^",
2128 "[[]][[ab]]^",
2129 "x.[[]][[ab]]^",
2130 "x.[[]][[]]^",
2131 "[[x::]][[ab]]^",
2132 "[[x::]][[]]^",
2133 "[[::x::]][[ab]]^",
2134 "some text [[scope::more::]][[identif]]^ier",
2135 "some text [[scope::]][[mor]]^e::identifier",
2136 "weird case foo::[[::bar::]][[baz]]^",
Sam McCalld4df3722020-02-10 11:52:42 +01002137 "/* [[]][[]]^ */",
Nathan Ridgef1e6f572019-06-15 02:26:47 +00002138 }) {
Sam McCall6f997832019-04-10 11:50:40 +00002139 Annotations F(Case);
2140 auto Offset = cantFail(positionToOffset(F.code(), F.point()));
2141 auto ToStringRef = [&](Range R) {
2142 return F.code().slice(cantFail(positionToOffset(F.code(), R.start)),
2143 cantFail(positionToOffset(F.code(), R.end)));
2144 };
2145 auto WantQualifier = ToStringRef(F.ranges()[0]),
2146 WantName = ToStringRef(F.ranges()[1]);
Eric Liu25d74e92018-08-24 11:23:56 +00002147
Sam McCall6f997832019-04-10 11:50:40 +00002148 auto Prefix = guessCompletionPrefix(F.code(), Offset);
2149 // Even when components are empty, check their offsets are correct.
2150 EXPECT_EQ(WantQualifier, Prefix.Qualifier) << Case;
2151 EXPECT_EQ(WantQualifier.begin(), Prefix.Qualifier.begin()) << Case;
2152 EXPECT_EQ(WantName, Prefix.Name) << Case;
2153 EXPECT_EQ(WantName.begin(), Prefix.Name.begin()) << Case;
2154 }
Eric Liu25d74e92018-08-24 11:23:56 +00002155}
2156
2157TEST(CompletionTest, EnableSpeculativeIndexRequest) {
2158 MockFSProvider FS;
2159 MockCompilationDatabase CDB;
Sam McCall6ef1cce2020-01-24 14:08:56 +01002160 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
Eric Liu25d74e92018-08-24 11:23:56 +00002161
2162 auto File = testPath("foo.cpp");
2163 Annotations Test(R"cpp(
2164 namespace ns1 { int abc; }
2165 namespace ns2 { int abc; }
2166 void f() { ns1::ab$1^; ns1::ab$2^; }
Haojian Wu744eb3c2018-12-21 09:32:49 +00002167 void f2() { ns2::ab$3^; }
Eric Liu25d74e92018-08-24 11:23:56 +00002168 )cpp");
2169 runAddDocument(Server, File, Test.code());
2170 clangd::CodeCompleteOptions Opts = {};
2171
2172 IndexRequestCollector Requests;
2173 Opts.Index = &Requests;
2174 Opts.SpeculativeIndexRequest = true;
2175
2176 auto CompleteAtPoint = [&](StringRef P) {
2177 cantFail(runCodeComplete(Server, File, Test.point(P), Opts));
Eric Liu25d74e92018-08-24 11:23:56 +00002178 };
2179
2180 CompleteAtPoint("1");
Kadir Cetinkayade859972019-10-07 17:12:18 +00002181 auto Reqs1 = Requests.consumeRequests(1);
Eric Liu25d74e92018-08-24 11:23:56 +00002182 ASSERT_EQ(Reqs1.size(), 1u);
2183 EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre("ns1::"));
2184
2185 CompleteAtPoint("2");
Kadir Cetinkayade859972019-10-07 17:12:18 +00002186 auto Reqs2 = Requests.consumeRequests(1);
Eric Liu25d74e92018-08-24 11:23:56 +00002187 // Speculation succeeded. Used speculative index result.
2188 ASSERT_EQ(Reqs2.size(), 1u);
2189 EXPECT_EQ(Reqs2[0], Reqs1[0]);
2190
2191 CompleteAtPoint("3");
2192 // Speculation failed. Sent speculative index request and the new index
2193 // request after sema.
Kadir Cetinkayade859972019-10-07 17:12:18 +00002194 auto Reqs3 = Requests.consumeRequests(2);
Eric Liu25d74e92018-08-24 11:23:56 +00002195 ASSERT_EQ(Reqs3.size(), 2u);
2196}
2197
Eric Liu83f63e42018-09-03 10:18:21 +00002198TEST(CompletionTest, InsertTheMostPopularHeader) {
Eric Liuc0ac4bb2018-11-22 15:02:05 +00002199 std::string DeclFile = URI::create(testPath("foo")).toString();
Ilya Biryukoved913a22019-10-24 15:40:23 +02002200 Symbol Sym = func("Func");
2201 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2202 Sym.IncludeHeaders.emplace_back("\"foo.h\"", 2);
2203 Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000);
Eric Liu83f63e42018-09-03 10:18:21 +00002204
Ilya Biryukoved913a22019-10-24 15:40:23 +02002205 auto Results = completions("Fun^", {Sym}).Completions;
Eric Liu83f63e42018-09-03 10:18:21 +00002206 assert(!Results.empty());
2207 EXPECT_THAT(Results[0], AllOf(Named("Func"), InsertInclude("\"bar.h\"")));
2208 EXPECT_EQ(Results[0].Includes.size(), 2u);
2209}
2210
2211TEST(CompletionTest, NoInsertIncludeIfOnePresent) {
Sam McCall2dee4d42020-03-31 23:09:28 +02002212 Annotations Test(R"cpp(
2213 #include "foo.h"
2214 Fun^
2215 )cpp");
2216 auto TU = TestTU::withCode(Test.code());
2217 TU.AdditionalFiles["foo.h"] = "";
Eric Liu83f63e42018-09-03 10:18:21 +00002218
Eric Liuc0ac4bb2018-11-22 15:02:05 +00002219 std::string DeclFile = URI::create(testPath("foo")).toString();
Ilya Biryukoved913a22019-10-24 15:40:23 +02002220 Symbol Sym = func("Func");
2221 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
2222 Sym.IncludeHeaders.emplace_back("\"foo.h\"", 2);
2223 Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000);
Eric Liu83f63e42018-09-03 10:18:21 +00002224
2225 EXPECT_THAT(
Sam McCall2dee4d42020-03-31 23:09:28 +02002226 completions(TU, Test.point(), {Sym}).Completions,
Eric Liu83f63e42018-09-03 10:18:21 +00002227 UnorderedElementsAre(
2228 AllOf(Named("Func"), HasInclude("\"foo.h\""), Not(InsertInclude()))));
2229}
2230
Eric Liud25f1212018-09-06 09:59:37 +00002231TEST(CompletionTest, MergeMacrosFromIndexAndSema) {
2232 Symbol Sym;
2233 Sym.Name = "Clangd_Macro_Test";
2234 Sym.ID = SymbolID("c:foo.cpp@8@macro@Clangd_Macro_Test");
2235 Sym.SymInfo.Kind = index::SymbolKind::Macro;
Eric Liu6df66002018-09-06 18:52:26 +00002236 Sym.Flags |= Symbol::IndexedForCodeCompletion;
Eric Liud25f1212018-09-06 09:59:37 +00002237 EXPECT_THAT(completions("#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym})
2238 .Completions,
2239 UnorderedElementsAre(Named("Clangd_Macro_Test")));
2240}
2241
Sam McCall1b29dec2019-05-02 16:12:36 +00002242TEST(CompletionTest, MacroFromPreamble) {
Sam McCall2dee4d42020-03-31 23:09:28 +02002243 Annotations Test(R"cpp(#define CLANGD_PREAMBLE_MAIN x
Eric Liu467c5f92018-09-19 09:35:04 +00002244
2245 int x = 0;
2246 #define CLANGD_MAIN x
2247 void f() { CLANGD_^ }
Sam McCall2dee4d42020-03-31 23:09:28 +02002248 )cpp");
2249 auto TU = TestTU::withCode(Test.code());
2250 TU.HeaderCode = "#define CLANGD_PREAMBLE_HEADER x";
2251 auto Results = completions(TU, Test.point(), {func("CLANGD_INDEX")});
Sam McCall1b29dec2019-05-02 16:12:36 +00002252 // We should get results from the main file, including the preamble section.
2253 // However no results from included files (the index should cover them).
2254 EXPECT_THAT(Results.Completions,
2255 UnorderedElementsAre(Named("CLANGD_PREAMBLE_MAIN"),
2256 Named("CLANGD_MAIN"),
2257 Named("CLANGD_INDEX")));
Eric Liu467c5f92018-09-19 09:35:04 +00002258}
2259
Eric Liu6df66002018-09-06 18:52:26 +00002260TEST(CompletionTest, DeprecatedResults) {
2261 std::string Body = R"cpp(
2262 void TestClangd();
2263 void TestClangc() __attribute__((deprecated("", "")));
2264 )cpp";
2265
2266 EXPECT_THAT(
2267 completions(Body + "int main() { TestClang^ }").Completions,
2268 UnorderedElementsAre(AllOf(Named("TestClangd"), Not(Deprecated())),
2269 AllOf(Named("TestClangc"), Deprecated())));
2270}
2271
Kadir Cetinkaya1f946ee2020-01-13 09:00:19 +01002272TEST(SignatureHelpTest, PartialSpec) {
2273 const auto Results = signatures(R"cpp(
2274 template <typename T> struct Foo {};
2275 template <typename T> struct Foo<T*> { Foo(T); };
2276 Foo<int*> F(^);)cpp");
2277 EXPECT_THAT(Results.signatures, Contains(Sig("Foo([[T]])")));
2278 EXPECT_EQ(0, Results.activeParameter);
2279}
2280
Kadir Cetinkaya0b77d032018-09-10 14:22:42 +00002281TEST(SignatureHelpTest, InsideArgument) {
2282 {
2283 const auto Results = signatures(R"cpp(
2284 void foo(int x);
2285 void foo(int x, int y);
2286 int main() { foo(1+^); }
2287 )cpp");
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00002288 EXPECT_THAT(Results.signatures,
2289 ElementsAre(Sig("foo([[int x]]) -> void"),
2290 Sig("foo([[int x]], [[int y]]) -> void")));
Kadir Cetinkaya0b77d032018-09-10 14:22:42 +00002291 EXPECT_EQ(0, Results.activeParameter);
2292 }
2293 {
2294 const auto Results = signatures(R"cpp(
2295 void foo(int x);
2296 void foo(int x, int y);
2297 int main() { foo(1^); }
2298 )cpp");
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00002299 EXPECT_THAT(Results.signatures,
2300 ElementsAre(Sig("foo([[int x]]) -> void"),
2301 Sig("foo([[int x]], [[int y]]) -> void")));
Kadir Cetinkaya0b77d032018-09-10 14:22:42 +00002302 EXPECT_EQ(0, Results.activeParameter);
2303 }
2304 {
2305 const auto Results = signatures(R"cpp(
2306 void foo(int x);
2307 void foo(int x, int y);
2308 int main() { foo(1^0); }
2309 )cpp");
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00002310 EXPECT_THAT(Results.signatures,
2311 ElementsAre(Sig("foo([[int x]]) -> void"),
2312 Sig("foo([[int x]], [[int y]]) -> void")));
Kadir Cetinkaya0b77d032018-09-10 14:22:42 +00002313 EXPECT_EQ(0, Results.activeParameter);
2314 }
2315 {
2316 const auto Results = signatures(R"cpp(
2317 void foo(int x);
2318 void foo(int x, int y);
2319 int bar(int x, int y);
2320 int main() { bar(foo(2, 3^)); }
2321 )cpp");
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00002322 EXPECT_THAT(Results.signatures,
2323 ElementsAre(Sig("foo([[int x]], [[int y]]) -> void")));
Kadir Cetinkaya0b77d032018-09-10 14:22:42 +00002324 EXPECT_EQ(1, Results.activeParameter);
2325 }
2326}
2327
Kadir Cetinkaya873cae52018-09-11 15:12:10 +00002328TEST(SignatureHelpTest, ConstructorInitializeFields) {
2329 {
2330 const auto Results = signatures(R"cpp(
2331 struct A {
2332 A(int);
2333 };
2334 struct B {
2335 B() : a_elem(^) {}
2336 A a_elem;
2337 };
2338 )cpp");
Ilya Biryukov22fa4652019-01-03 13:28:05 +00002339 EXPECT_THAT(Results.signatures,
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00002340 UnorderedElementsAre(Sig("A([[int]])"), Sig("A([[A &&]])"),
2341 Sig("A([[const A &]])")));
Kadir Cetinkaya873cae52018-09-11 15:12:10 +00002342 }
2343 {
2344 const auto Results = signatures(R"cpp(
2345 struct A {
2346 A(int);
2347 };
2348 struct C {
2349 C(int);
2350 C(A);
2351 };
2352 struct B {
2353 B() : c_elem(A(1^)) {}
2354 C c_elem;
2355 };
2356 )cpp");
Ilya Biryukov22fa4652019-01-03 13:28:05 +00002357 EXPECT_THAT(Results.signatures,
Ilya Biryukov4ef0f822019-06-04 09:36:59 +00002358 UnorderedElementsAre(Sig("A([[int]])"), Sig("A([[A &&]])"),
2359 Sig("A([[const A &]])")));
Kadir Cetinkaya873cae52018-09-11 15:12:10 +00002360 }
2361}
2362
Kadir Cetinkaya0ed5d292018-09-27 14:21:07 +00002363TEST(CompletionTest, IncludedCompletionKinds) {
Sam McCall2dee4d42020-03-31 23:09:28 +02002364 Annotations Test(R"cpp(#include "^")cpp");
2365 auto TU = TestTU::withCode(Test.code());
2366 TU.AdditionalFiles["sub/bar.h"] = "";
2367 TU.ExtraArgs.push_back("-I" + testPath("sub"));
2368
2369 auto Results = completions(TU, Test.point());
Kadir Cetinkaya0ed5d292018-09-27 14:21:07 +00002370 EXPECT_THAT(Results.Completions,
2371 AllOf(Has("sub/", CompletionItemKind::Folder),
2372 Has("bar.h\"", CompletionItemKind::File)));
2373}
2374
Haojian Wu1c6b6de2018-10-02 14:46:08 +00002375TEST(CompletionTest, NoCrashAtNonAlphaIncludeHeader) {
Sam McCall2dee4d42020-03-31 23:09:28 +02002376 completions(
Haojian Wu1c6b6de2018-10-02 14:46:08 +00002377 R"cpp(
2378 #include "./^"
Ilya Biryukov22fa4652019-01-03 13:28:05 +00002379 )cpp");
Haojian Wu1c6b6de2018-10-02 14:46:08 +00002380}
2381
Eric Liu670c1472018-09-27 18:46:00 +00002382TEST(CompletionTest, NoAllScopesCompletionWhenQualified) {
2383 clangd::CodeCompleteOptions Opts = {};
2384 Opts.AllScopes = true;
2385
2386 auto Results = completions(
2387 R"cpp(
2388 void f() { na::Clangd^ }
2389 )cpp",
2390 {cls("na::ClangdA"), cls("nx::ClangdX"), cls("Clangd3")}, Opts);
2391 EXPECT_THAT(Results.Completions,
2392 UnorderedElementsAre(
2393 AllOf(Qualifier(""), Scope("na::"), Named("ClangdA"))));
2394}
2395
2396TEST(CompletionTest, AllScopesCompletion) {
2397 clangd::CodeCompleteOptions Opts = {};
2398 Opts.AllScopes = true;
2399
2400 auto Results = completions(
2401 R"cpp(
2402 namespace na {
2403 void f() { Clangd^ }
2404 }
2405 )cpp",
2406 {cls("nx::Clangd1"), cls("ny::Clangd2"), cls("Clangd3"),
2407 cls("na::nb::Clangd4")},
2408 Opts);
2409 EXPECT_THAT(
2410 Results.Completions,
2411 UnorderedElementsAre(AllOf(Qualifier("nx::"), Named("Clangd1")),
2412 AllOf(Qualifier("ny::"), Named("Clangd2")),
2413 AllOf(Qualifier(""), Scope(""), Named("Clangd3")),
2414 AllOf(Qualifier("nb::"), Named("Clangd4"))));
2415}
2416
2417TEST(CompletionTest, NoQualifierIfShadowed) {
2418 clangd::CodeCompleteOptions Opts = {};
2419 Opts.AllScopes = true;
2420
2421 auto Results = completions(R"cpp(
2422 namespace nx { class Clangd1 {}; }
2423 using nx::Clangd1;
2424 void f() { Clangd^ }
2425 )cpp",
2426 {cls("nx::Clangd1"), cls("nx::Clangd2")}, Opts);
2427 // Although Clangd1 is from another namespace, Sema tells us it's in-scope and
2428 // needs no qualifier.
2429 EXPECT_THAT(Results.Completions,
2430 UnorderedElementsAre(AllOf(Qualifier(""), Named("Clangd1")),
2431 AllOf(Qualifier("nx::"), Named("Clangd2"))));
2432}
Kadir Cetinkaya0ed5d292018-09-27 14:21:07 +00002433
Kadir Cetinkayab9157902018-10-24 15:24:29 +00002434TEST(CompletionTest, NoCompletionsForNewNames) {
2435 clangd::CodeCompleteOptions Opts;
2436 Opts.AllScopes = true;
2437 auto Results = completions(R"cpp(
2438 void f() { int n^ }
2439 )cpp",
2440 {cls("naber"), cls("nx::naber")}, Opts);
2441 EXPECT_THAT(Results.Completions, UnorderedElementsAre());
2442}
Sam McCall39e86fa2018-11-14 09:05:19 +00002443
Kirill Bobyrev7f0dcf62019-11-22 12:48:06 +01002444TEST(CompletionTest, Lambda) {
2445 clangd::CodeCompleteOptions Opts = {};
2446
2447 auto Results = completions(R"cpp(
2448 void function() {
2449 auto Lambda = [](int a, const double &b) {return 1.f;};
2450 Lam^
2451 }
2452 )cpp",
2453 {}, Opts);
2454
2455 ASSERT_EQ(Results.Completions.size(), 1u);
2456 const auto &A = Results.Completions.front();
2457 EXPECT_EQ(A.Name, "Lambda");
2458 EXPECT_EQ(A.Signature, "(int a, const double &b) const");
2459 EXPECT_EQ(A.Kind, CompletionItemKind::Variable);
2460 EXPECT_EQ(A.ReturnType, "float");
2461 EXPECT_EQ(A.SnippetSuffix, "(${1:int a}, ${2:const double &b})");
2462}
2463
Sam McCall39e86fa2018-11-14 09:05:19 +00002464TEST(CompletionTest, ObjectiveCMethodNoArguments) {
2465 auto Results = completions(R"objc(
2466 @interface Foo
2467 @property(nonatomic, setter=setXToIgnoreComplete:) int value;
2468 @end
2469 Foo *foo = [Foo new]; int y = [foo v^]
2470 )objc",
Ilya Biryukov22fa4652019-01-03 13:28:05 +00002471 /*IndexSymbols=*/{},
2472 /*Opts=*/{}, "Foo.m");
Sam McCall39e86fa2018-11-14 09:05:19 +00002473
2474 auto C = Results.Completions;
2475 EXPECT_THAT(C, ElementsAre(Named("value")));
2476 EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method)));
2477 EXPECT_THAT(C, ElementsAre(ReturnType("int")));
2478 EXPECT_THAT(C, ElementsAre(Signature("")));
2479 EXPECT_THAT(C, ElementsAre(SnippetSuffix("")));
2480}
2481
2482TEST(CompletionTest, ObjectiveCMethodOneArgument) {
2483 auto Results = completions(R"objc(
2484 @interface Foo
2485 - (int)valueForCharacter:(char)c;
2486 @end
2487 Foo *foo = [Foo new]; int y = [foo v^]
2488 )objc",
Ilya Biryukov22fa4652019-01-03 13:28:05 +00002489 /*IndexSymbols=*/{},
2490 /*Opts=*/{}, "Foo.m");
Sam McCall39e86fa2018-11-14 09:05:19 +00002491
2492 auto C = Results.Completions;
2493 EXPECT_THAT(C, ElementsAre(Named("valueForCharacter:")));
2494 EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method)));
2495 EXPECT_THAT(C, ElementsAre(ReturnType("int")));
2496 EXPECT_THAT(C, ElementsAre(Signature("(char)")));
2497 EXPECT_THAT(C, ElementsAre(SnippetSuffix("${1:(char)}")));
2498}
2499
2500TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromBeginning) {
2501 auto Results = completions(R"objc(
2502 @interface Foo
2503 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;
2504 @end
2505 id val = [Foo foo^]
2506 )objc",
Ilya Biryukov22fa4652019-01-03 13:28:05 +00002507 /*IndexSymbols=*/{},
2508 /*Opts=*/{}, "Foo.m");
Sam McCall39e86fa2018-11-14 09:05:19 +00002509
2510 auto C = Results.Completions;
2511 EXPECT_THAT(C, ElementsAre(Named("fooWithValue:")));
2512 EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method)));
2513 EXPECT_THAT(C, ElementsAre(ReturnType("id")));
2514 EXPECT_THAT(C, ElementsAre(Signature("(int) fooey:(unsigned int)")));
Ilya Biryukov22fa4652019-01-03 13:28:05 +00002515 EXPECT_THAT(
2516 C, ElementsAre(SnippetSuffix("${1:(int)} fooey:${2:(unsigned int)}")));
Sam McCall39e86fa2018-11-14 09:05:19 +00002517}
2518
2519TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
2520 auto Results = completions(R"objc(
2521 @interface Foo
2522 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;
2523 @end
2524 id val = [Foo fooWithValue:10 f^]
2525 )objc",
Ilya Biryukov22fa4652019-01-03 13:28:05 +00002526 /*IndexSymbols=*/{},
2527 /*Opts=*/{}, "Foo.m");
Sam McCall39e86fa2018-11-14 09:05:19 +00002528
2529 auto C = Results.Completions;
2530 EXPECT_THAT(C, ElementsAre(Named("fooey:")));
2531 EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method)));
2532 EXPECT_THAT(C, ElementsAre(ReturnType("id")));
2533 EXPECT_THAT(C, ElementsAre(Signature("(unsigned int)")));
2534 EXPECT_THAT(C, ElementsAre(SnippetSuffix("${1:(unsigned int)}")));
2535}
2536
Ilya Biryukov85346752019-05-28 15:33:37 +00002537TEST(CompletionTest, CursorInSnippets) {
2538 clangd::CodeCompleteOptions Options;
2539 Options.EnableSnippets = true;
2540 auto Results = completions(
2541 R"cpp(
2542 void while_foo(int a, int b);
2543 void test() {
2544 whil^
2545 })cpp",
2546 /*IndexSymbols=*/{}, Options);
2547
2548 // Last placeholder in code patterns should be $0 to put the cursor there.
Nathan Ridgef1e6f572019-06-15 02:26:47 +00002549 EXPECT_THAT(Results.Completions,
2550 Contains(AllOf(
2551 Named("while"),
2552 SnippetSuffix(" (${1:condition}) {\n${0:statements}\n}"))));
Ilya Biryukov85346752019-05-28 15:33:37 +00002553 // However, snippets for functions must *not* end with $0.
2554 EXPECT_THAT(Results.Completions,
2555 Contains(AllOf(Named("while_foo"),
2556 SnippetSuffix("(${1:int a}, ${2:int b})"))));
2557}
2558
Ilya Biryukovc514ade2019-01-24 10:41:43 +00002559TEST(CompletionTest, WorksWithNullType) {
2560 auto R = completions(R"cpp(
2561 int main() {
2562 for (auto [loopVar] : y ) { // y has to be unresolved.
2563 int z = loopV^;
2564 }
2565 }
2566 )cpp");
2567 EXPECT_THAT(R.Completions, ElementsAre(Named("loopVar")));
2568}
2569
Kadir Cetinkaya60ec08f2019-02-26 14:23:47 +00002570TEST(CompletionTest, UsingDecl) {
2571 const char *Header(R"cpp(
2572 void foo(int);
2573 namespace std {
2574 using ::foo;
2575 })cpp");
2576 const char *Source(R"cpp(
2577 void bar() {
2578 std::^;
2579 })cpp");
2580 auto Index = TestTU::withHeaderCode(Header).index();
2581 clangd::CodeCompleteOptions Opts;
2582 Opts.Index = Index.get();
2583 Opts.AllScopes = true;
2584 auto R = completions(Source, {}, Opts);
2585 EXPECT_THAT(R.Completions,
2586 ElementsAre(AllOf(Scope("std::"), Named("foo"),
2587 Kind(CompletionItemKind::Reference))));
2588}
2589
Eric Liue98b86c2019-02-27 11:42:37 +00002590TEST(CompletionTest, ScopeIsUnresolved) {
2591 clangd::CodeCompleteOptions Opts = {};
2592 Opts.AllScopes = true;
2593
2594 auto Results = completions(R"cpp(
2595 namespace a {
2596 void f() { b::X^ }
2597 }
2598 )cpp",
2599 {cls("a::b::XYZ")}, Opts);
2600 EXPECT_THAT(Results.Completions,
2601 UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ"))));
2602}
2603
2604TEST(CompletionTest, NestedScopeIsUnresolved) {
2605 clangd::CodeCompleteOptions Opts = {};
2606 Opts.AllScopes = true;
2607
2608 auto Results = completions(R"cpp(
2609 namespace a {
2610 namespace b {}
2611 void f() { b::c::X^ }
2612 }
2613 )cpp",
2614 {cls("a::b::c::XYZ")}, Opts);
2615 EXPECT_THAT(Results.Completions,
2616 UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ"))));
2617}
2618
Sam McCallb814e572019-04-10 15:16:54 +00002619// Clang parser gets confused here and doesn't report the ns:: prefix.
2620// Naive behavior is to insert it again. We examine the source and recover.
2621TEST(CompletionTest, NamespaceDoubleInsertion) {
Sam McCall6f997832019-04-10 11:50:40 +00002622 clangd::CodeCompleteOptions Opts = {};
2623
2624 auto Results = completions(R"cpp(
Sam McCallb814e572019-04-10 15:16:54 +00002625 namespace foo {
Sam McCall6f997832019-04-10 11:50:40 +00002626 namespace ns {}
2627 #define M(X) < X
2628 M(ns::ABC^
Sam McCallb814e572019-04-10 15:16:54 +00002629 }
Sam McCall6f997832019-04-10 11:50:40 +00002630 )cpp",
Sam McCallb814e572019-04-10 15:16:54 +00002631 {cls("foo::ns::ABCDE")}, Opts);
Sam McCall6f997832019-04-10 11:50:40 +00002632 EXPECT_THAT(Results.Completions,
2633 UnorderedElementsAre(AllOf(Qualifier(""), Named("ABCDE"))));
2634}
2635
Ilya Biryukov8613e902019-10-04 08:10:27 +00002636TEST(CompletionTest, DerivedMethodsAreAlwaysVisible) {
2637 // Despite the fact that base method matches the ref-qualifier better,
2638 // completion results should only include the derived method.
2639 auto Completions = completions(R"cpp(
2640 struct deque_base {
2641 float size();
2642 double size() const;
2643 };
2644 struct deque : deque_base {
2645 int size() const;
2646 };
2647
2648 auto x = deque().^
2649 )cpp")
2650 .Completions;
2651 EXPECT_THAT(Completions,
2652 ElementsAre(AllOf(ReturnType("int"), Named("size"))));
2653}
2654
Sam McCall26290352020-02-04 14:42:06 +01002655TEST(CompletionTest, NoCrashWithIncompleteLambda) {
2656 auto Completions = completions("auto&& x = []{^").Completions;
2657 // The completion of x itself can cause a problem: in the code completion
2658 // callback, its type is not known, which affects the linkage calculation.
2659 // A bad linkage value gets cached, and subsequently updated.
2660 EXPECT_THAT(Completions, Contains(Named("x")));
2661
2662 auto Signatures = signatures("auto x() { x(^").signatures;
2663 EXPECT_THAT(Signatures, Contains(Sig("x() -> auto")));
2664}
2665
Sam McCall038f03c2020-03-31 23:33:56 +02002666TEST(CompletionTest, DelayedTemplateParsing) {
2667 Annotations Test(R"cpp(
2668 int xxx;
2669 template <typename T> int foo() { return xx^; }
2670 )cpp");
2671 auto TU = TestTU::withCode(Test.code());
2672 // Even though delayed-template-parsing is on, we will disable it to provide
2673 // completion in templates.
2674 TU.ExtraArgs.push_back("-fdelayed-template-parsing");
2675
2676 EXPECT_THAT(completions(TU, Test.point()).Completions,
2677 Contains(Named("xxx")));
2678}
2679
Sam McCalld4df3722020-02-10 11:52:42 +01002680TEST(CompletionTest, CompletionRange) {
2681 const char *WithRange = "auto x = [[abc]]^";
2682 auto Completions = completions(WithRange);
2683 EXPECT_EQ(Completions.CompletionRange, Annotations(WithRange).range());
2684 Completions = completionsNoCompile(WithRange);
2685 EXPECT_EQ(Completions.CompletionRange, Annotations(WithRange).range());
2686
2687 const char *EmptyRange = "auto x = [[]]^";
2688 Completions = completions(EmptyRange);
2689 EXPECT_EQ(Completions.CompletionRange, Annotations(EmptyRange).range());
2690 Completions = completionsNoCompile(EmptyRange);
2691 EXPECT_EQ(Completions.CompletionRange, Annotations(EmptyRange).range());
2692
2693 // Sema doesn't trigger at all here, while the no-sema completion runs
2694 // heuristics as normal and reports a range. It'd be nice to be consistent.
2695 const char *NoCompletion = "/* [[]]^ */";
2696 Completions = completions(NoCompletion);
2697 EXPECT_EQ(Completions.CompletionRange, llvm::None);
2698 Completions = completionsNoCompile(NoCompletion);
2699 EXPECT_EQ(Completions.CompletionRange, Annotations(NoCompletion).range());
2700}
2701
Eric Liu00d99bd2019-04-11 09:36:36 +00002702TEST(NoCompileCompletionTest, Basic) {
2703 auto Results = completionsNoCompile(R"cpp(
2704 void func() {
2705 int xyz;
2706 int abc;
2707 ^
2708 }
2709 )cpp");
Sam McCall8940f462019-05-06 12:03:26 +00002710 EXPECT_FALSE(Results.RanParser);
Eric Liu00d99bd2019-04-11 09:36:36 +00002711 EXPECT_THAT(Results.Completions,
2712 UnorderedElementsAre(Named("void"), Named("func"), Named("int"),
2713 Named("xyz"), Named("abc")));
2714}
2715
2716TEST(NoCompileCompletionTest, WithFilter) {
2717 auto Results = completionsNoCompile(R"cpp(
2718 void func() {
2719 int sym1;
2720 int sym2;
2721 int xyz1;
2722 int xyz2;
2723 sy^
2724 }
2725 )cpp");
2726 EXPECT_THAT(Results.Completions,
2727 UnorderedElementsAre(Named("sym1"), Named("sym2")));
2728}
2729
Sam McCallc316b222019-04-26 07:45:49 +00002730TEST(NoCompileCompletionTest, WithIndex) {
2731 std::vector<Symbol> Syms = {func("xxx"), func("a::xxx"), func("ns::b::xxx"),
2732 func("c::xxx"), func("ns::d::xxx")};
2733 auto Results = completionsNoCompile(
2734 R"cpp(
2735 // Current-scopes, unqualified completion.
2736 using namespace a;
2737 namespace ns {
2738 using namespace b;
2739 void foo() {
2740 xx^
2741 }
Ilya Biryukov2fe0a142019-08-01 11:05:06 +00002742 }
Sam McCallc316b222019-04-26 07:45:49 +00002743 )cpp",
2744 Syms);
2745 EXPECT_THAT(Results.Completions,
2746 UnorderedElementsAre(AllOf(Qualifier(""), Scope("")),
2747 AllOf(Qualifier(""), Scope("a::")),
2748 AllOf(Qualifier(""), Scope("ns::b::"))));
2749 CodeCompleteOptions Opts;
2750 Opts.AllScopes = true;
2751 Results = completionsNoCompile(
2752 R"cpp(
2753 // All-scopes unqualified completion.
2754 using namespace a;
2755 namespace ns {
2756 using namespace b;
2757 void foo() {
2758 xx^
2759 }
Ilya Biryukov2fe0a142019-08-01 11:05:06 +00002760 }
Sam McCallc316b222019-04-26 07:45:49 +00002761 )cpp",
2762 Syms, Opts);
2763 EXPECT_THAT(Results.Completions,
2764 UnorderedElementsAre(AllOf(Qualifier(""), Scope("")),
2765 AllOf(Qualifier(""), Scope("a::")),
2766 AllOf(Qualifier(""), Scope("ns::b::")),
2767 AllOf(Qualifier("c::"), Scope("c::")),
2768 AllOf(Qualifier("d::"), Scope("ns::d::"))));
2769 Results = completionsNoCompile(
2770 R"cpp(
2771 // Qualified completion.
2772 using namespace a;
2773 namespace ns {
2774 using namespace b;
2775 void foo() {
2776 b::xx^
2777 }
Ilya Biryukov2fe0a142019-08-01 11:05:06 +00002778 }
Sam McCallc316b222019-04-26 07:45:49 +00002779 )cpp",
2780 Syms, Opts);
2781 EXPECT_THAT(Results.Completions,
2782 ElementsAre(AllOf(Qualifier(""), Scope("ns::b::"))));
2783 Results = completionsNoCompile(
2784 R"cpp(
2785 // Absolutely qualified completion.
2786 using namespace a;
2787 namespace ns {
2788 using namespace b;
2789 void foo() {
2790 ::a::xx^
2791 }
Ilya Biryukov2fe0a142019-08-01 11:05:06 +00002792 }
Sam McCallc316b222019-04-26 07:45:49 +00002793 )cpp",
2794 Syms, Opts);
2795 EXPECT_THAT(Results.Completions,
2796 ElementsAre(AllOf(Qualifier(""), Scope("a::"))));
2797}
2798
Sam McCall9aad25f2017-12-05 07:20:26 +00002799} // namespace
2800} // namespace clangd
2801} // namespace clang