Fix completion of headers.

This commit is contained in:
scturtle 2018-01-29 22:26:13 +08:00
parent 5bd466ab17
commit e145f77996
5 changed files with 40 additions and 26 deletions

View File

@ -104,7 +104,8 @@ struct Config {
// An example value is { ".h", ".hpp" } // An example value is { ".h", ".hpp" }
// //
// This is significantly faster than using a regex. // This is significantly faster than using a regex.
std::vector<std::string> includeCompletionWhitelistLiteralEnding; std::vector<std::string> includeCompletionWhitelistLiteralEnding = {
".h", ".hpp", ".hh"};
// Regex patterns to match include completion candidates against. They // Regex patterns to match include completion candidates against. They
// receive the absolute file path. // receive the absolute file path.
// //

View File

@ -78,30 +78,18 @@ bool TrimPath(Project* project,
lsCompletionItem BuildCompletionItem(Config* config, lsCompletionItem BuildCompletionItem(Config* config,
const std::string& path, const std::string& path,
bool use_angle_brackets, bool /*use_angle_brackets*/,
bool is_stl) { bool is_stl) {
lsCompletionItem item; lsCompletionItem item;
if (use_angle_brackets) item.label = ElideLongPath(config, path);
item.label = "#include <" + ElideLongPath(config, path) + ">";
else
item.label = "#include \"" + ElideLongPath(config, path) + "\"";
item.detail = path; item.detail = path;
// Replace the entire existing content.
// NOTE: When submitting completion items, textEdit->range must be updated.
item.textEdit = lsTextEdit(); item.textEdit = lsTextEdit();
if (use_angle_brackets) item.textEdit->newText = path;
item.textEdit->newText = "#include <" + path + ">";
else
item.textEdit->newText = "#include \"" + path + "\"";
item.insertTextFormat = lsInsertTextFormat::PlainText; item.insertTextFormat = lsInsertTextFormat::PlainText;
if (is_stl) if (is_stl)
item.kind = lsCompletionItemKind::Module; item.kind = lsCompletionItemKind::Module;
else else
item.kind = lsCompletionItemKind::File; item.kind = lsCompletionItemKind::File;
return item; return item;
} }
@ -127,8 +115,8 @@ void IncludeComplete::Rescan() {
Timer timer; Timer timer;
InsertStlIncludes(); InsertStlIncludes();
InsertIncludesFromDirectory(config_->projectRoot, // InsertIncludesFromDirectory(config_->projectRoot,
false /*use_angle_brackets*/); // false /*use_angle_brackets*/);
for (const std::string& dir : project_->quote_include_directories) for (const std::string& dir : project_->quote_include_directories)
InsertIncludesFromDirectory(dir, false /*use_angle_brackets*/); InsertIncludesFromDirectory(dir, false /*use_angle_brackets*/);
for (const std::string& dir : project_->angle_include_directories) for (const std::string& dir : project_->angle_include_directories)

View File

@ -45,11 +45,32 @@ lsPosition CharPos(const std::string& search,
return result; return result;
} }
bool ShouldRunIncludeCompletion(const std::string& line) { std::tuple<bool, std::string, std::string> ShouldRunIncludeCompletion(
const std::string& line) {
size_t start = 0; size_t start = 0;
while (start < line.size() && isspace(line[start])) while (start < line.size() && isspace(line[start]))
++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. // TODO: eliminate |line_number| param.

View File

@ -3,6 +3,7 @@
#include "language_server_api.h" #include "language_server_api.h"
#include <string> #include <string>
#include <tuple>
// Utility method to map |position| to an offset inside of |content|. // Utility method to map |position| to an offset inside of |content|.
int GetOffsetForPosition(lsPosition position, const std::string& content); int GetOffsetForPosition(lsPosition position, const std::string& content);
@ -11,7 +12,8 @@ lsPosition CharPos(const std::string& search,
char character, char character,
int character_offset = 0); int character_offset = 0);
bool ShouldRunIncludeCompletion(const std::string& line); std::tuple<bool, std::string, std::string> ShouldRunIncludeCompletion(
const std::string& line);
// TODO: eliminate |line_number| param. // TODO: eliminate |line_number| param.
optional<lsRange> ExtractQuotedRange(int line_number, const std::string& line); optional<lsRange> ExtractQuotedRange(int line_number, const std::string& line);

View File

@ -283,7 +283,10 @@ struct TextDocumentCompletionHandler : MessageHandler {
&existing_completion); &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_TextDocumentComplete out;
out.id = request->id; out.id = request->id;
@ -296,18 +299,17 @@ struct TextDocumentCompletionHandler : MessageHandler {
include_complete->completion_items.end()); include_complete->completion_items.end());
if (lock) if (lock)
lock.unlock(); lock.unlock();
// Update textEdit params.
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;
item.textEdit->range.start.character = 0; item.textEdit->range.start.character = 0;
item.textEdit->range.end.line = request->params.position.line; item.textEdit->range.end.line = request->params.position.line;
item.textEdit->range.end.character = (int)buffer_line.size(); 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, prefix,
FilterAndSortCompletionResponse(&out, buffer_line,
config->completion.filterAndSort); config->completion.filterAndSort);
QueueManager::WriteStdout(IpcId::TextDocumentCompletion, out); QueueManager::WriteStdout(IpcId::TextDocumentCompletion, out);
} else { } else {