blob: 4b16dd59c011efacc9b4f9090b8c115725d4a5c9 [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
20#include "Quality.h"
21#include "TestTU.h"
22#include "gmock/gmock.h"
23#include "gtest/gtest.h"
24
25namespace clang {
26namespace clangd {
27namespace {
28
29TEST(QualityTests, SymbolQualitySignalExtraction) {
30 auto Header = TestTU::withHeaderCode(R"cpp(
31 int x;
32
33 [[deprecated]]
34 int f() { return x; }
35 )cpp");
36 auto Symbols = Header.headerSymbols();
37 auto AST = Header.build();
38
39 SymbolQualitySignals Quality;
40 Quality.merge(findSymbol(Symbols, "x"));
41 EXPECT_FALSE(Quality.Deprecated);
Sam McCallc5707b62018-05-15 17:43:27 +000042 EXPECT_EQ(Quality.References, SymbolQualitySignals().References);
Sam McCall4a3c69b2018-06-06 08:53:36 +000043 EXPECT_EQ(Quality.Category, SymbolQualitySignals::Variable);
Sam McCallc5707b62018-05-15 17:43:27 +000044
45 Symbol F = findSymbol(Symbols, "f");
46 F.References = 24; // TestTU doesn't count references, so fake it.
47 Quality = {};
48 Quality.merge(F);
49 EXPECT_FALSE(Quality.Deprecated); // FIXME: Include deprecated bit in index.
Sam McCallc5707b62018-05-15 17:43:27 +000050 EXPECT_EQ(Quality.References, 24u);
Sam McCall4a3c69b2018-06-06 08:53:36 +000051 EXPECT_EQ(Quality.Category, SymbolQualitySignals::Function);
Sam McCallc5707b62018-05-15 17:43:27 +000052
53 Quality = {};
54 Quality.merge(CodeCompletionResult(&findDecl(AST, "f"), /*Priority=*/42));
55 EXPECT_TRUE(Quality.Deprecated);
Sam McCallc5707b62018-05-15 17:43:27 +000056 EXPECT_EQ(Quality.References, SymbolQualitySignals().References);
Sam McCall4a3c69b2018-06-06 08:53:36 +000057 EXPECT_EQ(Quality.Category, SymbolQualitySignals::Function);
Sam McCallc5707b62018-05-15 17:43:27 +000058}
59
60TEST(QualityTests, SymbolRelevanceSignalExtraction) {
Ilya Biryukovf0296462018-06-04 14:50:59 +000061 TestTU Test;
62 Test.HeaderCode = R"cpp(
Sam McCalldb41e1c2018-06-05 12:22:43 +000063 int header();
64 int header_main();
Ilya Biryukovf0296462018-06-04 14:50:59 +000065 )cpp";
66 Test.Code = R"cpp(
Sam McCalldb41e1c2018-06-05 12:22:43 +000067 int ::header_main() {}
68 int main();
Sam McCallc5707b62018-05-15 17:43:27 +000069
Ilya Biryukovf0296462018-06-04 14:50:59 +000070 [[deprecated]]
Sam McCalldb41e1c2018-06-05 12:22:43 +000071 int deprecated() { return 0; }
Sam McCalld9b54f02018-06-05 16:30:25 +000072
73 namespace { struct X { void y() { int z; } }; }
Ilya Biryukovf0296462018-06-04 14:50:59 +000074 )cpp";
75 auto AST = Test.build();
76
Sam McCalldb41e1c2018-06-05 12:22:43 +000077 SymbolRelevanceSignals Relevance;
78 Relevance.merge(CodeCompletionResult(&findDecl(AST, "deprecated"),
79 /*Priority=*/42, nullptr, false,
80 /*Accessible=*/false));
81 EXPECT_EQ(Relevance.NameMatch, SymbolRelevanceSignals().NameMatch);
82 EXPECT_TRUE(Relevance.Forbidden);
Sam McCalld9b54f02018-06-05 16:30:25 +000083 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::GlobalScope);
Ilya Biryukovf0296462018-06-04 14:50:59 +000084
Sam McCalldb41e1c2018-06-05 12:22:43 +000085 Relevance = {};
86 Relevance.merge(CodeCompletionResult(&findDecl(AST, "main"), 42));
87 EXPECT_FLOAT_EQ(Relevance.ProximityScore, 1.0) << "Decl in current file";
88 Relevance = {};
89 Relevance.merge(CodeCompletionResult(&findDecl(AST, "header"), 42));
90 EXPECT_FLOAT_EQ(Relevance.ProximityScore, 0.0) << "Decl from header";
91 Relevance = {};
92 Relevance.merge(CodeCompletionResult(&findDecl(AST, "header_main"), 42));
93 EXPECT_FLOAT_EQ(Relevance.ProximityScore, 1.0) << "Current file and header";
Sam McCalld9b54f02018-06-05 16:30:25 +000094
95 Relevance = {};
96 Relevance.merge(CodeCompletionResult(&findAnyDecl(AST, "X"), 42));
97 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FileScope);
98 Relevance = {};
99 Relevance.merge(CodeCompletionResult(&findAnyDecl(AST, "y"), 42));
100 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::ClassScope);
101 Relevance = {};
102 Relevance.merge(CodeCompletionResult(&findAnyDecl(AST, "z"), 42));
103 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FunctionScope);
Sam McCallc5707b62018-05-15 17:43:27 +0000104}
105
106// Do the signals move the scores in the direction we expect?
107TEST(QualityTests, SymbolQualitySignalsSanity) {
108 SymbolQualitySignals Default;
109 EXPECT_EQ(Default.evaluate(), 1);
110
111 SymbolQualitySignals Deprecated;
112 Deprecated.Deprecated = true;
113 EXPECT_LT(Deprecated.evaluate(), Default.evaluate());
114
115 SymbolQualitySignals WithReferences, ManyReferences;
116 WithReferences.References = 10;
117 ManyReferences.References = 1000;
118 EXPECT_GT(WithReferences.evaluate(), Default.evaluate());
119 EXPECT_GT(ManyReferences.evaluate(), WithReferences.evaluate());
120
Sam McCall4a3c69b2018-06-06 08:53:36 +0000121 SymbolQualitySignals Variable, Macro;
122 Variable.Category = SymbolQualitySignals::Variable;
123 Macro.Category = SymbolQualitySignals::Macro;
124 EXPECT_GT(Variable.evaluate(), Default.evaluate());
125 EXPECT_LT(Macro.evaluate(), Default.evaluate());
Sam McCallc5707b62018-05-15 17:43:27 +0000126}
127
128TEST(QualityTests, SymbolRelevanceSignalsSanity) {
129 SymbolRelevanceSignals Default;
130 EXPECT_EQ(Default.evaluate(), 1);
131
132 SymbolRelevanceSignals Forbidden;
133 Forbidden.Forbidden = true;
134 EXPECT_LT(Forbidden.evaluate(), Default.evaluate());
135
136 SymbolRelevanceSignals PoorNameMatch;
Aaron Ballman655ef182018-05-18 14:53:32 +0000137 PoorNameMatch.NameMatch = 0.2f;
Sam McCallc5707b62018-05-15 17:43:27 +0000138 EXPECT_LT(PoorNameMatch.evaluate(), Default.evaluate());
Ilya Biryukovf0296462018-06-04 14:50:59 +0000139
140 SymbolRelevanceSignals WithProximity;
Aaron Ballmanb1403fa2018-06-05 12:14:47 +0000141 WithProximity.ProximityScore = 0.2f;
Sam McCalldb41e1c2018-06-05 12:22:43 +0000142 EXPECT_GT(WithProximity.evaluate(), Default.evaluate());
Sam McCalld9b54f02018-06-05 16:30:25 +0000143
144 SymbolRelevanceSignals Scoped;
145 Scoped.Scope = SymbolRelevanceSignals::FileScope;
146 EXPECT_EQ(Scoped.evaluate(), Default.evaluate());
147 Scoped.Query = SymbolRelevanceSignals::CodeComplete;
148 EXPECT_GT(Scoped.evaluate(), Default.evaluate());
Sam McCallc5707b62018-05-15 17:43:27 +0000149}
150
151TEST(QualityTests, SortText) {
Aaron Ballman655ef182018-05-18 14:53:32 +0000152 EXPECT_LT(sortText(std::numeric_limits<float>::infinity()), sortText(1000.2f));
153 EXPECT_LT(sortText(1000.2f), sortText(1));
154 EXPECT_LT(sortText(1), sortText(0.3f));
155 EXPECT_LT(sortText(0.3f), sortText(0));
Sam McCallc5707b62018-05-15 17:43:27 +0000156 EXPECT_LT(sortText(0), sortText(-10));
157 EXPECT_LT(sortText(-10), sortText(-std::numeric_limits<float>::infinity()));
158
159 EXPECT_LT(sortText(1, "z"), sortText(0, "a"));
160 EXPECT_LT(sortText(0, "a"), sortText(0, "z"));
161}
162
163} // namespace
164} // namespace clangd
165} // namespace clang