From ddc318eef3cbbd6daf0a09dcf795b207c19e5c83 Mon Sep 17 00:00:00 2001 From: Chao Shen Date: Sat, 24 Mar 2018 12:21:23 +0800 Subject: [PATCH] Preprocessor keyword completion. --- src/messages/text_document_completion.cc | 63 ++++++++++++++++++------ 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/src/messages/text_document_completion.cc b/src/messages/text_document_completion.cc index 8378539f..7229d65b 100644 --- a/src/messages/text_document_completion.cc +++ b/src/messages/text_document_completion.cc @@ -98,6 +98,8 @@ void DecorateIncludePaths(const std::smatch& match, struct ParseIncludeLineResult { bool ok; + std::string keyword; + std::string quote; std::string pattern; std::smatch match; }; @@ -115,8 +117,28 @@ ParseIncludeLineResult ParseIncludeLine(const std::string& line) { "(.*)"); // [7]: suffix after quote char std::smatch match; bool ok = std::regex_match(line, match, pattern); - std::string text = match[3].str() + match[6].str(); - return {ok, text, match}; + return {ok, match[3], match[5], match[6], match}; +} + +static const std::vector preprocessorKeywords = { + "define", "undef", "include", "if", "ifdef", "ifndef", + "else", "elif", "endif", "line", "error", "pragma"}; + +std::vector preprocessorKeywordCompletionItems( + const std::smatch& match) { + std::vector items; + for (auto& keyword : preprocessorKeywords) { + lsCompletionItem item; + item.label = keyword; + item.priority_ = (keyword == "include" ? 2 : 1); + item.textEdit = lsTextEdit(); + std::string space = (keyword == "else" || keyword == "endif") ? "" : " "; + item.textEdit->newText = match[1].str() + "#" + match[2].str() + keyword + + space + match[6].str(); + item.insertTextFormat = lsInsertTextFormat::PlainText; + items.push_back(item); + } + return items; } template @@ -298,22 +320,31 @@ struct Handler_TextDocumentCompletion : MessageHandler { Out_TextDocumentComplete out; out.id = request->id; - { - std::unique_lock lock( - include_complete->completion_items_mutex, std::defer_lock); - if (include_complete->is_scanning) - lock.lock(); - out.result.items = include_complete->completion_items; + if (result.quote.empty() && result.pattern.empty()) { + // no quote or path of file, do preprocessor keyword completion + if (!std::any_of(preprocessorKeywords.begin(), + preprocessorKeywords.end(), + [&result](std::string_view k) { + return k == result.keyword; + })) { + out.result.items = preprocessorKeywordCompletionItems(result.match); + FilterAndSortCompletionResponse(&out, result.keyword, + config->completion.filterAndSort); + } + } else if (result.keyword.compare("include") == 0) { + { + // do include completion + std::unique_lock lock( + include_complete->completion_items_mutex, std::defer_lock); + if (include_complete->is_scanning) + lock.lock(); + out.result.items = include_complete->completion_items; + } + FilterAndSortCompletionResponse(&out, result.pattern, + config->completion.filterAndSort); + DecorateIncludePaths(result.match, &out.result.items); } - // Needed by |FilterAndSortCompletionResponse|. - for (lsCompletionItem& item : out.result.items) - item.filterText = "include" + item.label; - - FilterAndSortCompletionResponse(&out, result.pattern, - config->completion.filterAndSort); - DecorateIncludePaths(result.match, &out.result.items); - for (lsCompletionItem& item : out.result.items) { item.textEdit->range.start.line = request->params.position.line; item.textEdit->range.start.character = 0;