project: improve ComputeGuessScore heuristics

This commit is contained in:
Fangrui Song 2019-07-20 06:13:53 -07:00
parent ab6498e2ff
commit a43e51f3bf

View File

@ -306,15 +306,40 @@ void LoadDirectoryListing(ProjectProcessor &proc, const std::string &root,
// Computes a score based on how well |a| and |b| match. This is used for // Computes a score based on how well |a| and |b| match. This is used for
// argument guessing. // argument guessing.
int ComputeGuessScore(std::string_view a, std::string_view b) { int ComputeGuessScore(std::string_view a, std::string_view b) {
// Increase score based on common prefix and suffix. Prefixes are prioritized. int score = 0;
if (a.size() > b.size()) unsigned h = 0;
std::swap(a, b); llvm::SmallDenseMap<unsigned, int> m;
size_t i = std::mismatch(a.begin(), a.end(), b.begin()).first - a.begin(); for (uint8_t c : a)
size_t j = std::mismatch(a.rbegin(), a.rend(), b.rbegin()).first - a.rbegin(); if (c == '/') {
int score = 10 * i + j; score -= 9;
if (i + j < a.size()) if (h)
score -= 100 * (std::count(a.begin() + i, a.end() - j, '/') + m[h]++;
std::count(b.begin() + i, b.end() - j, '/')); h = 0;
} else {
h = h * 33 + c;
}
h = 0;
for (uint8_t c : b)
if (c == '/') {
score -= 9;
auto it = m.find(h);
if (it != m.end() && it->second > 0) {
it->second--;
score += 31;
}
h = 0;
} else {
h = h * 33 + c;
}
uint8_t c;
int d[127] = {};
for (int i = a.size(); i-- && (c = a[i]) != '/'; )
if (c < 127)
d[c]++;
for (int i = b.size(); i-- && (c = b[i]) != '/'; )
if (c < 127 && d[c])
d[c]--, score++;
return score; return score;
} }