mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-27 10:02:03 +00:00
completion: delete insertText; don't set filterText if it is the same as label
It decreases Content-Length: from 32K to 25K for the following case: #include <bits/stdc++.h> int main() { std::| } Also * make results deterministic when completion text is empty * sort by newText, label, filterText
This commit is contained in:
parent
9d767ffa99
commit
8fc6b8a9f4
@ -119,10 +119,9 @@ struct CompletionItem {
|
|||||||
std::string label;
|
std::string label;
|
||||||
CompletionItemKind kind = CompletionItemKind::Text;
|
CompletionItemKind kind = CompletionItemKind::Text;
|
||||||
std::string detail;
|
std::string detail;
|
||||||
std::optional<std::string> documentation;
|
std::string documentation;
|
||||||
std::string sortText;
|
std::string sortText;
|
||||||
std::optional<std::string> filterText;
|
std::string filterText;
|
||||||
std::string insertText;
|
|
||||||
InsertTextFormat insertTextFormat = InsertTextFormat::PlainText;
|
InsertTextFormat insertTextFormat = InsertTextFormat::PlainText;
|
||||||
TextEdit textEdit;
|
TextEdit textEdit;
|
||||||
std::vector<TextEdit> additionalTextEdits;
|
std::vector<TextEdit> additionalTextEdits;
|
||||||
|
@ -22,9 +22,23 @@ using namespace llvm;
|
|||||||
|
|
||||||
MAKE_REFLECT_TYPE_PROXY(InsertTextFormat);
|
MAKE_REFLECT_TYPE_PROXY(InsertTextFormat);
|
||||||
MAKE_REFLECT_TYPE_PROXY(CompletionItemKind);
|
MAKE_REFLECT_TYPE_PROXY(CompletionItemKind);
|
||||||
MAKE_REFLECT_STRUCT(CompletionItem, label, kind, detail, documentation,
|
|
||||||
sortText, filterText, insertText, insertTextFormat,
|
void Reflect(Writer &vis, CompletionItem &v) {
|
||||||
textEdit, additionalTextEdits);
|
REFLECT_MEMBER_START();
|
||||||
|
REFLECT_MEMBER(label);
|
||||||
|
REFLECT_MEMBER(kind);
|
||||||
|
REFLECT_MEMBER(detail);
|
||||||
|
if (v.documentation.size())
|
||||||
|
REFLECT_MEMBER(documentation);
|
||||||
|
REFLECT_MEMBER(sortText);
|
||||||
|
if (v.filterText.size())
|
||||||
|
REFLECT_MEMBER(filterText);
|
||||||
|
REFLECT_MEMBER(insertTextFormat);
|
||||||
|
REFLECT_MEMBER(textEdit);
|
||||||
|
if (v.additionalTextEdits.size())
|
||||||
|
REFLECT_MEMBER(additionalTextEdits);
|
||||||
|
REFLECT_MEMBER_END();
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct CompletionList {
|
struct CompletionList {
|
||||||
@ -55,7 +69,6 @@ void DecorateIncludePaths(const std::smatch &match,
|
|||||||
item.textEdit.newText =
|
item.textEdit.newText =
|
||||||
prefix + quote0 + item.textEdit.newText + quote1 + suffix;
|
prefix + quote0 + item.textEdit.newText + quote1 + suffix;
|
||||||
item.label = prefix + quote0 + item.label + quote1 + suffix;
|
item.label = prefix + quote0 + item.label + quote1 + suffix;
|
||||||
item.filterText = std::nullopt;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,8 +125,8 @@ void FilterCandidates(CompletionList &result, const std::string &complete_text,
|
|||||||
std::string sort(4, ' ');
|
std::string sort(4, ' ');
|
||||||
for (auto &item : items) {
|
for (auto &item : items) {
|
||||||
item.textEdit.range = lsRange{begin_pos, end_pos};
|
item.textEdit.range = lsRange{begin_pos, end_pos};
|
||||||
if (has_open_paren && item.filterText)
|
if (has_open_paren)
|
||||||
item.textEdit.newText = *item.filterText;
|
item.textEdit.newText = item.filterText;
|
||||||
// https://github.com/Microsoft/language-server-protocol/issues/543
|
// https://github.com/Microsoft/language-server-protocol/issues/543
|
||||||
// Order of textEdit and additionalTextEdits is unspecified.
|
// Order of textEdit and additionalTextEdits is unspecified.
|
||||||
auto &edits = item.additionalTextEdits;
|
auto &edits = item.additionalTextEdits;
|
||||||
@ -121,48 +134,44 @@ void FilterCandidates(CompletionList &result, const std::string &complete_text,
|
|||||||
Position start = edits[0].range.start, end = edits[0].range.end;
|
Position start = edits[0].range.start, end = edits[0].range.end;
|
||||||
item.textEdit.range.start = start;
|
item.textEdit.range.start = start;
|
||||||
item.textEdit.newText = edits[0].newText + item.textEdit.newText;
|
item.textEdit.newText = edits[0].newText + item.textEdit.newText;
|
||||||
if (start.line == begin_pos.line && item.filterText) {
|
if (start.line == begin_pos.line) {
|
||||||
item.filterText =
|
item.filterText =
|
||||||
buffer_line.substr(start.character,
|
buffer_line.substr(start.character,
|
||||||
end.character - start.character) +
|
end.character - start.character) +
|
||||||
*item.filterText;
|
item.filterText;
|
||||||
}
|
}
|
||||||
edits.erase(edits.begin());
|
edits.erase(edits.begin());
|
||||||
}
|
}
|
||||||
|
if (item.filterText == item.label)
|
||||||
|
item.filterText.clear();
|
||||||
for (auto i = sort.size(); i && ++sort[i - 1] == 'A';)
|
for (auto i = sort.size(); i && ++sort[i - 1] == 'A';)
|
||||||
sort[--i] = ' ';
|
sort[--i] = ' ';
|
||||||
item.sortText = sort;
|
item.sortText = sort;
|
||||||
// Compatibility
|
|
||||||
item.insertText = item.textEdit.newText;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// No complete text; don't run any filtering logic except to trim the items.
|
if (!g_config->completion.filterAndSort) {
|
||||||
if (!g_config->completion.filterAndSort || complete_text.empty()) {
|
|
||||||
finalize();
|
finalize();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure all items have |filterText| set, code that follow needs it.
|
if (complete_text.size()) {
|
||||||
for (auto &item : items) {
|
// Fuzzy match and remove awful candidates.
|
||||||
if (!item.filterText)
|
bool sensitive = g_config->completion.caseSensitivity;
|
||||||
item.filterText = item.label;
|
FuzzyMatcher fuzzy(complete_text, sensitive);
|
||||||
|
for (CompletionItem &item : items) {
|
||||||
|
const std::string &filter =
|
||||||
|
item.filterText.size() ? item.filterText : item.label;
|
||||||
|
item.score_ = ReverseSubseqMatch(complete_text, filter, sensitive) >= 0
|
||||||
|
? fuzzy.Match(filter)
|
||||||
|
: FuzzyMatcher::kMinScore;
|
||||||
|
}
|
||||||
|
items.erase(std::remove_if(items.begin(), items.end(),
|
||||||
|
[](const CompletionItem &item) {
|
||||||
|
return item.score_ <= FuzzyMatcher::kMinScore;
|
||||||
|
}),
|
||||||
|
items.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fuzzy match and remove awful candidates.
|
|
||||||
bool sensitive = g_config->completion.caseSensitivity;
|
|
||||||
FuzzyMatcher fuzzy(complete_text, sensitive);
|
|
||||||
for (auto &item : items) {
|
|
||||||
item.score_ =
|
|
||||||
ReverseSubseqMatch(complete_text, *item.filterText, sensitive) >= 0
|
|
||||||
? fuzzy.Match(*item.filterText)
|
|
||||||
: FuzzyMatcher::kMinScore;
|
|
||||||
}
|
|
||||||
items.erase(std::remove_if(items.begin(), items.end(),
|
|
||||||
[](const CompletionItem &item) {
|
|
||||||
return item.score_ <= FuzzyMatcher::kMinScore;
|
|
||||||
}),
|
|
||||||
items.end());
|
|
||||||
std::sort(items.begin(), items.end(),
|
std::sort(items.begin(), items.end(),
|
||||||
[](const CompletionItem &lhs, const CompletionItem &rhs) {
|
[](const CompletionItem &lhs, const CompletionItem &rhs) {
|
||||||
int t = int(lhs.additionalTextEdits.size() -
|
int t = int(lhs.additionalTextEdits.size() -
|
||||||
@ -173,9 +182,13 @@ void FilterCandidates(CompletionList &result, const std::string &complete_text,
|
|||||||
return lhs.score_ > rhs.score_;
|
return lhs.score_ > rhs.score_;
|
||||||
if (lhs.priority_ != rhs.priority_)
|
if (lhs.priority_ != rhs.priority_)
|
||||||
return lhs.priority_ < rhs.priority_;
|
return lhs.priority_ < rhs.priority_;
|
||||||
if (lhs.filterText->size() != rhs.filterText->size())
|
t = lhs.textEdit.newText.compare(rhs.textEdit.newText);
|
||||||
return lhs.filterText->size() < rhs.filterText->size();
|
if (t)
|
||||||
return *lhs.filterText < *rhs.filterText;
|
return t < 0;
|
||||||
|
t = lhs.label.compare(rhs.label);
|
||||||
|
if (t)
|
||||||
|
return t < 0;
|
||||||
|
return lhs.filterText < rhs.filterText;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Trim result.
|
// Trim result.
|
||||||
@ -281,8 +294,7 @@ void BuildItem(const CodeCompletionResult &R, const CodeCompletionString &CCS,
|
|||||||
case CodeCompletionString::CK_TypedText:
|
case CodeCompletionString::CK_TypedText:
|
||||||
text = Chunk.Text;
|
text = Chunk.Text;
|
||||||
for (auto i = first; i < out.size(); i++)
|
for (auto i = first; i < out.size(); i++)
|
||||||
if (Kind == CodeCompletionString::CK_TypedText && !out[i].filterText)
|
out[i].filterText = text;
|
||||||
out[i].filterText = text;
|
|
||||||
break;
|
break;
|
||||||
case CodeCompletionString::CK_Placeholder:
|
case CodeCompletionString::CK_Placeholder:
|
||||||
text = Chunk.Text;
|
text = Chunk.Text;
|
||||||
@ -402,7 +414,7 @@ public:
|
|||||||
ls_items[j].priority_ = CCS->getPriority();
|
ls_items[j].priority_ = CCS->getPriority();
|
||||||
if (!g_config->completion.detailedLabel) {
|
if (!g_config->completion.detailedLabel) {
|
||||||
ls_items[j].detail = ls_items[j].label;
|
ls_items[j].detail = ls_items[j].label;
|
||||||
ls_items[j].label = ls_items[j].filterText.value_or("");
|
ls_items[j].label = ls_items[j].filterText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if LLVM_VERSION_MAJOR >= 7
|
#if LLVM_VERSION_MAJOR >= 7
|
||||||
|
Loading…
Reference in New Issue
Block a user