Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 1 | //===-- 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 McCall | 3f0243f | 2018-07-03 08:09:29 +0000 | [diff] [blame] | 20 | #include "FileDistance.h" |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 21 | #include "Quality.h" |
Eric Liu | 09c3c37 | 2018-06-15 08:58:12 +0000 | [diff] [blame] | 22 | #include "TestFS.h" |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 23 | #include "TestTU.h" |
Eric Liu | 8944f0e | 2018-07-05 08:14:04 +0000 | [diff] [blame] | 24 | #include "clang/AST/Decl.h" |
| 25 | #include "clang/AST/DeclCXX.h" |
Eric Liu | d7de811 | 2018-07-24 08:51:52 +0000 | [diff] [blame] | 26 | #include "clang/AST/Type.h" |
Eric Liu | 5d2a807 | 2018-07-23 10:56:37 +0000 | [diff] [blame] | 27 | #include "clang/Sema/CodeCompleteConsumer.h" |
Eric Liu | 8944f0e | 2018-07-05 08:14:04 +0000 | [diff] [blame] | 28 | #include "llvm/Support/Casting.h" |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 29 | #include "gmock/gmock.h" |
| 30 | #include "gtest/gtest.h" |
Eric Liu | 3fac4ef | 2018-10-17 11:19:02 +0000 | [diff] [blame] | 31 | #include <vector> |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 32 | |
Sam McCall | c008af6 | 2018-10-20 15:30:37 +0000 | [diff] [blame] | 33 | using namespace llvm; |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 34 | namespace clang { |
| 35 | namespace clangd { |
Eric Liu | 09c3c37 | 2018-06-15 08:58:12 +0000 | [diff] [blame] | 36 | |
| 37 | // Force the unittest URI scheme to be linked, |
| 38 | static int LLVM_ATTRIBUTE_UNUSED UnittestSchemeAnchorDest = |
| 39 | UnittestSchemeAnchorSource; |
| 40 | |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 41 | namespace { |
| 42 | |
| 43 | TEST(QualityTests, SymbolQualitySignalExtraction) { |
| 44 | auto Header = TestTU::withHeaderCode(R"cpp( |
Sam McCall | e018b36 | 2018-06-08 09:36:34 +0000 | [diff] [blame] | 45 | int _X; |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 46 | |
| 47 | [[deprecated]] |
Sam McCall | e018b36 | 2018-06-08 09:36:34 +0000 | [diff] [blame] | 48 | int _f() { return _X; } |
Eric Liu | 4859738 | 2018-10-18 12:23:05 +0000 | [diff] [blame] | 49 | |
| 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 McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 55 | )cpp"); |
Eric Liu | 4859738 | 2018-10-18 12:23:05 +0000 | [diff] [blame] | 56 | Header.ExtraArgs = {"-DMAC=mac_name"}; |
| 57 | |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 58 | auto Symbols = Header.headerSymbols(); |
| 59 | auto AST = Header.build(); |
| 60 | |
| 61 | SymbolQualitySignals Quality; |
Sam McCall | e018b36 | 2018-06-08 09:36:34 +0000 | [diff] [blame] | 62 | Quality.merge(findSymbol(Symbols, "_X")); |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 63 | EXPECT_FALSE(Quality.Deprecated); |
Eric Liu | 4859738 | 2018-10-18 12:23:05 +0000 | [diff] [blame] | 64 | EXPECT_FALSE(Quality.ImplementationDetail); |
Sam McCall | e018b36 | 2018-06-08 09:36:34 +0000 | [diff] [blame] | 65 | EXPECT_TRUE(Quality.ReservedName); |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 66 | EXPECT_EQ(Quality.References, SymbolQualitySignals().References); |
Sam McCall | 4a3c69b | 2018-06-06 08:53:36 +0000 | [diff] [blame] | 67 | EXPECT_EQ(Quality.Category, SymbolQualitySignals::Variable); |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 68 | |
Eric Liu | 4859738 | 2018-10-18 12:23:05 +0000 | [diff] [blame] | 69 | 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 McCall | e018b36 | 2018-06-08 09:36:34 +0000 | [diff] [blame] | 77 | Symbol F = findSymbol(Symbols, "_f"); |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 78 | F.References = 24; // TestTU doesn't count references, so fake it. |
| 79 | Quality = {}; |
| 80 | Quality.merge(F); |
Eric Liu | 6df6600 | 2018-09-06 18:52:26 +0000 | [diff] [blame] | 81 | EXPECT_TRUE(Quality.Deprecated); |
Sam McCall | e018b36 | 2018-06-08 09:36:34 +0000 | [diff] [blame] | 82 | EXPECT_FALSE(Quality.ReservedName); |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 83 | EXPECT_EQ(Quality.References, 24u); |
Sam McCall | 4a3c69b | 2018-06-06 08:53:36 +0000 | [diff] [blame] | 84 | EXPECT_EQ(Quality.Category, SymbolQualitySignals::Function); |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 85 | |
| 86 | Quality = {}; |
Sam McCall | e018b36 | 2018-06-08 09:36:34 +0000 | [diff] [blame] | 87 | Quality.merge(CodeCompletionResult(&findDecl(AST, "_f"), /*Priority=*/42)); |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 88 | EXPECT_TRUE(Quality.Deprecated); |
Sam McCall | e018b36 | 2018-06-08 09:36:34 +0000 | [diff] [blame] | 89 | EXPECT_FALSE(Quality.ReservedName); |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 90 | EXPECT_EQ(Quality.References, SymbolQualitySignals().References); |
Sam McCall | 4a3c69b | 2018-06-06 08:53:36 +0000 | [diff] [blame] | 91 | EXPECT_EQ(Quality.Category, SymbolQualitySignals::Function); |
Sam McCall | c3b5bad | 2018-06-14 13:42:21 +0000 | [diff] [blame] | 92 | |
| 93 | Quality = {}; |
| 94 | Quality.merge(CodeCompletionResult("if")); |
| 95 | EXPECT_EQ(Quality.Category, SymbolQualitySignals::Keyword); |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | TEST(QualityTests, SymbolRelevanceSignalExtraction) { |
Ilya Biryukov | f029646 | 2018-06-04 14:50:59 +0000 | [diff] [blame] | 99 | TestTU Test; |
| 100 | Test.HeaderCode = R"cpp( |
Kirill Bobyrev | 47d7f52 | 2018-07-11 14:49:49 +0000 | [diff] [blame] | 101 | 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 Biryukov | f029646 | 2018-06-04 14:50:59 +0000 | [diff] [blame] | 113 | Test.Code = R"cpp( |
Kirill Bobyrev | 47d7f52 | 2018-07-11 14:49:49 +0000 | [diff] [blame] | 114 | using hdr::Bar; |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 115 | |
Kirill Bobyrev | 47d7f52 | 2018-07-11 14:49:49 +0000 | [diff] [blame] | 116 | using flags::FLAGS_FOO; |
Sam McCall | d9b54f0 | 2018-06-05 16:30:25 +0000 | [diff] [blame] | 117 | |
Kirill Bobyrev | 47d7f52 | 2018-07-11 14:49:49 +0000 | [diff] [blame] | 118 | 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 Biryukov | f029646 | 2018-06-04 14:50:59 +0000 | [diff] [blame] | 126 | )cpp"; |
| 127 | auto AST = Test.build(); |
| 128 | |
Sam McCall | db41e1c | 2018-06-05 12:22:43 +0000 | [diff] [blame] | 129 | 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 McCall | d9b54f0 | 2018-06-05 16:30:25 +0000 | [diff] [blame] | 135 | EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::GlobalScope); |
Ilya Biryukov | f029646 | 2018-06-04 14:50:59 +0000 | [diff] [blame] | 136 | |
Sam McCall | db41e1c | 2018-06-05 12:22:43 +0000 | [diff] [blame] | 137 | Relevance = {}; |
| 138 | Relevance.merge(CodeCompletionResult(&findDecl(AST, "main"), 42)); |
Eric Liu | 3fac4ef | 2018-10-17 11:19:02 +0000 | [diff] [blame] | 139 | EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f) |
| 140 | << "Decl in current file"; |
Sam McCall | db41e1c | 2018-06-05 12:22:43 +0000 | [diff] [blame] | 141 | Relevance = {}; |
| 142 | Relevance.merge(CodeCompletionResult(&findDecl(AST, "header"), 42)); |
Eric Liu | 3fac4ef | 2018-10-17 11:19:02 +0000 | [diff] [blame] | 143 | EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 0.6f) << "Decl from header"; |
Sam McCall | db41e1c | 2018-06-05 12:22:43 +0000 | [diff] [blame] | 144 | Relevance = {}; |
| 145 | Relevance.merge(CodeCompletionResult(&findDecl(AST, "header_main"), 42)); |
Eric Liu | 3fac4ef | 2018-10-17 11:19:02 +0000 | [diff] [blame] | 146 | EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f) |
Eric Liu | 09c3c37 | 2018-06-15 08:58:12 +0000 | [diff] [blame] | 147 | << "Current file and header"; |
Sam McCall | d9b54f0 | 2018-06-05 16:30:25 +0000 | [diff] [blame] | 148 | |
Kirill Bobyrev | 47d7f52 | 2018-07-11 14:49:49 +0000 | [diff] [blame] | 149 | 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 Liu | 3fac4ef | 2018-10-17 11:19:02 +0000 | [diff] [blame] | 169 | EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f) |
Kirill Bobyrev | 47d7f52 | 2018-07-11 14:49:49 +0000 | [diff] [blame] | 170 | << "Using declaration in main file"; |
| 171 | Relevance.merge(constructShadowDeclCompletionResult("FLAGS_FOO")); |
Eric Liu | 3fac4ef | 2018-10-17 11:19:02 +0000 | [diff] [blame] | 172 | EXPECT_FLOAT_EQ(Relevance.SemaFileProximityScore, 1.0f) |
Kirill Bobyrev | 47d7f52 | 2018-07-11 14:49:49 +0000 | [diff] [blame] | 173 | << "Using declaration in main file"; |
| 174 | |
Sam McCall | d9b54f0 | 2018-06-05 16:30:25 +0000 | [diff] [blame] | 175 | 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 McCall | abe3737 | 2018-06-27 11:43:54 +0000 | [diff] [blame] | 184 | // 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 Liu | 52a11b5 | 2018-10-24 13:45:17 +0000 | [diff] [blame] | 188 | |
| 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 McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | // Do the signals move the scores in the direction we expect? |
| 198 | TEST(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 McCall | e018b36 | 2018-06-08 09:36:34 +0000 | [diff] [blame] | 206 | SymbolQualitySignals ReservedName; |
| 207 | ReservedName.ReservedName = true; |
| 208 | EXPECT_LT(ReservedName.evaluate(), Default.evaluate()); |
| 209 | |
Eric Liu | 4859738 | 2018-10-18 12:23:05 +0000 | [diff] [blame] | 210 | SymbolQualitySignals ImplementationDetail; |
| 211 | ImplementationDetail.ImplementationDetail = true; |
| 212 | EXPECT_LT(ImplementationDetail.evaluate(), Default.evaluate()); |
| 213 | |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 214 | SymbolQualitySignals WithReferences, ManyReferences; |
Eric Liu | cdc5f6a | 2018-06-28 16:51:12 +0000 | [diff] [blame] | 215 | WithReferences.References = 20; |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 216 | ManyReferences.References = 1000; |
| 217 | EXPECT_GT(WithReferences.evaluate(), Default.evaluate()); |
| 218 | EXPECT_GT(ManyReferences.evaluate(), WithReferences.evaluate()); |
| 219 | |
Eric Liu | d7de811 | 2018-07-24 08:51:52 +0000 | [diff] [blame] | 220 | SymbolQualitySignals Keyword, Variable, Macro, Constructor, Function; |
Sam McCall | c3b5bad | 2018-06-14 13:42:21 +0000 | [diff] [blame] | 221 | Keyword.Category = SymbolQualitySignals::Keyword; |
Sam McCall | 4a3c69b | 2018-06-06 08:53:36 +0000 | [diff] [blame] | 222 | Variable.Category = SymbolQualitySignals::Variable; |
| 223 | Macro.Category = SymbolQualitySignals::Macro; |
Eric Liu | d7de811 | 2018-07-24 08:51:52 +0000 | [diff] [blame] | 224 | Constructor.Category = SymbolQualitySignals::Constructor; |
| 225 | Function.Category = SymbolQualitySignals::Function; |
Sam McCall | 4a3c69b | 2018-06-06 08:53:36 +0000 | [diff] [blame] | 226 | EXPECT_GT(Variable.evaluate(), Default.evaluate()); |
Sam McCall | c3b5bad | 2018-06-14 13:42:21 +0000 | [diff] [blame] | 227 | EXPECT_GT(Keyword.evaluate(), Variable.evaluate()); |
Sam McCall | 4a3c69b | 2018-06-06 08:53:36 +0000 | [diff] [blame] | 228 | EXPECT_LT(Macro.evaluate(), Default.evaluate()); |
Eric Liu | d7de811 | 2018-07-24 08:51:52 +0000 | [diff] [blame] | 229 | EXPECT_LT(Constructor.evaluate(), Function.evaluate()); |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 230 | } |
| 231 | |
| 232 | TEST(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 Ballman | 655ef18 | 2018-05-18 14:53:32 +0000 | [diff] [blame] | 241 | PoorNameMatch.NameMatch = 0.2f; |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 242 | EXPECT_LT(PoorNameMatch.evaluate(), Default.evaluate()); |
Ilya Biryukov | f029646 | 2018-06-04 14:50:59 +0000 | [diff] [blame] | 243 | |
Eric Liu | 3fac4ef | 2018-10-17 11:19:02 +0000 | [diff] [blame] | 244 | 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 McCall | 3f0243f | 2018-07-03 08:09:29 +0000 | [diff] [blame] | 259 | |
| 260 | SymbolRelevanceSignals IndexProximate; |
| 261 | IndexProximate.SymbolURI = "unittest:/foo/bar.h"; |
Sam McCall | c008af6 | 2018-10-20 15:30:37 +0000 | [diff] [blame] | 262 | StringMap<SourceParams> ProxSources; |
Sam McCall | 3f0243f | 2018-07-03 08:09:29 +0000 | [diff] [blame] | 263 | 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 McCall | d9b54f0 | 2018-06-05 16:30:25 +0000 | [diff] [blame] | 272 | |
| 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 Liu | 5d2a807 | 2018-07-23 10:56:37 +0000 | [diff] [blame] | 278 | |
| 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 Liu | 52a11b5 | 2018-10-24 13:45:17 +0000 | [diff] [blame] | 286 | |
| 287 | SymbolRelevanceSignals InBaseClass; |
| 288 | InBaseClass.InBaseClass = true; |
| 289 | EXPECT_LT(InBaseClass.evaluate(), Default.evaluate()); |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 290 | } |
| 291 | |
Eric Liu | 3fac4ef | 2018-10-17 11:19:02 +0000 | [diff] [blame] | 292 | TEST(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 McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 321 | TEST(QualityTests, SortText) { |
Kirill Bobyrev | 47d7f52 | 2018-07-11 14:49:49 +0000 | [diff] [blame] | 322 | EXPECT_LT(sortText(std::numeric_limits<float>::infinity()), |
| 323 | sortText(1000.2f)); |
Aaron Ballman | 655ef18 | 2018-05-18 14:53:32 +0000 | [diff] [blame] | 324 | EXPECT_LT(sortText(1000.2f), sortText(1)); |
| 325 | EXPECT_LT(sortText(1), sortText(0.3f)); |
| 326 | EXPECT_LT(sortText(0.3f), sortText(0)); |
Sam McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 327 | 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 Liu | 8944f0e | 2018-07-05 08:14:04 +0000 | [diff] [blame] | 334 | TEST(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 McCall | c008af6 | 2018-10-20 15:30:37 +0000 | [diff] [blame] | 350 | isa<CXXConstructorDecl>(&ND); |
Eric Liu | 8944f0e | 2018-07-05 08:14:04 +0000 | [diff] [blame] | 351 | }); |
| 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 Liu | 5d2a807 | 2018-07-23 10:56:37 +0000 | [diff] [blame] | 359 | TEST(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 Liu | d7de811 | 2018-07-24 08:51:52 +0000 | [diff] [blame] | 400 | TEST(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 McCall | c008af6 | 2018-10-20 15:30:37 +0000 | [diff] [blame] | 412 | isa<CXXConstructorDecl>(&ND); |
Eric Liu | d7de811 | 2018-07-24 08:51:52 +0000 | [diff] [blame] | 413 | }); |
| 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 Cetinkaya | 2f84d91 | 2018-08-08 08:59:29 +0000 | [diff] [blame] | 425 | TEST(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 McCall | c5707b6 | 2018-05-15 17:43:27 +0000 | [diff] [blame] | 447 | } // namespace |
| 448 | } // namespace clangd |
| 449 | } // namespace clang |