mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-21 23:25:07 +00:00
Use Sema/CodeCompleteConsumer
This commit is contained in:
parent
d3536831c3
commit
a4dd5d0c44
@ -5,8 +5,10 @@
|
||||
#include "log.hh"
|
||||
#include "platform.h"
|
||||
|
||||
#include <clang/Sema/CodeCompleteConsumer.h>
|
||||
#include <llvm/ADT/Twine.h>
|
||||
#include <llvm/Support/Threading.h>
|
||||
using namespace clang;
|
||||
using namespace llvm;
|
||||
|
||||
#include <algorithm>
|
||||
@ -30,23 +32,16 @@ std::string StripFileType(const std::string& path) {
|
||||
return Ret.str();
|
||||
}
|
||||
|
||||
unsigned GetCompletionPriority(const CXCompletionString& str,
|
||||
unsigned GetCompletionPriority(const CodeCompletionString& CCS,
|
||||
CXCursorKind result_kind,
|
||||
const std::optional<std::string>& typedText) {
|
||||
unsigned priority = clang_getCompletionPriority(str);
|
||||
|
||||
// XXX: What happens if priority overflows?
|
||||
if (result_kind == CXCursor_Destructor) {
|
||||
priority *= 100;
|
||||
}
|
||||
if (result_kind == CXCursor_ConversionFunction ||
|
||||
unsigned priority = CCS.getPriority();
|
||||
if (CCS.getAvailability() != CXAvailability_Available ||
|
||||
result_kind == CXCursor_Destructor ||
|
||||
result_kind == CXCursor_ConversionFunction ||
|
||||
(result_kind == CXCursor_CXXMethod && typedText &&
|
||||
StartsWith(*typedText, "operator"))) {
|
||||
StartsWith(*typedText, "operator")))
|
||||
priority *= 100;
|
||||
}
|
||||
if (clang_getCompletionAvailability(str) != CXAvailability_Available) {
|
||||
priority *= 100;
|
||||
}
|
||||
return priority;
|
||||
}
|
||||
|
||||
@ -142,85 +137,76 @@ lsCompletionItemKind GetCompletionKind(CXCursorKind cursor_kind) {
|
||||
}
|
||||
}
|
||||
|
||||
void BuildCompletionItemTexts(std::vector<lsCompletionItem>& out,
|
||||
CXCompletionString completion_string,
|
||||
void BuildCompletionItemTexts(std::vector<lsCompletionItem> &out,
|
||||
CodeCompletionString &CCS,
|
||||
bool include_snippets) {
|
||||
assert(!out.empty());
|
||||
auto out_first = out.size() - 1;
|
||||
|
||||
std::string result_type;
|
||||
|
||||
int num_chunks = clang_getNumCompletionChunks(completion_string);
|
||||
for (int i = 0; i < num_chunks; ++i) {
|
||||
CXCompletionChunkKind kind =
|
||||
clang_getCompletionChunkKind(completion_string, i);
|
||||
|
||||
for (unsigned i = 0, num_chunks = CCS.size(); i < num_chunks; ++i) {
|
||||
const CodeCompletionString::Chunk &Chunk = CCS[i];
|
||||
CodeCompletionString::ChunkKind Kind = Chunk.Kind;
|
||||
std::string text;
|
||||
switch (kind) {
|
||||
// clang-format off
|
||||
case CXCompletionChunk_LeftParen: text = '('; break;
|
||||
case CXCompletionChunk_RightParen: text = ')'; break;
|
||||
case CXCompletionChunk_LeftBracket: text = '['; break;
|
||||
case CXCompletionChunk_RightBracket: text = ']'; break;
|
||||
case CXCompletionChunk_LeftBrace: text = '{'; break;
|
||||
case CXCompletionChunk_RightBrace: text = '}'; break;
|
||||
case CXCompletionChunk_LeftAngle: text = '<'; break;
|
||||
case CXCompletionChunk_RightAngle: text = '>'; break;
|
||||
case CXCompletionChunk_Comma: text = ", "; break;
|
||||
case CXCompletionChunk_Colon: text = ':'; break;
|
||||
case CXCompletionChunk_SemiColon: text = ';'; break;
|
||||
case CXCompletionChunk_Equal: text = '='; break;
|
||||
case CXCompletionChunk_HorizontalSpace: text = ' '; break;
|
||||
case CXCompletionChunk_VerticalSpace: text = ' '; break;
|
||||
// clang-format on
|
||||
|
||||
case CXCompletionChunk_ResultType:
|
||||
result_type =
|
||||
ToString(clang_getCompletionChunkText(completion_string, i));
|
||||
continue;
|
||||
|
||||
case CXCompletionChunk_TypedText:
|
||||
case CXCompletionChunk_Placeholder:
|
||||
case CXCompletionChunk_Text:
|
||||
case CXCompletionChunk_Informative:
|
||||
text = ToString(clang_getCompletionChunkText(completion_string, i));
|
||||
|
||||
for (auto i = out_first; i < out.size(); ++i) {
|
||||
// first typed text is used for filtering
|
||||
if (kind == CXCompletionChunk_TypedText && !out[i].filterText)
|
||||
switch (Kind) {
|
||||
case CodeCompletionString::CK_TypedText:
|
||||
case CodeCompletionString::CK_Text:
|
||||
case CodeCompletionString::CK_Placeholder:
|
||||
case CodeCompletionString::CK_Informative:
|
||||
if (Chunk.Text)
|
||||
text = Chunk.Text;
|
||||
for (auto i = out_first; i < out.size(); i++) {
|
||||
// first TypedText is used for filtering
|
||||
if (Kind == CodeCompletionString::CK_TypedText && !out[i].filterText)
|
||||
out[i].filterText = text;
|
||||
|
||||
if (kind == CXCompletionChunk_Placeholder)
|
||||
if (Kind == CodeCompletionString::CK_Placeholder)
|
||||
out[i].parameters_.push_back(text);
|
||||
}
|
||||
break;
|
||||
|
||||
case CXCompletionChunk_CurrentParameter:
|
||||
case CodeCompletionString::CK_ResultType:
|
||||
if (Chunk.Text)
|
||||
result_type = Chunk.Text;
|
||||
continue;
|
||||
case CodeCompletionString::CK_CurrentParameter:
|
||||
// We have our own parsing logic for active parameter. This doesn't seem
|
||||
// to be very reliable.
|
||||
continue;
|
||||
|
||||
case CXCompletionChunk_Optional: {
|
||||
CXCompletionString nested =
|
||||
clang_getCompletionChunkCompletionString(completion_string, i);
|
||||
case CodeCompletionString::CK_Optional: {
|
||||
// duplicate last element, the recursive call will complete it
|
||||
out.push_back(out.back());
|
||||
BuildCompletionItemTexts(out, nested, include_snippets);
|
||||
BuildCompletionItemTexts(out, *Chunk.Optional, include_snippets);
|
||||
continue;
|
||||
}
|
||||
// clang-format off
|
||||
case CodeCompletionString::CK_LeftParen: text = '('; break;
|
||||
case CodeCompletionString::CK_RightParen: text = ')'; break;
|
||||
case CodeCompletionString::CK_LeftBracket: text = '['; break;
|
||||
case CodeCompletionString::CK_RightBracket: text = ']'; break;
|
||||
case CodeCompletionString::CK_LeftBrace: text = '{'; break;
|
||||
case CodeCompletionString::CK_RightBrace: text = '}'; break;
|
||||
case CodeCompletionString::CK_LeftAngle: text = '<'; break;
|
||||
case CodeCompletionString::CK_RightAngle: text = '>'; break;
|
||||
case CodeCompletionString::CK_Comma: text = ", "; break;
|
||||
case CodeCompletionString::CK_Colon: text = ':'; break;
|
||||
case CodeCompletionString::CK_SemiColon: text = ';'; break;
|
||||
case CodeCompletionString::CK_Equal: text = '='; break;
|
||||
case CodeCompletionString::CK_HorizontalSpace: text = ' '; break;
|
||||
case CodeCompletionString::CK_VerticalSpace: text = ' '; break;
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
for (auto i = out_first; i < out.size(); ++i)
|
||||
out[i].label += text;
|
||||
|
||||
if (kind == CXCompletionChunk_Informative)
|
||||
if (Kind == CodeCompletionString::CK_Informative)
|
||||
continue;
|
||||
|
||||
for (auto i = out_first; i < out.size(); ++i) {
|
||||
if (!include_snippets && !out[i].parameters_.empty())
|
||||
continue;
|
||||
|
||||
if (kind == CXCompletionChunk_Placeholder) {
|
||||
if (Kind == CodeCompletionString::CK_Placeholder) {
|
||||
out[i].insertText +=
|
||||
"${" + std::to_string(out[i].parameters_.size()) + ":" + text + "}";
|
||||
out[i].insertTextFormat = lsInsertTextFormat::Snippet;
|
||||
@ -243,106 +229,71 @@ void BuildCompletionItemTexts(std::vector<lsCompletionItem>& out,
|
||||
|
||||
// |do_insert|: if |!do_insert|, do not append strings to |insert| after
|
||||
// a placeholder.
|
||||
void BuildDetailString(CXCompletionString completion_string,
|
||||
std::string& label,
|
||||
std::string& detail,
|
||||
std::string& insert,
|
||||
bool& do_insert,
|
||||
lsInsertTextFormat& format,
|
||||
std::vector<std::string>* parameters,
|
||||
bool include_snippets,
|
||||
int& angle_stack) {
|
||||
int num_chunks = clang_getNumCompletionChunks(completion_string);
|
||||
auto append = [&](const char* text) {
|
||||
detail += text;
|
||||
if (do_insert && include_snippets)
|
||||
insert += text;
|
||||
};
|
||||
for (int i = 0; i < num_chunks; ++i) {
|
||||
CXCompletionChunkKind kind =
|
||||
clang_getCompletionChunkKind(completion_string, i);
|
||||
|
||||
switch (kind) {
|
||||
case CXCompletionChunk_Optional: {
|
||||
CXCompletionString nested =
|
||||
clang_getCompletionChunkCompletionString(completion_string, i);
|
||||
// Do not add text to insert string if we're in angle brackets.
|
||||
bool should_insert = do_insert && angle_stack == 0;
|
||||
BuildDetailString(nested, label, detail, insert,
|
||||
should_insert, format, parameters,
|
||||
include_snippets, angle_stack);
|
||||
break;
|
||||
}
|
||||
|
||||
case CXCompletionChunk_Placeholder: {
|
||||
std::string text =
|
||||
ToString(clang_getCompletionChunkText(completion_string, i));
|
||||
parameters->push_back(text);
|
||||
detail += text;
|
||||
// Add parameter declarations as snippets if enabled
|
||||
if (include_snippets) {
|
||||
insert +=
|
||||
"${" + std::to_string(parameters->size()) + ":" + text + "}";
|
||||
format = lsInsertTextFormat::Snippet;
|
||||
} else
|
||||
do_insert = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case CXCompletionChunk_CurrentParameter:
|
||||
// We have our own parsing logic for active parameter. This doesn't seem
|
||||
// to be very reliable.
|
||||
break;
|
||||
|
||||
case CXCompletionChunk_TypedText: {
|
||||
std::string text =
|
||||
ToString(clang_getCompletionChunkText(completion_string, i));
|
||||
label = text;
|
||||
detail += text;
|
||||
if (do_insert)
|
||||
insert += text;
|
||||
break;
|
||||
}
|
||||
|
||||
case CXCompletionChunk_Text: {
|
||||
std::string text =
|
||||
ToString(clang_getCompletionChunkText(completion_string, i));
|
||||
detail += text;
|
||||
if (do_insert)
|
||||
insert += text;
|
||||
break;
|
||||
}
|
||||
|
||||
case CXCompletionChunk_Informative: {
|
||||
detail += ToString(clang_getCompletionChunkText(completion_string, i));
|
||||
break;
|
||||
}
|
||||
|
||||
case CXCompletionChunk_ResultType: {
|
||||
CXString text = clang_getCompletionChunkText(completion_string, i);
|
||||
std::string new_detail = ToString(text) + detail + " ";
|
||||
detail = new_detail;
|
||||
break;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
case CXCompletionChunk_LeftParen: append("("); break;
|
||||
case CXCompletionChunk_RightParen: append(")"); break;
|
||||
case CXCompletionChunk_LeftBracket: append("["); break;
|
||||
case CXCompletionChunk_RightBracket: append("]"); break;
|
||||
case CXCompletionChunk_LeftBrace: append("{"); break;
|
||||
case CXCompletionChunk_RightBrace: append("}"); break;
|
||||
case CXCompletionChunk_LeftAngle: append("<"); angle_stack++; break;
|
||||
case CXCompletionChunk_RightAngle: append(">"); angle_stack--; break;
|
||||
case CXCompletionChunk_Comma: append(", "); break;
|
||||
case CXCompletionChunk_Colon: append(":"); break;
|
||||
case CXCompletionChunk_SemiColon: append(";"); break;
|
||||
case CXCompletionChunk_Equal: append("="); break;
|
||||
// clang-format on
|
||||
case CXCompletionChunk_HorizontalSpace:
|
||||
case CXCompletionChunk_VerticalSpace:
|
||||
append(" ");
|
||||
break;
|
||||
void BuildDetailString(const CodeCompletionString &CCS, lsCompletionItem &item,
|
||||
bool &do_insert, std::vector<std::string> *parameters,
|
||||
bool include_snippets, int &angle_stack) {
|
||||
for (unsigned i = 0, num_chunks = CCS.size(); i < num_chunks; ++i) {
|
||||
const CodeCompletionString::Chunk &Chunk = CCS[i];
|
||||
CodeCompletionString::ChunkKind Kind = Chunk.Kind;
|
||||
const char* text = nullptr;
|
||||
switch (Kind) {
|
||||
case CodeCompletionString::CK_TypedText:
|
||||
item.label = Chunk.Text;
|
||||
[[fallthrough]];
|
||||
case CodeCompletionString::CK_Text:
|
||||
item.detail += Chunk.Text;
|
||||
if (do_insert)
|
||||
item.insertText += Chunk.Text;
|
||||
break;
|
||||
case CodeCompletionString::CK_Placeholder: {
|
||||
parameters->push_back(Chunk.Text);
|
||||
item.detail += Chunk.Text;
|
||||
// Add parameter declarations as snippets if enabled
|
||||
if (include_snippets) {
|
||||
item.insertText += "${" + std::to_string(parameters->size()) + ":" + Chunk.Text + "}";
|
||||
item.insertTextFormat = lsInsertTextFormat::Snippet;
|
||||
} else
|
||||
do_insert = false;
|
||||
break;
|
||||
}
|
||||
case CodeCompletionString::CK_Informative:
|
||||
item.detail += Chunk.Text;
|
||||
break;
|
||||
case CodeCompletionString::CK_Optional: {
|
||||
// Do not add text to insert string if we're in angle brackets.
|
||||
bool should_insert = do_insert && angle_stack == 0;
|
||||
BuildDetailString(*Chunk.Optional, item, should_insert,
|
||||
parameters, include_snippets, angle_stack);
|
||||
break;
|
||||
}
|
||||
case CodeCompletionString::CK_ResultType:
|
||||
item.detail = Chunk.Text + item.detail + " ";
|
||||
break;
|
||||
case CodeCompletionString::CK_CurrentParameter:
|
||||
// We have our own parsing logic for active parameter. This doesn't seem
|
||||
// to be very reliable.
|
||||
break;
|
||||
// clang-format off
|
||||
case CodeCompletionString::CK_LeftParen: text = "("; break;
|
||||
case CodeCompletionString::CK_RightParen: text = ")"; break;
|
||||
case CodeCompletionString::CK_LeftBracket: text = "["; break;
|
||||
case CodeCompletionString::CK_RightBracket: text = "]"; break;
|
||||
case CodeCompletionString::CK_LeftBrace: text = "{"; break;
|
||||
case CodeCompletionString::CK_RightBrace: text = "}"; break;
|
||||
case CodeCompletionString::CK_LeftAngle: text = "<"; angle_stack++; break;
|
||||
case CodeCompletionString::CK_RightAngle: text = ">"; angle_stack--; break;
|
||||
case CodeCompletionString::CK_Comma: text = ", "; break;
|
||||
case CodeCompletionString::CK_Colon: text = ":"; break;
|
||||
case CodeCompletionString::CK_SemiColon: text = ";"; break;
|
||||
case CodeCompletionString::CK_Equal: text = "="; break;
|
||||
case CodeCompletionString::CK_HorizontalSpace:
|
||||
case CodeCompletionString::CK_VerticalSpace: text = " "; break;
|
||||
// clang-format on
|
||||
}
|
||||
if (text) {
|
||||
item.detail += text;
|
||||
if (do_insert && include_snippets)
|
||||
item.insertText += text;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -483,35 +434,24 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) {
|
||||
|
||||
for (unsigned i = 0; i < cx_results->NumResults; ++i) {
|
||||
CXCompletionResult& result = cx_results->Results[i];
|
||||
|
||||
// TODO: Try to figure out how we can hide base method calls without
|
||||
// also hiding method implementation assistance, ie,
|
||||
//
|
||||
// void Foo::* {
|
||||
// }
|
||||
//
|
||||
|
||||
if (clang_getCompletionAvailability(result.CompletionString) ==
|
||||
CXAvailability_NotAvailable)
|
||||
auto CCS = (CodeCompletionString *)result.CompletionString;
|
||||
if (CCS->getAvailability() == CXAvailability_NotAvailable)
|
||||
continue;
|
||||
|
||||
// TODO: fill in more data
|
||||
lsCompletionItem ls_completion_item;
|
||||
|
||||
ls_completion_item.kind = GetCompletionKind(result.CursorKind);
|
||||
ls_completion_item.documentation =
|
||||
ToString(clang_getCompletionBriefComment(result.CompletionString));
|
||||
lsCompletionItem ls_item;
|
||||
ls_item.kind = GetCompletionKind(result.CursorKind);
|
||||
if (const char* brief = CCS->getBriefComment())
|
||||
ls_item.documentation = brief;
|
||||
|
||||
// label/detail/filterText/insertText/priority
|
||||
if (g_config->completion.detailedLabel) {
|
||||
ls_completion_item.detail = ToString(
|
||||
clang_getCompletionParent(result.CompletionString, nullptr));
|
||||
ls_item.detail = CCS->getParentContextName().str();
|
||||
|
||||
auto first_idx = ls_result.size();
|
||||
ls_result.push_back(ls_completion_item);
|
||||
ls_result.push_back(ls_item);
|
||||
|
||||
// label/filterText/insertText
|
||||
BuildCompletionItemTexts(ls_result, result.CompletionString,
|
||||
BuildCompletionItemTexts(ls_result, *CCS,
|
||||
g_config->client.snippetSupport);
|
||||
|
||||
for (auto i = first_idx; i < ls_result.size(); ++i) {
|
||||
@ -520,28 +460,21 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) {
|
||||
ls_result[i].insertText += "$0";
|
||||
}
|
||||
|
||||
ls_result[i].priority_ =
|
||||
GetCompletionPriority(result.CompletionString, result.CursorKind,
|
||||
ls_result[i].filterText);
|
||||
ls_result[i].priority_ = GetCompletionPriority(
|
||||
*CCS, result.CursorKind, ls_result[i].filterText);
|
||||
}
|
||||
} else {
|
||||
bool do_insert = true;
|
||||
int angle_stack = 0;
|
||||
BuildDetailString(result.CompletionString, ls_completion_item.label,
|
||||
ls_completion_item.detail,
|
||||
ls_completion_item.insertText, do_insert,
|
||||
ls_completion_item.insertTextFormat,
|
||||
&ls_completion_item.parameters_,
|
||||
BuildDetailString(*CCS, ls_item, do_insert,
|
||||
&ls_item.parameters_,
|
||||
g_config->client.snippetSupport, angle_stack);
|
||||
if (g_config->client.snippetSupport &&
|
||||
ls_completion_item.insertTextFormat ==
|
||||
lsInsertTextFormat::Snippet) {
|
||||
ls_completion_item.insertText += "$0";
|
||||
}
|
||||
ls_completion_item.priority_ =
|
||||
GetCompletionPriority(result.CompletionString, result.CursorKind,
|
||||
ls_completion_item.label);
|
||||
ls_result.push_back(ls_completion_item);
|
||||
ls_item.insertTextFormat == lsInsertTextFormat::Snippet)
|
||||
ls_item.insertText += "$0";
|
||||
ls_item.priority_ =
|
||||
GetCompletionPriority(*CCS, result.CursorKind, ls_item.label);
|
||||
ls_result.push_back(ls_item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,10 +19,11 @@ enum class lsCompletionTriggerKind {
|
||||
// Completion was triggered by typing an identifier (24x7 code
|
||||
// complete), manual invocation (e.g Ctrl+Space) or via API.
|
||||
Invoked = 1,
|
||||
|
||||
// Completion was triggered by a trigger character specified by
|
||||
// the `triggerCharacters` properties of the `CompletionRegistrationOptions`.
|
||||
TriggerCharacter = 2
|
||||
TriggerCharacter = 2,
|
||||
// Completion was re-triggered as the current completion list is incomplete.
|
||||
TriggerForIncompleteCompletions = 3,
|
||||
};
|
||||
MAKE_REFLECT_TYPE_PROXY(lsCompletionTriggerKind);
|
||||
|
||||
@ -30,7 +31,7 @@ MAKE_REFLECT_TYPE_PROXY(lsCompletionTriggerKind);
|
||||
// request is triggered.
|
||||
struct lsCompletionContext {
|
||||
// How the completion was triggered.
|
||||
lsCompletionTriggerKind triggerKind;
|
||||
lsCompletionTriggerKind triggerKind = lsCompletionTriggerKind::Invoked;
|
||||
|
||||
// The trigger character (a single character) that has trigger code complete.
|
||||
// Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
|
||||
@ -42,7 +43,7 @@ struct lsCompletionParams : lsTextDocumentPositionParams {
|
||||
// The completion context. This is only available it the client specifies to
|
||||
// send this using
|
||||
// `ClientCapabilities.textDocument.completion.contextSupport === true`
|
||||
std::optional<lsCompletionContext> context;
|
||||
lsCompletionContext context;
|
||||
};
|
||||
MAKE_REFLECT_STRUCT(lsCompletionParams, textDocument, position, context);
|
||||
|
||||
@ -254,6 +255,7 @@ struct Handler_TextDocumentCompletion : MessageHandler {
|
||||
void Run(std::unique_ptr<InMessage> message) override {
|
||||
auto request = std::shared_ptr<In_TextDocumentComplete>(
|
||||
static_cast<In_TextDocumentComplete*>(message.release()));
|
||||
auto& params = request->params;
|
||||
|
||||
auto write_empty_result = [request]() {
|
||||
Out_TextDocumentComplete out;
|
||||
@ -261,7 +263,7 @@ struct Handler_TextDocumentCompletion : MessageHandler {
|
||||
pipeline::WriteStdout(kMethodType, out);
|
||||
};
|
||||
|
||||
std::string path = request->params.textDocument.uri.GetPath();
|
||||
std::string path = params.textDocument.uri.GetPath();
|
||||
WorkingFile* file = working_files->GetFileByFilename(path);
|
||||
if (!file) {
|
||||
write_empty_result();
|
||||
@ -271,21 +273,19 @@ struct Handler_TextDocumentCompletion : MessageHandler {
|
||||
// It shouldn't be possible, but sometimes vscode will send queries out
|
||||
// of order, ie, we get completion request before buffer content update.
|
||||
std::string buffer_line;
|
||||
if (request->params.position.line >= 0 &&
|
||||
request->params.position.line < file->buffer_lines.size()) {
|
||||
buffer_line = file->buffer_lines[request->params.position.line];
|
||||
}
|
||||
if (params.position.line >= 0 &&
|
||||
params.position.line < file->buffer_lines.size())
|
||||
buffer_line = file->buffer_lines[params.position.line];
|
||||
|
||||
// Check for - and : before completing -> or ::, since vscode does not
|
||||
// support multi-character trigger characters.
|
||||
if (request->params.context &&
|
||||
request->params.context->triggerKind ==
|
||||
if (params.context.triggerKind ==
|
||||
lsCompletionTriggerKind::TriggerCharacter &&
|
||||
request->params.context->triggerCharacter) {
|
||||
params.context.triggerCharacter) {
|
||||
bool did_fail_check = false;
|
||||
|
||||
std::string character = *request->params.context->triggerCharacter;
|
||||
int preceding_index = request->params.position.character - 2;
|
||||
std::string character = *params.context.triggerCharacter;
|
||||
int preceding_index = params.position.character - 2;
|
||||
|
||||
// If the character is '"', '<' or '/', make sure that the line starts
|
||||
// with '#'.
|
||||
@ -318,11 +318,11 @@ struct Handler_TextDocumentCompletion : MessageHandler {
|
||||
|
||||
bool is_global_completion = false;
|
||||
std::string existing_completion;
|
||||
lsPosition end_pos = request->params.position;
|
||||
lsPosition end_pos = params.position;
|
||||
if (file) {
|
||||
request->params.position = file->FindStableCompletionSource(
|
||||
request->params.position, &is_global_completion,
|
||||
&existing_completion, &end_pos);
|
||||
params.position = file->FindStableCompletionSource(
|
||||
request->params.position, &is_global_completion, &existing_completion,
|
||||
&end_pos);
|
||||
}
|
||||
|
||||
ParseIncludeLineResult result = ParseIncludeLine(buffer_line);
|
||||
@ -359,16 +359,16 @@ struct Handler_TextDocumentCompletion : MessageHandler {
|
||||
}
|
||||
|
||||
for (lsCompletionItem& item : out.result.items) {
|
||||
item.textEdit->range.start.line = request->params.position.line;
|
||||
item.textEdit->range.start.line = params.position.line;
|
||||
item.textEdit->range.start.character = 0;
|
||||
item.textEdit->range.end.line = request->params.position.line;
|
||||
item.textEdit->range.end.line = params.position.line;
|
||||
item.textEdit->range.end.character = (int)buffer_line.size();
|
||||
}
|
||||
|
||||
pipeline::WriteStdout(kMethodType, out);
|
||||
} else {
|
||||
ClangCompleteManager::OnComplete callback = std::bind(
|
||||
[this, request, is_global_completion, existing_completion,
|
||||
[this, request, params, is_global_completion, existing_completion,
|
||||
has_open_paren](const std::vector<lsCompletionItem>& results,
|
||||
bool is_cached_result) {
|
||||
Out_TextDocumentComplete out;
|
||||
@ -381,7 +381,7 @@ struct Handler_TextDocumentCompletion : MessageHandler {
|
||||
|
||||
// Cache completion results.
|
||||
if (!is_cached_result) {
|
||||
std::string path = request->params.textDocument.uri.GetPath();
|
||||
std::string path = params.textDocument.uri.GetPath();
|
||||
if (is_global_completion) {
|
||||
global_code_complete_cache->WithLock([&]() {
|
||||
global_code_complete_cache->cached_path_ = path;
|
||||
@ -391,7 +391,7 @@ struct Handler_TextDocumentCompletion : MessageHandler {
|
||||
non_global_code_complete_cache->WithLock([&]() {
|
||||
non_global_code_complete_cache->cached_path_ = path;
|
||||
non_global_code_complete_cache->cached_completion_position_ =
|
||||
request->params.position;
|
||||
params.position;
|
||||
non_global_code_complete_cache->cached_results_ = results;
|
||||
});
|
||||
}
|
||||
@ -421,16 +421,14 @@ struct Handler_TextDocumentCompletion : MessageHandler {
|
||||
callback(global_code_complete_cache->cached_results_,
|
||||
true /*is_cached_result*/);
|
||||
});
|
||||
clang_complete->CodeComplete(request->id, request->params,
|
||||
freshen_global);
|
||||
} else if (non_global_code_complete_cache->IsCacheValid(
|
||||
request->params)) {
|
||||
clang_complete->CodeComplete(request->id, params, freshen_global);
|
||||
} else if (non_global_code_complete_cache->IsCacheValid(params)) {
|
||||
non_global_code_complete_cache->WithLock([&]() {
|
||||
callback(non_global_code_complete_cache->cached_results_,
|
||||
true /*is_cached_result*/);
|
||||
});
|
||||
} else {
|
||||
clang_complete->CodeComplete(request->id, request->params, callback);
|
||||
clang_complete->CodeComplete(request->id, params, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user