Preprocessor keyword completion.

This commit is contained in:
Chao Shen 2018-03-24 12:21:23 +08:00 committed by Jacob Dufault
parent d87afce1fc
commit ddc318eef3

View File

@ -98,6 +98,8 @@ void DecorateIncludePaths(const std::smatch& match,
struct ParseIncludeLineResult { struct ParseIncludeLineResult {
bool ok; bool ok;
std::string keyword;
std::string quote;
std::string pattern; std::string pattern;
std::smatch match; std::smatch match;
}; };
@ -115,8 +117,28 @@ ParseIncludeLineResult ParseIncludeLine(const std::string& line) {
"(.*)"); // [7]: suffix after quote char "(.*)"); // [7]: suffix after quote char
std::smatch match; std::smatch match;
bool ok = std::regex_match(line, match, pattern); bool ok = std::regex_match(line, match, pattern);
std::string text = match[3].str() + match[6].str(); return {ok, match[3], match[5], match[6], match};
return {ok, text, match}; }
static const std::vector<std::string> preprocessorKeywords = {
"define", "undef", "include", "if", "ifdef", "ifndef",
"else", "elif", "endif", "line", "error", "pragma"};
std::vector<lsCompletionItem> preprocessorKeywordCompletionItems(
const std::smatch& match) {
std::vector<lsCompletionItem> 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 <typename T> template <typename T>
@ -298,21 +320,30 @@ struct Handler_TextDocumentCompletion : MessageHandler {
Out_TextDocumentComplete out; Out_TextDocumentComplete out;
out.id = request->id; out.id = request->id;
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<std::mutex> lock( std::unique_lock<std::mutex> lock(
include_complete->completion_items_mutex, std::defer_lock); include_complete->completion_items_mutex, std::defer_lock);
if (include_complete->is_scanning) if (include_complete->is_scanning)
lock.lock(); lock.lock();
out.result.items = include_complete->completion_items; out.result.items = include_complete->completion_items;
} }
// Needed by |FilterAndSortCompletionResponse|.
for (lsCompletionItem& item : out.result.items)
item.filterText = "include" + item.label;
FilterAndSortCompletionResponse(&out, result.pattern, FilterAndSortCompletionResponse(&out, result.pattern,
config->completion.filterAndSort); config->completion.filterAndSort);
DecorateIncludePaths(result.match, &out.result.items); DecorateIncludePaths(result.match, &out.result.items);
}
for (lsCompletionItem& item : out.result.items) { for (lsCompletionItem& item : out.result.items) {
item.textEdit->range.start.line = request->params.position.line; item.textEdit->range.start.line = request->params.position.line;