[clangd] Fix division by zero when computing scores

NameMatch could be a float close to zero, in such cases we were
dividing by zero and moreover propogating a "NaN" to clients, which is invalid
per JSON.

This fixes the issue by only using Quality scores whenever the NameMatch is low,
as we do in CodeCompletion ranking.

Fixes https://github.com/clangd/clangd/issues/648.

Differential Revision: https://reviews.llvm.org/D94755
This commit is contained in:
Kadir Cetinkaya 2021-01-15 11:12:11 +01:00
parent f07403eb1a
commit a1d4649a5b
No known key found for this signature in database
GPG Key ID: E39E36B8D2057ED6
2 changed files with 12 additions and 6 deletions

View File

@ -70,6 +70,7 @@
#include "llvm/Support/ScopedPrinter.h"
#include <algorithm>
#include <iterator>
#include <limits>
// We log detailed candidate here if you run with -debug-only=codecomplete.
#define DEBUG_TYPE "CodeComplete"
@ -1655,9 +1656,10 @@ private:
evaluateSymbolAndRelevance(Scores.Quality, Scores.Relevance);
// NameMatch is in fact a multiplier on total score, so rescoring is
// sound.
Scores.ExcludingName = Relevance.NameMatch
? Scores.Total / Relevance.NameMatch
: Scores.Quality;
Scores.ExcludingName =
Relevance.NameMatch > std::numeric_limits<float>::epsilon()
? Scores.Total / Relevance.NameMatch
: Scores.Quality;
return Scores;
case RM::DecisionForest:

View File

@ -25,6 +25,7 @@
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
#include <limits>
#include <tuple>
#define DEBUG_TYPE "FindSymbols"
@ -146,8 +147,9 @@ getWorkspaceSymbols(llvm::StringRef Query, int Limit,
return;
}
Relevance.merge(Sym);
auto Score = evaluateSymbolAndRelevance(Quality.evaluateHeuristics(),
Relevance.evaluateHeuristics());
auto QualScore = Quality.evaluateHeuristics();
auto RelScore = Relevance.evaluateHeuristics();
auto Score = evaluateSymbolAndRelevance(QualScore, RelScore);
dlog("FindSymbols: {0}{1} = {2}\n{3}{4}\n", Sym.Scope, Sym.Name, Score,
Quality, Relevance);
@ -159,7 +161,9 @@ getWorkspaceSymbols(llvm::StringRef Query, int Limit,
Info.containerName = Scope.str();
// Exposed score excludes fuzzy-match component, for client-side re-ranking.
Info.score = Score / Relevance.NameMatch;
Info.score = Relevance.NameMatch > std::numeric_limits<float>::epsilon()
? Score / Relevance.NameMatch
: QualScore;
Top.push({Score, std::move(Info)});
});
for (auto &R : std::move(Top).items())