From e145f779960021fe278f8c76b130c219cdb674ad Mon Sep 17 00:00:00 2001 From: scturtle Date: Mon, 29 Jan 2018 22:26:13 +0800 Subject: [PATCH] Fix completion of headers. --- src/config.h | 3 ++- src/include_complete.cc | 22 +++++---------------- src/lex_utils.cc | 25 ++++++++++++++++++++++-- src/lex_utils.h | 4 +++- src/messages/text_document_completion.cc | 12 +++++++----- 5 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/config.h b/src/config.h index 405716fc..d6c9905c 100644 --- a/src/config.h +++ b/src/config.h @@ -104,7 +104,8 @@ struct Config { // An example value is { ".h", ".hpp" } // // This is significantly faster than using a regex. - std::vector includeCompletionWhitelistLiteralEnding; + std::vector includeCompletionWhitelistLiteralEnding = { + ".h", ".hpp", ".hh"}; // Regex patterns to match include completion candidates against. They // receive the absolute file path. // diff --git a/src/include_complete.cc b/src/include_complete.cc index 5f10aaa3..54d1ca57 100644 --- a/src/include_complete.cc +++ b/src/include_complete.cc @@ -78,30 +78,18 @@ bool TrimPath(Project* project, lsCompletionItem BuildCompletionItem(Config* config, const std::string& path, - bool use_angle_brackets, + bool /*use_angle_brackets*/, bool is_stl) { lsCompletionItem item; - if (use_angle_brackets) - item.label = "#include <" + ElideLongPath(config, path) + ">"; - else - item.label = "#include \"" + ElideLongPath(config, path) + "\""; - + item.label = 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.textEdit->newText = path; item.insertTextFormat = lsInsertTextFormat::PlainText; if (is_stl) item.kind = lsCompletionItemKind::Module; else item.kind = lsCompletionItemKind::File; - return item; } @@ -127,8 +115,8 @@ void IncludeComplete::Rescan() { Timer timer; InsertStlIncludes(); - InsertIncludesFromDirectory(config_->projectRoot, - false /*use_angle_brackets*/); + // InsertIncludesFromDirectory(config_->projectRoot, + // false /*use_angle_brackets*/); for (const std::string& dir : project_->quote_include_directories) InsertIncludesFromDirectory(dir, false /*use_angle_brackets*/); for (const std::string& dir : project_->angle_include_directories) diff --git a/src/lex_utils.cc b/src/lex_utils.cc index 0f5bd63d..20fab59e 100644 --- a/src/lex_utils.cc +++ b/src/lex_utils.cc @@ -45,11 +45,32 @@ lsPosition CharPos(const std::string& search, return result; } -bool ShouldRunIncludeCompletion(const std::string& line) { +std::tuple ShouldRunIncludeCompletion( + const std::string& line) { size_t start = 0; while (start < line.size() && isspace(line[start])) ++start; - return start < line.size() && line[start] == '#'; + if (start >= line.size() || line[start] != '#') + return std::make_tuple(false, "", ""); + ++start; + if (line.compare(start, 7, "include") == 0) { + start += 7; + while (start < line.size() && isspace(line[start])) + ++start; + } + std::string surrounding, prefix; + if (start >= line.size()) + return std::make_tuple(false, "", ""); + else if (line[start] == '"') + surrounding = "\"\""; + else if (line[start] == '<') + surrounding = "<>"; + else + return std::make_tuple(false, "", ""); + ++start; + if (start < line.size()) + prefix = line.substr(start); + return std::make_tuple(true, surrounding, prefix); } // TODO: eliminate |line_number| param. diff --git a/src/lex_utils.h b/src/lex_utils.h index 69355ba4..9933bded 100644 --- a/src/lex_utils.h +++ b/src/lex_utils.h @@ -3,6 +3,7 @@ #include "language_server_api.h" #include +#include // Utility method to map |position| to an offset inside of |content|. int GetOffsetForPosition(lsPosition position, const std::string& content); @@ -11,7 +12,8 @@ lsPosition CharPos(const std::string& search, char character, int character_offset = 0); -bool ShouldRunIncludeCompletion(const std::string& line); +std::tuple ShouldRunIncludeCompletion( + const std::string& line); // TODO: eliminate |line_number| param. optional ExtractQuotedRange(int line_number, const std::string& line); diff --git a/src/messages/text_document_completion.cc b/src/messages/text_document_completion.cc index 1286e511..3c5faee7 100644 --- a/src/messages/text_document_completion.cc +++ b/src/messages/text_document_completion.cc @@ -283,7 +283,10 @@ struct TextDocumentCompletionHandler : MessageHandler { &existing_completion); } - if (ShouldRunIncludeCompletion(buffer_line)) { + bool yes; + std::string surrounding, prefix; + std::tie(yes, surrounding, prefix) = ShouldRunIncludeCompletion(buffer_line); + if (yes) { Out_TextDocumentComplete out; out.id = request->id; @@ -296,18 +299,17 @@ struct TextDocumentCompletionHandler : MessageHandler { include_complete->completion_items.end()); if (lock) lock.unlock(); - - // Update textEdit params. for (lsCompletionItem& item : out.result.items) { item.textEdit->range.start.line = request->params.position.line; item.textEdit->range.start.character = 0; item.textEdit->range.end.line = request->params.position.line; item.textEdit->range.end.character = (int)buffer_line.size(); + item.textEdit->newText = std::string("#include ") + surrounding[0] + + item.textEdit->newText + surrounding[1]; } } - TrimInPlace(buffer_line); - FilterAndSortCompletionResponse(&out, buffer_line, + FilterAndSortCompletionResponse(&out, prefix, config->completion.filterAndSort); QueueManager::WriteStdout(IpcId::TextDocumentCompletion, out); } else {