diff --git a/src/clang_complete.cc b/src/clang_complete.cc index da6fe90d..1a35bff5 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -29,7 +29,7 @@ unsigned Flags() { unsigned GetCompletionPriority(const CXCompletionString& str, CXCursorKind result_kind, - const std::string& typedText) { + const optional& typedText) { unsigned priority = clang_getCompletionPriority(str); // XXX: What happens if priority overflows? @@ -37,8 +37,8 @@ unsigned GetCompletionPriority(const CXCompletionString& str, priority *= 100; } if (result_kind == CXCursor_ConversionFunction || - (result_kind == CXCursor_CXXMethod && - StartsWith(typedText, "operator"))) { + (result_kind == CXCursor_CXXMethod && typedText && + StartsWith(*typedText, "operator"))) { priority *= 100; } if (clang_getCompletionAvailability(str) != CXAvailability_Available) { @@ -193,7 +193,7 @@ void BuildCompletionItemTexts(std::vector& out, for (auto i = out_first; i < out.size(); ++i) { // first typed text is used for filtering - if (kind == CXCompletionChunk_TypedText && out[i].filterText.empty()) + if (kind == CXCompletionChunk_TypedText && !out[i].filterText) out[i].filterText = text; if (kind == CXCompletionChunk_Placeholder) diff --git a/src/language_server_api.h b/src/language_server_api.h index 95aca47d..395dc61b 100644 --- a/src/language_server_api.h +++ b/src/language_server_api.h @@ -364,7 +364,7 @@ struct lsCompletionItem { // A string that should be used when filtering a set of // completion items. When `falsy` the label is used. - std::string filterText; + optional filterText; // A string that should be inserted a document when selecting // this completion. When `falsy` the label is used. diff --git a/src/lex_utils.cc b/src/lex_utils.cc index ba99e818..b7424701 100644 --- a/src/lex_utils.cc +++ b/src/lex_utils.cc @@ -80,7 +80,7 @@ void DecorateIncludePaths(const std::smatch& match, for (lsCompletionItem& item : *items) { item.textEdit->newText = prefix + item.textEdit->newText + suffix; item.label = prefix + item.label + suffix; - item.filterText = item.label; + item.filterText = nullopt; } } diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index c6658234..6dd2f4ab 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -38,7 +38,7 @@ struct lsCompletionOptions { // for // '::' and '>' for '->'. See // https://github.com/Microsoft/language-server-protocol/issues/138. - std::vector triggerCharacters = {".", ":", ">", "#", "<", "\""}; + std::vector triggerCharacters = {".", ":", ">", "#", "<", "\"", "/"}; }; MAKE_REFLECT_STRUCT(lsCompletionOptions, resolveProvider, triggerCharacters); diff --git a/src/messages/text_document_completion.cc b/src/messages/text_document_completion.cc index 1c3e7fdc..961d0790 100644 --- a/src/messages/text_document_completion.cc +++ b/src/messages/text_document_completion.cc @@ -76,9 +76,9 @@ bool CompareLsCompletionItem(const lsCompletionItem& lhs, return lhs.skip_ < rhs.skip_; if (lhs.priority_ != rhs.priority_) return lhs.priority_ < rhs.priority_; - if (lhs.filterText.length() != rhs.filterText.length()) - return lhs.filterText.length() < rhs.filterText.length(); - return lhs.filterText < rhs.filterText; + if (lhs.filterText->length() != rhs.filterText->length()) + return lhs.filterText->length() < rhs.filterText->length(); + return *lhs.filterText < *rhs.filterText; } template @@ -121,7 +121,7 @@ void FilterAndSortCompletionResponse( auto& items = complete_response->result.items; - if (!enable) { + if (!enable || complete_text.empty()) { // Just set the |sortText| to be the priority and return. char buf[16]; for (auto& item : items) @@ -130,17 +130,15 @@ void FilterAndSortCompletionResponse( } // Make sure all items have |filterText| set, code that follow needs it. - for (auto& item : items) { - if (item.filterText.empty()) { + for (auto& item : items) + if (!item.filterText) item.filterText = item.label; - } - } // If the text doesn't start with underscore, // remove all candidates that start with underscore. - if (!complete_text.empty() && complete_text[0] != '_') { + if (complete_text[0] != '_') { auto filter = [](const lsCompletionItem& item) { - return item.filterText[0] == '_'; + return (*item.filterText)[0] == '_'; }; items.erase(std::remove_if(items.begin(), items.end(), filter), items.end()); @@ -150,7 +148,7 @@ void FilterAndSortCompletionResponse( bool found = false; for (auto& item : items) { std::tie(item.found_, item.skip_) = - SubsequenceCountSkip(complete_text, item.filterText); + SubsequenceCountSkip(complete_text, *item.filterText); found = found || item.found_; } @@ -179,10 +177,12 @@ void FilterAndSortCompletionResponse( for (size_t i = 0; i < items.size(); ++i) items[i].sortText = tofixedbase64(i, buf); - // If there are too many results... - const size_t kMaxResultSize = 100u; - if (items.size() > kMaxResultSize) - items.resize(kMaxResultSize); + // FIXME + // The trigger behivour of vscode is puzzling. + // So maybe it's not feasible to cut out any results. + // const size_t kMaxResultSize = 100u; + // if (items.size() > kMaxResultSize) + // items.resize(kMaxResultSize); } struct TextDocumentCompletionHandler : MessageHandler { @@ -224,8 +224,8 @@ struct TextDocumentCompletionHandler : MessageHandler { std::string character = *request->params.context->triggerCharacter; char preceding_index = request->params.position.character - 2; - // If the character is '"' or '<', make sure that the line starts with '#'. - if (character == "\"" || character == "<") { + // If the character is '"', '<' or '/', make sure that the line starts with '#'. + if (character == "\"" || character == "<" || character == "/") { size_t i = 0; while (i < buffer_line.size() && isspace(buffer_line[i])) ++i;