blob: 097fd3231556877136fe57e36927f4f88d0b91f4 [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(
Sam McCalle018b362018-06-08 09:36:34 +000031 int _X;
Sam McCallc5707b62018-05-15 17:43:27 +000032
33 [[deprecated]]
Sam McCalle018b362018-06-08 09:36:34 +000034 int _f() { return _X; }
Sam McCallc5707b62018-05-15 17:43:27 +000035 )cpp");
36 auto Symbols = Header.headerSymbols();
37 auto AST = Header.build();
38
39 SymbolQualitySignals Quality;
Sam McCalle018b362018-06-08 09:36:34 +000040 Quality.merge(findSymbol(Symbols, "_X"));
Sam McCallc5707b62018-05-15 17:43:27 +000041 EXPECT_FALSE(Quality.Deprecated);
Sam McCalle018b362018-06-08 09:36:34 +000042 EXPECT_TRUE(Quality.ReservedName);
Sam McCallc5707b62018-05-15 17:43:27 +000043 EXPECT_EQ(Quality.References, SymbolQualitySignals().References);
Sam McCall4a3c69b2018-06-06 08:53:36 +000044 EXPECT_EQ(Quality.Category, SymbolQualitySignals::Variable);
Sam McCallc5707b62018-05-15 17:43:27 +000045
Sam McCalle018b362018-06-08 09:36:34 +000046 Symbol F = findSymbol(Symbols, "_f");
Sam McCallc5707b62018-05-15 17:43:27 +000047 F.References = 24; // TestTU doesn't count references, so fake it.
48 Quality = {};
49 Quality.merge(F);
50 EXPECT_FALSE(Quality.Deprecated); // FIXME: Include deprecated bit in index.
Sam McCalle018b362018-06-08 09:36:34 +000051 EXPECT_FALSE(Quality.ReservedName);
Sam McCallc5707b62018-05-15 17:43:27 +000052 EXPECT_EQ(Quality.References, 24u);
Sam McCall4a3c69b2018-06-06 08:53:36 +000053 EXPECT_EQ(Quality.Category, SymbolQualitySignals::Function);
Sam McCallc5707b62018-05-15 17:43:27 +000054
55 Quality = {};
Sam McCalle018b362018-06-08 09:36:34 +000056 Quality.merge(CodeCompletionResult(&findDecl(AST, "_f"), /*Priority=*/42));
Sam McCallc5707b62018-05-15 17:43:27 +000057 EXPECT_TRUE(Quality.Deprecated);
Sam McCalle018b362018-06-08 09:36:34 +000058 EXPECT_FALSE(Quality.ReservedName);
Sam McCallc5707b62018-05-15 17:43:27 +000059 EXPECT_EQ(Quality.References, SymbolQualitySignals().References);
Sam McCall4a3c69b2018-06-06 08:53:36 +000060 EXPECT_EQ(Quality.Category, SymbolQualitySignals::Function);
Sam McCallc5707b62018-05-15 17:43:27 +000061}
62
63TEST(QualityTests, SymbolRelevanceSignalExtraction) {
Ilya Biryukovf0296462018-06-04 14:50:59 +000064 TestTU Test;
65 Test.HeaderCode = R"cpp(
Sam McCalldb41e1c2018-06-05 12:22:43 +000066 int header();
67 int header_main();
Ilya Biryukovf0296462018-06-04 14:50:59 +000068 )cpp";
69 Test.Code = R"cpp(
Sam McCalldb41e1c2018-06-05 12:22:43 +000070 int ::header_main() {}
71 int main();
Sam McCallc5707b62018-05-15 17:43:27 +000072
Ilya Biryukovf0296462018-06-04 14:50:59 +000073 [[deprecated]]
Sam McCalldb41e1c2018-06-05 12:22:43 +000074 int deprecated() { return 0; }
Sam McCalld9b54f02018-06-05 16:30:25 +000075
76 namespace { struct X { void y() { int z; } }; }
Ilya Biryukovf0296462018-06-04 14:50:59 +000077 )cpp";
78 auto AST = Test.build();
79
Sam McCalldb41e1c2018-06-05 12:22:43 +000080 SymbolRelevanceSignals Relevance;
81 Relevance.merge(CodeCompletionResult(&findDecl(AST, "deprecated"),
82 /*Priority=*/42, nullptr, false,
83 /*Accessible=*/false));
84 EXPECT_EQ(Relevance.NameMatch, SymbolRelevanceSignals().NameMatch);
85 EXPECT_TRUE(Relevance.Forbidden);
Sam McCalld9b54f02018-06-05 16:30:25 +000086 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::GlobalScope);
Ilya Biryukovf0296462018-06-04 14:50:59 +000087
Sam McCalldb41e1c2018-06-05 12:22:43 +000088 Relevance = {};
89 Relevance.merge(CodeCompletionResult(&findDecl(AST, "main"), 42));
90 EXPECT_FLOAT_EQ(Relevance.ProximityScore, 1.0) << "Decl in current file";
91 Relevance = {};
92 Relevance.merge(CodeCompletionResult(&findDecl(AST, "header"), 42));
93 EXPECT_FLOAT_EQ(Relevance.ProximityScore, 0.0) << "Decl from header";
94 Relevance = {};
95 Relevance.merge(CodeCompletionResult(&findDecl(AST, "header_main"), 42));
96 EXPECT_FLOAT_EQ(Relevance.ProximityScore, 1.0) << "Current file and header";
Sam McCalld9b54f02018-06-05 16:30:25 +000097
98 Relevance = {};
99 Relevance.merge(CodeCompletionResult(&findAnyDecl(AST, "X"), 42));
100 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FileScope);
101 Relevance = {};
102 Relevance.merge(CodeCompletionResult(&findAnyDecl(AST, "y"), 42));
103 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::ClassScope);
104 Relevance = {};
105 Relevance.merge(CodeCompletionResult(&findAnyDecl(AST, "z"), 42));
106 EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FunctionScope);
Sam McCallc5707b62018-05-15 17:43:27 +0000107}
108
109// Do the signals move the scores in the direction we expect?
110TEST(QualityTests, SymbolQualitySignalsSanity) {
111 SymbolQualitySignals Default;
112 EXPECT_EQ(Default.evaluate(), 1);
113
114 SymbolQualitySignals Deprecated;
115 Deprecated.Deprecated = true;
116 EXPECT_LT(Deprecated.evaluate(), Default.evaluate());
117
Sam McCalle018b362018-06-08 09:36:34 +0000118 SymbolQualitySignals ReservedName;
119 ReservedName.ReservedName = true;
120 EXPECT_LT(ReservedName.evaluate(), Default.evaluate());
121
Sam McCallc5707b62018-05-15 17:43:27 +0000122 SymbolQualitySignals WithReferences, ManyReferences;
123 WithReferences.References = 10;
124 ManyReferences.References = 1000;
125 EXPECT_GT(WithReferences.evaluate(), Default.evaluate());
126 EXPECT_GT(ManyReferences.evaluate(), WithReferences.evaluate());
127
Sam McCall4a3c69b2018-06-06 08:53:36 +0000128 SymbolQualitySignals Variable, Macro;
129 Variable.Category = SymbolQualitySignals::Variable;
130 Macro.Category = SymbolQualitySignals::Macro;
131 EXPECT_GT(Variable.evaluate(), Default.evaluate());
132 EXPECT_LT(Macro.evaluate(), Default.evaluate());
Sam McCallc5707b62018-05-15 17:43:27 +0000133}
134
135TEST(QualityTests, SymbolRelevanceSignalsSanity) {
136 SymbolRelevanceSignals Default;
137 EXPECT_EQ(Default.evaluate(), 1);
138
139 SymbolRelevanceSignals Forbidden;
140 Forbidden.Forbidden = true;
141 EXPECT_LT(Forbidden.evaluate(), Default.evaluate());
142
143 SymbolRelevanceSignals PoorNameMatch;
Aaron Ballman655ef182018-05-18 14:53:32 +0000144 PoorNameMatch.NameMatch = 0.2f;
Sam McCallc5707b62018-05-15 17:43:27 +0000145 EXPECT_LT(PoorNameMatch.evaluate(), Default.evaluate());
Ilya Biryukovf0296462018-06-04 14:50:59 +0000146
147 SymbolRelevanceSignals WithProximity;
Aaron Ballmanb1403fa2018-06-05 12:14:47 +0000148 WithProximity.ProximityScore = 0.2f;
Sam McCalldb41e1c2018-06-05 12:22:43 +0000149 EXPECT_GT(WithProximity.evaluate(), Default.evaluate());
Sam McCalld9b54f02018-06-05 16:30:25 +0000150
151 SymbolRelevanceSignals Scoped;
152 Scoped.Scope = SymbolRelevanceSignals::FileScope;
153 EXPECT_EQ(Scoped.evaluate(), Default.evaluate());
154 Scoped.Query = SymbolRelevanceSignals::CodeComplete;
155 EXPECT_GT(Scoped.evaluate(), Default.evaluate());
Sam McCallc5707b62018-05-15 17:43:27 +0000156}
157
158TEST(QualityTests, SortText) {
Aaron Ballman655ef182018-05-18 14:53:32 +0000159 EXPECT_LT(sortText(std::numeric_limits<float>::infinity()), sortText(1000.2f));
160 EXPECT_LT(sortText(1000.2f), sortText(1));
161 EXPECT_LT(sortText(1), sortText(0.3f));
162 EXPECT_LT(sortText(0.3f), sortText(0));
Sam McCallc5707b62018-05-15 17:43:27 +0000163 EXPECT_LT(sortText(0), sortText(-10));
164 EXPECT_LT(sortText(-10), sortText(-std::numeric_limits<float>::infinity()));
165
166 EXPECT_LT(sortText(1, "z"), sortText(0, "a"));
167 EXPECT_LT(sortText(0, "a"), sortText(0, "z"));
168}
169
170} // namespace
171} // namespace clangd
172} // namespace clang