From e182ac12ae3508dd8bcc76a85a9f70678384eee8 Mon Sep 17 00:00:00 2001 From: Jacob Dufault Date: Sun, 21 May 2017 14:01:52 -0700 Subject: [PATCH] Elide long include path proposals --- src/command_line.cc | 3 ++- src/config.h | 5 +++++ src/include_completion.cc | 38 +++++++++++++++++++++++++++----------- src/language_server_api.h | 20 ++++++++++++++++++-- 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/src/command_line.cc b/src/command_line.cc index 58713d50..6d60d7a9 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -1801,7 +1801,7 @@ bool QueryDbMainLoop( Out_TextDocumentComplete complete_response; complete_response.id = msg->id; complete_response.result.isIncomplete = false; - + { std::unique_lock lock(include_completion->completion_items_mutex, std::defer_lock); if (include_completion->is_scanning) @@ -1821,6 +1821,7 @@ bool QueryDbMainLoop( } } + std::cerr << "[complete] Returning " << complete_response.result.items.size() << " include completions" << std::endl; ipc->SendOutMessageToClient(IpcId::TextDocumentCompletion, complete_response); } else { diff --git a/src/config.h b/src/config.h index 9e72a669..1efaaf83 100644 --- a/src/config.h +++ b/src/config.h @@ -29,6 +29,10 @@ struct Config { // If true, document links are reported for #include directives. bool showDocumentLinksOnIncludes = true; + // Maximum path length to show in completion results. Paths longer than this + // will be elided with ".." put at the front. Set to 0 or a negative number + // to disable eliding. + int includeCompletionMaximumPathLength = 30; // Whitelist that file paths will be tested against. If a file path does not // end in one of these values, it will not be considered for auto-completion. // An example value is { ".h", ".hpp" } @@ -57,6 +61,7 @@ MAKE_REFLECT_STRUCT(Config, indexerCount, enableIndexing, enableCacheWrite, enableCacheRead, + includeCompletionMaximumPathLength, includeCompletionWhitelistLiteralEnding, includeCompletionWhitelist, includeCompletionBlacklist, diff --git a/src/include_completion.cc b/src/include_completion.cc index 72adaf89..e40d8d6c 100644 --- a/src/include_completion.cc +++ b/src/include_completion.cc @@ -10,6 +10,17 @@ namespace { +std::string ElideLongPath(Config* config, const std::string& path) { + if (config->includeCompletionMaximumPathLength <= 0) + return path; + + if (path.size() <= config->includeCompletionMaximumPathLength) + return path; + + int start = path.size() - config->includeCompletionMaximumPathLength; + return ".." + path.substr(start + 2); +} + size_t TrimCommonPathPrefix(const std::string& result, const std::string& trimmer) { size_t i = 0; while (i < result.size() && i < trimmer.size()) { @@ -56,12 +67,22 @@ bool TrimPath(Project* project, const std::string& project_root, std::string& in return angle; } -lsCompletionItem BuildCompletionItem(std::string path, bool use_angle_brackets, bool is_stl) { +lsCompletionItem BuildCompletionItem(Config* config, std::string path, bool use_angle_brackets, bool is_stl) { lsCompletionItem item; if (use_angle_brackets) - item.label = "#include <" + std::string(path) + ">"; + item.label = "#include <" + ElideLongPath(config, path) + ">"; else - item.label = "#include \"" + std::string(path) + "\""; + item.label = "#include \"" + ElideLongPath(config, path) + "\""; + + item.detail = path; + + // Replace the entire existing content. + // NOTE: When submitting completion items, textEdit->range must be updated. + item.textEdit = lsTextEdit(); + if (use_angle_brackets) + item.textEdit->newText = "#include <" + path + ">"; + else + item.textEdit->newText = "#include \"" + path + "\""; item.insertTextFormat = lsInsertTextFormat::PlainText; if (is_stl) @@ -69,11 +90,6 @@ lsCompletionItem BuildCompletionItem(std::string path, bool use_angle_brackets, else item.kind = lsCompletionItemKind::File; - // Replace the entire existing content. - // NOTE: When submitting completion items, textEdit->range must be updated. - item.textEdit = lsTextEdit(); - item.textEdit->newText = item.label; - return item; } @@ -115,7 +131,7 @@ void IncludeCompletion::AddFile(std::string path) { return; bool use_angle_brackets = TrimPath(project_, config_->projectRoot, path); - lsCompletionItem item = BuildCompletionItem(path, use_angle_brackets, false /*is_stl*/); + lsCompletionItem item = BuildCompletionItem(config_, path, use_angle_brackets, false /*is_stl*/); if (is_scanning) { std::lock_guard lock(completion_items_mutex); @@ -136,7 +152,7 @@ void IncludeCompletion::InsertIncludesFromDirectory( if (match_ && !match_->IsMatch(directory + path)) return; - result.push_back(BuildCompletionItem(path, use_angle_brackets, false /*is_stl*/)); + result.push_back(BuildCompletionItem(config_, path, use_angle_brackets, false /*is_stl*/)); }); std::lock_guard lock(completion_items_mutex); @@ -146,6 +162,6 @@ void IncludeCompletion::InsertIncludesFromDirectory( void IncludeCompletion::InsertStlIncludes() { std::lock_guard lock(completion_items_mutex); for (const char* stl_header : kStandardLibraryIncludes) { - completion_items.insert(BuildCompletionItem(stl_header, true /*use_angle_brackets*/, true /*is_stl*/)); + completion_items.insert(BuildCompletionItem(config_, stl_header, true /*use_angle_brackets*/, true /*is_stl*/)); } } diff --git a/src/language_server_api.h b/src/language_server_api.h index 19e9e7b1..16edc5de 100644 --- a/src/language_server_api.h +++ b/src/language_server_api.h @@ -461,7 +461,13 @@ struct lsCompletionItem { // a completion and a completion resolve request. // data ? : any - inline bool operator==(const lsCompletionItem& other) const { return label == other.label; } + inline bool operator==(const lsCompletionItem& other) const { + if (textEdit && other.textEdit) + return textEdit->newText == other.textEdit->newText; + if (!insertText.empty()) + return insertText == other.insertText; + return label == other.label; + } }; MAKE_REFLECT_STRUCT(lsCompletionItem, label, @@ -472,7 +478,17 @@ MAKE_REFLECT_STRUCT(lsCompletionItem, insertText, insertTextFormat, textEdit); -MAKE_HASHABLE(lsCompletionItem, t.label); +namespace std { +template<> struct hash { + std::size_t operator()(const lsCompletionItem& t) const { + if (t.textEdit) + return std::hash()(t.textEdit->newText); + if (!t.insertText.empty()) + return std::hash()(t.insertText); + return std::hash()(t.label); + } +}; +} struct lsTextDocumentItem { // The text document's URI.