mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-26 09:31:59 +00:00
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:
parent
fae959e0ee
commit
566b508b8e
@ -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 == ":");
|
||||||
|
Loading…
Reference in New Issue
Block a user