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"
41 TEST(QualityTests, SymbolQualitySignalExtraction) {
46 int _f() { return _X; }
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
53 auto Symbols = Header.headerSymbols();
54 auto AST = Header.
build();
58 EXPECT_TRUE(
Quality.ImplementationDetail);
64 EXPECT_TRUE(
Quality.Deprecated);
65 EXPECT_FALSE(
Quality.ReservedName);
66 EXPECT_EQ(
Quality.References, 24u);
71 EXPECT_TRUE(
Quality.Deprecated);
72 EXPECT_FALSE(
Quality.ReservedName);
77 Quality.merge(CodeCompletionResult(
"if"));
86 EXPECT_FALSE(
Quality.Deprecated);
87 EXPECT_FALSE(
Quality.ImplementationDetail);
88 EXPECT_TRUE(
Quality.ReservedName);
91 TEST(QualityTests, SymbolRelevanceSignalExtraction) {
97 namespace hdr { class Bar {}; } // namespace hdr
99 #define DEFINE_FLAG(X) \
109 using flags::FLAGS_FOO;
111 int ::header_main() {}
115 int deprecated() { return 0; }
117 namespace { struct X { void y() { int z; } }; }
120 auto AST = Test.
build();
123 Relevance.
merge(CodeCompletionResult(&
findDecl(AST,
"deprecated"),
131 Relevance.
merge(CodeCompletionResult(&
findDecl(AST,
"main"), 42));
133 <<
"Decl in current file";
135 Relevance.
merge(CodeCompletionResult(&
findDecl(AST,
"header"), 42));
138 Relevance.
merge(CodeCompletionResult(&
findDecl(AST,
"header_main"), 42));
140 <<
"Current file and header";
142 auto ConstructShadowDeclCompletionResult = [&](
const std::string DeclName) {
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)
151 CodeCompletionResult Result(Shadow->getTargetDecl(), 42);
152 Result.ShadowDecl = Shadow;
157 Relevance.
merge(ConstructShadowDeclCompletionResult(
"Bar"));
159 <<
"Using declaration in main file";
160 Relevance.
merge(ConstructShadowDeclCompletionResult(
"FLAGS_FOO"));
162 <<
"Using declaration in main file";
175 Relevance.
merge(CodeCompletionResult(&
findDecl(AST,
"S::S"), 42));
181 BaseMember.InBaseClass =
true;
182 Relevance.
merge(BaseMember);
189 bool Matched =
false;
196 EXPECT_TRUE(Matched);
200 TEST(QualityTests, SymbolQualitySignalsSanity) {
202 EXPECT_EQ(Default.evaluateHeuristics(), 1);
206 EXPECT_LT(
Deprecated.evaluateHeuristics(), Default.evaluateHeuristics());
215 Default.evaluateHeuristics());
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());
242 TEST(QualityTests, SymbolRelevanceSignalsSanity) {
244 EXPECT_EQ(Default.evaluateHeuristics(), 1);
257 Default.evaluateHeuristics());
263 WithSemaScopeProximity.SemaSaysInScope =
true;
264 EXPECT_GT(WithSemaScopeProximity.evaluateHeuristics(),
265 Default.evaluateHeuristics());
270 EXPECT_GT(WithSemaScopeProximity.evaluateHeuristics(),
271 Default.evaluateHeuristics());
274 IndexProximate.
SymbolURI =
"unittest:/foo/bar.h";
275 llvm::StringMap<SourceParams> ProxSources;
276 ProxSources.try_emplace(
testPath(
"foo/baz.h"));
281 IndexDistant.
SymbolURI =
"unittest:/elsewhere/path.h";
284 << IndexProximate << IndexDistant;
285 EXPECT_GT(IndexDistant.evaluateHeuristics(), Default.evaluateHeuristics());
296 Instance.
Context = CodeCompletionContext::CCC_DotMemberAccess;
305 llvm::StringSet<> Words = {
"one",
"two",
"three"};
308 WithoutMatchingWord.
Name =
"four";
310 Default.evaluateHeuristics());
313 WithMatchingWord.
Name =
"TheTwoTowers";
315 Default.evaluateHeuristics());
318 TEST(QualityTests, ScopeProximity) {
320 ScopeDistance ScopeProximity({
"x::y::z::",
"x::",
"llvm::",
""});
328 EXPECT_GT(Global, NotMatched);
332 EXPECT_GT(NonParent, Global);
336 EXPECT_GT(GrandParent, Global);
340 EXPECT_GT(
Parent, GrandParent);
344 EXPECT_GT(Enclosing,
Parent);
347 TEST(QualityTests, SortText) {
348 EXPECT_LT(
sortText(std::numeric_limits<float>::infinity()),
354 EXPECT_LT(
sortText(-10),
sortText(-std::numeric_limits<float>::infinity()));
360 TEST(QualityTests, NoBoostForClassConstructor) {
367 auto Symbols = Header.headerSymbols();
368 auto AST = Header.
build();
370 const NamedDecl *Foo = &
findDecl(AST,
"Foo");
372 Cls.
merge(CodeCompletionResult(Foo, 0));
374 const NamedDecl *CtorDecl = &
findDecl(AST, [](
const NamedDecl &ND) {
375 return (ND.getQualifiedNameAsString() ==
"Foo::Foo") &&
376 isa<CXXConstructorDecl>(&ND);
379 Ctor.
merge(CodeCompletionResult(CtorDecl, 0));
385 TEST(QualityTests, IsInstanceMember) {
391 template <typename T> void tpl(T *t) {}
396 auto Symbols = Header.headerSymbols();
411 auto AST = Header.
build();
412 const NamedDecl *Foo = &
findDecl(AST,
"Foo::foo");
414 const NamedDecl *Tpl = &
findDecl(AST,
"Foo::tpl");
417 Rel.
merge(CodeCompletionResult(Foo, 0));
419 Rel.
merge(CodeCompletionResult(
Bar, 0));
422 Rel.
merge(CodeCompletionResult(Tpl, 0));
426 TEST(QualityTests, ConstructorDestructor) {
434 auto Symbols = Header.headerSymbols();
435 auto AST = Header.
build();
437 const NamedDecl *CtorDecl = &
findDecl(AST, [](
const NamedDecl &ND) {
438 return (ND.getQualifiedNameAsString() ==
"Foo::Foo") &&
439 isa<CXXConstructorDecl>(&ND);
441 const NamedDecl *DtorDecl = &
findDecl(AST, [](
const NamedDecl &ND) {
442 return (ND.getQualifiedNameAsString() ==
"Foo::~Foo") &&
443 isa<CXXDestructorDecl>(&ND);
447 CtorQ.
merge(CodeCompletionResult(CtorDecl, 0));
452 CtorQ.merge(CtorSym);
456 DtorQ.
merge(CodeCompletionResult(DtorDecl, 0));
464 bool operator<(const Foo& f1);
467 auto AST = Header.
build();
470 if (
const auto *OD = dyn_cast<FunctionDecl>(&ND))
471 if (OD->isOverloadedOperator())
480 TEST(QualityTests, ItemWithFixItsRankedDown) {
487 auto AST = Header.
build();
490 RelevanceWithFixIt.
merge(CodeCompletionResult(&
findDecl(AST,
"x"), 0,
nullptr,
491 false,
true, {FixItHint{}}));
495 RelevanceWithoutFixIt.
merge(
496 CodeCompletionResult(&
findDecl(AST,
"x"), 0,
nullptr,
false,
true, {}));