mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-22 15:45:08 +00:00
Completion changes (maybe fix some crashes)
This commit is contained in:
parent
0876886c60
commit
706479aded
@ -8,7 +8,41 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <execinfo.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
constexpr int kBacktraceBufferSize = 300;
|
||||||
|
|
||||||
|
#if false
|
||||||
|
void EmitBacktrace() {
|
||||||
|
void* buffer[kBacktraceBufferSize];
|
||||||
|
int nptrs = backtrace(buffer, kBacktraceBufferSize);
|
||||||
|
|
||||||
|
fprintf(stderr, "backtrace() returned %d addresses\n", nptrs);
|
||||||
|
|
||||||
|
/* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
|
||||||
|
would produce similar output to the following: */
|
||||||
|
|
||||||
|
char** strings = backtrace_symbols(buffer, nptrs);
|
||||||
|
if (!strings) {
|
||||||
|
perror("Failed to emit backtrace");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < nptrs; j++)
|
||||||
|
fprintf(stderr, "%s\n", strings[j]);
|
||||||
|
|
||||||
|
free(strings);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned Flags() {
|
unsigned Flags() {
|
||||||
// TODO: use clang_defaultEditingTranslationUnitOptions()?
|
// TODO: use clang_defaultEditingTranslationUnitOptions()?
|
||||||
return
|
return
|
||||||
@ -333,46 +367,50 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) {
|
|||||||
timer.ResetAndPrint("[complete] clangCodeCompleteAt");
|
timer.ResetAndPrint("[complete] clangCodeCompleteAt");
|
||||||
std::cerr << "[complete] Got " << cx_results->NumResults << " results" << std::endl;
|
std::cerr << "[complete] Got " << cx_results->NumResults << " results" << std::endl;
|
||||||
|
|
||||||
NonElidedVector<lsCompletionItem> ls_result;
|
{
|
||||||
ls_result.reserve(cx_results->NumResults);
|
NonElidedVector<lsCompletionItem> ls_result;
|
||||||
|
ls_result.reserve(cx_results->NumResults);
|
||||||
|
|
||||||
timer.Reset();
|
timer.Reset();
|
||||||
for (unsigned i = 0; i < cx_results->NumResults; ++i) {
|
for (unsigned i = 0; i < cx_results->NumResults; ++i) {
|
||||||
CXCompletionResult& result = cx_results->Results[i];
|
CXCompletionResult& result = cx_results->Results[i];
|
||||||
|
|
||||||
// TODO: Try to figure out how we can hide base method calls without also
|
// TODO: Try to figure out how we can hide base method calls without also
|
||||||
// hiding method implementation assistance, ie,
|
// hiding method implementation assistance, ie,
|
||||||
//
|
//
|
||||||
// void Foo::* {
|
// void Foo::* {
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
|
||||||
if (clang_getCompletionAvailability(result.CompletionString) == CXAvailability_NotAvailable)
|
if (clang_getCompletionAvailability(result.CompletionString) == CXAvailability_NotAvailable)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// TODO: fill in more data
|
// TODO: fill in more data
|
||||||
lsCompletionItem ls_completion_item;
|
lsCompletionItem ls_completion_item;
|
||||||
|
|
||||||
// kind/label/detail/docs/sortText
|
// kind/label/detail/docs/sortText
|
||||||
ls_completion_item.kind = GetCompletionKind(result.CursorKind);
|
ls_completion_item.kind = GetCompletionKind(result.CursorKind);
|
||||||
BuildDetailString(result.CompletionString, ls_completion_item.label, ls_completion_item.detail, ls_completion_item.insertText, &ls_completion_item.parameters_);
|
BuildDetailString(result.CompletionString, ls_completion_item.label, ls_completion_item.detail, ls_completion_item.insertText, &ls_completion_item.parameters_);
|
||||||
ls_completion_item.insertText += "$0";
|
ls_completion_item.insertText += "$0";
|
||||||
ls_completion_item.documentation = clang::ToString(clang_getCompletionBriefComment(result.CompletionString));
|
ls_completion_item.documentation = clang::ToString(clang_getCompletionBriefComment(result.CompletionString));
|
||||||
ls_completion_item.sortText = (const char)uint64_t(GetCompletionPriority(result.CompletionString, result.CursorKind, ls_completion_item.label));
|
ls_completion_item.sortText = (const char)uint64_t(GetCompletionPriority(result.CompletionString, result.CursorKind, ls_completion_item.label));
|
||||||
|
|
||||||
// If this function is slow we can skip building insertText at the cost of some code duplication.
|
// If this function is slow we can skip building insertText at the cost of some code duplication.
|
||||||
if (!IsCallKind(result.CursorKind))
|
if (!IsCallKind(result.CursorKind))
|
||||||
ls_completion_item.insertText = "";
|
ls_completion_item.insertText = "";
|
||||||
|
|
||||||
ls_result.push_back(ls_completion_item);
|
ls_result.push_back(ls_completion_item);
|
||||||
|
}
|
||||||
|
timer.ResetAndPrint("[complete] Building " + std::to_string(ls_result.size()) + " completion results");
|
||||||
|
|
||||||
|
request->on_complete(ls_result);
|
||||||
|
timer.ResetAndPrint("[complete] Running user-given completion func");
|
||||||
}
|
}
|
||||||
timer.ResetAndPrint("[complete] Building " + std::to_string(ls_result.size()) + " completion results");
|
|
||||||
|
|
||||||
|
// Make sure |ls_results| is destroyed before clearing |cx_results|.
|
||||||
clang_disposeCodeCompleteResults(cx_results);
|
clang_disposeCodeCompleteResults(cx_results);
|
||||||
timer.ResetAndPrint("[complete] clang_disposeCodeCompleteResults");
|
timer.ResetAndPrint("[complete] clang_disposeCodeCompleteResults");
|
||||||
|
|
||||||
request->on_complete(ls_result);
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -386,6 +424,7 @@ CompletionSession::CompletionSession(const Project::Entry& file, WorkingFiles* w
|
|||||||
|
|
||||||
CompletionSession::~CompletionSession() {
|
CompletionSession::~CompletionSession() {
|
||||||
std::cerr << "[complete] CompletionSession::~CompletionSession() for " << file.filename << std::endl;
|
std::cerr << "[complete] CompletionSession::~CompletionSession() for " << file.filename << std::endl;
|
||||||
|
// EmitBacktrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
LruSessionCache::LruSessionCache(int max_entries) : max_entries_(max_entries) {}
|
LruSessionCache::LruSessionCache(int max_entries) : max_entries_(max_entries) {}
|
||||||
@ -401,7 +440,7 @@ std::shared_ptr<CompletionSession> LruSessionCache::TryGetEntry(const std::strin
|
|||||||
std::shared_ptr<CompletionSession> LruSessionCache::TryTakeEntry(const std::string& filename) {
|
std::shared_ptr<CompletionSession> LruSessionCache::TryTakeEntry(const std::string& filename) {
|
||||||
for (int i = 0; i < entries_.size(); ++i) {
|
for (int i = 0; i < entries_.size(); ++i) {
|
||||||
if (entries_[i]->file.filename == filename) {
|
if (entries_[i]->file.filename == filename) {
|
||||||
std::shared_ptr<CompletionSession> result = std::move(entries_[i]);
|
std::shared_ptr<CompletionSession> result = entries_[i];
|
||||||
entries_.erase(entries_.begin() + i);
|
entries_.erase(entries_.begin() + i);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -410,9 +449,9 @@ std::shared_ptr<CompletionSession> LruSessionCache::TryTakeEntry(const std::stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LruSessionCache::InsertEntry(std::shared_ptr<CompletionSession> session) {
|
void LruSessionCache::InsertEntry(std::shared_ptr<CompletionSession> session) {
|
||||||
if (entries_.size() >= max_entries_)
|
if (entries_.size() && entries_.size() >= max_entries_)
|
||||||
entries_.pop_back();
|
entries_.pop_back();
|
||||||
entries_.insert(entries_.begin(), std::move(session));
|
entries_.insert(entries_.begin(), session);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangCompleteManager::ParseRequest::ParseRequest(const std::string& path)
|
ClangCompleteManager::ParseRequest::ParseRequest(const std::string& path)
|
||||||
@ -432,6 +471,8 @@ ClangCompleteManager::ClangCompleteManager(Config* config, Project* project, Wor
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClangCompleteManager::~ClangCompleteManager() {}
|
||||||
|
|
||||||
void ClangCompleteManager::CodeComplete(const lsTextDocumentPositionParams& completion_location, const OnComplete& on_complete) {
|
void ClangCompleteManager::CodeComplete(const lsTextDocumentPositionParams& completion_location, const OnComplete& on_complete) {
|
||||||
// completion thread will create the CompletionSession if needed.
|
// completion thread will create the CompletionSession if needed.
|
||||||
|
|
||||||
@ -454,7 +495,7 @@ void ClangCompleteManager::NotifyView(const std::string& filename) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
std::cerr << "[complete] Creating new edit code completion session for " << filename << std::endl;
|
std::cerr << "[complete] Creating new edit code completion session for " << filename << std::endl;
|
||||||
view_sessions_.InsertEntry(MakeUnique<CompletionSession>(
|
view_sessions_.InsertEntry(std::make_shared<CompletionSession>(
|
||||||
project_->FindCompilationEntryForFile(filename), working_files_));
|
project_->FindCompilationEntryForFile(filename), working_files_));
|
||||||
parse_requests_.Enqueue(ParseRequest(filename));
|
parse_requests_.Enqueue(ParseRequest(filename));
|
||||||
}
|
}
|
||||||
@ -471,14 +512,16 @@ void ClangCompleteManager::NotifyEdit(const std::string& filename) {
|
|||||||
if (edit_sessions_.TryGetEntry(filename))
|
if (edit_sessions_.TryGetEntry(filename))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (std::shared_ptr<CompletionSession> session = view_sessions_.TryTakeEntry(filename)) {
|
std::shared_ptr<CompletionSession> session = view_sessions_.TryTakeEntry(filename);
|
||||||
edit_sessions_.InsertEntry(std::move(session));
|
if (session) {
|
||||||
|
edit_sessions_.InsertEntry(session);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cerr << "[complete] Creating new edit code completion session for " << filename << std::endl;
|
||||||
|
edit_sessions_.InsertEntry(std::make_shared<CompletionSession>(
|
||||||
|
project_->FindCompilationEntryForFile(filename), working_files_));
|
||||||
|
parse_requests_.PriorityEnqueue(ParseRequest(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cerr << "[complete] Creating new edit code completion session for " << filename << std::endl;
|
|
||||||
edit_sessions_.InsertEntry(MakeUnique<CompletionSession>(
|
|
||||||
project_->FindCompilationEntryForFile(filename), working_files_));
|
|
||||||
parse_requests_.PriorityEnqueue(ParseRequest(filename));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangCompleteManager::NotifySave(const std::string& filename) {
|
void ClangCompleteManager::NotifySave(const std::string& filename) {
|
||||||
@ -490,7 +533,7 @@ void ClangCompleteManager::NotifySave(const std::string& filename) {
|
|||||||
|
|
||||||
if (!edit_sessions_.TryGetEntry(filename)) {
|
if (!edit_sessions_.TryGetEntry(filename)) {
|
||||||
std::cerr << "[complete] Creating new edit code completion session for " << filename << std::endl;
|
std::cerr << "[complete] Creating new edit code completion session for " << filename << std::endl;
|
||||||
edit_sessions_.InsertEntry(MakeUnique<CompletionSession>(
|
edit_sessions_.InsertEntry(std::make_shared<CompletionSession>(
|
||||||
project_->FindCompilationEntryForFile(filename), working_files_));
|
project_->FindCompilationEntryForFile(filename), working_files_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,7 +551,7 @@ std::shared_ptr<CompletionSession> ClangCompleteManager::TryGetSession(const std
|
|||||||
if (!session && create_if_needed) {
|
if (!session && create_if_needed) {
|
||||||
// Create new session. Default to edited_sessions_ since invoking code
|
// Create new session. Default to edited_sessions_ since invoking code
|
||||||
// completion almost certainly implies an edit.
|
// completion almost certainly implies an edit.
|
||||||
edit_sessions_.InsertEntry(MakeUnique<CompletionSession>(
|
edit_sessions_.InsertEntry(std::make_shared<CompletionSession>(
|
||||||
project_->FindCompilationEntryForFile(filename), working_files_));
|
project_->FindCompilationEntryForFile(filename), working_files_));
|
||||||
session = edit_sessions_.TryGetEntry(filename);
|
session = edit_sessions_.TryGetEntry(filename);
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ struct LruSessionCache {
|
|||||||
struct ClangCompleteManager {
|
struct ClangCompleteManager {
|
||||||
using OnDiagnostic = std::function<void(std::string path, NonElidedVector<lsDiagnostic> diagnostics)>;
|
using OnDiagnostic = std::function<void(std::string path, NonElidedVector<lsDiagnostic> diagnostics)>;
|
||||||
using OnComplete = std::function<void(NonElidedVector<lsCompletionItem> results)>;
|
using OnComplete = std::function<void(NonElidedVector<lsCompletionItem> results)>;
|
||||||
|
|
||||||
struct ParseRequest {
|
struct ParseRequest {
|
||||||
ParseRequest(const std::string& path);
|
ParseRequest(const std::string& path);
|
||||||
|
|
||||||
@ -62,6 +62,7 @@ struct ClangCompleteManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ClangCompleteManager(Config* config, Project* project, WorkingFiles* working_files, OnDiagnostic on_diagnostic);
|
ClangCompleteManager(Config* config, Project* project, WorkingFiles* working_files, OnDiagnostic on_diagnostic);
|
||||||
|
~ClangCompleteManager();
|
||||||
|
|
||||||
// Start a code completion at the given location. |on_complete| will run when
|
// Start a code completion at the given location. |on_complete| will run when
|
||||||
// completion results are available. |on_complete| may run on any thread.
|
// completion results are available. |on_complete| may run on any thread.
|
||||||
@ -102,4 +103,4 @@ struct ClangCompleteManager {
|
|||||||
// Parse requests. The path may already be parsed, in which case it should be
|
// Parse requests. The path may already be parsed, in which case it should be
|
||||||
// reparsed.
|
// reparsed.
|
||||||
ThreadedQueue<ParseRequest> parse_requests_;
|
ThreadedQueue<ParseRequest> parse_requests_;
|
||||||
};
|
};
|
||||||
|
@ -1672,10 +1672,13 @@ bool QueryDbMainLoop(
|
|||||||
// note: path is updated in the normal completion handler.
|
// note: path is updated in the normal completion handler.
|
||||||
global_code_complete_cache->cached_results = results;
|
global_code_complete_cache->cached_results = results;
|
||||||
};
|
};
|
||||||
clang_complete->CodeComplete(msg->params, std::move(freshen_global));
|
|
||||||
|
|
||||||
// Note: callback will delete the message (ie, |params|) so we need to run completion_manager->CodeComplete before |callback|.
|
// Note: |callback| will delete the message (ie, |params|) so we
|
||||||
|
// need to run completion_manager->CodeComplete before |callback|.
|
||||||
|
lsTextDocumentPositionParams params = msg->params;
|
||||||
callback(global_code_complete_cache->cached_results);
|
callback(global_code_complete_cache->cached_results);
|
||||||
|
|
||||||
|
clang_complete->CodeComplete(params, std::move(freshen_global));
|
||||||
}
|
}
|
||||||
else if (non_global_code_complete_cache->IsCacheValid(msg->params)) {
|
else if (non_global_code_complete_cache->IsCacheValid(msg->params)) {
|
||||||
std::cerr << "[complete] Using cached completion results at " << msg->params.position.ToString() << std::endl;
|
std::cerr << "[complete] Using cached completion results at " << msg->params.position.ToString() << std::endl;
|
||||||
|
Loading…
Reference in New Issue
Block a user