clang-tools 19.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() {}
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, nullptr, false,
125 /*Accessible=*/false));
126 EXPECT_EQ(Relevance.NameMatch, SymbolRelevanceSignals().NameMatch);
127 EXPECT_TRUE(Relevance.Forbidden);
128 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::GlobalScope);
129
130 Relevance = {};
131 Relevance.merge(CodeCompletionResult(&findDecl(AST, "main"), 42));
132 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f)
133 << "Decl in current file";
134 Relevance = {};
135 Relevance.merge(CodeCompletionResult(&findDecl(AST, "header"), 42));
136 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 0.6f) << "Decl from header";
137 Relevance = {};
138 Relevance.merge(CodeCompletionResult(&findDecl(AST, "header_main"), 42));
139 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f)
140 << "Current file and header";
141
142 auto ConstructShadowDeclCompletionResult = [&](const std::string DeclName) {
143 auto *Shadow =
144 *dyn_cast<UsingDecl>(&findDecl(AST, [&](const NamedDecl &ND) {
145 if (const UsingDecl *Using = dyn_cast<UsingDecl>(&ND))
146 if (Using->shadow_size() &&
147 Using->getQualifiedNameAsString() == DeclName)
148 return true;
149 return false;
150 }))->shadow_begin();
151 CodeCompletionResult Result(Shadow->getTargetDecl(), 42);
152 Result.ShadowDecl = Shadow;
153 return Result;
154 };
155
156 Relevance = {};
157 Relevance.merge(ConstructShadowDeclCompletionResult("Bar"));
158 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f)
159 << "Using declaration in main file";
160 Relevance.merge(ConstructShadowDeclCompletionResult("FLAGS_FOO"));
161 EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f)
162 << "Using declaration in main file";
163
164 Relevance = {};
165 Relevance.merge(CodeCompletionResult(&findUnqualifiedDecl(AST, "X"), 42));
166 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FileScope);
167 Relevance = {};
168 Relevance.merge(CodeCompletionResult(&findUnqualifiedDecl(AST, "y"), 42));
169 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::ClassScope);
170 Relevance = {};
171 Relevance.merge(CodeCompletionResult(&findUnqualifiedDecl(AST, "z"), 42));
172 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FunctionScope);
173 // The injected class name is treated as the outer class name.
174 Relevance = {};
175 Relevance.merge(CodeCompletionResult(&findDecl(AST, "S::S"), 42));
176 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::GlobalScope);
177
178 Relevance = {};
179 EXPECT_FALSE(Relevance.InBaseClass);
180 auto BaseMember = CodeCompletionResult(&findUnqualifiedDecl(AST, "y"), 42);
181 BaseMember.InBaseClass = true;
182 Relevance.merge(BaseMember);
183 EXPECT_TRUE(Relevance.InBaseClass);
184
185 auto Index = Test.index();
187 Req.Query = "X";
188 Req.AnyScope = true;
189 bool Matched = false;
190 Index->fuzzyFind(Req, [&](const Symbol &S) {
191 Matched = true;
192 Relevance = {};
193 Relevance.merge(S);
194 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FileScope);
195 });
196 EXPECT_TRUE(Matched);
197}
198
199// Do the signals move the scores in the direction we expect?
200TEST(QualityTests, SymbolQualitySignalsSanity) {
201 SymbolQualitySignals Default;
202 EXPECT_EQ(Default.evaluateHeuristics(), 1);
203
205 Deprecated.Deprecated = true;
206 EXPECT_LT(Deprecated.evaluateHeuristics(), Default.evaluateHeuristics());
207
208 SymbolQualitySignals ReservedName;
209 ReservedName.ReservedName = true;
210 EXPECT_LT(ReservedName.evaluateHeuristics(), Default.evaluateHeuristics());
211
212 SymbolQualitySignals ImplementationDetail;
213 ImplementationDetail.ImplementationDetail = true;
214 EXPECT_LT(ImplementationDetail.evaluateHeuristics(),
215 Default.evaluateHeuristics());
216
217 SymbolQualitySignals WithReferences, ManyReferences;
218 WithReferences.References = 20;
219 ManyReferences.References = 1000;
220 EXPECT_GT(WithReferences.evaluateHeuristics(), Default.evaluateHeuristics());
221 EXPECT_GT(ManyReferences.evaluateHeuristics(),
222 WithReferences.evaluateHeuristics());
223
225 Destructor, Operator;
234 EXPECT_GT(Variable.evaluateHeuristics(), Default.evaluateHeuristics());
235 EXPECT_GT(Keyword.evaluateHeuristics(), Variable.evaluateHeuristics());
236 EXPECT_LT(Macro.evaluateHeuristics(), Default.evaluateHeuristics());
237 EXPECT_LT(Operator.evaluateHeuristics(), Default.evaluateHeuristics());
238 EXPECT_LT(Constructor.evaluateHeuristics(), Function.evaluateHeuristics());
239 EXPECT_LT(Destructor.evaluateHeuristics(), Constructor.evaluateHeuristics());
240}
241
242TEST(QualityTests, SymbolRelevanceSignalsSanity) {
244 EXPECT_EQ(Default.evaluateHeuristics(), 1);
245
246 SymbolRelevanceSignals Forbidden;
247 Forbidden.Forbidden = true;
248 EXPECT_LT(Forbidden.evaluateHeuristics(), Default.evaluateHeuristics());
249
250 SymbolRelevanceSignals PoorNameMatch;
251 PoorNameMatch.NameMatch = 0.2f;
252 EXPECT_LT(PoorNameMatch.evaluateHeuristics(), Default.evaluateHeuristics());
253
254 SymbolRelevanceSignals WithSemaFileProximity;
255 WithSemaFileProximity.SemaFileProximityScore = 0.2f;
256 EXPECT_GT(WithSemaFileProximity.evaluateHeuristics(),
257 Default.evaluateHeuristics());
258
259 ScopeDistance ScopeProximity({"x::y::"});
260
261 SymbolRelevanceSignals WithSemaScopeProximity;
262 WithSemaScopeProximity.ScopeProximityMatch = &ScopeProximity;
263 WithSemaScopeProximity.SemaSaysInScope = true;
264 EXPECT_GT(WithSemaScopeProximity.evaluateHeuristics(),
265 Default.evaluateHeuristics());
266
267 SymbolRelevanceSignals WithIndexScopeProximity;
268 WithIndexScopeProximity.ScopeProximityMatch = &ScopeProximity;
269 WithIndexScopeProximity.SymbolScope = "x::";
270 EXPECT_GT(WithSemaScopeProximity.evaluateHeuristics(),
271 Default.evaluateHeuristics());
272
273 SymbolRelevanceSignals IndexProximate;
274 IndexProximate.SymbolURI = "unittest:/foo/bar.h";
275 llvm::StringMap<SourceParams> ProxSources;
276 ProxSources.try_emplace(testPath("foo/baz.h"));
277 URIDistance Distance(ProxSources);
278 IndexProximate.FileProximityMatch = &Distance;
279 EXPECT_GT(IndexProximate.evaluateHeuristics(), Default.evaluateHeuristics());
280 SymbolRelevanceSignals IndexDistant = IndexProximate;
281 IndexDistant.SymbolURI = "unittest:/elsewhere/path.h";
282 EXPECT_GT(IndexProximate.evaluateHeuristics(),
283 IndexDistant.evaluateHeuristics())
284 << IndexProximate << IndexDistant;
285 EXPECT_GT(IndexDistant.evaluateHeuristics(), Default.evaluateHeuristics());
286
289 EXPECT_LT(Scoped.evaluateHeuristics(), Default.evaluateHeuristics());
291 EXPECT_GT(Scoped.evaluateHeuristics(), Default.evaluateHeuristics());
292
293 SymbolRelevanceSignals Instance;
294 Instance.IsInstanceMember = false;
295 EXPECT_EQ(Instance.evaluateHeuristics(), Default.evaluateHeuristics());
296 Instance.Context = CodeCompletionContext::CCC_DotMemberAccess;
297 EXPECT_LT(Instance.evaluateHeuristics(), Default.evaluateHeuristics());
298 Instance.IsInstanceMember = true;
299 EXPECT_EQ(Instance.evaluateHeuristics(), Default.evaluateHeuristics());
300
301 SymbolRelevanceSignals InBaseClass;
302 InBaseClass.InBaseClass = true;
303 EXPECT_LT(InBaseClass.evaluateHeuristics(), Default.evaluateHeuristics());
304
305 llvm::StringSet<> Words = {"one", "two", "three"};
306 SymbolRelevanceSignals WithoutMatchingWord;
307 WithoutMatchingWord.ContextWords = &Words;
308 WithoutMatchingWord.Name = "four";
309 EXPECT_EQ(WithoutMatchingWord.evaluateHeuristics(),
310 Default.evaluateHeuristics());
311 SymbolRelevanceSignals WithMatchingWord;
312 WithMatchingWord.ContextWords = &Words;
313 WithMatchingWord.Name = "TheTwoTowers";
314 EXPECT_GT(WithMatchingWord.evaluateHeuristics(),
315 Default.evaluateHeuristics());
316}
317
318TEST(QualityTests, ScopeProximity) {
319 SymbolRelevanceSignals Relevance;
320 ScopeDistance ScopeProximity({"x::y::z::", "x::", "llvm::", ""});
321 Relevance.ScopeProximityMatch = &ScopeProximity;
322
323 Relevance.SymbolScope = "other::";
324 float NotMatched = Relevance.evaluateHeuristics();
325
326 Relevance.SymbolScope = "";
327 float Global = Relevance.evaluateHeuristics();
328 EXPECT_GT(Global, NotMatched);
329
330 Relevance.SymbolScope = "llvm::";
331 float NonParent = Relevance.evaluateHeuristics();
332 EXPECT_GT(NonParent, Global);
333
334 Relevance.SymbolScope = "x::";
335 float GrandParent = Relevance.evaluateHeuristics();
336 EXPECT_GT(GrandParent, Global);
337
338 Relevance.SymbolScope = "x::y::";
339 float Parent = Relevance.evaluateHeuristics();
340 EXPECT_GT(Parent, GrandParent);
341
342 Relevance.SymbolScope = "x::y::z::";
343 float Enclosing = Relevance.evaluateHeuristics();
344 EXPECT_GT(Enclosing, Parent);
345}
346
347TEST(QualityTests, SortText) {
348 EXPECT_LT(sortText(std::numeric_limits<float>::infinity()),
349 sortText(1000.2f));
350 EXPECT_LT(sortText(1000.2f), sortText(1));
351 EXPECT_LT(sortText(1), sortText(0.3f));
352 EXPECT_LT(sortText(0.3f), sortText(0));
353 EXPECT_LT(sortText(0), sortText(-10));
354 EXPECT_LT(sortText(-10), sortText(-std::numeric_limits<float>::infinity()));
355
356 EXPECT_LT(sortText(1, "z"), sortText(0, "a"));
357 EXPECT_LT(sortText(0, "a"), sortText(0, "z"));
358}
359
360TEST(QualityTests, NoBoostForClassConstructor) {
361 auto Header = TestTU::withHeaderCode(R"cpp(
362 class Foo {
363 public:
364 Foo(int);
365 };
366 )cpp");
367 auto Symbols = Header.headerSymbols();
368 auto AST = Header.build();
369
370 const NamedDecl *Foo = &findDecl(AST, "Foo");
372 Cls.merge(CodeCompletionResult(Foo, /*Priority=*/0));
373
374 const NamedDecl *CtorDecl = &findDecl(AST, [](const NamedDecl &ND) {
375 return (ND.getQualifiedNameAsString() == "Foo::Foo") &&
376 isa<CXXConstructorDecl>(&ND);
377 });
379 Ctor.merge(CodeCompletionResult(CtorDecl, /*Priority=*/0));
380
382 EXPECT_EQ(Ctor.Scope, SymbolRelevanceSignals::GlobalScope);
383}
384
385TEST(QualityTests, IsInstanceMember) {
386 auto Header = TestTU::withHeaderCode(R"cpp(
387 class Foo {
388 public:
389 static void foo() {}
390
391 template <typename T> void tpl(T *t) {}
392
393 void bar() {}
394 };
395 )cpp");
396 auto Symbols = Header.headerSymbols();
397
399 const Symbol &FooSym = findSymbol(Symbols, "Foo::foo");
400 Rel.merge(FooSym);
401 EXPECT_FALSE(Rel.IsInstanceMember);
402 const Symbol &BarSym = findSymbol(Symbols, "Foo::bar");
403 Rel.merge(BarSym);
404 EXPECT_TRUE(Rel.IsInstanceMember);
405
406 Rel.IsInstanceMember = false;
407 const Symbol &TplSym = findSymbol(Symbols, "Foo::tpl");
408 Rel.merge(TplSym);
409 EXPECT_TRUE(Rel.IsInstanceMember);
410
411 auto AST = Header.build();
412 const NamedDecl *Foo = &findDecl(AST, "Foo::foo");
413 const NamedDecl *Bar = &findDecl(AST, "Foo::bar");
414 const NamedDecl *Tpl = &findDecl(AST, "Foo::tpl");
415
416 Rel.IsInstanceMember = false;
417 Rel.merge(CodeCompletionResult(Foo, /*Priority=*/0));
418 EXPECT_FALSE(Rel.IsInstanceMember);
419 Rel.merge(CodeCompletionResult(Bar, /*Priority=*/0));
420 EXPECT_TRUE(Rel.IsInstanceMember);
421 Rel.IsInstanceMember = false;
422 Rel.merge(CodeCompletionResult(Tpl, /*Priority=*/0));
423 EXPECT_TRUE(Rel.IsInstanceMember);
424}
425
426TEST(QualityTests, ConstructorDestructor) {
427 auto Header = TestTU::withHeaderCode(R"cpp(
428 class Foo {
429 public:
430 Foo(int);
431 ~Foo();
432 };
433 )cpp");
434 auto Symbols = Header.headerSymbols();
435 auto AST = Header.build();
436
437 const NamedDecl *CtorDecl = &findDecl(AST, [](const NamedDecl &ND) {
438 return (ND.getQualifiedNameAsString() == "Foo::Foo") &&
439 isa<CXXConstructorDecl>(&ND);
440 });
441 const NamedDecl *DtorDecl = &findDecl(AST, [](const NamedDecl &ND) {
442 return (ND.getQualifiedNameAsString() == "Foo::~Foo") &&
443 isa<CXXDestructorDecl>(&ND);
444 });
445
447 CtorQ.merge(CodeCompletionResult(CtorDecl, /*Priority=*/0));
448 EXPECT_EQ(CtorQ.Category, SymbolQualitySignals::Constructor);
449
450 CtorQ.Category = SymbolQualitySignals::Unknown;
451 const Symbol &CtorSym = findSymbol(Symbols, "Foo::Foo");
452 CtorQ.merge(CtorSym);
453 EXPECT_EQ(CtorQ.Category, SymbolQualitySignals::Constructor);
454
456 DtorQ.merge(CodeCompletionResult(DtorDecl, /*Priority=*/0));
458}
459
460TEST(QualityTests, Operator) {
461 auto Header = TestTU::withHeaderCode(R"cpp(
462 class Foo {
463 public:
464 bool operator<(const Foo& f1);
465 };
466 )cpp");
467 auto AST = Header.build();
468
469 const NamedDecl *Operator = &findDecl(AST, [](const NamedDecl &ND) {
470 if (const auto *OD = dyn_cast<FunctionDecl>(&ND))
471 if (OD->isOverloadedOperator())
472 return true;
473 return false;
474 });
476 Q.merge(CodeCompletionResult(Operator, /*Priority=*/0));
477 EXPECT_EQ(Q.Category, SymbolQualitySignals::Operator);
478}
479
480TEST(QualityTests, ItemWithFixItsRankedDown) {
482 Opts.IncludeFixIts = true;
483
484 auto Header = TestTU::withHeaderCode(R"cpp(
485 int x;
486 )cpp");
487 auto AST = Header.build();
488
489 SymbolRelevanceSignals RelevanceWithFixIt;
490 RelevanceWithFixIt.merge(CodeCompletionResult(&findDecl(AST, "x"), 0, nullptr,
491 false, true, {FixItHint{}}));
492 EXPECT_TRUE(RelevanceWithFixIt.NeedsFixIts);
493
494 SymbolRelevanceSignals RelevanceWithoutFixIt;
495 RelevanceWithoutFixIt.merge(
496 CodeCompletionResult(&findDecl(AST, "x"), 0, nullptr, false, true, {}));
497 EXPECT_FALSE(RelevanceWithoutFixIt.NeedsFixIts);
498
499 EXPECT_LT(RelevanceWithFixIt.evaluateHeuristics(),
500 RelevanceWithoutFixIt.evaluateHeuristics());
501}
502
503} // namespace
504} // namespace clangd
505} // namespace clang
SignatureQualitySignals Quality
const Node * Parent
Support lookups like FileDistance, but the lookup keys are symbol scopes.
Definition: FileDistance.h:112
An immutable symbol container that stores a set of symbols.
Definition: Symbol.h:199
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition: TestTU.cpp:219
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:549
SlabTuple indexMainDecls(ParsedAST &AST)
Retrieves symbols and refs of local top level decls in AST (i.e.
Definition: FileIndex.cpp:223
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:260
const Symbol & findSymbol(const SymbolSlab &Slab, llvm::StringRef QName)
Definition: TestTU.cpp:185
@ Deprecated
Deprecated or obsolete code.
Definition: Protocol.h:905
volatile int UnittestSchemeAnchorSource
Definition: TestFS.cpp:137
static int LLVM_ATTRIBUTE_UNUSED UnittestSchemeAnchorDest
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: sample.cpp:5
bool IncludeFixIts
Include completions that require small corrections, e.g.
Definition: CodeComplete.h:97
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:175
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:326
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
std::string Code
Definition: TestTU.h:49
ParsedAST build() const
Definition: TestTU.cpp:114
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:175