clang-tools 22.0.0git
QualityTests.cpp
Go to the documentation of this file.
1//===-- QualityTests.cpp ----------------------------------------*- C++ -*-===//
2//
3// 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
6//
7//===----------------------------------------------------------------------===//
8//
9// Evaluating scoring functions isn't a great fit for assert-based tests.
10// For interesting cases, both exact scores and "X beats Y" are too brittle to
11// make good hard assertions.
12//
13// Here we test the signal extraction and sanity-check that signals point in
14// the right direction. This should be supplemented by quality metrics which
15// we can compute from a corpus of queries and preferred rankings.
16//
17//===----------------------------------------------------------------------===//
18
19#include "FileDistance.h"
20#include "Quality.h"
21#include "TestFS.h"
22#include "TestTU.h"
23#include "index/FileIndex.h"
24#include "clang/AST/Decl.h"
25#include "clang/AST/DeclCXX.h"
26#include "clang/Sema/CodeCompleteConsumer.h"
27#include "llvm/Support/Casting.h"
28#include "gmock/gmock.h"
29#include "gtest/gtest.h"
30#include <vector>
31
32namespace clang {
33namespace clangd {
34
35// Force the unittest URI scheme to be linked,
36static int LLVM_ATTRIBUTE_UNUSED UnittestSchemeAnchorDest =
38
39namespace {
40
41TEST(QualityTests, SymbolQualitySignalExtraction) {
42 auto Header = TestTU::withHeaderCode(R"cpp(
43 int _X;
44
45 [[deprecated]]
46 int _f() { return _X; }
47
48 #define DECL_NAME(x, y) x##_##y##_Decl
49 #define DECL(x, y) class DECL_NAME(x, y) {};
50 DECL(X, Y); // X_Y_Decl
51 )cpp");
52
53 auto Symbols = Header.headerSymbols();
54 auto AST = Header.build();
55
57 Quality.merge(findSymbol(Symbols, "X_Y_Decl"));
58 EXPECT_TRUE(Quality.ImplementationDetail);
59
60 Symbol F = findSymbol(Symbols, "_f");
61 F.References = 24; // TestTU doesn't count references, so fake it.
62 Quality = {};
63 Quality.merge(F);
64 EXPECT_TRUE(Quality.Deprecated);
65 EXPECT_FALSE(Quality.ReservedName);
66 EXPECT_EQ(Quality.References, 24u);
67 EXPECT_EQ(Quality.Category, SymbolQualitySignals::Function);
68
69 Quality = {};
70 Quality.merge(CodeCompletionResult(&findDecl(AST, "_f"), /*Priority=*/42));
71 EXPECT_TRUE(Quality.Deprecated);
72 EXPECT_FALSE(Quality.ReservedName);
73 EXPECT_EQ(Quality.References, SymbolQualitySignals().References);
74 EXPECT_EQ(Quality.Category, SymbolQualitySignals::Function);
75
76 Quality = {};
77 Quality.merge(CodeCompletionResult("if"));
78 EXPECT_EQ(Quality.Category, SymbolQualitySignals::Keyword);
79
80 // Testing ReservedName in main file, we don't index those symbols in headers.
81 auto MainAST = TestTU::withCode("int _X;").build();
82 SymbolSlab MainSymbols = std::get<0>(indexMainDecls(MainAST));
83
84 Quality = {};
85 Quality.merge(findSymbol(MainSymbols, "_X"));
86 EXPECT_FALSE(Quality.Deprecated);
87 EXPECT_FALSE(Quality.ImplementationDetail);
88 EXPECT_TRUE(Quality.ReservedName);
89}
90
91TEST(QualityTests, SymbolRelevanceSignalExtraction) {
92 TestTU Test;
93 Test.HeaderCode = R"cpp(
94 int header();
95 int header_main();
96
97 namespace hdr { class Bar {}; } // namespace hdr
98
99 #define DEFINE_FLAG(X) \
100 namespace flags { \
101 int FLAGS_##X; \
102 } \
103
104 DEFINE_FLAG(FOO)
105 )cpp";
106 Test.Code = R"cpp(
107 using hdr::Bar;
108
109 using flags::FLAGS_FOO;
110
111 int ::header_main() { return 0; }
112 int main();
113
114 [[deprecated]]
115 int deprecated() { return 0; }
116
117 namespace { struct X { void y() { int z; } }; }
118 struct S{};
119 )cpp";
120 auto AST = Test.build();
121
122 SymbolRelevanceSignals Relevance;
123 Relevance.merge(CodeCompletionResult(&findDecl(AST, "deprecated"),
124 /*Priority=*/42,
125 /*Qualifier=*/std::nullopt,
126 /*QualifierIsInformative=*/false,
127 /*Accessible=*/false));
128 EXPECT_EQ(Relevance.NameMatch, SymbolRelevanceSignals().NameMatch);
129 EXPECT_TRUE(Relevance.Forbidden);
130 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::GlobalScope);
131
132 Relevance = {};
133 Relevance.merge(CodeCompletionResult(&findDecl(AST, "main"), 42));
134 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f)
135 << "Decl in current file";
136 Relevance = {};
137 Relevance.merge(CodeCompletionResult(&findDecl(AST, "header"), 42));
138 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 0.6f) << "Decl from header";
139 Relevance = {};
140 Relevance.merge(CodeCompletionResult(&findDecl(AST, "header_main"), 42));
141 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f)
142 << "Current file and header";
143
144 auto ConstructShadowDeclCompletionResult = [&](const std::string DeclName) {
145 auto *Shadow =
146 *dyn_cast<UsingDecl>(&findDecl(AST, [&](const NamedDecl &ND) {
147 if (const UsingDecl *Using = dyn_cast<UsingDecl>(&ND))
148 if (Using->shadow_size() &&
149 Using->getQualifiedNameAsString() == DeclName)
150 return true;
151 return false;
152 }))->shadow_begin();
153 CodeCompletionResult Result(Shadow->getTargetDecl(), 42);
154 Result.ShadowDecl = Shadow;
155 return Result;
156 };
157
158 Relevance = {};
159 Relevance.merge(ConstructShadowDeclCompletionResult("Bar"));
160 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f)
161 << "Using declaration in main file";
162 Relevance.merge(ConstructShadowDeclCompletionResult("FLAGS_FOO"));
163 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f)
164 << "Using declaration in main file";
165
166 Relevance = {};
167 Relevance.merge(CodeCompletionResult(&findUnqualifiedDecl(AST, "X"), 42));
168 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FileScope);
169 Relevance = {};
170 Relevance.merge(CodeCompletionResult(&findUnqualifiedDecl(AST, "y"), 42));
171 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::ClassScope);
172 Relevance = {};
173 Relevance.merge(CodeCompletionResult(&findUnqualifiedDecl(AST, "z"), 42));
174 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FunctionScope);
175 // The injected class name is treated as the outer class name.
176 Relevance = {};
177 Relevance.merge(CodeCompletionResult(&findDecl(AST, "S::S"), 42));
178 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::GlobalScope);
179
180 Relevance = {};
181 EXPECT_FALSE(Relevance.InBaseClass);
182 auto BaseMember = CodeCompletionResult(&findUnqualifiedDecl(AST, "y"), 42);
183 BaseMember.InBaseClass = true;
184 Relevance.merge(BaseMember);
185 EXPECT_TRUE(Relevance.InBaseClass);
186
187 auto Index = Test.index();
189 Req.Query = "X";
190 Req.AnyScope = true;
191 bool Matched = false;
192 Index->fuzzyFind(Req, [&](const Symbol &S) {
193 Matched = true;
194 Relevance = {};
195 Relevance.merge(S);
196 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FileScope);
197 });
198 EXPECT_TRUE(Matched);
199}
200
201// Do the signals move the scores in the direction we expect?
202TEST(QualityTests, SymbolQualitySignalsSanity) {
203 SymbolQualitySignals Default;
204 EXPECT_EQ(Default.evaluateHeuristics(), 1);
205
207 Deprecated.Deprecated = true;
208 EXPECT_LT(Deprecated.evaluateHeuristics(), Default.evaluateHeuristics());
209
210 SymbolQualitySignals ReservedName;
211 ReservedName.ReservedName = true;
212 EXPECT_LT(ReservedName.evaluateHeuristics(), Default.evaluateHeuristics());
213
214 SymbolQualitySignals ImplementationDetail;
215 ImplementationDetail.ImplementationDetail = true;
216 EXPECT_LT(ImplementationDetail.evaluateHeuristics(),
217 Default.evaluateHeuristics());
218
219 SymbolQualitySignals WithReferences, ManyReferences;
220 WithReferences.References = 20;
221 ManyReferences.References = 1000;
222 EXPECT_GT(WithReferences.evaluateHeuristics(), Default.evaluateHeuristics());
223 EXPECT_GT(ManyReferences.evaluateHeuristics(),
224 WithReferences.evaluateHeuristics());
225
227 Destructor, Operator;
236 EXPECT_GT(Variable.evaluateHeuristics(), Default.evaluateHeuristics());
237 EXPECT_GT(Keyword.evaluateHeuristics(), Variable.evaluateHeuristics());
238 EXPECT_LT(Macro.evaluateHeuristics(), Default.evaluateHeuristics());
239 EXPECT_LT(Operator.evaluateHeuristics(), Default.evaluateHeuristics());
240 EXPECT_LT(Constructor.evaluateHeuristics(), Function.evaluateHeuristics());
241 EXPECT_LT(Destructor.evaluateHeuristics(), Constructor.evaluateHeuristics());
242}
243
244TEST(QualityTests, SymbolRelevanceSignalsSanity) {
246 EXPECT_EQ(Default.evaluateHeuristics(), 1);
247
248 SymbolRelevanceSignals Forbidden;
249 Forbidden.Forbidden = true;
250 EXPECT_LT(Forbidden.evaluateHeuristics(), Default.evaluateHeuristics());
251
252 SymbolRelevanceSignals PoorNameMatch;
253 PoorNameMatch.NameMatch = 0.2f;
254 EXPECT_LT(PoorNameMatch.evaluateHeuristics(), Default.evaluateHeuristics());
255
256 SymbolRelevanceSignals WithSemaFileProximity;
257 WithSemaFileProximity.SemaFileProximityScore = 0.2f;
258 EXPECT_GT(WithSemaFileProximity.evaluateHeuristics(),
259 Default.evaluateHeuristics());
260
261 ScopeDistance ScopeProximity({"x::y::"});
262
263 SymbolRelevanceSignals WithSemaScopeProximity;
264 WithSemaScopeProximity.ScopeProximityMatch = &ScopeProximity;
265 WithSemaScopeProximity.SemaSaysInScope = true;
266 EXPECT_GT(WithSemaScopeProximity.evaluateHeuristics(),
267 Default.evaluateHeuristics());
268
269 SymbolRelevanceSignals WithIndexScopeProximity;
270 WithIndexScopeProximity.ScopeProximityMatch = &ScopeProximity;
271 WithIndexScopeProximity.SymbolScope = "x::";
272 EXPECT_GT(WithSemaScopeProximity.evaluateHeuristics(),
273 Default.evaluateHeuristics());
274
275 SymbolRelevanceSignals IndexProximate;
276 IndexProximate.SymbolURI = "unittest:/foo/bar.h";
277 llvm::StringMap<SourceParams> ProxSources;
278 ProxSources.try_emplace(testPath("foo/baz.h"));
279 URIDistance Distance(ProxSources);
280 IndexProximate.FileProximityMatch = &Distance;
281 EXPECT_GT(IndexProximate.evaluateHeuristics(), Default.evaluateHeuristics());
282 SymbolRelevanceSignals IndexDistant = IndexProximate;
283 IndexDistant.SymbolURI = "unittest:/elsewhere/path.h";
284 EXPECT_GT(IndexProximate.evaluateHeuristics(),
285 IndexDistant.evaluateHeuristics())
286 << IndexProximate << IndexDistant;
287 EXPECT_GT(IndexDistant.evaluateHeuristics(), Default.evaluateHeuristics());
288
291 EXPECT_LT(Scoped.evaluateHeuristics(), Default.evaluateHeuristics());
293 EXPECT_GT(Scoped.evaluateHeuristics(), Default.evaluateHeuristics());
294
295 SymbolRelevanceSignals Instance;
296 Instance.IsInstanceMember = false;
297 EXPECT_EQ(Instance.evaluateHeuristics(), Default.evaluateHeuristics());
298 Instance.Context = CodeCompletionContext::CCC_DotMemberAccess;
299 EXPECT_LT(Instance.evaluateHeuristics(), Default.evaluateHeuristics());
300 Instance.IsInstanceMember = true;
301 EXPECT_EQ(Instance.evaluateHeuristics(), Default.evaluateHeuristics());
302
303 SymbolRelevanceSignals InBaseClass;
304 InBaseClass.InBaseClass = true;
305 EXPECT_LT(InBaseClass.evaluateHeuristics(), Default.evaluateHeuristics());
306
307 llvm::StringSet<> Words = {"one", "two", "three"};
308 SymbolRelevanceSignals WithoutMatchingWord;
309 WithoutMatchingWord.ContextWords = &Words;
310 WithoutMatchingWord.Name = "four";
311 EXPECT_EQ(WithoutMatchingWord.evaluateHeuristics(),
312 Default.evaluateHeuristics());
313 SymbolRelevanceSignals WithMatchingWord;
314 WithMatchingWord.ContextWords = &Words;
315 WithMatchingWord.Name = "TheTwoTowers";
316 EXPECT_GT(WithMatchingWord.evaluateHeuristics(),
317 Default.evaluateHeuristics());
318}
319
320TEST(QualityTests, ScopeProximity) {
321 SymbolRelevanceSignals Relevance;
322 ScopeDistance ScopeProximity({"x::y::z::", "x::", "llvm::", ""});
323 Relevance.ScopeProximityMatch = &ScopeProximity;
324
325 Relevance.SymbolScope = "other::";
326 float NotMatched = Relevance.evaluateHeuristics();
327
328 Relevance.SymbolScope = "";
329 float Global = Relevance.evaluateHeuristics();
330 EXPECT_GT(Global, NotMatched);
331
332 Relevance.SymbolScope = "llvm::";
333 float NonParent = Relevance.evaluateHeuristics();
334 EXPECT_GT(NonParent, Global);
335
336 Relevance.SymbolScope = "x::";
337 float GrandParent = Relevance.evaluateHeuristics();
338 EXPECT_GT(GrandParent, Global);
339
340 Relevance.SymbolScope = "x::y::";
341 float Parent = Relevance.evaluateHeuristics();
342 EXPECT_GT(Parent, GrandParent);
343
344 Relevance.SymbolScope = "x::y::z::";
345 float Enclosing = Relevance.evaluateHeuristics();
346 EXPECT_GT(Enclosing, Parent);
347}
348
349TEST(QualityTests, SortText) {
350 EXPECT_LT(sortText(std::numeric_limits<float>::infinity()),
351 sortText(1000.2f));
352 EXPECT_LT(sortText(1000.2f), sortText(1));
353 EXPECT_LT(sortText(1), sortText(0.3f));
354 EXPECT_LT(sortText(0.3f), sortText(0));
355 EXPECT_LT(sortText(0), sortText(-10));
356 EXPECT_LT(sortText(-10), sortText(-std::numeric_limits<float>::infinity()));
357
358 EXPECT_LT(sortText(1, "z"), sortText(0, "a"));
359 EXPECT_LT(sortText(0, "a"), sortText(0, "z"));
360}
361
362TEST(QualityTests, NoBoostForClassConstructor) {
363 auto Header = TestTU::withHeaderCode(R"cpp(
364 class Foo {
365 public:
366 Foo(int);
367 };
368 )cpp");
369 auto Symbols = Header.headerSymbols();
370 auto AST = Header.build();
371
372 const NamedDecl *Foo = &findDecl(AST, "Foo");
374 Cls.merge(CodeCompletionResult(Foo, /*Priority=*/0));
375
376 const NamedDecl *CtorDecl = &findDecl(AST, [](const NamedDecl &ND) {
377 return (ND.getQualifiedNameAsString() == "Foo::Foo") &&
378 isa<CXXConstructorDecl>(&ND);
379 });
381 Ctor.merge(CodeCompletionResult(CtorDecl, /*Priority=*/0));
382
384 EXPECT_EQ(Ctor.Scope, SymbolRelevanceSignals::GlobalScope);
385}
386
387TEST(QualityTests, IsInstanceMember) {
388 auto Header = TestTU::withHeaderCode(R"cpp(
389 class Foo {
390 public:
391 static void foo() {}
392
393 template <typename T> void tpl(T *t) {}
394
395 void bar() {}
396 };
397 )cpp");
398 auto Symbols = Header.headerSymbols();
399
401 const Symbol &FooSym = findSymbol(Symbols, "Foo::foo");
402 Rel.merge(FooSym);
403 EXPECT_FALSE(Rel.IsInstanceMember);
404 const Symbol &BarSym = findSymbol(Symbols, "Foo::bar");
405 Rel.merge(BarSym);
406 EXPECT_TRUE(Rel.IsInstanceMember);
407
408 Rel.IsInstanceMember = false;
409 const Symbol &TplSym = findSymbol(Symbols, "Foo::tpl");
410 Rel.merge(TplSym);
411 EXPECT_TRUE(Rel.IsInstanceMember);
412
413 auto AST = Header.build();
414 const NamedDecl *Foo = &findDecl(AST, "Foo::foo");
415 const NamedDecl *Bar = &findDecl(AST, "Foo::bar");
416 const NamedDecl *Tpl = &findDecl(AST, "Foo::tpl");
417
418 Rel.IsInstanceMember = false;
419 Rel.merge(CodeCompletionResult(Foo, /*Priority=*/0));
420 EXPECT_FALSE(Rel.IsInstanceMember);
421 Rel.merge(CodeCompletionResult(Bar, /*Priority=*/0));
422 EXPECT_TRUE(Rel.IsInstanceMember);
423 Rel.IsInstanceMember = false;
424 Rel.merge(CodeCompletionResult(Tpl, /*Priority=*/0));
425 EXPECT_TRUE(Rel.IsInstanceMember);
426}
427
428TEST(QualityTests, ConstructorDestructor) {
429 auto Header = TestTU::withHeaderCode(R"cpp(
430 class Foo {
431 public:
432 Foo(int);
433 ~Foo();
434 };
435 )cpp");
436 auto Symbols = Header.headerSymbols();
437 auto AST = Header.build();
438
439 const NamedDecl *CtorDecl = &findDecl(AST, [](const NamedDecl &ND) {
440 return (ND.getQualifiedNameAsString() == "Foo::Foo") &&
441 isa<CXXConstructorDecl>(&ND);
442 });
443 const NamedDecl *DtorDecl = &findDecl(AST, [](const NamedDecl &ND) {
444 return (ND.getQualifiedNameAsString() == "Foo::~Foo") &&
445 isa<CXXDestructorDecl>(&ND);
446 });
447
449 CtorQ.merge(CodeCompletionResult(CtorDecl, /*Priority=*/0));
450 EXPECT_EQ(CtorQ.Category, SymbolQualitySignals::Constructor);
451
452 CtorQ.Category = SymbolQualitySignals::Unknown;
453 const Symbol &CtorSym = findSymbol(Symbols, "Foo::Foo");
454 CtorQ.merge(CtorSym);
455 EXPECT_EQ(CtorQ.Category, SymbolQualitySignals::Constructor);
456
458 DtorQ.merge(CodeCompletionResult(DtorDecl, /*Priority=*/0));
460}
461
462TEST(QualityTests, Operator) {
463 auto Header = TestTU::withHeaderCode(R"cpp(
464 class Foo {
465 public:
466 bool operator<(const Foo& f1);
467 };
468 )cpp");
469 auto AST = Header.build();
470
471 const NamedDecl *Operator = &findDecl(AST, [](const NamedDecl &ND) {
472 if (const auto *OD = dyn_cast<FunctionDecl>(&ND))
473 if (OD->isOverloadedOperator())
474 return true;
475 return false;
476 });
478 Q.merge(CodeCompletionResult(Operator, /*Priority=*/0));
479 EXPECT_EQ(Q.Category, SymbolQualitySignals::Operator);
480}
481
482TEST(QualityTests, ItemWithFixItsRankedDown) {
484 Opts.IncludeFixIts = true;
485
486 auto Header = TestTU::withHeaderCode(R"cpp(
487 int x;
488 )cpp");
489 auto AST = Header.build();
490
491 SymbolRelevanceSignals RelevanceWithFixIt;
492 RelevanceWithFixIt.merge(CodeCompletionResult(
493 &findDecl(AST, "x"), /*Priority=*/0, /*Qualifier=*/std::nullopt,
494 /*QualifierIsInformative=*/false, /*Accessible=*/true, {FixItHint{}}));
495 EXPECT_TRUE(RelevanceWithFixIt.NeedsFixIts);
496
497 SymbolRelevanceSignals RelevanceWithoutFixIt;
498 RelevanceWithoutFixIt.merge(CodeCompletionResult(
499 &findDecl(AST, "x"), /*Priority=*/0, /*Qualifier=*/std::nullopt,
500 /*QualifierIsInformative=*/false, /*Accessible=*/true, {}));
501 EXPECT_FALSE(RelevanceWithoutFixIt.NeedsFixIts);
502
503 EXPECT_LT(RelevanceWithFixIt.evaluateHeuristics(),
504 RelevanceWithoutFixIt.evaluateHeuristics());
505}
506
507} // namespace
508} // namespace clangd
509} // namespace clang
Support lookups like FileDistance, but the lookup keys are symbol scopes.
An immutable symbol container that stores a set of symbols.
Definition Symbol.h:201
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
Definition AST.cpp:45
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition TestTU.cpp:220
std::string sortText(float Score, llvm::StringRef Name)
Returns a string that sorts in the same order as (-Score, Tiebreak), for LSP.
Definition Quality.cpp:552
SlabTuple indexMainDecls(ParsedAST &AST)
Retrieves symbols and refs of local top level decls in AST (i.e.
std::string testPath(PathRef File, llvm::sys::path::Style Style)
Definition TestFS.cpp:93
TEST(BackgroundQueueTest, Priority)
const NamedDecl & findUnqualifiedDecl(ParsedAST &AST, llvm::StringRef Name)
Definition TestTU.cpp:261
const Symbol & findSymbol(const SymbolSlab &Slab, llvm::StringRef QName)
Definition TestTU.cpp:186
@ Deprecated
Deprecated or obsolete code.
Definition Protocol.h:919
volatile int UnittestSchemeAnchorSource
Definition TestFS.cpp:137
static int LLVM_ATTRIBUTE_UNUSED UnittestSchemeAnchorDest
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition sample.cpp:5
std::string Query
A query string for the fuzzy find.
Definition Index.h:29
bool AnyScope
If set to true, allow symbols from any scope.
Definition Index.h:39
Attributes of a symbol that affect how much we like it.
Definition Quality.h:56
enum clang::clangd::SymbolQualitySignals::SymbolCategory Category
void merge(const CodeCompletionResult &SemaCCResult)
Definition Quality.cpp:178
Attributes of a symbol-query pair that affect how much we like it.
Definition Quality.h:86
float NameMatch
0-1+ fuzzy-match score for unqualified name. Must be explicitly assigned.
Definition Quality.h:90
bool NeedsFixIts
Whether fixits needs to be applied for that completion or not.
Definition Quality.h:95
llvm::StringRef Name
The name of the symbol (for ContextWords). Must be explicitly assigned.
Definition Quality.h:88
llvm::StringRef SymbolURI
These are used to calculate proximity between the index symbol and the query.
Definition Quality.h:101
llvm::StringSet * ContextWords
Lowercase words relevant to the context (e.g. near the completion point).
Definition Quality.h:92
void merge(const CodeCompletionResult &SemaResult)
Definition Quality.cpp:329
CodeCompletionContext::Kind Context
Definition Quality.h:126
float SemaFileProximityScore
FIXME: unify with index proximity score - signals should be source-independent.
Definition Quality.h:105
enum clang::clangd::SymbolRelevanceSignals::QueryType Query
enum clang::clangd::SymbolRelevanceSignals::AccessibleScope Scope
std::optional< llvm::StringRef > SymbolScope
Definition Quality.h:109
The class presents a C++ symbol, e.g.
Definition Symbol.h:39
unsigned References
The number of translation units that reference this symbol from their main file.
Definition Symbol.h:62
std::string Code
Definition TestTU.h:49
ParsedAST build() const
Definition TestTU.cpp:115
static TestTU withHeaderCode(llvm::StringRef HeaderCode)
Definition TestTU.h:42
static TestTU withCode(llvm::StringRef Code)
Definition TestTU.h:36
std::string HeaderCode
Definition TestTU.h:53
std::unique_ptr< SymbolIndex > index() const
Definition TestTU.cpp:176