forked from OSchip/llvm-project
[clangd] Use fuzzy match to select top N index results.
Summary: This makes performance slower but more predictable (it always processes every symbol). We need to find ways to make this fast, possibly by precomputing short queries or capping the number of scored results. But our current approach is too naive. It also no longer returns results in a "good" order. In fact it's pathological: the top N results are ranked from worst to best. Indexes aren't responsible for ranking and MergedIndex can't do a good job, so I'm pleased that this will make any hidden assumptions we have more noticeable :-) Reviewers: hokein Subscribers: klimek, ilya-biryukov, cfe-commits Differential Revision: https://reviews.llvm.org/D42060 llvm-svn: 322821
This commit is contained in:
parent
83b0a98902
commit
a5ce243fa3
|
@ -8,7 +8,9 @@
|
|||
//===-------------------------------------------------------------------===//
|
||||
|
||||
#include "MemIndex.h"
|
||||
#include "../FuzzyMatch.h"
|
||||
#include "../Logger.h"
|
||||
#include <queue>
|
||||
|
||||
namespace clang {
|
||||
namespace clangd {
|
||||
|
@ -32,7 +34,9 @@ bool MemIndex::fuzzyFind(
|
|||
assert(!StringRef(Req.Query).contains("::") &&
|
||||
"There must be no :: in query.");
|
||||
|
||||
unsigned Matched = 0;
|
||||
std::priority_queue<std::pair<float, const Symbol *>> Top;
|
||||
FuzzyMatcher Filter(Req.Query);
|
||||
bool More = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> Lock(Mutex);
|
||||
for (const auto Pair : Index) {
|
||||
|
@ -42,15 +46,18 @@ bool MemIndex::fuzzyFind(
|
|||
if (!Req.Scopes.empty() && !llvm::is_contained(Req.Scopes, Sym->Scope))
|
||||
continue;
|
||||
|
||||
// FIXME(ioeric): use fuzzy matcher.
|
||||
if (StringRef(Sym->Name).find_lower(Req.Query) != StringRef::npos) {
|
||||
if (++Matched > Req.MaxCandidateCount)
|
||||
return false;
|
||||
Callback(*Sym);
|
||||
if (auto Score = Filter.match(Sym->Name)) {
|
||||
Top.emplace(-*Score, Sym);
|
||||
if (Top.size() > Req.MaxCandidateCount) {
|
||||
More = true;
|
||||
Top.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (; !Top.empty(); Top.pop())
|
||||
Callback(*Top.top().second);
|
||||
}
|
||||
return true;
|
||||
return More;
|
||||
}
|
||||
|
||||
std::unique_ptr<SymbolIndex> MemIndex::build(SymbolSlab Slab) {
|
||||
|
|
|
@ -149,12 +149,22 @@ TEST(MemIndexTest, MemIndexLimitedNumMatches) {
|
|||
EXPECT_EQ(Matches.size(), Req.MaxCandidateCount);
|
||||
}
|
||||
|
||||
TEST(MemIndexTest, FuzzyMatch) {
|
||||
MemIndex I;
|
||||
I.build(
|
||||
generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}));
|
||||
FuzzyFindRequest Req;
|
||||
Req.Query = "lol";
|
||||
Req.MaxCandidateCount = 2;
|
||||
EXPECT_THAT(match(I, Req),
|
||||
UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
|
||||
}
|
||||
|
||||
TEST(MemIndexTest, MatchQualifiedNamesWithoutSpecificScope) {
|
||||
MemIndex I;
|
||||
I.build(generateSymbols({"a::xyz", "b::yz", "yz"}));
|
||||
FuzzyFindRequest Req;
|
||||
Req.Query = "y";
|
||||
auto Matches = match(I, Req);
|
||||
EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::xyz", "b::yz", "yz"));
|
||||
}
|
||||
|
||||
|
@ -164,7 +174,6 @@ TEST(MemIndexTest, MatchQualifiedNamesWithGlobalScope) {
|
|||
FuzzyFindRequest Req;
|
||||
Req.Query = "y";
|
||||
Req.Scopes = {""};
|
||||
auto Matches = match(I, Req);
|
||||
EXPECT_THAT(match(I, Req), UnorderedElementsAre("yz"));
|
||||
}
|
||||
|
||||
|
@ -174,7 +183,6 @@ TEST(MemIndexTest, MatchQualifiedNamesWithOneScope) {
|
|||
FuzzyFindRequest Req;
|
||||
Req.Query = "y";
|
||||
Req.Scopes = {"a"};
|
||||
auto Matches = match(I, Req);
|
||||
EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::xyz", "a::yy"));
|
||||
}
|
||||
|
||||
|
@ -184,7 +192,6 @@ TEST(MemIndexTest, MatchQualifiedNamesWithMultipleScopes) {
|
|||
FuzzyFindRequest Req;
|
||||
Req.Query = "y";
|
||||
Req.Scopes = {"a", "b"};
|
||||
auto Matches = match(I, Req);
|
||||
EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::xyz", "a::yy", "b::yz"));
|
||||
}
|
||||
|
||||
|
@ -194,7 +201,6 @@ TEST(MemIndexTest, NoMatchNestedScopes) {
|
|||
FuzzyFindRequest Req;
|
||||
Req.Query = "y";
|
||||
Req.Scopes = {"a"};
|
||||
auto Matches = match(I, Req);
|
||||
EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::xyz"));
|
||||
}
|
||||
|
||||
|
@ -204,7 +210,6 @@ TEST(MemIndexTest, IgnoreCases) {
|
|||
FuzzyFindRequest Req;
|
||||
Req.Query = "AB";
|
||||
Req.Scopes = {"ns"};
|
||||
auto Matches = match(I, Req);
|
||||
EXPECT_THAT(match(I, Req), UnorderedElementsAre("ns::ABC", "ns::abc"));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue