blob: 9df895cd7399d64c1107167e44ba9119a0e0d95e [file] [log] [blame]
Sam McCallc5707b62018-05-15 17:43:27 +00001//===-- SourceCodeTests.cpp ------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Evaluating scoring functions isn't a great fit for assert-based tests.
11// For interesting cases, both exact scores and "X beats Y" are too brittle to
12// make good hard assertions.
13//
14// Here we test the signal extraction and sanity-check that signals point in
15// the right direction. This should be supplemented by quality metrics which
16// we can compute from a corpus of queries and preferred rankings.
17//
18//===----------------------------------------------------------------------===//
19
Sam McCall3f0243f2018-07-03 08:09:29 +000020#include "FileDistance.h"
Sam McCallc5707b62018-05-15 17:43:27 +000021#include "Quality.h"
Eric Liu09c3c372018-06-15 08:58:12 +000022#include "TestFS.h"
Sam McCallc5707b62018-05-15 17:43:27 +000023#include "TestTU.h"
Eric Liu8944f0e2018-07-05 08:14:04 +000024#include "clang/AST/Decl.h"
25#include "clang/AST/DeclCXX.h"
Eric Liud7de8112018-07-24 08:51:52 +000026#include "clang/AST/Type.h"
Eric Liu5d2a8072018-07-23 10:56:37 +000027#include "clang/Sema/CodeCompleteConsumer.h"
Eric Liu8944f0e2018-07-05 08:14:04 +000028#include "llvm/Support/Casting.h"
Sam McCallc5707b62018-05-15 17:43:27 +000029#include "gmock/gmock.h"
30#include "gtest/gtest.h"
Eric Liu3fac4ef2018-10-17 11:19:02 +000031#include <vector>
Sam McCallc5707b62018-05-15 17:43:27 +000032
Sam McCallc008af62018-10-20 15:30:37 +000033using namespace llvm;
Sam McCallc5707b62018-05-15 17:43:27 +000034namespace clang {
35namespace clangd {
Eric Liu09c3c372018-06-15 08:58:12 +000036
37// Force the unittest URI scheme to be linked,
38static int LLVM_ATTRIBUTE_UNUSED UnittestSchemeAnchorDest =
39 UnittestSchemeAnchorSource;
40
Sam McCallc5707b62018-05-15 17:43:27 +000041namespace {
42
43TEST(QualityTests, SymbolQualitySignalExtraction) {
44 auto Header = TestTU::withHeaderCode(R"cpp(
Sam McCalle018b362018-06-08 09:36:34 +000045 int _X;
Sam McCallc5707b62018-05-15 17:43:27 +000046
47 [[deprecated]]
Sam McCalle018b362018-06-08 09:36:34 +000048 int _f() { return _X; }
Eric Liu48597382018-10-18 12:23:05 +000049
50 #define DECL_NAME(x, y) x##_##y##_Decl
51 #define DECL(x, y) class DECL_NAME(x, y) {};
52 DECL(X, Y); // X_Y_Decl
53
54 class MAC {};
Sam McCallc5707b62018-05-15 17:43:27 +000055 )cpp");
Eric Liu48597382018-10-18 12:23:05 +000056 Header.ExtraArgs = {"-DMAC=mac_name"};
57
Sam McCallc5707b62018-05-15 17:43:27 +000058 auto Symbols = Header.headerSymbols();
59 auto AST = Header.build();
60
61 SymbolQualitySignals Quality;
Sam McCalle018b362018-06-08 09:36:34 +000062 Quality.merge(findSymbol(Symbols, "_X"));
Sam McCallc5707b62018-05-15 17:43:27 +000063 EXPECT_FALSE(Quality.Deprecated);
Eric Liu48597382018-10-18 12:23:05 +000064 EXPECT_FALSE(Quality.ImplementationDetail);
Sam McCalle018b362018-06-08 09:36:34 +000065 EXPECT_TRUE(Quality.ReservedName);
Sam McCallc5707b62018-05-15 17:43:27 +000066 EXPECT_EQ(Quality.References, SymbolQualitySignals().References);
Sam McCall4a3c69b2018-06-06 08:53:36 +000067 EXPECT_EQ(Quality.Category, SymbolQualitySignals::Variable);
Sam McCallc5707b62018-05-15 17:43:27 +000068
Eric Liu48597382018-10-18 12:23:05 +000069 Quality.merge(findSymbol(Symbols, "X_Y_Decl"));
70 EXPECT_TRUE(Quality.ImplementationDetail);
71
72 Quality.ImplementationDetail = false;
73 Quality.merge(
74 CodeCompletionResult(&findDecl(AST, "mac_name"), /*Priority=*/42));
75 EXPECT_TRUE(Quality.ImplementationDetail);
76
Sam McCalle018b362018-06-08 09:36:34 +000077 Symbol F = findSymbol(Symbols, "_f");
Sam McCallc5707b62018-05-15 17:43:27 +000078 F.References = 24; // TestTU doesn't count references, so fake it.
79 Quality = {};
80 Quality.merge(F);
Eric Liu6df66002018-09-06 18:52:26 +000081 EXPECT_TRUE(Quality.Deprecated);
Sam McCalle018b362018-06-08 09:36:34 +000082 EXPECT_FALSE(Quality.ReservedName);
Sam McCallc5707b62018-05-15 17:43:27 +000083 EXPECT_EQ(Quality.References, 24u);
Sam McCall4a3c69b2018-06-06 08:53:36 +000084 EXPECT_EQ(Quality.Category, SymbolQualitySignals::Function);
Sam McCallc5707b62018-05-15 17:43:27 +000085
86 Quality = {};
Sam McCalle018b362018-06-08 09:36:34 +000087 Quality.merge(CodeCompletionResult(&findDecl(AST, "_f"), /*Priority=*/42));
Sam McCallc5707b62018-05-15 17:43:27 +000088 EXPECT_TRUE(Quality.Deprecated);
Sam McCalle018b362018-06-08 09:36:34 +000089 EXPECT_FALSE(Quality.ReservedName);
Sam McCallc5707b62018-05-15 17:43:27 +000090 EXPECT_EQ(Quality.References, SymbolQualitySignals().References);
Sam McCall4a3c69b2018-06-06 08:53:36 +000091 EXPECT_EQ(Quality.Category, SymbolQualitySignals::Function);
Sam McCallc3b5bad2018-06-14 13:42:21 +000092
93 Quality = {};
94 Quality.merge(CodeCompletionResult("if"));
95 EXPECT_EQ(Quality.Category, SymbolQualitySignals::Keyword);
Sam McCallc5707b62018-05-15 17:43:27 +000096}
97
98TEST(QualityTests, SymbolRelevanceSignalExtraction) {
Ilya Biryukovf0296462018-06-04 14:50:59 +000099 TestTU Test;
100 Test.HeaderCode = R"cpp(
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000101 int header();
102 int header_main();
103
104 namespace hdr { class Bar {}; } // namespace hdr
105
106 #define DEFINE_FLAG(X) \
107 namespace flags { \
108 int FLAGS_##X; \
109 } \
110
111 DEFINE_FLAG(FOO)
112 )cpp";
Ilya Biryukovf0296462018-06-04 14:50:59 +0000113 Test.Code = R"cpp(
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000114 using hdr::Bar;
Sam McCallc5707b62018-05-15 17:43:27 +0000115
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000116 using flags::FLAGS_FOO;
Sam McCalld9b54f02018-06-05 16:30:25 +0000117
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000118 int ::header_main() {}
119 int main();
120
121 [[deprecated]]
122 int deprecated() { return 0; }
123
124 namespace { struct X { void y() { int z; } }; }
125 struct S{}
Ilya Biryukovf0296462018-06-04 14:50:59 +0000126 )cpp";
127 auto AST = Test.build();
128
Sam McCalldb41e1c2018-06-05 12:22:43 +0000129 SymbolRelevanceSignals Relevance;
130 Relevance.merge(CodeCompletionResult(&findDecl(AST, "deprecated"),
131 /*Priority=*/42, nullptr, false,
132 /*Accessible=*/false));
133 EXPECT_EQ(Relevance.NameMatch, SymbolRelevanceSignals().NameMatch);
134 EXPECT_TRUE(Relevance.Forbidden);
Sam McCalld9b54f02018-06-05 16:30:25 +0000135 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::GlobalScope);
Ilya Biryukovf0296462018-06-04 14:50:59 +0000136
Sam McCalldb41e1c2018-06-05 12:22:43 +0000137 Relevance = {};
138 Relevance.merge(CodeCompletionResult(&findDecl(AST, "main"), 42));
Eric Liu3fac4ef2018-10-17 11:19:02 +0000139 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f)
140 << "Decl in current file";
Sam McCalldb41e1c2018-06-05 12:22:43 +0000141 Relevance = {};
142 Relevance.merge(CodeCompletionResult(&findDecl(AST, "header"), 42));
Eric Liu3fac4ef2018-10-17 11:19:02 +0000143 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 0.6f) << "Decl from header";
Sam McCalldb41e1c2018-06-05 12:22:43 +0000144 Relevance = {};
145 Relevance.merge(CodeCompletionResult(&findDecl(AST, "header_main"), 42));
Eric Liu3fac4ef2018-10-17 11:19:02 +0000146 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f)
Eric Liu09c3c372018-06-15 08:58:12 +0000147 << "Current file and header";
Sam McCalld9b54f02018-06-05 16:30:25 +0000148
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000149 auto constructShadowDeclCompletionResult = [&](const std::string DeclName) {
150 auto *Shadow =
151 *dyn_cast<UsingDecl>(
152 &findAnyDecl(AST,
153 [&](const NamedDecl &ND) {
154 if (const UsingDecl *Using =
155 dyn_cast<UsingDecl>(&ND))
156 if (Using->shadow_size() &&
157 Using->getQualifiedNameAsString() == DeclName)
158 return true;
159 return false;
160 }))
161 ->shadow_begin();
162 CodeCompletionResult Result(Shadow->getTargetDecl(), 42);
163 Result.ShadowDecl = Shadow;
164 return Result;
165 };
166
167 Relevance = {};
168 Relevance.merge(constructShadowDeclCompletionResult("Bar"));
Eric Liu3fac4ef2018-10-17 11:19:02 +0000169 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f)
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000170 << "Using declaration in main file";
171 Relevance.merge(constructShadowDeclCompletionResult("FLAGS_FOO"));
Eric Liu3fac4ef2018-10-17 11:19:02 +0000172 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f)
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000173 << "Using declaration in main file";
174
Sam McCalld9b54f02018-06-05 16:30:25 +0000175 Relevance = {};
176 Relevance.merge(CodeCompletionResult(&findAnyDecl(AST, "X"), 42));
177 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FileScope);
178 Relevance = {};
179 Relevance.merge(CodeCompletionResult(&findAnyDecl(AST, "y"), 42));
180 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::ClassScope);
181 Relevance = {};
182 Relevance.merge(CodeCompletionResult(&findAnyDecl(AST, "z"), 42));
183 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FunctionScope);
Sam McCallabe37372018-06-27 11:43:54 +0000184 // The injected class name is treated as the outer class name.
185 Relevance = {};
186 Relevance.merge(CodeCompletionResult(&findDecl(AST, "S::S"), 42));
187 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::GlobalScope);
Eric Liu52a11b52018-10-24 13:45:17 +0000188
189 Relevance = {};
190 EXPECT_FALSE(Relevance.InBaseClass);
191 auto BaseMember = CodeCompletionResult(&findAnyDecl(AST, "y"), 42);
192 BaseMember.InBaseClass = true;
193 Relevance.merge(BaseMember);
194 EXPECT_TRUE(Relevance.InBaseClass);
Sam McCallc5707b62018-05-15 17:43:27 +0000195}
196
197// Do the signals move the scores in the direction we expect?
198TEST(QualityTests, SymbolQualitySignalsSanity) {
199 SymbolQualitySignals Default;
200 EXPECT_EQ(Default.evaluate(), 1);
201
202 SymbolQualitySignals Deprecated;
203 Deprecated.Deprecated = true;
204 EXPECT_LT(Deprecated.evaluate(), Default.evaluate());
205
Sam McCalle018b362018-06-08 09:36:34 +0000206 SymbolQualitySignals ReservedName;
207 ReservedName.ReservedName = true;
208 EXPECT_LT(ReservedName.evaluate(), Default.evaluate());
209
Eric Liu48597382018-10-18 12:23:05 +0000210 SymbolQualitySignals ImplementationDetail;
211 ImplementationDetail.ImplementationDetail = true;
212 EXPECT_LT(ImplementationDetail.evaluate(), Default.evaluate());
213
Sam McCallc5707b62018-05-15 17:43:27 +0000214 SymbolQualitySignals WithReferences, ManyReferences;
Eric Liucdc5f6a2018-06-28 16:51:12 +0000215 WithReferences.References = 20;
Sam McCallc5707b62018-05-15 17:43:27 +0000216 ManyReferences.References = 1000;
217 EXPECT_GT(WithReferences.evaluate(), Default.evaluate());
218 EXPECT_GT(ManyReferences.evaluate(), WithReferences.evaluate());
219
Eric Liud7de8112018-07-24 08:51:52 +0000220 SymbolQualitySignals Keyword, Variable, Macro, Constructor, Function;
Sam McCallc3b5bad2018-06-14 13:42:21 +0000221 Keyword.Category = SymbolQualitySignals::Keyword;
Sam McCall4a3c69b2018-06-06 08:53:36 +0000222 Variable.Category = SymbolQualitySignals::Variable;
223 Macro.Category = SymbolQualitySignals::Macro;
Eric Liud7de8112018-07-24 08:51:52 +0000224 Constructor.Category = SymbolQualitySignals::Constructor;
225 Function.Category = SymbolQualitySignals::Function;
Sam McCall4a3c69b2018-06-06 08:53:36 +0000226 EXPECT_GT(Variable.evaluate(), Default.evaluate());
Sam McCallc3b5bad2018-06-14 13:42:21 +0000227 EXPECT_GT(Keyword.evaluate(), Variable.evaluate());
Sam McCall4a3c69b2018-06-06 08:53:36 +0000228 EXPECT_LT(Macro.evaluate(), Default.evaluate());
Eric Liud7de8112018-07-24 08:51:52 +0000229 EXPECT_LT(Constructor.evaluate(), Function.evaluate());
Sam McCallc5707b62018-05-15 17:43:27 +0000230}
231
232TEST(QualityTests, SymbolRelevanceSignalsSanity) {
233 SymbolRelevanceSignals Default;
234 EXPECT_EQ(Default.evaluate(), 1);
235
236 SymbolRelevanceSignals Forbidden;
237 Forbidden.Forbidden = true;
238 EXPECT_LT(Forbidden.evaluate(), Default.evaluate());
239
240 SymbolRelevanceSignals PoorNameMatch;
Aaron Ballman655ef182018-05-18 14:53:32 +0000241 PoorNameMatch.NameMatch = 0.2f;
Sam McCallc5707b62018-05-15 17:43:27 +0000242 EXPECT_LT(PoorNameMatch.evaluate(), Default.evaluate());
Ilya Biryukovf0296462018-06-04 14:50:59 +0000243
Eric Liu3fac4ef2018-10-17 11:19:02 +0000244 SymbolRelevanceSignals WithSemaFileProximity;
245 WithSemaFileProximity.SemaFileProximityScore = 0.2f;
246 EXPECT_GT(WithSemaFileProximity.evaluate(), Default.evaluate());
247
248 ScopeDistance ScopeProximity({"x::y::"});
249
250 SymbolRelevanceSignals WithSemaScopeProximity;
251 WithSemaScopeProximity.ScopeProximityMatch = &ScopeProximity;
252 WithSemaScopeProximity.SemaSaysInScope = true;
253 EXPECT_GT(WithSemaScopeProximity.evaluate(), Default.evaluate());
254
255 SymbolRelevanceSignals WithIndexScopeProximity;
256 WithIndexScopeProximity.ScopeProximityMatch = &ScopeProximity;
257 WithIndexScopeProximity.SymbolScope = "x::";
258 EXPECT_GT(WithSemaScopeProximity.evaluate(), Default.evaluate());
Sam McCall3f0243f2018-07-03 08:09:29 +0000259
260 SymbolRelevanceSignals IndexProximate;
261 IndexProximate.SymbolURI = "unittest:/foo/bar.h";
Sam McCallc008af62018-10-20 15:30:37 +0000262 StringMap<SourceParams> ProxSources;
Sam McCall3f0243f2018-07-03 08:09:29 +0000263 ProxSources.try_emplace(testPath("foo/baz.h"));
264 URIDistance Distance(ProxSources);
265 IndexProximate.FileProximityMatch = &Distance;
266 EXPECT_GT(IndexProximate.evaluate(), Default.evaluate());
267 SymbolRelevanceSignals IndexDistant = IndexProximate;
268 IndexDistant.SymbolURI = "unittest:/elsewhere/path.h";
269 EXPECT_GT(IndexProximate.evaluate(), IndexDistant.evaluate())
270 << IndexProximate << IndexDistant;
271 EXPECT_GT(IndexDistant.evaluate(), Default.evaluate());
Sam McCalld9b54f02018-06-05 16:30:25 +0000272
273 SymbolRelevanceSignals Scoped;
274 Scoped.Scope = SymbolRelevanceSignals::FileScope;
275 EXPECT_EQ(Scoped.evaluate(), Default.evaluate());
276 Scoped.Query = SymbolRelevanceSignals::CodeComplete;
277 EXPECT_GT(Scoped.evaluate(), Default.evaluate());
Eric Liu5d2a8072018-07-23 10:56:37 +0000278
279 SymbolRelevanceSignals Instance;
280 Instance.IsInstanceMember = false;
281 EXPECT_EQ(Instance.evaluate(), Default.evaluate());
282 Instance.Context = CodeCompletionContext::CCC_DotMemberAccess;
283 EXPECT_LT(Instance.evaluate(), Default.evaluate());
284 Instance.IsInstanceMember = true;
285 EXPECT_EQ(Instance.evaluate(), Default.evaluate());
Eric Liu52a11b52018-10-24 13:45:17 +0000286
287 SymbolRelevanceSignals InBaseClass;
288 InBaseClass.InBaseClass = true;
289 EXPECT_LT(InBaseClass.evaluate(), Default.evaluate());
Sam McCallc5707b62018-05-15 17:43:27 +0000290}
291
Eric Liu3fac4ef2018-10-17 11:19:02 +0000292TEST(QualityTests, ScopeProximity) {
293 SymbolRelevanceSignals Relevance;
294 ScopeDistance ScopeProximity({"x::y::z::", "x::", "llvm::", ""});
295 Relevance.ScopeProximityMatch = &ScopeProximity;
296
297 Relevance.SymbolScope = "other::";
298 float NotMatched = Relevance.evaluate();
299
300 Relevance.SymbolScope = "";
301 float Global = Relevance.evaluate();
302 EXPECT_GT(Global, NotMatched);
303
304 Relevance.SymbolScope = "llvm::";
305 float NonParent = Relevance.evaluate();
306 EXPECT_GT(NonParent, Global);
307
308 Relevance.SymbolScope = "x::";
309 float GrandParent = Relevance.evaluate();
310 EXPECT_GT(GrandParent, Global);
311
312 Relevance.SymbolScope = "x::y::";
313 float Parent = Relevance.evaluate();
314 EXPECT_GT(Parent, GrandParent);
315
316 Relevance.SymbolScope = "x::y::z::";
317 float Enclosing = Relevance.evaluate();
318 EXPECT_GT(Enclosing, Parent);
319}
320
Sam McCallc5707b62018-05-15 17:43:27 +0000321TEST(QualityTests, SortText) {
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000322 EXPECT_LT(sortText(std::numeric_limits<float>::infinity()),
323 sortText(1000.2f));
Aaron Ballman655ef182018-05-18 14:53:32 +0000324 EXPECT_LT(sortText(1000.2f), sortText(1));
325 EXPECT_LT(sortText(1), sortText(0.3f));
326 EXPECT_LT(sortText(0.3f), sortText(0));
Sam McCallc5707b62018-05-15 17:43:27 +0000327 EXPECT_LT(sortText(0), sortText(-10));
328 EXPECT_LT(sortText(-10), sortText(-std::numeric_limits<float>::infinity()));
329
330 EXPECT_LT(sortText(1, "z"), sortText(0, "a"));
331 EXPECT_LT(sortText(0, "a"), sortText(0, "z"));
332}
333
Eric Liu8944f0e2018-07-05 08:14:04 +0000334TEST(QualityTests, NoBoostForClassConstructor) {
335 auto Header = TestTU::withHeaderCode(R"cpp(
336 class Foo {
337 public:
338 Foo(int);
339 };
340 )cpp");
341 auto Symbols = Header.headerSymbols();
342 auto AST = Header.build();
343
344 const NamedDecl *Foo = &findDecl(AST, "Foo");
345 SymbolRelevanceSignals Cls;
346 Cls.merge(CodeCompletionResult(Foo, /*Priority=*/0));
347
348 const NamedDecl *CtorDecl = &findAnyDecl(AST, [](const NamedDecl &ND) {
349 return (ND.getQualifiedNameAsString() == "Foo::Foo") &&
Sam McCallc008af62018-10-20 15:30:37 +0000350 isa<CXXConstructorDecl>(&ND);
Eric Liu8944f0e2018-07-05 08:14:04 +0000351 });
352 SymbolRelevanceSignals Ctor;
353 Ctor.merge(CodeCompletionResult(CtorDecl, /*Priority=*/0));
354
355 EXPECT_EQ(Cls.Scope, SymbolRelevanceSignals::GlobalScope);
356 EXPECT_EQ(Ctor.Scope, SymbolRelevanceSignals::GlobalScope);
357}
358
Eric Liu5d2a8072018-07-23 10:56:37 +0000359TEST(QualityTests, IsInstanceMember) {
360 auto Header = TestTU::withHeaderCode(R"cpp(
361 class Foo {
362 public:
363 static void foo() {}
364
365 template <typename T> void tpl(T *t) {}
366
367 void bar() {}
368 };
369 )cpp");
370 auto Symbols = Header.headerSymbols();
371
372 SymbolRelevanceSignals Rel;
373 const Symbol &FooSym = findSymbol(Symbols, "Foo::foo");
374 Rel.merge(FooSym);
375 EXPECT_FALSE(Rel.IsInstanceMember);
376 const Symbol &BarSym = findSymbol(Symbols, "Foo::bar");
377 Rel.merge(BarSym);
378 EXPECT_TRUE(Rel.IsInstanceMember);
379
380 Rel.IsInstanceMember =false;
381 const Symbol &TplSym = findSymbol(Symbols, "Foo::tpl");
382 Rel.merge(TplSym);
383 EXPECT_TRUE(Rel.IsInstanceMember);
384
385 auto AST = Header.build();
386 const NamedDecl *Foo = &findDecl(AST, "Foo::foo");
387 const NamedDecl *Bar = &findDecl(AST, "Foo::bar");
388 const NamedDecl *Tpl = &findDecl(AST, "Foo::tpl");
389
390 Rel.IsInstanceMember = false;
391 Rel.merge(CodeCompletionResult(Foo, /*Priority=*/0));
392 EXPECT_FALSE(Rel.IsInstanceMember);
393 Rel.merge(CodeCompletionResult(Bar, /*Priority=*/0));
394 EXPECT_TRUE(Rel.IsInstanceMember);
395 Rel.IsInstanceMember = false;
396 Rel.merge(CodeCompletionResult(Tpl, /*Priority=*/0));
397 EXPECT_TRUE(Rel.IsInstanceMember);
398}
399
Eric Liud7de8112018-07-24 08:51:52 +0000400TEST(QualityTests, ConstructorQuality) {
401 auto Header = TestTU::withHeaderCode(R"cpp(
402 class Foo {
403 public:
404 Foo(int);
405 };
406 )cpp");
407 auto Symbols = Header.headerSymbols();
408 auto AST = Header.build();
409
410 const NamedDecl *CtorDecl = &findAnyDecl(AST, [](const NamedDecl &ND) {
411 return (ND.getQualifiedNameAsString() == "Foo::Foo") &&
Sam McCallc008af62018-10-20 15:30:37 +0000412 isa<CXXConstructorDecl>(&ND);
Eric Liud7de8112018-07-24 08:51:52 +0000413 });
414
415 SymbolQualitySignals Q;
416 Q.merge(CodeCompletionResult(CtorDecl, /*Priority=*/0));
417 EXPECT_EQ(Q.Category, SymbolQualitySignals::Constructor);
418
419 Q.Category = SymbolQualitySignals::Unknown;
420 const Symbol &CtorSym = findSymbol(Symbols, "Foo::Foo");
421 Q.merge(CtorSym);
422 EXPECT_EQ(Q.Category, SymbolQualitySignals::Constructor);
423}
424
Kadir Cetinkaya2f84d912018-08-08 08:59:29 +0000425TEST(QualityTests, ItemWithFixItsRankedDown) {
426 CodeCompleteOptions Opts;
427 Opts.IncludeFixIts = true;
428
429 auto Header = TestTU::withHeaderCode(R"cpp(
430 int x;
431 )cpp");
432 auto AST = Header.build();
433
434 SymbolRelevanceSignals RelevanceWithFixIt;
435 RelevanceWithFixIt.merge(CodeCompletionResult(&findDecl(AST, "x"), 0, nullptr,
436 false, true, {FixItHint{}}));
437 EXPECT_TRUE(RelevanceWithFixIt.NeedsFixIts);
438
439 SymbolRelevanceSignals RelevanceWithoutFixIt;
440 RelevanceWithoutFixIt.merge(
441 CodeCompletionResult(&findDecl(AST, "x"), 0, nullptr, false, true, {}));
442 EXPECT_FALSE(RelevanceWithoutFixIt.NeedsFixIts);
443
444 EXPECT_LT(RelevanceWithFixIt.evaluate(), RelevanceWithoutFixIt.evaluate());
445}
446
Sam McCallc5707b62018-05-15 17:43:27 +0000447} // namespace
448} // namespace clangd
449} // namespace clang