Fix regressions in completion filtering. Also improve performance slightly.

If there was no filter then we would return all results - this caused huge delays for #include completion.
This commit is contained in:
Jacob Dufault 2018-02-21 23:30:35 -08:00
parent fae959e0ee
commit 566b508b8e

View File

@ -103,6 +103,9 @@ void FilterAndSortCompletionResponse(
Out_TextDocumentComplete* complete_response, Out_TextDocumentComplete* complete_response,
const std::string& complete_text, const std::string& complete_text,
bool enable) { bool enable) {
if (!enable)
return;
ScopedPerfTimer timer("FilterAndSortCompletionResponse"); ScopedPerfTimer timer("FilterAndSortCompletionResponse");
// Used to inject more completions. // Used to inject more completions.
@ -119,23 +122,38 @@ void FilterAndSortCompletionResponse(
} }
#endif #endif
auto& items = complete_response->result.items; auto& items = complete_response->result.items;
if (!enable || complete_text.empty()) { auto finalize = [&]() {
// Just set the |sortText| to be the priority and return. const size_t kMaxResultSize = 100u;
if (items.size() > kMaxResultSize) {
items.resize(kMaxResultSize);
complete_response->result.isIncomplete = true;
}
// Set sortText. Note that this happens after resizing - we could do it
// before, but then we should also sort by priority.
char buf[16]; char buf[16];
for (auto& item : items) for (size_t i = 0; i < items.size(); ++i)
item.sortText = tofixedbase64(item.priority_, buf); items[i].sortText = tofixedbase64(i, buf);
};
// No complete text; don't run any filtering logic except to trim the items.
if (complete_text.empty()) {
finalize();
return; return;
} }
// Make sure all items have |filterText| set, code that follow needs it. // Make sure all items have |filterText| set, code that follow needs it.
for (auto& item : items) for (auto& item : items) {
if (!item.filterText) if (!item.filterText)
item.filterText = item.label; item.filterText = item.label;
}
// If the text doesn't start with underscore, // If the text doesn't start with underscore, remove all candidates that
// remove all candidates that start with underscore. // start with underscore.
if (complete_text[0] != '_') { if (complete_text[0] != '_') {
auto filter = [](const lsCompletionItem& item) { auto filter = [](const lsCompletionItem& item) {
return (*item.filterText)[0] == '_'; return (*item.filterText)[0] == '_';
@ -144,26 +162,23 @@ void FilterAndSortCompletionResponse(
items.end()); items.end());
} }
// Fuzzy match. // Fuzzy match. Remove any candidates that do not match.
bool found = false; bool found = false;
for (auto& item : items) { for (auto& item : items) {
std::tie(item.found_, item.skip_) = std::tie(item.found_, item.skip_) =
SubsequenceCountSkip(complete_text, *item.filterText); SubsequenceCountSkip(complete_text, *item.filterText);
found = found || item.found_; found = found || item.found_;
} }
if (found) { if (found) {
auto filter = [](const lsCompletionItem& item) { return !item.found_; }; auto filter = [](const lsCompletionItem& item) { return !item.found_; };
items.erase(std::remove_if(items.begin(), items.end(), filter), items.erase(std::remove_if(items.begin(), items.end(), filter),
items.end()); items.end());
}
// Order all items and set |sortText|. // Order all items and set |sortText|.
const size_t kMaxSortSize = 200u; const size_t kMaxSortSize = 200u;
if (found) { if (items.size() <= kMaxSortSize) {
if (items.size() <= kMaxSortSize)
std::sort(items.begin(), items.end(), CompareLsCompletionItem); std::sort(items.begin(), items.end(), CompareLsCompletionItem);
else { } else {
// Just place items that found the text before those not. // Just place items that found the text before those not.
std::vector<lsCompletionItem> items_found, items_notfound; std::vector<lsCompletionItem> items_found, items_notfound;
for (auto& item : items) for (auto& item : items)
@ -173,15 +188,8 @@ void FilterAndSortCompletionResponse(
} }
} }
char buf[16]; // Trim result.
for (size_t i = 0; i < items.size(); ++i) finalize();
items[i].sortText = tofixedbase64(i, buf);
const size_t kMaxResultSize = 100u;
if (items.size() > kMaxResultSize) {
items.resize(kMaxResultSize);
complete_response->result.isIncomplete = true;
}
} }
struct TextDocumentCompletionHandler : MessageHandler { struct TextDocumentCompletionHandler : MessageHandler {
@ -239,7 +247,8 @@ struct TextDocumentCompletionHandler : MessageHandler {
} }
// If the character is > but - does not preced it, or if it is : and : // If the character is > but - does not preced it, or if it is : and :
// does not preced it, do not show completion results. // does not preced it, do not show completion results.
else if (preceding_index < (int)buffer_line.size()) { else if (preceding_index >= 0 &&
preceding_index < (int)buffer_line.size()) {
char preceding = buffer_line[preceding_index]; char preceding = buffer_line[preceding_index];
did_fail_check = (preceding != '-' && character == ">") || did_fail_check = (preceding != '-' && character == ">") ||
(preceding != ':' && character == ":"); (preceding != ':' && character == ":");