From f498f0ccb1673e208a7512b1f5b8f72a444cec21 Mon Sep 17 00:00:00 2001 From: Jacob Dufault Date: Wed, 28 Jun 2017 23:59:38 -0700 Subject: [PATCH] Fix showing duplicate completion entries, always provide insertText. --- src/clang_complete.cc | 4 ---- src/command_line.cc | 26 +++++++++++++++++++++++++- src/language_server_api.cc | 8 ++++++++ src/language_server_api.h | 5 +++++ 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index 615502fa..6f5762f4 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -395,10 +395,6 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) { ls_completion_item.documentation = clang::ToString(clang_getCompletionBriefComment(result.CompletionString)); ls_completion_item.sortText = (const char)uint64_t(GetCompletionPriority(result.CompletionString, result.CursorKind, ls_completion_item.label)); - // If this function is slow we can skip building insertText at the cost of some code duplication. - if (!IsCallKind(result.CursorKind)) - ls_completion_item.insertText = ""; - ls_result.push_back(ls_completion_item); } timer.ResetAndPrint("[complete] Building " + std::to_string(ls_result.size()) + " completion results"); diff --git a/src/command_line.cc b/src/command_line.cc index 4a8c5968..ebf0a90a 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -478,8 +478,17 @@ void FilterCompletionResponse(Out_TextDocumentComplete* complete_response, NonElidedVector filtered_result; filtered_result.reserve(kMaxResultSize); + std::unordered_set inserted; + inserted.reserve(kMaxResultSize); + for (const lsCompletionItem& item : complete_response->result.items) { if (item.label.find(complete_text) != std::string::npos) { + // Don't insert the same completion entry. + if (!inserted.insert(item.InsertedContent()).second) { + std::cerr << "foo " << item.InsertedContent(); + continue; + } + filtered_result.push_back(item); if (filtered_result.size() >= kMaxResultSize) break; @@ -489,7 +498,10 @@ void FilterCompletionResponse(Out_TextDocumentComplete* complete_response, if (filtered_result.size() < kMaxResultSize) { for (const lsCompletionItem& item : complete_response->result.items) { if (SubstringMatch(complete_text, item.label)) { - //std::cerr << "!! emitting " << item.label << std::endl; + // Don't insert the same completion entry. + if (!inserted.insert(item.InsertedContent()).second) + continue; + filtered_result.push_back(item); if (filtered_result.size() >= kMaxResultSize) break; @@ -2355,8 +2367,16 @@ bool QueryDbMainLoop( << " candidates for query " << msg->params.query << std::endl; std::string query = msg->params.query; + + std::unordered_set inserted_results; + inserted_results.reserve(config->maxWorkspaceSearchResults); + for (int i = 0; i < db->detailed_names.size(); ++i) { if (db->detailed_names[i].find(query) != std::string::npos) { + // Do not show the same entry twice. + if (!inserted_results.insert(db->detailed_names[i]).second) + continue; + InsertSymbolIntoResult(db, working_files, db->symbols[i], &response.result); if (response.result.size() >= config->maxWorkspaceSearchResults) break; @@ -2366,6 +2386,10 @@ bool QueryDbMainLoop( if (response.result.size() < config->maxWorkspaceSearchResults) { for (int i = 0; i < db->detailed_names.size(); ++i) { if (SubstringMatch(query, db->detailed_names[i])) { + // Do not show the same entry twice. + if (!inserted_results.insert(db->detailed_names[i]).second) + continue; + InsertSymbolIntoResult(db, working_files, db->symbols[i], &response.result); if (response.result.size() >= config->maxWorkspaceSearchResults) break; diff --git a/src/language_server_api.cc b/src/language_server_api.cc index 50274683..08d3c062 100644 --- a/src/language_server_api.cc +++ b/src/language_server_api.cc @@ -215,6 +215,14 @@ bool lsTextEdit::operator==(const lsTextEdit& that) { return range == that.range && newText == that.newText; } +const std::string& lsCompletionItem::InsertedContent() const { + if (textEdit) + return textEdit->newText; + if (!insertText.empty()) + return insertText; + return label; +} + void Reflect(Reader& reader, lsInitializeParams::lsTrace& value) { std::string v = reader.GetString(); if (v == "off") diff --git a/src/language_server_api.h b/src/language_server_api.h index 60f7422e..d009c28c 100644 --- a/src/language_server_api.h +++ b/src/language_server_api.h @@ -461,6 +461,11 @@ struct lsCompletionItem { // An data entry field that is preserved on a completion item between // a completion and a completion resolve request. // data ? : any + + // Use this helper to figure out what content the completion item will insert + // into the document, as it could live in either |textEdit|, |insertText|, or + // |label|. + const std::string& InsertedContent() const; }; MAKE_REFLECT_STRUCT(lsCompletionItem, label,